Compare commits

..

6 Commits

Author SHA1 Message Date
TEC caa23dcb70
etc/ORG-NEWS: Mention the new \P entity 2023-04-13 15:05:44 +08:00
TEC 87543ee6fb
oc-csl: Recognise ¶/§ entity locators
* lisp/oc-csl.el: Recognise org-entity based paragraph and section
locators "\P" and "\S".
2023-04-13 14:52:14 +08:00
TEC 798fb3aaa9
org-entities: Treat ¶ similarly to §
* lisp/org-entities.el: Treat pilcrows / paragraph symbols similarly to
section symbols (§), move them next to each other and add a \P entity.
2023-04-13 14:52:14 +08:00
TEC bc91d8e72b
org-entities: § is a section sign, not paragraph
* lisp/org-entities.el: Correct the ASCII version of § to be "section",
not "paragraph".
2023-04-13 14:52:14 +08:00
TEC 2e26a3757b
ob-tangle: Edit default file mode to match docstr
* lisp/ob-tangle.el (org-babel-tangle-default-file-mode): The docstring
states that it the default value is read-write for the user, read only
for everyone else.  This is not consistent with the default value which
is actually read-*execute* for the user, read only for everyone else.
The default value is updated to be read-write for the user, as stated in
the docstring.

Reported-by: Ruijie Yu <ruijie@netyu.xyz>
Link: https://list.orgmode.org/orgmode/sdv3554xtat.fsf@fw.net.yu
2023-04-13 14:51:16 +08:00
TEC d035cc36cd
ob-tangle: Fix interpretation of rw-r--r-- modes
* lisp/ob-tangle.el (org-babel-interpret-file-mode): When specifying a
file mode in the "rw-r--r--" style, this is interpreted by splicing the
user, group, and other compenents into a "u=rw,g=r,o=r" style string and
applying `file-modes-symbolic-to-number`.  For correct interpretation,
we need to ensure the dashes are removed in this process.
2023-04-13 13:46:15 +08:00
196 changed files with 13468 additions and 31354 deletions

View File

@ -4,7 +4,7 @@ effectively.
We value a nice tone in our discussions: please check and respect the
[[https://www.gnu.org/philosophy/kind-communication.en.html][GNU Kind Communications Guidelines]].
* Contribute as an Org user
* Contribute as a Org user
You can contribute by helping others in various channels.
@ -16,7 +16,7 @@ You can contribute with bug reports and patches.
See these [[https://orgmode.org/worg/org-contribute.html#org069b83a][directions]].
* As an Org maintainer
* As a Org maintainer
We encourage you to volunteer to maintain one of the Org files.

View File

@ -27,7 +27,6 @@ help helpall::
$(info make all - ditto)
$(info make compile - build Org ELisp files)
$(info make single - build Org ELisp files, single Emacs per source)
$(info make native - build Org natively compiled Elisp files)
$(info make autoloads - create org-loaddefs.el to load Org in-place)
$(info make test - build Org ELisp files and run test suite)
$(info make vanilla - run Emacs with this Org-mode and no personal config)

View File

@ -9,9 +9,8 @@ Check the [[https://orgmode.org][Org Mode website]] for more.
Org is part of GNU Emacs: you probably don't need to install it.
To install a more recent version, please use command: =M-x
list-packages=, find "org" in the list, click on it, and click
"Install" in the popped up window.
To install a more recent version, please do it from [[https://elpa.gnu.org/packages/org.html][GNU ELPA]] by
running this command: =M-x package-install RET org RET=
* Join the GNU Project

View File

@ -1,6 +1,6 @@
# SETUPFILE for Org manual
# Copyright (C) 2021-2024 Free Software Foundation, Inc.
# Copyright (C) 2021-2023 Free Software Foundation, Inc.
#
# This file is part of GNU Emacs.
#

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -9,17 +9,13 @@
% Specify how many you want here.
\columnsperpage=3
% Set letterpaper to 0 for A4 paper, 1 for letter (US) paper. Useful
% only when columnsperpage is 2 or 3.
\letterpaper=1
% PDF output layout. 0 for A4, 1 for letter (US), a `l' is added for
% a landscape layout.
\input pdflayout.sty
\pdflayout=(1l)
\pdflayout=(0l)
% Nothing else needs to be changed below this line.
% Copyright (C) 1987, 1993, 1996--1997, 2001--2024 Free Software
% Copyright (C) 1987, 1993, 1996--1997, 2001--2023 Free Software
% Foundation, Inc.
% This document is free software: you can redistribute it and/or modify
@ -112,14 +108,17 @@
\footline{\hss\folio}
\def\makefootline{\baselineskip10pt\hsize6.5in\line{\the\footline}}
\else %2 or 3 columns uses prereduced size
\hsize 3.2in
\if 1\the\letterpaper
\hsize 3.2in
\vsize 7.95in
\hoffset -.75in
\voffset -.745in
\else
\hsize 3.2in
\vsize 7.65in
\hoffset -.25in
\voffset -.745in
\fi
\hoffset -.75in
\voffset -.745in
\font\titlefont=cmbx10 \scaledmag2
\font\headingfont=cmbx10 \scaledmag1
\font\smallfont=cmr6
@ -276,7 +275,7 @@
%**end of header
\title{Org-Mode Reference Card}
\title{Org-Mode Reference Card (1/2)}
\centerline{(for version \orgversionnumber)}
@ -478,7 +477,7 @@ after ``{\tt :}'', and dictionary words elsewhere.
\newcolumn
\title{Org-Mode Reference Card}
\title{Org-Mode Reference Card (2/2)}
\centerline{(for version \orgversionnumber)}

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
The files OrgOdtContentTemplate.xml and OrgOdtStyles.xml have the
following copyright information:
Copyright (C) 2010-2024 Free Software Foundation, Inc.
Copyright (C) 2010-2023 Free Software Foundation, Inc.
These files are part of GNU Emacs.

View File

@ -1,3 +1,4 @@
.NOTPARALLEL: # always run this make serially
.SUFFIXES: # we don't need default suffix rules
ifeq ($(MAKELEVEL), 0)
$(error This make needs to be started as a sub-make from the toplevel directory.)
@ -9,8 +10,7 @@ LISPA := $(LISPV) $(LISPI)
LISPB := $(LISPA:%el=%elc) org-install.elc
LISPF := $(filter-out $(LISPA),$(sort $(wildcard *.el)))
LISPC := $(filter-out $(LISPB) $(LISPN:%el=%elc),$(LISPF:%el=%elc))
LISPN := $(filter-out $(LISPB) $(LISPN:%el=%eln),$(LISPF:%el=%eln))
_ORGCM_ := dirall single native source slint1 slint2
_ORGCM_ := dirall single source slint1 slint2
-include local.mk
.PHONY: all compile compile-dirty \
@ -19,7 +19,7 @@ _ORGCM_ := dirall single native source slint1 slint2
install clean cleanauto cleanall cleanelc clean-install
# do not clean here, done in toplevel make
all compile compile-dirty:: | autoloads
all compile compile-dirty:: autoloads
ifeq ($(filter-out $(_ORGCM_),$(ORGCM)),)
$(MAKE) compile-$(ORGCM)
else
@ -27,11 +27,10 @@ else
endif
compile-dirall: dirall
compile-single: $(LISPC) | single
compile-native: $(LISPN) | native
compile-source: | source dirall
compile-slint1: | dirall slint1
compile-slint2: | source dirall slint1
compile-single: single $(LISPC)
compile-source: source dirall
compile-slint1: dirall slint1
compile-slint2: source dirall slint1
# internal
dirall:
@ -39,8 +38,6 @@ dirall:
@$(ELCDIR)
single:
@$(info ==================== $@ ====================)
native:
@$(info ==================== $@ ====================)
source: cleanelc
@$(info ==================== $@ ====================)
@$(foreach elc,$(LISPC),$(MAKE) $(elc) && $(RM) $(elc);)
@ -52,10 +49,6 @@ slint1:
@$(info Compiling single $(abspath $<)...)
-@$(ELC) $<
%.eln: %.el
@$(info Native compiling single $(abspath $<)...)
-@$(ELN) $<
autoloads: cleanauto $(LISPI) $(LISPV)
$(LISPV): $(LISPF)

View File

@ -1,6 +1,6 @@
;;; ob-C.el --- Babel Functions for C and Similar Languages -*- lexical-binding: t; -*-
;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Thierry Banel
@ -93,45 +93,44 @@ parameter may be used, like rdmd --chatty"
is currently being evaluated.")
(defun org-babel-execute:cpp (body params)
"Execute BODY according to its header arguments PARAMS.
"Execute BODY according to PARAMS.
This function calls `org-babel-execute:C++'."
(org-babel-execute:C++ body params))
(defun org-babel-expand-body:cpp (body params)
"Expand C++ BODY with org-babel according to its header arguments PARAMS."
"Expand a block of C++ code with org-babel according to its header arguments."
(org-babel-expand-body:C++ body params))
(defun org-babel-execute:C++ (body params)
"Execute C++ BODY with org-babel according to its header arguments PARAMS.
"Execute a block of C++ code with org-babel.
This function is called by `org-babel-execute-src-block'."
(let ((org-babel-c-variant 'cpp)) (org-babel-C-execute body params)))
(defun org-babel-expand-body:C++ (body params)
"Expand C++ BODY with org-babel according to its header arguments PARAMS."
"Expand a block of C++ code with org-babel according to its header arguments."
(let ((org-babel-c-variant 'cpp)) (org-babel-C-expand-C++ body params)))
(defun org-babel-execute:D (body params)
"Execute D BODY with org-babel according to its header arguments PARAMS.
"Execute a block of D code with org-babel.
This function is called by `org-babel-execute-src-block'."
(let ((org-babel-c-variant 'd)) (org-babel-C-execute body params)))
(defun org-babel-expand-body:D (body params)
"Expand D BODY with org-babel according to its header arguments PARAMS."
"Expand a block of D code with org-babel according to its header arguments."
(let ((org-babel-c-variant 'd)) (org-babel-C-expand-D body params)))
(defun org-babel-execute:C (body params)
"Execute a C BODY according to its header arguments PARAMS.
"Execute a block of C code with org-babel.
This function is called by `org-babel-execute-src-block'."
(let ((org-babel-c-variant 'c)) (org-babel-C-execute body params)))
(defun org-babel-expand-body:C (body params)
"Expand C BODY according to its header arguments PARAMS."
"Expand a block of C code with org-babel according to its header arguments."
(let ((org-babel-c-variant 'c)) (org-babel-C-expand-C body params)))
(defun org-babel-C-execute (body params)
"Execute C/C++/D BODY according to its header arguments PARAMS.
This function should only be called by `org-babel-execute:C' or
`org-babel-execute:C++' or `org-babel-execute:D'."
"This function should only be called by `org-babel-execute:C'
or `org-babel-execute:C++' or `org-babel-execute:D'."
(let* ((tmp-src-file (org-babel-temp-file
"C-src-"
(pcase org-babel-c-variant
@ -197,11 +196,11 @@ This function should only be called by `org-babel-execute:C' or
)))
(defun org-babel-C-expand-C++ (body params)
"Expand C/C++ BODY with according to its header arguments PARAMS."
"Expand a block of C/C++ code with org-babel according to its header arguments."
(org-babel-C-expand-C body params))
(defun org-babel-C-expand-C (body params)
"Expand C/C++ BODY according to its header arguments PARAMS."
"Expand a block of C/C++ code with org-babel according to its header arguments."
(let ((vars (org-babel--get-vars params))
(colnames (cdr (assq :colname-names params)))
(main-p (not (string= (cdr (assq :main params)) "no")))
@ -213,9 +212,7 @@ This function should only be called by `org-babel-execute:C' or
nil))
(namespaces (org-babel-read
(cdr (assq :namespaces params))
nil))
(prologue (cdr (assq :prologue params)))
(epilogue (cdr (assq :epilogue params))))
nil)))
(when (stringp includes)
(setq includes (split-string includes)))
(when (stringp namespaces)
@ -229,11 +226,6 @@ This function should only be called by `org-babel-execute:C' or
(nconc result (list (concat y " " x)))
(setq y nil)))
(setq defines (cdr result))))
(setq body
(concat
(and prologue (concat prologue "\n"))
body
(and epilogue (concat "\n" epilogue "\n"))))
(mapconcat 'identity
(list
;; includes
@ -277,7 +269,7 @@ This function should only be called by `org-babel-execute:C' or
body) "\n") "\n")))
(defun org-babel-C-expand-D (body params)
"Expand D BODY according to its header arguments PARAMS."
"Expand a block of D code with org-babel according to its header arguments."
(let ((vars (org-babel--get-vars params))
(colnames (cdr (assq :colname-names params)))
(main-p (not (string= (cdr (assq :main params)) "no")))
@ -321,15 +313,13 @@ This function should only be called by `org-babel-execute:C' or
(format "int main() {\n%s\nreturn 0;\n}\n" body)))
(defun org-babel-prep-session:C (_session _params)
"Throw and error that sessions are not supported.
This function does nothing as C is a compiled language with no support
for sessions."
"This function does nothing as C is a compiled language with no
support for sessions."
(error "C is a compiled language -- no support for sessions"))
(defun org-babel-load-session:C (_session _body _params)
"Throw and error that sessions are not supported.
This function does nothing as C is a compiled language with no support
for sessions."
"This function does nothing as C is a compiled language with no
support for sessions."
(error "C is a compiled language -- no support for sessions"))
;; helper functions
@ -349,7 +339,7 @@ FORMAT can be either a format string or a function which is called with VAL."
(type
(pcase basetype
(`integerp '("int" "%d"))
(`floatp '("double" "%s")) ;; %f rounds, use %s to print the float literally
(`floatp '("double" "%f"))
(`stringp
(list
(if (eq org-babel-c-variant 'd) "string" "const char*")
@ -389,11 +379,10 @@ FORMAT can be either a format string or a function which is called with VAL."
type))))
(defun org-babel-C-val-to-base-type (val)
"Determine the base type of VAL.
The type is:
- `integerp' if all base values are integers;
- `floatp' if all base values are either floating points or integers;
- `stringp' otherwise."
"Determine the base type of VAL which may be
`integerp' if all base values are integers
`floatp' if all base values are either floating points or integers
`stringp' otherwise."
(cond
((integerp val) 'integerp)
((floatp val) 'floatp)
@ -412,7 +401,7 @@ The type is:
(t 'stringp)))
(defun org-babel-C-var-to-C (pair)
"Convert PAIR of (var . val) C variable assignment."
"Convert an elisp val into a string of C code specifying a var of the same value."
;; TODO list support
(let ((var (car pair))
(val (cdr pair)))

View File

@ -1,6 +1,6 @@
;;; ob-R.el --- Babel Functions for R -*- lexical-binding: t; -*-
;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Dan Davison
@ -36,7 +36,7 @@
(require 'ob)
(declare-function orgtbl-to-tsv "org-table" (table params))
(declare-function run-ess-r "ext:ess-r-mode" (&optional start-args))
(declare-function R "ext:essd-r" (&optional start-args))
(declare-function inferior-ess-send-input "ext:ess-inf" ())
(declare-function ess-make-buffer-current "ext:ess-inf" ())
(declare-function ess-eval-buffer "ext:ess-inf" (vis))
@ -64,7 +64,6 @@
(colormodel . :any)
(useDingbats . :any)
(horizontal . :any)
(async . ((yes no)))
(results . ((file list vector table scalar verbatim)
(raw html latex org code pp drawer)
(replace silent none append prepend)
@ -92,6 +91,15 @@ this variable.")
:version "24.1"
:type 'string)
(defvar ess-current-process-name) ; dynamically scoped
(defvar ess-local-process-name) ; dynamically scoped
(defun org-babel-edit-prep:R (info)
(let ((session (cdr (assq :session (nth 2 info)))))
(when (and session
(string-prefix-p "*" session)
(string-suffix-p "*" session))
(org-babel-R-initiate-session session nil))))
;; The usage of utils::read.table() ensures that the command
;; read.table() can be found even in circumstances when the utils
;; package is not in the search path from R.
@ -148,7 +156,7 @@ This function is used when the table does not contain a header.")
"\n"))
(defun org-babel-execute:R (body params)
"Execute a block of R code BODY according to PARAMS.
"Execute a block of R code.
This function is called by `org-babel-execute-src-block'."
(save-excursion
(let* ((result-params (cdr (assq :result-params params)))
@ -207,8 +215,7 @@ This function is called by `org-babel-execute-src-block'."
;; helper functions
(defun org-babel-variable-assignments:R (params)
"Return list of R statements assigning the block's variables.
Retrieve variables from PARAMS."
"Return list of R statements assigning the block's variables."
(let ((vars (org-babel--get-vars params)))
(mapcar
(lambda (pair)
@ -254,44 +261,41 @@ Retrieve variables from PARAMS."
(t (format "%s <- %S" name (prin1-to-string value))))))
(defvar ess-current-process-name) ; dynamically scoped
(defvar ess-local-process-name) ; dynamically scoped
(defvar ess-ask-for-ess-directory) ; dynamically scoped
(defvar ess-gen-proc-buffer-name-function) ; defined in ess-inf.el
(defun org-babel-R-initiate-session (session params)
"Create or return the current R SESSION buffer.
Use PARAMS to set default directory when creating a new session."
"If there is not a current R process then create one."
(unless (string= session "none")
(let* ((session (or session "*R*"))
(ess-ask-for-ess-directory
(and (boundp 'ess-ask-for-ess-directory)
ess-ask-for-ess-directory
(not (cdr (assq :dir params)))))
;; Make ESS name the process buffer as SESSION.
(ess-gen-proc-buffer-name-function
(lambda (_) session)))
(let ((session (or session "*R*"))
(ess-ask-for-ess-directory
(and (boundp 'ess-ask-for-ess-directory)
ess-ask-for-ess-directory
(not (cdr (assq :dir params))))))
(if (org-babel-comint-buffer-livep session)
session
(save-window-excursion
(when (get-buffer session)
;; Session buffer exists, but with dead process
(set-buffer session))
(org-require-package 'ess-r-mode "ESS")
(set-buffer (run-ess-r))
(org-require-package 'ess "ESS") (R)
(let ((R-proc (get-process (or ess-local-process-name
ess-current-process-name))))
(while (process-get R-proc 'callbacks)
(ess-wait-for-process R-proc)))
(rename-buffer
(if (bufferp session)
(buffer-name session)
(if (stringp session)
session
(buffer-name))))
(current-buffer))))))
(defun org-babel-R-associate-session (session)
"Associate R code buffer with an R session.
Make SESSION be the inferior ESS process associated with the
current code buffer."
(when-let ((process (get-buffer-process session)))
(setq ess-local-process-name (process-name process))
(ess-make-buffer-current))
(setq-local ess-gen-proc-buffer-name-function (lambda (_) session)))
(setq ess-local-process-name
(process-name (get-buffer-process session)))
(ess-make-buffer-current))
(defvar org-babel-R-graphics-devices
'((:bmp "bmp" "filename")

View File

@ -1,6 +1,6 @@
;;; ob-awk.el --- Babel Functions for Awk -*- lexical-binding: t; -*-
;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Maintainer: Tyler Smith <tyler@plantarum.ca>
@ -48,18 +48,12 @@
(defvar org-babel-awk-command "awk"
"Name of the awk executable command.")
(defun org-babel-expand-body:awk (body params)
(defun org-babel-expand-body:awk (body _params)
"Expand BODY according to PARAMS, return the expanded body."
(let ((prologue (cdr (assq :prologue params)))
(epilogue (cdr (assq :epilogue params))))
(concat
(and prologue (concat prologue "\n"))
body
(and epilogue (concat "\n" epilogue "\n")))))
body)
(defun org-babel-execute:awk (body params)
"Execute a block of Awk code BODY with org-babel.
PARAMS is a plist of src block parameters .
"Execute a block of Awk code with org-babel.
This function is called by `org-babel-execute-src-block'."
(message "Executing Awk source code block")
(let* ((result-params (cdr (assq :result-params params)))
@ -106,9 +100,7 @@ This function is called by `org-babel-execute-src-block'."
(cdr (assq :rowname-names params)) (cdr (assq :rownames params))))))
(defun org-babel-awk-var-to-awk (var &optional sep)
"Return a printed value of VAR suitable for parsing with awk.
SEP, when non-nil is a separator used when converting list values to awk
table."
"Return a printed value of VAR suitable for parsing with awk."
(let ((echo-var (lambda (v) (if (stringp v) v (format "%S" v)))))
(cond
((and (listp var) (listp (car var)))

View File

@ -1,6 +1,6 @@
;;; ob-calc.el --- Babel Functions for Calc -*- lexical-binding: t; -*-
;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Maintainer: Tom Gillespie <tgbugs@gmail.com>
@ -44,19 +44,13 @@
(defvar org-babel-default-header-args:calc nil
"Default arguments for evaluating a calc source block.")
(defun org-babel-expand-body:calc (body params)
"Expand BODY according to PARAMS, return the expanded body."
(let ((prologue (cdr (assq :prologue params)))
(epilogue (cdr (assq :epilogue params))))
(concat
(and prologue (concat prologue "\n"))
body
(and epilogue (concat "\n" epilogue "\n")))))
(defun org-babel-expand-body:calc (body _params)
"Expand BODY according to PARAMS, return the expanded body." body)
(defvar org--var-syms) ; Dynamically scoped from org-babel-execute:calc
(defun org-babel-execute:calc (body params)
"Execute BODY of calc code with Babel using PARAMS."
"Execute a block of calc code with Babel."
(unless (get-buffer "*Calculator*")
(save-window-excursion (calc) (calc-quit)))
(let* ((vars (org-babel--get-vars params))
@ -64,19 +58,7 @@
(var-names (mapcar #'symbol-name org--var-syms)))
(mapc
(lambda (pair)
(let ((val (cdr pair)))
(calc-push-list
;; For a vector, Calc follows the format (vec 1 2 3 ...) so
;; a matrix becomes (vec (vec 1 2 3) (vec 4 5 6) ...). See
;; the comments in "Arithmetic routines." section of
;; calc.el.
(list (if (listp val)
(cons 'vec
(if (null (cdr val))
(car val)
(mapcar (lambda (x) (if (listp x) (cons 'vec x) x))
val)))
val))))
(calc-push-list (list (cdr pair)))
(calc-store-into (car pair)))
vars)
(mapc
@ -117,8 +99,6 @@
(calc-pop 1)))))
(defun org-babel-calc-maybe-resolve-var (el)
"Resolve user variables in EL.
EL is taken from the output of `math-read-exprs'."
(if (consp el)
(if (and (eq 'var (car el)) (member (cadr el) org--var-syms))
(progn

View File

@ -1,6 +1,6 @@
;;; ob-clojure.el --- Babel Functions for Clojure -*- lexical-binding: t; -*-
;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
;; Author: Joel Boehland, Eric Schulte, Oleh Krehel, Frederick Giasson
;; Maintainer: Daniel Kraus <daniel@kraus.my>
@ -237,9 +237,7 @@ or set the `:backend' header argument"))))
"clojure" (format "clojure -A%s" alias)
cmd0)
cmd0)))
(setq
org-babel-comint-prompt-regexp-old comint-prompt-regexp
comint-prompt-regexp inf-clojure-comint-prompt-regexp)
(setq comint-prompt-regexp inf-clojure-comint-prompt-regexp)
(funcall-interactively #'inf-clojure cmd)
(goto-char (point-max))))
(sit-for 1))

View File

@ -1,6 +1,6 @@
;;; ob-comint.el --- Babel Functions for Interaction with Comint Buffers -*- lexical-binding: t; -*-
;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Keywords: literate programming, reproducible research, comint
@ -58,47 +58,6 @@ executed inside the protection of `save-excursion' and
(let ((comint-input-filter (lambda (_input) nil)))
,@body))))))
(defvar-local org-babel-comint-prompt-regexp-old nil
"Fallback regexp used to detect prompt.")
(defcustom org-babel-comint-fallback-regexp-threshold 5.0
"Waiting time until trying to use fallback regexp to detect prompt.
This is useful when prompt unexpectedly changes."
:type 'float
:group 'org-babel)
(defun org-babel-comint--set-fallback-prompt ()
"Swap `comint-prompt-regexp' and `org-babel-comint-prompt-regexp-old'."
(when org-babel-comint-prompt-regexp-old
(let ((tmp comint-prompt-regexp))
(setq comint-prompt-regexp org-babel-comint-prompt-regexp-old
org-babel-comint-prompt-regexp-old tmp))))
(defun org-babel-comint--prompt-filter (string &optional prompt-regexp)
"Remove PROMPT-REGEXP from STRING.
PROMPT-REGEXP defaults to `comint-prompt-regexp'."
(let* ((prompt-regexp (or prompt-regexp comint-prompt-regexp))
;; We need newline in case if we do progressive replacement
;; of agglomerated comint prompts with `comint-prompt-regexp'
;; containing ^.
(separator "org-babel-comint--prompt-filter-separator\n"))
(while (string-match-p prompt-regexp string)
(setq string
(replace-regexp-in-string
(format "\\(?:%s\\)?\\(?:%s\\)[ \t]*" separator prompt-regexp)
separator string)))
(delete "" (split-string string separator))))
(defun org-babel-comint--echo-filter (string &optional echo)
"Remove ECHO from STRING."
(and echo string
(string-match
(replace-regexp-in-string "\n" "[\r\n]+" (regexp-quote echo))
string)
(setq string (substring string (match-end 0))))
string)
(defmacro org-babel-comint-with-output (meta &rest body)
"Evaluate BODY in BUFFER and return process output.
Will wait until EOE-INDICATOR appears in the output, then return
@ -115,7 +74,9 @@ or user `keyboard-quit' during execution of body."
(let ((buffer (nth 0 meta))
(eoe-indicator (nth 1 meta))
(remove-echo (nth 2 meta))
(full-body (nth 3 meta)))
(full-body (nth 3 meta))
(org-babel-comint-prompt-separator
"org-babel-comint-prompt-separator"))
`(org-babel-comint-in-buffer ,buffer
(let* ((string-buffer "")
(comint-output-filter-functions
@ -132,39 +93,43 @@ or user `keyboard-quit' during execution of body."
;; pass FULL-BODY to process
,@body
;; wait for end-of-evaluation indicator
(let ((start-time (current-time)))
(while (progn
(goto-char comint-last-input-end)
(not (save-excursion
(and (re-search-forward
(regexp-quote ,eoe-indicator) nil t)
(re-search-forward
comint-prompt-regexp nil t)))))
(accept-process-output
(get-buffer-process (current-buffer))
org-babel-comint-fallback-regexp-threshold)
(when (and org-babel-comint-prompt-regexp-old
(> (float-time (time-since start-time))
org-babel-comint-fallback-regexp-threshold)
(progn
(goto-char comint-last-input-end)
(save-excursion
(and
(re-search-forward
(regexp-quote ,eoe-indicator) nil t)
(re-search-forward
org-babel-comint-prompt-regexp-old nil t)))))
(org-babel-comint--set-fallback-prompt))))
(while (progn
(goto-char comint-last-input-end)
(not (save-excursion
(and (re-search-forward
(regexp-quote ,eoe-indicator) nil t)
(re-search-forward
comint-prompt-regexp nil t)))))
(accept-process-output (get-buffer-process (current-buffer))))
;; replace cut dangling text
(goto-char (process-mark (get-buffer-process (current-buffer))))
(insert dangling-text)
;; remove echo'd FULL-BODY from input
(and ,remove-echo ,full-body
(setq string-buffer (org-babel-comint--echo-filter string-buffer ,full-body)))
;; Filter out prompts.
(org-babel-comint--prompt-filter string-buffer)))))
(setq string-buffer
(replace-regexp-in-string
;; Sometimes, we get multiple agglomerated
;; prompts together in a single output:
;; "prompt prompt prompt output"
;; Remove them progressively, so that
;; possible "^" in the prompt regexp gets to
;; work as we remove the heading prompt
;; instance.
(if (string-prefix-p "^" comint-prompt-regexp)
(format "^\\(%s\\)+" (substring comint-prompt-regexp 1))
comint-prompt-regexp)
,org-babel-comint-prompt-separator
string-buffer))
;; remove echo'd FULL-BODY from input
(when (and ,remove-echo ,full-body
(string-match
(replace-regexp-in-string
"\n" "[\r\n]+" (regexp-quote (or ,full-body "")))
string-buffer))
(setq string-buffer (substring string-buffer (match-end 0))))
(delete "" (split-string
string-buffer
,org-babel-comint-prompt-separator))))))
(defun org-babel-comint-input-command (buffer cmd)
"Pass CMD to BUFFER.
@ -180,23 +145,11 @@ The input will not be echoed."
Note: this is only safe when waiting for the result of a single
statement (not large blocks of code)."
(org-babel-comint-in-buffer buffer
(let ((start-time (current-time)))
(while (progn
(goto-char comint-last-input-end)
(not (and (re-search-forward comint-prompt-regexp nil t)
(goto-char (match-beginning 0)))))
(accept-process-output
(get-buffer-process buffer)
org-babel-comint-fallback-regexp-threshold)
(when (and org-babel-comint-prompt-regexp-old
(> (float-time (time-since start-time))
org-babel-comint-fallback-regexp-threshold)
(progn
(goto-char comint-last-input-end)
(save-excursion
(re-search-forward
org-babel-comint-prompt-regexp-old nil t))))
(org-babel-comint--set-fallback-prompt))))))
(while (progn
(goto-char comint-last-input-end)
(not (and (re-search-forward comint-prompt-regexp nil t)
(goto-char (match-beginning 0)))))
(accept-process-output (get-buffer-process buffer)))))
(defun org-babel-comint-eval-invisibly-and-wait-for-file
(buffer file string &optional period)
@ -239,8 +192,8 @@ comint process. It should return a string that will be passed
to `org-babel-insert-result'.")
(defvar-local org-babel-comint-async-dangling nil
"Dangling piece of the last process output, as a string.
Used when `org-babel-comint-async-indicator' is spread across multiple
"Dangling piece of the last process output, in case
`org-babel-comint-async-indicator' is spread across multiple
comint outputs due to buffering.")
(defun org-babel-comint-use-async (params)
@ -268,8 +221,6 @@ STRING contains the output originally inserted into the comint buffer."
(file-callback org-babel-comint-async-file-callback)
(combined-string (concat org-babel-comint-async-dangling string))
(new-dangling combined-string)
;; Assumes comint filter called with session buffer current
(session-dir default-directory)
;; list of UUID's matched by `org-babel-comint-async-indicator'
uuid-list)
(with-temp-buffer
@ -294,8 +245,7 @@ STRING contains the output originally inserted into the comint buffer."
(let* ((info (org-babel-get-src-block-info))
(params (nth 2 info))
(result-params
(cdr (assq :result-params params)))
(default-directory session-dir))
(cdr (assq :result-params params))))
(org-babel-insert-result
(funcall file-callback
(nth
@ -325,10 +275,9 @@ STRING contains the output originally inserted into the comint buffer."
until (and (equal (match-string 1) "start")
(equal (match-string 2) uuid))
finally return (+ 1 (match-end 0)))))
;; Remove prompt
(res-promptless (org-trim (string-join (mapcar #'org-trim (org-babel-comint--prompt-filter res-str-raw)) "\n") "\n"))
;; Apply user callback
(res-str (funcall org-babel-comint-async-chunk-callback res-promptless)))
;; Apply callback to clean up the result
(res-str (funcall org-babel-comint-async-chunk-callback
res-str-raw)))
;; Search for uuid in associated org-buffers to insert results
(cl-loop for buf in org-buffers
until (with-current-buffer buf
@ -339,8 +288,7 @@ STRING contains the output originally inserted into the comint buffer."
(let* ((info (org-babel-get-src-block-info))
(params (nth 2 info))
(result-params
(cdr (assq :result-params params)))
(default-directory session-dir))
(cdr (assq :result-params params))))
(org-babel-insert-result
res-str result-params info))
t))))

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
;;; ob-css.el --- Babel Functions for CSS -*- lexical-binding: t; -*-
;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Keywords: literate programming, reproducible research
@ -36,7 +36,7 @@
(defvar org-babel-default-header-args:css '())
(defun org-babel-execute:css (body _params)
"Execute BODY of CSS code.
"Execute a block of CSS code.
This function is called by `org-babel-execute-src-block'."
body)

View File

@ -1,6 +1,6 @@
;;; ob-ditaa.el --- Babel Functions for ditaa -*- lexical-binding: t; -*-
;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Keywords: literate programming, reproducible research
@ -83,11 +83,11 @@ Do not leave leading or trailing spaces in this string."
:type 'string)
(defun org-babel-execute:ditaa (body params)
"Execute BODY of Ditaa code with org-babel according to PARAMS.
"Execute a block of Ditaa code with org-babel.
This function is called by `org-babel-execute-src-block'."
(let* ((out-file (or (cdr (assq :file params))
(error
"Ditaa code block requires :file header argument")))
"ditaa code block requires :file header argument")))
(cmdline (cdr (assq :cmdline params)))
(java (cdr (assq :java params)))
(in-file (org-babel-temp-file "ditaa-"))

View File

@ -1,6 +1,6 @@
;;; ob-dot.el --- Babel Functions for dot -*- lexical-binding: t; -*-
;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Maintainer: Justin Abrahms <justin@abrah.ms>
@ -51,9 +51,7 @@
(defun org-babel-expand-body:dot (body params)
"Expand BODY according to PARAMS, return the expanded body."
(let ((vars (org-babel--get-vars params))
(prologue (cdr (assq :prologue params)))
(epilogue (cdr (assq :epilogue params))))
(let ((vars (org-babel--get-vars params)))
(mapc
(lambda (pair)
(let ((name (symbol-name (car pair)))
@ -66,13 +64,10 @@
t
t))))
vars)
(concat
(and prologue (concat prologue "\n"))
body
(and epilogue (concat "\n" epilogue "\n")))))
body))
(defun org-babel-execute:dot (body params)
"Execute Dot BODY with org-babel according to PARAMS.
"Execute a block of Dot code with org-babel.
This function is called by `org-babel-execute-src-block'."
(let* ((out-file (cdr (or (assq :file params)
(error "You need to specify a :file parameter"))))

View File

@ -1,6 +1,6 @@
;;; ob-emacs-lisp.el --- Babel Functions for Emacs-lisp Code -*- lexical-binding: t; -*-
;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Keywords: literate programming, reproducible research
@ -53,23 +53,18 @@ by `org-edit-src-code'.")
"Expand BODY according to PARAMS, return the expanded body."
(let ((vars (org-babel--get-vars params))
(print-level nil)
(print-length nil)
(prologue (cdr (assq :prologue params)))
(epilogue (cdr (assq :epilogue params))))
(print-length nil))
(if (null vars) (concat body "\n")
(format "(let (%s)\n%s%s%s\n)"
(format "(let (%s)\n%s\n)"
(mapconcat
(lambda (var)
(format "%S" `(,(car var) ',(cdr var))))
vars "\n ")
(if prologue (concat prologue "\n ") "")
body
(if epilogue (concat "\n " epilogue "\n") "")))))
body))))
(defun org-babel-execute:emacs-lisp (body params)
"Execute emacs-lisp code BODY according to PARAMS."
"Execute a block of emacs-lisp code with Babel."
(let* ((lexical (cdr (assq :lexical params)))
(session (cdr (assq :session params)))
(result-params (cdr (assq :result-params params)))
(body (format (if (member "output" result-params)
"(with-output-to-string %s\n)"
@ -80,8 +75,6 @@ by `org-edit-src-code'.")
(concat "(pp " body ")")
body))
(org-babel-emacs-lisp-lexical lexical))))
(when (and session (not (equal session "none")))
(error "ob-emacs-lisp backend does not support sessions"))
(org-babel-result-cond result-params
(let ((print-level nil)
(print-length nil))
@ -107,17 +100,12 @@ and the LEXICAL argument to `eval'."
(defun org-babel-edit-prep:emacs-lisp (info)
"Set `lexical-binding' in Org edit buffer.
Set `lexical-binding' in Org edit buffer according to the
corresponding :lexical source block argument provide in the INFO
channel, as returned by `org-babel-get-src-block-info'."
corresponding :lexical source block argument."
(setq lexical-binding
(org-babel-emacs-lisp-lexical
(org-babel-read
(cdr (assq :lexical (nth 2 info)))))))
(defun org-babel-prep-session:emacs-lisp (_session _params)
"Return an error because we do not support sessions."
(error "ob-emacs-lisp backend does not support sessions"))
(org-babel-make-language-alias "elisp" "emacs-lisp")
(provide 'ob-emacs-lisp)

View File

@ -1,6 +1,6 @@
;;; ob-eshell.el --- Babel Functions for Eshell -*- lexical-binding: t; -*-
;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
;; Author: stardiviner <numbchild@gmail.com>
;; Maintainer: stardiviner <numbchild@gmail.com>
@ -94,11 +94,10 @@ The PARAMS are variables assignments."
session))
(defun org-babel-variable-assignments:eshell (params)
"Convert ob-eshell variables from PARAMS into Eshell variables assignments."
"Convert ob-eshell :var specified variables into Eshell variables assignments."
(mapcar
(lambda (pair)
;; Use `ignore' to suppress value in the command output.
(format "(ignore (setq %s %S))" (car pair) (cdr pair)))
(format "(setq %s %S)" (car pair) (cdr pair)))
(org-babel--get-vars params)))
(defun org-babel-load-session:eshell (session body params)

View File

@ -1,6 +1,6 @@
;;; ob-eval.el --- Babel Functions for External Code Evaluation -*- lexical-binding: t; -*-
;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Keywords: literate programming, reproducible research, comint
@ -106,6 +106,11 @@ returned."
(error-file (if error-buffer (org-babel-temp-file "ob-error-") nil))
(shell-file-name (org-babel--get-shell-file-name))
exit-status)
;; There is an error in `process-file' when `error-file' exists.
;; This is fixed in Emacs trunk as of 2012-12-21; let's use this
;; workaround for now.
(unless (file-remote-p default-directory)
(delete-file error-file))
;; we always call this with 'replace, remove conditional
;; Replace specified region with output from command.
(org-babel--write-temp-buffer-input-file input-file)

View File

@ -1,6 +1,6 @@
;;; ob-exp.el --- Exportation of Babel Source Blocks -*- lexical-binding: t; -*-
;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
;; Authors: Eric Schulte
;; Dan Davison
@ -32,10 +32,8 @@
(declare-function org-babel-lob-get-info "ob-lob" (&optional datum no-eval))
(declare-function org-element-at-point "org-element" (&optional pom cached-only))
(declare-function org-element-context "org-element" (&optional element))
(declare-function org-element-property "org-element-ast" (property node))
(declare-function org-element-begin "org-element" (node))
(declare-function org-element-end "org-element" (node))
(declare-function org-element-type "org-element-ast" (node &optional anonymous))
(declare-function org-element-property "org-element" (property element))
(declare-function org-element-type "org-element" (element))
(declare-function org-escape-code-in-string "org-src" (s))
(declare-function org-export-copy-buffer "ox"
(&optional buffer drop-visibility
@ -43,7 +41,8 @@
drop-locals))
(declare-function org-in-commented-heading-p "org" (&optional no-inheritance element))
(declare-function org-in-archived-heading-p "org" (&optional no-inheritance element))
(declare-function org-src-preserve-indentation-p "org-src" (node))
(defvar org-src-preserve-indentation)
(defcustom org-export-use-babel t
"Switch controlling code evaluation and header processing during export.
@ -172,7 +171,7 @@ this template."
;; buffer.
(org-fold-core-ignore-modifications
(while (re-search-forward regexp nil t)
(setq element (save-match-data (org-element-at-point)))
(setq element (org-element-at-point))
(unless (save-match-data
(or (org-in-commented-heading-p nil element)
(org-in-archived-heading-p nil element)))
@ -196,11 +195,11 @@ this template."
nil)
(type type)))
(begin
(copy-marker (org-element-begin element)))
(copy-marker (org-element-property :begin element)))
(end
(copy-marker
(save-excursion
(goto-char (org-element-end element))
(goto-char (org-element-property :end element))
(skip-chars-backward " \r\t\n")
(point)))))
(pcase type
@ -218,27 +217,22 @@ this template."
(goto-char begin)
(let ((replacement
(org-babel-exp-do-export info 'inline)))
(cond
((equal replacement "")
;; Replacement code is empty: remove
;; inline source block, including extra
;; white space that might have been
;; created when inserting results.
(delete-region begin
(progn (goto-char end)
(skip-chars-forward " \t")
(point))))
((not replacement)
;; Replacement code cannot be determined.
;; Leave the code block as is.
(goto-char end))
;; Otherwise: remove inline source block
;; but preserve following white spaces.
;; Then insert value.
((not (string= replacement
(buffer-substring begin end)))
(delete-region begin end)
(insert replacement))))))
(if (equal replacement "")
;; Replacement code is empty: remove
;; inline source block, including extra
;; white space that might have been
;; created when inserting results.
(delete-region begin
(progn (goto-char end)
(skip-chars-forward " \t")
(point)))
;; Otherwise: remove inline source block
;; but preserve following white spaces.
;; Then insert value.
(unless (string= replacement
(buffer-substring begin end))
(delete-region begin end)
(insert replacement))))))
((or `babel-call `inline-babel-call)
(org-babel-exp-do-export
(or (org-babel-lob-get-info element)
@ -254,27 +248,21 @@ this template."
;; the object/element, including any extra
;; white space that might have been created
;; when including results.
(cond
((equal rep "")
(delete-region
begin
(progn (goto-char end)
(if (not (eq type 'babel-call))
(progn (skip-chars-forward " \t")
(point))
(skip-chars-forward " \r\t\n")
(line-beginning-position)))))
((not rep)
;; Replacement code cannot be determined.
;; Leave the code block as is.
(goto-char end))
(t
(if (equal rep "")
(delete-region
begin
(progn (goto-char end)
(if (not (eq type 'babel-call))
(progn (skip-chars-forward " \t")
(point))
(skip-chars-forward " \r\t\n")
(line-beginning-position))))
;; Otherwise, preserve trailing
;; spaces/newlines and then, insert
;; replacement string.
(goto-char begin)
(delete-region begin end)
(insert rep)))))
(insert rep))))
(`src-block
(let ((match-start (copy-marker (match-beginning 0)))
(ind (org-current-text-indentation)))
@ -289,26 +277,28 @@ this template."
((equal replacement "")
(goto-char end)
(skip-chars-forward " \r\t\n")
(forward-line 0)
(beginning-of-line)
(delete-region begin (point)))
(t
(if (org-src-preserve-indentation-p element)
(if (or org-src-preserve-indentation
(org-element-property
:preserve-indent element))
;; Indent only code block
;; markers.
(with-temp-buffer
;; Do not use tabs for block
;; indentation.
(when (fboundp 'indent-tabs-mode)
;; Do not use tabs for block
;; indentation.
(when (fboundp 'indent-tabs-mode)
(indent-tabs-mode -1)
;; FIXME: Emacs 26
;; compatibility.
(setq-local indent-tabs-mode nil))
(insert replacement)
(skip-chars-backward " \r\t\n")
(indent-line-to ind)
(goto-char 1)
(indent-line-to ind)
(setq replacement (buffer-string)))
(insert replacement)
(skip-chars-backward " \r\t\n")
(indent-line-to ind)
(goto-char 1)
(indent-line-to ind)
(setq replacement (buffer-string)))
;; Indent everything.
(with-temp-buffer
;; Do not use tabs for block
@ -342,12 +332,7 @@ this template."
'(org-reference nil))))))
(defun org-babel-exp-do-export (info type &optional hash)
"Return a string with the exported content of a code block defined by INFO.
TYPE is the code block type: `block', `inline', or `lob'. HASH is the
result hash.
Return nil when exported content cannot be determined.
"Return a string with the exported content of a code block.
The function respects the value of the :exports header argument."
(let ((silently (lambda () (let ((session (cdr (assq :session (nth 2 info)))))
(unless (equal "none" session)
@ -361,10 +346,7 @@ The function respects the value of the :exports header argument."
("results" (org-babel-exp-results info type nil hash) "")
("both"
(org-babel-exp-results info type nil hash)
(org-babel-exp-code info type))
(unknown-value
(warn "Unknown value of src block parameter :exports %S" unknown-value)
nil))))
(org-babel-exp-code info type)))))
(defcustom org-babel-exp-code-template
"#+begin_src %lang%switches%flags\n%body\n#+end_src"
@ -410,7 +392,7 @@ replaced with its value."
:package-version '(Org . "8.3"))
(defun org-babel-exp-code (info type)
"Return the original code block of TYPE defined by INFO, formatted for export."
"Return the original code block formatted for export."
(setf (nth 1 info)
(if (string= "strip-export" (cdr (assq :noweb (nth 2 info))))
(replace-regexp-in-string
@ -440,9 +422,6 @@ replaced with its value."
(defun org-babel-exp-results (info type &optional silent hash)
"Evaluate and return the results of the current code block for export.
INFO is as returned by `org-babel-get-src-block-info'. TYPE is the
code block type. HASH is the result hash.
Results are prepared in a manner suitable for export by Org mode.
This function is called by `org-babel-exp-do-export'. The code
block will be evaluated. Optional argument SILENT can be used to

View File

@ -1,6 +1,6 @@
;;; ob-forth.el --- Babel Functions for Forth -*- lexical-binding: t; -*-
;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Keywords: literate programming, reproducible research, forth
@ -45,7 +45,7 @@
"Default header arguments for forth code blocks.")
(defun org-babel-execute:forth (body params)
"Execute Forth BODY according to PARAMS.
"Execute a block of Forth code with org-babel.
This function is called by `org-babel-execute-src-block'."
(if (string= "none" (cdr (assq :session params)))
(error "Non-session evaluation not supported for Forth code blocks")
@ -55,7 +55,6 @@ This function is called by `org-babel-execute-src-block'."
(car (last all-results))))))
(defun org-babel-forth-session-execute (body params)
"Execute Forth BODY in session defined via PARAMS."
(org-require-package 'forth-mode)
(let ((proc (forth-proc))
(rx " \\(\n:\\|compiled\n\\|ok\n\\)")

View File

@ -1,6 +1,6 @@
;;; ob-fortran.el --- Babel Functions for Fortran -*- lexical-binding: t; -*-
;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
;; Authors: Sergey Litvinov
;; Eric Schulte
@ -51,8 +51,7 @@
:type 'string)
(defun org-babel-execute:fortran (body params)
"Execute Fortran BODY according to PARAMS.
This function is called by `org-babel-execute-src-block'."
"This function should only be called by `org-babel-execute:fortran'."
(let* ((tmp-src-file (org-babel-temp-file "fortran-src-" ".F90"))
(tmp-bin-file (org-babel-temp-file "fortran-bin-" org-babel-exeext))
(cmdline (cdr (assq :cmdline params)))
@ -83,10 +82,9 @@ This function is called by `org-babel-execute-src-block'."
(cdr (assq :rowname-names params)) (cdr (assq :rownames params)))))))
(defun org-babel-expand-body:fortran (body params)
"Expand a fortran BODY according to its header arguments defined in PARAMS."
"Expand a block of fortran or fortran code with org-babel according to
its header arguments."
(let ((vars (org-babel--get-vars params))
(prologue (cdr (assq :prologue params)))
(epilogue (cdr (assq :epilogue params)))
(main-p (not (string= (cdr (assq :main params)) "no")))
(includes (or (cdr (assq :includes params))
(org-babel-read (org-entry-get nil "includes" t))))
@ -109,20 +107,12 @@ This function is called by `org-babel-execute-src-block'."
(concat
;; variables
(mapconcat 'org-babel-fortran-var-to-fortran vars "\n")
(and prologue (concat prologue "\n"))
body
(and prologue (concat prologue "\n")))
body)
params)
(concat
(and prologue (concat prologue "\n"))
body
(and epilogue (concat "\n" epilogue "\n"))))
"\n")
"\n")))
body) "\n") "\n")))
(defun org-babel-fortran-ensure-main-wrap (body params)
"Wrap BODY in a \"program ... end program\" block if none exists.
Variable assignments are derived from PARAMS."
"Wrap body in a \"program ... end program\" block if none exists."
(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"))
@ -130,22 +120,20 @@ Variable assignments are derived from PARAMS."
(format "program main\n%s\nend program main\n" body)))
(defun org-babel-prep-session:fortran (_session _params)
"Do nothing.
This function does nothing as fortran is a compiled language with no
"This function does nothing as fortran is a compiled language with no
support for sessions."
(error "Fortran is a compiled languages -- no support for sessions"))
(defun org-babel-load-session:fortran (_session _body _params)
"Do nothing.
This function does nothing as fortran is a compiled language with no
"This function does nothing as fortran is a compiled language with no
support for sessions."
(error "Fortran is a compiled languages -- no support for sessions"))
;; helper functions
(defun org-babel-fortran-var-to-fortran (pair)
"Convert PAIR of (VAR . VAL) into a string of fortran code.
The fortran code will assign VAL to VAR variable."
"Convert an elisp val into a string of fortran code specifying a var
of the same value."
;; TODO list support
(let ((var (car pair))
(val (cdr pair)))
@ -176,7 +164,7 @@ The fortran code will assign VAL to VAR variable."
(error "The type of parameter %s is not supported by ob-fortran" var)))))
(defun org-babel-fortran-transform-list (val)
"Return a fortran representation of enclose syntactic list VAL."
"Return a fortran representation of enclose syntactic lists."
(if (listp val)
(concat "(/" (mapconcat #'org-babel-fortran-transform-list val ", ") "/)")
(format "%S" val)))

View File

@ -1,9 +1,9 @@
;;; ob-gnuplot.el --- Babel Functions for Gnuplot -*- lexical-binding: t; -*-
;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Maintainer: Ihor Radchenko <yantar92 at posteo dot net>
;; Maintainer: Ihor Radchenko <yantar92@gmail.com>
;; Keywords: literate programming, reproducible research
;; URL: https://orgmode.org
@ -45,7 +45,6 @@
(require 'ob)
(require 'org-macs)
(require 'ox-ascii)
(declare-function org-time-string-to-time "org" (s))
(declare-function orgtbl-to-generic "org-table" (table params))
@ -187,7 +186,7 @@ code."
;; value of the variable
(mapc (lambda (pair)
(setq body (replace-regexp-in-string
(format "\\$%s" (car pair)) (cdr pair) body t t)))
(format "\\$%s" (car pair)) (cdr pair) body)))
vars)
(when prologue (funcall add-to-body prologue))
(when epilogue (setq body (concat body "\n" epilogue)))
@ -197,7 +196,7 @@ code."
body))
(defun org-babel-execute:gnuplot (body params)
"Execute Gnuplot BODY according to PARAMS.
"Execute a block of Gnuplot code.
This function is called by `org-babel-execute-src-block'."
(org-require-package 'gnuplot)
(let ((session (cdr (assq :session params)))
@ -252,8 +251,7 @@ This function is called by `org-babel-execute-src-block'."
buffer)))
(defun org-babel-variable-assignments:gnuplot (params)
"Return list of gnuplot statements assigning the block's variables.
PARAMS is src block parameters alist defining variable assignments."
"Return list of gnuplot statements assigning the block's variables."
(mapcar
(lambda (pair) (format "%s = \"%s\"" (car pair) (cdr pair)))
(org-babel-gnuplot-process-vars params)))
@ -297,29 +295,14 @@ Pass PARAMS through to `orgtbl-to-generic' when exporting TABLE."
(require 'ox-org)
(with-temp-file data-file
(insert (let ((org-babel-gnuplot-timestamp-fmt
(or (plist-get params :timefmt) "%Y-%m-%d-%H:%M:%S"))
;; Create custom limited backend that will disable
;; advanced ASCII export features that may alter the
;; original data.
(ob-gnuplot-data
(org-export-create-backend
:parent 'ascii
:transcoders
`(;; Do not try to resolve links. Export them verbatim.
(link . (lambda (link _ _) (org-element-interpret-data link)))
;; Drop emphasis markers from verbatim and code.
;; This way, data can use verbatim when escaping
;; is necessary and yet be readable by Gnuplot,
;; which is not aware about Org's markup.
(verbatim . (lambda (verbatim _ _) (org-element-property :value verbatim)))
(code . (lambda (code _ _) (org-element-property :value code)))))))
(or (plist-get params :timefmt) "%Y-%m-%d-%H:%M:%S")))
(orgtbl-to-generic
table
(org-combine-plists
`( :sep "\t" :fmt org-babel-gnuplot-quote-tsv-field
'( :sep "\t" :fmt org-babel-gnuplot-quote-tsv-field
;; Two setting below are needed to make :fmt work.
:raw t
:backend ,ob-gnuplot-data)
:backend ascii)
params)))))
data-file)

View File

@ -1,6 +1,6 @@
;;; ob-groovy.el --- Babel Functions for Groovy -*- lexical-binding: t; -*-
;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
;; Author: Miro Bezjak <bezjak.miro@gmail.com>
;; Maintainer: Palak Mathur <palakmathur@gmail.com>
@ -50,7 +50,7 @@ parameters may be used, like groovy -v"
:type 'string)
(defun org-babel-execute:groovy (body params)
"Execute Groovy BODY according to PARAMS.
"Execute a block of Groovy code with org-babel.
This function is called by `org-babel-execute-src-block'."
(message "Executing Groovy source code block")
(let* ((processed-params (org-babel-process-params params))
@ -81,7 +81,6 @@ println(new Runner().run())
(defun org-babel-groovy-evaluate
(session body &optional result-type result-params)
"Evaluate BODY in external Groovy process.
SESSION must be nil as sessions are not yet supported.
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."
@ -108,8 +107,9 @@ in BODY as elisp."
(error "Sessions are not (yet) supported for Groovy"))
(defun org-babel-groovy-initiate-session (&optional _session)
"Do nothing.
Sessions are not supported in Groovy."
"If there is not a current inferior-process-buffer in SESSION
then create. Return the initialized session. Sessions are not
supported in Groovy."
nil)
(provide 'ob-groovy)

View File

@ -1,6 +1,6 @@
;;; ob-haskell.el --- Babel Functions for Haskell -*- lexical-binding: t; -*-
;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Maintainer: Lawrence Bottorff <borgauf@gmail.com>
@ -61,7 +61,7 @@
(defvar org-babel-haskell-lhs2tex-command "lhs2tex")
(defvar org-babel-haskell-eoe "org-babel-haskell-eoe")
(defvar org-babel-haskell-eoe "\"org-babel-haskell-eoe\"")
(defvar haskell-prompt-regexp)
@ -77,35 +77,8 @@ a parameter, such as \"ghc -v\"."
(defconst org-babel-header-args:haskell '((compile . :any))
"Haskell-specific header arguments.")
(defun org-babel-haskell-with-session--worker (params todo)
"See `org-babel-haskell-with-session'."
(let* ((sn (cdr (assq :session params)))
(session (org-babel-haskell-initiate-session sn params))
(one-shot (equal sn "none")))
(unwind-protect
(funcall todo session)
(when (and one-shot (buffer-live-p session))
;; As we don't control how the session temporary buffer is
;; created, we need to explicitly work around the hooks and
;; query functions.
(with-current-buffer session
(let ((kill-buffer-query-functions nil)
(kill-buffer-hook nil))
(kill-buffer session)))))))
(defmacro org-babel-haskell-with-session (session-symbol params &rest body)
"Get the session identified by PARAMS and run BODY with it.
Get or create a session, as needed to match PARAMS. Assign the session to
SESSION-SYMBOL. Execute BODY. Destroy the session if needed.
Return the value of the last form of BODY."
(declare (indent 2) (debug (symbolp form body)))
`(org-babel-haskell-with-session--worker ,params (lambda (,session-symbol) ,@body)))
(defun org-babel-haskell-execute (body params)
"Execute Haskell BODY according to PARAMS.
This function should only be called by `org-babel-execute:haskell'."
"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
@ -152,60 +125,36 @@ This function should only be called by `org-babel-execute:haskell'."
(org-require-package 'inf-haskell "haskell-mode")
(add-hook 'inferior-haskell-hook
(lambda ()
(setq-local
org-babel-comint-prompt-regexp-old comint-prompt-regexp
comint-prompt-regexp
(concat haskell-prompt-regexp "\\|^λ?> "))))
(org-babel-haskell-with-session session params
(cl-labels
((send-txt-to-ghci (txt)
(insert txt) (comint-send-input nil t))
(send-eoe ()
(send-txt-to-ghci (concat "putStrLn \"" org-babel-haskell-eoe "\"\n")))
(comint-with-output (todo)
(let ((comint-preoutput-filter-functions
(cons 'ansi-color-filter-apply
comint-preoutput-filter-functions)))
(org-babel-comint-with-output
(session org-babel-haskell-eoe nil nil)
(funcall todo)))))
(let* ((result-type (cdr (assq :result-type params)))
(full-body (org-babel-expand-body:generic
body params
(org-babel-variable-assignments:haskell params)))
(raw (pcase result-type
(`output
(comint-with-output
(lambda () (send-txt-to-ghci (org-trim full-body)) (send-eoe))))
(`value
;; We first compute the value and store it,
;; ignoring any output.
(comint-with-output
(lambda ()
(send-txt-to-ghci "__LAST_VALUE_IMPROBABLE_NAME__=()::()\n")
(send-txt-to-ghci (org-trim full-body))
(send-txt-to-ghci "__LAST_VALUE_IMPROBABLE_NAME__=it\n")
(send-eoe)))
;; We now display and capture the value.
(comint-with-output
(lambda()
(send-txt-to-ghci "__LAST_VALUE_IMPROBABLE_NAME__\n")
(send-eoe))))))
(results (mapcar #'org-strip-quotes
(cdr (member org-babel-haskell-eoe
(reverse (mapcar #'org-trim raw)))))))
(org-babel-reassemble-table
(let ((result
(pcase result-type
(`output (mapconcat #'identity (reverse results) "\n"))
(`value (car results)))))
(org-babel-result-cond (cdr (assq :result-params params))
result (when result (org-babel-script-escape result))))
(org-babel-pick-name (cdr (assq :colname-names params))
(cdr (assq :colname-names params)))
(org-babel-pick-name (cdr (assq :rowname-names params))
(cdr (assq :rowname-names params))))))))
(setq-local comint-prompt-regexp
(concat haskell-prompt-regexp "\\|^λ?> "))))
(let* ((session (cdr (assq :session params)))
(result-type (cdr (assq :result-type params)))
(full-body (org-babel-expand-body:generic
body params
(org-babel-variable-assignments:haskell params)))
(session (org-babel-haskell-initiate-session session params))
(comint-preoutput-filter-functions
(cons 'ansi-color-filter-apply comint-preoutput-filter-functions))
(raw (org-babel-comint-with-output
(session org-babel-haskell-eoe nil full-body)
(insert (org-trim full-body))
(comint-send-input nil t)
(insert org-babel-haskell-eoe)
(comint-send-input nil t)))
(results (mapcar #'org-strip-quotes
(cdr (member org-babel-haskell-eoe
(reverse (mapcar #'org-trim raw)))))))
(org-babel-reassemble-table
(let ((result
(pcase result-type
(`output (mapconcat #'identity (reverse results) "\n"))
(`value (car results)))))
(org-babel-result-cond (cdr (assq :result-params params))
result (when result (org-babel-script-escape result))))
(org-babel-pick-name (cdr (assq :colname-names params))
(cdr (assq :colname-names params)))
(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."
@ -214,65 +163,13 @@ This function should only be called by `org-babel-execute:haskell'."
(org-babel-interpret-haskell body params)
(org-babel-haskell-execute body params))))
;; Variable defined in inf-haskell (haskell-mode package).
(defvar inferior-haskell-buffer)
(defvar inferior-haskell-root-dir)
(defun org-babel-haskell-initiate-session (&optional session-name _params)
(defun org-babel-haskell-initiate-session (&optional _session _params)
"Initiate a haskell session.
Return the initialized session, i.e. the buffer for this session.
When SESSION-NAME is nil, use a global session named
\"*ob-haskell*\". When SESSION-NAME is the string \"none\", use
a temporary buffer. Else, (re)use the session named
SESSION-NAME. The buffer name is the session name. See also
`org-babel-haskell-with-session'."
If there is not a current inferior-process-buffer in SESSION
then create one. Return the initialized session."
(org-require-package 'inf-haskell "haskell-mode")
(cond
((equal "none" session-name)
;; Temporary buffer name.
(setq session-name (generate-new-buffer-name " *ob-haskell-tmp*")))
((eq nil session-name)
;; The global default session. As haskell-mode is using the buffer
;; named "*haskell*", we stay away from it.
(setq session-name "*ob-haskell*"))
((not (stringp session-name))
(error "session-name must be a string")))
(let ((session (get-buffer session-name)))
;; NOTE: By construction, as SESSION-NAME is a string, session is
;; either nil or a live buffer.
(save-window-excursion
(or (org-babel-comint-buffer-livep session)
(let ((inferior-haskell-buffer session))
;; As inferior-haskell expects the buffer to be named
;; "*haskell*", we temporarily rename it while executing
;; `run-haskell' (unless the user explicitly requested to
;; use the name "*haskell*").
(when (not (equal "*haskell*" session-name))
(when (bufferp session)
(when (bufferp "*haskell*")
(user-error "Conflicting buffer '*haskell*', rename it or kill it"))
(with-current-buffer session (rename-buffer "*haskell*"))))
(unwind-protect
(let ((inferior-haskell-root-dir default-directory))
(run-haskell)
(sleep-for 0.25)
(setq session inferior-haskell-buffer))
(when (and (not (equal "*haskell*" session-name))
(bufferp session))
(with-current-buffer session (rename-buffer session-name))))
;; Disable secondary prompt: If we do not do this,
;; org-comint may treat secondary prompts as a part of
;; output.
(org-babel-comint-input-command
session
":set prompt-cont \"\"")
session)
))
session))
(or (get-buffer "*haskell*")
(save-window-excursion (run-haskell) (sleep-for 0.25) (current-buffer))))
(defun org-babel-load-session:haskell (session body params)
"Load BODY into SESSION."
@ -329,7 +226,7 @@ constructs (header arguments, no-web syntax etc...) are ignored."
(let* ((contents (buffer-string))
(haskell-regexp
(concat "^\\([ \t]*\\)#\\+begin_src[ \t]haskell*\\(.*\\)[\r\n]"
"\\(\\(?:.\\|\n\\)*?\\)[\r\n][ \t]*#\\+end_src.*"))
"\\([^\000]*?\\)[\r\n][ \t]*#\\+end_src.*"))
(base-name (file-name-sans-extension (buffer-file-name)))
(tmp-file (org-babel-temp-file "haskell-"))
(tmp-org-file (concat tmp-file ".org"))
@ -339,7 +236,6 @@ constructs (header arguments, no-web syntax etc...) are ignored."
(command (concat org-babel-haskell-lhs2tex-command
" " (org-babel-process-file-name lhs-file)
" > " (org-babel-process-file-name tex-file)))
;; FIXME: What if src block has :preserve-indentation flag?
(preserve-indentp org-src-preserve-indentation)
indentation)
;; escape haskell source-code blocks
@ -374,7 +270,7 @@ constructs (header arguments, no-web syntax etc...) are ignored."
(goto-char (point-min)) (forward-line 2)
(insert "%include polycode.fmt\n")
;; ensure all \begin/end{code} statements start at the first column
(while (re-search-forward "^[ \t]+\\\\begin{code}\\(?:.\\|\n\\)+\\\\end{code}" nil t)
(while (re-search-forward "^[ \t]+\\\\begin{code}[^\000]+\\\\end{code}" nil t)
(replace-match (save-match-data (org-remove-indentation (match-string 0)))
t t))
;; save org exported latex to a .lhs file

View File

@ -1,6 +1,6 @@
;;; ob-java.el --- org-babel functions for java evaluation -*- lexical-binding: t -*-
;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
;; Authors: Eric Schulte
;; Dan Davison
@ -341,13 +341,9 @@ is simplest to expand the code block from the inside out."
(imports-val (assq :imports params))
(imports (if imports-val
(split-string (org-babel-read (cdr imports-val) nil) " ")
nil))
(prologue (cdr (assq :prologue params)))
(epilogue (cdr (assq :epilogue params))))
nil)))
(with-temp-buffer
(when prologue (insert prologue "\n"))
(insert body)
(when epilogue (insert "\n" epilogue))
;; wrap main. If there are methods defined, but no main method
;; and no class, wrap everything in a generic main method.

View File

@ -1,6 +1,6 @@
;;; ob-js.el --- Babel Functions for Javascript -*- lexical-binding: t; -*-
;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Keywords: literate programming, reproducible research, js
@ -69,14 +69,11 @@
:safe #'stringp)
(defvar org-babel-js-function-wrapper
;; Note that newline after %s - it makes sure that closing
;; parenthesis are not shadowed if the last line of the body is a
;; line comment.
"require('process').stdout.write(require('util').inspect(function(){%s\n}()));"
"require('process').stdout.write(require('util').inspect(function(){%s}()));"
"Javascript code to print value of body.")
(defun org-babel-execute:js (body params)
"Execute Javascript BODY according to PARAMS.
"Execute a block of Javascript code with org-babel.
This function is called by `org-babel-execute-src-block'."
(let* ((org-babel-js-cmd (or (cdr (assq :cmd params)) org-babel-js-cmd))
(session (cdr (assq :session params)))
@ -158,8 +155,7 @@ specifying a variable of the same value."
session))
(defun org-babel-variable-assignments:js (params)
"Return list of Javascript statements assigning the block's variables.
The variables are defined in PARAMS."
"Return list of Javascript statements assigning the block's variables."
(mapcar
(lambda (pair) (format "var %s=%s;"
(car pair) (org-babel-js-var-to-js (cdr pair))))

View File

@ -1,6 +1,6 @@
;;; ob-julia.el --- org-babel functions for julia code evaluation -*- lexical-binding: t; -*-
;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
;; Copyright (C) 2013-2023 Free Software Foundation, Inc.
;; Authors: G. Jay Kerns
;; Maintainer: Pedro Bruel <pedro.bruel@gmail.com>
;; Keywords: literate programming, reproducible research, scientific computing
@ -70,15 +70,12 @@
(defvar ess-local-process-name) ; dynamically scoped
(defvar ess-eval-visibly-p) ; dynamically scoped
(defvar ess-local-customize-alist); dynamically scoped
(defvar ess-gen-proc-buffer-name-function) ; defined in ess-inf.el
(defun org-babel-julia-associate-session (session)
"Associate R code buffer with an R session.
Make SESSION be the inferior ESS process associated with the
current code buffer."
(when-let ((process (get-buffer-process session)))
(setq ess-local-process-name (process-name process))
(ess-make-buffer-current))
(setq-local ess-gen-proc-buffer-name-function (lambda (_) session)))
(defun org-babel-edit-prep:julia (info)
(let ((session (cdr (assq :session (nth 2 info)))))
(when (and session
(string-prefix-p "*" session)
(string-suffix-p "*" session))
(org-babel-julia-initiate-session session nil))))
(defun org-babel-expand-body:julia (body params &optional _graphics-file)
"Expand BODY according to PARAMS, return the expanded body."
@ -184,13 +181,10 @@ end"
(defun org-babel-julia-initiate-session (session params)
"If there is not a current julia process then create one."
(unless (string= session "none")
(let* ((session (or session "*Julia*"))
(ess-ask-for-ess-directory
(and (bound-and-true-p ess-ask-for-ess-directory)
(not (cdr (assq :dir params)))))
;; Make ESS name the process buffer as SESSION.
(ess-gen-proc-buffer-name-function
(lambda (_) session)))
(let ((session (or session "*Julia*"))
(ess-ask-for-ess-directory
(and (bound-and-true-p ess-ask-for-ess-directory)
(not (cdr (assq :dir params))))))
(if (org-babel-comint-buffer-livep session)
session
;; FIXME: Depending on `display-buffer-alist', (julia) may end up
@ -204,6 +198,12 @@ end"
(set-buffer session))
(org-require-package 'ess "ESS")
(set-buffer (julia))
(rename-buffer
(if (bufferp session)
(buffer-name session)
(if (stringp session)
session
(buffer-name))))
(current-buffer))))))
(defun org-babel-julia-graphical-output-file (params)

View File

@ -1,6 +1,6 @@
;;; ob-latex.el --- Babel Functions for LaTeX -*- lexical-binding: t; -*-
;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Keywords: literate programming, reproducible research
@ -37,7 +37,7 @@
(require 'ob)
(require 'org-macs)
(declare-function org-latex-preview-create-image "org-latex-preview" (string tofile options buffer &optional type))
(declare-function org-create-formula-image "org" (string tofile options buffer &optional type))
(declare-function org-latex-compile "ox-latex" (texfile &optional snippet))
(declare-function org-latex-guess-inputenc "ox-latex" (header))
(declare-function org-splice-latex-header "org" (tpl def-pkg pkg snippets-p &optional extra))
@ -48,10 +48,10 @@
(defvar org-babel-tangle-lang-exts)
(add-to-list 'org-babel-tangle-lang-exts '("latex" . "tex"))
(defvar org-latex-preview-header) ; From org-latex-preview.el
(defvar org-latex-preview-appearance-options) ; From org-latex-preview.el
(defvar org-latex-default-packages-alist) ; From org-latex-preview.el
(defvar org-latex-packages-alist) ; From org-latex-preview.el
(defvar org-format-latex-header) ; From org.el
(defvar org-format-latex-options) ; From org.el
(defvar org-latex-default-packages-alist) ; From org.el
(defvar org-latex-packages-alist) ; From org.el
(defvar org-babel-default-header-args:latex
'((:results . "latex") (:exports . "results"))
@ -136,18 +136,12 @@ exporting the literal LaTeX source."
(regexp-quote (format "%S" (car pair)))
(if (stringp (cdr pair))
(cdr pair) (format "%S" (cdr pair)))
body t t)))
body)))
(org-babel--get-vars params))
(let ((prologue (cdr (assq :prologue params)))
(epilogue (cdr (assq :epilogue params))))
(org-trim
(concat
(and prologue (concat prologue "\n"))
body
(and epilogue (concat "\n" epilogue "\n"))))))
(org-trim body))
(defun org-babel-execute:latex (body params)
"Execute LaTeX BODY according to PARAMS.
"Execute a block of LaTeX code with Babel.
This function is called by `org-babel-execute-src-block'."
(setq body (org-babel-expand-body:latex body params))
(if (cdr (assq :file params))
@ -167,11 +161,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))
(let ((org-latex-preview-header
(concat org-latex-preview-header "\n"
(let ((org-format-latex-header
(concat org-format-latex-header "\n"
(mapconcat #'identity headers "\n"))))
(org-latex-preview-create-image
body out-file org-latex-preview-appearance-options in-buffer)))
(org-create-formula-image
body out-file org-format-latex-options in-buffer)))
((string= "svg" extension)
(with-temp-file tex-file
(insert (concat (funcall org-babel-latex-preamble params)
@ -238,7 +232,7 @@ This function is called by `org-babel-execute-src-block'."
(insert
(org-latex-guess-inputenc
(org-splice-latex-header
org-latex-preview-header
org-format-latex-header
(delq
nil
(mapcar
@ -279,9 +273,7 @@ This function is called by `org-babel-execute-src-block'."
body))
(defun org-babel-latex-convert-pdf (pdffile out-file im-in-options im-out-options)
"Generate OUT-FILE from PDFFILE using imagemagick.
IM-IN-OPTIONS are command line options for input file, as a string;
and IM-OUT-OPTIONS are the output file options."
"Generate a file from a pdf file using imagemagick."
(let ((cmd (concat "convert " im-in-options " " pdffile " "
im-out-options " " out-file)))
(message "Converting pdffile file %s..." cmd)

View File

@ -1,6 +1,6 @@
;;; ob-lilypond.el --- Babel Functions for Lilypond -*- lexical-binding: t; -*-
;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
;; Author: Martyn Jago
;; Keywords: babel language, literate programming
@ -40,8 +40,10 @@
(declare-function org-fold-show-all "org-fold" (&optional types))
;; FIXME: Doesn't this rather belong in lilypond-mode.el?
(defalias 'lilypond-mode 'LilyPond-mode)
(add-to-list 'org-babel-tangle-lang-exts '("LilyPond" . "ly"))
(add-to-list 'org-src-lang-modes '("lilypond" . "LilyPond"))
(defvar org-babel-default-header-args:lilypond '()
"Default header arguments for lilypond code blocks.
@ -58,13 +60,23 @@ and stored in `org-babel-default-header-args:lilypond'
See `org-babel-lilypond-set-header-args'.")
(defvar org-babel-lilypond-compile-post-tangle t
"When non-nil, compile tangled file after `org-babel-tangle'.")
"Following the org-babel-tangle (C-c C-v t) command,
org-babel-lilypond-compile-post-tangle determines whether ob-lilypond should
automatically attempt to compile the resultant tangled file.
If the value is nil, no automated compilation takes place.
Default value is t.")
(defvar org-babel-lilypond-display-pdf-post-tangle t
"When non-nil, display pdf after successful LilyPond compilation.")
"Following a successful LilyPond compilation
org-babel-lilypond-display-pdf-post-tangle determines whether to automate the
drawing / redrawing of the resultant pdf. If the value is nil,
the pdf is not automatically redrawn. Default value is t.")
(defvar org-babel-lilypond-play-midi-post-tangle t
"When non-nil, play midi file after successful LilyPond compilation.")
"Following a successful LilyPond compilation
org-babel-lilypond-play-midi-post-tangle determines whether to automate the
playing of the resultant midi file. If the value is nil,
the midi file is not automatically played. Default value is t")
(defvar org-babel-lilypond-ly-command ""
"Command to execute lilypond on your system.
@ -131,9 +143,7 @@ blocks.")
(defun org-babel-expand-body:lilypond (body params)
"Expand BODY according to PARAMS, return the expanded body."
(let ((vars (org-babel--get-vars params))
(prologue (cdr (assq :prologue params)))
(epilogue (cdr (assq :epilogue params))))
(let ((vars (org-babel--get-vars params)))
(mapc
(lambda (pair)
(let ((name (symbol-name (car pair)))
@ -142,75 +152,54 @@ blocks.")
(replace-regexp-in-string
(concat "$" (regexp-quote name))
(if (stringp value) value (format "%S" value))
body t t))))
body))))
vars)
(concat
(and prologue (concat prologue "\n"))
body
(and epilogue (concat "\n" epilogue "\n")))))
body))
(defun org-babel-execute:lilypond (body params)
"Execute LilyPond src block according to arrange mode.
See `org-babel-execute-src-block' for BODY and PARAMS.
When in arrange mode, tangle all blocks and process the result.
Otherwise, execute block according to header settings."
"This function is called by `org-babel-execute-src-block'.
Depending on whether we are in arrange mode either:
1. Attempt to execute lilypond block according to header settings
(This is the default basic mode)
2. Tangle all lilypond blocks and process the result (arrange mode)"
(org-babel-lilypond-set-header-args org-babel-lilypond-arrange-mode)
(if org-babel-lilypond-arrange-mode
(org-babel-lilypond-tangle)
(org-babel-lilypond-process-basic body params)))
(defun org-babel-lilypond-tangle ()
"Tangle lilypond blocks, then `org-babel-liypond-execute-tangled-ly'."
"ob-lilypond specific tangle, attempts to invoke
=ly-execute-tangled-ly= if tangle is successful. Also passes
specific arguments to =org-babel-tangle=."
(interactive)
(if (org-babel-tangle nil "yes" "lilypond")
(org-babel-lilypond-execute-tangled-ly) nil))
;; https://lilypond.org/doc/v2.24/Documentation/usage/other-programs
(defvar org-babel-lilypond-paper-settings
"#(if (ly:get-option 'use-paper-size-for-page)
(begin (ly:set-option 'use-paper-size-for-page #f)
(ly:set-option 'tall-page-formats '%s)))
\\paper {
indent=0\\mm
tagline=\"\"
oddFooterMarkup=##f
oddHeaderMarkup=##f
bookTitleMarkup=##f
scoreTitleMarkup=##f
}\n"
"The paper settings required to generate music fragments.
They are needed for mixing music and text in basic-mode.")
(defun org-babel-lilypond-process-basic (body params)
"Execute a lilypond block in basic mode.
See `org-babel-execute-src-block' for BODY and PARAMS."
"Execute a lilypond block in basic mode."
(let* ((out-file (cdr (assq :file params)))
(file-type (file-name-extension out-file))
(cmdline (or (cdr (assq :cmdline params))
""))
(in-file (org-babel-temp-file "lilypond-")))
(with-temp-file in-file
(insert
(format org-babel-lilypond-paper-settings file-type)
(org-babel-expand-body:generic body params)))
(insert (org-babel-expand-body:generic body params)))
(org-babel-eval
(concat
org-babel-lilypond-ly-command
" -dbackend=eps "
"-dno-gs-load-fonts "
"-dinclude-eps-fonts "
(or (assoc-default file-type
'(("pdf" . "--pdf ")
("eps" . "--eps ")))
(or (cdr (assoc (file-name-extension out-file)
'(("pdf" . "--pdf ")
("ps" . "--ps ")
("png" . "--png "))))
"--png ")
"--output="
(file-name-sans-extension out-file)
" "
cmdline
in-file)
""))
nil)
in-file) "")) nil)
(defun org-babel-prep-session:lilypond (_session _params)
"Return an error because LilyPond exporter does not support sessions."
@ -230,7 +219,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))
@ -240,20 +229,27 @@ If error in compilation, attempt to mark the error in lilypond org file."
(org-babel-lilypond-attempt-to-open-pdf org-babel-lilypond-temp-file)
(org-babel-lilypond-attempt-to-play-midi org-babel-lilypond-temp-file)))))
;;Ignoring second arg for pre Org 9.7 compatibility
(defun org-babel-lilypond-compile-lilyfile (filename &optional _)
"Compile Lilypond FILENAME and check for compile errors."
(message "Compiling %s..." filename)
(let ((args (delq nil (list
(and org-babel-lilypond-gen-png "--png")
(and org-babel-lilypond-gen-html "--html")
(and org-babel-lilypond-gen-pdf "--pdf")
(and org-babel-lilypond-use-eps "-dbackend=eps")
(and org-babel-lilypond-gen-svg "-dbackend=svg")
(concat "--output=" (file-name-sans-extension filename))
filename))))
(apply #'call-process org-babel-lilypond-ly-command nil
"*lilypond*" 'display args)))
(defun org-babel-lilypond-compile-lilyfile (file-name &optional test)
"Compile lilypond file and check for compile errors.
FILE-NAME is full path to lilypond (.ly) file."
(message "Compiling LilyPond...")
(let ((arg-1 org-babel-lilypond-ly-command) ;program
;; (arg-2 nil) ;infile
(arg-3 "*lilypond*") ;buffer
(arg-4 t) ;display
(arg-5 (if org-babel-lilypond-gen-png "--png" "")) ;&rest...
(arg-6 (if org-babel-lilypond-gen-html "--html" ""))
(arg-7 (if org-babel-lilypond-gen-pdf "--pdf" ""))
(arg-8 (if org-babel-lilypond-use-eps "-dbackend=eps" ""))
(arg-9 (if org-babel-lilypond-gen-svg "-dbackend=svg" ""))
(arg-10 (concat "--output=" (file-name-sans-extension file-name)))
(arg-11 file-name))
(if test
`(,arg-1 ,nil ,arg-3 ,arg-4 ,arg-5 ,arg-6 ;; arg-2
,arg-7 ,arg-8 ,arg-9 ,arg-10 ,arg-11)
(call-process
arg-1 nil arg-3 arg-4 arg-5 arg-6 ;; arg-2
arg-7 arg-8 arg-9 arg-10 arg-11))))
(defun org-babel-lilypond-check-for-compile-error (file-name &optional test)
"Check for compile error.
@ -280,7 +276,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)))
@ -294,7 +290,7 @@ LINE is the erroneous line."
(goto-char temp))))
(defun org-babel-lilypond-parse-line-num (&optional buffer)
"Extract error line number in BUFFER or `current-buffer'."
"Extract error line number."
(when buffer (set-buffer buffer))
(let ((start
(and (search-backward ":" nil t)
@ -427,7 +423,8 @@ These depend upon whether we are in Arrange mode i.e. MODE is t."
ob-lilypond-header-args)))
(defun org-babel-lilypond-set-header-args (mode)
"Set lilypond babel header according to MODE."
"Set org-babel-default-header-args:lilypond
dependent on ORG-BABEL-LILYPOND-ARRANGE-MODE."
(setq org-babel-default-header-args:lilypond
(org-babel-lilypond-get-header-args mode)))

View File

@ -1,6 +1,6 @@
;;; ob-lisp.el --- Babel Functions for Common Lisp -*- lexical-binding: t; -*-
;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
;; Authors: Joel Boehland
;; Eric Schulte
@ -74,19 +74,13 @@ current directory string."
(let* ((vars (org-babel--get-vars params))
(result-params (cdr (assq :result-params params)))
(print-level nil) (print-length nil)
(prologue (cdr (assq :prologue params)))
(epilogue (cdr (assq :epilogue params)))
(body (if (null vars) (org-trim body)
(concat "(let ("
(mapconcat
(lambda (var)
(format "(%S (quote %S))" (car var) (cdr var)))
vars "\n ")
")\n"
(and prologue (concat prologue "\n"))
body
(and epilogue (concat "\n" epilogue "\n"))
")"))))
")\n" body ")"))))
(if (or (member "code" result-params)
(member "pp" result-params))
(format "(pprint %s)" body)
@ -96,41 +90,37 @@ current directory string."
"Execute a block of Common Lisp code with Babel.
BODY is the contents of the block, as a string. PARAMS is
a property list containing the parameters of the block."
(let (eval-and-grab-output)
(pcase org-babel-lisp-eval-fn
(`slime-eval (org-require-package 'slime "SLIME")
(setq eval-and-grab-output 'swank:eval-and-grab-output))
(`sly-eval (org-require-package 'sly "SLY")
(setq eval-and-grab-output 'slynk:eval-and-grab-output)))
(org-babel-reassemble-table
(let ((result
(funcall (if (member "output" (cdr (assq :result-params params)))
#'car #'cadr)
(with-temp-buffer
(insert (org-babel-expand-body:lisp body params))
(funcall org-babel-lisp-eval-fn
`(,eval-and-grab-output
,(let ((dir (if (assq :dir params)
(cdr (assq :dir params))
default-directory)))
(format
(if dir (format org-babel-lisp-dir-fmt dir)
"(progn %s\n)")
(buffer-substring-no-properties
(point-min) (point-max)))))
(cdr (assq :package params)))))))
(org-babel-result-cond (cdr (assq :result-params params))
(org-strip-quotes result)
(condition-case nil
(read (org-babel-lisp-vector-to-list result))
(error 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))))))
(pcase org-babel-lisp-eval-fn
(`slime-eval (org-require-package 'slime "SLIME"))
(`sly-eval (org-require-package 'sly "SLY")))
(org-babel-reassemble-table
(let ((result
(funcall (if (member "output" (cdr (assq :result-params params)))
#'car #'cadr)
(with-temp-buffer
(insert (org-babel-expand-body:lisp body params))
(funcall org-babel-lisp-eval-fn
`(swank:eval-and-grab-output
,(let ((dir (if (assq :dir params)
(cdr (assq :dir params))
default-directory)))
(format
(if dir (format org-babel-lisp-dir-fmt dir)
"(progn %s\n)")
(buffer-substring-no-properties
(point-min) (point-max)))))
(cdr (assq :package params)))))))
(org-babel-result-cond (cdr (assq :result-params params))
(org-strip-quotes result)
(condition-case nil
(read (org-babel-lisp-vector-to-list result))
(error 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-lisp-vector-to-list (results)
"Convert #(...) values in RESULTS string into a (...) list."
;; TODO: better would be to replace #(...) with [...]
(replace-regexp-in-string "#(" "(" results))

View File

@ -1,6 +1,6 @@
;;; ob-lob.el --- Functions Supporting the Library of Babel -*- lexical-binding: t; -*-
;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
;; Authors: Eric Schulte
;; Dan Davison
@ -34,8 +34,8 @@
(declare-function org-babel-ref-split-args "ob-ref" (arg-string))
(declare-function org-element-at-point "org-element" (&optional pom cached-only))
(declare-function org-element-context "org-element" (&optional element))
(declare-function org-element-property "org-element-ast" (property node))
(declare-function org-element-type "org-element-ast" (node &optional anonymous))
(declare-function org-element-property "org-element" (property element))
(declare-function org-element-type "org-element" (element))
(defvar org-babel-library-of-babel nil
"Library of source-code blocks.

View File

@ -1,6 +1,6 @@
;;; ob-lua.el --- Org Babel functions for Lua evaluation -*- lexical-binding: t; -*-
;; Copyright (C) 2014, 2016-2024 Free Software Foundation, Inc.
;; Copyright (C) 2014, 2016-2023 Free Software Foundation, Inc.
;; Authors: Dieter Schoen
;; Keywords: literate programming, reproducible research
@ -82,7 +82,7 @@ This will typically be `lua-mode'."
:type 'symbol)
(defun org-babel-execute:lua (body params)
"Execute Lua BODY according to PARAMS.
"Execute a block of Lua code with Babel.
This function is called by `org-babel-execute-src-block'."
(let* ((session (org-babel-lua-initiate-session
(cdr (assq :session params))))
@ -129,8 +129,7 @@ VARS contains resolved variable references."
;; helper functions
(defun org-babel-variable-assignments:lua (params)
"Return a list of Lua statements assigning the block's variables.
The variable definitions are defining in PARAMS."
"Return a list of Lua statements assigning the block's variables."
(mapcar
(lambda (pair)
(format "%s=%s"
@ -177,20 +176,13 @@ Emacs-lisp table, otherwise return the results as a string."
(cdr (assoc session org-babel-lua-buffers)))
(defun org-babel-lua-with-earmuffs (session)
"Return buffer name for SESSION, as *SESSION*."
(let ((name (if (stringp session) session (format "%s" session))))
(if (and (string= "*" (substring name 0 1))
(string= "*" (substring name (- (length name) 1))))
name
(format "*%s*" name))))
(defun org-babel-session-buffer:lua (session &optional _)
"Return session buffer name for SESSION."
(or (org-babel-lua-session-buffer session)
(org-babel-lua-with-earmuffs session)))
(defun org-babel-lua-without-earmuffs (session)
"Remove stars around *SESSION*, leaving SESSION."
(let ((name (if (stringp session) session (format "%s" session))))
(if (and (string= "*" (substring name 0 1))
(string= "*" (substring name (- (length name) 1))))
@ -289,11 +281,7 @@ fd:close()")
(defun org-babel-lua-evaluate
(session body &optional result-type result-params preamble)
"Evaluate BODY in SESSION as Lua code.
RESULT-TYPE and RESULT-PARAMS are passed to
`org-babel-lua-evaluate-session' or
`org-babel-lua-evaluate-external-process'.
PREAMBLE is passed to `org-babel-lua-evaluate-external-process'."
"Evaluate BODY as Lua code."
(if session
(org-babel-lua-evaluate-session
session body result-type result-params)
@ -302,12 +290,10 @@ PREAMBLE is passed to `org-babel-lua-evaluate-external-process'."
(defun org-babel-lua-evaluate-external-process
(body &optional result-type result-params preamble)
"Evaluate BODY in external Lua process.
"Evaluate BODY in external lua process.
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.
RESULT-PARAMS list all the :result header arg parameters.
PREAMBLE string is appended to BODY."
last statement in BODY, as elisp."
(let ((raw
(pcase result-type
(`output (org-babel-eval org-babel-lua-command
@ -340,7 +326,7 @@ PREAMBLE string is appended to BODY."
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.005)))
(let* ((send-wait (lambda () (comint-send-input nil t) (sleep-for 0 5)))
(dump-last-value
(lambda
(tmp-file pp)
@ -413,7 +399,7 @@ fd:close()"
(org-babel-lua-table-or-string results)))))
(defun org-babel-lua-read-string (string)
"Strip single quotes from around Lua STRING."
"Strip single quotes from around Lua string."
(org-unbracket-string "'" "'" string))
(provide 'ob-lua)

View File

@ -1,6 +1,6 @@
;;; ob-makefile.el --- Babel Functions for Makefile -*- lexical-binding: t; -*-
;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Thomas S. Dye
@ -36,8 +36,7 @@
(defvar org-babel-default-header-args:makefile '())
(defun org-babel-execute:makefile (body _params)
"Execute makefile BODY.
Second function argument is ignored.
"Execute a block of makefile code.
This function is called by `org-babel-execute-src-block'."
body)

View File

@ -1,6 +1,6 @@
;;; ob-matlab.el --- Babel support for Matlab -*- lexical-binding: t; -*-
;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
;; Author: Dan Davison
;; Keywords: literate programming, reproducible research

View File

@ -1,6 +1,6 @@
;;; ob-maxima.el --- Babel Functions for Maxima -*- lexical-binding: t; -*-
;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
;; Author: Eric S Fraga
;; Eric Schulte
@ -37,11 +37,6 @@
(require 'ob)
(defconst org-babel-header-args:maxima
'((batch . ((batchload batch load)))
(graphics-pkg . ((plot draw))))
"Maxima-specific header arguments.")
(defvar org-babel-tangle-lang-exts)
(add-to-list 'org-babel-tangle-lang-exts '("maxima" . "max"))
@ -53,102 +48,43 @@
:group 'org-babel
:type 'string)
(defvar org-babel-maxima--command-arguments-default
"--very-quiet"
"Command-line arguments sent to Maxima by default.
If the `:batch' header argument is set to `batchload' or unset,
then the `:cmdline' header argument is appended to this default;
otherwise, if the `:cmdline' argument is set, it over-rides this
default. See `org-babel-maxima-command' and
`org-babel-execute:maxima'.")
(defvar org-babel-maxima--graphic-package-options
'((plot . "(set_plot_option ('[gnuplot_term, %s]), set_plot_option ('[gnuplot_out_file, %S]))$")
(draw . "(load(draw), set_draw_defaults(terminal='%s,file_name=%S))$"))
"An alist of graphics packages and Maxima code.
Each element is a cons (PACKAGE-NAME . FORMAT-STRING).
FORMAT-STRING contains Maxima code to configure the graphics
package; it must contain `%s' to set the terminal and `%S' to set
the filename, in that order. The default graphics package is
`plot'; `draw' is also supported. See
`org-babel-maxima-expand'.")
(defvar org-babel-maxima--default-epilogue
'((graphical-output . "gnuplot_close ()$")
(non-graphical-output . ""))
"The final Maxima code executed in a source block.
An alist with the epilogue for graphical and non-graphical
output. See `org-babel-maxima-expand'.")
(defun org-babel-maxima-expand (body params)
"Expand Maxima BODY according to its header arguments from PARAMS."
(let* ((vars (org-babel--get-vars params))
(graphic-file (ignore-errors (org-babel-graphical-output-file params)))
(epilogue (cdr (assq :epilogue params)))
(prologue (cdr (assq :prologue params))))
"Expand a block of Maxima code according to its header arguments."
(let ((vars (org-babel--get-vars params))
(epilogue (cdr (assq :epilogue params)))
(prologue (cdr (assq :prologue params))))
(mapconcat 'identity
(delq nil
(list
;; Any code from the specified prologue at the start.
prologue
;; graphic output
(if graphic-file
(let* ((graphics-pkg (intern (or (cdr (assq :graphics-pkg params)) "plot")))
(graphic-format-string (cdr (assq graphics-pkg org-babel-maxima--graphic-package-options)))
(graphic-terminal (file-name-extension graphic-file))
(graphic-file (if (eq graphics-pkg 'plot) graphic-file (file-name-sans-extension graphic-file))))
(format graphic-format-string graphic-terminal graphic-file)))
;; variables
(mapconcat 'org-babel-maxima-var-to-maxima vars "\n")
;; body
body
;; Any code from the specified epilogue at the end.
epilogue
(if graphic-file
(cdr (assq :graphical-output org-babel-maxima--default-epilogue))
(cdr (assq :non-graphical-output org-babel-maxima--default-epilogue)))))
(list
;; Any code from the specified prologue at the start.
prologue
;; graphic output
(let ((graphic-file (ignore-errors (org-babel-graphical-output-file params))))
(if graphic-file
(format
"set_plot_option ([gnuplot_term, png]); set_plot_option ([gnuplot_out_file, %S]);"
graphic-file)
""))
;; variables
(mapconcat 'org-babel-maxima-var-to-maxima vars "\n")
;; body
body
;; Any code from the specified epilogue at the end.
epilogue
"gnuplot_close ()$")
"\n")))
(defvar org-babel-maxima--output-filter-regexps
'("batch" ;; remove the `batch' or `batchload' line
"^rat: replaced .*$" ;; remove notices from `rat'
"^;;; Loading #P" ;; remove notices from the lisp implementation
"^read and interpret" ;; remove notice from `batch'
"^(%\\([i]-?[0-9]+\\))[ ]$" ;; remove empty input lines from `batch'-ing
)
"Regexps to remove extraneous lines from Maxima's output.
See `org-babel-maxima--output-filter'.")
(defun org-babel-maxima--output-filter (line)
"Filter empty or undesired lines from Maxima output.
Return nil if LINE is zero-length or it matches a regexp in
`org-babel-maxima--output-filter'; otherwise, return LINE."
(unless (or (= 0 (length line))
(cl-some #'(lambda(r) (string-match r line))
org-babel-maxima--output-filter-regexps))
line))
(defun org-babel-execute:maxima (body params)
"Execute Maxima BODY according to PARAMS.
"Execute a block of Maxima entries with org-babel.
This function is called by `org-babel-execute-src-block'."
(message "Executing Maxima source code block")
(let ((result-params (split-string (or (cdr (assq :results params)) "")))
(result
(let* ((cmdline (or (cdr (assq :cmdline params)) ""))
(batch/load (or (cdr (assq :batch params)) "batchload"))
(cmdline (if (or (equal cmdline "") (equal batch/load "batchload"))
;; legacy behaviour:
;; ensure that --very-quiet is on command-line by default
(concat cmdline " " org-babel-maxima--command-arguments-default)
;; if using an alternate loader, :cmdline overwrites default
cmdline))
(in-file (org-babel-temp-file "maxima-" ".max"))
(cmd (format "%s -r %s %s"
(cmd (format "%s --very-quiet -r %s %s"
org-babel-maxima-command
(shell-quote-argument
;; bind linenum to 0 so the first line
;; of in-file has line number 1
(format "(linenum:0, %s(%S))$" batch/load in-file))
(format "batchload(%S)$" in-file))
cmdline)))
(with-temp-file in-file (insert (org-babel-maxima-expand body params)))
(message cmd)
@ -157,7 +93,12 @@ This function is called by `org-babel-execute-src-block'."
(mapconcat
#'identity
(delq nil
(mapcar #'org-babel-maxima--output-filter
(mapcar (lambda (line)
(unless (or (string-match "batch" line)
(string-match "^rat: replaced .*$" line)
(string-match "^;;; Loading #P" line)
(= 0 (length line)))
line))
(split-string raw "[\r\n]"))) "\n")))))
(if (ignore-errors (org-babel-graphical-output-file params))
nil
@ -169,11 +110,11 @@ This function is called by `org-babel-execute-src-block'."
(defun org-babel-prep-session:maxima (_session _params)
"Throw an error. Maxima does not support sessions."
(error "Maxima does not support sessions"))
(defun org-babel-maxima-var-to-maxima (pair)
"Convert an elisp variable-value PAIR to maxima code."
"Convert an elisp val into a string of maxima code specifying a var
of the same value."
(let ((var (car pair))
(val (cdr pair)))
(when (symbolp val)

View File

@ -1,6 +1,6 @@
;;; ob-ocaml.el --- Babel Functions for Ocaml -*- lexical-binding: t; -*-
;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Keywords: literate programming, reproducible research
@ -63,7 +63,7 @@
:type 'string)
(defun org-babel-execute:ocaml (body params)
"Execute Ocaml BODY according to PARAMS."
"Execute a block of Ocaml code with Babel."
(let* ((full-body (org-babel-expand-body:generic
body params
(org-babel-variable-assignments:ocaml params)))
@ -121,8 +121,7 @@
(get-buffer tuareg-interactive-buffer-name)))
(defun org-babel-variable-assignments:ocaml (params)
"Return list of ocaml statements assigning the block's variables.
The variables are defined in PARAMS."
"Return list of ocaml statements assigning the block's variables."
(mapcar
(lambda (pair) (format "let %s = %s;;" (car pair)
(org-babel-ocaml-elisp-to-ocaml (cdr pair))))

View File

@ -1,6 +1,6 @@
;;; ob-octave.el --- Babel Functions for Octave and Matlab -*- lexical-binding: t; -*-
;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
;; Author: Dan Davison
;; Keywords: literate programming, reproducible research
@ -70,12 +70,11 @@ end")
(defvar org-babel-octave-eoe-output "ans = org_babel_eoe")
(defun org-babel-execute:matlab (body params)
"Execute Matlab BODY according to PARAMS."
"Execute a block of matlab code with Babel."
(org-babel-execute:octave body params 'matlab))
(defun org-babel-execute:octave (body params &optional matlabp)
"Execute Octave or Matlab BODY according to PARAMS.
When MATLABP is non-nil, execute Matlab. Otherwise, execute Octave."
"Execute a block of octave code with Babel."
(let* ((session
(funcall (intern (format "org-babel-%s-initiate-session"
(if matlabp "matlab" "octave")))
@ -110,8 +109,7 @@ When MATLABP is non-nil, execute Matlab. Otherwise, execute Octave."
(org-babel-prep-session:octave session params 'matlab))
(defun org-babel-variable-assignments:octave (params)
"Return list of octave statements assigning the block's variables.
The variables are taken from PARAMS."
"Return list of octave statements assigning the block's variables."
(mapcar
(lambda (pair)
(format "%s=%s;"
@ -122,22 +120,21 @@ The variables are taken from PARAMS."
(defalias 'org-babel-variable-assignments:matlab
'org-babel-variable-assignments:octave)
(defun org-babel-octave-var-to-octave (value)
"Convert an emacs-lisp VALUE into an octave variable.
(defun org-babel-octave-var-to-octave (var)
"Convert an emacs-lisp value into an octave variable.
Converts an emacs-lisp variable into a string of octave code
specifying a variable of the same value."
(if (listp value)
(concat "[" (mapconcat #'org-babel-octave-var-to-octave value
(if (listp (car value)) "; " ",")) "]")
(if (listp var)
(concat "[" (mapconcat #'org-babel-octave-var-to-octave var
(if (listp (car var)) "; " ",")) "]")
(cond
((stringp value)
(format "'%s'" value))
((stringp var)
(format "'%s'" var))
(t
(format "%s" value)))))
(format "%s" var)))))
(defun org-babel-prep-session:octave (session params &optional matlabp)
"Prepare SESSION according to the header arguments specified in PARAMS.
The session will be an Octave session, unless MATLABP is non-nil."
"Prepare SESSION according to the header arguments specified in PARAMS."
(let* ((session (org-babel-octave-initiate-session session params matlabp))
(var-lines (org-babel-variable-assignments:octave params)))
(org-babel-comint-in-buffer session
@ -150,14 +147,13 @@ The session will be an Octave session, unless MATLABP is non-nil."
(defun org-babel-matlab-initiate-session (&optional session params)
"Create a matlab inferior process buffer.
If there is not a current inferior-process-buffer in SESSION then
create. Return the initialized session. PARAMS are src block parameters."
create. Return the initialized session."
(org-babel-octave-initiate-session session params 'matlab))
(defun org-babel-octave-initiate-session (&optional session _params matlabp)
"Create an octave inferior process buffer.
If there is not a current inferior-process-buffer in SESSION then
create. Return the initialized session. The session will be an
Octave session, unless MATLABP is non-nil."
create. Return the initialized session."
(if matlabp
(org-require-package 'matlab "matlab-mode")
(or (require 'octave-inf nil 'noerror)
@ -184,8 +180,7 @@ value of the last statement in BODY, as elisp."
(org-babel-octave-evaluate-external-process body result-type matlabp)))
(defun org-babel-octave-evaluate-external-process (body result-type matlabp)
"Evaluate BODY in an external Octave or Matalab process.
Process the result as RESULT-TYPE. Use Octave, unless MATLABP is non-nil."
"Evaluate BODY in an external octave process."
(let ((cmd (if matlabp
org-babel-matlab-shell-command
org-babel-octave-shell-command)))

View File

@ -1,6 +1,6 @@
;;; ob-org.el --- Babel Functions for Org Code Blocks -*- lexical-binding: t; -*-
;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Keywords: literate programming, reproducible research
@ -45,25 +45,15 @@
"Default header inserted during export of org blocks.")
(defun org-babel-expand-body:org (body params)
"Expand Org BODY according to PARAMS.
$VAR instances are replaced by VAR values defined in PARAMS."
(dolist (var (org-babel--get-vars params))
(setq body (replace-regexp-in-string
(regexp-quote (format "$%s" (car var)))
(format "%s" (cdr var))
body 'fixedcase 'literal)))
(let ((prologue (cdr (assq :prologue params)))
(epilogue (cdr (assq :epilogue params))))
(concat
(and prologue (concat prologue "\n"))
body
(and epilogue (concat "\n" epilogue "\n")))))
body nil 'literal)))
body)
(defun org-babel-execute:org (body params)
"Execute a Org BODY according to PARAMS.
The BODY is returned expanded as is or exported, if PARAMS define
latex/html/ascii result type.
"Execute a block of Org code with.
This function is called by `org-babel-execute-src-block'."
(let ((result-params (split-string (or (cdr (assq :results params)) "")))
(body (org-babel-expand-body:org

View File

@ -1,6 +1,6 @@
;;; ob-perl.el --- Babel Functions for Perl -*- lexical-binding: t; -*-
;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
;; Authors: Dan Davison
;; Eric Schulte

View File

@ -1,6 +1,6 @@
;;; ob-plantuml.el --- Babel Functions for Plantuml -*- lexical-binding: t; -*-
;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
;; Author: Zhang Weize
;; Keywords: literate programming, reproducible research
@ -57,7 +57,7 @@ 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-args'."
You can also configure extra arguments via `org-plantuml-executable-args'."
:group 'org-babel
:package-version '(Org . "9.4")
:type 'symbol
@ -143,7 +143,6 @@ This function is called by `org-babel-execute-src-block'."
("eps" '("-teps"))
("pdf" '("-tpdf"))
("tex" '("-tlatex"))
("tikz" '("-tlatex:nopreamble"))
("vdx" '("-tvdx"))
("xmi" '("-txmi"))
("scxml" '("-tscxml"))

View File

@ -1,6 +1,6 @@
;;; ob-processing.el --- Babel functions for processing -*- lexical-binding: t; -*-
;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
;; Author: Jarmo Hurri (adapted from ob-asymptote.el written by Eric Schulte)
;; Maintainer: Jarmo Hurri <jarmo.hurri@iki.fi>
@ -118,7 +118,7 @@
(message "Not inside a Processing source block."))))
(defun org-babel-execute:processing (body params)
"Execute Processing code BODY according to PARAMS.
"Execute a block of Processing code.
This function is called by `org-babel-execute-src-block'."
(let ((sketch-code
(org-babel-expand-body:generic
@ -144,8 +144,7 @@ Processing does not support sessions."
(error "Processing does not support sessions"))
(defun org-babel-variable-assignments:processing (params)
"Return list of processing statements assigning the block's variables.
The variable assignments are defined in PARAMS."
"Return list of processing statements assigning the block's variables."
(mapcar #'org-babel-processing-var-to-processing
(org-babel--get-vars params)))

View File

@ -1,6 +1,6 @@
;;; ob-python.el --- Babel Functions for Python -*- lexical-binding: t; -*-
;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
;; Authors: Eric Schulte
;; Dan Davison
@ -41,65 +41,35 @@
(defvar org-babel-default-header-args:python '())
(defconst org-babel-header-args:python
'((return . :any)
(python . :any)
(async . ((yes no))))
"Python-specific header arguments.")
(defcustom org-babel-python-command 'auto
"Command (including arguments) for interactive and non-interactive Python code.
When not `auto', it overrides `org-babel-python-command-session'
and `org-babel-python-command-nonsession'."
:package-version '(Org . "9.7")
:group 'org-babel
:type '(choice string (const auto)))
(defcustom org-babel-python-command-session 'auto
"Command (including arguments) for starting interactive Python sessions.
If `auto' (the default), uses the values from
`python-shell-interpreter' and `python-shell-interpreter-args'.
If `org-babel-python-command' is set, then it overrides this
option."
:package-version '(Org . "9.7")
:group 'org-babel
:type '(choice string (const auto)))
(defcustom org-babel-python-command-nonsession "python"
"Command (including arguments) for executing non-interactive Python code.
If `org-babel-python-command' is set, then it overrides this option."
:package-version '(Org . "9.7")
(defcustom org-babel-python-command "python"
"Name of the command for executing Python code."
:version "24.4"
:package-version '(Org . "8.0")
:group 'org-babel
:type 'string)
(defcustom org-babel-python-hline-to "None"
"Replace hlines in incoming tables with this when translating to python."
:group 'org-babel
:version "24.4"
:package-version '(Org . "8.0")
:type 'string)
(defcustom org-babel-python-None-to 'hline
"Replace `None' in python tables with this before returning."
:group 'org-babel
:version "24.4"
:package-version '(Org . "8.0")
:type 'symbol)
(defun org-babel-python-associate-session (session)
"Associate Python code buffer with an Python session.
Make SESSION without earmuffs be the Python buffer name."
(setq-local python-shell-buffer-name
(org-babel-python-without-earmuffs session)))
(defun org-babel-execute:python (body params)
"Execute Python BODY according to PARAMS.
"Execute a block of Python code with Babel.
This function is called by `org-babel-execute-src-block'."
(let* ((org-babel-python-command
(or (cdr (assq :python params))
org-babel-python-command))
(session (org-babel-python-initiate-session
(cdr (assq :session params))))
(graphics-file (and (member "graphics" (assq :result-params params))
(org-babel-graphical-output-file params)))
(result-params (cdr (assq :result-params params)))
(result-type (cdr (assq :result-type params)))
(return-val (when (eq result-type 'value)
@ -115,7 +85,7 @@ This function is called by `org-babel-execute-src-block'."
(format (if session "\n%s" "\nreturn %s") return-val))))
(result (org-babel-python-evaluate
session full-body result-type
result-params preamble async graphics-file)))
result-params preamble async)))
(org-babel-reassemble-table
result
(org-babel-pick-name (cdr (assq :colname-names params))
@ -147,63 +117,8 @@ VARS contains resolved variable references."
;; helper functions
(defconst org-babel-python--output-graphics-wrapper "\
import matplotlib.pyplot
matplotlib.pyplot.gcf().clear()
%s
matplotlib.pyplot.savefig('%s')"
"Format string for saving Python graphical output.
Has two %s escapes, for the Python code to be evaluated, and the
file to save the graphics to.")
(defconst org-babel-python--def-format-value "\
def __org_babel_python_format_value(result, result_file, result_params):
with open(result_file, 'w') as f:
if 'graphics' in result_params:
result.savefig(result_file)
elif 'pp' in result_params:
import pprint
f.write(pprint.pformat(result))
elif 'list' in result_params and isinstance(result, dict):
f.write(str(['{} :: {}'.format(k, v) for k, v in result.items()]))
else:
if not set(result_params).intersection(\
['scalar', 'verbatim', 'raw']):
def dict2table(res):
if isinstance(res, dict):
return [(k, dict2table(v)) for k, v in res.items()]
elif isinstance(res, list) or isinstance(res, tuple):
return [dict2table(x) for x in res]
else:
return res
if 'table' in result_params:
result = dict2table(result)
try:
import pandas
except ImportError:
pass
else:
if isinstance(result, pandas.DataFrame) and 'table' in result_params:
result = [[result.index.name or ''] + list(result.columns)] + \
[None] + [[i] + list(row) for i, row in result.iterrows()]
elif isinstance(result, pandas.Series) and 'table' in result_params:
result = list(result.items())
try:
import numpy
except ImportError:
pass
else:
if isinstance(result, numpy.ndarray):
if 'table' in result_params:
result = result.tolist()
else:
result = repr(result)
f.write(str(result))"
"Python function to format value result and save it to file.")
(defun org-babel-variable-assignments:python (params)
"Return a list of Python statements assigning the block's variables.
The assignments are defined in PARAMS."
"Return a list of Python statements assigning the block's variables."
(mapcar
(lambda (pair)
(format "%s=%s"
@ -225,13 +140,9 @@ specifying a variable of the same value."
(defun org-babel-python-table-or-string (results)
"Convert RESULTS into an appropriate elisp value.
If the results look like a list or tuple (but not a dict), then
convert them into an Emacs-lisp table. Otherwise return the
results as a string."
(let ((res (if (and (> (length results) 0)
(string-equal "{" (substring results 0 1)))
results ;don't covert dicts to elisp
(org-babel-script-escape results))))
If the results look like a list or tuple, then convert them into an
Emacs-lisp table, otherwise return the results as a string."
(let ((res (org-babel-script-escape results)))
(if (listp res)
(mapcar (lambda (el) (if (eq el 'None)
org-babel-python-None-to el))
@ -245,7 +156,6 @@ results as a string."
(cdr (assoc session org-babel-python-buffers)))
(defun org-babel-python-with-earmuffs (session)
"Return SESSION name as string, ensuring *...* around."
(let ((name (if (stringp session) session (format "%s" session))))
(if (and (string= "*" (substring name 0 1))
(string= "*" (substring name (- (length name) 1))))
@ -253,113 +163,54 @@ results as a string."
(format "*%s*" name))))
(defun org-babel-python-without-earmuffs (session)
"Return SESSION name as string, without *...* around."
(let ((name (if (stringp session) session (format "%s" session))))
(if (and (string= "*" (substring name 0 1))
(string= "*" (substring name (- (length name) 1))))
(substring name 1 (- (length name) 1))
name)))
(defun org-babel-session-buffer:python (session &optional _)
"Return session buffer name for SESSION."
(or (org-babel-python-session-buffer session)
(org-babel-python-with-earmuffs session)))
(defun org-babel-python--python-util-comint-end-of-output-p ()
"Return non-nil if the last prompt matches input prompt.
Backport of `python-util-comint-end-of-output-p' to emacs28. To
be removed after minimum supported version reaches emacs29."
(when-let ((prompt (python-util-comint-last-prompt)))
(python-shell-comint-end-of-output-p
(buffer-substring-no-properties
(car prompt) (cdr prompt)))))
(defun org-babel-python--command (is-session)
"Helper function to return the Python command.
This checks `org-babel-python-command', and then
`org-babel-python-command-session' (if IS-SESSION) or
`org-babel-python-command-nonsession' (if not IS-SESSION). If
IS-SESSION, this might return `nil', which means to use
`python-shell-calculate-command'."
(or (unless (eq org-babel-python-command 'auto)
org-babel-python-command)
(if is-session
(unless (eq org-babel-python-command-session 'auto)
org-babel-python-command-session)
org-babel-python-command-nonsession)))
(defvar-local org-babel-python--initialized nil
"Flag used to mark that python session has been initialized.")
(defun org-babel-python--setup-session ()
"Babel Python session setup code, to be run once per session.
Function should be run from within the Python session buffer.
This is often run as a part of `python-shell-first-prompt-hook',
unless the Python session was created outside Org."
(python-shell-send-string-no-output org-babel-python--def-format-value)
(setq-local org-babel-python--initialized t))
(defun org-babel-python-initiate-session-by-key (&optional session)
"Initiate a python session.
If there is not a current inferior-process-buffer matching
SESSION then create it. If inferior process already
exists (e.g. if it was manually started with `run-python'), make
sure it's configured to work with ob-python. If session has
already been configured as such, do nothing. Return the
initialized session."
If there is not a current inferior-process-buffer in SESSION
then create. Return the initialized session."
(save-window-excursion
(let* ((session (if session (intern session) :default))
(py-buffer (org-babel-session-buffer:python session))
(py-buffer (or (org-babel-python-session-buffer session)
(org-babel-python-with-earmuffs session)))
(cmd (if (member system-type '(cygwin windows-nt ms-dos))
(concat org-babel-python-command " -i")
org-babel-python-command))
(python-shell-buffer-name
(org-babel-python-without-earmuffs py-buffer))
(existing-session-p (comint-check-proc py-buffer))
(cmd (org-babel-python--command t)))
(if cmd
(let* ((cmd-split (split-string-and-unquote cmd))
(python-shell-interpreter (car cmd-split))
(python-shell-interpreter-args
(combine-and-quote-strings
(append (cdr cmd-split)
(when (member system-type
'(cygwin windows-nt ms-dos))
(list "-i"))))))
(run-python))
(run-python))
(existing-session-p (comint-check-proc py-buffer)))
(run-python cmd)
(with-current-buffer py-buffer
(if existing-session-p
;; Session was created outside Org. Assume first prompt
;; already happened; run session setup code directly
(unless org-babel-python--initialized
;; Ensure first prompt. Based on python-tests.el
;; (`python-tests-shell-wait-for-prompt')
(while (not (org-babel-python--python-util-comint-end-of-output-p))
(sit-for 0.1))
(org-babel-python--setup-session))
;; Adding to `python-shell-first-prompt-hook' immediately
;; after `run-python' should be safe from race conditions,
;; because subprocess output only arrives when Emacs is
;; waiting (see elisp manual, "Output from Processes")
(add-hook
'python-shell-first-prompt-hook
#'org-babel-python--setup-session
nil 'local)))
;; Wait until Python initializes
;; This is more reliable compared to
;; `org-babel-comint-wait-for-output' as python may emit
;; multiple prompts during initialization.
(with-current-buffer py-buffer
(while (not org-babel-python--initialized)
(sleep-for 0.010)))
;; Adding to `python-shell-first-prompt-hook' immediately
;; after `run-python' should be safe from race conditions,
;; because subprocess output only arrives when Emacs is
;; waiting (see elisp manual, "Output from Processes")
(add-hook
'python-shell-first-prompt-hook
(lambda () (setq-local org-babel-python--initialized t))
nil 'local))
;; Don't hang if session was started externally
(unless existing-session-p
;; Wait until Python initializes
;; This is more reliable compared to
;; `org-babel-comint-wait-for-output' as python may emit
;; multiple prompts during initialization.
(with-current-buffer py-buffer
(while (not org-babel-python--initialized)
(org-babel-comint-wait-for-output py-buffer))))
(setq org-babel-python-buffers
(cons (cons session py-buffer)
(assq-delete-all session org-babel-python-buffers)))
session)))
(defun org-babel-python-initiate-session (&optional session _params)
"Initiate Python session named SESSION according to PARAMS.
If there is not a current inferior-process-buffer matching
SESSION then create it. If inferior process already
exists (e.g. if it was manually started with `run-python'), make
sure it's configured to work with ob-python. If session has
already been configured as such, do nothing."
"Create a session named SESSION according to PARAMS."
(unless (string= session "none")
(org-babel-python-session-buffer
(org-babel-python-initiate-session-by-key session))))
@ -367,10 +218,31 @@ already been configured as such, do nothing."
(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():
%s
open('%s', 'w').write( str(main()) )")
(defconst org-babel-python-pp-wrapper-method
"
import pprint
def main():
%s
open('%s', 'w').write( pprint.pformat(main()) )")
(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.
RESULT-PARAMS defines the result type."
"Return Python code to evaluate SRC-FILE and write result to RESULT-FILE."
(format "\
import ast
with open('%s') as __org_babel_python_tmpfile:
@ -381,25 +253,30 @@ if isinstance(__org_babel_python_final, ast.Expr):
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_python_format_value(__org_babel_python_final, '%s', %s)"
__org_babel_python_final = None"
(org-babel-process-file-name src-file 'noquote)
(org-babel-process-file-name result-file 'noquote)
(org-babel-python-var-to-python result-params)))
(if (member "pp" result-params) "True" "False")))
(defun org-babel-python-evaluate
(session body &optional result-type result-params preamble async graphics-file)
(session body &optional result-type result-params preamble async)
"Evaluate BODY as Python code."
(if session
(if async
(org-babel-python-async-evaluate-session
session body result-type result-params graphics-file)
session body result-type result-params)
(org-babel-python-evaluate-session
session body result-type result-params graphics-file))
session body result-type result-params))
(org-babel-python-evaluate-external-process
body result-type result-params preamble graphics-file)))
body result-type result-params preamble)))
(defun org-babel-python--shift-right (body &optional count)
(with-temp-buffer
@ -415,38 +292,31 @@ __org_babel_python_format_value(__org_babel_python_final, '%s', %s)"
(buffer-string)))
(defun org-babel-python-evaluate-external-process
(body &optional result-type result-params preamble graphics-file)
(body &optional result-type result-params preamble)
"Evaluate BODY in external python process.
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. If GRAPHICS-FILE is
non-nil, then save graphical results to that file instead."
string. If RESULT-TYPE equals `value' then return the value of the
last statement in BODY, as elisp."
(let ((raw
(pcase result-type
(`output (org-babel-eval (org-babel-python--command nil)
(`output (org-babel-eval org-babel-python-command
(concat preamble (and preamble "\n")
(if graphics-file
(format org-babel-python--output-graphics-wrapper
body graphics-file)
body))))
(`value (let ((results-file (or graphics-file
(org-babel-temp-file "python-"))))
(org-babel-eval (org-babel-python--command nil)
body)))
(`value (let ((tmp-file (org-babel-temp-file "python-")))
(org-babel-eval
org-babel-python-command
(concat
preamble (and preamble "\n")
(format
(concat org-babel-python--def-format-value "
def main():
%s
__org_babel_python_format_value(main(), '%s', %s)")
(org-babel-python--shift-right body)
(org-babel-process-file-name results-file 'noquote)
(org-babel-python-var-to-python result-params))))
(org-babel-eval-read-file results-file))))))
(if (member "pp" result-params)
org-babel-python-pp-wrapper-method
org-babel-python-wrapper-method)
(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 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.
@ -470,50 +340,41 @@ finally:
(org-babel-python-without-earmuffs session)))
(python-shell-send-string body))
;; same as `python-shell-comint-end-of-output-p' in emacs-25.1+
(while (not (and (python-shell-comint-end-of-output-p string-buffer)
(string-match
org-babel-python-eoe-indicator
string-buffer)))
(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 graphics-file)
(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. If GRAPHICS-FILE is
non-nil, then save graphical results to that file instead."
string. If RESULT-TYPE equals `value' then return the value of the
last statement in BODY, as elisp."
(let* ((tmp-src-file (org-babel-temp-file "python-"))
(results
(progn
(with-temp-file tmp-src-file
(insert (if (and graphics-file (eq result-type 'output))
(format org-babel-python--output-graphics-wrapper
body graphics-file)
body)))
(with-temp-file tmp-src-file (insert body))
(pcase result-type
(`output
(let ((body (format "\
with open('%s') as f:
exec(compile(f.read(), f.name, 'exec'))"
(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* ((results-file (or graphics-file
(org-babel-temp-file "python-")))
(let* ((tmp-results-file (org-babel-temp-file "python-"))
(body (org-babel-python-format-session-value
tmp-src-file results-file result-params)))
tmp-src-file tmp-results-file result-params)))
(org-babel-python-send-string session body)
(sleep-for 0.010)
(org-babel-eval-read-file results-file)))))))
(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."
"Strip \\='s from around Python string."
(if (and (string-prefix-p "'" string)
(string-suffix-p "'" string))
(substring string 1 -1)
@ -531,7 +392,7 @@ with open('%s') as f:
(org-babel-python-table-or-string results))))
(defun org-babel-python-async-evaluate-session
(session body &optional result-type result-params graphics-file)
(session body &optional result-type result-params)
"Asynchronously evaluate BODY in SESSION.
Returns a placeholder string for insertion, to later be replaced
by `org-babel-comint-async-filter'."
@ -539,37 +400,28 @@ by `org-babel-comint-async-filter'."
session (current-buffer)
"ob_comint_async_python_\\(.+\\)_\\(.+\\)"
'org-babel-chomp 'org-babel-python-async-value-callback)
(pcase result-type
(`output
(let ((uuid (org-id-uuid)))
(with-temp-buffer
(insert (format org-babel-python-async-indicator "start" uuid))
(insert "\n")
(insert (if graphics-file
(format org-babel-python--output-graphics-wrapper
body graphics-file)
body))
(insert "\n")
(insert (format org-babel-python-async-indicator "end" uuid))
(let ((python-shell-buffer-name
(org-babel-python-without-earmuffs session)))
(python-shell-send-buffer)))
uuid))
(`value
(let ((results-file (or graphics-file
(org-babel-temp-file "python-")))
(tmp-src-file (org-babel-temp-file "python-")))
(with-temp-file tmp-src-file (insert body))
(with-temp-buffer
(insert (org-babel-python-format-session-value
tmp-src-file results-file result-params))
(insert "\n")
(unless graphics-file
(insert (format org-babel-python-async-indicator "file" results-file)))
(let ((python-shell-buffer-name
(org-babel-python-without-earmuffs session)))
(python-shell-send-buffer)))
results-file))))
(let ((python-shell-buffer-name (org-babel-python-without-earmuffs session)))
(pcase result-type
(`output
(let ((uuid (org-id-uuid)))
(with-temp-buffer
(insert (format org-babel-python-async-indicator "start" uuid))
(insert "\n")
(insert body)
(insert "\n")
(insert (format org-babel-python-async-indicator "end" uuid))
(python-shell-send-buffer))
uuid))
(`value
(let ((tmp-results-file (org-babel-temp-file "python-"))
(tmp-src-file (org-babel-temp-file "python-")))
(with-temp-file tmp-src-file (insert body))
(with-temp-buffer
(insert (org-babel-python-format-session-value tmp-src-file tmp-results-file result-params))
(insert "\n")
(insert (format org-babel-python-async-indicator "file" tmp-results-file))
(python-shell-send-buffer))
tmp-results-file)))))
(provide 'ob-python)

View File

@ -1,6 +1,6 @@
;;; ob-ref.el --- Babel Functions for Referencing External Data -*- lexical-binding: t; -*-
;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
;; Authors: Eric Schulte
;; Dan Davison
@ -59,9 +59,8 @@
(declare-function org-babel-lob-get-info "ob-lob" (&optional datum no-eval))
(declare-function org-element-at-point "org-element" (&optional pom cached-only))
(declare-function org-element-property "org-element-ast" (property node))
(declare-function org-element-post-affiliated "org-element" (node))
(declare-function org-element-type "org-element-ast" (node &optional anonymous))
(declare-function org-element-property "org-element" (property element))
(declare-function org-element-type "org-element" (element))
(declare-function org-end-of-meta-data "org" (&optional full))
(declare-function org-find-property "org" (property &optional value))
(declare-function org-id-find-id-file "org-id" (id))
@ -156,9 +155,8 @@ Emacs Lisp representation of the value of the variable."
(when (string-match "^\\(.+\\):\\(.+\\)$" ref)
(setq split-file (match-string 1 ref))
(setq split-ref (match-string 2 ref))
(when (file-exists-p split-file)
(find-file split-file)
(setq ref split-ref)))
(find-file split-file)
(setq ref split-ref))
(org-with-wide-buffer
(goto-char (point-min))
(let* ((params (append args '((:results . "none"))))
@ -173,7 +171,7 @@ Emacs Lisp representation of the value of the variable."
(let ((e (org-element-at-point)))
(when (equal (org-element-property :name e) ref)
(goto-char
(org-element-post-affiliated e))
(org-element-property :post-affiliated e))
(pcase (org-element-type e)
(`babel-call
(throw :found

View File

@ -1,6 +1,6 @@
;;; ob-ruby.el --- Babel Functions for Ruby -*- lexical-binding: t; -*-
;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Keywords: literate programming, reproducible research
@ -73,7 +73,7 @@ It's possible to override it by using a header argument `:ruby'")
:type 'symbol)
(defun org-babel-execute:ruby (body params)
"Execute Ruby BODY according to PARAMS.
"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)) params))
@ -127,8 +127,7 @@ This function is called by `org-babel-execute-src-block'."
;; helper functions
(defun org-babel-variable-assignments:ruby (params)
"Return list of ruby statements assigning the block's variables.
The assignments are defined in PARAMS."
"Return list of ruby statements assigning the block's variables."
(mapcar
(lambda (pair)
(format "%s=%s"
@ -141,7 +140,7 @@ The assignments are defined in PARAMS."
Convert an elisp value into a string of ruby source code
specifying a variable of the same value."
(if (listp var)
(concat "[" (mapconcat #'org-babel-ruby-var-to-ruby var ", \n") "]")
(concat "[" (mapconcat #'org-babel-ruby-var-to-ruby var ", ") "]")
(if (eq var 'hline)
org-babel-ruby-hline-to
(format "%S" var))))
@ -153,28 +152,20 @@ Emacs-lisp table, otherwise return the results as a string."
(let ((res (org-babel-script-escape results)))
(if (listp res)
(mapcar (lambda (el) (if (not el)
org-babel-ruby-nil-to el))
org-babel-ruby-nil-to el))
res)
res)))
(defvar org-babel-ruby-prompt "_org_babel_ruby_prompt "
"String used for unique prompt.")
(defvar org-babel-ruby-define-prompt
(format "IRB.conf[:PROMPT][:CUSTOM] = { :PROMPT_I => \"%s\" }" org-babel-ruby-prompt))
(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.
Session settings (`:ruby' header arg value) are taken from PARAMS."
then create one. Return the initialized session."
(unless (string= session "none")
(org-require-package 'inf-ruby)
(let* ((command (cdr (or (assq :ruby params)
(assoc inf-ruby-default-implementation
inf-ruby-implementations))))
(buffer (get-buffer (format "*%s*" session)))
(new-session? (not buffer))
(session-buffer (or buffer (save-window-excursion
(run-ruby-or-pop-to-buffer
(if (functionp command)
@ -185,32 +176,16 @@ Session settings (`:ruby' header arg value) are taken from PARAMS."
(inf-ruby-buffer)))
(current-buffer)))))
(if (org-babel-comint-buffer-livep session-buffer)
(progn
(sit-for .25)
;; Setup machine-readable prompt: no echo, prompts matching
;; uniquely by regexp.
(when new-session?
(with-current-buffer session-buffer
(setq-local
org-babel-comint-prompt-regexp-old comint-prompt-regexp
comint-prompt-regexp (concat "^" org-babel-ruby-prompt))
(insert org-babel-ruby-define-prompt ";")
(insert "_org_prompt_mode=conf.prompt_mode;conf.prompt_mode=:CUSTOM;")
(insert "conf.echo=false\n")
(comint-send-input nil t)))
session-buffer)
(progn (sit-for .25) session-buffer)
(sit-for .5)
(org-babel-ruby-initiate-session session)))))
(defvar org-babel-ruby-eoe-indicator ":org_babel_ruby_eoe"
"String to indicate that evaluation has completed.")
(defvar org-babel-ruby-f-write
"File.open('%s','w'){|f| f.write((_.class == String) ? _ : _.inspect)}")
(defvar org-babel-ruby-pp-f-write
"File.open('%s','w'){|f| $stdout = f; pp(results); $stdout = orig_out}")
(defvar org-babel-ruby-wrapper-method
"
def main()
@ -219,7 +194,6 @@ end
results = main()
File.open('%s', 'w'){ |f| f.write((results.class == String) ? results : results.inspect) }
")
(defvar org-babel-ruby-pp-wrapper-method
"
require 'pp'
@ -263,6 +237,7 @@ return the value of the last statement in BODY, as elisp."
(org-babel-comint-with-output
(buffer org-babel-ruby-eoe-indicator t eoe-string)
(insert eoe-string) (comint-send-input nil t))
;; Now we can start the evaluation.
(mapconcat
#'identity
(butlast
@ -271,9 +246,14 @@ return the value of the last statement in BODY, as elisp."
#'org-trim
(org-babel-comint-with-output
(buffer org-babel-ruby-eoe-indicator t body)
(insert (org-babel-chomp body) "\n" eoe-string)
(comint-send-input nil t))
"\n") "[\r\n]")) "\n")))
(mapc
(lambda (line)
(insert (org-babel-chomp line)) (comint-send-input nil t))
(list "conf.echo=false;_org_prompt_mode=conf.prompt_mode;conf.prompt_mode=:NULL"
body
"conf.prompt_mode=_org_prompt_mode;conf.echo=true"
eoe-string)))
"\n") "[\r\n]") 4) "\n")))
(`value
(let* ((tmp-file (org-babel-temp-file "ruby-"))
(ppp (or (member "code" result-params)
@ -293,7 +273,7 @@ return the value of the last statement in BODY, as elisp."
"results=_" "require 'pp'" "orig_out = $stdout"
(format org-babel-ruby-pp-f-write
(org-babel-process-file-name tmp-file 'noquote))))
(list (format "puts \"%s\"" org-babel-ruby-eoe-indicator))))
(list org-babel-ruby-eoe-indicator)))
(comint-send-input nil t))
(org-babel-eval-read-file tmp-file))))))

View File

@ -1,6 +1,6 @@
;;; ob-sass.el --- Babel Functions for the Sass CSS generation language -*- lexical-binding: t; -*-
;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Keywords: literate programming, reproducible research

View File

@ -1,6 +1,6 @@
;;; ob-scheme.el --- Babel Functions for Scheme -*- lexical-binding: t; -*-
;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
;; Authors: Eric Schulte
;; Michael Gauland
@ -54,7 +54,7 @@
(defvar geiser-debug-jump-to-debug-p) ; Defined in geiser-debug.el
(defvar geiser-repl-use-other-window) ; Defined in geiser-repl.el
(defvar geiser-repl-window-allow-split) ; Defined in geiser-repl.el
(declare-function geiser-connect "ext:geiser-repl" (impl &optional host port))
(declare-function run-geiser "ext:geiser-repl" (impl))
(declare-function geiser "ext:geiser-repl" (impl))
(declare-function geiser-mode "ext:geiser-mode" ())
@ -78,17 +78,6 @@
(defvar org-babel-default-header-args:scheme '()
"Default header arguments for scheme code blocks.")
(defconst org-babel-header-args:scheme '((host . :any)
(port . :any))
"Header arguments supported in Scheme.")
(defun org-babel-scheme-expand-header-arg-vars (vars)
"Expand :var header arguments given as VARS."
(mapconcat
(lambda (var)
(format "(define %S %S)" (car var) (cdr var)))
vars
"\n"))
(defun org-babel-expand-body:scheme (body params)
"Expand BODY according to PARAMS, return the expanded body."
@ -97,7 +86,13 @@
(postpends (cdr (assq :epilogue params))))
(concat (and prepends (concat prepends "\n"))
(if (null vars) body
(concat (org-babel-scheme-expand-header-arg-vars vars) "\n" body))
(format "(let (%s)\n%s\n)"
(mapconcat
(lambda (var)
(format "%S" (print `(,(car var) ',(cdr var)))))
vars
"\n ")
body))
(and postpends (concat "\n" postpends)))))
@ -124,17 +119,13 @@
(with-current-buffer (set-buffer buffer)
geiser-impl--implementation))
(defun org-babel-scheme-get-repl (impl name &optional host port)
"Switch to a Scheme REPL, creating it if it doesn't exist.
If the variables HOST and PORT are set, connect to the running Scheme REPL."
(defun org-babel-scheme-get-repl (impl name)
"Switch to a scheme REPL, creating it if it doesn't exist."
(let ((buffer (org-babel-scheme-get-session-buffer name)))
(or buffer
(progn
(if (fboundp 'geiser)
(if (and host port)
(geiser-connect impl host port)
(geiser impl))
(geiser impl)
;; Obsolete since Geiser 0.26.
(run-geiser impl))
(when name
@ -171,7 +162,7 @@ org-babel-scheme-execute-with-geiser will use a temporary session."
,@body
(current-message))))
(defun org-babel-scheme-execute-with-geiser (code output impl repl &optional host port)
(defun org-babel-scheme-execute-with-geiser (code output impl repl)
"Execute code in specified REPL.
If the REPL doesn't exist, create it using the given scheme
implementation.
@ -187,7 +178,7 @@ is true; otherwise returns the last value."
(let ((geiser-repl-window-allow-split nil)
(geiser-repl-use-other-window nil))
(let ((repl-buffer (save-current-buffer
(org-babel-scheme-get-repl impl repl host port))))
(org-babel-scheme-get-repl impl repl))))
(when (not (eq impl (org-babel-scheme-get-buffer-impl
(current-buffer))))
(message "Implementation mismatch: %s (%s) %s (%s)" impl (symbolp impl)
@ -251,8 +242,6 @@ This function is called by `org-babel-execute-src-block'."
geiser-scheme-implementation
geiser-default-implementation
(car geiser-active-implementations)))
(host (cdr (assq :host params)))
(port (cdr (assq :port params)))
(session (org-babel-scheme-make-session-name
source-buffer-name (cdr (assq :session params)) impl))
(full-body (org-babel-expand-body:scheme body params))
@ -262,9 +251,7 @@ This function is called by `org-babel-execute-src-block'."
full-body ; code
(string= result-type "output") ; output?
impl ; implementation
(and (not (string= session "none")) session) ; session
host ; REPL host
port))) ; REPL port
(and (not (string= session "none")) session)))) ; session
(let ((table
(org-babel-reassemble-table
result

View File

@ -1,6 +1,6 @@
;;; ob-screen.el --- Babel Support for Interactive Terminal -*- lexical-binding: t; -*-
;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
;; Author: Benjamin Andresen
;; Maintainer: Ken Mankoff <mankoff@gmail.com>
@ -50,8 +50,8 @@ In case you want to use a different screen than one selected by your $PATH")
"Default arguments to use when running screen source blocks.")
(defun org-babel-execute:screen (body params)
"Send BODY via screen to a terminal using Babel, according to PARAMS.
\"default\" session is used when none is specified in the PARAMS."
"Send a block of code via screen to a terminal using Babel.
\"default\" session is used when none is specified."
(message "Sending source code block to interactive terminal session...")
(save-window-excursion
(let* ((session (cdr (assq :session params)))

View File

@ -1,6 +1,6 @@
;;; ob-sed.el --- Babel Functions for Sed Scripts -*- lexical-binding: t; -*-
;; Copyright (C) 2015-2024 Free Software Foundation, Inc.
;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
;; Author: Bjarte Johansen
;; Keywords: literate programming, reproducible research

View File

@ -1,6 +1,6 @@
;;; ob-shell.el --- Babel Functions for Shell Evaluation -*- lexical-binding: t; -*-
;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Maintainer: Matthew Trzcinski <matt@excalamus.com>
@ -45,11 +45,6 @@
(declare-function orgtbl-to-generic "org-table" (table params))
(defvar org-babel-default-header-args:shell '())
(defconst org-babel-header-args:shell
'((async . ((yes no))))
"Shell-specific header arguments.")
(defvar org-babel-shell-names)
(defconst org-babel-shell-set-prompt-commands
@ -57,6 +52,8 @@
("fish" . "function fish_prompt\n\techo \"%s\"\nend")
;; prompt2 is like PS2 in POSIX shells.
("csh" . "set prompt=\"%s\"\nset prompt2=\"\"")
;; PowerShell, similar to fish, does not have PS2 equivalent.
("posh" . "function prompt { \"%s\" }")
;; PROMPT_COMMAND can override PS1 settings. Disable it.
;; Disable PS2 to avoid garbage in multi-line inputs.
(t . "PROMPT_COMMAND=;PS1=\"%s\";PS2="))
@ -70,6 +67,8 @@ that will be called with a single additional argument: prompt string.
The fallback association template is defined in (t . \"template\")
alist element.")
(defvar org-babel-prompt-command)
(defun org-babel-shell-initialize ()
"Define execution functions associated to shell names.
This function has to be called whenever `org-babel-shell-names'
@ -81,8 +80,10 @@ is modified outside the Customize interface."
(lambda (body params)
(:documentation
(format "Execute a block of %s commands with Babel." name))
(let ((explicit-shell-file-name name)
(shell-file-name name))
(let ((shell-file-name name)
(org-babel-prompt-command
(or (cdr (assoc name org-babel-shell-set-prompt-commands))
(alist-get t org-babel-shell-set-prompt-commands))))
(org-babel-execute:shell body params))))
(put fname 'definition-name 'org-babel-shell-initialize))
(defalias (intern (concat "org-babel-variable-assignments:" name))
@ -92,9 +93,6 @@ variables."
name))
(funcall (if (fboundp 'defvar-1) #'defvar-1 #'set) ;Emacs-29
(intern (concat "org-babel-default-header-args:" name))
nil)
(funcall (if (fboundp 'defvar-1) #'defvar-1 #'set) ;Emacs-29
(intern (concat "org-babel-header-args:" name))
nil)))
(defcustom org-babel-shell-names
@ -122,7 +120,7 @@ a shell execution being its exit code."
:package-version '(Org . "9.4"))
(defun org-babel-execute:shell (body params)
"Execute Shell BODY according to PARAMS.
"Execute a block of Shell commands with Babel.
This function is called by `org-babel-execute-src-block'."
(let* ((session (org-babel-sh-initiate-session
(cdr (assq :session params))))
@ -174,11 +172,6 @@ This function is called by `org-babel-execute-src-block'."
"Return a list of statements declaring the values as a generic variable."
(format "%s=%s" varname (org-babel-sh-var-to-sh values sep hline)))
(defun org-babel--variable-assignments:fish
(varname values &optional sep hline)
"Return a list of statements declaring the values as a fish variable."
(format "set %s %s" varname (org-babel-sh-var-to-sh values sep hline)))
(defun org-babel--variable-assignments:bash_array
(varname values &optional sep hline)
"Return a list of statements declaring the values as a bash array."
@ -224,11 +217,8 @@ This function is called by `org-babel-execute-src-block'."
(if (string-suffix-p "bash" shell-file-name)
(org-babel--variable-assignments:bash
(car pair) (cdr pair) sep hline)
(if (string-suffix-p "fish" shell-file-name)
(org-babel--variable-assignments:fish
(car pair) (cdr pair) sep hline)
(org-babel--variable-assignments:sh-generic
(car pair) (cdr pair) sep hline))))
(org-babel--variable-assignments:sh-generic
(car pair) (cdr pair) sep hline)))
(org-babel--get-vars params))))
(defun org-babel-sh-var-to-sh (var &optional sep hline)
@ -269,16 +259,10 @@ var of the same value."
(org-babel-comint-wait-for-output (current-buffer))
(org-babel-comint-input-command
(current-buffer)
(format
(or (cdr (assoc (file-name-nondirectory shell-file-name)
org-babel-shell-set-prompt-commands))
(alist-get t org-babel-shell-set-prompt-commands))
org-babel-sh-prompt))
(setq-local
org-babel-comint-prompt-regexp-old comint-prompt-regexp
comint-prompt-regexp
(concat "^" (regexp-quote org-babel-sh-prompt)
" *"))
(format org-babel-prompt-command org-babel-sh-prompt))
(setq-local comint-prompt-regexp
(concat "^" (regexp-quote org-babel-sh-prompt)
" *"))
;; Needed for Emacs 23 since the marker is initially
;; undefined and the filter functions try to use it without
;; checking.
@ -373,13 +357,7 @@ return the value of the last statement in BODY."
(when padline (insert "\n"))
(insert body))
(set-file-modes script-file #o755)
(if (file-remote-p script-file)
;; Run remote script using its local path as COMMAND.
;; The remote execution is ensured by setting
;; correct `default-directory'.
(let ((default-directory (file-name-directory script-file)))
(org-babel-eval (file-local-name script-file) ""))
(org-babel-eval script-file ""))))
(org-babel-eval script-file "")))
(t (org-babel-eval shell-file-name (org-trim body))))))
(when (and results value-is-exit-status)
(setq results (car (reverse (split-string results "\n" t)))))

View File

@ -1,6 +1,6 @@
;;; ob-sql.el --- Babel Functions for SQL -*- lexical-binding: t; -*-
;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Maintainer: Daniel Kraus <daniel@kraus.my>
@ -113,7 +113,9 @@
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)))
(condition-case nil
(sql-set-product product)
(user-error "Cannot set `sql-product' in Org Src edit buffer"))))
(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."
@ -407,11 +409,11 @@ argument mechanism."
val (if sqlite
nil
'(:fmt (lambda (el) (if (stringp el)
el
(format "%S" el))))))))
el
(format "%S" el))))))))
data-file)
(if (stringp val) val (format "%S" val))))
body t t)))
body)))
vars)
body)

View File

@ -1,6 +1,6 @@
;;; ob-sqlite.el --- Babel Functions for SQLite Databases -*- lexical-binding: t; -*-
;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Maintainer: Nick Savage <nick@nicksavage.ca>
@ -57,20 +57,13 @@
(defun org-babel-expand-body:sqlite (body params)
"Expand BODY according to the values of PARAMS."
(let ((prologue (cdr (assq :prologue params)))
(epilogue (cdr (assq :epilogue params))))
(mapconcat 'identity
(list
prologue
(org-babel-sql-expand-vars
body (org-babel--get-vars params) t)
epilogue)
"\n")))
(org-babel-sql-expand-vars
body (org-babel--get-vars params) t))
(defvar org-babel-sqlite3-command "sqlite3")
(defun org-babel-execute:sqlite (body params)
"Execute Sqlite BODY according to PARAMS.
"Execute a block of Sqlite code with Babel.
This function is called by `org-babel-execute-src-block'."
(let ((result-params (split-string (or (cdr (assq :results params)) "")))
(db (cdr (assq :db params)))
@ -81,6 +74,7 @@ This function is called by `org-babel-execute-src-block'."
(lambda (arg) (car (assq arg params)))
(list :header :echo :bail :column
:csv :html :line :list)))))
(unless db (error "ob-sqlite: can't evaluate without a database"))
(with-temp-buffer
(insert
(org-babel-eval
@ -103,7 +97,7 @@ This function is called by `org-babel-execute-src-block'."
(member :html others) separator)
""
"-csv"))
(cons "db" (or db ""))))
(cons "db " db)))
;; body of the code block
(org-babel-expand-body:sqlite body params)))
(org-babel-result-cond result-params
@ -128,8 +122,7 @@ This function is called by `org-babel-execute-src-block'."
(org-babel-sql-expand-vars body vars t))
(defun org-babel-sqlite-table-or-scalar (result)
"Cleanup cells in the RESULT table.
If RESULT is a trivial 1x1 table, then unwrap it."
"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) t)
@ -140,7 +133,7 @@ If RESULT is a trivial 1x1 table, then unwrap it."
result)))
(defun org-babel-sqlite-offset-colnames (table headers-p)
"If HEADERS-P is non-nil then offset the first row as column names in TABLE."
"If HEADERS-P is non-nil then offset the first row as column names."
(if headers-p
(cons (car table) (cons 'hline (cdr table)))
table))

View File

@ -1,6 +1,6 @@
;;; ob-table.el --- Support for Calling Babel Functions from Tables -*- lexical-binding: t; -*-
;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Keywords: literate programming, reproducible research

View File

@ -1,6 +1,6 @@
;;; ob-tangle.el --- Extract Source Code From Org Files -*- lexical-binding: t; -*-
;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
;; Author: Eric Schulte
;; Keywords: literate programming, reproducible research
@ -40,11 +40,11 @@
(declare-function org-babel-update-block-body "ob-core" (new-body))
(declare-function org-back-to-heading "org" (&optional invisible-ok))
(declare-function org-before-first-heading-p "org" ())
(declare-function org-element-lineage "org-element-ast" (datum &optional types with-self))
(declare-function org-element-property "org-element-ast" (property node))
(declare-function org-element-begin "org-element" (node))
(declare-function org-element--cache-active-p "org-element" ())
(declare-function org-element-lineage "org-element" (datum &optional types with-self))
(declare-function org-element-property "org-element" (property element))
(declare-function org-element-at-point "org-element" (&optional pom cached-only))
(declare-function org-element-type-p "org-element-ast" (node types))
(declare-function org-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))
@ -166,23 +166,6 @@ read-write permissions for the user, read-only for everyone else."
:package-version '(Org . "9.6")
:type 'integer)
(defcustom org-babel-tangle-remove-file-before-write 'auto
"How to overwrite the existing tangle target.
When set to nil, `org-babel-tangle' will replace contents of an existing
tangle target (and fail when tangle target is read-only).
When set to t, the tangle target (including read-only) will be deleted
first and a new file, possibly with different ownership and
permissions, will be created.
When set to symbol `auto', overwrite read-only tangle targets and
replace contents otherwise."
:group 'org-babel-tangle
:package-version '(Org . "9.7")
:type '(choice
(const :tag "Replace contents, but keep the same file" nil)
(const :tag "Re-create file" t)
(const :tag "Re-create when read-only" auto))
:safe t)
(defun org-babel-find-file-noselect-refresh (file)
"Find file ensuring that the latest changes on disk are
represented in the file."
@ -222,20 +205,21 @@ source code blocks by languages matching a regular expression.
Return list of the tangled file names."
(interactive "fFile to tangle: \nP")
(org-with-file-buffer file
(org-with-wide-buffer
(mapcar #'expand-file-name
(org-babel-tangle nil target-file lang-re)))))
(let* ((visited (find-buffer-visiting file))
(buffer (or visited (find-file-noselect file))))
(prog1
(with-current-buffer buffer
(org-with-wide-buffer
(mapcar #'expand-file-name
(org-babel-tangle nil target-file lang-re))))
(unless visited (kill-buffer buffer)))))
(defun org-babel-tangle-publish (_ filename pub-dir)
"Tangle FILENAME and place the results in PUB-DIR."
(unless (file-exists-p pub-dir)
(make-directory pub-dir t))
(setq pub-dir (file-name-as-directory pub-dir))
;; Rename files to avoid copying to same file when publishing to ./
;; `copy-file' would throw an error when copying file to self.
(mapc (lambda (el) (rename-file el pub-dir t))
(org-babel-tangle-file filename)))
(mapc (lambda (el) (copy-file el pub-dir t)) (org-babel-tangle-file filename)))
;;;###autoload
(defun org-babel-tangle (&optional arg target-file lang-re)
@ -269,8 +253,7 @@ matching a regular expression."
(when (equal arg '(16))
(or (cdr (assq :tangle (nth 2 (org-babel-get-src-block-info 'no-eval))))
(user-error "Point is not in a source code block"))))
path-collector
(source-file buffer-file-name))
path-collector)
(mapc ;; map over file-names
(lambda (by-fn)
(let ((file-name (car by-fn)))
@ -327,28 +310,10 @@ matching a regular expression."
(compare-buffer-substrings
nil nil nil
tangle-buf nil nil)))))))
(when (equal (if (file-name-absolute-p file-name)
file-name
(expand-file-name file-name))
(if (file-name-absolute-p source-file)
source-file
(expand-file-name source-file)))
(error "Not allowed to tangle into the same file as self"))
;; We do not erase, but overwrite previous file
;; to preserve any existing symlinks.
;; This behavior is modified using
;; `org-babel-tangle-remove-file-before-write' to
;; tangle to read-only files.
(when (and
(file-exists-p file-name)
(pcase org-babel-tangle-remove-file-before-write
(`auto (not (file-writable-p file-name)))
(`t t)
(`nil nil)
(_ (error "Invalid value of `org-babel-tangle-remove-file-before-write': %S"
org-babel-tangle-remove-file-before-write))))
;; erase previous file
(when (file-exists-p file-name)
(delete-file file-name))
(write-region nil nil file-name)
(write-region nil nil file-name)
(mapc (lambda (mode) (set-file-modes file-name mode)) modes))
(push file-name path-collector))))))
(if (equal arg '(4))
@ -413,7 +378,7 @@ references."
(goto-char (point-min))
(while (or (re-search-forward "\\[\\[file:.*\\]\\[.*\\]\\]" nil t)
(re-search-forward (org-babel-noweb-wrap) nil t))
(delete-region (save-excursion (forward-line) (point))
(delete-region (save-excursion (beginning-of-line 1) (point))
(save-excursion (end-of-line 1) (forward-char 1) (point)))))
(defun org-babel-spec-to-string (spec)
@ -462,19 +427,17 @@ that the appropriate major-mode is set. SPEC has the form:
org-babel-tangle-comment-format-end link-data)))))
(defun org-babel-effective-tangled-filename (buffer-fn src-lang src-tfile)
"Return effective tangled absolute filename of a source-code block.
BUFFER-FN is the absolute file name of the buffer, SRC-LANG the
language of the block and SRC-TFILE is the value of the :tangle
header argument, as computed by `org-babel-tangle-single-block'."
(let* ((fnd (file-name-directory buffer-fn))
(base-name (cond
((string= "yes" src-tfile)
;; Use the buffer name
(file-name-sans-extension buffer-fn))
((string= "no" src-tfile) nil)
((> (length src-tfile) 0)
(expand-file-name src-tfile fnd))))
(ext (or (cdr (assoc src-lang org-babel-tangle-lang-exts)) src-lang)))
"Return effective tangled filename of a source-code block.
BUFFER-FN is the name of the buffer, SRC-LANG the language of the
block and SRC-TFILE is the value of the :tangle header argument,
as computed by `org-babel-tangle-single-block'."
(let ((base-name (cond
((string= "yes" src-tfile)
;; Use the buffer name
(file-name-sans-extension buffer-fn))
((string= "no" src-tfile) nil)
((> (length src-tfile) 0) src-tfile)))
(ext (or (cdr (assoc src-lang org-babel-tangle-lang-exts)) src-lang)))
(when base-name
;; decide if we want to add ext to base-name
(if (and ext (string= "yes" src-tfile))
@ -491,16 +454,13 @@ 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)
(buffer-fn (buffer-file-name (buffer-base-buffer)))
last-heading-pos blocks)
(let ((counter 0) last-heading-pos blocks)
(org-babel-map-src-blocks (buffer-file-name)
(let ((current-heading-pos
(or (org-element-begin
(org-element-lineage
(org-element-at-point)
'headline t))
1)))
(if (org-element--cache-active-p)
(or (org-element-property :begin (org-element-lineage (org-element-at-point) '(headline) t)) 1)
(org-with-wide-buffer
(org-with-limited-levels (outline-previous-heading))))))
(if (eq last-heading-pos current-heading-pos) (cl-incf counter)
(setq counter 1)
(setq last-heading-pos current-heading-pos)))
@ -510,7 +470,6 @@ code blocks by target file."
(src-lang (nth 0 info))
(src-tfile (cdr (assq :tangle (nth 2 info)))))
(unless (or (string= src-tfile "no")
(not src-lang) ;; src block without lang
(and tangle-file (not (equal tangle-file src-tfile)))
(and lang-re (not (string-match-p lang-re src-lang))))
;; Add the spec for this block to blocks under its tangled
@ -518,7 +477,7 @@ code blocks by target file."
(let* ((block (org-babel-tangle-single-block counter))
(src-tfile (cdr (assq :tangle (nth 4 block))))
(file-name (org-babel-effective-tangled-filename
buffer-fn src-lang src-tfile))
(nth 1 block) src-lang src-tfile))
(by-fn (assoc file-name blocks)))
(if by-fn (setcdr by-fn (cons (cons src-lang block) (cdr by-fn)))
(push (cons file-name (list (cons src-lang block))) blocks)))))))
@ -532,7 +491,12 @@ code blocks by target file."
The PARAMS are the 3rd element of the info for the same src block."
(unless (string= "no" (cdr (assq :comments params)))
(save-match-data
(let* ((l (org-no-properties
(let* (;; The created link is transient. Using ID is not necessary,
;; but could have side-effects if used. An ID property may
;; be added to existing entries thus creating unexpected file
;; modifications.
(org-id-link-to-org-use-id nil)
(l (org-no-properties
(cl-letf (((symbol-function 'org-store-link-functions)
(lambda () nil)))
(org-store-link nil))))
@ -549,7 +513,6 @@ The PARAMS are the 3rd element of the info for the same src block."
(cdr (assq :tangle params)))))
bare))))))
(defvar org-outline-regexp) ; defined in lisp/org.el
(defun org-babel-tangle-single-block (block-counter &optional only-this-block)
"Collect the tangled source for current block.
Return the list of block attributes needed by
@ -607,8 +570,8 @@ non-nil, return the full association list to be used by
(buffer-substring
(max (condition-case nil
(save-excursion
(org-back-to-heading t)
(re-search-forward org-outline-regexp))
(org-back-to-heading t) ; Sets match data
(match-end 0))
(error (point-min)))
(save-excursion
(if (re-search-backward
@ -625,12 +588,13 @@ non-nil, return the full association list to be used by
link
source-name
params
(if (org-src-preserve-indentation-p) (org-trim body t)
(if org-src-preserve-indentation
(org-trim body t)
(org-trim (org-remove-indentation body)))
comment)))
(if only-this-block
(let* ((file-name (org-babel-effective-tangled-filename
file src-lang src-tfile)))
(nth 1 result) src-lang src-tfile)))
(list (cons file-name (list (cons src-lang result)))))
result)))
@ -651,12 +615,9 @@ by `org-babel-get-src-block-info'."
;; de-tangling functions
(defun org-babel-detangle (&optional source-code-file)
"Propagate changes from current source buffer back to the original Org file.
"Propagate changes in source file back original to Org file.
This requires that code blocks were tangled with link comments
which enable the original code blocks to be found.
Optional argument SOURCE-CODE-FILE is the file path to be used instead
of the current buffer."
which enable the original code blocks to be found."
(interactive)
(save-excursion
(when source-code-file (find-file source-code-file))
@ -711,7 +672,8 @@ of the current buffer."
(org-back-to-heading t))
;; Do not skip the first block if it begins at point min.
(cond ((or (org-at-heading-p)
(not (org-element-type-p (org-element-at-point) 'src-block)))
(not (eq (org-element-type (org-element-at-point))
'src-block)))
(org-babel-next-src-block n))
((= n 1))
(t (org-babel-next-src-block (1- n)))))

View File

@ -1,6 +1,6 @@
;;; ob.el --- Working with Code Blocks in Org -*- lexical-binding: t; -*-
;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
;; Authors: Eric Schulte
;; Keywords: literate programming, reproducible research

View File

@ -1,6 +1,6 @@
;;; oc-basic.el --- basic backend for citations -*- lexical-binding: t; -*-
;;; oc-basic.el --- basic back-end for citations -*- lexical-binding: t; -*-
;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
@ -78,19 +78,9 @@
(declare-function org-open-at-point "org" (&optional arg))
(declare-function org-open-file "org" (path &optional in-emacs line search))
(declare-function org-element-create "org-element-ast" (type &optional props &rest children))
(declare-function org-element-set "org-element-ast" (old new &optional keep-props))
(declare-function org-element-interpret-data "org-element" (data))
(declare-function org-element-parse-secondary-string "org-element" (string restriction &optional parent))
(declare-function org-element-map "org-element"
( data types fun
&optional
info first-match no-recursion
with-affiliated no-undefer))
(declare-function org-element-property "org-element-ast" (property node))
(declare-function org-element-type-p "org-element-ast" (node types))
(declare-function org-element-contents "org-element-ast" (node))
(declare-function org-element-property "org-element" (property element))
(declare-function org-element-type "org-element" (element))
(declare-function org-export-data "org-export" (data info))
(declare-function org-export-derived-backend-p "org-export" (backend &rest backends))
@ -172,7 +162,7 @@ Return a hash table with citation references as keys and fields alist as values.
(puthash (cdr (assq 'id item))
(mapcar (pcase-lambda (`(,field . ,value))
(pcase field
((or 'author 'editor)
((or 'author 'editors)
;; Author and editors are arrays of
;; objects, each of them designing a
;; person. These objects may contain
@ -282,9 +272,6 @@ Optional argument INFO is the export state, as a property list."
(plist-get info :cite-basic/bibliography)
(let ((results nil))
(dolist (file (org-cite-list-bibliography-files))
;; Follow symlinks, to look into modification time of the
;; actual file, not its symlink.
(setq file (file-truename file))
(when (file-readable-p file)
(with-temp-buffer
(when (or (org-file-has-changed-p file)
@ -343,9 +330,9 @@ FIELD is a symbol. ENTRY-OR-KEY is either an association list, as returned by
Optional argument INFO is the export state, as a property list.
Return value may be nil or a string. If current export backend is derived
from `latex', return a raw string object instead, unless optional
argument RAW is non-nil.
Return value may be nil or a string. If current export back-end is derived
from `latex', return a raw string instead, unless optional argument RAW is
non-nil.
Throw an error if the field value is non-string and non-nil."
(let ((value
@ -368,27 +355,17 @@ Throw an error if the field value is non-string and non-nil."
(defun org-cite-basic--shorten-names (names)
"Return a list of family names from a list of full NAMES.
NAMES can be a string or raw string object.
To better accomomodate corporate names, this will only shorten
personal names of the form \"family, given\"."
(let (names-string raw-p)
(cond
((stringp names) (setq names-string names))
((org-element-type-p names 'raw)
(setq names-string (mapconcat #'identity (org-element-contents names) "")
raw-p t)))
(when names-string
(setq names-string
(mapconcat
(lambda (name)
(if (eq 1 (length name))
(cdr (split-string name))
(car (split-string name ", "))))
(split-string names-string " and ")
", "))
(if raw-p (org-export-raw-string names-string)
names-string))))
(when (stringp names)
(mapconcat
(lambda (name)
(if (eq 1 (length name))
(cdr (split-string name))
(car (split-string name ", "))))
(split-string names " and ")
", ")))
(defun org-cite-basic--number-to-suffix (n)
"Compute suffix associated to number N.
@ -444,7 +421,7 @@ necessary, unless optional argument NO-SUFFIX is non-nil."
(year
(or (org-cite-basic--get-field 'year entry-or-key info 'raw)
(let ((date
(org-cite-basic--get-field 'date entry-or-key info 'raw)))
(org-cite-basic--get-field 'date entry-or-key info t)))
(and (stringp date)
(string-match (rx string-start
(group (= 4 digit))
@ -472,38 +449,6 @@ necessary, unless optional argument NO-SUFFIX is non-nil."
new))))
(if no-suffix year (concat year suffix)))))))
(defun org-cite-basic--print-bibtex-string (element &optional info)
"Print Bibtex formatted string ELEMENT, according to Bibtex syntax.
Remove all the {...} that are not a part of LaTeX macros and parse the
LaTeX fragments. Do nothing when current backend is derived from
LaTeX, according to INFO.
Return updated ELEMENT."
(if (org-export-derived-backend-p (plist-get info :back-end) 'latex)
;; Derived from LaTeX, no need to use manual ad-hoc LaTeX
;; parser.
element
;; Convert ELEMENT to anonymous when ELEMENT is string.
;; Otherwise, we cannot modify ELEMENT by side effect.
(when (org-element-type-p element 'plain-text)
(setq element (org-element-create 'anonymous nil element)))
;; Approximately parse LaTeX fragments, assuming Org mode syntax
;; (it is close to original LaTeX, and we do not want to
;; re-implement complete LaTeX parser here))
(org-element-map element t
(lambda (str)
(when (stringp str)
(org-element-set
str
(org-element-parse-secondary-string
str '(latex-fragment entity))))))
;; Strip the remaining { and }.
(org-element-map element t
(lambda (str)
(when (stringp str)
(org-element-set str (replace-regexp-in-string "[{}]" "" str)))))
element))
(defun org-cite-basic--print-entry (entry style &optional info)
"Format ENTRY according to STYLE string.
ENTRY is an alist, as returned by `org-cite-basic--get-entry'.
@ -515,29 +460,27 @@ Optional argument INFO is the export state, as a property list."
(org-cite-basic--get-field 'journal entry info)
(org-cite-basic--get-field 'institution entry info)
(org-cite-basic--get-field 'school entry info))))
(org-cite-basic--print-bibtex-string
(pcase style
("plain"
(let ((year (org-cite-basic--get-year entry info 'no-suffix)))
(org-cite-concat
(org-cite-basic--shorten-names author) ". "
title (and from (list ", " from)) ", " year ".")))
("numeric"
(let ((n (org-cite-basic--key-number (cdr (assq 'id entry)) info))
(year (org-cite-basic--get-year entry info 'no-suffix)))
(org-cite-concat
(format "[%d] " n) author ", "
(org-cite-emphasize 'italic title)
(and from (list ", " from)) ", "
year ".")))
;; Default to author-year. Use year disambiguation there.
(_
(let ((year (org-cite-basic--get-year entry info)))
(org-cite-concat
author " (" year "). "
(org-cite-emphasize 'italic title)
(and from (list ", " from)) "."))))
info)))
(pcase style
("plain"
(let ((year (org-cite-basic--get-year entry info 'no-suffix)))
(org-cite-concat
(org-cite-basic--shorten-names author) ". "
title (and from (list ", " from)) ", " year ".")))
("numeric"
(let ((n (org-cite-basic--key-number (cdr (assq 'id entry)) info))
(year (org-cite-basic--get-year entry info 'no-suffix)))
(org-cite-concat
(format "[%d] " n) author ", "
(org-cite-emphasize 'italic title)
(and from (list ", " from)) ", "
year ".")))
;; Default to author-year. Use year disambiguation there.
(_
(let ((year (org-cite-basic--get-year entry info)))
(org-cite-concat
author " (" year "). "
(org-cite-emphasize 'italic title)
(and from (list ", " from)) "."))))))
;;; "Activate" capability
@ -710,30 +653,22 @@ export communication channel, as a property list."
;; "author" style.
(`(,(or "author" "a") . ,variant)
(let ((caps (member variant '("caps" "c"))))
(org-cite-basic--format-author-year
citation
(lambda (p c s) (org-cite-concat p c s))
(lambda (prefix author _ suffix)
(org-cite-concat
prefix
(if caps (org-cite-capitalize author) author)
suffix))
(org-export-data
(mapconcat
(lambda (key)
(or
(let ((author (org-cite-basic--get-author key info)))
(if caps (capitalize author) author))
"??"))
(org-cite-get-references citation t)
org-cite-basic-author-year-separator)
info)))
;; "noauthor" style.
(`(,(or "noauthor" "na") . ,variant)
(let ((bare? (funcall has-variant-p variant 'bare)))
(org-cite-basic--format-author-year
citation
(lambda (prefix contents suffix)
(org-cite-concat
(unless bare? "(")
prefix
contents
suffix
(unless bare? ")")))
(lambda (prefix _ year suffix)
(org-cite-concat prefix year suffix))
info)))
(format (if (funcall has-variant-p variant 'bare) "%s" "(%s)")
(mapconcat (lambda (key) (or (org-cite-basic--get-year key info) "????"))
(org-cite-get-references citation t)
org-cite-basic-author-year-separator)))
;; "nocite" style.
(`(,(or "nocite" "n") . ,_) nil)
;; "text" and "note" styles.
@ -749,11 +684,10 @@ export communication channel, as a property list."
(lambda (p c s) (org-cite-concat p c s))
(lambda (p a y s)
(org-cite-concat p
(if caps (org-cite-capitalize a) a)
(if caps (capitalize a) a)
(if bare " " " (")
y
(and (not bare) ")")
s))
y s
(and (not bare) ")")))
info)))
;; "numeric" style.
;;
@ -774,7 +708,7 @@ export communication channel, as a property list."
(lambda (p c s)
(org-cite-concat (and (not bare) "(") p c s (and (not bare) ")")))
(lambda (p a y s)
(org-cite-concat p (if caps (org-cite-capitalize a) a) ", " y s))
(org-cite-concat p (if caps (capitalize a) a) ", " y s))
info)))
;; This should not happen.
(_ (error "Invalid style: %S" style)))))
@ -782,7 +716,7 @@ export communication channel, as a property list."
(defun org-cite-basic-export-bibliography (keys _files style _props backend info)
"Generate bibliography.
KEYS is the list of cited keys, as strings. STYLE is the expected bibliography
style, as a string. BACKEND is the export backend, as a symbol. INFO is the
style, as a string. BACKEND is the export back-end, as a symbol. INFO is the
export state, as a property list."
(mapconcat
(lambda (entry)
@ -806,7 +740,7 @@ When DATUM is a citation reference, open bibliography entry referencing
the citation key. Otherwise, select which key to follow among all keys
present in the citation."
(let* ((key
(if (org-element-type-p datum 'citation-reference)
(if (eq 'citation-reference (org-element-type datum))
(org-element-property :key datum)
(pcase (org-cite-get-references datum t)
(`(,key) key)
@ -878,7 +812,7 @@ Return nil if there are no bibliography files or no entries."
(let ((date (org-cite-basic--get-year entry nil 'no-suffix)))
(format "%4s" (or date "")))
org-cite-basic-column-separator
(org-cite-basic--get-field 'title entry nil 'raw))))
(org-cite-basic--get-field 'title entry nil t))))
(puthash completion key org-cite-basic--completion-cache)))
(unless (map-empty-p org-cite-basic--completion-cache) ;no key
(puthash entries t org-cite-basic--completion-cache)

View File

@ -1,6 +1,6 @@
;;; oc-biblatex.el --- biblatex citation processor for Org -*- lexical-binding: t; -*-
;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
@ -26,7 +26,7 @@
;; The processor relies on "biblatex" LaTeX package. As such it ensures that
;; the package is properly required in the document's preamble. More
;; accurately, it will reuse any "\usepackage{biblatex}" already present in
;; accurately, it will re-use any "\usepackage{biblatex}" already present in
;; the document (e.g., through `org-latex-packages-alist'), or insert one using
;; options defined in `org-cite-biblatex-options'.
@ -70,8 +70,7 @@
(require 'org-macs)
(require 'oc)
(declare-function org-element-property "org-element-ast" (property node))
(declare-function org-element-parent "org-element-ast" (node))
(declare-function org-element-property "org-element" (property element))
(declare-function org-export-data "org-export" (data info))
@ -232,7 +231,7 @@ When NO-OPT argument is non-nil, only provide mandatory arguments."
(let* ((origin (pcase references
(`(,reference) reference)
(`(,reference . ,_)
(org-element-parent reference))))
(org-element-property :parent reference))))
(suffix (org-element-property :suffix origin))
(prefix (org-element-property :prefix origin)))
(concat (and prefix
@ -376,47 +375,61 @@ INFO is the export state, as a property list."
(other
(user-error "Invalid entry %S in `org-cite-biblatex-styles'" other))))))
(defun org-cite-biblatex--generate-latex-usepackage (info)
"Ensure that the biblatex package is loaded.
This is performed by extracting relevant information from the
INFO export plist, and modifying any existing
\\usepackage{biblatex} statement in the LaTeX header."
(let ((style (org-cite-bibliography-style info))
(usepackage-rx (rx "\\usepackage"
(opt (group "[" (*? anything) "]"))
"{biblatex}")))
(concat
(if (string-match usepackage-rx (plist-get info :latex-full-header))
;; "biblatex" package loaded, but with none (or different) options.
;; Replace with style-including command.
(plist-put info :latex-full-header
(replace-match
(format "\\usepackage%s{biblatex}"
(save-match-data
(org-cite-biblatex--package-options nil style)))
t t
(plist-get info :latex-full-header)))
;; No "biblatex" package loaded. Insert "usepackage" command
;; with appropriate options, including style.
(format "\\usepackage%s{biblatex}\n"
(org-cite-biblatex--package-options
org-cite-biblatex-options style))))))
(defun org-cite-biblatex-prepare-preamble (output _keys files style &rest _)
"Prepare document preamble for \"biblatex\" usage.
(defun org-cite-biblatex--generate-latex-bibresources (info)
"From INFO generate LaTeX that loads the relevant bibliography resource files."
(let ((files (plist-get info :bibliography)))
(mapconcat (lambda (f)
(format "\\addbibresource%s{%s}"
(if (org-url-p f) "[location=remote]" "")
f))
files
"\n")))
OUTPUT is the final output of the export process. FILES is the list of file
names used as the bibliography.
This function ensures \"biblatex\" package is required. It also adds resources
to the document, and set styles."
(with-temp-buffer
(save-excursion (insert output))
(when (search-forward "\\begin{document}" nil t)
;; Ensure there is a \usepackage{biblatex} somewhere or add one.
;; Then set options.
(goto-char (match-beginning 0))
(let ((re (rx "\\usepackage"
(opt (group "[" (*? anything) "]"))
"{biblatex}")))
(cond
;; No "biblatex" package loaded. Insert "usepackage" command
;; with appropriate options, including style.
((not (re-search-backward re nil t))
(save-excursion
(insert
(format "\\usepackage%s{biblatex}\n"
(org-cite-biblatex--package-options
org-cite-biblatex-options style)))))
;; "biblatex" package loaded, but without any option.
;; Include style only.
((not (match-beginning 1))
(search-forward "{" nil t)
(insert (org-cite-biblatex--package-options nil style)))
;; "biblatex" package loaded with some options set. Override
;; style-related options with ours.
(t
(replace-match
(save-match-data
(org-cite-biblatex--package-options (match-string 1) style))
nil nil nil 1))))
;; Insert resources below.
(forward-line)
(insert (mapconcat (lambda (f)
(format "\\addbibresource%s{%s}"
(if (org-url-p f) "[location=remote]" "")
f))
files
"\n")
"\n"))
(buffer-string)))
;;; Register `biblatex' processor
(org-cite-register-processor 'biblatex
:export-bibliography #'org-cite-biblatex-export-bibliography
:export-citation #'org-cite-biblatex-export-citation
:export-finalizer #'org-cite-biblatex-prepare-preamble
:cite-styles #'org-cite-biblatex-list-styles)
(provide 'oc-biblatex)

View File

@ -1,6 +1,6 @@
;;; oc-bibtex.el --- Vanilla citation processor for LaTeX -*- lexical-binding: t; -*-
;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
@ -41,7 +41,7 @@
(require 'oc)
(declare-function org-element-property "org-element-ast" (property node))
(declare-function org-element-property "org-element" (property element))
(declare-function org-export-data "org-export" (data info))

View File

@ -1,6 +1,6 @@
;;; oc-csl.el --- csl citation processor for Org -*- lexical-binding: t; -*-
;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
;; Maintainer: András Simonyi <andras.simonyi@gmail.com>
@ -137,8 +137,8 @@
(declare-function org-element-interpret-data "org-element" (data))
(declare-function org-element-map "org-element" (data types fun &optional info first-match no-recursion with-affiliated))
(declare-function org-element-property "org-element-ast" (property node))
(declare-function org-element-put-property "org-element-ast" (node property value))
(declare-function org-element-property "org-element" (property element))
(declare-function org-element-put-property "org-element" (element property value))
(declare-function org-export-data "org-export" (data info))
(declare-function org-export-derived-backend-p "org-export" (backend &rest backends))
@ -184,8 +184,8 @@ looks for style files in this directory, too."
:safe #'booleanp)
(defcustom org-cite-csl-no-citelinks-backends '(ascii)
"List of export backends for which cite linking is disabled.
Cite linking for export backends derived from any of the backends listed here,
"List of export back-ends for which cite linking is disabled.
Cite linking for export back-ends derived from any of the back-ends listed here,
is also disabled."
:group 'org-cite
:package-version '(Org . "9.5")
@ -215,20 +215,19 @@ Used only when `second-field-align' is activated by the used CSL style."
:safe #'stringp)
(defcustom org-cite-csl-latex-label-separator "0.6em"
"Distance between citation label and bibliography item for LaTeX output.
The value is a string representing the distance in valid LaTeX units.
Used only when `second-field-align' is activated by the used CSL
style.
"Distance between citation label and bibliography item for LaTeX
output in valid LaTeX units. Used only when `second-field-align'
is activated by the used CSL style.
The indentation length in these cases is computed as the sum of
`org-cite-csl-latex-label-separator' and the maximal label width, for
example,
`org-cite-csl-latex-label-separator' and the maximal label width,
for example,
indentation length
<------------------------->
max. label width separator
max. label width separator
<---------------><-------->
[Doe22] John Doe. A title...
[Doe22] John Doe. A title...
[DoeSmithJones19] John Doe, Jane Smith and...
[SmithDoe02] Jane Smith and John Doe...
@ -443,8 +442,8 @@ INFO is the export state, as a property list."
(defun org-cite-csl--create-structure-params (citation info)
"Return citeproc structure creation params for CITATION object.
STYLE is the citation style, as a string or nil. INFO is the export
state, as a property list."
STYLE is the citation style, as a string or nil. INFO is the export state, as
a property list."
(let ((style (org-cite-citation-style citation info)))
(pcase style
;; "author" style.
@ -504,8 +503,7 @@ state, as a property list."
(_ (error "Invalid style: %S" style)))))
(defun org-cite-csl--no-citelinks-p (info)
"Non-nil when export backend should not create cite-reference links.
INFO is the info channel plist."
"Non-nil when export BACKEND should not create cite-reference links."
(or (not org-cite-csl-link-cites)
(and org-cite-csl-no-citelinks-backends
(apply #'org-export-derived-backend-p
@ -847,11 +845,27 @@ INFO is the export state, as a property list."
;; process.
(org-cite-parse-elements output)))))
(defun org-cite-csl-finalizer (output _keys _files _style _backend info)
"Add \"hanging\" package if missing from LaTeX output.
OUTPUT is the export document, as a string. INFO is the export state, as a
property list."
(org-cite-csl--barf-without-citeproc)
(if (not (eq 'org-latex (org-cite-csl--output-format info)))
output
(with-temp-buffer
(save-excursion (insert output))
(when (search-forward "\\begin{document}" nil t)
(goto-char (match-beginning 0))
;; Insert the CSL-specific parts of the LaTeX preamble.
(insert (org-cite-csl--generate-latex-preamble info)))
(buffer-string))))
;;; Register `csl' processor
(org-cite-register-processor 'csl
:export-citation #'org-cite-csl-render-citation
:export-bibliography #'org-cite-csl-render-bibliography
:export-finalizer #'org-cite-csl-finalizer
:cite-styles
'((("author" "a") ("bare" "b") ("caps" "c") ("full" "f") ("bare-caps" "bc") ("caps-full" "cf") ("bare-caps-full" "bcf"))
(("noauthor" "na") ("bare" "b") ("caps" "c") ("bare-caps" "bc"))

View File

@ -1,6 +1,6 @@
;;; oc-natbib.el --- Citation processor using natbib LaTeX package -*- lexical-binding: t; -*-
;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
@ -48,7 +48,7 @@
(require 'oc)
(declare-function org-element-property "org-element-ast" (property node))
(declare-function org-element-property "org-element" (property element))
(declare-function org-export-data "org-export" (data info))
@ -168,25 +168,32 @@ state, as a property list."
(org-cite-natbib--build-optional-arguments citation info)
(org-cite-natbib--build-arguments citation)))
(defun org-cite-natbib--generate-latex-preamble (info)
"Ensure that the \"natbib\" package is loaded.
INFO is a plist used as a communication channel."
(and (not (string-match
(rx "\\usepackage" (opt "[" (*? nonl) "]") "{natbib}")
(plist-get info :latex-full-header)))
(format "\\usepackage%s{natbib}\n"
(if (null org-cite-natbib-options)
""
(format "[%s]"
(mapconcat #'symbol-name
org-cite-natbib-options
","))))))
(defun org-cite-natbib-use-package (output &rest _)
"Ensure output requires \"natbib\" package.
OUTPUT is the final output of the export process."
(with-temp-buffer
(save-excursion (insert output))
(when (search-forward "\\begin{document}" nil t)
;; Ensure there is a \usepackage{natbib} somewhere or add one.
(goto-char (match-beginning 0))
(let ((re (rx "\\usepackage" (opt "[" (*? nonl) "]") "{natbib}")))
(unless (re-search-backward re nil t)
(insert
(format "\\usepackage%s{natbib}\n"
(if (null org-cite-natbib-options)
""
(format "[%s]"
(mapconcat #'symbol-name
org-cite-natbib-options
","))))))))
(buffer-string)))
;;; Register `natbib' processor
(org-cite-register-processor 'natbib
:export-bibliography #'org-cite-natbib-export-bibliography
:export-citation #'org-cite-natbib-export-citation
:export-finalizer #'org-cite-natbib-use-package
:cite-styles
'((("author" "a") ("caps" "a") ("full" "f"))
(("noauthor" "na") ("bare" "b"))

View File

@ -1,6 +1,6 @@
;;; oc.el --- Org Cite library -*- lexical-binding: t; -*-
;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
@ -46,13 +46,13 @@
;; The "export" capability is slightly more involved as one need to
;; select the processor providing it, but may also provide a default
;; style for citations and bibliography. Also, the choice of an
;; export processor may depend of the current export backend. The
;; association between export backends and triplets of parameters can
;; export processor may depend of the current export back-end. The
;; association between export back-ends and triplets of parameters can
;; be set in `org-cite-export-processors' variable, or in a document,
;; through the "cite_export" keyword.
;; Eventually, this library provides some tools, mainly targeted at
;; processor implementers. Most are export-specific and are located
;; processor implementors. Most are export-specific and are located
;; in the "Tools only available during export" and "Tools generating
;; or operating on parsed data" sections.
@ -71,33 +71,25 @@
(declare-function org-at-heading-p "org" (&optional _))
(declare-function org-collect-keywords "org" (keywords &optional unique directory))
(declare-function org-element-adopt "org-element-ast" (parent &rest children))
(declare-function org-element-adopt-elements "org-element" (parent &rest children))
(declare-function org-element-citation-parser "org-element" ())
(declare-function org-element-citation-reference-parser "org-element" ())
(declare-function org-element-class "org-element" (datum &optional parent))
(declare-function org-element-contents "org-element-ast" (node))
(declare-function org-element-create "org-element-ast" (type &optional props &rest children))
(declare-function org-element-extract "org-element-ast" (node))
(declare-function org-element-insert-before "org-element-ast" (node location))
(declare-function org-element-lineage "org-element-ast" (datum &optional types with-self))
(declare-function org-element-contents "org-element" (element))
(declare-function org-element-create "org-element" (type &optional props &rest children))
(declare-function org-element-extract-element "org-element" (element))
(declare-function org-element-insert-before "org-element" (element location))
(declare-function org-element-lineage "org-element" (datum &optional types with-self))
(declare-function org-element-map "org-element" (data types fun &optional info first-match no-recursion with-affiliated))
(declare-function org-element-normalize-string "org-element" (s))
(declare-function org-element-parse-buffer "org-element" (&optional granularity visible-only keep-deferred))
(declare-function org-element-parse-buffer "org-element" (&optional granularity visible-only))
(declare-function org-element-parse-secondary-string "org-element" (string restriction &optional parent))
(declare-function org-element-context "org-element" (&optional element))
(declare-function org-element-property "org-element-ast" (property node))
(declare-function org-element-begin "org-element" (node))
(declare-function org-element-end "org-element" (node))
(declare-function org-element-post-affiliated "org-element" (node))
(declare-function org-element-post-blank "org-element" (node))
(declare-function org-element-contents-begin "org-element" (node))
(declare-function org-element-contents-end "org-element" (node))
(declare-function org-element-parent "org-element-ast" (node))
(declare-function org-element-put-property "org-element-ast" (node property value))
(declare-function org-element-property "org-element" (property element))
(declare-function org-element-put-property "org-element" (element property value))
(declare-function org-element-restriction "org-element" (element))
(declare-function org-element-set "org-element-ast" (old new))
(declare-function org-element-type "org-element-ast" (node &optional anonymous))
(declare-function org-element-type-p "org-element-ast" (node types))
(declare-function org-element-set-element "org-element" (old new))
(declare-function org-element-type "org-element" (element))
(declare-function org-export-derived-backend-p "org-export" (backend &rest backends))
(declare-function org-export-get-next-element "org-export" (blob info &optional n))
@ -151,12 +143,12 @@ File names must be absolute."
When nil, citations and bibliography are not exported.
When non-nil, the value is an association list between export backends and
When non-nil, the value is an association list between export back-ends and
citation export processors:
(BACKEND . PROCESSOR)
(BACK-END . PROCESSOR)
where BACKEND is the name of an export backend or t, and PROCESSOR is a
where BACK-END is the name of an export back-end or t, and PROCESSOR is a
triplet following the pattern
(NAME BIBLIOGRAPHY-STYLE CITATION-STYLE)
@ -168,7 +160,7 @@ exporting a citation), as a string or nil. Both BIBLIOGRAPHY-STYLE and
CITATION-STYLE are optional. NAME is mandatory.
The export process selects the citation processor associated to the current
export backend, or the most specific backend the current one is derived from,
export back-end, or the most specific back-end the current one is derived from,
or, if all are inadequate, to the processor associated to t. For example, with
the following value
@ -176,9 +168,9 @@ the following value
(latex biblatex)
(t csl))
exporting with `beamer' or any backend derived from it will use `natbib',
whereas exporting with `latex' or any backend derived from it but different
from `beamer' will use `biblatex' processor. Any other backend, such as
exporting with `beamer' or any back-end derived from it will use `natbib',
whereas exporting with `latex' or any back-end derived from it but different
from `beamer' will use `biblatex' processor. Any other back-end, such as
`html', will use `csl' processor.
CITATION-STYLE is overridden by adding a style to any citation object. A nil
@ -195,7 +187,7 @@ or
#+CITE_EXPORT: basic
In that case, `basic' processor is used on every export, independently on the
backend."
back-end."
:group 'org-cite
:package-version '(Org . "9.5")
:type '(choice (const :tag "No export" nil)
@ -353,7 +345,7 @@ optional keys can be set:
arguments: the list of citation keys used in the document, as
strings, a list of bibliography files, the style, as a string
or nil, the local properties, as a property list, the export
backend, as a symbol, and the communication channel, as a
back-end, as a symbol, and the communication channel, as a
property list.
It is called at each \"print_bibliography\" keyword in the
@ -366,7 +358,7 @@ optional keys can be set:
Function rendering citations. It is called with four
arguments: a citation object, the style, as a pair, the
export backend, as a symbol, and the communication channel,
export back-end, as a symbol, and the communication channel,
as a property list.
It is called on each citation object in the parse tree. It
@ -381,7 +373,7 @@ optional keys can be set:
six arguments: the output, as a string, a list of citation
keys used in the document, a list of bibliography files, the
expected bibliography style, as a string or nil, the export
backend, as a symbol, and the communication channel, as a
back-end, as a symbol, and the communication channel, as a
property list.
It must return a string, which will become the final output
@ -476,11 +468,11 @@ PROCESSOR is the name of a cite processor, as a symbol. CAPABILITY is
"Set `:post-blank' property from element or object before DATUM to BLANKS.
DATUM is an element or object. BLANKS is an integer. DATUM is modified
by side-effect."
(if (not (org-element-type-p datum 'plain-text))
(if (not (eq 'plain-text (org-element-type datum)))
(org-element-put-property datum :post-blank blanks)
;; Remove any blank from string before DATUM so it is exported
;; with exactly BLANKS white spaces.
(org-element-set
(org-element-set-element
datum
(replace-regexp-in-string
"[ \t\n]*\\'" (make-string blanks ?\s) datum))))
@ -500,11 +492,11 @@ S is split at beginning of match group N upon matching REGEXP against it.
This function assumes S precedes CITATION."
;; When extracting the citation, remove white spaces before it, but
;; preserve those after it.
(let ((post-blank (org-element-post-blank citation)))
(let ((post-blank (org-element-property :post-blank citation)))
(when (and post-blank (> post-blank 0))
(org-element-insert-before (make-string post-blank ?\s) citation)))
(org-element-insert-before
(org-element-put-property (org-element-extract citation)
(org-element-put-property (org-element-extract-element citation)
:post-blank 0)
s)
(string-match regexp s)
@ -518,21 +510,21 @@ This function assumes S precedes CITATION."
(substring s split))))
(when (org-string-nw-p first-part)
(org-element-insert-before first-part citation))
(org-element-set s last-part)))
(org-element-set-element s last-part)))
(defun org-cite--move-punct-before (punct citation s info)
"Move punctuation PUNCT before CITATION object.
String S contains PUNCT. INFO is the export state, as a property list.
The function assumes S follows CITATION. Parse tree is modified by side-effect."
(if (equal s punct)
(org-element-extract s) ;it would be empty anyway
(org-element-set s (substring s (length punct))))
(org-element-extract-element s) ;it would be empty anyway
(org-element-set-element s (substring s (length punct))))
;; Remove blanks before citation.
(org-cite--set-previous-post-blank citation 0 info)
(org-element-insert-before
;; Blanks between citation and punct are now before punct and
;; citation.
(concat (make-string (or (org-element-post-blank citation) 0) ?\s)
(concat (make-string (or (org-element-property :post-blank citation) 0) ?\s)
punct)
citation))
@ -610,18 +602,7 @@ to (adaptive outside after)."
(append (mapcar (lambda (value)
(pcase value
(`(,f . ,d)
(setq f (org-strip-quotes f))
(if (or (file-name-absolute-p f)
(file-remote-p f)
(equal d default-directory))
;; Keep absolute paths, remote paths, and
;; local relative paths.
f
;; Adjust relative bibliography path for
;; #+SETUP files located in other directory.
;; Also, see `org-export--update-included-link'.
(file-relative-name
(expand-file-name f d) default-directory)))))
(expand-file-name (org-strip-quotes f) d))))
(pcase (org-collect-keywords
'("BIBLIOGRAPHY") nil '("BIBLIOGRAPHY"))
(`(("BIBLIOGRAPHY" . ,pairs)) pairs)))
@ -638,12 +619,12 @@ or from the current buffer."
(let ((contents (org-element-contents citation)))
(cond
((null contents)
(org-with-point-at (org-element-contents-begin citation)
(narrow-to-region (point) (org-element-contents-end citation))
(org-with-point-at (org-element-property :contents-begin citation)
(narrow-to-region (point) (org-element-property :contents-end citation))
(let ((references nil))
(while (not (eobp))
(let ((reference (org-element-citation-reference-parser)))
(goto-char (org-element-end reference))
(goto-char (org-element-property :end reference))
(push (if keys-only
(org-element-property :key reference)
reference)
@ -655,8 +636,8 @@ or from the current buffer."
(defun org-cite-boundaries (citation)
"Return the beginning and end strict position of CITATION.
Returns a (BEG . END) pair."
(let ((beg (org-element-begin citation))
(end (org-with-point-at (org-element-end citation)
(let ((beg (org-element-property :begin citation))
(end (org-with-point-at (org-element-property :end citation)
(skip-chars-backward " \t")
(point))))
(cons beg end)))
@ -665,15 +646,15 @@ Returns a (BEG . END) pair."
"Return citation REFERENCE's key boundaries as buffer positions.
The function returns a pair (START . END) where START and END denote positions
in the current buffer. Positions include leading \"@\" character."
(org-with-point-at (org-element-begin reference)
(let ((end (org-element-end reference)))
(org-with-point-at (org-element-property :begin reference)
(let ((end (org-element-property :end reference)))
(re-search-forward org-element-citation-key-re end t)
(cons (match-beginning 0) (match-end 0)))))
(defun org-cite-main-affixes (citation)
"Return main affixes for CITATION object.
Some export backends only support a single pair of affixes per
Some export back-ends only support a single pair of affixes per
citation, even if it contains multiple keys. This function
decides what affixes are the most appropriate.
@ -749,7 +730,7 @@ When removing the last reference, also remove the whole citation."
(org-with-point-at begin
(skip-chars-backward " \t")
(point)))
(pos-after-blank (org-element-end datum))
(pos-after-blank (org-element-property :end datum))
(first-on-line?
(= pos-before-blank (line-beginning-position)))
(last-on-line?
@ -772,22 +753,22 @@ When removing the last reference, also remove the whole citation."
(when (= pos-after-blank end)
(org-with-point-at pos-before-blank (insert " ")))))))
('citation-reference
(let* ((citation (org-element-parent datum))
(let* ((citation (org-element-property :parent datum))
(references (org-cite-get-references citation))
(begin (org-element-begin datum))
(end (org-element-end datum)))
(begin (org-element-property :begin datum))
(end (org-element-property :end datum)))
(cond
;; Single reference.
((= 1 (length references))
(org-cite-delete-citation citation))
;; First reference, no prefix.
((and (= begin (org-element-contents-begin citation))
((and (= begin (org-element-property :contents-begin citation))
(not (org-element-property :prefix citation)))
(org-with-point-at (org-element-begin datum)
(org-with-point-at (org-element-property :begin datum)
(skip-chars-backward " \t")
(delete-region (point) end)))
;; Last reference, no suffix.
((and (= end (org-element-contents-end citation))
((and (= end (org-element-property :contents-end citation))
(not (org-element-property :suffix citation)))
(delete-region (1- begin) (1- (cdr (org-cite-boundaries citation)))))
;; Somewhere in-between.
@ -961,12 +942,11 @@ the sole contents of the footnote, e.g., after calling `org-cite-wrap-citation'.
When non-nil, the return value if the footnote container."
(let ((footnote
(org-element-lineage
citation
'(footnote-definition footnote-reference))))
(org-element-lineage citation
'(footnote-definition footnote-reference))))
(and footnote
(or (not strict)
(equal (org-element-contents (org-element-parent citation))
(equal (org-element-contents (org-element-property :parent citation))
(list citation)))
;; Return value.
footnote)))
@ -984,15 +964,15 @@ Return newly created footnote object."
(list 'footnote-reference
(list :label nil
:type 'inline
:contents-begin (org-element-begin citation)
:contents-end (org-element-end citation)
:post-blank (org-element-post-blank citation)))))
:contents-begin (org-element-property :begin citation)
:contents-end (org-element-property :end citation)
:post-blank (org-element-property :post-blank citation)))))
;; Remove any white space before citation.
(org-cite--set-previous-post-blank citation 0 info)
;; Footnote swallows citation.
(org-element-insert-before footnote citation)
(org-element-adopt footnote
(org-element-extract citation))))
(org-element-adopt-elements footnote
(org-element-extract-element citation))))
(defun org-cite-adjust-note (citation info &optional rule punct)
"Adjust note number location for CITATION object, and punctuation around it.
@ -1071,8 +1051,8 @@ the same object, call `org-cite-adjust-note' first."
;; as an argument is not available.
(rx-to-string `(seq string-start ,final-punct) t)
"" next)))
(org-element-set previous new-prev)
(org-element-set next new-next)
(org-element-set-element previous new-prev)
(org-element-set-element next new-next)
(setq previous new-prev)
(setq next new-next)
(setq punct final-punct)
@ -1091,15 +1071,15 @@ the same object, call `org-cite-adjust-note' first."
(replace-regexp-in-string
previous-punct-re "" previous nil nil 1))
(new-next (if (stringp next) (concat punct next) punct)))
(org-element-set previous new-prev)
(org-element-set-element previous new-prev)
(cond
((stringp next)
(org-element-set next new-next))
(org-element-set-element next new-next))
(next
(org-element-insert-before new-next next))
(t
(org-element-adopt
(org-element-parent citation)
(org-element-adopt-elements
(org-element-property :parent citation)
new-next)))
(setq previous new-prev)
(setq next new-next)
@ -1166,7 +1146,7 @@ raises an error if S contains a headline."
(insert s)
(pcase (org-element-contents (org-element-parse-buffer))
('nil nil)
(`(,(and section (guard (org-element-type-p section 'section))))
(`(,(and section (guard (eq 'section (org-element-type section)))))
(org-element-contents section))
(_
(error "Headlines cannot replace a keyword")))))
@ -1226,23 +1206,14 @@ and must return either a string, an object, or a secondary string."
(org-cite-concat result separator (funcall function datum))))
result)))
(defun org-cite-capitalize (str)
"Capitalize string of raw string object STR."
(cond
((stringp str) (capitalize str))
((org-element-type-p str 'raw)
(org-export-raw-string
(capitalize (mapconcat #'identity (org-element-contents str) ""))))
(t (error "%S must be either a string or raw string object" str))))
;;; Internal interface with fontification (activate capability)
(defun org-cite-fontify-default (cite)
"Fontify CITE with `org-cite' and `org-cite-key' faces.
CITE is a citation object. The function applies `org-cite' face
on the whole citation, and `org-cite-key' face on each key."
(let ((beg (org-element-begin cite))
(end (org-with-point-at (org-element-end cite)
(let ((beg (org-element-property :begin cite))
(end (org-with-point-at (org-element-property :end cite)
(skip-chars-backward " \t")
(point))))
(add-text-properties beg end '(font-lock-multiline t))
@ -1266,12 +1237,10 @@ from the processor set in `org-cite-activate-processor'."
(let ((cite (org-with-point-at (match-beginning 0)
(org-element-citation-parser))))
(when cite
;; Do not alter match data as font-lock expects us to set it
;; appropriately.
(save-match-data (funcall activate cite))
(funcall activate cite)
;; Move after cite object and make sure to return
;; a non-nil value.
(goto-char (org-element-end cite)))))))
(goto-char (org-element-property :end cite)))))))
;;; Internal interface with Org Export library (export capability)
@ -1308,12 +1277,12 @@ side-effect."
;; Value is an alist. It must come from
;; `org-cite-export-processors' variable. Find the most
;; appropriate processor according to current export
;; backend.
;; back-end.
((and (pred consp) alist)
(let* ((backend (plist-get info :back-end))
(candidates
;; Limit candidates to processors associated to
;; backends derived from or equal to the current
;; back-ends derived from or equal to the current
;; one.
(sort (seq-filter
(pcase-lambda (`(,key . ,_))
@ -1365,7 +1334,7 @@ selected citation processor."
(defun org-cite-export-bibliography (keyword _ info)
"Return bibliography associated to \"print_bibliography\" KEYWORD.
BACKEND is the export backend, as a symbol. INFO is a plist
BACKEND is the export back-end, as a symbol. INFO is a plist
used as a communication channel."
(pcase (plist-get info :cite-export)
('nil nil)
@ -1389,7 +1358,7 @@ INFO is the communication channel, as a plist. Parse tree is modified
by side-effect."
(dolist (cite (org-cite-list-citations info))
(let ((replacement (org-cite-export-citation cite nil info))
(blanks (or (org-element-post-blank cite) 0)))
(blanks (or (org-element-property :post-blank cite) 0)))
(if (null replacement)
;; Before removing the citation, transfer its `:post-blank'
;; property to the object before, if any.
@ -1423,7 +1392,7 @@ by side-effect."
(_
(error "Invalid return value from citation export processor: %S"
replacement))))
(org-element-extract cite))))
(org-element-extract-element cite))))
(defun org-cite-process-bibliography (info)
"Replace all \"print_bibliography\" keywords in the parse tree.
@ -1434,18 +1403,18 @@ by side effect."
(lambda (keyword)
(when (equal "PRINT_BIBLIOGRAPHY" (org-element-property :key keyword))
(let ((replacement (org-cite-export-bibliography keyword nil info))
(blanks (or (org-element-post-blank keyword) 0)))
(blanks (or (org-element-property :post-blank keyword) 0)))
(pcase replacement
;; Before removing the citation, transfer its
;; `:post-blank' property to the element before, if any.
('nil
(org-cite--set-previous-post-blank keyword blanks info)
(org-element-extract keyword))
(org-element-extract-element keyword))
;; Handle `:post-blank' before replacing keyword with string.
((pred stringp)
(let ((output (concat (org-element-normalize-string replacement)
(make-string blanks ?\n))))
(org-element-set keyword (org-export-raw-string output))))
(org-element-set-element keyword (org-export-raw-string output))))
;; List of elements: splice contents before keyword and
;; remove the latter. Transfer `:post-blank' to last
;; element.
@ -1455,11 +1424,11 @@ by side effect."
(setq last datum)
(org-element-insert-before datum keyword))
(org-cite--set-post-blank last blanks)
(org-element-extract keyword)))
(org-element-extract-element keyword)))
;; Single element: replace the keyword.
(`(,(pred symbolp) . ,_)
(org-cite--set-post-blank replacement blanks)
(org-element-set keyword replacement))
(org-element-set-element keyword replacement))
(_
(error "Invalid return value from citation export processor: %S"
replacement))))))
@ -1515,7 +1484,7 @@ CONTEXT is the element or object at point, as returned by `org-element-context'.
;;
;; XXX: Inserting citation in a secondary value is not allowed
;; yet. Is it useful?
((let ((post (org-element-post-affiliated context)))
((let ((post (org-element-property :post-affiliated context)))
(and post (< (point) post)))
(let ((case-fold-search t))
(looking-back
@ -1531,14 +1500,14 @@ CONTEXT is the element or object at point, as returned by `org-element-context'.
((memq type '(nil paragraph)))
;; So are contents of verse blocks.
((eq type 'verse-block)
(and (>= (point) (org-element-contents-begin context))
(< (point) (org-element-contents-end context))))
(and (>= (point) (org-element-property :contents-begin context))
(< (point) (org-element-property :contents-end context))))
;; In an headline or inlinetask, point must be either on the
;; heading itself or on the blank lines below.
((memq type '(headline inlinetask))
(or (not (org-at-heading-p))
(and (save-excursion
(forward-line 0)
(beginning-of-line)
(and (let ((case-fold-search t))
(not (looking-at-p "\\*+ END[ \t]*$")))
(let ((case-fold-search nil))
@ -1557,43 +1526,43 @@ CONTEXT is the element or object at point, as returned by `org-element-context'.
;; White spaces after an object or blank lines after an element
;; are OK.
((>= (point)
(save-excursion (goto-char (org-element-end context))
(skip-chars-backward " \r\t\n")
(if (eq (org-element-class context) 'object) (point)
(line-beginning-position 2)))))
(save-excursion (goto-char (org-element-property :end context))
(skip-chars-backward " \r\t\n")
(if (eq (org-element-class context) 'object) (point)
(line-beginning-position 2)))))
;; At the beginning of a footnote definition, right after the
;; label, is OK.
((eq type 'footnote-definition) (looking-at (rx space)))
;; At the start of a list item is fine, as long as the bullet is
;; unaffected.
((eq type 'item)
(> (point) (+ (org-element-begin context)
(> (point) (+ (org-element-property :begin context)
(org-current-text-indentation)
(if (org-element-property :checkbox context)
5 1))))
;; Other elements are invalid.
((eq (org-element-class context) 'element) nil)
;; Just before object is fine.
((= (point) (org-element-begin context)))
((= (point) (org-element-property :begin context)))
;; Within recursive object too, but not in a link.
((eq type 'link) nil)
((eq type 'table-cell)
;; :contents-begin is not reliable on empty cells, so special
;; case it.
(<= (save-excursion (skip-chars-backward " \t") (point))
(org-element-contents-end context)))
((let ((cbeg (org-element-contents-begin context))
(cend (org-element-contents-end context)))
(org-element-property :contents-end context)))
((let ((cbeg (org-element-property :contents-begin context))
(cend (org-element-property :contents-end context)))
(and cbeg (>= (point) cbeg) (<= (point) cend)))))))
(defun org-cite--insert-string-before (string reference)
"Insert STRING before citation REFERENCE object."
(org-with-point-at (org-element-begin reference)
(org-with-point-at (org-element-property :begin reference)
(insert string ";")))
(defun org-cite--insert-string-after (string reference)
"Insert STRING after citation REFERENCE object."
(org-with-point-at (org-element-end reference)
(org-with-point-at (org-element-property :end reference)
;; Make sure to move forward when we're inserting at point, so the
;; insertion can happen multiple times.
(if (char-equal ?\; (char-before))
@ -1664,7 +1633,7 @@ More specifically,
;; action depends on the point.
(if arg
(org-cite-delete-citation context)
(let* ((begin (org-element-begin context))
(let* ((begin (org-element-property :begin context))
(style-end (1- (org-with-point-at begin (search-forward ":")))))
(if (>= style-end (point))
;; On style part, edit the style.
@ -1678,7 +1647,7 @@ More specifically,
;; point.
(let* ((references (org-cite-get-references context))
(key (concat "@" (funcall select-key nil))))
(if (< (point) (org-element-contents-begin context))
(if (< (point) (org-element-property :contents-begin context))
(org-cite--insert-string-before key (car references))
(org-cite--insert-string-after key (org-last references))))))))
;; On a citation reference. If ARG is not nil, remove the
@ -1733,7 +1702,7 @@ ARG is the prefix argument received when calling interactively the function."
(let ((context (org-element-context))
(insert (org-cite-processor-insert (org-cite-get-processor name))))
(cond
((org-element-type-p context '(citation citation-reference))
((memq (org-element-type context) '(citation citation-reference))
(funcall insert context arg))
((org-cite--allowed-p context)
(funcall insert nil arg))

View File

@ -1,6 +1,6 @@
;;; ol-bbdb.el --- Links to BBDB entries -*- lexical-binding: t; -*-
;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
;; Authors: Carsten Dominik <carsten.dominik@gmail.com>
;; Thomas Baumann <thomas dot baumann at ch dot tum dot de>
@ -226,7 +226,7 @@ date year)."
;;; Implementation
(defun org-bbdb-store-link (&optional _interactive?)
(defun org-bbdb-store-link ()
"Store a link to a BBDB database entry."
(when (eq major-mode 'bbdb-mode)
;; This is BBDB, we make this link!

View File

@ -1,6 +1,6 @@
;;; ol-bibtex.el --- Links to BibTeX entries -*- lexical-binding: t; -*-
;;
;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
;;
;; Authors: Bastien Guerry <bzg@gnu.org>
;; Carsten Dominik <carsten dot dominik at gmail dot com>
@ -266,7 +266,7 @@ a missing title field."
:type 'boolean)
(defcustom org-bibtex-headline-format-function
#'org-bibtex-headline-format-default
(lambda (entry) (cdr (assq :title entry)))
"Function returning the headline text for `org-bibtex-write'.
It should take a single argument, the bibtex entry (an alist as
returned by `org-bibtex-read'). The default value simply returns
@ -507,7 +507,7 @@ 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 (&optional _interactive?)
(defun org-bibtex-store-link ()
"Store a link to a BibTeX entry."
(when (eq major-mode 'bibtex-mode)
(let* ((search (org-create-file-search-in-bibtex))
@ -636,27 +636,22 @@ With prefix argument OPTIONAL also prompt for optional fields."
With prefix argument OPTIONAL also prompt for optional fields."
(interactive) (org-map-entries (lambda () (org-bibtex-check optional))))
(defun org-bibtex-headline-format-default (entry)
"Return headline text according to ENTRY title."
(cdr (assq :title entry)))
(defun org-bibtex-create (&optional arg update-heading)
(defun org-bibtex-create (&optional arg nonew)
"Create a new entry at the given level.
With a prefix ARG, query for optional fields as well.
If UPDATE-HEADING is non-nil, add data to the headline of the entry at
point."
With a prefix arg, query for optional fields as well.
If nonew is t, add data to the headline of the entry at point."
(interactive "P")
(let* ((type (completing-read
"Type: " (mapcar (lambda (type)
(substring (symbol-name (car type)) 1))
org-bibtex-types)
nil nil (when update-heading
(org-bibtex-get org-bibtex-type-property-name))))
nil nil (when nonew
(org-bibtex-get org-bibtex-type-property-name))))
(type (if (keywordp type) type (intern (concat ":" type))))
(org-bibtex-treat-headline-as-title (if update-heading nil t)))
(org-bibtex-treat-headline-as-title (if nonew nil t)))
(unless (assoc type org-bibtex-types)
(error "Type:%s is not known" type))
(if update-heading
(if nonew
(org-back-to-heading)
(org-insert-heading)
(let ((title (org-bibtex-ask :title)))
@ -723,32 +718,29 @@ Return the number of saved entries."
(interactive "fFile: ")
(org-bibtex-read-buffer (find-file-noselect file 'nowarn 'rawfile)))
(defun org-bibtex-write (&optional noindent update-heading)
(defun org-bibtex-write (&optional noindent)
"Insert a heading built from the first element of `org-bibtex-entries'.
When optional argument NOINDENT is non-nil, do not indent the properties
drawer. If UPDATE-HEADING is non-nil, add data to the headline of the
entry at point."
drawer."
(interactive)
(unless org-bibtex-entries
(error "No entries in `org-bibtex-entries'"))
(let* ((entry (pop org-bibtex-entries))
(org-special-properties nil) ; avoids errors with `org-entry-put'
(val (lambda (field) (cdr (assoc field entry))))
(togtag (lambda (tag) (org-toggle-tag tag 'on)))
(insert-raw (not update-heading)))
(unless update-heading
(org-insert-heading)
(insert (funcall org-bibtex-headline-format-function entry))
(insert "\n:PROPERTIES:\n"))
(org-bibtex-put "TITLE" (funcall val :title) insert-raw)
(togtag (lambda (tag) (org-toggle-tag tag 'on))))
(org-insert-heading)
(insert (funcall org-bibtex-headline-format-function entry))
(insert "\n:PROPERTIES:\n")
(org-bibtex-put "TITLE" (funcall val :title) 'insert)
(org-bibtex-put org-bibtex-type-property-name
(downcase (funcall val :type))
insert-raw)
'insert)
(dolist (pair entry)
(pcase (car pair)
(:title nil)
(:type nil)
(:key (org-bibtex-put org-bibtex-key-property (cdr pair) insert-raw))
(:key (org-bibtex-put org-bibtex-key-property (cdr pair) 'insert))
(:keywords (if org-bibtex-tags-are-keywords
(dolist (kw (split-string (cdr pair) ", *"))
(funcall
@ -756,28 +748,22 @@ entry at point."
(replace-regexp-in-string
"[^[:alnum:]_@#%]" ""
(replace-regexp-in-string "[ \t]+" "_" kw))))
(org-bibtex-put (car pair) (cdr pair) insert-raw)))
(_ (org-bibtex-put (car pair) (cdr pair) insert-raw))))
(unless update-heading
(insert ":END:\n"))
(org-bibtex-put (car pair) (cdr pair) 'insert)))
(_ (org-bibtex-put (car pair) (cdr pair) 'insert))))
(insert ":END:\n")
(mapc togtag org-bibtex-tags)
(unless noindent
(org-indent-region
(save-excursion (org-back-to-heading t) (point))
(point)))))
(defun org-bibtex-yank (&optional update-heading)
"If kill ring holds a bibtex entry yank it as an Org headline.
When called with non-nil prefix argument UPDATE-HEADING, add data to the
headline of the entry at point."
(interactive "P")
(defun org-bibtex-yank ()
"If kill ring holds a bibtex entry yank it as an Org headline."
(interactive)
(let (entry)
(with-temp-buffer
(yank 1)
(bibtex-mode)
(setf entry (org-bibtex-read)))
(with-temp-buffer (yank 1) (setf entry (org-bibtex-read)))
(if entry
(org-bibtex-write nil update-heading)
(org-bibtex-write)
(error "Yanked text does not appear to contain a BibTeX entry"))))
(defun org-bibtex-import-from-file (file)

View File

@ -1,6 +1,6 @@
;;; ol-docview.el --- Links to Docview mode buffers -*- lexical-binding: t; -*-
;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
;; Author: Jan Böcker <jan.boecker at jboecker dot de>
;; Keywords: outlines, hypermedia, calendar, wp
@ -57,21 +57,20 @@
:export #'org-docview-export
:store #'org-docview-store-link)
(defun org-docview-export (link description backend _info)
"Export a docview LINK with DESCRIPTION for BACKEND."
(defun org-docview-export (link description format)
"Export a docview link from Org files."
(let ((path (if (string-match "\\(.+\\)::.+" link) (match-string 1 link)
link))
(desc (or description link)))
(when (stringp path)
(setq path (expand-file-name path))
(cond
((eq backend 'html) (format "<a href=\"%s\">%s</a>" path desc))
((eq backend 'latex) (format "\\href{%s}{%s}" path desc))
((eq backend 'ascii) (format "[%s] (<%s>)" desc path))
((eq format 'html) (format "<a href=\"%s\">%s</a>" path desc))
((eq format 'latex) (format "\\href{%s}{%s}" path desc))
((eq format 'ascii) (format "%s (%s)" desc path))
(t path)))))
(defun org-docview-open (link _)
"Open docview: LINK."
(string-match "\\(.*?\\)\\(?:::\\([0-9]+\\)\\)?$" link)
(let ((path (match-string 1 link))
(page (and (match-beginning 2)
@ -83,7 +82,7 @@
(error "No such file: %s" path))
(when page (doc-view-goto-page page))))
(defun org-docview-store-link (&optional _interactive?)
(defun org-docview-store-link ()
"Store a link to a docview buffer."
(when (eq major-mode 'doc-view-mode)
;; This buffer is in doc-view-mode

View File

@ -1,6 +1,6 @@
;;; ol-doi.el --- DOI links support in Org -*- lexical-binding: t; -*-
;; Copyright (C) 2021-2024 Free Software Foundation, Inc.
;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
@ -40,8 +40,7 @@
(defun org-link-doi-open (path arg)
"Open a \"doi\" type link.
PATH is a the path to search for, as a string.
ARG is passed to `browse-url'."
PATH is a the path to search for, as a string."
(browse-url (url-encode-url (concat org-link-doi-server-url path)) arg))
(defun org-link-doi-export (path desc backend info)

View File

@ -1,6 +1,6 @@
;;; ol-eshell.el --- Links to Working Directories in Eshell -*- lexical-binding: t; -*-
;; Copyright (C) 2011-2024 Free Software Foundation, Inc.
;; Copyright (C) 2011-2023 Free Software Foundation, Inc.
;; Author: Konrad Hinsen <konrad.hinsen AT fastmail.net>
@ -37,8 +37,8 @@
:store #'org-eshell-store-link)
(defun org-eshell-open (link _)
"Switch to an eshell buffer and execute a command line for LINK.
The LINK can be just a command line (executed in the default
"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
followed by a colon."
(let* ((buffer-and-command
@ -60,10 +60,9 @@ followed by a colon."
(insert command)
(eshell-send-input)))
(defun org-eshell-store-link (&optional _interactive?)
"Store eshell link.
When opened, the link switches back to the current eshell buffer and
the current working directory."
(defun org-eshell-store-link ()
"Store a link that, when opened, switches back to the current eshell buffer
and the current working directory."
(when (eq major-mode 'eshell-mode)
(let* ((command (concat "cd " (eshell/pwd)))
(link (concat (buffer-name) ":" command)))

View File

@ -1,6 +1,6 @@
;;; ol-eww.el --- Store URL and kill from Eww mode -*- lexical-binding: t -*-
;; Copyright (C) 2014-2024 Free Software Foundation, Inc.
;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
;; Author: Marco Wahl <marcowahlsoft>a<gmailcom>
;; Keywords: link, eww
@ -62,7 +62,7 @@
"Open URL with Eww in the current buffer."
(eww url))
(defun org-eww-store-link (&optional _interactive?)
(defun org-eww-store-link ()
"Store a link to the url of an EWW buffer."
(when (eq major-mode 'eww-mode)
(org-link-store-props
@ -162,7 +162,6 @@ keep the structure of the Org file."
;; Additional keys for eww-mode
(defun org-eww-extend-eww-keymap ()
"Add ol-eww bindings to `eww-mode-map'."
(define-key eww-mode-map "\C-c\C-x\M-w" 'org-eww-copy-for-org-mode)
(define-key eww-mode-map "\C-c\C-x\C-w" 'org-eww-copy-for-org-mode))

View File

@ -1,6 +1,6 @@
;;; ol-gnus.el --- Links to Gnus Groups and Messages -*- lexical-binding: t; -*-
;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
;; Tassilo Horn <tassilo at member dot fsf dot org>
@ -123,7 +123,7 @@ If `org-store-link' was called with a prefix arg the meaning of
(url-encode-url message-id))
(concat "gnus:" group "#" message-id)))
(defun org-gnus-store-link (&optional _interactive?)
(defun org-gnus-store-link ()
"Store a link to a Gnus folder or message."
(pcase major-mode
(`gnus-group-mode
@ -137,23 +137,27 @@ If `org-store-link' was called with a prefix arg the meaning of
(let* ((group
(pcase (gnus-find-method-for-group gnus-newsgroup-name)
(`(nnvirtual . ,_)
(with-current-buffer gnus-summary-buffer
(save-excursion
(car (nnvirtual-map-article (gnus-summary-article-number))))))
(save-excursion
(car (nnvirtual-map-article (gnus-summary-article-number)))))
(`(,(or `nnselect `nnir) . ,_) ; nnir is for Emacs < 28.
(with-current-buffer gnus-summary-buffer
(save-excursion
(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"))))))
(save-excursion
(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 (with-current-buffer gnus-summary-buffer
(save-excursion
(gnus-summary-article-header))))
(header (if (eq major-mode 'gnus-article-mode)
;; When in an article, first move to summary
;; buffer, with point on the summary of the
;; current article before extracting headers.
(save-window-excursion
(save-excursion
(gnus-article-show-summary)
(gnus-summary-article-header)))
(gnus-summary-article-header)))
(from (mail-header-from header))
(message-id (org-unbracket-string "<" ">" (mail-header-id header)))
(date (org-trim (mail-header-date header)))

View File

@ -1,6 +1,6 @@
;;; ol-info.el --- Links to Info Nodes -*- lexical-binding: t; -*-
;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
;; Keywords: outlines, hypermedia, calendar, wp
@ -50,7 +50,7 @@
:insert-description #'org-info-description-as-command)
;; Implementation
(defun org-info-store-link (&optional _interactive?)
(defun org-info-store-link ()
"Store a link to an Info file and node."
(when (eq major-mode 'Info-mode)
(let ((link (concat "info:"
@ -129,27 +129,23 @@ If LINK is not an info link then DESC is returned."
(defconst org-info-emacs-documents
'("ada-mode" "auth" "autotype" "bovine" "calc" "ccmode" "cl" "dbus" "dired-x"
"ebrowse" "ede" "ediff" "edt" "efaq-w32" "efaq" "eglot" "eieio" "eintr"
"elisp" "emacs-gnutls" "emacs-mime" "emacs" "epa" "erc" "ert" "eshell"
"eudc" "eww" "flymake" "forms" "gnus" "htmlfontify" "idlwave" "ido" "info"
"mairix-el" "message" "mh-e" "modus-themes" "newsticker" "nxml-mode" "octave-mode"
"org" "pcl-cvs" "pgg" "rcirc" "reftex" "remember" "sasl" "sc" "semantic"
"ses" "sieve" "smtpmail" "speedbar" "srecode" "todo-mode" "tramp" "transient"
"url" "use-package" "vhdl-mode" "vip" "viper" "vtable" "widget" "wisent" "woman")
"ebrowse" "ede" "ediff" "edt" "efaq-w32" "efaq" "eieio" "eintr" "elisp"
"emacs-gnutls" "emacs-mime" "emacs" "epa" "erc" "ert" "eshell" "eudc" "eww"
"flymake" "forms" "gnus" "htmlfontify" "idlwave" "ido" "info" "mairix-el"
"message" "mh-e" "newsticker" "nxml-mode" "octave-mode" "org" "pcl-cvs"
"pgg" "rcirc" "reftex" "remember" "sasl" "sc" "semantic" "ses" "sieve"
"smtpmail" "speedbar" "srecode" "todo-mode" "tramp" "url" "vip" "viper"
"widget" "wisent" "woman")
"List of Emacs documents available.
Taken from <https://www.gnu.org/software/emacs/manual/html_mono/.>")
(defcustom org-info-other-documents
(defconst org-info-other-documents
'(("dir" . "https://www.gnu.org/manual/manual.html") ; index
("libc" . "https://www.gnu.org/software/libc/manual/html_mono/libc.html")
("make" . "https://www.gnu.org/software/make/manual/make.html"))
"Alist of documents generated from Texinfo source.
When converting info links to HTML, links to any one of these manuals are
converted to use these URL."
:group 'org-link
:type '(alist :key-type string :value-type string)
:package-version '(Org . "9.7")
:safe t)
converted to use these URL.")
(defun org-info-map-html-url (filename)
"Return URL or HTML file associated to Info FILENAME.
@ -157,11 +153,11 @@ If FILENAME refers to an official GNU document, return a URL pointing to
the official page for that document, e.g., use \"gnu.org\" for all Emacs
related documents. Otherwise, append \".html\" extension to FILENAME.
See `org-info-emacs-documents' and `org-info-other-documents' for details."
(cond ((cdr (assoc filename org-info-other-documents)))
((member filename org-info-emacs-documents)
(format "https://www.gnu.org/software/emacs/manual/html_mono/%s.html"
filename))
(t (concat filename ".html"))))
(cond ((member filename org-info-emacs-documents)
(format "https://www.gnu.org/software/emacs/manual/html_mono/%s.html"
filename))
((cdr (assoc filename org-info-other-documents)))
(t (concat filename ".html"))))
(defun org-info--expand-node-name (node)
"Expand Info NODE to HTML cross reference."

View File

@ -1,6 +1,6 @@
;;; ol-irc.el --- Links to IRC Sessions -*- lexical-binding: t; -*-
;;
;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
;;
;; Author: Philip Jackson <emacs@shellarchive.co.uk>
;; Keywords: erc, irc, link, org
@ -103,7 +103,7 @@ attributes that are found."
parts))
;;;###autoload
(defun org-irc-store-link (&optional _interactive?)
(defun org-irc-store-link ()
"Dispatch to the appropriate function to store a link to an IRC session."
(cond
((eq major-mode 'erc-mode)

View File

@ -1,6 +1,6 @@
;;; ol-man.el --- Links to man pages -*- lexical-binding: t; -*-
;;
;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
;; Maintainer: Bastien Guerry <bzg@gnu.org>
;; Keywords: outlines, hypermedia, calendar, wp
@ -24,17 +24,12 @@
;;
;;; Commentary:
;; This file implements links to man pages from within Org mode.
;;; Code:
(require 'org-macs)
(org-assert-version)
(require 'ol)
(org-link-set-parameters "man"
:complete #'org-man-complete
:follow #'org-man-open
:export #'org-man-export
:store #'org-man-store-link)
@ -42,29 +37,15 @@
(defcustom org-man-command 'man
"The Emacs command to be used to display a man page."
:group 'org-link
:type '(choice (const man) (const :tag "WoMan (obsolete)" woman)))
:type '(choice (const man) (const woman)))
(declare-function Man-translate-references "man" (ref))
(defun org-man-open (path _)
"Visit the manpage on PATH.
PATH should be a topic that can be thrown at the man command.
If PATH contains extra ::STRING which will use `occur' to search
matched strings in man buffer."
(require 'man) ; For `Man-translate-references'
(string-match "\\(.*?\\)\\(?:::\\(.*\\)\\)?$" path)
(let* ((command (match-string 1 path))
;; FIXME: Remove after we drop Emacs 29 support.
;; Working around security bug #66390.
(command (if (not (equal (Man-translate-references ";id") ";id"))
;; We are on Emacs that escapes man command args
;; (see Emacs commit 820f0793f0b).
command
;; Older Emacs without the fix - escape the
;; arguments ourselves.
(mapconcat 'identity
(mapcar #'shell-quote-argument
(split-string command "\\s-+"))
" ")))
(search (match-string 2 path))
(buffer (funcall org-man-command command)))
(when search
@ -82,7 +63,7 @@ matched strings in man buffer."
(set-window-point window point)
(set-window-start window point)))))))
(defun org-man-store-link (&optional _interactive?)
(defun org-man-store-link ()
"Store a link to a README file."
(when (memq major-mode '(Man-mode woman-mode))
;; This is a man page, we do make this link
@ -101,31 +82,18 @@ matched strings in man buffer."
(match-string 1 (buffer-name))
(error "Cannot create link to this man page")))
(defun org-man-export (link description backend)
"Export a man page LINK with DESCRIPTION.
BACKEND is the current export backend."
(defun org-man-export (link description format)
"Export a man page link from Org files."
(let ((path (format "http://man.he.net/?topic=%s&section=all" link))
(desc (or description link)))
(cond
((eq backend 'html) (format "<a target=\"_blank\" href=\"%s\">%s</a>" path desc))
((eq backend 'latex) (format "\\href{%s}{%s}" path desc))
((eq backend 'texinfo) (format "@uref{%s,%s}" path desc))
((eq backend 'ascii) (format "[%s] (<%s>)" desc path))
((eq backend 'md) (format "[%s](%s)" desc path))
((eq format 'html) (format "<a target=\"_blank\" href=\"%s\">%s</a>" path desc))
((eq format 'latex) (format "\\href{%s}{%s}" path desc))
((eq format 'texinfo) (format "@uref{%s,%s}" path desc))
((eq format 'ascii) (format "%s (%s)" desc path))
((eq format 'md) (format "[%s](%s)" desc path))
(t path))))
(defvar Man-completion-cache) ; Defined in `man'.
(defun org-man-complete (&optional _arg)
"Complete man pages for `org-insert-link'."
(require 'man)
(concat
"man:"
(let ((completion-ignore-case t) ; See `man' comments.
(Man-completion-cache)) ; See `man' implementation.
(completing-read
"Manual entry: "
'Man-completion-table))))
(provide 'ol-man)
;;; ol-man.el ends here

View File

@ -1,6 +1,6 @@
;;; ol-mhe.el --- Links to MH-E Messages -*- lexical-binding: t; -*-
;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
;; Author: Thomas Baumann <thomas dot baumann at ch dot tum dot de>
;; Keywords: outlines, hypermedia, calendar, wp
@ -80,7 +80,7 @@ supported by MH-E."
(org-link-set-parameters "mhe" :follow #'org-mhe-open :store #'org-mhe-store-link)
;; Implementation
(defun org-mhe-store-link (&optional _interactive?)
(defun org-mhe-store-link ()
"Store a link to an MH-E folder or message."
(when (or (eq major-mode 'mh-folder-mode)
(eq major-mode 'mh-show-mode))

View File

@ -1,6 +1,6 @@
;;; ol-rmail.el --- Links to Rmail Messages -*- lexical-binding: t; -*-
;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
;; Keywords: outlines, hypermedia, calendar, wp
@ -51,7 +51,7 @@
:store #'org-rmail-store-link)
;; Implementation
(defun org-rmail-store-link (&optional _interactive?)
(defun org-rmail-store-link ()
"Store a link to an Rmail folder or message."
(when (or (eq major-mode 'rmail-mode)
(eq major-mode 'rmail-summary-mode))

View File

@ -1,6 +1,6 @@
;;; ol-w3m.el --- Copy and Paste From W3M -*- lexical-binding: t; -*-
;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
;; Author: Andy Stewart <lazycat dot manatee at gmail dot com>
;; Keywords: outlines, hypermedia, calendar, wp

View File

@ -1,6 +1,6 @@
;;; ol.el --- Org links library -*- lexical-binding: t; -*-
;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
;; Copyright (C) 2018-2023 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
;; Keywords: outlines, hypermedia, calendar, wp
@ -52,19 +52,17 @@
(declare-function org-do-occur "org" (regexp &optional cleanup))
(declare-function org-element-at-point "org-element" (&optional pom cached-only))
(declare-function org-element-cache-refresh "org-element" (pos))
(declare-function org-element-cache-reset "org-element" (&optional all no-persistence))
(declare-function org-element-context "org-element" (&optional element))
(declare-function org-element-lineage "org-element-ast" (datum &optional types with-self))
(declare-function org-element-lineage "org-element" (datum &optional types with-self))
(declare-function org-element-link-parser "org-element" ())
(declare-function org-element-property "org-element-ast" (property node))
(declare-function org-element-begin "org-element" (node))
(declare-function org-element-end "org-element" (node))
(declare-function org-element-type-p "org-element-ast" (node types))
(declare-function org-element-property "org-element" (property element))
(declare-function org-element-type "org-element" (element))
(declare-function org-element-update-syntax "org-element" ())
(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-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))
(declare-function org-load-modules-maybe "org" (&optional force))
(declare-function org-mark-ring-push "org" (&optional pos buffer))
@ -116,11 +114,11 @@ below.
Function that accepts four arguments:
- the path, as a string,
- the description as a string, or nil,
- the export backend,
- the export back-end,
- the export communication channel, as a plist.
When nil, export for that type of link is delegated to the
backend.
back-end.
`:store'
@ -198,16 +196,6 @@ link.
:type '(alist :tag "Link display parameters"
:value-type plist))
(defun org-link--set-link-display (symbol value)
"Set `org-link-descriptive' (SYMBOL) to VALUE.
Also, ensure that links are updated in current buffer.
This function is intended to be used as a :set function."
(set symbol value)
(dolist (buf (org-buffer-list))
(with-current-buffer buf
(org-link-descriptive-ensure))))
(defcustom org-link-descriptive t
"Non-nil means Org displays descriptive links.
@ -219,7 +207,6 @@ literally.
You can interactively set the value of this variable by calling
`org-toggle-link-display' or from the \"Org > Hyperlinks\" menu."
:group 'org-link
:set #'org-link--set-link-display
:type 'boolean
:safe #'booleanp)
@ -247,7 +234,7 @@ adaptive Use relative path for files in the current directory and sub-
directories of it. For other files, use an absolute path.
Alternatively, users may supply a custom function that takes the
filename in the link as an argument and returns the path."
full filename as an argument and returns the path."
:group 'org-link
:type '(choice
(const relative)
@ -308,7 +295,10 @@ or emacs-wiki packages to Org syntax.
The function must accept two parameters, a TYPE containing the link
protocol name like \"rmail\" or \"gnus\" as a string, and the linked path,
which is everything after the link protocol. It should return a cons
with possibly modified values of type and path."
with possibly modified values of type and path.
Org contains a function for this, so if you set this variable to
`org-translate-link-from-planner', you should be able follow many
links created by planner."
:group 'org-link-follow
:type '(choice (const nil) (function))
:safe #'null)
@ -369,17 +359,14 @@ another window."
(const wl-other-frame)))))
(defcustom org-link-search-must-match-exact-headline 'query-to-create
"Control fuzzy link behaviour when specific matches not found.
"Non-nil means internal fuzzy links can only match headlines.
When nil, if a fuzzy link does not match a more specific
target (such as a heading, named block, target, or code ref),
attempt a regular text search. When set to the special value
`query-to-create', offer to create a new heading matching the
link instead. Otherwise, signal an error rather than attempting
a regular text search.
When nil, the fuzzy link may point to a target or a named
construct in the document. When set to the special value
`query-to-create', offer to create a new headline when none
matched.
This option only affects behaviour in Org buffers. Spaces and
statistics cookies are ignored during heading searches."
Spaces and statistics cookies are ignored during heading searches."
:group 'org-link-follow
:version "24.1"
:type '(choice
@ -533,16 +520,6 @@ links more efficient."
(defvar-local org-target-link-regexp nil
"Regular expression matching radio targets in plain text.")
(defconst org-target-link-regexp-limit (ash 2 12)
"Maximum allowed length of regexp.
The number should generally be ~order of magnitude smaller than
MAX_BUF_SIZE in src/regex-emacs.c. The number of regexp-emacs.c is
for processed regexp, which appears to be larger compared to the
original string length.")
(defvar-local org-target-link-regexps nil
"List of regular expressions matching radio targets in plain text.
This list is non-nil, when a single regexp would be too long to match
all the possible targets, exceeding Emacs' regexp length limit.")
(defvar org-link-types-re nil
"Matches a link that has a url-like prefix like \"http:\".")
@ -777,8 +754,8 @@ White spaces are not significant."
(while (re-search-forward re nil t)
(forward-char -1)
(let ((object (org-element-context)))
(when (org-element-type-p object 'radio-target)
(goto-char (org-element-begin object))
(when (eq (org-element-type object) 'radio-target)
(goto-char (org-element-property :begin object))
(org-fold-show-context 'link-search)
(throw :radio-match nil))))
(goto-char origin)
@ -829,74 +806,6 @@ spec."
(org-with-point-at (car region)
(not (org-in-regexp org-link-any-re))))
(defun org-link--try-link-store-functions (interactive?)
"Try storing external links, prompting if more than one is possible.
Each function returned by `org-store-link-functions' is called in
turn. If multiple functions return non-nil, prompt for which
link should be stored.
Argument INTERACTIVE? indicates whether `org-store-link' was
called interactively and is passed to the link store functions.
Return t when a link has been stored in `org-link-store-props'."
(let ((results-alist nil))
(dolist (f (org-store-link-functions))
(when (condition-case nil
(funcall f interactive?)
;; FIXME: The store function used (< Org 9.7) to accept
;; no arguments; provide backward compatibility support
;; for them.
(wrong-number-of-arguments
(funcall f)))
;; FIXME: return value is not link's plist, so we store the
;; new value before it is modified. It would be cleaner to
;; ask store link functions to return the plist instead.
(push (cons f (copy-sequence org-store-link-plist))
results-alist)))
(pcase results-alist
(`nil nil)
(`((,_ . ,_)) t) ;single choice: nothing to do
(`((,name . ,_) . ,_)
;; Reinstate link plist associated to the chosen
;; function.
(apply #'org-link-store-props
(cdr (assoc-string
(completing-read
(format "Store link with (default %s): " name)
(mapcar #'car results-alist)
nil t nil nil (symbol-name name))
results-alist)))
t))))
(defun org-link--add-to-stored-links (link desc)
"Add LINK to `org-stored-links' with description DESC."
(cond
((not (member (list link desc) org-stored-links))
(push (list link desc) org-stored-links)
(message "Stored: %s" (or desc link)))
((equal (list link desc) (car org-stored-links))
(message "This link has already been stored"))
(t
(setq org-stored-links
(delete (list link desc) org-stored-links))
(push (list link desc) org-stored-links)
(message "Link moved to front: %s" (or desc link)))))
(defun org-link--file-link-to-here ()
"Return as (LINK . DESC) a file link with search string to here."
(let ((link (concat "file:"
(abbreviate-file-name
(buffer-file-name (buffer-base-buffer)))))
desc)
(when org-link-context-for-files
(pcase (org-link-precise-link-target)
(`nil nil)
(`(,search-string ,search-desc ,_position)
(setq link (format "%s::%s" link search-string))
(setq desc search-desc))))
(cons link desc)))
;;; Public API
@ -923,13 +832,6 @@ PARAMETERS should be keyword value pairs. See
(org-link-make-regexps)
(when (featurep 'org-element) (org-element-update-syntax)))))
;; This way, one can add multiple functions as, say, :follow parameter.
;; For example,
;; (add-function :before-until (org-link-get-parameter "id" :follow) #'my-function)
;; See https://orgmode.org/list/a123389c-8f86-4836-a4fe-1e3f4281d33b@app.fastmail.com
(gv-define-setter org-link-get-parameter (value type key)
`(org-link-set-parameters ,type ,key ,value))
(defun org-link-make-regexps ()
"Update the link regular expressions.
This should be called after the variable `org-link-parameters' has changed."
@ -942,12 +844,12 @@ This should be called after the variable `org-link-parameters' has changed."
org-link-plain-re
(let* ((non-space-bracket "[^][ \t\n()<>]")
(parenthesis
`(seq (any "<([")
`(seq "("
(0+ (or (regex ,non-space-bracket)
(seq (any "<([")
(seq "("
(0+ (regex ,non-space-bracket))
(any "])>"))))
(any "])>"))))
")")))
")")))
;; Heuristics for an URL link inspired by
;; https://daringfireball.net/2010/07/improved_regex_for_matching_urls
(rx-to-string
@ -980,8 +882,7 @@ This should be called after the variable `org-link-parameters' has changed."
org-link-plain-re "\\)"))))
(defun org-link-complete-file (&optional arg)
"Create a file link using completion.
With optional ARG \\='(16), abbreviate the file name in the link."
"Create a file link using completion."
(let ((file (read-file-name "File: "))
(pwd (file-name-as-directory (expand-file-name ".")))
(pwd1 (file-name-as-directory (abbreviate-file-name
@ -1026,7 +927,7 @@ according to FMT (default from `org-link-email-description-format')."
(org-replace-escapes fmt table)))
(defun org-link-store-props (&rest plist)
"Store link properties PLIST.
"Store link properties.
The properties are pre-processed by extracting names, addresses
and dates."
(let ((x (plist-get plist :from)))
@ -1058,7 +959,7 @@ and dates."
(setq org-store-link-plist plist))
(defun org-link-add-props (&rest plist)
"Add these properties to the link property list PLIST."
"Add these properties to the link property list."
(let (key value)
(while plist
(setq key (pop plist) value (pop plist))
@ -1130,9 +1031,7 @@ LINK is escaped with backslashes for inclusion in buffer."
"List of functions that are called to create and store a link.
The functions are defined in the `:store' property of
`org-link-parameters'. Each function should accept an argument
INTERACTIVE? which indicates whether the user has initiated
`org-store-link' interactively.
`org-link-parameters'.
Each function will be called in turn until one returns a non-nil
value. Each function should check if it is responsible for
@ -1156,9 +1055,6 @@ and then used in capture templates."
if store-func
collect store-func))
(defvar org-link--abbrev-functions nil
"Alist of abbrev link expressions and functions.")
(defun org-link-expand-abbrev (link)
"Replace link abbreviations in LINK string.
Abbreviations are defined in `org-link-abbrev-alist'."
@ -1173,27 +1069,14 @@ Abbreviations are defined in `org-link-abbrev-alist'."
(setq rpl (cdr as))
(cond
((symbolp rpl) (funcall rpl tag))
((string-match "%(\\([^) ]+\\))" rpl) ; %(function)
((string-match "%(\\([^)]+\\))" rpl)
(replace-match
(save-match-data
(funcall (intern-soft (match-string 1 rpl)) tag))
t t rpl))
((string-match "%(\\(.+\\))" rpl) ; %(sexpr using tag)
(replace-match
(save-match-data
(funcall (or (cdr (assoc (match-string 1 rpl)
org-link--abbrev-functions))
(cdar (push (cons (match-string 1 rpl)
(eval (read (format
"(lambda (tag) (%s))"
(match-string 1 rpl)))))
org-link--abbrev-functions)))
tag))
t t rpl))
((string-match-p "%[0-<>^_]?[0-9]*\\(?:\\.[0-9]+\\)?s" rpl)
(format-spec rpl `((?s . ,(or tag "")))))
((string-match-p "%[0-<>^_]?[0-9]*\\(?:\\.[0-9]+\\)?h" rpl)
(format-spec rpl `((?h . ,(url-hexify-string (or tag ""))))))
((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))
(t (concat rpl tag)))))))
(defun org-link-open (link &optional arg)
@ -1235,7 +1118,7 @@ for internal and \"file\" links, or stored as a parameter in
(_ path))
;; Prevent fuzzy links from matching themselves.
(and (equal type "fuzzy")
(+ 2 (org-element-begin link)))))
(+ 2 (org-element-property :begin link)))))
(point))))
(unless (and (<= (point-min) destination)
(>= (point-max) destination))
@ -1249,14 +1132,14 @@ for internal and \"file\" links, or stored as a parameter in
;; argument, as it was mandatory before Org 9.4. This is
;; deprecated, but support it for now.
(condition-case nil
(funcall f path arg)
(funcall (org-link-get-parameter type :follow) path arg)
(wrong-number-of-arguments
(funcall f path)))))))))
(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.
Optional argument ARG is passed to `org-open-file' when S is a
\"file\" link."
Optional argument is passed to `org-open-file' when S is
a \"file\" link."
(interactive "sLink: \nP")
(pcase (with-temp-buffer
(let ((org-inhibit-startup nil))
@ -1267,8 +1150,8 @@ Optional argument ARG is passed to `org-open-file' when S is a
(`nil (user-error "No valid link in %S" s))
(link (org-link-open link arg))))
(defun org-link-search (s &optional avoid-pos stealth new-heading-container)
"Search for a search string S in the accessible part of the buffer.
(defun org-link-search (s &optional avoid-pos stealth)
"Search for a search string S.
If S starts with \"#\", it triggers a custom ID search.
@ -1287,16 +1170,8 @@ When optional argument STEALTH is non-nil, do not modify
visibility around point, thus ignoring `org-show-context-detail'
variable.
When optional argument NEW-HEADING-CONTAINER is an element, any
new heading that is created (see
`org-link-search-must-match-exact-headline') will be added as a
subheading of NEW-HEADING-CONTAINER. Otherwise, new headings are
created at level 1 at the end of the accessible part of the
buffer.
Search is case-insensitive and ignores white spaces. Return type
of matched result, which is either `dedicated' or `fuzzy'. Search
respects buffer narrowing."
of matched result, which is either `dedicated' or `fuzzy'."
(unless (org-string-nw-p s) (error "Invalid search string \"%s\"" s))
(let* ((case-fold-search t)
(origin (point))
@ -1323,7 +1198,8 @@ respects buffer narrowing."
(catch :coderef-match
(while (re-search-forward re nil t)
(let ((element (org-element-at-point)))
(when (and (org-element-type-p element '(example-block src-block))
(when (and (memq (org-element-type element)
'(example-block src-block))
(org-match-line
(concat ".*?" (org-src-coderef-regexp
(org-src-coderef-format element)
@ -1347,9 +1223,9 @@ respects buffer narrowing."
(while (re-search-forward target nil t)
(backward-char)
(let ((context (org-element-context)))
(when (org-element-type-p context 'target)
(when (eq (org-element-type context) 'target)
(setq type 'dedicated)
(goto-char (org-element-begin context))
(goto-char (org-element-property :begin context))
(throw :target-match t))))
nil))))
;; Look for elements named after S, only if not in a headline
@ -1361,9 +1237,9 @@ respects buffer narrowing."
(while (re-search-forward name nil t)
(let* ((element (org-element-at-point))
(name (org-element-property :name element)))
(when (and name (equal (mapcar #'upcase words) (mapcar #'upcase (split-string name))))
(when (and name (equal words (split-string name)))
(setq type 'dedicated)
(forward-line 0)
(beginning-of-line)
(throw :name-match t))))
nil))))
;; Regular text search. Prefer headlines in Org mode buffers.
@ -1378,38 +1254,24 @@ respects buffer narrowing."
(goto-char (point-min))
(catch :found
(while (re-search-forward title-re nil t)
(when (equal (mapcar #'upcase words)
(mapcar #'upcase
(split-string
(org-link--normalize-string
(org-get-heading t t t t)))))
(when (equal words
(split-string
(org-link--normalize-string
(org-get-heading t t t t))))
(throw :found t)))
nil)))
(forward-line 0)
(beginning-of-line)
(setq type 'dedicated))
;; Offer to create non-existent headline depending on
;; `org-link-search-must-match-exact-headline'.
((and (derived-mode-p 'org-mode)
(eq org-link-search-must-match-exact-headline 'query-to-create)
(yes-or-no-p "No match - create this as a new heading? "))
(let* ((container-ok (and new-heading-container
(org-element-type-p new-heading-container '(headline))))
(new-heading-position (if container-ok
(- (org-element-end new-heading-container) 1)
(point-max)))
(new-heading-level (if container-ok
(+ 1 (org-element-property :level new-heading-container))
1)))
;; Need to widen when target is outside accessible portion of
;; buffer, since the we want the user to end up there.
(unless (and (<= (point-min) new-heading-position)
(>= (point-max) new-heading-position))
(widen))
(goto-char new-heading-position)
(unless (bolp) (newline))
(org-insert-heading nil t new-heading-level)
(insert (if starred (substring s 1) s) "\n")
(forward-line -1)))
(goto-char (point-max))
(unless (bolp) (newline))
(org-insert-heading nil t t)
(insert s "\n")
(beginning-of-line 0))
;; Only headlines are looked after. No need to process
;; further: throw an error.
((and (derived-mode-p 'org-mode)
@ -1432,7 +1294,7 @@ respects buffer narrowing."
(<= (match-end 3) (point)))
(org-element-lineage
(save-match-data (org-element-context))
'link t)))
'(link) t)))
(goto-char (match-beginning 0))
(setq type 'fuzzy)
(throw :fuzzy-match t)))
@ -1459,75 +1321,9 @@ priority cookie or tag."
(org-link--normalize-string
(or string (org-get-heading t t t t)))))
(defun org-link-precise-link-target ()
"Determine search string and description for storing a link.
If a search string (see `org-link-search') is found, return
list (SEARCH-STRING DESC POSITION). Otherwise, return nil.
If there is an active region, the contents (or a part of it, see
`org-link-context-for-files') is used as the search string.
In Org buffers, if point is at a named element (such as a source
block), the name is used for the search string. If at a heading,
its CUSTOM_ID is used to form a search string of the form
\"#id\", if present, otherwise the current heading text is used
in the form \"*Heading\".
If none of those finds a suitable search string, the current line
is used as the search string.
The description DESC is nil (meaning the user will be prompted
for a description when inserting the link) for search strings
based on a region or the current line. For other cases, DESC is
a cleaned-up version of the name or heading at point.
POSITION is the buffer position at which the search string
matches."
(let* ((region (org-link--context-from-region))
(result
(cond
(region
(list (org-link--normalize-string region t)
nil
(region-beginning)))
((derived-mode-p 'org-mode)
(let* ((element (org-element-at-point))
(name (org-element-property :name element))
(heading (org-element-lineage element '(headline inlinetask) t))
(custom-id (org-entry-get heading "CUSTOM_ID")))
(cond
(name
(list name
name
(org-element-begin element)))
((org-before-first-heading-p)
(list (org-link--normalize-string (org-current-line-string) t)
nil
(line-beginning-position)))
(heading
(list (if custom-id (concat "#" custom-id)
(org-link-heading-search-string))
(org-link--normalize-string
(org-get-heading t t t t))
(org-element-begin heading))))))
;; Not in an org-mode buffer, no region
(t
(list (org-link--normalize-string (org-current-line-string) t)
nil
(line-beginning-position))))))
;; Only use search option if there is some text.
(when (org-string-nw-p (car result))
result)))
(defun org-link-open-as-file (path in-emacs)
(defun org-link-open-as-file (path arg)
"Pretend PATH is a file name and open it.
IN-EMACS is passed to `org-open-file'.
According to \"file\"-link syntax, PATH may include additional
search options, separated from the file name with \"::\".
@ -1537,12 +1333,11 @@ This function is meant to be used as a possible tool for
(match-string 1 path)))
(file-name (if (not option) path
(substring path 0 (match-beginning 0)))))
(if (and (string-match "[*?{]" (file-name-nondirectory file-name))
(not (file-exists-p file-name)))
(dired file-name)
(if (string-match "[*?{]" (file-name-nondirectory file-name))
(dired file-name)
(apply #'org-open-file
file-name
in-emacs
arg
(cond ((not option) nil)
((string-match-p "\\`[0-9]+\\'" option)
(list (string-to-number option)))
@ -1596,7 +1391,7 @@ PATH is a symbol name, as a string."
((and (pred boundp) variable) (describe-variable variable))
(name (user-error "Unknown function or variable: %s" name))))
(defun org-link--store-help (&optional _interactive?)
(defun org-link--store-help ()
"Store \"help\" type link."
(when (eq major-mode 'help-mode)
(let ((symbol
@ -1678,10 +1473,10 @@ is non-nil, move backward."
(let ((context (save-excursion
(unless search-backward (forward-char -1))
(org-element-context))))
(pcase (org-element-lineage context 'link t)
(pcase (org-element-lineage context '(link) t)
(`nil nil)
(link
(goto-char (org-element-begin link))
(goto-char (org-element-property :begin link))
(when (org-invisible-p) (org-fold-show-context 'link-search))
(throw :found t)))))
(goto-char pos)
@ -1714,12 +1509,10 @@ If the link is in hidden text, expose it."
\\<org-mode-map>
This link is added to `org-stored-links' and can later be inserted
into an Org buffer with `org-insert-link' (`\\[org-insert-link]').
When optional argument INTERACTIVE? is nil, the link is not stored in
`org-stored-links', but returned as a string.
For some link types, a `\\[universal-argument]' prefix ARG is interpreted. \
A single
`\\[universal-argument]' negates `org-link-context-for-files' for file links or
`\\[universal-argument]' negates `org-context-in-file-links' for file links or
`org-gnus-prefer-web-links' for links to Usenet articles.
A `\\[universal-argument] \\[universal-argument]' prefix ARG forces \
@ -1731,12 +1524,7 @@ prefix ARG forces storing a link for each line in the
active region.
Assume the function is called interactively if INTERACTIVE? is
non-nil.
In Org buffers, an additional \"human-readable\" simple file link
is stored as an alternative to persistent org-id or other links,
if at a heading with a CUSTOM_ID property or an element with a
NAME."
non-nil."
(interactive "P\np")
(org-load-modules-maybe)
(if (and (equal arg '(64)) (org-region-active-p))
@ -1751,19 +1539,36 @@ NAME."
(move-beginning-of-line 2)
(set-mark (point)))))
(setq org-store-link-plist nil)
;; Negate `org-context-in-file-links' when given a single universal arg.
(let ((org-link-context-for-files (org-xor org-link-context-for-files
(equal arg '(4))))
link cpltxt desc search agenda-link) ;; description
(let (link cpltxt desc search custom-id agenda-link) ;; description
(cond
;; Store a link using an external link type, if any function is
;; available, unless external link types are skipped for this
;; call using two universal args. If more than one function
;; can generate a link from current location, ask the user
;; which one to use.
;; available. If more than one can generate a link from current
;; location, ask which one to use.
((and (not (equal arg '(16)))
(org-link--try-link-store-functions interactive?))
(setq link (plist-get org-store-link-plist :link))
(let ((results-alist nil))
(dolist (f (org-store-link-functions))
(when (funcall f)
;; XXX: return value is not link's plist, so we
;; store the new value before it is modified. It
;; would be cleaner to ask store link functions to
;; return the plist instead.
(push (cons f (copy-sequence org-store-link-plist))
results-alist)))
(pcase results-alist
(`nil nil)
(`((,_ . ,_)) t) ;single choice: nothing to do
(`((,name . ,_) . ,_)
;; Reinstate link plist associated to the chosen
;; function.
(apply #'org-link-store-props
(cdr (assoc-string
(completing-read
(format "Store link with (default %s): " name)
(mapcar #'car results-alist)
nil t nil nil (symbol-name name))
results-alist)))
t))))
(setq link (plist-get org-store-link-plist :link))
;; If store function actually set `:description' property, use
;; it, even if it is nil. Otherwise, fallback to nil (ask user).
(setq desc (plist-get org-store-link-plist :description)))
@ -1785,7 +1590,7 @@ NAME."
(setq link nil))
;; A code reference exists. Use it.
((save-excursion
(forward-line 0)
(beginning-of-line)
(re-search-forward (org-src-coderef-regexp coderef-format)
(line-end-position)
t))
@ -1814,7 +1619,6 @@ NAME."
(org-with-point-at m
(setq agenda-link (org-store-link nil interactive?))))))
;; Calendar mode
((eq major-mode 'calendar-mode)
(let ((cd (calendar-cursor-to-date)))
(setq link
@ -1823,7 +1627,6 @@ NAME."
(org-encode-time 0 0 0 (nth 1 cd) (nth 0 cd) (nth 2 cd))))
(org-link-store-props :type "calendar" :date cd)))
;; Image mode
((eq major-mode 'image-mode)
(setq cpltxt (concat "file:"
(abbreviate-file-name buffer-file-name))
@ -1841,22 +1644,15 @@ NAME."
(setq cpltxt (concat "file:" file)
link cpltxt)))
;; Try `org-create-file-search-functions`. If any are
;; successful, create a file link to the current buffer with
;; the provided search string. (sets `link` and `cpltxt` to
;; the same thing; it looks like the intention originally was
;; that cpltxt was a description, which might have been set by
;; the search-function (removed in switch to lexical binding)).
((setq search (run-hook-with-args-until-success
'org-create-file-search-functions))
(setq link (concat "file:" (abbreviate-file-name buffer-file-name)
"::" search))
(setq cpltxt (or link))) ;; description
;; Main logic for storing built-in link types in org-mode
;; buffers
((and (buffer-file-name (buffer-base-buffer)) (derived-mode-p 'org-mode))
(org-with-limited-levels
(setq custom-id (org-entry-get nil "CUSTOM_ID"))
(cond
;; Store a link using the target at point
((org-in-regexp "[^<]<<\\([^<>]+\\)>>[^>]" 1)
@ -1870,21 +1666,74 @@ NAME."
;; links. Maybe the case of identical target and
;; description should be handled by `org-insert-link'.
cpltxt nil
desc nil))
(t
desc nil
;; Do not append #CUSTOM_ID link below.
custom-id nil))
((and (featurep 'org-id)
(or (eq org-id-link-to-org-use-id t)
(and interactive?
(or (eq org-id-link-to-org-use-id 'create-if-interactive)
(and (eq org-id-link-to-org-use-id
'create-if-interactive-and-no-custom-id)
(not custom-id))))
(and org-id-link-to-org-use-id (org-entry-get nil "ID"))))
;; Store a link using the ID at point
(setq link (condition-case nil
(prog1 (org-id-store-link)
(setq desc (plist-get org-store-link-plist :description)))
(error
;; Probably before first headline, link only to file
(concat "file:"
(abbreviate-file-name
(buffer-file-name (buffer-base-buffer))))))))
(t
;; Just link to current headline.
(let ((here (org-link--file-link-to-here)))
(setq cpltxt (car here))
(setq desc (cdr here)))
(setq link cpltxt)))))
(setq cpltxt (concat "file:"
(abbreviate-file-name
(buffer-file-name (buffer-base-buffer)))))
;; 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))
(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 linked to file, but not an org-mode buffer.
((buffer-file-name (buffer-base-buffer))
;; Just link to this file here.
(let ((here (org-link--file-link-to-here)))
(setq cpltxt (car here))
(setq desc (cdr here)))
(setq link cpltxt))
(setq cpltxt (concat "file:"
(abbreviate-file-name
(buffer-file-name (buffer-base-buffer)))))
;; Add a context search string.
(when (org-xor org-link-context-for-files (equal arg '(4)))
(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?
(user-error "No method for storing a link from this buffer"))
@ -1900,18 +1749,17 @@ NAME."
;; Store and return the link
(if (not (and interactive? link))
(or agenda-link (and link (org-link-make-string link desc)))
(org-link--add-to-stored-links link desc)
;; In org buffers, store an additional "human-readable" link
;; using custom id, if available.
(when (and (buffer-file-name (buffer-base-buffer))
(derived-mode-p 'org-mode)
(org-entry-get nil "CUSTOM_ID"))
(let ((here (org-link--file-link-to-here)))
(setq link (car here))
(setq desc (cdr here)))
(unless (equal (list link desc) (car org-stored-links))
(org-link--add-to-stored-links link desc)))
(car org-stored-links)))))
(if (member (list link desc) org-stored-links)
(message "This link has already been stored")
(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
(defun org-insert-link (&optional complete-file link-location description)
@ -1972,7 +1820,7 @@ non-interactively, don't allow to edit the default description."
(all-prefixes (append (mapcar #'car abbrevs)
(mapcar #'car org-link-abbrev-alist)
(org-link-types)))
entry link-original)
entry)
(cond
(link-location) ; specified by arg, just use it.
((org-in-regexp org-link-bracket-re 1)
@ -1994,34 +1842,18 @@ non-interactively, don't allow to edit the default description."
(t
;; Read link, with completion for stored links.
(org-link--fontify-links-to-this-file)
(switch-to-buffer-other-window "*Org Links*")
(org-switch-to-buffer-other-window "*Org Links*")
(with-current-buffer "*Org Links*"
(read-only-mode 1)
(let ((inhibit-read-only t)
;; FIXME Duplicate: Also in 'ox.el'.
(propertize-help-key
(lambda (key)
;; Add `face' *and* `font-lock-face' to "work
;; reliably in any buffer", per a comment in
;; `help--key-description-fontified'.
(propertize key
'font-lock-face 'help-key-binding
'face 'help-key-binding))))
(erase-buffer)
(insert
(apply #'format "Type %s to complete link type, then %s to complete destination.\n"
(mapcar propertize-help-key
(list "TAB" "RET"))))
(when org-stored-links
(insert (apply #'format "\nStored links accessible with %s/%s or %s/%s are:\n\n"
(mapcar propertize-help-key
(list "<up>" "<down>"
"M-p" "M-n"
"RET"))))
(insert (mapconcat #'org-link--prettify
(reverse org-stored-links)
"\n"))))
(goto-char (point-min)))
(erase-buffer)
(insert "Insert a link.
Use TAB to complete link prefixes, then RET for type-specific completion support\n")
(when org-stored-links
(insert "\nStored links are available with <up>/<down> or M-p/n \
\(most recent with RET):\n\n")
(insert (mapconcat #'org-link--prettify
(reverse org-stored-links)
"\n")))
(goto-char (point-min)))
(when (get-buffer-window "*Org Links*" 'visible)
(let ((cw (selected-window)))
(select-window (get-buffer-window "*Org Links*" 'visible))
@ -2036,13 +1868,14 @@ non-interactively, don't allow to edit the default description."
org-link--insert-history)))
(setq link
(org-completing-read
(org-format-prompt "Insert link" (caar org-stored-links))
"Link: "
(append
(mapcar (lambda (x) (concat x ":")) all-prefixes)
(mapcar #'car org-stored-links)
;; Allow description completion. Avoid "nil" option
;; in the case of `completing-read-default' when
;; some links have no description.
;; in the case of `completing-read-default' and
;; an error in `ido-completing-read' when some links
;; have no description.
(delq nil (mapcar 'cadr org-stored-links)))
nil nil nil
'org-link--history
@ -2057,16 +1890,17 @@ non-interactively, don't allow to edit the default description."
(setq link (substring link 0 -1))))
(setq link (with-current-buffer origbuf
(org-link--try-special-completion link)))))
(when-let ((window (get-buffer-window "*Org Links*" t)))
(quit-window 'kill window))
(set-window-configuration wcf)
(when (get-buffer "*Org Links*")
(kill-buffer "*Org Links*")))
(kill-buffer "*Org Links*"))
(setq entry (assoc link org-stored-links))
(or entry (push link org-link--insert-history))
(setq desc (or desc (nth 1 entry)))))
(setq link-original link)
(when (funcall (if (equal complete-file '(64)) 'not 'identity)
(not org-link-keep-stored-after-insertion))
(setq org-stored-links (delq (assoc link org-stored-links)
org-stored-links)))
(when (and (string-match org-link-plain-re link)
(not (string-match org-ts-regexp link)))
;; URL-like link, normalize the use of angular brackets.
@ -2109,7 +1943,8 @@ non-interactively, don't allow to edit the default description."
((eq org-link-file-path-type 'relative)
(setq path (file-relative-name path)))
((functionp org-link-file-path-type)
(setq path (funcall org-link-file-path-type path)))
(setq path (funcall org-link-file-path-type
(expand-file-name path))))
(t
(save-match-data
(if (string-match (concat "^" (regexp-quote
@ -2160,10 +1995,6 @@ non-interactively, don't allow to edit the default description."
(read-string "Description: " initial-input)
initial-input)))
(when (funcall (if (equal complete-file '(64)) 'not 'identity)
(not org-link-keep-stored-after-insertion))
(setq org-stored-links (delq (assoc link-original org-stored-links)
org-stored-links)))
(unless (org-string-nw-p desc) (setq desc nil))
(when remove (apply #'delete-region remove))
(insert (org-link-make-string link desc))
@ -2208,39 +2039,6 @@ This command can be called in any mode to insert a link in Org syntax."
(org-load-modules-maybe)
(org-run-like-in-org-mode 'org-insert-link))
(defun org--re-list-search-forward (regexp-list &optional bound noerror count)
"Like `re-search-forward', but REGEXP-LIST is a list of regexps.
BOUND, NOERROR, and COUNT are passed to `re-search-forward'."
(let (result (min-found most-positive-fixnum)
(pos-found nil)
(min-found-data nil)
(tail regexp-list))
(while tail
(setq result (save-excursion (re-search-forward (pop tail) bound t count)))
(when (and result (< result min-found))
(setq min-found result
pos-found (match-end 0)
min-found-data (match-data))))
(if (= most-positive-fixnum min-found)
(pcase noerror
(`t nil)
(_ (re-search-forward (car regexp-list) bound noerror count)))
(set-match-data min-found-data)
(goto-char pos-found))))
(defun org--re-list-looking-at (regexp-list &optional inhibit-modify)
"Like `looking-at', but REGEXP-LIST is a list of regexps.
INHIBIT-MODIFY is passed to `looking-at'."
(catch :found
(while regexp-list
(when
(if inhibit-modify
(looking-at-p (pop regexp-list))
;; FIXME: In Emacs <29, `looking-at' does not accept
;; optional INHIBIT-MODIFY argument.
(looking-at (pop regexp-list)))
(throw :found t)))))
;;;###autoload
(defun org-update-radio-target-regexp ()
"Find all radio targets in this file and update the regular expression.
@ -2260,7 +2058,7 @@ Also refresh fontification if needed."
;; Make sure point is really within the object.
(backward-char)
(let ((obj (org-element-context)))
(when (org-element-type-p obj 'radio-target)
(when (eq (org-element-type obj) 'radio-target)
(cl-pushnew (org-element-property :value obj) rtn
:test #'equal))))
rtn))))
@ -2278,30 +2076,6 @@ Also refresh fontification if needed."
targets
"\\|")
after-re)))
(setq org-target-link-regexps nil)
(let (current-length sub-targets)
(when (<= org-target-link-regexp-limit (length org-target-link-regexp))
(while (or targets sub-targets)
(when (and sub-targets
(or (not targets)
(>= (+ current-length (length (car targets)))
org-target-link-regexp-limit)))
(push (concat before-re
(mapconcat
(lambda (x)
(replace-regexp-in-string
" +" "\\s-+" (regexp-quote x) t t))
(nreverse sub-targets)
"\\|")
after-re)
org-target-link-regexps)
(setq current-length nil
sub-targets nil))
(unless current-length
(setq current-length (+ (length before-re) (length after-re))))
(when targets (push (pop targets) sub-targets))
(cl-incf current-length (length (car sub-targets))))
(setq org-target-link-regexps (nreverse org-target-link-regexps))))
(unless (equal old-regexp org-target-link-regexp)
;; Clean-up cache.
(let ((regexp (cond ((not old-regexp) org-target-link-regexp)
@ -2317,11 +2091,9 @@ Also refresh fontification if needed."
after-re)))))
(when (and (featurep 'org-element)
(not (bound-and-true-p org-mode-loading)))
(if org-target-link-regexps
(org-element-cache-reset)
(org-with-point-at 1
(while (re-search-forward regexp nil t)
(org-element-cache-refresh (match-beginning 1)))))))
(org-with-point-at 1
(while (re-search-forward regexp nil t)
(org-element-cache-refresh (match-beginning 1))))))
;; Re fontify buffer.
(when (memq 'radio org-highlight-links)
(org-restart-font-lock)))))

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
;;; org-archive.el --- Archiving for Org -*- lexical-binding: t; -*-
;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
;; Keywords: outlines, hypermedia, calendar, wp
@ -34,9 +34,9 @@
(require 'org)
(require 'cl-lib)
(declare-function org-element-type "org-element" (element))
(declare-function org-datetree-find-date-create "org-datetree" (date &optional keep-restriction))
(declare-function org-inlinetask-remove-END-maybe "org-inlinetask" ())
(declare-function org-timestamp-to-now "org" (timestamp-string &optional seconds))
;; From org-element.el
(defvar org-element--cache-avoid-synchronous-headline-re-parsing)
@ -154,10 +154,10 @@ archive location, but not yet deleted from the original file.")
;;;###autoload
(defun org-add-archive-files (files)
"Splice the archive FILES into the list of files.
"Splice the archive files into the list of files.
This implies visiting all these files and finding out what the
archive file is."
(seq-uniq
(org-uniquify
(apply
'append
(mapcar
@ -166,9 +166,7 @@ archive file is."
nil
(with-current-buffer (org-get-agenda-file-buffer f)
(cons f (org-all-archive-files)))))
files))
#'file-equal-p
))
files))))
(defun org-all-archive-files ()
"List of all archive files used in the current buffer."
@ -254,7 +252,8 @@ direct children of this heading."
(newfile-p (and (org-string-nw-p afile)
(not (file-exists-p afile))))
(buffer (cond ((not (org-string-nw-p afile)) this-buffer)
((find-file-noselect afile 'nowarn))
((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))
@ -478,9 +477,9 @@ Archiving time is retained in the ARCHIVE_TIME node property."
(goto-char e)
(or (bolp) (newline))
(insert leader org-archive-sibling-heading "\n")
(forward-line -1)
(beginning-of-line 0)
(org-toggle-tag org-archive-tag 'on))
(forward-line 0)
(beginning-of-line 1)
(if org-archive-reversed-order
(outline-next-heading)
(org-end-of-subtree t t))
@ -525,12 +524,12 @@ When TAG is non-nil, don't move trees, but mark them with the ARCHIVE tag."
(let (ts)
(and (re-search-forward org-ts-regexp end t)
(setq ts (match-string 0))
(< (org-timestamp-to-now ts) 0)
(< (org-time-stamp-to-now ts) 0)
(if (not (looking-at
(concat "--\\(" org-ts-regexp "\\)")))
(concat "--\\(" org-ts-regexp "\\)")))
(concat "old timestamp " ts)
(setq ts (concat "old timestamp " ts (match-string 0)))
(and (< (org-timestamp-to-now (match-string 1)) 0)
(and (< (org-time-stamp-to-now (match-string 1)) 0)
ts)))))
tag))
@ -591,9 +590,8 @@ don't move trees, but mark them with the ARCHIVE tag."
;;;###autoload
(defun org-toggle-archive-tag (&optional find-done)
"Toggle the archive tag for the current headline.
With prefix argument FIND-DONE, check all children of current headline
and offer tagging the children that do not contain any open TODO
items."
With prefix ARG, check all children of current headline and offer tagging
the children that do not contain any open TODO items."
(interactive "P")
(if (and (org-region-active-p) org-loop-over-headlines-in-active-region)
(let ((cl (if (eq org-loop-over-headlines-in-active-region 'start-level)
@ -610,7 +608,7 @@ items."
(org-back-to-heading t)
(setq set (org-toggle-tag org-archive-tag))
(when set (org-fold-subtree t)))
(and set (forward-line 0))
(and set (beginning-of-line 1))
(message "Subtree %s" (if set "archived" "unarchived"))))))
(defun org-archive-set-tag ()

View File

@ -1,6 +1,6 @@
;;; org-attach-git.el --- Automatic git commit extension to org-attach -*- lexical-binding: t; -*-
;; Copyright (C) 2019-2024 Free Software Foundation, Inc.
;; Copyright (C) 2019-2023 Free Software Foundation, Inc.
;; Original Author: John Wiegley <johnw@newartisans.com>
;; Restructurer: Gustav Wikström <gustav@whil.se>

View File

@ -1,6 +1,6 @@
;;; org-attach.el --- Manage file attachments to Org outlines -*- lexical-binding: t; -*-
;; Copyright (C) 2008-2024 Free Software Foundation, Inc.
;; Copyright (C) 2008-2023 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@newartisans.com>
;; Keywords: org data attachment
@ -44,12 +44,8 @@
(declare-function dired-dwim-target-directory "dired-aux")
(declare-function dired-get-marked-files "dired" (&optional localp arg filter distinguish-one-marked error))
(declare-function org-element-property "org-element-ast" (property node))
(declare-function org-element-begin "org-element" (node))
(declare-function org-element-end "org-element" (node))
(declare-function org-element-contents-begin "org-element" (node))
(declare-function org-element-contents-end "org-element" (node))
(declare-function org-element-type-p "org-element-ast" (node types))
(declare-function org-element-property "org-element" (property element))
(declare-function org-element-type "org-element" (element))
(declare-function org-inlinetask-goto-beginning "org-inlinetask" ())
(declare-function org-inlinetask-in-task-p "org-inlinetask" ())
@ -142,7 +138,7 @@ Selective means to respect the inheritance setting in
(const :tag "Inherit parent node attachments" t)
(const :tag "Respect org-use-property-inheritance" selective)))
(defcustom org-attach-store-link-p 'attached
(defcustom org-attach-store-link-p nil
"Non-nil means store a link to a file when attaching it.
When t, store the link to original file location.
When `file', store link to the attached file location.
@ -301,71 +297,68 @@ ask the user instead, else remove without asking."
"The dispatcher for attachment commands.
Shows a list of commands and prompts for another key to execute a command."
(interactive)
(let (c marker)
(let ((dir (org-attach-dir nil 'no-fs-check))
c marker)
(when (eq major-mode 'org-agenda-mode)
(setq marker (or (get-text-property (point) 'org-hd-marker)
(get-text-property (point) 'org-marker)))
(unless marker
(error "No item in current line")))
(org-with-point-at marker
(let ((dir (org-attach-dir nil 'no-fs-check)))
(if (and (featurep 'org-inlinetask)
(not (org-inlinetask-in-task-p)))
(org-with-limited-levels
(org-back-to-heading-or-point-min t))
(if (and (featurep 'org-inlinetask)
(not (org-inlinetask-in-task-p)))
(org-with-limited-levels
(org-back-to-heading-or-point-min t))
(if (and (featurep 'org-inlinetask)
(org-inlinetask-in-task-p))
(org-inlinetask-goto-beginning)
(org-back-to-heading-or-point-min t)))
(save-excursion
(save-window-excursion
(unless org-attach-expert
(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")
(unless (and dir (file-directory-p dir))
"\n(Not yet created)")
"\n\n"
(format "Select an Attachment Command:\n\n%s"
(mapconcat
(lambda (entry)
(pcase entry
(`((,key . ,_) ,_ ,docstring)
(format "%c %s"
key
(replace-regexp-in-string "\n\\([\t ]*\\)"
" "
docstring
nil nil 1)))
(_
(user-error
"Invalid `org-attach-commands' item: %S"
entry))))
org-attach-commands
"\n"))))
(goto-char (point-min)))
(org-fit-window-to-buffer (get-buffer-window "*Org Attach*"))
(unwind-protect
(let ((msg (format "Select command: [%s]"
(concat (mapcar #'caar org-attach-commands)))))
(message msg)
(while (and (setq c (read-char-exclusive))
(memq c '(?\C-n ?\C-p ?\C-v ?\M-v)))
(org-scroll c t)))
(when-let ((window (get-buffer-window "*Org Attach*" t)))
(quit-window 'kill window))
(and (get-buffer "*Org Attach*") (kill-buffer "*Org Attach*")))))
(let ((command (cl-some (lambda (entry)
(and (memq c (nth 0 entry)) (nth 1 entry)))
org-attach-commands)))
(if (commandp command)
(command-execute command)
(error "No such attachment command: %c" c)))))))
(org-inlinetask-in-task-p))
(org-inlinetask-goto-beginning)
(org-back-to-heading-or-point-min t)))
(save-excursion
(save-window-excursion
(unless org-attach-expert
(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")
(unless (and dir (file-directory-p dir))
"\n(Not yet created)")
"\n\n"
(format "Select an Attachment Command:\n\n%s"
(mapconcat
(lambda (entry)
(pcase entry
(`((,key . ,_) ,_ ,docstring)
(format "%c %s"
key
(replace-regexp-in-string "\n\\([\t ]*\\)"
" "
docstring
nil nil 1)))
(_
(user-error
"Invalid `org-attach-commands' item: %S"
entry))))
org-attach-commands
"\n"))))
(goto-char (point-min)))
(org-fit-window-to-buffer (get-buffer-window "*Org Attach*"))
(let ((msg (format "Select command: [%s]"
(concat (mapcar #'caar org-attach-commands)))))
(message msg)
(while (and (setq c (read-char-exclusive))
(memq c '(?\C-n ?\C-p ?\C-v ?\M-v)))
(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)))
org-attach-commands)))
(if (commandp command)
(command-execute command)
(error "No such attachment command: %c" c))))))
;;;###autoload
(defun org-attach-dir (&optional create-if-not-exists-p no-fs-check)
@ -440,26 +433,17 @@ ignoring nils. If EXISTING is non-nil, then return the first path
found in the filesystem. Otherwise return the first non-nil value."
(let ((fun-list org-attach-id-to-path-function-list)
(base-dir (expand-file-name org-attach-id-dir))
(default-base-dir (expand-file-name "data/"))
preferred first)
(while (and fun-list
(not preferred))
(let* ((name (funcall (car fun-list) id))
(candidate (and name (expand-file-name name base-dir)))
;; Try the default value `org-attach-id-dir' as a fallback.
(candidate2 (and name (not (equal base-dir default-base-dir))
(expand-file-name name default-base-dir))))
(candidate (and name (expand-file-name name base-dir))))
(setq fun-list (cdr fun-list))
(when candidate
(if (or (not existing) (file-directory-p candidate))
(setq preferred candidate)
(unless first
(setq first candidate)))
(when (and existing
candidate2
(not (file-directory-p candidate))
(file-directory-p candidate2))
(setq preferred candidate2)))))
(setq first candidate))))))
(or preferred first)))
(defun org-attach-check-absolute-path (dir)
@ -529,13 +513,9 @@ DIR-property exists (that is different from the unset one)."
(defun org-attach-tag (&optional off)
"Turn the autotag on or (if OFF is set) off."
(when org-attach-auto-tag
;; FIXME: There is currently no way to set #+FILETAGS
;; programatically. Do nothing when before first heading
;; (attaching to file) to avoid blocking error.
(unless (org-before-first-heading-p)
(save-excursion
(org-back-to-heading t)
(org-toggle-tag org-attach-auto-tag (if off 'off 'on))))))
(save-excursion
(org-back-to-heading t)
(org-toggle-tag org-attach-auto-tag (if off 'off 'on)))))
(defun org-attach-untag ()
"Turn the autotag off."
@ -594,7 +574,7 @@ METHOD may be `cp', `mv', `ln', `lns' or `url' default taken from
((eq method 'url)
(if (org--should-fetch-remote-resource-p file)
(url-copy-file file attach-file)
(error "The remote resource %S is considered unsafe, and will not be downloaded"
(error "The remote resource %S is considered unsafe, and will not be downloaded."
file))))
(run-hook-with-args 'org-attach-after-change-hook attach-dir)
(org-attach-tag)
@ -757,20 +737,20 @@ 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 (org-element-type-p link 'link)
(when (and (eq 'link (org-element-type link))
(string-equal "attachment"
(org-element-property :type link)))
(let* ((description (and (org-element-contents-begin link)
(let* ((description (and (org-element-property :contents-begin link)
(buffer-substring-no-properties
(org-element-contents-begin link)
(org-element-contents-end link))))
(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-end link))
(goto-char (org-element-property :end link))
(skip-chars-backward " \t")
(delete-region (org-element-begin link) (point))
(delete-region (org-element-property :begin link) (point))
(insert new-link)))))))
(defun org-attach-follow (file arg)

View File

@ -1,6 +1,6 @@
;;; org-capture.el --- Fast note taking in Org -*- lexical-binding: t; -*-
;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
;; Keywords: outlines, hypermedia, calendar, wp
@ -58,13 +58,11 @@
(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 "org-datetree" (d &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" (&optional pom cached-only))
(declare-function org-element-lineage "org-element-ast" (datum &optional types with-self))
(declare-function org-element-property "org-element-ast" (property node))
(declare-function org-element-contents-end "org-element" (node))
(declare-function org-element-post-affiliated "org-element" (node))
(declare-function org-element-lineage "org-element" (datum &optional types with-self))
(declare-function org-element-property "org-element" (property element))
(declare-function org-encrypt-entry "org-crypt" ())
(declare-function org-insert-link "ol" (&optional complete-file link-location default-description))
(declare-function org-link-make-string "ol" (link &optional description))
@ -222,9 +220,6 @@ target Specification of where the captured item should be placed.
(clock)
File to the entry that is currently being clocked
(here)
The position of point
(function function-finding-location)
Most general way: write your own function which both visits
the file and moves point to the right location
@ -371,10 +366,6 @@ be replaced with content and expanded:
%^{prompt} Prompt the user for a string and replace this sequence with it.
A default value and a completion table can be specified like this:
%^{prompt|default|completion2|completion3|...}.
%^{prompt}X where X is one of g, G, t, T, u, U, C, or L.
Same as %^X (see above), but also supply custom
prompt/completions. Default value and completions as in
%^{prompt|default|...}X are allowed.
%? After completing the template, position cursor here.
%\\1 ... %\\N Insert the text entered at the nth %^{prompt}, where N
is a number, starting from 1.
@ -505,6 +496,12 @@ The capture buffer is current and still narrowed."
:version "24.1"
:type 'hook)
(defcustom org-capture-bookmark t
"When non-nil, add bookmark pointing at the last stored position when capturing."
:group 'org-capture
:version "24.3"
:type 'boolean)
;;; The property list for keeping information about the capture process
(defvar org-capture-plist nil
@ -582,9 +579,7 @@ this template to be accessible only from `message-mode' buffers,
use this:
(setq org-capture-templates-contexts
\\='((\"c\" ((in-mode . \"message-mode\")))
(\"d\" (my-context-function
(in-mode . \"org-mode\")))))
\\='((\"c\" ((in-mode . \"message-mode\")))))
Here are the available contexts definitions:
@ -996,15 +991,14 @@ Store them in the capture property list."
(let ((target-entry-p t))
(save-excursion
(pcase (or target (org-capture-get :target))
((or `here
`(here))
(`here
(org-capture-put :exact-position (point) :insert-here t))
(`(file ,path)
(set-buffer (org-capture-target-buffer path))
(org-capture-put-target-region-and-position)
(widen)
(setq target-entry-p nil))
(`(id ,(and id (or (pred stringp) (pred symbolp))))
(`(id ,id)
(pcase (org-id-find id)
(`(,path . ,position)
(set-buffer (org-capture-target-buffer path))
@ -1012,7 +1006,7 @@ Store them in the capture property list."
(org-capture-put-target-region-and-position)
(goto-char position))
(_ (error "Cannot find target ID \"%s\"" id))))
(`(file+headline ,path ,(and headline (pred stringp)))
(`(file+headline ,path ,headline)
(set-buffer (org-capture-target-buffer path))
;; Org expects the target file to be in Org mode, otherwise
;; it throws an error. However, the default notes files
@ -1029,12 +1023,12 @@ Store them in the capture property list."
(if (re-search-forward (format org-complex-heading-regexp-format
(regexp-quote headline))
nil t)
(forward-line 0)
(beginning-of-line)
(goto-char (point-max))
(unless (bolp) (insert "\n"))
(insert "* " headline "\n")
(forward-line -1)))
(`(file+olp ,path . ,(and outline-path (guard outline-path)))
(beginning-of-line 0)))
(`(file+olp ,path . ,outline-path)
(let ((m (org-find-olp (cons (org-capture-expand-file path)
outline-path))))
(set-buffer (marker-buffer m))
@ -1042,7 +1036,7 @@ Store them in the capture property list."
(widen)
(goto-char m)
(set-marker m nil)))
(`(file+regexp ,path ,(and regexp (pred stringp)))
(`(file+regexp ,path ,regexp)
(set-buffer (org-capture-target-buffer path))
(org-capture-put-target-region-and-position)
(widen)
@ -1110,7 +1104,7 @@ Store them in the capture property list."
;; the following is the keep-restriction argument for
;; org-datetree-find-date-create
(when outline-path 'subtree-at-point))))
(`(file+function ,path ,(and function (pred functionp)))
(`(file+function ,path ,function)
(set-buffer (org-capture-target-buffer path))
(org-capture-put-target-region-and-position)
(widen)
@ -1118,7 +1112,7 @@ Store them in the capture property list."
(org-capture-put :exact-position (point))
(setq target-entry-p
(and (derived-mode-p 'org-mode) (org-at-heading-p))))
(`(function ,(and fun (pred functionp)))
(`(function ,fun)
(funcall fun)
(org-capture-put :exact-position (point))
(setq target-entry-p
@ -1174,9 +1168,9 @@ When INHIBIT-WCONF-STORE is non-nil, don't store the window configuration, as it
may have been stored before."
(unless inhibit-wconf-store
(org-capture-put :return-to-wconf (current-window-configuration)))
(pop-to-buffer
(org-capture-get-indirect-buffer (org-capture-get :buffer) "CAPTURE")
'(org-display-buffer-split))
(delete-other-windows)
(org-switch-to-buffer-other-window
(org-capture-get-indirect-buffer (org-capture-get :buffer) "CAPTURE"))
(widen)
(org-fold-show-all)
(goto-char (org-capture-get :pos))
@ -1274,7 +1268,7 @@ may have been stored before."
(catch :found
(while (re-search-forward item-regexp end t)
(when (setq item (org-element-lineage
(org-element-at-point) 'plain-list t))
(org-element-at-point) '(plain-list) t))
(goto-char (org-element-property (if prepend? :post-affiliated
:contents-end)
item))
@ -1316,7 +1310,7 @@ may have been stored before."
(point-marker))))
(when item
(let ((i (save-excursion
(goto-char (org-element-post-affiliated item))
(goto-char (org-element-property :post-affiliated item))
(org-current-text-indentation))))
(save-excursion
(goto-char beg)
@ -1324,7 +1318,7 @@ may have been stored before."
(while (< (point) end)
(indent-to i)
(forward-line)))
;; Prepending an item could change the type of the list
;; Pre-pending an item could change the type of the list
;; if there is a mismatch. In this situation,
;; prioritize the existing list.
(when prepend?
@ -1379,13 +1373,13 @@ may have been stored before."
;; Narrow to the table, possibly creating one if necessary.
(catch :found
(while (re-search-forward org-table-dataline-regexp end t)
(pcase (org-element-lineage (org-element-at-point) 'table t)
(pcase (org-element-lineage (org-element-at-point) '(table) t)
(`nil nil)
((pred (lambda (e) (eq 'table.el (org-element-property :type e))))
nil)
(table
(goto-char (org-element-contents-end table))
(narrow-to-region (org-element-post-affiliated table)
(goto-char (org-element-property :contents-end table))
(narrow-to-region (org-element-property :post-affiliated table)
(point))
(throw :found t))))
;; No table found. Create it with an empty header.
@ -1415,7 +1409,7 @@ may have been stored before."
(goto-char (point-min))
(cond
((not (re-search-forward org-table-hline-regexp nil t)))
((re-search-forward org-table-dataline-regexp nil t) (forward-line 0))
((re-search-forward org-table-dataline-regexp nil t) (beginning-of-line))
(t (goto-char (org-table-end)))))
(t
(goto-char (org-table-end))))
@ -1504,15 +1498,10 @@ Of course, if exact position has been required, just put it there."
(point))))))
(with-current-buffer (buffer-base-buffer (current-buffer))
(org-with-point-at pos
;; FIXME: `org-capture-bookmark' is obsolete. To be removed
;; in future Org releases.
(when (with-no-warnings org-capture-bookmark)
(when org-capture-bookmark
(let ((bookmark (plist-get org-bookmark-names-plist :last-capture)))
(when bookmark
(condition-case err
(bookmark-set bookmark)
(error
(message "Bookmark set error: %S" err))))))
(when bookmark (with-demoted-errors "Bookmark set error: %S"
(bookmark-set bookmark)))))
(move-marker org-capture-last-stored-marker (point))))))
(defun org-capture-narrow (beg end)
@ -1675,8 +1664,11 @@ Expansion occurs in a temporary Org mode buffer."
(org-no-properties org-clock-heading)
""))
(v-K (if (marker-buffer org-clock-marker)
(org-with-point-at org-clock-marker
(org-store-link nil nil))
(org-link-make-string
(format "%s::*%s"
(buffer-file-name (marker-buffer org-clock-marker))
v-k)
v-k)
""))
(v-f (or (org-capture-get :original-file-nondirectory) ""))
(v-F (or (org-capture-get :original-file) ""))
@ -1694,7 +1686,7 @@ Expansion occurs in a temporary Org mode buffer."
(message "no template") (ding)
(sit-for 1))
(save-window-excursion
(switch-to-buffer-other-window (get-buffer-create "*Capture*"))
(org-switch-to-buffer-other-window (get-buffer-create "*Capture*"))
(erase-buffer)
(setq buffer-file-name nil)
(setq mark-active nil)
@ -1866,7 +1858,7 @@ Expansion occurs in a temporary Org mode buffer."
(let* ((upcase? (equal (upcase key) key))
(org-end-time-was-given nil)
(time (org-read-date upcase? t nil prompt)))
(org-insert-timestamp
(org-insert-time-stamp
time (or org-time-was-given upcase?)
(member key '("u" "U"))
nil nil (list org-end-time-was-given))))

View File

@ -1,6 +1,6 @@
;;; org-clock.el --- The time clocking code for Org mode -*- lexical-binding: t; -*-
;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
;; Keywords: outlines, hypermedia, calendar, wp
@ -36,11 +36,9 @@
(declare-function calendar-iso-to-absolute "cal-iso" (date))
(declare-function notifications-notify "notifications" (&rest params))
(declare-function org-element-property "org-element-ast" (property node))
(declare-function org-element-contents-end "org-element" (node))
(declare-function org-element-end "org-element" (node))
(declare-function org-element-type "org-element-ast" (node &optional anonymous))
(declare-function org-element-type-p "org-element-ast" (node types))
(declare-function org-element-property "org-element" (property element))
(declare-function org-element-type "org-element" (element))
(declare-function org-element--cache-active-p "org-element" ())
(defvar org-element-use-cache)
(declare-function org-inlinetask-at-task-p "org-inlinetask" ())
(declare-function org-inlinetask-goto-beginning "org-inlinetask" ())
@ -130,7 +128,7 @@ clocking out."
"Rounding minutes when clocking in or out.
The default value is 0 so that no rounding is done.
When set to a non-integer value, use the car of
`org-timestamp-rounding-minutes', like for setting a timestamp.
`org-time-stamp-rounding-minutes', like for setting a time-stamp.
E.g. if `org-clock-rounding-minutes' is set to 5, time is 14:47
and you clock in: then the clock starts at 14:45. If you clock
@ -350,15 +348,14 @@ For more information, see `org-clocktable-write-default'."
:type 'function)
(defcustom org-clock-clocktable-language-setup
'(("en" "File" "L" "Timestamp" "Headline" "Time" "ALL" "Total time" "File time" "Clock summary at")
("de" "Datei" "E" "Zeitstempel" "Kopfzeile" "Dauer" "GESAMT" "Gesamtdauer" "Dateizeit" "Erstellt am")
("es" "Archivo" "N" "Fecha y hora" "Tarea" "Duración" "TODO" "Duración total" "Tiempo archivo" "Generado el")
("fr" "Fichier" "N" "Horodatage" "En-tête" "Durée" "TOUT" "Durée totale" "Durée fichier" "Horodatage sommaire à")
("nl" "Bestand" "N" "Tijdstip" "Rubriek" "Duur" "ALLES" "Totale duur" "Bestandstijd" "Klok overzicht op")
("nn" "Fil" "N" "Tidspunkt" "Overskrift" "Tid" "ALLE" "Total tid" "Filtid" "Tidsoversyn")
("pl" "Plik" "P" "Data i godzina" "Nagłówek" "Czas" "WSZYSTKO" "Czas całkowity" "Czas pliku" "Poddumowanie zegara na")
'(("en" "File" "L" "Timestamp" "Headline" "Time" "ALL" "Total time" "File time" "Clock summary at")
("es" "Archivo" "N" "Fecha y hora" "Tarea" "Duración" "TODO" "Duración total" "Tiempo archivo" "Generado el")
("fr" "Fichier" "N" "Horodatage" "En-tête" "Durée" "TOUT" "Durée totale" "Durée fichier" "Horodatage sommaire à")
("nl" "Bestand" "N" "Tijdstip" "Rubriek" "Duur" "ALLES" "Totale duur" "Bestandstijd" "Klok overzicht op")
("nn" "Fil" "N" "Tidspunkt" "Overskrift" "Tid" "ALLE" "Total tid" "Filtid" "Tidsoversyn")
("de" "Datei" "E" "Zeitstempel" "Kopfzeile" "Dauer" "GESAMT" "Gesamtdauer" "Dateizeit" "Erstellt am")
("pt-BR" "Arquivo" "N" "Data e hora" "Título" "Hora" "TODOS" "Hora total" "Hora do arquivo" "Resumo das horas em")
("sk" "Súbor" "L" "Časová značka" "Záhlavie" "Čas" "VŠETKO" "Celkový čas" "Čas súboru" "Časový súhrn pre"))
("sk" "Súbor" "L" "Časová značka" "Záhlavie" "Čas" "VŠETKO" "Celkový čas" "Čas súboru" "Časový súhrn pre"))
"Terms used in clocktable, translated to different languages."
:group 'org-clocktable
:version "24.1"
@ -418,8 +415,8 @@ play with them."
:type 'string)
(defcustom org-clock-clocked-in-display 'mode-line
"Where to display clocked in task and accumulated time when clocked in.
"When clocked in for a task, Org can display the current
task and accumulated time in the mode line and/or frame title.
Allowed values are:
both displays in both mode line and frame title
@ -514,11 +511,7 @@ to add an effort property.")
(defvar org-clock-in-hook nil
"Hook run when starting the clock.")
(defvar org-clock-out-hook nil
"Hook run when stopping the current clock.
The point is at the current clock line when the hook is executed.
The hook functions can access `org-clock-out-removed-last-clock' to
check whether the latest CLOCK line has been cleared.")
"Hook run when stopping the current clock.")
(defvar org-clock-cancel-hook nil
"Hook run when canceling the current clock.")
@ -572,10 +565,6 @@ of a different task.")
Assume S in the English term to translate. Return S as-is if it
cannot be translated."
(or (nth (pcase s
;; "L" stands for "Level"
;; "ALL" stands for a line summarizing clock data across
;; all the files, when the clocktable includes multiple
;; files.
("File" 1) ("L" 2) ("Timestamp" 3) ("Headline" 4) ("Time" 5)
("ALL" 6) ("Total time" 7) ("File time" 8) ("Clock summary at" 9))
(assoc-string language org-clock-clocktable-language-setup t))
@ -590,7 +579,6 @@ cannot be translated."
(org-no-properties (org-get-heading t t t t))))))
(defun org-clock-menu ()
"Pop up org-clock menu."
(interactive)
(popup-menu
'("Clock"
@ -600,12 +588,7 @@ cannot be translated."
["Switch task" (lambda () (interactive) (org-clock-in '(4))) :active t :keys "C-u C-c C-x C-i"])))
(defun org-clock-history-push (&optional pos buffer)
"Push point marker to the clock history.
When POS is provided, use it as marker point.
When BUFFER and POS are provided, use marker at POS in base buffer of
BUFFER."
;; When buffer is provided, POS must be provided.
(cl-assert (or (not buffer) pos))
"Push a marker to the clock history."
(setq org-clock-history-length (max 1 org-clock-history-length))
(let ((m (move-marker (make-marker)
(or pos (point)) (org-base-buffer
@ -625,10 +608,7 @@ BUFFER."
(push m org-clock-history)))
(defun org-clock-save-markers-for-cut-and-paste (beg end)
"Save relative positions of markers in region BEG..END.
Save `org-clock-marker', `org-clock-hd-marker',
`org-clock-default-task', `org-clock-interrupted-task', and the
markers in `org-clock-history'."
"Save relative positions of markers in region."
(org-check-and-save-marker org-clock-marker beg end)
(org-check-and-save-marker org-clock-hd-marker beg end)
(org-check-and-save-marker org-clock-default-task beg end)
@ -654,7 +634,6 @@ markers in `org-clock-history'."
(defun org-clock-select-task (&optional prompt)
"Select a task that was recently associated with clocking.
PROMPT is the prompt text to be used, as a string.
Return marker position of the selected task. Raise an error if
there is no recent clock to choose from."
(let (och chl sel-list rpl (i 0) s)
@ -665,7 +644,7 @@ there is no recent clock to choose from."
(if (zerop chl)
(user-error "No recent clock")
(save-window-excursion
(switch-to-buffer-other-window
(org-switch-to-buffer-other-window
(get-buffer-create "*Clock Task Select*"))
(erase-buffer)
(when (marker-buffer org-clock-default-task)
@ -695,11 +674,8 @@ there is no recent clock to choose from."
;; `fit-window-to-buffer'
(fit-window-to-buffer nil nil (if (< chl 10) chl (+ 5 chl)))
(message (or prompt "Select task for clocking:"))
(unwind-protect (setq cursor-type nil rpl (read-char-exclusive))
(when-let ((window (get-buffer-window "*Clock Task Select*" t)))
(quit-window 'kill window))
(when (get-buffer "*Clock Task Select*")
(kill-buffer "*Clock Task Select*")))
(setq cursor-type nil rpl (read-char-exclusive))
(kill-buffer)
(cond
((eq rpl ?q) nil)
((eq rpl ?x) nil)
@ -926,7 +902,7 @@ If CLOCK-SOUND is non-nil, it overrides `org-clock-sound'."
(if (executable-find "aplay")
(start-process "org-clock-play-notification" nil
"aplay" file)
(condition-case-unless-debug nil
(condition-case nil
(play-sound-file file)
(error (beep t) (beep t))))))))))
@ -943,11 +919,9 @@ If CLOCK-SOUND is non-nil, it overrides `org-clock-sound'."
(save-excursion
(goto-char (point-min))
(while (re-search-forward org-clock-re nil t)
(when (save-match-data
(org-element-type-p (org-element-at-point) 'clock))
(push (cons (copy-marker (match-end 1) t)
(org-time-string-to-time (match-string 1)))
clocks)))))
(push (cons (copy-marker (match-end 1) t)
(org-time-string-to-time (match-string 1)))
clocks))))
clocks))
(defsubst org-is-active-clock (clock)
@ -961,7 +935,7 @@ If CLOCK-SOUND is non-nil, it overrides `org-clock-sound'."
`(with-current-buffer (marker-buffer (car ,clock))
(org-with-wide-buffer
(goto-char (car ,clock))
(forward-line 0)
(beginning-of-line)
,@forms)))
(defmacro org-with-clock (clock &rest forms)
@ -1067,8 +1041,8 @@ CLOCK is a cons cell of the form (MARKER START-TIME)."
(catch 'exit
(while (re-search-backward drawer-re beg t)
(let ((element (org-element-at-point)))
(when (org-element-type-p element 'drawer)
(when (> (org-element-end element) (car clock))
(when (eq (org-element-type element) 'drawer)
(when (> (org-element-property :end element) (car clock))
(org-fold-hide-drawer-toggle 'off nil element))
(throw 'exit nil)))))))))))
@ -1336,6 +1310,8 @@ time as the start time. See `org-clock-continuously' to make this
the default behavior."
(interactive "P")
(setq org-clock-notification-was-shown nil)
(unless org-element-use-cache
(org-refresh-effort-properties))
(catch 'abort
(let ((interrupting (and (not org-clock-resolving-clocks-due-to-idleness)
(org-clocking-p)))
@ -1413,8 +1389,8 @@ the default behavior."
(when newstate (org-todo newstate))))
((and org-clock-in-switch-to-state
(not (looking-at (concat org-outline-regexp "[ \t]*"
org-clock-in-switch-to-state
"\\>"))))
org-clock-in-switch-to-state
"\\>"))))
(org-todo org-clock-in-switch-to-state)))
(setq org-clock-heading (org-clock--mode-line-heading))
(org-clock-find-position org-clock-in-resume)
@ -1440,15 +1416,12 @@ the default behavior."
(sit-for 2)
(throw 'abort nil))
(t
;; Make sure that point moves after clock line upon
;; inserting it. Then, users can continue typing even if
;; point was right where the clock is inserted.
(insert-before-markers-and-inherit "\n")
(backward-char 1)
(when (and (save-excursion
(end-of-line 0)
(org-in-item-p)))
(forward-line 0)
(beginning-of-line 1)
(indent-line-to (max 0 (- (current-indentation) 2))))
(insert-and-inherit org-clock-string " ")
(setq org-clock-effort (org-entry-get (point) org-effort-property))
@ -1468,8 +1441,8 @@ the default behavior."
leftover)
start-time
(org-current-time org-clock-rounding-minutes t)))
(setq ts (org-insert-timestamp org-clock-start-time
'with-hm 'inactive))
(setq ts (org-insert-time-stamp org-clock-start-time
'with-hm 'inactive))
(org-indent-line)))
(move-marker org-clock-marker (point) (buffer-base-buffer))
(move-marker org-clock-hd-marker
@ -1505,33 +1478,6 @@ the default behavior."
(message "Clock starts at %s - %s" ts org--msg-extra)
(run-hooks 'org-clock-in-hook))))))
(defvar org-clock--auto-clockout-timer-obj nil
"Timer object holding the existing clockout timer.")
(defun org-clock--auto-clockout-maybe ()
"Clock out the currently clocked in task when idle.
See `org-clock-auto-clockout-timer' to set the idle time span.
This function is to be called by a timer."
(when (and (numberp org-clock-auto-clockout-timer)
org-clock-current-task)
(let ((user-idle-seconds (org-user-idle-seconds)))
(cond
;; Already idle. Clock out.
((>= user-idle-seconds org-clock-auto-clockout-timer)
(setq org-clock--auto-clockout-timer-obj nil)
(org-clock-out))
;; Emacs is idle but system is not. Retry assuming that system will remain idle.
((>= (org-emacs-idle-seconds) org-clock-auto-clockout-timer)
(setq org-clock--auto-clockout-timer-obj
(run-with-timer
(- org-clock-auto-clockout-timer user-idle-seconds)
nil #'org-clock--auto-clockout-maybe)))
;; Emacs is not idle. Check again next time we are idle.
(t
(setq org-clock--auto-clockout-timer-obj
(run-with-idle-timer
org-clock-auto-clockout-timer nil #'org-clock--auto-clockout-maybe)))))))
(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.
@ -1539,11 +1485,9 @@ 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
(not (timerp org-clock--auto-clockout-timer-obj)))
(setq org-clock--auto-clockout-timer-obj
(run-with-idle-timer
org-clock-auto-clockout-timer nil #'org-clock--auto-clockout-maybe))))
org-clock-current-task)
(run-with-idle-timer
org-clock-auto-clockout-timer nil #'org-clock-out)))
;;;###autoload
(defun org-clock-toggle-auto-clockout ()
@ -1651,9 +1595,9 @@ line and position cursor in that line."
" *\\sw+ +[012][0-9]:[0-5][0-9]\\)\\][ \t]*$")))
(while (re-search-forward open-clock-re end t)
(let ((element (org-element-at-point)))
(when (and (org-element-type-p element 'clock)
(when (and (eq (org-element-type element) 'clock)
(eq (org-element-property :status element) 'running))
(forward-line 0)
(beginning-of-line)
(throw 'exit t))))))
;; Look for an existing clock drawer.
(when drawer
@ -1661,8 +1605,8 @@ line and position cursor in that line."
(let ((drawer-re (concat "^[ \t]*:" (regexp-quote drawer) ":[ \t]*$")))
(while (re-search-forward drawer-re end t)
(let ((element (org-element-at-point)))
(when (org-element-type-p element 'drawer)
(let ((cend (org-element-contents-end element)))
(when (eq (org-element-type element) 'drawer)
(let ((cend (org-element-property :contents-end element)))
(if (and (not org-log-states-order-reversed) cend)
(goto-char cend)
(forward-line))
@ -1675,7 +1619,7 @@ line and position cursor in that line."
(save-excursion
(while (re-search-forward clock-re end t)
(let ((element (org-element-at-point)))
(when (org-element-type-p element 'clock)
(when (eq (org-element-type element) 'clock)
(setq positions (cons (line-beginning-position) positions)
count (1+ count))))))
(cond
@ -1683,18 +1627,19 @@ line and position cursor in that line."
(org-fold-core-ignore-modifications
;; Skip planning line and property drawer, if any.
(org-end-of-meta-data)
(unless (bolp) (insert-before-markers-and-inherit "\n"))
(unless (bolp) (insert-and-inherit "\n"))
;; Create a new drawer if necessary.
(when (and org-clock-into-drawer
(or (not (wholenump org-clock-into-drawer))
(< org-clock-into-drawer 2)))
(let ((beg (point)))
;; Make sure that point moves after drawer upon
;; inserting it. Then, users can continue typing even
;; if point was right where the clock is inserted.
(insert-before-markers-and-inherit ":" drawer ":\n:END:\n")
(insert-and-inherit ":" drawer ":\n:END:\n")
(org-indent-region beg (point))
(org-fold-region (line-end-position -1) (1- (point)) t 'drawer)
(if (eq org-fold-core-style 'text-properties)
(org-fold-region
(line-end-position -1) (1- (point)) t 'drawer)
(org-fold-region
(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
@ -1719,13 +1664,13 @@ line and position cursor in that line."
"\n:END:\n")
(let ((end (point-marker)))
(goto-char beg)
(save-excursion (insert-before-markers-and-inherit ":" drawer ":\n"))
(save-excursion (insert-and-inherit ":" drawer ":\n"))
(org-fold-region (line-end-position) (1- end) t 'outline)
(org-indent-region (point) end)
(forward-line)
(unless org-log-states-order-reversed
(goto-char end)
(forward-line -2))
(beginning-of-line -1))
(set-marker end nil)))))
(org-log-states-order-reversed (goto-char (car (last positions))))
(t (goto-char (car positions))))))))
@ -1738,11 +1683,6 @@ and current `frame-title-format' is equal to `org-clock-frame-title-format'."
(equal frame-title-format org-clock-frame-title-format))
(setq frame-title-format org-frame-title-format-backup)))
(defvar org-clock-out-removed-last-clock nil
"When non-nil, the last `org-clock-out' removed the clock line.
This can happen when `org-clock-out-remove-zero-time-clocks' is set to
non-nil and the latest clock took 0 minutes.")
;;;###autoload
(defun org-clock-out (&optional switch-to-state fail-quietly at-time)
"Stop the currently running clock.
@ -1773,7 +1713,7 @@ to, overriding the existing value of `org-clock-out-switch-to-state'."
(save-restriction
(widen)
(goto-char org-clock-marker)
(forward-line 0)
(beginning-of-line 1)
(if (and (looking-at (concat "[ \t]*" org-keyword-time-regexp))
(equal (match-string 1) org-clock-string))
(setq ts (match-string 2))
@ -1782,7 +1722,7 @@ to, overriding the existing value of `org-clock-out-switch-to-state'."
(delete-region (point) (line-end-position))
(org-fold-core-ignore-modifications
(insert-and-inherit "--")
(setq te (org-insert-timestamp (or at-time now) 'with-hm 'inactive))
(setq te (org-insert-time-stamp (or at-time now) 'with-hm 'inactive))
(setq s (org-time-convert-to-integer
(time-subtract
(org-time-string-to-time te)
@ -1821,10 +1761,10 @@ to, overriding the existing value of `org-clock-out-switch-to-state'."
(when newstate (org-todo newstate))))
((and org-clock-out-switch-to-state
(not (looking-at
(concat
org-outline-regexp "[ \t]*"
org-clock-out-switch-to-state
"\\>"))))
(concat
org-outline-regexp "[ \t]*"
org-clock-out-switch-to-state
"\\>"))))
(org-todo org-clock-out-switch-to-state))))))
(force-mode-line-update)
(message (if remove
@ -1833,7 +1773,6 @@ to, overriding the existing value of `org-clock-out-switch-to-state'."
te (org-duration-from-minutes (+ (* 60 h) m)))
(unless (org-clocking-p)
(setq org-clock-current-task nil))
(setq org-clock-out-removed-last-clock remove)
(run-hooks 'org-clock-out-hook)
;; Add a note, but only if we didn't remove the clock line.
(when (and org-log-note-clock-out (not remove))
@ -2176,7 +2115,6 @@ Use `\\[org-clock-remove-overlays]' to remove the subtree times."
h m))))
(defvar-local org-clock-overlays nil)
(put 'org-clock-overlays 'permanent-local t)
(defun org-clock-put-overlay (time)
"Put an overlay on the headline at point, displaying TIME.
@ -2451,7 +2389,7 @@ have priority."
d (+ d shift)))
((or `week `thisweek)
(let* ((ws (or wstart 1))
(diff (+ (* -7 shift) (mod (+ dow 7 (- ws)) 7))))
(diff (+ (* -7 shift) (if (= dow 0) (- 7 ws) (- dow ws)))))
(setq m 0 h org-extend-today-until d (- d diff) d1 (+ 7 d))))
((or `month `thismonth)
(setq h org-extend-today-until m 0 d (or mstart 1)
@ -2602,7 +2540,7 @@ the currently selected interval size."
(goto-char b)
(insert ins)
(delete-region (point) (+ (point) (- e b)))
(forward-line 0)
(beginning-of-line 1)
(org-update-dblock)
t)))))
@ -2904,13 +2842,13 @@ from the dynamic block definition."
(if timestamp (concat ts "|") "") ;timestamp, maybe
(if tags (concat (mapconcat #'identity tgs ", ") "|") "") ;tags, maybe
(if properties ;properties columns, maybe
(concat (mapconcat (lambda (p) (or (cdr (assoc p props)) ""))
properties
"|")
"|")
(concat (mapconcat (lambda (p) (or (cdr (assoc p props)) ""))
properties
"|")
"|")
"")
(if indent ;indentation
(org-clocktable-indent-string level)
(org-clocktable-indent-string level)
"")
(format-field headline)
;; Empty fields for higher levels.
@ -2918,7 +2856,7 @@ from the dynamic block definition."
(format-field (org-duration-from-minutes time))
(make-string (max 0 (- time-columns level)) ?|)
(if (eq formula '%)
(format "%.1f |" (* 100 (/ time (float total-time))))
(format "%.1f |" (* 100 (/ time (float total-time))))
"")
"\n")))))))
(delete-char -1)
@ -2929,7 +2867,7 @@ from the dynamic block definition."
(when (and contents (string-match "^\\([ \t]*#\\+tblfm:.*\\)" contents))
(setq recalc t)
(insert "\n" (match-string 1 contents))
(forward-line -1))))
(beginning-of-line 0))))
;; Insert specified formula line.
((stringp formula)
(insert "\n#+TBLFM: " formula)
@ -3170,58 +3108,57 @@ PROPERTIES: The list properties specified in the `:properties' parameter
Otherwise, return nil."
(interactive)
(let ((origin (point))) ;; `save-excursion' may not work when deleting.
(prog1
(save-excursion
(forward-line 0)
(skip-chars-forward " \t")
(when (looking-at org-clock-string)
(let ((re (concat "[ \t]*" org-clock-string
" *[[<]\\([^]>]+\\)[]>]\\(-+[[<]\\([^]>]+\\)[]>]"
"\\([ \t]*=>.*\\)?\\)?"))
ts te h m s neg)
(cond
((not (looking-at re))
nil)
((not (match-end 2))
(when (and (equal (marker-buffer org-clock-marker) (current-buffer))
(> org-clock-marker (point))
(<= org-clock-marker (line-end-position)))
;; The clock is running here
(setq org-clock-start-time
(org-time-string-to-time (match-string 1)))
(org-clock-update-mode-line)))
(t
;; Prevent recursive call from `org-timestamp-change'.
(cl-letf (((symbol-function 'org-clock-update-time-maybe) #'ignore))
;; Update timestamps.
(save-excursion
(goto-char (match-beginning 1)) ; opening timestamp
(save-match-data (org-timestamp-change 0 'day)))
;; Refresh match data.
(looking-at re)
(save-excursion
(goto-char (match-beginning 3)) ; closing timestamp
(save-match-data (org-timestamp-change 0 'day))))
;; Refresh match data.
(looking-at re)
(and (match-end 4) (delete-region (match-beginning 4) (match-end 4)))
(end-of-line 1)
(setq ts (match-string 1)
te (match-string 3))
(setq s (- (org-time-string-to-seconds te)
(org-time-string-to-seconds ts))
neg (< s 0)
s (abs s)
h (floor (/ s 3600))
s (- s (* 3600 h))
m (floor (/ s 60))
s (- s (* 60 s)))
(insert " => " (format (if neg "-%d:%02d" "%2d:%02d") h m))
t)))))
;; Move back to initial position, but never beyond updated
;; clock.
(unless (< (point) origin)
(goto-char origin)))))
(save-excursion
(beginning-of-line 1)
(skip-chars-forward " \t")
(when (looking-at org-clock-string)
(let ((re (concat "[ \t]*" org-clock-string
" *[[<]\\([^]>]+\\)[]>]\\(-+[[<]\\([^]>]+\\)[]>]"
"\\([ \t]*=>.*\\)?\\)?"))
ts te h m s neg)
(cond
((not (looking-at re))
nil)
((not (match-end 2))
(when (and (equal (marker-buffer org-clock-marker) (current-buffer))
(> org-clock-marker (point))
(<= org-clock-marker (line-end-position)))
;; The clock is running here
(setq org-clock-start-time
(org-time-string-to-time (match-string 1)))
(org-clock-update-mode-line)))
(t
;; Prevent recursive call from `org-timestamp-change'.
(cl-letf (((symbol-function 'org-clock-update-time-maybe) #'ignore))
;; Update timestamps.
(save-excursion
(goto-char (match-beginning 1)) ; opening timestamp
(save-match-data (org-timestamp-change 0 'day)))
;; Refresh match data.
(looking-at re)
(save-excursion
(goto-char (match-beginning 3)) ; closing timestamp
(save-match-data (org-timestamp-change 0 'day))))
;; Refresh match data.
(looking-at re)
(and (match-end 4) (delete-region (match-beginning 4) (match-end 4)))
(end-of-line 1)
(setq ts (match-string 1)
te (match-string 3))
(setq s (- (org-time-string-to-seconds te)
(org-time-string-to-seconds ts))
neg (< s 0)
s (abs s)
h (floor (/ s 3600))
s (- s (* 3600 h))
m (floor (/ s 60))
s (- s (* 60 s)))
(insert " => " (format (if neg "-%d:%02d" "%2d:%02d") h m))
t)))))
;; Move back to initial position, but never beyond updated
;; clock.
(unless (< (point) origin)
(goto-char origin))))
(defun org-clock-save ()
"Persist various clock-related data to disk.

View File

@ -1,6 +1,6 @@
;;; org-colview.el --- Column View in Org -*- lexical-binding: t; -*-
;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
;; Keywords: outlines, hypermedia, calendar, wp
@ -37,13 +37,13 @@
(declare-function org-agenda-redo "org-agenda" (&optional all))
(declare-function org-agenda-do-context-action "org-agenda" ())
(declare-function org-clock-sum-today "org-clock" (&optional headline-filter))
(declare-function org-element-extract "org-element-ast" (node))
(declare-function org-element-extract-element "org-element" (element))
(declare-function org-element-interpret-data "org-element" (data))
(declare-function org-element-map "org-element" (data types fun &optional info first-match no-recursion with-affiliated))
(declare-function org-element-parse-secondary-string "org-element" (string restriction &optional parent))
(declare-function org-element-property "org-element-ast" (property node))
(declare-function org-element-property "org-element" (property element))
(declare-function org-element-restriction "org-element" (element))
(declare-function org-element-type-p "org-element-ast" (node types))
(declare-function org-element-type "org-element" (element))
(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))
@ -59,19 +59,6 @@
;;; Configuration
(defcustom org-columns-checkbox-allowed-values '("[ ]" "[X]")
"Allowed values for columns with SUMMARY-TYPE that uses checkbox.
The affected summary types are \"X%\", \"X/\", and \"X\" (see info
node `(org)Column attributes')."
:group 'org-properties
:package-version '(Org . "9.6")
:type '(repeat (choice
(const :tag "Unchecked [ ]" "[ ]")
(const :tag "Checked [X]" "[X]")
(const :tag "No checkbox" "")
(const :tag "Intermediate state [-]" "[-]")
(string :tag "Arbitrary string"))))
(defcustom org-columns-modify-value-for-display-function nil
"Function that modifies values for display in column view.
For example, it can be used to cut out a certain part from a time stamp.
@ -129,10 +116,6 @@ in `org-columns-summary-types-default', which see."
(defvar-local org-columns-overlays nil
"Holds the list of current column overlays.")
(put 'org-columns-overlays 'permanent-local t)
(defvar-local org-columns-global nil
"Local variable, holds non-nil when current columns are global.")
(defvar-local org-columns-current-fmt nil
"Local variable, holds the currently active column format.")
@ -196,10 +179,28 @@ See `org-columns-summary-types' for details.")
(org-defkey org-columns-map "\M-b" #'backward-char)
(org-defkey org-columns-map "a" #'org-columns-edit-allowed)
(org-defkey org-columns-map "s" #'org-columns-edit-attributes)
(org-defkey org-columns-map "\M-f" #'forward-char)
(org-defkey org-columns-map [right] #'forward-char)
(org-defkey org-columns-map [up] #'org-columns-move-up)
(org-defkey org-columns-map [down] #'org-columns-move-down)
(org-defkey org-columns-map "\M-f"
(lambda () (interactive) (goto-char (1+ (point)))))
(org-defkey org-columns-map [right]
(lambda () (interactive) (goto-char (1+ (point)))))
(org-defkey org-columns-map [down]
(lambda () (interactive)
(let ((col (current-column)))
(beginning-of-line 2)
(while (and (org-invisible-p2) (not (eobp)))
(beginning-of-line 2))
(move-to-column col)
(if (derived-mode-p 'org-agenda-mode)
(org-agenda-do-context-action)))))
(org-defkey org-columns-map [up]
(lambda () (interactive)
(let ((col (current-column)))
(beginning-of-line 0)
(while (and (org-invisible-p2) (not (bobp)))
(beginning-of-line 0))
(move-to-column col)
(if (eq major-mode 'org-agenda-mode)
(org-agenda-do-context-action)))))
(org-defkey org-columns-map [(shift right)] #'org-columns-next-allowed-value)
(org-defkey org-columns-map "n" #'org-columns-next-allowed-value)
(org-defkey org-columns-map [(shift left)] #'org-columns-previous-allowed-value)
@ -208,8 +209,6 @@ See `org-columns-summary-types' for details.")
(org-defkey org-columns-map ">" #'org-columns-widen)
(org-defkey org-columns-map [(meta right)] #'org-columns-move-right)
(org-defkey org-columns-map [(meta left)] #'org-columns-move-left)
(org-defkey org-columns-map [(meta down)] #'org-columns-move-row-down)
(org-defkey org-columns-map [(meta up)] #'org-columns-move-row-up)
(org-defkey org-columns-map [(shift meta right)] #'org-columns-new)
(org-defkey org-columns-map [(shift meta left)] #'org-columns-delete)
(dotimes (i 10)
@ -231,8 +230,6 @@ See `org-columns-summary-types' for details.")
"--"
["Move column right" org-columns-move-right t]
["Move column left" org-columns-move-left t]
["Move row up" org-columns-move-row-up t]
["Move row down" org-columns-move-row-down t]
["Add column" org-columns-new t]
["Delete column" org-columns-delete t]
"--"
@ -378,19 +375,17 @@ ORIGINAL is the real string, i.e., before it is modified by
"Store the relative remapping of column header-line.
This is needed to later remove this relative remapping.")
(defvar org-columns--read-only-string nil)
(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 (and (not org-columns-header-line-remap)
(or (fboundp 'face-remap-add-relative)
(ignore-errors (require 'face-remap))))
(when (and (ignore-errors (require 'face-remap))
org-columns-header-line-remap)
(setq org-columns-header-line-remap
(face-remap-add-relative 'header-line '(:inherit default))))
(save-excursion
(forward-line 0)
(beginning-of-line)
(let* ((level-face (and (looking-at "\\(\\**\\)\\(\\* \\)")
(org-get-level-face 2)))
(ref-face (or level-face
@ -453,36 +448,18 @@ DATELINE is non-nil when the face used should be
(line-end-position 0)
(line-beginning-position 2)
'read-only
(or org-columns--read-only-string
(setq org-columns--read-only-string
(substitute-command-keys
"Type \\<org-columns-map>`\\[org-columns-edit-value]' \
to edit property")))))))))
(defun org-columns--truncate-below-width (string width)
"Return a substring of STRING no wider than WIDTH.
This substring must start at 0, and must be the longest possible
substring whose `string-width' does not exceed WIDTH."
(declare (side-effect-free t))
(let ((end (min width (length string))) res)
(while (and end (>= end 0))
(let* ((curr (string-width (substring string 0 end)))
(excess (- curr width)))
(if (> excess 0)
(cl-decf end (max 1 (/ excess 2)))
(setq res (substring string 0 end) end nil))))
res))
(substitute-command-keys
"Type \\<org-columns-map>`\\[org-columns-edit-value]' \
to edit property")))))))
(defun org-columns-add-ellipses (string width)
"Truncate STRING with WIDTH characters, with ellipses."
(cond
((<= (string-width string) width) string)
((<= width (string-width org-columns-ellipses))
(org-columns--truncate-below-width org-columns-ellipses width))
(t (concat
(org-columns--truncate-below-width
string (- width (string-width org-columns-ellipses)))
org-columns-ellipses))))
((<= (length string) width) string)
((<= width (length org-columns-ellipses))
(substring org-columns-ellipses 0 width))
(t (concat (substring string 0 (- width (length org-columns-ellipses)))
org-columns-ellipses))))
(defvar org-columns-full-header-line-format nil
"The full header line format, will be shifted by horizontal scrolling." )
@ -547,8 +524,7 @@ for the duration of the command.")
(setq header-line-format org-previous-header-line-format)
(kill-local-variable 'org-previous-header-line-format)
(remove-hook 'post-command-hook #'org-columns-hscroll-title 'local))
(when (markerp org-columns-begin-marker)
(set-marker org-columns-begin-marker nil))
(set-marker org-columns-begin-marker nil)
(when (markerp org-columns-top-level-marker)
(set-marker org-columns-top-level-marker nil))
(with-silent-modifications
@ -750,7 +726,7 @@ an integer, select that value."
(let ((all
(or (org-property-get-allowed-values pom key)
(pcase (nth column org-columns-current-fmt-compiled)
(`(,_ ,_ ,_ ,(or "X" "X/" "X%") ,_) org-columns-checkbox-allowed-values))
(`(,_ ,_ ,_ ,(or "X" "X/" "X%") ,_) '("[ ]" "[X]")))
(org-colview-construct-allowed-dates value))))
(if previous (reverse all) all))))
(when (equal key "ITEM") (error "Cannot edit item headline from here"))
@ -840,7 +816,7 @@ current specifications. This function also sets
(let ((case-fold-search t))
(while (re-search-forward "^[ \t]*#\\+COLUMNS: .+$" nil t)
(let ((element (org-element-at-point)))
(when (org-element-type-p element 'keyword)
(when (eq (org-element-type element) 'keyword)
(throw :found (org-element-property :value element)))))
nil)))
org-columns-default-format)))
@ -873,7 +849,6 @@ turn on column view for the whole buffer unconditionally.
When COLUMNS-FMT-STRING is non-nil, use it as the column format."
(interactive "P")
(org-columns-remove-overlays)
(setq-local org-columns-global global)
(save-excursion
(when global (goto-char (point-min)))
(if (markerp org-columns-begin-marker)
@ -896,7 +871,7 @@ When COLUMNS-FMT-STRING is non-nil, use it as the column format."
;; Collect contents of columns ahead of time so as to
;; compute their maximum width.
(org-scan-tags
(lambda () (cons (point-marker) (org-columns--collect-values))) t org--matcher-tags-todo-only)))
(lambda () (cons (point) (org-columns--collect-values))) t org--matcher-tags-todo-only)))
(when cache
(org-columns--set-widths cache)
(org-columns--display-here-title)
@ -994,30 +969,6 @@ details."
(interactive "p")
(org-columns-widen (- arg)))
(defun org-columns-move-up ()
"In column view, move cursor up one row.
When in agenda column view, also call `org-agenda-do-context-action'."
(interactive)
(let ((col (current-column)))
(forward-line -1)
(while (and (org-invisible-p2) (not (bobp)))
(forward-line -1))
(move-to-column col)
(if (eq major-mode 'org-agenda-mode)
(org-agenda-do-context-action))))
(defun org-columns-move-down ()
"In column view, move cursor down one row.
When in agenda column view, also call `org-agenda-do-context-action'."
(interactive)
(let ((col (current-column)))
(forward-line 1)
(while (and (org-invisible-p2) (not (eobp)))
(forward-line 1))
(move-to-column col)
(if (derived-mode-p 'org-agenda-mode)
(org-agenda-do-context-action))))
(defun org-columns-move-right ()
"Swap this column with the one to the right."
(interactive)
@ -1052,27 +1003,6 @@ When in agenda column view, also call `org-agenda-do-context-action'."
(org-columns-move-right)
(backward-char 1)))
(defun org-columns--move-row (&optional up)
"Move the current table row down.
With non-nil optional argument UP, move it up."
(let ((inhibit-read-only t)
(col (current-column)))
(if up (org-move-subtree-up)
(org-move-subtree-down))
(let ((org-columns-inhibit-recalculation t))
(org-columns-redo)
(move-to-column col))))
(defun org-columns-move-row-down ()
"Move the current table row down."
(interactive)
(org-columns--move-row))
(defun org-columns-move-row-up ()
"Move the current table row up."
(interactive)
(org-columns--move-row 'up))
(defun org-columns-store-format ()
"Store the text version of the current columns format.
The format is stored either in the COLUMNS property of the node
@ -1090,7 +1020,7 @@ the current buffer."
(catch :found
(while (re-search-forward "^[ \t]*#\\+COLUMNS:\\(.*\\)" nil t)
(let ((element (save-match-data (org-element-at-point))))
(when (and (org-element-type-p element 'keyword)
(when (and (eq (org-element-type element) 'keyword)
(equal (org-element-property :key element)
"COLUMNS"))
(replace-match (concat " " fmt) t t nil 1)
@ -1140,7 +1070,7 @@ the current buffer."
(if (derived-mode-p 'org-mode)
;; Since we already know the columns format, provide it
;; instead of computing again.
(funcall-interactively #'org-columns org-columns-global org-columns-current-fmt)
(call-interactively #'org-columns org-columns-current-fmt)
(org-agenda-redo)
(call-interactively #'org-agenda-columns)))
(message "Recomputing columns...done")))
@ -1200,7 +1130,7 @@ This function updates `org-columns-current-fmt-compiled'."
(defun org-columns--age-to-minutes (s)
"Turn age string S into a number of minutes.
An age is either computed from a given timestamp, or indicated
An age is either computed from a given time-stamp, or indicated
as a canonical duration, i.e., using units defined in
`org-duration-canonical-units'."
(cond
@ -1229,8 +1159,8 @@ Return the result as a duration."
SPEC is a column format specification. When optional argument
UPDATE is non-nil, summarized values can replace existing ones in
properties drawers."
(let* ((lmax (if (bound-and-true-p org-inlinetask-max-level)
org-inlinetask-max-level
(let* ((lmax (if (bound-and-true-p org-inlinetask-min-level)
org-inlinetask-min-level
29)) ;Hard-code deepest level.
(lvals (make-vector (1+ lmax) nil))
(level 0)
@ -1266,9 +1196,9 @@ properties drawers."
;; property `org-summaries', in alist whose key is SPEC.
(let* ((summary
(and summarize
(let ((values
(cl-loop for l from (1+ level) to lmax
append (aref lvals l))))
(let ((values (append (and (/= last-level inminlevel)
(aref lvals last-level))
(aref lvals inminlevel))))
(and values (funcall summarize values printf))))))
;; Leaf values are not summaries: do not mark them.
(when summary
@ -1492,7 +1422,7 @@ an inline src-block."
(org-element-map data
'(footnote-reference inline-babel-call inline-src-block target
radio-target statistics-cookie)
#'org-element-extract)
#'org-element-extract-element)
(org-no-properties (org-element-interpret-data data))))
;;;###autoload
@ -1563,7 +1493,7 @@ PARAMS is a property list of parameters:
(setq view-file filename)
(setq view-pos position))
(_ (user-error "Cannot find entry with :ID: %s" id)))
(with-current-buffer (if view-file (org-get-agenda-file-buffer view-file)
(with-current-buffer (if view-file (get-file-buffer view-file)
(current-buffer))
(org-with-wide-buffer
(when view-pos (goto-char view-pos))
@ -1572,10 +1502,7 @@ PARAMS is a property list of parameters:
(plist-get params :skip-empty-rows)
(plist-get params :exclude-tags)
(plist-get params :format)
view-pos)))))
(width-specs
(mapcar (lambda (spec) (nth 2 spec))
org-columns-current-fmt-compiled)))
view-pos))))))
(when table
;; Prune level information from the table. Also normalize
;; headings: remove stars, add indentation entities, if
@ -1611,11 +1538,6 @@ PARAMS is a property list of parameters:
(append (mapcar (lambda (x) (if (eq 'hline x) x (cons "" x)))
table)
(list (cons "/" (make-list size "<>")))))))
(when (seq-find #'identity width-specs)
;; There are width specifiers in column format. Pass them
;; to the resulting table, adding alignment field as the first
;; row.
(push (mapcar (lambda (width) (when width (format "<%d>" width))) width-specs) table))
(let ((content-lines (org-split-string (plist-get params :content) "\n"))
recalc)
;; Insert affiliated keywords before the table.
@ -1637,9 +1559,7 @@ PARAMS is a property list of parameters:
(insert "\n" line)
(unless recalc (setq recalc t))))))
(when recalc (org-table-recalculate 'all t))
(org-table-align)
(when (seq-find #'identity width-specs)
(org-table-shrink))))))
(org-table-align)))))
;;;###autoload
(defun org-columns-insert-dblock ()

View File

@ -1,6 +1,6 @@
;;; org-compat.el --- Compatibility Code for Older Emacsen -*- lexical-binding: t; -*-
;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
;; Keywords: outlines, hypermedia, calendar, wp
@ -52,15 +52,9 @@
(declare-function org-element-at-point "org-element" (&optional pom cached-only))
(declare-function org-element-at-point-no-context "org-element" (&optional pom))
(declare-function org-element-context "org-element" (&optional element))
(declare-function org-element-lineage "org-element-ast" (blob &optional types with-self))
(declare-function org-element-type "org-element-ast" (node &optional anonymous))
(declare-function org-element-type-p "org-element-ast" (node types))
(declare-function org-element-property "org-element-ast" (property node))
(declare-function org-element-begin "org-element" (node))
(declare-function org-element-end "org-element" (node))
(declare-function org-element-contents-begin "org-element" (node))
(declare-function org-element-contents-end "org-element" (node))
(declare-function org-element-post-affiliated "org-element" (node))
(declare-function org-element-lineage "org-element" (blob &optional types with-self))
(declare-function org-element-type "org-element" (element))
(declare-function org-element-property "org-element" (property element))
(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))
@ -103,25 +97,6 @@
;;; Emacs < 29 compatibility
(if (fboundp 'display-buffer-full-frame)
(defalias 'org-display-buffer-full-frame #'display-buffer-full-frame)
(defun org-display-buffer-full-frame (buffer alist)
"Display BUFFER in the current frame, taking the entire frame.
ALIST is an association list of action symbols and values. See
Info node `(elisp) Buffer Display Action Alists' for details of
such alists.
This is an action function for buffer display, see Info
node `(elisp) Buffer Display Action Functions'. It should be
called only by `display-buffer' or a function directly or
indirectly called by the latter."
(when-let ((window (or (display-buffer-reuse-window buffer alist)
(display-buffer-same-window buffer alist)
(display-buffer-pop-up-window buffer alist)
(display-buffer-use-some-window buffer alist))))
(delete-other-windows window)
window)))
(defvar org-file-has-changed-p--hash-table (make-hash-table :test #'equal)
"Internal variable used by `org-file-has-changed-p'.")
@ -156,41 +131,9 @@ Upper-case and lower-case letters are treated as equal.
Unibyte strings are converted to multibyte for comparison."
(eq t (compare-strings string1 0 nil string2 0 nil t))))
(defun org-buffer-text-pixel-width ()
"Return pixel width of text in current buffer.
This function uses `buffer-text-pixel-size', when available, and falls
back to `window-text-pixel-size' otherwise."
(if (fboundp 'buffer-text-pixel-size)
(car (buffer-text-pixel-size nil nil t))
(if (get-buffer-window (current-buffer))
;; FIXME: 10000 because `most-positive-fixnum' ain't working
;; (tests failing) and this call will be removed after we drop
;; Emacs 28 support anyway.
(car (window-text-pixel-size
nil (point-min) (point-max) 10000))
(let ((dedicatedp (window-dedicated-p))
(oldbuffer (window-buffer)))
(unwind-protect
(progn
;; Do not throw error in dedicated windows.
(set-window-dedicated-p nil nil)
(set-window-buffer nil (current-buffer))
(car (window-text-pixel-size
nil (point-min) (point-max) 10000)))
(set-window-buffer nil oldbuffer)
(set-window-dedicated-p nil dedicatedp))))))
;;; Emacs < 28.1 compatibility
(if (= 2 (cdr (subr-arity (symbol-function 'get-buffer-create))))
;; Emacs >27.
(defalias 'org-get-buffer-create #'get-buffer-create)
(defun org-get-buffer-create (buffer-or-name &optional _)
"Call `get-buffer-create' with BUFFER-OR-NAME argument.
Ignore optional argument."
(get-buffer-create buffer-or-name)))
(if (fboundp 'file-name-concat)
(defalias 'org-file-name-concat #'file-name-concat)
(defun org-file-name-concat (directory &rest components)
@ -199,7 +142,7 @@ Ignore optional argument."
Elements in COMPONENTS must be a string or nil.
DIRECTORY or the non-final elements in COMPONENTS may or may not end
with a slash -- if they don't end with a slash, a slash will be
inserted before concatenating."
inserted before contatenating."
(save-match-data
(mapconcat
#'identity
@ -251,18 +194,6 @@ removed."
default)))
": ")))
(if (fboundp 'ensure-list)
(defalias 'org-ensure-list #'ensure-list)
(defun org-ensure-list (object)
"Return OBJECT as a list.
If OBJECT is already a list, return OBJECT itself. If it's
not a list, return a one-element list containing OBJECT.
Compatability substitute for `ensure-list' in Emacs 28."
(if (listp object)
object
(list object))))
;;; Emacs < 27.1 compatibility
@ -274,25 +205,6 @@ Compatability substitute for `ensure-list' in Emacs 28."
`(progn ,@body))
(defalias 'org-combine-change-calls 'combine-change-calls))
;; `flatten-tree' was added in Emacs 27.1.
(if (fboundp 'flatten-tree)
(defalias 'org--flatten-tree #'flatten-tree)
;; The implementation is taken from Emacs subr.el 8664ba18c7c5.
(defun org--flatten-tree (tree)
"Return a \"flattened\" copy of TREE.
A `flatten-tree' polyfill for compatibility with Emacs versions
older than 27.1"
(let (elems)
(while (consp tree)
(let ((elem (pop tree)))
(while (consp elem)
(push (cdr elem) tree)
(setq elem (car elem)))
(if elem (push elem elems))))
(if tree (push tree elems))
(nreverse elems))))
(if (version< emacs-version "27.1")
(defsubst org-replace-buffer-contents (source &optional _max-secs _max-costs)
(replace-buffer-contents source))
@ -379,24 +291,6 @@ Execute BODY, and unwind connection-local variables."
`(with-connection-local-profiles (connection-local-get-profiles nil)
,@body)))
;; assoc-delete-all missing from 26.1
(if (fboundp 'assoc-delete-all)
(defalias 'org-assoc-delete-all 'assoc-delete-all)
;; from compat/compat-27.el
(defun org-assoc-delete-all (key alist &optional test)
"Delete all matching key from alist, default test equal"
(unless test (setq test #'equal))
(while (and (consp (car alist))
(funcall test (caar alist) key))
(setq alist (cdr alist)))
(let ((tail alist) tail-cdr)
(while (setq tail-cdr (cdr tail))
(if (and (consp (car tail-cdr))
(funcall test (caar tail-cdr) key))
(setcdr tail (cdr tail-cdr))
(setq tail tail-cdr))))
alist))
;;; Emacs < 26.1 compatibility
@ -493,8 +387,6 @@ Counting starts at 1."
(define-obsolete-function-alias 'org-string-match-p 'string-match-p "9.0")
;;;; Functions and variables from previous releases now obsolete.
(define-obsolete-variable-alias 'org-export-ignored-local-variables
'org-element-ignored-local-variables "Org 9.7")
(define-obsolete-function-alias 'org-habit-get-priority
'org-habit-get-urgency "Org 9.7")
(define-obsolete-function-alias 'org-timestamp-format
@ -522,7 +414,7 @@ Counting starts at 1."
'completing-read "9.0")
(define-obsolete-function-alias 'org-iread-file-name 'read-file-name "9.0")
(define-obsolete-function-alias 'org-days-to-time
'org-timestamp-to-now "8.2")
'org-time-stamp-to-now "8.2")
(define-obsolete-variable-alias 'org-agenda-ignore-drawer-properties
'org-agenda-ignore-properties "9.0")
(define-obsolete-function-alias 'org-preview-latex-fragment
@ -660,419 +552,14 @@ Counting starts at 1."
(define-obsolete-function-alias 'org-file-url-p 'org-url-p "9.6")
(define-obsolete-variable-alias 'org-plantuml-executable-args 'org-plantuml-args
"Org 9.6")
(defconst org-latex-line-break-safe "\\\\[0pt]"
"Linebreak protecting the following [...].
Without \"[0pt]\" it would be interpreted as an optional argument to
the \\\\.
This constant, for example, makes the below code not err:
\\begin{tabular}{c|c}
[t] & s\\\\[0pt]
[I] & A\\\\[0pt]
[m] & kg
\\end{tabular}")
(make-obsolete 'org-latex-line-break-safe
"should not be used - it is not safe in all the scenarios."
"9.7")
(defun org-in-fixed-width-region-p ()
"Non-nil if point in a fixed-width region."
(save-match-data
(org-element-type-p (org-element-at-point) 'fixed-width)))
(eq 'fixed-width (org-element-type (org-element-at-point)))))
(make-obsolete 'org-in-fixed-width-region-p
"use `org-element' library"
"9.0")
(define-obsolete-variable-alias
'org-format-latex-options 'org-latex-preview-appearance-options "9.7")
(make-obsolete-variable
'org-format-latex-signal-error "no longer used" "9.7")
(define-obsolete-variable-alias
'org-format-latex-header 'org-latex-preview-preamble "9.7")
(define-obsolete-variable-alias
'org-preview-latex-default-process 'org-latex-preview-process-default "9.7")
(define-obsolete-variable-alias
'org-preview-latex-process-alist 'org-latex-preview-process-alist "9.7")
(define-obsolete-function-alias
'org-clear-latex-preview 'org-latex-preview-clear-overlays "9.7")
(make-obsolete
'org-place-formula-image "no longer used" "9.7")
(define-obsolete-function-alias
'org-latex-color-format 'org-latex-preview--format-color "9.7")
(define-obsolete-function-alias
'org-latex-color 'org-latex-preview--attr-color "9.7")
;; MathML related functions from org-latex-preview.el
(define-obsolete-variable-alias
'org-latex-to-mathml-jar-file 'org-mathml-converter-jar-file "9.7")
(define-obsolete-variable-alias
'org-latex-to-mathml-convert-command 'org-mathml-convert-command "9.7")
(define-obsolete-function-alias
'org-format-latex-mathml-available-p 'org-mathml-converter-available-p "9.7")
(define-obsolete-function-alias
'org-create-math-formula 'org-mathml-convert-latex "9.7")
;; FIXME: Unused; obsoleted; to be removed.
(defun org-format-latex-as-mathml (latex-frag latex-frag-type
prefix &optional dir)
(let* ((absprefix (expand-file-name prefix dir))
(print-length nil) (print-level nil)
(formula-id (concat
"formula-"
(sha1
(prin1-to-string
(list latex-frag
org-latex-to-mathml-convert-command)))))
(formula-cache (format "%s-%s.mathml" absprefix formula-id))
(formula-cache-dir (file-name-directory formula-cache)))
(unless (file-directory-p formula-cache-dir)
(make-directory formula-cache-dir t))
(unless (file-exists-p formula-cache)
(org-mathml-convert-latex latex-frag formula-cache))
(if (file-exists-p formula-cache)
;; Successful conversion. Return the link to MathML file.
(org-add-props
(format "[[file:%s]]" (file-relative-name formula-cache dir))
(list 'org-latex-src (replace-regexp-in-string "\"" "" latex-frag)
'org-latex-src-embed-type (if latex-frag-type
'paragraph 'character)))
;; Failed conversion. Return the LaTeX fragment verbatim
latex-frag)))
(make-obsolete #'org-format-latex-as-mathml "to be removed" "9.7")
;; FIXME: Unused; obsoleted; to be removed.
(defun org-dvipng-color (attr)
"Return a RGB color specification for dvipng."
(org-dvipng-color-format (face-attribute 'default attr nil)))
;; FIXME: Unused; obsoleted; to be removed.
(defun org-dvipng-color-format (color-name)
"Convert COLOR-NAME to a RGB color value for dvipng."
(apply #'format "rgb %s %s %s"
(mapcar 'org-latex-preview--normalize-color
(color-values color-name))))
(make-obsolete
'org-dvipng-color "to be removed" "9.7")
(make-obsolete
'org-dvipng-color-format "to be removed" "9.7")
;; FIXME: Unused; obsoleted; to be removed.
(defun org-normalize-color (value)
"Return string to be used as color value for an RGB component."
(format "%g" (/ value 65535.0)))
(make-obsolete 'org-normalize-color "to be removed" "9.7")
;; FIXME: Unused; obsoleted; to be removed.
(defcustom org-preview-latex-image-directory "ltximg/"
"Path to store latex preview images.
A relative path here creates many directories relative to the
processed Org files paths. An absolute path puts all preview
images at the same place."
:group 'org-latex
:version "26.1"
:package-version '(Org . "9.0")
:type 'string)
(make-obsolete-variable
'org-preview-latex-image-directory "replaced with org-persist" "9.7")
;; FIXME: Unused; obsoleted; to be removed.
(defun org-format-latex
(prefix &optional beg end dir overlays msg forbuffer processing-type)
"Replace LaTeX fragments with links to an image.
The function takes care of creating the replacement image.
Only consider fragments between BEG and END when those are
provided.
When optional argument OVERLAYS is non-nil, display the image on
top of the fragment instead of replacing it.
PROCESSING-TYPE is the conversion method to use, as a symbol.
Some of the options can be changed using the variable
`org-format-latex-options', which see."
(when (and overlays (fboundp 'clear-image-cache)) (clear-image-cache))
(unless (eq processing-type 'verbatim)
(let* ((math-regexp "\\$\\|\\\\[([]\\|^[ \t]*\\\\begin{[A-Za-z0-9*]+}")
(cnt 0)
checkdir-flag)
(goto-char (or beg (point-min)))
;; Optimize overlay creation: (info "(elisp) Managing Overlays").
(when (and overlays (memq processing-type '(dvipng imagemagick)))
(overlay-recenter (or end (point-max))))
(while (re-search-forward math-regexp end t)
(unless (and overlays
(eq (get-char-property (point) 'org-overlay-type)
'org-latex-overlay))
(let* ((context (org-element-context))
(type (org-element-type context)))
(when (memq type '(latex-environment latex-fragment))
(let ((block-type (eq type 'latex-environment))
(value (org-element-property :value context))
(beg (org-element-property :begin context))
(end (save-excursion
(goto-char (org-element-property :end context))
(skip-chars-backward " \r\t\n")
(point))))
(cond
((eq processing-type 'mathjax)
;; Prepare for MathJax processing.
(if (not (string-match "\\`\\$\\$?" value))
(goto-char end)
(delete-region beg end)
(if (string= (match-string 0 value) "$$")
(insert "\\[" (substring value 2 -2) "\\]")
(insert "\\(" (substring value 1 -1) "\\)"))))
((eq processing-type 'html)
(goto-char beg)
(delete-region beg end)
(insert (org-format-latex-as-html value)))
((assq processing-type org-preview-latex-process-alist)
;; Process to an image.
(cl-incf cnt)
(goto-char beg)
(let* ((processing-info
(cdr (assq processing-type org-preview-latex-process-alist)))
(face (face-at-point))
;; Get the colors from the face at point.
(fg
(let ((color (plist-get org-format-latex-options
:foreground)))
(if forbuffer
(cond
((eq color 'auto)
(face-attribute face :foreground nil 'default))
((eq color 'default)
(face-attribute 'default :foreground nil))
(t color))
color)))
(bg
(let ((color (plist-get org-format-latex-options
:background)))
(if forbuffer
(cond
((eq color 'auto)
(face-attribute face :background nil 'default))
((eq color 'default)
(face-attribute 'default :background nil))
(t color))
color)))
(hash (sha1 (prin1-to-string
(list org-format-latex-header
org-latex-default-packages-alist
org-latex-packages-alist
org-format-latex-options
forbuffer value fg bg))))
(imagetype (or (plist-get processing-info :image-output-type) "png"))
(absprefix (expand-file-name prefix dir))
(linkfile (format "%s_%s.%s" prefix hash imagetype))
(movefile (format "%s_%s.%s" absprefix hash imagetype))
(sep (and block-type "\n\n"))
(link (concat sep "[[file:" linkfile "]]" sep))
(options
(org-combine-plists
org-format-latex-options
`(:foreground ,fg :background ,bg))))
(when msg (message msg cnt))
(unless checkdir-flag ; Ensure the directory exists.
(setq checkdir-flag t)
(let ((todir (file-name-directory absprefix)))
(unless (file-directory-p todir)
(make-directory todir t))))
(unless (file-exists-p movefile)
(org-create-formula-image
value movefile options forbuffer processing-type))
(org-place-formula-image link block-type beg end value overlays movefile imagetype)))
((eq processing-type 'mathml)
;; Process to MathML.
(unless (org-format-latex-mathml-available-p)
(user-error "LaTeX to MathML converter not configured"))
(cl-incf cnt)
(when msg (message msg cnt))
(goto-char beg)
(delete-region beg end)
(insert (org-format-latex-as-mathml
value block-type prefix dir)))
(t
(error "Unknown conversion process %s for LaTeX fragments"
processing-type)))))))))))
;; FIXME: Unused; obsoleted; to be removed.
(defun org-place-formula-image (link block-type beg end value overlays movefile imagetype)
"Place an overlay from BEG to END showing MOVEFILE.
The overlay will be above BEG if OVERLAYS is non-nil."
(if overlays
(progn
(dolist (o (overlays-in beg end))
(when (eq (overlay-get o 'org-overlay-type)
'org-latex-overlay)
(delete-overlay o)))
(let ((ov (make-overlay beg end))
(imagetype (or (intern imagetype) 'png)))
(overlay-put ov 'org-overlay-type 'org-latex-overlay)
(overlay-put ov 'evaporate t)
(overlay-put ov
'modification-hooks
(list (lambda (o _flag _beg _end &optional _l)
(delete-overlay o))))
(overlay-put ov
'display
(list 'image :type imagetype :file movefile :ascent 'center)))
(goto-char end))
(delete-region beg end)
(insert
(org-add-props link
(list 'org-latex-src
(replace-regexp-in-string "\"" "" value)
'org-latex-src-embed-type
(if block-type 'paragraph 'character))))))
;; FIXME: Unused; obsoleted; to be removed.
(defun org-create-formula-image
(string tofile options buffer &optional processing-type)
"Create an image from LaTeX source using external processes.
The LaTeX STRING is saved to a temporary LaTeX file, then
converted to an image file by process PROCESSING-TYPE defined in
`org-preview-latex-process-alist'. A nil value defaults to
`org-preview-latex-default-process'.
The generated image file is eventually moved to TOFILE.
The OPTIONS argument controls the size, foreground color and
background color of the generated image.
When BUFFER non-nil, this function is used for LaTeX previewing.
Otherwise, it is used to deal with LaTeX snippets showed in
a HTML file."
(let* ((processing-type (or processing-type
org-preview-latex-default-process))
(processing-info
(cdr (assq processing-type org-preview-latex-process-alist)))
(programs (plist-get processing-info :programs))
(error-message (or (plist-get processing-info :message) ""))
(image-input-type (plist-get processing-info :image-input-type))
(image-output-type (plist-get processing-info :image-output-type))
(post-clean (or (plist-get processing-info :post-clean)
'(".dvi" ".xdv" ".pdf" ".tex" ".aux" ".log"
".svg" ".png" ".jpg" ".jpeg" ".out")))
(latex-header
(or (plist-get processing-info :latex-header)
(org-latex-make-preamble
(org-export-get-environment (org-export-get-backend 'latex))
org-format-latex-header
'snippet)))
(latex-compiler (plist-get processing-info :latex-compiler))
(tmpdir temporary-file-directory)
(texfilebase (make-temp-name
(expand-file-name "orgtex" tmpdir)))
(texfile (concat texfilebase ".tex"))
(image-size-adjust (or (plist-get processing-info :image-size-adjust)
'(1.0 . 1.0)))
(scale (* (if buffer (car image-size-adjust) (cdr image-size-adjust))
(or (plist-get options (if buffer :scale :html-scale)) 1.0)))
(dpi (* scale (if (and buffer (display-graphic-p)) (org--get-display-dpi) 140.0)))
(fg (or (plist-get options (if buffer :foreground :html-foreground))
"Black"))
(bg (or (plist-get options (if buffer :background :html-background))
"Transparent"))
(image-converter
(or (and (string= bg "Transparent")
(plist-get processing-info :transparent-image-converter))
(plist-get processing-info :image-converter)))
(log-buf (get-buffer-create "*Org Preview LaTeX Output*"))
(resize-mini-windows nil)) ;Fix Emacs flicker when creating image.
(dolist (program programs)
(org-check-external-command program error-message))
(if (eq fg 'default)
(setq fg (org-latex-color :foreground))
(setq fg (org-latex-color-format fg)))
(setq bg (cond
((eq bg 'default) (org-latex-color :background))
((string= bg "Transparent") nil)
(t (org-latex-color-format bg))))
;; Remove TeX \par at end of snippet to avoid trailing space.
(if (string-suffix-p string "\n")
(aset string (1- (length string)) ?%)
(setq string (concat string "%")))
(with-temp-file texfile
(insert latex-header)
(insert "\n\\begin{document}\n"
"\\definecolor{fg}{rgb}{" fg "}%\n"
(if bg
(concat "\\definecolor{bg}{rgb}{" bg "}%\n"
"\n\\pagecolor{bg}%\n")
"")
"\n{\\color{fg}\n"
string
"\n}\n"
"\n\\end{document}\n"))
(let* ((err-msg (format "Please adjust `%s' part of \
`org-preview-latex-process-alist'."
processing-type))
(image-input-file
(org-compile-file
texfile latex-compiler image-input-type err-msg log-buf))
(image-output-file
(org-compile-file
image-input-file image-converter image-output-type err-msg log-buf
`((?D . ,(shell-quote-argument (format "%s" dpi)))
(?S . ,(shell-quote-argument (format "%s" (/ dpi 140.0))))))))
(copy-file image-output-file tofile 'replace)
(dolist (e post-clean)
(when (file-exists-p (concat texfilebase e))
(delete-file (concat texfilebase e))))
image-output-file)))
;; FIXME: Unused; obsoleted; to be removed.
(defun org-html-format-latex (latex-frag processing-type info)
"Format a LaTeX fragment LATEX-FRAG into HTML.
PROCESSING-TYPE designates the tool used for conversion. It can
be `mathjax', `verbatim', `html', nil, t or symbols in
`org-preview-latex-process-alist', e.g., `dvipng', `dvisvgm' or
`imagemagick'. See `org-html-with-latex' for more information.
INFO is a plist containing export properties."
(let ((cache-relpath "") (cache-dir ""))
(unless (or (eq processing-type 'mathjax)
(eq processing-type 'html))
(let ((bfn (or (buffer-file-name)
(make-temp-name
(expand-file-name "latex" temporary-file-directory))))
(latex-header
(let ((header (plist-get info :latex-header)))
(and header
(concat (mapconcat
(lambda (line) (concat "#+LATEX_HEADER: " line))
(org-split-string header "\n")
"\n")
"\n")))))
(setq cache-relpath
(concat (file-name-as-directory org-preview-latex-image-directory)
(file-name-sans-extension
(file-name-nondirectory bfn)))
cache-dir (file-name-directory bfn))
;; Re-create LaTeX environment from original buffer in
;; temporary buffer so that dvipng/imagemagick can properly
;; turn the fragment into an image.
(setq latex-frag (concat latex-header latex-frag))))
(org-export-with-buffer-copy
:to-buffer (get-buffer-create " *Org HTML Export LaTeX*")
:drop-visibility t :drop-narrowing t :drop-contents t
(erase-buffer)
(insert latex-frag)
(org-format-latex cache-relpath nil nil cache-dir nil
"Creating LaTeX Image..." nil processing-type)
(buffer-string))))
(make-obsolete #'org-format-latex "to be removed" "9.7")
(make-obsolete #'org-create-formula-image "to be removed" "9.7")
(make-obsolete #'org-html-format-latex "to be removed" "9.7")
;; FIXME: Unused; obsoleted; to be removed.
(defun org-let (list &rest body) ;FIXME: So many kittens are suffering here.
(declare (indent 1) (obsolete cl-progv "2021"))
@ -1089,23 +576,6 @@ INFO is a plist containing export properties."
(define-obsolete-function-alias 'org--math-always-on
'org--math-p "9.7")
(defmacro org-no-popups (&rest body)
"Suppress popup windows and evaluate BODY."
`(let (pop-up-frames pop-up-windows)
,@body))
(make-obsolete 'org-no-popups "no longer used" "9.7")
(defun org-switch-to-buffer-other-window (&rest args)
"Switch to buffer in a second window on the current frame.
In particular, do not allow pop-up frames.
Returns the newly created buffer."
(let (pop-up-frames pop-up-windows)
(apply #'switch-to-buffer-other-window args)))
(make-obsolete 'org-switch-to-buffer-other-window "no longer used" "9.7")
(make-obsolete 'org-refresh-category-properties "no longer used" "9.7")
(make-obsolete 'org-refresh-effort-properties "no longer used" "9.7")
(defun org-compatible-face (inherits specs)
"Make a compatible face specification.
If INHERITS is an existing face and if the Emacs version supports
@ -1152,7 +622,7 @@ See `org-link-parameters' for documentation on the other parameters."
(defun org-table-recognize-table.el ()
"If there is a table.el table nearby, recognize it and move into it."
(when (org-at-table.el-p)
(forward-line 0)
(beginning-of-line)
(unless (or (looking-at org-table-dataline-regexp)
(not (looking-at org-table1-hline-regexp)))
(forward-line)
@ -1194,23 +664,13 @@ See `org-link-parameters' for documentation on the other parameters."
(org-unbracket-string "<" ">" s))
(make-obsolete 'org-remove-angle-brackets 'org-unbracket-string "9.0")
(defcustom org-capture-bookmark t
"When non-nil, add bookmark pointing at the last stored position when capturing."
:group 'org-capture
:version "24.3"
:type 'boolean)
(make-obsolete-variable
'org-capture-bookmark
"use `org-bookmark-names-plist' instead."
"9.7")
(defcustom org-publish-sitemap-file-entry-format "%t"
"Format string for site-map file entry.
You could use brackets to delimit on what part the link will be.
%t is the title.
%a is the author.
%d is the date."
%d is the date formatted using `org-publish-sitemap-date-format'."
:group 'org-export-publish
:type 'string)
(make-obsolete-variable
@ -1427,21 +887,21 @@ When optional argument ELEMENT is a parsed drawer, as returned by
When buffer positions BEG and END are provided, hide or show that
region as a drawer without further ado."
(declare (obsolete "use `org-hide-drawer-toggle' instead." "9.4"))
(if (and beg end) (org-fold-region beg end flag 'drawer)
(if (and beg end) (org-fold-region beg end flag (if (eq org-fold-core-style 'text-properties) 'drawer 'outline))
(let ((drawer
(or element
(and (save-excursion
(forward-line 0)
(beginning-of-line)
(looking-at-p "^[ \t]*:\\(\\(?:\\w\\|[-_]\\)+\\):[ \t]*$"))
(org-element-at-point)))))
(when (org-element-type-p drawer '(drawer property-drawer))
(let ((post (org-element-post-affiliated drawer)))
(when (memq (org-element-type drawer) '(drawer property-drawer))
(let ((post (org-element-property :post-affiliated drawer)))
(org-fold-region
(save-excursion (goto-char post) (line-end-position))
(save-excursion (goto-char (org-element-end drawer))
(save-excursion (goto-char (org-element-property :end drawer))
(skip-chars-backward " \t\n")
(line-end-position))
flag 'drawer)
flag (if (eq org-fold-core-style 'text-properties) 'drawer '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)))
@ -1465,7 +925,7 @@ an error. Return a non-nil value when toggling is successful."
(goto-char start)
(while (and (< (point) end)
(re-search-forward "^[ \t]*#\\+begin_?\
\\([^ \n]+\\)\\(\\([^\n]+\\)\\)?\n\\(\\(?:.\\|\n\\)+?\\)#\\+end_?\\1[ \t]*$" end t))
\\([^ \n]+\\)\\(\\([^\n]+\\)\\)?\n\\([^\000]+?\\)#\\+end_?\\1[ \t]*$" end t))
(save-excursion
(save-match-data
(goto-char (match-beginning 0))
@ -1673,15 +1133,6 @@ context. See the individual commands for more information."
(define-obsolete-function-alias 'ob-clojure-eval-with-babashka
#'ob-clojure-eval-with-cmd "9.7")
(define-obsolete-function-alias 'org-export-get-parent
'org-element-parent "9.7")
(define-obsolete-function-alias 'org-export-get-parent-element
'org-element-parent-element "9.7")
(define-obsolete-function-alias 'org-print-speed-command
'org--print-speed-command "9.7"
"Internal function. Subject of unannounced changes.")
;;;; Obsolete link types
(eval-after-load 'ol
@ -1932,7 +1383,7 @@ ELEMENT is the element at point."
;; Only in inline footnotes, within the definition.
(and (eq (org-element-property :type object) 'inline)
(< (save-excursion
(goto-char (org-element-begin object))
(goto-char (org-element-property :begin object))
(search-forward ":" nil t 2))
(point))))
(otherwise t))))
@ -1941,7 +1392,7 @@ ELEMENT is the element at point."
"Function used for `flyspell-generic-check-word-predicate'."
(if (org-at-heading-p)
;; At a headline or an inlinetask, check title only.
(and (save-excursion (forward-line 0)
(and (save-excursion (beginning-of-line)
(and (let ((case-fold-search t))
(not (looking-at-p "\\*+ END[ \t]*$")))
(let ((case-fold-search nil))
@ -1953,19 +1404,19 @@ ELEMENT is the element at point."
;; Ignore checks in code, verbatim and others.
(org--flyspell-object-check-p (org-element-at-point-no-context)))
(let* ((element (org-element-at-point-no-context))
(post-affiliated (org-element-post-affiliated element)))
(post-affiliated (org-element-property :post-affiliated element)))
(cond
;; Ignore checks in all affiliated keywords but captions.
((< (point) post-affiliated)
(and (save-excursion
(forward-line 0)
(beginning-of-line)
(let ((case-fold-search t)) (looking-at "[ \t]*#\\+CAPTION:")))
(> (point) (match-end 0))
(org--flyspell-object-check-p element)))
;; Ignore checks in LOGBOOK (or equivalent) drawer.
((let ((log (org-log-into-drawer)))
(and log
(let ((drawer (org-element-lineage element 'drawer)))
(let ((drawer (org-element-lineage element '(drawer))))
(and drawer
(org-string-equal-ignore-case
log (org-element-property :drawer-name drawer))))))
@ -1979,7 +1430,7 @@ ELEMENT is the element at point."
(save-excursion
(end-of-line)
(skip-chars-forward " \r\t\n")
(< (point) (org-element-end element)))))
(< (point) (org-element-property :end element)))))
;; Arbitrary list of keywords where checks are meaningful.
;; Make sure point is on the value part of the element.
(keyword
@ -1991,8 +1442,8 @@ ELEMENT is the element at point."
;; table rows (after affiliated keywords) but some objects
;; must not be affected.
((paragraph table-row verse-block)
(let ((cbeg (org-element-contents-begin element))
(cend (org-element-contents-end element)))
(let ((cbeg (org-element-property :contents-begin element))
(cend (org-element-property :contents-end element)))
(and cbeg (>= (point) cbeg) (< (point) cend)
(org--flyspell-object-check-p element))))))))))
(put 'org-mode 'flyspell-mode-predicate 'org-mode-flyspell-verify)
@ -2127,7 +1578,7 @@ key."
"Run `org-back-to-heading' when in org-mode."
(if (derived-mode-p 'org-mode)
(progn
(forward-line 0)
(beginning-of-line)
(or (org-at-heading-p (not invisible-ok))
(let (found)
(save-excursion

View File

@ -1,6 +1,6 @@
;;; org-crypt.el --- Public Key Encryption for Org Entries -*- lexical-binding: t; -*-
;;
;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
;; Author: John Wiegley <johnw@gnu.org>
@ -71,18 +71,16 @@
(defvar epg-context)
(declare-function org-back-over-empty-lines "org" ())
(declare-function org-current-level "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 element))
(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-fold-subtree "org-fold" (flag))
(declare-function org-make-tags-matcher "org" (match &optional only-local-tags))
(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))
(declare-function org-cycle-set-startup-visibility "org-cycle" ())
(defgroup org-crypt nil
"Org Crypt."
@ -115,16 +113,16 @@ This setting can be overridden in the CRYPTKEY property."
(defcustom org-crypt-disable-auto-save 'ask
"What org-decrypt should do if `auto-save-mode' is enabled.
t : Disable `auto-save-mode' for the current buffer
t : Disable auto-save-mode for the current buffer
prior to decrypting an entry.
nil : Leave `auto-save-mode' enabled.
nil : Leave auto-save-mode enabled.
This may cause data to be written to disk unencrypted!
`ask' : Ask user whether or not to disable `auto-save-mode'
`ask' : Ask user whether or not to disable auto-save-mode
for the current buffer.
`encrypt': Leave `auto-save-mode' enabled for the current buffer,
`encrypt': Leave auto-save-mode enabled for the current buffer,
but automatically re-encrypt all decrypted entries
*before* auto-saving.
NOTE: This only works for entries which have a tag
@ -167,7 +165,7 @@ and END are buffer positions delimiting the encrypted area."
(cons start (line-beginning-position 2)))))))))
(defun org-crypt-check-auto-save ()
"Check whether `auto-save-mode' is enabled for the current buffer.
"Check whether auto-save-mode is enabled for the current buffer.
`auto-save-mode' may cause leakage when decrypting entries, so
check whether it's enabled, and decide what to do about it.
@ -179,7 +177,7 @@ See `org-crypt-disable-auto-save'."
(eq org-crypt-disable-auto-save t)
(and
(eq org-crypt-disable-auto-save 'ask)
(y-or-n-p "`org-decrypt': auto-save-mode may cause leakage. Disable it for current buffer? ")))
(y-or-n-p "org-decrypt: auto-save-mode may cause leakage. Disable it for current buffer? ")))
(message "org-decrypt: Disabling auto-save-mode for %s"
(or (buffer-file-name) (current-buffer)))
;; The argument to auto-save-mode has to be "-1", since
@ -246,13 +244,12 @@ Assume `epg-context' is set."
;; contents in the buffer.
(error
(insert contents)
(error "%s" (error-message-string err)))))
(error (error-message-string err)))))
(when folded-heading
(goto-char folded-heading)
(org-fold-subtree t))
nil)))))
(defvar org-outline-regexp-bol)
;;;###autoload
(defun org-decrypt-entry ()
"Decrypt the content of the current headline."
@ -268,44 +265,23 @@ Assume `epg-context' is set."
(save-excursion
(org-previous-visible-heading 1)
(point))))
(level (org-current-level))
(encrypted-text (org-crypt--encrypted-text beg end))
(decrypted-text
(decode-coding-string
(epg-decrypt-string epg-context encrypted-text)
'utf-8))
origin-marker)
'utf-8)))
;; Delete region starting just before point, because the
;; outline property starts at the \n of the heading.
(delete-region (1- (point)) end)
(setq origin-marker (point-marker))
(if (string-match (org-headline-re level) decrypted-text)
;; If decrypted text contains other headings with levels
;; below LEVEL, adjust the subtree.
(let ((start 0) (min-level level))
(while (string-match (org-headline-re level) decrypted-text start)
(setq min-level (min min-level (1- (length (match-string 0 decrypted-text))))
start (match-end 0)))
(insert "\n"
(replace-regexp-in-string
org-outline-regexp-bol
(concat (make-string (1+ (- level min-level)) ?*) "\\&")
decrypted-text)))
;; 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)))
;; Apply initial visibility.
(save-restriction
(narrow-to-region origin-marker (point))
(set-marker origin-marker nil)
(org-cycle-set-startup-visibility))
;; ... but keep the previous folded state.
;; 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-fold-subtree t))

View File

@ -1,6 +1,6 @@
;;; org-ctags.el --- Integrate Emacs "tags" Facility with Org -*- lexical-binding: t; -*-
;; Copyright (C) 2007-2024 Free Software Foundation, Inc.
;; Copyright (C) 2007-2023 Free Software Foundation, Inc.
;; Author: Paul Sexton <eeeickythump@gmail.com>
;; Keywords: org, wp
@ -28,7 +28,7 @@
;;
;; Allows Org mode to make use of the Emacs `etags' system. Defines
;; tag destinations in Org files as any text between <<double angled
;; brackets>>. This allows the tags-generation program `exuberant
;; brackets>>. This allows the tags-generation program `exuberant
;; ctags' to parse these files and create tag tables that record where
;; these destinations are found. Plain [[links]] in org mode files
;; which do not have <<matching destinations>> within the same file
@ -66,7 +66,7 @@
;; search the entire text of the current buffer for 'tag'.
;;
;; This behavior can be modified by changing the value of
;; ORG-CTAGS-OPEN-LINK-FUNCTIONS. For example, I have the following in my
;; ORG-CTAGS-OPEN-LINK-FUNCTIONS. For example I have the following in my
;; .emacs, which describes the same behavior as the above paragraph with
;; one difference:
;;
@ -149,7 +149,7 @@
(defvar org-ctags-enabled-p t
"Activate ctags support in org mode?")
(defvar org-ctags-tag-regexp "/<<([^<>]+)>>/\\1/d,definition/"
(defvar org-ctags-tag-regexp "/<<([^>]+)>>/\\1/d,definition/"
"Regexp expression used by ctags external program.
The regexp matches tag destinations in Org files.
Format is: /REGEXP/TAGNAME/FLAGS,TAGTYPE/
@ -484,11 +484,11 @@ its subdirectories contain large numbers of taggable files."
(setq exitcode
(shell-command
(format (concat "%s --langdef=orgmode --langmap=orgmode:.org "
"--regex-orgmode=\"%s\" -f \"%s\" -e -R %s")
"--regex-orgmode=\"%s\" -f \"%s\" -e -R \"%s\"")
org-ctags-path-to-ctags
org-ctags-tag-regexp
(expand-file-name (concat dir-name "/TAGS"))
(expand-file-name (concat (shell-quote-argument dir-name) "/*")))))
(expand-file-name (concat dir-name "/*")))))
(cond
((eql 0 exitcode)
(setq-local org-ctags-tag-list
@ -506,11 +506,12 @@ its subdirectories contain large numbers of taggable files."
(defun org-ctags-find-tag-interactive ()
"Prompt for the name of a tag, with autocompletion, then visit the named tag.
Uses `ido-mode' if available.
If the user enters a string that does not match an existing tag, create
a new topic."
(interactive)
(let* ((tag (completing-read "Topic: " org-ctags-tag-list
nil 'confirm nil 'org-ctags-find-tag-history)))
(let* ((tag (ido-completing-read "Topic: " org-ctags-tag-list
nil 'confirm nil 'org-ctags-find-tag-history)))
(when tag
(cond
((member tag org-ctags-tag-list)

View File

@ -1,8 +1,8 @@
;;; org-cycle.el --- Visibility cycling of Org entries -*- lexical-binding: t; -*-
;;
;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
;;
;; Maintainer: Ihor Radchenko <yantar92 at posteo dot net>
;; Maintainer: Ihor Radchenko <yantar92 at gmail dot com>
;; Keywords: folding, visibility cycling, invisible text
;; URL: https://orgmode.org
;;
@ -35,10 +35,9 @@
(require 'org-macs)
(require 'org-fold)
(declare-function org-element-type-p "org-element-ast" (node types))
(declare-function org-element-property "org-element-ast" (property node))
(declare-function org-element-post-affiliated "org-element" (node))
(declare-function org-element-lineage "org-element-ast" (datum &optional types with-self))
(declare-function org-element-type "org-element" (element))
(declare-function org-element-property "org-element" (property element))
(declare-function org-element-lineage "org-element" (datum &optional types with-self))
(declare-function org-element-at-point "org-element" (&optional pom cached-only))
(declare-function org-display-inline-images "org" (&optional include-linked refresh beg end))
(declare-function org-get-tags "org" (&optional pos local fontify))
@ -116,7 +115,6 @@ than its value."
(const :tag "No limit" nil)
(integer :tag "Maximum level")))
(defvaralias 'org-hide-block-startup 'org-cycle-hide-block-startup)
(defcustom org-cycle-hide-block-startup nil
"Non-nil means entering Org mode will fold all blocks.
This can also be set in on a per-file basis with
@ -127,7 +125,6 @@ This can also be set in on a per-file basis with
:group 'org-cycle
:type 'boolean)
(defvaralias 'org-hide-drawer-startup 'org-cycle-hide-drawer-startup)
(defcustom org-cycle-hide-drawer-startup t
"Non-nil means entering Org mode will fold all drawers.
This can also be set in on a per-file basis with
@ -203,7 +200,6 @@ Special case: when 0, never leave empty lines in collapsed view."
:type 'integer)
(put 'org-cycle-separator-lines 'safe-local-variable 'integerp)
(defvaralias 'org-pre-cycle-hook 'org-cycle-pre-hook)
(defcustom org-cycle-pre-hook nil
"Hook that is run before visibility cycling is happening.
The function(s) in this hook must accept a single argument which indicates
@ -244,7 +240,6 @@ normal outline commands like `show-all', but not with the cycling commands."
:package-version '(Org . "9.6")
:type 'boolean)
(defvaralias 'org-tab-first-hook 'org-cycle-tab-first-hook)
(defvar org-cycle-tab-first-hook nil
"Hook for functions to attach themselves to TAB.
See `org-ctrl-c-ctrl-c-hook' for more information.
@ -340,10 +335,6 @@ same as `S-TAB') also when called without prefix argument."
(and org-cycle-level-after-item/entry-creation
(or (org-cycle-level)
(org-cycle-item-indentation))))
(when (and org-cycle-max-level
(or (not (integerp org-cycle-max-level))
(< org-cycle-max-level 1)))
(user-error "`org-cycle-max-level' must be a positive integer"))
(let* ((limit-level
(or org-cycle-max-level
(and (boundp 'org-inlinetask-min-level)
@ -397,8 +388,8 @@ same as `S-TAB') also when called without prefix argument."
((org-fold-hide-drawer-toggle nil t element))
;; Table: enter it or move to the next field.
((and (org-match-line "[ \t]*[|+]")
(org-element-lineage element 'table t))
(if (and (org-element-type-p element 'table)
(org-element-lineage element '(table) t))
(if (and (eq 'table (org-element-type element))
(eq 'table.el (org-element-property :type element)))
(message (substitute-command-keys "\\<org-mode-map>\
Use `\\[org-edit-special]' to edit table.el tables"))
@ -413,8 +404,8 @@ Use `\\[org-edit-special]' to edit table.el tables"))
t)))
(and item
(= (line-beginning-position)
(org-element-post-affiliated
item)))))
(org-element-property :post-affiliated
item)))))
(org-match-line org-outline-regexp))
(or (bolp) (not (eq org-cycle-emulate-tab 'exc-hl-bol))))
(org-cycle-internal-local))
@ -430,7 +421,7 @@ Use `\\[org-edit-special]' to edit table.el tables"))
(call-interactively (global-key-binding (kbd "TAB"))))
((or (eq org-cycle-emulate-tab t)
(and (memq org-cycle-emulate-tab '(white whitestart))
(save-excursion (forward-line 0) (looking-at "[ \t]*"))
(save-excursion (beginning-of-line 1) (looking-at "[ \t]*"))
(or (and (eq org-cycle-emulate-tab 'white)
(= (match-end 0) (line-end-position)))
(and (eq org-cycle-emulate-tab 'whitestart)
@ -489,7 +480,7 @@ Use `\\[org-edit-special]' to edit table.el tables"))
(save-excursion
(if (org-at-item-p)
(progn
(forward-line 0)
(beginning-of-line)
(setq struct (org-list-struct))
(setq eoh (line-end-position))
(setq eos (org-list-get-item-end-before-blank (point) struct))
@ -511,16 +502,16 @@ Use `\\[org-edit-special]' to edit table.el tables"))
(save-excursion
(org-list-search-forward (org-item-beginning-re) eos t))))))
;; Determine end invisible part of buffer (EOL)
(forward-line 1)
(beginning-of-line 2)
(if (eq org-fold-core-style 'text-properties)
(while (and (not (eobp)) ;this is like `next-line'
(org-fold-folded-p (1- (point))))
(goto-char (org-fold-next-visibility-change nil nil t))
(and (eolp) (forward-line 1)))
(and (eolp) (beginning-of-line 2)))
(while (and (not (eobp)) ;this is like `next-line'
(get-char-property (1- (point)) 'invisible))
(goto-char (next-single-char-property-change (point) 'invisible))
(and (eolp) (forward-line 1))))
(and (eolp) (beginning-of-line 2))))
(setq eol (point)))
;; Find out what to do next and set `this-command'
(cond
@ -554,7 +545,7 @@ Use `\\[org-edit-special]' to edit table.el tables"))
(save-excursion
(org-back-to-heading)
(while (org-list-search-forward (org-item-beginning-re) eos t)
(forward-line 0)
(beginning-of-line 1)
(let* ((struct (org-list-struct))
(prevs (org-list-prevs-alist struct))
(end (org-list-get-bottom-point struct)))
@ -619,7 +610,7 @@ With a numeric prefix, show all headlines up to that level."
(cond
;; `fold' is technically not allowed value, but it is often
;; intuitively tried by users by analogy with #+STARTUP: fold.
((memq org-startup-folded '(t fold overview))
((memq org-startup-folded '(t fold))
(org-cycle-overview))
((eq org-startup-folded 'content)
(org-cycle-content))
@ -647,21 +638,20 @@ With a numeric prefix, show all headlines up to that level."
"Switch subtree visibility according to VISIBILITY property."
(interactive)
(let ((regexp (org-re-property "VISIBILITY")))
(save-excursion
(goto-char (point-min))
(org-with-point-at 1
(while (re-search-forward regexp nil t)
(let ((state (match-string 3)))
(let ((state (match-string 3)))
(if (not (org-at-property-p)) (outline-next-heading)
(save-excursion
(org-back-to-heading t)
(org-fold-subtree t)
(pcase state
("folded"
("folded"
(org-fold-subtree t))
("children"
("children"
(org-fold-show-hidden-entry)
(org-fold-show-children))
("content"
("content"
;; Newline before heading will be outside the
;; narrowing. Make sure that it is revealed.
(org-fold-heading nil)
@ -669,9 +659,10 @@ With a numeric prefix, show all headlines up to that level."
(save-restriction
(org-narrow-to-subtree)
(org-cycle-content))))
((or "all" "showall")
((or "all" "showall")
(org-fold-show-subtree))
(_ nil)))))))))
(_ nil)))
(org-end-of-subtree t)))))))
(defun org-cycle-overview ()
"Switch to overview mode, showing only top-level headlines."
@ -696,7 +687,7 @@ With a numeric prefix, show all headlines up to that level."
(defun org-cycle-content (&optional arg)
"Show all headlines in the buffer, like a table of contents.
With numerical argument ARG, show content up to level ARG."
With numerical argument N, show content up to level N."
(interactive "p")
(org-fold-show-all '(headings))
(save-excursion
@ -718,9 +709,7 @@ With numerical argument ARG, show content up to level ARG."
"Temporarily store scroll position to restore.")
(defun org-cycle-optimize-window-after-visibility-change (state)
"Adjust the window after a change in outline visibility.
This function is the default value of the hook `org-cycle-hook'.
STATE is the current outline visibility state. It should be one of
symbols `content', `all', `folded', `children', or `subtree'."
This function is the default value of the hook `org-cycle-hook'."
(when (get-buffer-window (current-buffer))
(let ((repeat (eq last-command this-command)))
(unless repeat
@ -806,9 +795,7 @@ STATE should be one of the symbols listed in the docstring of
(defun org-cycle-display-inline-images (state)
"Auto display inline images under subtree when cycling.
It works when `org-cycle-inline-images-display' is non-nil.
STATE is the current outline visibility state. It should be one of
symbols `content', `all', `folded', `children', or `subtree'."
It works when `org-cycle-inline-images-display' is non-nil."
(when org-cycle-inline-images-display
(pcase state
('children

View File

@ -1,6 +1,6 @@
;;; org-datetree.el --- Create date entries in a tree -*- lexical-binding: t; -*-
;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
;; Keywords: outlines, hypermedia, calendar, wp
@ -198,9 +198,9 @@ inserted into the buffer."
(unless (bolp) (insert "\n"))
(org-datetree-insert-line year month day insert))
((= (string-to-number (match-string 1)) (or day month year))
(forward-line 0))
(beginning-of-line))
(t
(forward-line 0)
(beginning-of-line)
(org-datetree-insert-line year month day insert)))))
(defun org-datetree-insert-line (year &optional month day text)
@ -222,11 +222,11 @@ inserted into the buffer."
(save-excursion
(insert "\n")
(org-indent-line)
(org-insert-timestamp
(org-insert-time-stamp
(org-encode-time 0 0 0 day month year)
nil
(eq org-datetree-add-timestamp 'inactive))))
(forward-line 0))
(beginning-of-line))
(defun org-datetree-file-entry-under (txt d)
"Insert a node TXT into the date tree under date D."

View File

@ -1,6 +1,6 @@
;;; org-duration.el --- Library handling durations -*- lexical-binding: t; -*-
;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
;; Copyright (C) 2017-2023 Free Software Foundation, Inc.
;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
;; Keywords: outlines, hypermedia, calendar, wp

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
;;; org-entities.el --- Support for Special Entities -*- lexical-binding: t; -*-
;; Copyright (C) 2010-2024 Free Software Foundation, Inc.
;; Copyright (C) 2010-2023 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik@gmail.com>,
;; Ulf Stegemann <ulf at zeitform dot de>
@ -29,7 +29,6 @@
(require 'org-macs)
(org-assert-version)
(require 'seq) ; Emacs 27 does not preload seq.el; for `seq-every-p'.
(declare-function org-mode "org" ())
(declare-function org-toggle-pretty-entities "org" ())
@ -42,19 +41,14 @@
(defun org-entities--user-safe-p (v)
"Non-nil if V is a safe value for `org-entities-user'."
(cond
((not v) t)
((listp v)
(seq-every-p
(lambda (e)
(pcase e
(`(,(and (pred stringp)
(pred (string-match-p "\\`[a-zA-Z][a-zA-Z0-9]*\\'")))
,(pred stringp) ,(pred booleanp) ,(pred stringp)
,(pred stringp) ,(pred stringp) ,(pred stringp))
t)
(_ nil)))
v))))
(pcase v
(`nil t)
(`(,(and (pred stringp)
(pred (string-match-p "\\`[a-zA-Z][a-zA-Z0-9]*\\'")))
,(pred stringp) ,(pred booleanp) ,(pred stringp)
,(pred stringp) ,(pred stringp) ,(pred stringp))
t)
(_ nil)))
(defcustom org-entities-user nil
"User-defined entities used in Org to produce special characters.

View File

@ -1,6 +1,6 @@
;;; org-faces.el --- Face definitions -*- lexical-binding: t; -*-
;; Copyright (C) 2004-2024 Free Software Foundation, Inc.
;; Copyright (C) 2004-2023 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
;; Keywords: outlines, hypermedia, calendar, wp
@ -108,7 +108,7 @@ color of the frame."
"Face used for drawers."
:group 'org-faces)
(defface org-property-value '((t :inherit default))
(defface org-property-value nil
"Face used for the value of a property."
:group 'org-faces)
@ -389,10 +389,6 @@ changes."
"Face used for tables."
:group 'org-faces)
(defface org-table-row '((t :inherit org-table))
"Face used to fontify whole table rows (including newlines and indentation)."
:group 'org-faces)
(defface org-table-header '((t :inherit org-table
:background "LightGray"
:foreground "Black"))

View File

@ -1,6 +1,6 @@
;;; org-feed.el --- Add RSS feed items to Org files -*- lexical-binding: t; -*-
;;
;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
;;
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
;; Keywords: outlines, hypermedia, calendar, wp
@ -475,7 +475,7 @@ This will find DRAWER and extract the alist."
(goto-char pos)
(let ((end (save-excursion (org-end-of-subtree t t))))
(if (re-search-forward
(concat "^[ \t]*:" drawer ":[ \t]*\n\\(\\(?:.\\|\n\\)*?\\)\n[ \t]*:END:")
(concat "^[ \t]*:" drawer ":[ \t]*\n\\([^\000]*?\\)\n[ \t]*:END:")
end t)
(read (match-string 1))
nil))))
@ -495,7 +495,7 @@ This will find DRAWER and extract the alist."
(match-beginning 0)))))
(outline-next-heading)
(insert " :" drawer ":\n :END:\n")
(forward-line -1))
(beginning-of-line 0))
(insert (pp-to-string status)))))
(defun org-feed-add-items (pos entries)
@ -508,7 +508,7 @@ This will find DRAWER and extract the alist."
(setq level (org-get-valid-level (length (match-string 1)) 1))
(org-end-of-subtree t t)
(skip-chars-backward " \t\n")
(forward-line 1)
(beginning-of-line 2)
(setq pos (point))
(while (setq entry (pop entries))
(org-paste-subtree level entry 'yank))
@ -565,7 +565,7 @@ If that property is already present, nothing changes."
(let ((v (plist-get entry (intern (concat ":" name)))))
(save-excursion
(save-match-data
(forward-line 0)
(beginning-of-line)
(if (looking-at
(concat "^\\([ \t]*\\)%" name "[ \t]*$"))
(org-feed-make-indented-block
@ -633,7 +633,7 @@ containing the properties `:guid' and `:item-full-text'."
end (and (re-search-forward "</item>" nil t)
(match-beginning 0)))
(setq item (buffer-substring beg end)
guid (if (string-match "<guid\\>.*?>\\(\\(?:.\\|\n\\)*?\\)</guid>" item)
guid (if (string-match "<guid\\>.*?>\\([^\000]*?\\)</guid>" item)
(xml-substitute-special (match-string-no-properties 1 item))))
(setq entry (list :guid guid :item-full-text item))
(push entry entries)
@ -647,7 +647,7 @@ containing the properties `:guid' and `:item-full-text'."
(with-temp-buffer
(insert (plist-get entry :item-full-text))
(goto-char (point-min))
(while (re-search-forward "<\\([a-zA-Z]+\\>\\).*?>\\(\\(?:.\\|\n\\)*?\\)</\\1>"
(while (re-search-forward "<\\([a-zA-Z]+\\>\\).*?>\\([^\000]*?\\)</\\1>"
nil t)
(setq entry (plist-put entry
(intern (concat ":" (match-string 1)))

View File

@ -1,8 +1,8 @@
;;; org-fold-core.el --- Folding buffer text -*- lexical-binding: t; -*-
;;
;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
;;
;; Author: Ihor Radchenko <yantar92 at posteo dot net>
;; Author: Ihor Radchenko <yantar92 at gmail dot com>
;; Keywords: folding, invisible text
;; URL: https://orgmode.org
;;
@ -280,13 +280,12 @@
;;; Customization
(defcustom org-fold-core-style (if (version< emacs-version "29")
'text-properties
'overlays)
(defcustom org-fold-core-style 'text-properties
"Internal implementation detail used to hide folded text.
Can be either `text-properties' or `overlays'.
The former is faster on large files in Emacs <29, while the latter is
generally less error-prone with regard to third-party packages.
The former is faster on large files, while the latter is generally
less error-prone with regard to third-party packages that haven't yet
adapted to the new folding implementation.
Important: This variable must be set before loading Org."
:group 'org
@ -381,9 +380,6 @@ The following properties are known:
`buffer-invisibility-spec' will be used as is.
Note that changing this property from nil to t may
clear the setting in `buffer-invisibility-spec'.
- :font-lock :: non-nil means that newlines after the fold should
be re-fontified upon folding/unfolding. See
`org-activate-folds'.
- :alias :: a list of aliases for the SPEC-SYMBOL.
- :fragile :: Must be a function accepting two arguments.
Non-nil means that changes in region may cause
@ -428,7 +424,7 @@ Return nil when there is no matching folding spec."
(unless org-fold-core--spec-symbols
(dolist (spec (org-fold-core-folding-spec-list))
(push (cons spec spec) org-fold-core--spec-symbols)
(dolist (alias (cdr (assq :alias (assq spec org-fold-core--specs))))
(dolist (alias (assq :alias (assq spec org-fold-core--specs)))
(push (cons alias spec) org-fold-core--spec-symbols))))
(alist-get spec-or-alias org-fold-core--spec-symbols)))
@ -437,7 +433,7 @@ Return nil when there is no matching folding spec."
(org-fold-core-get-folding-spec-from-alias spec-or-alias))
(defsubst org-fold-core--check-spec (spec-or-alias)
"Throw an error if SPEC-OR-ALIAS is not in `org-fold-core-folding-spec-list'."
"Throw an error if SPEC-OR-ALIAS is not in `org-fold-core--spec-priority-list'."
(unless (org-fold-core-folding-spec-p spec-or-alias)
(error "%s is not a valid folding spec" spec-or-alias)))
@ -506,34 +502,26 @@ hanging around."
;; different buffer. This can happen, for example, when
;; org-capture copies local variables into *Capture* buffer.
(setq buffers (list (current-buffer)))
(let ((all-buffers (buffer-local-value
'org-fold-core--indirect-buffers
(or (buffer-base-buffer) (current-buffer)))))
(dolist (buf (cons (or (buffer-base-buffer) (current-buffer))
(buffer-local-value 'org-fold-core--indirect-buffers (or (buffer-base-buffer) (current-buffer)))))
(if (buffer-live-p buf)
(push buf buffers)
(dolist (spec (org-fold-core-folding-spec-list))
(when (and (not (org-fold-core-get-folding-spec-property spec :global))
(gethash (cons buf spec) org-fold-core--property-symbol-cache))
;; Make sure that dead-properties variable can be passed
;; as argument to `remove-text-properties'.
(push t dead-properties)
(push (gethash (cons buf spec) org-fold-core--property-symbol-cache)
dead-properties)))))
(when dead-properties
(with-current-buffer (or (buffer-base-buffer) (current-buffer))
(setq-local org-fold-core--indirect-buffers
(seq-filter #'buffer-live-p all-buffers))))))
(dolist (buf (cons (or (buffer-base-buffer) (current-buffer))
(buffer-local-value 'org-fold-core--indirect-buffers (or (buffer-base-buffer) (current-buffer)))))
(if (buffer-live-p buf)
(push buf buffers)
(dolist (spec (org-fold-core-folding-spec-list))
(when (and (not (org-fold-core-get-folding-spec-property spec :global))
(gethash (cons buf spec) org-fold-core--property-symbol-cache))
;; Make sure that dead-properties variable can be passed
;; as argument to `remove-text-properties'.
(push t dead-properties)
(push (gethash (cons buf spec) org-fold-core--property-symbol-cache)
dead-properties))))))
(dolist (buf buffers)
(with-current-buffer buf
(when dead-properties
(with-silent-modifications
(save-restriction
(widen)
(remove-text-properties
(point-min) (point-max)
dead-properties))))
(with-silent-modifications
(save-restriction
(widen)
(remove-text-properties
(point-min) (point-max)
dead-properties)))
,@body))))
;; This is the core function used to fold text in buffers. We use
@ -557,10 +545,7 @@ and the setup appears to be created for different buffer,
copy the old invisibility state into new buffer-local text properties,
unless RETURN-ONLY is non-nil."
(if (eq org-fold-core-style 'overlays)
(or (gethash (cons 'global spec) org-fold-core--property-symbol-cache)
(puthash (cons 'global spec)
(org-fold-core-get-folding-property-symbol spec nil 'global)
org-fold-core--property-symbol-cache))
(org-fold-core-get-folding-property-symbol spec nil 'global)
(let* ((buf (or buffer (current-buffer))))
;; Create unique property symbol for SPEC in BUFFER
(let ((local-prop (or (gethash (cons buf spec) org-fold-core--property-symbol-cache)
@ -640,10 +625,6 @@ unless RETURN-ONLY is non-nil."
text-property-default-nonsticky
full-prop-list))))))))))))))
(defun org-fold-core--update-buffer-folds ()
"Copy folding state in a new buffer with text copied from old buffer."
(org-fold-core--property-symbol-get-create (car (org-fold-core-folding-spec-list))))
(defun org-fold-core-decouple-indirect-buffer-folds ()
"Copy and decouple folding state in a newly created indirect buffer.
This function is mostly intended to be used in
@ -651,7 +632,7 @@ This function is mostly intended to be used in
(when (and (buffer-base-buffer)
(eq org-fold-core-style 'text-properties)
(not (memql 'ignore-indirect org-fold-core--optimise-for-huge-buffers)))
(org-fold-core--update-buffer-folds)))
(org-fold-core--property-symbol-get-create (car (org-fold-core-folding-spec-list)))))
;;; API
@ -794,19 +775,16 @@ corresponding folding spec (if the text is folded using that spec)."
(when (and spec (not (eq spec 'all))) (org-fold-core--check-spec spec))
(org-with-point-at pom
(cond
((or (null spec) (eq spec 'all))
(catch :single-spec
(let ((result))
(dolist (lspec (org-fold-core-folding-spec-list))
(let ((val (if (eq org-fold-core-style 'text-properties)
(get-text-property (point) (org-fold-core--property-symbol-get-create lspec nil t))
(get-char-property (point) (org-fold-core--property-symbol-get-create lspec nil t)))))
(when (and val (null spec)) (throw :single-spec val))
(when val (push val result))))
(reverse result))))
(t (if (eq org-fold-core-style 'text-properties)
(get-text-property (point) (org-fold-core--property-symbol-get-create spec nil t))
(get-char-property (point) (org-fold-core--property-symbol-get-create spec nil t))))))))
((eq spec 'all)
(let ((result))
(dolist (spec (org-fold-core-folding-spec-list))
(let ((val (get-char-property (point) (org-fold-core--property-symbol-get-create spec nil t))))
(when val (push val result))))
(reverse result)))
((null spec)
(let ((result (get-char-property (point) 'invisible)))
(when (org-fold-core-folding-spec-p result) result)))
(t (get-char-property (point) (org-fold-core--property-symbol-get-create spec nil t)))))))
(defun org-fold-core-get-folding-specs-in-region (beg end)
"Get all folding specs in region from BEG to END."
@ -918,19 +896,14 @@ Search backwards when PREVIOUS-P is non-nil."
(unless spec-or-alias
(setq spec-or-alias (org-fold-core-folding-spec-list)))
(setq pos (or pos (point)))
(let ((limit (or limit (if previous-p (point-min) (point-max)))))
(catch :limit
(dolist (prop (mapcar
(lambda (el)
(org-fold-core--property-symbol-get-create el nil t))
spec-or-alias))
(when (= limit pos) (throw :limit limit))
(setq
limit
(if previous-p
(previous-single-char-property-change pos prop nil limit)
(next-single-char-property-change pos prop nil limit))))
limit)))
(apply (if previous-p
#'max
#'min)
(mapcar (if previous-p
(lambda (prop) (max (or limit (point-min)) (previous-single-char-property-change pos prop nil (or limit (point-min)))))
(lambda (prop) (next-single-char-property-change pos prop nil (or limit (point-max)))))
(mapcar (lambda (el) (org-fold-core--property-symbol-get-create el nil t))
spec-or-alias))))
(defun org-fold-core-previous-folding-state-change (&optional spec-or-alias pos limit)
"Call `org-fold-core-next-folding-state-change' searching backwards."
@ -1011,24 +984,6 @@ WITH-MARKERS must be nil when RELATIVE is non-nil."
;;;;; Region visibility
(defvar org-fold-core--keep-overlays nil
"When non-nil, `org-fold-core-region' will not remove existing overlays.")
(defvar org-fold-core--isearch-overlays) ; defined below
(defmacro org-fold-core--keep-overlays (&rest body)
"Run BODY with `org-fold-core--keep-overlays' set to t."
(declare (debug (body)))
`(let ((org-fold-core--keep-overlays t))
,@body))
(defvar org-fold-core--isearch-active nil
"When non-nil, `org-fold-core-region' records created overlays.
New overlays will be added to `org-fold-core--isearch-overlays'.")
(defmacro org-fold-core--with-isearch-active (&rest body)
"Run BODY with `org-fold-core--isearch-active' set to t."
(declare (debug (body)))
`(let ((org-fold-core--isearch-active t))
,@body))
;; This is the core function performing actual folding/unfolding. The
;; folding state is stored in text property (folding property)
;; returned by `org-fold-core--property-symbol-get-create'. The value of the
@ -1041,43 +996,7 @@ If SPEC-OR-ALIAS is omitted and FLAG is nil, unfold everything in the region."
(when spec (org-fold-core--check-spec spec))
(with-silent-modifications
(org-with-wide-buffer
;; Arrange fontifying newlines after all the folds between FROM
;; and TO to match the first character before the fold; not the
;; last as per Emacs defaults. This makes :extend faces span
;; past the ellipsis. See bug#65896. The face properties are
;; assigned via `org-activate-folds'.
(when (or (not spec) (org-fold-core-get-folding-spec-property spec :font-lock))
(when (equal ?\n (char-after from))
(font-lock-flush from (1+ from)))
(when (equal ?\n (char-after to))
(font-lock-flush to (1+ to)))
(dolist (region (org-fold-core-get-regions :from from :to to :specs spec))
(when (equal ?\n (char-after (cadr region)))
(font-lock-flush (cadr region) (1+ (cadr region))))
;; Re-fontify beginning of the fold - we may
;; unfold inside an existing fold, with FROM begin a newline
;; after spliced fold.
(when (equal ?\n (char-after (car region)))
(font-lock-flush (car region) (1+ (car region))))))
(when (eq org-fold-core-style 'overlays)
(if org-fold-core--keep-overlays
(mapc
(lambda (ov)
(when (or (not spec)
(eq spec (overlay-get ov 'invisible)))
(when (and org-fold-core--isearch-active
(overlay-get ov 'invisible)
(org-fold-core-get-folding-spec-property
(overlay-get ov 'invisible) :isearch-open))
(when (overlay-get ov 'invisible)
(overlay-put ov 'org-invisible (overlay-get ov 'invisible)))
(overlay-put ov 'invisible nil)
(when org-fold-core--isearch-active
(cl-pushnew ov org-fold-core--isearch-overlays)))))
(overlays-in from to))
(when spec
(remove-overlays from to 'org-invisible spec)
(remove-overlays from to 'invisible spec))))
(when (eq org-fold-core-style 'overlays) (remove-overlays from to 'invisible spec))
(if flag
(if (not spec)
(error "Calling `org-fold-core-region' with missing SPEC")
@ -1087,15 +1006,17 @@ If SPEC-OR-ALIAS is omitted and FLAG is nil, unfold everything in the region."
(let ((o (make-overlay from to nil
(org-fold-core-get-folding-spec-property spec :front-sticky)
(org-fold-core-get-folding-spec-property spec :rear-sticky))))
(when org-fold-core--isearch-active
(push o org-fold-core--isearch-overlays))
(overlay-put o 'evaporate t)
(overlay-put o (org-fold-core--property-symbol-get-create spec) spec)
(overlay-put o 'invisible spec)
;; Preserve priority.
(overlay-put o 'priority (length (member spec (org-fold-core-folding-spec-list))))
(overlay-put o 'isearch-open-invisible #'org-fold-core--isearch-show)
(overlay-put o 'isearch-open-invisible-temporary #'org-fold-core--isearch-show-temporary))
;; FIXME: Disabling to work around Emacs bug#60399
;; and https://orgmode.org/list/87zgb6tk6h.fsf@localhost.
;; The proper fix will require making sure that
;; `org-fold-core-isearch-open-function' does not
;; delete the overlays used by isearch.
;; (overlay-put o 'isearch-open-invisible-temporary #'org-fold-core--isearch-show-temporary)
)
(put-text-property from to (org-fold-core--property-symbol-get-create spec) spec)
(put-text-property from to 'isearch-open-invisible #'org-fold-core--isearch-show)
(put-text-property from to 'isearch-open-invisible-temporary #'org-fold-core--isearch-show-temporary)
@ -1119,13 +1040,7 @@ If SPEC-OR-ALIAS is omitted and FLAG is nil, unfold everything in the region."
(setq pos next))
(setq pos (next-single-char-property-change pos 'invisible nil to)))))))
(when (eq org-fold-core-style 'text-properties)
(remove-text-properties from to (list (org-fold-core--property-symbol-get-create spec) nil)))))
;; Re-calculate trailing faces for all the folds revealed
;; by unfolding or created by folding.
(when (or (not spec) (org-fold-core-get-folding-spec-property spec :font-lock))
(dolist (region (org-fold-core-get-regions :from from :to to :specs spec))
(when (equal ?\n (char-after (cadr region)))
(font-lock-flush (cadr region) (1+ (cadr region))))))))))
(remove-text-properties from to (list (org-fold-core--property-symbol-get-create spec) nil)))))))))
(cl-defmacro org-fold-core-regions (regions &key override clean-markers relative)
"Fold every region in REGIONS list in current buffer.
@ -1188,19 +1103,13 @@ TYPE can be either `text-properties' or `overlays'."
(setq-local isearch-filter-predicate #'org-fold-core--isearch-filter-predicate-text-properties))
(`overlays
(when (eq org-fold-core-style 'text-properties)
(add-function :before (local 'isearch-filter-predicate) #'org-fold-core--create-isearch-overlays)
;; When `isearch-filter-predicate' is called outside isearch,
;; it is common that `isearch-mode-end-hook' does not get
;; executed, but `isearch-clean-overlays' usually does.
(advice-add
'isearch-clean-overlays :after
#'org-fold-core--clear-isearch-overlays
'((name . isearch-clean-overlays@org-fold-core)))))
(setq-local isearch-filter-predicate #'org-fold-core--isearch-filter-predicate-overlays)
(add-hook 'isearch-mode-end-hook #'org-fold-core--clear-isearch-overlays nil 'local)))
(_ (error "%s: Unknown type of setup for `org-fold-core--isearch-setup'" type))))
(defun org-fold-core--isearch-reveal (pos)
"Default function used to reveal hidden text at POS for isearch."
(let ((region (org-fold-core-get-region-at-point nil pos)))
(let ((region (org-fold-core-get-region-at-point pos)))
(org-fold-core-region (car region) (cdr region) nil)))
(defun org-fold-core--isearch-filter-predicate-text-properties (beg end)
@ -1235,35 +1144,34 @@ This function is intended to be used as `isearch-filter-predicate'."
"Clear `org-fold-core--isearch-local-regions'."
(clrhash org-fold-core--isearch-local-regions))
(defun org-fold-core--isearch-show (overlay-or-region)
"Reveal text at OVERLAY-OR-REGION found by isearch."
(let (beg end)
(if (overlayp overlay-or-region)
(setq beg (overlay-start overlay-or-region)
end (overlay-end overlay-or-region))
(setq beg (car overlay-or-region)
end (cdr overlay-or-region)))
;; FIXME: Reveal the match (usually point, but may sometimes go beyond the region).
(when (< beg (point) end)
(funcall org-fold-core-isearch-open-function (point)))
(org-fold-core-region beg end nil)))
(defun org-fold-core--isearch-show (_)
"Reveal text at point found by isearch."
(funcall org-fold-core-isearch-open-function (point)))
(defun org-fold-core--isearch-show-temporary (region hide-p)
"Temporarily reveal text in REGION.
Hide text instead if HIDE-P is non-nil.
REGION can also be an overlay in current buffer."
(save-match-data ; match data must not be modified.
(let ((org-fold-core-style (if (overlayp region) 'overlays 'text-properties)))
(if hide-p
(if (not (overlayp region))
nil ;; FIXME: after isearch supports text properties.
(when (overlay-get region 'org-invisible)
(overlay-put region 'invisible (overlay-get region 'org-invisible))))
;; isearch expects all the temporarily opened overlays to exist.
;; See https://debbugs.gnu.org/cgi/bugreport.cgi?bug=60399
(org-fold-core--keep-overlays
(org-fold-core--with-isearch-active
(org-fold-core--isearch-show region)))))))
(when (overlayp region)
(setq region (cons (overlay-start region)
(overlay-end region))))
(if (not hide-p)
(let ((pos (car region)))
(while (< pos (cdr region))
(let ((spec-no-open
(catch :found
(dolist (spec (org-fold-core-get-folding-spec 'all pos))
(unless (org-fold-core-get-folding-spec-property spec :isearch-open)
(throw :found spec))))))
(if spec-no-open
;; Skip regions folded with folding specs that cannot be opened.
(setq pos (org-fold-core-next-folding-state-change spec-no-open pos (cdr region)))
(dolist (spec (org-fold-core-get-folding-spec 'all pos))
(push (cons spec (org-fold-core-get-region-at-point spec pos)) (gethash region org-fold-core--isearch-local-regions)))
(org-fold-core--isearch-show region)
(setq pos (org-fold-core-next-folding-state-change nil pos (cdr region)))))))
(mapc (lambda (val) (org-fold-core-region (cadr val) (cddr val) t (car val))) (gethash region org-fold-core--isearch-local-regions))
(remhash region org-fold-core--isearch-local-regions)))
(defvar-local org-fold-core--isearch-special-specs nil
"List of specs that can break visibility state when converted to overlays.
@ -1278,28 +1186,49 @@ instead of text properties. The created overlays will be stored in
(while (< pos end)
;; We need loop below to make sure that we clean all invisible
;; properties, which may be nested.
(catch :repeat
(dolist (spec (org-fold-core-get-folding-spec 'all pos))
(unless (org-fold-core-get-folding-spec-property spec :isearch-ignore)
(let* ((region (org-fold-core-get-region-at-point spec pos)))
(when (memq spec org-fold-core--isearch-special-specs)
(setq end (max end (cdr region)))
(when (< (car region) beg)
(setq beg (car region))
(setq pos beg)
(throw :repeat t)))
;; Changing text properties is considered buffer modification.
;; We do not want it here.
(with-silent-modifications
(org-fold-core-region (car region) (cdr region) nil spec)
(let ((org-fold-core-style 'overlays))
(org-fold-core--with-isearch-active
(org-fold-core-region (car region) (cdr region) t spec)))))))
(setq pos (org-fold-core-next-folding-state-change nil pos end))))))
(dolist (spec (org-fold-core-get-folding-spec 'all pos))
(unless (org-fold-core-get-folding-spec-property spec :isearch-ignore)
(let* ((region (org-fold-core-get-region-at-point spec pos)))
(when (memq spec org-fold-core--isearch-special-specs)
(setq pos (min pos (car region)))
(setq end (max end (cdr region))))
;; Changing text properties is considered buffer modification.
;; We do not want it here.
(with-silent-modifications
(org-fold-core-region (car region) (cdr region) nil spec)
;; The overlay is modeled after `outline-flag-region'
;; [2020-05-09 Sat] overlay for 'outline blocks.
(let ((o (make-overlay (car region) (cdr region) nil 'front-advance)))
(overlay-put o 'evaporate t)
(overlay-put o 'invisible spec)
(overlay-put o 'org-invisible spec)
;; Make sure that overlays are applied in the same order
;; with the folding specs.
;; Note: `memq` returns cdr with car equal to the first
;; found matching element.
(overlay-put o 'priority (length (memq spec (org-fold-core-folding-spec-list))))
;; `delete-overlay' here means that spec information will be lost
;; for the region. The region will remain visible.
(if (org-fold-core-get-folding-spec-property spec :isearch-open)
(overlay-put o 'isearch-open-invisible #'delete-overlay)
(overlay-put o 'isearch-open-invisible #'ignore)
(overlay-put o 'isearch-open-invisible-temporary #'ignore))
(push o org-fold-core--isearch-overlays))))))
(setq pos (org-fold-core-next-folding-state-change nil pos end)))))
(defun org-fold-core--isearch-filter-predicate-overlays (beg end)
"Return non-nil if text between BEG and END is deemed visible by isearch.
This function is intended to be used as `isearch-filter-predicate'."
(org-fold-core--create-isearch-overlays beg end) ;; trick isearch by creating overlays in place of invisible text
(isearch-filter-visible beg end))
(defun org-fold-core--clear-isearch-overlay (ov)
"Convert OV region back into using text properties."
(let ((spec (overlay-get ov 'invisible)))
(let ((spec (if isearch-mode-end-hook-quit
;; Restore all folds.
(overlay-get ov 'org-invisible)
;; Leave opened folds open.
(overlay-get ov 'invisible))))
;; Ignore deleted overlays.
(when (and spec
(overlay-buffer ov))
@ -1308,6 +1237,8 @@ instead of text properties. The created overlays will be stored in
(with-silent-modifications
(when (<= (overlay-end ov) (point-max))
(org-fold-core-region (overlay-start ov) (overlay-end ov) t spec)))))
(when (member ov isearch-opened-overlays)
(setq isearch-opened-overlays (delete ov isearch-opened-overlays)))
(delete-overlay ov))
(defun org-fold-core--clear-isearch-overlays ()
@ -1322,8 +1253,6 @@ instead of text properties. The created overlays will be stored in
"Non-nil: skip processing modifications in `org-fold-core--fix-folded-region'.")
(defvar org-fold-core--ignore-fragility-checks nil
"Non-nil: skip fragility checks in `org-fold-core--fix-folded-region'.")
(defvar org-fold-core--suppress-folding-fix nil
"Non-nil: skip folding fix in `org-fold-core--fix-folded-region'.")
(defmacro org-fold-core-ignore-modifications (&rest body)
"Run BODY ignoring buffer modifications in `org-fold-core--fix-folded-region'."
@ -1332,47 +1261,12 @@ instead of text properties. The created overlays will be stored in
(unwind-protect (progn ,@body)
(setq org-fold-core--last-buffer-chars-modified-tick (buffer-chars-modified-tick)))))
(defmacro org-fold-core-suppress-folding-fix (&rest body)
"Run BODY skipping re-folding checks in `org-fold-core--fix-folded-region'."
(declare (debug (form body)) (indent 0))
`(let ((org-fold-core--suppress-folding-fix t))
(progn ,@body)))
(defmacro org-fold-core-ignore-fragility-checks (&rest body)
"Run BODY skipping :fragility checks in `org-fold-core--fix-folded-region'."
(declare (debug (form body)) (indent 0))
`(let ((org-fold-core--ignore-fragility-checks t))
(progn ,@body)))
(defvar org-fold-core--region-delayed-list nil
"List holding (MKFROM MKTO FLAG SPEC-OR-ALIAS) arguments to process.
The list is used by `org-fold-core--region-delayed'.")
(defun org-fold-core--region-delayed (from to flag &optional spec-or-alias)
"Call `org-fold-core-region' after current command.
Pass the same FROM, TO, FLAG, and SPEC-OR-ALIAS."
;; Setup delayed folding.
(add-hook 'post-command-hook #'org-fold-core--process-delayed)
(let ((frommk (make-marker))
(tomk (make-marker)))
(set-marker frommk from (current-buffer))
(set-marker tomk to (current-buffer))
(push (list frommk tomk flag spec-or-alias) org-fold-core--region-delayed-list)))
(defun org-fold-core--process-delayed ()
"Perform folding for `org-fold-core--region-delayed-list'."
(when org-fold-core--region-delayed-list
(mapc (lambda (args)
(when (and (buffer-live-p (marker-buffer (nth 0 args)))
(buffer-live-p (marker-buffer (nth 1 args)))
(< (nth 0 args) (nth 1 args)))
(org-with-point-at (car args)
(apply #'org-fold-core-region args))))
;; Restore the initial folding order.
(nreverse org-fold-core--region-delayed-list))
;; Cleanup `post-command-hook'.
(remove-hook 'post-command-hook #'org-fold-core--process-delayed)
(setq org-fold-core--region-delayed-list nil)))
(defvar-local org-fold-core--last-buffer-chars-modified-tick nil
"Variable storing the last return value of `buffer-chars-modified-tick'.")
@ -1390,19 +1284,19 @@ to :front-sticky/:rear-sticky folding spec property.
If the folded region is folded with a spec with non-nil :fragile
property, unfold the region if the :fragile function returns non-nil."
;; If no insertions or deletions in buffer, skip all the checks.
(unless (or org-fold-core--ignore-modifications
(eq org-fold-core--last-buffer-chars-modified-tick (buffer-chars-modified-tick))
(unless (or (eq org-fold-core--last-buffer-chars-modified-tick (buffer-chars-modified-tick))
org-fold-core--ignore-modifications
(memql 'ignore-modification-checks org-fold-core--optimise-for-huge-buffers))
;; Store the new buffer modification state.
(setq org-fold-core--last-buffer-chars-modified-tick (buffer-chars-modified-tick))
(save-match-data
;; Handle changes in all the indirect buffers and in the base
;; buffer. Work around Emacs bug#46982.
;; Re-hide text inserted in the middle/front/back of a folded
;; region.
(unless (or org-fold-core--suppress-folding-fix (equal from to)) ; Ignore deletions.
(when (eq org-fold-core-style 'text-properties)
(org-fold-core-cycle-over-indirect-buffers
(when (eq org-fold-core-style 'text-properties)
(org-fold-core-cycle-over-indirect-buffers
;; Re-hide text inserted in the middle/front/back of a folded
;; region.
(unless (equal from to) ; Ignore deletions.
(dolist (spec (org-fold-core-folding-spec-list))
;; Reveal fully invisible text inserted in the middle
;; of visible portion of the buffer. This is needed,
@ -1490,10 +1384,7 @@ property, unfold the region if the :fragile function returns non-nil."
(cons fold-begin fold-end)
spec))
;; Reveal completely, not just from the SPEC.
;; Do it only after command is finished -
;; some Emacs commands assume that
;; visibility is not altered by `after-change-functions'.
(org-fold-core--region-delayed fold-begin fold-end nil)))))
(org-fold-core-region fold-begin fold-end nil)))))
;; Move to next fold.
(setq pos (org-fold-core-next-folding-state-change spec pos local-to)))))))))))))

View File

@ -1,8 +1,8 @@
;;; org-fold.el --- Folding of Org entries -*- lexical-binding: t; -*-
;;
;; Copyright (C) 2020-2024 Free Software Foundation, Inc.
;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
;;
;; Author: Ihor Radchenko <yantar92 at posteo dot net>
;; Author: Ihor Radchenko <yantar92 at gmail dot com>
;; Keywords: folding, invisible text
;; URL: https://orgmode.org
;;
@ -61,12 +61,11 @@
(defvar org-element-headline-re)
(declare-function isearch-filter-visible "isearch" (beg end))
(declare-function org-element-type "org-element-ast" (node &optional anonymous))
(declare-function org-element-type "org-element" (element))
(declare-function org-element-at-point "org-element" (&optional pom cached-only))
(declare-function org-element-property "org-element-ast" (property node))
(declare-function org-element-end "org-element" (node))
(declare-function org-element-post-affiliated "org-element" (node))
(declare-function org-element-property "org-element" (property element))
(declare-function org-element--current-element "org-element" (limit &optional granularity mode structure))
(declare-function org-element--cache-active-p "org-element" ())
(declare-function org-toggle-custom-properties-visibility "org" ())
(declare-function org-item-re "org-list" ())
(declare-function org-up-heading-safe "org" ())
@ -190,10 +189,7 @@ smart Make point visible, and do insertion/deletion if it is
Never delete a previously invisible character or add in the
middle or right after an invisible region. Basically, this
allows insertion and backward-delete right before ellipses.
FIXME: maybe in this case we should not even show?
This variable only affects commands listed in
`org-fold-catch-invisible-edits-commands'."
FIXME: maybe in this case we should not even show?"
:group 'org-edit-structure
:version "24.1"
:type '(choice
@ -203,33 +199,6 @@ This variable only affects commands listed in
(const :tag "Show invisible part and do the edit" show)
(const :tag "Be smart and do the right thing" smart)))
(defcustom org-fold-catch-invisible-edits-commands
;; We do not add non-Org commands here by default to avoid advising
;; globally. See `org-fold--advice-edit-commands'.
'((org-self-insert-command . insert)
(org-delete-backward-char . delete-backward)
(org-delete-char . delete)
(org-meta-return . insert)
(org-return . insert))
"Alist of commands where Org checks for invisible edits.
Each element is (COMMAND . KIND), where COMMAND is symbol representing
command as stored in `this-command' and KIND is symbol `insert',
symbol `delete', or symbol `delete-backward'.
The checks are performed around `point'.
This variable must be set before loading Org in order to take effect.
Also, see `org-fold-catch-invisible-edits'."
:group 'org-edit-structure
:package-version '("Org" . "9.7")
:type '(alist
:key-type symbol
:value-type (choice
(const insert)
(const delete)
(const delete-backward))))
;;; Core functionality
;;; API
@ -255,7 +224,6 @@ Also, see `org-fold-catch-invisible-edits'."
(:ellipsis . ,ellipsis)
(:fragile . ,#'org-fold--reveal-outline-maybe)
(:isearch-open . t)
(:font-lock . t)
;; This is needed to make sure that inserting a
;; new planning line in folded heading is not
;; revealed. Also, the below combination of :front-sticky and
@ -268,7 +236,6 @@ Also, see `org-fold-catch-invisible-edits'."
(:ellipsis . ,ellipsis)
(:fragile . ,#'org-fold--reveal-drawer-or-block-maybe)
(:isearch-open . t)
(:font-lock . t)
(:front-sticky . t)
(:alias . ( block center-block comment-block
dynamic-block example-block export-block
@ -278,7 +245,6 @@ Also, see `org-fold-catch-invisible-edits'."
(:ellipsis . ,ellipsis)
(:fragile . ,#'org-fold--reveal-drawer-or-block-maybe)
(:isearch-open . t)
(:font-lock . t)
(:front-sticky . t)
(:alias . (drawer property-drawer)))
,org-link--description-folding-spec
@ -392,7 +358,7 @@ of the current heading, or to 1 if the current line is not a heading."
(interactive (list
(cond
(current-prefix-arg (prefix-numeric-value current-prefix-arg))
((save-excursion (forward-line 0)
((save-excursion (beginning-of-line)
(looking-at outline-regexp))
(funcall outline-level))
(t 1))))
@ -532,12 +498,12 @@ Return a non-nil value when toggling is successful."
comment-block dynamic-block example-block export-block
quote-block special-block src-block verse-block))
(_ (error "Unknown category: %S" category))))
(let* ((post (org-element-post-affiliated element))
(let* ((post (org-element-property :post-affiliated element))
(start (save-excursion
(goto-char post)
(line-end-position)))
(end (save-excursion
(goto-char (org-element-end element))
(goto-char (org-element-property :end element))
(skip-chars-backward " \t\n")
(line-end-position))))
;; Do nothing when not before or at the block opening line or
@ -596,12 +562,10 @@ Return a non-nil value when toggling is successful."
(interactive)
(org-block-map (apply-partially #'org-fold-hide-block-toggle 'hide)))
(defun org-fold-hide-drawer-all (&optional begin end)
"Fold all drawers in the current buffer or active region BEGIN..END."
(interactive (list (and (use-region-p) (region-beginning))
(and (use-region-p) (region-end))))
(let ((begin (or begin (point-min)))
(end (or end (point-max))))
(defun org-fold-hide-drawer-all ()
"Fold all drawers in the current buffer."
(let ((begin (point-min))
(end (point-max)))
(org-fold--hide-drawers begin end)))
(defun org-fold--hide-drawers (begin end)
@ -620,7 +584,7 @@ Return a non-nil value when toggling is successful."
;; Make sure to skip drawer entirely or we might flag it
;; another time when matching its ending line with
;; `org-drawer-regexp'.
(goto-char (org-element-end drawer))))))))
(goto-char (org-element-property :end drawer))))))))
(defun org-fold-hide-archived-subtrees (beg end)
"Re-hide all archived subtrees after a visibility state change."
@ -629,7 +593,7 @@ Return a non-nil value when toggling is successful."
(re (concat org-outline-regexp-bol ".*:" org-archive-tag ":")))
(goto-char beg)
;; Include headline point is currently on.
(forward-line 0)
(beginning-of-line)
(while (and (< (point) end) (re-search-forward re end t))
(when (member org-archive-tag (org-get-tags nil t))
(org-fold-subtree t)
@ -664,33 +628,32 @@ DETAIL is either nil, `minimal', `local', `ancestors',
(when (org-invisible-p)
;; FIXME: No clue why, but otherwise the following might not work.
(redisplay)
;; Reveal emphasis markers.
(when (eq detail 'local)
(let (org-hide-emphasis-markers
org-link-descriptive
org-pretty-entities
(org-hide-macro-markers nil)
(region (or (org-find-text-property-region (point) 'org-emphasis)
(org-find-text-property-region (point) 'org-macro)
(org-find-text-property-region (point) 'invisible))))
;; Silence byte-compiler.
(ignore org-hide-macro-markers)
(when region
(org-with-point-at (car region)
(forward-line 0)
(let (font-lock-extend-region-functions)
(font-lock-fontify-region (max (point-min) (1- (car region))) (cdr region))))))
;; Unfold links.
(let (region)
(dolist (spec '(org-link org-link-description))
(setq region (org-fold-get-region-at-point spec))
(when region (org-fold-region (car region) (cdr region) nil spec)))))
(let (region)
(dolist (spec (org-fold-core-folding-spec-list))
;; Links are taken care by above.
(unless (memq spec '(org-link org-link-description))
(setq region (org-fold-get-region-at-point spec))
(let ((region (org-fold-get-region-at-point)))
;; Reveal emphasis markers.
(when (eq detail 'local)
(let (org-hide-emphasis-markers
org-link-descriptive
org-pretty-entities
(org-hide-macro-markers nil)
(region (or (org-find-text-property-region (point) 'org-emphasis)
(org-find-text-property-region (point) 'org-macro)
(org-find-text-property-region (point) 'invisible)
region)))
;; Silence byte-compiler.
(ignore org-hide-macro-markers)
(when region
(org-with-point-at (car region)
(beginning-of-line)
(let (font-lock-extend-region-functions)
(font-lock-fontify-region (max (point-min) (1- (car region))) (cdr region))))))
;; Unfold links.
(when region
(dolist (spec '(org-link org-link-description))
(org-fold-region (car region) (cdr region) nil spec))))
(when region
(dolist (spec (org-fold-core-folding-spec-list))
;; Links are taken care by above.
(unless (memq spec '(org-link org-link-description))
(org-fold-region (car region) (cdr region) nil spec))))))
(unless (org-before-first-heading-p)
(org-with-limited-levels
@ -736,10 +699,9 @@ go to the parent and show the entire tree."
;;; Make isearch search in some text hidden via text properties.
(defun org-fold--isearch-reveal (pos)
(defun org-fold--isearch-reveal (&rest _)
"Reveal text at POS found by isearch."
(org-with-point-at pos
(org-fold-show-context 'isearch)))
(org-fold-show-context 'isearch))
;;; Handling changes in folded elements
@ -764,7 +726,7 @@ the contents consists of blank lines.
Assume that point is located at the header line."
(org-with-wide-buffer
(forward-line 0)
(beginning-of-line)
(org-fold-region
(max (point-min) (1- (point)))
(let ((endl (line-end-position)))
@ -775,7 +737,7 @@ Assume that point is located at the header line."
(if (equal (point)
(save-excursion
(goto-char endl)
(org-end-of-subtree t)
(org-end-of-subtree)
(skip-chars-forward "\n\t\r ")))
(point)
endl)))
@ -792,7 +754,7 @@ This function is intended to be used as :fragile property of
;; The line before beginning of the fold should be either a
;; headline or a list item.
(backward-char)
(forward-line 0)
(beginning-of-line)
;; Make sure that headline is not partially hidden.
(unless (org-fold-folded-p nil 'headline)
(org-fold--reveal-headline-at-point))
@ -804,14 +766,14 @@ This function is intended to be used as :fragile property of
(org-fold--reveal-headline-at-point))))
;; Make sure that headline after is not partially hidden.
(goto-char (cdr region))
(forward-line 0)
(beginning-of-line)
(unless (org-fold-folded-p nil 'headline)
(when (looking-at-p org-element-headline-re)
(org-fold--reveal-headline-at-point)))
;; Check the validity of headline
(goto-char (car region))
(backward-char)
(forward-line 0)
(beginning-of-line)
(unless (let ((case-fold-search t))
(looking-at (rx-to-string
`(or (regex ,(org-item-re))
@ -847,7 +809,7 @@ This function is intended to be used as :fragile property of
;; The line before beginning of the fold should be the
;; first line of the drawer/block.
(backward-char)
(forward-line 0)
(beginning-of-line)
(unless (let ((case-fold-search t))
(looking-at begin-re)) ; the match-data will be used later
(throw :exit (setq unfold? t))))
@ -867,7 +829,7 @@ This function is intended to be used as :fragile property of
;; The last line of the folded text should match `end-re'.
(save-excursion
(goto-char fold-end)
(forward-line 0)
(beginning-of-line)
(unless (let ((case-fold-search t))
(looking-at end-re))
(throw :exit (setq unfold? t))))
@ -941,19 +903,6 @@ The detailed reaction depends on the user option
;; Don't do the edit, make the user repeat it in full visibility
(user-error "Edit in invisible region aborted, repeat to confirm with text visible"))))))))
(defun org-fold-check-before-invisible-edit-maybe (&rest _)
"Check before invisible command by `this-command'."
(when (derived-mode-p 'org-mode)
(pcase (alist-get this-command org-fold-catch-invisible-edits-commands)
((pred null) nil)
(kind (org-fold-check-before-invisible-edit kind)))))
(defun org-fold--advice-edit-commands ()
"Advice editing commands according to `org-fold-catch-invisible-edits-commands'.
The advices are installed in current buffer."
(dolist (command (mapcar #'car org-fold-catch-invisible-edits-commands))
(advice-add command :before #'org-fold-check-before-invisible-edit-maybe)))
(provide 'org-fold)
;;; org-fold.el ends here

View File

@ -1,6 +1,6 @@
;;; org-footnote.el --- Footnote support in Org -*- lexical-binding: t; -*-
;;
;; Copyright (C) 2009-2024 Free Software Foundation, Inc.
;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
;;
;; Author: Carsten Dominik <carsten.dominik@gmail.com>
;; Keywords: outlines, hypermedia, calendar, wp
@ -45,10 +45,9 @@
(declare-function org-element-at-point "org-element" (&optional pom cached-only))
(declare-function org-element-class "org-element" (datum &optional parent))
(declare-function org-element-context "org-element" (&optional element))
(declare-function org-element-lineage "org-element-ast" (blob &optional types with-self))
(declare-function org-element-property "org-element-ast" (property node))
(declare-function org-element-type "org-element-ast" (node &optional anonymous))
(declare-function org-element-type-p "org-element-ast" (node types))
(declare-function org-element-lineage "org-element" (blob &optional types with-self))
(declare-function org-element-property "org-element" (property element))
(declare-function org-element-type "org-element" (element))
(declare-function org-end-of-subtree "org" (&optional invisible-ok to-heading))
(declare-function org-fill-paragraph "org" (&optional justify region))
(declare-function org-in-block-p "org" (names))
@ -137,7 +136,6 @@ Possible values are:
nil Prompt the user for each label.
t Create unique labels of the form [fn:1], [fn:2], etc.
anonymous Create anonymous footnotes
confirm Like t, but let the user edit the created value.
The label can be removed from the minibuffer to create
an anonymous footnote.
@ -147,7 +145,6 @@ random Automatically generate a unique, random label."
(const :tag "Prompt for label" nil)
(const :tag "Create automatic [fn:N]" t)
(const :tag "Offer automatic [fn:N] for editing" confirm)
(const :tag "Create anoymous [fn::]" anonymous)
(const :tag "Create a random label" random))
:safe #'symbolp)
@ -186,21 +183,21 @@ extracted will be filled again."
"Is point in a context where footnotes are allowed?"
(save-match-data
(not (or (org-at-comment-p)
(org-inside-LaTeX-fragment-p)
;; Avoid literal example.
(org-in-verbatim-emphasis)
(save-excursion
(forward-line 0)
(looking-at "[ \t]*:[ \t]+"))
;; Avoid forbidden blocks.
(org-in-block-p org-footnote-forbidden-blocks)))))
(org-inside-LaTeX-fragment-p)
;; Avoid literal example.
(org-in-verbatim-emphasis)
(save-excursion
(beginning-of-line)
(looking-at "[ \t]*:[ \t]+"))
;; Avoid forbidden blocks.
(org-in-block-p org-footnote-forbidden-blocks)))))
(defun org-footnote-at-reference-p ()
"Non-nil if point is at a footnote reference.
If so, return a list containing its label, beginning and ending
positions, and the definition, when inline."
(let ((reference (org-element-context)))
(when (org-element-type-p reference 'footnote-reference)
(when (eq 'footnote-reference (org-element-type reference))
(let ((end (save-excursion
(goto-char (org-element-property :end reference))
(skip-chars-backward " \t")
@ -226,7 +223,7 @@ defined locally.
The return value is nil if not at a footnote definition, and
a list with label, start, end and definition of the footnote
otherwise."
(pcase (org-element-lineage (org-element-at-point) 'footnote-definition t)
(pcase (org-element-lineage (org-element-at-point) '(footnote-definition) t)
(`nil nil)
(definition
(let* ((label (org-element-property :label definition))
@ -272,7 +269,7 @@ otherwise."
((memq type '(headline inlinetask))
(or (not (org-at-heading-p))
(and (save-excursion
(forward-line 0)
(beginning-of-line)
(and (let ((case-fold-search t))
(not (looking-at-p "\\*+ END[ \t]*$")))
(let ((case-fold-search nil))
@ -284,10 +281,10 @@ otherwise."
;; White spaces after an object or blank lines after an element
;; are OK.
((>= (point)
(save-excursion (goto-char (org-element-property :end context))
(skip-chars-backward " \r\t\n")
(if (eq (org-element-class context) 'object) (point)
(line-beginning-position 2)))))
(save-excursion (goto-char (org-element-property :end context))
(skip-chars-backward " \r\t\n")
(if (eq (org-element-class context) 'object) (point)
(line-beginning-position 2)))))
;; At the beginning of a footnote definition, right after the
;; label, is OK.
((eq type 'footnote-definition) (looking-at (rx space)))
@ -301,7 +298,7 @@ otherwise."
;; :contents-begin is not reliable on empty cells, so special
;; case it.
(<= (save-excursion (skip-chars-backward " \t") (point))
(org-element-property :contents-end context)))
(org-element-property :contents-end context)))
((let ((cbeg (org-element-property :contents-begin context))
(cend (org-element-property :contents-end context)))
(and cbeg (>= (point) cbeg) (<= (point) cend))))))))
@ -371,14 +368,14 @@ References are sorted according to a deep-reading order."
;; Ensure point is within the reference before parsing it.
(backward-char)
(let ((object (org-element-context)))
(when (org-element-type-p object 'footnote-reference)
(when (eq (org-element-type object) 'footnote-reference)
(let* ((label (org-element-property :label object))
(begin (org-element-property :begin object))
(size
(and (eq (org-element-property :type object) 'inline)
(- (org-element-property :contents-end object)
(org-element-property :contents-begin object)))))
(let ((d (org-element-lineage object 'footnote-definition)))
(let ((d (org-element-lineage object '(footnote-definition))))
(push (list label (copy-marker begin) (not d) size)
references)
(when d
@ -423,7 +420,7 @@ while collecting them."
(backward-char)
(let ((element (org-element-at-point)))
(let ((label (org-element-property :label element)))
(when (and (org-element-type-p element 'footnote-definition)
(when (and (eq (org-element-type element) 'footnote-definition)
(not (member label seen)))
(push label seen)
(let* ((beg (progn
@ -519,7 +516,7 @@ This function is meant to be used for fontification only."
;; Definition: also grab the last square bracket, matched in
;; `org-footnote-re' for non-inline footnotes.
((and (save-excursion
(forward-line 0)
(beginning-of-line)
(save-match-data (org-footnote-in-valid-context-p)))
(save-excursion
(end-of-line)
@ -636,8 +633,8 @@ This function ignores narrowing, if any."
(while (re-search-forward org-footnote-re nil t)
(backward-char)
(let ((context (org-element-context)))
(when (org-element-type-p
context '(footnote-definition footnote-reference))
(when (memq (org-element-type context)
'(footnote-definition footnote-reference))
(let ((label (org-element-property :label context)))
(when label (cl-pushnew label all :test #'equal))))))
all)))
@ -668,16 +665,15 @@ or new, let the user edit the definition of the footnote."
(user-error "Cannot insert a footnote here"))
(let* ((all (org-footnote-all-labels))
(label
(unless (eq org-footnote-auto-label 'anonymous)
(if (eq org-footnote-auto-label 'random)
(format "%x" (abs (random)))
(org-footnote-normalize-label
(let ((propose (org-footnote-unique-label all)))
(if (eq org-footnote-auto-label t) propose
(completing-read
"Label (leave empty for anonymous): "
(mapcar #'list all) nil nil
(and (eq org-footnote-auto-label 'confirm) propose)))))))))
(if (eq org-footnote-auto-label 'random)
(format "%x" (abs (random)))
(org-footnote-normalize-label
(let ((propose (org-footnote-unique-label all)))
(if (eq org-footnote-auto-label t) propose
(completing-read
"Label (leave empty for anonymous): "
(mapcar #'list all) nil nil
(and (eq org-footnote-auto-label 'confirm) propose))))))))
(cond ((not label)
(insert "[fn::]")
(backward-char 1))

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