From 16a0a6db93ec8fae73b4fbaea6fadb15ae10b36a Mon Sep 17 00:00:00 2001 From: Daniel Weschke Date: Sun, 22 Jun 2025 17:08:08 +0200 Subject: [PATCH] update packages --- lisp/ace-window/ace-window-pkg.el | 22 +- lisp/ace-window/ace-window.el | 3 +- .../all-the-icons-ivy-rich-pkg.el | 26 +- .../all-the-icons-ivy-rich.el | 3 +- lisp/all-the-icons/all-the-icons-faces.el | 3 +- lisp/all-the-icons/all-the-icons-pkg.el | 22 +- lisp/all-the-icons/all-the-icons.el | 3 +- lisp/all-the-icons/data/data-alltheicons.el | 2 + lisp/all-the-icons/data/data-faicons.el | 2 + lisp/all-the-icons/data/data-fileicons.el | 2 + lisp/all-the-icons/data/data-material.el | 2 + lisp/all-the-icons/data/data-octicons.el | 2 + lisp/all-the-icons/data/data-weathericons.el | 2 + lisp/amx/amx-pkg.el | 26 +- lisp/amx/amx.el | 3 +- lisp/anaconda-mode/anaconda-mode-pkg.el | 30 +- lisp/anaconda-mode/anaconda-mode.el | 3 +- lisp/anaconda-mode/anaconda-mode.py | 3 +- lisp/async/async-bytecomp.el | 2 +- lisp/async/async-pkg.el | 22 +- lisp/async/async.el | 3 +- lisp/avy/avy-pkg.el | 24 +- lisp/avy/avy.el | 3 +- lisp/biblio-core/biblio-core-pkg.el | 28 +- lisp/biblio-core/biblio-core.el | 3 +- lisp/biblio/biblio-dblp.el | 2 +- lisp/biblio/biblio-pkg.el | 24 +- lisp/biblio/biblio.el | 3 +- .../bibtex-completion-pkg.el | 33 +- lisp/bibtex-completion/bibtex-completion.el | 3 +- lisp/cfrs/cfrs-pkg.el | 25 +- lisp/cfrs/cfrs.el | 3 +- lisp/citeproc/citeproc-pkg.el | 38 +- lisp/citeproc/citeproc-rt.el | 4 +- lisp/citeproc/citeproc.el | 3 +- lisp/cl-libify/cl-libify-pkg.el | 22 +- lisp/cl-libify/cl-libify.el | 3 +- lisp/company-anaconda/company-anaconda-pkg.el | 32 +- lisp/company-anaconda/company-anaconda.el | 3 +- lisp/company-ledger/company-ledger-pkg.el | 24 +- lisp/company-ledger/company-ledger.el | 3 +- .../company-quickhelp-pkg.el | 24 +- lisp/company-quickhelp/company-quickhelp.el | 3 +- .../company-statistics-pkg.el | 24 +- lisp/company-statistics/company-statistics.el | 3 +- lisp/company-web/company-web-pkg.el | 28 +- lisp/company-web/company-web.el | 3 +- lisp/company/company-cmake.el | 1 - lisp/company/company-keywords.el | 5 + lisp/company/company-pkg.el | 19 +- lisp/company/company.el | 23 +- lisp/compat/NEWS.org | 78 +- lisp/compat/compat-25.el | 25 +- lisp/compat/compat-26.el | 4 +- lisp/compat/compat-27.el | 2 +- lisp/compat/compat-28.el | 39 +- lisp/compat/compat-29.el | 64 +- lisp/compat/compat-30.el | 474 + lisp/compat/compat-macs.el | 27 +- lisp/compat/compat-pkg.el | 2 +- lisp/compat/compat.el | 18 +- lisp/compat/compat.info | 930 +- lisp/counsel/counsel-pkg.el | 28 +- lisp/counsel/counsel.el | 866 +- lisp/crdt/README-elpa | 21 +- lisp/ctable/ctable-pkg.el | 24 +- lisp/ctable/ctable.el | 3 +- lisp/dash/dash-pkg.el | 22 +- lisp/dash/dash.el | 125 +- lisp/dash/dash.info | 432 +- lisp/dashboard/dashboard-pkg.el | 24 +- lisp/dashboard/dashboard-widgets.el | 129 +- lisp/dashboard/dashboard.el | 3 +- lisp/deft/deft-pkg.el | 22 +- lisp/deft/deft.el | 3 +- lisp/diff-hl/diff-hl-inline-popup.el | 3 +- lisp/diff-hl/diff-hl-margin.el | 10 +- lisp/diff-hl/diff-hl-pkg.el | 24 +- lisp/diff-hl/diff-hl-show-hunk-posframe.el | 26 +- lisp/diff-hl/diff-hl-show-hunk.el | 11 +- lisp/diff-hl/diff-hl.el | 132 +- lisp/dim/dim-pkg.el | 22 +- lisp/dim/dim.el | 3 +- lisp/elisp-refs/elisp-refs-pkg.el | 23 +- lisp/elisp-refs/elisp-refs.el | 3 +- lisp/emacsql/README.md | 434 + lisp/emacsql/emacsql-pkg.el | 19 +- lisp/emacsql/emacsql-sqlite-builtin.el | 8 +- lisp/emacsql/emacsql-sqlite-common.el | 22 - lisp/emacsql/emacsql-sqlite.el | 4 +- lisp/emacsql/emacsql.el | 52 +- lisp/emojify/emojify-pkg.el | 26 +- lisp/emojify/emojify.el | 3 +- lisp/ess-R-data-view/ess-R-data-view-pkg.el | 21 +- lisp/ess-R-data-view/ess-R-data-view.el | 3 +- lisp/ess/ess-bugs-l.el | 4 +- lisp/ess/ess-custom.el | 2 +- lisp/ess/ess-help.el | 2 +- lisp/ess/ess-pkg.el | 41 +- lisp/ess/ess-r-flymake.el | 10 +- lisp/ess/ess-r-mode.el | 14 +- lisp/ess/ess-rdired.el | 2 +- lisp/ess/ess-sas-d.el | 2 +- lisp/ess/ess-tracebug.el | 6 +- lisp/ess/ess.el | 3 +- lisp/ess/essd-els.el | 2 +- lisp/f/f-pkg.el | 26 +- lisp/f/f-shortdoc.el | 1 - lisp/f/f.el | 3 +- lisp/flycheck-ledger/flycheck-ledger-pkg.el | 24 +- lisp/flycheck-ledger/flycheck-ledger.el | 3 +- lisp/flycheck-pos-tip/flycheck-pos-tip-pkg.el | 28 +- lisp/flycheck-pos-tip/flycheck-pos-tip.el | 3 +- lisp/flycheck/flycheck-pkg.el | 26 +- lisp/flycheck/flycheck.el | 38 +- .../flyspell-correct-ivy-pkg.el | 23 +- .../flyspell-correct-ivy.el | 3 +- lisp/flyspell-correct/flyspell-correct-ido.el | 1 - lisp/flyspell-correct/flyspell-correct-pkg.el | 19 +- lisp/flyspell-correct/flyspell-correct.el | 3 +- lisp/focus/focus-pkg.el | 21 +- lisp/focus/focus.el | 3 +- lisp/git-messenger/git-messenger-pkg.el | 14 +- lisp/git-messenger/git-messenger.el | 3 +- lisp/gnuplot/dir | 18 + lisp/gnuplot/gnuplot-context.el | 474 +- lisp/gnuplot/gnuplot-eldoc.el | 631 + lisp/gnuplot/gnuplot-gui.el | 308 +- lisp/gnuplot/gnuplot-pkg.el | 24 +- lisp/gnuplot/gnuplot.el | 1310 +- lisp/gnuplot/gnuplot.info | 26562 ++++++++++++++++ lisp/helpful/helpful-pkg.el | 30 +- lisp/helpful/helpful.el | 5 +- lisp/ht/ht-pkg.el | 21 +- lisp/ht/ht.el | 3 +- lisp/htmlize/htmlize-pkg.el | 22 +- lisp/htmlize/htmlize.el | 3 +- lisp/hydra/hydra-pkg.el | 24 +- lisp/hydra/hydra.el | 23 +- lisp/indent-guide/indent-guide-pkg.el | 11 +- lisp/indent-guide/indent-guide.el | 3 +- lisp/iscroll/iscroll-pkg.el | 22 +- lisp/iscroll/iscroll.el | 3 +- lisp/ivy-bibtex/ivy-bibtex-pkg.el | 23 +- lisp/ivy-bibtex/ivy-bibtex.el | 3 +- lisp/ivy-rich/ivy-rich-pkg.el | 24 +- lisp/ivy-rich/ivy-rich.el | 3 +- lisp/ivy/colir.el | 6 +- lisp/ivy/elpa.el | 6 - lisp/ivy/ivy-faces.el | 7 + lisp/ivy/ivy-overlay.el | 18 +- lisp/ivy/ivy-pkg.el | 22 +- lisp/ivy/ivy.el | 294 +- lisp/ivy/ivy.info | 420 +- lisp/js2-mode/js2-mode-pkg.el | 32 +- lisp/js2-mode/js2-mode.el | 3 +- lisp/key-chord/key-chord-pkg.el | 21 +- lisp/key-chord/key-chord.el | 345 +- lisp/langtool/langtool-pkg.el | 22 +- lisp/langtool/langtool.el | 3 +- lisp/ledger-mode/ledger-complete.el | 33 +- lisp/ledger-mode/ledger-exec.el | 2 +- lisp/ledger-mode/ledger-mode-pkg.el | 11 +- lisp/ledger-mode/ledger-mode.el | 2 + lisp/ledger-mode/ledger-navigate.el | 23 +- lisp/ledger-mode/ledger-reconcile.el | 4 +- lisp/ledger-mode/ledger-regex.el | 23 +- lisp/ledger-mode/ledger-sort.el | 2 +- lisp/ledger-mode/ledger-state.el | 36 +- lisp/ledger-mode/ledger-texi.el | 2 +- lisp/ledger-mode/ledger-xact.el | 2 +- lisp/llama/.dir-locals.el | 6 + lisp/llama/llama-pkg.el | 18 +- lisp/llama/llama.el | 173 +- lisp/lv/lv-pkg.el | 11 +- lisp/lv/lv.el | 3 + lisp/magit-section/magit-section-pkg.el | 30 +- lisp/magit-section/magit-section.el | 445 +- lisp/magit-section/magit-section.info | 2 +- lisp/magit/.dir-locals.el | 15 + lisp/magit/AUTHORS.md | 2 + lisp/magit/git-commit.el | 1224 + lisp/magit/git-rebase.el | 160 +- lisp/magit/magit-apply.el | 97 +- lisp/magit/magit-base.el | 90 +- lisp/magit/magit-bisect.el | 2 +- lisp/magit/magit-blame.el | 21 +- lisp/magit/magit-bookmark.el | 5 + lisp/magit/magit-branch.el | 37 +- lisp/magit/magit-diff.el | 381 +- lisp/magit/magit-dired.el | 109 + lisp/magit/magit-ediff.el | 5 +- lisp/magit/magit-extras.el | 73 - lisp/magit/magit-fetch.el | 4 +- lisp/magit/magit-files.el | 75 +- lisp/magit/magit-git.el | 91 +- lisp/magit/magit-gitignore.el | 7 +- lisp/magit/magit-log.el | 204 +- lisp/magit/magit-margin.el | 20 +- lisp/magit/magit-merge.el | 23 +- lisp/magit/magit-mode.el | 101 +- lisp/magit/magit-pkg.el | 40 +- lisp/magit/magit-process.el | 134 +- lisp/magit/magit-push.el | 10 +- lisp/magit/magit-refs.el | 39 +- lisp/magit/magit-remote.el | 15 +- lisp/magit/magit-sequence.el | 138 +- lisp/magit/magit-sparse-checkout.el | 2 +- lisp/magit/magit-stash.el | 30 +- lisp/magit/magit-status.el | 35 +- lisp/magit/magit-submodule.el | 30 +- lisp/magit/magit-subtree.el | 1 - lisp/magit/magit-transient.el | 102 +- lisp/magit/magit-version.el | 6 +- lisp/magit/magit-wip.el | 21 + lisp/magit/magit.el | 14 +- lisp/magit/magit.info | 771 +- lisp/markdown-mode/markdown-mode-pkg.el | 22 +- lisp/markdown-mode/markdown-mode.el | 314 +- lisp/memoize/memoize-pkg.el | 19 +- lisp/memoize/memoize.el | 3 +- lisp/multiple-cursors/multiple-cursors-pkg.el | 22 +- lisp/multiple-cursors/multiple-cursors.el | 3 +- lisp/notmuch/notmuch-hello.el | 4 +- lisp/notmuch/notmuch-mua.el | 4 +- lisp/notmuch/notmuch-pkg.el | 11 +- lisp/notmuch/notmuch-show.el | 4 +- lisp/notmuch/notmuch-tree.el | 12 +- lisp/notmuch/notmuch.el | 28 +- lisp/ob-async/ob-async-pkg.el | 26 +- lisp/ob-async/ob-async.el | 3 +- lisp/ol-notmuch/ol-notmuch-pkg.el | 28 +- lisp/ol-notmuch/ol-notmuch.el | 7 +- lisp/olivetti/olivetti-pkg.el | 22 +- lisp/olivetti/olivetti.el | 3 +- lisp/org-appear/org-appear-pkg.el | 21 +- lisp/org-appear/org-appear.el | 3 +- lisp/org-brain/org-brain-pkg.el | 24 +- lisp/org-brain/org-brain.el | 3 +- lisp/org-cliplink/org-cliplink-pkg.el | 19 +- lisp/org-cliplink/org-cliplink-transport.el | 1 - lisp/org-cliplink/org-cliplink.el | 3 +- lisp/org-drill/org-drill-pkg.el | 28 +- lisp/org-drill/org-drill.el | 3 +- .../org-fancy-priorities-pkg.el | 22 +- .../org-fancy-priorities.el | 3 +- lisp/org-fragtog/org-fragtog-pkg.el | 19 +- lisp/org-fragtog/org-fragtog.el | 3 +- lisp/org-ref/doi-utils.el | 1 - lisp/org-ref/org-ref-bibtex.el | 1 - lisp/org-ref/org-ref-helm.el | 1 - lisp/org-ref/org-ref-ivy.el | 1 - lisp/org-ref/org-ref-pkg.el | 44 +- lisp/org-ref/org-ref.el | 3 +- lisp/org-roam-bibtex/org-roam-bibtex-pkg.el | 30 +- lisp/org-roam-bibtex/org-roam-bibtex.el | 3 +- .../org-roam-timestamps-pkg.el | 24 +- .../org-roam-timestamps.el | 3 +- lisp/org-roam-ui/org-roam-ui-pkg.el | 20 +- lisp/org-roam-ui/org-roam-ui.el | 3 +- lisp/org-roam/org-roam-capture.el | 3 +- lisp/org-roam/org-roam-compat.el | 3 +- lisp/org-roam/org-roam-dailies.el | 3 +- lisp/org-roam/org-roam-db.el | 5 +- lisp/org-roam/org-roam-export.el | 3 +- lisp/org-roam/org-roam-graph.el | 3 +- lisp/org-roam/org-roam-id.el | 3 +- lisp/org-roam/org-roam-log.el | 3 +- lisp/org-roam/org-roam-migrate.el | 3 +- lisp/org-roam/org-roam-mode.el | 86 +- lisp/org-roam/org-roam-node.el | 115 +- lisp/org-roam/org-roam-overlay.el | 3 +- lisp/org-roam/org-roam-pkg.el | 30 +- lisp/org-roam/org-roam-protocol.el | 3 +- lisp/org-roam/org-roam-utils.el | 6 +- lisp/org-roam/org-roam.el | 5 +- lisp/org-roam/org-roam.info | 8 +- .../org-sticky-header-pkg.el | 24 +- lisp/org-sticky-header/org-sticky-header.el | 3 +- lisp/org-superstar/org-superstar-pkg.el | 24 +- lisp/org-superstar/org-superstar.el | 3 +- .../org-table-sticky-header-pkg.el | 23 +- .../org-table-sticky-header.el | 3 +- lisp/org/.dir-locals.el | 2 +- lisp/org/CONTRIBUTE.org | 4 +- lisp/org/Makefile | 13 +- lisp/org/README-elpa | 20 +- lisp/org/README.org | 5 +- lisp/org/doc/doc-setup.org | 2 +- lisp/org/doc/org-guide.org | 349 +- lisp/org/doc/org-manual.org | 2472 +- lisp/org/doc/org-version.inc | 4 +- lisp/org/doc/org.texi | 2407 +- lisp/org/doc/orgcard.tex | 21 +- lisp/org/doc/orgguide.texi | 386 +- lisp/org/etc/ORG-NEWS | 1744 +- lisp/org/etc/styles/README | 2 +- lisp/org/local.mk | 2 +- lisp/org/ob-C.el | 61 +- lisp/org/ob-R.el | 58 +- lisp/org/ob-awk.el | 20 +- lisp/org/ob-calc.el | 36 +- lisp/org/ob-clojure.el | 174 +- lisp/org/ob-comint.el | 177 +- lisp/org/ob-core.el | 784 +- lisp/org/ob-css.el | 4 +- lisp/org/ob-ditaa.el | 11 +- lisp/org/ob-dot.el | 13 +- lisp/org/ob-emacs-lisp.el | 26 +- lisp/org/ob-eshell.el | 16 +- lisp/org/ob-eval.el | 19 +- lisp/org/ob-exp.el | 448 +- lisp/org/ob-forth.el | 7 +- lisp/org/ob-fortran.el | 36 +- lisp/org/ob-gnuplot.el | 44 +- lisp/org/ob-groovy.el | 12 +- lisp/org/ob-haskell.el | 226 +- lisp/org/ob-java.el | 8 +- lisp/org/ob-js.el | 17 +- lisp/org/ob-julia.el | 37 +- lisp/org/ob-latex.el | 36 +- lisp/org/ob-lilypond.el | 125 +- lisp/org/ob-lisp.el | 72 +- lisp/org/ob-lob.el | 8 +- lisp/org/ob-lua.el | 120 +- lisp/org/ob-makefile.el | 5 +- lisp/org/ob-matlab.el | 2 +- lisp/org/ob-maxima.el | 129 +- lisp/org/ob-ocaml.el | 9 +- lisp/org/ob-octave.el | 43 +- lisp/org/ob-org.el | 18 +- lisp/org/ob-perl.el | 2 +- lisp/org/ob-plantuml.el | 7 +- lisp/org/ob-processing.el | 9 +- lisp/org/ob-python.el | 459 +- lisp/org/ob-ref.el | 14 +- lisp/org/ob-ruby.el | 58 +- lisp/org/ob-sass.el | 2 +- lisp/org/ob-scheme.el | 125 +- lisp/org/ob-screen.el | 8 +- lisp/org/ob-sed.el | 4 +- lisp/org/ob-shell.el | 122 +- lisp/org/ob-sql.el | 14 +- lisp/org/ob-sqlite.el | 23 +- lisp/org/ob-table.el | 26 +- lisp/org/ob-tangle.el | 159 +- lisp/org/ob.el | 4 +- lisp/org/oc-basic.el | 190 +- lisp/org/oc-biblatex.el | 40 +- lisp/org/oc-bibtex.el | 4 +- lisp/org/oc-csl.el | 188 +- lisp/org/oc-natbib.el | 25 +- lisp/org/oc.el | 226 +- lisp/org/ol-bbdb.el | 14 +- lisp/org/ol-bibtex.el | 65 +- lisp/org/ol-docview.el | 17 +- lisp/org/ol-doi.el | 5 +- lisp/org/ol-eshell.el | 13 +- lisp/org/ol-eww.el | 5 +- lisp/org/ol-gnus.el | 40 +- lisp/org/ol-info.el | 24 +- lisp/org/ol-irc.el | 4 +- lisp/org/ol-man.el | 54 +- lisp/org/ol-mhe.el | 6 +- lisp/org/ol-rmail.el | 6 +- lisp/org/ol-w3m.el | 4 +- lisp/org/ol.el | 711 +- lisp/org/org-agenda.el | 2234 +- lisp/org/org-archive.el | 34 +- lisp/org/org-attach-git.el | 2 +- lisp/org/org-attach.el | 163 +- lisp/org/org-capture.el | 120 +- lisp/org/org-clock.el | 302 +- lisp/org/org-colview.el | 251 +- lisp/org/org-compat.el | 287 +- lisp/org/org-crypt.el | 64 +- lisp/org/org-ctags.el | 111 +- lisp/org/org-cycle.el | 75 +- lisp/org/org-datetree.el | 69 +- lisp/org/org-duration.el | 211 +- lisp/org/org-element-ast.el | 1151 + lisp/org/org-element.el | 6356 ++-- lisp/org/org-entities.el | 34 +- lisp/org/org-faces.el | 19 +- lisp/org/org-feed.el | 16 +- lisp/org/org-fold-core.el | 361 +- lisp/org/org-fold.el | 176 +- lisp/org/org-footnote.el | 77 +- lisp/org/org-goto.el | 30 +- lisp/org/org-habit.el | 17 +- lisp/org/org-id.el | 301 +- lisp/org/org-indent.el | 19 +- lisp/org/org-inlinetask.el | 19 +- lisp/org/org-keys.el | 163 +- lisp/org/org-lint.el | 635 +- lisp/org/org-list.el | 398 +- lisp/org/org-loaddefs.el | 2628 +- lisp/org/org-macro.el | 54 +- lisp/org/org-macs.el | 578 +- lisp/org/org-mobile.el | 20 +- lisp/org/org-mouse.el | 49 +- lisp/org/org-num.el | 16 +- lisp/org/org-pcomplete.el | 65 +- lisp/org/org-persist.el | 679 +- lisp/org/org-pkg.el | 2 +- lisp/org/org-plot.el | 10 +- lisp/org/org-protocol.el | 73 +- lisp/org/org-refile.el | 209 +- lisp/org/org-src.el | 355 +- lisp/org/org-table.el | 635 +- lisp/org/org-tempo.el | 10 +- lisp/org/org-timer.el | 65 +- lisp/org/org-version.el | 4 +- lisp/org/org.el | 5519 ++-- lisp/org/org.info | 5705 ++-- lisp/org/orgguide.info | 651 +- lisp/org/ox-ascii.el | 138 +- lisp/org/ox-beamer.el | 174 +- lisp/org/ox-html.el | 325 +- lisp/org/ox-icalendar.el | 427 +- lisp/org/ox-koma-letter.el | 30 +- lisp/org/ox-latex.el | 684 +- lisp/org/ox-man.el | 60 +- lisp/org/ox-md.el | 72 +- lisp/org/ox-odt.el | 316 +- lisp/org/ox-org.el | 47 +- lisp/org/ox-publish.el | 168 +- lisp/org/ox-texinfo.el | 174 +- lisp/org/ox.el | 2025 +- lisp/orgit/orgit-pkg.el | 30 +- lisp/orgit/orgit.el | 20 +- lisp/ov/ov-pkg.el | 14 +- lisp/ov/ov.el | 3 +- lisp/ox-pandoc/ox-pandoc-pkg.el | 30 +- lisp/ox-pandoc/ox-pandoc.el | 39 +- lisp/ox-reveal/ox-reveal-pkg.el | 21 +- lisp/ox-reveal/ox-reveal.el | 3 +- lisp/ox-tufte/ox-tufte-pkg.el | 16 +- lisp/ox-tufte/ox-tufte.el | 3 +- lisp/page-break-lines/page-break-lines-pkg.el | 22 +- lisp/page-break-lines/page-break-lines.el | 3 +- lisp/parsebib/parsebib-pkg.el | 22 +- lisp/parsebib/parsebib.el | 9 +- lisp/pdf-tools/pdf-tools-pkg.el | 26 +- lisp/pdf-tools/pdf-tools.el | 3 +- lisp/persist/persist-pkg.el | 2 +- lisp/persist/persist.el | 90 +- lisp/persist/persist.texi | 22 +- lisp/persist/test/persist-tests.el | 102 +- lisp/pfuture/pfuture-pkg.el | 19 +- lisp/pfuture/pfuture.el | 3 +- lisp/php-mode/php-align.el | 1 - lisp/php-mode/php-complete.el | 1 - lisp/php-mode/php-defs.el | 1 - lisp/php-mode/php-face.el | 1 - lisp/php-mode/php-flymake.el | 1 - lisp/php-mode/php-format.el | 1 - lisp/php-mode/php-ide-phpactor.el | 1 - lisp/php-mode/php-ide.el | 1 - lisp/php-mode/php-local-manual.el | 11 +- lisp/php-mode/php-mode-debug.el | 1 - lisp/php-mode/php-mode-pkg.el | 19 +- lisp/php-mode/php-mode.el | 3 +- lisp/php-mode/php-project.el | 1 - lisp/php-mode/php.el | 49 +- lisp/pkg-info/pkg-info-pkg.el | 22 +- lisp/pkg-info/pkg-info.el | 3 +- lisp/plantuml-mode/plantuml-mode-pkg.el | 15 +- lisp/plantuml-mode/plantuml-mode.el | 53 +- lisp/polymode/polymode-base.el | 14 +- lisp/polymode/polymode-classes.el | 19 +- lisp/polymode/polymode-compat.el | 113 +- lisp/polymode/polymode-core.el | 302 +- lisp/polymode/polymode-debug.el | 6 +- lisp/polymode/polymode-export.el | 10 +- lisp/polymode/polymode-methods.el | 38 +- lisp/polymode/polymode-pkg.el | 19 +- lisp/polymode/polymode-test-utils.el | 28 +- lisp/polymode/polymode-weave.el | 8 +- lisp/polymode/polymode.el | 49 +- lisp/popup/popup-pkg.el | 22 +- lisp/popup/popup.el | 3 +- lisp/popwin/popwin-pkg.el | 22 +- lisp/popwin/popwin.el | 3 +- lisp/pos-tip/pos-tip-pkg.el | 13 +- lisp/pos-tip/pos-tip.el | 3 +- lisp/posframe/posframe-benchmark.el | 1 - lisp/posframe/posframe-pkg.el | 22 +- lisp/posframe/posframe.el | 3 +- lisp/powershell/powershell-pkg.el | 22 +- lisp/powershell/powershell.el | 77 +- lisp/pythonic/pythonic-pkg.el | 26 +- lisp/pythonic/pythonic.el | 3 +- lisp/restart-emacs/restart-emacs-pkg.el | 22 +- lisp/restart-emacs/restart-emacs.el | 3 +- lisp/s/s-pkg.el | 21 +- lisp/s/s.el | 3 +- lisp/seq/seq-pkg.el | 2 +- lisp/simple-httpd/simple-httpd-pkg.el | 19 +- lisp/simple-httpd/simple-httpd.el | 3 +- lisp/spacemacs-theme/spacemacs-dark-theme.el | 1 + lisp/spacemacs-theme/spacemacs-light-theme.el | 1 + lisp/spacemacs-theme/spacemacs-theme-pkg.el | 14 +- lisp/spacemacs-theme/spacemacs-theme.el | 278 +- lisp/sphinx-doc/sphinx-doc-pkg.el | 26 +- lisp/sphinx-doc/sphinx-doc.el | 3 +- lisp/srefactor/srefactor-lisp.el | 1 - lisp/srefactor/srefactor-pkg.el | 17 +- lisp/srefactor/srefactor-ui.el | 1 - lisp/srefactor/srefactor.el | 3 +- .../stickyfunc-enhance-pkg.el | 17 +- lisp/stickyfunc-enhance/stickyfunc-enhance.el | 3 +- .../string-inflection-pkg.el | 21 +- lisp/string-inflection/string-inflection.el | 3 +- lisp/swiper/swiper-pkg.el | 24 +- lisp/swiper/swiper.el | 74 +- lisp/systemd/systemd-pkg.el | 21 +- lisp/systemd/systemd.el | 3 +- lisp/tablist/tablist-pkg.el | 21 +- lisp/tablist/tablist.el | 3 +- lisp/transient/transient-pkg.el | 28 +- lisp/transient/transient.el | 800 +- lisp/transient/transient.info | 612 +- lisp/treemacs-magit/treemacs-magit-pkg.el | 25 +- lisp/treemacs-magit/treemacs-magit.el | 3 +- lisp/treemacs/Changelog.org | 3 + lisp/treemacs/treemacs-compatibility.el | 2 +- lisp/treemacs/treemacs-core-utils.el | 13 +- lisp/treemacs/treemacs-customization.el | 27 + lisp/treemacs/treemacs-diagnostics.el | 102 - lisp/treemacs/treemacs-follow-mode.el | 5 +- lisp/treemacs/treemacs-icons.el | 2 + lisp/treemacs/treemacs-macros.el | 18 +- lisp/treemacs/treemacs-mode.el | 7 +- lisp/treemacs/treemacs-pkg.el | 35 +- lisp/treemacs/treemacs-scope.el | 15 +- .../treemacs-single-file-git-status.py | 9 +- lisp/treemacs/treemacs.el | 5 +- .../virtual-auto-fill-pkg.el | 26 +- lisp/virtual-auto-fill/virtual-auto-fill.el | 3 +- .../visual-fill-column-pkg.el | 19 +- lisp/visual-fill-column/visual-fill-column.el | 9 +- lisp/vterm/vterm-pkg.el | 22 +- lisp/vterm/vterm.el | 3 +- .../web-completion-data-pkg.el | 22 +- .../web-completion-data.el | 3 +- lisp/web-mode/web-mode-pkg.el | 19 +- lisp/web-mode/web-mode.el | 17 +- lisp/websocket/websocket-pkg.el | 22 +- lisp/websocket/websocket.el | 3 +- lisp/with-editor/with-editor-pkg.el | 26 +- lisp/with-editor/with-editor.el | 16 +- lisp/with-editor/with-editor.info | 6 +- .../snippets/python-mode/.yas-setup.el | 110 +- .../yasnippet-snippets-pkg.el | 22 +- lisp/yasnippet-snippets/yasnippet-snippets.el | 3 +- lisp/yasnippet/yasnippet-pkg.el | 21 +- lisp/yasnippet/yasnippet.el | 97 +- 558 files changed, 68349 insertions(+), 26568 deletions(-) create mode 100644 lisp/compat/compat-30.el create mode 100644 lisp/emacsql/README.md delete mode 100644 lisp/emacsql/emacsql-sqlite-common.el create mode 100644 lisp/gnuplot/dir create mode 100644 lisp/gnuplot/gnuplot-eldoc.el create mode 100644 lisp/gnuplot/gnuplot.info delete mode 100644 lisp/ivy/elpa.el create mode 100644 lisp/llama/.dir-locals.el create mode 100644 lisp/magit/.dir-locals.el create mode 100644 lisp/magit/git-commit.el create mode 100644 lisp/magit/magit-dired.el create mode 100644 lisp/org/org-element-ast.el delete mode 100644 lisp/treemacs/treemacs-diagnostics.el diff --git a/lisp/ace-window/ace-window-pkg.el b/lisp/ace-window/ace-window-pkg.el index 859329d6..07a340d7 100644 --- a/lisp/ace-window/ace-window-pkg.el +++ b/lisp/ace-window/ace-window-pkg.el @@ -1,14 +1,10 @@ -(define-package "ace-window" "20220911.358" "Quickly switch windows." +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "ace-window" "20220911.358" + "Quickly switch windows." '((avy "0.5.0")) - :commit "77115afc1b0b9f633084cf7479c767988106c196" :authors - '(("Oleh Krehel" . "ohwoeowho@gmail.com")) - :maintainers - '(("Oleh Krehel" . "ohwoeowho@gmail.com")) - :maintainer - '("Oleh Krehel" . "ohwoeowho@gmail.com") - :keywords - '("window" "location") - :url "https://github.com/abo-abo/ace-window") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/abo-abo/ace-window" + :commit "77115afc1b0b9f633084cf7479c767988106c196" + :revdesc "77115afc1b0b" + :keywords '("window" "location") + :authors '(("Oleh Krehel" . "ohwoeowho@gmail.com")) + :maintainers '(("Oleh Krehel" . "ohwoeowho@gmail.com"))) diff --git a/lisp/ace-window/ace-window.el b/lisp/ace-window/ace-window.el index ccb27832..b93b6335 100644 --- a/lisp/ace-window/ace-window.el +++ b/lisp/ace-window/ace-window.el @@ -5,7 +5,8 @@ ;; Author: Oleh Krehel ;; Maintainer: Oleh Krehel ;; URL: https://github.com/abo-abo/ace-window -;; Version: 0.10.0 +;; Package-Version: 20220911.358 +;; Package-Revision: 77115afc1b0b ;; Package-Requires: ((avy "0.5.0")) ;; Keywords: window, location diff --git a/lisp/all-the-icons-ivy-rich/all-the-icons-ivy-rich-pkg.el b/lisp/all-the-icons-ivy-rich/all-the-icons-ivy-rich-pkg.el index 9dd40919..c22fa189 100644 --- a/lisp/all-the-icons-ivy-rich/all-the-icons-ivy-rich-pkg.el +++ b/lisp/all-the-icons-ivy-rich/all-the-icons-ivy-rich-pkg.el @@ -1,16 +1,12 @@ -(define-package "all-the-icons-ivy-rich" "20230420.1234" "Better experience with icons for ivy" - '((emacs "25.1") - (ivy-rich "0.1.0") +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "all-the-icons-ivy-rich" "20230420.1234" + "Better experience with icons for ivy." + '((emacs "25.1") + (ivy-rich "0.1.0") (all-the-icons "2.2.0")) - :commit "c098cc85123a401b0ab8f2afd3a25853e61d7d28" :authors - '(("Vincent Zhang" . "seagle0128@gmail.com")) - :maintainers - '(("Vincent Zhang" . "seagle0128@gmail.com")) - :maintainer - '("Vincent Zhang" . "seagle0128@gmail.com") - :keywords - '("convenience" "icons" "ivy") - :url "https://github.com/seagle0128/all-the-icons-ivy-rich") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/seagle0128/all-the-icons-ivy-rich" + :commit "c098cc85123a401b0ab8f2afd3a25853e61d7d28" + :revdesc "c098cc85123a" + :keywords '("convenience" "icons" "ivy") + :authors '(("Vincent Zhang" . "seagle0128@gmail.com")) + :maintainers '(("Vincent Zhang" . "seagle0128@gmail.com"))) diff --git a/lisp/all-the-icons-ivy-rich/all-the-icons-ivy-rich.el b/lisp/all-the-icons-ivy-rich/all-the-icons-ivy-rich.el index cc3ace13..02aea1a0 100644 --- a/lisp/all-the-icons-ivy-rich/all-the-icons-ivy-rich.el +++ b/lisp/all-the-icons-ivy-rich/all-the-icons-ivy-rich.el @@ -4,7 +4,8 @@ ;; Author: Vincent Zhang ;; Homepage: https://github.com/seagle0128/all-the-icons-ivy-rich -;; Version: 1.9.0 +;; Package-Version: 20230420.1234 +;; Package-Revision: c098cc85123a ;; Package-Requires: ((emacs "25.1") (ivy-rich "0.1.0") (all-the-icons "2.2.0")) ;; Keywords: convenience, icons, ivy diff --git a/lisp/all-the-icons/all-the-icons-faces.el b/lisp/all-the-icons/all-the-icons-faces.el index 4408e97b..9baa891d 100644 --- a/lisp/all-the-icons/all-the-icons-faces.el +++ b/lisp/all-the-icons/all-the-icons-faces.el @@ -1,9 +1,8 @@ -;;; all-the-icons-faces.el --- A module of faces for all-the-icons +;;; all-the-icons-faces.el --- A module of faces for all-the-icons -*- lexical-binding: t; -*- ;; Copyright (C) 2016 Dominic Charlesworth ;; Author: Dominic Charlesworth -;; Version: 1.0.0 ;; Package-Requires: ((emacs "24.3")) ;; URL: https://github.com/domtronn/all-the-icons.el ;; Keywords: convenient, lisp diff --git a/lisp/all-the-icons/all-the-icons-pkg.el b/lisp/all-the-icons/all-the-icons-pkg.el index 67d5195d..d30e1f43 100644 --- a/lisp/all-the-icons/all-the-icons-pkg.el +++ b/lisp/all-the-icons/all-the-icons-pkg.el @@ -1,14 +1,10 @@ -(define-package "all-the-icons" "20240623.1800" "A library for inserting Developer icons" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "all-the-icons" "20250527.927" + "A library for inserting Developer icons." '((emacs "24.3")) - :commit "39ef44f810c34e8900978788467cc675870bcd19" :authors - '(("Dominic Charlesworth" . "dgc336@gmail.com")) - :maintainers - '(("Dominic Charlesworth" . "dgc336@gmail.com")) - :maintainer - '("Dominic Charlesworth" . "dgc336@gmail.com") - :keywords - '("convenient" "lisp") - :url "https://github.com/domtronn/all-the-icons.el") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/domtronn/all-the-icons.el" + :commit "4778632b29c8c8d2b7cd9ce69535d0be01d846f9" + :revdesc "4778632b29c8" + :keywords '("convenient" "lisp") + :authors '(("Dominic Charlesworth" . "dgc336@gmail.com")) + :maintainers '(("Dominic Charlesworth" . "dgc336@gmail.com"))) diff --git a/lisp/all-the-icons/all-the-icons.el b/lisp/all-the-icons/all-the-icons.el index 682af163..606d3b86 100644 --- a/lisp/all-the-icons/all-the-icons.el +++ b/lisp/all-the-icons/all-the-icons.el @@ -3,7 +3,8 @@ ;; Copyright (C) 2016 Dominic Charlesworth ;; Author: Dominic Charlesworth -;; Version: 5.0.0 +;; Package-Version: 20250527.927 +;; Package-Revision: 4778632b29c8 ;; Package-Requires: ((emacs "24.3")) ;; URL: https://github.com/domtronn/all-the-icons.el ;; Keywords: convenient, lisp diff --git a/lisp/all-the-icons/data/data-alltheicons.el b/lisp/all-the-icons/data/data-alltheicons.el index 3322500f..e5446a5f 100644 --- a/lisp/all-the-icons/data/data-alltheicons.el +++ b/lisp/all-the-icons/data/data-alltheicons.el @@ -1,3 +1,5 @@ +;; -*- lexical-binding: t -*- + (defvar all-the-icons-data/alltheicons-alist '( diff --git a/lisp/all-the-icons/data/data-faicons.el b/lisp/all-the-icons/data/data-faicons.el index 6ab04806..eb56602e 100644 --- a/lisp/all-the-icons/data/data-faicons.el +++ b/lisp/all-the-icons/data/data-faicons.el @@ -1,3 +1,5 @@ +;; -*- lexical-binding: t -*- + (defvar all-the-icons-data/fa-icon-alist '( diff --git a/lisp/all-the-icons/data/data-fileicons.el b/lisp/all-the-icons/data/data-fileicons.el index bbeda49e..f5d09a4f 100644 --- a/lisp/all-the-icons/data/data-fileicons.el +++ b/lisp/all-the-icons/data/data-fileicons.el @@ -1,3 +1,5 @@ +;; -*- lexical-binding: t -*- + (defvar all-the-icons-data/file-icon-alist '( diff --git a/lisp/all-the-icons/data/data-material.el b/lisp/all-the-icons/data/data-material.el index bafcfe78..aedb84b9 100644 --- a/lisp/all-the-icons/data/data-material.el +++ b/lisp/all-the-icons/data/data-material.el @@ -1,3 +1,5 @@ +;; -*- lexical-binding: t -*- + (defvar all-the-icons-data/material-icons-alist '(("3d_rotation" . "\xe84d") ("ac_unit" . "\xeb3b") diff --git a/lisp/all-the-icons/data/data-octicons.el b/lisp/all-the-icons/data/data-octicons.el index 432251ed..069dbb5a 100644 --- a/lisp/all-the-icons/data/data-octicons.el +++ b/lisp/all-the-icons/data/data-octicons.el @@ -1,3 +1,5 @@ +;; -*- lexical-binding: t -*- + (defvar all-the-icons-data/octicons-alist '( diff --git a/lisp/all-the-icons/data/data-weathericons.el b/lisp/all-the-icons/data/data-weathericons.el index 676581c3..daac9773 100644 --- a/lisp/all-the-icons/data/data-weathericons.el +++ b/lisp/all-the-icons/data/data-weathericons.el @@ -1,3 +1,5 @@ +;; -*- lexical-binding: t -*- + (defvar all-the-icons-data/weather-icons-alist '( diff --git a/lisp/amx/amx-pkg.el b/lisp/amx/amx-pkg.el index 25b7dd84..ce955fce 100644 --- a/lisp/amx/amx-pkg.el +++ b/lisp/amx/amx-pkg.el @@ -1,16 +1,12 @@ -(define-package "amx" "20230413.1210" "Alternative M-x with extra features." +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "amx" "20230413.1210" + "Alternative M-x with extra features." '((emacs "24.4") - (s "0")) - :commit "1c2428d21e9d2ee8bee944b572a39ca8c91ca13b" :authors - '(("Ryan C. Thompson" . "rct@thompsonclan.org") - ("Cornelius Mika" . "cornelius.mika@gmail.com")) - :maintainers - '(("Ryan C. Thompson" . "rct@thompsonclan.org")) - :maintainer - '("Ryan C. Thompson" . "rct@thompsonclan.org") - :keywords - '("convenience" "usability" "completion") - :url "http://github.com/DarwinAwardWinner/amx/") -;; Local Variables: -;; no-byte-compile: t -;; End: + (s "0")) + :url "http://github.com/DarwinAwardWinner/amx/" + :commit "1c2428d21e9d2ee8bee944b572a39ca8c91ca13b" + :revdesc "1c2428d21e9d" + :keywords '("convenience" "usability" "completion") + :authors '(("Ryan C. Thompson" . "rct@thompsonclan.org") + ("Cornelius Mika" . "cornelius.mika@gmail.com")) + :maintainers '(("Ryan C. Thompson" . "rct@thompsonclan.org"))) diff --git a/lisp/amx/amx.el b/lisp/amx/amx.el index f0bdfc6e..7cd6a69d 100644 --- a/lisp/amx/amx.el +++ b/lisp/amx/amx.el @@ -9,7 +9,8 @@ ;; Maintainer: Ryan C. Thompson ;; URL: http://github.com/DarwinAwardWinner/amx/ ;; Package-Requires: ((emacs "24.4") (s "0")) -;; Version: 3.4 +;; Package-Version: 20230413.1210 +;; Package-Revision: 1c2428d21e9d ;; Keywords: convenience, usability, completion ;; This file is not part of GNU Emacs. diff --git a/lisp/anaconda-mode/anaconda-mode-pkg.el b/lisp/anaconda-mode/anaconda-mode-pkg.el index 78d0db34..3f357b17 100644 --- a/lisp/anaconda-mode/anaconda-mode-pkg.el +++ b/lisp/anaconda-mode/anaconda-mode-pkg.el @@ -1,18 +1,14 @@ -(define-package "anaconda-mode" "20250310.1512" "Code navigation, documentation lookup and completion for Python" - '((emacs "25.1") +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "anaconda-mode" "20250430.227" + "Code navigation, documentation lookup and completion for Python." + '((emacs "25.1") (pythonic "0.1.0") - (dash "2.6.0") - (s "1.9") - (f "0.16.2")) - :commit "28b3e0088ac7113390aa006bf277c8aa14e561a2" :authors - '(("Artem Malyshev" . "proofit404@gmail.com")) - :maintainers - '(("Artem Malyshev" . "proofit404@gmail.com")) - :maintainer - '("Artem Malyshev" . "proofit404@gmail.com") - :keywords - '("convenience" "anaconda") - :url "https://github.com/proofit404/anaconda-mode") -;; Local Variables: -;; no-byte-compile: t -;; End: + (dash "2.6.0") + (s "1.9") + (f "0.16.2")) + :url "https://github.com/proofit404/anaconda-mode" + :commit "ee1562c6b443be9208910c700e229824b2f1af7a" + :revdesc "ee1562c6b443" + :keywords '("convenience" "anaconda") + :authors '(("Artem Malyshev" . "proofit404@gmail.com")) + :maintainers '(("Artem Malyshev" . "proofit404@gmail.com"))) diff --git a/lisp/anaconda-mode/anaconda-mode.el b/lisp/anaconda-mode/anaconda-mode.el index 2bcc03b3..5ec2af7e 100644 --- a/lisp/anaconda-mode/anaconda-mode.el +++ b/lisp/anaconda-mode/anaconda-mode.el @@ -4,7 +4,8 @@ ;; Author: Artem Malyshev ;; URL: https://github.com/proofit404/anaconda-mode -;; Version: 0.1.16 +;; Package-Version: 20250430.227 +;; Package-Revision: ee1562c6b443 ;; Package-Requires: ((emacs "25.1") (pythonic "0.1.0") (dash "2.6.0") (s "1.9") (f "0.16.2")) ;; Keywords: convenience anaconda diff --git a/lisp/anaconda-mode/anaconda-mode.py b/lisp/anaconda-mode/anaconda-mode.py index 225de368..8c35e35b 100644 --- a/lisp/anaconda-mode/anaconda-mode.py +++ b/lisp/anaconda-mode/anaconda-mode.py @@ -77,7 +77,8 @@ def install_deps_pip(): import venv temp_dir = pathlib.Path(tempfile.mkdtemp()) venv.create(temp_dir, with_pip=True) - cmd = [temp_dir / 'bin' / 'pip', 'install', '--target', server_directory] + binname = 'Scripts' if sys.platform == 'win32' else 'bin' + cmd = [temp_dir / binname / 'pip', 'install', '--target', server_directory] cmd.extend(missing_dependencies) try: subprocess.check_call(cmd) diff --git a/lisp/async/async-bytecomp.el b/lisp/async/async-bytecomp.el index 7f46ed91..eadb5df6 100644 --- a/lisp/async/async-bytecomp.el +++ b/lisp/async/async-bytecomp.el @@ -66,7 +66,7 @@ all packages are always compiled asynchronously." "The variable used by `async-inject-variables' when (re)compiling async.") (defun async-bytecomp--file-to-comp-buffer (file-or-dir &optional quiet type) - (let ((bn (file-name-nondirectory file-or-dir)) + (let ((bn (file-name-nondirectory (directory-file-name file-or-dir))) (action-name (pcase type ('file "File") ('directory "Directory")))) diff --git a/lisp/async/async-pkg.el b/lisp/async/async-pkg.el index baddf1d0..b74d1c7c 100644 --- a/lisp/async/async-pkg.el +++ b/lisp/async/async-pkg.el @@ -1,14 +1,10 @@ -(define-package "async" "20241126.810" "Asynchronous processing in Emacs" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "async" "20250325.509" + "Asynchronous processing in Emacs." '((emacs "24.4")) - :commit "b99658e831bc7e7d20ed4bb0a85bdb5c7dd74142" :authors - '(("John Wiegley" . "jwiegley@gmail.com")) - :maintainers - '(("Thierry Volpiatto" . "thievol@posteo.net")) - :maintainer - '("Thierry Volpiatto" . "thievol@posteo.net") - :keywords - '("async") - :url "https://github.com/jwiegley/emacs-async") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/jwiegley/emacs-async" + :commit "bb3f31966ed65a76abe6fa4f80a960a2917f554e" + :revdesc "bb3f31966ed6" + :keywords '("async") + :authors '(("John Wiegley" . "jwiegley@gmail.com")) + :maintainers '(("Thierry Volpiatto" . "thievol@posteo.net"))) diff --git a/lisp/async/async.el b/lisp/async/async.el index fe4091f4..a1912597 100644 --- a/lisp/async/async.el +++ b/lisp/async/async.el @@ -6,7 +6,8 @@ ;; Maintainer: Thierry Volpiatto ;; Created: 18 Jun 2012 -;; Version: 1.9.9 +;; Package-Version: 20250325.509 +;; Package-Revision: bb3f31966ed6 ;; Package-Requires: ((emacs "24.4")) ;; Keywords: async diff --git a/lisp/avy/avy-pkg.el b/lisp/avy/avy-pkg.el index b93988a3..c0614c52 100644 --- a/lisp/avy/avy-pkg.el +++ b/lisp/avy/avy-pkg.el @@ -1,15 +1,11 @@ -(define-package "avy" "20241101.1357" "Jump to arbitrary positions in visible text and select text quickly." - '((emacs "24.1") +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "avy" "20241101.1357" + "Jump to arbitrary positions in visible text and select text quickly." + '((emacs "24.1") (cl-lib "0.5")) - :commit "933d1f36cca0f71e4acb5fac707e9ae26c536264" :authors - '(("Oleh Krehel" . "ohwoeowho@gmail.com")) - :maintainers - '(("Oleh Krehel" . "ohwoeowho@gmail.com")) - :maintainer - '("Oleh Krehel" . "ohwoeowho@gmail.com") - :keywords - '("point" "location") - :url "https://github.com/abo-abo/avy") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/abo-abo/avy" + :commit "933d1f36cca0f71e4acb5fac707e9ae26c536264" + :revdesc "933d1f36cca0" + :keywords '("point" "location") + :authors '(("Oleh Krehel" . "ohwoeowho@gmail.com")) + :maintainers '(("Oleh Krehel" . "ohwoeowho@gmail.com"))) diff --git a/lisp/avy/avy.el b/lisp/avy/avy.el index e037d1c6..5606c1ae 100644 --- a/lisp/avy/avy.el +++ b/lisp/avy/avy.el @@ -4,7 +4,8 @@ ;; Author: Oleh Krehel ;; URL: https://github.com/abo-abo/avy -;; Version: 0.5.0 +;; Package-Version: 20241101.1357 +;; Package-Revision: 933d1f36cca0 ;; Package-Requires: ((emacs "24.1") (cl-lib "0.5")) ;; Keywords: point, location diff --git a/lisp/biblio-core/biblio-core-pkg.el b/lisp/biblio-core/biblio-core-pkg.el index f3c7c00d..3a1c5842 100644 --- a/lisp/biblio-core/biblio-core-pkg.el +++ b/lisp/biblio-core/biblio-core-pkg.el @@ -1,17 +1,13 @@ -(define-package "biblio-core" "20230202.1721" "A framework for looking up and displaying bibliographic entries" - '((emacs "24.3") +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "biblio-core" "20230202.1721" + "A framework for looking up and displaying bibliographic entries." + '((emacs "24.3") (let-alist "1.0.4") - (seq "1.11") - (dash "2.12.1")) - :commit "ee52f6cda82ea6fbc3b400e7b12132595cc0374c" :authors - '(("Clément Pit-Claudel" . "clement.pitclaudel@live.com")) - :maintainers - '(("Clément Pit-Claudel" . "clement.pitclaudel@live.com")) - :maintainer - '("Clément Pit-Claudel" . "clement.pitclaudel@live.com") - :keywords - '("bib" "tex" "convenience" "hypermedia") - :url "https://github.com/cpitclaudel/biblio.el") -;; Local Variables: -;; no-byte-compile: t -;; End: + (seq "1.11") + (dash "2.12.1")) + :url "https://github.com/cpitclaudel/biblio.el" + :commit "ee52f6cda82ea6fbc3b400e7b12132595cc0374c" + :revdesc "ee52f6cda82e" + :keywords '("bib" "tex" "convenience" "hypermedia") + :authors '(("Clément Pit-Claudel" . "clement.pitclaudel@live.com")) + :maintainers '(("Clément Pit-Claudel" . "clement.pitclaudel@live.com"))) diff --git a/lisp/biblio-core/biblio-core.el b/lisp/biblio-core/biblio-core.el index 917346c2..582f9c14 100644 --- a/lisp/biblio-core/biblio-core.el +++ b/lisp/biblio-core/biblio-core.el @@ -3,7 +3,8 @@ ;; Copyright (C) 2016 Clément Pit-Claudel ;; Author: Clément Pit-Claudel -;; Version: 0.3 +;; Package-Version: 20230202.1721 +;; Package-Revision: ee52f6cda82e ;; Package-Requires: ((emacs "24.3") (let-alist "1.0.4") (seq "1.11") (dash "2.12.1")) ;; Keywords: bib, tex, convenience, hypermedia ;; URL: https://github.com/cpitclaudel/biblio.el diff --git a/lisp/biblio/biblio-dblp.el b/lisp/biblio/biblio-dblp.el index 5eacd2be..833c5b5b 100644 --- a/lisp/biblio/biblio-dblp.el +++ b/lisp/biblio/biblio-dblp.el @@ -65,7 +65,7 @@ (defun biblio-dblp--url (query) "Create a DBLP url to look up QUERY." - (format "https://dblp.uni-trier.de/search/publ/api?q=%s&format=xml" (url-encode-url query))) + (format "https://dblp.org/search/publ/api?q=%s&format=xml" (url-encode-url query))) ;;;###autoload (defun biblio-dblp-backend (command &optional arg &rest more) diff --git a/lisp/biblio/biblio-pkg.el b/lisp/biblio/biblio-pkg.el index 7c2da6f7..15f33d1e 100644 --- a/lisp/biblio/biblio-pkg.el +++ b/lisp/biblio/biblio-pkg.el @@ -1,15 +1,11 @@ -(define-package "biblio" "20250102.1345" "Browse and import bibliographic references and BibTeX records from CrossRef, arXiv, DBLP, HAL, IEEE Xplore, Dissemin, and doi.org" - '((emacs "24.3") +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "biblio" "20250409.2132" + "Browse and import bibliographic references and BibTeX records from CrossRef, arXiv, DBLP, HAL, IEEE Xplore, Dissemin, and doi.org." + '((emacs "24.3") (biblio-core "0.3")) - :commit "b700f0f2929829b2ca971511c5ebe61c67027e9f" :authors - '(("Clément Pit-Claudel" . "clement.pitclaudel@live.com")) - :maintainers - '(("Clément Pit-Claudel" . "clement.pitclaudel@live.com")) - :maintainer - '("Clément Pit-Claudel" . "clement.pitclaudel@live.com") - :keywords - '("bib" "tex" "convenience" "hypermedia") - :url "https://github.com/cpitclaudel/biblio.el") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/cpitclaudel/biblio.el" + :commit "0314982c0ca03d0f8e0ddbe9fc20588c35021098" + :revdesc "0314982c0ca0" + :keywords '("bib" "tex" "convenience" "hypermedia") + :authors '(("Clément Pit-Claudel" . "clement.pitclaudel@live.com")) + :maintainers '(("Clément Pit-Claudel" . "clement.pitclaudel@live.com"))) diff --git a/lisp/biblio/biblio.el b/lisp/biblio/biblio.el index 949f8290..0edfa056 100644 --- a/lisp/biblio/biblio.el +++ b/lisp/biblio/biblio.el @@ -3,7 +3,8 @@ ;; Copyright (C) 2016 Clément Pit-Claudel ;; Author: Clément Pit-Claudel -;; Version: 0.3 +;; Package-Version: 20250409.2132 +;; Package-Revision: 0314982c0ca0 ;; Package-Requires: ((emacs "24.3") (biblio-core "0.3")) ;; Keywords: bib, tex, convenience, hypermedia ;; URL: https://github.com/cpitclaudel/biblio.el diff --git a/lisp/bibtex-completion/bibtex-completion-pkg.el b/lisp/bibtex-completion/bibtex-completion-pkg.el index e7cb8ea9..4635c1e8 100644 --- a/lisp/bibtex-completion/bibtex-completion-pkg.el +++ b/lisp/bibtex-completion/bibtex-completion-pkg.el @@ -1,19 +1,16 @@ -(define-package "bibtex-completion" "20241116.726" "A BibTeX backend for completion frameworks" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "bibtex-completion" "20241116.726" + "A BibTeX backend for completion frameworks." '((parsebib "6.0") - (s "1.9.0") - (dash "2.6.0") - (f "0.16.2") - (cl-lib "0.5") - (biblio "0.2") - (emacs "26.1")) - :commit "6064e8625b2958f34d6d40312903a85c173b5261" :authors - '(("Titus von der Malsburg" . "malsburg@posteo.de") - ("Justin Burkett" . "justin@burkett.cc")) - :maintainers - '(("Titus von der Malsburg" . "malsburg@posteo.de")) - :maintainer - '("Titus von der Malsburg" . "malsburg@posteo.de") - :url "https://github.com/tmalsburg/helm-bibtex") -;; Local Variables: -;; no-byte-compile: t -;; End: + (s "1.9.0") + (dash "2.6.0") + (f "0.16.2") + (cl-lib "0.5") + (biblio "0.2") + (emacs "26.1")) + :url "https://github.com/tmalsburg/helm-bibtex" + :commit "6064e8625b2958f34d6d40312903a85c173b5261" + :revdesc "6064e8625b29" + :authors '(("Titus von der Malsburg" . "malsburg@posteo.de") + ("Justin Burkett" . "justin@burkett.cc")) + :maintainers '(("Titus von der Malsburg" . "malsburg@posteo.de"))) diff --git a/lisp/bibtex-completion/bibtex-completion.el b/lisp/bibtex-completion/bibtex-completion.el index 4e135124..45664a31 100644 --- a/lisp/bibtex-completion/bibtex-completion.el +++ b/lisp/bibtex-completion/bibtex-completion.el @@ -4,7 +4,8 @@ ;; Justin Burkett ;; Maintainer: Titus von der Malsburg ;; URL: https://github.com/tmalsburg/helm-bibtex -;; Version: 1.0.0 +;; Package-Version: 20241116.726 +;; Package-Revision: 6064e8625b29 ;; Package-Requires: ((parsebib "6.0") (s "1.9.0") (dash "2.6.0") (f "0.16.2") (cl-lib "0.5") (biblio "0.2") (emacs "26.1")) ;; This program is free software; you can redistribute it and/or modify diff --git a/lisp/cfrs/cfrs-pkg.el b/lisp/cfrs/cfrs-pkg.el index 0b5bbabd..053ebfc7 100644 --- a/lisp/cfrs/cfrs-pkg.el +++ b/lisp/cfrs/cfrs-pkg.el @@ -1,15 +1,12 @@ -(define-package "cfrs" "20220129.1149" "Child-frame based read-string" - '((emacs "26.1") - (dash "2.11.0") - (s "1.10.0") +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "cfrs" "20220129.1149" + "Child-frame based read-string." + '((emacs "26.1") + (dash "2.11.0") + (s "1.10.0") (posframe "0.6.0")) - :commit "f3a21f237b2a54e6b9f8a420a9da42b4f0a63121" :authors - '(("Alexander Miller" . "alexanderm@web.de")) - :maintainers - '(("Alexander Miller" . "alexanderm@web.de")) - :maintainer - '("Alexander Miller" . "alexanderm@web.de") - :url "https://github.com/Alexander-Miller/cfrs") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/Alexander-Miller/cfrs" + :commit "f3a21f237b2a54e6b9f8a420a9da42b4f0a63121" + :revdesc "f3a21f237b2a" + :authors '(("Alexander Miller" . "alexanderm@web.de")) + :maintainers '(("Alexander Miller" . "alexanderm@web.de"))) diff --git a/lisp/cfrs/cfrs.el b/lisp/cfrs/cfrs.el index 36e59cc8..602756d1 100644 --- a/lisp/cfrs/cfrs.el +++ b/lisp/cfrs/cfrs.el @@ -4,7 +4,8 @@ ;; Author: Alexander Miller ;; Package-Requires: ((emacs "26.1") (dash "2.11.0") (s "1.10.0") (posframe "0.6.0")) -;; Package-Version: 1.6.0 +;; Package-Version: 20220129.1149 +;; Package-Revision: f3a21f237b2a ;; Homepage: https://github.com/Alexander-Miller/cfrs ;; This program is free software; you can redistribute it and/or modify diff --git a/lisp/citeproc/citeproc-pkg.el b/lisp/citeproc/citeproc-pkg.el index 5f9e0ce2..28c658b4 100644 --- a/lisp/citeproc/citeproc-pkg.el +++ b/lisp/citeproc/citeproc-pkg.el @@ -1,22 +1,18 @@ -(define-package "citeproc" "20240722.1110" "A CSL 1.0.2 Citation Processor" - '((emacs "26") - (dash "2.13.0") - (s "1.12.0") - (f "0.18.0") - (queue "0.2") +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "citeproc" "20250525.1011" + "A CSL 1.0.2 Citation Processor." + '((emacs "26") + (dash "2.13.0") + (s "1.12.0") + (f "0.18.0") + (queue "0.2") (string-inflection "1.0") - (org "9") - (parsebib "2.4") - (compat "28.1")) - :commit "54184baaff555b5c7993d566d75dd04ed485b5c0" :authors - '(("András Simonyi" . "andras.simonyi@gmail.com")) - :maintainers - '(("András Simonyi" . "andras.simonyi@gmail.com")) - :maintainer - '("András Simonyi" . "andras.simonyi@gmail.com") - :keywords - '("bib") - :url "https://github.com/andras-simonyi/citeproc-el") -;; Local Variables: -;; no-byte-compile: t -;; End: + (org "9") + (parsebib "2.4") + (compat "28.1")) + :url "https://github.com/andras-simonyi/citeproc-el" + :commit "e3bf1f80bcd64edf4afef564c0d94d38aa567d61" + :revdesc "e3bf1f80bcd6" + :keywords '("bib") + :authors '(("András Simonyi" . "andras.simonyi@gmail.com")) + :maintainers '(("András Simonyi" . "andras.simonyi@gmail.com"))) diff --git a/lisp/citeproc/citeproc-rt.el b/lisp/citeproc/citeproc-rt.el index 26d06222..fb3091f5 100644 --- a/lisp/citeproc/citeproc-rt.el +++ b/lisp/citeproc/citeproc-rt.el @@ -264,7 +264,9 @@ on any dominated branch for which PRED holds." (if (and s (s-matches-p "" s)) (let* ((parsed (citeproc-lib-parse-html-frag s)) (body (cddr (cl-caddr parsed))) - (stripped (if (eq (caar body) 'p) (cl-cddar body) body))) + (stripped (if (and (consp (car body)) (eq (caar body) 'p)) + (cl-cddar body) + body))) (if (= 1 (length stripped)) (citeproc-rt-from-html (car stripped)) (cons nil (mapcar 'citeproc-rt-from-html stripped)))) diff --git a/lisp/citeproc/citeproc.el b/lisp/citeproc/citeproc.el index 6fa01161..09a950cb 100644 --- a/lisp/citeproc/citeproc.el +++ b/lisp/citeproc/citeproc.el @@ -7,7 +7,8 @@ ;; URL: https://github.com/andras-simonyi/citeproc-el ;; Keywords: bib ;; Package-Requires: ((emacs "26") (dash "2.13.0") (s "1.12.0") (f "0.18.0") (queue "0.2") (string-inflection "1.0") (org "9") (parsebib "2.4")(compat "28.1")) -;; Version: 0.9.3 +;; Package-Version: 20250525.1011 +;; Package-Revision: e3bf1f80bcd6 ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by diff --git a/lisp/cl-libify/cl-libify-pkg.el b/lisp/cl-libify/cl-libify-pkg.el index 1481265b..97411ffc 100644 --- a/lisp/cl-libify/cl-libify-pkg.el +++ b/lisp/cl-libify/cl-libify-pkg.el @@ -1,14 +1,10 @@ -(define-package "cl-libify" "20181130.230" "Update elisp code to use cl-lib instead of cl" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "cl-libify" "20181130.230" + "Update elisp code to use cl-lib instead of cl." '((emacs "25")) - :commit "e205b96f944a4f312fd523804cbbaf00027a3c8b" :authors - '(("Steve Purcell" . "steve@sanityinc.com")) - :maintainers - '(("Steve Purcell" . "steve@sanityinc.com")) - :maintainer - '("Steve Purcell" . "steve@sanityinc.com") - :keywords - '("lisp") - :url "https://github.com/purcell/cl-libify") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/purcell/cl-libify" + :commit "e205b96f944a4f312fd523804cbbaf00027a3c8b" + :revdesc "e205b96f944a" + :keywords '("lisp") + :authors '(("Steve Purcell" . "steve@sanityinc.com")) + :maintainers '(("Steve Purcell" . "steve@sanityinc.com"))) diff --git a/lisp/cl-libify/cl-libify.el b/lisp/cl-libify/cl-libify.el index b3a5de7d..03cce39b 100644 --- a/lisp/cl-libify/cl-libify.el +++ b/lisp/cl-libify/cl-libify.el @@ -6,7 +6,8 @@ ;; Keywords: lisp ;; Homepage: https://github.com/purcell/cl-libify ;; Package-Requires: ((emacs "25")) -;; Package-Version: 0 +;; Package-Version: 20181130.230 +;; Package-Revision: e205b96f944a ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by diff --git a/lisp/company-anaconda/company-anaconda-pkg.el b/lisp/company-anaconda/company-anaconda-pkg.el index 8243270c..ea93cb12 100644 --- a/lisp/company-anaconda/company-anaconda-pkg.el +++ b/lisp/company-anaconda/company-anaconda-pkg.el @@ -1,19 +1,15 @@ -(define-package "company-anaconda" "20230821.2126" "Anaconda backend for company-mode" - '((emacs "25.1") - (company "0.8.0") +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "company-anaconda" "20230821.2126" + "Anaconda backend for company-mode." + '((emacs "25.1") + (company "0.8.0") (anaconda-mode "0.1.1") - (cl-lib "0.5.0") - (dash "2.6.0") - (s "1.9")) - :commit "14867265e474f7a919120bbac74870c3256cbacf" :authors - '(("Artem Malyshev" . "proofit404@gmail.com")) - :maintainers - '(("Artem Malyshev" . "proofit404@gmail.com")) - :maintainer - '("Artem Malyshev" . "proofit404@gmail.com") - :keywords - '("convenience" "company" "anaconda") - :url "https://github.com/proofit404/anaconda-mode") -;; Local Variables: -;; no-byte-compile: t -;; End: + (cl-lib "0.5.0") + (dash "2.6.0") + (s "1.9")) + :url "https://github.com/proofit404/anaconda-mode" + :commit "14867265e474f7a919120bbac74870c3256cbacf" + :revdesc "14867265e474" + :keywords '("convenience" "company" "anaconda") + :authors '(("Artem Malyshev" . "proofit404@gmail.com")) + :maintainers '(("Artem Malyshev" . "proofit404@gmail.com"))) diff --git a/lisp/company-anaconda/company-anaconda.el b/lisp/company-anaconda/company-anaconda.el index d6fbc0a1..e524d129 100644 --- a/lisp/company-anaconda/company-anaconda.el +++ b/lisp/company-anaconda/company-anaconda.el @@ -4,7 +4,8 @@ ;; Author: Artem Malyshev ;; URL: https://github.com/proofit404/anaconda-mode -;; Version: 0.2.0 +;; Package-Version: 20230821.2126 +;; Package-Revision: 14867265e474 ;; Package-Requires: ((emacs "25.1") (company "0.8.0") (anaconda-mode "0.1.1") (cl-lib "0.5.0") (dash "2.6.0") (s "1.9")) ;; Keywords: convenience company anaconda diff --git a/lisp/company-ledger/company-ledger-pkg.el b/lisp/company-ledger/company-ledger-pkg.el index c496586e..4009f9e3 100644 --- a/lisp/company-ledger/company-ledger-pkg.el +++ b/lisp/company-ledger/company-ledger-pkg.el @@ -1,15 +1,11 @@ -(define-package "company-ledger" "20210910.250" "Fuzzy auto-completion for Ledger & friends" - '((emacs "24.3") +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "company-ledger" "20210910.250" + "Fuzzy auto-completion for Ledger & friends." + '((emacs "24.3") (company "0.8.0")) - :commit "55fdddd6c5e9c061c685b474ef5e148a4ac9b576" :authors - '(("Debanjum Singh Solanky" . "debanjumATgmailDOTcom")) - :maintainers - '(("Debanjum Singh Solanky" . "debanjumATgmailDOTcom")) - :maintainer - '("Debanjum Singh Solanky" . "debanjumATgmailDOTcom") - :keywords - '("abbrev" "matching" "auto-complete" "beancount" "ledger" "company") - :url "https://github.com/debanjum/company-ledger") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/debanjum/company-ledger" + :commit "55fdddd6c5e9c061c685b474ef5e148a4ac9b576" + :revdesc "55fdddd6c5e9" + :keywords '("abbrev" "matching" "auto-complete" "beancount" "ledger" "company") + :authors '(("Debanjum Singh Solanky" . "debanjumATgmailDOTcom")) + :maintainers '(("Debanjum Singh Solanky" . "debanjumATgmailDOTcom"))) diff --git a/lisp/company-ledger/company-ledger.el b/lisp/company-ledger/company-ledger.el index 00579259..4bc31d5c 100644 --- a/lisp/company-ledger/company-ledger.el +++ b/lisp/company-ledger/company-ledger.el @@ -5,7 +5,8 @@ ;; Author: Debanjum Singh Solanky ;; Description: Fuzzy auto-completion for ledger & friends ;; Keywords: abbrev, matching, auto-complete, beancount, ledger, company -;; Version: 0.1.0 +;; Package-Version: 20210910.250 +;; Package-Revision: 55fdddd6c5e9 ;; Package-Requires: ((emacs "24.3") (company "0.8.0")) ;; URL: https://github.com/debanjum/company-ledger diff --git a/lisp/company-quickhelp/company-quickhelp-pkg.el b/lisp/company-quickhelp/company-quickhelp-pkg.el index 84bd908c..3420f4b4 100644 --- a/lisp/company-quickhelp/company-quickhelp-pkg.el +++ b/lisp/company-quickhelp/company-quickhelp-pkg.el @@ -1,16 +1,12 @@ -(define-package "company-quickhelp" "20231026.1714" "Popup documentation for completion candidates" - '((emacs "24.3") +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "company-quickhelp" "20231026.1714" + "Popup documentation for completion candidates." + '((emacs "24.3") (company "0.8.9") (pos-tip "0.4.6")) - :commit "5bda859577582cc42d16fc0eaf5f7c8bedfd9e69" :authors - '(("Lars Andersen" . "expez@expez.com")) - :maintainers - '(("Lars Andersen" . "expez@expez.com")) - :maintainer - '("Lars Andersen" . "expez@expez.com") - :keywords - '("company" "popup" "documentation" "quickhelp") - :url "https://www.github.com/expez/company-quickhelp") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://www.github.com/expez/company-quickhelp" + :commit "5bda859577582cc42d16fc0eaf5f7c8bedfd9e69" + :revdesc "5bda85957758" + :keywords '("company" "popup" "documentation" "quickhelp") + :authors '(("Lars Andersen" . "expez@expez.com")) + :maintainers '(("Lars Andersen" . "expez@expez.com"))) diff --git a/lisp/company-quickhelp/company-quickhelp.el b/lisp/company-quickhelp/company-quickhelp.el index 17b32a9e..8ba7e895 100644 --- a/lisp/company-quickhelp/company-quickhelp.el +++ b/lisp/company-quickhelp/company-quickhelp.el @@ -5,7 +5,8 @@ ;; Author: Lars Andersen ;; URL: https://www.github.com/expez/company-quickhelp ;; Keywords: company popup documentation quickhelp -;; Version: 2.2.0 +;; Package-Version: 20231026.1714 +;; Package-Revision: 5bda85957758 ;; Package-Requires: ((emacs "24.3") (company "0.8.9") (pos-tip "0.4.6")) ;; This file is not part of GNU Emacs. diff --git a/lisp/company-statistics/company-statistics-pkg.el b/lisp/company-statistics/company-statistics-pkg.el index d2ed09d1..30d04b03 100644 --- a/lisp/company-statistics/company-statistics-pkg.el +++ b/lisp/company-statistics/company-statistics-pkg.el @@ -1,15 +1,11 @@ -(define-package "company-statistics" "20170210.1933" "Sort candidates using completion history" - '((emacs "24.3") +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "company-statistics" "20170210.1933" + "Sort candidates using completion history." + '((emacs "24.3") (company "0.8.5")) - :commit "e62157d43b2c874d2edbd547c3bdfb05d0a7ae5c" :authors - '(("Ingo Lohmar" . "i.lohmar@gmail.com")) - :maintainers - '(("Ingo Lohmar" . "i.lohmar@gmail.com")) - :maintainer - '("Ingo Lohmar" . "i.lohmar@gmail.com") - :keywords - '("abbrev" "convenience" "matching") - :url "https://github.com/company-mode/company-statistics") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/company-mode/company-statistics" + :commit "e62157d43b2c874d2edbd547c3bdfb05d0a7ae5c" + :revdesc "e62157d43b2c" + :keywords '("abbrev" "convenience" "matching") + :authors '(("Ingo Lohmar" . "i.lohmar@gmail.com")) + :maintainers '(("Ingo Lohmar" . "i.lohmar@gmail.com"))) diff --git a/lisp/company-statistics/company-statistics.el b/lisp/company-statistics/company-statistics.el index 7c6326aa..684023a6 100644 --- a/lisp/company-statistics/company-statistics.el +++ b/lisp/company-statistics/company-statistics.el @@ -4,7 +4,8 @@ ;; Author: Ingo Lohmar ;; URL: https://github.com/company-mode/company-statistics -;; Version: 0.2.3 +;; Package-Version: 20170210.1933 +;; Package-Revision: e62157d43b2c ;; Keywords: abbrev, convenience, matching ;; Package-Requires: ((emacs "24.3") (company "0.8.5")) diff --git a/lisp/company-web/company-web-pkg.el b/lisp/company-web/company-web-pkg.el index 635230e2..8a733ef9 100644 --- a/lisp/company-web/company-web-pkg.el +++ b/lisp/company-web/company-web-pkg.el @@ -1,17 +1,13 @@ -(define-package "company-web" "20220115.2146" "Company version of ac-html, complete for web,html,emmet,jade,slim modes" - '((company "0.8.0") - (dash "2.8.0") - (cl-lib "0.5.0") +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "company-web" "20220115.2146" + "Company version of ac-html, complete for web,html,emmet,jade,slim modes." + '((company "0.8.0") + (dash "2.8.0") + (cl-lib "0.5.0") (web-completion-data "0.1.0")) - :commit "e0c6bfa3ae7006c73d0fdfc0fdb69816309baf1b" :authors - '(("Olexandr Sydorchuk" . "olexandr.syd@gmail.com")) - :maintainers - '(("Olexandr Sydorchuk" . "olexandr.syd@gmail.com")) - :maintainer - '("Olexandr Sydorchuk" . "olexandr.syd@gmail.com") - :keywords - '("html" "company") - :url "https://github.com/osv/company-web") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/osv/company-web" + :commit "e0c6bfa3ae7006c73d0fdfc0fdb69816309baf1b" + :revdesc "e0c6bfa3ae70" + :keywords '("html" "company") + :authors '(("Olexandr Sydorchuk" . "olexandr.syd@gmail.com")) + :maintainers '(("Olexandr Sydorchuk" . "olexandr.syd@gmail.com"))) diff --git a/lisp/company-web/company-web.el b/lisp/company-web/company-web.el index d45711bb..9c6773de 100644 --- a/lisp/company-web/company-web.el +++ b/lisp/company-web/company-web.el @@ -3,7 +3,8 @@ ;; Copyright (C) 2015 Olexandr Sydorchuk ;; Author: Olexandr Sydorchuk -;; Version: 2.1 +;; Package-Version: 20220115.2146 +;; Package-Revision: e0c6bfa3ae70 ;; Keywords: html, company ;; Package-Requires: ((company "0.8.0") (dash "2.8.0") (cl-lib "0.5.0") (web-completion-data "0.1.0")) ;; URL: https://github.com/osv/company-web diff --git a/lisp/company/company-cmake.el b/lisp/company/company-cmake.el index 1ee98b94..724ed23a 100644 --- a/lisp/company/company-cmake.el +++ b/lisp/company/company-cmake.el @@ -3,7 +3,6 @@ ;; Copyright (C) 2013-2015, 2017-2018, 2020, 2023 Free Software Foundation, Inc. ;; Author: Chen Bin -;; Version: 0.2 ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by diff --git a/lisp/company/company-keywords.el b/lisp/company/company-keywords.el index b4063582..785a090e 100644 --- a/lisp/company/company-keywords.el +++ b/lisp/company/company-keywords.el @@ -377,6 +377,11 @@ "new" "null" "object" "override" "package" "private" "protected" "return" "sealed" "super" "this" "throw" "trait" "true" "try" "type" "val" "var" "while" "with" "yield") + (sh-mode + "break" "case" "continue" "do" "done" "elif" "else" "esac" "eval" + "exec" "exit" "export" "false" "fi" "for" "function" "if" "in" "readonly" + "return" "set" "shift" "test" "then" "time" "times" "trap" "true" "unset" + "until" "while") (swift-mode "Protocol" "Self" "Type" "and" "as" "assignment" "associatedtype" "associativity" "available" "break" "case" "catch" "class" "column" "continue" diff --git a/lisp/company/company-pkg.el b/lisp/company/company-pkg.el index 34245b98..0683790b 100644 --- a/lisp/company/company-pkg.el +++ b/lisp/company/company-pkg.el @@ -1,12 +1,9 @@ -(define-package "company" "20250228.258" "Modular text completion framework" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "company" "20250426.1319" + "Modular text completion framework." '((emacs "26.1")) - :commit "8d599ebc8a9aca27c0a6157aeb31c5b7f05ed0a3" :maintainers - '(("Dmitry Gutov" . "dmitry@gutov.dev")) - :maintainer - '("Dmitry Gutov" . "dmitry@gutov.dev") - :keywords - '("abbrev" "convenience" "matching") - :url "http://company-mode.github.io/") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "http://company-mode.github.io/" + :commit "41f07c7d401c1374a76f3004a3448d3d36bdf347" + :revdesc "41f07c7d401c" + :keywords '("abbrev" "convenience" "matching") + :maintainers '(("Dmitry Gutov" . "dmitry@gutov.dev"))) diff --git a/lisp/company/company.el b/lisp/company/company.el index 1646e1fc..09cfd464 100644 --- a/lisp/company/company.el +++ b/lisp/company/company.el @@ -5,7 +5,8 @@ ;; Author: Nikolaj Schumacher ;; Maintainer: Dmitry Gutov ;; URL: http://company-mode.github.io/ -;; Version: 1.0.2 +;; Package-Version: 20250426.1319 +;; Package-Revision: 41f07c7d401c ;; Keywords: abbrev, convenience, matching ;; Package-Requires: ((emacs "26.1")) @@ -1408,11 +1409,13 @@ be recomputed when this value changes." (car backends))) (entity (company--force-sync backend '(prefix) backend)) (prefix (company--prefix-str entity)) - (suffix (company--suffix-str entity))) - (setq args (list arg prefix suffix)) + (suffix (company--suffix-str entity)) + (company-backend backend)) (or - (apply backend command args) - (cons prefix suffix)))))) + (company-call-backend 'adjust-boundaries arg prefix suffix) + (if (company--proper-suffix-p arg prefix suffix) + (cons prefix suffix) + (cons prefix ""))))))) (`expand-common (apply #'company--multi-expand-common backends @@ -2616,12 +2619,12 @@ For more details see `company-insertion-on-trigger' and (defsubst company-keep (command) (and (symbolp command) (get command 'company-keep))) -(defun company--proper-suffix-p (candidate) +(defun company--proper-suffix-p (candidate prefix suffix) (and (>= (length candidate) - (+ (length company-prefix) - (length company-suffix))) - (string-suffix-p company-suffix candidate + (+ (length prefix) + (length suffix))) + (string-suffix-p suffix candidate (company-call-backend 'ignore-case)))) (defun company--boundaries (&optional candidate) @@ -2633,7 +2636,7 @@ For more details see `company-insertion-on-trigger' and company-prefix company-suffix) (and ;; Default to replacing the suffix only if the completion ends with it. - (company--proper-suffix-p candidate) + (company--proper-suffix-p candidate company-prefix company-suffix) (cons company-prefix company-suffix)) (cons company-prefix ""))) diff --git a/lisp/compat/NEWS.org b/lisp/compat/NEWS.org index 8191bc08..0234be86 100644 --- a/lisp/compat/NEWS.org +++ b/lisp/compat/NEWS.org @@ -2,6 +2,82 @@ #+link: compat-gh https://github.com/emacs-compat/compat/issues/ #+options: toc:nil num:nil author:nil +* Release of "Compat" Version 30.1.0.1 + +- compat-28: Fix =named-let= tail recursion. + +(Release <2025-06-19 Thu>) + +* Release of "Compat" Version 30.1.0.0 + +- compat-30: Add oklab color functions. + +(Release <2025-04-02 Wed>) + +* Release of "Compat" Version 30.0.2.0 + +- compat-30: Rename =trusted-files= to =trusted-content=. + +(Release <2025-01-04 Sat>) + +* Release of "Compat" Version 30.0.1.0 + +- compat-30: New variable =untrusted-content=. +- compat-30: New variable =trusted-files=. +- compat-30: New function =trusted-content-p=. + +(Release <2024-12-15 Sun>) + +* Release of "Compat" Version 30.0.0.0 + +- compat-28: Mark =subr-native-elisp-p= as obsolete (renamed in Emacs 30). +- compat-30: New function =char-to-name=. +- compat-30: New function =obarray-clear=. +- compat-30: New function =interpreted-function-p=. +- compat-30: New function =primitive-function-p=. +- compat-30: New function =closurep=. +- compat-30: Add extended function =sort= with keyword arguments. +- compat-30: New function =value<=. +- compat-30: Add extended =copy-tree= with support for copying records with + non-nil optional second argument. +- compat-30: New macro =static-if=. +- compat-30: New alias =drop=. +- compat-30: New function =merge-ordered-lists=. +- compat-30: New variables =completion-lazy-hilit= and =completion-lazy-hilit-fn= + and new function =completion-lazy-hilit=. +- compat-30: New function =require-with-check=. +- compat-30: New functions =find-buffer= and =get-truename-buffer=. +- compat-30: Add extended =completion-metadata-get= with support for + =completion-category-overrides= and =completion-extra-properties=. + +(Release <2024-07-08 Mon>) + +* Release of "Compat" Version 29.1.4.5 + +- Minor optimization of ~plist-get~ and ~plist-put~. +- Minor compatibility adjustments for the Emacs 30 development version. +- A minimal version of =compat.el= will be part of Emacs 30. Emacs :core packages + can directly ~(require 'compat)~ without the ~NOERROR~ flag. Furthermore Compat + will not be installed unnecessarily. If a package depending on Emacs 25.1 and + Compat 29.1 is installed on Emacs 30.1, Compat 29.1 will not be installed from + ELPA, since Emacs 30.1 already provides the required functionality. + +(Release <2024-03-16 Sat>) + +* Release of "Compat" Version 29.1.4.4 + +- Fix ~Package-Requires~ header in compat.el +- Fix ~Maintainer~ header in compat.el + +(Release <2023-11-13 Mon>) + +* Release of "Compat" Version 29.1.4.3 + +- compat-29: Add function =char-uppercase-p=. +- compat-29: Add function =window-configuration-equal-p=. + +(Release <2023-11-04 Sat>) + * Release of "Compat" Version 29.1.4.2 - compat-28: Improve =make-separator-line= visuals on graphic displays. @@ -265,7 +341,7 @@ directly (see [[compat-srht:2]]). * Release of "Compat" Version 28.1.1.0 This release mostly fixes a number of smaller bugs that were not -identified as of 28.1.0.0. Nevertheless these warrent a version bump, +identified as of 28.1.0.0. Nevertheless these warrant a version bump, as some of these changes a functional. These include: - The addition of the =file-attribute-*= accessor functions. diff --git a/lisp/compat/compat-25.el b/lisp/compat/compat-25.el index b393dc8e..51c4f068 100644 --- a/lisp/compat/compat-25.el +++ b/lisp/compat/compat-25.el @@ -1,6 +1,6 @@ ;;; compat-25.el --- Functionality added in Emacs 25.1 -*- lexical-binding: t; -*- -;; Copyright (C) 2021-2023 Free Software Foundation, Inc. +;; Copyright (C) 2021-2025 Free Software Foundation, Inc. ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -40,23 +40,6 @@ usage: (bool-vector &rest OBJECTS)" i (1+ i))) vec)) -;;;; Defined in fns.c - -(compat-defun sort (seq predicate) ;; - "Handle vector SEQ." - :extended t - (cond - ((listp seq) - (sort seq predicate)) - ((vectorp seq) - (let* ((list (sort (append seq nil) predicate)) - (p list) (i 0)) - (while p - (aset seq i (car p)) - (setq i (1+ i) p (cdr p))) - (apply #'vector list))) - ((signal 'wrong-type-argument 'list-or-vector-p)))) - ;;;; Defined in editfns.c (compat-defalias format-message format) ;; @@ -267,5 +250,11 @@ itself or not." form)))))))) (t form))) +;;;; Defined in minibuffer.el + +(compat-defun completion--category-override (category tag) ;; + "Return completion category override for CATEGORY and TAG." + (assq tag (cdr (assq category completion-category-overrides)))) + (provide 'compat-25) ;;; compat-25.el ends here diff --git a/lisp/compat/compat-26.el b/lisp/compat/compat-26.el index 0c22fbf0..9f5e1998 100644 --- a/lisp/compat/compat-26.el +++ b/lisp/compat/compat-26.el @@ -1,6 +1,6 @@ ;;; compat-26.el --- Functionality added in Emacs 26.1 -*- lexical-binding: t; -*- -;; Copyright (C) 2021-2023 Free Software Foundation, Inc. +;; Copyright (C) 2021-2025 Free Software Foundation, Inc. ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -75,7 +75,7 @@ see `region-noncontiguous-p' and `extract-rectangle-bounds'." ;;;; Defined in subr.el -(compat-defun provided-mode-derived-p (mode &rest modes) ;; +(compat-defun provided-mode-derived-p (mode &rest modes) ;; "Non-nil if MODE is derived from one of MODES. Uses the `derived-mode-parent' property of the symbol to trace backwards. If you just want to check `major-mode', use `derived-mode-p'." diff --git a/lisp/compat/compat-27.el b/lisp/compat/compat-27.el index 3ff075dd..30a49474 100644 --- a/lisp/compat/compat-27.el +++ b/lisp/compat/compat-27.el @@ -1,6 +1,6 @@ ;;; compat-27.el --- Functionality added in Emacs 27.1 -*- lexical-binding: t; -*- -;; Copyright (C) 2021-2023 Free Software Foundation, Inc. +;; Copyright (C) 2021-2025 Free Software Foundation, Inc. ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by diff --git a/lisp/compat/compat-28.el b/lisp/compat/compat-28.el index fe693155..ed05b870 100644 --- a/lisp/compat/compat-28.el +++ b/lisp/compat/compat-28.el @@ -1,6 +1,6 @@ ;;; compat-28.el --- Functionality added in Emacs 28.1 -*- lexical-binding: t; -*- -;; Copyright (C) 2021-2023 Free Software Foundation, Inc. +;; Copyright (C) 2021-2025 Free Software Foundation, Inc. ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -34,7 +34,7 @@ ;; FIXME Should handle multibyte regular expressions (compat-defun string-search (needle haystack &optional start-pos) ;; - "Search for the string NEEDLE in the strign HAYSTACK. + "Search for the string NEEDLE in the string HAYSTACK. The return value is the position of the first occurrence of NEEDLE in HAYSTACK, or nil if no match was found. @@ -52,9 +52,8 @@ issues are inherited." (when (and start-pos (or (< (length haystack) start-pos) (< start-pos 0))) (signal 'args-out-of-range (list start-pos))) - (save-match-data - (let ((case-fold-search nil)) - (string-match (regexp-quote needle) haystack start-pos)))) + (let (case-fold-search) + (string-match-p (regexp-quote needle) haystack start-pos))) (compat-defun length= (sequence length) ;; [[compat-tests:length=]] "Returns non-nil if SEQUENCE has a length equal to LENGTH." @@ -66,7 +65,7 @@ issues are inherited." t)) ((arrayp sequence) (= (length sequence) length)) - ((signal 'wrong-type-argument sequence)))) + (t (signal 'wrong-type-argument (list 'sequencep sequence))))) (compat-defun length< (sequence length) ;; [[compat-tests:length<]] "Returns non-nil if SEQUENCE is shorter than LENGTH." @@ -76,7 +75,7 @@ issues are inherited." (null (nthcdr (1- length) sequence))) ((arrayp sequence) (< (length sequence) length)) - ((signal 'wrong-type-argument sequence)))) + (t (signal 'wrong-type-argument (list 'sequencep sequence))))) (compat-defun length> (sequence length) ;; [[compat-tests:length>]] "Returns non-nil if SEQUENCE is longer than LENGTH." @@ -85,7 +84,7 @@ issues are inherited." (and (nthcdr length sequence) t)) ((arrayp sequence) (> (length sequence) length)) - ((signal 'wrong-type-argument sequence)))) + (t (signal 'wrong-type-argument (list 'sequencep sequence))))) ;;;; Defined in fileio.c @@ -191,7 +190,7 @@ and BLUE, is normalized to have its value in [0,65535]." ;; The "RGBi" (RGB Intensity) specification is defined by ;; XCMS[0], see [1] for the implementation in Xlib. ;; - ;; [0] http://www.nic.funet.fi/pub/X11/X11R4/DOCS/color/Xcms.text + ;; [0] https://www.nic.funet.fi/pub/X11/X11R4/DOCS/color/Xcms.text ;; [1] https://gitlab.freedesktop.org/xorg/lib/libx11/-/blob/master/src/xcms/LRGB.c#L1392 ((string-match ;; (rx bos "rgbi:" (* space) @@ -355,11 +354,10 @@ REPLACEMENT can use the following special elements: (compat-defun buffer-local-boundp (symbol buffer) ;; "Return non-nil if SYMBOL is bound in BUFFER. Also see `local-variable-p'." - (catch 'fail - (condition-case nil - (buffer-local-value symbol buffer) - (void-variable nil (throw 'fail nil))) - t)) + (condition-case nil + (progn (buffer-local-value symbol buffer) + t) + (void-variable nil))) (compat-defmacro with-existing-directory (&rest body) ;; "Execute BODY with `default-directory' bound to an existing directory. @@ -398,7 +396,8 @@ not a list, return a one-element list containing OBJECT." ;;;; Defined in data.c -(compat-defalias subr-native-elisp-p ignore) ;; +;; Renamed in Emacs 30 to `native-comp-function-p'. +(compat-defalias subr-native-elisp-p ignore :obsolete t) ;; ;;;; Defined in subr-x.el @@ -519,7 +518,11 @@ as the new values of the bound variables in the recursive invocation." (cons (car handler) (funcall tco-progn (cdr handler)))) (nthcdr 3 expr)))) - ((memq (car-safe expr) '(and progn)) + ((eq (car-safe expr) 'and) + (if (cddr expr) + (funcall tco `(if ,(cadr expr) ,(cons 'and (cddr expr)))) + (funcall tco (cadr expr)))) + ((eq (car-safe expr) 'progn) (cons (car expr) (funcall tco-progn (cdr expr)))) ((memq (car-safe expr) '(let let*)) (append (list (car expr) (cadr expr)) @@ -784,7 +787,7 @@ Other uses risk returning non-nil value that point to the wrong file." ;;;; Defined in env.el (compat-defmacro with-environment-variables (variables &rest body) ;; - "Set VARIABLES in the environent and execute BODY. + "Set VARIABLES in the environment and execute BODY. VARIABLES is a list of variable settings of the form (VAR VALUE), where VAR is the name of the variable (a string) and VALUE is its value (also a string). @@ -837,7 +840,7 @@ function will never return nil." ;;;; Defined in button.el ;; Obsolete Alias since 29 -(compat-defalias button-buttonize buttonize :obsolete t) ;; +(compat-defalias button-buttonize buttonize :obsolete t) ;; ;;;; Defined in wid-edit.el diff --git a/lisp/compat/compat-29.el b/lisp/compat/compat-29.el index 675d2c76..a0831e66 100644 --- a/lisp/compat/compat-29.el +++ b/lisp/compat/compat-29.el @@ -1,6 +1,6 @@ ;;; compat-29.el --- Functionality added in Emacs 29.1 -*- lexical-binding: t; -*- -;; Copyright (C) 2021-2023 Free Software Foundation, Inc. +;; Copyright (C) 2021-2025 Free Software Foundation, Inc. ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -37,6 +37,10 @@ (locate-file "simple" load-path (get-load-suffixes)))) "Directory where Emacs's own *.el and *.elc Lisp files are installed.") +;;;; Defined in window.c + +(compat-defalias window-configuration-equal-p compare-window-configurations) ;; + ;;;; Defined in xdisp.c (compat-defun get-display-property (position prop &optional object properties) ;; @@ -98,38 +102,40 @@ Unibyte strings are converted to multibyte for comparison." (compat-defun plist-get (plist prop &optional predicate) ;; "Handle optional argument PREDICATE." :extended t - (if (or (null predicate) (eq predicate 'eq)) - (plist-get plist prop) - (catch 'found - (while (consp plist) - (when (funcall predicate prop (car plist)) - (throw 'found (cadr plist))) - (setq plist (cddr plist)))))) + (pcase predicate + ((or `nil `eq) (plist-get plist prop)) + (`equal (lax-plist-get plist prop)) + (_ (catch 'found + (while (consp plist) + (when (funcall predicate prop (car plist)) + (throw 'found (cadr plist))) + (setq plist (cddr plist))))))) (compat-defun plist-put (plist prop val &optional predicate) ;; "Handle optional argument PREDICATE." :extended t - (if (or (null predicate) (eq predicate 'eq)) - (plist-put plist prop val) - (catch 'found - (let ((tail plist)) - (while (consp tail) - (when (funcall predicate prop (car tail)) - (setcar (cdr tail) val) - (throw 'found plist)) - (setq tail (cddr tail)))) - (nconc plist (list prop val))))) + (pcase predicate + ((or `nil `eq) (plist-put plist prop val)) + (`equal (lax-plist-put plist prop val)) + (_ (catch 'found + (let ((tail plist)) + (while (consp tail) + (when (funcall predicate prop (car tail)) + (setcar (cdr tail) val) + (throw 'found plist)) + (setq tail (cddr tail)))) + (nconc plist (list prop val)))))) (compat-defun plist-member (plist prop &optional predicate) ;; "Handle optional argument PREDICATE." :extended t - (if (or (null predicate) (eq predicate 'eq)) - (plist-member plist prop) - (catch 'found - (while (consp plist) - (when (funcall predicate prop (car plist)) - (throw 'found plist)) - (setq plist (cddr plist)))))) + (pcase predicate + ((or `nil `eq) (plist-member plist prop)) + (_ (catch 'found + (while (consp plist) + (when (funcall predicate prop (car plist)) + (throw 'found plist)) + (setq plist (cddr plist))))))) ;;;; Defined in gv.el @@ -506,6 +512,14 @@ thus overriding the value of the TIMEOUT argument to that function.") ;;;; Defined in simple.el +(compat-defun char-uppercase-p (char) ;; + "Return non-nil if CHAR is an upper-case character. +If the Unicode tables are not yet available, e.g. during bootstrap, +then gives correct answers only for ASCII characters." + (cond ((unicode-property-table-internal 'lowercase) + (characterp (get-char-code-property char 'lowercase))) + ((and (>= char ?A) (<= char ?Z))))) + (compat-defun use-region-noncontiguous-p () ;; "Return non-nil for a non-contiguous region if `use-region-p'." (and (use-region-p) (region-noncontiguous-p))) diff --git a/lisp/compat/compat-30.el b/lisp/compat/compat-30.el new file mode 100644 index 00000000..2decb937 --- /dev/null +++ b/lisp/compat/compat-30.el @@ -0,0 +1,474 @@ +;;; compat-30.el --- Functionality added in Emacs 30 -*- lexical-binding: t; -*- + +;; Copyright (C) 2023-2025 Free Software Foundation, Inc. + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; Functionality added in Emacs 30, needed by older Emacs versions. + +;;; Code: + +(eval-when-compile (load "compat-macs.el" nil t t)) +(compat-require compat-29 "29.1") + +(compat-version "29.3") +(compat-defvar untrusted-content nil ;; + "Non-nil means that current buffer originated from an untrusted source. +Email clients and some other modes may set this non-nil to mark the +buffer contents as untrusted. + +This variable might be subject to change without notice." + :local permanent) + +(compat-version "30.1") + +;;;; Defined in lread.c + +(compat-defun obarray-clear (ob) ;; + "Remove all symbols from obarray OB." + (fillarray ob 0)) + +;;;; Defined in buffer.c + +(compat-defun find-buffer (variable value) ;; + "Return the buffer with buffer-local VARIABLE equal to VALUE. +If there is no such live buffer, return nil." + (cl-loop for buffer the buffers + if (equal (buffer-local-value variable buffer) value) + return buffer)) + +(compat-defun get-truename-buffer (filename) ;; + "Return the buffer with `file-truename' equal to FILENAME (a string). +If there is no such live buffer, return nil. +See also `find-buffer-visiting'." + (find-buffer 'buffer-file-truename filename)) + +;;;; Defined in files.el + +(compat-defvar trusted-content nil ;; + "List of files and directories whose content we trust. +Be extra careful here since trusting means that Emacs might execute the +code contained within those files and directories without an explicit +request by the user. +One important case when this might happen is when `flymake-mode' is +enabled (for example, when it is added to a mode hook). +Each element of the list should be a string: +- If it ends in \"/\", it is considered as a directory name and means that + Emacs should trust all the files whose name has this directory as a prefix. +- else it is considered as a file name. +Use abbreviated file names. For example, an entry \"~/mycode\" means +that Emacs will trust all the files in your directory \"mycode\". +This variable can also be set to `:all', in which case Emacs will trust +all files, which opens a gaping security hole." + :risky t) + +(compat-defun trusted-content-p () ;; + "Return non-nil if we trust the contents of the current buffer. +Here, \"trust\" means that we are willing to run code found inside of it. +See also `trusted-content'." + (and (not untrusted-content) + (or + (eq trusted-content :all) + (and + buffer-file-truename + (with-demoted-errors "trusted-content-p: %S" + (let ((exists (file-exists-p buffer-file-truename))) + (or + (if (and exists user-init-file) + (file-equal-p buffer-file-truename user-init-file) + (equal buffer-file-truename user-init-file)) + (let ((file (abbreviate-file-name buffer-file-truename)) + (trusted nil)) + (dolist (tf trusted-content) + (when (or (if exists (file-equal-p tf file) (equal tf file)) + (and (string-suffix-p "/" tf) + (string-prefix-p tf file))) + (setq trusted t))) + trusted)))))))) + +(compat-defun require-with-check (feature &optional filename noerror) ;; + "If FEATURE is not already loaded, load it from FILENAME. +This is like `require' except if FEATURE is already a member of the list +`features’, then check if it was provided by a different file than the +one that is about to be loaded now (presumably because `load-path' has +been changed since FILENAME was loaded). If that is the case, either +signal an error (the default), or forcibly reload the new file (if +NOERROR is equal to `reload'), or otherwise emit a warning." + (let ((lh load-history) + (res (require feature filename (if (eq noerror 'reload) nil noerror)))) + ;; If the `feature' was not yet provided, `require' just loaded the right + ;; file, so we're done. + (when (and res (eq lh load-history)) + ;; If `require' did nothing, we need to make sure that was warranted. + (let* ((fn (locate-file (or filename (symbol-name feature)) + load-path (get-load-suffixes) nil + )) ;; load-prefer-newer + ;; We used to look for `fn' in `load-history' with `assoc' + ;; which works in most cases, but in some cases (e.g. when + ;; `load-prefer-newer' is set) `locate-file' can return a + ;; different file than the file that `require' would load, + ;; so the file won't be found in `load-history' even though + ;; we did load "it". (bug#74040) + ;; So use a "permissive" search which doesn't pay attention to + ;; differences between file extensions. + (prefix (if (string-match + (concat (regexp-opt (get-load-suffixes)) "\\'") fn) + (concat (substring fn 0 (match-beginning 0)) ".") + fn)) + (lh load-history)) + (while (and lh (let ((file (car-safe (car lh)))) + (not (and file (string-prefix-p prefix file))))) + (setq lh (cdr lh))) + (cond + (lh nil) ;We loaded the right file. + ((eq noerror 'reload) (load fn nil 'nomessage)) + ((and fn (memq feature features)) + (funcall (if noerror #'warn #'error) + "Feature `%S' is now provided by a different file %s" + feature fn)) + (fn + (funcall (if noerror #'warn #'error) + "Could not load file %s" fn)) + (t + (funcall (if noerror #'warn #'error) + "Could not locate file %s in load path" + (or filename (symbol-name feature))))))) + res)) + +;;;; Defined in minibuffer.el + +(compat-defun completion--metadata-get-1 (metadata prop) ;; + "Helper function. +See for `completion-metadata-get' for METADATA and PROP arguments." + (or (alist-get prop metadata) + (plist-get completion-extra-properties + (or (get prop 'completion-extra-properties--keyword) + (put prop 'completion-extra-properties--keyword + (intern (concat ":" (symbol-name prop)))))))) + +(compat-defun completion-metadata-get (metadata prop) ;; + "Get property PROP from completion METADATA. +If the metadata specifies a completion category, the variables +`completion-category-overrides' and +`completion-category-defaults' take precedence for +category-specific overrides. If the completion metadata does not +specify the property, the `completion-extra-properties' plist is +consulted. Note that the keys of the +`completion-extra-properties' plist are keyword symbols, not +plain symbols." + :extended t + (if-let ((cat (and (not (eq prop 'category)) + (completion--metadata-get-1 metadata 'category))) + (over (completion--category-override cat prop))) + (cdr over) + (completion--metadata-get-1 metadata prop))) + +(compat-defvar completion-lazy-hilit nil ;; + "If non-nil, request lazy highlighting of completion candidates. + +Lisp programs (a.k.a. \"front ends\") that present completion +candidates may opt to bind this variable to a non-nil value when +calling functions (such as `completion-all-completions') which +produce completion candidates. This tells the underlying +completion styles that they do not need to fontify (i.e., +propertize with the `face' property) completion candidates in a +way that highlights the matching parts. Then it is the front end +which presents the candidates that becomes responsible for this +fontification. The front end does that by calling the function +`completion-lazy-hilit' on each completion candidate that is to be +displayed to the user. + +Note that only some completion styles take advantage of this +variable for optimization purposes. Other styles will ignore the +hint and fontify eagerly as usual. It is still safe for a +front end to call `completion-lazy-hilit' in these situations. + +To author a completion style that takes advantage of this variable, +see `completion-lazy-hilit-fn' and `completion-pcm--hilit-commonality'.") + +(compat-defvar completion-lazy-hilit-fn nil ;; + "Fontification function set by lazy-highlighting completions styles. +When a given style wants to enable support for `completion-lazy-hilit' +\(which see), that style should set this variable to a function of one +argument. It will be called with each completion candidate, a string, to +be displayed to the user, and should destructively propertize these +strings with the `face' property.") + +(compat-defun completion-lazy-hilit (str) ;; + "Return a copy of completion candidate STR that is `face'-propertized. +See documentation of the variable `completion-lazy-hilit' for more +details." + (if (and completion-lazy-hilit completion-lazy-hilit-fn) + (funcall completion-lazy-hilit-fn (copy-sequence str)) + str)) + +;;;; Defined in color.el + +(compat-defun color-oklab-to-xyz (l a b) ;; + "Convert the OkLab color represented by L A B to CIE XYZ. +Oklab is a perceptual color space created by Björn Ottosson +. It has the property that +changes in the hue and saturation of a color can be made while maintaining +the same perceived lightness." + :feature color + (let ((ll (expt (+ (* 1.0 l) (* 0.39633779 a) (* 0.21580376 b)) 3)) + (mm (expt (+ (* 1.00000001 l) (* -0.10556134 a) (* -0.06385417 b)) 3)) + (ss (expt (+ (* 1.00000005 l) (* -0.08948418 a) (* -1.29148554 b)) 3))) + (list (+ (* ll 1.22701385) (* mm -0.55779998) (* ss 0.28125615)) + (+ (* ll -0.04058018) (* mm 1.11225687) (* ss -0.07167668)) + (+ (* ll -0.07638128) (* mm -0.42148198) (* ss 1.58616322))))) + +(compat-defun color-xyz-to-oklab (x y z) ;; + "Convert the CIE XYZ color represented by X Y Z to Oklab." + :feature color + (let ((ll (+ (* x 0.8189330101) (* y 0.3618667424) (* z -0.1288597137))) + (mm (+ (* x 0.0329845436) (* y 0.9293118715) (* z 0.0361456387))) + (ss (+ (* x 0.0482003018) (* y 0.2643662691) (* z 0.6338517070)))) + (let* + ((cube-root (lambda (f) + (if (< f 0) + (- (expt (- f) (/ 1.0 3.0))) + (expt f (/ 1.0 3.0))))) + (lll (funcall cube-root ll)) + (mmm (funcall cube-root mm)) + (sss (funcall cube-root ss))) + (list (+ (* lll 0.2104542553) (* mmm 0.7936177850) (* sss -0.0040720468)) + (+ (* lll 1.9779984951) (* mmm -2.4285922050) (* sss 0.4505937099)) + (+ (* lll 0.0259040371) (* mmm 0.7827717662) (* sss -0.8086757660)))))) + +(compat-defun color-oklab-to-srgb (l a b) ;; + "Convert the Oklab color represented by L A B to sRGB." + :feature color + (apply #'color-xyz-to-srgb (color-oklab-to-xyz l a b))) + +(compat-defun color-srgb-to-oklab (r g b) ;; + "Convert the sRGB color R G B to Oklab." + :feature color + (apply #'color-xyz-to-oklab (color-srgb-to-xyz r g b))) + +;;;; Defined in subr.el + +(compat-defmacro static-if (condition then-form &rest else-forms) ;; + "A conditional compilation macro. +Evaluate CONDITION at macro-expansion time. If it is non-nil, +expand the macro to THEN-FORM. Otherwise expand it to ELSE-FORMS +enclosed in a `progn' form. ELSE-FORMS may be empty." + (declare (indent 2) (debug (sexp sexp &rest sexp))) + (if (eval condition lexical-binding) + then-form + (cons 'progn else-forms))) + +(compat-defun closurep (object) ;; + "Return t if OBJECT is a function of type closure." + (declare (side-effect-free error-free)) + (eq (car-safe object) 'closure)) + +(compat-defalias interpreted-function-p closurep) ;; + +(compat-defun primitive-function-p (object) ;; + "Return t if OBJECT is a built-in primitive function. +This excludes special forms, since they are not functions." + (declare (side-effect-free error-free)) + (and (subrp object) + (not (or (with-no-warnings (subr-native-elisp-p object)) + (special-form-p object))))) + +(compat-defalias drop nthcdr) ;; + +(compat-defun merge-ordered-lists (lists &optional error-function) ;; + "Merge LISTS in a consistent order. +LISTS is a list of lists of elements. +Merge them into a single list containing the same elements (removing +duplicates), obeying their relative positions in each list. +The order of the (sub)lists determines the final order in those cases where +the order within the sublists does not impose a unique choice. +Equality of elements is tested with `eql'. + +If a consistent order does not exist, call ERROR-FUNCTION with +a remaining list of lists that we do not know how to merge. +It should return the candidate to use to continue the merge, which +has to be the head of one of the lists. +By default we choose the head of the first list." + (let ((result '())) + (setq lists (remq nil lists)) + (while (cdr (setq lists (delq nil lists))) + (let* ((next nil) + (tail lists)) + (while tail + (let ((candidate (caar tail)) + (other-lists lists)) + (while other-lists + (if (not (memql candidate (cdr (car other-lists)))) + (setq other-lists (cdr other-lists)) + (setq candidate nil) + (setq other-lists nil))) + (if (not candidate) + (setq tail (cdr tail)) + (setq next candidate) + (setq tail nil)))) + (unless next + (setq next (funcall (or error-function #'caar) lists)) + (unless (funcall + (eval-when-compile (if (fboundp 'compat--assoc) 'compat--assoc 'assoc)) + next lists #'eql) + (error "Invalid candidate returned by error-function: %S" next))) + (push next result) + (setq lists + (mapcar (lambda (l) (if (eql (car l) next) (cdr l) l)) + lists)))) + (if (null result) (car lists) + (append (nreverse result) (car lists))))) + +(compat-defun copy-tree (tree &optional vectors-and-records) ;; + "Handle copying records when optional arg is non-nil." + :extended t + (declare (side-effect-free error-free)) + (if (fboundp 'recordp) + (if (consp tree) + (let (result) + (while (consp tree) + (let ((newcar (car tree))) + (if (or (consp (car tree)) + (and vectors-and-records + (or (vectorp (car tree)) (recordp (car tree))))) + (setq newcar (compat--copy-tree (car tree) vectors-and-records))) + (push newcar result)) + (setq tree (cdr tree))) + (nconc (nreverse result) + (if (and vectors-and-records (or (vectorp tree) (recordp tree))) + (compat--copy-tree tree vectors-and-records) + tree))) + (if (and vectors-and-records (or (vectorp tree) (recordp tree))) + (let ((i (length (setq tree (copy-sequence tree))))) + (while (>= (setq i (1- i)) 0) + (aset tree i (compat--copy-tree (aref tree i) vectors-and-records))) + tree) + tree)) + (copy-tree tree vectors-and-records))) + +;;;; Defined in fns.c + +(compat-defun value< (a b) ;; + "Return non-nil if A precedes B in standard value order. +A and B must have the same basic type. +Numbers are compared with <. +Strings and symbols are compared with string-lessp. +Lists, vectors, bool-vectors and records are compared lexicographically. +Markers are compared lexicographically by buffer and position. +Buffers and processes are compared by name. +Other types are considered unordered and the return value will be ‘nil’." + (cond + ((or (and (numberp a) (numberp b)) + (and (markerp a) (markerp b))) + (< a b)) + ((or (and (stringp a) (stringp b)) + (and (symbolp a) (symbolp b))) + (string< a b)) + ((and (listp a) (listp b)) + (while (and (consp a) (consp b) (equal (car a) (car b))) + (setq a (cdr a) b (cdr b))) + (cond + ((not b) nil) + ((not a) t) + ((and (consp a) (consp b)) (value< (car a) (car b))) + (t (value< a b)))) + ((and (vectorp a) (vectorp b)) + (let* ((na (length a)) + (nb (length b)) + (n (min na nb)) + (i 0)) + (while (and (< i n) (equal (aref a i) (aref b i))) + (cl-incf i)) + (if (< i n) (value< (aref a i) (aref b i)) (< n nb)))) + ((and (bufferp a) (bufferp b)) + ;; `buffer-name' is nil for killed buffers. + (setq a (buffer-name a) + b (buffer-name b)) + (cond + ((and a b) (string< a b)) + (b t))) + ((and (processp a) (processp b)) + (string< (process-name a) (process-name b))) + ;; TODO Add support for more types here. + ;; Other values of equal type are considered unordered (return value nil). + ((eq (type-of a) (type-of b)) nil) + ;; Different types. + (t (error "value< type mismatch: %S %S" a b)))) + +(compat-defun sort (seq &optional lessp &rest rest) ;; + "Sort function with support for keyword arguments. +The following arguments are defined: + +:key FUNC -- FUNC is a function that takes a single element from SEQ and + returns the key value to be used in comparison. If absent or nil, + `identity' is used. + +:lessp FUNC -- FUNC is a function that takes two arguments and returns + non-nil if the first element should come before the second. + If absent or nil, `value<' is used. + +:reverse BOOL -- if BOOL is non-nil, the sorting order implied by FUNC is + reversed. This does not affect stability: equal elements still retain + their order in the input sequence. + +:in-place BOOL -- if BOOL is non-nil, SEQ is sorted in-place and returned. + Otherwise, a sorted copy of SEQ is returned and SEQ remains unmodified; + this is the default. + +For compatibility, the calling convention (sort SEQ LESSP) can also be used; +in this case, sorting is always done in-place." + :extended t + (let ((in-place t) (reverse nil) (orig-seq seq)) + (when (or (not lessp) rest) + (setq + rest (if lessp (cons lessp rest) rest) + in-place (plist-get rest :in-place) + reverse (plist-get rest :reverse) + lessp (let ((key (plist-get rest :key)) + (< (or (plist-get rest :lessp) #'value<))) + (if key + (lambda (a b) (funcall < (funcall key a) (funcall key b))) + <)) + seq (if (or (and (eval-when-compile (< emacs-major-version 25)) (vectorp orig-seq)) + in-place) + seq + (copy-sequence seq)))) + ;; Emacs 24 does not support vectors. Convert to list. + (when (and (eval-when-compile (< emacs-major-version 25)) (vectorp orig-seq)) + (setq seq (append seq nil))) + (setq seq (if reverse + (nreverse (sort (nreverse seq) lessp)) + (sort seq lessp))) + ;; Emacs 24: Convert back to vector. + (if (and (eval-when-compile (< emacs-major-version 25)) (vectorp orig-seq)) + (if in-place + (cl-loop for i from 0 for x in seq + do (aset orig-seq i x) + finally return orig-seq) + (apply #'vector seq)) + seq))) + +;;;; Defined in mule-cmds.el + +(compat-defun char-to-name (char) ;; + "Return the Unicode name for CHAR, if it has one, else nil. +Return nil if CHAR is not a character." + (and (characterp char) + (or (get-char-code-property char 'name) + (get-char-code-property char 'old-name)))) + +(provide 'compat-30) +;;; compat-30.el ends here diff --git a/lisp/compat/compat-macs.el b/lisp/compat/compat-macs.el index 6c6e2207..c5567da0 100644 --- a/lisp/compat/compat-macs.el +++ b/lisp/compat/compat-macs.el @@ -1,6 +1,6 @@ ;;; compat-macs.el --- Compatibility Macros -*- lexical-binding: t; no-byte-compile: t; -*- -;; Copyright (C) 2021-2023 Free Software Foundation, Inc. +;; Copyright (C) 2021-2025 Free Software Foundation, Inc. ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -17,12 +17,13 @@ ;;; Commentary: -;; This file provides *internal* macros, which are used by Compat to -;; facilitate the definition of compatibility functions, macros and -;; variables. The `compat-macs' feature should never be loaded at -;; runtime in your Emacs and will only be used during byte -;; compilation. Every definition provided here should be considered -;; internal and may change any time between Compat releases. +;; WARNING: This file provides *internal* macros. The macros are used +;; by Compat to facilitate the definition of compatibility functions, +;; compatibility macros and compatibility variables. The +;; `compat-macs' feature should never be loaded at runtime in your +;; Emacs and will only be used during byte compilation. Every +;; definition provided here is internal, may change any time between +;; Compat releases and must not be used by other packages. ;;; Code: @@ -141,7 +142,7 @@ REST are attributes and the function BODY." (defmacro compat-guard (cond &rest rest) "Guard definition with a runtime COND and a version check. The runtime condition must make sure that no definition is -overriden. REST is an attribute plist followed by the definition +overridden. REST is an attribute plist followed by the definition body. The attributes specify the conditions under which the definition is generated. @@ -220,6 +221,8 @@ definition is generated. - :constant :: Mark the variable as constant if t. +- :risky :: Mark the variable as risky if t. + - :local :: Make the variable buffer-local if t. If the value is `permanent' make the variable additionally permanently local. @@ -231,15 +234,18 @@ definition is generated. (doc-string 3) (indent 2)) (compat-macs--guard attrs (list :constant #'booleanp + :risky #'booleanp :local (lambda (x) (memq x '(nil t permanent))) :obsolete (lambda (x) (or (booleanp x) (stringp x)))) - (lambda (constant local obsolete) + (lambda (constant risky local obsolete) (compat-macs--strict (not (boundp name)) "%s already defined" name) (compat-macs--assert (not (and constant local)) "Both :constant and :local") + (compat-macs--assert (not (and local risky)) "Both :risky and :local") ;; The boundp check is performed at runtime to make sure that we never ;; redefine an existing definition if Compat is loaded on a newer Emacs ;; version. - `((unless (boundp ',name) + `((defvar ,name) + (unless (boundp ',name) (,(if constant 'defconst 'defvar) ,name ,initval ,(compat-macs--docstring 'variable name docstring)) @@ -248,6 +254,7 @@ definition is generated. ',name ,(if (stringp obsolete) obsolete "No substitute") ,compat-macs--version)))) ,@(and local `((make-variable-buffer-local ',name))) + ,@(and risky `((put ',name 'risky-local-variable t))) ,@(and (eq local 'permanent) `((put ',name 'permanent-local t))))))) (defmacro compat-version (version) diff --git a/lisp/compat/compat-pkg.el b/lisp/compat/compat-pkg.el index 34f3bc6e..4b26a4f6 100644 --- a/lisp/compat/compat-pkg.el +++ b/lisp/compat/compat-pkg.el @@ -1,2 +1,2 @@ ;; Generated package description from compat.el -*- no-byte-compile: t -*- -(define-package "compat" "29.1.4.2" "Emacs Lisp Compatibility Library" '((emacs "24.4") (seq "2.3")) :commit "74300f16a1630a33a86710aa20c1fc26f5f89f75" :authors '(("Philip Kaludercic" . "philipk@posteo.net") ("Daniel Mendler" . "mail@daniel-mendler.de")) :maintainer '(("Daniel Mendler" . "mail@daniel-mendler.de") ("Compat Development" . "~pkal/compat-devel@lists.sr.ht")) :keywords '("lisp" "maint") :url "https://github.com/emacs-compat/compat") +(define-package "compat" "30.1.0.1" "Emacs Lisp Compatibility Library" '((emacs "24.4") (seq "2.23")) :commit "cccd41f549fa88031a32deb26253b462021d7e12" :authors '(("Philip Kaludercic" . "philipk@posteo.net") ("Daniel Mendler" . "mail@daniel-mendler.de")) :maintainer '("Compat Development" . "~pkal/compat-devel@lists.sr.ht") :keywords '("lisp" "maint") :url "https://github.com/emacs-compat/compat") diff --git a/lisp/compat/compat.el b/lisp/compat/compat.el index 9c0b4e6c..7fc500f5 100644 --- a/lisp/compat/compat.el +++ b/lisp/compat/compat.el @@ -1,12 +1,12 @@ ;;; compat.el --- Emacs Lisp Compatibility Library -*- lexical-binding: t; -*- -;; Copyright (C) 2021-2023 Free Software Foundation, Inc. +;; Copyright (C) 2021-2025 Free Software Foundation, Inc. ;; Author: Philip Kaludercic , Daniel Mendler -;; Maintainer: Daniel Mendler , Compat Development <~pkal/compat-devel@lists.sr.ht> -;; Version: 29.1.4.2 +;; Maintainer: Compat Development <~pkal/compat-devel@lists.sr.ht> +;; Version: 30.1.0.1 ;; URL: https://github.com/emacs-compat/compat -;; Package-Requires: ((emacs "24.4") (seq "2.3")) +;; Package-Requires: ((emacs "24.4") (seq "2.23")) ;; Keywords: lisp, maint ;; This program is free software; you can redistribute it and/or modify @@ -49,11 +49,11 @@ ;; Ensure that the newest compatibility layer is required at compile ;; time and runtime, but only if needed. (eval-when-compile - (defmacro compat--maybe-require-29 () - (when (version< emacs-version "29.1") - (require 'compat-29) - '(require 'compat-29)))) -(compat--maybe-require-29) + (defmacro compat--maybe-require () + (when (version< emacs-version "30.1") + (require 'compat-30) + '(require 'compat-30)))) +(compat--maybe-require) ;;;; Macros for extended compatibility function calls diff --git a/lisp/compat/compat.info b/lisp/compat/compat.info index 5cbba00a..afaf9571 100644 --- a/lisp/compat/compat.info +++ b/lisp/compat/compat.info @@ -1,7 +1,7 @@ -This is doc9SKjtU.info, produced by makeinfo version 6.8 from +This is docA0lLBy.info, produced by makeinfo version 7.1.1 from compat.texi. -Copyright © 2022-2023 Free Software Foundation, Inc. +Copyright © 2022-2025 Free Software Foundation, Inc. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, @@ -20,16 +20,16 @@ START-INFO-DIR-ENTRY END-INFO-DIR-ENTRY  -File: doc9SKjtU.info, Node: Top, Next: Introduction, Up: (dir) +File: docA0lLBy.info, Node: Top, Next: Introduction, Up: (dir) "Compat" Manual *************** This manual documents the usage of the "Compat" Emacs lisp library, the forward-compatibility library for Emacs Lisp, corresponding to version -29.1.4.2. +30.1.0.1. - Copyright © 2022-2023 Free Software Foundation, Inc. + Copyright © 2022-2025 Free Software Foundation, Inc. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, @@ -50,7 +50,7 @@ forward-compatibility library for Emacs Lisp, corresponding to version * Function Index:: * Variable Index:: -— The Detailed Node Listing — +-- The Detailed Node Listing -- Introduction @@ -65,10 +65,11 @@ Support * Emacs 27.1:: Compatibility support for Emacs 27.1 * Emacs 28.1:: Compatibility support for Emacs 28.1 * Emacs 29.1:: Compatibility support for Emacs 29.1 +* Emacs 30.1:: Compatibility support for Emacs 30.1  -File: doc9SKjtU.info, Node: Introduction, Next: Support, Prev: Top, Up: Top +File: docA0lLBy.info, Node: Introduction, Next: Support, Prev: Top, Up: Top 1 Introduction ************** @@ -80,7 +81,7 @@ File: doc9SKjtU.info, Node: Introduction, Next: Support, Prev: Top, Up: Top * Limitations::  -File: doc9SKjtU.info, Node: Overview, Next: Usage, Up: Introduction +File: docA0lLBy.info, Node: Overview, Next: Usage, Up: Introduction 1.1 Overview ============ @@ -95,7 +96,7 @@ audience are package developers that are interested in using newer developments, without having to break compatibility.  -File: doc9SKjtU.info, Node: Usage, Next: Limitations, Prev: Overview, Up: Introduction +File: docA0lLBy.info, Node: Usage, Next: Limitations, Prev: Overview, Up: Introduction 1.2 Usage ========= @@ -103,9 +104,9 @@ File: doc9SKjtU.info, Node: Usage, Next: Limitations, Prev: Overview, Up: In The intended use-case for this library is for package developers to add as a dependency in the header. The version of the Compat library mirrors the version of Emacs releases. The current version of Compat -corresponds to the upcoming Emacs 29 release. +corresponds to the current Emacs release. - ;; Package-Requires: ((emacs "24.4") (compat "29.1.4.2")) + ;; Package-Requires: ((emacs "24.4") (compat "30.1.0.1")) There is no need to depend on ‘emacs 24.4’ specifically. One can choose any newer version, if features not provided by Compat necessitate @@ -115,26 +116,31 @@ it, for example bug fixes or UI improvements. (require 'compat) - should be added early on. In packages which are part of Emacs itself -and which want to take advantage of Compat, the ‘noerror’ flag should be -specified: ‘(require 'compat nil 'noerror)’. In the future a minimal -version of Compat may be added to the Emacs core, such that the -‘noerror’ flag will not be necessary anymore. + should be added early on. This will load all necessary Compat +definitions. Compat loads the ‘seq’ library which is preloaded by +default on Emacs 29. Note that if Compat is installed on a recent +version of Emacs, all of the definitions are disabled at compile time, +such that no negative performance impact is incurred. - This will load all necessary Compat definitions. Compat loads the -‘seq’ library which is preloaded by default on Emacs 29. Note that if -Compat is installed on a recent version of Emacs, all of the definitions -are disabled at compile time, such that no negative performance impact -is incurred. + A minimal version of Compat will be present in Emacs version 30 and +newer. Packages which are part of Emacs itself and want to take +advantage of Compat, can also use ‘(require 'compat)’. The advantage of +the inclusion of a minimal Compat in Emacs is that Compat will not be +installed if you require a version older or equal than the current Emacs +version. For example, if a package depending on Emacs 25.1 and Compat +29.1 is installed on Emacs 30.1, Compat will not be pulled in as +dependency, since Emacs 30.1 already provides the required +functionality. - Note that Compat provides replacement functions with extended -functionality for functions that are already defined (‘sort’, ‘assoc’, -...). These functions may have changed their calling convention -(additional optional arguments) or may have changed their behavior. -These functions must be looked up explicitly with ‘compat-function’ or -called explicitly with ‘compat-call’. We call them “Extended -Definitions”. In contrast, newly “Added Definitions” can be called as -usual. + Compat provides replacement functions with extended functionality for +functions that are already defined, e.g., ‘sort’ or ‘assoc’. These +functions may have changed their calling convention (additional optional +arguments) or may have changed their behavior. These functions must be +looked up explicitly with ‘compat-function’ or called explicitly with +‘compat-call’. We call them “Extended Definitions”. In contrast, newly +“Added Definitions” can be called as usual. The Compat manual +explicitly documents the calling convention of each compatibility +function. (compat-call assoc key alist testfn) ;; Call extended `assoc' (mapcan fun seq) ;; Call newly added `mapcan' @@ -152,22 +158,16 @@ usual. ‘compat-call’ for a more convenient macro to directly call compatibility functions. - If Compat is used in core packages, where Compat must be required -currently with the ‘noerror’ flag, the macros ‘compat-call’ and -‘compat-function’ ar not available. In the future the macros could be -added to subr. Alternatively a minimal version of compat.el could be -added to the core. For now it is necessary to replicate the definition -of the macros within core packages. For example the package ERC defines -its own macro ‘erc-compat-call’, which replicates the Compat definition -precisely. + If Compat is used in Emacs core packages, the macros ‘compat-call’ +and ‘compat-function’ will be available in Emacs version 30 and newer. - This design has been chosen since Compat does not advise or override -existing functions. Generally Compat is written in defensive style -which is supposed to reduce potential breakage, and to increase the -chances of staying binary compatible across releases. The extensive -test coverage ensures that we can maintain high quality, which is -crucial for Compat which is not restricted to a namespace like usual -libraries. + The macros ‘compat-call’ and ‘compat-function’ are introduced by +Compat, since Compat does not advise or override existing functions. +Generally Compat is written in defensive style which is supposed to +reduce potential breakage, and to increase the chances of staying binary +compatible across releases. The extensive test coverage ensures that we +can maintain high quality, which is crucial for Compat which is not +restricted to a namespace like usual libraries. If you intend to use a compatibility function in your code it is recommended that you take a look at the test suite ‘compat-tests.el’. @@ -185,7 +185,7 @@ provide a development mailing list <~pkal/compat-devel@lists.sr.ht>).  -File: doc9SKjtU.info, Node: Limitations, Prev: Usage, Up: Introduction +File: docA0lLBy.info, Node: Limitations, Prev: Usage, Up: Introduction 1.3 Limitations =============== @@ -202,7 +202,7 @@ Compat, since Elisp has seen significant changes at that version. Since On the library level, subr-x was introduced in 24.4. Most popular Emacs packages already require 24.4 or even newer versions of Emacs. Supporting for more historical Emacs versions would complicate -maintainance while only few packages and users would benefit. +maintenance while only few packages and users would benefit. Below we list a number of reasons why certain functionality cannot be provided. Note that in some special cases exceptions can be made and @@ -211,8 +211,8 @@ from the list. In case you miss functionality which you think should belong here, a *note report: Development. would be much appreciated. • The additional functionality is a command or a user-facing minor or - major mode. Compat is limited to functionality on the “library - level”. Generally functions provided by Compat are + major mode. Compat is limited to functionality on the "library + level". Generally functions provided by Compat are non-interactive, such that the user interface (M-x) is unaffected by the presence of Compat. @@ -224,9 +224,9 @@ belong here, a *note report: Development. would be much appreciated. includes some private functions, they are meant purely for internal usage. - • The added or extended function belongs to the “application level” - and not the “library level”. Features which are not preloaded - often belong to the “application level”. Application examples are + • The added or extended function belongs to the "application level" + and not the "library level". Features which are not preloaded + often belong to the "application level". Application examples are programming modes or modes like Dired, IRC and Gnus. If these modes are extended with new functions, these are not ported back. @@ -248,7 +248,7 @@ belong here, a *note report: Development. would be much appreciated. library functions show wrong behavior for edge cases. In those cases Compat could in principle provide a compatibility function which is invoked via ‘compat-call’. Such extended definitions - would increase the maintainance burden of Compat. At the same time + would increase the maintenance burden of Compat. At the same time the benefits would be small given that Compat does not override existing definitions. @@ -269,20 +269,20 @@ belong here, a *note report: Development. would be much appreciated. external libraries that cannot be reasonably duplicated in the scope of a compatibility library. Sometimes new functions on the C level rely on internal data structures, which we cannot access, - rendering a backport impossible. For example a missing libxml - cannot be emulated. + rendering a backport impossible. For example a missing libxml or + libtreesitter cannot be emulated. • The semantics of Elisp changed on a deep level. For example the - addition of Bigint support in Emacs 27.1 cannot be replicated on - the level of Compat. + addition of big integer support in Emacs 27.1 cannot be replicated + on the level of Compat.  -File: doc9SKjtU.info, Node: Support, Next: Development, Prev: Introduction, Up: Top +File: docA0lLBy.info, Node: Support, Next: Development, Prev: Introduction, Up: Top 2 Support ********* -This section goes into the features that Compat manages and doesn’t +This section goes into the features that Compat manages and doesn't manage to provide for each Emacs version. * Menu: @@ -292,9 +292,10 @@ manage to provide for each Emacs version. * Emacs 27.1:: Compatibility support for Emacs 27.1 * Emacs 28.1:: Compatibility support for Emacs 28.1 * Emacs 29.1:: Compatibility support for Emacs 29.1 +* Emacs 30.1:: Compatibility support for Emacs 30.1  -File: doc9SKjtU.info, Node: Emacs 25.1, Next: Emacs 26.1, Up: Support +File: docA0lLBy.info, Node: Emacs 25.1, Next: Emacs 26.1, Up: Support 2.1 Emacs 25.1 ============== @@ -309,7 +310,7 @@ functions are made available by Compat on Emacs versions older than -- User Option: text-quoting-style The value of this user option is a symbol that specifies the style Emacs should use for single quotes in the wording of help and - messages. If the option’s value is ‘curve’, the style is ‘like + messages. If the option's value is ‘curve’, the style is ‘like this’ with curved single quotes. If the value is ‘straight’, the style is 'like this' with straight apostrophes. If the value is ‘grave’, quotes are not translated and the style is `like this' @@ -384,7 +385,7 @@ functions are made available by Compat on Emacs versions older than This is a generalized variable (*note (elisp)Generalized Variables::) that can be used to change a value with ‘setf’. When using it to set a value, optional argument REMOVE non-‘nil’ means - to remove KEY’s association from ALIST if the new value is ‘eql’ to + to remove KEY's association from ALIST if the new value is ‘eql’ to DEFAULT. *note (elisp)Association Lists::. @@ -416,11 +417,11 @@ functions are made available by Compat on Emacs versions older than Check whether HASH-TABLE is empty (has 0 elements). -- Macro: thread-first &rest forms - Combine FORMS into a single expression by “threading” each element + Combine FORMS into a single expression by "threading" each element as the _first_ argument of their successor. Elements of FORMS can either be an list of an atom. - For example, consider the threading expression and it’s equivalent + For example, consider the threading expression and it's equivalent macro expansion: (thread-first @@ -437,11 +438,11 @@ functions are made available by Compat on Emacs versions older than restricted to arithmetic or side-effect free code. -- Macro: thread-last &rest forms - Combine FORMS into a single expression by “threading” each element + Combine FORMS into a single expression by "threading" each element as the _last_ argument of their successor. Elements of FORMS can either be an list of an atom. - For example, consider the threading expression and it’s equivalent + For example, consider the threading expression and it's equivalent macro expansion: (thread-first @@ -476,28 +477,7 @@ functions are made available by Compat on Emacs versions older than *Note (elisp)Bool-Vectors::. -2.1.2 Extended Definitions --------------------------- - -These functions must be called explicitly via ‘compat-call’, since their -calling convention or behavior was extended in Emacs 25.1: - - -- Function: compat-call sort sequence predicate - This function sorts SEQUENCE stably. Note that this function - doesn’t work for all sequences; it may be used only for lists and - vectors. If SEQUENCE is a list, it is modified destructively. - This functions returns the sorted SEQUENCE and compares elements - using PREDICATE. A stable sort is one in which elements with equal - sort keys maintain their relative order before and after the sort. - Stability is important when successive sorts are used to order - elements according to different criteria. - - *Note (elisp)Sequence Functions::. - - The compatibility version adds support for vectors to be sorted, - not just lists. - -2.1.3 Missing Definitions +2.1.2 Missing Definitions ------------------------- Compat does not provide support for the following Lisp features @@ -525,7 +505,7 @@ implemented in 25.1: • The ‘thunk’ library.  -File: doc9SKjtU.info, Node: Emacs 26.1, Next: Emacs 27.1, Prev: Emacs 25.1, Up: Support +File: docA0lLBy.info, Node: Emacs 26.1, Next: Emacs 27.1, Prev: Emacs 25.1, Up: Support 2.2 Emacs 26.1 ============== @@ -608,7 +588,7 @@ functions are made available by Compat on Emacs versions older than Return a hash of BUFFER-OR-NAME. If ‘nil’, this defaults to the current buffer. As opposed to ‘secure-hash’, this function computes the hash based on the internal representation of the - buffer, disregarding any coding systems. It’s therefore only + buffer, disregarding any coding systems. It's therefore only useful when comparing two buffers running in the same Emacs, and is not guaranteed to return the same hash between different Emacs versions. It should be somewhat more efficient on larger buffers @@ -693,7 +673,7 @@ functions are made available by Compat on Emacs versions older than -- Function: file-local-name filename This function returns the _local part_ of FILENAME. This is the - part of the file’s name that identifies it on the remote host, and + part of the file's name that identifies it on the remote host, and is typically obtained by removing from the remote file name the parts that specify the remote host and the method of accessing it. For example: @@ -715,7 +695,7 @@ functions are made available by Compat on Emacs versions older than CHOICES is an alist where the first element in each entry is a character to be entered, the second element is a short name for the - entry to be displayed while prompting (if there’s room, it might be + entry to be displayed while prompting (if there's room, it might be shortened), and the third, optional entry is a longer explanation that will be displayed in a help buffer if the user requests more help. @@ -805,9 +785,9 @@ calling convention or behavior was extended in Emacs 26.1: -- Function: compat-call make-temp-file prefix &optional dir-flag suffix text This function creates a temporary file and returns its name. Emacs - creates the temporary file’s name by adding to PREFIX some random + creates the temporary file's name by adding to PREFIX some random characters that are different in each Emacs job. The result is - guaranteed to be a newly created file, containing TEXT if that’s + guaranteed to be a newly created file, containing TEXT if that's given as a string and empty otherwise. On MS-DOS, this function can truncate PREFIX to fit into the 8+3 file-name limits. If PREFIX is a relative file name, it is expanded against @@ -936,7 +916,7 @@ implemented in 26.1: • The ‘svg’ library (published separately as a :core package).  -File: doc9SKjtU.info, Node: Emacs 27.1, Next: Emacs 28.1, Prev: Emacs 26.1, Up: Support +File: docA0lLBy.info, Node: Emacs 27.1, Next: Emacs 28.1, Prev: Emacs 26.1, Up: Support 2.3 Emacs 27.1 ============== @@ -984,7 +964,7 @@ functions are made available by Compat on Emacs versions older than character. Optionally, it ignores any input that is not a member of CHARS, a list of accepted characters. The HISTORY argument specifies the history list symbol to use; if it is omitted or - ‘nil’, this function doesn’t use the history. + ‘nil’, this function doesn't use the history. If you bind ‘help-form’ to a non-‘nil’ value while calling ‘read-char-from-minibuffer’, then pressing ‘help-char’ causes it to @@ -1024,10 +1004,10 @@ functions are made available by Compat on Emacs versions older than -- Function: string-distance string1 string2 &optional bytecompare This function returns the _Levenshtein distance_ between the source string STRING1 and the target string STRING2. The Levenshtein - distance is the number of single-character changes—deletions, - insertions, or replacements—required to transform the source string - into the target string; it is one possible definition of the _edit - distance_ between strings. + distance is the number of single-character changes--deletions, + insertions, or replacements--required to transform the source + string into the target string; it is one possible definition of the + _edit distance_ between strings. Letter-case of the strings is significant for the computed distance, but their text properties are ignored. If the optional @@ -1047,7 +1027,7 @@ functions are made available by Compat on Emacs versions older than returns the value of the last form in BODY; otherwise, it returns ‘nil’. - Here’s the example at the beginning of this subsection rewritten + Here's the example at the beginning of this subsection rewritten using ‘ignore-errors’: (ignore-errors (delete-file filename)) @@ -1068,7 +1048,7 @@ functions are made available by Compat on Emacs versions older than *Note (elisp)Progress::. -- Function: flatten-tree tree - This function returns a “flattened” copy of TREE, that is, a list + This function returns a "flattened" copy of TREE, that is, a list containing all the non-‘nil’ terminal nodes, or leaves, of the tree of cons cells rooted at TREE. Leaves in the returned list are in the same order as in TREE. @@ -1204,14 +1184,14 @@ functions are made available by Compat on Emacs versions older than it moves point, but it returns a structure that describes the match instead of returning it in ‘match-beginning’ and friends. - If the text property can’t be found, the function returns ‘nil’. - If it’s found, point is placed at the end of the region that has + If the text property can't be found, the function returns ‘nil’. + If it's found, point is placed at the end of the region that has this text property match, and a ‘prop-match’ structure is returned. PREDICATE can either be ‘t’ (which is a synonym for ‘equal’), ‘nil’ - (which means “not equal”), or a predicate that will be called with + (which means "not equal"), or a predicate that will be called with two parameters: The first is VALUE, and the second is the value of - the text property we’re inspecting. + the text property we're inspecting. If NOT-CURRENT, if point is in a region where we have a match, then skip past that and find the next instance instead. @@ -1221,12 +1201,12 @@ functions are made available by Compat on Emacs versions older than (the end of the match), and ‘prop-match-value’ (the value of PROPERTY at the start of the match). - In the examples below, imagine that you’re in a buffer that looks + In the examples below, imagine that you're in a buffer that looks like this: This is a bold and here's bolditalic and this is the end. - That is, the “bold” words are the ‘bold’ face, and the “italic” + That is, the "bold" words are the ‘bold’ face, and the "italic" word is in the ‘italic’ face. With point at the start: @@ -1323,7 +1303,7 @@ calling convention or behavior was extended in Emacs 27.1: -- Function: compat-call regexp-opt strings &optional paren This function returns an efficient regular expression that will match any of the strings in the list STRINGS. This is useful when - you need to make matching or searching as fast as possible—for + you need to make matching or searching as fast as possible--for example, for Font Lock mode. *Note (elisp)Regexp Functions::. @@ -1405,7 +1385,7 @@ implemented in 27.1: • The ‘image-converter’ library.  -File: doc9SKjtU.info, Node: Emacs 28.1, Next: Emacs 29.1, Prev: Emacs 27.1, Up: Support +File: docA0lLBy.info, Node: Emacs 28.1, Next: Emacs 29.1, Prev: Emacs 27.1, Up: Support 2.4 Emacs 28.1 ============== @@ -1459,13 +1439,13 @@ available by Compat. -- Function: file-name-concat directory &rest components Concatenate COMPONENTS to DIRECTORY, inserting a slash before the - components if DIRECTORY or the preceding component didn’t end with + components if DIRECTORY or the preceding component didn't end with a slash. (file-name-concat "/tmp" "foo") ⇒ "/tmp/foo" A DIRECTORY or components that are ‘nil’ or the empty string are - ignored—they are filtered out first and do not affect the results + ignored--they are filtered out first and do not affect the results in any way. This is almost the same as using ‘concat’, but DIRNAME (and the @@ -1506,31 +1486,35 @@ available by Compat. *Note (elisp)Insertion::. - -- Function: replace-string-in-region regexp replacement &optional - start end - This function replaces all the occurrences of REGEXP with - REPLACEMENT in the region of buffer text between START and END; - START defaults to position of point, and END defaults to the last - accessible position of the buffer. The search for REGEXP is - case-sensitive, and REPLACEMENT is inserted without changing its - letter-case. The REPLACEMENT string can use the same special - elements starting with ‘\’ as ‘replace-match’ does. The function - returns the number of replaced occurrences, or ‘nil’ if REGEXP is - not found. The function preserves the position of point. - - (replace-regexp-in-region "foo[ \t]+bar" "foobar") - *Note (elisp)Search and Replace::. - - -- Function: replace-regexp-in-string string replacement &optional + -- Function: replace-string-in-region string replacement &optional start end This function works similarly to ‘replace-regexp-in-region’, but searches for, and replaces, literal STRINGs instead of regular expressions. - *Note (elisp)Search and Replace::. + -- Function: replace-regexp-in-string regexp rep string &optional + fixedcase literal subexp start + This function copies STRING and searches it for matches for REGEXP, + and replaces them with REP. It returns the modified copy. If + START is non-‘nil’, the search for matches starts at that index in + STRING, and the returned value does not include the first START + characters of STRING. To get the whole transformed string, + concatenate the first START characters of STRING with the return + value. + + This function uses ‘replace-match’ to do the replacement, and it + passes the optional arguments FIXEDCASE, LITERAL and SUBEXP along + to ‘replace-match’. + + Instead of a string, REP can be a function. In that case, + ‘replace-regexp-in-string’ calls REP for each match, passing the + text of the match as its sole argument. It collects the value REP + returns and passes that to ‘replace-match’ as the replacement + string. The match data at this point are the result of matching + REGEXP against a substring of STRING. -- Function: buffer-local-boundp variable buffer - This returns non-‘nil’ if there’s either a buffer-local binding of + This returns non-‘nil’ if there's either a buffer-local binding of VARIABLE (a symbol) in buffer BUFFER, or VARIABLE has a global binding. @@ -1539,9 +1523,9 @@ available by Compat. -- Macro: with-existing-directory body... This macro ensures that ‘default-directory’ is bound to an existing directory before executing BODY. If ‘default-directory’ already - exists, that’s preferred, and otherwise some other directory is + exists, that's preferred, and otherwise some other directory is used. This macro can be useful, for instance, when calling an - external command that requires that it’s running in a directory + external command that requires that it's running in a directory that exists. The chosen directory is not guaranteed to be writable. @@ -1549,14 +1533,14 @@ available by Compat. -- Macro: dlet (bindings...) forms... This special form is like ‘let’, but it binds all variables - dynamically. This is rarely useful—you usually want to bind normal - variables lexically, and special variables (i.e., variables that - are defined with ‘defvar’) dynamically, and this is what ‘let’ + dynamically. This is rarely useful--you usually want to bind + normal variables lexically, and special variables (i.e., variables + that are defined with ‘defvar’) dynamically, and this is what ‘let’ does. ‘dlet’ can be useful when interfacing with old code that assumes that certain variables are dynamically bound (*note (elisp)Dynamic - Binding::), but it’s impractical to ‘defvar’ these variables. + Binding::), but it's impractical to ‘defvar’ these variables. ‘dlet’ will temporarily make the bound variables special, execute the forms, and then make the variables non-special again. @@ -1602,7 +1586,7 @@ available by Compat. character. PADDING defaults to the space character. If STRING is longer than LENGTH, no padding is done. If START is ‘nil’ or omitted, the padding is appended to the characters of STRING, and - if it’s non-‘nil’, the padding is prepended to STRING’s characters. + if it's non-‘nil’, the padding is prepended to STRING's characters. *Note (elisp)Creating Strings::. @@ -1663,7 +1647,7 @@ available by Compat. ‘minibuffer-default-prompt-format’ variable. ‘minibuffer-default-prompt-format’ is a format string (defaulting - to ‘" (default %s)"’ that says how the “default” bit in prompts + to ‘" (default %s)"’ that says how the "default" bit in prompts like ‘"Local filename (default somefile): "’ are to be formatted. To allow the users to customize how this is displayed, code that @@ -1683,7 +1667,7 @@ available by Compat. default values are displayed. If DEFAULT is ‘nil’, there is no default value, and therefore no - “default value” string is included in the result value. If DEFAULT + "default value" string is included in the result value. If DEFAULT is a non-‘nil’ list, the first element of the list is used in the prompt. @@ -1718,7 +1702,7 @@ available by Compat. temporarily when executing BODY. The previous values are restored when the form finishes. The argument VARIABLES should be a list of pairs of strings of the form ‘(VAR VALUE)’, where VAR is the name - of the environment variable and VALUE is that variable’s value. + of the environment variable and VALUE is that variable's value. (with-environment-variables (("LANG" "C") ("LANGUAGE" "en_US:en")) @@ -1775,11 +1759,6 @@ available by Compat. native compilation is not available, this function behaves identically to ‘subrp’. - -- Function: subr-native-elisp-p object - Return ‘t’ if OBJECT if the object is native compiled lisp. If - native compilation is not available, this function always returns - ‘nil’. - -- Function: native-comp-available-p This function returns non-‘nil’ if the running Emacs process has the native-compilation support compiled into it. On systems that @@ -1866,7 +1845,7 @@ implemented in 28.1: • The ‘multisession’ library.  -File: doc9SKjtU.info, Node: Emacs 29.1, Prev: Emacs 28.1, Up: Support +File: docA0lLBy.info, Node: Emacs 29.1, Next: Emacs 30.1, Prev: Emacs 28.1, Up: Support 2.5 Emacs 29.1 ============== @@ -1882,9 +1861,15 @@ will be the need for changes, so use these functions with care. The ‘defcustom’ type ‘key’ introduced in Emacs 29.1 is made available by Compat. + -- Variable: untrusted-content + Non-nil means that current buffer originated from an untrusted + source. Email clients and some other modes may set this non-nil to + mark the buffer contents as untrusted. This variable might be + subject to change without notice. + -- Variable: lisp-directory This variable holds a string naming the directory which holds - Emacs’s own ‘*.el’ and ‘*.elc’ files. This is usually the place + Emacs's own ‘*.el’ and ‘*.elc’ files. This is usually the place where those files are located in the Emacs installation tree, unless Emacs is run from its build directory in which case it points to the ‘lisp’ subdirectory in the source directory from @@ -1896,7 +1881,7 @@ by Compat. -- Function: readablep object This predicate says whether OBJECT has “readable syntax”, i.e., it can be written out and then read back by the Emacs Lisp reader. If - it can’t, this function returns ‘nil’; if it can, this function + it can't, this function returns ‘nil’; if it can, this function returns a printed representation (via ‘prin1’). -- Function: substitute-quotes string @@ -1935,7 +1920,7 @@ by Compat. -- Macro: with-memoization PLACE CODE... This macro provides a simple way to do memoization. CODE is - evaluated and then stashed in PLACE. If PLACE’s value is + evaluated and then stashed in PLACE. If PLACE's value is non-‘nil’, return that value instead of evaluating CODE. -- Special Form: with-restriction start end [:label label] body @@ -1992,8 +1977,12 @@ by Compat. Like ‘line-end-position’, but ignores fields (and is more efficient). + -- Function: char-uppercase-p char + Return non-‘nil’ if CHAR is an uppercase character according to + Unicode. + -- Macro: with-delayed-message (timeout message) body... - Sometimes it’s unclear whether an operation will take a long time + Sometimes it's unclear whether an operation will take a long time to execute or not, or it can be inconvenient to implement a progress reporter. This macro can be used in those situations. @@ -2002,7 +1991,7 @@ by Compat. In this example, if the body takes more than two seconds to execute, the message will be displayed. If it takes a shorter time - than that, the message won’t be displayed. In either case, the + than that, the message won't be displayed. In either case, the body is evaluated as normally, and the return value of the final element in the body is the return value of the macro. @@ -2018,7 +2007,7 @@ by Compat. MESSAGE is not displayed. -- Function: buttonize string callback &optional data help-echo - Sometimes it’s more convenient to make a string into a button + Sometimes it's more convenient to make a string into a button without inserting it into a buffer immediately, for instance when creating data structures that may then, later, be inserted into a buffer. This function makes STRING into such a string, and @@ -2030,7 +2019,7 @@ by Compat. help-echo Make the region between START and END into a button. When clicked, CALLBACK will be called with the DATA as the function argument. If - DATA isn’t present (or is nil), the button itself will be used + DATA isn't present (or is nil), the button itself will be used instead as the function argument. If HELP-ECHO, use that as the help-echo property. @@ -2047,7 +2036,7 @@ by Compat. argument should be either a string or a buffer, and defaults to the current buffer. If the optional PROPERTIES argument is non-‘nil’, it should be a ‘display’ property, and in that case, POSITION and - OBJECT are ignored. (This can be useful if you’ve already gotten + OBJECT are ignored. (This can be useful if you've already gotten the ‘display’ property with ‘get-char-property’, for instance (*note Examining Properties: (elisp)Examining Properties.). @@ -2103,7 +2092,7 @@ by Compat. (function-alias-p 'a) ⇒ (b c) - If there’s a loop in the definitions, an error will be signalled. + If there's a loop in the definitions, an error will be signalled. If NOERROR is non-‘nil’, the non-looping parts of the chain is returned instead. @@ -2134,7 +2123,7 @@ by Compat. is ARG (or ‘nil’ if ARG is omitted). • A cons-cell ‘(OPER . EXPR)’ where OPER is one of ‘not’ - Satisfied if EXPR doesn’t satisfy ‘buffer-match-p’ with + Satisfied if EXPR doesn't satisfy ‘buffer-match-p’ with the same buffer and ‘arg’. ‘or’ Satisfied if EXPR is a list and _any_ condition in EXPR @@ -2144,9 +2133,9 @@ by Compat. Satisfied if EXPR is a list and _all_ conditions in EXPR satisfy ‘buffer-match-p’, with the same buffer and ‘arg’. ‘derived-mode’ - Satisfied if the buffer’s major mode derives from EXPR. + Satisfied if the buffer's major mode derives from EXPR. ‘major-mode’ - Satisfied if the buffer’s major mode is equal to EXPR. + Satisfied if the buffer's major mode is equal to EXPR. Prefer using ‘derived-mode’ instead when both can work. • t Satisfied by any buffer. A convenient alternative to ‘""’ (empty string), ‘(and)’ (empty conjunction) or ‘always’. @@ -2170,7 +2159,7 @@ by Compat. that happens, characters no longer map in a simple way to display columns, and display layout decisions with such strings, such as truncating too wide strings, can be a complex job. This function - helps in performing suvh jobs: it splits up its argument STRING + helps in performing such jobs: it splits up its argument STRING into a list of substrings, where each substring produces a single grapheme cluster that should be displayed as a unit. Lisp programs can then use this list to construct visually-valid substrings of @@ -2197,7 +2186,7 @@ by Compat. purpose of detecting the lack of changes in buffer text. Any other changes that are normally perceived as "buffer modifications", such as changes in text properties, ‘buffer-file-coding-system’, buffer - multibyteness, etc. – will not be noticed, and the buffer will + multibyteness, etc. - will not be noticed, and the buffer will still be marked unmodified, effectively ignoring those changes. -- Function: file-attribute-file-identifier @@ -2258,7 +2247,7 @@ by Compat. may be preceded by one or more modifier keys. Finally, a limited number of characters have a special shorthand syntax. - Here’s some example key sequences. + Here's some example key sequences. ‘f’ The key ‘f’. @@ -2295,7 +2284,7 @@ by Compat. If KEY is ‘’, this sets the default binding in KEYMAP. When an event has no binding of its own, the Emacs command loop uses the - keymap’s default binding, if there is one. + keymap's default binding, if there is one. Every prefix of KEY must be a prefix key (i.e., bound to a keymap) or undefined; otherwise an error is signaled. If some prefix of @@ -2334,8 +2323,8 @@ by Compat. map. One use of this function is in preparation for defining a longer - key that uses KEY as a prefix—which would not be allowed if KEY has - a non-prefix binding. For example: + key that uses KEY as a prefix--which would not be allowed if KEY + has a non-prefix binding. For example: (keymap-global-unset "C-l") ⇒ nil @@ -2386,7 +2375,7 @@ by Compat. frequently have to bind a large number of keys at once, and using ‘keymap-set’ on them all can be tedious and error-prone. Instead you can use ‘define-keymap’, which creates a keymap and binds a - number of keys. Here’s a very basic example: + number of keys. Here's a very basic example: (define-keymap "n" #'forward-line @@ -2400,7 +2389,7 @@ by Compat. accepted by ‘keymap-set’. In addition, the key can be the special symbol ‘:menu’, in which case the definition should be a menu definition as accepted by ‘easy-menu-define’ (*note (elisp)Easy - Menu::). Here’s a brief example of this usage: + Menu::). Here's a brief example of this usage: (define-keymap :full t "g" #'eww-reload @@ -2411,7 +2400,7 @@ by Compat. A number of keywords can be used before the key/definition pairs to change features of the new keymap. If any of the feature keywords is missing from the ‘define-keymap’ call, the default value for - that feature is ‘nil’. Here’s a list of the available feature + that feature is ‘nil’. Here's a list of the available feature keywords: ‘:full’ @@ -2449,18 +2438,18 @@ by Compat. -- Function: defvar-keymap (variable-name &rest defs) By far, the most common thing to do with a keymap is to bind it to - a variable. This is what virtually all modes do—a mode called + a variable. This is what virtually all modes do--a mode called ‘foo’ almost always has a variable called ‘foo-mode-map’. This macro defines NAME as a variable, passes OPTIONS and PAIRS to ‘define-keymap’, and uses the result as the default value for the variable. - OPTIONS is like the keywords in ‘define-keymap’, but there’s an + OPTIONS is like the keywords in ‘define-keymap’, but there's an additional ‘:doc’ keyword that provides the doc string for the defined variable. - Here’s an example: + Here's an example: (defvar-keymap eww-textarea-map :parent text-mode-map @@ -2473,6 +2462,12 @@ by Compat. This is comparable to ‘and-let*’. + -- Function: window-configuration-equal-p config1 config2 + This function says whether two window configurations have the same + window layout, but ignores the values of point and the saved + scrolling positions--it can return ‘t’ even if those aspects + differ. + -- Macro: ert-with-temp-file name &rest body Bind NAME to the name of a new temporary file and evaluate BODY. Delete the temporary file after BODY exits normally or non-locally. @@ -2500,7 +2495,7 @@ by Compat. variables in NAMES bound to a fresh uninterned symbol, or “gensym”, in Common Lisp parlance. For macros requiring more than one gensym, use of ‘cl-with-gensyms’ shortens the code and renders - one’s intentions clearer. Compare: + one's intentions clearer. Compare: (defmacro my-macro (foo) (let ((bar (gensym "bar")) @@ -2607,7 +2602,7 @@ calling convention or behavior was extended in Emacs 29.1: Split STRING into a list of strings on newline boundaries. If the optional argument OMIT-NULLS is non-‘nil’, remove empty lines from the results. If the optional argument KEEP-NEWLINES is non-‘nil’, - don’t remove the trailing newlines from the result strings. + don't remove the trailing newlines from the result strings. *Note (elisp)Creating Strings::. @@ -2677,6 +2672,8 @@ implemented in 29.1: • The function ‘string-pixel-width’ and ‘buffer-text-pixel-size’. • The function ‘minibuffer-lazy-highlight-setup’. • The function ‘pp-emacs-lisp-code’. + • The function ‘bidi-string-strip-control-characters’. + • The native function ‘current-cpu-time’. • The functions ‘xdg-state-home’, ‘xdg-current-desktop’ and ‘xdg-session-type’. • The macro ‘setopt’. @@ -2686,9 +2683,323 @@ implemented in 29.1: • The ‘string-edit’ library. • The ‘vtable’ library. • The ‘pixel-fill’ library. + • Support for symbols with position information.  -File: doc9SKjtU.info, Node: Development, Next: Function Index, Prev: Support, Up: Top +File: docA0lLBy.info, Node: Emacs 30.1, Prev: Emacs 29.1, Up: Support + +2.6 Emacs 30.1 +============== + +2.6.1 Added Definitions +----------------------- + +The following functions and macros are implemented in Emacs 30.1. These +functions are made available by Compat on Emacs versions older than +30.1. Note that due to upstream changes, it might happen that there +will be the need for changes, so use these functions with care. + + -- Variable: trusted-content + List of files and directories whose content we trust. Be extra + careful here since trusting means that Emacs might execute the code + contained within those files and directories without an explicit + request by the user. One important case when this might happen is + when ‘flymake-mode’ is enabled (for example, when it is added to a + mode hook). Each element of the list should be a string: - If it + ends in "/", it is considered as a directory name and means that + Emacs should trust all the files whose name has this directory as a + prefix. - else it is considered as a file name. Use abbreviated + file names. For example, an entry "~/mycode" means that Emacs will + trust all the files in your directory "mycode". This variable can + also be set to ‘:all’, in which case Emacs will trust all files, + which opens a gaping security hole. + + -- Function: trusted-content-p + Return non-nil if we trust the contents of the current buffer. + Here, "trust" means that we are willing to run code found inside of + it. See also ‘trusted-content’. + + -- Function: color-oklab-to-xyz l a b + Convert the OkLab color represented by L A B to CIE XYZ. Oklab is a + perceptual color space created by Björn Ottosson + . It has the property + that changes in the hue and saturation of a color can be made while + maintaining the same perceived lightness. + + -- Function: color-xyz-to-oklab x y z + Convert the CIE XYZ color represented by X Y Z to Oklab. + + -- Function: color-oklab-to-srgb l a b + Convert the Oklab color represented by L A B to sRGB. + + -- Function: color-srgb-to-oklab r g b + Convert the sRGB color R G B to Oklab. + + -- Function: char-to-name char + This function returns the Unicode name of CHAR. It returns ‘nil’ + if CHAR is not a character or has no Unicode name. + + -- Function: obarray-clear obarray + This function removes all symbols from OBARRAY. + + -- Function: closurep object + This function returns ‘t’ if OBJECT is a closure, which is a + particular kind of function object. Currently closures are used + for all byte-code functions and all interpreted functions. + + -- Function: interpreted-function-p object + This function returns ‘t’ if OBJECT is an interpreted function. + + -- Function: primitive-function-p object + Return ‘t’ if OBJECT is a built-in primitive function. This + excludes special forms, since they are not functions. + + -- Function: value< a b + This function returns non-‘nil’ if A comes before B in the standard + sorting order; this means that it returns ‘nil’ when B comes before + A, or if they are equal or unordered. + + The arguments A and B must have the same type. Specifically: + + • Numbers are compared using ‘<’. + • Strings are compared using ‘string<’ and symbols are compared + by comparing their names as strings. + • Conses, lists, vectors and records are compared + lexicographically. This means that the two sequences are + compared element-wise from left to right until they differ, + and the result is then that of ‘value<’ on the first pair of + differing elements. If one sequence runs out of elements + before the other, the shorter sequence comes before the + longer. + • Markers are compared first by buffer, then by position. + • Buffers and processes are compared by comparing their names as + strings. Dead buffers (whose name is ‘nil’) will compare + before any live buffer. + • Other types are considered unordered and the return value will + be ‘nil’. + + Examples: + (value< -4 3.5) ⇒ t + (value< "dog" "cat") ⇒ nil + (value< 'yip 'yip) ⇒ nil + (value< '(3 2) '(3 2 0)) ⇒ t + (value< [3 2 "a"] [3 2 "b"]) ⇒ t + + Note that ‘nil’ is treated as either a symbol or an empty list, + depending on what it is compared against: + + (value< nil '(0)) ⇒ t + (value< 'nib nil) ⇒ t + + There is no limit to the length of sequences (lists, vectors and so + on) that can be compared, but ‘value<’ may fail with an error if + used to compare circular or deeply nested data structures. + + -- Function: drop n list + This function is an alias for ‘nthcdr’. It returns the Nth CDR of + LIST. In other words, it skips past the first N links of LIST and + returns what follows. + + -- Function: get-truename-buffer filename + Return the buffer with ‘file-truename’ equal to FILENAME (a + string). If there is no such live buffer, return nil. See also + ‘find-buffer-visiting’. + + -- Function: find-buffer variable value + Return the buffer with buffer-local VARIABLE equal to VALUE. If + there is no such live buffer, return nil. + + -- Function: require-with-check feature &optional filename noerror + This function works like ‘require’, except if FEATURE is already + loaded (i.e. is already a member of the list in ‘features’, see + below). If FEATURE is already loaded, this function checks if + FEATURE was provided by a file different from FILENAME, and if so, + it by default signals an error. If the value of the optional + argument NOERROR is ‘reload’, the function doesn't signal an error, + but instead forcibly reloads FILENAME; if NOERROR is some other + non-‘nil’ value, the function emits a warning about FEATURE being + already provided by another file. + + -- Function: merge-ordered-lists lists &optional error-function + Merge LISTS in a consistent order. LISTS is a list of lists of + elements. Merge them into a single list containing the same + elements (removing duplicates), obeying their relative positions in + each list. The order of the (sub)lists determines the final order + in those cases where the order within the sublists does not impose + a unique choice. Equality of elements is tested with ‘eql’. + + If a consistent order does not exist, call ERROR-FUNCTION with a + remaining list of lists that we do not know how to merge. It + should return the candidate to use to continue the merge, which has + to be the head of one of the lists. By default we choose the head + of the first list. + + -- Variable: completion-lazy-hilit + If non-nil, request lazy highlighting of completion candidates. + + Lisp programs (a.k.a. "front ends") that present completion + candidates may opt to bind this variable to a non-nil value when + calling functions (such as ‘completion-all-completions’) which + produce completion candidates. This tells the underlying + completion styles that they do not need to fontify (i.e., + propertize with the ‘face’ property) completion candidates in a way + that highlights the matching parts. Then it is the front end which + presents the candidates that becomes responsible for this + fontification. The front end does that by calling the function + ‘completion-lazy-hilit’ on each completion candidate that is to be + displayed to the user. + + Note that only some completion styles take advantage of this + variable for optimization purposes. Other styles will ignore the + hint and fontify eagerly as usual. It is still safe for a front + end to call ‘completion-lazy-hilit’ in these situations. + + To author a completion style that takes advantage of this variable, + see ‘completion-lazy-hilit-fn’ and + ‘completion-pcm--hilit-commonality’. + + -- Variable: completion-lazy-hilit-fn + Fontification function set by lazy-highlighting completions styles. + When a given style wants to enable support for + ‘completion-lazy-hilit’ (which see), that style should set this + variable to a function of one argument. It will be called with + each completion candidate, a string, to be displayed to the user, + and should destructively propertize these strings with the ‘face’ + property. + + -- Function: completion-lazy-hilit str + Return a copy of completion candidate STR that is face-propertized. + See documentation of the variable ‘completion-lazy-hilit’ for more + details. + + -- Macro: static-if condition then-form else-forms... + Test CONDITION at macro-expansion time. If its value is non-‘nil’, + expand the macro to THEN-FORM, otherwise expand it to ELSE-FORMS + enclosed in a ‘progn’. ELSE-FORMS may be empty. + + Here is an example of its use from CC Mode, which prevents a + ‘defadvice’ form being compiled in newer versions of Emacs: + (static-if (boundp 'comment-line-break-function) + (progn) + (defvar c-inside-line-break-advice nil) + (defadvice indent-new-comment-line (around c-line-break-advice + activate preactivate) + "Call `c-indent-new-comment-line' if in CC Mode." + (if (or c-inside-line-break-advice + (not c-buffer-is-cc-mode)) + ad-do-it + (let ((c-inside-line-break-advice t)) + (c-indent-new-comment-line (ad-get-arg 0)))))) + +2.6.2 Extended Definitions +-------------------------- + +These functions must be called explicitly via ‘compat-call’, since their +calling convention or behavior was extended in Emacs 30.1: + + -- Function: compat-call sort sequence &rest keyword-args + This function sorts SEQUENCE, which must be a list or vector, and + returns a sorted sequence of the same type. The sort is stable, + which means that elements with equal sort keys maintain their + relative order. It takes the following optional keyword arguments: + + ‘:key KEYFUNC’ + Use KEYFUNC, a function that takes a single element from + SEQUENCE and returns its key value, to generate the keys used + in comparison. If this argument is absent or if KEYFUNC is + ‘nil’ then ‘identity’ is assumed; that is, the elements + themselves are used as sorting keys. + + ‘:lessp PREDICATE’ + Use PREDICATE to order the keys. PREDICATE is a function that + takes two sort keys as arguments and returns non-‘nil’ if the + first should come before the second. If this argument is + absent or PREDICATE is ‘nil’, then ‘value<’ is used, which is + applicable to many different Lisp types and generally sorts in + ascending order. + + For consistency, any predicate must obey the following rules: + • It must be “antisymmetric”: it cannot both order A before + B and B before A. + • It must be “transitive”: if it orders A before B and B + before C, then it must also order A before C. + + ‘:reverse FLAG’ + If FLAG is non-‘nil’, the sorting order is reversed. With the + default ‘:lessp’ predicate this means sorting in descending + order. + + ‘:in-place FLAG’ + If FLAG is non-‘nil’, then SEQUENCE is sorted in-place + (destructively) and returned. If ‘nil’, or if this argument + is not given, a sorted copy of the input is returned and + SEQUENCE itself remains unmodified. In-place sorting is + slightly faster, but the original sequence is lost. + + If the default behaviour is not suitable for your needs, it is + usually easier and faster to supply a new ‘:key’ function than a + different ‘:lessp’ predicate. For example, consider sorting these + strings: + + (setq numbers '("one" "two" "three" "four" "five" "six")) + (sort numbers) + ⇒ ("five" "four" "one" "six" "three" "two") + + You can sort the strings by length instead by supplying a different + key function: + + (sort numbers :key #'length) + ⇒ ("one" "two" "six" "four" "five" "three") + + Note how strings of the same length keep their original order, + thanks to the sorting stability. Now suppose you want to sort by + length, but use the string contents to break ties. The easiest way + is to specify a key function that transforms an element to a value + that is sorted this way. Since ‘value<’ orders compound objects + (conses, lists, vectors and records) lexicographically, you could + do: + + (sort numbers :key (lambda (x) (cons (length x) x))) + ⇒ ("one" "six" "two" "five" "four" "three") + + because ‘(3 . "six")’ is ordered before ‘(3 . "two")’ and so on. + + For compatibility with previous versions of Emacs, the ‘sort’ + function can also be called using the fixed two-argument form: + + (sort SEQUENCE PREDICATE) + + where PREDICATE is the ‘:lessp’ argument. When using this form, + sorting is always done in-place. + + -- Function: compat-call completion-metadata-get metadata prop + Get property PROP from completion METADATA. If the metadata + specifies a completion category, the variables + ‘completion-category-overrides’ and ‘completion-category-defaults’ + take precedence for category-specific overrides. If the completion + metadata does not specify the property, the + ‘completion-extra-properties’ plist is consulted. Note that the + keys of the ‘completion-extra-properties’ plist are keyword + symbols, not plain symbols. + + -- Function: compat-call copy-tree tree &optional vectors-and-records + This function returns a copy of the tree TREE. If TREE is a cons + cell, this makes a new cons cell with the same CAR and CDR, then + recursively copies the CAR and CDR in the same way. + + Normally, when TREE is anything other than a cons cell, ‘copy-tree’ + simply returns TREE. However, if VECTORS-AND-RECORDS is non-‘nil’, + it copies vectors and records too (and operates recursively on + their elements). The TREE argument must not contain cycles. + +2.6.3 Missing Definitions +------------------------- + +Compat does not provide support for the following Lisp features +implemented in 30.1: + + +File: docA0lLBy.info, Node: Development, Next: Function Index, Prev: Support, Up: Top 3 Development ************* @@ -2706,13 +3017,26 @@ issues. We also provide a development mailing list to have signed the FSF copyright assignment (https://www.gnu.org/software/emacs/manual/html_node/emacs/Copyright-Assignment.html), before any non-trivial contribution (roughly 15 lines of code) can be -applied. It is important that you provide tests when you contribute new +applied. + + It is important that you provide tests when you contribute new functionality. Compat has 100% test coverage by the test suite. We use continuous integration to check if patches preserve existing functionality. + Development for the currently stable Emacs version happens in the +main branch of the Compat Git repository. ELPA-devel nightly builds are +created from this branch. New features, which are not yet ready to be +merged directly into the main branch, are developed in feature branches. +Furthermore the Git repository has a branch emacs- where the +development for the upcoming Emacs release takes place. This branch is +separate from the main branch since the new functionality should not be +made available (neither via ELPA nor ELPA-devel) before the new Emacs +version has been reasonably stabilized, e.g., around the time when the +Emacs version branch is created in the Emacs repository on Savannah. +  -File: doc9SKjtU.info, Node: Function Index, Next: Variable Index, Prev: Development, Up: Top +File: docA0lLBy.info, Node: Function Index, Next: Variable Index, Prev: Development, Up: Top Appendix A Function Index ************************* @@ -2720,53 +3044,63 @@ Appendix A Function Index [index] * Menu: -* add-display-text-property: Emacs 29.1. (line 186) +* add-display-text-property: Emacs 29.1. (line 196) * alist-get: Emacs 25.1. (line 82) * always: Emacs 28.1. (line 83) * and-let*: Emacs 26.1. (line 158) * assoc-delete-all: Emacs 26.1. (line 13) * bignump: Emacs 27.1. (line 55) * bool-vector: Emacs 25.1. (line 177) -* bounds-of-thing-at-mouse: Emacs 28.1. (line 292) +* bounds-of-thing-at-mouse: Emacs 28.1. (line 296) * buffer-hash: Emacs 26.1. (line 80) -* buffer-local-boundp: Emacs 28.1. (line 125) -* buffer-local-restore-state: Emacs 29.1. (line 50) -* buffer-local-set-state: Emacs 29.1. (line 50) -* buffer-match-p: Emacs 29.1. (line 254) -* buttonize: Emacs 29.1. (line 152) -* buttonize-region: Emacs 29.1. (line 161) -* cl-constantly: Emacs 29.1. (line 626) -* cl-once-only: Emacs 29.1. (line 649) -* cl-with-gensyms: Emacs 29.1. (line 630) -* color-dark-p: Emacs 28.1. (line 322) -* color-values-from-color-spec: Emacs 28.1. (line 328) -* compat-call: Usage. (line 45) +* buffer-local-boundp: Emacs 28.1. (line 129) +* buffer-local-restore-state: Emacs 29.1. (line 56) +* buffer-local-set-state: Emacs 29.1. (line 56) +* buffer-match-p: Emacs 29.1. (line 264) +* buttonize: Emacs 29.1. (line 162) +* buttonize-region: Emacs 29.1. (line 171) +* char-to-name: Emacs 30.1. (line 50) +* char-uppercase-p: Emacs 29.1. (line 133) +* cl-constantly: Emacs 29.1. (line 642) +* cl-once-only: Emacs 29.1. (line 665) +* cl-with-gensyms: Emacs 29.1. (line 646) +* closurep: Emacs 30.1. (line 57) +* color-dark-p: Emacs 28.1. (line 326) +* color-oklab-to-srgb: Emacs 30.1. (line 44) +* color-oklab-to-xyz: Emacs 30.1. (line 34) +* color-srgb-to-oklab: Emacs 30.1. (line 47) +* color-values-from-color-spec: Emacs 28.1. (line 332) +* color-xyz-to-oklab: Emacs 30.1. (line 41) +* compat-call: Usage. (line 50) * compat-call alist-get: Emacs 26.1. (line 344) * compat-call assoc: Emacs 26.1. (line 316) * compat-call assoc-delete-all: Emacs 27.1. (line 417) -* compat-call count-windows: Emacs 28.1. (line 412) -* compat-call define-key: Emacs 29.1. (line 746) +* compat-call completion-metadata-get: Emacs 30.1. (line 287) +* compat-call copy-tree: Emacs 30.1. (line 297) +* compat-call count-windows: Emacs 28.1. (line 411) +* compat-call define-key: Emacs 29.1. (line 762) * compat-call executable-find: Emacs 27.1. (line 429) * compat-call file-size-human-readable: Emacs 27.1. (line 397) * compat-call line-number-at-pos: Emacs 26.1. (line 330) * compat-call lookup-key: Emacs 27.1. (line 356) * compat-call make-temp-file: Emacs 26.1. (line 278) -* compat-call plist-get: Emacs 29.1. (line 762) -* compat-call plist-member: Emacs 29.1. (line 786) -* compat-call plist-put: Emacs 29.1. (line 774) +* compat-call plist-get: Emacs 29.1. (line 778) +* compat-call plist-member: Emacs 29.1. (line 802) +* compat-call plist-put: Emacs 29.1. (line 790) * compat-call recenter: Emacs 27.1. (line 346) * compat-call regexp-opt: Emacs 27.1. (line 385) -* compat-call set-transient-map: Emacs 29.1. (line 701) +* compat-call set-transient-map: Emacs 29.1. (line 717) * compat-call setq-local: Emacs 27.1. (line 370) -* compat-call sort: Emacs 25.1. (line 189) -* compat-call string-lines: Emacs 29.1. (line 737) +* compat-call sort: Emacs 30.1. (line 212) +* compat-call string-lines: Emacs 29.1. (line 753) * compat-call string-trim: Emacs 26.1. (line 375) * compat-call string-trim-left: Emacs 26.1. (line 359) * compat-call string-trim-right: Emacs 26.1. (line 367) -* compat-call string-width: Emacs 28.1. (line 395) -* compat-function: Usage. (line 53) -* compiled-function-p: Emacs 29.1. (line 222) -* count-sentences: Emacs 29.1. (line 25) +* compat-call string-width: Emacs 28.1. (line 394) +* compat-function: Usage. (line 58) +* compiled-function-p: Emacs 29.1. (line 232) +* completion-lazy-hilit: Emacs 30.1. (line 182) +* count-sentences: Emacs 29.1. (line 31) * cXXXr: Emacs 26.1. (line 66) * cXXXXr: Emacs 26.1. (line 67) * date-days-in-month: Emacs 27.1. (line 213) @@ -2776,27 +3110,28 @@ Appendix A Function Index * decoded-time-hour: Emacs 27.1. (line 170) * decoded-time-minute: Emacs 27.1. (line 165) * decoded-time-month: Emacs 27.1. (line 180) -* decoded-time-period: Emacs 28.1. (line 359) +* decoded-time-period: Emacs 28.1. (line 363) * decoded-time-second: Emacs 27.1. (line 160) * decoded-time-weekday: Emacs 27.1. (line 190) * decoded-time-year: Emacs 27.1. (line 185) * decoded-time-zone: Emacs 27.1. (line 200) -* define-keymap: Emacs 29.1. (line 514) -* defvar-keymap: Emacs 29.1. (line 582) -* delete-line: Emacs 29.1. (line 59) -* directory-abbrev-apply: Emacs 29.1. (line 378) -* directory-abbrev-make-regexp: Emacs 29.1. (line 375) -* directory-empty-p: Emacs 28.1. (line 243) +* define-keymap: Emacs 29.1. (line 524) +* defvar-keymap: Emacs 29.1. (line 592) +* delete-line: Emacs 29.1. (line 65) +* directory-abbrev-apply: Emacs 29.1. (line 388) +* directory-abbrev-make-regexp: Emacs 29.1. (line 385) +* directory-empty-p: Emacs 28.1. (line 247) * directory-name-p: Emacs 25.1. (line 56) -* dlet: Emacs 28.1. (line 143) +* dlet: Emacs 28.1. (line 147) * dolist-with-progress-reporter: Emacs 27.1. (line 119) -* ensure-list: Emacs 28.1. (line 158) -* ert-with-temp-directory: Emacs 29.1. (line 614) -* ert-with-temp-file: Emacs 29.1. (line 608) +* drop: Emacs 30.1. (line 110) +* ensure-list: Emacs 28.1. (line 162) +* ert-with-temp-directory: Emacs 29.1. (line 630) +* ert-with-temp-file: Emacs 29.1. (line 624) * file-attribute-access-time: Emacs 26.1. (line 223) * file-attribute-collect: Emacs 26.1. (line 260) * file-attribute-device-number: Emacs 26.1. (line 255) -* file-attribute-file-identifier: Emacs 29.1. (line 335) +* file-attribute-file-identifier: Emacs 29.1. (line 345) * file-attribute-group-id: Emacs 26.1. (line 218) * file-attribute-inode-number: Emacs 26.1. (line 250) * file-attribute-link-number: Emacs 26.1. (line 208) @@ -2806,71 +3141,77 @@ Appendix A Function Index * file-attribute-status-change-time: Emacs 26.1. (line 234) * file-attribute-type: Emacs 26.1. (line 203) * file-attribute-user-id: Emacs 26.1. (line 213) -* file-backup-file-names: Emacs 28.1. (line 347) -* file-has-changed-p: Emacs 29.1. (line 360) +* file-backup-file-names: Emacs 28.1. (line 351) +* file-has-changed-p: Emacs 29.1. (line 370) * file-local-name: Emacs 26.1. (line 167) -* file-modes-number-to-symbolic: Emacs 28.1. (line 341) +* file-modes-number-to-symbolic: Emacs 28.1. (line 345) * file-name-concat: Emacs 28.1. (line 53) -* file-name-parent-directory: Emacs 29.1. (line 351) +* file-name-parent-directory: Emacs 29.1. (line 361) * file-name-quote: Emacs 26.1. (line 102) * file-name-quoted-p: Emacs 26.1. (line 95) -* file-name-split: Emacs 29.1. (line 341) +* file-name-split: Emacs 29.1. (line 351) * file-name-unquote: Emacs 26.1. (line 90) -* file-name-with-extension: Emacs 28.1. (line 225) +* file-name-with-extension: Emacs 28.1. (line 229) * file-size-human-readable-iec: Emacs 27.1. (line 251) +* find-buffer: Emacs 30.1. (line 120) * fixnump: Emacs 27.1. (line 60) * flatten-tree: Emacs 27.1. (line 132) * format-message: Emacs 25.1. (line 44) -* format-prompt: Emacs 28.1. (line 254) -* funcall-with-delayed-message: Emacs 29.1. (line 144) -* function-alias-p: Emacs 29.1. (line 229) +* format-prompt: Emacs 28.1. (line 258) +* funcall-with-delayed-message: Emacs 29.1. (line 154) +* function-alias-p: Emacs 29.1. (line 239) * garbage-collect-maybe: Emacs 28.1. (line 68) * gensym: Emacs 26.1. (line 70) -* get-display-property: Emacs 29.1. (line 169) -* get-scratch-buffer-create: Emacs 29.1. (line 38) +* get-display-property: Emacs 29.1. (line 179) +* get-scratch-buffer-create: Emacs 29.1. (line 44) +* get-truename-buffer: Emacs 30.1. (line 115) * hash-table-empty: Emacs 25.1. (line 119) * if-let: Emacs 25.1. (line 96) * if-let*: Emacs 26.1. (line 149) * ignore-errors: Emacs 27.1. (line 106) * image-property: Emacs 26.1. (line 198) * insert-into-buffer: Emacs 28.1. (line 92) -* key-parse: Emacs 29.1. (line 415) -* key-valid-p: Emacs 29.1. (line 383) -* keymap-global-lookup: Emacs 29.1. (line 510) -* keymap-global-set: Emacs 29.1. (line 444) -* keymap-global-unset: Emacs 29.1. (line 464) -* keymap-local-lookup: Emacs 29.1. (line 506) -* keymap-local-set: Emacs 29.1. (line 454) -* keymap-local-unset: Emacs 29.1. (line 479) -* keymap-lookup: Emacs 29.1. (line 493) -* keymap-set: Emacs 29.1. (line 420) -* keymap-substitute: Emacs 29.1. (line 485) +* interpreted-function-p: Emacs 30.1. (line 62) +* key-parse: Emacs 29.1. (line 425) +* key-valid-p: Emacs 29.1. (line 393) +* keymap-global-lookup: Emacs 29.1. (line 520) +* keymap-global-set: Emacs 29.1. (line 454) +* keymap-global-unset: Emacs 29.1. (line 474) +* keymap-local-lookup: Emacs 29.1. (line 516) +* keymap-local-set: Emacs 29.1. (line 464) +* keymap-local-unset: Emacs 29.1. (line 489) +* keymap-lookup: Emacs 29.1. (line 503) +* keymap-set: Emacs 29.1. (line 430) +* keymap-substitute: Emacs 29.1. (line 495) * length<: Emacs 28.1. (line 45) * length=: Emacs 28.1. (line 42) * length>: Emacs 28.1. (line 50) -* list-of-strings-p: Emacs 29.1. (line 62) -* macroexp-file-name: Emacs 28.1. (line 301) +* list-of-strings-p: Emacs 29.1. (line 68) +* macroexp-file-name: Emacs 28.1. (line 305) * macroexp-parse: Emacs 25.1. (line 174) * macroexp-quote: Emacs 25.1. (line 171) -* macroexp-warn-and-return: Emacs 28.1. (line 305) +* macroexp-warn-and-return: Emacs 28.1. (line 309) * macroexpand-1: Emacs 25.1. (line 164) * major-mode-restore: Emacs 27.1. (line 22) * major-mode-suspend: Emacs 27.1. (line 13) * make-empty-file: Emacs 27.1. (line 254) -* make-lock-file-name: Emacs 28.1. (line 355) +* make-lock-file-name: Emacs 28.1. (line 359) * make-nearby-temp-file: Emacs 26.1. (line 120) * make-separator-line: Emacs 28.1. (line 88) * mapcan: Emacs 26.1. (line 53) -* mark-thing-at-mouse: Emacs 28.1. (line 298) -* match-buffers: Emacs 29.1. (line 288) +* mark-thing-at-mouse: Emacs 28.1. (line 302) +* match-buffers: Emacs 29.1. (line 298) +* merge-ordered-lists: Emacs 30.1. (line 135) * minibuffer-history-value: Emacs 27.1. (line 32) -* named-let: Emacs 28.1. (line 207) -* native-comp-available-p: Emacs 28.1. (line 376) -* ntake: Emacs 29.1. (line 209) +* named-let: Emacs 28.1. (line 211) +* native-comp-available-p: Emacs 28.1. (line 375) +* ntake: Emacs 29.1. (line 219) +* obarray-clear: Emacs 30.1. (line 54) * package-get-version: Emacs 27.1. (line 205) -* plistp: Emacs 29.1. (line 65) -* pos-bol: Emacs 29.1. (line 119) -* pos-eol: Emacs 29.1. (line 123) +* plistp: Emacs 29.1. (line 71) +* pos-bol: Emacs 29.1. (line 125) +* pos-eol: Emacs 29.1. (line 129) +* primitive-function-p: Emacs 30.1. (line 65) * process-lines-handling-status: Emacs 28.1. (line 20) * process-lines-ignore-status: Emacs 28.1. (line 16) * proper-list-p: Emacs 27.1. (line 76) @@ -2878,58 +3219,62 @@ Appendix A Function Index * read-answer: Emacs 26.1. (line 17) * read-char-from-minibuffer: Emacs 27.1. (line 44) * read-multiple-choice: Emacs 26.1. (line 185) -* readablep: Emacs 29.1. (line 28) +* readablep: Emacs 29.1. (line 34) * region-bounds: Emacs 25.1. (line 28) * region-noncontiguous-p: Emacs 25.1. (line 34) -* replace-regexp-in-string: Emacs 28.1. (line 117) +* replace-regexp-in-string: Emacs 28.1. (line 108) * replace-string-in-region: Emacs 28.1. (line 102) +* require-with-check: Emacs 30.1. (line 124) * ring-resize: Emacs 27.1. (line 28) * save-mark-and-excursion: Emacs 25.1. (line 39) -* string-chop-newline: Emacs 28.1. (line 202) -* string-clean-whitespace: Emacs 28.1. (line 171) +* static-if: Emacs 30.1. (line 187) +* string-chop-newline: Emacs 28.1. (line 206) +* string-clean-whitespace: Emacs 28.1. (line 175) * string-distance: Emacs 27.1. (line 86) -* string-equal-ignore-case: Emacs 29.1. (line 242) -* string-fill: Emacs 28.1. (line 178) -* string-glyph-split: Emacs 29.1. (line 297) +* string-equal-ignore-case: Emacs 29.1. (line 252) +* string-fill: Emacs 28.1. (line 182) +* string-glyph-split: Emacs 29.1. (line 307) * string-greaterp: Emacs 25.1. (line 64) -* string-lines: Emacs 28.1. (line 186) -* string-pad: Emacs 28.1. (line 193) +* string-lines: Emacs 28.1. (line 190) +* string-pad: Emacs 28.1. (line 197) * string-replace: Emacs 28.1. (line 77) * string-search: Emacs 28.1. (line 34) -* string-split: Emacs 29.1. (line 248) -* subr-native-elisp-p: Emacs 28.1. (line 371) -* subr-primitive-p: Emacs 28.1. (line 364) -* substitute-quotes: Emacs 29.1. (line 34) -* take: Emacs 29.1. (line 195) +* string-split: Emacs 29.1. (line 258) +* subr-primitive-p: Emacs 28.1. (line 368) +* substitute-quotes: Emacs 29.1. (line 40) +* take: Emacs 29.1. (line 205) * temporary-file-directory: Emacs 26.1. (line 137) * text-property-search-backward: Emacs 27.1. (line 332) * text-property-search-forward: Emacs 27.1. (line 260) * text-quoting-style: Emacs 28.1. (line 28) -* thing-at-mouse: Emacs 28.1. (line 285) +* thing-at-mouse: Emacs 28.1. (line 289) * thread-first: Emacs 25.1. (line 122) * thread-last: Emacs 25.1. (line 143) * time-equal-p: Emacs 27.1. (line 208) -* use-region-beginning: Emacs 29.1. (line 47) -* use-region-end: Emacs 29.1. (line 44) -* use-region-noncontiguous-p: Emacs 29.1. (line 41) +* trusted-content-p: Emacs 30.1. (line 29) +* use-region-beginning: Emacs 29.1. (line 53) +* use-region-end: Emacs 29.1. (line 50) +* use-region-noncontiguous-p: Emacs 29.1. (line 47) +* value<: Emacs 30.1. (line 69) * when-let: Emacs 25.1. (line 114) * when-let*: Emacs 26.1. (line 153) -* while-let: Emacs 29.1. (line 602) -* with-buffer-unmodified-if-unchanged: Emacs 29.1. (line 320) -* with-delayed-message: Emacs 29.1. (line 127) -* with-environment-variables: Emacs 28.1. (line 309) -* with-existing-directory: Emacs 28.1. (line 132) +* while-let: Emacs 29.1. (line 612) +* window-configuration-equal-p: Emacs 29.1. (line 618) +* with-buffer-unmodified-if-unchanged: Emacs 29.1. (line 330) +* with-delayed-message: Emacs 29.1. (line 137) +* with-environment-variables: Emacs 28.1. (line 313) +* with-existing-directory: Emacs 28.1. (line 136) * with-file-modes: Emacs 25.1. (line 71) -* with-memoization: Emacs 29.1. (line 68) +* with-memoization: Emacs 29.1. (line 74) * with-minibuffer-selected-window: Emacs 27.1. (line 38) -* with-restriction: Emacs 29.1. (line 73) +* with-restriction: Emacs 29.1. (line 79) * with-suppressed-warnings: Emacs 27.1. (line 65) -* with-window-non-dedicated: Emacs 28.1. (line 384) -* without-restriction: Emacs 29.1. (line 107) +* with-window-non-dedicated: Emacs 28.1. (line 383) +* without-restriction: Emacs 29.1. (line 113) * xor: Emacs 27.1. (line 142)  -File: doc9SKjtU.info, Node: Variable Index, Prev: Function Index, Up: Top +File: docA0lLBy.info, Node: Variable Index, Prev: Function Index, Up: Top Appendix B Variable Index ************************* @@ -2937,31 +3282,36 @@ Appendix B Variable Index [index] * Menu: +* completion-lazy-hilit: Emacs 30.1. (line 149) +* completion-lazy-hilit-fn: Emacs 30.1. (line 173) * exec-path: Emacs 27.1. (line 228) * gensym-counter: Emacs 26.1. (line 77) -* lisp-directory: Emacs 29.1. (line 17) +* lisp-directory: Emacs 29.1. (line 23) * mounted-file-systems: Emacs 26.1. (line 133) * regexp-unmatchable: Emacs 27.1. (line 152) -* set-transient-map-timeout: Emacs 29.1. (line 727) +* set-transient-map-timeout: Emacs 29.1. (line 743) * text-quoting-style: Emacs 25.1. (line 13) +* trusted-content: Emacs 30.1. (line 14) +* untrusted-content: Emacs 29.1. (line 17)  Tag Table: -Node: Top829 -Node: Introduction2258 -Node: Overview2421 -Node: Usage2947 -Node: Limitations7304 -Node: Support12150 -Node: Emacs 25.112735 -Node: Emacs 26.122137 -Node: Emacs 27.139431 -Node: Emacs 28.159828 -Node: Emacs 29.179909 -Node: Development116718 -Node: Function Index117738 -Node: Variable Index133024 +Node: Top831 +Node: Introduction2328 +Node: Overview2491 +Node: Usage3017 +Node: Limitations7396 +Node: Support12246 +Node: Emacs 25.112899 +Node: Emacs 26.121371 +Node: Emacs 27.138655 +Node: Emacs 28.159021 +Node: Emacs 29.179131 +Node: Emacs 30.1116768 +Node: Development131578 +Node: Function Index133312 +Node: Variable Index150131  End Tag Table diff --git a/lisp/counsel/counsel-pkg.el b/lisp/counsel/counsel-pkg.el index 54380b5a..506e4a34 100644 --- a/lisp/counsel/counsel-pkg.el +++ b/lisp/counsel/counsel-pkg.el @@ -1,16 +1,12 @@ -(define-package "counsel" "20250304.939" "Various completion functions using Ivy" - '((emacs "24.5") - (ivy "0.15.0") - (swiper "0.15.0")) - :commit "db61f55bc281c28beb723ef17cfe74f59580d2f4" :authors - '(("Oleh Krehel" . "ohwoeowho@gmail.com")) - :maintainers - '(("Basil L. Contovounesios" . "basil@contovou.net")) - :maintainer - '("Basil L. Contovounesios" . "basil@contovou.net") - :keywords - '("convenience" "matching" "tools") - :url "https://github.com/abo-abo/swiper") -;; Local Variables: -;; no-byte-compile: t -;; End: +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "counsel" "20250329.1401" + "Various completion functions using Ivy." + '((emacs "24.5") + (ivy "0.15.1") + (swiper "0.15.1")) + :url "https://github.com/abo-abo/swiper" + :commit "e33b028ed4b1258a211c87fd5fe801bed25de429" + :revdesc "e33b028ed4b1" + :keywords '("convenience" "matching" "tools") + :authors '(("Oleh Krehel" . "ohwoeowho@gmail.com")) + :maintainers '(("Basil L. Contovounesios" . "basil@contovou.net"))) diff --git a/lisp/counsel/counsel.el b/lisp/counsel/counsel.el index 55aee579..3294dd4a 100644 --- a/lisp/counsel/counsel.el +++ b/lisp/counsel/counsel.el @@ -5,8 +5,9 @@ ;; Author: Oleh Krehel ;; Maintainer: Basil L. Contovounesios ;; URL: https://github.com/abo-abo/swiper -;; Version: 0.15.0 -;; Package-Requires: ((emacs "24.5") (ivy "0.15.0") (swiper "0.15.0")) +;; Package-Version: 20250329.1401 +;; Package-Revision: e33b028ed4b1 +;; Package-Requires: ((emacs "24.5") (ivy "0.15.1") (swiper "0.15.1")) ;; Keywords: convenience, matching, tools ;; This file is part of GNU Emacs. @@ -44,18 +45,26 @@ (require 'ivy) (require 'swiper) -(require 'compile) -(require 'dired) - (eval-when-compile (require 'subr-x)) +(eval-when-compile + (unless (fboundp 'static-if) + (defmacro static-if (condition then-form &rest else-forms) + "Expand to THEN-FORM or ELSE-FORMS based on compile-time CONDITION. +Polyfill for Emacs 30 `static-if'." + (declare (debug (sexp sexp &rest sexp)) (indent 2)) + (if (eval condition lexical-binding) + then-form + (macroexp-progn else-forms))))) + (defgroup counsel nil "Completion functions using Ivy." :group 'matching :prefix "counsel-") + +;;; Utility -;;* Utility (defun counsel--elisp-to-pcre (regex &optional look-around) "Convert REGEX from Elisp format to PCRE format, on best-effort basis. REGEX may be of any format returned by an Ivy regex function, @@ -139,13 +148,16 @@ When NOERROR is non-nil, return nil instead of raising an error." (unless noerror (user-error "Required program \"%s\" not found in your path" program)))))) -(declare-function eshell-split-path "esh-util") - (defun counsel-prompt-function-dir () "Return prompt appended with the parent directory." + (declare (obsolete "it is no longer used." "0.15.1")) (require 'esh-util) (let* ((dir (ivy-state-directory ivy-last)) - (parts (nthcdr 3 (eshell-split-path dir))) + (parts (nthcdr 3 (funcall (if (fboundp 'eshell-split-filename) + ;; New name since Emacs 30. + #'eshell-split-filename + 'eshell-split-path) + dir))) (dir (format " [%s]: " (if parts (apply #'concat "..." parts) dir)))) (ivy-add-prompt-count (replace-regexp-in-string ; Insert dir before any trailing colon. @@ -182,8 +194,9 @@ Return a list or string depending on input." (defalias 'counsel--null-device (if (fboundp 'null-device) #'null-device (lambda () null-device)) "Compatibility shim for Emacs 28 function `null-device'.") + +;;;; Async utility -;;* Async Utility (defvar counsel--async-time nil "Store the time when a new process was started. Or the time of the last minibuffer update.") @@ -357,8 +370,9 @@ Update the minibuffer with the amount of lines collected every (let ((process (get-process (or name " *counsel*")))) (when process (delete-process process)))) + +;;; Completion at point -;;* Completion at point (define-obsolete-function-alias 'counsel-el #'complete-symbol "0.13.2 (2020-05-20)") (define-obsolete-function-alias 'counsel-cl @@ -368,7 +382,8 @@ Update the minibuffer with the amount of lines collected every (define-obsolete-function-alias 'counsel-clj #'complete-symbol "0.13.2 (2020-05-20)") -;;** `counsel-company' +;;;; `counsel-company' + (defvar company-candidates) (declare-function company-abort "ext:company") (declare-function company-complete "ext:company") @@ -399,7 +414,8 @@ Update the minibuffer with the amount of lines collected every (when annot (company--clean-string annot))))) -;;** `counsel-irony' +;;;; `counsel-irony' + (declare-function irony-completion-candidates-async "ext:irony-completion") (declare-function irony-completion-symbol-bounds "ext:irony-completion") (declare-function irony-completion-annotation "ext:irony-completion") @@ -432,9 +448,10 @@ Update the minibuffer with the amount of lines collected every (ivy-configure #'counsel-irony :display-fn #'ivy-display-function-overlay) + +;;; Elisp symbols +;;;; `counsel-describe-variable' -;;* Elisp symbols -;;** `counsel-describe-variable' (defvar counsel-describe-map (let ((map (make-sparse-keymap))) (define-key map (kbd "C-.") #'counsel-find-symbol) @@ -443,8 +460,8 @@ Update the minibuffer with the amount of lines collected every (ivy-set-actions 'counsel-describe-variable - '(("I" counsel-info-lookup-symbol "info") - ("d" counsel--find-symbol "definition"))) + `(("I" ,#'counsel-info-lookup-symbol "info") + ("d" ,#'counsel--find-symbol "definition"))) (defvar counsel-describe-symbol-history () "History list for variable and function names. @@ -455,24 +472,28 @@ Used by commands `counsel-describe-symbol', "Jump to the definition of the current symbol." (interactive) (ivy-exit-with-action #'counsel--find-symbol)) -(put 'counsel-find-symbol 'no-counsel-M-x t) +(function-put #'counsel-find-symbol 'no-counsel-M-x t) (defun counsel--info-lookup-symbol () "Lookup the current symbol in the info docs." (interactive) (ivy-exit-with-action #'counsel-info-lookup-symbol)) -(defvar find-tag-marker-ring) -(declare-function xref-push-marker-stack "xref") - -(defalias 'counsel--push-xref-marker - ;; Added in Emacs 25.1. - (if (require 'xref nil t) - #'xref-push-marker-stack - (require 'etags) - (lambda (&optional m) - (ring-insert (with-no-warnings find-tag-marker-ring) (or m (point-marker))))) - "Compatibility shim for `xref-push-marker-stack'.") +(defun counsel--push-xref-marker (&optional m) + "Compatibility shim for `xref-push-marker-stack'." + (static-if (require 'xref nil t) + ;; Added in Emacs 25.1. + (progn + (unless (fboundp 'xref-push-marker-stack) + (require 'xref)) + (xref-push-marker-stack m)) + (unless (boundp 'find-tag-marker-ring) + (require 'etags)) + (unless (fboundp 'ring-insert) + (require 'ring)) + (defvar find-tag-marker-ring) + (declare-function ring-insert "ring" (ring item)) + (ring-insert find-tag-marker-ring (or m (point-marker))))) (defun counsel--find-symbol (x) "Find symbol definition that corresponds to string X." @@ -537,11 +558,12 @@ Variables declared using `defcustom' are highlighted according to :parent 'counsel-describe-symbol :display-transformer-fn #'counsel-describe-variable-transformer) -;;** `counsel-describe-function' +;;;; `counsel-describe-function' + (ivy-set-actions 'counsel-describe-function - '(("I" counsel-info-lookup-symbol "info") - ("d" counsel--find-symbol "definition"))) + `(("I" ,#'counsel-info-lookup-symbol "info") + ("d" ,#'counsel--find-symbol "definition"))) (defcustom counsel-describe-function-function #'describe-function "Function to call to describe a function passed as parameter." @@ -563,6 +585,10 @@ Variables declared using `defcustom' are highlighted according to (function-item ivy-thing-at-point) (function-item ivy-function-called-at-point))) +(defun counsel--describe-function (candidate) + "Pass string CANDIDATE to `counsel-describe-function-function'." + (funcall counsel-describe-function-function (intern candidate))) + ;;;###autoload (defun counsel-describe-function () "Forward to `describe-function'. @@ -579,16 +605,16 @@ to `ivy-highlight-face'." :history 'counsel-describe-symbol-history :keymap counsel-describe-map :preselect (funcall counsel-describe-function-preselect) - :action (lambda (x) - (funcall counsel-describe-function-function (intern x))) + :action #'counsel--describe-function :caller 'counsel-describe-function))) (ivy-configure 'counsel-describe-function :parent 'counsel-describe-symbol :display-transformer-fn #'counsel-describe-function-transformer) -;;** `counsel-describe-symbol' -(defcustom counsel-describe-symbol-function #'describe-symbol +;;;; `counsel-describe-symbol' + +(defcustom counsel-describe-symbol-function 'describe-symbol "Function to call to describe a symbol passed as parameter." :type 'function) @@ -599,6 +625,7 @@ to `ivy-highlight-face'." (unless (functionp 'describe-symbol) (user-error "This command requires Emacs 25.1 or later")) (require 'help-mode) + (defvar describe-symbol-backends) (let ((enable-recursive-minibuffers t)) (ivy-read "Describe symbol: " obarray :predicate (lambda (sym) @@ -622,7 +649,8 @@ to `ivy-highlight-face'." `(("I" ,#'counsel-info-lookup-symbol "info") ("d" ,#'counsel--find-symbol "definition"))) -;;** `counsel-set-variable' +;;;; `counsel-set-variable' + (defvar counsel-set-variable-history nil "Store history for `counsel-set-variable'.") @@ -746,7 +774,8 @@ With a prefix arg, restrict list to variables defined using (when doc (lv-delete-window))))) -;;** `counsel-apropos' +;;;; `counsel-apropos' + ;;;###autoload (defun counsel-apropos () "Show all matching symbols. @@ -778,7 +807,8 @@ a symbol and how to search for them." (ivy-configure 'counsel-apropos :sort-fn #'ivy-string<) -;;** `counsel-info-lookup-symbol' +;;;; `counsel-info-lookup-symbol' + (defvar info-lookup-mode) (declare-function info-lookup-guess-default "info-look") (declare-function info-lookup->completions "info-look") @@ -813,7 +843,8 @@ With prefix arg MODE a query for the symbol help mode is offered." (ivy-configure 'counsel-info-lookup-symbol :sort-fn #'ivy-string<) -;;** `counsel-M-x' +;;;; `counsel-M-x' + (defface counsel-key-binding '((t :inherit font-lock-keyword-face)) "Face used by `counsel-M-x' for key bindings." @@ -968,10 +999,11 @@ when available, in that order of precedence." (ivy-set-actions 'counsel-M-x - `(("d" counsel--find-symbol "definition") - ("h" ,(lambda (x) (funcall counsel-describe-function-function (intern x))) "help"))) + `(("d" ,#'counsel--find-symbol "definition") + ("h" ,#'counsel--describe-function "help"))) + +;;;; `counsel-command-history' -;;** `counsel-command-history' (defun counsel-command-history-action-eval (cmd) "Eval the command CMD." (eval (read cmd) t)) @@ -994,7 +1026,8 @@ when available, in that order of precedence." :action #'counsel-command-history-action-eval :caller 'counsel-command-history)) -;;** `counsel-load-library' +;;;; `counsel-load-library' + (defun counsel-library-candidates () "Return a list of completion candidates for `counsel-load-library'." (let ((suffix (concat (regexp-opt '(".el" ".el.gz") t) "\\'")) @@ -1051,9 +1084,10 @@ The libraries are offered from `load-path'." (ivy-set-actions 'counsel-load-library - '(("d" counsel--find-symbol "definition"))) + `(("d" ,#'counsel--find-symbol "definition"))) + +;;;; `counsel-find-library' -;;** `counsel-find-library' (declare-function find-library-name "find-func") (defun counsel-find-library-other-window (library) (let ((buf (find-file-noselect (find-library-name library)))) @@ -1081,7 +1115,8 @@ The libraries are offered from `load-path'." :keymap counsel-describe-map :caller 'counsel-find-library))) -;;** `counsel-load-theme' +;;;; `counsel-load-theme' + (declare-function powerline-reset "ext:powerline") (defun counsel-load-theme-action (x) @@ -1106,7 +1141,8 @@ Usable with `ivy-resume', `ivy-next-line-and-call' and :action #'counsel-load-theme-action :caller 'counsel-load-theme)) -;;** `counsel-descbinds' +;;;; `counsel-descbinds' + (ivy-set-actions 'counsel-descbinds '(("d" counsel-descbinds-action-find "definition") @@ -1191,7 +1227,8 @@ BUFFER defaults to the current one." :history 'counsel-descbinds-history :caller 'counsel-descbinds)) -;;** `counsel-describe-face' +;;;; `counsel-describe-face' + (defcustom counsel-describe-face-function #'describe-face "Function to call to describe a face or face name argument." :type 'function) @@ -1239,7 +1276,8 @@ back to the face of the character after point, and finally the '(("c" counsel-customize-face "customize") ("C" counsel-customize-face-other-window "customize other window"))) -;;** `counsel-faces' +;;;; `counsel-faces' + (defvar counsel--faces-format "%-40s %s") (defun counsel--faces-format-function (names) @@ -1281,8 +1319,79 @@ selected face." ("C" counsel-customize-face-other-window "customize other window") ("h" counsel-highlight-with-face "highlight"))) -;;* Git -;;** `counsel-git' +;;;; Modes + +(defvar counsel-minor-history nil + "History for `counsel-minor'.") + +(defun counsel--minor-candidates () + "Return completion alist for `counsel-minor'. + +The alist element is cons of minor mode string with its lighter +and minor mode symbol." + (cl-mapcan + (let ((suffix (propertize " \"%s\"" 'face 'font-lock-string-face))) + (lambda (mode) + (when (and (boundp mode) (commandp mode)) + (let ((lighter (cdr (assq mode minor-mode-alist)))) + (list (cons (concat + (if (symbol-value mode) "-" "+") + (symbol-name mode) + (and lighter + (format suffix + (format-mode-line (cons t lighter))))) + mode)))))) + minor-mode-list)) + +;;;###autoload +(defun counsel-minor () + "Enable or disable minor mode. + +Disabled minor modes are prefixed with \"+\", and +selecting one of these will enable it. +Enabled minor modes are prefixed with \"-\", and +selecting one of these will enable it. + +Additional actions:\\ + + \\[ivy-dispatching-done] d: Go to minor mode definition + \\[ivy-dispatching-done] h: Describe minor mode" + + (interactive) + (ivy-read "Minor modes (enable +mode or disable -mode): " + (counsel--minor-candidates) + :require-match t + :history 'counsel-minor-history + :action (lambda (x) + (call-interactively (cdr x))))) + +(ivy-configure 'counsel-minor + :initial-input "^+" + :sort-fn #'ivy-string<) + +(ivy-set-actions + 'counsel-minor + `(("d" ,(lambda (x) (find-function (cdr x))) "definition") + ("h" ,(lambda (x) (describe-function (cdr x))) "help"))) + +;;;###autoload +(defun counsel-major () + (interactive) + (ivy-read "Major modes: " obarray + :predicate (lambda (f) + (and (commandp f) + (string-suffix-p "-mode" (symbol-name f)) + (or (and (autoloadp (symbol-function f)) + (let ((doc-split (help-split-fundoc (documentation f) f))) + ;; major mode starters have no arguments + (and doc-split (null (cdr (read (car doc-split))))))) + (null (help-function-arglist f))))) + :action #'counsel-M-x-action + :caller 'counsel-major)) + +;;; Git +;;;; `counsel-git' + (defvar counsel-git-cmd "git ls-files -z --full-name --" "Command for `counsel-git'.") @@ -1353,6 +1462,10 @@ INITIAL-INPUT can be given as the initial minibuffer input." (let ((inhibit-read-only t)) (erase-buffer) (dired-mode default-directory counsel-dired-listing-switches) + (defvar dired-sort-inhibit) + (defvar dired-subdir-alist) + (declare-function dired-insert-set-properties "dired") + (declare-function dired-move-to-filename "dired") (insert " " default-directory ":\n") (let ((point (point))) (insert " " full-cmd "\n") @@ -1374,7 +1487,8 @@ INITIAL-INPUT can be given as the initial minibuffer input." (forward-line 2) (dired-move-to-filename))))))) -;;** `counsel-git-grep' +;;;; `counsel-git-grep' + (defvar counsel-git-grep-map (let ((map (make-sparse-keymap))) (define-key map (kbd "C-l") #'ivy-call-and-recenter) @@ -1696,7 +1810,8 @@ When CMD is non-nil, prompt for a specific \"git grep\" command." (goto-char (point-min))) (perform-replace from to t t nil)))))))))) -;;** `counsel-git-stash' +;;;; `counsel-git-stash' + (defun counsel-git-stash-kill-action (x) "Add git stash command to kill ring. The git command applies the stash entry where candidate X was found in." @@ -1717,7 +1832,8 @@ done") "\n" t))) :action #'counsel-git-stash-kill-action :caller 'counsel-git-stash))) -;;** `counsel-git-log' +;;;; `counsel-git-log' + (defvar counsel-git-log-cmd "GIT_PAGER=cat git log --no-color --grep '%s'" "Command used for \"git log\".") @@ -1751,7 +1867,8 @@ done") "\n" t))) 'counsel-git-log '(("v" counsel-git-log-show-commit-action "visit commit"))) -;;** `counsel-git-change-worktree' +;;;; `counsel-git-change-worktree' + (defun counsel-git-change-worktree-action (git-root-dir tree) "Find the corresponding file in the worktree located at tree. The current buffer is assumed to be in a subdirectory of GIT-ROOT-DIR. @@ -1799,7 +1916,8 @@ TREE is the selected candidate." :require-match t :caller 'counsel-git-change-worktree))) -;;** `counsel-git-checkout' +;;;; `counsel-git-checkout' + (defun counsel-git-checkout-action (branch) "Switch branch by invoking git-checkout(1). The command is passed a single argument comprising all characters @@ -1852,16 +1970,17 @@ currently checked out." (add-to-list 'counsel-async-split-string-re-alist '(counsel-git-log . "^commit ")) (add-to-list 'counsel-async-ignore-re-alist '(counsel-git-log . "^[ \n]*$")) + +;;; File +;;;; `counsel-find-file' -;;* File -;;** `counsel-find-file' (defvar counsel-find-file-map (let ((map (make-sparse-keymap))) (define-key map (kbd "C-DEL") #'counsel-up-directory) (define-key map (kbd "C-") #'counsel-up-directory) (define-key map (kbd "`") #'counsel-file-jump-from-find) (define-key map (kbd "C-`") (ivy-make-magic-action #'counsel-find-file "b")) - (define-key map [remap undo] #'counsel-find-file-undo) + (define-key map `[remap ,#'undo] #'counsel-find-file-undo) map)) (defun counsel-file-jump-from-find () @@ -1922,7 +2041,8 @@ choose between `yes-or-no-p' and `y-or-n-p'; otherwise default to (defun counsel-find-file-copy (x) "Copy file X." - (require 'dired-aux) + ;; Autoloaded by `dired'. + (declare-function dired-copy-file "dired-aux") (counsel--find-file-1 "Copy file to: " ivy--directory (lambda (new-name) @@ -1931,6 +2051,9 @@ choose between `yes-or-no-p' and `y-or-n-p'; otherwise default to (defun counsel-find-file-delete (x) "Delete file X." + (defvar dired-recursive-deletes) + (declare-function dired-clean-up-after-deletion "dired") + (declare-function dired-delete-file "dired") (when (or delete-by-moving-to-trash ;; `dired-delete-file', which see, already prompts for directories (eq t (car (file-attributes x))) @@ -1943,7 +2066,8 @@ choose between `yes-or-no-p' and `y-or-n-p'; otherwise default to (defun counsel-find-file-move (x) "Move or rename file X." - (require 'dired-aux) + ;; Autoloaded by `dired'. + (declare-function dired-rename-file "dired-aux") (counsel--find-file-1 "Rename file to: " ivy--directory (lambda (new-name) @@ -2063,8 +2187,9 @@ The preselect behavior can be customized via user options (file-name-nondirectory buffer-file-name)))) (defun counsel--find-file-1 (prompt initial-input action caller) + (declare-function dired-current-directory "dired") (let ((default-directory - (if (eq major-mode 'dired-mode) + (if (derived-mode-p 'dired-mode) (dired-current-directory) default-directory))) (ivy-read prompt #'read-file-name-internal @@ -2082,6 +2207,7 @@ The preselect behavior can be customized via user options "Forward to `find-file'. When INITIAL-INPUT is non-nil, use it in the minibuffer during completion." (interactive) + (require 'dired) (defvar tramp-archive-enabled) (let ((tramp-archive-enabled nil) (default-directory (or initial-directory default-directory))) @@ -2311,14 +2437,14 @@ result as a URL." (format formatter word-at-point))))) counsel-url-expansions-alist)))) -;;** `counsel-dired' -(declare-function dired "dired") +;;;; `counsel-dired' ;;;###autoload (defun counsel-dired (&optional initial-input) "Forward to `dired'. When INITIAL-INPUT is non-nil, use it in the minibuffer during completion." (interactive) + (require 'dired) (let ((counsel--find-file-predicate #'file-directory-p)) (counsel--find-file-1 "Dired (directory): " initial-input @@ -2328,7 +2454,8 @@ When INITIAL-INPUT is non-nil, use it in the minibuffer during completion." (ivy-configure 'counsel-dired :parent 'read-file-name-internal) -;;** `counsel-recentf' +;;;; `counsel-recentf' + (defvar recentf-list) (declare-function recentf-mode "recentf") @@ -2344,7 +2471,6 @@ https://www.freedesktop.org/wiki/Specifications/desktop-bookmark-spec")) (defun counsel-recentf () "Find a file on `recentf-list'." (interactive) - (require 'recentf) (recentf-mode) (ivy-read "Recentf: " (counsel-recentf-candidates) :action (lambda (f) @@ -2411,30 +2537,29 @@ For convenience, BEG and END default to `point-min' and This information is parsed from the file \"recently-used.xbel\", which lists both files and directories, under `xdg-data-home'. This function uses the `dom' library from Emacs 25.1 or later." - (unless (require 'dom nil t) + (unless (eval-and-compile (require 'dom nil t)) (user-error "This function requires Emacs 25.1 or later")) - (declare-function dom-attr "dom" (node attr)) (declare-function dom-by-tag "dom" (dom tag)) (let ((file-of-recent-files (expand-file-name "recently-used.xbel" (counsel--xdg-data-home)))) (unless (file-readable-p file-of-recent-files) (user-error "List of XDG recent files not found: %s" file-of-recent-files)) - (cl-mapcan (lambda (bookmark-node) - (let* ((file (dom-attr bookmark-node 'href)) - (file (string-remove-prefix "file://" file)) - (file (url-unhex-string file t)) - (file (decode-coding-string file 'utf-8 t))) - (and (file-exists-p file) - (list file)))) - (let ((dom (with-temp-buffer - (insert-file-contents file-of-recent-files) - (counsel--xml-parse-region)))) - (nreverse (dom-by-tag dom 'bookmark)))))) + (when (fboundp 'dom-attr) ;; Pacify Emacs 24. + (cl-mapcan (lambda (bookmark-node) + (let* ((file (dom-attr bookmark-node 'href)) + (file (string-remove-prefix "file://" file)) + (file (url-unhex-string file t)) + (file (decode-coding-string file 'utf-8 t))) + (and (file-exists-p file) + (list file)))) + (let ((dom (with-temp-buffer + (insert-file-contents file-of-recent-files) + (counsel--xml-parse-region)))) + (nreverse (dom-by-tag dom 'bookmark))))))) (defun counsel-buffer-or-recentf-candidates () "Return candidates for `counsel-buffer-or-recentf'." - (require 'recentf) (recentf-mode) (let ((buffers (delq nil (mapcar #'buffer-file-name (buffer-list))))) (nconc @@ -2470,7 +2595,8 @@ This function uses the `dom' library from Emacs 25.1 or later." (ivy-append-face var 'ivy-highlight-face) var)) -;;** `counsel-bookmark' +;;;; `counsel-bookmark' + (defcustom counsel-bookmark-avoid-dired nil "If non-nil, open directory bookmarks with `counsel-find-file'. By default `counsel-bookmark' opens a dired buffer for directories." @@ -2520,7 +2646,8 @@ By default `counsel-bookmark' opens a dired buffer for directories." ("r" ,(counsel--apply-bookmark-fn #'counsel-find-file-as-root) "open as root"))) -;;** `counsel-bookmarked-directory' +;;;; `counsel-bookmarked-directory' + (defun counsel-bookmarked-directory--candidates () "Get a list of bookmarked directories sorted by file path." (bookmark-maybe-load-default-file) @@ -2543,15 +2670,16 @@ current value of `default-directory'." :action #'dired)) (ivy-set-actions 'counsel-bookmarked-directory - `(("j" dired-other-window "other window") - ("x" counsel-find-file-extern "open externally") - ("r" counsel-find-file-as-root "open as root") + `(("j" ,#'dired-other-window "other window") + ("x" ,#'counsel-find-file-extern "open externally") + ("r" ,#'counsel-find-file-as-root "open as root") ("f" ,(lambda (dir) (let ((default-directory dir)) (call-interactively #'find-file))) "find-file"))) -;;** `counsel-file-register' +;;;; `counsel-file-register' + ;;;###autoload (defun counsel-file-register () "Search file in register. @@ -2588,7 +2716,8 @@ can use `C-x r j i' to open that file." 'counsel-file-register '(("j" find-file-other-window "other window"))) -;;** `counsel-locate' +;;;; `counsel-locate' + (defcustom counsel-locate-cmd (cond ((memq system-type '(darwin berkeley-unix)) #'counsel-locate-cmd-noregex) ((and (eq system-type 'windows-nt) @@ -2633,7 +2762,10 @@ string - the full shell command to run." (defalias 'counsel-find-file-extern #'counsel-locate-action-extern) -(declare-function dired-jump "dired-x") +(eval-and-compile + ;; Autoloaded by `dired' since Emacs 28. + (unless (fboundp 'dired-jump) + (autoload 'dired-jump "dired-x" nil t))) (defun counsel-locate-action-dired (x) "Use `dired-jump' on X." @@ -2735,7 +2867,8 @@ INITIAL-INPUT can be given as the initial minibuffer input." :unwind-fn #'counsel-delete-process :exit-codes '(1 "Nothing found")) -;;** `counsel-tracker' +;;;; `counsel-tracker' + (defun counsel-tracker-function (input) "Call the \"tracker\" shell command with INPUT." (or @@ -2764,7 +2897,8 @@ INITIAL-INPUT can be given as the initial minibuffer input." :display-transformer-fn #'counsel-tracker-transformer :unwind-fn #'counsel-delete-process) -;;** `counsel-fzf' +;;;; `counsel-fzf' + (defvar counsel-fzf-cmd "fzf -f \"%s\"" "Command for `counsel-fzf'.") @@ -2839,7 +2973,8 @@ FZF-PROMPT, if non-nil, is passed as `ivy-read' prompt argument." '(("x" counsel-locate-action-extern "xdg-open") ("d" counsel-locate-action-dired "dired"))) -;;** `counsel-dpkg' +;;;; `counsel-dpkg' + ;;;###autoload (defun counsel-dpkg () "Call the \"dpkg\" shell command." @@ -2860,7 +2995,8 @@ FZF-PROMPT, if non-nil, is passed as `ivy-read' prompt argument." (message (cdr x))) :caller 'counsel-dpkg))) -;;** `counsel-rpm' +;;;; `counsel-rpm' + ;;;###autoload (defun counsel-rpm () "Call the \"rpm\" shell command." @@ -2901,7 +3037,8 @@ FZF-PROMPT, if non-nil, is passed as `ivy-read' prompt argument." "Arguments for the `find-command' when using `counsel-file-jump'." :type '(repeat string)) -;;** `counsel-file-jump' +;;;; `counsel-file-jump' + (defvar counsel-file-jump-map (let ((map (make-sparse-keymap))) (define-key map (kbd "`") #'counsel-find-file-from-jump) @@ -2943,11 +3080,12 @@ INITIAL-DIRECTORY, if non-nil, is used as the root directory for search." (dired (or (file-name-directory x) default-directory))) "open in dired"))) +;;;; `counsel-dired-jump' + (defcustom counsel-dired-jump-args (split-string ". -name .git -prune -o -type d -print") "Arguments for the `find-command' when using `counsel-dired-jump'." :type '(repeat string)) -;;** `counsel-dired-jump' ;;;###autoload (defun counsel-dired-jump (&optional initial-input initial-directory) "Jump to a directory (see `dired-jump') below the current directory. @@ -2969,9 +3107,10 @@ INITIAL-DIRECTORY, if non-nil, is used as the root directory for search." :history 'file-name-history :keymap counsel-find-file-map :caller 'counsel-dired-jump))) + +;;; Grep +;;;; `counsel-ag' -;;* Grep -;;** `counsel-ag' (defvar counsel-ag-map (let ((map (make-sparse-keymap))) (define-key map (kbd "C-l") #'ivy-call-and-recenter) @@ -3201,7 +3340,8 @@ Works for `counsel-git-grep', `counsel-ag', etc." (counsel-grep-like-occur counsel-ag-command)) -;;** `counsel-pt' +;;;; `counsel-pt' + (defcustom counsel-pt-base-command "pt --nocolor --nogroup -e %s" "Alternative to `counsel-ag-base-command' using pt." :type 'string) @@ -3222,7 +3362,8 @@ This uses `counsel-ag' with `counsel-pt-base-command' instead of :display-transformer-fn #'counsel-git-grep-transformer :grep-p t) -;;** `counsel-ack' +;;;; `counsel-ack' + (defcustom counsel-ack-base-command (concat (file-name-nondirectory @@ -3244,7 +3385,8 @@ This uses `counsel-ag' with `counsel-ack-base-command' replacing initial-input nil nil nil :caller 'counsel-ack))) -;;** `counsel-rg' +;;;; `counsel-rg' + (defcustom counsel-rg-base-command `("rg" "--max-columns" "240" @@ -3264,7 +3406,9 @@ Note: don't use single quotes for the regexp." (defun counsel--rg-targets () "Return a list of files to operate on, based on `dired-mode' marks." - (when (eq major-mode 'dired-mode) + (when (derived-mode-p 'dired-mode) + (declare-function dired-get-marked-files "dired") + (declare-function dired-toggle-marks "dired") (let ((files (dired-get-marked-files 'no-dir nil nil t))) (when (or (cdr files) @@ -3307,7 +3451,8 @@ Example input with inclusion and exclusion file patterns: :grep-p t :exit-codes '(1 "No matches found")) -;;** `counsel-grep' +;;;; `counsel-grep' + (defvar counsel-grep-map (let ((map (make-sparse-keymap))) (define-key map (kbd "C-l") #'ivy-call-and-recenter) @@ -3451,7 +3596,8 @@ the initial search pattern." '((counsel-grep . ivy-recompute-index-swiper-async-backward)))) (counsel-grep initial-input))) -;;** `counsel-grep-or-swiper' +;;;; `counsel-grep-or-swiper' + (defcustom counsel-grep-swiper-limit 300000 "Buffer size threshold for `counsel-grep-or-swiper'. When the number of characters in a buffer exceeds this threshold, @@ -3487,7 +3633,8 @@ When non-nil, INITIAL-INPUT is the initial search pattern." (save-buffer)) (counsel-grep initial-input))) -;;** `counsel-grep-or-swiper-backward' +;;;; `counsel-grep-or-swiper-backward' + ;;;###autoload (defun counsel-grep-or-swiper-backward (&optional initial-input) "Call `swiper-backward' for small buffers and `counsel-grep-backward' for @@ -3498,7 +3645,8 @@ large ones. When non-nil, INITIAL-INPUT is the initial search pattern." (counsel-grep . ivy-recompute-index-swiper-async-backward)))) (counsel-grep-or-swiper initial-input))) -;;** `counsel-recoll' +;;;; `counsel-recoll' + (defun counsel-recoll-function (str) "Run recoll for STR." (or @@ -3539,9 +3687,10 @@ INITIAL-INPUT can be given as the initial minibuffer input." (ivy-configure 'counsel-recoll :unwind-fn #'counsel-delete-process) + +;;; Org +;;;; `counsel-org-tag' -;;* Org -;;** `counsel-org-tag' (defvar counsel-org-tags nil "Store the current list of tags.") @@ -3549,13 +3698,11 @@ INITIAL-INPUT can be given as the initial minibuffer input." (defvar org-indent-mode) (defvar org-indent-indentation-per-level) (defvar org-tags-column) -(declare-function org-get-tags-string "org") (declare-function org-get-tags "org") -(declare-function org-make-tag-string "org") (declare-function org-move-to-column "org-compat") (defun counsel--org-make-tag-string () - (if (fboundp #'org-make-tag-string) + (if (fboundp 'org-make-tag-string) ;; >= Org 9.2 (org-make-tag-string (counsel--org-get-tags)) (with-no-warnings @@ -3606,7 +3753,10 @@ INITIAL-INPUT can be given as the initial minibuffer input." (defvar org-agenda-bulk-marked-entries) -(declare-function org-get-at-bol "org") +;; Moved from `org' to `org-macs' in Emacs 27. +(declare-function org-get-at-bol "org-macs") +(declare-function org-trim "org-macs") + (declare-function org-agenda-error "org-agenda") (defun counsel-org-tag-action (x) @@ -3869,7 +4019,8 @@ version. Argument values are based on the (version< org-version "9.1.1")) 2 0))) -;;** `counsel-org-file' +;;;; `counsel-org-file' + (declare-function org-attach-dir "org-attach") (declare-function org-attach-file-list "org-attach") (defvar org-attach-directory) @@ -3903,40 +4054,48 @@ include attachments of other Org buffers." :action #'counsel-locate-action-dired :caller 'counsel-org-file)) -;;** `counsel-org-entity' -(defvar org-entities) -(defvar org-entities-user) +;;;; `counsel-org-entity' ;;;###autoload (defun counsel-org-entity () "Complete Org entities using Ivy." (interactive) (require 'org) - (ivy-read "Entity: " (cl-loop for element in (append org-entities org-entities-user) - unless (stringp element) - collect (cons - (format "%20s | %20s | %20s | %s" - (cl-first element) ; name - (cl-second element) ; latex - (cl-fourth element) ; html - (cl-seventh element)) ; utf-8 - element)) + (defvar org-entities) + (defvar org-entities-user) + (ivy-read "Entity: " + (cl-loop for element in (append org-entities org-entities-user) + when (consp element) + collect (cons + (format "%20s | %20s | %20s | %s" + (nth 0 element) ; Name. + (nth 1 element) ; LaTeX. + (nth 3 element) ; HTML. + (nth 6 element)) ; UTF-8. + element)) :require-match t - :action '(1 - ("u" (lambda (candidate) - (insert (cl-seventh (cdr candidate)))) "utf-8") - ("o" (lambda (candidate) - (insert "\\" (cl-first (cdr candidate)))) "org-entity") - ("l" (lambda (candidate) - (insert (cl-second (cdr candidate)))) "latex") - ("h" (lambda (candidate) - (insert (cl-fourth (cdr candidate)))) "html") - ("a" (lambda (candidate) - (insert (cl-fifth (cdr candidate)))) "ascii") - ("L" (lambda (candidate) - (insert (cl-sixth (cdr candidate))) "Latin-1"))))) + :action `(1 + ("u" ,(lambda (candidate) + (insert (nth 6 (cdr candidate)))) + "UTF-8") + ("o" ,(lambda (candidate) + (insert "\\" (nth 0 (cdr candidate)))) + "Org entity") + ("l" ,(lambda (candidate) + (insert (nth 1 (cdr candidate)))) + "LaTeX") + ("h" ,(lambda (candidate) + (insert (nth 3 (cdr candidate)))) + "HTML") + ("a" ,(lambda (candidate) + (insert (nth 4 (cdr candidate)))) + "ASCII") + ("L" ,(lambda (candidate) + (insert (nth 5 (cdr candidate)))) + "Latin-1")))) + +;;;; `counsel-org-capture' -;;** `counsel-org-capture' (defvar org-capture-templates) (defvar org-capture-templates-contexts) (declare-function org-contextualize-keys "org") @@ -3995,19 +4154,26 @@ include attachments of other Org buffers." (customize-variable 'org-capture-templates)) "customize org-capture-templates"))) -;;** `counsel-org-agenda-headlines' +;;;; `counsel-org-agenda-headlines' + (defvar org-odd-levels-only) -(declare-function org-set-startup-visibility "org") -(declare-function org-show-entry "org") (declare-function org-map-entries "org") (declare-function org-heading-components "org") (defun counsel-org-agenda-headlines-action-goto (headline) "Go to the `org-mode' agenda HEADLINE." (find-file (nth 1 headline)) - (org-set-startup-visibility) + (if (fboundp 'org-cycle-set-startup-visibility) + (org-cycle-set-startup-visibility) + ;; Obsolete alias since Org 9.6 / Emacs 29. + (with-no-warnings + (org-set-startup-visibility))) (goto-char (nth 2 headline)) - (org-show-entry)) + (if (fboundp 'org-fold-show-entry) + (org-fold-show-entry) + ;; Obsolete alias since Org 9.6 / Emacs 29. + (with-no-warnings + (org-show-entry)))) (ivy-set-actions 'counsel-org-agenda-headlines @@ -4090,7 +4256,9 @@ This variable has no effect unless :history 'counsel-org-agenda-headlines-history :caller 'counsel-org-agenda-headlines))) -;;** `counsel-org-link' +;;;; `counsel-org-link' + +;; Moved from `org' to `ol' in Emacs 27. (declare-function org-insert-link "ol") (declare-function org-id-get-create "org-id") @@ -4110,9 +4278,10 @@ This variable has no effect unless :action #'counsel-org-link-action :history 'counsel-org-link-history :caller 'counsel-org-link)) + +;;; Misc. Emacs +;;;; `counsel-mark-ring' -;; Misc. Emacs -;;** `counsel-mark-ring' (defface counsel--mark-ring-highlight '((t :inherit highlight)) "Face for current `counsel-mark-ring' line." @@ -4216,7 +4385,8 @@ Position of selected mark outside accessible part of buffer"))) :unwind-fn #'counsel--mark-ring-unwind :sort-fn #'ivy-string<) -;;** `counsel-evil-marks' +;;;; `counsel-evil-marks' + (defvar counsel-evil-marks-exclude-registers nil "List of evil registers to not display in `counsel-evil-marks' by default. Each member of the list should be a character (stored as an integer).") @@ -4281,7 +4451,8 @@ When ARG is non-nil, display all active evil registers." (message "No evil marks are active"))) (user-error "Required feature `evil' not installed or loaded"))) -;;** `counsel-package' +;;;; `counsel-package' + (defvar package--initialized) (defvar package-alist) (defvar package-archive-contents) @@ -4289,7 +4460,7 @@ When ARG is non-nil, display all active evil registers." (defvar package-user-dir) (declare-function package-installed-p "package") (declare-function package-delete "package") -(declare-function package-desc-extras "package") +(declare-function package-desc-extras "package" t t) (defvar counsel-package-history nil "History for `counsel-package'.") @@ -4373,16 +4544,16 @@ Additional actions:\\ '(("d" counsel-package-action-describe "describe package") ("h" counsel-package-action-homepage "open package homepage"))) -;;** `counsel-tmm' +;;;; `counsel-tmm' + (declare-function tmm-get-keymap "tmm" (elt &optional in-x-menu)) -(declare-function tmm--completion-table "tmm" (items)) (defalias 'counsel--menu-keymap ;; Added in Emacs 28.1. (if (fboundp 'menu-bar-keymap) #'menu-bar-keymap - (autoload 'tmm-get-keybind "tmm") - (declare-function tmm-get-keybind "tmm" (keyseq)) + ;; Removed in Emacs 28.1. + (declare-function tmm-get-keybind "tmm" (keyseq) t) (lambda () (tmm-get-keybind [menu-bar]))) "Compatibility shim for `menu-bar-keymap'.") @@ -4394,9 +4565,14 @@ Additional actions:\\ chosen-string) (setq tmm-km-list nil) (map-keymap (lambda (k v) (tmm-get-keymap (cons k v))) menu) - (setq tmm-km-list (nreverse tmm-km-list)) - (setq out (ivy-read "Menu bar: " (tmm--completion-table tmm-km-list) - :require-match t)) + (let ((items (setq tmm-km-list (nreverse tmm-km-list)))) + (setq out (ivy-read "Menu bar: " + ;; From `tmm--completion-table', removed in Emacs 31. + (lambda (str pred action) + (if (eq action 'metadata) + '(metadata (display-sort-function . identity)) + (complete-with-action action items str pred))) + :require-match t))) (setq choice (cdr (assoc out tmm-km-list))) (setq chosen-string (car choice)) (setq choice (cdr choice)) @@ -4416,7 +4592,8 @@ Additional actions:\\ (setq tmm-table-undef nil) (counsel-tmm-prompt (counsel--menu-keymap))) -;;** `counsel-yank-pop' +;;;; `counsel-yank-pop' + (defcustom counsel-yank-pop-truncate-radius 2 "Number of context lines around `counsel-yank-pop' candidates." :type 'integer) @@ -4666,7 +4843,7 @@ Note: Duplicate elements of `kill-ring' are always deleted." :action #'counsel-yank-pop-action :caller 'counsel-yank-pop))) -(put #'counsel-yank-pop 'delete-selection 'yank) +(function-put #'counsel-yank-pop 'delete-selection 'yank) (ivy-configure 'counsel-yank-pop :height 5 @@ -4677,7 +4854,8 @@ Note: Duplicate elements of `kill-ring' are always deleted." '(("d" counsel-yank-pop-action-remove "delete") ("r" counsel-yank-pop-action-rotate "rotate"))) -;;** `counsel-register' +;;;; `counsel-register' + (defvar counsel-register-actions '(("\\`buffer" . jump-to-register) ("\\`text" . insert-register) @@ -4731,7 +4909,8 @@ matching the register's value description against a regexp in (ivy-configure 'counsel-register :sort-fn #'ivy-string<) -;;** `counsel-evil-registers' +;;;; `counsel-evil-registers' + (defface counsel-evil-register-face '((t :inherit counsel-outline-1)) "Face for highlighting `evil' registers in ivy." @@ -4765,14 +4944,15 @@ S will be of the form \"[register]: content\"." (insert (replace-regexp-in-string "\\`\\[.*?]: " "" s t t)))) -;;** `counsel-imenu' -(defvar imenu-auto-rescan) -(defvar imenu-auto-rescan-maxout) +;;;; `counsel-imenu' + (declare-function imenu--subalist-p "imenu") (declare-function imenu--make-index-alist "imenu") (defun counsel--imenu-candidates () (require 'imenu) + (defvar imenu-auto-rescan) + (defvar imenu-auto-rescan-maxout) (let* ((imenu-auto-rescan t) (imenu-auto-rescan-maxout (if current-prefix-arg (buffer-size) @@ -4842,7 +5022,8 @@ PREFIX is used to create the key." :history 'counsel-imenu-history :caller 'counsel-imenu)) -;;** `counsel-list-processes' +;;;; `counsel-list-processes' + (defun counsel-list-processes-action-delete (x) "Delete process X." (delete-process x) @@ -4874,7 +5055,8 @@ An extra action allows to switch to the process buffer." ("s" counsel-list-processes-action-switch "switch")) :caller 'counsel-list-processes)) -;;** `counsel-ace-link' +;;;; `counsel-ace-link' + (defun counsel-ace-link () "Use Ivy completion for `ace-link'." (interactive) @@ -4904,7 +5086,8 @@ An extra action allows to switch to the process buffer." :require-match t :caller 'counsel-ace-link)))) -;;** `counsel-minibuffer-history' +;;;; `counsel-minibuffer-history' + ;;;###autoload (defun counsel-minibuffer-history () "Browse minibuffer history." @@ -4917,7 +5100,8 @@ An extra action allows to switch to the process buffer." (insert (substring-no-properties (car x)))) :caller 'counsel-minibuffer-history))) -;;** `counsel-esh-history' +;;;; `counsel-esh-history' + (defvar comint-input-ring-index) (defvar eshell-history-index) (defvar slime-repl-input-history-position) @@ -5015,7 +5199,8 @@ An extra action allows to switch to the process buffer." ;; `counsel-slime-repl-history' within ;; `counsel--browse-history-action'. -;;** `counsel-hydra-heads' +;;;; `counsel-hydra-heads' + (defvar hydra-curr-body-fn) (declare-function hydra-keyboard-quit "ext:hydra") @@ -5039,7 +5224,9 @@ An extra action allows to switch to the process buffer." (ivy-read "head: " head-names :action (lambda (x) (call-interactively (cdr x)))) (hydra-keyboard-quit))) -;;** `counsel-semantic' + +;;;; `counsel-semantic' + (declare-function semantic-tag-start "semantic/tag") (declare-function semantic-tag-class "semantic/tag") (declare-function semantic-tag-name "semantic/tag") @@ -5117,8 +5304,7 @@ TREEP is used to expand internal nodes." (counsel-semantic) (counsel-imenu))) -;;** `counsel-outline' -(declare-function org-trim "org-macs") +;;;; `counsel-outline' (defcustom counsel-outline-face-style nil "Determines how to style outline headings during completion. @@ -5329,7 +5515,8 @@ the face to apply." :caller (or (plist-get settings :caller) 'counsel-outline)))) -;;** `counsel-ibuffer' +;;;; `counsel-ibuffer' + (defvar counsel-ibuffer--buffer-name nil "Name of the buffer to use for `counsel-ibuffer'.") @@ -5397,7 +5584,8 @@ the values are the corresponding buffer objects." '(("j" counsel-ibuffer-visit-buffer-other-window "other window") ("v" counsel-ibuffer-visit-ibuffer "switch to Ibuffer"))) -;;** `counsel-switch-to-shell-buffer' +;;;; `counsel-switch-to-shell-buffer' + (defun counsel--buffers-with-mode (mode) "Return names of buffers with MODE as their `major-mode'." (let (bufs) @@ -5427,7 +5615,8 @@ If there is no such buffer, start a new `shell' with NAME." (reusable-frames . visible))) (shell name))) -;;** `counsel-unicode-char' +;;;; `counsel-unicode-char' + (defvar counsel-unicode-char-history nil "History for `counsel-unicode-char'.") @@ -5484,7 +5673,8 @@ COUNT defaults to 1." 'counsel-unicode-char '(("w" counsel-unicode-copy "copy"))) -;;** `counsel-colors' +;;;; Colors + (defun counsel-colors-action-insert-hex (color) "Insert the hexadecimal RGB value of COLOR." (insert (get-text-property 0 'hex color))) @@ -5493,7 +5683,8 @@ COUNT defaults to 1." "Kill the hexadecimal RGB value of COLOR." (kill-new (get-text-property 0 'hex color))) -;;** `counsel-colors-emacs' +;;;;; `counsel-colors-emacs' + (defvar counsel-colors-emacs-history () "History for `counsel-colors-emacs'.") @@ -5586,7 +5777,8 @@ selected color." '(("h" counsel-colors-action-insert-hex "insert hexadecimal value") ("H" counsel-colors-action-kill-hex "kill hexadecimal value"))) -;;** `counsel-colors-web' +;;;;; `counsel-colors-web' + (defvar shr-color-html-colors-alist) (defun counsel-colors--web-alist () @@ -5635,7 +5827,8 @@ selected color." '(("h" counsel-colors-action-insert-hex "insert hexadecimal value") ("H" counsel-colors-action-kill-hex "kill hexadecimal value"))) -;;** `counsel-fonts' +;;;; `counsel-fonts' + (defvar counsel-fonts-history () "History for `counsel-fonts'.") @@ -5663,15 +5856,17 @@ You can insert or kill the name of the selected font." (propertize "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 'face (list :family font-name)))) -;;** `counsel-kmacro' +;;;; `counsel-kmacro' + (defvar counsel-kmacro-map (let ((map (make-sparse-keymap))) (define-key map (kbd "C-k") #'counsel-kmacro-kill) map)) +;; Avoid (declare (modes ...)) warnings in Emacs < 28. +(function-put #'counsel-kmacro-kill 'command-modes '(minibuffer-mode)) (defun counsel-kmacro-kill () "Kill the line, or delete the currently selected keyboard macro." - (declare (modes minibuffer-mode)) (interactive) (unless (window-minibuffer-p) (user-error "No completion session is active")) @@ -5911,7 +6106,8 @@ The existing CANDIDATE, its counter and format, are left unchanged." ("v" ,#'counsel-kmacro-action-copy-initial-counter-value "copy starting counter value"))) -;;** `counsel-geiser-doc-look-up-manual' +;;;; `counsel-geiser-doc-look-up-manual' + (declare-function geiser-doc-manual-for-symbol "ext:geiser-doc") (defvar geiser-completion-symbol-list-func) @@ -5928,9 +6124,10 @@ The existing CANDIDATE, its counter and format, are left unchanged." :action (lambda (cand) (geiser-doc-manual-for-symbol (intern cand))) :caller 'counsel-geiser-doc-look-up-manual)) + +;;; Misc. OS +;;;; `counsel-rhythmbox' -;;* Misc. OS -;;** `counsel-rhythmbox' (declare-function dbus-call-method "dbus") (declare-function dbus-get-property "dbus") @@ -6049,7 +6246,7 @@ The existing CANDIDATE, its counter and format, are left unchanged." ("s" counsel-rhythmbox-toggle-shuffle "Shuffle on/off")) :caller 'counsel-rhythmbox)) -;;** `counsel-linux-app' +;;;; `counsel-linux-app' ;; Added in Emacs 26.1. (require 'xdg nil t) @@ -6215,7 +6412,8 @@ This function always returns its elements in a stable order." (when (file-exists-p dir) (let ((dir (file-name-as-directory dir))) ;; Function `directory-files-recursively' added in Emacs 25.1. - (dolist (file (directory-files-recursively dir "\\.desktop\\'")) + (dolist (file (and (fboundp 'directory-files-recursively) + (directory-files-recursively dir "\\.desktop\\'"))) (let ((id (subst-char-in-string ?/ ?- (file-relative-name file dir)))) (when (and (not (gethash id hash)) (file-readable-p file)) (push (cons id file) result) @@ -6340,7 +6538,8 @@ When ARG is non-nil, ignore NoDisplay property in *.desktop files." :action #'counsel-linux-app-action-default :caller 'counsel-linux-app)) -;;** `counsel-wmctrl' +;;;; `counsel-wmctrl' + (defun counsel-wmctrl-action (x) "Select the desktop window that corresponds to X." (counsel--run "wmctrl" "-i" "-a" (cdr x))) @@ -6457,7 +6656,8 @@ in the current window." '(("x" counsel-open-buffer-file-externally "open externally") ("j" ivy--switch-buffer-other-window-action "other window"))) -;;** `counsel-compile' +;;;; `counsel-compile' + (defvar counsel-compile-history nil "History for `counsel-compile'. @@ -6748,6 +6948,8 @@ This is determined by `counsel-compile-local-builds', which see." ;; things like infer `default-directory' from 'cd's in the string. (defun counsel-compile--update-history (_proc) "Update `counsel-compile-history' from the compilation state." + (defvar compilation-arguments) + (defvar compilation-environment) (let* ((srcdir (counsel--compile-root)) (blddir default-directory) (bldenv compilation-environment) @@ -6776,6 +6978,7 @@ edited the command, thus losing our embedded state.") If CMD has the `recursive' property set we call `counsel-compile' again to further refine the compile options in the directory specified by the `blddir' property." + (defvar compilation-environment) (let ((blddir (get-text-property 0 'blddir cmd)) (bldenv (get-text-property 0 'bldenv cmd))) (if (get-text-property 0 'recursive cmd) @@ -6812,7 +7015,8 @@ handling for the `counsel-compile' metadata." ;; operation which doesn't include the metadata we want. (defvar counsel-compile-map (let ((map (make-sparse-keymap))) - (define-key map [remap ivy-insert-current] #'counsel-compile-edit-command) + (define-key map `[remap ,#'ivy-insert-current] + #'counsel-compile-edit-command) map) "Additional ivy keybindings during command selection.") @@ -6824,6 +7028,8 @@ Additional actions: \\{counsel-compile-map}" (interactive) + (require 'compile) + (require 'dired) ;; For face `dired-directory'. (setq counsel-compile--current-build-dir (or dir (counsel--compile-root) default-directory)) @@ -6882,134 +7088,155 @@ Additional actions: (ivy-configure 'counsel-compile-env :format-fn #'counsel-compile-env--format-hint) -;;** `counsel-minor' -(defvar counsel-minor-history nil - "History for `counsel-minor'.") - -(defun counsel--minor-candidates () - "Return completion alist for `counsel-minor'. - -The alist element is cons of minor mode string with its lighter -and minor mode symbol." - (cl-mapcan - (let ((suffix (propertize " \"%s\"" 'face 'font-lock-string-face))) - (lambda (mode) - (when (and (boundp mode) (commandp mode)) - (let ((lighter (cdr (assq mode minor-mode-alist)))) - (list (cons (concat - (if (symbol-value mode) "-" "+") - (symbol-name mode) - (and lighter - (format suffix - (format-mode-line (cons t lighter))))) - mode)))))) - minor-mode-list)) - -;;;###autoload -(defun counsel-minor () - "Enable or disable minor mode. - -Disabled minor modes are prefixed with \"+\", and -selecting one of these will enable it. -Enabled minor modes are prefixed with \"-\", and -selecting one of these will enable it. - -Additional actions:\\ - - \\[ivy-dispatching-done] d: Go to minor mode definition - \\[ivy-dispatching-done] h: Describe minor mode" - - (interactive) - (ivy-read "Minor modes (enable +mode or disable -mode): " - (counsel--minor-candidates) - :require-match t - :history 'counsel-minor-history - :action (lambda (x) - (call-interactively (cdr x))))) - -(ivy-configure 'counsel-minor - :initial-input "^+" - :sort-fn #'ivy-string<) - -(ivy-set-actions - 'counsel-minor - `(("d" ,(lambda (x) (find-function (cdr x))) "definition") - ("h" ,(lambda (x) (describe-function (cdr x))) "help"))) - -;;;###autoload -(defun counsel-major () - (interactive) - (ivy-read "Major modes: " obarray - :predicate (lambda (f) - (and (commandp f) - (string-suffix-p "-mode" (symbol-name f)) - (or (and (autoloadp (symbol-function f)) - (let ((doc-split (help-split-fundoc (documentation f) f))) - ;; major mode starters have no arguments - (and doc-split (null (cdr (read (car doc-split))))))) - (null (help-function-arglist f))))) - :action #'counsel-M-x-action - :caller 'counsel-major)) - -;;** `counsel-search' -(declare-function request "ext:request") +;;;; `counsel-search' (defcustom counsel-search-engine 'ddg "The search engine choice in `counsel-search-engines-alist'." :type '(choice - (const ddg) - (const google))) + (const :tag "DuckDuckGo" ddg) + (const :tag "Google" google))) (defcustom counsel-search-engines-alist - '((google - "http://suggestqueries.google.com/complete/search" - "https://www.google.com/search?q=" - counsel--search-request-data-google) - (ddg + '((ddg "https://duckduckgo.com/ac/" "https://duckduckgo.com/html/?q=" - counsel--search-request-data-ddg)) - "Search engine parameters for `counsel-search'." + counsel--search-request-data-ddg) + (google + "https://suggestqueries.google.com/complete/search" + "https://www.google.com/search?q=" + counsel--search-request-data-google)) + "List of search engine parameters for `counsel-search'. +Each element is of the form (SYMBOL SUGGEST BROWSE EXTRACT), where: +SYMBOL identifies the search engine, as per `counsel-search-engine'. +SUGGEST is the URL to query for suggestions. +BROWSE is the URL prefix for visiting the selected result. +EXTRACT is a function that takes the object parsed from the SUGGEST + endpoint and transforms it into a set of Ivy candidates." + :package-version '(counsel . "0.15.1") :type '(alist :key-type symbol :value-type (list string string function))) (defun counsel--search-request-data-google (data) - (mapcar #'identity (aref data 1))) + "Extract Google suggestions from parsed JSON DATA. +Expects input of the form [\"a\" [\"ab\" \"ac\"] ...]." + (append (aref data 1) ())) (defun counsel--search-request-data-ddg (data) + "Extract DuckDuckGo suggestions from parsed JSON DATA. +Expects input of the form [((phrase . \"ab\")) ...]." (mapcar #'cdar data)) +(defvar counsel--native-json) +(put 'counsel--native-json 'variable-documentation + "Non-nil if Emacs supports JSON natively, or void.") + +(defun counsel--search-update (extract str type) + "Call EXTRACT on JSON STR of Content-TYPE." + (unless (fboundp 'mail-header-parse-content-type) + (require 'mail-parse)) + (declare-function json-parse-string "json.c") + (declare-function json-read-from-string "json") + (declare-function mail-content-type-get "mail-parse") + (declare-function mail-header-parse-content-type "mail-parse") + (let* ((ct (and type (mail-header-parse-content-type type))) + (coding (coding-system-from-name (mail-content-type-get ct 'charset)))) + (when coding + (setq str (decode-coding-string str coding t)))) + (let ((obj (if counsel--native-json + (json-parse-string str :object-type 'alist) + (defvar json-array-type) + (defvar json-object-type) + (let ((json-array-type 'vector) + (json-object-type 'alist)) + (json-read-from-string str))))) + (ivy-update-candidates (funcall extract obj)))) + +(defun counsel--search-plz (url extract) + "Fetch URL with `plz' and EXTRACT its JSON payload." + (declare-function plz "ext:plz") + (declare-function plz-response-body "ext:plz") + (declare-function plz-response-headers "ext:plz") + ;; Doesn't handle Content-Type, so defer decoding+parsing until :then. + ;; (See URL `https://github.com/alphapapa/plz.el/pull/66'.) + ;; Ask for a `plz-response' object because it already contains the parsed + ;; headers (though just widening the response buffer could be quicker). + (plz 'get url :as 'response :decode nil :noquery t + :then (lambda (response) + (let* ((heads (plz-response-headers response)) + (body (plz-response-body response)) + (ct (cdr (assq 'content-type heads)))) + (counsel--search-update extract body ct))))) + +(defun counsel--search-request (url extract) + "Fetch URL with `request' and EXTRACT its JSON payload." + (declare-function request "ext:request") + (declare-function request-response-header "ext:request") + ;; Doesn't handle Content-Type (expects coding system a priori), + ;; so defer decoding+parsing until :success. + (request url :type "GET" + :success (cl-function + (lambda (&key data response &allow-other-keys) + (let ((ct (request-response-header response "content-type"))) + (counsel--search-update extract data ct)))))) + +(defvar counsel--search-backend) +(put 'counsel--search-backend 'variable-documentation + "Feature symbol indicating available HTTP library, or void. +Valid values are the keys of `counsel--search-backends'.") + +(defvar counsel--search-backends + `((plz ,#'counsel--search-plz) + (request ,#'counsel--search-request)) + "List of (BACKEND GETTER) for `counsel-search'. +BACKEND is a feature symbol like `counsel--search-backend'. +GETTER is a function taking a URL and an EXTRACT function as in + `counsel-search-engines-alist'.") + (defun counsel-search-function (input) "Create a request to a search engine with INPUT. Return 0 tells `ivy--exhibit' not to update the minibuffer. We update it in the callback with `ivy-update-candidates'." (or (ivy-more-chars) - (let ((engine (cdr (assoc counsel-search-engine counsel-search-engines-alist)))) - (request - (nth 0 engine) - :type "GET" - :params (list - (cons "client" "firefox") - (cons "q" input)) - :parser 'json-read - :success (cl-function - (lambda (&key data &allow-other-keys) - (ivy-update-candidates - (funcall (nth 2 engine) data))))) + (let* ((backend (assq counsel--search-backend counsel--search-backends)) + (engine (assq counsel-search-engine counsel-search-engines-alist)) + (suggest (nth 1 engine)) + (extract (nth 3 engine)) + (url (concat suggest (if (ivy--string-search "?" suggest) "&" "?") + ;; FIXME: `client' needed only for `google'? + (url-build-query-string `(("client" "firefox") + ("q" ,input)))))) + ;; Do we need to cancel requests already in flight? + (funcall (nth 1 backend) url extract) 0))) -(defun counsel-search-action (x) - "Search for X." - (browse-url - (concat - (nth 2 (assoc counsel-search-engine counsel-search-engines-alist)) - (url-hexify-string x)))) +(defun counsel-search-action (candidate) + "Browse the search results for `counsel-search' CANDIDATE." + (let ((engine (assq counsel-search-engine counsel-search-engines-alist))) + (browse-url (concat (nth 2 engine) (url-hexify-string candidate))))) (defun counsel-search () - "Ivy interface for dynamically querying a search engine." + "Ivy interface for querying a search engine. +Dynamically displays search suggestions for the current input. +The user options `counsel-search-engine' and +`counsel-search-engines-alist' determine the engine." (interactive) - (require 'request) - (require 'json) + (unless (boundp 'counsel--search-backend) + (setq counsel--search-backend + ;; `plz' is on GNU ELPA; `request' on NonGNU ELPA. + (or (require 'plz nil t) + (require 'request nil t) + (user-error + "Required package `plz' (or `request') not installed")))) + ;; - Emacs 27: optional native JSON support. + ;; - Emacs 28: `json-available-p'. + ;; - Emacs 30: unconditional native JSON support. + ;; That means the following sets `counsel--native-json' to nil even for + ;; Emacs 27 with native JSON support, in the interest of simplicity. + (or (boundp 'counsel--native-json) + (setq counsel--native-json + (and (fboundp 'json-available-p) + (json-available-p))) + (require 'json)) (ivy-read "search: " #'counsel-search-function :action #'counsel-search-action :dynamic-collection t @@ -7018,7 +7245,13 @@ We update it in the callback with `ivy-update-candidates'." (define-obsolete-function-alias 'counsel-google #'counsel-search "0.13.2 (2019-10-17)") -;;** `counsel-compilation-errors' +;;;; `counsel-compilation-errors' + +(declare-function compilation--message->loc "compile" t t) +(declare-function compilation-buffer-p "compile") +(declare-function compilation-next-single-property-change "compile") +(declare-function compile-goto-error "compile") + (defun counsel--compilation-errors-buffer (buf) (with-current-buffer buf (let ((res nil) @@ -7052,12 +7285,14 @@ We update it in the callback with `ivy-update-candidates'." (defun counsel-compilation-errors () "Compilation errors." (interactive) + (require 'compile) (ivy-read "compilation errors: " (counsel-compilation-errors-cands) :require-match t :action #'counsel-compilation-errors-action :history 'counsel-compilation-errors-history)) -;;** `counsel-flycheck' +;;;; `counsel-flycheck' + (defvar flycheck-current-errors) (declare-function flycheck-error-filename "ext:flycheck") (declare-function flycheck-error-line "ext:flycheck") @@ -7107,34 +7342,33 @@ We update it in the callback with `ivy-update-candidates'." :require-match t :action #'counsel-flycheck-errors-action :history 'counsel-flycheck-errors-history)) + +;;; `counsel-mode' - -;;* `counsel-mode' (defvar counsel-mode-map (let ((map (make-sparse-keymap))) - (dolist (binding - '((execute-extended-command . counsel-M-x) - (describe-bindings . counsel-descbinds) - (describe-function . counsel-describe-function) - (describe-variable . counsel-describe-variable) - (describe-symbol . counsel-describe-symbol) - (apropos-command . counsel-apropos) - (describe-face . counsel-describe-face) - (list-faces-display . counsel-faces) - (find-file . counsel-find-file) - (find-library . counsel-find-library) - (imenu . counsel-imenu) - (load-library . counsel-load-library) - (load-theme . counsel-load-theme) - (yank-pop . counsel-yank-pop) - (info-lookup-symbol . counsel-info-lookup-symbol) - (pop-to-mark-command . counsel-mark-ring) - (geiser-doc-look-up-manual . counsel-geiser-doc-look-up-manual) - (bookmark-jump . counsel-bookmark))) - (define-key map (vector 'remap (car binding)) (cdr binding))) + (define-key map `[remap ,#'execute-extended-command] #'counsel-M-x) + (define-key map `[remap ,#'describe-bindings] #'counsel-descbinds) + (define-key map `[remap ,#'describe-function] #'counsel-describe-function) + (define-key map `[remap ,#'describe-variable] #'counsel-describe-variable) + (define-key map [remap describe-symbol] #'counsel-describe-symbol) + (define-key map `[remap ,#'apropos-command] #'counsel-apropos) + (define-key map `[remap ,#'describe-face] #'counsel-describe-face) + (define-key map `[remap ,#'list-faces-display] #'counsel-faces) + (define-key map `[remap ,#'find-file] #'counsel-find-file) + (define-key map `[remap ,#'find-library] #'counsel-find-library) + (define-key map `[remap ,#'imenu] #'counsel-imenu) + (define-key map `[remap ,#'load-library] #'counsel-load-library) + (define-key map `[remap ,#'load-theme] #'counsel-load-theme) + (define-key map `[remap ,#'yank-pop] #'counsel-yank-pop) + (define-key map `[remap ,#'info-lookup-symbol] #'counsel-info-lookup-symbol) + (define-key map `[remap ,#'pop-to-mark-command] #'counsel-mark-ring) + (define-key map [remap geiser-doc-look-up-manual] + #'counsel-geiser-doc-look-up-manual) + (define-key map `[remap ,#'bookmark-jump] #'counsel-bookmark) map) - "Map for `counsel-mode'. -Remaps built-in functions to counsel replacements.") + "Keymap for `counsel-mode'. +Remaps built-in and external functions to Counsel replacements.") (defcustom counsel-mode-override-describe-bindings nil "Whether to override `describe-bindings' when `counsel-mode' is active." diff --git a/lisp/crdt/README-elpa b/lisp/crdt/README-elpa index 8a64a80d..ae546a98 100644 --- a/lisp/crdt/README-elpa +++ b/lisp/crdt/README-elpa @@ -13,8 +13,7 @@ • Comint derivatives integration (experimental) -[CRDT] - +[CRDT] https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type 2 Usage @@ -129,7 +128,7 @@ ─────────────── Visualizing author of parts of the document - Turn on `crdt-visualize-author-mode' to color text based on + Turn on `crdt-visualize-author-mode' to color text based on which user authored it. Synchronizing Org folding status @@ -138,11 +137,11 @@ enabling this minor mode are unaffected. Comint integration - Just go ahead and share you comint REPL buffer! Tested: `shell' - and `cmuscheme'. By default, when sharing a comint buffer, - `crdt.el' temporarily reset input history (as in `M-n' `M-p') so - others don't spy into your `.bash_history' and alike. You can - customize this behavior using variable + Just go ahead and share you comint REPL buffer! Tested: + `shell' and `cmuscheme'. By default, when sharing a comint + buffer, `crdt.el' temporarily reset input history (as in `M-n' + `M-p') so others don't spy into your `.bash_history' and alike. + You can customize this behavior using variable `crdt-comint-share-input-history'. @@ -194,8 +193,8 @@ └──── -[tuntox] +[tuntox] https://gitlab.com/gjedeer/tuntox -[Tox] +[Tox] https://tox.chat -[their website] +[their website] https://www.remlab.net/miredo/ diff --git a/lisp/ctable/ctable-pkg.el b/lisp/ctable/ctable-pkg.el index 65dad3ec..379f904b 100644 --- a/lisp/ctable/ctable-pkg.el +++ b/lisp/ctable/ctable-pkg.el @@ -1,15 +1,11 @@ -(define-package "ctable" "20210128.629" "Table component for Emacs Lisp" - '((emacs "24.3") +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "ctable" "20210128.629" + "Table component for Emacs Lisp." + '((emacs "24.3") (cl-lib "0.5")) - :commit "48b73742757a3ae5736d825fe49e00034cc453b5" :authors - '(("SAKURAI Masashi" . "m.sakuraiatkiwanami.net")) - :maintainers - '(("SAKURAI Masashi" . "m.sakuraiatkiwanami.net")) - :maintainer - '("SAKURAI Masashi" . "m.sakuraiatkiwanami.net") - :keywords - '("table") - :url "https://github.com/kiwanami/emacs-ctable") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/kiwanami/emacs-ctable" + :commit "48b73742757a3ae5736d825fe49e00034cc453b5" + :revdesc "48b73742757a" + :keywords '("table") + :authors '(("SAKURAI Masashi" . "m.sakuraiatkiwanami.net")) + :maintainers '(("SAKURAI Masashi" . "m.sakuraiatkiwanami.net"))) diff --git a/lisp/ctable/ctable.el b/lisp/ctable/ctable.el index 29e832ae..1c490588 100644 --- a/lisp/ctable/ctable.el +++ b/lisp/ctable/ctable.el @@ -4,7 +4,8 @@ ;; Author: SAKURAI Masashi ;; URL: https://github.com/kiwanami/emacs-ctable -;; Version: 0.1.3 +;; Package-Version: 20210128.629 +;; Package-Revision: 48b73742757a ;; Package-Requires: ((emacs "24.3") (cl-lib "0.5")) ;; Keywords: table diff --git a/lisp/dash/dash-pkg.el b/lisp/dash/dash-pkg.el index 6b4ebeff..3fd56b18 100644 --- a/lisp/dash/dash-pkg.el +++ b/lisp/dash/dash-pkg.el @@ -1,14 +1,10 @@ -(define-package "dash" "20240510.1327" "A modern list library for Emacs" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "dash" "20250312.1307" + "A modern list library for Emacs." '((emacs "24")) - :commit "1de9dcb83eacfb162b6d9a118a4770b1281bcd84" :authors - '(("Magnar Sveen" . "magnars@gmail.com")) - :maintainers - '(("Magnar Sveen" . "magnars@gmail.com")) - :maintainer - '("Magnar Sveen" . "magnars@gmail.com") - :keywords - '("extensions" "lisp") - :url "https://github.com/magnars/dash.el") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/magnars/dash.el" + :commit "fcb5d831fc08a43f984242c7509870f30983c27c" + :revdesc "fcb5d831fc08" + :keywords '("extensions" "lisp") + :authors '(("Magnar Sveen" . "magnars@gmail.com")) + :maintainers '(("Basil L. Contovounesios" . "basil@contovou.net"))) diff --git a/lisp/dash/dash.el b/lisp/dash/dash.el index ed2a8592..b23ffcf4 100644 --- a/lisp/dash/dash.el +++ b/lisp/dash/dash.el @@ -1,12 +1,14 @@ ;;; dash.el --- A modern list library for Emacs -*- lexical-binding: t -*- -;; Copyright (C) 2012-2024 Free Software Foundation, Inc. +;; Copyright (C) 2012-2025 Free Software Foundation, Inc. ;; Author: Magnar Sveen -;; Version: 2.19.1 +;; Maintainer: Basil L. Contovounesios +;; Package-Version: 20250312.1307 +;; Package-Revision: fcb5d831fc08 ;; Package-Requires: ((emacs "24")) ;; Keywords: extensions, lisp -;; Homepage: https://github.com/magnars/dash.el +;; URL: https://github.com/magnars/dash.el ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -30,6 +32,15 @@ ;;; Code: (eval-when-compile + (unless (fboundp 'static-if) + (defmacro static-if (condition then-form &rest else-forms) + "Expand to THEN-FORM or ELSE-FORMS based on compile-time CONDITION. +Polyfill for Emacs 30 `static-if'." + (declare (debug (sexp sexp &rest sexp)) (indent 2)) + (if (eval condition lexical-binding) + then-form + (cons 'progn else-forms)))) + ;; TODO: Emacs 24.3 first introduced `gv', so remove this and all ;; calls to `defsetf' when support for earlier versions is dropped. (unless (fboundp 'gv-define-setter) @@ -784,19 +795,24 @@ See also: `-flatten'" list) (defalias '-concat #'append - "Concatenate all the arguments and make the result a list. + "Concatenate all SEQUENCES and make the result a list. The result is a list whose elements are the elements of all the arguments. Each argument may be a list, vector or string. All arguments except the last argument are copied. The last argument -is just used as the tail of the new list. +is just used as the tail of the new list. If the last argument is not +a list, this results in a dotted list. + +As an exception, if all the arguments except the last are nil, and the +last argument is not a list, the return value is that last argument +unaltered, not a list. \(fn &rest SEQUENCES)") (defalias '-copy #'copy-sequence "Create a shallow copy of LIST. - -\(fn LIST)") +The elements of LIST are not copied; they are shared with the original. +\n(fn LIST)") (defmacro --splice (pred form list) "Splice lists generated by FORM in place of items satisfying PRED in LIST. @@ -1036,13 +1052,9 @@ See also: `-first-item', etc." (declare (pure t) (side-effect-free t)) (car (last list))) -;; Use `with-no-warnings' to suppress unbound `-last-item' or -;; undefined `gv--defsetter' warnings arising from both -;; `gv-define-setter' and `defsetf' in certain Emacs versions. -(with-no-warnings - (if (fboundp 'gv-define-setter) - (gv-define-setter -last-item (val x) `(setcar (last ,x) ,val)) - (defsetf -last-item (x) (val) `(setcar (last ,x) ,val)))) +(static-if (fboundp 'gv-define-setter) + (gv-define-setter -last-item (val x) `(setcar (last ,x) ,val)) + (defsetf -last-item (x) (val) `(setcar (last ,x) ,val))) (defun -butlast (list) "Return a list of all items in list except for the last." @@ -1241,6 +1253,17 @@ For another variant, see also `-take-while'." (declare (important-return-value t)) (--drop-while (funcall pred it) list)) +;; Added in Emacs 29. +(static-if (fboundp 'take) + (defun dash--take (n list) + "Return the first N elements of LIST. +Like `take', but ensure result is fresh." + (let ((prefix (take n list))) + (if (eq prefix list) + ;; If same list is returned, make a copy. + (copy-sequence prefix) + prefix)))) + (defun -take (n list) "Return a copy of the first N items in LIST. Return a copy of LIST if it contains N items or fewer. @@ -1248,7 +1271,9 @@ Return nil if N is zero or less. See also: `-take-last'." (declare (side-effect-free t)) - (--take-while (< it-index n) list)) + (static-if (fboundp 'dash--take) + (dash--take n list) + (--take-while (< it-index n) list))) (defun -take-last (n list) "Return a copy of the last N items of LIST in order. @@ -1274,7 +1299,9 @@ Return nil if LIST contains N items or fewer. See also: `-drop'." (declare (side-effect-free t)) - (nbutlast (copy-sequence list) n)) + (static-if (fboundp 'dash--take) + (dash--take (- (length list) n) list) + (nbutlast (copy-sequence list) n))) (defun -split-at (n list) "Split LIST into two sublists after the Nth element. @@ -2440,7 +2467,7 @@ Similar to &hash but check whether the map is not nil." `(let ((,src ,source)) (when ,src (gethash ,key ,src))))) -(defalias 'dash-expand:&keys 'dash-expand:&plist) +(defalias 'dash-expand:&keys #'dash-expand:&plist) (defun dash--match-kv-1 (match-form source type) "Match MATCH-FORM against SOURCE of type TYPE. @@ -2901,16 +2928,14 @@ example: (let ((cmp -compare-fn)) (cond ((memq cmp '(nil equal)) #'assoc) ((eq cmp #'eq) #'assq) - ;; Since Emacs 26, `assoc' accepts a custom `testfn'. - ;; Version testing would be simpler here, but feature - ;; testing gets more brownie points, I guess. - ((condition-case nil - (with-no-warnings (assoc nil () #'eql)) - (wrong-number-of-arguments t)) - (lambda (key alist) - (--first (and (consp it) (funcall cmp (car it) key)) alist))) - ((with-no-warnings - (lambda (key alist) + ((lambda (key alist) + ;; Since Emacs 26, `assoc' accepts a custom `testfn'. + ;; Version testing would be simpler here, but feature + ;; testing gets more brownie points, I guess. + (static-if (condition-case nil + (assoc nil () #'eql) + (wrong-number-of-arguments t)) + (--first (and (consp it) (funcall cmp (car it) key)) alist) (assoc key alist cmp))))))) (defun dash--hash-test-fn () @@ -3298,9 +3323,10 @@ Return the sorted list. LIST is NOT modified by side effects. COMPARATOR is called with two elements of LIST, and should return non-nil if the first element should sort before the second." (declare (important-return-value t)) - ;; Not yet worth changing to (sort list :lessp comparator); - ;; still seems as fast or slightly faster. - (sort (copy-sequence list) comparator)) + (static-if (condition-case nil (sort []) (wrong-number-of-arguments)) + ;; Since Emacs 30. + (sort list :lessp comparator) + (sort (copy-sequence list) comparator))) (defmacro --sort (form list) "Anaphoric form of `-sort'." @@ -3635,7 +3661,13 @@ structure such as plist or alist." ;;; Combinators -(defalias '-partial #'apply-partially) +(defalias '-partial #'apply-partially + "Return a function that is a partial application of FUN to ARGS. +ARGS is a list of the first N arguments to pass to FUN. +The result is a new function which does the same as FUN, except that +the first N arguments are fixed at the values with which this function +was called. +\n(fn FUN &rest ARGS)") (defun -rpartial (fn &rest args) "Return a function that is a partial application of FN to ARGS. @@ -3801,11 +3833,9 @@ See also: `-orfn' and `-not'." ;; Open-code for speed. (cond ((cdr preds) (lambda (&rest args) (--every (apply it args) preds))) (preds (car preds)) - ;; As a `pure' function, this runtime check may generate - ;; backward-incompatible bytecode for `(-andfn)' at compile-time, - ;; but I doubt that's a problem in practice (famous last words). - ((fboundp 'always) #'always) - ((lambda (&rest _) t)))) + ((static-if (fboundp 'always) + #'always + (lambda (&rest _) t))))) (defun -iteratefn (fn n) "Return a function FN composed N times with itself. @@ -3925,13 +3955,13 @@ This function satisfies the following laws: `(;; TODO: Do not fontify the following automatic variables ;; globally; detect and limit to their local anaphoric scope. (,(rx symbol-start (| "acc" "it" "it-index" "other") symbol-end) - 0 font-lock-variable-name-face) + . 'font-lock-variable-name-face) ;; Macros in dev/examples.el. Based on `lisp-mode-symbol-regexp'. (,(rx ?\( (group (| "defexamples" "def-example-group")) symbol-end (+ (in "\t ")) (group (* (| (syntax word) (syntax symbol) (: ?\\ nonl))))) - (1 font-lock-keyword-face) - (2 font-lock-function-name-face)) + (1 'font-lock-keyword-face) + (2 'font-lock-function-name-face)) ;; Symbols in dev/examples.el. ,(rx symbol-start (| "=>" "~>" "!!>") symbol-end) ;; Elisp macro fontification was static prior to Emacs 25. @@ -4067,15 +4097,14 @@ See also `dash-fontify-mode-lighter' and (if dash-fontify-mode (font-lock-add-keywords nil dash--keywords t) (font-lock-remove-keywords nil dash--keywords)) - (cond ((fboundp 'font-lock-flush) ;; Added in Emacs 25. - (font-lock-flush)) - ;; `font-lock-fontify-buffer' unconditionally enables - ;; `font-lock-mode' and is marked `interactive-only' in later - ;; Emacs versions which have `font-lock-flush', so we guard - ;; and pacify as needed, respectively. - (font-lock-mode - (with-no-warnings - (font-lock-fontify-buffer))))) + (static-if (fboundp 'font-lock-flush) + ;; Added in Emacs 25. + (font-lock-flush) + (when font-lock-mode + ;; Unconditionally enables `font-lock-mode' and is marked + ;; `interactive-only' in later Emacs versions which have + ;; `font-lock-flush'. + (font-lock-fontify-buffer)))) (defun dash--turn-on-fontify-mode () "Enable `dash-fontify-mode' if in an Emacs Lisp buffer." diff --git a/lisp/dash/dash.info b/lisp/dash/dash.info index 5caf7dde..c87eccf1 100644 --- a/lisp/dash/dash.info +++ b/lisp/dash/dash.info @@ -1,8 +1,8 @@ This is dash.info, produced by makeinfo version 7.1.1 from dash.texi. -This manual is for Dash version 2.19.1. +This manual is for Dash version 2.20.0. - Copyright © 2012-2024 Free Software Foundation, Inc. + Copyright © 2012-2025 Free Software Foundation, Inc. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, @@ -22,9 +22,9 @@ File: dash.info, Node: Top, Next: Installation, Up: (dir) Dash **** -This manual is for Dash version 2.19.1. +This manual is for Dash version 2.20.0. - Copyright © 2012-2024 Free Software Foundation, Inc. + Copyright © 2012-2025 Free Software Foundation, Inc. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, @@ -110,7 +110,7 @@ File: dash.info, Node: Using in a package, Next: Fontification of special vari If you use Dash in your own package, be sure to list it as a dependency in the library's headers as follows (*note (elisp)Library Headers::). - ;; Package-Requires: ((dash "2.19.1")) + ;; Package-Requires: ((dash "2.20.0"))  File: dash.info, Node: Fontification of special variables, Next: Info symbol lookup, Prev: Using in a package, Up: Installation @@ -353,7 +353,8 @@ The results are collected in order and returned as a new list. ⇒ (0 1 0 2 0 3) -- Function: -copy (list) - Create a shallow copy of LIST. + Create a shallow copy of LIST. The elements of LIST are not + copied; they are shared with the original. (-copy '(1 2 3)) ⇒ (1 2 3) @@ -639,12 +640,17 @@ Functions returning a modified copy of the input list. ⇒ (40 50 60) -- Function: -concat (&rest sequences) - Concatenate all the arguments and make the result a list. The - result is a list whose elements are the elements of all the - arguments. Each argument may be a list, vector or string. + Concatenate all SEQUENCES and make the result a list. The result + is a list whose elements are the elements of all the arguments. + Each argument may be a list, vector or string. All arguments except the last argument are copied. The last - argument is just used as the tail of the new list. + argument is just used as the tail of the new list. If the last + argument is not a list, this results in a dotted list. + + As an exception, if all the arguments except the last are ‘nil’, + and the last argument is not a list, the return value is that last + argument unaltered, not a list. (-concat '(1)) ⇒ (1) @@ -4550,8 +4556,8 @@ Index (line 445) * -fixfn: Function combinators. (line 224) -* -flatten: List to list. (line 38) -* -flatten-n: List to list. (line 60) +* -flatten: List to list. (line 43) +* -flatten-n: List to list. (line 65) * -flip: Function combinators. (line 95) * -fourth-item: Other list operations. @@ -4563,7 +4569,7 @@ Index * -if-let: Binding. (line 34) * -if-let*: Binding. (line 45) * -inits: Reductions. (line 222) -* -insert-at: List to list. (line 114) +* -insert-at: List to list. (line 119) * -interleave: Other list operations. (line 56) * -interpose: Other list operations. @@ -4636,16 +4642,16 @@ Index * -reductions-r: Reductions. (line 154) * -reductions-r-from: Reductions. (line 118) * -remove: Sublist selection. (line 26) -* -remove-at: List to list. (line 151) -* -remove-at-indices: List to list. (line 170) +* -remove-at: List to list. (line 156) +* -remove-at-indices: List to list. (line 175) * -remove-first: Sublist selection. (line 44) * -remove-item: Sublist selection. (line 84) * -remove-last: Sublist selection. (line 65) * -repeat: Unfolding. (line 44) -* -replace: List to list. (line 72) -* -replace-at: List to list. (line 125) -* -replace-first: List to list. (line 86) -* -replace-last: List to list. (line 100) +* -replace: List to list. (line 77) +* -replace-at: List to list. (line 130) +* -replace-first: List to list. (line 91) +* -replace-last: List to list. (line 105) * -rotate: Other list operations. (line 8) * -rotate-args: Function combinators. @@ -4701,7 +4707,7 @@ Index (line 215) * -unzip-lists: Other list operations. (line 196) -* -update-at: List to list. (line 137) +* -update-at: List to list. (line 142) * -when-let: Binding. (line 9) * -when-let*: Binding. (line 21) * -zip: Other list operations. @@ -4746,199 +4752,199 @@ Ref: -splice10052 Ref: -splice-list11125 Ref: -mapcat11584 Ref: -copy11957 -Node: Sublist selection12145 -Ref: -filter12338 -Ref: -remove12889 -Ref: -remove-first13436 -Ref: -remove-last14280 -Ref: -remove-item15008 -Ref: -non-nil15408 -Ref: -slice15690 -Ref: -take16219 -Ref: -take-last16637 -Ref: -drop17074 -Ref: -drop-last17521 -Ref: -take-while17953 -Ref: -drop-while18578 -Ref: -select-by-indices19209 -Ref: -select-columns19716 -Ref: -select-column20419 -Node: List to list20882 -Ref: -keep21074 -Ref: -concat21650 -Ref: -flatten22178 -Ref: -flatten-n22938 -Ref: -replace23322 -Ref: -replace-first23783 -Ref: -replace-last24278 -Ref: -insert-at24766 -Ref: -replace-at25091 -Ref: -update-at25478 -Ref: -remove-at26019 -Ref: -remove-at-indices26646 -Node: Reductions27336 -Ref: -reduce-from27532 -Ref: -reduce-r-from28254 -Ref: -reduce29515 -Ref: -reduce-r30264 -Ref: -reductions-from31540 -Ref: -reductions-r-from32342 -Ref: -reductions33168 -Ref: -reductions-r33875 -Ref: -count34616 -Ref: -sum34846 -Ref: -running-sum35034 -Ref: -product35355 -Ref: -running-product35563 -Ref: -inits35904 -Ref: -tails36149 -Ref: -common-prefix36394 -Ref: -common-suffix36688 -Ref: -min36982 -Ref: -min-by37208 -Ref: -max37729 -Ref: -max-by37954 -Ref: -frequencies38480 -Node: Unfolding39095 -Ref: -iterate39336 -Ref: -unfold39783 -Ref: -repeat40588 -Ref: -cycle40872 -Node: Predicates41269 -Ref: -some41446 -Ref: -every41873 -Ref: -any?42585 -Ref: -all?42934 -Ref: -none?43674 -Ref: -only-some?43994 -Ref: -contains?44539 -Ref: -is-prefix?45045 -Ref: -is-suffix?45377 -Ref: -is-infix?45709 -Ref: -cons-pair?46069 -Node: Partitioning46400 -Ref: -split-at46588 -Ref: -split-with47252 -Ref: -split-on47892 -Ref: -split-when48563 -Ref: -separate49206 -Ref: -partition49740 -Ref: -partition-all50189 -Ref: -partition-in-steps50614 -Ref: -partition-all-in-steps51160 -Ref: -partition-by51674 -Ref: -partition-by-header52052 -Ref: -partition-after-pred52653 -Ref: -partition-before-pred53104 -Ref: -partition-before-item53489 -Ref: -partition-after-item53796 -Ref: -group-by54098 -Node: Indexing54531 -Ref: -elem-index54733 -Ref: -elem-indices55220 -Ref: -find-index55679 -Ref: -find-last-index56346 -Ref: -find-indices56995 -Ref: -grade-up57755 -Ref: -grade-down58162 -Node: Set operations58576 -Ref: -union58759 -Ref: -difference59189 -Ref: -intersection59617 -Ref: -powerset60046 -Ref: -permutations60323 -Ref: -distinct60761 -Ref: -same-items?61155 -Node: Other list operations61764 -Ref: -rotate61989 -Ref: -cons*62342 -Ref: -snoc62764 -Ref: -interpose63176 -Ref: -interleave63470 -Ref: -iota63836 -Ref: -zip-with64319 -Ref: -zip-pair65125 -Ref: -zip-lists65691 -Ref: -zip-lists-fill66489 -Ref: -zip67199 -Ref: -zip-fill68226 -Ref: -unzip-lists69140 -Ref: -unzip69763 -Ref: -pad70756 -Ref: -table71241 -Ref: -table-flat72027 -Ref: -first73030 -Ref: -last73561 -Ref: -first-item73907 -Ref: -second-item74319 -Ref: -third-item74736 -Ref: -fourth-item75111 -Ref: -fifth-item75489 -Ref: -last-item75864 -Ref: -butlast76225 -Ref: -sort76470 -Ref: -list76964 -Ref: -fix77533 -Node: Tree operations78022 -Ref: -tree-seq78218 -Ref: -tree-map79079 -Ref: -tree-map-nodes79519 -Ref: -tree-reduce80383 -Ref: -tree-reduce-from81265 -Ref: -tree-mapreduce81865 -Ref: -tree-mapreduce-from82724 -Ref: -clone84009 -Node: Threading macros84347 -Ref: ->84572 -Ref: ->>85060 -Ref: -->85563 -Ref: -as->86120 -Ref: -some->86574 -Ref: -some->>86959 -Ref: -some-->87406 -Ref: -doto87973 -Node: Binding88526 -Ref: -when-let88733 -Ref: -when-let*89194 -Ref: -if-let89723 -Ref: -if-let*90089 -Ref: -let90712 -Ref: -let*96788 -Ref: -lambda97725 -Ref: -setq98531 -Node: Side effects99332 -Ref: -each99526 -Ref: -each-while100051 -Ref: -each-indexed100671 -Ref: -each-r101263 -Ref: -each-r-while101705 -Ref: -dotimes102349 -Node: Destructive operations102900 -Ref: !cons103118 -Ref: !cdr103322 -Node: Function combinators103515 -Ref: -partial103719 -Ref: -rpartial104237 -Ref: -juxt104885 -Ref: -compose105337 -Ref: -applify105944 -Ref: -on106374 -Ref: -flip107138 -Ref: -rotate-args107660 -Ref: -const108289 -Ref: -cut108631 -Ref: -not109111 -Ref: -orfn109655 -Ref: -andfn110448 -Ref: -iteratefn111235 -Ref: -fixfn111937 -Ref: -prodfn113511 -Node: Development114638 -Node: Contribute114927 -Node: Contributors115935 -Node: FDL118028 -Node: GPL143147 -Node: Index180693 +Node: Sublist selection12223 +Ref: -filter12416 +Ref: -remove12967 +Ref: -remove-first13514 +Ref: -remove-last14358 +Ref: -remove-item15086 +Ref: -non-nil15486 +Ref: -slice15768 +Ref: -take16297 +Ref: -take-last16715 +Ref: -drop17152 +Ref: -drop-last17599 +Ref: -take-while18031 +Ref: -drop-while18656 +Ref: -select-by-indices19287 +Ref: -select-columns19794 +Ref: -select-column20497 +Node: List to list20960 +Ref: -keep21152 +Ref: -concat21728 +Ref: -flatten22508 +Ref: -flatten-n23268 +Ref: -replace23652 +Ref: -replace-first24113 +Ref: -replace-last24608 +Ref: -insert-at25096 +Ref: -replace-at25421 +Ref: -update-at25808 +Ref: -remove-at26349 +Ref: -remove-at-indices26976 +Node: Reductions27666 +Ref: -reduce-from27862 +Ref: -reduce-r-from28584 +Ref: -reduce29845 +Ref: -reduce-r30594 +Ref: -reductions-from31870 +Ref: -reductions-r-from32672 +Ref: -reductions33498 +Ref: -reductions-r34205 +Ref: -count34946 +Ref: -sum35176 +Ref: -running-sum35364 +Ref: -product35685 +Ref: -running-product35893 +Ref: -inits36234 +Ref: -tails36479 +Ref: -common-prefix36724 +Ref: -common-suffix37018 +Ref: -min37312 +Ref: -min-by37538 +Ref: -max38059 +Ref: -max-by38284 +Ref: -frequencies38810 +Node: Unfolding39425 +Ref: -iterate39666 +Ref: -unfold40113 +Ref: -repeat40918 +Ref: -cycle41202 +Node: Predicates41599 +Ref: -some41776 +Ref: -every42203 +Ref: -any?42915 +Ref: -all?43264 +Ref: -none?44004 +Ref: -only-some?44324 +Ref: -contains?44869 +Ref: -is-prefix?45375 +Ref: -is-suffix?45707 +Ref: -is-infix?46039 +Ref: -cons-pair?46399 +Node: Partitioning46730 +Ref: -split-at46918 +Ref: -split-with47582 +Ref: -split-on48222 +Ref: -split-when48893 +Ref: -separate49536 +Ref: -partition50070 +Ref: -partition-all50519 +Ref: -partition-in-steps50944 +Ref: -partition-all-in-steps51490 +Ref: -partition-by52004 +Ref: -partition-by-header52382 +Ref: -partition-after-pred52983 +Ref: -partition-before-pred53434 +Ref: -partition-before-item53819 +Ref: -partition-after-item54126 +Ref: -group-by54428 +Node: Indexing54861 +Ref: -elem-index55063 +Ref: -elem-indices55550 +Ref: -find-index56009 +Ref: -find-last-index56676 +Ref: -find-indices57325 +Ref: -grade-up58085 +Ref: -grade-down58492 +Node: Set operations58906 +Ref: -union59089 +Ref: -difference59519 +Ref: -intersection59947 +Ref: -powerset60376 +Ref: -permutations60653 +Ref: -distinct61091 +Ref: -same-items?61485 +Node: Other list operations62094 +Ref: -rotate62319 +Ref: -cons*62672 +Ref: -snoc63094 +Ref: -interpose63506 +Ref: -interleave63800 +Ref: -iota64166 +Ref: -zip-with64649 +Ref: -zip-pair65455 +Ref: -zip-lists66021 +Ref: -zip-lists-fill66819 +Ref: -zip67529 +Ref: -zip-fill68556 +Ref: -unzip-lists69470 +Ref: -unzip70093 +Ref: -pad71086 +Ref: -table71571 +Ref: -table-flat72357 +Ref: -first73360 +Ref: -last73891 +Ref: -first-item74237 +Ref: -second-item74649 +Ref: -third-item75066 +Ref: -fourth-item75441 +Ref: -fifth-item75819 +Ref: -last-item76194 +Ref: -butlast76555 +Ref: -sort76800 +Ref: -list77294 +Ref: -fix77863 +Node: Tree operations78352 +Ref: -tree-seq78548 +Ref: -tree-map79409 +Ref: -tree-map-nodes79849 +Ref: -tree-reduce80713 +Ref: -tree-reduce-from81595 +Ref: -tree-mapreduce82195 +Ref: -tree-mapreduce-from83054 +Ref: -clone84339 +Node: Threading macros84677 +Ref: ->84902 +Ref: ->>85390 +Ref: -->85893 +Ref: -as->86450 +Ref: -some->86904 +Ref: -some->>87289 +Ref: -some-->87736 +Ref: -doto88303 +Node: Binding88856 +Ref: -when-let89063 +Ref: -when-let*89524 +Ref: -if-let90053 +Ref: -if-let*90419 +Ref: -let91042 +Ref: -let*97118 +Ref: -lambda98055 +Ref: -setq98861 +Node: Side effects99662 +Ref: -each99856 +Ref: -each-while100381 +Ref: -each-indexed101001 +Ref: -each-r101593 +Ref: -each-r-while102035 +Ref: -dotimes102679 +Node: Destructive operations103230 +Ref: !cons103448 +Ref: !cdr103652 +Node: Function combinators103845 +Ref: -partial104049 +Ref: -rpartial104567 +Ref: -juxt105215 +Ref: -compose105667 +Ref: -applify106274 +Ref: -on106704 +Ref: -flip107468 +Ref: -rotate-args107990 +Ref: -const108619 +Ref: -cut108961 +Ref: -not109441 +Ref: -orfn109985 +Ref: -andfn110778 +Ref: -iteratefn111565 +Ref: -fixfn112267 +Ref: -prodfn113841 +Node: Development114968 +Node: Contribute115257 +Node: Contributors116265 +Node: FDL118358 +Node: GPL143477 +Node: Index181023  End Tag Table diff --git a/lisp/dashboard/dashboard-pkg.el b/lisp/dashboard/dashboard-pkg.el index 8b4cc18d..bf3703b1 100644 --- a/lisp/dashboard/dashboard-pkg.el +++ b/lisp/dashboard/dashboard-pkg.el @@ -1,15 +1,11 @@ -(define-package "dashboard" "20250227.121" "A startup screen extracted from Spacemacs" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "dashboard" "20250521.900" + "A startup screen extracted from Spacemacs." '((emacs "27.1")) - :commit "9616e5b5e793c3d8228a8fccf7b9ef7ace365005" :authors - '(("Rakan Al-Hneiti" . "rakan.alhneiti@gmail.com")) - :maintainers - '(("Jen-Chieh" . "jcs090218@gmail.com") - ("Ricardo Arredondo" . "ricardo.richo@gmail.com")) - :maintainer - '("Jen-Chieh" . "jcs090218@gmail.com") - :keywords - '("startup" "screen" "tools" "dashboard") - :url "https://github.com/emacs-dashboard/emacs-dashboard") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/emacs-dashboard/emacs-dashboard" + :commit "f07661b39bec3683cf9edb7b1c58f6e658b6f764" + :revdesc "f07661b39bec" + :keywords '("startup" "screen" "tools" "dashboard") + :authors '(("Rakan Al-Hneiti" . "rakan.alhneiti@gmail.com")) + :maintainers '(("Jen-Chieh" . "jcs090218@gmail.com") + ("Ricardo Arredondo" . "ricardo.richo@gmail.com"))) diff --git a/lisp/dashboard/dashboard-widgets.el b/lisp/dashboard/dashboard-widgets.el index a7865bf6..b25e78e8 100644 --- a/lisp/dashboard/dashboard-widgets.el +++ b/lisp/dashboard/dashboard-widgets.el @@ -135,13 +135,6 @@ See `create-image' and Info node `(elisp)Image Descriptors'." (make-obsolete-variable 'dashboard-set-navigator 'dashboard-startupify-list "1.9.0") -(defcustom dashboard-set-init-info t - "When non nil, init info will be displayed under the banner." - :type 'boolean - :group 'dashboard) -(make-obsolete-variable 'dashboard-set-init-info - 'dashboard-startupify-list "1.9.0") - (defcustom dashboard-set-footer t "When non nil, a footer will be displayed at the bottom." :type 'boolean @@ -159,7 +152,7 @@ See `create-image' and Info node `(elisp)Image Descriptors'." "While any text editor can save your files, only Emacs can save your soul" "I showed you my source code, pls respond") "A list of messages, one of which dashboard chooses to display." - :type '(list string) + :type '(repeat string) :group 'dashboard) (defcustom dashboard-icon-type (and (or dashboard-set-heading-icons @@ -194,10 +187,14 @@ The value can be one of: `all-the-icons', `nerd-icons'." (projects . "nf-oct-rocket") (registers . "nf-oct-database")))) "Association list for the icons of the heading sections. -Will be of the form `(list-type . icon-name-string)`. -If nil it is disabled. Possible values for list-type are: -`recents' `bookmarks' `projects' `agenda' `registers'" - :type '(alist :key-type symbol :value-type string) +Will be of the form `(SECTION . ICON)`, where SECTION could be any dashboard +section, for example: `recents' `bookmarks' `projects' `agenda' `registers'. + +ICON could be the name of the icon belonging to `octicon' family +or (ICON-FUNCTION ICON-NAME), for example: \"nf-oct-file\" using +nerd-icons or (all-the-icons-faicon \"newspaper-o\") using all-the-icons." + :type '(alist :key-type symbol + :value-type (choice string (cons function string))) :group 'dashboard) (defcustom dashboard-heading-icon-height 1.2 @@ -288,24 +285,45 @@ Example: (const nil))))) :group 'dashboard) -(defcustom dashboard-init-info - (lambda () - (let ((package-count 0) (time (emacs-init-time))) - (when (bound-and-true-p package-alist) - (setq package-count (length package-activated-list))) - (when (boundp 'straight--profile-cache) - (setq package-count (+ (hash-table-count straight--profile-cache) package-count))) - (when (fboundp 'elpaca--queued) - (setq time (format "%f seconds" (float-time (time-subtract elpaca-after-init-time - before-init-time)))) - (setq package-count (length (elpaca--queued)))) - (if (zerop package-count) - (format "Emacs started in %s" time) - (format "%d packages loaded in %s" package-count time)))) - "Init info with packages loaded and init time." - :type '(function string) +(defcustom dashboard-init-info #'dashboard-init--info + "Custom function that must return a string to place instead of init-info." + :type 'function :group 'dashboard) +(defun dashboard-init--time () + "Return Emacs starting time in string including seconds ending." + (if (fboundp 'elpaca--queued) + (format "%s seconds" + (float-time (time-subtract elpaca-after-init-time + before-init-time))) + (emacs-init-time))) + +(defun dashboard-init--packages-count () + "Get the intalled package count depending on package manager. +Supported package managers are: package.el, straight.el and elpaca.el." + (let* ((package-count (if (bound-and-true-p package-alist) + (length package-activated-list) + 0)) + (straight-count (if (boundp 'straight--profile-cache) + (hash-table-count straight--profile-cache) + 0)) + (elpaca-count (if (fboundp 'elpaca--queued) + (length (elpaca--queued)) + 0))) + (+ package-count straight-count elpaca-count))) + + +(defun dashboard-init--info () + "Format init message. +Use `dashboard-init--time' and `dashboard-init--package-count' to generate +init message." + (let ((init-time (dashboard-init--time)) + (packages-count (dashboard-init--packages-count))) + (if (zerop packages-count) + (format "Emacs started in %s" init-time) + (format "%d packages installed. Emacs started in %s." + packages-count init-time)))) + (defcustom dashboard-display-icons-p #'display-graphic-p "Predicate to determine whether dashboard should show icons. Can be nil to not show icons and any truthy value to show them. When set to a @@ -653,30 +671,8 @@ When called with TIMES return a function that insert TIMES number of newlines." (defun dashboard-insert-heading (heading &optional shortcut icon) "Insert a widget HEADING in dashboard buffer, adding SHORTCUT, ICON if provided." - (when (and (dashboard-display-icons-p) dashboard-set-heading-icons) - (let ((args `( :height ,dashboard-heading-icon-height - :v-adjust ,dashboard-heading-icon-v-adjust - :face dashboard-heading))) - (insert - (pcase heading - ("Recent Files:" - (apply #'dashboard-octicon (cdr (assoc 'recents dashboard-heading-icons)) args)) - ("Bookmarks:" - (apply #'dashboard-octicon (cdr (assoc 'bookmarks dashboard-heading-icons)) args)) - ((or "Agenda for today:" - "Agenda for the coming week:") - (apply #'dashboard-octicon (cdr (assoc 'agenda dashboard-heading-icons)) args)) - ("Registers:" - (apply #'dashboard-octicon (cdr (assoc 'registers dashboard-heading-icons)) args)) - ("Projects:" - (apply #'dashboard-octicon (cdr (assoc 'projects dashboard-heading-icons)) args)) - ("List Directories:" - (apply #'dashboard-octicon (cdr (assoc 'ls-directories dashboard-heading-icons)) args)) - ("List Files:" - (apply #'dashboard-octicon (cdr (assoc 'ls-files dashboard-heading-icons)) args)) - (_ - (if (null icon) " " icon)))) - (insert " "))) + (when (and (dashboard-display-icons-p) dashboard-set-heading-icons icon) + (insert icon " ")) (insert (propertize heading 'face 'dashboard-heading)) @@ -876,10 +872,15 @@ Argument IMAGE-PATH path to the image." ;;; Initialize info (defun dashboard-insert-init-info () "Insert init info." - (let ((init-info (if (functionp dashboard-init-info) - (funcall dashboard-init-info) - dashboard-init-info))) - (dashboard-insert-center (propertize init-info 'face 'font-lock-comment-face)))) + (let ((init-info (cond ((stringp dashboard-init-info) + dashboard-init-info) + ((functionp dashboard-init-info) + (funcall dashboard-init-info)) + (t + (user-error "Unknown init info type (%s): %s" + (type-of dashboard-init-info) dashboard-init-info))))) + (dashboard-insert-center + (propertize init-info 'face 'font-lock-comment-face)))) (defun dashboard-insert-navigator () "Insert Navigator of the dashboard." @@ -930,7 +931,8 @@ WIDGET-PARAMS are passed to the \"widget-create\" function." (when (and ,list ,shortcut-char dashboard-show-shortcuts) - ,shortcut-char)) + ,shortcut-char) + (dashboard-heading-icon ,shortcut-id)) (if ,list (when (and (dashboard-insert-section-list ,section-name @@ -941,6 +943,19 @@ WIDGET-PARAMS are passed to the \"widget-create\" function." (dashboard-insert-shortcut ,shortcut-id ,shortcut-char ,section-name)) (insert (propertize "\n --- No items ---" 'face 'dashboard-no-items-face))))) +(defun dashboard-heading-icon (section) + "Get the icon for SECTION from `dashboard-heading-icons'. +Return a space if icon is not found." + (let ((args (list :height dashboard-heading-icon-height + :v-adjust dashboard-heading-icon-v-adjust + :face 'dashboard-heading)) + (icon (assoc section dashboard-heading-icons))) + (if icon (cond + ((stringp (cdr icon)) (apply #'dashboard-octicon (cdr icon) args)) + ((listp (cdr icon)) (apply (cadr icon) (caddr icon) args)) + (t (error "Bad value %s in `dashboard-heading-icons'" icon))) + " "))) + ;; ;;; Section list diff --git a/lisp/dashboard/dashboard.el b/lisp/dashboard/dashboard.el index 2d6cb759..5cbd7a77 100644 --- a/lisp/dashboard/dashboard.el +++ b/lisp/dashboard/dashboard.el @@ -12,7 +12,8 @@ ;;; License: GPLv3 ;; ;; Created: October 05, 2016 -;; Package-Version: 1.9.0-SNAPSHOT +;; Package-Version: 20250521.900 +;; Package-Revision: f07661b39bec ;; Keywords: startup, screen, tools, dashboard ;; Package-Requires: ((emacs "27.1")) diff --git a/lisp/deft/deft-pkg.el b/lisp/deft/deft-pkg.el index 7c2bbe2a..84da58ea 100644 --- a/lisp/deft/deft-pkg.el +++ b/lisp/deft/deft-pkg.el @@ -1,12 +1,10 @@ -(define-package "deft" "20240524.1524" "quickly browse, filter, and edit plain text notes" 'nil :commit "b369d7225d86551882568788a23c5497b232509c" :authors - '(("Jason R. Blevins" . "jrblevin@xbeta.org")) - :maintainers - '(("Jason R. Blevins" . "jrblevin@xbeta.org")) - :maintainer - '("Jason R. Blevins" . "jrblevin@xbeta.org") - :keywords - '("plain text" "notes" "simplenote" "notational velocity") - :url "https://jblevins.org/projects/deft/") -;; Local Variables: -;; no-byte-compile: t -;; End: +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "deft" "20240524.1524" + "Quickly browse, filter, and edit plain text notes." + () + :url "https://jblevins.org/projects/deft/" + :commit "b369d7225d86551882568788a23c5497b232509c" + :revdesc "b369d7225d86" + :keywords '("plain text" "notes" "simplenote" "notational velocity") + :authors '(("Jason R. Blevins" . "jrblevin@xbeta.org")) + :maintainers '(("Jason R. Blevins" . "jrblevin@xbeta.org"))) diff --git a/lisp/deft/deft.el b/lisp/deft/deft.el index 1d32e8f0..9a86311b 100644 --- a/lisp/deft/deft.el +++ b/lisp/deft/deft.el @@ -26,7 +26,8 @@ ;; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ;; POSSIBILITY OF SUCH DAMAGE. -;;; Version: 0.8 +;; Package-Version: 20240524.1524 +;; Package-Revision: b369d7225d86 ;;; Author: Jason R. Blevins ;;; Keywords: plain text, notes, Simplenote, Notational Velocity ;;; URL: https://jblevins.org/projects/deft/ diff --git a/lisp/diff-hl/diff-hl-inline-popup.el b/lisp/diff-hl/diff-hl-inline-popup.el index 48a6f991..0f202aff 100644 --- a/lisp/diff-hl/diff-hl-inline-popup.el +++ b/lisp/diff-hl/diff-hl-inline-popup.el @@ -154,7 +154,8 @@ FOOTER are showed at start and end." diff-hl-inline-popup--current-footer))) ;; https://debbugs.gnu.org/38563, `company--replacement-string'. (add-face-text-property 0 (length str) 'default t str) - (overlay-put diff-hl-inline-popup--current-popup 'after-string str)))) + (put-text-property 0 1 'cursor 0 str) + (overlay-put diff-hl-inline-popup--current-popup 'before-string str)))) (defun diff-hl-inline-popup--popup-down() "Scrolls one line down." diff --git a/lisp/diff-hl/diff-hl-margin.el b/lisp/diff-hl/diff-hl-margin.el index c3fffde1..3f142a2c 100644 --- a/lisp/diff-hl/diff-hl-margin.el +++ b/lisp/diff-hl/diff-hl-margin.el @@ -1,6 +1,6 @@ ;;; diff-hl-margin.el --- Highlight buffer changes on margins -*- lexical-binding: t -*- -;; Copyright (C) 2012-2017 Free Software Foundation, Inc. +;; Copyright (C) 2012-2025 Free Software Foundation, Inc. ;; This file is part of GNU Emacs. @@ -147,7 +147,15 @@ You probably shouldn't use this function directly." ,(propertize char 'face (intern (format "diff-hl-margin-%s" type))))))))) +(defun diff-hl-margin-ensure-visible () + (let ((width-var (intern (format "%s-margin-width" diff-hl-side)))) + (when (zerop (symbol-value width-var)) + (set width-var 1) + (dolist (win (get-buffer-window-list)) + (set-window-buffer win (current-buffer)))))) + (defun diff-hl-highlight-on-margin (ovl type _shape) + (diff-hl-margin-ensure-visible) (let ((spec (cdr (assoc (cons type diff-hl-side) (diff-hl-margin-spec-cache))))) (overlay-put ovl 'before-string spec))) diff --git a/lisp/diff-hl/diff-hl-pkg.el b/lisp/diff-hl/diff-hl-pkg.el index c368d451..40c821da 100644 --- a/lisp/diff-hl/diff-hl-pkg.el +++ b/lisp/diff-hl/diff-hl-pkg.el @@ -1,15 +1,11 @@ -(define-package "diff-hl" "20250223.2320" "Highlight uncommitted changes using VC" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "diff-hl" "20250613.2144" + "Highlight uncommitted changes using VC." '((cl-lib "0.2") - (emacs "25.1")) - :commit "685e99135001da13caecdff71acea1ee20bed373" :authors - '(("Dmitry Gutov" . "dmitry@gutov.dev")) - :maintainers - '(("Dmitry Gutov" . "dmitry@gutov.dev")) - :maintainer - '("Dmitry Gutov" . "dmitry@gutov.dev") - :keywords - '("vc" "diff") - :url "https://github.com/dgutov/diff-hl") -;; Local Variables: -;; no-byte-compile: t -;; End: + (emacs "26.1")) + :url "https://github.com/dgutov/diff-hl" + :commit "830b05253ba8f35b80448e5de2201aecb6943840" + :revdesc "830b05253ba8" + :keywords '("vc" "diff") + :authors '(("Dmitry Gutov" . "dmitry@gutov.dev")) + :maintainers '(("Dmitry Gutov" . "dmitry@gutov.dev"))) diff --git a/lisp/diff-hl/diff-hl-show-hunk-posframe.el b/lisp/diff-hl/diff-hl-show-hunk-posframe.el index 735fcd5e..48ea54b4 100644 --- a/lisp/diff-hl/diff-hl-show-hunk-posframe.el +++ b/lisp/diff-hl/diff-hl-show-hunk-posframe.el @@ -76,15 +76,7 @@ Customize it to change the base properties of the text.") (interactive) (diff-hl-show-hunk-posframe--transient-mode -1) (when (frame-live-p diff-hl-show-hunk--frame) - (make-frame-invisible diff-hl-show-hunk--frame)) - (when diff-hl-show-hunk--original-frame - (when (frame-live-p diff-hl-show-hunk--original-frame) - (let ((frame diff-hl-show-hunk--original-frame)) - (select-frame-set-input-focus frame) - ;; In Gnome, sometimes the input focus is not restored to the - ;; original frame, so we try harder in a while - (run-with-timer 0.1 nil (lambda () (select-frame-set-input-focus frame))))) - (setq diff-hl-show-hunk--original-frame nil))) + (make-frame-invisible diff-hl-show-hunk--frame))) (defvar diff-hl-show-hunk-posframe--transient-mode-map (let ((map (make-sparse-keymap))) @@ -179,7 +171,6 @@ The button calls an ACTION." (user-error "Package `posframe' is not workable. Please customize diff-hl-show-hunk-function")) - (diff-hl-show-hunk--posframe-hide) (setq diff-hl-show-hunk--hide-function #'diff-hl-show-hunk--posframe-hide) ;; put an overlay to override read-only-mode keymap @@ -192,10 +183,14 @@ The button calls an ACTION." 'keymap diff-hl-show-hunk-posframe--transient-mode-map))) (setq posframe-mouse-banish nil) - (setq diff-hl-show-hunk--original-frame last-event-frame) + (setq diff-hl-show-hunk--original-frame (selected-frame)) - (let* ((hunk-overlay diff-hl-show-hunk--original-overlay) - (position (overlay-end hunk-overlay))) + (let* ((overlay diff-hl-show-hunk--original-overlay) + (type (overlay-get overlay 'diff-hl-hunk-type)) + (position (save-excursion + (goto-char (overlay-end overlay)) + (forward-line -1) + (point)))) (setq diff-hl-show-hunk--frame (posframe-show buffer @@ -207,12 +202,12 @@ The button calls an ACTION." :internal-border-color diff-hl-show-hunk-posframe-internal-border-color :hidehandler nil ;; Sometimes, header-line is not taken into account, so put a min height and a min width - :min-height (when diff-hl-show-hunk-posframe-show-header-line 10) :min-width (when diff-hl-show-hunk-posframe-show-header-line (length (diff-hl-show-hunk-posframe--header-line))) :respect-header-line diff-hl-show-hunk-posframe-show-header-line :respect-tab-line nil :respect-mode-line nil + :y-pixel-offset (if (eq type 'delete) (- (default-line-height))) :override-parameters diff-hl-show-hunk-posframe-parameters))) (set-frame-parameter diff-hl-show-hunk--frame 'drag-internal-border t) @@ -231,8 +226,7 @@ The button calls an ACTION." (setq cursor-type 'box) ;; Recenter around point - (recenter))) - (select-frame-set-input-focus diff-hl-show-hunk--frame)) + (recenter)))) (provide 'diff-hl-show-hunk-posframe) ;;; diff-hl-show-hunk-posframe.el ends here diff --git a/lisp/diff-hl/diff-hl-show-hunk.el b/lisp/diff-hl/diff-hl-show-hunk.el index 3e82e102..45f201c9 100644 --- a/lisp/diff-hl/diff-hl-show-hunk.el +++ b/lisp/diff-hl/diff-hl-show-hunk.el @@ -132,6 +132,7 @@ point in that buffer to the corresponding line of the original buffer." (defvar vc-sentinel-movepoint) (let* ((buffer (or (buffer-base-buffer) (current-buffer))) + (diff-hl-update-async nil) (line (line-number-at-pos)) (dest-buffer diff-hl-show-hunk-diff-buffer-name)) (with-current-buffer buffer @@ -338,7 +339,8 @@ end of the OVERLAY, so posframe/inline is placed below the hunk." (set-window-start nil (point))) ((> (point) pt) (redisplay)))) - (goto-char (1- (overlay-end overlay))))) + (goto-char (1- (overlay-end overlay))) + (forward-line 0))) ;;;###autoload (defun diff-hl-show-hunk-next () @@ -347,7 +349,8 @@ end of the OVERLAY, so posframe/inline is placed below the hunk." (let* ((point (if diff-hl-show-hunk--original-overlay (overlay-start diff-hl-show-hunk--original-overlay) nil)) - (next-overlay (diff-hl-show-hunk--next-hunk nil point))) + (next-overlay (diff-hl-show-hunk--next-hunk nil point)) + (inhibit-redisplay t)) (if (not next-overlay) (message "There is no next change") (diff-hl-show-hunk-hide) @@ -361,10 +364,6 @@ end of the OVERLAY, so posframe/inline is placed below the hunk." The backend is determined by `diff-hl-show-hunk-function'." (interactive) - ;; Close any previous hunk - (save-excursion - (diff-hl-show-hunk-hide)) - (unless (vc-backend buffer-file-name) (user-error "The buffer is not under version control")) diff --git a/lisp/diff-hl/diff-hl.el b/lisp/diff-hl/diff-hl.el index 5a2a5df2..8b7749fb 100644 --- a/lisp/diff-hl/diff-hl.el +++ b/lisp/diff-hl/diff-hl.el @@ -1,12 +1,13 @@ ;;; diff-hl.el --- Highlight uncommitted changes using VC -*- lexical-binding: t -*- -;; Copyright (C) 2012-2024 Free Software Foundation, Inc. +;; Copyright (C) 2012-2025 Free Software Foundation, Inc. ;; Author: Dmitry Gutov ;; URL: https://github.com/dgutov/diff-hl ;; Keywords: vc, diff -;; Version: 1.10.0 -;; Package-Requires: ((cl-lib "0.2") (emacs "25.1")) +;; Package-Version: 20250613.2144 +;; Package-Revision: 830b05253ba8 +;; Package-Requires: ((cl-lib "0.2") (emacs "26.1")) ;; This file is part of GNU Emacs. @@ -116,6 +117,20 @@ :group 'diff-hl :type 'boolean) +(defcustom diff-hl-fallback-to-margin t + "Non-nil to use margin instead of fringe on non-graphic displays. + +This resizes the margin to 1 if it's not visible." + :group 'diff-hl + :type 'boolean) + +(defcustom diff-hl-autohide-margin nil + "Non-nil to reset margin width to 0 when no indicators shown. + +When you use it, it's recommended to verify first that other enabled +features don't use margin for their indicators." + :type 'boolean) + (defcustom diff-hl-highlight-function 'diff-hl-highlight-on-fringe "Function to highlight the current line. Its arguments are overlay, change type and position within a hunk." @@ -147,6 +162,12 @@ (set-default var value) (when on (global-diff-hl-mode 1))))) +(defcustom diff-hl-bmp-max-width 16 + "Maximum width of the fringe indicator bitmaps, in pixels. +The bitmap width is decided by comparing this value with the current width +of the fringe. When the fringe is hidden, this value is also used." + :type 'integer) + (defcustom diff-hl-highlight-revert-hunk-function #'diff-hl-revert-narrow-to-hunk "Function to emphasize the current hunk in `diff-hl-revert-hunk'. @@ -230,8 +251,8 @@ It can be a relative expression as well, such as \"HEAD^\" with Git, or (truncate (* (frame-char-height) spacing)) spacing))) (w (min (frame-parameter nil (intern (format "%s-fringe" diff-hl-side))) - 16)) - (_ (when (zerop w) (setq w 16))) + diff-hl-bmp-max-width)) + (_ (when (zerop w) (setq w diff-hl-bmp-max-width))) (middle (make-vector h (expt 2 (1- w)))) (ones (1- (expt 2 w))) (top (copy-sequence middle)) @@ -302,6 +323,7 @@ It can be a relative expression as well, such as \"HEAD^\" with Git, or (defvar vc-svn-diff-switches) (defvar vc-fossil-diff-switches) +(defvar vc-jj-diff-switches) (defmacro diff-hl-with-diff-switches (body) `(let ((vc-git-diff-switches @@ -317,6 +339,7 @@ It can be a relative expression as well, such as \"HEAD^\" with Git, or (vc-hg-diff-switches nil) (vc-svn-diff-switches nil) (vc-fossil-diff-switches '("-c" "0")) + (vc-jj-diff-switches '("--git" "--context=0")) (vc-diff-switches '("-U0")) ,@(when (boundp 'vc-disable-async-diff) '((vc-disable-async-diff t)))) @@ -342,21 +365,24 @@ It can be a relative expression as well, such as \"HEAD^\" with Git, or (if (and (eq backend 'Git) (not diff-hl-reference-revision) (not diff-hl-show-staged-changes)) - (apply #'vc-git-command buffer 1 + (apply #'vc-git-command buffer + (if (diff-hl--use-async-p) 'async 1) (list file) "diff-files" (cons "-p" (vc-switches 'git 'diff))) (condition-case err (vc-call-backend backend 'diff (list file) diff-hl-reference-revision nil - buffer) + buffer + (diff-hl--use-async-p)) (error ;; https://github.com/dgutov/diff-hl/issues/117 (when (string-match-p "\\`Failed (status 128)" (error-message-string err)) (vc-call-backend backend 'diff (list file) "4b825dc642cb6eb9a060e54bf8d69288fbee4904" nil - buffer))))) + buffer + (diff-hl--use-async-p)))))) buffer) (defun diff-hl-changes () @@ -373,14 +399,19 @@ It can be a relative expression as well, such as \"HEAD^\" with Git, or ((eq state 'removed) `((1 ,(line-number-at-pos (point-max)) delete)))))))) +(defun diff-hl-process-wait (buf) + (let ((proc (get-buffer-process buf))) + (while (process-live-p proc) + (accept-process-output proc 0.01)))) + (defun diff-hl-changes-from-buffer (buf) + (diff-hl-process-wait buf) (with-current-buffer buf (let (res) (goto-char (point-min)) (unless (eobp) ;; TODO: When 27.1 is the minimum requirement, we can drop ;; these bindings: that version, in addition to switching over - ;; to the diff-refine var, also added the ;; called-interactively-p check, so refinement can't be ;; triggered by code calling the navigation functions, only by ;; direct interactive invocations. @@ -407,14 +438,30 @@ It can be a relative expression as well, such as \"HEAD^\" with Git, or (push (list line len type) res))))) (nreverse res)))) +(defun diff-hl--use-async-p () + (and diff-hl-update-async + (not + (run-hook-with-args-until-success 'diff-hl-async-inhibit-functions + default-directory)))) + (defun diff-hl-update () "Updates the diff-hl overlay." - (if (and diff-hl-update-async - (not - (run-hook-with-args-until-success 'diff-hl-async-inhibit-functions - default-directory))) + (if (diff-hl--use-async-p) ;; TODO: debounce if a thread is already running. - (make-thread 'diff-hl--update-safe "diff-hl--update-safe") + (let ((buf (current-buffer)) + (temp-buffer + (if (< emacs-major-version 28) + (generate-new-buffer " *temp*") + (generate-new-buffer " *temp*" t)))) + ;; Switch buffer temporarily, to "unlock" it for other threads. + (with-current-buffer temp-buffer + (make-thread + (lambda () + (kill-buffer temp-buffer) + (when (buffer-live-p buf) + (set-buffer buf) + (diff-hl--update-safe))) + "diff-hl--update-safe"))) (diff-hl--update))) (defun diff-hl-with-editor-p (_dir) @@ -433,6 +480,8 @@ It can be a relative expression as well, such as \"HEAD^\" with Git, or (let ((changes (diff-hl-changes)) (current-line 1)) (diff-hl-remove-overlays) + (when (not changes) + (diff-hl--autohide-margin)) (save-excursion (save-restriction (widen) @@ -463,6 +512,16 @@ It can be a relative expression as well, such as \"HEAD^\" with Git, or (overlay-put h 'insert-in-front-hooks hook) (overlay-put h 'insert-behind-hooks hook))))))))) +(defun diff-hl--autohide-margin () + (let ((width-var (intern (format "%s-margin-width" diff-hl-side)))) + (when (and diff-hl-autohide-margin + (> (symbol-value width-var) 0)) + (if (eql (default-value width-var) 0) + (kill-local-variable width-var) + (set width-var 0)) + (dolist (win (get-buffer-window-list)) + (set-window-buffer win (current-buffer)))))) + (defvar-local diff-hl--modified-tick nil) (put 'diff-hl--modified-tick 'permanent-local t) @@ -478,9 +537,14 @@ It can be a relative expression as well, such as \"HEAD^\" with Git, or (funcall diff-hl-highlight-function o type shape) o)) +(autoload 'diff-hl-highlight-on-margin "diff-hl-margin") + (defun diff-hl-highlight-on-fringe (ovl type shape) - (overlay-put ovl 'before-string (diff-hl-fringe-spec type shape - diff-hl-side))) + (if (and diff-hl-fallback-to-margin + (not (display-graphic-p))) + (diff-hl-highlight-on-margin ovl type shape) + (overlay-put ovl 'before-string (diff-hl-fringe-spec type shape + diff-hl-side)))) (defun diff-hl-remove-overlays (&optional beg end) (save-restriction @@ -526,7 +590,11 @@ It can be a relative expression as well, such as \"HEAD^\" with Git, or (let ((revs (diff-hl-diff-read-revisions rev1))) (setq rev1 (car revs) rev2 (cdr revs)))) - (vc-diff-internal t (vc-deduce-fileset) rev1 rev2 t) + (vc-diff-internal + (if (boundp 'vc-allow-async-diff) + vc-allow-async-diff + t) + (vc-deduce-fileset) rev1 rev2 t) (vc-run-delayed (if (< (line-number-at-pos (point-max)) 3) (with-current-buffer buffer (diff-hl-remove-overlays)) (when (or (not rev2) diff-hl-goto-hunk-old-revisions) @@ -615,6 +683,7 @@ in the source file, or the last line of the hunk above it." (let* ((diff-buffer (get-buffer-create (generate-new-buffer-name "*diff-hl*"))) (buffer (current-buffer)) + (diff-hl-update-async nil) (line (save-excursion (diff-hl-find-current-hunk) (line-number-at-pos))) @@ -755,7 +824,7 @@ its end position." (user-error "Only Git supports staging; this file is controlled by %s" backend)))) (defun diff-hl-stage-diff (orig-buffer) - (let ((patchfile (make-temp-file "diff-hl-stage-patch")) + (let ((patchfile (make-nearby-temp-file "diff-hl-stage-patch")) success) (write-region (point-min) (point-max) patchfile nil 'silent) @@ -763,7 +832,7 @@ its end position." (with-current-buffer orig-buffer (with-output-to-string (vc-git-command standard-output 0 - patchfile + (file-local-name patchfile) "apply" "--cached" ) (setq success t))) (delete-file patchfile)) @@ -786,7 +855,9 @@ Only supported with Git." (with-current-buffer dest-buffer (let ((inhibit-read-only t)) (erase-buffer))) - (diff-hl-diff-buffer-with-reference file dest-buffer nil 3) + (let (diff-hl-reference-revision + diff-hl-update-async) + (diff-hl-diff-buffer-with-reference file dest-buffer nil 3)) (with-current-buffer dest-buffer (with-no-warnings (let (diff-auto-refine-mode) @@ -961,7 +1032,8 @@ The value of this variable is a mode line template as in (remove-hook 'magit-revert-buffer-hook 'diff-hl-update t) (remove-hook 'magit-not-reverted-hook 'diff-hl-update t) (remove-hook 'text-scale-mode-hook 'diff-hl-maybe-redefine-bitmaps t) - (diff-hl-remove-overlays))) + (diff-hl-remove-overlays) + (diff-hl--autohide-margin))) (defun diff-hl-after-checkin () (let ((fileset (vc-deduce-fileset t))) @@ -1096,6 +1168,11 @@ the user should be returned." (declare-function diff-no-select "diff") +(defvar diff-hl-temporary-directory (if (and (eq system-type 'gnu/linux) + (file-directory-p "/dev/shm/")) + "/dev/shm/" + temporary-file-directory)) + (defun diff-hl-diff-buffer-with-reference (file &optional dest-buffer backend context-lines) "Compute the diff between the current buffer contents and reference in BACKEND. The diffs are computed in the buffer DEST-BUFFER. This requires @@ -1106,10 +1183,7 @@ CONTEXT-LINES is the size of the unified diff context, defaults to 0." (save-current-buffer (let* ((dest-buffer (or dest-buffer "*diff-hl-diff-buffer-with-reference*")) (backend (or backend (vc-backend file))) - (temporary-file-directory - (if (and (eq system-type 'gnu/linux) (file-directory-p "/dev/shm/")) - "/dev/shm/" - temporary-file-directory)) + (temporary-file-directory diff-hl-temporary-directory) (rev (if (and (eq backend 'Git) (not diff-hl-reference-revision) @@ -1122,12 +1196,10 @@ CONTEXT-LINES is the size of the unified diff context, defaults to 0." (or (diff-hl-resolved-reference-revision backend) (diff-hl-working-revision file backend))))) (switches (format "-U %d --strip-trailing-cr" (or context-lines 0)))) - (diff-no-select rev (current-buffer) switches 'noasync + (diff-no-select rev (current-buffer) switches (not (diff-hl--use-async-p)) (get-buffer-create dest-buffer)) - (with-current-buffer dest-buffer - (let ((inhibit-read-only t)) - ;; Function `diff-sentinel' adds a final line, so remove it - (delete-matching-lines "^Diff finished.*"))) + ;; Function `diff-sentinel' adds a summary line, but that seems fine. + ;; In all commands which use exact text we call it synchronously. (get-buffer-create dest-buffer)))) (defun diff-hl-resolved-reference-revision (backend) diff --git a/lisp/dim/dim-pkg.el b/lisp/dim/dim-pkg.el index 520fac52..ee22fefa 100644 --- a/lisp/dim/dim-pkg.el +++ b/lisp/dim/dim-pkg.el @@ -1,14 +1,10 @@ -(define-package "dim" "20160818.949" "Change mode-line names of major/minor modes" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "dim" "20160818.949" + "Change mode-line names of major/minor modes." '((emacs "24.4")) - :commit "110624657fec0c8a7b3589108230e6a635302ae0" :authors - '(("Alex Kost" . "alezost@gmail.com")) - :maintainers - '(("Alex Kost" . "alezost@gmail.com")) - :maintainer - '("Alex Kost" . "alezost@gmail.com") - :keywords - '("convenience") - :url "https://github.com/alezost/dim.el") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/alezost/dim.el" + :commit "110624657fec0c8a7b3589108230e6a635302ae0" + :revdesc "110624657fec" + :keywords '("convenience") + :authors '(("Alex Kost" . "alezost@gmail.com")) + :maintainers '(("Alex Kost" . "alezost@gmail.com"))) diff --git a/lisp/dim/dim.el b/lisp/dim/dim.el index 6be9a0aa..16fb3110 100644 --- a/lisp/dim/dim.el +++ b/lisp/dim/dim.el @@ -4,7 +4,8 @@ ;; Author: Alex Kost ;; Created: 24 Dec 2015 -;; Version: 0.1 +;; Package-Version: 20160818.949 +;; Package-Revision: 110624657fec ;; URL: https://github.com/alezost/dim.el ;; Keywords: convenience ;; Package-Requires: ((emacs "24.4")) diff --git a/lisp/elisp-refs/elisp-refs-pkg.el b/lisp/elisp-refs/elisp-refs-pkg.el index 88eab124..68c1f5d9 100644 --- a/lisp/elisp-refs/elisp-refs-pkg.el +++ b/lisp/elisp-refs/elisp-refs-pkg.el @@ -1,14 +1,11 @@ -(define-package "elisp-refs" "20230920.201" "find callers of elisp functions or macros" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "elisp-refs" "20230920.201" + "Find callers of elisp functions or macros." '((dash "2.12.0") - (s "1.11.0")) - :commit "541a064c3ce27867872cf708354a65d83baf2a6d" :authors - '(("Wilfred Hughes" . "me@wilfred.me.uk")) - :maintainers - '(("Wilfred Hughes" . "me@wilfred.me.uk")) - :maintainer - '("Wilfred Hughes" . "me@wilfred.me.uk") - :keywords - '("lisp")) -;; Local Variables: -;; no-byte-compile: t -;; End: + (s "1.11.0")) + :url "https://github.com/Wilfred/elisp-refs" + :commit "541a064c3ce27867872cf708354a65d83baf2a6d" + :revdesc "541a064c3ce2" + :keywords '("lisp") + :authors '(("Wilfred Hughes" . "me@wilfred.me.uk")) + :maintainers '(("Wilfred Hughes" . "me@wilfred.me.uk"))) diff --git a/lisp/elisp-refs/elisp-refs.el b/lisp/elisp-refs/elisp-refs.el index 21b3546a..fc421345 100644 --- a/lisp/elisp-refs/elisp-refs.el +++ b/lisp/elisp-refs/elisp-refs.el @@ -3,7 +3,8 @@ ;; Copyright (C) 2016-2020 Wilfred Hughes ;; Author: Wilfred Hughes -;; Version: 1.6 +;; Package-Version: 20230920.201 +;; Package-Revision: 541a064c3ce2 ;; Keywords: lisp ;; Package-Requires: ((dash "2.12.0") (s "1.11.0")) diff --git a/lisp/emacsql/README.md b/lisp/emacsql/README.md new file mode 100644 index 00000000..5a6e0041 --- /dev/null +++ b/lisp/emacsql/README.md @@ -0,0 +1,434 @@ +# EmacSQL + +EmacSQL is a high-level Emacs Lisp front-end for SQLite. + +PostgreSQL and MySQL are also supported, but use of these connectors +is not recommended. + +Any [readable lisp value][readable] can be stored as a value in +EmacSQL, including numbers, strings, symbols, lists, vectors, and +closures. EmacSQL has no concept of "TEXT" values; it's all just lisp +objects. The lisp object `nil` corresponds 1:1 with `NULL` in the +database. + +Requires Emacs 26 or later. + +[![Compile](https://github.com/magit/emacsql/actions/workflows/compile.yml/badge.svg)](https://github.com/magit/emacsql/actions/workflows/compile.yml) +[![Test](https://github.com/magit/emacsql/actions/workflows/test.yml/badge.svg)](https://github.com/magit/emacsql/actions/workflows/test.yml) +[![NonGNU ELPA](https://emacsair.me/assets/badges/nongnu-elpa.svg)](https://elpa.nongnu.org/nongnu-devel/emacsql.html) +[![MELPA Stable](https://stable.melpa.org/packages/emacsql-badge.svg)](https://stable.melpa.org/#/emacsql) +[![MELPA](https://melpa.org/packages/emacsql-badge.svg)](https://melpa.org/#/emacsql) + +### FAQ +#### Why are all values stored as strings? + +EmacSQL is not intended to interact with arbitrary databases, but to +be an ACID-compliant database for Emacs extensions. This means that +EmacSQL cannot be used with a regular SQL database used by other +non-Emacs clients. + +All database values must be s-expressions. When EmacSQL stores a +value — string, symbol, cons, etc. — it is printed and written to +the database in its printed form. Strings are wrapped in quotes +and escaped as necessary. That means "bare" symbols in the database +generally look like strings. The only exception is `nil`, which is +stored as `NULL`. + +#### Will EmacSQL ever support arbitrary databases? + +The author of EmacSQL [thinks][mistake] that it was probably a +design mistake to restrict it to Emacs by storing only printed values, +and that it would be a lot more useful if it just handled primitive +database types. + +However, EmacSQL is in maintenance mode and there are no plans to +make any fundamental changes, not least because they would break all +existing packages and databases that rely on the current EmacSQL +behavior. + +### Windows Issues + +Emacs `start-process-shell-command` function is not supported on +Windows. Since both `emacsql-mysql` and `emacsql-psql` rely on this +function, neither of these connection types are supported on Windows. + +## Example Usage + +```el +(defvar db (emacsql-sqlite-open "~/company.db")) + +;; Create a table. Table and column identifiers are symbols. +(emacsql db [:create-table people ([name id salary])]) + +;; Or optionally provide column constraints. +(emacsql db [:create-table people + ([name (id integer :primary-key) (salary float)])]) + +;; Insert some data: +(emacsql db [:insert :into people + :values (["Jeff" 1000 60000.0] ["Susan" 1001 64000.0])]) + +;; Query the database for results: +(emacsql db [:select [name id] + :from people + :where (> salary 62000)]) +;; => (("Susan" 1001)) + +;; Queries can be templates, using $1, $2, etc.: +(emacsql db [:select [name id] + :from people + :where (> salary $s1)] + 50000) +;; => (("Jeff" 1000) ("Susan" 1001)) +``` + +When editing these prepared SQL s-expression statements, the `M-x +emacsql-show-last-sql` command (think `eval-last-sexp`) is useful for +seeing what the actual SQL expression will become when compiled. + +## Schema + +A table schema is a list whose first element is a vector of column +specifications. The rest of the list specifies table constraints. A +column identifier is a symbol and a column's specification can either +be just this symbol or it can include constraints as a list. Because +EmacSQL stores entire lisp objects as values, the only relevant (and +allowed) types are `integer`, `float`, and `object` (default). + + ([() ...] ( ...) ...]) + +Dashes in identifiers are converted into underscores when compiled +into SQL. This allows for lisp-style identifiers to be used in SQL. +Constraints follow the compilation rules below. + +```el +;; No constraints schema with four columns: +([name id building room]) + +;; Add some column constraints: +([(name :unique) (id integer :primary-key) building room]) + +;; Add some table constraints: +([(name :unique) (id integer :primary-key) building room] + (:unique [building room]) + (:check (> id 0))) +``` + +Here's an example using foreign keys. + +```el +;; "subjects" table schema +([(id integer :primary-key) subject]) + +;; "tag" table references subjects +([(subject-id integer) tag] + (:foreign-key [subject-id] :references subjects [id] + :on-delete :cascade)) +``` + +Foreign key constraints are enabled by default in EmacSQL. + +## Operators + +Expressions are written lisp-style, with the operator first. If it +looks like an operator EmacSQL treats it like an operator. However, +several operators are special. + + <= >= funcall quote + +The `<=` and `>=` operators accept 2 or 3 operands, transforming into +a SQL `_ BETWEEN _ AND _` operator as appropriate. + +For function-like "operators" like `count` and `max` use the `funcall` +"operator." + +```el +[:select (funcall max age) :from people] +``` + +With `glob` and `like` SQL operators keep in mind that they're +matching the *printed* representations of these values, even if the +value is a string. + +The `||` concatenation operator is unsupported because concatenating +printed representations breaks an important constraint: all values must +remain readable within SQLite. + +## Quoting + +Inside expressions, EmacSQL cannot tell the difference between symbol +literals and column references. If you're talking about the symbol +itself, just quote it as you would in normal Elisp. Note that this +does not "escape" `$tn` parameter symbols. + +```el +(emacsql db [... :where (= category 'hiking)]) +``` + +Quoting a string makes EmacSQL handle it as a "raw string." These raw +strings are not printed when being assembled into a query. These are +intended for use in special circumstances like filenames (`ATTACH`) or +pattern matching (`LIKE`). It is vital that raw strings are not +returned as results. + +```el +(emacsql db [... :where (like name '"%foo%")]) +(emacsql db [:attach '"/path/to/foo.db" :as foo]) +``` + +Since template parameters include their type they never need to be +quoted. + +## Prepared Statements + +The database is interacted with via prepared SQL s-expression +statements. You shouldn't normally be concatenating strings on your +own. (And it leaves out any possibility of a SQL injection!) See the +"Usage" section above for examples. A statement is a vector of +keywords and other lisp object. + +Prepared EmacSQL s-expression statements are compiled into SQL +statements. The statement compiler is memorized so that using the same +statement multiple times is fast. To assist in this, the statement can +act as a template -- using `$i1`, `$s2`, etc. -- working like the +Elisp `format` function. + +### Compilation Rules + +Rather than the typical uppercase SQL keywords, keywords in a prepared +EmacSQL statement are literally just that: lisp keywords. EmacSQL only +understands a very small amount of SQL's syntax. The compiler follows +some simple rules to convert an s-expression into SQL. + +#### All prepared statements are vectors. + +A prepared s-expression statement is a vector beginning with a keyword +followed by a series of keywords and special values. This includes +most kinds of sub-queries. + +```el +[:select ... :from ...] +[:select tag :from tags + :where (in tag [:select ...])] +``` + +#### Keywords are split and capitalized. + +Dashes are converted into spaces and the keyword gets capitalized. For +example, `:if-not-exists` becomes `IF NOT EXISTS`. How you choose to +combine keywords is up to your personal taste (e.g., `:drop :table` vs. +`:drop-table`). + +#### Standalone symbols are identifiers. + +EmacSQL doesn't know what symbols refer to identifiers and what +symbols should be treated as values. Use quotes to mark a symbol as a +value. For example, `people` here will be treated as an identifier. + +```el +[:insert-into people :values ...] +``` + +#### Row-oriented information is always represented as vectors. + +This includes rows being inserted, and sets of columns in a query. If +you're talking about a row-like thing then put it in a vector. + +```el +[:select [id name] :from people] +``` + +Note that `*` is actually a SQL keyword, so don't put it in a vector. + +```el +[:select * :from ...] +``` + +#### Lists are treated as expressions. + +This is true even within row-oriented vectors. + +```el +[... :where (= name "Bob")] +[:select [(/ seconds 60) count] :from ...] +``` + +Some things that are traditionally keywords -- particularly those that +are mixed in with expressions -- have been converted into operators +(`AS`, `ASC`, `DESC`). + +```el +[... :order-by [(asc b), (desc a)]] ; "ORDER BY b ASC, a DESC" +[:select p:name :from (as people p)] ; "SELECT p.name FROM people AS p" +``` + +#### The `:values` keyword is special. + +What follows `:values` is always treated like a vector or list of +vectors. Normally this sort of thing would appear to be a column +reference. + +```el +[... :values [1 2 3]] +[... :values ([1 2 3] [4 5 6])] ; insert multiple rows +``` + +#### A list whose first element is a vector is a table schema. + +This is to distinguish schemata from everything else. With the +exception of what follows `:values`, nothing else is shaped like this. + +```el +[:create-table people ([(id :primary-key) name])] +``` + +### Templates + +To make statement compilation faster, and to avoid making you build up +statements dynamically, you can insert `$tn` parameters in place of +identifiers and values. These refer to the argument's type and its +argument position after the statement in the `emacsql` function, +one-indexed. + +```el +(emacsql db [:select * :from $i1 :where (> salary $s2)] 'employees 50000) + +(emacsql db [:select * :from employees :where (like name $r1)] "%Smith%") +``` + +The letter before the number is the type. + + * `i` : identifier + * `s` : scalar + * `v` : vector (or multiple vectors) + * `r` : raw, unprinted strings + * `S` : schema + +When combined with `:values`, the vector type can refer to lists of +rows. + +```el +(emacsql db [:insert-into favorite-characters :values $v1] + '([0 "Calvin"] [1 "Hobbes"] [3 "Susie"])) +``` + +This is why rows must be vectors and not lists. + +### Ignored Features + +EmacSQL doesn't cover all of SQLite's features. Here are a list of +things that aren't supported, and probably will never be. + + * Collating. SQLite has three built-in collation functions: BINARY + (default), NOCASE, and RTRIM. EmacSQL values never have right-hand + whitespace, so RTRIM won't be of any use. NOCASE is broken + (ASCII-only) and there's little reason to use it. + + * Text manipulation functions. Like collating this is incompatible + with EmacSQL s-expression storage. + + * Date and time. These are incompatible with the printed values + stored by EmacSQL and therefore have little use. + +## Limitations + +EmacSQL is *not* intended to play well with other programs accessing +the SQLite database. Non-numeric values are stored encoded as +s-expressions TEXT values. This avoids ambiguities in parsing output +from the command line and allows for storage of Emacs richer data +types. This is an efficient, ACID-compliant database specifically for +Emacs. + +## Emacs Lisp Indentation Annoyance + +By default, `emacs-lisp-mode` indents vectors as if they were regular +function calls. + +```el +;; Ugly indentation! +(emacsql db [:select * + :from people + :where (> age 60)]) +``` + +Calling the function `emacsql-fix-vector-indentation` (interactive) +advises the major mode to fix this annoyance. + +```el +;; Such indent! +(emacsql db [:select * + :from people + :where (> age 60)]) +``` + +## Contributing and Extending + +To run the test suite, clone the `pg` and `sqlite3` packages into +sibling directories. The Makefile will automatically put these paths on +the Emacs load path (override `LDFLAGS` if your situation is different). + +```shell +git clone https://github.com/emarsden/pg-el ../pg +git clone https://github.com/pekingduck/emacs-sqlite3-api ../sqlite3 +``` + +Or set `LOAD_PATH` to point at these packages elsewhere: + +```shell +make LOAD_PATH='-L path/to/pg -L path/to/sqlite3' +``` + +Then invoke make: + +```shell +make test +``` + +If the environment variable `PGDATABASE` is present then the unit +tests will also be run with PostgreSQL (emacsql-psql). Provide +`PGHOST`, `PGPORT`, and `PGUSER` if needed. If `PGUSER` is provided, +the pg.el back-end (emacsql-pg) will also be tested. + +If the environment variable `MYSQL_DBNAME` is present then the unit +tests will also be run with MySQL in the named database. Note that +this is not an official MySQL variable, just something made up for +EmacSQL. + +### Creating a New Front-end + +EmacSQL uses EIEIO so that interactions with a connection occur +through generic functions. You need to define a new class that +inherits from `emacsql-connection`. + + * Implement `emacsql-send-message`, `emacsql-waiting-p`, + `emacsql-parse`, and `emacsql-close`. + * Provide a constructor that initializes the connection and calls + `emacsql-register` (for automatic connection cleanup). + * Provide `emacsql-types` if needed (hint: use a class-allocated slot). + * Ensure that you properly read NULL as nil (hint: ask your back-end + to print it that way). + * Register all reserved words with `emacsql-register-reserved`. + * Preferably provide `emacsql-reconnect` if possible. + * Set the default isolation level to *serializable*. + * Enable autocommit mode by default. + * Prefer ANSI syntax (value escapes, identifier escapes, etc.). + * Enable foreign key constraints by default. + +The goal of the autocommit, isolation, parsing, and foreign key +configuration settings is to normalize the interface as much as +possible. The connection's user should have the option to be agnostic +about which back-end is actually in use. + +The provided implementations should serve as useful examples. If your +back-end outputs data in a clean, standard way you may be able to use +the emacsql-protocol-mixin class to do most of the work. + +## See Also + + * [SQLite Documentation](https://www.sqlite.org/docs.html) + +[readable]: http://nullprogram.com/blog/2013/12/30/#almost_everything_prints_readably +[mistake]: https://github.com/magit/emacsql/issues/35#issuecomment-346352439 + + + diff --git a/lisp/emacsql/emacsql-pkg.el b/lisp/emacsql/emacsql-pkg.el index d084c5e0..c3161a1d 100644 --- a/lisp/emacsql/emacsql-pkg.el +++ b/lisp/emacsql/emacsql-pkg.el @@ -1,12 +1,9 @@ -(define-package "emacsql" "20250301.1637" "High-level SQL database front-end" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "emacsql" "20250601.1009" + "High-level SQL database front-end." '((emacs "26.1")) - :commit "f111b0acc79eadeeb3c6c1332d943f11fd6932ff" :authors - '(("Christopher Wellons" . "wellons@nullprogram.com")) - :maintainers - '(("Jonas Bernoulli" . "emacs.emacsql@jonas.bernoulli.dev")) - :maintainer - '("Jonas Bernoulli" . "emacs.emacsql@jonas.bernoulli.dev") - :url "https://github.com/magit/emacsql") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/magit/emacsql" + :commit "ced062890061b6e4fbe4d00c0617f7ff84fff25c" + :revdesc "ced062890061" + :authors '(("Christopher Wellons" . "wellons@nullprogram.com")) + :maintainers '(("Jonas Bernoulli" . "emacs.emacsql@jonas.bernoulli.dev"))) diff --git a/lisp/emacsql/emacsql-sqlite-builtin.el b/lisp/emacsql/emacsql-sqlite-builtin.el index 15c6020e..94edd26c 100644 --- a/lisp/emacsql/emacsql-sqlite-builtin.el +++ b/lisp/emacsql/emacsql-sqlite-builtin.el @@ -16,10 +16,9 @@ (require 'emacsql-sqlite) -(require 'sqlite nil t) -(declare-function sqlite-open "sqlite") -(declare-function sqlite-select "sqlite") -(declare-function sqlite-close "sqlite") +(declare-function sqlite-open "sqlite.c") +(declare-function sqlite-select "sqlite.c") +(declare-function sqlite-close "sqlite.c") (emacsql-register-reserved emacsql-sqlite-reserved) @@ -28,7 +27,6 @@ (cl-defmethod initialize-instance :after ((connection emacsql-sqlite-builtin-connection) &rest _) - (require (quote sqlite)) (oset connection handle (sqlite-open (oref connection file))) (emacsql-sqlite-set-busy-timeout connection) diff --git a/lisp/emacsql/emacsql-sqlite-common.el b/lisp/emacsql/emacsql-sqlite-common.el deleted file mode 100644 index 129d1401..00000000 --- a/lisp/emacsql/emacsql-sqlite-common.el +++ /dev/null @@ -1,22 +0,0 @@ -;;; emacsql-sqlite-common.el --- Transitional library that should not be loaded -*- lexical-binding:t -*- - -;; This is free and unencumbered software released into the public domain. - -;; Author: Jonas Bernoulli -;; Maintainer: Jonas Bernoulli - -;; SPDX-License-Identifier: Unlicense - -;;; Commentary: - -;; Transitional library that should not be loaded. If your package still -;; requires this library, change it to require `emacsql-sqlite' instead. - -;;; Code: - -(require 'emacsql-sqlite) - -(provide 'emacsql-sqlite-common) - -;;; emacsql-sqlite-common.el ends here - diff --git a/lisp/emacsql/emacsql-sqlite.el b/lisp/emacsql/emacsql-sqlite.el index b58a1181..3add7aeb 100644 --- a/lisp/emacsql/emacsql-sqlite.el +++ b/lisp/emacsql/emacsql-sqlite.el @@ -1,4 +1,4 @@ -;;; emacsql-sqlite.el --- Code used by multiple SQLite back-ends -*- lexical-binding:t -*- +;;; emacsql-sqlite.el --- Code used by both SQLite back-ends -*- lexical-binding:t -*- ;; This is free and unencumbered software released into the public domain. @@ -9,7 +9,7 @@ ;;; Commentary: -;; This library contains code that is used by multiple SQLite back-ends. +;; This library contains code that is used by both SQLite back-ends. ;;; Code: diff --git a/lisp/emacsql/emacsql.el b/lisp/emacsql/emacsql.el index 1b299ea2..8c287748 100644 --- a/lisp/emacsql/emacsql.el +++ b/lisp/emacsql/emacsql.el @@ -6,7 +6,8 @@ ;; Maintainer: Jonas Bernoulli ;; Homepage: https://github.com/magit/emacsql -;; Package-Version: 4.2.0 +;; Package-Version: 20250601.1009 +;; Package-Revision: ced062890061 ;; Package-Requires: ((emacs "26.1")) ;; SPDX-License-Identifier: Unlicense @@ -32,17 +33,13 @@ "The EmacSQL SQL database front-end." :group 'comm) -(defconst emacsql-version "4.2.0") +(defconst emacsql-version "4.3.1") (defvar emacsql-global-timeout 30 "Maximum number of seconds to wait before bailing out on a SQL command. -If nil, wait forever. This is used by the `mysql', `pg', `psql' and -`sqlite' back-ends. It is not being used by the `sqlite-builtin' and -`sqlite-module' back-ends, which only use `emacsql-sqlite-busy-timeout'.") - -(defvar emacsql-data-root - (file-name-directory (or load-file-name buffer-file-name)) - "Directory where EmacSQL is installed.") +If nil, wait forever. This is used by the `mysql', `pg' and `psql'. It +is not being used by the `sqlite-builtin' and `sqlite-module' back-ends, +which respect `emacsql-sqlite-busy-timeout' instead.") ;;; Database connection @@ -101,29 +98,6 @@ MESSAGE should not have a newline on the end." (goto-char (point-max)) (princ (concat message "\n") buffer))))) -(cl-defgeneric emacsql-process (this) - "Access internal `handle' slot directly, which you shouldn't do. -Using this function to do it anyway, means additionally using a -misnamed and obsolete accessor function." - (and (slot-boundp this 'handle) - (oref this handle))) -(cl-defmethod (setf emacsql-process) (value (this emacsql-connection)) - (oset this handle value)) -(make-obsolete 'emacsql-process "underlying slot is for internal use only." - "EmacSQL 4.0.0") - -(cl-defmethod slot-missing ((connection emacsql-connection) - slot-name operation &optional new-value) - "Treat removed `process' slot-name as an alias for internal `handle' slot." - (pcase (list operation slot-name) - ('(oref process) - (message "EmacSQL: Slot `process' is obsolete") - (oref connection handle)) - ('(oset process) - (message "EmacSQL: Slot `process' is obsolete") - (oset connection handle new-value)) - (_ (cl-call-next-method)))) - ;;; Sending and receiving (cl-defgeneric emacsql-send-message (connection message) @@ -159,8 +133,8 @@ misnamed and obsolete accessor function." (defun emacsql-compile (connection sql &rest args) "Compile s-expression SQL for CONNECTION into a string." - (let* ((mask (and connection (emacsql-types connection))) - (emacsql-type-map (or mask emacsql-type-map))) + (let ((emacsql-type-map (or (and connection (emacsql-types connection)) + emacsql-type-map))) (concat (apply #'emacsql-format (emacsql-prepare sql) args) ";"))) (cl-defgeneric emacsql (connection sql &rest args) @@ -205,14 +179,12 @@ specific error conditions." (goto-char (point-min)) (let* ((standard-input (current-buffer)) (value (read))) - (if (eql value 'error) + (if (eq value 'error) (emacsql-handle connection (read) (read)) (prog1 value - (unless (eq 'success (read)) + (unless (eq (read) 'success) (emacsql-handle connection (read) (read)))))))) -(provide 'emacsql) ; end of generic function declarations - ;;; Automatic connection cleanup (defun emacsql-register (connection) @@ -306,7 +278,7 @@ Each column must be a plain symbol, no expressions allowed here." (args (and (not (vectorp sql-and-args)) (cdr sql-and-args)))) (cl-assert (eq :select (elt sql 0))) (let ((vars (elt sql 1))) - (when (eq '* vars) + (when (eq vars '*) (error "Must explicitly list columns in `emacsql-with-bind'")) (cl-assert (cl-every #'symbolp vars)) `(let ((emacsql--results (emacsql ,connection ,sql ,@args)) @@ -402,4 +374,6 @@ Once activated, vector contents no longer indent like lists." (advice-add 'calculate-lisp-indent :around #'emacsql--calculate-vector-indent)) +(provide 'emacsql) + ;;; emacsql.el ends here diff --git a/lisp/emojify/emojify-pkg.el b/lisp/emojify/emojify-pkg.el index b01454b9..570f5dfc 100644 --- a/lisp/emojify/emojify-pkg.el +++ b/lisp/emojify/emojify-pkg.el @@ -1,16 +1,12 @@ -(define-package "emojify" "20210108.1111" "Display emojis in Emacs" - '((seq "1.11") - (ht "2.0") +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "emojify" "20210108.1111" + "Display emojis in Emacs." + '((seq "1.11") + (ht "2.0") (emacs "24.3")) - :commit "cfa00865388809363df3f884b4dd554a5d44f835" :authors - '(("Iqbal Ansari" . "iqbalansari02@yahoo.com")) - :maintainers - '(("Iqbal Ansari" . "iqbalansari02@yahoo.com")) - :maintainer - '("Iqbal Ansari" . "iqbalansari02@yahoo.com") - :keywords - '("multimedia" "convenience") - :url "https://github.com/iqbalansari/emacs-emojify") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/iqbalansari/emacs-emojify" + :commit "cfa00865388809363df3f884b4dd554a5d44f835" + :revdesc "cfa008653888" + :keywords '("multimedia" "convenience") + :authors '(("Iqbal Ansari" . "iqbalansari02@yahoo.com")) + :maintainers '(("Iqbal Ansari" . "iqbalansari02@yahoo.com"))) diff --git a/lisp/emojify/emojify.el b/lisp/emojify/emojify.el index fb993e11..61823ff7 100644 --- a/lisp/emojify/emojify.el +++ b/lisp/emojify/emojify.el @@ -5,7 +5,8 @@ ;; Author: Iqbal Ansari ;; Keywords: multimedia, convenience ;; URL: https://github.com/iqbalansari/emacs-emojify -;; Version: 1.2.1 +;; Package-Version: 20210108.1111 +;; Package-Revision: cfa008653888 ;; Package-Requires: ((seq "1.11") (ht "2.0") (emacs "24.3")) ;; This program is free software; you can redistribute it and/or modify diff --git a/lisp/ess-R-data-view/ess-R-data-view-pkg.el b/lisp/ess-R-data-view/ess-R-data-view-pkg.el index 85f75a21..040d9719 100644 --- a/lisp/ess-R-data-view/ess-R-data-view-pkg.el +++ b/lisp/ess-R-data-view/ess-R-data-view-pkg.el @@ -1,12 +1,11 @@ -(define-package "ess-R-data-view" "20130509.1158" "Data viewer for GNU R" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "ess-R-data-view" "20130509.1158" + "Data viewer for GNU R." '((ctable "20130313.1743") - (popup "20130324.1305") - (ess "20130225.1754")) - :commit "d6e98d3ae1e2a2ea39a56eebcdb73e99d29562e9" :authors - '(("myuhe" . "yuhei.maeda_at_gmail.com")) - :keywords - '("convenience") - :url "https://github.com/myuhe/ess-R-data-view.el") -;; Local Variables: -;; no-byte-compile: t -;; End: + (popup "20130324.1305") + (ess "20130225.1754")) + :url "https://github.com/myuhe/ess-R-data-view.el" + :commit "d6e98d3ae1e2a2ea39a56eebcdb73e99d29562e9" + :revdesc "d6e98d3ae1e2" + :keywords '("convenience") + :authors '(("myuhe" . "yuhei.maeda_at_gmail.com"))) diff --git a/lisp/ess-R-data-view/ess-R-data-view.el b/lisp/ess-R-data-view/ess-R-data-view.el index 68fb5d2d..1004afe9 100644 --- a/lisp/ess-R-data-view/ess-R-data-view.el +++ b/lisp/ess-R-data-view/ess-R-data-view.el @@ -3,7 +3,8 @@ ;; Author: myuhe ;; Maintainer: myuhe ;; URL: https://github.com/myuhe/ess-R-data-view.el -;; Version: 0.1 +;; Package-Version: 20130509.1158 +;; Package-Revision: d6e98d3ae1e2 ;; Created: 2013-05-09 ;; Keywords: convenience ;; Package-Requires: ((ctable "20130313.1743") (popup "20130324.1305") (ess "20130225.1754")) diff --git a/lisp/ess/ess-bugs-l.el b/lisp/ess/ess-bugs-l.el index 5cb707f3..1123ef15 100644 --- a/lisp/ess/ess-bugs-l.el +++ b/lisp/ess/ess-bugs-l.el @@ -64,8 +64,8 @@ Users whose default is not \\='sh, but are accessing a remote machine with `telnet' or `ssh', should have the following in their init file: (setq-default ess-bugs-batch-method \\='sh)" :group 'ess-bugs - :type '(choice (const sh :tag "Bourne/C-like Unix Shell") - (const dos :tag "DOS-like Windows shell"))) + :type '(choice (const :tag "Bourne/C-like Unix Shell" sh) + (const :tag "DOS-like Windows shell" dos))) (defcustom ess-bugs-batch-post-command (if (equal ess-bugs-batch-method 'sh) "&" " ") diff --git a/lisp/ess/ess-custom.el b/lisp/ess/ess-custom.el index f81b6787..1276e7f0 100644 --- a/lisp/ess/ess-custom.el +++ b/lisp/ess/ess-custom.el @@ -329,7 +329,7 @@ process. If a symbol, the symbol's value should be a directory. For example, the following setting would always start the process in the directory of the current file: - (setq ess-startup-directory ''default-directory) + (setq ess-startup-directory \\='default-directory) If `ess-startup-directory' is nil (the default) and `ess-startup-directory-function' is non-nil, the value returned diff --git a/lisp/ess/ess-help.el b/lisp/ess/ess-help.el index 0b2ccd13..7c997083 100644 --- a/lisp/ess/ess-help.el +++ b/lisp/ess/ess-help.el @@ -714,7 +714,7 @@ nil otherwise." (save-excursion (goto-char (point-min)) (while (search-forward "_" nil t) - (backward-delete-char 2) + (delete-char -2) (put-text-property (point) (1+ (point)) 'face 'underline)))) ;;*;; Link to Info diff --git a/lisp/ess/ess-pkg.el b/lisp/ess/ess-pkg.el index a990d92d..59ad83d1 100644 --- a/lisp/ess/ess-pkg.el +++ b/lisp/ess/ess-pkg.el @@ -1,23 +1,20 @@ -(define-package "ess" "20250110.1437" "Emacs Speaks Statistics" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "ess" "20250606.831" + "Emacs Speaks Statistics." '((emacs "25.1")) - :commit "0eb240bcb6d0e933615f6cfaa9761b629ddbabdd" :authors - '(("David Smith" . "dsmith@stats.adelaide.edu.au") - ("A.J. Rossini" . "blindglobe@gmail.com") - ("Richard M. Heiberger" . "rmh@temple.edu") - ("Kurt Hornik" . "Kurt.Hornik@R-project.org") - ("Martin Maechler" . "maechler@stat.math.ethz.ch") - ("Rodney A. Sparapani" . "rsparapa@mcw.edu") - ("Stephen Eglen" . "stephen@gnu.org") - ("Sebastian P. Luque" . "spluque@gmail.com") - ("Henning Redestig" . "henning.red@googlemail.com") - ("Vitalie Spinu" . "spinuvit@gmail.com") - ("Lionel Henry" . "lionel.hry@gmail.com") - ("J. Alexander Branham" . "alex.branham@gmail.com")) - :maintainers - '(("ESS Core Team" . "ESS-core@r-project.org")) - :maintainer - '("ESS Core Team" . "ESS-core@r-project.org") - :url "https://ess.r-project.org/") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://ess.r-project.org/" + :commit "cd85d1e1f0e897b409a948a3a4afdaffe032812e" + :revdesc "cd85d1e1f0e8" + :authors '(("David Smith" . "dsmith@stats.adelaide.edu.au") + ("A.J. Rossini" . "blindglobe@gmail.com") + ("Richard M. Heiberger" . "rmh@temple.edu") + ("Kurt Hornik" . "Kurt.Hornik@R-project.org") + ("Martin Maechler" . "maechler@stat.math.ethz.ch") + ("Rodney A. Sparapani" . "rsparapa@mcw.edu") + ("Stephen Eglen" . "stephen@gnu.org") + ("Sebastian P. Luque" . "spluque@gmail.com") + ("Henning Redestig" . "henning.red@googlemail.com") + ("Vitalie Spinu" . "spinuvit@gmail.com") + ("Lionel Henry" . "lionel.hry@gmail.com") + ("J. Alexander Branham" . "alex.branham@gmail.com")) + :maintainers '(("ESS Core Team" . "ESS-core@r-project.org"))) diff --git a/lisp/ess/ess-r-flymake.el b/lisp/ess/ess-r-flymake.el index 9df4402e..a9fedb31 100644 --- a/lisp/ess/ess-r-flymake.el +++ b/lisp/ess/ess-r-flymake.el @@ -62,7 +62,7 @@ "Default linters to use. Can be either a string with R expression to be used as is (e.g. `lintr::default_linters'). Or a list of strings where -each element is passed as argument to `lintr::with_defaults'." +each element is passed as argument to `lintr::linters_with_defaults'." :group 'ess-R :type '(choice string (repeat string)) :package-version '(ess . "18.10")) @@ -85,8 +85,8 @@ each element is passed as argument to `lintr::with_defaults'." if (!suppressWarnings(require(lintr, quietly=T))) { cat('@@error: @@`lintr` package not installed') } else { - if (packageVersion('lintr') <= '1.0.3') { - cat('@@error: @@Need `lintr` version > v1.0.3') + if (packageVersion('lintr') <= '3.0.0') { + cat('@@error: @@Need `lintr` version > v3.0.0') } else { tryCatch(lintr::lint(commandArgs(TRUE), ...), error = function(e) { @@ -120,12 +120,12 @@ we couldn't find a .lintr file." (defun ess-r--flymake-linters () "If `ess-r-flymake-linters' is a string, use that. -Otherwise, construct a string to pass to lintr::with_defaults." +Otherwise, construct a string to pass to lintr::linters_with_defaults." (replace-regexp-in-string "[\n\t ]+" " " (if (stringp ess-r-flymake-linters) ess-r-flymake-linters - (concat "lintr::with_defaults(" + (concat "lintr::linters_with_defaults(" (mapconcat #'identity ess-r-flymake-linters ", ") diff --git a/lisp/ess/ess-r-mode.el b/lisp/ess/ess-r-mode.el index 47165c2b..1cf1ae50 100644 --- a/lisp/ess/ess-r-mode.el +++ b/lisp/ess/ess-r-mode.el @@ -72,9 +72,9 @@ Fetching happens once per new ESSR version. The archive is stored in ~/.config/ESSR/ESSRv[VERSION].rds file. You can download and place it there manually if the remote has restricted network access." - :type '(choice (const nil :tag "Never") - (const ess-remote :tag "With ess-remote only") - (const t :tag "Always")) + :type '(choice (const :tag "Never" nil) + (const :tag "With ess-remote only" ess-remote) + (const :tag "Always" t)) :group 'ess-R) ;; Silence the byte compiler @@ -476,7 +476,7 @@ To be used as part of `font-lock-defaults' keywords." (ess-smart-operators . ess-r-smart-operators) (inferior-ess-program . inferior-ess-r-program) (inferior-ess-objects-command . inferior-ess-r-objects-command) - (inferior-ess-search-list-command . "search()\n") + (inferior-ess-search-list-command . "base::search()\n") (inferior-ess-help-command . inferior-ess-r-help-command) (inferior-ess-exit-command . "q()") (ess-error-regexp-alist . ess-r-error-regexp-alist) @@ -573,7 +573,7 @@ blocking commands will throw an error.") ;;;###autoload (defun run-ess-r (&optional start-args) - "Call 'R', the 'GNU S' system from the R Foundation. + "Call \\='R\\=', the \\='GNU S\\=' system from the R Foundation. Optional prefix (\\[universal-argument]) allows to set command line arguments, such as --vsize. This should be OS agnostic. If you have certain command line arguments that should always be passed @@ -2918,10 +2918,10 @@ needed." (defun ess-rutils-html-docs (&optional remote) "Use `browse-url' to navigate R html documentation. Documentation is produced by a modified help.start(), that -returns the URL produced by GNU R's http server. If called with a +returns the URL produced by GNU R\\='s http server. If called with a prefix, the modified help.start() is called with update=TRUE. The optional REMOTE argument should be a string with a valid URL for -the 'R_HOME' directory on a remote server (defaults to NULL)." +the \\='R_HOME\\=' directory on a remote server (defaults to NULL)." (interactive) (let* ((update (if current-prefix-arg "update=TRUE" "update=FALSE")) (remote (if (or (and remote (not (string= "" remote)))) diff --git a/lisp/ess/ess-rdired.el b/lisp/ess/ess-rdired.el index efc7fa1d..e025a5fd 100644 --- a/lisp/ess/ess-rdired.el +++ b/lisp/ess/ess-rdired.el @@ -87,7 +87,7 @@ (defcustom ess-rdired-auto-update-interval 5 "Seconds between refreshes of the `ess-rdired' buffer." - :type '(choice (const nil :tag "No auto updates") (integer :tag "Seconds")) + :type '(choice (const :tag "No auto updates" nil) (integer :tag "Seconds")) :group 'ess-R :package-version '(ess . "19.04")) diff --git a/lisp/ess/ess-sas-d.el b/lisp/ess/ess-sas-d.el index 98afed49..5cf147b9 100644 --- a/lisp/ess/ess-sas-d.el +++ b/lisp/ess/ess-sas-d.el @@ -287,7 +287,7 @@ indent line." (SAS))) (defun SAS () - "Call 'SAS', from SAS Institute." + "Call \\='SAS\\=', from SAS Institute." (interactive) (let* ((temp-dialect "SAS")) ;(cdr (rassoc ess-dialect SAS-customize-alist)))) (ess-write-to-dribble-buffer diff --git a/lisp/ess/ess-tracebug.el b/lisp/ess/ess-tracebug.el index 0a17d556..f7f2698f 100644 --- a/lisp/ess/ess-tracebug.el +++ b/lisp/ess/ess-tracebug.el @@ -555,9 +555,9 @@ If \\='strip, remove all such instances. Otherwise, if non-nil, `+ `ess-long+replacement'. This variable can be process-local but not buffer-local." :group 'ess-tracebug - :type '(choice (const nil :tag "No replacement") - (const strip :tag "Replace all") - (const t :tag "Replace 3 or more +"))) + :type '(choice (const :tag "No replacement" nil) + (const :tag "Replace all" strip) + (const :tag "Replace 3 or more +" t))) (defvar ess-long+replacement ". + " "Replacement used for long + prompt. diff --git a/lisp/ess/ess.el b/lisp/ess/ess.el index c12943ee..a807ab34 100644 --- a/lisp/ess/ess.el +++ b/lisp/ess/ess.el @@ -17,7 +17,8 @@ ;; ;; Maintainer: ESS Core Team ;; Created: 7 Jan 1994 -;; Version: 25.01.0 +;; Package-Version: 20250606.831 +;; Package-Revision: cd85d1e1f0e8 ;; URL: https://ess.r-project.org/ ;; Package-Requires: ((emacs "25.1")) ;; ESSR-Version: 1.8 diff --git a/lisp/ess/essd-els.el b/lisp/ess/essd-els.el index f1612cd6..67040a2b 100644 --- a/lisp/ess/essd-els.el +++ b/lisp/ess/essd-els.el @@ -62,7 +62,7 @@ The default value is nil." "Variables to customize for S+elsewhere.") (defun S+elsewhere (&optional _proc-name) - "Call 'S-PLUS 3.x', the 'Real Thing' from StatSci." + "Call \\='S-PLUS 3.x\\=', the \\='Real Thing\\=' from StatSci." ;; git commit 104c4d7c56bc239ea245562763caa317bc3a1a84 (declare (obsolete ess-remote "2000")) (ess-write-to-dribble-buffer diff --git a/lisp/f/f-pkg.el b/lisp/f/f-pkg.el index 0d3a4cdf..15f14e53 100644 --- a/lisp/f/f-pkg.el +++ b/lisp/f/f-pkg.el @@ -1,16 +1,12 @@ -(define-package "f" "20241003.1131" "Modern API for working with files and directories" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "f" "20241003.1131" + "Modern API for working with files and directories." '((emacs "24.1") - (s "1.7.0") - (dash "2.2.0")) - :commit "931b6d0667fe03e7bf1c6c282d6d8d7006143c52" :authors - '(("Johan Andersson" . "johan.rejeep@gmail.com")) - :maintainers - '(("Lucien Cartier-Tilet" . "lucien@phundrak.com")) - :maintainer - '("Lucien Cartier-Tilet" . "lucien@phundrak.com") - :keywords - '("files" "directories") - :url "http://github.com/rejeep/f.el") -;; Local Variables: -;; no-byte-compile: t -;; End: + (s "1.7.0") + (dash "2.2.0")) + :url "http://github.com/rejeep/f.el" + :commit "931b6d0667fe03e7bf1c6c282d6d8d7006143c52" + :revdesc "931b6d0667fe" + :keywords '("files" "directories") + :authors '(("Johan Andersson" . "johan.rejeep@gmail.com")) + :maintainers '(("Lucien Cartier-Tilet" . "lucien@phundrak.com"))) diff --git a/lisp/f/f-shortdoc.el b/lisp/f/f-shortdoc.el index f5c82b7e..e72fa57c 100644 --- a/lisp/f/f-shortdoc.el +++ b/lisp/f/f-shortdoc.el @@ -2,7 +2,6 @@ ;; Author: Lucien Cartier-Tilet ;; Maintainer: Lucien Cartier-Tilet -;; Version: 0.1.0 ;; Package-Requires: ((emacs "28.1")) ;; Homepage: https://github.com/rejeep/f.el diff --git a/lisp/f/f.el b/lisp/f/f.el index 1ab08d7c..b5d3821c 100644 --- a/lisp/f/f.el +++ b/lisp/f/f.el @@ -4,7 +4,8 @@ ;; Author: Johan Andersson ;; Maintainer: Lucien Cartier-Tilet -;; Version: 0.21.0 +;; Package-Version: 20241003.1131 +;; Package-Revision: 931b6d0667fe ;; Package-Requires: ((emacs "24.1") (s "1.7.0") (dash "2.2.0")) ;; Keywords: files, directories ;; Homepage: http://github.com/rejeep/f.el diff --git a/lisp/flycheck-ledger/flycheck-ledger-pkg.el b/lisp/flycheck-ledger/flycheck-ledger-pkg.el index 9f9db70b..f5872ea3 100644 --- a/lisp/flycheck-ledger/flycheck-ledger-pkg.el +++ b/lisp/flycheck-ledger/flycheck-ledger-pkg.el @@ -1,15 +1,11 @@ -(define-package "flycheck-ledger" "20200304.2204" "Flycheck integration for ledger files" - '((emacs "24.1") +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "flycheck-ledger" "20200304.2204" + "Flycheck integration for ledger files." + '((emacs "24.1") (flycheck "0.15")) - :commit "628e25ba66604946085571652a94a54f4d1ad96f" :authors - '(("Steve Purcell" . "steve@sanityinc.com")) - :maintainers - '(("Steve Purcell" . "steve@sanityinc.com")) - :maintainer - '("Steve Purcell" . "steve@sanityinc.com") - :keywords - '("convenience" "languages" "tools") - :url "https://github.com/purcell/flycheck-ledger") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/purcell/flycheck-ledger" + :commit "628e25ba66604946085571652a94a54f4d1ad96f" + :revdesc "628e25ba6660" + :keywords '("convenience" "languages" "tools") + :authors '(("Steve Purcell" . "steve@sanityinc.com")) + :maintainers '(("Steve Purcell" . "steve@sanityinc.com"))) diff --git a/lisp/flycheck-ledger/flycheck-ledger.el b/lisp/flycheck-ledger/flycheck-ledger.el index 67593762..b0de2c59 100644 --- a/lisp/flycheck-ledger/flycheck-ledger.el +++ b/lisp/flycheck-ledger/flycheck-ledger.el @@ -4,7 +4,8 @@ ;; Author: Steve Purcell ;; Homepage: https://github.com/purcell/flycheck-ledger -;; Version: DEV +;; Package-Version: 20200304.2204 +;; Package-Revision: 628e25ba6660 ;; Keywords: convenience languages tools ;; Package-Requires: ((emacs "24.1") (flycheck "0.15")) diff --git a/lisp/flycheck-pos-tip/flycheck-pos-tip-pkg.el b/lisp/flycheck-pos-tip/flycheck-pos-tip-pkg.el index ea9c1dec..bc706fa1 100644 --- a/lisp/flycheck-pos-tip/flycheck-pos-tip-pkg.el +++ b/lisp/flycheck-pos-tip/flycheck-pos-tip-pkg.el @@ -1,17 +1,13 @@ -(define-package "flycheck-pos-tip" "20200516.1600" "Display Flycheck errors in GUI tooltips" - '((emacs "24.1") +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "flycheck-pos-tip" "20200516.1600" + "Display Flycheck errors in GUI tooltips." + '((emacs "24.1") (flycheck "0.22") - (pos-tip "0.4.6")) - :commit "dc57beac0e59669926ad720c7af38b27c3a30467" :authors - '(("Akiha Senda" . "senda.akiha@gmail.com") - ("Sebastian Wiesner" . "swiesner@lunaryorn.com")) - :maintainers - '(("Sebastian Wiesner" . "swiesner@lunaryorn.com")) - :maintainer - '("Sebastian Wiesner" . "swiesner@lunaryorn.com") - :keywords - '("tools" "convenience") - :url "https://github.com/flycheck/flycheck-pos-tip") -;; Local Variables: -;; no-byte-compile: t -;; End: + (pos-tip "0.4.6")) + :url "https://github.com/flycheck/flycheck-pos-tip" + :commit "dc57beac0e59669926ad720c7af38b27c3a30467" + :revdesc "dc57beac0e59" + :keywords '("tools" "convenience") + :authors '(("Akiha Senda" . "senda.akiha@gmail.com") + ("Sebastian Wiesner" . "swiesner@lunaryorn.com")) + :maintainers '(("Sebastian Wiesner" . "swiesner@lunaryorn.com"))) diff --git a/lisp/flycheck-pos-tip/flycheck-pos-tip.el b/lisp/flycheck-pos-tip/flycheck-pos-tip.el index 58672178..8b500756 100644 --- a/lisp/flycheck-pos-tip/flycheck-pos-tip.el +++ b/lisp/flycheck-pos-tip/flycheck-pos-tip.el @@ -8,7 +8,8 @@ ;; Maintainer: Sebastian Wiesner ;; URL: https://github.com/flycheck/flycheck-pos-tip ;; Keywords: tools, convenience -;; Version: 0.4-cvs +;; Package-Version: 20200516.1600 +;; Package-Revision: dc57beac0e59 ;; Package-Requires: ((emacs "24.1") (flycheck "0.22") (pos-tip "0.4.6")) ;; This file is not part of GNU Emacs. diff --git a/lisp/flycheck/flycheck-pkg.el b/lisp/flycheck/flycheck-pkg.el index b725ec15..e18a3696 100644 --- a/lisp/flycheck/flycheck-pkg.el +++ b/lisp/flycheck/flycheck-pkg.el @@ -1,16 +1,12 @@ -(define-package "flycheck" "20250226.1541" "On-the-fly syntax checking" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "flycheck" "20250527.907" + "On-the-fly syntax checking." '((emacs "27.1")) - :commit "b9db1379dcc3e59238dc1fdd7db368c66e8734ba" :authors - '(("Sebastian Wiesner" . "swiesner@lunaryorn.com")) - :maintainers - '(("Clément Pit-Claudel" . "clement.pitclaudel@live.com") - ("fmdkdd" . "fmdkdd@gmail.com") - ("Bozhidar Batsov" . "bozhidar@batsov.dev")) - :maintainer - '("Clément Pit-Claudel" . "clement.pitclaudel@live.com") - :keywords - '("convenience" "languages" "tools") - :url "https://www.flycheck.org") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://www.flycheck.org" + :commit "a4d782e7af12e20037c0cecf0d4386cd2676c085" + :revdesc "a4d782e7af12" + :keywords '("convenience" "languages" "tools") + :authors '(("Sebastian Wiesner" . "swiesner@lunaryorn.com")) + :maintainers '(("Clément Pit-Claudel" . "clement.pitclaudel@live.com") + ("fmdkdd" . "fmdkdd@gmail.com") + ("Bozhidar Batsov" . "bozhidar@batsov.dev"))) diff --git a/lisp/flycheck/flycheck.el b/lisp/flycheck/flycheck.el index 98abb04f..94a74cd3 100644 --- a/lisp/flycheck/flycheck.el +++ b/lisp/flycheck/flycheck.el @@ -10,7 +10,8 @@ ;; Bozhidar Batsov ;; URL: https://www.flycheck.org ;; Keywords: convenience, languages, tools -;; Version: 35.0-snapshot +;; Package-Version: 20250527.907 +;; Package-Revision: a4d782e7af12 ;; Package-Requires: ((emacs "27.1")) ;; This file is not part of GNU Emacs. @@ -179,6 +180,7 @@ lua-luacheck lua markdown-markdownlint-cli + markdown-markdownlint-cli2 markdown-mdl markdown-pymarkdown nix @@ -1274,7 +1276,7 @@ Only has effect when variable `global-flycheck-mode' is non-nil." -(defconst flycheck-version "35.0-snapshot" +(defconst flycheck-version "35.0" "The current version of Flycheck. Should be kept in sync with the package version metadata. @@ -10891,6 +10893,7 @@ See URL `https://docs.astral.sh/ruff/'." :command ("ruff" "check" (config-file "--config" flycheck-python-ruff-config) + ;; older versions of ruff (before 0.2) used "text" instead of "concise" "--output-format=concise" (option "--stdin-filename" buffer-file-name) "-") @@ -11300,6 +11303,35 @@ See URL `https://github.com/igorshubovych/markdownlint-cli'." (url "https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#%s")) (and error-code `(url . ,(format url error-code)))))) +(flycheck-def-config-file-var flycheck-markdown-markdownlint-cli2-config + markdown-markdownlint-cli2 + '(".markdownlint-cli2.json" ".markdownlint-cli2.jsonc" ".markdownlint-cli2.yaml") + :package-version '(flycheck . "35")) + +(flycheck-define-checker markdown-markdownlint-cli2 + "Markdown checker using markdownlint-cli2. + +See URL `https://github.com/DavidAnson/markdownlint-cli2'." + :command ("markdownlint-cli2" + (config-file "--config" flycheck-markdown-markdownlint-cli2-config) + "--" + source) + :error-patterns + ((error line-start + (file-name) ":" line + (? ":" column) " " (id (one-or-more (not (any space)))) + " " (message) line-end)) + :error-filter + (lambda (errors) + (flycheck-sanitize-errors + (flycheck-remove-error-file-names "(string)" errors))) + :modes (markdown-mode gfm-mode) + :error-explainer + (lambda (err) + (let ((error-code (substring (flycheck-error-id err) 0 5)) + (url "https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#%s")) + (and error-code `(url . ,(format url error-code)))))) + (flycheck-def-option-var flycheck-markdown-mdl-rules nil markdown-mdl "Rules to enable for mdl. @@ -11361,7 +11393,7 @@ See URL `https://github.com/markdownlint/markdownlint'." See URL `https://pypi.org/project/pymarkdownlnt/'." :command ("pymarkdown" - (config-file "--config" flycheck-markdown-markdownlint-cli-config) + (config-file "--config" flycheck-markdown-pymarkdown-config) "scan" source) :error-patterns diff --git a/lisp/flyspell-correct-ivy/flyspell-correct-ivy-pkg.el b/lisp/flyspell-correct-ivy/flyspell-correct-ivy-pkg.el index 45719b15..7dfa2c56 100644 --- a/lisp/flyspell-correct-ivy/flyspell-correct-ivy-pkg.el +++ b/lisp/flyspell-correct-ivy/flyspell-correct-ivy-pkg.el @@ -1,14 +1,11 @@ -(define-package "flyspell-correct-ivy" "20220520.630" "Correcting words with flyspell via ivy interface" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "flyspell-correct-ivy" "20220520.630" + "Correcting words with flyspell via ivy interface." '((flyspell-correct "0.6.1") - (ivy "0.8.0") - (emacs "24.4")) - :commit "7d7b6b01188bd28e20a13736ac9f36c3367bd16e" :authors - '(("Boris Buliga" . "boris@d12frosted.io")) - :maintainers - '(("Boris Buliga" . "boris@d12frosted.io")) - :maintainer - '("Boris Buliga" . "boris@d12frosted.io") - :url "https://github.com/d12frosted/flyspell-correct") -;; Local Variables: -;; no-byte-compile: t -;; End: + (ivy "0.8.0") + (emacs "24.4")) + :url "https://github.com/d12frosted/flyspell-correct" + :commit "7d7b6b01188bd28e20a13736ac9f36c3367bd16e" + :revdesc "7d7b6b01188b" + :authors '(("Boris Buliga" . "boris@d12frosted.io")) + :maintainers '(("Boris Buliga" . "boris@d12frosted.io"))) diff --git a/lisp/flyspell-correct-ivy/flyspell-correct-ivy.el b/lisp/flyspell-correct-ivy/flyspell-correct-ivy.el index 3f315e9b..ab1533eb 100644 --- a/lisp/flyspell-correct-ivy/flyspell-correct-ivy.el +++ b/lisp/flyspell-correct-ivy/flyspell-correct-ivy.el @@ -4,7 +4,8 @@ ;; ;; Author: Boris Buliga ;; URL: https://github.com/d12frosted/flyspell-correct -;; Version: 0.6.1 +;; Package-Version: 20220520.630 +;; Package-Revision: 7d7b6b01188b ;; Package-Requires: ((flyspell-correct "0.6.1") (ivy "0.8.0") (emacs "24.4")) ;; ;; This file is not part of GNU Emacs. diff --git a/lisp/flyspell-correct/flyspell-correct-ido.el b/lisp/flyspell-correct/flyspell-correct-ido.el index b4520ecc..3ab3fd90 100644 --- a/lisp/flyspell-correct/flyspell-correct-ido.el +++ b/lisp/flyspell-correct/flyspell-correct-ido.el @@ -4,7 +4,6 @@ ;; ;; Author: Boris Buliga ;; URL: https://github.com/d12frosted/flyspell-correct -;; Version: 0.6.1 ;; Package-Requires: ((flyspell-correct "0.6.1") (emacs "24.1")) ;; ;; This file is not part of GNU Emacs. diff --git a/lisp/flyspell-correct/flyspell-correct-pkg.el b/lisp/flyspell-correct/flyspell-correct-pkg.el index d422c498..250e57eb 100644 --- a/lisp/flyspell-correct/flyspell-correct-pkg.el +++ b/lisp/flyspell-correct/flyspell-correct-pkg.el @@ -1,12 +1,9 @@ -(define-package "flyspell-correct" "20220520.630" "Correcting words with flyspell via custom interface" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "flyspell-correct" "20220520.630" + "Correcting words with flyspell via custom interface." '((emacs "24")) - :commit "7d7b6b01188bd28e20a13736ac9f36c3367bd16e" :authors - '(("Boris Buliga" . "boris@d12frosted.io")) - :maintainers - '(("Boris Buliga" . "boris@d12frosted.io")) - :maintainer - '("Boris Buliga" . "boris@d12frosted.io") - :url "https://github.com/d12frosted/flyspell-correct") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/d12frosted/flyspell-correct" + :commit "7d7b6b01188bd28e20a13736ac9f36c3367bd16e" + :revdesc "7d7b6b01188b" + :authors '(("Boris Buliga" . "boris@d12frosted.io")) + :maintainers '(("Boris Buliga" . "boris@d12frosted.io"))) diff --git a/lisp/flyspell-correct/flyspell-correct.el b/lisp/flyspell-correct/flyspell-correct.el index c661340c..0a6b1f2e 100644 --- a/lisp/flyspell-correct/flyspell-correct.el +++ b/lisp/flyspell-correct/flyspell-correct.el @@ -4,7 +4,8 @@ ;; ;; Author: Boris Buliga ;; URL: https://github.com/d12frosted/flyspell-correct -;; Version: 0.6.1 +;; Package-Version: 20220520.630 +;; Package-Revision: 7d7b6b01188b ;; Package-Requires: ((emacs "24")) ;; ;; This file is not part of GNU Emacs. diff --git a/lisp/focus/focus-pkg.el b/lisp/focus/focus-pkg.el index 80d7b209..3f31c263 100644 --- a/lisp/focus/focus-pkg.el +++ b/lisp/focus/focus-pkg.el @@ -1,13 +1,10 @@ -(define-package "focus" "20241029.1506" "Dim the font color of text in surrounding sections" - '((emacs "24.3") +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "focus" "20241029.1506" + "Dim the font color of text in surrounding sections." + '((emacs "24.3") (cl-lib "0.5")) - :commit "29b412b209c3542a7932c201f0166e48c9fd7fee" :authors - '(("Lars Tveito" . "larstvei@ifi.uio.no")) - :maintainers - '(("Lars Tveito" . "larstvei@ifi.uio.no")) - :maintainer - '("Lars Tveito" . "larstvei@ifi.uio.no") - :url "http://github.com/larstvei/Focus") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "http://github.com/larstvei/Focus" + :commit "29b412b209c3542a7932c201f0166e48c9fd7fee" + :revdesc "29b412b209c3" + :authors '(("Lars Tveito" . "larstvei@ifi.uio.no")) + :maintainers '(("Lars Tveito" . "larstvei@ifi.uio.no"))) diff --git a/lisp/focus/focus.el b/lisp/focus/focus.el index 290b805e..dff2383f 100644 --- a/lisp/focus/focus.el +++ b/lisp/focus/focus.el @@ -5,7 +5,8 @@ ;; Author: Lars Tveito ;; URL: http://github.com/larstvei/Focus ;; Created: 11th May 2015 -;; Version: 1.0.1 +;; Package-Version: 20241029.1506 +;; Package-Revision: 29b412b209c3 ;; Package-Requires: ((emacs "24.3") (cl-lib "0.5")) ;; This program is free software; you can redistribute it and/or modify diff --git a/lisp/git-messenger/git-messenger-pkg.el b/lisp/git-messenger/git-messenger-pkg.el index 08ca9fbd..744fcd9d 100644 --- a/lisp/git-messenger/git-messenger-pkg.el +++ b/lisp/git-messenger/git-messenger-pkg.el @@ -1,9 +1,9 @@ -(define-package "git-messenger" "20201202.1637" "Popup last commit of current line" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "git-messenger" "20201202.1637" + "Popup last commit of current line." '((emacs "24.3") (popup "0.5.3")) - :commit "fb9a049ac3b5fba7369ef1f027b97881f1e377ec" :authors - '(("Syohei YOSHIDA" . "syohex@gmail.com")) - :url "https://github.com/emacsorphanage/git-messenger") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/emacsorphanage/git-messenger" + :commit "fb9a049ac3b5fba7369ef1f027b97881f1e377ec" + :revdesc "fb9a049ac3b5" + :authors '(("Syohei YOSHIDA" . "syohex@gmail.com"))) diff --git a/lisp/git-messenger/git-messenger.el b/lisp/git-messenger/git-messenger.el index bc1ec0c2..0b8e16d4 100644 --- a/lisp/git-messenger/git-messenger.el +++ b/lisp/git-messenger/git-messenger.el @@ -5,7 +5,8 @@ ;; Author: Syohei YOSHIDA ;; Maintainer: Neil Okamoto ;; URL: https://github.com/emacsorphanage/git-messenger -;; Version: 0.18 +;; Package-Version: 20201202.1637 +;; Package-Revision: fb9a049ac3b5 ;; Package-Requires: ((emacs "24.3") (popup "0.5.3")) ;; This program is free software; you can redistribute it and/or modify diff --git a/lisp/gnuplot/dir b/lisp/gnuplot/dir new file mode 100644 index 00000000..37ad9fe4 --- /dev/null +++ b/lisp/gnuplot/dir @@ -0,0 +1,18 @@ +This is the file .../info/dir, which contains the +topmost node of the Info hierarchy, called (dir)Top. +The first time you invoke Info you start off looking at this node. + +File: dir, Node: Top This is the top of the INFO tree + + This (the Directory node) gives a menu of major topics. + Typing "q" exits, "H" lists all Info commands, "d" returns here, + "h" gives a primer for first-timers, + "mEmacs" visits the Emacs manual, etc. + + In Emacs, you can click mouse button 2 on a menu item or cross reference + to select it. + +* Menu: + +Math +* GNUPLOT: (gnuplot). An Interactive Plotting Program diff --git a/lisp/gnuplot/gnuplot-context.el b/lisp/gnuplot/gnuplot-context.el index 6b49ea78..1dd29451 100644 --- a/lisp/gnuplot/gnuplot-context.el +++ b/lisp/gnuplot/gnuplot-context.el @@ -2,8 +2,7 @@ ;; Copyright (C) 2012-2013 Jon Oddie -;; Author: Jon Oddie -;; URL: https://github.com/emacs-gnuplot/gnuplot +;; Author: Jon Oddie ;; This file is not part of GNU Emacs. @@ -41,30 +40,18 @@ ;; ;; Gnuplot's context sensitive mode is best controlled using Customize ;; (M-x customize-group gnuplot): simply enable the -;; `gnuplot-context-sensitive-mode' setting. You may also want to turn -;; on `gnuplot-tab-completion' so that the TAB key does auto-completion -;; on lines which are already indented. (This just sets the Emacs -;; variable `tab-always-indent' to `complete' in Gnuplot buffers). +;; `gnuplot-context-sensitive-mode' setting. You may also want to set +;; the Emacs variable `tab-always-indent' to `complete' so that the +;; TAB key does auto-completion on lines which are already indented. ;; ;; If you need to turn context sensitivity on or off from Lisp code ;; for some reason, call the function ;; `gnuplot-context-sensitive-mode', which behaves like a minor mode. ;; -;; With `eldoc-mode' support, gnuplot-mode will show one-line syntax -;; hints automatically in the echo area. Whether eldoc-mode is active -;; or not, you can always pop up a longer description of syntax using -;; `gnuplot-help-function' (C-c C-/ or C-c M-h). ElDoc support also -;; requires an additional file of help strings, `gnuplot-eldoc.el', -;; which should be included in recent Gnuplot releases. If it didn't -;; come with your Gnuplot installation, you'll need to grab a recent -;; source distribution of Gnuplot from http://gnuplot.info, and use -;; the `doc2texi.el' program in the docs/ directory to create it. So -;; long as the file is on your Emacs load path somewhere it will be -;; loaded automatically when needed. -;; -;; You can customize gnuplot-mode to turn on eldoc mode automatically -;; using variable `gnuplot-eldoc-mode'. Simply calling `eldoc-mode' -;; will also work. +;; With `eldoc-mode' support, `gnuplot-mode' will show one-line syntax +;; hints automatically in the echo area. Whether `eldoc-mode' is +;; active or not, you can always pop up a longer description of syntax +;; using `gnuplot-context-help-at-point' (C-c C-/ or C-c M-h). ;; ;; Internal details ;; ================ @@ -74,20 +61,22 @@ ;; features was to do a complete parse of the command line. So that's ;; what this package does. Instead of building a parse tree, it ;; matches up until the token at point, and then either makes a list -;; of possible completions, or sets the variables `gnuplot-eldoc' and -;; `gnuplot-info-at-point' based on where it is in the grammar at that -;; point. +;; of possible completions, or sets the variables +;; `gnuplot-context--eldoc' and `gnuplot-context--info-at-point' based +;; on where it is in the grammar at that point. ;; ;; The parsing/matching process happens in two phases: tokenizing -;; (`gnuplot-tokenize') and matching (`gnuplot-match-pattern'). In -;; order to be able to construct a full list of possible completions -;; via backtracking, the matching algorithm simulates a simple stack -;; machine with continuations. At byte-compile time, the PEG-like -;; grammar in S-expression notation (`gnuplot-grammar') is compiled -;; down into a vector of "machine code" for the parsing machine (see -;; `gnuplot-compile-pattern', `gnuplot-compile-grammar' and -;; `gnuplot-compiled-grammar'). This is complicated, but it seems to -;; work well enough, and it saves on the Emacs call stack. +;; (`gnuplot-context--tokenize') and matching +;; (`gnuplot-context--match-pattern'). In order to be able to +;; construct a full list of possible completions via backtracking, the +;; matching algorithm simulates a simple stack machine with +;; continuations. At byte-compile time, the PEG-like grammar in +;; S-expression notation (`gnuplot-grammar') is compiled down into a +;; vector of "machine code" for the parsing machine (see +;; `gnuplot-context--compile-pattern', +;; `gnuplot-context--compile-grammar' and +;; `gnuplot-context--compiled-grammar'). This is complicated, but it +;; seems to work well enough, and it saves on the Emacs call stack. ;; ;; Compiling the grammar does require increasing `max-lisp-eval-depth' ;; modestly. This shouldn't cause any problems on modern machines, and @@ -100,9 +89,9 @@ ;; The pattern-matching language ;; ============================= ;; -;; The gnuplot-mode grammar (see `gnuplot-compiled-grammar') is a list -;; of rules (RULE PATTERN), with each pattern written in S-expression -;; notation as follows: +;; The gnuplot-mode grammar (see `gnuplot-context--compiled-grammar') +;; is a list of rules (RULE PATTERN), with each pattern written in +;; S-expression notation as follows: ;; ;; any ;; Match any token @@ -166,8 +155,8 @@ ;; ;; (capture NAME PATTERN) ;; Match PATTERN, capturing the tokens in a capture group named -;; NAME. Capture groups are stored in `gnuplot-captures' -;; and can be retrieved using `gnuplot-capture-group'. This is +;; NAME. Capture groups are stored in `gnuplot-context--captures' +;; and can be retrieved using `gnuplot-context--capture-group'. This is ;; used to store the plotting style, which we need in order to ;; give the correct ElDoc string for "using" clauses, and for ;; info keywords (see below) @@ -192,7 +181,7 @@ ;; Evaluate LISP-FORM and fail if it returns NIL. We need this in ;; the patterns for "plot" and "splot" to check whether the ;; command at point should be parsed in parametric mode or -;; not. See `gnuplot-guess-parametric-p'. +;; not. See `gnuplot-context--guess-parametric-p'. ;; ;; ;; Bugs, TODOs, etc. @@ -229,22 +218,21 @@ ;;; Code: -(require 'cl-lib) (require 'gnuplot) -(require 'eldoc) -(require 'info) -(require 'info-look) +(require 'gnuplot-eldoc) ;;;; The tokenizer. -(cl-defstruct gnuplot-token +(cl-defstruct (gnuplot-context--token + (:constructor gnuplot-context--token-make) + (:copier nil)) start ; Buffer start position end ; Buffer end position id ; Text type) ; a symbol: name, number, string, operator, separator -(defvar gnuplot-operator-regexp +(defvar gnuplot-context--operator-regexp (eval-when-compile (regexp-opt '("(" ")" "(" ")" "{" "," "}" "[" ":" "]" "!" "**" "-" "+" "~" "!" "*" "/" @@ -253,7 +241,7 @@ "Regexp to match Gnuplot operators for tokenizing.") (eval-when-compile - (defmacro gnuplot-tokenize-by-regexps (&rest rules) + (defmacro gnuplot-context--tokenize-by-regexps (&rest rules) `(cond ,@(mapcar (lambda (rule) (let ((regexp (car rule)) @@ -261,27 +249,27 @@ `((looking-at ,regexp) (let ((str (match-string-no-properties 0))) (forward-char (length str)) - (make-gnuplot-token :id str - :type ',token-type - :start (match-beginning 0) - :end (match-end 0)))))) + (gnuplot-context--token-make :id str + :type ',token-type + :start (match-beginning 0) + :end (match-end 0)))))) rules)))) -(defun gnuplot-tokenize (&optional completing-p) +(defun gnuplot-context--tokenize (&optional completing-p) "Tokenize the Gnuplot command at point. -Return a list of `gnuplot-token' objects. +Return a list of `gnuplot-context--token' objects. If COMPLETING-P is non-nil, omits the token at point if it is a name; otherwise continues tokenizing up to the token at point. FIXME." (let ((tokens '()) (stop-point (min (point) - (gnuplot-point-at-end-of-command)))) + (gnuplot--point-at-end-of-command)))) (save-excursion (if (save-excursion ; HACK FIXME - (gnuplot-beginning-of-continuation) + (gnuplot--beginning-of-continuation) (looking-at "\\s-*if\\s-*(")) - (gnuplot-beginning-of-continuation) - (gnuplot-beginning-of-command)) + (gnuplot--beginning-of-continuation) + (gnuplot--beginning-of-command)) (while ;; Skip whitespace and continuation lines (progn @@ -295,23 +283,23 @@ name; otherwise continues tokenizing up to the token at point. FIXME." (let* ((from (point)) (token (cond - ((gnuplot-tokenize-by-regexps + ((gnuplot-context--tokenize-by-regexps ("[[:alpha:]_][[:alpha:]0-9_]*" name) ("[0-9]+\\(\\.[0-9]*\\)?\\([eE][+-]?[0-9]+\\)?\\|\\.[0-9]+\\([eE][+-]?[0-9]+\\)?" number) - (gnuplot-operator-regexp operator) + (gnuplot-context--operator-regexp operator) (";" separator))) ((looking-at "['\"]") (let* ((bounds (bounds-of-thing-at-point 'sexp)) (to (or (cdr bounds) stop-point))) (goto-char to) - (make-gnuplot-token + (gnuplot-context--token-make :id (buffer-substring-no-properties from to) :type 'string :start from :end to))) (t (error - "Gnuplot-tokenize: bad token beginning %s" + "gnuplot-context--tokenize: bad token beginning %s" (buffer-substring-no-properties (point) stop-point)))))) (push token tokens)))) @@ -323,19 +311,18 @@ name; otherwise continues tokenizing up to the token at point. FIXME." ;; in that position for completion. (if (and completing-p tokens - (eq (gnuplot-token-type (car tokens)) 'name) - (<= (point) (gnuplot-token-end (car tokens)))) + (eq (gnuplot-context--token-type (car tokens)) 'name) + (<= (point) (gnuplot-context--token-end (car tokens)))) (pop tokens)) (nreverse tokens))) - ;;;; The pattern and grammar compiler ;; ;; These functions compile the source S-expression grammar into a ;; vector of instructions for the parsing machine, -;; `gnuplot-match-pattern'. Its state consists of a program counter +;; `gnuplot-context--match-pattern'. Its state consists of a program counter ;; (PC), a position in the list of tokens, a call stack, and a second ;; stack of backtracking entries (continuations). Its "machine ;; instructions" are the following: @@ -344,15 +331,15 @@ name; otherwise continues tokenizing up to the token at point. FIXME." ;; Match any token (fails only at end of command). ;; ;; (literal LITERAL NO-COMPLETE) -;; Match token with `gnuplot-token-id' LITERAL or fail. If we +;; Match token with `gnuplot-context--token-id' LITERAL or fail. If we ;; have reached the token before point, include LITERAL in the ;; completion list unless NO-COMPLETE is non-`nil'. ;; ;; (token-type TYPE) -;; Match a token with `gnuplot-token-type' TYPE, or fail. +;; Match a token with `gnuplot-context--token-type' TYPE, or fail. ;; ;; (keyword REGEXP NAME) -;; Match any token whose `gnuplot-token-id' matches REGEXP. Use +;; Match any token whose `gnuplot-context--token-id' matches REGEXP. Use ;; NAME for the completion list. ;; ;; (jump OFFSET FIXED) @@ -404,12 +391,12 @@ name; otherwise continues tokenizing up to the token at point. FIXME." ;; ;; (save-start NAME) ;; Open a capture group named NAME. Pushes an entry onto -;; `gnuplot-captures' with current position in token list as the +;; `gnuplot-context--captures' with current position in token list as the ;; start of the group. ;; ;; (save-end NAME) ;; Close the capture group named NAME. Finds the topmost entry in -;; `gnuplot-captures' with this name and sets its endpoint to the +;; `gnuplot-context--captures' with this name and sets its endpoint to the ;; current position in token list. Error if no group with that ;; name is found. ;; @@ -419,13 +406,12 @@ name; otherwise continues tokenizing up to the token at point. FIXME." ;; for debugging purposes. ;; - (eval-and-compile ;; Compile a single pattern into a list of instructions. Leaves ;; calls to other rules as symbolic instructions (call SYMBOL) and ;; jumps, commits etc. as relative offsets; these are resolved into - ;; absolute locations by `gnuplot-compile-grammar', below. - (defun gnuplot-compile-pattern (pat) + ;; absolute locations by `gnuplot-context--compile-grammar', below. + (defun gnuplot-context--compile-pattern (pat) (cond ;; Strings match a single token literally ((stringp pat) @@ -442,7 +428,7 @@ name; otherwise continues tokenizing up to the token at point. FIXME." ;; Syntactic sugar: write sequences (sequence ...) as vectors [...] ((vectorp pat) - (gnuplot-compile-pattern + (gnuplot-context--compile-pattern (append '(sequence) pat '()))) ;; Other forms combine simpler patterns @@ -454,11 +440,11 @@ name; otherwise continues tokenizing up to the token at point. FIXME." ((sequence) (cl-destructuring-bind (subpats eldoc info) - (gnuplot-filter-arg-list (cdr pat)) + (gnuplot-context--filter-arg-list (cdr pat)) (let ((eldoc-push '()) (eldoc-pop '()) (info-push '()) (info-pop '()) (compiled - (mapcar 'gnuplot-compile-pattern subpats))) + (mapcar 'gnuplot-context--compile-pattern subpats))) (if eldoc (setq eldoc-push `((push eldoc ,eldoc)) eldoc-pop `((pop eldoc)))) @@ -479,16 +465,16 @@ name; otherwise continues tokenizing up to the token at point. FIXME." ((either) (cond ((= (length pat) 2) ; trivial case - (gnuplot-compile-pattern (cadr pat))) + (gnuplot-context--compile-pattern (cadr pat))) ((> (length pat) 3) ; could be more efficient... - (gnuplot-compile-pattern (gnuplot-either-helper pat))) + (gnuplot-context--compile-pattern (gnuplot-context--either-helper pat))) (t ; two patterns (let* ((pat1 (cadr pat)) (pat2 (cl-caddr pat)) - (pat1-c (gnuplot-compile-pattern pat1)) - (pat2-c (gnuplot-compile-pattern pat2)) + (pat1-c (gnuplot-context--compile-pattern pat1)) + (pat2-c (gnuplot-context--compile-pattern pat2)) (pat1-l (length pat1-c)) (pat2-l (length pat2-c))) `((choice ,(+ pat1-l 2)) @@ -499,7 +485,7 @@ name; otherwise continues tokenizing up to the token at point. FIXME." ;; Repetition (*) ((many) (let* ((pat1 (cons 'sequence (cdr pat))) - (pat1-c (gnuplot-compile-pattern pat1)) + (pat1-c (gnuplot-context--compile-pattern pat1)) (pat1-l (length pat1-c))) `((choice ,(+ pat1-l 3)) (check-progress) ; bail out of infinite loops @@ -509,14 +495,13 @@ name; otherwise continues tokenizing up to the token at point. FIXME." ;; Repetition (+) ((many1) (let* ((pat1 (cdr pat))) - (gnuplot-compile-pattern + (gnuplot-context--compile-pattern `(sequence ,@pat1 (many ,@pat1))))) - ;; Optional (?) ((maybe) (let* ((pat1 (cons 'sequence (cdr pat))) - (pat1-c (gnuplot-compile-pattern pat1)) + (pat1-c (gnuplot-context--compile-pattern pat1)) (pat1-l (length pat1-c))) `((choice ,(+ pat1-l 1)) ,@pat1-c))) @@ -525,20 +510,20 @@ name; otherwise continues tokenizing up to the token at point. FIXME." ((delimited-list) (let* ((item (cadr pat)) (sep (cl-caddr pat))) - (gnuplot-compile-pattern + (gnuplot-context--compile-pattern `(sequence ,item (many (sequence ,sep ,item)))))) ;; keywords ((kw) (cl-destructuring-bind (regex name) - (gnuplot-keyword-helper (cdr pat)) + (gnuplot-context--keyword-helper (cdr pat)) `((keyword ,regex ,name)))) ;; Capturing groups ((capture) (let* ((name (cadr pat)) (pat1 (cons 'sequence (cddr pat))) - (pat1-c (gnuplot-compile-pattern pat1))) + (pat1-c (gnuplot-context--compile-pattern pat1))) `((save-start ,name) ,@pat1-c (save-end ,name)))) @@ -546,7 +531,7 @@ name; otherwise continues tokenizing up to the token at point. FIXME." ;; Use the first token as an info keyword ((info-keyword) (let* ((pat1 (cons 'sequence (cdr pat))) - (pat1-c (gnuplot-compile-pattern pat1))) + (pat1-c (gnuplot-context--compile-pattern pat1))) `((push info first-token) ,@pat1-c (pop info)))) @@ -557,12 +542,12 @@ name; otherwise continues tokenizing up to the token at point. FIXME." `((assert ,form)))) (t - (error "Gnuplot-compile-pattern: bad pattern form %s" pat))))))) + (error "gnuplot-context--compile-pattern: bad pattern form %s" pat))))))) ;; Helper function for destructuring (sequence ...) forms in patterns ;; Takes the cdr of the sequence form, returns a list (PATTERNS ELDOC ;; INFO). - (defun gnuplot-filter-arg-list (args) + (defun gnuplot-context--filter-arg-list (args) (let ((accum '()) (eldoc nil) (info nil)) (dolist (item args) @@ -576,7 +561,7 @@ name; otherwise continues tokenizing up to the token at point. FIXME." ;; Helper function for compiling (kw...) patterns ;; Takes the cdr of the kw form, returns a list (REGEXP KEYWORD) - (defun gnuplot-keyword-helper (args) + (defun gnuplot-context--keyword-helper (args) (let ((keyword (car args)) (aliases (cdr args))) (when (consp keyword) (let ((pre (car keyword)) (suf (cdr keyword))) @@ -594,18 +579,18 @@ name; otherwise continues tokenizing up to the token at point. FIXME." ;; Helper function for compiling (either ...) patterns. Rewrites ;; alternates (either A B C) into (either A (either B (either C D))) - (defun gnuplot-either-helper (pat) + (defun gnuplot-context--either-helper (pat) (if (= (length pat) 3) pat `(either ,(cadr pat) - ,(gnuplot-either-helper + ,(gnuplot-context--either-helper (cons 'either (cddr pat)))))) ;; Compile the grammar (a list of rule-pattern pairs (RULE PATTERN)) ;; into a single vector of matching-machine instructions. Compiles ;; each pattern individually, then "links" them into one vector, ;; converting symbolic (call ...) instructions into numeric offsets - (defun gnuplot-compile-grammar (grammar start-symbol) + (defun gnuplot-context--compile-grammar (grammar start-symbol) (let ((compiled-pats '()) ; Alist of (name . instructions) ;; Reserve space for a jump to the start symbol (code-length 1)) @@ -614,7 +599,7 @@ name; otherwise continues tokenizing up to the token at point. FIXME." (dolist (item grammar) (let* ((name (car item)) (pat (cadr item)) - (code (gnuplot-compile-pattern pat))) + (code (gnuplot-context--compile-pattern pat))) (push (cons name code) compiled-pats) ;; Reserve space for a label at the beginning and (return) at ;; the end @@ -653,7 +638,7 @@ name; otherwise continues tokenizing up to the token at point. FIXME." (location (gethash name name->offset))) (if (not location) (error - (concat "gnuplot-compile-grammar: " + (concat "gnuplot-context--compile-grammar: " "No rule found for symbol `%s' in pattern `%s'") name pattern-name)) (setcdr inst `(,location ,name)))) @@ -664,14 +649,14 @@ name; otherwise continues tokenizing up to the token at point. FIXME." (setcdr inst `(,location)))) (t - (error "Gnuplot-compile-grammar: bad instruction %s" inst)))))))) + (error "gnuplot-context--compile-grammar: bad instruction %s" inst)))))))) object-code)))) ;;; The grammar. -(defvar gnuplot-compiled-grammar +(defvar gnuplot-context--compiled-grammar (eval-when-compile (let ((max-lisp-eval-depth 600)) - (gnuplot-compile-grammar + (gnuplot-context--compile-grammar '((expression [infix-expression (maybe "?" expression ":" expression)]) @@ -781,7 +766,7 @@ name; otherwise continues tokenizing up to the token at point. FIXME." (either ;; Parametric ranges - [(assert (gnuplot-guess-parametric-p)) + [(assert (gnuplot-context--guess-parametric-p)) (maybe t-axis-range) (maybe x-axis-range) (maybe y-axis-range)] ;; Non-parametric ranges @@ -790,13 +775,13 @@ name; otherwise continues tokenizing up to the token at point. FIXME." plot-body]) (splot-command - [ ;; This capturing group lets `gnuplot-find-using-eldoc' know + [ ;; This capturing group lets `gnuplot-context--find-using-eldoc' know ;; that this is an splot command (capture :splot-command (kw ("spl" . "ot"))) (either ;; Parametric ranges - [(assert (gnuplot-guess-parametric-p)) + [(assert (gnuplot-context--guess-parametric-p)) (maybe u-axis-range) (maybe v-axis-range) (maybe x-axis-range) (maybe y-axis-range) (maybe z-axis-range)] @@ -1007,7 +992,7 @@ name; otherwise continues tokenizing up to the token at point. FIXME." [(kw "thru") expression]) (using-modifier - [(:eldoc gnuplot-find-using-eldoc) + [(:eldoc gnuplot-context--find-using-eldoc) (kw ("u" . "sing")) (either string @@ -1660,7 +1645,6 @@ name; otherwise continues tokenizing up to the token at point. FIXME." "zzeroaxis") (maybe linestyle-spec)]) - ;;; Other commands (cd-command ["cd" string]) @@ -1720,58 +1704,52 @@ name; otherwise continues tokenizing up to the token at point. FIXME." ;; them. For normal use, they compile to no-ops. (eval-when-compile (when (not (featurep 'gnuplot-debug-context)) - (defmacro with-gnuplot-trace-buffer (&rest _) "No-op." '(progn nil)) - (defmacro gnuplot-trace (&rest _) "No-op." '(progn nil)) - (defmacro gnuplot-debug (&rest _) "No-op." '(progn nil)))) - + (defmacro gnuplot-context--with-trace-buffer (&rest _) "No-op." '(progn nil)) + (defmacro gnuplot-context--trace (&rest _) "No-op." '(progn nil)) + (defmacro gnuplot-context--debug (&rest _) "No-op." '(progn nil)))) ;;;; Variables to be set via pattern matching -(defvar gnuplot-completions nil +(defvar gnuplot-context--completions nil "List of possible `gnuplot-mode' completions at point. -This is filled in by `gnuplot-match-pattern' when it reaches the +This is filled in by `gnuplot-context--match-pattern' when it reaches the token before point.") -(defvar gnuplot-info-at-point nil +(defvar gnuplot-context--info-at-point nil "Relevant page of the Gnuplot info manual for the construction at point. -Set by `gnuplot-match-pattern' using information from -`gnuplot-compiled-grammar'. `gnuplot-match-pattern' pushes ElDoc -and info strings onto the stack as it runs, and scans the stack -for the topmost entry when it reaches the token at point.") +Set by `gnuplot-context--match-pattern' using information from +`gnuplot-context--compiled-grammar'. `gnuplot-context--match-pattern' +pushes ElDoc and info strings onto the stack as it runs, and scans the +stack for the topmost entry when it reaches the token at point.") -(defvar gnuplot-eldoc nil - "ElDoc documentation string for the Gnuplot construction at point. - -Set by `gnuplot-match-pattern'. See also `gnuplot-info-at-point'.") - -(defvar gnuplot-captures nil +(defvar gnuplot-context--captures nil "Alist of named capture groups for `gnuplot-mode' completion code. Each entry is of the form (NAME BEGIN END), where NAME is the name specified in the (capture NAME PATTERN) form in the -`gnuplot-compiled-grammar' source, BEGIN is the tail of the token +`gnuplot-context--compiled-grammar' source, BEGIN is the tail of the token list beginning the capture group, and END is the tail of the token list just after the end of the capture group.") -(defvar gnuplot-eldoc-hash nil - "ElDoc strings for `gnuplot-mode'. +(defvar gnuplot-context--eldoc nil + "ElDoc documentation string for the Gnuplot construction at point. -These have to be compiled from the Gnuplot source tree using -`doc2texi.el'.") +Set by `gnuplot-context--match-pattern'. See also +`gnuplot-context-info-at-point'.") ;;;; The pattern matching machine -(defun gnuplot-match-pattern (instructions tokens completing-p - &optional start-symbol) +(defun gnuplot-context--match-pattern (instructions tokens completing-p + &optional start-symbol) "Parse TOKENS, setting completions, info and ElDoc information. This function parses TOKENS by simulating a stack machine with unlimited backtracking. If COMPLETING-P is non-nil, it stops before the token at point and collects a list of the next tokens -that it would accept in `gnuplot-completions'. If COMPLETING-P is -nil, it parses up to the token at point and sets `gnuplot-eldoc' -and `gnuplot-info-at-point' based on the contents of the stack +that it would accept in `gnuplot-context--completions'. If COMPLETING-P is +nil, it parses up to the token at point and sets `gnuplot-context--eldoc' +and `gnuplot-context--info-at-point' based on the contents of the stack there." (catch 'return (let ((pc 0) ; Program counter @@ -1789,7 +1767,7 @@ there." ;; of conses (pc . tokens) (progress '())) - (with-gnuplot-trace-buffer (erase-buffer)) + (gnuplot-context--with-trace-buffer (erase-buffer)) (when start-symbol ; HACK FIXME (let ((look-for `(label ,start-symbol))) @@ -1797,17 +1775,17 @@ there." (cl-incf pc)) (cl-incf pc))) - (setq gnuplot-completions nil - gnuplot-eldoc nil - gnuplot-info-at-point nil - gnuplot-captures nil) + (setq gnuplot-context--completions nil + gnuplot-context--eldoc nil + gnuplot-context--info-at-point nil + gnuplot-context--captures nil) (cl-flet ((advance - () - (pop tokens) - (if (and (null tokens) (not completing-p)) - (gnuplot-scan-stack stack tokens))) - (fail () (setq fail t))) + () + (pop tokens) + (if (and (null tokens) (not completing-p)) + (gnuplot-context--scan-stack stack tokens))) + (fail () (setq fail t))) ;; Main loop (while t @@ -1815,7 +1793,7 @@ there." (opcode (car inst)) (token (car tokens)) (end-of-tokens (null tokens))) - (gnuplot-trace "%s\t%s\t%s\n" pc inst (and token (gnuplot-token-id token))) + (gnuplot-context--trace "%s\t%s\t%s\n" pc inst (and token (gnuplot-context--token-id token))) (cl-case opcode ;; (literal LITERAL NO-COMPLETE) @@ -1824,11 +1802,11 @@ there." (no-complete (cl-caddr inst))) (cond (end-of-tokens (unless no-complete - (gnuplot-trace "\tpushing \"%s\" to completions\n" expect) - (push expect gnuplot-completions)) + (gnuplot-context--trace "\tpushing \"%s\" to completions\n" expect) + (push expect gnuplot-context--completions)) (fail)) - ((not (equal (gnuplot-token-id token) expect)) + ((not (equal (gnuplot-context--token-id token) expect)) (fail)) ;; otherwise succeed @@ -1838,7 +1816,7 @@ there." ((token-type) (let ((expect (cadr inst))) (if (or end-of-tokens - (not (eq (gnuplot-token-type token) expect))) + (not (eq (gnuplot-context--token-type token) expect))) (fail) (advance)))) @@ -1848,16 +1826,16 @@ there." (let ((regexp (cadr inst)) (name (cl-caddr inst))) (cond (end-of-tokens - (gnuplot-trace "\tpushing \"%s\" to completions\n" name) - (push name gnuplot-completions) + (gnuplot-context--trace "\tpushing \"%s\" to completions\n" name) + (push name gnuplot-context--completions) (fail)) - ((not (string-match-p regexp (gnuplot-token-id token))) + ((not (string-match-p regexp (gnuplot-context--token-id token))) (fail)) ;; otherwise succeed (t - (setf (gnuplot-token-id token) name) + (setf (gnuplot-context--token-id token) name) (advance))))) ;; (any): match any token @@ -1896,7 +1874,7 @@ there." ;; backtracking points and continue at next instruction ((choice) (let ((location (cadr inst))) - (push `(,stack ,tokens ,location ,gnuplot-captures + (push `(,stack ,tokens ,location ,gnuplot-context--captures ,progress) backtrack))) @@ -1938,17 +1916,17 @@ there." ;; beginning of capture group NAME ((save-start) (let ((name (cadr inst))) - (push `(,name ,tokens nil) gnuplot-captures))) + (push `(,name ,tokens nil) gnuplot-context--captures))) ;; (save-end NAME): save current token pointer as end of ;; capture group NAME ((save-end) (let* ((name (cadr inst)) - (record (assoc name gnuplot-captures))) + (record (assoc name gnuplot-context--captures))) (if (not record) (error "Gnuplot-match-tokens: no open capture group named %s" name) (setf (cl-caddr record) tokens) - (gnuplot-debug (gnuplot-dump-captures))))) + (gnuplot-context--debug (gnuplot-dump-captures))))) ;; (check-progress): make sure not stuck in an infinite loop ((check-progress) @@ -1968,12 +1946,12 @@ there." (when fail (if (not backtrack) ; Out of backtracking stack: failed match (throw 'return nil) - (gnuplot-trace "\t*fail*\t%s\n" (length backtrack)) - (gnuplot-debug (gnuplot-dump-backtrack backtrack)) + (gnuplot-context--trace "\t*fail*\t%s\n" (length backtrack)) + (gnuplot-context--debug (gnuplot-dump-backtrack backtrack)) ;; If we got as far as token-at-point before failing, ;; scan the stack for eldoc and info strings (when (and end-of-tokens (not completing-p)) - (gnuplot-scan-stack stack tokens)) + (gnuplot-context--scan-stack stack tokens)) (cl-destructuring-bind (bt-stack bt-tokens bt-pc bt-captures bt-progress) @@ -1981,20 +1959,20 @@ there." (setq stack bt-stack tokens bt-tokens pc bt-pc - gnuplot-captures bt-captures + gnuplot-context--captures bt-captures progress bt-progress fail nil) - (gnuplot-debug (gnuplot-dump-progress progress))))))))))) + (gnuplot-context--debug (gnuplot-dump-progress progress))))))))))) -(defun gnuplot-scan-stack (stack tokens) +(defun gnuplot-context--scan-stack (stack tokens) "Scan STACK for the most recently pushed eldoc and info strings." - (gnuplot-trace "\t* scanning stack *\n") - (gnuplot-debug (gnuplot-backtrace stack)) - (gnuplot-debug (gnuplot-dump-captures)) + (gnuplot-context--trace "\t* scanning stack *\n") + (gnuplot-context--debug (gnuplot-backtrace stack)) + (gnuplot-context--debug (gnuplot-dump-captures)) (catch 'no-scan (while (and stack - (not (and gnuplot-info-at-point gnuplot-eldoc))) + (not (and gnuplot-context--info-at-point gnuplot-context--eldoc))) (let* ((item (car stack)) (type (car item)) (position (cl-caddr item))) ; must progress by at least one token @@ -2005,34 +1983,34 @@ there." (throw 'no-scan nil)) ((info) - (when (not gnuplot-info-at-point) + (when (not gnuplot-context--info-at-point) (let ((info (cadr item))) - (setq gnuplot-info-at-point + (setq gnuplot-context--info-at-point (cond ((eq info 'first-token) - (gnuplot-token-id (car position))) + (gnuplot-context--token-id (car position))) ((functionp info) (funcall info)) (t info))) - (when gnuplot-info-at-point - (gnuplot-trace "\tset info to \"%s\"\n" gnuplot-info-at-point) - (when (and (not gnuplot-eldoc) gnuplot-eldoc-hash) + (when gnuplot-context--info-at-point + (gnuplot-context--trace "\tset info to \"%s\"\n" gnuplot-context--info-at-point) + (unless gnuplot-context--eldoc (let ((eldoc - (car (gethash gnuplot-info-at-point gnuplot-eldoc-hash)))) + (car (gethash gnuplot-context--info-at-point gnuplot-eldoc-hash)))) (when eldoc - (setq gnuplot-eldoc eldoc) - (gnuplot-trace "\tand set eldoc to \"%s\"\n" eldoc)))))))) + (setq gnuplot-context--eldoc eldoc) + (gnuplot-context--trace "\tand set eldoc to \"%s\"\n" eldoc)))))))) ((eldoc) - (when (not gnuplot-eldoc) + (when (not gnuplot-context--eldoc) (let ((eldoc (cadr item))) - (setq gnuplot-eldoc + (setq gnuplot-context--eldoc (if (functionp eldoc) (funcall eldoc) eldoc)) - (gnuplot-trace "\tset eldoc to \"%s\"\n" gnuplot-eldoc))))))) + (gnuplot-context--trace "\tset eldoc to \"%s\"\n" gnuplot-context--eldoc))))))) (pop stack)))) -(defun gnuplot-capture-group (name) +(defun gnuplot-context--capture-group (name) "Return capture group NAME from the most recent parse, as a list of tokens." - (let ((record (assoc name gnuplot-captures))) + (let ((record (assoc name gnuplot-context--captures))) (if (not record) nil (let ((begin (cadr record)) (end (cl-caddr record)) @@ -2041,60 +2019,55 @@ there." (push (pop begin) accum)) (nreverse accum))))) -(defun gnuplot-capture-group->string (name) - (let ((tokens (gnuplot-capture-group name))) - (and tokens - (mapconcat 'gnuplot-token-id tokens " ")))) - ;;; Interface to the matching machine -(defun gnuplot-parse-at-point (completing-p) - (let ((tokens (gnuplot-tokenize completing-p))) - (gnuplot-match-pattern gnuplot-compiled-grammar tokens completing-p))) +(defun gnuplot-context--parse-at-point (completing-p) + (let ((tokens (gnuplot-context--tokenize completing-p))) + (gnuplot-context--match-pattern gnuplot-context--compiled-grammar tokens completing-p))) ;; Completions -(defun gnuplot-completions () - (gnuplot-parse-at-point t) - gnuplot-completions) +(defun gnuplot-context--completions () + (gnuplot-context--parse-at-point t) + gnuplot-context--completions) (defun gnuplot-context-completion-at-point () "Return completions of keyword preceding point, using context." (list (save-excursion - (skip-syntax-backward "w_" (gnuplot-point-at-beginning-of-command)) + (skip-syntax-backward "w_" (gnuplot--point-at-beginning-of-command)) (point)) (point) - (gnuplot-completions))) + (gnuplot-context--completions))) ;; Eldoc help -(defun gnuplot-eldoc-function () +(defun gnuplot-context-eldoc-function (&rest _) "Return the ElDoc string for the Gnuplot construction at point." - (gnuplot-parse-at-point nil) - gnuplot-eldoc) + (gnuplot-context--parse-at-point nil) + gnuplot-context--eldoc) -(defun gnuplot-help-function () +(defun gnuplot-context-help-at-point () "Pop up the extended documentation for the construction at point." - (interactive) - (gnuplot-parse-at-point nil) - (if (and gnuplot-info-at-point gnuplot-eldoc-hash) + (interactive nil gnuplot-mode gnuplot-comint-mode) + (gnuplot-context--parse-at-point nil) + (if gnuplot-context--info-at-point (let ((eldoc - (cadr (gethash gnuplot-info-at-point gnuplot-eldoc-hash)))) + (cadr (gethash gnuplot-context--info-at-point gnuplot-eldoc-hash)))) (if eldoc (message eldoc))))) ;; Info lookup -(defun gnuplot-info-at-point (&optional query) +(defun gnuplot-context-info-at-point (&optional query) "Open the relevant gnuplot info page for the construction at point." - (interactive "P") - (setq gnuplot-info-at-point nil) + (interactive "P" gnuplot-mode gnuplot-comint-mode) + (setq gnuplot-context--info-at-point nil) (unless query - (gnuplot-parse-at-point nil)) - (if (or query (not gnuplot-info-at-point)) + (gnuplot-context--parse-at-point nil)) + (if (or query (not gnuplot-context--info-at-point)) (let ((info (info-lookup-interactive-arguments 'symbol))) - (setq gnuplot-info-at-point (car info)))) - (when gnuplot-info-at-point - (gnuplot--find-info-node gnuplot-info-at-point))) + (setq gnuplot-context--info-at-point (car info)))) + (when gnuplot-context--info-at-point + (gnuplot-context--find-info-node gnuplot-context--info-at-point))) -(defun gnuplot--find-info-node (node) +(defun gnuplot-context--find-info-node (node) (save-window-excursion (info (format "(gnuplot)%s" node))) (gnuplot--adjust-info-display)) @@ -2105,7 +2078,7 @@ there." ;; ElDoc strings for "using" specs, which depend on other information ;; from the parsed command -(defvar gnuplot-using-eldoc +(defvar gnuplot-context--using-eldoc '(("boxerrorbars" . "x:y:ydelta{:xdelta} | x:y:ylow:yhigh{:xdelta}") ("boxes" . "x:y{:x_width}") ("boxxyerrorbars" . "x:y:xdelta:ydelta | x:y:xlow:xhigh:ylow:yhigh") @@ -2133,7 +2106,7 @@ there." ("xyerrorlines" . "x:y:xdelta:ydelta | x:y:xlow:xhigh:ylow:yhigh")) "Alist of ElDoc strings for Gnuplot \"using\" clauses in \"plot\" commands.") -(defvar gnuplot-using-3d-eldoc +(defvar gnuplot-context--using-3d-eldoc (append '(("fsteps" . "z | x:y:z") ("histeps" . "z | x:y:z") @@ -2145,28 +2118,28 @@ there." ("lines" . "z | x:y:z") ("steps" . "z | x:y:z") ("vectors" . "x:y:z:xdelta:ydelta:zdelta")) - gnuplot-using-eldoc) + gnuplot-context--using-eldoc) "Alist of ElDoc strings for Gnuplot \"using\" clauses in \"splot\" commands.") -(defun gnuplot-find-using-eldoc () +(defun gnuplot-context--find-using-eldoc () "Return ElDoc string for a Gnuplot \"using\" clause, based on plotting style. This will fail if the \"using\" clause comes before the \"with\" clause." - (let ((with-style (gnuplot-capture-group :with-style)) - (3d-p (gnuplot-capture-group :splot-command)) + (let ((with-style (gnuplot-context--capture-group :with-style)) + (3d-p (gnuplot-context--capture-group :splot-command)) (column-description nil)) (if with-style - (let ((with-style-string (gnuplot-token-id (car with-style)))) + (let ((with-style-string (gnuplot-context--token-id (car with-style)))) (setq column-description (or (and 3d-p - (cdr (assoc with-style-string gnuplot-using-3d-eldoc))) - (cdr (assoc with-style-string gnuplot-using-eldoc)) + (cdr (assoc with-style-string gnuplot-context--using-3d-eldoc))) + (cdr (assoc with-style-string gnuplot-context--using-eldoc)) "")))) (format "using %s {'format'}" column-description))) ;;; Needed for correctly parsing plot commands -(defun gnuplot-guess-parametric-p (&optional start) +(defun gnuplot-context--guess-parametric-p (&optional start) "Guess whether the command beginning at START is in parametric mode. Searches backward in current buffer for an \"(un)set parametric\" @@ -2176,13 +2149,11 @@ command." (catch 'result (while (search-backward-regexp "reset\\|set\\s-+parametric" (point-min) t) - (gnuplot-beginning-of-command) + (gnuplot--beginning-of-command) (cond ((looking-at "reset\\|unset\\s-+parametric") (throw 'result nil)) ((looking-at "set\\s-+parametric") (throw 'result t)))) nil))) - -;;;###autoload (define-minor-mode gnuplot-context-sensitive-mode "Use context-sensitive completion and help in `gnuplot-mode'. @@ -2198,70 +2169,35 @@ Key bindings: \\[completion-at-point] will complete the keyword at point based on its context in the command. To make keyword completion work on -pressing TAB, set `tab-always-indent' to `complete', or customize -`gnuplot-tab-completion' to make this automatic in gnuplot-mode -buffers. +pressing TAB, set `tab-always-indent' to `complete'. -\\[gnuplot-info-at-point] will try to find the most relevant +\\[gnuplot-context-info-at-point] will try to find the most relevant Gnuplot info node for the construction at point, prompting for a node name if nothing is found. -\\[gnuplot-help-function] will pop up a brief summary of the +\\[gnuplot-context-help-at-point] will pop up a brief summary of the syntax at point in the minibuffer. To have one-line syntax summaries appear in the echo area as you type, toggle -`eldoc-mode' or customize `gnuplot-eldoc-mode'. +`eldoc-mode'. To choose whether to use this mode by default in Gnuplot buffers, customize the variable -`gnuplot-use-context-sensitive-completion'. - -Note: help strings for eldoc-mode and \\[gnuplot-help-function] -need to be provided in an Emacs-readable form by the Gnuplot -distribution. See gnuplot-context.el for details." +`gnuplot-use-context-sensitive-completion'." + :interactive (gnuplot-mode gnuplot-comint-mode) :keymap - `((,(kbd "C-c C-/") . gnuplot-help-function) - (,(kbd "C-c C-d") . gnuplot-info-at-point)) + `((,(kbd "C-c C-/") . gnuplot-context-help-at-point) + (,(kbd "C-c C-d") . gnuplot-context-info-at-point)) (unless (derived-mode-p 'gnuplot-mode 'gnuplot-comint-mode) (message "Gnuplot context-sensitive mode works only in Gnuplot-mode buffers") (setq gnuplot-context-sensitive-mode nil)) (if gnuplot-context-sensitive-mode - ;; Turn on (progn - (setq gnuplot-completion-at-point-function #'gnuplot-context-completion-at-point) + (remove-hook 'completion-at-point-functions #'gnuplot-completion-at-point-info-look t) + (add-hook 'completion-at-point-functions #'gnuplot-context-completion-at-point nil t) + (add-hook 'eldoc-documentation-functions #'gnuplot-context-eldoc-function nil 'local)) + (add-hook 'completion-at-point-functions #'gnuplot-completion-at-point-info-look nil t) + (remove-hook 'completion-at-point-functions #'gnuplot-context-completion-at-point t) + (remove-hook 'eldoc-documentation-functions #'gnuplot-context-eldoc-function t))) - ;; Setup Eldoc - (setq-local eldoc-documentation-function #'gnuplot-eldoc-function) - (eldoc-add-command 'completion-at-point) ; Check for eldoc after completion - - ;; Try to load Eldoc strings - (when gnuplot-eldoc-mode - (unless gnuplot-eldoc-hash - (condition-case nil - (load-library "gnuplot-eldoc") - (error - (message "gnuplot-eldoc.el not found. Install it from the Gnuplot distribution.") - (setq gnuplot-eldoc-hash nil - gnuplot-eldoc-mode nil)))) - - (if gnuplot-eldoc-hash - (eldoc-mode 1) - (eldoc-mode 0))) - - ;; Set up tab-to-complete - (when gnuplot-tab-completion - (setq-local tab-always-indent 'complete))) - - ;; Turn off - (setq gnuplot-completion-at-point-function #'gnuplot-completion-at-point-info-look) - (setq eldoc-documentation-function nil) - (eldoc-mode 0))) - - -;;; All done! (provide 'gnuplot-context) - -;; Local Variables: -;; indent-tabs-mode: nil -;; End: - ;;; gnuplot-context.el ends here diff --git a/lisp/gnuplot/gnuplot-eldoc.el b/lisp/gnuplot/gnuplot-eldoc.el new file mode 100644 index 00000000..0425ffe9 --- /dev/null +++ b/lisp/gnuplot/gnuplot-eldoc.el @@ -0,0 +1,631 @@ +;;; gnuplot-eldoc.el -- Eldoc documentation strings for gnuplot-mode -*- lexical-binding: t -*- +;;; Automatically generated by doc2texi.el on Sun, 01 June 2025 + +;;;; This file is generated automatically from the Gnuplot +;;;; documentation by `doc2texi.el', part of the Gnuplot distribution. +;;;; It is not intended to be edited manually. See docs/gnuplot.doc +;;;; in the gnuplot source tree (available from +;;;; gnuplot.sourcefourge.net) for the original. + +;; This file is covered by the Gnuplot licensing terms: + +;; Copyright 1986 - 1993, 1998, 2004 Thomas Williams, Colin Kelley +;; +;; Permission to use, copy, and distribute this software and its +;; documentation for any purpose with or without fee is hereby granted, +;; provided that the above copyright notice appear in all copies and +;; that both that copyright notice and this permission notice appear +;; in supporting documentation. +;; +;; Permission to modify the software is granted, but not the right to +;; distribute the complete modified source code. Modifications are to +;; be distributed as patches to the released version. Permission to +;; distribute binaries produced by compiling modified sources is granted, +;; provided you +;; 1. distribute the corresponding source modifications from the +;; released version in the form of a patch file along with the binaries, +;; 2. add special version identification to distinguish your version +;; in addition to the base release version number, +;; 3. provide your name and address as the primary contact for the +;; support of your modified version, and +;; 4. retain our contact information in regard to use of the base +;; software. +;; Permission to distribute the released version of the source code along +;; with corresponding source modifications in the form of a patch file is +;; granted with same provisions 2 through 4 for binary distributions. +;; +;; This software is provided "as is" without express or implied warranty +;; to the extent permitted by applicable law. + +(eval-when-compile (defvar gnuplot-eldoc-hash nil)) +(setq gnuplot-eldoc-hash (let ((tbl (make-hash-table :test 'equal)) (alist '(("x11" "set terminal x11 { | window \"\"} [more ...]" "set terminal x11 { | window \"\"} + {title \"\"} + {{no}enhanced} {font } + {linewidth LW} + {{no}persist} {{no}raise} {{no}ctrlq} + {{no}replotonresize} + {close} + {size XX,YY} {position XX,YY} +set terminal x11 {reset}") ("wxt" "set term wxt {} [more ...]" "set term wxt {} + {size ,} {position ,} + {background | nobackground} + {{no}enhanced} + {font } {fontscale } + {title \"title\"} + {linewidth } {butt|rounded|square} + {dashlength
} + {{no}persist} + {{no}raise} + {{no}ctrl} + {close}") ("windows" "set terminal windows {} [more ...]" "set terminal windows {} + {color | monochrome} + {solid | dashed} + {rounded | butt} + {enhanced | noenhanced} + {font } + {fontscale } + {linewidth } + {pointscale } + {background } + {title \"Plot Window Title\"} + {{size | wsize} ,} + {position ,} + {docked {layout ,} | standalone} + {close}") ("tpic" "set terminal tpic ") ("tkcanvas" "set terminal tkcanvas {tcl | perl | perltkx | python | ruby | rexx} [more ...]" "set terminal tkcanvas {tcl | perl | perltkx | python | ruby | rexx} + {standalone | input} + {interactive} + {rounded | butt} + {nobackground | background } + {{no}rottext} + {size ,} + {{no}enhanced} + {externalimages | pixels}") ("tgif" "set terminal tgif {portrait | landscape | default} {<[x,y]>} [more ...]" "set terminal tgif {portrait | landscape | default} {<[x,y]>} + {monochrome | color} + {{linewidth | lw} } + {solid | dashed} + {font \"{,}\"}") ("tek40" "set terminal sixeltek {} {mono|color|colors } {size ,} [more ...]" "set terminal sixeltek {} {mono|color|colors } {size ,} + {animate}") ("svg" "set terminal svg {size , {|fixed|dynamic}} [more ...]" "set terminal svg {size , {|fixed|dynamic}} + {mouse} {standalone | jsdir } + {name } + {font \"{,}\"} {{no}enhanced} + {fontscale } + {rounded|butt|square} {solid|dashed} {linewidth } + {background }") ("regis" "set terminal regis {4 | 16}\"") ("pstricks" "set terminal pstricks [more ...]" "set terminal pstricks + {unit | size {unit},{unit}} + {standalone | input} + {blacktext | colortext | colourtext} + {linewidth } {rounded | butt} + {pointscale } + {psarrows | gparrows} + {background } + {pstricks | pdftricks2}") ("pdf" "set terminal pdf {monochrome|color|colour} [more ...]" "set terminal pdf {monochrome|color|colour} + {{no}enhanced} + {fname \"\"} {fsize } + {font \"{,}\"} {fontscale } + {linewidth } {rounded|butt} + {dl }} + {size {unit},{unit}}") ("dospc" "set terminal dospc [more ...]" "set terminal dospc + {{no}{enhanced}} + {fontscale } {pointsize } {linewidth }") ("pbm" "set terminal pbm {} {} {size ,}") ("mif" "set terminal mif {color | colour | monochrome} {polyline | vectors} [more ...]" "set terminal mif {color | colour | monochrome} {polyline | vectors} + {help | ?}") ("mp" "set term mp {color | colour | monochrome} [more ...]" "set term mp {color | colour | monochrome} + {solid | dashed} + {notex | tex | latex} + {magnification } + {psnfss | psnfss-version7 | nopsnfss} + {prologues } + {a4paper} + {amstex} + {\" {,}\"} ") ("lua" "set terminal lua | \"\" [more ...]" "set terminal lua | \"\" + { ...} + {help}") ("latex" "set terminal {latex | emtex} {default | {courier|roman} {}} [more ...]" "set terminal {latex | emtex} {default | {courier|roman} {}} + {size {unit}, {unit}} {rotate | norotate} + {color | monochrome}") ("imagen" "set terminal imagen {} {portrait | landscape} [more ...]" "set terminal imagen {} {portrait | landscape} + {[,]}") ("hppj" "set terminal hppj {FNT5X9 | FNT9X17 | FNT13X25}") ("hpljii" "set terminal hpljii | hpdj {}") ("hpgl" "set terminal hpgl {} {eject} {fontscale }") ("hp500c" "set terminal hp500c {} {}") ("gpic" "set terminal gpic { }") ("ggi" "set terminal ggi [acceleration ] [[mode] {mode}]") ("png_" "set terminal png [more ...]" "set terminal png + {{no}enhanced} + {{no}transparent} {{no}interlace} + {{no}truecolor} {rounded|butt} + {linewidth } {dashlength
} + {tiny | small | medium | large | giant} + {font \" {,}\"} {fontscale } + {size ,} {{no}crop} + {background }") ("fig" "set terminal fig {monochrome | color} [more ...]" "set terminal fig {monochrome | color} + {small | big | size {in|cm},{in|cm}} + {landscape | portrait} + {pointsmax } + {font \"{,}\"} {fontsize } + {textnormal | {textspecial texthidden textrigid}} + {{linewidth|lw} }") ("epson_180dpi" "set terminal dpu414 {small | medium | large} {normal | draft}") ("epson_180dpi" "set terminal nec_cp6 {monochrome | colour | draft}") ("emf" "set terminal emf {color | monochrome} [more ...]" "set terminal emf {color | monochrome} + {enhanced {noproportional}} + {rounded | butt} + {linewidth } {dashlength
} + {size XX,YY} {background } + {font \"{,}\"} + {fontscale }") ("eepic" "set terminal eepic {default} {color|monochrome|dashed} [more ...]" "set terminal eepic {default} {color|monochrome|dashed} + {rotate} {size XX,YY} + {small|tiny|}") ("dumb" "set terminal dumb {size ,} {[no]feed} [more ...]" "set terminal dumb {size ,} {[no]feed} + {aspect {,}} + {[no]enhanced} + {fillchar {solid|\"\"}} + {[no]attributes} + {mono|ansi|ansi256|ansirgb}") ("svga" "set terminal svga {font \"\"} [more ...]" "set terminal svga {font \"\"} + {{no}enhanced} + {background } + {linewidth|lw } + {pointscale|ps } + {fontscale|fs }") ("corel" "set terminal corel {monochrome | color} {\"\" {}} [more ...]" "set terminal corel {monochrome | color} {\"\" {}} + { { }}") ("context" "set term context {default} [more ...]" "set term context {default} + {defaultsize | size | size {in|cm}, {in|cm}} + {input | standalone} + {timestamp | notimestamp} + {noheader | header \"
\"} + {color | colour | monochrome} + {rounded | mitered | beveled} {round | butt | squared} + {dashed | solid} {dashlength | dl
} + {linewidth | lw } + {fontscale } + {mppoints | texpoints} + {inlineimages | externalimages} + {defaultfont | font \"{}{,}\"}") ("cgm" "set terminal cgm {color | monochrome} {solid | dashed} {{no}rotate} [more ...]" "set terminal cgm {color | monochrome} {solid | dashed} {{no}rotate} + {} {width } {linewidth } + {font \",\"} + {background }") ("canvas" "set terminal canvas {size , } {background } [more ...]" "set terminal canvas {size , } {background } + {font {}{,}} | {fsize } + {{no}enhanced} {linewidth } + {rounded | butt | square} + {dashlength
} + {standalone {mousing} | name ''} + {jsdir 'URL/for/javascripts'} + {title ''}") ("be" "set terminal be {reset} {}") ("aqua" "set terminal aqua {} {title \"\"} {size } [more ...]" "set terminal aqua {} {title \"\"} {size } + {font \"{,}\"} + {linewidth }\"} + {{no}enhanced} {solid|dashed} {dl }}") ("aifm" "set terminal aifm {color|monochrome} {\"\"} {}") ("While" "while () { [more ...]" "while () { + +}") ("warn" "warn \"message\"") ("vfill" "vfill FILE using x:y:z:radius:() [more ...]" "vfill FILE using x:y:z:radius:() +vgfill FILE using x:y:z:radius:()") ("vclear" "vclear {$gridname}") ("linetype_" "unset linetype N") ("toggle" "toggle { | \"plottitle\" | all}") ("test" "test {terminal | palette}") ("system_" "system \"command string\" [more ...]" "system \"command string\" +! command string +output = system(\"command string\") +show variable GPVAL_SYSTEM") ("stats_(Statistical_Summary)" "stats {} 'filename' {matrix | using N{:M}} {name 'prefix'} {{no}output} [more ...]" "stats {} 'filename' {matrix | using N{:M}} {name 'prefix'} {{no}output} +stats $voxelgridname {name 'prefix'}") ("voxel-grid" "splot $voxelgridname with {dots|points} {above } ... [more ...]" "splot $voxelgridname with {dots|points} {above } ... +splot $voxelgridname with isosurface {level } ...") ("matrix" "plot 'file' matrix every {} [more ...]" "plot 'file' matrix every {} + {:{} + {:{} + {:{} + {:{} + {:}}}}}") ("matrix" "sparse matrix=(cols,rows) origin=(x0,y0) dx= dy=") ("data-file" "splot '' {binary } [more ...]" "splot '' {binary } + {{nonuniform|sparse} matrix} + {index } + {every } + {using }") ("splot" "splot {} [more ...]" "splot {} + {} + | {{ | } {datafile-modifiers}} + | + | keyentry + {} {with " nil t) (delete-region (1+ (match-end 0)) (point-max))) - (beginning-of-line 1) + (forward-line 0) (when (looking-at " +") (replace-match "")) (goto-char (point-min))) @@ -1861,36 +1873,43 @@ INFO is a plist used as a communication channel." (pcase (org-export-collect-footnote-definitions info) (`nil nil) (definitions + (format + (plist-get info :html-footnotes-section) + (org-html--translate "Footnotes" info) (format - (plist-get info :html-footnotes-section) - (org-html--translate "Footnotes" info) - (format - "\n%s\n" - (mapconcat - (lambda (definition) - (pcase definition - (`(,n ,_ ,def) - ;; `org-export-collect-footnote-definitions' can return - ;; two kinds of footnote definitions: inline and blocks. - ;; Since this should not make any difference in the HTML - ;; output, we wrap the inline definitions within - ;; a "footpara" class paragraph. - (let ((inline? (not (org-element-map def org-element-all-elements - #'identity nil t))) - (anchor (org-html--anchor - (format "fn.%d" n) - n - (format " class=\"footnum\" href=\"#fnr.%d\" role=\"doc-backlink\"" n) - info)) - (contents (org-trim (org-export-data def info)))) - (format "
%s %s
\n" - (format (plist-get info :html-footnote-format) anchor) - (format "
%s
" - (if (not inline?) contents - (format "

%s

" - contents)))))))) - definitions - "\n")))))) + "\n%s\n" + (mapconcat + (lambda (definition) + (pcase definition + (`(,n ,label ,def) + ;; Do not assign number labels as they appear in Org mode + ;; - the footnotes are re-numbered by + ;; `org-export-get-footnote-number'. If the label is not + ;; a number, keep it. + (when (and (stringp label) + (equal label (number-to-string (string-to-number label)))) + (setq label nil)) + ;; `org-export-collect-footnote-definitions' can return + ;; two kinds of footnote definitions: inline and blocks. + ;; Since this should not make any difference in the HTML + ;; output, we wrap the inline definitions within + ;; a "footpara" class paragraph. + (let ((inline? (not (org-element-map def org-element-all-elements + #'identity nil t))) + (anchor (org-html--anchor + (format "fn.%s" (or label n)) + n + (format " class=\"footnum\" href=\"#fnr.%s\" role=\"doc-backlink\"" (or label n)) + info)) + (contents (org-trim (org-export-data def info)))) + (format "
%s %s
\n" + (format (plist-get info :html-footnote-format) anchor) + (format "
%s
" + (if (not inline?) contents + (format "

%s

" + contents)))))))) + definitions + "\n")))))) ;;; Template @@ -2033,7 +2052,7 @@ INFO is a plist used as a communication channel." (when value (pcase symbol (`font - (when-let + (when-let* ((value-new (pcase value ("TeX" "mathjax-tex") @@ -2197,8 +2216,7 @@ holding export options." (format "%s\n" (format decl (or (and org-html-coding-system - ;; FIXME: Use Emacs 22 style here, see `coding-system-get'. - (coding-system-get org-html-coding-system 'mime-charset)) + (coding-system-get org-html-coding-system :mime-charset)) "iso-8859-1")))))) (org-html-doctype info) "\n" @@ -2272,7 +2290,9 @@ INFO is a plist used as a communication channel." ;;;; Anchor (defun org-html--anchor (id desc attributes info) - "Format a HTML anchor." + "Format a HTML anchor. +ID is the anchor id. ATTRIBUTES is the anchor attributes, as a string. +DESC is the anchor text. INFO is the info plist." (let* ((name (and (plist-get info :html-allow-name-attribute-in-anchors) id)) (attributes (concat (and id (format " id=\"%s\"" id)) (and name (format " name=\"%s\"" name)) @@ -2282,7 +2302,9 @@ INFO is a plist used as a communication channel." ;;;; Todo (defun org-html--todo (todo info) - "Format TODO keywords into HTML." + "Format TODO keywords into HTML. +TODO is the keyword, as a string. +INFO is the info plist." (when todo (format "%s" (if (member todo org-done-keywords) "done" "todo") @@ -2327,9 +2349,9 @@ is the language used for CODE, as a string, or nil." ((not org-html-htmlize-output-type) (org-html-encode-plain-text code)) ;; No htmlize library or an inferior version of htmlize. ((not (progn (require 'htmlize nil t) - (fboundp 'htmlize-region-for-paste))) + (fboundp 'htmlize-region-for-paste))) ;; Emit a warning. - (message "Cannot fontify source block (htmlize.el >= 1.34 required)") + (warn "Cannot fontify source block (htmlize.el >= 1.34 required). Falling back to plain text. (see `org-html-htmlize-output-type')") (org-html-encode-plain-text code)) (t ;; Map language @@ -2446,14 +2468,19 @@ of contents as a string, or nil if it is empty." (org-export-get-relative-level headline info))) (org-export-collect-headlines info depth scope)))) (when toc-entries - (let ((toc (concat "
" - (org-html--toc-text toc-entries) - "
\n"))) + (let* ((toc-id-counter (plist-get info :org-html--toc-counter)) + (toc (concat (format "
" + (if toc-id-counter (format "-%d" toc-id-counter) "")) + (org-html--toc-text toc-entries) + "
\n"))) + (plist-put info :org-html--toc-counter (1+ (or toc-id-counter 0))) (if scope toc (let ((outer-tag (if (org-html--html5-fancy-p info) "nav" "div"))) - (concat (format "<%s id=\"table-of-contents\" role=\"doc-toc\">\n" outer-tag) + (concat (format "<%s id=\"table-of-contents%s\" role=\"doc-toc\">\n" + outer-tag + (if toc-id-counter (format "-%d" toc-id-counter) "")) (let ((top-level (plist-get info :html-toplevel-hlevel))) (format "%s\n" top-level @@ -2670,7 +2697,10 @@ information." (let ((attributes (org-export-read-attribute :attr_html example-block))) (if (plist-get attributes :textarea) (org-html--textarea-block example-block) - (format "
\n%s
" + (if-let* ((class-val (plist-get attributes :class))) + (setq attributes (plist-put attributes :class (concat "example " class-val))) + (setq attributes (plist-put attributes :class "example"))) + (format "\n%s" (let* ((reference (org-html--reference example-block info)) (a (org-html--make-attribute-string (if (or (not reference) (plist-member attributes :id)) @@ -2714,19 +2744,36 @@ CONTENTS is nil. INFO is a plist holding contextual information." (concat ;; Insert separator between two footnotes in a row. (let ((prev (org-export-get-previous-element footnote-reference info))) - (when (eq (org-element-type prev) 'footnote-reference) + (when (org-element-type-p prev 'footnote-reference) (plist-get info :html-footnote-separator))) (let* ((n (org-export-get-footnote-number footnote-reference info)) - (id (format "fnr.%d%s" - n + (label (org-element-property :label footnote-reference)) + ;; Do not assign number labels as they appear in Org mode - + ;; the footnotes are re-numbered by + ;; `org-export-get-footnote-number'. If the label is not a + ;; number, keep it. + (label (if (and (stringp label) + (equal label (number-to-string (string-to-number label)))) + nil + label)) + (id (format "fnr.%s%s" + (or label n) (if (org-export-footnote-first-reference-p footnote-reference info) "" - ".100")))) + (let ((label (org-element-property :label footnote-reference))) + (format + ".%d" + (org-export-get-ordinal + footnote-reference info '(footnote-reference) + `(lambda (ref _) + (if ,label + (equal (org-element-property :label ref) ,label) + (not (org-element-property :label ref))))))))))) (format (plist-get info :html-footnote-format) (org-html--anchor - id n (format " class=\"footref\" href=\"#fn.%d\" role=\"doc-backlink\"" n) info))))) + id n (format " class=\"footref\" href=\"#fn.%s\" role=\"doc-backlink\"" (or label n)) info))))) ;;;; Headline @@ -2798,14 +2845,15 @@ holding contextual information." ;; empty one to get the correct
\n%s%s\n%s
" (org-html-format-headline-default-function todo todo-type priority text tags info) (org-html-close-tag "br" nil info) - contents)) + (or contents ""))) ;;;; Italic @@ -2893,7 +2945,10 @@ INFO is a plist holding contextual information. See (defun org-html-format-list-item (contents type checkbox info &optional term-counter-id headline) - "Format a list item into HTML." + "Format a list item into HTML. +CONTENTS is the item contents. TYPE is one of symbols `ordered', +`unordered', or `descriptive'. CHECKBOX checkbox type is nil or one of +symbols `on', `off', or `trans'. INFO is the info plist." (let ((class (if checkbox (format " class=\"%s\"" (symbol-name checkbox)) "")) @@ -2935,7 +2990,7 @@ INFO is a plist holding contextual information. See "Transcode an ITEM element from Org to HTML. CONTENTS holds the contents of the item. INFO is a plist holding contextual information." - (let* ((plain-list (org-export-get-parent item)) + (let* ((plain-list (org-element-parent item)) (type (org-element-property :type plain-list)) (counter (org-element-property :counter item)) (checkbox (org-element-property :checkbox item)) @@ -3034,7 +3089,7 @@ used as a predicate for `org-export-get-ordinal' or a value to (org-element-property :value element))) (defun org-html--latex-environment-numbered-p (element) - "Non-nil when ELEMENT contains a numbered LaTeX math environment. + "Non-nil when ELEMENT is a numbered LaTeX math environment. Starred and \"displaymath\" environments are not numbered." (not (string-match-p "\\`[ \t]*\\\\begin{\\(.*\\*\\|displaymath\\)}" (org-element-property :value element)))) @@ -3059,6 +3114,7 @@ CONTENTS is nil. INFO is a plist holding contextual information." (attributes (org-export-read-attribute :attr_html latex-environment)) (label (org-html--reference latex-environment info t)) (caption (and (org-html--latex-environment-numbered-p latex-environment) + (org-html--math-environment-p latex-environment) (number-to-string (org-export-get-ordinal latex-environment info nil @@ -3094,6 +3150,7 @@ CONTENTS is nil. INFO is a plist holding contextual information." (let ((latex-frag (org-element-property :value latex-fragment)) (processing-type (plist-get info :with-latex))) (cond + ;; FIXME: Duplicated value in ‘cond’: t ((memq processing-type '(t mathjax)) (org-html-format-latex latex-frag 'mathjax info)) ((memq processing-type '(t html)) @@ -3116,6 +3173,9 @@ CONTENTS is nil. INFO is a plist holding contextual information." ;;;; Link (defun org-html-image-link-filter (data _backend info) +"Process image links that are inside descriptions. +DATA is the parse tree. INFO is and info plist. +See `org-export-insert-image-links' for more details." (org-export-insert-image-links data info org-html-inline-image-rules)) (defun org-html-inline-image-p (link info) @@ -3162,10 +3222,10 @@ images, set it to: (lambda (paragraph) (org-element-property :caption paragraph))" (let ((paragraph (pcase (org-element-type element) (`paragraph element) - (`link (org-export-get-parent element))))) - (and (eq (org-element-type paragraph) 'paragraph) + (`link (org-element-parent element))))) + (and (org-element-type-p paragraph 'paragraph) (or (not (and (boundp 'org-html-standalone-image-predicate) - (fboundp org-html-standalone-image-predicate))) + (fboundp org-html-standalone-image-predicate))) (funcall org-html-standalone-image-predicate paragraph)) (catch 'exit (let ((link-count 0)) @@ -3205,8 +3265,6 @@ INFO is a plist holding contextual information. See (desc (org-string-nw-p desc)) (path (cond - ((member type '("http" "https" "ftp" "mailto" "news")) - (url-encode-url (concat type ":" raw-path))) ((string= "file" type) ;; During publishing, turn absolute file names belonging ;; to base directory into relative file names. Otherwise, @@ -3220,7 +3278,7 @@ INFO is a plist holding contextual information. See (org-trim (plist-get info :html-link-home))))) (when (and home (plist-get info :html-link-use-abs-url) - (file-name-absolute-p raw-path)) + (not (file-name-absolute-p raw-path))) (setq raw-path (concat (file-name-as-directory home) raw-path)))) ;; Maybe turn ".org" into ".html". (setq raw-path (funcall link-org-files-as-html-maybe raw-path info)) @@ -3233,16 +3291,16 @@ INFO is a plist holding contextual information. See (concat raw-path "#" (org-publish-resolve-external-link option path t)))))) - (t raw-path))) + (t (url-encode-url (concat type ":" raw-path))))) (attributes-plist (org-combine-plists ;; Extract attributes from parent's paragraph. HACK: Only ;; do this for the first link in parent (inner image link ;; for inline images). This is needed as long as ;; attributes cannot be set on a per link basis. - (let* ((parent (org-export-get-parent-element link)) - (link (let ((container (org-export-get-parent link))) - (if (and (eq 'link (org-element-type container)) + (let* ((parent (org-element-parent-element link)) + (link (let ((container (org-element-parent link))) + (if (and (org-element-type-p container 'link) (org-html-inline-image-p link info)) container link)))) @@ -3282,7 +3340,7 @@ INFO is a plist holding contextual information. See (pcase (org-element-type destination) ;; ID link points to an external file. (`plain-text - (let ((fragment (concat "ID-" path)) + (let ((fragment (concat org-html--id-attr-prefix raw-path)) ;; Treat links to ".org" files as ".html", if needed. (path (funcall link-org-files-as-html-maybe destination info))) @@ -3317,7 +3375,7 @@ INFO is a plist holding contextual information. See (_ (if (and destination (memq (plist-get info :with-latex) '(mathjax t)) - (eq 'latex-environment (org-element-type destination)) + (org-element-type-p destination 'latex-environment) (eq 'math (org-latex--environment-type destination))) ;; Caption and labels are introduced within LaTeX ;; environment. Use "ref" or "eqref" macro, depending on user @@ -3328,7 +3386,7 @@ INFO is a plist holding contextual information. See (org-html-standalone-image-predicate #'org-html--has-caption-p) (counter-predicate - (if (eq 'latex-environment (org-element-type destination)) + (if (org-element-type-p destination 'latex-environment) #'org-html--math-environment-p #'org-html--has-caption-p)) (number @@ -3349,15 +3407,15 @@ INFO is a plist holding contextual information. See ;; Coderef: replace link with the reference name or the ;; equivalent line number. ((string= type "coderef") - (let ((fragment (concat "coderef-" (org-html-encode-plain-text path)))) + (let ((fragment (concat "coderef-" (org-html-encode-plain-text raw-path)))) (format "%s" fragment (format "class=\"coderef\" onmouseover=\"CodeHighlightOn(this, \ '%s');\" onmouseout=\"CodeHighlightOff(this, '%s');\"" fragment fragment) attributes - (format (org-export-get-coderef-format path desc) - (org-export-resolve-coderef path info))))) + (format (org-export-get-coderef-format raw-path desc) + (org-export-resolve-coderef raw-path info))))) ;; External link with a description part. ((and path desc) (format "%s" @@ -3389,7 +3447,7 @@ information." "Transcode a PARAGRAPH element from Org to HTML. CONTENTS is the contents of the paragraph, as a string. INFO is the plist used as a communication channel." - (let* ((parent (org-export-get-parent paragraph)) + (let* ((parent (org-element-parent paragraph)) (parent-type (org-element-type parent)) (style '((footnote-definition " class=\"footpara\"") (org-data " class=\"footpara\""))) @@ -3401,7 +3459,7 @@ the plist used as a communication channel." (not (org-export-get-previous-element paragraph info)) (let ((followers (org-export-get-next-element paragraph info 2))) (and (not (cdr followers)) - (memq (org-element-type (car followers)) '(nil plain-list))))) + (org-element-type-p (car followers) '(nil plain-list))))) ;; First paragraph in an item has no tag if it is alone or ;; followed, at most, by a sub-list. contents) @@ -3547,7 +3605,7 @@ holding contextual information." "Transcode a SECTION element from Org to HTML. CONTENTS holds the contents of the section. INFO is a plist holding contextual information." - (let ((parent (org-export-get-parent-headline section))) + (let ((parent (org-element-lineage section 'headline))) ;; Before first headline: no container, just return CONTENTS. (if (not parent) contents ;; Get div's class and id references. @@ -3616,32 +3674,32 @@ contextual information." (klipsify (and (plist-get info :html-klipsify-src) (member lang '("javascript" "js" "ruby" "scheme" "clojure" "php" "html"))))) - (if (not lang) (format "
\n%s
" label code) - (format "
\n%s%s\n
" - ;; Build caption. - (let ((caption (org-export-get-caption src-block))) - (if (not caption) "" - (let ((listing-number - (format - "%s " - (format - (org-html--translate "Listing %d:" info) - (org-export-get-ordinal - src-block info nil #'org-html--has-caption-p))))) - (format "" - listing-number - (org-trim (org-export-data caption info)))))) - ;; Contents. - (if klipsify - (format "
%s
" - lang - label - (if (string= lang "html") - " data-editor-type=\"html\"" - "") - code) - (format "
%s
" - lang label code))))))) + (format "
\n%s%s\n
" + ;; Build caption. + (let ((caption (org-export-get-caption src-block))) + (if (not caption) "" + (let ((listing-number + (format + "%s " + (format + (org-html--translate "Listing %d:" info) + (org-export-get-ordinal + src-block info nil #'org-html--has-caption-p))))) + (format "" + listing-number + (org-trim (org-export-data caption info)))))) + ;; Contents. + (if klipsify + (format "
%s
" + lang ; lang being nil is OK. + label + (if (string= lang "html") + " data-editor-type=\"html\"" + "") + code) + (format "
%s
" + ;; Lang being nil is OK. + lang label code)))))) ;;;; Statistics Cookie @@ -3684,8 +3742,8 @@ contextual information." "Transcode a TABLE-CELL element from Org to HTML. CONTENTS is nil. INFO is a plist used as a communication channel." - (let* ((table-row (org-export-get-parent table-cell)) - (table (org-export-get-parent-table table-cell)) + (let* ((table-row (org-element-parent table-cell)) + (table (org-element-lineage table-cell 'table)) (cell-attrs (if (not (plist-get info :html-table-align-individual-fields)) "" (format (if (and (boundp 'org-html-format-table-no-css) @@ -3749,7 +3807,7 @@ communication channel." ((not (= 1 group)) '("" . "\n")) ;; Row is from first group. Table has >=1 groups. ((org-export-table-has-header-p - (org-export-get-parent-table table-row) info) + (org-element-lineage table-row 'table) info) '("" . "\n")) ;; Row is from first and only group. (t '("" . "\n"))))) @@ -3776,7 +3834,7 @@ INFO is a plist used as a communication channel." (cdr (org-element-contents table-row))))) (defun org-html-table--table.el-table (table _info) - "Format table.el tables into HTML. + "Format table.el TABLE into HTML. INFO is a plist used as a communication channel." (when (eq (org-element-property :type table) 'table.el) (require 'table) @@ -3906,10 +3964,11 @@ contextual information." ;;; Filter Functions (defun org-html-final-function (contents _backend info) - "Filter to indent the HTML and convert HTML entities." + "Filter to indent the HTML and convert HTML entities. +CONTENTS is the exported HTML code. INFO is the info plist." (with-temp-buffer (insert contents) - (set-auto-mode t) + (delay-mode-hooks (set-auto-mode t)) (when (plist-get info :html-indent) (indent-region (point-min) (point-max))) (buffer-substring-no-properties (point-min) (point-max)))) @@ -3962,6 +4021,8 @@ to convert it." (interactive) (org-export-replace-region-by 'html)) +(defalias 'org-export-region-to-html #'org-html-convert-region-to-html) + ;;;###autoload (defun org-html-export-to-html (&optional async subtreep visible-only body-only ext-plist) diff --git a/lisp/org/ox-icalendar.el b/lisp/org/ox-icalendar.el index 81a77a77..66c65dc2 100644 --- a/lisp/org/ox-icalendar.el +++ b/lisp/org/ox-icalendar.el @@ -1,11 +1,11 @@ -;;; ox-icalendar.el --- iCalendar Back-End for Org Export Engine -*- lexical-binding: t; -*- +;;; ox-icalendar.el --- iCalendar Backend for Org Export Engine -*- lexical-binding: t; -*- -;; Copyright (C) 2004-2023 Free Software Foundation, Inc. +;; Copyright (C) 2004-2025 Free Software Foundation, Inc. ;; Author: Carsten Dominik ;; Nicolas Goaziou -;; Maintainer: Nicolas Goaziou -;; Keywords: outlines, hypermedia, calendar, wp +;; Maintainer: Jack Kamm +;; Keywords: outlines, hypermedia, calendar, text ;; URL: https://orgmode.org ;; This file is part of GNU Emacs. @@ -25,7 +25,7 @@ ;;; Commentary: ;; -;; This library implements an iCalendar back-end for Org generic +;; This library implements an iCalendar backend for Org generic ;; exporter. See Org manual for more information. ;; ;; It is expected to conform to RFC 5545. @@ -48,7 +48,7 @@ ;;; User-Configurable Variables (defgroup org-export-icalendar nil - "Options specific for iCalendar export back-end." + "Options specific for iCalendar export backend." :tag "Org Export iCalendar" :group 'org-export) @@ -96,7 +96,7 @@ and will fire at the event start." (defcustom org-icalendar-exclude-tags nil "Tags that exclude a tree from export. This variable allows specifying different exclude tags from other -back-ends. It can also be set with the ICALENDAR_EXCLUDE_TAGS +backends. It can also be set with the ICALENDAR_EXCLUDE_TAGS keyword." :group 'org-export-icalendar :type '(repeat (string :tag "Tag"))) @@ -168,8 +168,9 @@ This is a list with possibly several symbols in it. Valid symbols are: `todo-start' - Scheduling time stamps in TODO entries become start date. Some - calendar applications show TODO entries only after that date." + Scheduling time stamps in TODO entries become start date. (See + also `org-icalendar-todo-unscheduled-start', which controls the + start date for TODO entries without a scheduling time stamp)" :group 'org-export-icalendar :type '(set :greedy t @@ -221,7 +222,8 @@ Valid values are: nil don't include any task. t include tasks that are not in DONE state. `unblocked' include all TODO items that are not blocked. -`all' include both done and not done items." +`all' include both done and not done items. +\\(\"TODO\" ...) include specific TODO keywords." :group 'org-export-icalendar :type '(choice (const :tag "None" nil) @@ -231,6 +233,38 @@ t include tasks that are not in DONE state. (repeat :tag "Specific TODO keywords" (string :tag "Keyword")))) +(defcustom org-icalendar-todo-unscheduled-start 'recurring-deadline-warning + "Exported start date of unscheduled TODOs. + +If `org-icalendar-use-scheduled' contains `todo-start' and a task +has a \"SCHEDULED\" timestamp, that is always used as the start +date. Otherwise, this variable controls whether a start date is +exported and what its value is. + +Note that the iCalendar spec RFC 5545 does not generally require +tasks to have a start date, except for repeating tasks which do +require a start date. However some iCalendar programs ignore the +requirement for repeating tasks, and allow repeating deadlines +without a matching start date. + +This variable has no effect when `org-icalendar-include-todo' is nil. + +Valid values are: +`recurring-deadline-warning' If deadline repeater present, + use `org-deadline-warning-days' as start. +`deadline-warning' If deadline present, + use `org-deadline-warning-days' as start. +`current-datetime' Use the current date-time as start. +nil Never add a start time for unscheduled tasks." + :group 'org-export-icalendar + :type '(choice + (const :tag "Warning days if deadline recurring" recurring-deadline-warning) + (const :tag "Warning days if deadline present" deadline-warning) + (const :tag "Now" current-datetime) + (const :tag "No start date" nil)) + :package-version '(Org . "9.7") + :safe #'symbolp) + (defcustom org-icalendar-include-bbdb-anniversaries nil "Non-nil means a combined iCalendar file should include anniversaries. The anniversaries are defined in the BBDB database." @@ -297,6 +331,32 @@ Interesting value are: (const :tag "Universal time" ":%Y%m%dT%H%M%SZ") (string :tag "Explicit format"))) +(defcustom org-icalendar-ttl nil + "Time to live for the exported calendar. + +Subscribing clients to the exported ics file can derive the time +interval to read the file again from the server. One example of such +client is Nextcloud calendar, which respects the setting of +X-PUBLISHED-TTL in ICS files. Setting `org-icalendar-ttl' to \"PT1H\" +would advise a server to reload the file every hour. + +See https://icalendar.org/iCalendar-RFC-5545/3-8-2-5-duration.html +for a complete description of possible specifications of this +option. For example, \"PT1H\" stands for 1 hour and +\"PT0H27M34S\" stands for 0 hours, 27 minutes and 34 seconds. + +The default value is nil, which means no such option is set in +the ICS file. This option can also be set on a per-document basis +with the ICAL-TTL export keyword." + :group 'org-export-icalendar + :type '(choice + (const :tag "No refresh period" nil) + (const :tag "One hour" "PT1H") + (const :tag "One day" "PT1D") + (const :tag "One week" "PT7D") + (string :tag "Other")) + :package-version '(Org . "9.7")) + (defvar org-icalendar-after-save-hook nil "Hook run after an iCalendar file has been saved. This hook is run with the name of the file as argument. A good @@ -305,7 +365,7 @@ re-read the iCalendar file.") -;;; Define Back-End +;;; Define Backend (org-export-define-derived-backend 'icalendar 'ascii :translate-alist '((clock . nil) @@ -334,7 +394,8 @@ re-read the iCalendar file.") (:icalendar-use-deadline nil nil org-icalendar-use-deadline) (:icalendar-use-scheduled nil nil org-icalendar-use-scheduled) (:icalendar-scheduled-summary-prefix nil nil org-icalendar-scheduled-summary-prefix) - (:icalendar-deadline-summary-prefix nil nil org-icalendar-deadline-summary-prefix)) + (:icalendar-deadline-summary-prefix nil nil org-icalendar-deadline-summary-prefix) + (:icalendar-ttl "ICAL-TTL" nil org-icalendar-ttl)) :filters-alist '((:filter-headline . org-icalendar-clear-blank-lines)) :menu-entry @@ -540,20 +601,31 @@ or subject for the event." ;; line, real contents must be split at 74 chars. (while (< (setq chunk-end (+ chunk-start 74)) len) (setq folded-line - (concat folded-line "\r\n " + (concat folded-line "\n " (substring line chunk-start chunk-end)) chunk-start chunk-end)) - (concat folded-line "\r\n " (substring line chunk-start)))))) - (org-split-string s "\n") "\r\n"))) + (concat folded-line "\n " (substring line chunk-start)))))) + (org-split-string s "\n") "\n"))) +(defun org-icalendar--post-process-file (file) + "Post-process the exported iCalendar FILE. +Converts line endings to dos-style CRLF as per RFC 5545, then +runs `org-icalendar-after-save-hook'." + (with-temp-buffer + (insert-file-contents file) + (let ((coding-system-for-write (coding-system-change-eol-conversion + last-coding-system-used 'dos))) + (write-region nil nil file))) + (run-hook-with-args 'org-icalendar-after-save-hook file) + nil) ;;; Filters -(defun org-icalendar-clear-blank-lines (headline _back-end _info) +(defun org-icalendar-clear-blank-lines (headline _backend _info) "Remove blank lines in HEADLINE export. HEADLINE is a string representing a transcoded headline. -BACK-END and INFO are ignored." +BACKEND and INFO are ignored." (replace-regexp-in-string "^\\(?:[ \t]*\n\\)+" "" headline)) @@ -591,20 +663,22 @@ inlinetask within the section." (if (eq type 'inlinetask) (cons 'org-data (cons nil (org-element-contents entry))) (let ((first (car (org-element-contents entry)))) - (and (eq (org-element-type first) 'section) + (and (org-element-type-p first 'section) (cons 'org-data (cons nil (org-element-contents first)))))))) (concat (let ((todo-type (org-element-property :todo-type entry)) (uid (or (org-element-property :ID entry) (org-id-new))) (summary (org-icalendar-cleanup-string - (or (org-element-property :SUMMARY entry) - (org-export-data - (org-element-property :title entry) info)))) - (loc (org-icalendar-cleanup-string - (org-export-get-node-property - :LOCATION entry - (org-property-inherit-p "LOCATION")))) + (or + (let ((org-property-separators '(("SUMMARY" . "\n")))) + (org-entry-get entry "SUMMARY" 'selective)) + (org-export-data + (org-element-property :title entry) info)))) + (loc + (let ((org-property-separators '(("LOCATION" . "\n")))) + (org-icalendar-cleanup-string + (org-entry-get entry "LOCATION" 'selective)))) (class (org-icalendar-cleanup-string (org-export-get-node-property :CLASS entry @@ -613,7 +687,8 @@ inlinetask within the section." ;; (headline) or contents (inlinetask). (desc (org-icalendar-cleanup-string - (or (org-element-property :DESCRIPTION entry) + (or (let ((org-property-separators '(("DESCRIPTION" . "\n")))) + (org-entry-get entry "DESCRIPTION" 'selective)) (let ((contents (org-export-data inside info))) (cond ((not (org-string-nw-p contents)) nil) @@ -683,13 +758,16 @@ inlinetask within the section." ;; so, call `org-icalendar--vtodo' to transcode it into ;; a "VTODO" component. (when (and todo-type - (cl-case (plist-get info :icalendar-include-todo) - (all t) - (unblocked + (pcase (plist-get info :icalendar-include-todo) + (`all t) + (`unblocked (and (eq type 'headline) (not (org-icalendar-blocked-headline-p - entry info)))) - ((t) (eq todo-type 'todo)))) + entry info)))) + ;; unfinished + (`t (eq todo-type 'todo)) + ((and (pred listp) kwd-list) + (member (org-element-property :todo-keyword entry) kwd-list)))) (org-icalendar--vtodo entry uid summary loc desc cat tz class)) ;; Diary-sexp: Collect every diary-sexp element within ENTRY ;; and its title, and transcode them. If ENTRY is @@ -720,6 +798,15 @@ inlinetask within the section." ;; Don't forget components from inner entries. contents)))) +(defun org-icalendar--rrule (unit value) + "Format RRULE icalendar entry for UNIT frequency and VALUE interval. +UNIT is a symbol `hour', `day', `week', `month', or `year'." + (format "RRULE:FREQ=%s;INTERVAL=%d" + (cl-case unit + (hour "HOURLY") (day "DAILY") (week "WEEKLY") + (month "MONTHLY") (year "YEARLY")) + value)) + (defun org-icalendar--vevent (entry timestamp uid summary location description categories timezone class) "Create a VEVENT component. @@ -732,35 +819,50 @@ venue for the event. DESCRIPTION provides the complete description of the event. CATEGORIES defines the categories the event belongs to. TIMEZONE specifies a time zone for this event only. CLASS contains the visibility attribute. Three of them -(\"PUBLIC\", \"CONFIDENTIAL\", and \"PRIVATE\") are predefined, others +\\(\"PUBLIC\", \"CONFIDENTIAL\", and \"PRIVATE\") are predefined, others should be treated as \"PRIVATE\" if they are unknown to the iCalendar server. Return VEVENT component as a string." - (org-icalendar-fold-string - (if (eq (org-element-property :type timestamp) 'diary) - (org-icalendar-transcode-diary-sexp - (org-element-property :raw-value timestamp) uid summary) - (concat "BEGIN:VEVENT\n" - (org-icalendar-dtstamp) "\n" - "UID:" uid "\n" - (org-icalendar-convert-timestamp timestamp "DTSTART" nil timezone) "\n" - (org-icalendar-convert-timestamp timestamp "DTEND" t timezone) "\n" - ;; RRULE. - (when (org-element-property :repeater-type timestamp) - (format "RRULE:FREQ=%s;INTERVAL=%d\n" - (cl-case (org-element-property :repeater-unit timestamp) - (hour "HOURLY") (day "DAILY") (week "WEEKLY") - (month "MONTHLY") (year "YEARLY")) - (org-element-property :repeater-value timestamp))) - "SUMMARY:" summary "\n" - (and (org-string-nw-p location) (format "LOCATION:%s\n" location)) - (and (org-string-nw-p class) (format "CLASS:%s\n" class)) - (and (org-string-nw-p description) - (format "DESCRIPTION:%s\n" description)) - "CATEGORIES:" categories "\n" - ;; VALARM. - (org-icalendar--valarm entry timestamp summary) - "END:VEVENT")))) + (if (eq (org-element-property :type timestamp) 'diary) + (org-icalendar-transcode-diary-sexp + (org-element-property :raw-value timestamp) uid summary) + (concat "BEGIN:VEVENT\n" + (org-icalendar-dtstamp) "\n" + "UID:" uid "\n" + (org-icalendar-convert-timestamp timestamp "DTSTART" nil timezone) "\n" + (org-icalendar-convert-timestamp timestamp "DTEND" t timezone) "\n" + ;; RRULE. + (when (org-element-property :repeater-type timestamp) + (concat (org-icalendar--rrule + (org-element-property :repeater-unit timestamp) + (org-element-property :repeater-value timestamp)) + "\n")) + "SUMMARY:" summary "\n" + (and (org-string-nw-p location) (format "LOCATION:%s\n" location)) + (and (org-string-nw-p class) (format "CLASS:%s\n" class)) + (and (org-string-nw-p description) + (format "DESCRIPTION:%s\n" description)) + "CATEGORIES:" categories "\n" + ;; VALARM. + (org-icalendar--valarm entry timestamp summary) + "END:VEVENT\n"))) + +(defun org-icalendar--repeater-type (elem) + "Return ELEM's repeater-type if supported, else warn and return nil." + (let ((repeater-value (org-element-property :repeater-value elem)) + (repeater-type (org-element-property :repeater-type elem))) + (cond + ((not (and repeater-type + repeater-value + (> repeater-value 0))) + nil) + ;; TODO Add catch-up to supported repeaters (use EXDATE to implement) + ((not (memq repeater-type '(cumulate))) + (org-display-warning + (format "Repeater-type %s not currently supported by iCalendar export" + (symbol-name repeater-type))) + nil) + (repeater-type)))) (defun org-icalendar--vtodo (entry uid summary location description categories timezone class) @@ -769,51 +871,125 @@ Return VEVENT component as a string." ENTRY is either a headline or an inlinetask element. UID is the unique identifier for the task. SUMMARY defines a short summary or subject for the task. LOCATION defines the intended venue for -the task. DESCRIPTION provides the complete description of the -task. CATEGORIES defines the categories the task belongs to. -TIMEZONE specifies a time zone for this TODO only. +the task. CLASS sets the task class (e.g. confidential). DESCRIPTION +provides the complete description of the task. CATEGORIES defines the +categories the task belongs to. TIMEZONE specifies a time zone for +this TODO only. Return VTODO component as a string." - (let ((start (or (and (memq 'todo-start org-icalendar-use-scheduled) - (org-element-property :scheduled entry)) - ;; If we can't use a scheduled time for some - ;; reason, start task now. - (let ((now (decode-time))) - (list 'timestamp - (list :type 'active - :minute-start (nth 1 now) - :hour-start (nth 2 now) - :day-start (nth 3 now) - :month-start (nth 4 now) - :year-start (nth 5 now))))))) - (org-icalendar-fold-string - (concat "BEGIN:VTODO\n" - "UID:TODO-" uid "\n" - (org-icalendar-dtstamp) "\n" - (org-icalendar-convert-timestamp start "DTSTART" nil timezone) "\n" - (and (memq 'todo-due org-icalendar-use-deadline) - (org-element-property :deadline entry) - (concat (org-icalendar-convert-timestamp - (org-element-property :deadline entry) "DUE" nil timezone) - "\n")) - "SUMMARY:" summary "\n" - (and (org-string-nw-p location) (format "LOCATION:%s\n" location)) - (and (org-string-nw-p class) (format "CLASS:%s\n" class)) - (and (org-string-nw-p description) - (format "DESCRIPTION:%s\n" description)) - "CATEGORIES:" categories "\n" - "SEQUENCE:1\n" - (format "PRIORITY:%d\n" - (let ((pri (or (org-element-property :priority entry) - org-priority-default))) - (floor (- 9 (* 8. (/ (float (- org-priority-lowest pri)) - (- org-priority-lowest - org-priority-highest))))))) - (format "STATUS:%s\n" - (if (eq (org-element-property :todo-type entry) 'todo) - "NEEDS-ACTION" - "COMPLETED")) - "END:VTODO")))) + (let* ((sc (and (memq 'todo-start org-icalendar-use-scheduled) + (org-element-property :scheduled entry))) + (dl (and (memq 'todo-due org-icalendar-use-deadline) + (org-element-property :deadline entry))) + (sc-repeat-p (org-icalendar--repeater-type sc)) + (dl-repeat-p (org-icalendar--repeater-type dl)) + (repeat-value (or (org-element-property :repeater-value sc) + (org-element-property :repeater-value dl))) + (repeat-unit (or (org-element-property :repeater-unit sc) + (org-element-property :repeater-unit dl))) + (repeat-until (and sc-repeat-p (not dl-repeat-p) dl)) + (start + (cond + (sc) + ((eq org-icalendar-todo-unscheduled-start 'current-datetime) + (let ((now (decode-time))) + (list 'timestamp + (list :type 'active + :minute-start (nth 1 now) + :hour-start (nth 2 now) + :day-start (nth 3 now) + :month-start (nth 4 now) + :year-start (nth 5 now))))) + ((or (and (eq org-icalendar-todo-unscheduled-start + 'deadline-warning) + dl) + (and (eq org-icalendar-todo-unscheduled-start + 'recurring-deadline-warning) + dl-repeat-p)) + (let ((dl-raw (org-element-property :raw-value dl))) + (with-temp-buffer + (insert dl-raw) + (goto-char (point-min)) + (org-timestamp-down-day (org-get-wdays dl-raw)) + (org-element-timestamp-parser))))))) + (concat "BEGIN:VTODO\n" + "UID:TODO-" uid "\n" + (org-icalendar-dtstamp) "\n" + (when start (concat (org-icalendar-convert-timestamp + start "DTSTART" nil timezone) + "\n")) + (when (and dl (not repeat-until)) + (concat (org-icalendar-convert-timestamp + dl "DUE" nil timezone) + "\n")) + ;; RRULE + (cond + ;; SCHEDULED, DEADLINE have different repeaters + ((and dl-repeat-p + (not (and (eq repeat-value (org-element-property + :repeater-value dl)) + (eq repeat-unit (org-element-property + :repeater-unit dl))))) + ;; TODO Implement via RDATE with changing DURATION + (org-display-warning "Not yet implemented: \ +different repeaters on SCHEDULED and DEADLINE. Skipping.") + nil) + ;; DEADLINE has repeater but SCHEDULED doesn't + ((and dl-repeat-p (and sc (not sc-repeat-p))) + ;; TODO SCHEDULED should only apply to first instance; + ;; use RDATE with custom DURATION to implement that + (org-display-warning "Not yet implemented: \ +repeater on DEADLINE but not SCHEDULED. Skipping.") + nil) + ((or sc-repeat-p dl-repeat-p) + (concat + (org-icalendar--rrule repeat-unit repeat-value) + ;; add UNTIL part to RRULE + (when repeat-until + (let* ((start-time + (org-element-property :minute-start start)) + ;; RFC5545 requires UTC iff DTSTART is not local time + (local-time-p + (and (not timezone) + (equal org-icalendar-date-time-format + ":%Y%m%dT%H%M%S"))) + (encoded + (org-encode-time + 0 + (or (org-element-property :minute-start repeat-until) + 0) + (or (org-element-property :hour-start repeat-until) + 0) + (org-element-property :day-start repeat-until) + (org-element-property :month-start repeat-until) + (org-element-property :year-start repeat-until)))) + (concat ";UNTIL=" + (cond + ((not start-time) + (format-time-string "%Y%m%d" encoded)) + (local-time-p + (format-time-string "%Y%m%dT%H%M%S" encoded)) + ((format-time-string "%Y%m%dT%H%M%SZ" + encoded t)))))) + "\n"))) + "SUMMARY:" summary "\n" + (and (org-string-nw-p location) (format "LOCATION:%s\n" location)) + (and (org-string-nw-p class) (format "CLASS:%s\n" class)) + (and (org-string-nw-p description) + (format "DESCRIPTION:%s\n" description)) + "CATEGORIES:" categories "\n" + "SEQUENCE:1\n" + (format "PRIORITY:%d\n" + (let ((pri (or (org-element-property :priority entry) + org-priority-default))) + (floor (- 9 (* 8. (/ (float (- org-priority-lowest pri)) + (- org-priority-lowest + org-priority-highest))))))) + (format "STATUS:%s\n" + (if (eq (org-element-property :todo-type entry) 'todo) + "NEEDS-ACTION" + "COMPLETED")) + "END:VTODO\n"))) (defun org-icalendar--valarm (entry timestamp summary) "Create a VALARM component. @@ -872,26 +1048,32 @@ as a communication channel." (or (org-string-nw-p org-icalendar-timezone) (format-time-string "%Z")) ;; Description. (org-export-data (plist-get info :title) info) + ;; TTL + (plist-get info :icalendar-ttl) contents)) -(defun org-icalendar--vcalendar (name owner tz description contents) +(defun org-icalendar--vcalendar (name owner tz description ttl contents) "Create a VCALENDAR component. -NAME, OWNER, TZ, DESCRIPTION and CONTENTS are all strings giving, +NAME, OWNER, TZ, DESCRIPTION, TTL and CONTENTS are all strings giving, respectively, the name of the calendar, its owner, the timezone -used, a short description and the other components included." - (concat (format "BEGIN:VCALENDAR +used, a short description, time to live (refresh period) and +the other components included." + (org-icalendar-fold-string + (concat (format "BEGIN:VCALENDAR VERSION:2.0 X-WR-CALNAME:%s PRODID:-//%s//Emacs with Org mode//EN X-WR-TIMEZONE:%s -X-WR-CALDESC:%s -CALSCALE:GREGORIAN\n" - (org-icalendar-cleanup-string name) - (org-icalendar-cleanup-string owner) - (org-icalendar-cleanup-string tz) - (org-icalendar-cleanup-string description)) - contents - "END:VCALENDAR\n")) +X-WR-CALDESC:%s\n" + (org-icalendar-cleanup-string name) + (org-icalendar-cleanup-string owner) + (org-icalendar-cleanup-string tz) + (org-icalendar-cleanup-string description)) + (when ttl (format "X-PUBLISHED-TTL:%s\n" + (org-icalendar-cleanup-string ttl))) + "CALSCALE:GREGORIAN\n" + contents + "END:VCALENDAR\n"))) @@ -926,14 +1108,13 @@ Return ICS file name." (let ((file (buffer-file-name (buffer-base-buffer)))) (when (and file org-icalendar-store-UID) (org-icalendar-create-uid file 'warn-user))) - ;; Export part. Since this back-end is backed up by `ascii', ensure + ;; Export part. Since this backend is backed up by `ascii', ensure ;; links will not be collected at the end of sections. (let ((outfile (org-export-output-file-name ".ics" subtreep))) (org-export-to-file 'icalendar outfile async subtreep visible-only body-only '(:ascii-charset utf-8 :ascii-links-to-notes nil) - '(lambda (file) - (run-hook-with-args 'org-icalendar-after-save-hook file) nil)))) + #'org-icalendar--post-process-file))) ;;;###autoload (defun org-icalendar-export-agenda-files (&optional async) @@ -961,7 +1142,13 @@ external process." (catch 'nextfile (org-check-agenda-file file) (with-current-buffer (org-get-agenda-file-buffer file) - (org-icalendar-export-to-ics)))) + (condition-case err + (org-icalendar-export-to-ics) + (error + (warn "Exporting %s to icalendar failed: %s" + file + (error-message-string err)) + (signal (car err) (cdr err))))))) (org-release-buffers org-agenda-new-buffers))))) ;;;###autoload @@ -1018,8 +1205,9 @@ This function assumes major mode for current buffer is user-full-name (or (org-string-nw-p org-icalendar-timezone) (format-time-string "%Z")) org-icalendar-combined-description + org-icalendar-ttl contents))) - (run-hook-with-args 'org-icalendar-after-save-hook file))) + (org-icalendar--post-process-file file))) (defun org-icalendar--combine-files (&rest files) "Combine entries from multiple files into an iCalendar file. @@ -1042,6 +1230,8 @@ FILES is a list of files to build the calendar from." (format-time-string "%Z")) ;; Description. org-icalendar-combined-description + ;; TTL (Refresh period) + org-icalendar-ttl ;; Contents. (concat ;; Agenda contents. @@ -1061,8 +1251,7 @@ FILES is a list of files to build the calendar from." (when (and org-icalendar-include-bbdb-anniversaries (require 'ol-bbdb nil t)) (with-output-to-string (org-bbdb-anniv-export-ical))))))) - (run-hook-with-args 'org-icalendar-after-save-hook - org-icalendar-combined-agenda-file)) + (org-icalendar--post-process-file org-icalendar-combined-agenda-file)) (org-release-buffers org-agenda-new-buffers)))) diff --git a/lisp/org/ox-koma-letter.el b/lisp/org/ox-koma-letter.el index 33eb0597..3f9a0385 100644 --- a/lisp/org/ox-koma-letter.el +++ b/lisp/org/ox-koma-letter.el @@ -1,13 +1,13 @@ -;;; ox-koma-letter.el --- KOMA Scrlttr2 Back-End for Org Export Engine -*- lexical-binding: t; -*- +;;; ox-koma-letter.el --- KOMA Scrlttr2 Backend for Org Export Engine -*- lexical-binding: t; -*- -;; Copyright (C) 2007-2023 Free Software Foundation, Inc. +;; Copyright (C) 2007-2025 Free Software Foundation, Inc. ;; Author: Nicolas Goaziou ;; Alan Schmitt ;; Viktor Rosenfeld ;; Rasmus Pank Roulund ;; Maintainer: Marco Wahl -;; Keywords: org, wp, tex +;; Keywords: org, text, tex ;; This file is part of GNU Emacs. @@ -26,7 +26,7 @@ ;;; Commentary: ;; -;; This library implements a KOMA Scrlttr2 back-end, derived from the +;; This library implements a KOMA Scrlttr2 backend, derived from the ;; LaTeX one. ;; ;; Depending on the desired output format, three commands are provided @@ -34,8 +34,8 @@ ;; `org-koma-letter-export-to-latex' ("tex" file) and ;; `org-koma-letter-export-to-pdf' ("pdf" file). ;; -;; On top of buffer keywords supported by `latex' back-end (see -;; `org-latex-packages-alist'), this back-end introduces the following +;; On top of buffer keywords supported by `latex' backend (see +;; `org-latex-packages-alist'), this backend introduces the following ;; keywords: ;; - CLOSING: see `org-koma-letter-closing', ;; - FROM_ADDRESS: see `org-koma-letter-from-address', @@ -374,7 +374,7 @@ following ones: `p' Deactivate punch or center mark on left paper edge `T' Activate lower horizontal mark on left paper edge - `t' Deactivate lower horizontal mark on left paper edge + t Deactivate lower horizontal mark on left paper edge `V' Activate all vertical marks on upper paper edge `v' Deactivate all vertical marks on upper paper edge @@ -466,7 +466,7 @@ e.g. \"title-subject:t\"." "Holds special content temporarily.") -;;; Define Back-End +;;; Define Backend (org-export-define-derived-backend 'koma-letter 'latex :options-alist @@ -571,6 +571,9 @@ return a string or nil." KEYWORDS is a list of symbols. Return them as a string to be formatted. +INFO is the information plist possibly holding :special-tags-as-macro +property. See `org-koma-letter-special-tags-as-macro'. + The function is used for inserting content of special headings such as the one tagged with PS." (mapconcat @@ -586,7 +589,8 @@ such as the one tagged with PS." (defun org-koma-letter--add-latex-newlines (string) - "Replace regular newlines with LaTeX newlines (i.e. `\\\\')." + "Replace regular newlines with LaTeX newlines (i.e. `\\\\') in STRING. +Return a new string." (let ((str (org-trim string))) (when (org-string-nw-p str) (replace-regexp-in-string "\n" "\\\\\\\\\n" str)))) @@ -623,7 +627,7 @@ channel." (let ((key (org-element-property :key keyword)) (value (org-element-property :value keyword))) ;; Handle specifically KOMA-LETTER keywords. Otherwise, fallback - ;; to `latex' back-end. + ;; to `latex' backend. (if (equal key "KOMA-LETTER") value (org-export-with-backend 'latex keyword contents info)))) @@ -682,7 +686,7 @@ PLIST-KEY." CONTENTS is the transcoded contents string. INFO is a plist holding export options." (concat - ;; Time-stamp. + ;; Timestamp. (and (plist-get info :time-stamp-file) (format-time-string "%% Created %Y-%m-%d %a %H:%M\n")) ;; LaTeX compiler @@ -911,7 +915,9 @@ non-nil." (let (org-koma-letter-special-contents) (org-export-to-buffer 'koma-letter "*Org KOMA-LETTER Export*" async subtreep visible-only body-only ext-plist - (lambda () (LaTeX-mode))))) + (if (fboundp 'major-mode-remap) + (major-mode-remap 'latex-mode) + #'LaTeX-mode)))) ;;;###autoload (defun org-koma-letter-export-to-latex diff --git a/lisp/org/ox-latex.el b/lisp/org/ox-latex.el index 768bf402..e62e8404 100644 --- a/lisp/org/ox-latex.el +++ b/lisp/org/ox-latex.el @@ -1,10 +1,10 @@ -;;; ox-latex.el --- LaTeX Back-End for Org Export Engine -*- lexical-binding: t; -*- +;;; ox-latex.el --- LaTeX Backend for Org Export Engine -*- lexical-binding: t; -*- -;; Copyright (C) 2011-2023 Free Software Foundation, Inc. +;; Copyright (C) 2011-2025 Free Software Foundation, Inc. ;; Author: Nicolas Goaziou ;; Maintainer: Daniel Fleischer -;; Keywords: outlines, hypermedia, calendar, wp +;; Keywords: outlines, hypermedia, calendar, text ;; This file is part of GNU Emacs. @@ -50,7 +50,7 @@ (defvar engrave-faces-latex-mathescape) -;;; Define Back-End +;;; Define Backend (org-export-define-backend 'latex '((bold . org-latex-bold) @@ -135,6 +135,7 @@ (:latex-default-table-environment nil nil org-latex-default-table-environment) (:latex-default-quote-environment nil nil org-latex-default-quote-environment) (:latex-default-table-mode nil nil org-latex-default-table-mode) + (:latex-default-footnote-command "LATEX_FOOTNOTE_COMMAND" nil org-latex-default-footnote-command) (:latex-diary-timestamp-format nil nil org-latex-diary-timestamp-format) (:latex-engraved-options nil nil org-latex-engraved-options) (:latex-engraved-preamble nil nil org-latex-engraved-preamble) @@ -156,6 +157,7 @@ (:latex-src-block-backend nil nil org-latex-src-block-backend) (:latex-listings-langs nil nil org-latex-listings-langs) (:latex-listings-options nil nil org-latex-listings-options) + (:latex-listings-src-omit-language nil nil org-latex-listings-src-omit-language) (:latex-minted-langs nil nil org-latex-minted-langs) (:latex-minted-options nil nil org-latex-minted-options) (:latex-prefer-user-labels nil nil org-latex-prefer-user-labels) @@ -176,94 +178,105 @@ ;;; Internal Variables (defconst org-latex-language-alist - '(("am" :babel-ini-only "amharic" :polyglossia "amharic" :lang-name "Amharic") - ("ar" :babel "arabic" :polyglossia "arabic" :lang-name "Arabic") - ("ast" :babel-ini-only "asturian" :polyglossia "asturian" :lang-name "Asturian") - ("bg" :babel "bulgarian" :polyglossia "bulgarian" :lang-name "Bulgarian") - ("bn" :babel-ini-only "bengali" :polyglossia "bengali" :lang-name "Bengali") - ("bo" :babel-ini-only "tibetan" :polyglossia "tibetan" :lang-name "Tibetan") - ("br" :babel "breton" :polyglossia "breton" :lang-name "Breton") - ("ca" :babel "catalan" :polyglossia "catalan" :lang-name "Catalan") - ("cop" :babel-ini-only "coptic" :polyglossia "coptic" :lang-name "Coptic") - ("cs" :babel "czech" :polyglossia "czech" :lang-name "Czech") - ("cy" :babel "welsh" :polyglossia "welsh" :lang-name "Welsh") - ("da" :babel "danish" :polyglossia "danish" :lang-name "Danish") - ("de" :babel "ngerman" :polyglossia "german" :polyglossia-variant "german" :lang-name "German") - ("de-at" :babel "naustrian" :polyglossia "german" :polyglossia-variant "austrian" :lang-name "German") - ("dsb" :babel "lsorbian" :polyglossia "sorbian" :polyglossia-variant "lower" :lang-name "Lower Sorbian") - ("dv" :babel-ini-only "divehi" :polyglossia "divehi" :lang-name "Divehi") - ("el" :babel "greek" :polyglossia "greek" :lang-name "Greek") - ("el-polyton" :babel "polutonikogreek" :polyglossia "greek" :polyglossia-variant "polytonic" :lang-name "Polytonic Greek") - ("en" :babel "american" :polyglossia "english" :polyglossia-variant "usmax" :lang-name "English") - ("en-au" :babel "australian" :polyglossia "english" :polyglossia-variant "australian" :lang-name "English") - ("en-gb" :babel "british" :polyglossia "english" :polyglossia-variant "uk" :lang-name "English") - ("en-nz" :babel "newzealand" :polyglossia "english" :polyglossia-variant "newzealand" :lang-name "English") - ("en-us" :babel "american" :polyglossia "english" :polyglossia-variant "usmax" :lang-name "English") - ("eo" :babel "esperanto" :polyglossia "esperanto" :lang-name "Esperanto") - ("es" :babel "spanish" :polyglossia "spanish" :lang-name "Spanish") - ("es-mx" :babel "spanishmx" :polyglossia "spanish" :polyglossia-variant "mexican" :lang-name "Spanish") - ("et" :babel "estonian" :polyglossia "estonian" :lang-name "Estonian") - ("eu" :babel "basque" :polyglossia "basque" :lang-name "Basque") - ("fa" :babel "farsi" :polyglossia "farsi" :lang-name "Farsi") - ("fi" :babel "finnish" :polyglossia "finnish" :lang-name "Finnish") - ("fr" :babel "french" :polyglossia "french" :lang-name "French") - ("fr-ca" :babel "canadien" :polyglossia "french" :polyglossia-variant "canadian" :lang-name "French") - ("fur" :babel "friulan" :polyglossia "friulan" :lang-name "Friulian") - ("ga" :babel "irish" :polyglossia "irish" :lang-name "Irish") - ("gd" :babel "scottish" :polyglossia "scottish" :lang-name "Scottish Gaelic") - ("gl" :babel "galician" :polyglossia "galician" :lang-name "Galician") - ("he" :babel "hebrew" :polyglossia "hebrew" :lang-name "Hebrew") - ("hi" :babel "hindi" :polyglossia "hindi" :lang-name "Hindi") - ("hr" :babel "croatian" :polyglossia "croatian" :lang-name "Croatian") - ("hsb" :babel "uppersorbian" :polyglossia "sorbian" :polyglossia-variant "upper" :lang-name "Upper Sorbian") - ("hu" :babel "magyar" :polyglossia "magyar" :lang-name "Magyar") - ("hy" :babel-ini-only "armenian" :polyglossia "armenian" :lang-name "Armenian") - ("ia" :babel "interlingua" :polyglossia "interlingua" :lang-name "Interlingua") - ("id" :babel-ini-only "bahasai" :polyglossia "bahasai" :lang-name "Bahasai") - ("is" :babel "icelandic" :polyglossia "icelandic" :lang-name "Icelandic") - ("it" :babel "italian" :polyglossia "italian" :lang-name "Italian") - ("kn" :babel-ini-only "kannada" :polyglossia "kannada" :lang-name "Kannada") - ("la" :babel "latin" :polyglossia "latin" :lang-name "Latin") - ("la-classic" :babel "classiclatin" :polyglossia "latin" :polyglossia-variant "classic" :lang-name "Classic Latin") - ("la-medieval" :babel "medievallatin" :polyglossia "latin" :polyglossia-variant "medieval" :lang-name "Medieval Latin") - ("la-ecclesiastic" :babel "ecclesiasticlatin" :polyglossia "latin" :polyglossia-variant "ecclesiastic" :lang-name "Ecclesiastic Latin") - ("lo" :babel-ini-only "lao" :polyglossia "lao" :lang-name "Lao") - ("lt" :babel "lithuanian" :polyglossia "lithuanian" :lang-name "Lithuanian") - ("lv" :babel "latvian" :polyglossia "latvian" :lang-name "Latvian") - ("ml" :babel-ini-only "malayalam" :polyglossia "malayalam" :lang-name "Malayalam") - ("mr" :babel-ini-only "maranthi" :polyglossia "maranthi" :lang-name "Maranthi") - ("nb" :babel "norsk" :polyglossia "norwegian" :polyglossia-variant "bokmal" :lang-name "Norwegian Bokmål") - ("nl" :babel "dutch" :polyglossia "dutch" :lang-name "Dutch") - ("nn" :babel "nynorsk" :polyglossia "norwegian" :polyglossia-variant "nynorsk" :lang-name "Norwegian Nynorsk") - ("no" :babel "norsk" :polyglossia "norsk" :lang-name "Norwegian") - ("oc" :babel "occitan" :polyglossia "occitan" :lang-name "Occitan") - ("pl" :babel "polish" :polyglossia "polish" :lang-name "Polish") - ("pms" :babel "piedmontese" :polyglossia "piedmontese" :lang-name "Piedmontese") - ("pt" :babel "portuges" :polyglossia "portuges" :lang-name "Portuges") - ("pt-br" :babel "brazilian" :polyglossia "brazilian" :lang-name "Portuges") - ("rm" :babel-ini-only "romansh" :polyglossia "romansh" :lang-name "Romansh") - ("ro" :babel "romanian" :polyglossia "romanian" :lang-name "Romanian") - ("ru" :babel "russian" :polyglossia "russian" :lang-name "Russian") - ("sa" :babel-ini-only "sanskrit" :polyglossia "sanskrit" :lang-name "Sanskrit") - ("sk" :babel "slovak" :polyglossia "slovak" :lang-name "Slovak") - ("sl" :babel "slovene" :polyglossia "slovene" :lang-name "Slovene") - ("sq" :babel "albanian" :polyglossia "albanian" :lang-name "Albanian") - ("sr" :babel "serbian" :polyglossia "serbian" :lang-name "Serbian") - ("sv" :babel "swedish" :polyglossia "swedish" :lang-name "Swedish") - ("syr" :babel-ini-only "syriac" :polyglossia "syriac" :lang-name "Syriac") - ("ta" :babel-ini-only "tamil" :polyglossia "tamil" :lang-name "Tamil") - ("te" :babel-ini-only "telugu" :polyglossia "telugu" :lang-name "Telugu") - ("th" :babel "thai" :polyglossia "thai" :lang-name "Thai") - ("tk" :babel "turkmen" :polyglossia "turkmen" :lang-name "Turkmen") - ("tr" :babel "turkish" :polyglossia "turkish" :lang-name "Turkish") - ("uk" :babel "ukrainian" :polyglossia "ukrainian" :lang-name "Ukrainian") - ("ur" :babel-ini-only "urdu" :polyglossia "urdu" :lang-name "Urdu") - ("vi" :babel "vietnamese" :polyglossia "vietnamese" :lang-name "Vietnamese")) + (let ((de-default-plist '(:babel "ngerman" :babel-ini-alt "german" :polyglossia "german" :polyglossia-variant "german" :lang-name "German" :script "latin" :script-tag "latn")) + (zh-default-plist '(:babel-ini-only "chinese" :polyglossia "chinese" :polyglossia-variant "simplified" :lang-name "Chinese Simplified" :script "hans" :script-tag "hans"))) + `(("af" :babel "afrikaans" :polyglossia "afrikaans" :lang-name "Afrikaans" :script "latin" :script-tag "latn") + ("am" :babel-ini-only "amharic" :polyglossia "amharic" :lang-name "Amharic" :script "ethiopic" :script-tag "ethi") + ("ar" :babel-ini-only "arabic" :polyglossia "arabic" :lang-name "Arabic" :script "arabic" :script-tag "arab") + ("ast" :babel-ini-only "asturian" :polyglossia "asturian" :lang-name "Asturian" :script "latin" :script-tag "latn") + ("bg" :babel "bulgarian" :polyglossia "bulgarian" :lang-name "Bulgarian" :script "cyrillic" :script-tag "cyrl") + ("bn" :babel-ini-only "bengali" :polyglossia "bengali" :lang-name "Bengali" :script "bengali" :script-tag: "beng") + ("bo" :babel-ini-only "tibetan" :polyglossia "tibetan" :lang-name "Tibetan" :script "tibetan" :script-tag "tib") + ("br" :babel "breton" :polyglossia "breton" :lang-name "Breton" :script "latin" :script-tag "latn") + ("ca" :babel "catalan" :polyglossia "catalan" :lang-name "Catalan" :script "latin" :script-tag "latn") + ("cop" :babel-ini-only "coptic" :polyglossia "coptic" :lang-name "Coptic" :script "coptic" :script-tag "copt") + ("cs" :babel "czech" :polyglossia "czech" :lang-name "Czech" :script "latin" :script-tag "latn") + ("cy" :babel "welsh" :polyglossia "welsh" :lang-name "Welsh" :script "latin" :script-tag "latn") + ("da" :babel "danish" :polyglossia "danish" :lang-name "Danish" :script "latin" :script-tag "latn") + ("de" ,@de-default-plist) + ("de-de" ,@de-default-plist) + ("de-at" :babel "naustrian" :babel-ini-alt "german-austria" :polyglossia "german" :polyglossia-variant "austrian" :lang-name "German" :script "latin" :script-tag "latn") + ("dsb" :babel "lowersorbian" :babel-ini-alt "lsorbian" :polyglossia "sorbian" :polyglossia-variant "lower" :lang-name "Lower Sorbian" :script "latin" :script-tag "latn") + ("dv" :polyglossia "divehi" :lang-name "Dhivehi" :script "latin" :script-tag "latn") + ("el" :babel "greek" :polyglossia "greek" :lang-name "Greek" :script "greek" :script-tag "grek") + ("el-polyton" :babel "polutonikogreek" :babel-ini-alt "polytonicgreek" :polyglossia "greek" :polyglossia-variant "polytonic" :lang-name "Polytonic Greek" :script "greek" :script-tag "grek") + ("grc" :babel "greek.ancient" :babel-ini-alt "ancientgreek" :polyglossia "greek" :polyglossia-variant "ancient" :lang-name "Ancient Greek" :script "greek" :script-tag "grek") + ("en" :babel "english" :polyglossia "english" :polyglossia-variant "usmax" :lang-name "English" :script "latin" :script-tag "latn") + ("en-au" :babel "australian" :polyglossia "english" :polyglossia-variant "australian" :lang-name "English" :script "latin" :script-tag "latn") + ("en-ca" :babel "canadian" :polyglossia "english" :polyglossia-variant "canadian" :lang-name "English" :script "latin" :script-tag "latn") + ("en-gb" :babel "british" :polyglossia "english" :polyglossia-variant "uk" :lang-name "English" :script "latin" :script-tag "latn") + ("en-nz" :babel "newzealand" :polyglossia "english" :polyglossia-variant "newzealand" :lang-name "English" :script "latin" :script-tag "latn") + ("en-us" :babel "american" :polyglossia "english" :polyglossia-variant "usmax" :lang-name "English" :script "latin" :script-tag "latn") + ("eo" :babel "esperanto" :polyglossia "esperanto" :lang-name "Esperanto" :script "latin" :script-tag "latn") + ("es" :babel "spanish" :polyglossia "spanish" :lang-name "Spanish" :script "latin" :script-tag "latn") + ("es-mx" :babel "spanishmx" :polyglossia "spanish" :polyglossia-variant "mexican" :lang-name "Spanish" :script "latin" :script-tag "latn") + ("et" :babel "estonian" :polyglossia "estonian" :lang-name "Estonian" :script "latin" :script-tag "latn") + ("eu" :babel "basque" :polyglossia "basque" :lang-name "Basque" :script "latin" :script-tag "latn") + ("fa" :babel "persian" :polyglossia "persian" :lang-name "Persian" :script "arabic" :script-tag "arab") + ("fi" :babel "finnish" :polyglossia "finnish" :lang-name "Finnish" :script "latin" :script-tag "latn") + ("fr" :babel "french" :polyglossia "french" :lang-name "French" :script "latin" :script-tag "latn") + ("fr-ca" :babel "canadien" :babel-ini-alt "canadian" :polyglossia "french" :polyglossia-variant "canadian" :lang-name "French" :script "latin" :script-tag "latn") + ("fur" :babel "friulian" :polyglossia "friulian" :lang-name "Friulian" :script "latin" :script-tag "latn") + ("ga" :babel "irish" :polyglossia "gaelic" :polyglossia-variant "irish" :lang-name "Irish Gaelic" :script "latin" :script-tag "latn") + ("gd" :babel "scottish" :polyglossia "gaelic" :polyglossia-variant "scottish" :lang-name "Scottish Gaelic" :script "latin" :script-tag "latn") + ("gl" :babel "galician" :polyglossia "galician" :lang-name "Galician" :script "latin" :script-tag "latn") + ("he" :babel "hebrew" :polyglossia "hebrew" :lang-name "Hebrew" :script "hebrew" :script-tag "hebr") + ("hi" :babel "hindi" :polyglossia "hindi" :lang-name "Hindi" :script "devanagari" :script-tag "deva") + ("hr" :babel "croatian" :polyglossia "croatian" :lang-name "Croatian" :script "latin" :script-tag "latn") + ("hsb" :babel "uppersorbian" :polyglossia "sorbian" :polyglossia-variant "upper" :lang-name "Upper Sorbian" :script "latin" :script-tag "latn") + ("hu" :babel "magyar" :polyglossia "magyar" :lang-name "Magyar" :script "latin" :script-tag "latn") + ("hy" :babel-ini-only "armenian" :polyglossia "armenian" :lang-name "Armenian" :script "armenian" :script-tag "armn") + ("ia" :babel "interlingua" :polyglossia "interlingua" :lang-name "Interlingua" :script "latin" :script-tag "latn") + ("id" :babel "indonesian" :polyglossia "malay" :polyglossia-variant "indonesian" :lang-name "Indonesian" :script "latin" :script-tag "latn") + ("is" :babel "icelandic" :polyglossia "icelandic" :lang-name "Icelandic" :script "latin" :script-tag "latn") + ("it" :babel "italian" :polyglossia "italian" :lang-name "Italian" :script "latin" :script-tag "latn") + ("kn" :babel-ini-only "kannada" :polyglossia "kannada" :lang-name "Kannada" :script "kannada" :script-tag "knda") + ("la" :babel "latin" :polyglossia "latin" :lang-name "Latin" :script "latin" :script-tag "latn") + ("la-classic" :babel "classiclatin" :polyglossia "latin" :polyglossia-variant "classic" :lang-name "Classic Latin" :script "latin" :script-tag "latn") + ("la-medieval" :babel "medievallatin" :polyglossia "latin" :polyglossia-variant "medieval" :lang-name "Medieval Latin" :script "latin" :script-tag "latn") + ("la-ecclesiastic" :babel "ecclesiasticlatin" :polyglossia "latin" :polyglossia-variant "ecclesiastic" :lang-name "Ecclesiastic Latin" :script "latin" :script-tag "latn") + ("lo" :babel-ini-only "lao" :polyglossia "lao" :lang-name "Lao" :script "lao" :script-tag "lao") + ("lt" :babel "lithuanian" :polyglossia "lithuanian" :lang-name "Lithuanian" :script "latin" :script-tag "latn") + ("lv" :babel "latvian" :polyglossia "latvian" :lang-name "Latvian" :script "latin" :script-tag "latn") + ("ml" :babel-ini-only "malayalam" :polyglossia "malayalam" :lang-name "Malayalam" :script "malayalam" :script-tag "mlym") + ("mr" :babel-ini-only "marathi" :polyglossia "marathi" :lang-name "Marathi" :script "devanagari" :script-tag "deva") + ("ms" :babel "malay" :polyglossia "malay" :polyglossia-variant "malaysian" :lang-name "Malay" :script "latin" :script-tag "latn") + ("nb" :babel "norsk" :polyglossia "norwegian" :polyglossia-variant "bokmal" :lang-name "Norwegian Bokmål" :script "latin" :script-tag "latn") + ("nl" :babel "dutch" :polyglossia "dutch" :lang-name "Dutch" :script "latin" :script-tag "latn") + ("nn" :babel "nynorsk" :polyglossia "norwegian" :polyglossia-variant "nynorsk" :lang-name "Norwegian Nynorsk" :script "latin" :script-tag "latn") + ("no" :babel "norsk" :polyglossia "norsk" :lang-name "Norwegian" :script "latin" :script-tag "latn") + ("oc" :babel "occitan" :polyglossia "occitan" :lang-name "Occitan" :script "latin" :script-tag "latn") + ("pl" :babel "polish" :polyglossia "polish" :lang-name "Polish" :script "latin" :script-tag "latn") + ("pms" :babel "piedmontese" :polyglossia "piedmontese" :lang-name "Piedmontese" :script "latin" :script-tag "latn") + ("pt" :babel "portuges" :polyglossia "portuges" :lang-name "Portuges" :script "latin" :script-tag "latn") + ("pt-br" :babel "brazilian" :polyglossia "brazilian" :lang-name "Portuges" :script "latin" :script-tag "latn") + ("rm" :babel-ini-only "romansh" :polyglossia "romansh" :lang-name "Romansh" :script "latin" :script-tag "latn") + ("ro" :babel "romanian" :polyglossia "romanian" :lang-name "Romanian" :script "latin" :script-tag "latn") + ("ru" :babel "russian" :polyglossia "russian" :lang-name "Russian" :script "cyrillic" :script-tag "cyrl") + ("sa" :babel-ini-only "sanskrit" :polyglossia "sanskrit" :lang-name "Sanskrit" :script "devanagari" :script-tag "deva") + ("sk" :babel "slovak" :polyglossia "slovak" :lang-name "Slovak" :script "latin" :script-tag "latn") + ("sl" :babel "slovene" :polyglossia "slovene" :lang-name "Slovene" :script "latin" :script-tag "latn") + ("sq" :babel "albanian" :polyglossia "albanian" :lang-name "Albanian" :script "latin" :script-tag "latn") + ("sr" :babel "serbian" :polyglossia "serbian" :lang-name "Serbian" :script "latin" :script-tag "latn") + ("sr-cyrl" :babel-ini-only "serbian-cyrl" :polyglossia "serbian" :lang-name "Serbian" :script "cyrillic" :script-tag "cyrl") + ("sr-latn" :babel-ini-only "serbian-latin" :polyglossia "serbian" :lang-name "Serbian" :script "latin" :script-tag "latn") + ("sv" :babel "swedish" :polyglossia "swedish" :lang-name "Swedish" :script "latin" :script-tag "latn") + ("syr" :babel-ini-only "syriac" :polyglossia "syriac" :lang-name "Syriac" :script "syriac" :script-tag "syrc") + ("ta" :babel-ini-only "tamil" :polyglossia "tamil" :lang-name "Tamil" :script "tamil" :script-tag "taml") + ("te" :babel-ini-only "telugu" :polyglossia "telugu" :lang-name "Telugu" :script "telugu" :script-tag "telu") + ("th" :babel "thai" :polyglossia "thai" :lang-name "Thai" :script "thai" :script-tag "thai") + ("tk" :babel "turkmen" :polyglossia "turkmen" :lang-name "Turkmen" :script "latin" :script-tag "latn") + ("tr" :babel "turkish" :polyglossia "turkish" :lang-name "Turkish" :script "latin" :script-tag "latn") + ("uk" :babel "ukrainian" :polyglossia "ukrainian" :lang-name "Ukrainian" :script "cyrillic" :script-tag "cyrl") + ("ur" :babel-ini-only "urdu" :polyglossia "urdu" :lang-name "Urdu" :script "arabic" :script-tag "arab") + ("vi" :babel "vietnamese" :polyglossia "vietnamese" :lang-name "Vietnamese" :script "latin" :script-tag "latn") + ("zh" ,@zh-default-plist) + ("zh-cn" ,@zh-default-plist) + ("zh-tw" :babel-ini-only "chinese-traditional" :polyglossia "chinese" :polyglossia-variant "traditional" :lang-name "Chinese Traditional" :script "hant" :script-tag "hant"))) "Alist between language code and its properties for LaTeX export. -In each element of the list car is always the code of the -language and cdr is a property list. Valid keywords for this -list can be: +In each element of the list car is always the language code and +cdr is a property list. Valid keywords for this list can be: - `:babel' the name of the language loaded by the Babel LaTeX package @@ -274,27 +287,22 @@ list can be: exclusively through the new ini files method. See `http://mirrors.ctan.org/macros/latex/required/babel/base/babel.pdf' +- `:babel-ini-alt' an alternative language name when it is loaded + using ini files + - `:polyglossia-variant' the language variant loaded by Polyglossia -- `:lang-name' the actual name of the language.") +- `:lang-name' the actual name of the language -(defconst org-latex-line-break-safe "\\\\[0pt]" - "Linebreak protecting the following [...]. +- `:script' the script name -Without \"[0pt]\" it would be interpreted as an optional argument to -the \\\\. +- `:script-tag' the script otf tag.") -This constant, for example, makes the below code not err: -\\begin{tabular}{c|c} - [t] & s\\\\[0pt] - [I] & A\\\\[0pt] - [m] & kg -\\end{tabular}") -(defconst org-latex-table-matrix-macros `(("bordermatrix" . "\\cr") +(defconst org-latex-table-matrix-macros '(("bordermatrix" . "\\cr") ("qbordermatrix" . "\\cr") - ("kbordermatrix" . ,org-latex-line-break-safe)) + ("kbordermatrix" . "\\\\")) "Alist between matrix macros and their row ending.") (defconst org-latex-math-environments-re @@ -394,7 +402,8 @@ references." :group 'org-export-latex :type 'boolean :version "26.1" - :package-version '(Org . "8.3")) + :package-version '(Org . "8.3") + :safe #'booleanp) (defcustom org-latex-reference-command "\\ref{%s}" "Format string that takes a reference to produce a LaTeX reference command. @@ -405,8 +414,7 @@ use of a package such as hyperref or cleveref and then change the format string to \"\\autoref{%s}\" or \"\\cref{%s}\" for example." :group 'org-export-latex :type 'string - :package-version '(Org . "9.5") - :safe #'stringp) + :package-version '(Org . "9.5")) ;;;; Preamble @@ -600,8 +608,9 @@ which is replaced with the subtitle." (defcustom org-latex-toc-command "\\tableofcontents\n\n" "LaTeX command to set the table of contents, list of figures, etc. -This command only applies to the table of contents generated with -the toc:nil option, not to those generated with #+TOC keyword." +This command only applies to the table of contents generated with the +toc:t, toc:1, toc:2, toc:3, ... options, not to those generated with +the #+TOC keyword." :group 'org-export-latex :type 'string) @@ -659,6 +668,17 @@ The function result will be used in the section format string." ;;;; Footnotes +(defcustom org-latex-default-footnote-command "\\footnote{%s%s}" + "Default command used to insert footnotes. +Customize this command if the LaTeX class provides a different +command like \"\\sidenote{%s%s}\" that you want to use. +The value will be passed as an argument to `format' as the following + (format org-latex-default-footnote-command + footnote-description footnote-label)" + :group 'org-export-latex + :package-version '(Org . "9.7") + :type 'string) + (defcustom org-latex-footnote-separator "\\textsuperscript{,}\\," "Text used to separate footnotes." :group 'org-export-latex @@ -725,8 +745,7 @@ or if the image is wrapped within a \"wrapfigure\" environment. Scale overrides width and height." :group 'org-export-latex :package-version '(Org . "9.3") - :type 'string - :safe #'stringp) + :type 'string) (defcustom org-latex-image-default-height "" "Default height for images. @@ -743,8 +762,7 @@ environment." :group 'org-export-latex :type 'string :version "26.1" - :package-version '(Org . "9.0") - :safe #'stringp) + :package-version '(Org . "9.0")) (defcustom org-latex-inline-image-rules `(("file" . ,(rx "." @@ -774,7 +792,6 @@ default we use here encompasses both." :group 'org-export-latex :type 'string) - ;;;; Tables (defcustom org-latex-default-table-environment "tabular" @@ -788,8 +805,7 @@ default we use here encompasses both." "Default environment used to `quote' blocks." :group 'org-export-latex :package-version '(Org . "9.5") - :type 'string - :safe #'stringp) + :type 'string) (defcustom org-latex-default-table-mode 'table "Default mode for tables. @@ -949,7 +965,7 @@ would like color too. These can simply be added to (add-to-list \\='org-latex-packages-alist \\='(\"\" \"color\")) There are two further options for more comprehensive -fontification. The first can be set with, +fontification. The first can be set with, (setq org-latex-src-block-backend \\='minted) @@ -977,8 +993,8 @@ The most comprehensive option can be set with, which causes source code to be run through `engrave-faces-latex-buffer', which generates colorings using -Emacs' font-lock information. This requires the Emacs package -engrave-faces (available from ELPA), and the LaTeX package +Emacs's font-lock information. This requires the Emacs package +engrave-faces (available from GNU ELPA), and the LaTeX package fvextra be installed. The styling of the engraved result can be customized with @@ -1021,11 +1037,28 @@ in this list - but it does not hurt if it is present." (symbol :tag "Major mode ") (string :tag "Listings language")))) +(defcustom org-latex-listings-src-omit-language nil + "Discard src block language parameter in listings. + +Set this option to t to omit the \"language=\" in the parameters to +\"lstlisting\" environments when exporting an src block. + +This is necessary, for example, when the \"fancyvrb\" package is used +instead of \"listings\": + +#+LATEX_HEADER: \\RequirePackage{fancyvrb} +#+LATEX_HEADER: \\DefineVerbatimEnvironment{verbatim}{Verbatim}{...} +#+LATEX_HEADER: \\DefineVerbatimEnvironment{lstlisting}{Verbatim}{...}" + :group 'org-export-latex + :package-version '(Org . "9.7") + :type 'boolean + :safe #'booleanp) + (defcustom org-latex-listings-options nil "Association list of options for the latex listings package. These options are supplied as a comma-separated list to the -\\lstset command. Each element of the association list should be +\\lstlisting command. Each element of the association list should be a list or cons cell containing two strings: the name of the option, and the value. For example, @@ -1262,9 +1295,10 @@ block-specific options, you may use the following syntax: (defcustom org-latex-engraved-theme nil "The theme that should be used for engraved code, when non-nil. -This can be set to any theme defined in `engrave-faces-themes' or -loadable by Emacs. When set to t, the current Emacs theme is -used. When nil, no theme is applied." +This can be set to any theme defined in `engrave-faces-themes' +(from the engrave-faces package) or loadable by Emacs. When set +to t, the current Emacs theme is used. When nil, no theme is +applied." :group 'org-export-latex :package-version '(Org . "9.6") :type 'symbol) @@ -1272,8 +1306,8 @@ used. When nil, no theme is applied." (defun org-latex-generate-engraved-preamble (info) "Generate the preamble to setup engraved code. The result is constructed from the :latex-engraved-preamble and -:latex-engraved-options export options, the default values of -which are given by `org-latex-engraved-preamble' and +:latex-engraved-options export options (passed via INFO plist), the +default values of which are given by `org-latex-engraved-preamble' and `org-latex-engraved-options' respectively." (let* ((engraved-options (plist-get info :latex-engraved-options)) @@ -1324,7 +1358,8 @@ which are given by `org-latex-engraved-preamble' and \\floatname{listing}{\\listingsname} \\newcommand{\\listoflistingsname}{List of Listings} \\providecommand{\\listoflistings}{\\listof{listing}{\\listoflistingsname}}\n" - (if (memq 'src-block org-latex-caption-above) + (if (org-latex--caption-above-p + (org-element-create 'src-block) info) "plaintop" "plain")) t t engraved-preamble))) @@ -1356,7 +1391,7 @@ which are given by `org-latex-engraved-preamble' and "\n")) (t (funcall gen-theme-spec engraved-theme)))) (funcall gen-theme-spec engraved-theme)) - (message "Cannot engrave source blocks. Consider installing `engrave-faces'.") + (warn "Cannot engrave source blocks. Consider installing `engrave-faces'.") "% WARNING syntax highlighting unavailable as engrave-faces-latex was missing.\n") "\n"))) @@ -1487,14 +1522,15 @@ logfiles to remove, set `org-latex-logfiles-extensions'." ("Underfull \\hbox" . "[underfull hbox]") ("Overfull \\hbox" . "[overfull hbox]") ("Citation.*?undefined" . "[undefined citation]") + ("^!.+Unicode character" . "[unicode character(s) not supported by pdflatex. Set org-latex-compiler to lualatex or xelatex instead]") + ("Missing character: There is no" . "[Missing character(s): please load an appropriate font with the fontspec package]") ("Undefined control sequence" . "[undefined control sequence]")) "Alist of regular expressions and associated messages for the user. The regular expressions are used to find possible warnings in the log of a LaTeX-run. These warnings will be reported after calling `org-latex-compile'." :group 'org-export-latex - :version "26.1" - :package-version '(Org . "8.3") + :package-version '(Org . "9.7") :type '(repeat (cons (regexp :tag "Regexp") @@ -1524,12 +1560,11 @@ this case always return a unique label. Eventually, if FULL is non-nil, wrap label within \"\\label{}\"." (let* ((type (org-element-type datum)) (user-label - (org-element-property - (cl-case type - ((headline inlinetask) :CUSTOM_ID) - (target :value) - (otherwise :name)) - datum)) + (cl-case type + ((headline inlinetask) (org-element-property :CUSTOM_ID datum)) + (target (org-element-property :value datum)) + (otherwise (or (org-element-property :name datum) + (car (org-element-property :results datum)))))) (label (and (or user-label force) (if (and user-label (plist-get info :latex-prefer-user-labels)) @@ -1587,6 +1622,11 @@ For non-floats, see `org-latex--wrap-label'." (let ((type* (if (eq type 'latex-environment) (org-latex--environment-type element) type))) + ;; \captionof{%s} + ;; %s must be a registered LaTeX environment. + ;; figure is always there, while listing is defined by + ;; additional packages. + ;; See https://list.orgmode.org/orgmode/87twtovkjh.fsf@gmx.us/ (if nonfloat (cl-case type* (paragraph "figure") @@ -1631,7 +1671,7 @@ explicitly been loaded. Then it is added to the rest of package's options. The optional argument to Babel or the mandatory argument to -`\babelprovide' command may be \"AUTO\" which is then replaced +`\\babelprovide' command may be \"AUTO\" which is then replaced with the language of the document or `org-export-default-language' unless language in question is already loaded. @@ -1642,6 +1682,7 @@ Return the new header." (assoc language-code org-latex-language-alist))) (language (plist-get plist :babel)) (language-ini-only (plist-get plist :babel-ini-only)) + (language-ini-alt (plist-get plist :babel-ini-alt)) ;; If no language is set, or Babel package is not loaded, or ;; LANGUAGE keyword value is a language served by Babel ;; exclusively through ini files, return HEADER as-is. @@ -1673,7 +1714,8 @@ Return the new header." (replace-regexp-in-string (format "\\(\\\\babelprovide\\[.*\\]\\)\\({\\)%s}" prov) (format "\\1\\2%s}" - (or language language-ini-only)) + (if language-ini-alt language-ini-alt + (or language language-ini-only))) header t) header))))) @@ -1743,6 +1785,8 @@ and `org-latex-default-packages-alist'. If the fourth argument of a package is neither nil nor a member of the LaTeX compiler associated to the document, the package is removed. +LaTeX compiler is defined in :latex-compiler INFO plist entry. + Return new list of packages." (let ((compiler (or (plist-get info :latex-compiler) ""))) (if (not (member-ignore-case compiler org-latex-compilers)) pkg-alist @@ -1763,7 +1807,7 @@ This is used to choose a separator for constructs like \\verb." return (char-to-string c)))) (defun org-latex--make-option-string (options &optional separator) - "Return a comma separated string of keywords and values. + "Return a comma or SEPARATOR separated string of keywords and values. OPTIONS is an alist where the key is the options keyword as a string, and the value a list containing the keyword value, or nil." @@ -1786,11 +1830,11 @@ nil." INFO is the current export state, as a plist. This function should not be used for floats. See `org-latex--caption/label-string'." - (if (not (and (org-string-nw-p output) (org-element-property :name element))) - output - (concat (format "\\phantomsection\n\\label{%s}\n" - (org-latex--label element info)) - output))) + (let ((label (org-latex--label element info))) + (if (not (and (org-string-nw-p output) label)) + output + (concat (format "\\phantomsection\n\\label{%s}\n" label) + output)))) (defun org-latex--protect-text (text) "Protect special characters in string TEXT and return it." @@ -1874,7 +1918,7 @@ INFO is a plist used as a communication channel." (org-export-translate s :latex info)) (defun org-latex--format-spec (info) - "Create a format-spec for document meta-data. + "Create a format spec for document meta-data. INFO is a plist used as a communication channel." (let ((language (let* ((lang (plist-get info :language)) (plist (cdr @@ -1970,7 +2014,7 @@ holding export options." (let ((title (org-export-data (plist-get info :title) info)) (spec (org-latex--format-spec info))) (concat - ;; Time-stamp. + ;; Timestamp. (and (plist-get info :time-stamp-file) (format-time-string "%% Created %Y-%m-%d %a %H:%M\n")) ;; LaTeX compiler. @@ -2013,7 +2057,7 @@ holding export options." (and (stringp template) (format-spec template spec))) ;; engrave-faces-latex preamble - (when (and (eq org-latex-src-block-backend 'engraved) + (when (and (eq (plist-get info :latex-src-block-backend) 'engraved) (org-element-map (plist-get info :parse-tree) '(src-block inline-src-block) #'identity info t)) @@ -2081,7 +2125,7 @@ information." (concat (org-timestamp-translate (org-element-property :value clock)) (let ((time (org-element-property :duration clock))) (and time (format " (%s)" time))))) - org-latex-line-break-safe)) + "\\\\")) ;;;; Code @@ -2182,7 +2226,7 @@ CONTENTS is nil. INFO is a plist holding contextual information." (concat ;; Insert separator between two footnotes in a row. (let ((prev (org-export-get-previous-element footnote-reference info))) - (when (eq (org-element-type prev) 'footnote-reference) + (when (org-element-type-p prev 'footnote-reference) (plist-get info :latex-footnote-separator))) (cond ;; Use `:latex-footnote-defined-format' if the footnote has @@ -2198,14 +2242,14 @@ CONTENTS is nil. INFO is a plist holding contextual information." ((or (org-element-lineage footnote-reference '(footnote-reference footnote-definition table-cell verse-block)) - (eq 'item (org-element-type - (org-export-get-parent-element footnote-reference)))) + (org-element-type-p + (org-element-parent-element footnote-reference) 'item)) "\\footnotemark") ;; Otherwise, define it with \footnote command. (t (let ((def (org-export-get-footnote-definition footnote-reference info))) (concat - (format "\\footnote{%s%s}" (org-trim (org-export-data def info)) + (format (plist-get info :latex-default-footnote-command) (org-trim (org-export-data def info)) ;; Only insert a \label if there exist another ;; reference to def. (cond ((not label) "") @@ -2256,9 +2300,9 @@ holding contextual information." ((= (length sec) 4) (if numberedp (concat (car sec) "\n%s" (nth 1 sec)) (concat (nth 2 sec) "\n%s" (nth 3 sec))))))) - ;; Create a temporary export back-end that hard-codes + ;; Create a temporary export backend that hard-codes ;; "\underline" within "\section" and alike. - (section-back-end + (section-backend (org-export-create-backend :parent 'latex :transcoders @@ -2269,9 +2313,22 @@ holding contextual information." ;; with \texttt. (code . (lambda (o _ _) (org-latex--protect-texttt (org-element-property :value o)))) (verbatim . (lambda (o _ _) (org-latex--protect-texttt (org-element-property :value o))))))) + ;; Create a temporary export backend that strips footnotes from title. + ;; Footnotes are not allowed in \section and similar + ;; commands that contribute to TOC and footers. + ;; See https://orgmode.org/list/691643eb-49d0-45c3-ab7f-a1edbd093bef@gmail.com + ;; https://texfaq.org/FAQ-ftnsect + (section-no-footnote-backend + (org-export-create-backend + :parent section-backend + :transcoders + `((footnote-reference . ignore)))) (text (org-export-data-with-backend - (org-element-property :title headline) section-back-end info)) + (org-element-property :title headline) section-backend info)) + (text-no-footnote + (org-export-data-with-backend + (org-element-property :title headline) section-no-footnote-backend info)) (todo (and (plist-get info :with-todo-keywords) (let ((todo (org-element-property :todo-keyword headline))) @@ -2285,6 +2342,9 @@ holding contextual information." ;; The latter is required to remove tags from toc. (full-text (funcall (plist-get info :latex-format-headline-function) todo todo-type priority text tags info)) + (full-text-no-footnote + (funcall (plist-get info :latex-format-headline-function) + todo todo-type priority text-no-footnote tags info)) ;; Associate \label to the headline for internal links. (headline-label (org-latex--label headline info t t)) (pre-blanks @@ -2323,7 +2383,7 @@ holding contextual information." todo todo-type priority (org-export-data-with-backend (org-export-get-alt-title headline info) - section-back-end info) + section-backend info) (and (eq (plist-get info :with-tags) t) tags) info)) ;; Maybe end local TOC (see `org-latex-keyword'). @@ -2333,7 +2393,7 @@ holding contextual information." (let ((case-fold-search t) (section (let ((first (car (org-element-contents headline)))) - (and (eq (org-element-type first) 'section) first)))) + (and (org-element-type-p first 'section) first)))) (org-element-map section 'keyword (lambda (k) (and (equal (org-element-property :key k) "TOC") @@ -2342,10 +2402,14 @@ holding contextual information." (string-match-p "\\" v) (format "\\stopcontents[level-%d]" level))))) info t))))) - (if (and opt-title - (not (equal opt-title full-text)) + (if (and (or (and opt-title (not (equal opt-title full-text))) + ;; Heading contains footnotes. Add optional title + ;; version without footnotes to avoid footnotes in + ;; TOC/footers. + (and (not (equal full-text-no-footnote full-text)) + (setq opt-title full-text-no-footnote))) (string-match "\\`\\\\\\(.+?\\){" section-fmt)) - (format (replace-match "\\1[%s]" nil nil section-fmt 1) + (format (replace-match "\\1[%s]" nil nil section-fmt 1) ;; Replace square brackets with parenthesis ;; since square brackets are not supported in ;; optional arguments. @@ -2402,13 +2466,13 @@ contextual information." (let ((code (org-element-property :value inline-src-block)) (lang (org-element-property :language inline-src-block))) (pcase (plist-get info :latex-src-block-backend) - (`verbatim (org-latex--text-markup code 'code info)) + ((or `verbatim (guard (not lang))) (org-latex--text-markup code 'code info)) (`minted (org-latex-inline-src-block--minted info code lang)) (`engraved (org-latex-inline-src-block--engraved info code lang)) (`listings (org-latex-inline-src-block--listings info code lang)) (oldval - (message "Please update the LaTeX src-block-backend to %s" - (if oldval "listings" "verbatim")) + (warn "Please update `org-latex-src-block-backend' to %s" + (if oldval "listings" "verbatim")) (if oldval (org-latex-inline-src-block--listings info code lang) (org-latex--text-markup code 'code info)))))) @@ -2503,16 +2567,16 @@ contextual information." CONTENTS holds the contents of the item. INFO is a plist holding contextual information." (let* ((orderedp (eq (org-element-property - :type (org-export-get-parent item)) + :type (org-element-parent item)) 'ordered)) (level ;; Determine level of current item to determine the ;; correct LaTeX counter to use (enumi, enumii...). (let ((parent item) (level 0)) - (while (memq (org-element-type - (setq parent (org-export-get-parent parent))) - '(plain-list item)) - (when (and (eq (org-element-type parent) 'plain-list) + (while (org-element-type-p + (setq parent (org-element-parent parent)) + '(plain-list item)) + (when (and (org-element-type-p parent 'plain-list) (eq (org-element-property :type parent) 'ordered)) (cl-incf level))) @@ -2553,11 +2617,11 @@ contextual information." ((and contents (string-match-p "\\`[ \t]*\\[" contents) (not (let ((e (car (org-element-contents item)))) - (and (eq (org-element-type e) 'paragraph) - (let ((o (car (org-element-contents e)))) - (and (eq (org-element-type o) 'export-snippet) - (eq (org-export-snippet-backend o) - 'latex))))))) + (and (org-element-type-p e 'paragraph) + (let ((o (car (org-element-contents e)))) + (and (org-element-type-p o 'export-snippet) + (eq (org-export-snippet-backend o) + 'latex))))))) "\\relax ") (t " ")) (and contents (org-trim contents))))) @@ -2578,7 +2642,7 @@ CONTENTS is nil. INFO is a plist holding contextual information." (cond ((string-match-p "\\" value) (let* ((localp (string-match-p "\\" value)) - (parent (org-element-lineage keyword '(headline))) + (parent (org-element-lineage keyword 'headline)) (level (if (not (and localp parent)) 0 (org-export-get-relative-level parent info))) (depth @@ -2641,9 +2705,10 @@ CONTENTS is nil. INFO is a plist holding contextual information." (org-latex--label latex-environment info nil t) (org-latex--caption/label-string latex-environment info))) (caption-above-p - (memq type (append (plist-get info :latex-caption-above) '(math))))) + (or (eq type 'math) + (org-latex--caption-above-p latex-environment info)))) (if (not (or (org-element-property :name latex-environment) - (org-element-property :caption latex-environment))) + (org-element-property :caption latex-environment))) value ;; Environment is labeled: label must be within the environment ;; (otherwise, a reference pointing to that element will count @@ -2678,7 +2743,7 @@ CONTENTS is nil. INFO is a plist holding contextual information." (defun org-latex-line-break (_line-break _contents _info) "Transcode a LINE-BREAK object from Org to LaTeX. CONTENTS is nil. INFO is a plist holding contextual information." - (concat org-latex-line-break-safe "\n")) + "\\\\\n") ;;;; Link @@ -2690,7 +2755,7 @@ CONTENTS is nil. INFO is a plist holding contextual information." "Return LaTeX code for an inline image. LINK is the link pointing to the inline image. INFO is a plist used as a communication channel." - (let* ((parent (org-export-get-parent-element link)) + (let* ((parent (org-element-parent-element link)) (path (let ((raw-path (org-element-property :path link))) (if (not (file-name-absolute-p raw-path)) raw-path (expand-file-name raw-path)))) @@ -2700,16 +2765,33 @@ used as a communication channel." ;; Retrieve latex attributes from the element around. (attr (org-export-read-attribute :attr_latex parent)) (float (let ((float (plist-get attr :float))) - (cond ((string= float "wrap") 'wrap) - ((string= float "sideways") 'sideways) - ((string= float "multicolumn") 'multicolumn) - ((string= float "t") 'figure) - ((and (plist-member attr :float) (not float)) 'nonfloat) - (float float) - ((or (org-element-property :caption parent) - (org-string-nw-p (plist-get attr :caption))) - 'figure) - (t 'nonfloat)))) + (cond + ((org-element-map (org-element-contents parent) t + (lambda (node) + (cond + ((and (org-element-type-p node 'plain-text) + (not (org-string-nw-p node))) + nil) + ((eq link node) + ;; Objects inside link description are + ;; allowed. + (throw :org-element-skip nil)) + (t 'not-a-float))) + info 'first-match) + ;; Not a single link inside paragraph (spaces + ;; ignored). Cannot use float environment. It + ;; would be inside paragraph. + nil) + ((string= float "wrap") 'wrap) + ((string= float "sideways") 'sideways) + ((string= float "multicolumn") 'multicolumn) + ((string= float "t") 'figure) + ((and (plist-member attr :float) (not float)) 'nonfloat) + (float float) + ((or (org-element-property :caption parent) + (org-string-nw-p (plist-get attr :caption))) + 'figure) + (t 'nonfloat)))) (placement (let ((place (plist-get attr :placement))) (cond @@ -2721,7 +2803,7 @@ used as a communication channel." (center (cond ;; If link is an image link, do not center. - ((eq 'link (org-element-type (org-export-get-parent link))) nil) + ((org-element-type-p (org-element-parent link) 'link) nil) ((plist-member attr :center) (plist-get attr :center)) (t (plist-get info :latex-images-centered)))) (comment-include (if (plist-get attr :comment-include) "%" "")) @@ -2876,12 +2958,10 @@ INFO is a plist holding contextual information. See link (plist-get info :latex-inline-image-rules))) (path (org-latex--protect-text (pcase type - ((or "http" "https" "ftp" "mailto" "doi") - (concat type ":" raw-path)) ("file" (org-export-file-uri raw-path)) (_ - raw-path))))) + (concat type ":" raw-path)))))) (cond ;; Link type is handled by a special function. ((org-export-custom-protocol-maybe link desc 'latex info)) @@ -2964,7 +3044,12 @@ information." "Transcode a PARAGRAPH element from Org to LaTeX. CONTENTS is the contents of the paragraph, as a string. INFO is the plist used as a communication channel." - contents) + ;; Ensure that we do not create multiple paragraphs, when a single + ;; paragraph is expected. + ;; Multiple newlines may appear in CONTENTS, for example, when + ;; certain objects are stripped from export, leaving single newlines + ;; before and after. + (org-remove-blank-lines contents)) ;;;; Plain List @@ -3024,9 +3109,16 @@ contextual information." ;; Handle break preservation if required. (when (plist-get info :preserve-breaks) (setq output (replace-regexp-in-string - "\\(?:[ \t]*\\\\\\\\\\)?[ \t]*\n" - (concat org-latex-line-break-safe "\n") - output nil t))) + "\\(?:[ \t]*\\\\\\\\\\)?[ \t]*\n" "\\\\\n" output nil t))) + ;; Protect [foo] at the beginning of lines / beginning of the + ;; plain-text object. This prevents LaTeX from unexpectedly + ;; interpreting @@latex:\pagebreak@@ [foo] as a command with + ;; optional argument. + (setq output (replace-regexp-in-string + (rx bol (0+ space) (group "[")) + "{[}" + output + nil nil 1)) ;; Return value. output)) @@ -3062,7 +3154,7 @@ information." (format (plist-get info :latex-active-timestamp-format) (org-timestamp-translate scheduled))))))) " ") - org-latex-line-break-safe)) + "\\\\")) ;;;; Property Drawer @@ -3093,9 +3185,8 @@ it." (plist-get info :latex-default-table-mode)))) (when (and (member mode '("inline-math" "math")) ;; Do not wrap twice the same table. - (not (eq (org-element-type - (org-element-property :parent table)) - 'latex-matrices))) + (not (org-element-type-p + (org-element-parent table) 'latex-matrices))) (let* ((caption (and (not (string= mode "inline-math")) (org-element-property :caption table))) (name (and (not (string= mode "inline-math")) @@ -3118,7 +3209,7 @@ it." (while (and (zerop (or (org-element-property :post-blank previous) 0)) (setq next (org-export-get-next-element previous info)) - (eq (org-element-type next) 'table) + (org-element-type-p next 'table) (eq (org-element-property :type next) 'org) (string= (or (org-export-read-attribute :attr_latex next :mode) @@ -3126,8 +3217,8 @@ it." mode)) (org-element-put-property table :name nil) (org-element-put-property table :caption nil) - (org-element-extract-element previous) - (org-element-adopt-elements matrices previous) + (org-element-extract previous) + (org-element-adopt matrices previous) (setq previous next)) ;; Inherit `:post-blank' from the value of the last ;; swallowed table. Set the latter's `:post-blank' @@ -3137,8 +3228,8 @@ it." (org-element-put-property previous :post-blank 0) (org-element-put-property table :name nil) (org-element-put-property table :caption nil) - (org-element-extract-element previous) - (org-element-adopt-elements matrices previous)))))) + (org-element-extract previous) + (org-element-adopt matrices previous)))))) info) data) @@ -3181,24 +3272,23 @@ containing export options. Modify DATA by side-effect and return it." (org-element-map data '(entity latex-fragment) (lambda (object) ;; Skip objects already wrapped. - (when (and (not (eq (org-element-type - (org-element-property :parent object)) - 'latex-math-block)) + (when (and (not (org-element-type-p + (org-element-parent object) 'latex-math-block)) (funcall valid-object-p object)) (let ((math-block (list 'latex-math-block nil)) (next-elements (org-export-get-next-element object info t)) (last object)) ;; Wrap MATH-BLOCK around OBJECT in DATA. (org-element-insert-before math-block object) - (org-element-extract-element object) - (org-element-adopt-elements math-block object) + (org-element-extract object) + (org-element-adopt math-block object) (when (zerop (or (org-element-property :post-blank object) 0)) ;; MATH-BLOCK swallows consecutive math objects. (catch 'exit (dolist (next next-elements) (unless (funcall valid-object-p next) (throw 'exit nil)) - (org-element-extract-element next) - (org-element-adopt-elements math-block next) + (org-element-extract next) + (org-element-adopt math-block next) ;; Eschew the case: \beta$x$ -> \(\betax\). (org-element-put-property last :post-blank 1) (setq last next) @@ -3298,8 +3388,8 @@ contextual information." (`listings #'org-latex-src-block--listings) ((guard custom-env) #'org-latex-src-block--custom) (oldval - (message "Please update the LaTeX src-block-backend to %s" - (if oldval "listings" "verbatim")) + (warn "Please update `org-latex-src-block-backend' to %s" + (if oldval "listings" "verbatim")) (if oldval #'org-latex-src-block--listings #'org-latex-src-block--verbatim))) @@ -3458,7 +3548,7 @@ and FLOAT are extracted from SRC-BLOCK and INFO in `org-latex-src-block'." When the THEME symbol is non-nil, that theme will be used. When INLINE is nil, a Verbatim environment wrapped in a Code -environment will be used. When t, a Verb command will be used. +environment will be used. When t, a Verb command will be used. When OPTIONS is provided, as either a string or list of key-value pairs accepted by `org-latex--make-option-string', it is passed @@ -3475,8 +3565,8 @@ to the Verbatim environment or Verb command." (when lang-mode (if (functionp lang-mode) (funcall lang-mode) - (message "Cannot engrave code as %s. %s is undefined." - lang lang-mode))) + (warn "Cannot engrave code as %s. %s is undefined." + lang lang-mode))) (engrave-faces-latex-buffer))) (engraved-code (with-current-buffer engraved-buffer @@ -3501,7 +3591,7 @@ to the Verbatim environment or Verb command." engraved-wrapped "}") engraved-wrapped)) - (user-error "Cannot engrave code as `engrave-faces-latex' is unavailable."))) + (user-error "Cannot engrave code as `engrave-faces-latex' is unavailable"))) (cl-defun org-latex-src-block--engraved (&key src-block info lang caption caption-above-p num-start retain-labels attributes float &allow-other-keys) @@ -3595,12 +3685,16 @@ and FLOAT are extracted from SRC-BLOCK and INFO in `org-latex-src-block'." ((string= "multicolumn" float) '(("float" "*"))) ((and float (not (assoc "float" lst-opt))) `(("float" ,(plist-get info :latex-default-figure-position))))) - `(("language" ,lst-lang)) - (if label - `(("label" ,(org-latex--label src-block info))) - '(("label" " "))) - (if caption-str `(("caption" ,caption-str)) '(("caption" " "))) - `(("captionpos" ,(if caption-above-p "t" "b"))) + (unless (plist-get info :latex-listings-src-omit-language) + `(("language" ,lst-lang))) + (when label + `(("label" ,(org-latex--label src-block info)))) + (when caption-str + `(("caption" ,caption-str))) + (when caption-str + ;; caption-above-p means captionpos is t(op) + ;; else b(ottom) + `(("captionpos" ,(if caption-above-p "t" "b")))) (cond ((assoc "numbers" lst-opt) nil) ((not num-start) '(("numbers" "none"))) (t `(("firstnumber" ,(number-to-string (1+ num-start))) @@ -3666,7 +3760,7 @@ CONTENTS is the contents of the object." ;; takes care of tables with a "verbatim" mode. Otherwise, it ;; delegates the job to either `org-latex--table.el-table', ;; `org-latex--org-table', `org-latex--math-table' or -;; `org-latex--org-tabbing' functions, +;; `org-table--org-tabbing' functions, ;; depending of the type of the table and the mode requested. ;; ;; `org-latex--align-string' is a subroutine used to build alignment @@ -3840,11 +3934,11 @@ This function assumes TABLE has `org' as its `:type' property and (format "\\begin{%s}%s{%s}\n" table-env width alignment) (and above? (org-string-nw-p caption) - (concat caption org-latex-line-break-safe "\n")) + (concat caption "\\\\\n")) contents (and (not above?) (org-string-nw-p caption) - (concat caption org-latex-line-break-safe "\n")) + (concat caption "\\\\\n")) (format "\\end{%s}" table-env) (and fontsize "}")))) (t @@ -3929,7 +4023,7 @@ This function assumes TABLE has `org' as its `:type' property and (lambda (cell) (substring (org-element-interpret-data cell) 0 -1)) (org-element-map row 'table-cell #'identity info) "&") - (or (cdr (assoc env org-latex-table-matrix-macros)) org-latex-line-break-safe) + (or (cdr (assoc env org-latex-table-matrix-macros)) "\\\\") "\n"))) (org-element-map table 'table-row #'identity info) ""))) (concat @@ -3956,7 +4050,7 @@ This function assumes TABLE has `org' as its `:type' property and CONTENTS is the cell contents. INFO is a plist used as a communication channel." (let ((type (org-export-read-attribute - :attr_latex (org-export-get-parent-table table-cell) :mode)) + :attr_latex (org-element-lineage table-cell 'table) :mode)) (scientific-format (plist-get info :latex-table-scientific-notation))) (concat (if (and contents @@ -3979,7 +4073,7 @@ a communication channel." CONTENTS is the contents of the row. INFO is a plist used as a communication channel." (let* ((attr (org-export-read-attribute :attr_latex - (org-export-get-parent table-row))) + (org-element-parent table-row))) (booktabsp (if (plist-member attr :booktabs) (plist-get attr :booktabs) (plist-get info :latex-tables-booktabs))) (longtablep @@ -3996,22 +4090,34 @@ a communication channel." (org-export-get-previous-element table-row info) info)) "") (t "\\midrule")) + ;; Memorize table header in case it is multiline. We need this + ;; information to define contents before "\\endhead" in longtable environments. + (when (org-export-table-row-in-header-p table-row info) + (let ((table-head-cache (plist-get info :org-latex-table-head-cache))) + (unless (hash-table-p table-head-cache) + (setq table-head-cache (make-hash-table :test #'eq)) + (plist-put info :org-latex-table-head-cache table-head-cache)) + (if-let* ((head-contents (gethash (org-element-parent table-row) table-head-cache))) + (puthash (org-element-parent table-row) (concat head-contents "\\\\\n" contents) + table-head-cache) + (puthash (org-element-parent table-row) contents table-head-cache)))) + ;; Return LaTeX string as the transcoder. (concat ;; When BOOKTABS are activated enforce top-rule even when no ;; hline was specifically marked. (and booktabsp (not (org-export-get-previous-element table-row info)) "\\toprule\n") - contents org-latex-line-break-safe "\n" + contents "\\\\\n" (cond ;; Special case for long tables. Define header and footers. ((and longtablep (org-export-table-row-ends-header-p table-row info)) (let ((columns (cdr (org-export-table-dimensions - (org-export-get-parent-table table-row) info)))) + (org-element-lineage table-row 'table) info)))) (format "%s \\endfirsthead -\\multicolumn{%d}{l}{%s} \\\\[0pt] +\\multicolumn{%d}{l}{%s} \\\\ %s -%s \\\\[0pt]\n +%s \\\\\n %s \\endhead %s\\multicolumn{%d}{r}{%s} \\\\ @@ -4025,7 +4131,7 @@ a communication channel." "") (booktabsp "\\toprule\n") (t "\\hline\n")) - contents + (gethash (org-element-parent table-row) (plist-get info :org-latex-table-head-cache)) (if booktabsp "\\midrule" "\\hline") (if booktabsp "\\midrule" "\\hline") columns @@ -4089,10 +4195,11 @@ contextual information." (let* ((lin (org-export-read-attribute :attr_latex verse-block :lines)) (latcode (org-export-read-attribute :attr_latex verse-block :latexcode)) (cent (org-export-read-attribute :attr_latex verse-block :center)) + (lit (org-export-read-attribute :attr_latex verse-block :literal)) (attr (concat - (if cent "[\\versewidth]" "") - (if lin (format "\n\\poemlines{%s}" lin) "") - (if latcode (format "\n%s" latcode) ""))) + (if cent "[\\versewidth]" "") + (if lin (format "\n\\poemlines{%s}" lin) "") + (if latcode (format "\n%s" latcode) ""))) (versewidth (org-export-read-attribute :attr_latex verse-block :versewidth)) (vwidth (if versewidth (format "\\settowidth{\\versewidth}{%s}\n" versewidth) "")) (linreset (if lin "\n\\poemlines{0}" ""))) @@ -4101,20 +4208,37 @@ contextual information." verse-block ;; In a verse environment, add a line break to each newline ;; character and change each white space at beginning of a line - ;; into a space of 1 em. Also change each blank line with - ;; a vertical space of 1 em. + ;; into a normal space, calculated with `\fontdimen2\font'. One + ;; or more blank lines between lines are exported as a single + ;; blank line. If the `:lines' attribute is used, the last + ;; verse of each stanza ends with the string `\\!', according to + ;; the syntax of the `verse' package. The separation between + ;; stanzas can be controlled with the length `\stanzaskip', of + ;; the aforementioned package. If the `:literal' attribute is + ;; used, all blank lines are preserved and exported as + ;; `\vspace*{\baselineskip}', including the blank lines before + ;; or after CONTENTS. (format "%s\\begin{verse}%s\n%s\\end{verse}%s" vwidth attr (replace-regexp-in-string - "^[ \t]+" (lambda (m) (format "\\hspace*{%dem}" (length m))) + "^[ \t]+" (lambda (m) (format "\\hspace*{%d\\fontdimen2\\font}" (length m))) (replace-regexp-in-string - (concat "^[ \t]*" (regexp-quote org-latex-line-break-safe) "$") - "\\vspace*{1em}" + (if (not lit) + (rx-to-string + `(seq (group "\\\\\n") + (1+ (group line-start (0+ space) "\\\\\n")))) + "^[ \t]*\\\\$") + (if (not lit) + (if lin "\\\\!\n\n" "\n\n") + "\\vspace*{\\baselineskip}") (replace-regexp-in-string "\\([ \t]*\\\\\\\\\\)?[ \t]*\n" - (concat org-latex-line-break-safe "\n") - contents nil t) + "\\\\\n" + (if (not lit) + (concat (org-trim contents t) "\n") + contents) + nil t) nil t) nil t) linreset) @@ -4159,7 +4283,10 @@ will be displayed when `org-export-show-temporary-export-buffer' is non-nil." (interactive) (org-export-to-buffer 'latex "*Org LATEX Export*" - async subtreep visible-only body-only ext-plist (lambda () (LaTeX-mode)))) + async subtreep visible-only body-only ext-plist + (if (fboundp 'major-mode-remap) + (major-mode-remap 'latex-mode) + #'LaTeX-mode))) ;;;###autoload (defun org-latex-convert-region-to-latex () @@ -4170,6 +4297,8 @@ command to convert it." (interactive) (org-export-replace-region-by 'latex)) +(defalias 'org-export-region-to-latex #'org-latex-convert-region-to-latex) + ;;;###autoload (defun org-latex-export-to-latex (&optional async subtreep visible-only body-only ext-plist) @@ -4258,12 +4387,12 @@ produced." (and (search-forward-regexp (regexp-opt org-latex-compilers) (line-end-position 2) t) - (progn (beginning-of-line) (looking-at-p "%")) + (progn (forward-line 0) (eq (char-after) ?%)) (match-string 0))) ;; Cannot find the compiler inserted by ;; `org-latex-template' -> `org-latex--insert-compiler'. ;; Use a fallback. - "pdflatex")) + org-latex-compiler)) (process (if (functionp org-latex-pdf-process) org-latex-pdf-process ;; Replace "%latex" with "%L" and "%bib" and ;; "%bibtex" with "%B" to adhere to `format-spec' @@ -4278,28 +4407,47 @@ produced." (?L . ,(shell-quote-argument compiler)))) (log-buf-name "*Org PDF LaTeX Output*") (log-buf (and (not snippet) (get-buffer-create log-buf-name))) - (outfile (org-compile-file texfile process "pdf" - (format "See %S for details" log-buf-name) - log-buf spec))) - (unless snippet - (when org-latex-remove-logfiles - (mapc #'delete-file - (directory-files - (file-name-directory outfile) - t - (concat (regexp-quote (file-name-base outfile)) - "\\(?:\\.[0-9]+\\)?\\." - (regexp-opt org-latex-logfiles-extensions)) - t))) - (let ((warnings (org-latex--collect-warnings log-buf))) - (message (concat "PDF file produced" - (cond - ((eq warnings 'error) " with errors.") - (warnings (concat " with warnings: " warnings)) - (t ".")))))) + outfile) + ;; Erase compile buffer at the start. + (with-current-buffer log-buf + (erase-buffer)) + (setq outfile + (org-compile-file + texfile process "pdf" + (format "See %S for details" log-buf-name) + log-buf spec)) + (org-latex-compile--postprocess outfile log-buf snippet) ;; Return output file name. outfile)) +(defun org-latex-compile--postprocess (outfile log-buf &optional snippet) + "Process the results of creating OUTFILE via LaTeX compilation. +Warnings and errors are collected from LOG-BUF. +When SNIPPET is nil and `org-latex-remove-logfiles' non-nil, +log files (as specified by `org-latex-logfiles-extensions') are deleted." + (unless snippet + (when org-latex-remove-logfiles + (mapc #'delete-file + (directory-files + (or (file-name-directory outfile) default-directory) + t + (concat (regexp-quote (file-name-base outfile)) + "\\(?:\\.[0-9]+\\)?\\." + (regexp-opt org-latex-logfiles-extensions)) + t))) + (let ((warnings (org-latex--collect-warnings log-buf))) + (funcall + (if warnings + (apply-partially + #'display-warning + '(ox-latex)) + #'message) + (concat "PDF file produced" + (cond + ((eq warnings 'error) " with errors.") + (warnings (concat " with warnings: " warnings)) + (t "."))))))) + (defun org-latex--collect-warnings (buffer) "Collect some warnings from \"pdflatex\" command output. BUFFER is the buffer containing output. Return collected @@ -4309,7 +4457,11 @@ encountered or nil if there was none." (save-excursion (goto-char (point-max)) (when (re-search-backward "^[ \t]*This is .*?TeX.*?Version" nil t) - (if (re-search-forward "^!" nil t) 'error + (if (and + (re-search-forward "^!\\(.+\\)" nil t) + ;; This error is passed as missing character warning + (not (string-match-p "Unicode character" (match-string 1)))) + 'error (let ((case-fold-search t) (warnings "")) (dolist (warning org-latex-known-warnings) diff --git a/lisp/org/ox-man.el b/lisp/org/ox-man.el index bb716f7b..f527be3e 100644 --- a/lisp/org/ox-man.el +++ b/lisp/org/ox-man.el @@ -1,10 +1,10 @@ -;;; ox-man.el --- Man Back-End for Org Export Engine -*- lexical-binding: t; -*- +;;; ox-man.el --- Man Backend for Org Export Engine -*- lexical-binding: t; -*- -;; Copyright (C) 2011-2023 Free Software Foundation, Inc. +;; Copyright (C) 2011-2025 Free Software Foundation, Inc. ;; Author: Nicolas Goaziou ;; Luis R Anaya -;; Keywords: outlines, hypermedia, calendar, wp +;; Keywords: outlines, hypermedia, calendar, text ;; This file is part of GNU Emacs. @@ -23,7 +23,7 @@ ;;; Commentary: ;; -;; This library implements a Man back-end for Org generic exporter. +;; This library implements a Man backend for Org generic exporter. ;; ;; To test it, run ;; @@ -51,7 +51,7 @@ -;;; Define Back-End +;;; Define Backend (org-export-define-backend 'man '((babel-call . org-man-babel-call) @@ -293,6 +293,13 @@ This function shouldn't be used for floats. See "Protect minus and backslash characters in string TEXT." (replace-regexp-in-string "-" "\\-" text nil t)) +(defun org-man--protect-example (text) + "Escape necessary characters for verbatim TEXT." + ;; See man groff_man_style; \e must be used to render backslash. + ;; Note that groff's .eo (disable backslash) and .ec (re-enable + ;; backslash) cannot be used as per the same man page. + (replace-regexp-in-string "\\\\" "\\e" text nil t)) + ;;; Template @@ -400,7 +407,7 @@ information." (org-man--wrap-label example-block (format ".RS\n.nf\n%s\n.fi\n.RE" - (org-export-format-code-default example-block info)))) + (org-man--protect-example (org-export-format-code-default example-block info))))) ;;; Export Block @@ -510,8 +517,9 @@ contextual information." (expand-file-name "reshilite" tmpdir))) (org-lang (org-element-property :language inline-src-block)) (lst-lang - (cadr (assq (intern org-lang) - (plist-get info :man-source-highlight-langs)))) + (and org-lang + (cadr (assq (intern org-lang) + (plist-get info :man-source-highlight-langs))))) (cmd (concat (expand-file-name "source-highlight") " -s " lst-lang @@ -528,11 +536,11 @@ contextual information." (delete-file out-file) code-block) (format ".RS\n.nf\n\\fC\\m[black]%s\\m[]\\fP\n.fi\n.RE\n" - code)))) + (org-man--protect-example code))))) ;; Do not use a special package: transcode it verbatim. (t - (concat ".RS\n.nf\n" "\\fC" "\n" code "\n" + (concat ".RS\n.nf\n" "\\fC" "\n" (org-man--protect-example code) "\n" "\\fP\n.fi\n.RE\n"))))) @@ -554,7 +562,7 @@ contextual information." CONTENTS holds the contents of the item. INFO is a plist holding contextual information." (let* ((bullet (org-element-property :bullet item)) - (type (org-element-property :type (org-element-property :parent item))) + (type (org-element-property :type (org-element-parent item))) (checkbox (pcase (org-element-property :checkbox item) (`on "\\o'\\(sq\\(mu'") (`off "\\(sq ") @@ -614,10 +622,8 @@ INFO is a plist holding contextual information. See ;; Ensure DESC really exists, or set it to nil. (desc (and (not (string= desc "")) desc)) (path (pcase type - ((or "http" "https" "ftp" "mailto") - (concat type ":" raw-path)) ("file" (org-export-file-uri raw-path)) - (_ raw-path)))) + (_ (concat type ":" raw-path))))) (cond ;; Link type is handled by a special function. ((org-export-custom-protocol-maybe link desc 'man info)) @@ -645,19 +651,19 @@ information." "Transcode a PARAGRAPH element from Org to Man. CONTENTS is the contents of the paragraph, as a string. INFO is the plist used as a communication channel." - (let ((parent (plist-get (nth 1 paragraph) :parent))) + (let ((parent (org-element-parent paragraph))) (when parent - (let ((parent-type (car parent)) + (let ((parent-type (org-element-type parent)) (fixed-paragraph "")) (cond ((and (eq parent-type 'item) - (plist-get (nth 1 parent) :bullet )) + (org-element-property :bullet parent)) (setq fixed-paragraph (concat "" contents))) ((eq parent-type 'section) (setq fixed-paragraph (concat ".PP\n" contents))) ((eq parent-type 'footnote-definition) (setq fixed-paragraph contents)) (t (setq fixed-paragraph (concat "" contents)))) - fixed-paragraph )))) + fixed-paragraph)))) ;;; Plain List @@ -750,15 +756,16 @@ CONTENTS holds the contents of the item. INFO is a plist holding contextual information." (if (not (plist-get info :man-source-highlight)) (format ".RS\n.nf\n\\fC%s\\fP\n.fi\n.RE\n\n" - (org-export-format-code-default src-block info)) + (org-man--protect-example (org-export-format-code-default src-block info))) (let* ((tmpdir temporary-file-directory) (in-file (make-temp-name (expand-file-name "srchilite" tmpdir))) (out-file (make-temp-name (expand-file-name "reshilite" tmpdir))) (code (org-element-property :value src-block)) (org-lang (org-element-property :language src-block)) (lst-lang - (cadr (assq (intern org-lang) - (plist-get info :man-source-highlight-langs)))) + (and org-lang + (cadr (assq (intern org-lang) + (plist-get info :man-source-highlight-langs))))) (cmd (concat "source-highlight" " -s " lst-lang " -f groff_man " @@ -772,7 +779,7 @@ contextual information." (delete-file in-file) (delete-file out-file) code-block) - (format ".RS\n.nf\n\\fC\\m[black]%s\\m[]\\fP\n.fi\n.RE" code))))) + (format ".RS\n.nf\n\\fC\\m[black]%s\\m[]\\fP\n.fi\n.RE" (org-man--protect-example code)))))) ;;; Statistics Cookie @@ -836,9 +843,10 @@ contextual information." (format ".nf\n\\fC%s\\fP\n.fi" ;; Re-create table, without affiliated keywords. - (org-trim - (org-element-interpret-data - `(table nil ,@(org-element-contents table)))))) + (org-man--protect-example + (org-trim + (org-element-interpret-data + `(table nil ,@(org-element-contents table))))))) ;; Case 2: Standard table. (t (org-man-table--org-table table contents info)))) @@ -972,7 +980,7 @@ This function assumes TABLE has `org' as its `:type' attribute." ;;; Table Cell (defun org-man-table-cell (table-cell contents info) - "Transcode a TABLE-CELL element from Org to Man + "Transcode a TABLE-CELL element from Org to Man. CONTENTS is the cell contents. INFO is a plist used as a communication channel." (concat diff --git a/lisp/org/ox-md.el b/lisp/org/ox-md.el index 5be0ca22..0aa09703 100644 --- a/lisp/org/ox-md.el +++ b/lisp/org/ox-md.el @@ -1,10 +1,9 @@ -;;; ox-md.el --- Markdown Back-End for Org Export Engine -*- lexical-binding: t; -*- +;;; ox-md.el --- Markdown Backend for Org Export Engine -*- lexical-binding: t; -*- -;; Copyright (C) 2012-2023 Free Software Foundation, Inc. +;; Copyright (C) 2012-2025 Free Software Foundation, Inc. ;; Author: Nicolas Goaziou -;; Maintainer: Nicolas Goaziou -;; Keywords: org, wp, markdown +;; Keywords: org, text, markdown ;; This file is part of GNU Emacs. @@ -23,8 +22,8 @@ ;;; Commentary: -;; This library implements a Markdown back-end (vanilla flavor) for -;; Org exporter, based on `html' back-end. See Org manual for more +;; This library implements a Markdown backend (vanilla flavor) for +;; Org exporter, based on `html' backend. See Org manual for more ;; information. ;;; Code: @@ -40,7 +39,7 @@ ;;; User-Configurable Variables (defgroup org-export-md nil - "Options specific to Markdown export back-end." + "Options specific to Markdown export backend." :tag "Org Markdown" :group 'org-export :version "24.4" @@ -48,11 +47,15 @@ (defcustom org-md-headline-style 'atx "Style used to format headlines. -This variable can be set to either `atx' or `setext'." +This variable can be set to either `atx', `setext', or `mixed'. + +Mixed style uses Setext style markup for the first two headline levels +and uses ATX style markup for the remaining four levels." :group 'org-export-md :type '(choice (const :tag "Use \"atx\" style" atx) - (const :tag "Use \"Setext\" style" setext))) + (const :tag "Use \"Setext\" style" setext) + (const :tag "Use \"mixed\" style" mixed))) ;;;; Footnotes @@ -92,7 +95,7 @@ headings for its own use." -;;; Define Back-End +;;; Define Backend (org-export-define-derived-backend 'md 'html :filters-alist '((:filter-parse-tree . org-md-separate-elements)) @@ -150,10 +153,10 @@ headings for its own use." "Fix blank lines between elements. TREE is the parse tree being exported. BACKEND is the export -back-end used. INFO is a plist used as a communication channel. +backend used. INFO is a plist used as a communication channel. -Enforce a blank line between elements. There are two exceptions -to this rule: +Enforce a blank line between elements. There are exceptions to this +rule: 1. Preserve blank lines between sibling items in a plain list, @@ -161,16 +164,20 @@ to this rule: paragraph and the next sub-list when the latter ends the current item. + 3. Do not add blank lines after table rows. (This is irrelevant for + md exporter, but may surprise derived backends). + Assume BACKEND is `md'." - (org-element-map tree (remq 'item org-element-all-elements) + (org-element-map tree + (remq 'table-row (remq 'item org-element-all-elements)) (lambda (e) (org-element-put-property e :post-blank - (if (and (eq (org-element-type e) 'paragraph) - (eq (org-element-type (org-element-property :parent e)) 'item) + (if (and (org-element-type-p e 'paragraph) + (org-element-type-p (org-element-parent e) 'item) (org-export-first-sibling-p e info) (let ((next (org-export-get-next-element e info))) - (and (eq (org-element-type next) 'plain-list) + (and (org-element-type-p next 'plain-list) (not (org-export-get-next-element next info))))) 0 1)))) @@ -195,7 +202,7 @@ of contents can refer to headlines." (lambda (h) (let ((section (car (org-element-contents h)))) (and - (eq 'section (org-element-type section)) + (org-element-type-p section 'section) (org-element-map section 'keyword (lambda (keyword) (when (equal "TOC" (org-element-property :key keyword)) @@ -229,7 +236,7 @@ anchor tag for the section as a string. TAGS are the tags set on the section." (let ((anchor-lines (and anchor (concat anchor "\n\n")))) ;; Use "Setext" style - (if (and (eq style 'setext) (< level 3)) + (if (and (memq style '(setext mixed)) (< level 3)) (let* ((underline-char (if (= level 1) ?= ?-)) (underline (concat (make-string (length title) underline-char) "\n"))) @@ -305,13 +312,14 @@ INFO is a plist used as a communication channel." (section-title (org-html--translate "Footnotes" info))) (when fn-alist (format (plist-get info :md-footnotes-section) - (org-md--headline-title headline-style 1 section-title) + (org-md--headline-title headline-style (plist-get info :md-toplevel-hlevel) section-title) (mapconcat (lambda (fn) (org-md--footnote-formatted fn info)) fn-alist "\n"))))) (defun org-md--convert-to-html (datum _contents info) - "Convert DATUM into raw HTML, including contents." + "Convert DATUM into raw HTML. +CONTENTS is ignored. INFO is the info plist." (org-export-data-with-backend datum 'html info)) (defun org-md--identity (_datum contents _info) @@ -393,9 +401,10 @@ a communication channel." (cond ;; Cannot create a headline. Fall-back to a list. ((or (org-export-low-level-p headline info) - (not (memq style '(atx setext))) + (not (memq style '(atx mixed setext))) (and (eq style 'atx) (> level 6)) - (and (eq style 'setext) (> level 2))) + (and (eq style 'setext) (> level 2)) + (and (eq style 'mixed) (> level 6))) (let ((bullet (if (not (org-export-numbered-headline-p headline info)) "-" (concat (number-to-string @@ -437,7 +446,7 @@ as a communication channel." "Transcode ITEM element into Markdown format. CONTENTS is the item contents. INFO is a plist used as a communication channel." - (let* ((type (org-element-property :type (org-export-get-parent item))) + (let* ((type (org-element-property :type (org-element-parent item))) (struct (org-element-property :structure item)) (bullet (if (not (eq type 'ordered)) "-" (concat (number-to-string @@ -448,7 +457,7 @@ a communication channel." (org-list-parents-alist struct))))) ".")))) (concat bullet - (make-string (- 4 (length bullet)) ? ) + (make-string (max 1 (- 4 (length bullet))) ? ) (pcase (org-element-property :checkbox item) (`on "[X] ") (`trans "[-] ") @@ -540,11 +549,9 @@ INFO is a plist holding contextual information. See (type (org-element-property :type link)) (raw-path (org-element-property :path link)) (path (cond - ((member type '("http" "https" "ftp" "mailto")) - (concat type ":" raw-path)) ((string-equal type "file") (org-export-file-uri (funcall link-org-files-as-md raw-path))) - (t raw-path)))) + (t (concat type ":" raw-path))))) (cond ;; Link type is handled by a special function. ((org-export-custom-protocol-maybe link desc 'md info)) @@ -590,7 +597,7 @@ INFO is a plist holding contextual information. See (t (expand-file-name raw-path)))) (caption (org-export-data (org-export-get-caption - (org-export-get-parent-element link)) + (org-element-parent-element link)) info))) (format "![img](%s)" (if (not (org-string-nw-p caption)) path @@ -626,6 +633,12 @@ information." "Transcode PARAGRAPH element into Markdown format. CONTENTS is the paragraph contents. INFO is a plist used as a communication channel." + ;; Ensure that we do not create multiple paragraphs, when a single + ;; paragraph is expected. + ;; Multiple newlines may appear in CONTENTS, for example, when + ;; certain objects are stripped from export, leaving single newlines + ;; before and after. + (setq contents (org-remove-blank-lines contents)) (let ((first-object (car (org-element-contents paragraph)))) ;; If paragraph starts with a #, protect it. (if (and (stringp first-object) (string-prefix-p "#" first-object)) @@ -764,6 +777,7 @@ this command to convert it." (interactive) (org-export-replace-region-by 'md)) +(defalias 'org-export-region-to-md #'org-md-convert-region-to-md) ;;;###autoload (defun org-md-export-to-markdown (&optional async subtreep visible-only) diff --git a/lisp/org/ox-odt.el b/lisp/org/ox-odt.el index dd96ed8e..ba8b4d9d 100644 --- a/lisp/org/ox-odt.el +++ b/lisp/org/ox-odt.el @@ -1,9 +1,9 @@ ;;; ox-odt.el --- OpenDocument Text Exporter for Org Mode -*- lexical-binding: t; -*- -;; Copyright (C) 2010-2023 Free Software Foundation, Inc. +;; Copyright (C) 2010-2025 Free Software Foundation, Inc. ;; Author: Jambunathan K -;; Keywords: outlines, hypermedia, calendar, wp +;; Keywords: outlines, hypermedia, calendar, text ;; URL: https://orgmode.org ;; This file is part of GNU Emacs. @@ -39,7 +39,7 @@ (declare-function org-back-to-heading "org" (&optional invisible-ok)) (declare-function org-next-visible-heading "org" (arg)) -;;; Define Back-End +;;; Define Backend (org-export-define-backend 'odt '((bold . org-odt-bold) @@ -148,6 +148,10 @@ ;;; Internal Variables +(defvar org-odt--id-attr-prefix "ID-" + "Prefix to use in ID attributes. +This affects IDs that are determined from the ID property.") + (defconst org-odt-lib-dir (file-name-directory (or load-file-name (buffer-file-name))) "Location of ODT exporter. @@ -885,7 +889,7 @@ style from the list." When nil, export timestamps as plain text. -When non-nil, map `org-time-stamp-custom-formats' to a pair of +When non-nil, map `org-timestamp-custom-formats' to a pair of OpenDocument date-styles with names \"OrgDate1\" and \"OrgDate2\" respectively. A timestamp with no time component is formatted with style \"OrgDate1\" while one with explicit hour and minutes @@ -1009,7 +1013,7 @@ See `org-odt--build-date-styles' for implementation details." (setq exit-code (archive-zip-extract archive member)) (buffer-string))) (unless (zerop exit-code) - (message command-output) + (warn command-output) (error "Extraction failed"))))) ;;;; Target @@ -1303,7 +1307,7 @@ original parsed data. INFO is a plist holding export options." ;; today's date. (let* ((date (let ((date (plist-get info :date))) (and (not (cdr date)) - (eq (org-element-type (car date)) 'timestamp) + (org-element-type-p (car date) 'timestamp) (car date))))) (let ((iso-date (org-odt--format-timestamp date nil 'iso-date))) (concat @@ -1365,50 +1369,40 @@ original parsed data. INFO is a plist holding export options." ;; Ensure we have write permissions to this file. (set-file-modes (concat org-odt-zip-dir "styles.xml") #o600) - ;; FIXME: Who is opening an empty styles.xml before this point? - (with-current-buffer - (find-file-noselect (concat org-odt-zip-dir "styles.xml") t) - (revert-buffer t t) + (let ((styles-xml (concat org-odt-zip-dir "styles.xml"))) + (with-temp-buffer + (when (file-exists-p styles-xml) + (insert-file-contents styles-xml)) - ;; Write custom styles for source blocks - ;; Save STYLES used for colorizing of source blocks. - ;; Update styles.xml with styles that were collected as part of - ;; `org-odt-hfy-face-to-css' callbacks. - (let ((styles (mapconcat (lambda (style) (format " %s\n" (cddr style))) - hfy-user-sheet-assoc ""))) - (when styles - (goto-char (point-min)) - (when (re-search-forward "" nil t) - (goto-char (match-beginning 0)) - (insert "\n\n" styles "\n")))) + ;; Write custom styles for source blocks + ;; Save STYLES used for colorizing of source blocks. + ;; Update styles.xml with styles that were collected as part of + ;; `org-odt-hfy-face-to-css' callbacks. + (let ((styles (mapconcat (lambda (style) (format " %s\n" (cddr style))) + hfy-user-sheet-assoc ""))) + (when styles + (goto-char (point-min)) + (when (re-search-forward "" nil t) + (goto-char (match-beginning 0)) + (insert "\n\n" styles "\n")))) - ;; Update styles.xml - take care of outline numbering + ;; Update styles.xml - take care of outline numbering + ;; Outline numbering is retained only up to LEVEL. + ;; To disable outline numbering pass a LEVEL of 0. - ;; Don't make automatic backup of styles.xml file. This setting - ;; prevents the backed-up styles.xml file from being zipped in to - ;; odt file. This is more of a hackish fix. Better alternative - ;; would be to fix the zip command so that the output odt file - ;; includes only the needed files and excludes any auto-generated - ;; extra files like backups and auto-saves etc etc. Note that - ;; currently the zip command zips up the entire temp directory so - ;; that any auto-generated files created under the hood ends up in - ;; the resulting odt file. - (setq-local backup-inhibited t) + (let ((regex + "]*\\)text:level=\"\\([^\"]*\\)\"\\([^>]*\\)>") + (replacement + "")) + (goto-char (point-min)) + (while (re-search-forward regex nil t) + (unless (let ((sec-num (plist-get info :section-numbers)) + (level (string-to-number (match-string 2)))) + (if (wholenump sec-num) (<= level sec-num) sec-num)) + (replace-match replacement t nil)))) - ;; Outline numbering is retained only up to LEVEL. - ;; To disable outline numbering pass a LEVEL of 0. - - (goto-char (point-min)) - (let ((regex - "]*\\)text:level=\"\\([^\"]*\\)\"\\([^>]*\\)>") - (replacement - "")) - (while (re-search-forward regex nil t) - (unless (let ((sec-num (plist-get info :section-numbers)) - (level (string-to-number (match-string 2)))) - (if (wholenump sec-num) (<= level sec-num) sec-num)) - (replace-match replacement t nil)))) - (save-buffer 0))) + ;; Write back the new contents. + (write-region nil nil styles-xml)))) ;; Update content.xml. (let* ( ;; `org-display-custom-times' should be accessed right @@ -1521,7 +1515,7 @@ original parsed data. INFO is a plist holding export options." (let* ((date (plist-get info :date)) ;; Check if DATE is specified as a timestamp. (timestamp (and (not (cdr date)) - (eq (org-element-type (car date)) 'timestamp) + (org-element-type-p (car date) 'timestamp) (car date)))) (when date (concat @@ -1575,8 +1569,9 @@ channel." (let ((timestamp (org-element-property :value clock)) (duration (org-element-property :duration clock))) (format "\n%s" - (if (eq (org-element-type (org-export-get-next-element clock info)) - 'clock) "OrgClock" "OrgClockLastLine") + (if (org-element-type-p + (org-export-get-next-element clock info) 'clock) + "OrgClock" "OrgClockLastLine") (concat (format "%s" "OrgClockKeyword" org-clock-string) @@ -1694,7 +1689,7 @@ CONTENTS is nil. INFO is a plist holding contextual information." (concat ;; Insert separator between two footnotes in a row. (let ((prev (org-export-get-previous-element footnote-reference info))) - (and (eq (org-element-type prev) 'footnote-reference) + (and (org-element-type-p prev 'footnote-reference) (format "%s" "OrgSuperscript" ","))) ;; Transcode footnote reference. @@ -1785,7 +1780,7 @@ holding contextual information." ;; Extra targets. (extra-targets (let ((id (org-element-property :ID headline))) - (if id (org-odt--target "" (concat "ID-" id)) ""))) + (if id (org-odt--target "" (concat org-odt--id-attr-prefix id)) ""))) ;; Title. (anchored-title (org-odt--target full-text id))) (cond @@ -1802,8 +1797,8 @@ holding contextual information." ;; If top-level list, re-start numbering. Otherwise, ;; continue numbering. (format "text:continue-numbering=\"%s\"" - (let* ((parent (org-export-get-parent-headline - headline))) + (let* ((parent (org-element-lineage + headline 'headline))) (if (and parent (org-export-low-level-p parent info)) "true" "false"))))) @@ -1942,7 +1937,7 @@ contextual information." "Transcode an ITEM element from Org to ODT. CONTENTS holds the contents of the item. INFO is a plist holding contextual information." - (let* ((plain-list (org-export-get-parent item)) + (let* ((plain-list (org-element-parent item)) (count (org-element-property :counter item)) (type (org-element-property :type plain-list))) (unless (memq type '(ordered unordered descriptive-1 descriptive-2)) @@ -1950,7 +1945,16 @@ contextual information." (format "\n\n%s\n%s" (if count (format " text:start-value=\"%s\"" count) "") contents - (if (org-element-map item 'table #'identity info 'first-match) + (if (org-element-map item + 'table #'identity info 'first-match + ;; Ignore tables inside sub-lists. + '(plain-list)) + ;; `org-odt-table' will splice forced list ending (all + ;; the way up to the topmost list parent), table, and + ;; forced list re-opening in the middle of the item, + ;; marking text after table with + ;; So, we must match close instead + ;; of the original . "" "")))) @@ -2040,7 +2044,7 @@ CONTENTS is nil. INFO is a plist holding contextual information." (let* ((--numbered-parent-headline-at-<=-n (lambda (element n info) (cl-loop for x in (org-element-lineage element) - thereis (and (eq (org-element-type x) 'headline) + thereis (and (org-element-type-p x 'headline) (<= (org-export-get-relative-level x info) n) (org-export-numbered-headline-p x info) x)))) @@ -2083,10 +2087,10 @@ the generated string. Return value is a string if OP is set to `reference' or a cons cell like CAPTION . SHORT-CAPTION) where CAPTION and SHORT-CAPTION are strings." - (cl-assert (memq (org-element-type element) '(link table src-block paragraph))) + (cl-assert (org-element-type-p element '(link table src-block paragraph))) (let* ((element-or-parent (cl-case (org-element-type element) - (link (org-export-get-parent-element element)) + (link (org-element-parent-element element)) (t element))) ;; Get label and caption. (label (and (or (org-element-property :name element) @@ -2248,12 +2252,10 @@ SHORT-CAPTION are strings." "Return ODT code for an inline image. LINK is the link pointing to the inline image. INFO is a plist used as a communication channel." - (cl-assert (eq (org-element-type element) 'link)) - (let* ((src (let* ((type (org-element-property :type element)) - (raw-path (org-element-property :path element))) - (cond ((member type '("http" "https")) - (concat type ":" raw-path)) - ((file-name-absolute-p raw-path) + (cl-assert (org-element-type-p element 'link)) + (cl-assert (equal "file" (org-element-property :type element))) + (let* ((src (let ((raw-path (org-element-property :path element))) + (cond ((file-name-absolute-p raw-path) (expand-file-name raw-path)) (t raw-path)))) (src-expanded (if (file-name-absolute-p src) src @@ -2264,7 +2266,7 @@ used as a communication channel." (org-odt--copy-image-file src-expanded))) ;; Extract attributes from #+ATTR_ODT line. (attr-from (cl-case (org-element-type element) - (link (org-export-get-parent-element element)) + (link (org-element-parent-element element)) (t element))) ;; Convert attributes to a plist. (attr-plist (org-export-read-attribute :attr_odt attr-from)) @@ -2302,7 +2304,7 @@ used as a communication channel." ;; Check if this link was created by LaTeX-to-PNG converter. (replaces (org-element-property :replaces (if (not standalone-link-p) element - (org-export-get-parent-element element)))) + (org-element-parent-element element)))) ;; If yes, note down the type of the element - LaTeX Fragment ;; or LaTeX environment. It will go in to frame title. (title (and replaces (capitalize @@ -2338,7 +2340,7 @@ used as a communication channel." ;; converter. (replaces (org-element-property :replaces (if (not standalone-link-p) element - (org-export-get-parent-element element)))) + (org-element-parent-element element)))) ;; If yes, note down the type of the element - LaTeX Fragment ;; or LaTeX environment. It will go in to frame title. (title (and replaces (capitalize @@ -2510,7 +2512,7 @@ used as a communication channel." (org-element-property :name p)))) ;; Link should point to an image file. (lambda (l) - (cl-assert (eq (org-element-type l) 'link)) + (cl-assert (org-element-type-p l 'link)) (org-export-inline-image-p l (plist-get info :odt-inline-image-rules))))) (defun org-odt--enumerable-latex-image-p (element info) @@ -2525,7 +2527,7 @@ used as a communication channel." (org-element-property :name p)))) ;; Link should point to an image file. (lambda (l) - (cl-assert (eq (org-element-type l) 'link)) + (cl-assert (org-element-type-p l 'link)) (org-export-inline-image-p l (plist-get info :odt-inline-image-rules))))) (defun org-odt--enumerable-formula-p (element info) @@ -2537,7 +2539,7 @@ used as a communication channel." (org-element-property :name p))) ;; Link should point to a MathML or ODF file. (lambda (l) - (cl-assert (eq (org-element-type l) 'link)) + (cl-assert (org-element-type-p l 'link)) (org-export-inline-image-p l (plist-get info :odt-inline-formula-rules))))) (defun org-odt--standalone-link-p (element _info &optional @@ -2560,9 +2562,9 @@ Return nil, otherwise." (paragraph element) (link (and (or (not link-predicate) (funcall link-predicate element)) - (org-export-get-parent element))) + (org-element-parent element))) (t nil)))) - (when (and p (eq (org-element-type p) 'paragraph)) + (when (and p (org-element-type-p p 'paragraph)) (when (or (not paragraph-predicate) (funcall paragraph-predicate p)) (let ((contents (org-element-contents p))) @@ -2593,20 +2595,19 @@ Return nil, otherwise." ;; FIXME: Handle footnote-definition footnote-reference? (let* ((genealogy (org-element-lineage destination)) (data (reverse genealogy)) - (label (let ((type (org-element-type destination))) - (if (memq type '(headline target)) - (org-export-get-reference destination info) - (error "FIXME: Unable to resolve %S" destination))))) + (label (if (org-element-type-p destination '(headline target)) + (org-export-get-reference destination info) + (error "FIXME: Unable to resolve %S" destination)))) (or (let* ( ;; Locate top-level list. (top-level-list (cl-loop for x on data - when (eq (org-element-type (car x)) 'plain-list) + when (org-element-type-p (car x) 'plain-list) return x)) ;; Get list item nos. (item-numbers (cl-loop for (plain-list item . rest) on top-level-list by #'cddr - until (not (eq (org-element-type plain-list) 'plain-list)) + until (not (org-element-type-p plain-list 'plain-list)) collect (when (eq (org-element-property :type plain-list) 'ordered) @@ -2615,13 +2616,13 @@ Return nil, otherwise." ;; Locate top-most listified headline. (listified-headlines (cl-loop for x on data - when (and (eq (org-element-type (car x)) 'headline) + when (and (org-element-type-p (car x) 'headline) (org-export-low-level-p (car x) info)) return x)) ;; Get listified headline numbers. (listified-headline-nos (cl-loop for el in listified-headlines - when (eq (org-element-type el) 'headline) + when (org-element-type-p el 'headline) collect (when (org-export-numbered-headline-p el info) (1+ (length (org-export-get-previous-element el info t))))))) @@ -2644,7 +2645,7 @@ Return nil, otherwise." ;; Test if destination is a numbered headline. (org-export-numbered-headline-p destination info) (cl-loop for el in (cons destination genealogy) - when (and (eq (org-element-type el) 'headline) + when (and (org-element-type-p el 'headline) (not (org-export-low-level-p el info)) (org-export-numbered-headline-p el info)) return el)))) @@ -2657,7 +2658,7 @@ Return nil, otherwise." ;; Case 4: Locate a regular headline in the hierarchy. Display ;; its title. (let ((headline (cl-loop for el in (cons destination genealogy) - when (and (eq (org-element-type el) 'headline) + when (and (org-element-type-p el 'headline) (not (org-export-low-level-p el info))) return el))) ;; We found one. @@ -2681,8 +2682,6 @@ INFO is a plist holding contextual information. See (imagep (org-export-inline-image-p link (plist-get info :odt-inline-image-rules))) (path (cond - ((member type '("http" "https" "ftp" "mailto")) - (concat type ":" raw-path)) ((string= type "file") (let ((path-uri (org-export-file-uri raw-path))) (if (string-prefix-p "file://" path-uri) @@ -2692,9 +2691,10 @@ INFO is a plist holding contextual information. See ;; archive. The directory containing the odt file ;; is "../". (concat "../" path-uri)))) - (t raw-path))) + (t (concat type ":" raw-path)))) ;; Convert & to & for correct XML representation - (path (replace-regexp-in-string "&" "&" path))) + (path (replace-regexp-in-string "&" "&" path)) + (raw-path (replace-regexp-in-string "&" "&" raw-path))) (cond ;; Link type is handled by a special function. ((org-export-custom-protocol-maybe link desc 'odt info)) @@ -2773,10 +2773,10 @@ INFO is a plist holding contextual information. See ;; Coderef: replace link with the reference name or the ;; equivalent line number. ((string= type "coderef") - (let* ((line-no (format "%d" (org-export-resolve-coderef path info))) - (href (concat "coderef-" path))) + (let* ((line-no (format "%d" (org-export-resolve-coderef raw-path info))) + (href (concat "coderef-" raw-path))) (format - (org-export-get-coderef-format path desc) + (org-export-get-coderef-format raw-path desc) (format "%s" href line-no)))) @@ -2786,7 +2786,7 @@ INFO is a plist holding contextual information. See ;; Check if description is a link to an inline image. (if (and (not (cdr link-contents)) (let ((desc-element (car link-contents))) - (and (eq (org-element-type desc-element) 'link) + (and (org-element-type-p desc-element 'link) (org-export-inline-image-p desc-element (plist-get info :odt-inline-image-rules))))) @@ -2822,13 +2822,12 @@ information." (defun org-odt--paragraph-style (paragraph) "Return style of PARAGRAPH. Style is a symbol among `quoted', `centered' and nil." - (let ((up paragraph)) - (while (and (setq up (org-element-property :parent up)) - (not (memq (org-element-type up) - '(center-block quote-block section))))) - (cl-case (org-element-type up) - (center-block 'centered) - (quote-block 'quoted)))) + (cl-case (org-element-type + (org-element-lineage + paragraph + '(center-block quote-block section))) + (center-block 'center) + (quote-block 'quoted))) (defun org-odt--format-paragraph (paragraph contents info default center quote) "Format paragraph according to given styles. @@ -2845,8 +2844,8 @@ no special environment, a center block, or a quote block." ;; If PARAGRAPH is a leading paragraph in an item that has ;; a checkbox, splice checkbox and paragraph contents ;; together. - (concat (let ((parent (org-element-property :parent paragraph))) - (and (eq (org-element-type parent) 'item) + (concat (let ((parent (org-element-parent paragraph))) + (and (org-element-type-p parent 'item) (not (org-export-get-previous-element paragraph info)) (org-odt--checkbox parent))) contents))) @@ -2878,8 +2877,8 @@ contextual information." ;; If top-level list, re-start numbering. Otherwise, ;; continue numbering. (format "text:continue-numbering=\"%s\"" - (let* ((parent (org-export-get-parent plain-list))) - (if (and parent (eq (org-element-type parent) 'item)) + (let* ((parent (org-element-parent plain-list))) + (if (and parent (org-element-type-p parent 'item)) "true" "false"))) contents)) @@ -3118,7 +3117,7 @@ and prefix with \"OrgSrc\". For example, (defun org-odt-do-format-code (code info &optional lang refs retain-labels num-start) (let* ((lang (or (assoc-default lang org-src-lang-modes) lang)) - (lang-mode (and lang (intern (format "%s-mode" lang)))) + (lang-mode (if lang (intern (format "%s-mode" lang)) #'ignore)) (code-lines (org-split-string code "\n")) (code-length (length code-lines)) (use-htmlfontify-p (and (functionp lang-mode) @@ -3238,7 +3237,8 @@ contextual information." ;;;; Table Cell (defun org-odt-table-style-spec (element info) - (let* ((table (org-export-get-parent-table element)) + "Get table style from `:odt-table-styles' INFO property." + (let* ((table (org-element-lineage element 'table)) (table-attributes (org-export-read-attribute :attr_odt table)) (table-style (plist-get table-attributes :style))) (assoc table-style (plist-get info :odt-table-styles)))) @@ -3254,8 +3254,9 @@ Return a cons of (TABLE-CELL-STYLE-NAME . PARAGRAPH-STYLE-NAME). When STYLE-SPEC is nil, style the table cell the conventional way - choose cell borders based on row and column groupings and -choose paragraph alignment based on `org-col-cookies' text -property. See also `org-odt-table-style-spec'. +choose paragraph alignment based on table alignment cookies (see info +node `(org)Column Width and Alignment'). See also +`org-odt-table-style-spec'. When STYLE-SPEC is non-nil, ignore the above cookie and return styles congruent with the ODF-1.2 specification." @@ -3263,7 +3264,7 @@ styles congruent with the ODF-1.2 specification." (r (car table-cell-address)) (c (cdr table-cell-address)) (style-spec (org-odt-table-style-spec table-cell info)) (table-dimensions (org-export-table-dimensions - (org-export-get-parent-table table-cell) + (org-element-lineage table-cell 'table) info))) (when style-spec ;; LibreOffice - particularly the Writer - honors neither table @@ -3310,7 +3311,7 @@ channel." (r (car table-cell-address)) (c (cdr table-cell-address)) (horiz-span (or (org-export-table-cell-width table-cell info) 0)) - (table-row (org-export-get-parent table-cell)) + (table-row (org-element-parent table-cell)) (custom-style-prefix (org-odt-get-table-cell-styles table-cell info)) (paragraph-style @@ -3321,9 +3322,9 @@ channel." (cond ((and (= 1 (org-export-table-row-group table-row info)) (org-export-table-has-header-p - (org-export-get-parent-table table-row) info)) + (org-element-lineage table-row 'table) info)) "OrgTableHeading") - ((let* ((table (org-export-get-parent-table table-cell)) + ((let* ((table (org-element-lineage table-cell 'table)) (table-attrs (org-export-read-attribute :attr_odt table)) (table-header-columns (let ((cols (plist-get table-attrs :header-columns))) @@ -3381,7 +3382,7 @@ communication channel." (let* ((rowgroup-tags (if (and (= 1 (org-export-table-row-group table-row info)) (org-export-table-has-header-p - (org-export-get-parent-table table-row) info)) + (org-element-lineage table-row 'table) info)) ;; If the row belongs to the first rowgroup and the ;; table has more than one row groups, then this row ;; belongs to the header row group. @@ -3420,7 +3421,7 @@ contextual information." ;; such tables from export. (table.el (prog1 nil - (message + (warn (concat "(ox-odt): Found table.el-type table in the source Org file." " table.el doesn't support export to ODT format." @@ -3475,27 +3476,36 @@ pertaining to indentation here." (let* ((--element-preceded-by-table-p (lambda (element info) (cl-loop for el in (org-export-get-previous-element element info t) - thereis (eq (org-element-type el) 'table)))) + thereis (org-element-type-p el 'table)))) (--walk-list-genealogy-and-collect-tags (lambda (table info) (let* ((genealogy (org-element-lineage table)) + ;; FIXME: This will fail when the table is buried + ;; inside non-list parent greater element, like + ;; special block. The parent block will not be + ;; closed properly. + ;; Example: + ;; 1. List item + ;; - Sub-item + ;; #+begin_textbox + ;; | Table | + ;; #+end_textbox (list-genealogy - (when (eq (org-element-type (car genealogy)) 'item) + (when (org-element-type-p (car genealogy) 'item) (cl-loop for el in genealogy - when (memq (org-element-type el) - '(item plain-list)) + when (org-element-type-p el '(item plain-list)) collect el))) (llh-genealogy (apply #'nconc (cl-loop for el in genealogy - when (and (eq (org-element-type el) 'headline) + when (and (org-element-type-p el 'headline) (org-export-low-level-p el info)) collect (list el (assq 'headline (org-element-contents - (org-export-get-parent el))))))) + (org-element-parent el))))))) parent-list) (nconc ;; Handle list genealogy. @@ -3546,7 +3556,7 @@ pertaining to indentation here." ((let ((section? (org-export-get-previous-element parent-list info))) (and section? - (eq (org-element-type section?) 'section) + (org-element-type-p section? 'section) (assq 'table (org-element-contents section?)))) '("" . "")) (t @@ -3718,7 +3728,8 @@ contextual information." (defun org-odt--translate-latex-fragments (tree _backend info) (let ((processing-type (plist-get info :with-latex)) - (count 0)) + (count 0) + (warning nil)) ;; Normalize processing-type to one of dvipng, mathml or verbatim. ;; If the desired converter is not available, force verbatim ;; processing. @@ -3727,18 +3738,26 @@ contextual information." (if (and (fboundp 'org-format-latex-mathml-available-p) (org-format-latex-mathml-available-p)) (setq processing-type 'mathml) - (message "LaTeX to MathML converter not available.") + (setq warning "`org-odt-with-latex': LaTeX to MathML converter not available. Falling back to verbatim.") (setq processing-type 'verbatim))) ((dvipng imagemagick) (unless (and (org-check-external-command "latex" "" t) (org-check-external-command (if (eq processing-type 'dvipng) "dvipng" "convert") "" t)) - (message "LaTeX to PNG converter not available.") + (setq warning "`org-odt-with-latex': LaTeX to PNG converter not available. Falling back to verbatim.") (setq processing-type 'verbatim))) + (verbatim) ;; nothing to do (otherwise - (message "Unknown LaTeX option. Forcing verbatim.") + (setq warning "`org-odt-with-latex': Unknown LaTeX option. Forcing verbatim.") (setq processing-type 'verbatim))) + ;; Display warning if the selected PROCESSING-TYPE is not + ;; available, but there are fragments to be converted. + (when warning + (org-element-map tree '(latex-fragment latex-environment) + (lambda (_) (warn warning)) + info 'first-match nil t)) + ;; Store normalized value for later use. (when (plist-get info :with-latex) (plist-put info :with-latex processing-type)) @@ -3769,6 +3788,7 @@ contextual information." (link (with-temp-buffer (insert latex-frag) + (delay-mode-hooks (let ((org-inhibit-startup t)) (org-mode))) ;; When converting to a PNG image, make sure to ;; copy all LaTeX header specifications from the ;; Org source. @@ -3784,7 +3804,7 @@ contextual information." (goto-char (point-min)) (skip-chars-forward " \t\n") (org-element-link-parser)))) - (if (not (eq 'link (org-element-type link))) + (if (not (org-element-type-p link 'link)) (message "LaTeX Conversion failed.") ;; Conversion succeeded. Parse above Org-style link to ;; a `link' object. @@ -3796,7 +3816,7 @@ contextual information." ;; attributes, captions to the enclosing ;; paragraph. (latex-environment - (org-element-adopt-elements + (org-element-adopt (list 'paragraph (list :style "OrgFormula" :name @@ -3815,7 +3835,7 @@ contextual information." replacement :post-blank (org-element-property :post-blank latex-*)) ;; Replace now. - (org-element-set-element latex-* replacement))))) + (org-element-set latex-* replacement))))) info nil nil t))) tree) @@ -3859,20 +3879,20 @@ contextual information." (org-element-map tree 'plain-list (lambda (el) (when (eq (org-element-property :type el) 'descriptive) - (org-element-set-element + (org-element-set el - (apply 'org-element-adopt-elements + (apply 'org-element-adopt (list 'plain-list (list :type 'descriptive-1)) (mapcar (lambda (item) - (org-element-adopt-elements + (org-element-adopt (list 'item (list :checkbox (org-element-property :checkbox item))) (list 'paragraph (list :style "Text_20_body_20_bold") (or (org-element-property :tag item) "(no term)")) - (org-element-adopt-elements + (org-element-adopt (list 'plain-list (list :type 'descriptive-2)) - (apply 'org-element-adopt-elements + (apply 'org-element-adopt (list 'item nil) (org-element-contents item))))) (org-element-contents el))))) @@ -3926,10 +3946,10 @@ contextual information." (lambda (l1-list) (when (org-export-read-attribute :attr_odt l1-list :list-table) ;; Replace list with table. - (org-element-set-element + (org-element-set l1-list ;; Build replacement table. - (apply 'org-element-adopt-elements + (apply 'org-element-adopt (list 'table '(:type org :attr_odt (":style \"GriddedTable\""))) (org-element-map l1-list 'item (lambda (l1-item) @@ -3938,8 +3958,8 @@ contextual information." ;; Remove Level-2 list from the Level-item. It ;; will be subsequently attached as table-cells. (let ((cur l1-item-contents) prev) - (while (and cur (not (eq (org-element-type (car cur)) - 'plain-list))) + (while (and cur (not (org-element-type-p + (car cur) 'plain-list))) (setq prev cur) (setq cur (cdr cur))) (when prev @@ -3947,18 +3967,18 @@ contextual information." (setq l2-list (car cur))) (setq l1-item-leading-text l1-item-contents)) ;; Level-1 items start a table row. - (apply 'org-element-adopt-elements + (apply 'org-element-adopt (list 'table-row (list :type 'standard)) ;; Leading text of level-1 item define ;; the first table-cell. - (apply 'org-element-adopt-elements + (apply 'org-element-adopt (list 'table-cell nil) l1-item-leading-text) ;; Level-2 items define subsequent ;; table-cells of the row. (org-element-map l2-list 'item (lambda (l2-item) - (apply 'org-element-adopt-elements + (apply 'org-element-adopt (list 'table-cell nil) (org-element-contents l2-item))) info nil 'item)))) @@ -4014,7 +4034,7 @@ contextual information." ;; Delete temporary directory and also other embedded ;; files that get copied there. (delete-directory org-odt-zip-dir t)))) - (condition-case err + (condition-case-unless-debug err (progn (unless (executable-find "zip") ;; Not at all OSes ship with zip by default @@ -4079,9 +4099,6 @@ contextual information." (message "Created %s" (expand-file-name target)) ;; Cleanup work directory and work files. (funcall --cleanup-xml-buffers) - ;; Open the OpenDocument file in archive-mode for - ;; examination. - (find-file-noselect target t) ;; Return exported file. (cond ;; Case 1: Conversion desired on exported file. Run the @@ -4096,8 +4113,8 @@ contextual information." (error ;; Cleanup work directory and work files. (funcall --cleanup-xml-buffers) - (message "OpenDocument export failed: %s" - (error-message-string err)))))) + (error "OpenDocument export failed: %s" + (error-message-string err)))))) ;;;; Export to OpenDocument formula @@ -4322,15 +4339,15 @@ The list of the form (OUTPUT-FMT-1 OUTPUT-FMT-2 ...)." (defun org-odt-convert-read-params () "Return IN-FILE and OUT-FMT params for `org-odt-do-convert'. This is a helper routine for interactive use." - (let* ((input (if (featurep 'ido) 'ido-completing-read 'completing-read)) - (in-file (read-file-name "File to be converted: " + (let* ((in-file (read-file-name "File to be converted: " nil buffer-file-name t)) (in-fmt (file-name-extension in-file)) (out-fmt-choices (org-odt-reachable-formats in-fmt)) (out-fmt (or (and out-fmt-choices - (funcall input "Output format: " - out-fmt-choices nil nil nil)) + (completing-read + "Output format: " + out-fmt-choices nil nil nil)) (error "No known converter or no known output formats for %s files" in-fmt)))) @@ -4350,11 +4367,6 @@ is non-nil then the newly converted file is opened using ;;; Library Initializations -(dolist (desc org-odt-file-extensions) - ;; Let Emacs open all OpenDocument files in archive mode. - (add-to-list 'auto-mode-alist - (cons (concat "\\." (car desc) "\\'") 'archive-mode))) - (provide 'ox-odt) ;; Local variables: diff --git a/lisp/org/ox-org.el b/lisp/org/ox-org.el index ed72cf4f..2394a197 100644 --- a/lisp/org/ox-org.el +++ b/lisp/org/ox-org.el @@ -1,10 +1,9 @@ -;;; ox-org.el --- Org Back-End for Org Export Engine -*- lexical-binding: t; -*- +;;; ox-org.el --- Org Backend for Org Export Engine -*- lexical-binding: t; -*- -;; Copyright (C) 2013-2023 Free Software Foundation, Inc. +;; Copyright (C) 2013-2025 Free Software Foundation, Inc. ;; Author: Nicolas Goaziou -;; Maintainer: Nicolas Goaziou -;; Keywords: org, wp +;; Keywords: org, text ;; This file is part of GNU Emacs. @@ -54,6 +53,20 @@ setting of `org-html-htmlize-output-type' is `css'." (const :tag "Don't include external stylesheet link" nil) (string :tag "URL or local href"))) +(defcustom org-org-with-special-rows t + "Non-nil means export special table rows. +Special rows are the rows containing special marking characters, as +described in the Info node `(org)Advanced features'." + :group 'org-export-org + :type 'boolean + :package-version '(Org . "9.7")) + +(defcustom org-org-with-cite-processors nil + "Non-nil means use citation processors when exporting citations." + :group 'org-export-org + :type 'boolean + :package-version '(Org . "9.7")) + (org-export-define-backend 'org '((babel-call . org-org-identity) (bold . org-org-identity) @@ -75,6 +88,8 @@ setting of `org-html-htmlize-output-type' is `css'." (inline-src-block . org-org-identity) (inlinetask . org-org-identity) (italic . org-org-identity) + (citation . org-org-identity) + (citation-reference . org-org-identity) (item . org-org-identity) (keyword . org-org-keyword) (latex-environment . org-org-identity) @@ -112,7 +127,11 @@ setting of `org-html-htmlize-output-type' is `css'." (lambda (a s v b) (if a (org-org-export-to-org t s v b) (org-open-file (org-org-export-to-org nil s v b))))))) - :filters-alist '((:filter-parse-tree . org-org--add-missing-sections))) + :filters-alist '((:filter-parse-tree . org-org--add-missing-sections)) + :options-alist + ;; Export special table rows. + '((:with-special-rows nil nil org-org-with-special-rows) + (:with-cite-processors nil nil org-org-with-cite-processors))) (defun org-org--add-missing-sections (tree _backend _info) "Ensure each headline has an associated section. @@ -129,7 +148,7 @@ we make sure it is always called." (new-section (org-element-create 'section))) (pcase (org-element-type first-child) (`section nil) - (`nil (org-element-adopt-elements h new-section)) + (`nil (org-element-adopt h new-section)) (_ (org-element-insert-before new-section first-child)))))) tree) @@ -226,7 +245,7 @@ a communication channel." ;; them are included in the result. (let ((footnotes (org-element-map - (list (org-export-get-parent-headline section) section) + (list (or (org-element-lineage section 'headline) "") section) 'footnote-reference (lambda (fn) (and (eq (org-element-property :type fn) 'standard) @@ -320,17 +339,14 @@ publishing directory. Return output file name." (org-publish-org-to 'org filename ".org" plist pub-dir) (when (plist-get plist :htmlized-source) - (or (require 'htmlize nil t) - (error "Please install htmlize from https://github.com/hniksic/emacs-htmlize")) + (org-require-package 'htmlize) (require 'ox-html) (let* ((org-inhibit-startup t) (htmlize-output-type 'css) (html-ext (concat "." (or (plist-get plist :html-extension) org-html-extension "html"))) - (visitingp (find-buffer-visiting filename)) - (work-buffer (or visitingp (find-file-noselect filename))) newbuf) - (with-current-buffer work-buffer + (org-with-file-buffer filename (font-lock-ensure) (org-fold-show-all) (setq newbuf (htmlize-buffer))) @@ -338,17 +354,14 @@ Return output file name." (when org-org-htmlized-css-url (goto-char (point-min)) (and (re-search-forward - ".*" nil t) + ".*" nil t) (replace-match (format "" org-org-htmlized-css-url) t t))) (write-file (concat pub-dir (file-name-nondirectory filename) html-ext))) - (kill-buffer newbuf) - (unless visitingp (kill-buffer work-buffer))) - ;; FIXME: Why? Which buffer is this supposed to apply to? - (set-buffer-modified-p nil))) + (kill-buffer newbuf)))) (provide 'ox-org) diff --git a/lisp/org/ox-publish.el b/lisp/org/ox-publish.el index cff34f05..51cb7433 100644 --- a/lisp/org/ox-publish.el +++ b/lisp/org/ox-publish.el @@ -1,9 +1,8 @@ ;;; ox-publish.el --- Publish Related Org Mode Files as a Website -*- lexical-binding: t; -*- -;; Copyright (C) 2006-2023 Free Software Foundation, Inc. +;; Copyright (C) 2006-2025 Free Software Foundation, Inc. ;; Author: David O'Toole -;; Maintainer: Nicolas Goaziou -;; Keywords: hypermedia, outlines, wp +;; Keywords: hypermedia, outlines, text ;; This file is part of GNU Emacs. ;; @@ -27,7 +26,7 @@ ;; ;; ox-publish.el can do the following: ;; -;; + Publish all one's Org files to a given export back-end +;; + Publish all one's Org files to a given export backend ;; + Upload HTML, images, attachments and other files to a web server ;; + Exclude selected private pages from publishing ;; + Publish a clickable sitemap of pages @@ -57,6 +56,9 @@ "This will cache timestamps and titles for files in publishing projects. Blocks could hash sha1 values here.") +(defvar org-publish-transient-cache nil + "This will cache information during publishing process.") + (defvar org-publish-after-publishing-hook nil "Hook run each time a file is published. Every function in this hook will be called with two arguments: @@ -86,7 +88,7 @@ cdr of each element is in one of the following forms: (:components (\"project-1\" \"project-2\" ...)) -When the CDR of an element of org-publish-project-alist is in +When the CDR of an element of `org-publish-project-alist' is in this second form, the elements of the list after `:components' are taken to be components of the project, which group together files requiring different publishing options. When you publish @@ -129,14 +131,14 @@ considered relative to the base directory. When both `:include' and `:exclude' properties are given values, the exclusion step happens first. -One special property controls which back-end function to use for +One special property controls which backend function to use for publishing files in the project. This can be used to extend the set of file types publishable by `org-publish', as well as the set of output formats. `:publishing-function' - Function to publish file. Each back-end may define its + Function to publish file. Each backend may define its own (i.e. `org-latex-publish-to-pdf', `org-html-publish-to-html'). May be a list of functions, in which case each function in the list is invoked in turn. @@ -162,10 +164,10 @@ date. Some properties control details of the Org publishing process, and are equivalent to the corresponding user variables listed in -the right column. Back-end specific properties may also be -included. See the back-end documentation for more information. +the right column. Backend specific properties may also be +included. See the backend documentation for more information. - :author `user-full-name' + :author variable `user-full-name' :creator `org-export-creator-string' :email `user-mail-address' :exclude-tags `org-export-exclude-tags' @@ -174,7 +176,7 @@ included. See the back-end documentation for more information. :preserve-breaks `org-export-preserve-breaks' :section-numbers `org-export-with-section-numbers' :select-tags `org-export-select-tags' - :time-stamp-file `org-export-time-stamp-file' + :time-stamp-file `org-export-timestamp-file' :with-archived-trees `org-export-with-archived-trees' :with-author `org-export-with-author' :with-creator `org-export-with-creator' @@ -358,7 +360,9 @@ You can overwrite this default per project in your ;;; Timestamp-related functions (defun org-publish-timestamp-filename (filename &optional pub-dir pub-func) - "Return path to timestamp file for filename FILENAME." + "Return path to timestamp file for filename FILENAME. +The timestamp file name is constructed using FILENAME, publishing +directory PUB-DIR, and PUB-FUNC publishing function." (setq filename (concat filename "::" (or pub-dir "") "::" (format "%s" (or pub-func "")))) (concat "X" (if (fboundp 'sha1) (sha1 filename) (md5 filename)))) @@ -547,12 +551,12 @@ publishing FILENAME." -;;; Tools for publishing functions in back-ends +;;; Tools for publishing functions in backends (defun org-publish-org-to (backend filename extension plist &optional pub-dir) - "Publish an Org file to a specified back-end. + "Publish an Org file to a specified backend. -BACKEND is a symbol representing the back-end used for +BACKEND is a symbol representing the backend used for transcoding. FILENAME is the filename of the Org file to be published. EXTENSION is the extension used for the output string, with the leading dot. PLIST is the property list for the @@ -564,30 +568,25 @@ directory. Return output file name." (unless (or (not pub-dir) (file-exists-p pub-dir)) (make-directory pub-dir t)) ;; Check if a buffer visiting FILENAME is already open. - (let* ((org-inhibit-startup t) - (visiting (find-buffer-visiting filename)) - (work-buffer (or visiting (find-file-noselect filename)))) - (unwind-protect - (with-current-buffer work-buffer - (let ((output (org-export-output-file-name extension nil pub-dir))) - (org-export-to-file backend output - nil nil nil (plist-get plist :body-only) - ;; Add `org-publish--store-crossrefs' and - ;; `org-publish-collect-index' to final output filters. - ;; The latter isn't dependent on `:makeindex', since we - ;; want to keep it up-to-date in cache anyway. - (org-combine-plists - plist - `(:crossrefs - ,(org-publish-cache-get-file-property - ;; Normalize file names in cache. - (file-truename filename) :crossrefs nil t) - :filter-final-output - (org-publish--store-crossrefs - org-publish-collect-index - ,@(plist-get plist :filter-final-output))))))) - ;; Remove opened buffer in the process. - (unless visiting (kill-buffer work-buffer))))) + (let* ((org-inhibit-startup t)) + (org-with-file-buffer filename + (let ((output (org-export-output-file-name extension nil pub-dir))) + (org-export-to-file backend output + nil nil nil (plist-get plist :body-only) + ;; Add `org-publish--store-crossrefs' and + ;; `org-publish-collect-index' to final output filters. + ;; The latter isn't dependent on `:makeindex', since we + ;; want to keep it up-to-date in cache anyway. + (org-combine-plists + plist + `(:crossrefs + ,(org-publish-cache-get-file-property + ;; Normalize file names in cache. + (file-truename filename) :crossrefs nil t) + :filter-final-output + (org-publish--store-crossrefs + org-publish-collect-index + ,@(plist-get plist :filter-final-output))))))))) (defun org-publish-attachment (_plist filename pub-dir) "Publish a file with no transformation of any kind. @@ -795,17 +794,14 @@ Default for SITEMAP-FILENAME is `sitemap.org'." (concat (file-name-directory b) (org-publish-find-title b project)) b))) - (setq retval - (if ignore-case - (not (string-lessp (upcase B) (upcase A))) - (not (string-lessp B A)))))) + (setq retval (org-string<= A B nil ignore-case)))) ((or `anti-chronologically `chronologically) (let* ((adate (org-publish-find-date a project)) (bdate (org-publish-find-date b project))) (setq retval (not (if (eq sort-files 'chronologically) - (time-less-p bdate adate) - (time-less-p adate bdate)))))) + (time-less-p bdate adate) + (time-less-p adate bdate)))))) (`nil nil) (_ (user-error "Invalid sort value %s" sort-files))) ;; Directory-wise wins: @@ -830,7 +826,7 @@ Default for SITEMAP-FILENAME is `sitemap.org'." (mapcar #'file-name-directory files))) files))) ;; Eventually sort all entries. - (when (or sort-files (not (memq sort-folders 'ignore))) + (when (or sort-files (not (eq sort-folders 'ignore))) (setq files (sort files sort-predicate))) (funcall sitemap-builder title @@ -841,9 +837,9 @@ Default for SITEMAP-FILENAME is `sitemap.org'." "Find the PROPERTY of FILE in project. PROPERTY is a keyword referring to an export option, as defined -in `org-export-options-alist' or in export back-ends. In the +in `org-export-options-alist' or in export backends. In the latter case, optional argument BACKEND has to be set to the -back-end where the option is defined, e.g., +backend where the option is defined, e.g., (org-publish-find-property file :subtitle \\='latex) @@ -851,17 +847,13 @@ Return value may be a string or a list, depending on the type of PROPERTY, i.e. \"behavior\" parameter from `org-export-options-alist'." (let ((file (org-publish--expand-file-name file project))) (when (and (file-readable-p file) (not (directory-name-p file))) - (let* ((org-inhibit-startup t) - (visiting (find-buffer-visiting file)) - (buffer (or visiting (find-file-noselect file)))) - (unwind-protect - (plist-get (with-current-buffer buffer - (if (not visiting) (org-export-get-environment backend) - ;; Protect local variables in open buffers. - (org-export-with-buffer-copy - (org-export-get-environment backend)))) - property) - (unless visiting (kill-buffer buffer))))))) + (let* ((org-inhibit-startup t)) + (plist-get (org-with-file-buffer file + (if (not org-file-buffer-created) (org-export-get-environment backend) + ;; Protect local variables in open buffers. + (org-export-with-buffer-copy + (org-export-get-environment backend)))) + property))))) (defun org-publish-find-title (file project) "Find the title of FILE in PROJECT." @@ -875,7 +867,7 @@ PROPERTY, i.e. \"behavior\" parameter from `org-export-options-alist'." (org-no-properties (org-element-interpret-data parsed-title)) (file-name-nondirectory (file-name-sans-extension file))))) - (org-publish-cache-set-file-property file :title title))))) + (org-publish-cache-set-file-property file :title title nil 'transient))))) (defun org-publish-find-date (file project) "Find the date of FILE in PROJECT. @@ -891,7 +883,7 @@ time in `current-time' format." (file-attribute-modification-time (file-attributes file)) (let ((date (org-publish-find-property file :date project))) ;; DATE is a secondary string. If it contains - ;; a time-stamp, convert it to internal format. + ;; a timestamp, convert it to internal format. ;; Otherwise, use FILE modification time. (cond ((let ((ts (and (consp date) (assq 'timestamp date)))) (and ts @@ -900,7 +892,8 @@ time in `current-time' format." (org-time-string-to-time value)))))) ((file-exists-p file) (file-attribute-modification-time (file-attributes file))) - (t (error "No such file: \"%s\"" file))))))))) + (t (error "No such file: \"%s\"" file))))) + nil 'transient)))) (defun org-publish-sitemap-default-entry (entry style project) "Default format for site map ENTRY, as a string. @@ -1024,7 +1017,7 @@ the project." "Update index for a file in cache. OUTPUT is the output from transcoding current file. BACKEND is -the back-end that was used for transcoding. INFO is a plist +the backend that was used for transcoding. INFO is a plist containing publishing and export options. The index relative to current file is stored as an alist. An @@ -1042,7 +1035,7 @@ its CDR is a string." (org-element-map (plist-get info :parse-tree) 'keyword (lambda (k) (when (equal (org-element-property :key k) "INDEX") - (let ((parent (org-export-get-parent-headline k))) + (let ((parent (org-element-lineage k 'headline))) (list (org-element-property :value k) file (cond @@ -1056,7 +1049,8 @@ its CDR is a string." (replace-regexp-in-string "\\[[0-9]+%\\]\\|\\[[0-9]+/[0-9]+\\]" "" (org-element-property :raw-value parent))))))))) - info)))) + info)) + nil 'transient)) ;; Return output unchanged. output) @@ -1138,7 +1132,7 @@ publishing directory." "Store cross-references for current published file. OUTPUT is the produced output, as a string. BACKEND is the export -back-end used, as a symbol. INFO is the final export state, as +backend used, as a symbol. INFO is the final export state, as a plist. This function is meant to be used as a final output filter. See @@ -1170,7 +1164,7 @@ option, e.g., When PREFER-CUSTOM is non-nil, and SEARCH targets a headline in FILE, return its custom ID, if any. -It only makes sense to use this if export back-end builds +It only makes sense to use this if export backend builds references with `org-export-get-reference'." (cond ((and prefer-custom @@ -1259,6 +1253,9 @@ If FREE-CACHE, empty the cache." (error "Org publish timestamp: %s is not a directory" org-publish-timestamp-directory)) + (unless org-publish-transient-cache + (setq org-publish-transient-cache (make-hash-table :test #'equal))) + (unless (and org-publish-cache (string= (org-publish-cache-get ":project:") project-name)) (let* ((cache-file @@ -1282,6 +1279,8 @@ If FREE-CACHE, empty the cache." (message "%s" "Resetting org-publish-cache") (when (hash-table-p org-publish-cache) (clrhash org-publish-cache)) + (when (hash-table-p org-publish-transient-cache) + (clrhash org-publish-transient-cache)) (setq org-publish-cache nil)) (defun org-publish-cache-file-needs-publishing @@ -1306,7 +1305,7 @@ the file including them will be republished as well." (goto-char (point-min)) (while (re-search-forward "^[ \t]*#\\+INCLUDE:" nil t) (let ((element (org-element-at-point))) - (when (eq 'keyword (org-element-type element)) + (when (org-element-type-p element 'keyword) (let* ((value (org-element-property :value element)) (include-filename (and (string-match "\\`\\(\".+?\"\\|\\S-+\\)" value) @@ -1327,16 +1326,22 @@ the file including them will be republished as well." included-files-mtime)))))) (defun org-publish-cache-set-file-property - (filename property value &optional project-name) + (filename property value &optional project-name transient) "Set the VALUE for a PROPERTY of file FILENAME in publishing cache to VALUE. Use cache file of PROJECT-NAME. If the entry does not exist, it -will be created. Return VALUE." +will be created. Return VALUE. + +When TRANSIENT is non-nil, store value in transient cache that is only +maintained during the current publish process." ;; Evtl. load the requested cache file: (when project-name (org-publish-initialize-cache project-name)) - (let ((pl (org-publish-cache-get filename))) - (if pl (progn (plist-put pl property value) value) - (org-publish-cache-get-file-property - filename property value nil project-name)))) + (if transient + (puthash (cons filename property) value + org-publish-transient-cache) + (let ((pl (org-publish-cache-get filename))) + (if pl (progn (plist-put pl property value) value) + (org-publish-cache-get-file-property + filename property value nil project-name))))) (defun org-publish-cache-get-file-property (filename property &optional default no-create project-name) @@ -1345,13 +1350,14 @@ Use cache file of PROJECT-NAME. Return the value of that PROPERTY, or DEFAULT, if the value does not yet exist. Create the entry, if necessary, unless NO-CREATE is non-nil." (when project-name (org-publish-initialize-cache project-name)) - (let ((properties (org-publish-cache-get filename))) - (cond ((null properties) - (unless no-create - (org-publish-cache-set filename (list property default))) - default) - ((plist-member properties property) (plist-get properties property)) - (t default)))) + (or (gethash (cons filename property) org-publish-transient-cache) + (let ((properties (org-publish-cache-get filename))) + (cond ((null properties) + (unless no-create + (org-publish-cache-set filename (list property default))) + default) + ((plist-member properties property) (plist-get properties property)) + (t default))))) (defun org-publish-cache-get (key) "Return the value stored in `org-publish-cache' for key KEY. diff --git a/lisp/org/ox-texinfo.el b/lisp/org/ox-texinfo.el index 5befcac1..139a49d9 100644 --- a/lisp/org/ox-texinfo.el +++ b/lisp/org/ox-texinfo.el @@ -1,9 +1,8 @@ -;;; ox-texinfo.el --- Texinfo Back-End for Org Export Engine -*- lexical-binding: t; -*- +;;; ox-texinfo.el --- Texinfo Backend for Org Export Engine -*- lexical-binding: t; -*- -;; Copyright (C) 2012-2023 Free Software Foundation, Inc. +;; Copyright (C) 2012-2025 Free Software Foundation, Inc. ;; Author: Jonathan Leech-Pepin -;; Maintainer: Nicolas Goaziou -;; Keywords: outlines, hypermedia, calendar, wp +;; Keywords: outlines, hypermedia, calendar, text ;; This file is part of GNU Emacs. @@ -31,6 +30,7 @@ (require 'cl-lib) (require 'ox) +(require 'org-element-ast) (eval-when-compile (require 'subr-x)) @@ -38,7 +38,7 @@ (defvar org-texinfo-supports-math--cache) -;;; Define Back-End +;;; Define Backend (org-export-define-backend 'texinfo '((bold . org-texinfo-bold) @@ -110,7 +110,8 @@ (:subtitle "SUBTITLE" nil nil parse) (:subauthor "SUBAUTHOR" nil nil newline) (:texinfo-dircat "TEXINFO_DIR_CATEGORY" nil nil t) - (:texinfo-dirtitle "TEXINFO_DIR_TITLE" nil nil t) + (:texinfo-dirtitle "TEXINFO_DIR_TITLE" nil nil t) ;Obsolete. + (:texinfo-dirname "TEXINFO_DIR_NAME" nil nil t) (:texinfo-dirdesc "TEXINFO_DIR_DESC" nil nil t) (:texinfo-printed-title "TEXINFO_PRINTED_TITLE" nil nil t) ;; Other variables. @@ -147,12 +148,10 @@ "Default document encoding for Texinfo output. If nil it will default to `buffer-file-coding-system'." - :group 'org-export-texinfo :type 'coding-system) (defcustom org-texinfo-default-class "info" "The default Texinfo class." - :group 'org-export-texinfo :type '(string :tag "Texinfo class")) (defcustom org-texinfo-classes @@ -205,7 +204,6 @@ The sectioning structure of the class is given by the elements following the header string. For each sectioning level, a number of strings is specified. A %s formatter is mandatory in each section string and will be replaced by the title of the section." - :group 'org-export-texinfo :version "27.1" :package-version '(Org . "9.2") :type '(repeat @@ -233,7 +231,6 @@ TEXT the main headline text (string). TAGS the tags as a list of strings (list of strings or nil). The function result will be used in the section format string." - :group 'org-export-texinfo :type 'function :version "26.1" :package-version '(Org . "8.3")) @@ -244,38 +241,32 @@ The function result will be used in the section format string." "Column at which to start the description in the node listings. If a node title is greater than this length, the description will be placed after the end of the title." - :group 'org-export-texinfo :type 'integer) ;;;; Timestamps (defcustom org-texinfo-active-timestamp-format "@emph{%s}" "A printf format string to be applied to active timestamps." - :group 'org-export-texinfo :type 'string) (defcustom org-texinfo-inactive-timestamp-format "@emph{%s}" "A printf format string to be applied to inactive timestamps." - :group 'org-export-texinfo :type 'string) (defcustom org-texinfo-diary-timestamp-format "@emph{%s}" "A printf format string to be applied to diary timestamps." - :group 'org-export-texinfo :type 'string) ;;;; Links (defcustom org-texinfo-link-with-unknown-path-format "@indicateurl{%s}" "Format string for links with unknown path type." - :group 'org-export-texinfo :type 'string) ;;;; Tables (defcustom org-texinfo-tables-verbatim nil "When non-nil, tables are exported verbatim." - :group 'org-export-texinfo :type 'boolean) (defcustom org-texinfo-table-scientific-notation nil @@ -285,7 +276,6 @@ The format should have \"%s\" twice, for mantissa and exponent \(i.e. \"%s\\\\times10^{%s}\"). When nil, no transformation is made." - :group 'org-export-texinfo :type '(choice (string :tag "Format string") (const :tag "No formatting" nil))) @@ -297,7 +287,6 @@ This should an indicating command, e.g., \"@code\", \"@kbd\" or \"@samp\". It can be overridden locally using the \":indic\" attribute." - :group 'org-export-texinfo :type 'string :version "26.1" :package-version '(Org . "9.1") @@ -323,7 +312,6 @@ to typeset and protects special characters. When no association is found for a given markup, text is returned as-is." - :group 'org-export-texinfo :version "26.1" :package-version '(Org . "9.1") :type 'alist @@ -341,7 +329,6 @@ The function must accept two parameters: The function should return the string to be exported. The default function simply returns the value of CONTENTS." - :group 'org-export-texinfo :version "24.4" :package-version '(Org . "8.2") :type 'function) @@ -361,7 +348,6 @@ The function must accept six parameters: CONTENTS the contents of the inlinetask, as a string. The function should return the string to be exported." - :group 'org-export-texinfo :type 'function) ;;;; LaTeX @@ -374,7 +360,6 @@ fragments as Texinfo \"@displaymath\" and \"@math\" commands respectively. Alternatively, when set to `detect', the exporter does so only if the installed version of Texinfo supports the necessary commands." - :group 'org-export-texinfo :package-version '(Org . "9.6") :type '(choice (const :tag "Detect" detect) @@ -391,7 +376,6 @@ body but is followed by another item, then the second item is transcoded to `@itemx'. See info node `(org)Plain lists in Texinfo export' for how to enable this for individual lists." :package-version '(Org . "9.6") - :group 'org-export-texinfo :type 'boolean :safe t) @@ -406,7 +390,6 @@ relative file name, %F by the absolute file name, %b by the file base name (i.e. without directory and extension parts), %o by the base directory of the file and %O by the absolute file name of the output file." - :group 'org-export-texinfo :version "26.1" :package-version '(Org . "9.1") :type '(repeat :tag "Shell command sequence" @@ -417,7 +400,6 @@ the output file." "The list of file extensions to consider as Texinfo logfiles. The logfiles will be remove if `org-texinfo-remove-logfiles' is non-nil." - :group 'org-export-texinfo :type '(repeat (string :tag "Extension"))) (defcustom org-texinfo-remove-logfiles t @@ -486,7 +468,7 @@ If two strings share the same prefix (e.g. \"ISO-8859-1\" and (defun org-texinfo--normalize-headlines (tree _backend info) "Normalize headlines in TREE. -BACK-END is the symbol specifying back-end used for export. +BACKEND is the symbol specifying backend used for export. INFO is a plist used as a communication channel. Make sure every headline in TREE contains a section, since those @@ -501,10 +483,10 @@ Return new tree." (when contents (let ((first (org-element-map contents '(headline section) #'identity info t))) - (unless (eq (org-element-type first) 'section) - (apply #'org-element-set-contents - hl - (cons `(section (:parent ,hl)) contents))))))) + (unless (org-element-type-p first 'section) + (apply #'org-element-set-contents + hl + (org-element-create 'section `(:parent ,hl)) contents)))))) info) tree) @@ -559,7 +541,7 @@ node or anchor name is unique." ;; Consequently, we ensure that every parent headline gets ;; its node beforehand. As a recursive operation, this ;; achieves the desired effect. - (let ((parent (org-element-lineage datum '(headline)))) + (let ((parent (org-element-lineage datum 'headline))) (when (and parent (not (assq parent cache))) (org-texinfo--get-node parent info) (setq cache (plist-get info :texinfo-node-cache)))) @@ -657,7 +639,7 @@ Return new tree." (org-texinfo--massage-key-item plain-list item args info)) (push item items))))) (unless (org-element-contents plain-list) - (org-element-extract-element plain-list))))) + (org-element-extract plain-list))))) info) tree) @@ -687,9 +669,9 @@ specified by CMD and ARGS." (list :type cmd :attr_texinfo (list (format ":options %s" args)) :post-blank (if contents 1 0)) - (mapc #'org-element-extract-element contents)) + (mapc #'org-element-extract contents)) plain-list)) - (org-element-extract-element item)) + (org-element-extract item)) (defun org-texinfo--split-plain-list (plain-list items) "Insert a new plain list before the plain list PLAIN-LIST. @@ -700,7 +682,7 @@ new plain list." (list :type 'descriptive :attr_texinfo (org-element-property :attr_texinfo plain-list) :post-blank 1) - (mapc #'org-element-extract-element items)) + (mapc #'org-element-extract items)) plain-list)) (defun org-texinfo--massage-key-item (plain-list item args info) @@ -747,7 +729,7 @@ INFO is a plist used as a communication channel." (org-not-nil (org-export-read-attribute :attr_texinfo plain-list :compact))) (not (org-element-contents item)) - (eq 1 (org-element-property :post-blank item))) + (eq 1 (org-element-post-blank item))) (org-element-put-property next-item :findex findex) (org-element-put-property next-item :kindex kindex) (org-element-put-property item :findex nil) @@ -815,25 +797,49 @@ holding export options." (format "@copying\n%s@end copying\n\n" (org-element-normalize-string (org-export-data copying info)))) - ;; Info directory information. Only supply if both title and - ;; category are provided. - (let ((dircat (plist-get info :texinfo-dircat)) - (dirtitle - (let ((title (plist-get info :texinfo-dirtitle))) - (and title - (string-match "^\\(?:\\* \\)?\\(.*?\\)\\(\\.\\)?$" title) - (format "* %s." (match-string 1 title)))))) - (when (and dircat dirtitle) - (concat "@dircategory " dircat "\n" - "@direntry\n" - (let ((dirdesc - (let ((desc (plist-get info :texinfo-dirdesc))) - (cond ((not desc) nil) - ((string-suffix-p "." desc) desc) - (t (concat desc ".")))))) - (if dirdesc (format "%-23s %s" dirtitle dirdesc) dirtitle)) - "\n" - "@end direntry\n\n"))) + (let* ((dircat (or (plist-get info :texinfo-dircat) "Misc")) + (file (or (org-strip-quotes (plist-get info :texinfo-filename)) + (plist-get info :output-file))) + (file (if file (file-name-sans-extension file))) + (dn (or (plist-get info :texinfo-dirname) + (plist-get info :texinfo-dirtitle))) ;Obsolete name. + ;; Strip any terminating `.' from `dn'. + (dn (if (and dn (string-match "\\.\\'" dn)) (substring dn 0 -1) dn)) + ;; The direntry we need to produce has the shape: + ;; * DIRNAME: NODE. DESCRIPTION. + ;; where NODE is usually just `(FILENAME)', and where + ;; `* FILENAME.' is a shorthand for `* FILENAME: (FILENAME).' + (dirname + (cond + ((and dn (string-match + (eval-when-compile + (concat "\\`\\(?:" + "\\* \\(?1:.*\\)" ;Starts with `* ' or + "\\|\\(?1:.*(.*).*\\)" ;contains parens. + "\\)\\'")) + dn)) + ;; When users provide a `dn' that looks like a complete + ;; `* DIRNAME: (FILENAME).' thingy, we just trust them to + ;; provide something valid (just making sure it starts + ;; with `* ' and ends with `.'). + (format "* %s." (match-string 1 dn))) + ;; `dn' is presumed to be just the DIRNAME part, so generate + ;; either `* DIRNAME: (FILENAME).' or `* FILENAME.', whichever + ;; is shortest. + (dn + (format "* %s: (%s)." dn (or file dn))) + (t (format "* (%s)." file))))) + (concat "@dircategory " dircat "\n" + "@direntry\n" + (let ((dirdesc + (let ((desc (or (plist-get info :texinfo-dirdesc) + title))) + (cond ((not desc) nil) + ((string-suffix-p "." desc) desc) + (t (concat desc ".")))))) + (if dirdesc (format "%-23s %s" dirname dirdesc) dirname)) + "\n" + "@end direntry\n\n")) ;; Title "@finalout\n" "@titlepage\n" @@ -1046,7 +1052,7 @@ plist holding contextual information." ;; character before the closing brace. However, when the ;; footnote ends with a paragraph, it is visually pleasing ;; to move the brace right after its end. - (if (eq 'paragraph (org-element-type (org-last contents))) + (if (org-element-type-p (org-last contents) 'paragraph) (org-trim data) data)))) @@ -1179,21 +1185,21 @@ contextual information." CONTENTS holds the contents of the item. INFO is a plist holding contextual information." (let* ((tag (org-element-property :tag item)) - (plain-list (org-element-property :parent item)) + (plain-list (org-element-parent item)) (compact (and (eq (org-element-property :type plain-list) 'descriptive) (or (plist-get info :texinfo-compact-itemx) (org-not-nil (org-export-read-attribute - :attr_texinfo plain-list :compact))))) + :attr_texinfo plain-list :compact))))) (previous-item nil)) (when (and compact (org-export-get-next-element item info) (not (org-element-contents item)) - (eq 1 (org-element-property :post-blank item))) + (eq 1 (org-element-post-blank item))) (org-element-put-property item :post-blank 0)) (if (and compact (setq previous-item (org-export-get-previous-element item info)) (not (org-element-contents previous-item)) - (eq 0 (org-element-property :post-blank previous-item))) + (eq 0 (org-element-post-blank previous-item))) (format "@itemx%s\n%s" (if tag (concat " " (org-export-data tag info)) "") (or contents "")) @@ -1320,11 +1326,9 @@ INFO is a plist holding contextual information. See (desc (and (not (string= desc "")) desc)) (path (org-texinfo--sanitize-content (cond - ((member type '("http" "https" "ftp")) - (concat type ":" raw-path)) ((string-equal type "file") (org-export-file-uri raw-path)) - (t raw-path))))) + (t (concat type ":" raw-path)))))) (cond ((org-export-custom-protocol-maybe link desc 'texinfo info)) ((org-export-inline-image-p link org-texinfo-inline-image-rules) @@ -1350,10 +1354,11 @@ INFO is a plist holding contextual information. See ;; @anchor{}, so we refer to the headline parent ;; directly. (and `target - (guard (eq 'headline - (org-element-type - (org-element-property :parent destination)))))) - (let ((headline (org-element-lineage destination '(headline) t))) + (guard + (org-element-type-p + (org-element-parent destination) + 'headline)))) + (let ((headline (org-element-lineage destination 'headline t))) (org-texinfo--@ref headline desc info))) (_ (org-texinfo--@ref destination desc info))))) ((string= type "mailto") @@ -1371,7 +1376,7 @@ INFO is a plist holding contextual information. See "Return Texinfo code for an inline image. LINK is the link pointing to the inline image. INFO is the current state of the export, as a plist." - (let* ((parent (org-export-get-parent-element link)) + (let* ((parent (org-element-parent-element link)) (label (and (org-element-property :name parent) (org-texinfo--get-node parent info))) (caption (org-export-get-caption parent)) @@ -1512,7 +1517,12 @@ information." "Transcode a PARAGRAPH element from Org to Texinfo. CONTENTS is the contents of the paragraph, as a string. INFO is the plist used as a communication channel." - contents) + ;; Ensure that we do not create multiple paragraphs, when a single + ;; paragraph is expected. + ;; Multiple newlines may appear in CONTENTS, for example, when + ;; certain objects are stripped from export, leaving single newlines + ;; before and after. + (org-remove-blank-lines contents)) ;;;; Plain List @@ -1590,7 +1600,7 @@ information." (concat "@noindent" (mapconcat - 'identity + #'identity (delq nil (list (let ((closed (org-element-property :closed planning))) @@ -1652,7 +1662,7 @@ contextual information." "Transcode a SECTION element from Org to Texinfo. CONTENTS holds the contents of the section. INFO is a plist holding contextual information." - (let ((parent (org-export-get-parent-headline section))) + (let ((parent (org-element-lineage section 'headline))) (when parent ;first section is handled in `org-texinfo-template' (org-trim (concat contents @@ -1680,8 +1690,9 @@ as a communication channel." "Transcode a SRC-BLOCK element from Org to Texinfo. CONTENTS holds the contents of the item. INFO is a plist holding contextual information." - (let* ((lisp (string-match-p "lisp" - (org-element-property :language src-block))) + (let* ((lisp (string-match-p + "lisp" + (or (org-element-property :language src-block) ""))) (code (org-texinfo--sanitize-content (org-export-format-code-default src-block info))) (value (format @@ -1770,8 +1781,8 @@ a communication channel." ;; approximation of the length of the cell in the ;; output. It can sometimes fail (e.g. it considers ;; "/a/" being larger than "ab"). - (let ((w (- (org-element-property :contents-end cell) - (org-element-property :contents-begin cell)))) + (let ((w (- (org-element-contents-end cell) + (org-element-contents-begin cell)))) (aset widths idx (max w (aref widths idx)))) (cl-incf idx)) info))) @@ -1809,7 +1820,7 @@ a communication channel." (let ((rowgroup-tag (if (and (= 1 (org-export-table-row-group table-row info)) (org-export-table-has-header-p - (org-export-get-parent-table table-row) info)) + (org-element-lineage table-row 'table) info)) "@headitem " "@item "))) (concat rowgroup-tag contents "\n")))) @@ -1993,6 +2004,8 @@ command to convert it." (interactive) (org-export-replace-region-by 'texinfo)) +(defalias 'org-export-region-to-texinfo #'org-texinfo-convert-region-to-texinfo) + (defun org-texinfo-compile (file) "Compile a texinfo file. @@ -2024,9 +2037,11 @@ Once computed, the results remain cached." (unless (boundp 'org-texinfo-supports-math--cache) (setq org-texinfo-supports-math--cache (let ((math-example "1 + 1 = 2")) - (let* ((input-file (make-temp-file "test" nil ".info")) + (let* ((input-file (make-temp-file "test" nil ".texi")) + (output-file + (concat (file-name-sans-extension input-file) ".info")) (input-content (string-join - (list (format "@setfilename %s" input-file) + (list (format "@setfilename %s" output-file) "@node Top" "@displaymath" math-example @@ -2037,7 +2052,8 @@ Once computed, the results remain cached." (when-let* ((output-file ;; If compilation fails, consider math to ;; be not supported. - (ignore-errors (org-texinfo-compile input-file))) + (ignore-errors (let ((inhibit-message t)) + (org-texinfo-compile input-file)))) (output-content (with-temp-buffer (insert-file-contents output-file) (buffer-string)))) diff --git a/lisp/org/ox.el b/lisp/org/ox.el index e9cc0ed8..06c346b6 100644 --- a/lisp/org/ox.el +++ b/lisp/org/ox.el @@ -1,10 +1,10 @@ ;;; ox.el --- Export Framework for Org Mode -*- lexical-binding: t; -*- -;; Copyright (C) 2012-2023 Free Software Foundation, Inc. +;; Copyright (C) 2012-2025 Free Software Foundation, Inc. ;; Author: Nicolas Goaziou -;; Maintainer: Nicolas Goaziou -;; Keywords: outlines, hypermedia, calendar, wp +;; Maintainer: Ihor Radchenko +;; Keywords: outlines, hypermedia, calendar, text ;; This file is part of GNU Emacs. @@ -36,32 +36,32 @@ ;; ;; - The transcoder walks the parse tree, ignores or treat as plain ;; text elements and objects according to export options, and -;; eventually calls back-end specific functions to do the real +;; eventually calls backend specific functions to do the real ;; transcoding, concatenating their return value along the way. ;; ;; - The filter system is activated at the very beginning and the very ;; end of the export process, and each time an element or an object ;; has been converted. It is the entry point to fine-tune standard -;; output from back-end transcoders. See "The Filter System" +;; output from backend transcoders. See "The Filter System" ;; section for more information. ;; ;; The core functions is `org-export-as'. It returns the transcoded ;; buffer as a string. Its derivatives are `org-export-to-buffer' and ;; `org-export-to-file'. ;; -;; An export back-end is defined with `org-export-define-backend'. +;; An export backend is defined with `org-export-define-backend'. ;; This function can also support specific buffer keywords, OPTION ;; keyword's items and filters. Refer to function's documentation for ;; more information. ;; -;; If the new back-end shares most properties with another one, +;; If the new backend shares most properties with another one, ;; `org-export-define-derived-backend' can be used to simplify the ;; process. ;; -;; Any back-end can define its own variables. Among them, those +;; Any backend can define its own variables. Among them, those ;; customizable should belong to the `org-export-BACKEND' group. ;; -;; Tools for common tasks across back-ends are implemented in the +;; Tools for common tasks across backends are implemented in the ;; following part of the file. ;; ;; Eventually, a dispatcher (`org-export-dispatch') is provided in the @@ -81,6 +81,7 @@ (require 'ol) (require 'org-element) (require 'org-macro) +(require 'org-attach) ; org-attach adds staff to `org-export-before-parsing-functions' (require 'tabulated-list) (declare-function org-src-coderef-format "org-src" (&optional element)) @@ -119,9 +120,10 @@ (:headline-levels nil "H" org-export-headline-levels) (:preserve-breaks nil "\\n" org-export-preserve-breaks) (:section-numbers nil "num" org-export-with-section-numbers) - (:time-stamp-file nil "timestamp" org-export-time-stamp-file) + (:time-stamp-file nil "timestamp" org-export-timestamp-file) (:with-archived-trees nil "arch" org-export-with-archived-trees) (:with-author nil "author" org-export-with-author) + (:expand-links nil "expand-links" org-export-expand-links) (:with-broken-links nil "broken-links" org-export-with-broken-links) (:with-clocks nil "c" org-export-with-clocks) (:with-creator nil "creator" org-export-with-creator) @@ -139,6 +141,7 @@ (:with-properties nil "prop" org-export-with-properties) (:with-smart-quotes nil "'" org-export-with-smart-quotes) (:with-special-strings nil "-" org-export-with-special-strings) + (:with-special-rows nil nil nil) (:with-statistics-cookies nil "stat" org-export-with-statistics-cookies) (:with-sub-superscript nil "^" org-export-with-sub-superscripts) (:with-toc nil "toc" org-export-with-toc) @@ -149,11 +152,15 @@ (:with-title nil "title" org-export-with-title) (:with-todo-keywords nil "todo" org-export-with-todo-keywords) ;; Citations processing. + (:with-cite-processors nil nil org-export-process-citations) (:cite-export "CITE_EXPORT" nil org-cite-export-processors)) "Alist between export properties and ways to set them. -The key of the alist is the property name, and the value is a list -like (KEYWORD OPTION DEFAULT BEHAVIOR) where: +Each element of the alist is a list like +(ALIST-KEY KEYWORD OPTION DEFAULT BEHAVIOR) + +ALIST-KEY is the key of the alist - a symbol like `:option', and the +value is (KEYWORD OPTION ...). KEYWORD is a string representing a buffer keyword, or nil. Each property defined this way can also be set, during subtree @@ -178,11 +185,11 @@ BEHAVIOR determines how Org should handle multiple keywords for Values set through KEYWORD and OPTION have precedence over DEFAULT. -All these properties should be back-end agnostic. Back-end +All these properties should be backend agnostic. Backend specific properties are set through `org-export-define-backend'. Properties redefined there have precedence over these.") -(defconst org-export-filters-alist +(defvar org-export-filters-alist '((:filter-body . org-export-filter-body-functions) (:filter-bold . org-export-filter-bold-functions) (:filter-babel-call . org-export-filter-babel-call-functions) @@ -243,7 +250,7 @@ The key of each association is a property name accessible through the communication channel. Its value is a configurable global variable defining initial filters. -This list is meant to install user specified filters. Back-end +This list is meant to install user specified filters. Backend developers may install their own filters using `org-export-define-backend'. Filters defined there will always be prepended to the current list, so they always get applied @@ -263,30 +270,13 @@ whose extension is either \"png\", \"jpeg\", \"jpg\", \"gif\", See `org-export-inline-image-p' for more information about rules.") -(defconst org-export-ignored-local-variables - '( org-font-lock-keywords - org-element--cache org-element--cache-size - org-element--headline-cache org-element--headline-cache-size - org-element--cache-hash-left org-element--cache-hash-right - org-element--cache-sync-requests org-element--cache-sync-timer - org-element--cache-sync-keys-value org-element--cache-change-tic - org-element--cache-last-buffer-size - org-element--cache-diagnostics-ring - org-element--cache-diagnostics-ring-size - org-element--cache-gapless - org-element--cache-change-warning) - "List of variables not copied through upon buffer duplication. -Export process takes place on a copy of the original buffer. -When this copy is created, all Org related local variables not in -this list are copied to the new buffer. Variables with an -unreadable value are also ignored.") - (defvar org-export-async-debug nil "Non-nil means asynchronous export process should leave data behind. This data is found in the appropriate \"*Org Export Process*\" buffer, and in files prefixed with \"org-export-process\" and -located in `temporary-file-directory'. +located in the directory defined by variable +`temporary-file-directory'. When non-nil, it will also set `debug-on-error' to a non-nil value in the external process.") @@ -296,7 +286,7 @@ value in the external process.") This is an alist: its CAR is the source of the result (destination file or buffer for a finished process, original buffer for a running one) and its CDR is a list -containing the back-end used, as a symbol, and either a process +containing the backend used, as a symbol, and either a process or the time at which it finished. It is used to build the menu from `org-export-stack'.") @@ -317,14 +307,14 @@ uses the same subtree if the previous command was restricted to a subtree.") ;; For compatibility with Org < 8 (defvar org-export-current-backend nil - "Name, if any, of the back-end used during an export process. + "Name, if any, of the backend used during an export process. Its value is a symbol such as `html', `latex', `ascii', or nil if -the back-end is anonymous (see `org-export-create-backend') or if +the backend is anonymous (see `org-export-create-backend') or if there is no export process in progress. It can be used to teach Babel blocks how to act differently -according to the back-end used.") +according to the backend used.") @@ -334,7 +324,7 @@ according to the back-end used.") ;; ;; They should never be accessed directly, as their value is to be ;; stored in a property list (cf. `org-export-options-alist'). -;; Back-ends will read their value from there instead. +;; Backends will read their value from there instead. (defgroup org-export nil "Options for exporting Org mode files." @@ -401,17 +391,25 @@ e.g. \"date:nil\"." :type 'boolean :safe #'booleanp) +(defcustom org-export-process-citations t + "Non-nil means process citations using citation processors. +nil will leave citation processing to export backend." + :group 'org-export-general + :type 'boolean + :package-version '(Org . "9.7") + :safe #'booleanp) + (defcustom org-export-date-timestamp-format nil - "Time-stamp format string to use for DATE keyword. + "Timestamp format string to use for DATE keyword. The format string, when specified, only applies if date consists -in a single time-stamp. Otherwise its value will be ignored. +in a single timestamp. Otherwise its value will be ignored. See `format-time-string' for details on how to build this string." :group 'org-export-general :type '(choice - (string :tag "Time-stamp format string") + (string :tag "Timestamp format string") (const :tag "No format string" nil)) :safe (lambda (x) (or (null x) (stringp x)))) @@ -525,7 +523,7 @@ t Allow export of math snippets." "The last level which is still exported as a headline. Inferior levels will usually produce itemize or enumerate lists -when exported, but back-end behavior may differ. +when exported, but backend behavior may differ. This option can also be set with the OPTIONS keyword, e.g. \"H:2\"." @@ -580,7 +578,7 @@ e.g. \"inline:nil\"." "Non-nil means include planning info in export. Planning info is the line containing either SCHEDULED:, -DEADLINE:, CLOSED: time-stamps, or a combination of them. +DEADLINE:, CLOSED: timestamps, or a combination of them. This option can also be set with the OPTIONS keyword, e.g. \"p:t\"." @@ -690,31 +688,14 @@ e.g. \"stat:nil\"" "Non-nil means interpret \"_\" and \"^\" for export. If you want to control how Org displays those characters, see -`org-use-sub-superscripts'. `org-export-with-sub-superscripts' -used to be an alias for `org-use-sub-superscripts' in Org <8.0, -it is not anymore. +`org-use-sub-superscripts'. When this option is turned on, you can use TeX-like syntax for sub- and superscripts and see them exported correctly. You can also set the option with #+OPTIONS: ^:t -Several characters after \"_\" or \"^\" will be considered as a -single item - so grouping with {} is normally not needed. For -example, the following things will be parsed as single sub- or -superscripts: - - 10^24 or 10^tau several digits will be considered 1 item. - 10^-12 or 10^-tau a leading sign with digits or a word - x^2-y^3 will be read as x^2 - y^3, because items are - terminated by almost any nonword/nondigit char. - x_{i^2} or x^(2-i) braces or parenthesis do grouping. - -Still, ambiguity is possible. So when in doubt, use {} to enclose -the sub/superscript. If you set this variable to the symbol `{}', -the braces are *required* in order to trigger interpretations as -sub/superscript. This can be helpful in documents that need \"_\" -frequently in plain text." +See `org-use-sub-superscripts' docstring for more details." :group 'org-export-general :version "24.4" :package-version '(Org . "8.0") @@ -808,7 +789,8 @@ e.g. \"title:nil\"." :type 'boolean :safe #'booleanp) -(defcustom org-export-time-stamp-file t +(defvaralias 'org-export-time-stamp-file 'org-export-timestamp-file) +(defcustom org-export-timestamp-file t "Non-nil means insert a time stamp into the exported file. The time stamp shows when the file was created. This option can also be set with the OPTIONS keyword, e.g. \"timestamp:nil\"." @@ -876,8 +858,14 @@ This option can also be set with the OPTIONS keyword, e.g., (const :tag "Mark broken links in output" mark) (const :tag "Raise an error" nil))) +(defcustom org-export-expand-links t + "When non-nil, expand environment variables in file paths." + :group 'org-export-general + :package-version '(Org . "9.7") + :type 'boolean) + (defcustom org-export-snippet-translation-alist nil - "Alist between export snippets back-ends and exporter back-ends. + "Alist between export snippets backends and exporter backends. This variable allows providing shortcuts for export snippets. @@ -886,14 +874,14 @@ For example, with: (setq org-export-snippet-translation-alist \\='((\"h\" . \"html\"))) -the HTML back-end will recognize the contents of \"@@h:@@\" as -HTML code while every other back-end will ignore it." +the HTML backend will recognize the contents of \"@@h:@@\" as +HTML code while every other backend will ignore it." :group 'org-export-general :version "24.4" :package-version '(Org . "8.0") :type '(repeat (cons (string :tag "Shortcut") - (string :tag "Back-end"))) + (string :tag "Backend"))) :safe (lambda (x) (and (listp x) (cl-every #'consp x) @@ -959,6 +947,31 @@ these cases." :group 'org-export-general :type 'boolean) +(defcustom org-export-body-only nil + "The initial \"Body only\" setting when exporting with `org-export-dispatch'. +Non-nil means only export body code, without the surrounding +template." + :group 'org-export-general + :package-version '(Org . "9.7") + :type 'boolean + :safe #'booleanp) + +(defcustom org-export-visible-only nil + "The initial \"Visible only\" setting when exporting with `org-export-dispatch'. +Non-nil means don't export the contents of hidden elements." + :group 'org-export-general + :package-version '(Org . "9.7") + :type 'boolean + :safe #'booleanp) + +(defcustom org-export-force-publishing nil + "The initial \"Force publishing\" setting for `org-export-dispatch'. +Non-nil means force all files in the project to be published." + :group 'org-export-general + :package-version '(Org . "9.7") + :type 'boolean + :safe #'booleanp) + (defcustom org-export-in-background nil "Non-nil means export and publishing commands will run in background. Results from an asynchronous export are never displayed @@ -1003,34 +1016,34 @@ mode." -;;; Defining Back-ends +;;; Defining Backends ;; -;; An export back-end is a structure with `org-export-backend' type +;; An export backend is a structure with `org-export-backend' type ;; and `name', `parent', `transcoders', `options', `filters', `blocks' ;; and `menu' slots. ;; -;; At the lowest level, a back-end is created with +;; At the lowest level, a backend is created with ;; `org-export-create-backend' function. ;; -;; A named back-end can be registered with -;; `org-export-register-backend' function. A registered back-end can +;; A named backend can be registered with +;; `org-export-register-backend' function. A registered backend can ;; later be referred to by its name, with `org-export-get-backend' -;; function. Also, such a back-end can become the parent of a derived -;; back-end from which slot values will be inherited by default. -;; `org-export-derived-backend-p' can check if a given back-end is -;; derived from a list of back-end names. +;; function. Also, such a backend can become the parent of a derived +;; backend from which slot values will be inherited by default. +;; `org-export-derived-backend-p' can check if a given backend is +;; derived from a list of backend names. ;; ;; `org-export-get-all-transcoders', `org-export-get-all-options' and ;; `org-export-get-all-filters' return the full alist of transcoders, ;; options and filters, including those inherited from ancestors. ;; ;; At a higher level, `org-export-define-backend' is the standard way -;; to define an export back-end. If the new back-end is similar to -;; a registered back-end, `org-export-define-derived-backend' may be +;; to define an export backend. If the new backend is similar to +;; a registered backend, `org-export-define-derived-backend' may be ;; used instead. ;; ;; Eventually `org-export-barf-if-invalid-backend' returns an error -;; when a given back-end hasn't been registered yet. +;; when a given backend hasn't been registered yet. (cl-defstruct (org-export-backend (:constructor org-export-create-backend) (:copier nil)) @@ -1038,24 +1051,24 @@ mode." ;;;###autoload (defun org-export-get-backend (name) - "Return export back-end named after NAME. -NAME is a symbol. Return nil if no such back-end is found." + "Return export backend named after NAME. +NAME is a symbol. Return nil if no such backend is found." (cl-find-if (lambda (b) (and (eq name (org-export-backend-name b)))) org-export-registered-backends)) (defun org-export-register-backend (backend) - "Register BACKEND as a known export back-end. + "Register BACKEND as a known export backend. BACKEND is a structure with `org-export-backend' type." - ;; Refuse to register an unnamed back-end. + ;; Refuse to register an unnamed backend. (unless (org-export-backend-name backend) - (error "Cannot register a unnamed export back-end")) - ;; Refuse to register a back-end with an unknown parent. + (error "Cannot register a unnamed export backend")) + ;; Refuse to register a backend with an unknown parent. (let ((parent (org-export-backend-parent backend))) (when (and parent (not (org-export-get-backend parent))) - (error "Cannot use unknown \"%s\" back-end as a parent" parent))) - ;; If a back-end with the same name as BACKEND is already + (error "Cannot use unknown \"%s\" backend as a parent" parent))) + ;; If a backend with the same name as BACKEND is already ;; registered, replace it with BACKEND. Otherwise, simply add - ;; BACKEND to the list of registered back-ends. + ;; BACKEND to the list of registered backends. (let ((old (org-export-get-backend (org-export-backend-name backend)))) (if old (setcar (memq old org-export-registered-backends) backend) (push backend org-export-registered-backends)))) @@ -1063,14 +1076,14 @@ BACKEND is a structure with `org-export-backend' type." (defun org-export-barf-if-invalid-backend (backend) "Signal an error if BACKEND isn't defined." (unless (org-export-backend-p backend) - (error "Unknown \"%s\" back-end: Aborting export" backend))) + (error "Unknown \"%s\" backend: Aborting export" backend))) ;;;###autoload (defun org-export-derived-backend-p (backend &rest backends) "Non-nil if BACKEND is derived from one of BACKENDS. -BACKEND is an export back-end, as returned by, e.g., +BACKEND is an export backend, as returned by, e.g., `org-export-create-backend', or a symbol referring to -a registered back-end. BACKENDS is constituted of symbols." +a registered backend. BACKENDS is constituted of symbols." (when (symbolp backend) (setq backend (org-export-get-backend backend))) (when backend (catch 'exit @@ -1084,20 +1097,20 @@ a registered back-end. BACKENDS is constituted of symbols." (defun org-export-get-all-transcoders (backend) "Return full translation table for BACKEND. -BACKEND is an export back-end, as return by, e.g,, +BACKEND is an export backend, as return by, e.g,, `org-export-create-backend'. Return value is an alist where keys are element or object types, as symbols, and values are transcoders. Unlike to `org-export-backend-transcoders', this function -also returns transcoders inherited from parent back-ends, +also returns transcoders inherited from parent backends, if any." (when (symbolp backend) (setq backend (org-export-get-backend backend))) (when backend (let ((transcoders (org-export-backend-transcoders backend)) parent) (while (setq parent (org-export-backend-parent backend)) - (setq backend (org-export-get-backend parent)) + (setq backend (if (symbolp parent) (org-export-get-backend parent) parent)) (setq transcoders (append transcoders (org-export-backend-transcoders backend)))) transcoders))) @@ -1105,12 +1118,12 @@ if any." (defun org-export-get-all-options (backend) "Return export options for BACKEND. -BACKEND is an export back-end, as return by, e.g,, +BACKEND is an export backend, as return by, e.g,, `org-export-create-backend'. See `org-export-options-alist' for the shape of the return value. Unlike to `org-export-backend-options', this function also -returns options inherited from parent back-ends, if any. +returns options inherited from parent backends, if any. Return nil if BACKEND is unknown." (when (symbolp backend) (setq backend (org-export-get-backend backend))) @@ -1125,12 +1138,12 @@ Return nil if BACKEND is unknown." (defun org-export-get-all-filters (backend) "Return complete list of filters for BACKEND. -BACKEND is an export back-end, as return by, e.g,, +BACKEND is an export backend, as return by, e.g,, `org-export-create-backend'. Return value is an alist where keys are symbols and values lists of functions. Unlike to `org-export-backend-filters', this function also -returns filters inherited from parent back-ends, if any." +returns filters inherited from parent backends, if any." (when (symbolp backend) (setq backend (org-export-get-backend backend))) (when backend (let ((filters (org-export-backend-filters backend)) @@ -1141,7 +1154,7 @@ returns filters inherited from parent back-ends, if any." filters))) (defun org-export-define-backend (backend transcoders &rest body) - "Define a new back-end BACKEND. + "Define a new backend BACKEND. TRANSCODERS is an alist between object or element types and functions handling them. @@ -1177,7 +1190,7 @@ The latter, when defined, is to be called on every text not recognized as an element or an object. It must accept two arguments: the text string and the information channel. It is an appropriate place to protect special chars relative to the -back-end. +backend. BODY can start with pre-defined keyword arguments. The following keywords are understood: @@ -1185,9 +1198,9 @@ keywords are understood: :filters-alist Alist between filters and function, or list of functions, - specific to the back-end. See `org-export-filters-alist' for + specific to the backend. See `org-export-filters-alist' for a list of all allowed filters. Filters defined here - shouldn't make a back-end test, as it may prevent back-ends + shouldn't make a backend test, as it may prevent backends derived from this one to behave properly. :menu-entry @@ -1199,13 +1212,13 @@ keywords are understood: where : - KEY is a free character selecting the back-end. + KEY is a free character selecting the backend. DESCRIPTION-OR-ORDINAL is either a string or a number. - If it is a string, is will be used to name the back-end in + If it is a string, is will be used to name the backend in its menu entry. If it is a number, the following menu will - be displayed as a sub-menu of the back-end with the same + be displayed as a sub-menu of the backend with the same KEY. Also, the number will be used to determine in which order such sub-menus will appear (lowest first). @@ -1225,7 +1238,7 @@ keywords are understood: Valid values include: - (?m \"My Special Back-end\" my-special-export-function) + (?m \"My Special Backend\" my-special-export-function) or @@ -1246,7 +1259,7 @@ keywords are understood: :options-alist - Alist between back-end specific properties introduced in + Alist between backend specific properties introduced in communication channel and how their value are acquired. See `org-export-options-alist' for more information about structure of the values." @@ -1267,10 +1280,10 @@ keywords are understood: :menu menu-entry)))) (defun org-export-define-derived-backend (child parent &rest body) - "Create a new back-end as a variant of an existing one. + "Create a new backend as a variant of an existing one. -CHILD is the name of the derived back-end. PARENT is the name of -the parent back-end. +CHILD is the name of the derived backend. PARENT is the name of +the parent backend. BODY can start with pre-defined keyword arguments. The following keywords are understood: @@ -1278,7 +1291,7 @@ keywords are understood: :filters-alist Alist of filters that will overwrite or complete filters - defined in PARENT back-end. See `org-export-filters-alist' + defined in PARENT backend. See `org-export-filters-alist' for a list of allowed filters. :menu-entry @@ -1289,25 +1302,25 @@ keywords are understood: :options-alist - Alist of back-end specific properties that will overwrite or - complete those defined in PARENT back-end. Refer to + Alist of backend specific properties that will overwrite or + complete those defined in PARENT backend. Refer to `org-export-options-alist' for more information about structure of the values. :translate-alist Alist of element and object types and transcoders that will - overwrite or complete transcode table from PARENT back-end. + overwrite or complete transcode table from PARENT backend. Refer to `org-export-define-backend' for detailed information about transcoders. -As an example, here is how one could define \"my-latex\" back-end -as a variant of `latex' back-end with a custom template function: +As an example, here is how one could define \"my-latex\" backend +as a variant of `latex' backend with a custom template function: (org-export-define-derived-backend \\='my-latex \\='latex :translate-alist \\='((template . my-latex-template-fun))) -The back-end could then be called with, for example: +The backend could then be called with, for example: (org-export-to-buffer \\='my-latex \"*Test my-latex*\")" (declare (indent 2)) @@ -1378,7 +1391,7 @@ The back-end could then be called with, for example: (defun org-export-get-environment (&optional backend subtreep ext-plist) "Collect export options from the current buffer. -Optional argument BACKEND is an export back-end, as returned by +Optional argument BACKEND is an export backend, as returned by `org-export-create-backend'. When optional argument SUBTREEP is non-nil, assume the export is @@ -1389,8 +1402,7 @@ external parameters overriding Org default settings, but still inferior to file-local settings." ;; First install #+BIND variables since these must be set before ;; global options are read. - (dolist (pair (org-export--list-bound-variables)) - (set (make-local-variable (car pair)) (nth 1 pair))) + (org-export--set-variables (org-export--list-bound-variables)) ;; Get and prioritize export options... (org-combine-plists ;; ... from global variables... @@ -1404,8 +1416,8 @@ inferior to file-local settings." (defun org-export--parse-option-keyword (options &optional backend) "Parse an OPTIONS line and return values as a plist. -Optional argument BACKEND is an export back-end, as returned by, -e.g., `org-export-create-backend'. It specifies which back-end +Optional argument BACKEND is an export backend, as returned by, +e.g., `org-export-create-backend'. It specifies which backend specific items to read, if any." (let ((line (let (alist) @@ -1418,7 +1430,7 @@ specific items to read, if any." (read (current-buffer))) ; moves point alist)))) alist)) - ;; Priority is given to back-end specific options. + ;; Priority is given to backend specific options. (all (append (org-export-get-all-options backend) org-export-options-alist)) (plist)) @@ -1431,8 +1443,8 @@ specific items to read, if any." (defun org-export--get-subtree-options (&optional backend) "Get export options in subtree at point. -Optional argument BACKEND is an export back-end, as returned by, -e.g., `org-export-create-backend'. It specifies back-end used +Optional argument BACKEND is an export backend, as returned by, +e.g., `org-export-create-backend'. It specifies backend used for export. Return options as a plist." ;; For each buffer keyword, create a headline property setting the ;; same property in communication channel. The name for the @@ -1454,7 +1466,7 @@ for export. Return options as a plist." (let ((case-fold-search nil)) (looking-at org-complex-heading-regexp) (match-string-no-properties 4)))))) - ;; Look for both general keywords and back-end specific + ;; Look for both general keywords and backend specific ;; options, with priority given to the latter. (options (append (org-export-get-all-options backend) org-export-options-alist))) @@ -1483,15 +1495,15 @@ for export. Return options as a plist." (defun org-export--get-inbuffer-options (&optional backend) "Return current buffer export options, as a plist. -Optional argument BACKEND, when non-nil, is an export back-end, +Optional argument BACKEND, when non-nil, is an export backend, as returned by, e.g., `org-export-create-backend'. It specifies -which back-end specific options should also be read in the +which backend specific options should also be read in the process. Assume buffer is in Org mode. Narrowing, if any, is ignored." (let* ((case-fold-search t) (options (append - ;; Priority is given to back-end specific options. + ;; Priority is given to backend specific options. (org-export-get-all-options backend) org-export-options-alist)) plist to-parse) @@ -1554,7 +1566,7 @@ Assume buffer is in Org mode. Narrowing, if any, is ignored." (org-element-restriction 'keyword)))) (org-element-map value 'plain-text (lambda (s) - (org-element-set-element + (org-element-set s (replace-regexp-in-string "\n" " " s)))) (setq plist (plist-put plist p value))))))) @@ -1579,12 +1591,12 @@ are like the arguments with the same names of function (defun org-export--get-global-options (&optional backend) "Return global export options as a plist. -Optional argument BACKEND, if non-nil, is an export back-end, as +Optional argument BACKEND, if non-nil, is an export backend, as returned by, e.g., `org-export-create-backend'. It specifies -which back-end specific export options should also be read in the +which backend specific export options should also be read in the process." (let (plist - ;; Priority is given to back-end specific options. + ;; Priority is given to backend specific options. (all (append (org-export-get-all-options backend) org-export-options-alist))) (dolist (cell all plist) @@ -1611,14 +1623,6 @@ an alist where associations are (VARIABLE-NAME VALUE)." (mapcar (lambda (v) (read (format "(%s)" v))) values))))) -;; defsubst org-export-get-parent must be defined before first use, -;; was originally defined in the topology section - -(defsubst org-export-get-parent (blob) - "Return BLOB parent or nil. -BLOB is the element or object considered." - (org-element-property :parent blob)) - ;;;; Tree Properties ;; ;; Tree properties are information extracted from parse tree. They @@ -1626,11 +1630,10 @@ BLOB is the element or object considered." ;; `org-export--collect-tree-properties'. ;; ;; Dedicated functions focus on computing the value of specific tree -;; properties during initialization. Thus, -;; `org-export--populate-ignore-list' lists elements and objects that -;; should be skipped during export, `org-export--get-min-level' gets -;; the minimal exportable level, used as a basis to compute relative -;; level for headlines. Eventually +;; properties during initialization. Thus, `org-export--prune-tree' +;; lists elements and objects that should be skipped during export, +;; `org-export--get-min-level' gets the minimal exportable level, used +;; as a basis to compute relative level for headlines. Eventually ;; `org-export--collect-headline-numbering' builds an alist between ;; headlines and their numbering. @@ -1642,6 +1645,7 @@ is a list holding export options. Following tree properties are set or updated: +`:parse-tree' Is simply set to DATA. `:headline-offset' Offset between true level of headlines and local level. An offset of -1 means a headline of level 2 should be considered as a level @@ -1682,7 +1686,7 @@ OPTIONS is a plist holding export options." (catch 'exit (let ((min-level 10000)) (dolist (datum (org-element-contents data)) - (when (and (eq (org-element-type datum) 'headline) + (when (and (org-element-type-p datum 'headline) (not (org-element-property :footnote-section-p datum)) (not (memq datum (plist-get options :ignore-list)))) (setq min-level (min (org-element-property :level datum) min-level)) @@ -1770,8 +1774,8 @@ not exported." ;; local structure of the document upon interpreting it back into ;; Org syntax. (let* ((previous (org-export-get-previous-element datum options)) - (before (or (org-element-property :post-blank previous) 0)) - (after (or (org-element-property :post-blank datum) 0))) + (before (or (org-element-post-blank previous) 0)) + (after (or (org-element-post-blank datum) 0))) (when previous (org-element-put-property previous :post-blank (max before after 1)))) t) @@ -1798,7 +1802,7 @@ not exported." (archived (plist-get options :with-archived-trees)) (tags (org-export-get-tags datum options nil t))) (or - (and (eq (org-element-type datum) 'inlinetask) + (and (org-element-type-p datum 'inlinetask) (not (plist-get options :with-inlinetasks))) ;; Ignore subtrees with an exclude tag. (cl-some (lambda (tag) (member tag excluded)) tags) @@ -1821,28 +1825,30 @@ not exported." (cond ((null properties-set) t) ((consp properties-set) (not (member-ignore-case (org-element-property :key datum) - properties-set)))))) + properties-set)))))) (planning (not (plist-get options :with-planning))) (property-drawer (not (plist-get options :with-properties))) (statistics-cookie (not (plist-get options :with-statistics-cookies))) (table (not (plist-get options :with-tables))) (table-cell (and (org-export-table-has-special-column-p - (org-export-get-parent-table datum)) + (org-element-lineage datum 'table)) (org-export-first-sibling-p datum options))) - (table-row (org-export-table-row-is-special-p datum options)) + (table-row + (unless (plist-get options :with-special-rows) + (org-export-table-row-is-special-p datum options))) (timestamp ;; `:with-timestamps' only applies to isolated timestamps ;; objects, i.e. timestamp objects in a paragraph containing only ;; timestamps and whitespaces. - (when (let ((parent (org-export-get-parent-element datum))) - (and (memq (org-element-type parent) '(paragraph verse-block)) + (when (let ((parent (org-element-parent-element datum))) + (and (org-element-type-p parent '(paragraph verse-block)) (not (org-element-map parent (cons 'plain-text - (remq 'timestamp org-element-all-objects)) - (lambda (obj) + (remq 'timestamp org-element-all-objects)) + (lambda (obj) (or (not (stringp obj)) (org-string-nw-p obj))) - options t)))) + options t)))) (cl-case (plist-get options :with-timestamps) ((nil) t) (active @@ -1856,13 +1862,13 @@ not exported." ;; ;; `org-export-data' reads a parse tree (obtained with, i.e. ;; `org-element-parse-buffer') and transcodes it into a specified -;; back-end output. It takes care of filtering out elements or +;; backend output. It takes care of filtering out elements or ;; objects according to export options and organizing the output blank ;; lines and white space are preserved. The function memoizes its ;; results, so it is cheap to call it within transcoders. ;; -;; It is possible to modify locally the back-end used by -;; `org-export-data' or even use a temporary back-end by using +;; It is possible to modify locally the backend used by +;; `org-export-data' or even use a temporary backend by using ;; `org-export-data-with-backend'. ;; ;; `org-export-transcoder' is an accessor returning appropriate @@ -1877,13 +1883,47 @@ INFO is a plist containing export directives." (let ((transcoder (cdr (assq type (plist-get info :translate-alist))))) (and (functionp transcoder) transcoder))))) +(defun org-export--keep-spaces (data info) + "Non-nil, when post-blank spaces after removing DATA should be preserved. +INFO is the info channel. + +This function returns nil, when previous exported element already has +trailing spaces or when DATA does not have non-zero non-nil +`:post-blank' property. + +When the return value is non-nil, it is a string containing the trailing +spaces." + ;; When DATA is an object, interpret this as if DATA should be + ;; ignored (see `org-export--prune-tree'). Keep spaces in place of + ;; removed element, if necessary. Example: "Foo.[10%] Bar" would + ;; become "Foo.Bar" if we do not keep spaces. Another example: "A + ;; space@@ascii:*@@ character." should become "A space character" + ;; in non-ASCII export. + (let ((post-blank (org-element-post-blank data))) + (unless (or (not post-blank) + (zerop post-blank) + (eq 'element (org-element-class data))) + (let ((previous (org-export-get-previous-element data info))) + (unless (or (not previous) + (pcase (org-element-type previous) + (`plain-text + (string-match-p + (rx (any " \t\r\n") eos) previous)) + (_ (org-element-post-blank previous)))) + ;; When previous element does not have + ;; trailing spaces, keep the trailing + ;; spaces from DATA. + (make-string post-blank ?\s)))))) + ;;;###autoload (defun org-export-data (data info) - "Convert DATA into current back-end format. + "Convert DATA into current backend format. DATA is a parse tree, an element or an object or a secondary string. INFO is a plist holding export options. +The `:filter-parse-tree' filters are not applied. + Return a string." (or (gethash data (plist-get info :exported-data)) ;; Handle broken links according to @@ -1895,12 +1935,12 @@ Return a string." (progn ,@body) (org-link-broken (pcase (plist-get info :with-broken-links) - (`nil (user-error "Unable to resolve link: %S" (nth 1 err))) + (`nil (user-error "Org export aborted. Unable to resolve link: %S\nSee `org-export-with-broken-links'" (nth 1 err))) (`mark (org-export-data (format "[BROKEN LINK: %s]" (nth 1 err)) info)) (_ nil)))))) (let* ((type (org-element-type data)) - (parent (org-export-get-parent data)) + (parent (org-element-parent data)) (results (cond ;; Ignored element/object. @@ -1925,15 +1965,11 @@ Return a string." (eq (plist-get info :with-archived-trees) 'headline) (org-element-property :archivedp data))) (let ((transcoder (org-export-transcoder data info))) - (or (and (functionp transcoder) - (if (eq type 'link) - (broken-link-handler - (funcall transcoder data nil info)) - (funcall transcoder data nil info))) - ;; Export snippets never return a nil value so - ;; that white spaces following them are never - ;; ignored. - (and (eq type 'export-snippet) "")))) + (and (functionp transcoder) + (if (eq type 'link) + (broken-link-handler + (funcall transcoder data nil info)) + (funcall transcoder data nil info))))) ;; Element/Object with contents. (t (let ((transcoder (org-export-transcoder data info))) @@ -1958,8 +1994,8 @@ Return a string." ;; first line's indentation. (and (eq type 'paragraph) - (memq (org-element-type parent) - '(footnote-definition item)) + (org-element-type-p + parent '(footnote-definition item)) (eq (car (org-element-contents parent)) data) (eq (org-element-property :pre-blank parent) @@ -1974,14 +2010,14 @@ Return a string." (puthash data (cond - ((not results) "") - ((memq type '(nil org-data plain-text raw)) results) + ((not results) (or (org-export--keep-spaces data info) "")) + ((memq type '(nil org-data plain-text raw)) results) ;; Append the same white space between elements or objects ;; as in the original buffer, and call appropriate filters. (t (org-export-filter-apply-functions (plist-get info (intern (format ":filter-%s" type))) - (let ((blank (or (org-element-property :post-blank data) 0))) + (let ((blank (or (org-element-post-blank data) 0))) (if (eq (org-element-class data parent) 'object) (concat results (make-string blank ?\s)) (concat (org-element-normalize-string results) @@ -2012,8 +2048,8 @@ recursively convert DATA using BACKEND translation table." :exported-data (make-hash-table :test 'eq :size 401))))) (prog1 (org-export-data data new-info) ;; Preserve `:internal-references', as those do not depend on - ;; the back-end used; we need to make sure that any new - ;; reference when the temporary back-end was active gets through + ;; the backend used; we need to make sure that any new + ;; reference when the temporary backend was active gets through ;; the default one. (plist-put info :internal-references (plist-get new-info :internal-references))))) @@ -2041,9 +2077,9 @@ keywords before output." ;; They are the functional counterpart of hooks, as every filter in ;; a set is applied to the return value of the previous one. ;; -;; Every set is back-end agnostic. Although, a filter is always -;; called, in addition to the string it applies to, with the back-end -;; used as argument, so it's easy for the end-user to add back-end +;; Every set is backend agnostic. Although, a filter is always +;; called, in addition to the string it applies to, with the backend +;; used as argument, so it's easy for the end-user to add backend ;; specific filters in the set. The communication channel, as ;; a plist, is required as the third argument. ;; @@ -2056,7 +2092,7 @@ keywords before output." ;; - `:filter-options' applies to the property list containing export ;; options. Unlike to other filters, functions in this list accept ;; two arguments instead of three: the property list containing -;; export options and the back-end. Users can set its value through +;; export options and the backend. Users can set its value through ;; `org-export-filter-options-functions' variable. ;; ;; - `:filter-parse-tree' applies directly to the complete parsed @@ -2104,7 +2140,7 @@ being exported. Visibility and narrowing are preserved. Point is at the beginning of the buffer. Every function in this hook will be called with one argument: the -back-end currently used, as a symbol.") +backend currently used, as a symbol.") (defvar org-export-before-parsing-functions nil "Abnormal hook run before parsing an export buffer. @@ -2115,7 +2151,7 @@ being exported. Visibility and narrowing are preserved. Point is at the beginning of the buffer. Every function in this hook will be called with one argument: the -back-end currently used, as a symbol.") +backend currently used, as a symbol.") ;;;; Special Filters @@ -2123,34 +2159,34 @@ back-end currently used, as a symbol.") (defvar org-export-filter-options-functions nil "List of functions applied to the export options. Each filter is called with two arguments: the export options, as -a plist, and the back-end, as a symbol. It must return +a plist, and the backend, as a symbol. It must return a property list containing export options.") (defvar org-export-filter-parse-tree-functions nil "List of functions applied to the parsed tree. Each filter is called with three arguments: the parse tree, as -returned by `org-element-parse-buffer', the back-end, as +returned by `org-element-parse-buffer', the backend, as a symbol, and the communication channel, as a plist. It must return the modified parse tree to transcode.") (defvar org-export-filter-plain-text-functions nil "List of functions applied to plain text. Each filter is called with three arguments: a string which -contains no Org syntax, the back-end, as a symbol, and the +contains no Org syntax, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-body-functions nil "List of functions applied to transcoded body. Each filter is called with three arguments: a string which -contains no Org syntax, the back-end, as a symbol, and the +contains no Org syntax, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-final-output-functions nil "List of functions applied to the transcoded string. Each filter is called with three arguments: the full transcoded -string, the back-end, as a symbol, and the communication channel, +string, the backend, as a symbol, and the communication channel, as a plist. It must return a string that will be used as the final export output.") @@ -2160,176 +2196,176 @@ final export output.") (defvar org-export-filter-babel-call-functions nil "List of functions applied to a transcoded babel-call. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-center-block-functions nil "List of functions applied to a transcoded center block. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-clock-functions nil "List of functions applied to a transcoded clock. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-diary-sexp-functions nil "List of functions applied to a transcoded diary-sexp. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-drawer-functions nil "List of functions applied to a transcoded drawer. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-dynamic-block-functions nil "List of functions applied to a transcoded dynamic-block. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-example-block-functions nil "List of functions applied to a transcoded example-block. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-export-block-functions nil "List of functions applied to a transcoded export-block. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-fixed-width-functions nil "List of functions applied to a transcoded fixed-width. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-footnote-definition-functions nil "List of functions applied to a transcoded footnote-definition. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-headline-functions nil "List of functions applied to a transcoded headline. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-horizontal-rule-functions nil "List of functions applied to a transcoded horizontal-rule. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-inlinetask-functions nil "List of functions applied to a transcoded inlinetask. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-item-functions nil "List of functions applied to a transcoded item. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-keyword-functions nil "List of functions applied to a transcoded keyword. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-latex-environment-functions nil "List of functions applied to a transcoded latex-environment. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-node-property-functions nil "List of functions applied to a transcoded node-property. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-paragraph-functions nil "List of functions applied to a transcoded paragraph. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-plain-list-functions nil "List of functions applied to a transcoded plain-list. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-planning-functions nil "List of functions applied to a transcoded planning. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-property-drawer-functions nil "List of functions applied to a transcoded property-drawer. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-quote-block-functions nil "List of functions applied to a transcoded quote block. Each filter is called with three arguments: the transcoded quote -data, as a string, the back-end, as a symbol, and the +data, as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-section-functions nil "List of functions applied to a transcoded section. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-special-block-functions nil "List of functions applied to a transcoded special block. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-src-block-functions nil "List of functions applied to a transcoded src-block. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-table-functions nil "List of functions applied to a transcoded table. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-table-cell-functions nil "List of functions applied to a transcoded table-cell. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-table-row-functions nil "List of functions applied to a transcoded table-row. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-verse-block-functions nil "List of functions applied to a transcoded verse block. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") @@ -2338,128 +2374,128 @@ channel, as a plist. It must return a string or nil.") (defvar org-export-filter-bold-functions nil "List of functions applied to transcoded bold text. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-code-functions nil "List of functions applied to transcoded code text. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-entity-functions nil "List of functions applied to a transcoded entity. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-export-snippet-functions nil "List of functions applied to a transcoded export-snippet. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-footnote-reference-functions nil "List of functions applied to a transcoded footnote-reference. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-inline-babel-call-functions nil "List of functions applied to a transcoded inline-babel-call. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-inline-src-block-functions nil "List of functions applied to a transcoded inline-src-block. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-italic-functions nil "List of functions applied to transcoded italic text. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-latex-fragment-functions nil "List of functions applied to a transcoded latex-fragment. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-line-break-functions nil "List of functions applied to a transcoded line-break. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-link-functions nil "List of functions applied to a transcoded link. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-radio-target-functions nil "List of functions applied to a transcoded radio-target. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-statistics-cookie-functions nil "List of functions applied to a transcoded statistics-cookie. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-strike-through-functions nil "List of functions applied to transcoded strike-through text. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-subscript-functions nil "List of functions applied to a transcoded subscript. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-superscript-functions nil "List of functions applied to a transcoded superscript. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-target-functions nil "List of functions applied to a transcoded target. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-timestamp-functions nil "List of functions applied to a transcoded timestamp. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-underline-functions nil "List of functions applied to transcoded underline text. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") (defvar org-export-filter-verbatim-functions nil "List of functions applied to transcoded verbatim text. Each filter is called with three arguments: the transcoded data, -as a string, the back-end, as a symbol, and the communication +as a string, the backend, as a symbol, and the communication channel, as a plist. It must return a string or nil.") ;;;; Filters Tools ;; ;; Internal function `org-export-install-filters' installs filters -;; hard-coded in back-ends (developer filters) and filters from global +;; hard-coded in backends (developer filters) and filters from global ;; variables (user filters) in the communication channel. ;; ;; Internal function `org-export-filter-apply-functions' takes care @@ -2471,7 +2507,7 @@ channel, as a plist. It must return a string or nil.") "Call every function in FILTERS. Functions are called with three arguments: a value, the export -back-end name and the communication channel. First function in +backend name and the communication channel. First function in FILTERS is called with VALUE as its first argument. Second function in FILTERS is called with the previous result as its value, etc. @@ -2508,7 +2544,7 @@ Return the updated communication channel." (append (if (listp info-value) info-value (list info-value)) default-value))))) - ;; Prepend back-end specific filters to that list. + ;; Prepend backend specific filters to that list. (dolist (p (org-export-get-all-filters (plist-get info :back-end))) ;; Single values get consed, lists are appended. (let ((key (car p)) (value (cdr p))) @@ -2546,41 +2582,33 @@ Return the updated communication channel." ;; associated to the file, that is before parsing. ;; ;; `org-export-insert-default-template' is a command to insert -;; a default template (or a back-end specific template) at point or in +;; a default template (or a backend specific template) at point or in ;; current subtree. +(defun org-export--set-variables (variable-alist) + "Set buffer-local variables according to VARIABLE-ALIST in current buffer." + (pcase-dolist (`(,var . ,val) variable-alist) + (set (make-local-variable var) (car val)))) + (cl-defun org-export-copy-buffer (&key to-buffer drop-visibility drop-narrowing drop-contents drop-locals) "Return a copy of the current buffer. -The copy preserves Org buffer-local variables, visibility and -narrowing. +This function calls `org-element-copy-buffer', passing the same +arguments TO-BUFFER, DROP-VISIBILITY, DROP-NARROWING, DROP-CONTENTS, +and DROP-LOCALS. -IMPORTANT: The buffer copy may also have `buffer-file-name' copied. -To prevent Emacs overwriting the original buffer file, -`write-contents-functions' is set to (always). Do not alter this -variable and do not do anything that might alter it (like calling a -major mode) to prevent data corruption. Also, do note that Emacs may -jump into the created buffer if the original file buffer is closed and -then re-opened. Making edits in the buffer copy may also trigger -Emacs save dialog. Prefer using `org-export-with-buffer-copy' macro -when possible. - -When optional key `:to-buffer' is non-nil, copy into BUFFER. - -Optional keys `:drop-visibility', `:drop-narrowing', `:drop-contents', -and `:drop-locals' are passed to `org-export--generate-copy-script'." - (let ((copy-buffer-fun (org-export--generate-copy-script - (current-buffer) - :copy-unreadable 'do-not-check - :drop-visibility drop-visibility - :drop-narrowing drop-narrowing - :drop-contents drop-contents - :drop-locals drop-locals)) - (new-buf (or to-buffer (generate-new-buffer (buffer-name))))) - (with-current-buffer new-buf - (funcall copy-buffer-fun) - (set-buffer-modified-p nil)) +In addition, buffer-local variables are set according to #+BIND: +keywords." + (let ((new-buf (org-element-copy-buffer + :to-buffer to-buffer + :drop-visibility drop-visibility + :drop-narrowing drop-narrowing + :drop-contents drop-contents + :drop-locals drop-locals))) + (let ((bind-variables (org-export--list-bound-variables))) + (with-current-buffer new-buf + (org-export--set-variables bind-variables))) new-buf)) (cl-defmacro org-export-with-buffer-copy ( &rest body @@ -2589,136 +2617,25 @@ and `:drop-locals' are passed to `org-export--generate-copy-script'." drop-locals &allow-other-keys) "Apply BODY in a copy of the current buffer. -The copy preserves local variables, visibility and contents of -the original buffer. Point is at the beginning of the buffer -when BODY is applied. +This macro is like `org-element-with-buffer-copy', passing the same +arguments BODY, TO-BUFFER, DROP-VISIBILITY, DROP-NARROWING, +DROP-CONTENTS, and DROP-LOCALS. -Optional keys can modify what is being copied and the generated buffer -copy. `:to-buffer', `:drop-visibility', `:drop-narrowing', -`:drop-contents', and `:drop-locals' are passed as arguments to -`org-export-copy-buffer'." +In addition, buffer-local variables are set according to #+BIND: +keywords." (declare (debug t)) - (org-with-gensyms (buf-copy) - `(let ((,buf-copy (org-export-copy-buffer - :to-buffer ,to-buffer - :drop-visibility ,drop-visibility - :drop-narrowing ,drop-narrowing - :drop-contents ,drop-contents - :drop-locals ,drop-locals))) - (unwind-protect - (with-current-buffer ,buf-copy - (goto-char (point-min)) - (prog1 - (progn ,@body) - ;; `org-export-copy-buffer' carried the value of - ;; `buffer-file-name' from the original buffer. When not - ;; killed, the new buffer copy may become a target of - ;; `find-file'. Prevent this. - (setq buffer-file-name nil))) - (and (buffer-live-p ,buf-copy) - ;; Kill copy without confirmation. - (progn (with-current-buffer ,buf-copy - (restore-buffer-modified-p nil)) - (unless ,to-buffer - (kill-buffer ,buf-copy)))))))) - -(cl-defun org-export--generate-copy-script (buffer - &key - copy-unreadable - drop-visibility - drop-narrowing - drop-contents - drop-locals) - "Generate a function duplicating BUFFER. - -The copy will preserve local variables, visibility, contents and -narrowing of the original buffer. If a region was active in -BUFFER, contents will be narrowed to that region instead. - -When optional key `:copy-unreadable' is non-nil, do not ensure that all -the copied local variables will be readable in another Emacs session. - -When optional keys `:drop-visibility', `:drop-narrowing', -`:drop-contents', or `:drop-locals' are non-nil, do not preserve -visibility, narrowing, contents, or local variables correspondingly. - -The resulting function can be evaluated at a later time, from -another buffer, effectively cloning the original buffer there. - -The function assumes BUFFER's major mode is `org-mode'." - (with-current-buffer buffer - (let ((str (unless drop-contents (org-with-wide-buffer (buffer-string)))) - (narrowing - (unless drop-narrowing - (if (org-region-active-p) - (list (region-beginning) (region-end)) - (list (point-min) (point-max))))) - (pos (point)) - (varvals - (unless drop-locals - (let ((bound-variables (org-export--list-bound-variables)) - (varvals nil)) - (dolist (entry (buffer-local-variables (buffer-base-buffer))) - (when (consp entry) - (let ((var (car entry)) - (val (cdr entry))) - (and (not (memq var org-export-ignored-local-variables)) - (or (memq var - '(default-directory - ;; Required to convert file - ;; links in the #+INCLUDEd - ;; files. See - ;; `org-export--prepare-file-contents'. - buffer-file-name - buffer-file-coding-system - ;; Needed to preserve folding state - char-property-alias-alist)) - (assq var bound-variables) - (string-match "^\\(org-\\|orgtbl-\\)" - (symbol-name var))) - ;; Skip unreadable values, as they cannot be - ;; sent to external process. - (or copy-unreadable (not val) - (ignore-errors (read (format "%S" val)))) - (push (cons var val) varvals))))) - varvals))) - (ols - (unless drop-visibility - (let (ov-set) - (dolist (ov (overlays-in (point-min) (point-max))) - (let ((invis-prop (overlay-get ov 'invisible))) - (when invis-prop - (push (list (overlay-start ov) (overlay-end ov) - invis-prop) - ov-set)))) - ov-set)))) - (lambda () - (let ((inhibit-modification-hooks t)) - ;; Set major mode. Ignore `org-mode-hook' and other hooks as - ;; they have been run already in BUFFER. - (unless (eq major-mode 'org-mode) - (delay-mode-hooks - (let ((org-inhibit-startup t)) (org-mode)))) - ;; Copy specific buffer local variables and variables set - ;; through BIND keywords. - (pcase-dolist (`(,var . ,val) varvals) - (set (make-local-variable var) val)) - ;; Whole buffer contents when requested. - (when str (erase-buffer) (insert str)) - ;; Make org-element-cache not complain about changed buffer - ;; state. - (org-element-cache-reset nil 'no-persistence) - ;; Narrowing. - (when narrowing - (apply #'narrow-to-region narrowing)) - ;; Current position of point. - (goto-char pos) - ;; Overlays with invisible property. - (pcase-dolist (`(,start ,end ,invis) ols) - (overlay-put (make-overlay start end) 'invisible invis)) - ;; Never write the buffer copy to disk, despite - ;; `buffer-file-name' not being nil. - (setq write-contents-functions (list (lambda (&rest _) t)))))))) + ;; Drop keyword arguments from BODY. + (while (keywordp (car body)) (pop body) (pop body)) + (org-with-gensyms (bind-variables) + `(let ((,bind-variables (org-export--list-bound-variables))) + (org-element-with-buffer-copy + :to-buffer ,to-buffer + :drop-visibility ,drop-visibility + :drop-narrowing ,drop-narrowing + :drop-contents ,drop-contents + :drop-locals ,drop-locals + (org-export--set-variables ,bind-variables) + ,@body)))) (defun org-export--delete-comment-trees () "Delete commented trees and commented inlinetasks in the buffer. @@ -2730,8 +2647,8 @@ Narrowing, if any, is ignored." (while (re-search-forward regexp nil t) (let ((element (org-element-at-point))) (when (org-element-property :commentedp element) - (delete-region (org-element-property :begin element) - (org-element-property :end element)))))))) + (delete-region (org-element-begin element) + (org-element-end element)))))))) (defun org-export--prune-tree (data info) "Prune non exportable elements from DATA. @@ -2755,7 +2672,13 @@ from tree." (let ((type (org-element-type data))) (if (org-export--skip-p data info selected excluded) (if (memq type '(table-cell table-row)) (push data ignore) - (org-element-extract-element data)) + (if-let* ((keep-spaces (org-export--keep-spaces data info))) + ;; Keep spaces in place of removed + ;; element, if necessary. + ;; Example: "Foo.[10%] Bar" would become + ;; "Foo.Bar" if we do not keep spaces. + (org-element-set data keep-spaces) + (org-element-extract data))) (if (and (eq type 'headline) (eq (plist-get info :with-archived-trees) 'headline) @@ -2770,26 +2693,26 @@ from tree." org-element-secondary-value-alist))) (mapc walk-data (org-element-property p data)))))))) (definitions - ;; Collect definitions before possibly pruning them so as - ;; to avoid parsing them again if they are required. - (org-element-map data '(footnote-definition footnote-reference) - (lambda (f) - (cond - ((eq 'footnote-definition (org-element-type f)) f) - ((and (eq 'inline (org-element-property :type f)) - (org-element-property :label f)) - f) - (t nil)))))) + ;; Collect definitions before possibly pruning them so as + ;; to avoid parsing them again if they are required. + (org-element-map data '(footnote-definition footnote-reference) + (lambda (f) + (cond + ((org-element-type-p f 'footnote-definition) f) + ((and (eq 'inline (org-element-property :type f)) + (org-element-property :label f)) + f) + (t nil)))))) ;; If a select tag is active, also ignore the section before the ;; first headline, if any. (when selected (let ((first-element (car (org-element-contents data)))) - (when (eq (org-element-type first-element) 'section) - (org-element-extract-element first-element)))) + (when (org-element-type-p first-element 'section) + (org-element-extract first-element)))) ;; Prune tree and communication channel. (funcall walk-data data) (dolist (entry (append - ;; Priority is given to back-end specific options. + ;; Priority is given to backend specific options. (org-export-get-all-options (plist-get info :back-end)) org-export-options-alist)) (when (eq (nth 4 entry) 'parse) @@ -2818,7 +2741,7 @@ a list of footnote definitions or in the widened buffer." (let ((known-definitions (org-element-map tree '(footnote-reference footnote-definition) (lambda (f) - (and (or (eq (org-element-type f) 'footnote-definition) + (and (or (org-element-type-p f 'footnote-definition) (eq (org-element-property :type f) 'inline)) (org-element-property :label f))))) ) ;; seen @@ -2834,27 +2757,27 @@ a list of footnote definitions or in the widened buffer." (while undefined (let* ((label (pop undefined)) (definition - (cond - ((cl-some - (lambda (d) (and (equal (org-element-property :label d) label) - d)) - definitions)) - ((pcase (org-footnote-get-definition label) - (`(,_ ,beg . ,_) - (org-with-wide-buffer - (goto-char beg) - (let ((datum (org-element-context))) - (if (eq (org-element-type datum) 'footnote-reference) - datum - ;; Parse definition with contents. - (save-restriction - (narrow-to-region - (org-element-property :begin datum) - (org-element-property :end datum)) - (org-element-map (org-element-parse-buffer) - 'footnote-definition #'identity nil t)))))) - (_ nil))) - (t (user-error "Definition not found for footnote %s" label))))) + (cond + ((cl-some + (lambda (d) (and (equal (org-element-property :label d) label) + d)) + definitions)) + ((pcase (org-footnote-get-definition label) + (`(,_ ,beg . ,_) + (org-with-wide-buffer + (goto-char beg) + (let ((datum (org-element-context))) + (if (org-element-type-p datum 'footnote-reference) + datum + ;; Parse definition with contents. + (save-restriction + (narrow-to-region + (org-element-begin datum) + (org-element-end datum)) + (org-element-map (org-element-parse-buffer nil nil 'defer) + 'footnote-definition #'identity nil t)))))) + (_ nil))) + (t (user-error "Definition not found for footnote %s" label))))) (push label defined) (push definition missing-definitions) ;; Look for footnote references within DEFINITION, since @@ -2867,7 +2790,7 @@ a list of footnote definitions or in the widened buffer." ;; definitions. Make sure those are changed into real footnote ;; definitions. (mapcar (lambda (d) - (if (eq (org-element-type d) 'footnote-definition) d + (if (org-element-type-p d 'footnote-definition) d (let ((label (org-element-property :label d))) (apply #'org-element-create 'footnote-definition `(:label ,label :post-blank 1) @@ -2893,13 +2816,13 @@ containing their first reference." (lambda (h) (and (org-element-property :footnote-section-p h) h)) nil t))) (and footnote-section - (apply #'org-element-adopt-elements + (apply #'org-element-adopt footnote-section (nreverse definitions))))) ;; If there should be a footnote section, create one containing all ;; the definitions at the end of the tree. (org-footnote-section - (org-element-adopt-elements + (org-element-adopt tree (org-element-create 'headline (list :footnote-section-p t @@ -2925,14 +2848,14 @@ containing their first reference." (unless (member label seen) (push label seen) (let ((definition - (cl-some - (lambda (d) - (and (equal (org-element-property :label d) - label) - d)) - definitions))) - (org-element-adopt-elements - (org-element-lineage reference '(section)) + (cl-some + (lambda (d) + (and (equal (org-element-property :label d) + label) + d)) + definitions))) + (org-element-adopt + (org-element-lineage reference 'section) definition) ;; Also insert definitions for nested ;; references, if any. @@ -2950,7 +2873,7 @@ returned by the function." (lambda (datum) (let* ((type (org-element-type datum)) (post-blank - (pcase (org-element-property :post-blank datum) + (pcase (org-element-post-blank datum) (`nil nil) (n (make-string n (if (eq type 'latex-environment) ?\n ?\s))))) (new @@ -2991,20 +2914,35 @@ returned by the function." post-blank))))))))) (when new ;; Splice NEW at DATUM location in parse tree. - (dolist (e new (org-element-extract-element datum)) + (dolist (e new (org-element-extract datum)) (unless (equal e "") (org-element-insert-before e datum)))))) info nil nil t) ;; Return modified parse tree. data) +(defun org-export--expand-links (tree info) + "Modify TREE, expanding link paths according to `:expand-links' in INFO." + (when (plist-get info :expand-links) + (org-element-map tree 'link + (lambda (link) + (when (equal "file" (org-element-property :type link)) + (org-element-put-property + link :path + (substitute-env-in-file-name + (org-element-property :path link))))) + info nil nil 'with-affiliated))) + ;;;###autoload (defun org-export-as (backend &optional subtreep visible-only body-only ext-plist) "Transcode current Org buffer into BACKEND code. -BACKEND is either an export back-end, as returned by, e.g., +See info node `(org)Advanced Export Configuration' for the details of +the transcoding process. + +BACKEND is either an export backend, as returned by, e.g., `org-export-create-backend', or a symbol referring to -a registered back-end. +a registered backend. If narrowing is active in the current buffer, only transcode its narrowed part. @@ -3052,102 +2990,19 @@ Return code as a string." (info (org-combine-plists (org-export--get-export-attributes backend subtreep visible-only body-only) - (org-export--get-buffer-attributes))) - (parsed-keywords - (delq nil - (mapcar (lambda (o) (and (eq (nth 4 o) 'parse) (nth 1 o))) - (append (org-export-get-all-options backend) - org-export-options-alist)))) - tree modified-tick) + (org-export--get-buffer-attributes)))) ;; Update communication channel and get parse tree. Buffer ;; isn't parsed directly. Instead, all buffer modifications ;; and consequent parsing are undertaken in a temporary copy. (org-export-with-buffer-copy (font-lock-mode -1) - ;; Run first hook with current back-end's name as argument. - (run-hook-with-args 'org-export-before-processing-hook - (org-export-backend-name backend)) - (org-export-expand-include-keyword) - (org-export--delete-comment-trees) - (org-macro-initialize-templates org-export-global-macros) - (org-macro-replace-all org-macro-templates parsed-keywords) - ;; Refresh buffer properties and radio targets after previous - ;; potentially invasive changes. - (org-set-regexps-and-options) - (org-update-radio-target-regexp) - (setq modified-tick (buffer-chars-modified-tick)) - ;; Possibly execute Babel code. Re-run a macro expansion - ;; specifically for {{{results}}} since inline source blocks - ;; may have generated some more. Refresh buffer properties - ;; and radio targets another time. - (when org-export-use-babel - (org-babel-exp-process-buffer) - (org-macro-replace-all '(("results" . "$1")) parsed-keywords) - (unless (eq modified-tick (buffer-chars-modified-tick)) - (org-set-regexps-and-options) - (org-update-radio-target-regexp)) - (setq modified-tick (buffer-chars-modified-tick))) - ;; Run last hook with current back-end's name as argument. - ;; Update buffer properties and radio targets one last time - ;; before parsing. - (goto-char (point-min)) - (save-excursion - (run-hook-with-args 'org-export-before-parsing-hook - (org-export-backend-name backend))) - (unless (eq modified-tick (buffer-chars-modified-tick)) - (org-set-regexps-and-options) - (org-update-radio-target-regexp)) - (setq modified-tick (buffer-chars-modified-tick)) - ;; Update communication channel with environment. - (setq info - (org-combine-plists - info (org-export-get-environment backend subtreep ext-plist))) - ;; Pre-process citations environment, i.e. install - ;; bibliography list, and citation processor in INFO. - (org-cite-store-bibliography info) - (org-cite-store-export-processor info) - ;; De-activate uninterpreted data from parsed keywords. - (dolist (entry (append (org-export-get-all-options backend) - org-export-options-alist)) - (pcase entry - (`(,p ,_ ,_ ,_ parse) - (let ((value (plist-get info p))) - (plist-put info - p - (org-export--remove-uninterpreted-data value info)))) - (_ nil))) - ;; Install user's and developer's filters. - (setq info (org-export-install-filters info)) - ;; Call options filters and update export options. We do not - ;; use `org-export-filter-apply-functions' here since the - ;; arity of such filters is different. - (let ((backend-name (org-export-backend-name backend))) - (dolist (filter (plist-get info :filter-options)) - (let ((result (funcall filter info backend-name))) - (when result (setq info result))))) - ;; Parse buffer. - (setq tree (org-element-parse-buffer nil visible-only)) - ;; Prune tree from non-exported elements and transform - ;; uninterpreted elements or objects in both parse tree and - ;; communication channel. - (org-export--prune-tree tree info) - (org-export--remove-uninterpreted-data tree info) - ;; Call parse tree filters. - (setq tree - (org-export-filter-apply-functions - (plist-get info :filter-parse-tree) tree info)) - ;; Now tree is complete, compute its properties and add them - ;; to communication channel. - (setq info (org-export--collect-tree-properties tree info)) - ;; Process citations and bibliography. Replace each citation - ;; and "print_bibliography" keyword in the parse tree with - ;; the output of the selected citation export processor. - (org-cite-process-citations info) - (org-cite-process-bibliography info) + (setq info (org-export--annotate-info + backend info subtreep visible-only ext-plist)) ;; Eventually transcode TREE. Wrap the resulting string into ;; a template. (let* ((body (org-element-normalize-string - (or (org-export-data tree info) ""))) + (or (org-export-data (plist-get info :parse-tree) info) + ""))) (inner-template (cdr (assq 'inner-template (plist-get info :translate-alist)))) (full-body (org-export-filter-apply-functions @@ -3161,7 +3016,8 @@ Return code as a string." (if (or (not (functionp template)) body-only) full-body (funcall template full-body info)))) ;; Call citation export finalizer. - (setq output (org-cite-finalize-export output info)) + (when (plist-get info :with-cite-processors) + (setq output (org-cite-finalize-export output info))) ;; Remove all text properties since they cannot be ;; retrieved from an external process. Finally call ;; final-output filter and return result. @@ -3170,13 +3026,121 @@ Return code as a string." (plist-get info :filter-final-output) output info))))))))) +(defun org-export--annotate-info (backend info &optional subtreep visible-only ext-plist) + "Annotate the INFO plist according to the BACKEND. + +This is run in the context of the current buffer. + +When optional argument SUBTREEP is non-nil, transcode the +sub-tree at point, extracting information from the headline +properties first. + +When optional argument VISIBLE-ONLY is non-nil, don't process the +contents of hidden elements. + +Optional argument EXT-PLIST, when provided, is a property list +with external parameters overriding Org default settings, but +still inferior to file-local settings." + (let ((parsed-keywords + (delq nil + (mapcar (lambda (o) (and (eq (nth 4 o) 'parse) (nth 1 o))) + (append (org-export-get-all-options backend) + org-export-options-alist)))) + tree modified-tick) + ;; Run first hook with current backend's name as argument. + (run-hook-with-args 'org-export-before-processing-hook + (org-export-backend-name backend)) + (org-export-expand-include-keyword nil nil nil nil (plist-get info :expand-links)) + (org-export--delete-comment-trees) + (org-macro-initialize-templates org-export-global-macros) + (org-macro-replace-all org-macro-templates parsed-keywords) + ;; Refresh buffer properties and radio targets after previous + ;; potentially invasive changes. + (org-set-regexps-and-options) + (org-update-radio-target-regexp) + (setq modified-tick (buffer-chars-modified-tick)) + ;; Possibly execute Babel code. Re-run a macro expansion + ;; specifically for {{{results}}} since inline source blocks + ;; may have generated some more. Refresh buffer properties + ;; and radio targets another time. + (when org-export-use-babel + (org-babel-exp-process-buffer) + (org-macro-replace-all '(("results" . "$1")) parsed-keywords) + (unless (eq modified-tick (buffer-chars-modified-tick)) + (org-set-regexps-and-options) + (org-update-radio-target-regexp)) + (setq modified-tick (buffer-chars-modified-tick))) + ;; Run last hook with current backend's name as argument. + ;; Update buffer properties and radio targets one last time + ;; before parsing. + (goto-char (point-min)) + (save-excursion + (run-hook-with-args 'org-export-before-parsing-hook + (org-export-backend-name backend))) + (unless (eq modified-tick (buffer-chars-modified-tick)) + (org-set-regexps-and-options) + (org-update-radio-target-regexp)) + (setq modified-tick (buffer-chars-modified-tick)) + ;; Update communication channel with environment. + (setq info + (org-combine-plists + info (org-export-get-environment backend subtreep ext-plist))) + ;; Pre-process citations environment, i.e. install + ;; bibliography list, and citation processor in INFO. + (when (plist-get info :with-cite-processors) + (org-cite-store-bibliography info) + (org-cite-store-export-processor info)) + ;; De-activate uninterpreted data from parsed keywords. + (dolist (entry (append (org-export-get-all-options backend) + org-export-options-alist)) + (pcase entry + (`(,p ,_ ,_ ,_ parse) + (let ((value (plist-get info p))) + (plist-put info + p + (org-export--remove-uninterpreted-data value info)))) + (_ nil))) + ;; Install user's and developer's filters. + (setq info (org-export-install-filters info)) + ;; Call options filters and update export options. We do not + ;; use `org-export-filter-apply-functions' here since the + ;; arity of such filters is different. + (let ((backend-name (org-export-backend-name backend))) + (dolist (filter (plist-get info :filter-options)) + (let ((result (funcall filter info backend-name))) + (when result (setq info result))))) + ;; Parse buffer. + (setq tree (org-element-parse-buffer nil visible-only 'defer)) + ;; Prune tree from non-exported elements and transform + ;; uninterpreted elements or objects in both parse tree and + ;; communication channel. + (org-export--prune-tree tree info) + (org-export--remove-uninterpreted-data tree info) + ;; Expand environment variables in link paths. + (org-export--expand-links tree info) + ;; Call parse tree filters. + (setq tree + (org-export-filter-apply-functions + (plist-get info :filter-parse-tree) tree info)) + ;; Now tree is complete, compute its properties and add them + ;; to communication channel. This is responsible for setting + ;; :parse-tree to TREE. + (setq info (org-export--collect-tree-properties tree info)) + ;; Process citations and bibliography. Replace each citation + ;; and "print_bibliography" keyword in the parse tree with + ;; the output of the selected citation export processor. + (when (plist-get info :with-cite-processors) + (org-cite-process-citations info) + (org-cite-process-bibliography info)) + info)) + ;;;###autoload (defun org-export-string-as (string backend &optional body-only ext-plist) "Transcode STRING into BACKEND code. -BACKEND is either an export back-end, as returned by, e.g., +BACKEND is either an export backend, as returned by, e.g., `org-export-create-backend', or a symbol referring to -a registered back-end. +a registered backend. When optional argument BODY-ONLY is non-nil, only return body code, without preamble nor postamble. @@ -3194,9 +3158,9 @@ Return code as a string." ;;;###autoload (defun org-export-replace-region-by (backend) "Replace the active region by its export to BACKEND. -BACKEND is either an export back-end, as returned by, e.g., +BACKEND is either an export backend, as returned by, e.g., `org-export-create-backend', or a symbol referring to -a registered back-end." +a registered backend." (unless (org-region-active-p) (user-error "No active region to replace")) (insert (org-export-string-as @@ -3207,7 +3171,7 @@ a registered back-end." "Insert all export keywords with default values at beginning of line. BACKEND is a symbol referring to the name of a registered export -back-end, for which specific export options should be added to +backend, for which specific export options should be added to the template, or `default' for default template. When it is nil, the user will be prompted for a category. @@ -3247,7 +3211,7 @@ locally for the subtree through node properties." (option (unless (assoc option options) (push (cons option (eval (nth 3 entry) t)) options)))))) ;; Move to an appropriate location in order to insert options. - (unless subtreep (beginning-of-line)) + (unless subtreep (forward-line 0)) ;; First (multiple) OPTIONS lines. Never go past fill-column. (when options (let ((items @@ -3267,12 +3231,12 @@ locally for the subtree through node properties." (cl-incf width (1+ (length item)))))) (insert "\n"))))) ;; Then the rest of keywords, in the order specified in either - ;; `org-export-options-alist' or respective export back-ends. + ;; `org-export-options-alist' or respective export backends. (dolist (key (nreverse keywords)) (let ((val (cond ((equal (car key) "DATE") (or (cdr key) (with-temp-buffer - (org-insert-time-stamp nil)))) + (org-insert-timestamp nil)))) ((equal (car key) "TITLE") (or (let ((visited-file (buffer-file-name (buffer-base-buffer)))) @@ -3287,18 +3251,29 @@ locally for the subtree through node properties." (downcase (car key)) (if (org-string-nw-p val) (format " %s" val) "")))))))) -(defun org-export-expand-include-keyword (&optional included dir footnotes) +(defun org-export-expand-include-keyword (&optional included dir footnotes includer-file expand-env) "Expand every include keyword in buffer. + Optional argument INCLUDED is a list of included file names along with their line restriction, when appropriate. It is used to -avoid infinite recursion. Optional argument DIR is the current -working directory. It is used to properly resolve relative -paths. Optional argument FOOTNOTES is a hash-table used for -storing and resolving footnotes. It is created automatically." - (let ((includer-file (buffer-file-name (buffer-base-buffer))) +avoid infinite recursion. + +Optional argument DIR is the current working directory. It is used to +properly resolve relative paths. + +Optional argument FOOTNOTES is a hash-table used for +storing and resolving footnotes. It is created automatically. + +Optional argument INCLUDER-FILE is the file path corresponding to the +buffer contents being included. It is used when current buffer does +not have `buffer-file-name' assigned. + +When optional argument EXPAND-ENV is non-nil, expand environment +variables in include file names." + (let ((includer-file (or includer-file + (buffer-file-name (buffer-base-buffer)))) (case-fold-search t) (file-prefix (make-hash-table :test #'equal)) - (current-prefix 0) (footnotes (or footnotes (make-hash-table :test #'equal))) (include-re "^[ \t]*#\\+INCLUDE:")) ;; If :minlevel is not set the text-property @@ -3314,128 +3289,195 @@ storing and resolving footnotes. It is created automatically." (goto-char (point-min)) (while (re-search-forward include-re nil t) (unless (org-in-commented-heading-p) - (let ((element (save-match-data (org-element-at-point)))) - (when (eq (org-element-type element) 'keyword) - (beginning-of-line) - ;; Extract arguments from keyword's value. - (let* ((value (org-element-property :value element)) - (ind (org-current-text-indentation)) - location - (coding-system-for-read - (or (and (string-match ":coding +\\(\\S-+\\)>" value) - (prog1 (intern (match-string 1 value)) - (setq value (replace-match "" nil nil value)))) - coding-system-for-read)) - (file - (and (string-match "^\\(\".+?\"\\|\\S-+\\)\\(?:\\s-+\\|$\\)" - value) - (prog1 - (save-match-data - (let ((matched (match-string 1 value)) - stripped) - (when (string-match "\\(::\\(.*?\\)\\)\"?\\'" - matched) - (setq location (match-string 2 matched)) - (setq matched - (replace-match "" nil nil matched 1))) - (setq stripped (org-strip-quotes matched)) - (if (org-url-p stripped) - stripped - (expand-file-name stripped dir)))) - (setq value (replace-match "" nil nil value))))) - (only-contents - (and (string-match ":only-contents *\\([^: \r\t\n]\\S-*\\)?" - value) - (prog1 (org-not-nil (match-string 1 value)) - (setq value (replace-match "" nil nil value))))) - (lines - (and (string-match - ":lines +\"\\([0-9]*-[0-9]*\\)\"" - value) - (prog1 (match-string 1 value) - (setq value (replace-match "" nil nil value))))) - (env (cond - ((string-match "\\" value) 'literal) - ((string-match "\\" value) - (match-string 1 value)))) - ;; Remove keyword. - (delete-region (point) (line-beginning-position 2)) - (cond - ((not file) nil) - ((and (not (org-url-p file)) (not (file-readable-p file))) - (error "Cannot include file %s" file)) - ;; Check if files has already been parsed. Look after - ;; inclusion lines too, as different parts of the same - ;; file can be included too. - ((member (list file lines) included) - (error "Recursive file inclusion: %s" file)) - (t - (cond - ((eq env 'literal) - (insert - (let ((ind-str (make-string ind ?\s)) - (arg-str (if (stringp args) (format " %s" args) "")) - (contents - (org-escape-code-in-string - (org-export--prepare-file-contents file lines)))) - (format "%s#+BEGIN_%s%s\n%s%s#+END_%s\n" - ind-str block arg-str contents ind-str block)))) - ((stringp block) - (insert - (let ((ind-str (make-string ind ?\s)) - (contents - (org-export--prepare-file-contents file lines))) - (format "%s#+BEGIN_%s\n%s%s#+END_%s\n" - ind-str block contents ind-str block)))) - (t - (insert - (with-temp-buffer - (let ((org-inhibit-startup t) - (lines - (if location - (org-export--inclusion-absolute-lines - file location only-contents lines) - lines))) - (org-mode) - (insert - (org-export--prepare-file-contents - file lines ind minlevel - (or (gethash file file-prefix) - (puthash file - (cl-incf current-prefix) - file-prefix)) - footnotes - includer-file))) - (org-export-expand-include-keyword - (cons (list file lines) included) - (unless (org-url-p file) - (file-name-directory file)) - footnotes) - (buffer-string))))) - ;; Expand footnotes after all files have been - ;; included. Footnotes are stored at end of buffer. - (unless included - (org-with-wide-buffer - (goto-char (point-max)) - (maphash (lambda (k v) - (insert (format "\n[fn:%s] %s\n" k v))) - footnotes)))))))))))) + (let ((element (org-element-at-point))) + (when (org-element-type-p element 'keyword) + (forward-line 0) + ;; Extract arguments from keyword's value. + (let* ((value (org-element-property :value element)) + (parameters (org-export-parse-include-value value dir)) + (file (if expand-env + (substitute-env-in-file-name + (plist-get parameters :file)) + (plist-get parameters :file)))) + ;; Remove keyword. + (delete-region (point) (line-beginning-position 2)) + (cond + ((not file)) ; Do nothing. + ((and (not (org-url-p file)) + (not (file-readable-p file))) + (error "Cannot include file %s" file)) + ;; Check if files has already been parsed. Look after + ;; inclusion lines too, as different parts of the same + ;; file can be included too. + ((member (list file (plist-get parameters :lines)) included) + (error "Recursive file inclusion: %s" file)) + (t + (org-export--blindly-expand-include + parameters + :includer-file includer-file + :file-prefix file-prefix + :footnotes footnotes + :already-included included + :expand-env expand-env) + ;; Expand footnotes after all files have been + ;; included. Footnotes are stored at end of buffer. + (unless included + (org-with-wide-buffer + (goto-char (point-max)) + (maphash (lambda (k v) + (insert (format "\n[fn:%s] %s\n" k v))) + footnotes)))))))))))) + +(defun org-export-parse-include-value (value &optional dir) + "Extract the various parameters from #+include: VALUE. + +More specifically, this extracts the following parameters to a +plist: :file, :coding-system, :location, :only-contents, :lines, +:env, :minlevel, :args, and :block. + +The :file parameter is expanded relative to DIR. + +The :file, :block, and :args parameters are extracted +positionally, while the remaining parameters are extracted as +plist-style keywords. + +Any remaining unmatched content is passed through +`org-babel-parse-header-arguments' (without evaluation) and +provided as the :unmatched parameter." + (let* (location + (coding-system + (and (string-match ":coding +\\(\\S-+\\)>" value) + (prog1 (intern (match-string 1 value)) + (setq value (replace-match "" nil nil value))))) + (file + (and (string-match "^\\(\".+?\"\\|\\S-+\\)\\(?:\\s-+\\|$\\)" value) + (let ((matched (match-string 1 value)) stripped) + (setq value (replace-match "" nil nil value)) + (when (string-match "\\(::\\(.*?\\)\\)\"?\\'" + matched) + (setq location (match-string 2 matched)) + (setq matched + (replace-match "" nil nil matched 1))) + (setq stripped (org-strip-quotes matched)) + (if (org-url-p stripped) + stripped + (expand-file-name stripped dir))))) + (only-contents + (and (string-match ":only-contents *\\([^: \r\t\n]\\S-*\\)?" + value) + (prog1 (org-not-nil (match-string 1 value)) + (setq value (replace-match "" nil nil value))))) + (lines + (and (string-match + ":lines +\"\\([0-9]*-[0-9]*\\)\"" + value) + (prog1 (match-string 1 value) + (setq value (replace-match "" nil nil value))))) + (env (cond + ((string-match "\\" value) 'literal) + ((string-match "\\" value)) + (or (= (match-beginning 0) 0) + (not (= ?: (aref value (1- (match-beginning 0)))))) + (prog1 (match-string 1 value) + (setq value (replace-match "" nil nil value)))))) + (list :file file + :coding-system coding-system + :location location + :only-contents only-contents + :lines lines + :env env + :minlevel minlevel + :args args + :block block + :unmatched (org-babel-parse-header-arguments value t)))) + +(cl-defun org-export--blindly-expand-include + (parameters + &key includer-file file-prefix footnotes already-included expand-env) + "Unconditionally include reference defined by PARAMETERS in the buffer. +PARAMETERS is a plist of the form returned by `org-export-parse-include-value'. + +INCLUDER-FILE is a path to the file where the include keyword is +being expanded. FILE-PREFIX is a hash-table of file and +prefixes, which can be provided to ensure consistent prefixing. +FOOTNOTES is a hash-table for storing and resolving footnotes, +which when provided allows footnotes to be handled appropriately. +ALREADY-INCLUDED is a list of included names along with their +line restriction which prevents recursion. EXPAND-ENV is a flag to +expand environment variables for #+INCLUDE keywords in the included +file." + (let* ((coding-system-for-read + (or (plist-get parameters :coding-system) + coding-system-for-read)) + (file (plist-get parameters :file)) + (lines (plist-get parameters :lines)) + (args (plist-get parameters :args)) + (block (plist-get parameters :block)) + (ind (org-current-text-indentation))) + (cond + ((eq (plist-get parameters :env) 'literal) + (insert + (let ((ind-str (make-string ind ?\s)) + (arg-str (if (stringp args) (format " %s" args) "")) + (contents + (org-escape-code-in-string + (org-export--prepare-file-contents file lines)))) + (format "%s#+BEGIN_%s%s\n%s%s#+END_%s\n" + ind-str block arg-str contents ind-str block)))) + ((stringp block) + (insert + (let ((ind-str (make-string ind ?\s)) + (contents + (org-export--prepare-file-contents file lines))) + (format "%s#+BEGIN_%s\n%s%s#+END_%s\n" + ind-str block contents ind-str block)))) + (t + (insert + (with-temp-buffer + (let ((org-inhibit-startup t) + (lines + (if-let* ((location (plist-get parameters :location))) + (org-export--inclusion-absolute-lines + file location + (plist-get parameters :only-contents) + lines) + lines))) + (org-mode) + (insert + (org-export--prepare-file-contents + file lines ind (plist-get parameters :minlevel) + (and file-prefix + (or (gethash file file-prefix) + (puthash file + (hash-table-count file-prefix) + file-prefix))) + footnotes includer-file))) + (org-export-expand-include-keyword + (cons (list file lines) already-included) + (unless (org-url-p file) + (file-name-directory file)) + footnotes includer-file expand-env) + (buffer-string))))))) (defun org-export--inclusion-absolute-lines (file location only-contents lines) "Resolve absolute lines for an included file with file-link. @@ -3460,12 +3502,12 @@ Return a string of lines to be included in the format expected by (error "%s for %s::%s" (error-message-string err) file location))) (let* ((element (org-element-at-point)) (contents-begin - (and only-contents (org-element-property :contents-begin element)))) + (and only-contents (org-element-contents-begin element)))) (narrow-to-region - (or contents-begin (org-element-property :begin element)) + (or contents-begin (org-element-begin element)) (org-element-property (if contents-begin :contents-end :end) element)) (when (and only-contents - (memq (org-element-type element) '(headline inlinetask))) + (org-element-type-p element '(headline inlinetask))) ;; Skip planning line and property-drawer. (goto-char (point-min)) (when (looking-at-p org-planning-line-re) (forward-line)) @@ -3474,7 +3516,7 @@ Return a string of lines to be included in the format expected by (narrow-to-region (point) (point-max)))) (when lines (org-skip-whitespace) - (beginning-of-line) + (forward-line 0) (let* ((lines (split-string lines "-")) (lbeg (string-to-number (car lines))) (lend (string-to-number (cadr lines))) @@ -3512,18 +3554,18 @@ Move point after the link." (if (or (not (string= "file" (org-element-property :type link))) (file-remote-p path) (file-name-absolute-p path)) - (goto-char (org-element-property :end link)) + (goto-char (org-element-end link)) (let ((new-path (file-relative-name (expand-file-name path file-dir) includer-dir)) (new-link (org-element-copy link))) (org-element-put-property new-link :path new-path) - (when (org-element-property :contents-begin link) - (org-element-adopt-elements new-link + (when (org-element-contents-begin link) + (org-element-adopt new-link (buffer-substring - (org-element-property :contents-begin link) - (org-element-property :contents-end link)))) - (delete-region (org-element-property :begin link) - (org-element-property :end link)) + (org-element-contents-begin link) + (org-element-contents-end link)))) + (delete-region (org-element-begin link) + (org-element-end link)) (insert (org-element-interpret-data new-link)))))) (defun org-export--prepare-file-contents @@ -3582,18 +3624,18 @@ is to happen." (while (re-search-forward org-link-any-re nil t) (let ((link (save-excursion (forward-char -1) - (save-match-data (org-element-context))))) - (when (eq 'link (org-element-type link)) + (org-element-context)))) + (when (org-element-type-p link 'link) ;; Look for file links within link's description. ;; Org doesn't support such construct, but ;; `org-export-insert-image-links' may activate ;; them. (let ((contents-begin - (org-element-property :contents-begin link)) - (begin (org-element-property :begin link))) + (org-element-contents-begin link)) + (begin (org-element-begin link))) (when contents-begin (save-excursion - (goto-char (org-element-property :contents-end link)) + (goto-char (org-element-contents-end link)) (while (re-search-backward regexp contents-begin t) (save-match-data (org-export--update-included-link @@ -3609,7 +3651,7 @@ is to happen." ;; override blank lines in included file. (goto-char (point-min)) (org-skip-whitespace) - (beginning-of-line) + (forward-line 0) (delete-region (point-min) (point)) (goto-char (point-max)) (skip-chars-backward " \r\t\n") @@ -3625,8 +3667,8 @@ is to happen." (while (not (or (eobp) (looking-at org-outline-regexp-bol))) ;; Do not move footnote definitions out of column 0. (unless (and (looking-at org-footnote-definition-re) - (eq (org-element-type (org-element-at-point)) - 'footnote-definition)) + (org-element-type-p + (org-element-at-point) 'footnote-definition)) (insert ind-str)) (forward-line)))) ;; When MINLEVEL is specified, compute minimal level for headlines @@ -3664,7 +3706,7 @@ is to happen." (lambda (f old new) ;; Replace OLD label with NEW in footnote F. (save-excursion - (goto-char (+ (org-element-property :begin f) 4)) + (goto-char (+ (org-element-begin f) 4)) (looking-at (regexp-quote old)) (replace-match new)))) (seen-alist)) @@ -3673,8 +3715,8 @@ is to happen." (let ((footnote (save-excursion (backward-char) (org-element-context)))) - (when (memq (org-element-type footnote) - '(footnote-definition footnote-reference)) + (when (org-element-type-p + footnote '(footnote-definition footnote-reference)) (let* ((label (org-element-property :label footnote))) ;; Update the footnote-reference at point and collect ;; the new label, which is only used for footnotes @@ -3709,10 +3751,10 @@ See also `org-export-copy-to-kill-ring'." -;;; Tools For Back-Ends +;;; Tools For Backends ;; ;; A whole set of tools is available to help build new exporters. Any -;; function general enough to have its use across many back-ends +;; function general enough to have its use across many backends ;; should be added here. ;;;; For Affiliated Keywords @@ -3777,23 +3819,24 @@ Caption lines are separated by a white space." (`nil nil) (c (setq caption - (nconc (list " ") - (copy-sequence c) caption))))) - (cdr caption))) + (if caption + (nconc caption (list " ") (copy-sequence c)) + (copy-sequence c)))))) + caption)) -;;;; For Derived Back-ends +;;;; For Derived Backends ;; ;; `org-export-with-backend' is a function allowing to locally use -;; another back-end to transcode some object or element. In a derived -;; back-end, it may be used as a fall-back function once all specific +;; another backend to transcode some object or element. In a derived +;; backend, it may be used as a fall-back function once all specific ;; cases have been treated. (defun org-export-with-backend (backend data &optional contents info) "Call a transcoder from BACKEND on DATA. -BACKEND is an export back-end, as returned by, e.g., +BACKEND is an export backend, as returned by, e.g., `org-export-create-backend', or a symbol referring to -a registered back-end. DATA is an Org element, object, secondary +a registered backend. DATA is an Org element, object, secondary string or string. CONTENTS, when non-nil, is the transcoded contents of DATA element, as a string. INFO, when non-nil, is the communication channel used for export, as a plist." @@ -3811,7 +3854,7 @@ the communication channel used for export, as a plist." :back-end backend :translate-alist all-transcoders :exported-data (make-hash-table :test #'eq :size 401))))) - ;; `:internal-references' are shared across back-ends. + ;; `:internal-references' are shared across backends. (prog1 (if (eq type 'plain-text) (funcall transcoder data new-info) (funcall transcoder data contents new-info)) @@ -3821,20 +3864,20 @@ the communication channel used for export, as a plist." ;;;; For Export Snippets ;; -;; Every export snippet is transmitted to the back-end. Though, the +;; Every export snippet is transmitted to the backend. Though, the ;; latter will only retain one type of export-snippet, ignoring -;; others, based on the former's target back-end. The function -;; `org-export-snippet-backend' returns that back-end for a given +;; others, based on the former's target backend. The function +;; `org-export-snippet-backend' returns that backend for a given ;; export-snippet. (defun org-export-snippet-backend (export-snippet) - "Return EXPORT-SNIPPET targeted back-end as a symbol. + "Return EXPORT-SNIPPET targeted backend as a symbol. Translation, with `org-export-snippet-translation-alist', is applied." - (let ((back-end (org-element-property :back-end export-snippet))) + (let ((backend (org-element-property :back-end export-snippet))) (intern - (or (cdr (assoc back-end org-export-snippet-translation-alist)) - back-end)))) + (or (cdr (assoc backend org-export-snippet-translation-alist)) + backend)))) ;;;; For Footnotes @@ -3845,7 +3888,7 @@ applied." ;; transcoded data. ;; ;; `org-export-footnote-first-reference-p' is a predicate used by some -;; back-ends, when they need to attach the footnote definition only to +;; backends, when they need to attach the footnote definition only to ;; the first occurrence of the corresponding label. ;; ;; `org-export-get-footnote-definition' and @@ -4113,7 +4156,7 @@ inherited from parent headlines and FILETAGS keywords." (let ((current-tag-list (org-element-property :tags element))) (dolist (parent (org-element-lineage element)) (dolist (tag (org-element-property :tags parent)) - (when (and (memq (org-element-type parent) '(headline inlinetask)) + (when (and (org-element-type-p parent '(headline inlinetask)) (not (member tag current-tag-list))) (push tag current-tag-list)))) ;; Add FILETAGS keywords and return results. @@ -4129,15 +4172,10 @@ If optional argument INHERITED is non-nil, the value can be inherited from a parent headline. Return value is a string or nil." - (let ((headline (if (eq (org-element-type datum) 'headline) datum - (org-export-get-parent-headline datum)))) + (let ((headline (if (org-element-type-p datum 'headline) datum + (org-element-lineage datum 'headline)))) (if (not inherited) (org-element-property property datum) - (let ((parent headline)) - (catch 'found - (while parent - (when (plist-member (nth 1 parent) property) - (throw 'found (org-element-property property parent))) - (setq parent (org-element-property :parent parent)))))))) + (org-element-property-inherited property headline 'with-self nil nil t)))) (defun org-export-get-category (blob info) "Return category for element or object BLOB. @@ -4170,8 +4208,9 @@ If no optional title is defined, fall-back to the regular title." BLOB is an element or an object. If BLOB is a headline, non-nil means it is the first sibling in the sub-tree. INFO is a plist used as a communication channel." - (memq (org-element-type (org-export-get-previous-element blob info)) - '(nil section))) + (org-element-type-p + (org-export-get-previous-element blob info) + '(nil section))) (defun org-export-last-sibling-p (datum info) "Non-nil when DATUM is the last sibling in its parent. @@ -4179,7 +4218,7 @@ DATUM is an element or an object. INFO is a plist used as a communication channel." (let ((next (org-export-get-next-element datum info))) (or (not next) - (and (eq 'headline (org-element-type datum)) + (and (org-element-type-p datum 'headline) (> (org-element-property :level datum) (org-element-property :level next)))))) @@ -4205,7 +4244,7 @@ meant to be translated with `org-export-data' or alike." (cond ((not date) nil) ((and fmt (not (cdr date)) - (eq (org-element-type (car date)) 'timestamp)) + (org-element-type-p (car date) 'timestamp)) (org-format-timestamp (car date) fmt)) (t date)))) @@ -4249,11 +4288,11 @@ meant to be translated with `org-export-data' or alike." "Try exporting LINK object with a dedicated function. DESC is its description, as a string, or nil. BACKEND is the -back-end used for export, as a symbol. +backend used for export, as a symbol. Return output as a string, or nil if no protocol handles LINK. -A custom protocol has precedence over regular back-end export. +A custom protocol has precedence over regular backend export. The function ignores links with an implicit type (e.g., \"custom-id\")." (let ((type (org-element-property :type link))) @@ -4307,13 +4346,13 @@ This only applies to links without a description." "Insert image links in DATA. Org syntax does not support nested links. Nevertheless, some -export back-ends support images as descriptions of links. Since +export backends support images as descriptions of links. Since images are really links to image files, we need to make an exception about links nesting. This function recognizes links whose contents are really images and turn them into proper nested links. It is meant to be used -as a parse tree filter in back-ends supporting such constructs. +as a parse tree filter in backends supporting such constructs. DATA is a parse tree. INFO is the current state of the export process, as a plist. @@ -4340,8 +4379,8 @@ Return modified DATA." (string-match-p (cdr rule) path))) (or rules org-export-default-inline-image-rule)) ;; Replace contents with image link. - (org-element-adopt-elements - (org-element-set-contents l nil) + (org-element-adopt + (org-element-set-contents l) (with-temp-buffer (save-excursion (insert contents)) (org-element-link-parser)))))))) @@ -4394,13 +4433,14 @@ A search cell follows the pattern (TYPE . SEARCH) where - NAME or RESULTS affiliated keyword if TYPE is `other'. A search cell is the internal representation of a fuzzy link. It -ignores white spaces and statistics cookies, if applicable." +ignores case, white spaces, and statistics cookies, if applicable." (pcase (org-element-type datum) (`headline - (let ((title (split-string - (replace-regexp-in-string - "\\[[0-9]*\\(?:%\\|/[0-9]*\\)\\]" " " - (org-element-property :raw-value datum))))) + (let ((title (mapcar #'upcase + (split-string + (replace-regexp-in-string + "\\[[0-9]*\\(?:%\\|/[0-9]*\\)\\]" " " + (org-element-property :raw-value datum)))))) (delq nil (list (cons 'headline title) @@ -4408,7 +4448,9 @@ ignores white spaces and statistics cookies, if applicable." (let ((custom-id (org-element-property :custom-id datum))) (and custom-id (cons 'custom-id custom-id))))))) (`target - (list (cons 'target (split-string (org-element-property :value datum))))) + (list (cons 'target + (mapcar #'upcase + (split-string (org-element-property :value datum)))))) ((and (let name (or (org-element-property :name datum) (car (org-element-property :results datum)))) (guard name)) @@ -4419,12 +4461,19 @@ ignores white spaces and statistics cookies, if applicable." "Return search cells associated to string S. S is either the path of a fuzzy link or a search option, i.e., it tries to match either a headline (through custom ID or title), -a target or a named element." +a target or a named element. + +The title match is case-insensitive." (pcase (string-to-char s) - (?* (list (cons 'headline (split-string (substring s 1))))) + (?* (list (cons 'headline (mapcar #'upcase (split-string (substring s 1)))))) (?# (list (cons 'custom-id (substring s 1)))) ((let search (split-string s)) - (list (cons 'target search) (cons 'other search))))) + (cl-remove-duplicates + (list (cons 'target search) + (cons 'other search) + (cons 'target (mapcar #'upcase search)) + (cons 'other (mapcar #'upcase search))) + :test #'equal)))) (defun org-export-match-search-cell-p (datum cells) "Non-nil when DATUM matches search cells CELLS. @@ -4452,7 +4501,7 @@ Return value can be an object or an element: - Otherwise, throw an error. PSEUDO-TYPES are pseudo-elements types, i.e., elements defined -specifically in an export back-end, that could have a name +specifically in an export backend, that could have a name affiliated keyword. Assume LINK type is \"fuzzy\". White spaces are not @@ -4491,7 +4540,7 @@ significant." ;; Matching both a name and a target is not valid, and ;; therefore undefined. (or (cl-some (lambda (datum) - (and (not (eq (org-element-type datum) 'headline)) + (and (not (org-element-type-p datum 'headline)) datum)) matches) (car matches)) @@ -4693,7 +4742,7 @@ matching DATUM before creating a new reference." ;; unique, e.g., there might be duplicate custom ID or ;; two headings with the same title in the file. ;; - ;; As a consequence, before re-using any reference to + ;; As a consequence, before reusing any reference to ;; an element or object, we check that it doesn't refer ;; to a previous element or object. (new (or (cl-some @@ -4741,7 +4790,7 @@ case, return the sequence number of ELEMENT among elements or objects of the same type." ;; Ordinal of a target object refer to the ordinal of the closest ;; table, item, or headline containing the object. - (when (eq (org-element-type element) 'target) + (when (org-element-type-p element 'target) (setq element (org-element-lineage element @@ -4752,7 +4801,7 @@ objects of the same type." ;; Special case 2: An item returns its number as a list. (item (let ((struct (org-element-property :structure element))) (org-list-get-item-number - (org-element-property :begin element) + (org-element-begin element) struct (org-list-prevs-alist struct) (org-list-parents-alist struct)))) @@ -4767,7 +4816,10 @@ objects of the same type." (lambda (el) (let ((cached (org-element-property :org-export--counter el))) (cond - ((eq element el) (1+ counter)) + ((and (eq element el) + (or (not predicate) + (funcall predicate el info))) + (1+ counter)) ;; Use cached result. ((and cached (equal predicate (car cached)) @@ -4789,13 +4841,13 @@ objects of the same type." ;;;; For Raw objects ;; ;; `org-export-raw-string' builds a pseudo-object out of a string -;; that any export back-end returns as-is. +;; that any export backend returns as-is. ;;;###autoload (defun org-export-raw-string (s) "Return a raw object containing string S. A raw string is exported as-is, with no additional processing -from the export back-end." +from the export backend." (unless (stringp s) (error "Wrong raw contents type: %S" s)) (org-element-create 'raw nil s)) @@ -4867,9 +4919,7 @@ reference on that line (string)." ;; to the code proper. (code (replace-regexp-in-string "\n\\'" "" - (if (or org-src-preserve-indentation - (org-element-property :preserve-indent element)) - value + (if (org-src-preserve-indentation-p element) value (org-remove-indentation value)))) ;; Build a regexp matching a loc with a reference. (ref-re (org-src-coderef-regexp (org-src-coderef-format element)))) @@ -5039,8 +5089,7 @@ A table has a header when it contains at least two row groups." cache))))) (defun org-export-table-row-is-special-p (table-row _) - "Non-nil if TABLE-ROW is considered special. -All special rows will be ignored during export." + "Non-nil if TABLE-ROW is considered special." (when (eq (org-element-property :type table-row) 'standard) (let ((first-cell (org-element-contents (car (org-element-contents table-row))))) @@ -5051,7 +5100,7 @@ All special rows will be ignored during export." ;; ... the table contains a special column and the row start ;; with a marking character among, "^", "_", "$" or "!", (and (org-export-table-has-special-column-p - (org-export-get-parent table-row)) + (org-element-parent table-row)) (member first-cell '(("^") ("_") ("$") ("!")))) ;; ... it contains only alignment cookies and empty cells. (let ((special-row-p 'empty)) @@ -5087,7 +5136,7 @@ header." ;; First time a row is queried, populate cache with all the ;; rows from the table. (let ((group 0) row-flag) - (org-element-map (org-export-get-parent table-row) 'table-row + (org-element-map (org-element-parent table-row) 'table-row (lambda (row) (if (eq (org-element-property :type row) 'rule) (setq row-flag nil) @@ -5103,8 +5152,8 @@ INFO is a plist used as the communication channel. Return value is the width given by the last width cookie in the same column as TABLE-CELL, or nil." - (let* ((row (org-export-get-parent table-cell)) - (table (org-export-get-parent row)) + (let* ((row (org-element-parent table-cell)) + (table (org-element-parent row)) (cells (org-element-contents row)) (columns (length cells)) (column (- columns (length (memq table-cell cells)))) @@ -5152,8 +5201,8 @@ column (see `org-table-number-fraction' for more information). Possible values are `left', `right' and `center'." ;; Load `org-table-number-fraction' and `org-table-number-regexp'. (require 'org-table) - (let* ((row (org-export-get-parent table-cell)) - (table (org-export-get-parent row)) + (let* ((row (org-element-parent table-cell)) + (table (org-element-parent row)) (cells (org-element-contents row)) (columns (length cells)) (column (- columns (length (memq table-cell cells)))) @@ -5177,7 +5226,7 @@ Possible values are `left', `right' and `center'." (total-cells 0) cookie-align previous-cell-number-p) - (dolist (row (org-element-contents (org-export-get-parent row))) + (dolist (row (org-element-contents (org-element-parent row))) (cond ;; In a special row, try to find an alignment cookie at ;; COLUMN. @@ -5236,8 +5285,8 @@ Return value is a list of symbols, or nil. Possible values are: row (resp. last row) of the table, ignoring table rules, if any. Returned borders ignore special rows." - (let* ((row (org-export-get-parent table-cell)) - (table (org-export-get-parent-table table-cell)) + (let* ((row (org-element-parent table-cell)) + (table (org-element-lineage table-cell 'table)) borders) ;; Top/above border? TABLE-CELL has a border above when a rule ;; used to demarcate row groups can be found above. Hence, @@ -5316,7 +5365,7 @@ INFO is a plist used as a communication channel." ;; A cell starts a column group either when it is at the beginning ;; of a row (or after the special column, if any) or when it has ;; a left border. - (or (eq (org-element-map (org-export-get-parent table-cell) 'table-cell + (or (eq (org-element-map (org-element-parent table-cell) 'table-cell 'identity info 'first-match) table-cell) (memq 'left (org-export-table-cell-borders table-cell info)))) @@ -5327,7 +5376,7 @@ INFO is a plist used as a communication channel." ;; A cell ends a column group either when it is at the end of a row ;; or when it has a right border. (or (eq (car (last (org-element-contents - (org-export-get-parent table-cell)))) + (org-element-parent table-cell)))) table-cell) (memq 'right (org-export-table-cell-borders table-cell info)))) @@ -5354,7 +5403,7 @@ INFO is a plist used as a communication channel." INFO is a plist used as a communication channel. Always return nil for special rows and rows separators." (and (org-export-table-has-header-p - (org-export-get-parent-table table-row) info) + (org-element-lineage table-row 'table) info) (eql (org-export-table-row-group table-row info) 1))) (defun org-export-table-row-starts-header-p (table-row info) @@ -5370,10 +5419,11 @@ INFO is a plist used as a communication channel." (org-export-table-row-ends-rowgroup-p table-row info))) (defun org-export-table-row-number (table-row info) - "Return TABLE-ROW number. + "Return TABLE-ROW number in the exported table. INFO is a plist used as a communication channel. Return value is zero-indexed and ignores separators. The function returns nil -for special rows and separators." +when TABLE-ROW is a separator or when it is listed in :ignore-list +property of the INFO plist." (when (eq (org-element-property :type table-row) 'standard) (let* ((cache (or (plist-get info :table-row-number-cache) (let ((table (make-hash-table :test #'eq))) @@ -5384,7 +5434,7 @@ for special rows and separators." ;; First time a row is queried, populate cache with all the ;; rows from the table. (let ((number -1)) - (org-element-map (org-export-get-parent-table table-row) 'table-row + (org-element-map (org-element-lineage table-row 'table) 'table-row (lambda (row) (when (eq (org-element-property :type row) 'standard) (puthash row (cl-incf number) cache))) @@ -5421,7 +5471,7 @@ a communication channel. Address is a CONS cell (ROW . COLUMN), where ROW and COLUMN are zero-based index. Only exportable cells are considered. The function returns nil for other cells." - (let* ((table-row (org-export-get-parent table-cell)) + (let* ((table-row (org-element-parent table-cell)) (row-number (org-export-table-row-number table-row info))) (when row-number (cons row-number @@ -5468,7 +5518,7 @@ return nil." ;; `org-export-collect-tables', `org-export-collect-figures' and ;; `org-export-collect-listings' can be derived from it. ;; -;; `org-export-toc-entry-backend' builds a special anonymous back-end +;; `org-export-toc-entry-backend' builds a special anonymous backend ;; useful to export table of contents' entries. (defun org-export-collect-headlines (info &optional n scope) @@ -5490,19 +5540,19 @@ argument N becomes relative to the level of that headline. Return a list of all exportable headlines as parsed elements. Footnote sections are ignored." (let* ((scope (cond ((not scope) (plist-get info :parse-tree)) - ((eq (org-element-type scope) 'headline) scope) - ((org-export-get-parent-headline scope)) + ((org-element-type-p scope 'headline) scope) + ((org-element-lineage scope 'headline)) (t (plist-get info :parse-tree)))) (limit (plist-get info :headline-levels)) (n (if (not (wholenump n)) limit - (min (if (eq (org-element-type scope) 'org-data) n + (min (if (org-element-type-p scope 'org-data) n (+ (org-export-get-relative-level scope info) n)) limit)))) (org-element-map (org-element-contents scope) 'headline (lambda (h) (and (not (org-element-property :footnote-section-p h)) (not (equal "notoc" - (org-export-get-node-property :UNNUMBERED h t))) + (org-export-get-node-property :UNNUMBERED h t))) (>= n (org-export-get-relative-level h info)) h)) info))) @@ -5544,7 +5594,7 @@ collected. A figure is a paragraph type element, with a caption, verifying PREDICATE. The latter has to be provided since a \"figure\" is -a vague concept that may depend on back-end. +a vague concept that may depend on backend. Return a list of elements recognized as figures." (org-export-collect-elements 'paragraph info predicate)) @@ -5572,12 +5622,12 @@ required on headlines excluded from table of contents." (equal "notoc" (org-export-get-node-property :UNNUMBERED headline t)))) (defun org-export-toc-entry-backend (parent &rest transcoders) - "Return an export back-end appropriate for table of contents entries. + "Return an export backend appropriate for table of contents entries. -PARENT is an export back-end the returned back-end should inherit +PARENT is an export backend the returned backend should inherit from. -By default, the back-end removes footnote references and targets. +By default, the backend removes footnote references and targets. It also changes links and radio targets into regular text. TRANSCODERS optional argument, when non-nil, specifies additional transcoders. A transcoder follows the pattern (TYPE . FUNCTION) @@ -5607,7 +5657,7 @@ transcoding it." ;; Dictionary for smart quotes is stored in ;; `org-export-smart-quotes-alist'. -(defconst org-export-smart-quotes-alist +(defcustom org-export-smart-quotes-alist '(("ar" (primary-opening :utf-8 "«" :html "«" :latex "\\guillemotleft{}" @@ -5762,7 +5812,7 @@ transcoding it." :utf-8 "„" :html "„" :latex "\\glqq{}" :texinfo "@quotedblbase{}") (secondary-closing :utf-8 "“" :html "“" :latex "\\grqq{}" :texinfo "@quotedblleft{}") - (apostrophe :utf-8 "’" :html: "'")) + (apostrophe :utf-8 "’" :html "'")) ("sl" ;; Based on https://sl.wikipedia.org/wiki/Narekovaj (primary-opening :utf-8 "«" :html "«" :latex "{}<<" @@ -5794,17 +5844,40 @@ A quote type can be any symbol among `primary-opening', Valid encodings include `:utf-8', `:html', `:latex' and `:texinfo'. -If no translation is found, the quote character is left as-is.") +If no translation is found, the quote character is left as-is." + :group 'org-export-general + :package-version '(Org . "9.7") + :type '(alist + :key-type + (string :tag "Language name") + :value-type + (alist + :key-type + (choice + (const :tag "Primary opening" primary-opening) + (const :tag "Primary closing" primary-closing) + (const :tag "Secondary opening" secondary-opening) + (const :tag "Secondary closing" secondary-closing) + (const :tag "Apostrophe" apostrophe)) + :value-type + (plist + :key-type + (choice + (const :tag "UTF-8 ASCII translation" :utf-8) + (const :tag "HTML translation" :html) + (const :tag "LaTeX translation" :latex) + (const :tag "TeXInfo translation" :texinfo)) + :value-type string)))) (defun org-export--smart-quote-status (s info) "Return smart quote status at the beginning of string S. INFO is the current export state, as a plist." - (let* ((parent (org-element-property :parent s)) + (let* ((parent (org-element-parent s)) (cache (or (plist-get info :smart-quote-cache) (let ((table (make-hash-table :test #'eq))) (plist-put info :smart-quote-cache table) table))) - (value (gethash parent cache 'missing-data))) + (value (gethash (cons parent (org-element-secondary-p s)) cache 'missing-data))) (if (not (eq value 'missing-data)) (cdr (assq s value)) (let (level1-open full-status) (org-element-map @@ -5835,7 +5908,7 @@ INFO is the current export state, as a plist." text info))) (cond ((not p) nil) ((stringp p) (substring p -1)) - ((memq (org-element-property :post-blank p) + ((memq (org-element-post-blank p) '(0 nil)) 'no-blank) (t 'blank))))) @@ -5872,7 +5945,57 @@ INFO is the current export state, as a plist." (when current-status (push (cons text (nreverse current-status)) full-status)))) info nil org-element-recursive-objects) - (puthash parent full-status cache) + ;; When quotes are not balanced, treat them as apostrophes. + (setq full-status (nreverse full-status)) + (let (primary-openings secondary-openings) + (dolist (substatus full-status) + (let ((status (cdr substatus))) + (while status + (pcase (car status) + (`apostrophe nil) + (`primary-opening + (push status primary-openings)) + (`secondary-opening + (push status secondary-openings)) + (`secondary-closing + (if secondary-openings + ;; Remove matched opening. + (pop secondary-openings) + ;; No matching openings for a given closing. Replace + ;; it with apostrophe. + (setcar status 'apostrophe))) + (`primary-closing + (when secondary-openings + ;; Some secondary opening quotes are not closed + ;; within "...". Replace them all with apostrophes. + (dolist (opening secondary-openings) + (setcar opening 'apostrophe)) + (setq secondary-openings nil)) + (if primary-openings + ;; Remove matched opening. + (pop primary-openings) + ;; No matching openings for a given closing. + (error "This should no happen")))) + (setq status (cdr status))))) + (when primary-openings + ;; Trailing unclosed " + (unless (= 1 (length primary-openings)) + (error "This should not happen")) + ;; Mark for not replacing. + (setcar (car primary-openings) nil) + ;; Mark all the secondary openings and closings after + ;; trailing unclosed " as apostrophes. + (let ((after-unbalanced-primary nil)) + (dolist (substatus full-status) + (let ((status (cdr substatus))) + (while status + (when (eq status (car primary-openings)) + (setq after-unbalanced-primary t)) + (when after-unbalanced-primary + (when (memq (car status) '(secondary-opening secondary-closing)) + (setcar status 'apostrophe))) + (setq status (cdr status)))))))) + (puthash (cons parent (org-element-secondary-p s)) full-status cache) (cdr (assq s full-status)))))) (defun org-export-activate-smart-quotes (s encoding info &optional original) @@ -5905,29 +6028,21 @@ Return the new string." ;; ;; Here are various functions to retrieve information about the ;; neighborhood of a given element or object. Neighbors of interest -;; are direct parent (`org-export-get-parent'), parent headline -;; (`org-export-get-parent-headline'), first element containing an -;; object, (`org-export-get-parent-element'), parent table -;; (`org-export-get-parent-table'), previous element or object -;; (`org-export-get-previous-element') and next element or object -;; (`org-export-get-next-element'). - -;; defsubst org-export-get-parent must be defined before first use +;; are parent headline (`org-export-get-parent-headline'), first +;; element containing an object, (`org-element-parent-element'), +;; parent table (`org-export-get-parent-table'), previous element or +;; object (`org-export-get-previous-element') and next element or +;; object (`org-export-get-next-element'). (defun org-export-get-parent-headline (blob) "Return BLOB parent headline or nil. BLOB is the element or object being considered." - (org-element-lineage blob '(headline))) - -(defun org-export-get-parent-element (object) - "Return first element containing OBJECT or nil. -OBJECT is the object to consider." - (org-element-lineage object org-element-all-elements)) + (org-element-lineage blob 'headline)) (defun org-export-get-parent-table (object) "Return OBJECT parent table or nil. OBJECT is either a `table-cell' or `table-element' type object." - (org-element-lineage object '(table))) + (org-element-lineage object 'table)) (defun org-export-get-previous-element (blob info &optional n) "Return previous element or object. @@ -5941,7 +6056,7 @@ containing up to N siblings before BLOB, from farthest to closest. With any other non-nil value, return a list containing all of them." (let* ((secondary (org-element-secondary-p blob)) - (parent (org-export-get-parent blob)) + (parent (org-element-parent blob)) (siblings (if secondary (org-element-property secondary parent) (org-element-contents parent))) @@ -5966,7 +6081,7 @@ containing up to N siblings after BLOB, from closest to farthest. With any other non-nil value, return a list containing all of them." (let* ((secondary (org-element-secondary-p blob)) - (parent (org-export-get-parent blob)) + (parent (org-element-parent blob)) (siblings (cdr (memq blob (if secondary (org-element-property secondary parent) @@ -6015,7 +6130,7 @@ them." ("ro" :default "Autor") ("ru" :html "Автор" :utf-8 "Автор") ("sl" :default "Avtor") - ("sv" :html "Författare") + ("sv" :default "Författare") ("tr" :default "Yazar") ("uk" :html "Автор" :utf-8 "Автор") ("zh-CN" :html "作者" :utf-8 "作者") @@ -6025,11 +6140,13 @@ them." ("cs" :default "Pokračování z předchozí strany") ("de" :default "Fortsetzung von vorheriger Seite") ("es" :html "Continúa de la página anterior" :ascii "Continua de la pagina anterior" :default "Continúa de la página anterior") + ("et" :default "Jätk eelmisele leheküljele" :html "Jätk eelmisele leheküljele" :utf-8 "Jätk eelmisele leheküljele") ("fa" :default "ادامه از صفحهٔ قبل") ("fr" :default "Suite de la page précédente") ("it" :default "Continua da pagina precedente") ("ja" :default "前ページからの続き") ("nl" :default "Vervolg van vorige pagina") + ("nn" :default "Held fram frå førre side") ("pl" :default "Ciąg dalszy poprzedniej strony") ("pt" :default "Continuação da página anterior") ("pt_BR" :html "Continuação da página anterior" :ascii "Continuacao da pagina anterior" :default "Continuação da página anterior") @@ -6037,32 +6154,41 @@ them." ("ru" :html "(Продолжение)" :utf-8 "(Продолжение)") ("sl" :default "Nadaljevanje s prejšnje strani") + ("sv" :default "Fortsättning från föregående sida") ("tr" :default "Önceki sayfadan devam ediyor")) ("Continued on next page" ("ar" :default "التتمة في الصفحة التالية") ("cs" :default "Pokračuje na další stránce") ("de" :default "Fortsetzung nächste Seite") ("es" :html "Continúa en la siguiente página" :ascii "Continua en la siguiente pagina" :default "Continúa en la siguiente página") + ("et" :default "Jätkub järgmisel leheküljel" :html "Jätkub järgmisel leheküljel" :utf-8 "Jätkub järgmisel leheküljel") ("fa" :default "ادامه در صفحهٔ بعد") ("fr" :default "Suite page suivante") ("it" :default "Continua alla pagina successiva") ("ja" :default "次ページに続く") ("nl" :default "Vervolg op volgende pagina") - ("pl" :default "Kontynuacja na następnej stronie") + ("nn" :default "Held fram på neste side") + ("pl" :default "Ciąg dalszy na następnej stronie") ("pt" :default "Continua na página seguinte") ("pt_BR" :html "Continua na próxima página" :ascii "Continua na proxima pagina" :default "Continua na próxima página") ("ro" :default "Continuare pe pagina următoare") ("ru" :html "(Продолжение следует)" :utf-8 "(Продолжение следует)") ("sl" :default "Nadaljevanje na naslednji strani") + ("sv" :default "Fortsätter på nästa sida") ("tr" :default "Devamı sonraki sayfada")) ("Created" ("cs" :default "Vytvořeno") + ("de" :default "Erstellt am") + ("et" :default "Loodud") ("fa" :default "ساخته شده") ("nl" :default "Gemaakt op") ;; must be followed by a date or date+time + ("nn" :default "Oppretta") + ("pl" :default "Wygenerowano o") ; must be followed by a date or date+time ("pt_BR" :default "Criado em") ("ro" :default "Creat") ("sl" :default "Ustvarjeno") + ("sv" :default "Skapat") ("tr" :default "Oluşturuldu")) ("Date" ("ar" :default "بتاريخ") @@ -6072,7 +6198,7 @@ them." ("de" :default "Datum") ("eo" :default "Dato") ("es" :default "Fecha") - ("et" :html "Kuupäev" :utf-8 "Kuupäev") + ("et" :default "Kuupäev" :html "Kuupäev" :utf-8 "Kuupäev") ("fa" :default "تاریخ") ("fi" :html "Päivämäärä") ("hu" :html "Dátum") @@ -6099,7 +6225,7 @@ them." ("da" :default "Ligning") ("de" :default "Gleichung") ("es" :ascii "Ecuacion" :html "Ecuación" :default "Ecuación") - ("et" :html "Võrrand" :utf-8 "Võrrand") + ("et" :default "Võrrand" :html "Võrrand" :utf-8 "Võrrand") ("fa" :default "معادله") ("fr" :ascii "Equation" :default "Équation") ("is" :default "Jafna") @@ -6108,6 +6234,7 @@ them." ("no" :default "Ligning") ("nb" :default "Ligning") ("nn" :default "Likning") + ("pl" :default "Równanie" :ascii "Rownanie") ("pt_BR" :html "Equação" :default "Equação" :ascii "Equacao") ("ro" :default "Ecuația") ("ru" :html "Уравнение" @@ -6131,6 +6258,7 @@ them." ("no" :default "Illustrasjon") ("nb" :default "Illustrasjon") ("nn" :default "Illustrasjon") + ("pl" :default "Obrazek") ; alternatively "Rysunek" ("pt_BR" :default "Figura") ("ro" :default "Imaginea") ("ru" :html "Рисунок" :utf-8 "Рисунок") @@ -6140,24 +6268,25 @@ them." ("Figure %d:" ("ar" :default "شكل %d:") ("cs" :default "Obrázek %d:") - ("da" :default "Figur %d") + ("da" :default "Figur %d:") ("de" :default "Abbildung %d:") ("es" :default "Figura %d:") ("et" :default "Joonis %d:") ("fa" :default "شکل %d:") - ("fr" :default "Figure %d :" :html "Figure %d :") - ("is" :default "Mynd %d") + ("fr" :default "Figure %d:" :html "Figure %d :") + ("is" :default "Mynd %d:") ("it" :default "Figura %d:") - ("ja" :default "図%d: " :html "図%d: ") + ("ja" :default "図%d:" :html "図%d:") ("nl" :default "Figuur %d:" :html "Figuur %d:") - ("no" :default "Illustrasjon %d") - ("nb" :default "Illustrasjon %d") - ("nn" :default "Illustrasjon %d") + ("no" :default "Illustrasjon %d:") + ("nb" :default "Illustrasjon %d:") + ("nn" :default "Illustrasjon %d:") + ("pl" :default "Obrazek %d:") ; alternatively "Rysunek %d" ("pt_BR" :default "Figura %d:") ("ro" :default "Imaginea %d:") ("ru" :html "Рис. %d.:" :utf-8 "Рис. %d.:") - ("sl" :default "Slika %d") - ("sv" :default "Illustration %d") + ("sl" :default "Slika %d:") + ("sv" :default "Illustration %d:") ("tr" :default "Şekil %d:") ("zh-CN" :html "图%d " :utf-8 "图%d ")) ("Footnotes" @@ -6168,7 +6297,7 @@ them." ("de" :html "Fußnoten" :default "Fußnoten") ("eo" :default "Piednotoj") ("es" :ascii "Notas al pie de pagina" :html "Notas al pie de página" :default "Notas al pie de página") - ("et" :html "Allmärkused" :utf-8 "Allmärkused") + ("et" :default "Allmärkused" :html "Allmärkused" :utf-8 "Allmärkused") ("fa" :default "پانوشت‌ها") ("fi" :default "Alaviitteet") ("fr" :default "Notes de bas de page") @@ -6202,12 +6331,15 @@ them." ("fr" :default "Liste des programmes") ("ja" :default "ソースコード目次") ("nl" :default "Lijst van programma's") + ("nn" :default "Programliste") ("no" :default "Dataprogrammer") ("nb" :default "Dataprogrammer") + ("pl" :default "Indeks") ; probably too vague but better than nothing ("pt_BR" :html "Índice de Listagens" :default "Índice de Listagens" :ascii "Indice de Listagens") ("ru" :html "Список распечаток" :utf-8 "Список распечаток") ("sl" :default "Seznam programskih izpisov") + ("sv" :default "Programlistningar") ("tr" :default "Program Listesi") ("zh-CN" :html "代码目录" :utf-8 "代码目录")) ("List of Tables" @@ -6226,6 +6358,7 @@ them." ("no" :default "Tabeller") ("nb" :default "Tabeller") ("nn" :default "Tabeller") + ("pl" :default "Indeks tabel") ("pt_BR" :html "Índice de Tabelas" :default "Índice de Tabelas" :ascii "Indice de Tabelas") ("ro" :default "Tabele") ("ru" :html "Список таблиц" @@ -6246,34 +6379,40 @@ them." ("it" :default "Listato") ("ja" :default "ソースコード") ("nl" :default "Programma") + ("nn" :default "Program") ("no" :default "Dataprogram") ("nb" :default "Dataprogram") + ("pl" :default "Indeks") ("pt_BR" :default "Listagem") ("ro" :default "Lista") ("ru" :html "Распечатка" :utf-8 "Распечатка") ("sl" :default "Izpis programa") + ("sv" :default "Programlistning") ("tr" :default "Program") ("zh-CN" :html "代码" :utf-8 "代码")) ("Listing %d:" ("ar" :default "برنامج %d:") ("cs" :default "Program %d:") - ("da" :default "Program %d") - ("de" :default "Programmlisting %d") - ("es" :default "Listado de programa %d") - ("et" :default "Loend %d") + ("da" :default "Program %d:") + ("de" :default "Programmlisting %d:") + ("es" :default "Listado de programa %d:") + ("et" :default "Loend %d:") ("fa" :default "برنامه‌ریزی %d:") - ("fr" :default "Programme %d :" :html "Programme %d :") - ("it" :default "Listato %d :") + ("fr" :default "Programme %d:" :html "Programme %d :") + ("it" :default "Listato %d:") ("ja" :default "ソースコード%d:") ("nl" :default "Programma %d:" :html "Programma %d:") - ("no" :default "Dataprogram %d") - ("nb" :default "Dataprogram %d") - ("ro" :default "Lista %d") + ("nn" :default "Program %d:") + ("no" :default "Dataprogram %d:") + ("nb" :default "Dataprogram %d:") + ("ro" :default "Lista %d:") + ("pl" :default "Indeks %d:") ("pt_BR" :default "Listagem %d:") ("ru" :html "Распечатка %d.:" :utf-8 "Распечатка %d.:") - ("sl" :default "Izpis programa %d") + ("sl" :default "Izpis programa %d:") + ("sv" :default "Programlistning %d:") ("tr" :default "Program %d:") ("zh-CN" :html "代码%d " :utf-8 "代码%d ")) ("References" @@ -6281,69 +6420,91 @@ them." ("cs" :default "Reference") ("de" :default "Quellen") ("es" :default "Referencias") + ("et" :default "Viited") ("fa" :default "منابع") ("fr" :ascii "References" :default "Références") ("it" :default "Riferimenti") ("nl" :default "Bronverwijzingen") + ("nn" :default "Kjelder") + ("pl" :default "Odwołania") ; could be "Referencje" but I think its too englishy ("pt_BR" :html "Referências" :default "Referências" :ascii "Referencias") ("ro" :default "Bibliografie") ("sl" :default "Reference") + ("sv" :default "Referenser") ("tr" :default "Referanslar")) ("See figure %s" ("cs" :default "Viz obrázek %s") + ("et" :default "Vaata joonist %s") + ("de" :default "Siehe Abbildung %s") ("fa" :default "نمایش شکل %s") ("fr" :default "cf. figure %s" :html "cf. figure %s" :latex "cf.~figure~%s") ("it" :default "Vedi figura %s") ("nl" :default "Zie figuur %s" :html "Zie figuur %s" :latex "Zie figuur~%s") + ("nn" :default "Sjå figur %s") + ("pl" :default "Patrz obrazek %s") ; alternatively "Patrz rysunek %s" ("pt_BR" :default "Veja a figura %s") ("ro" :default "Vezi figura %s") ("sl" :default "Glej sliko %s") + ("sv" :default "Se illustration %s") ("tr" :default "bkz. şekil %s")) ("See listing %s" ("cs" :default "Viz program %s") + ("et" :default "Vaata loendit %s") + ("de" :default "Siehe Programmlisting %s") ("fa" :default "نمایش برنامه‌ریزی %s") ("fr" :default "cf. programme %s" :html "cf. programme %s" :latex "cf.~programme~%s") ("nl" :default "Zie programma %s" :html "Zie programma %s" :latex "Zie programma~%s") + ("nn" :default "Sjå program %s") + ("pl" :default "Patrz indeks %s") ("pt_BR" :default "Veja a listagem %s") ("ro" :default "Vezi tabelul %s") ("sl" :default "Glej izpis programa %s") + ("sv" :default "Se programlistning %s") ("tr" :default "bkz. program %s")) ("See section %s" ("ar" :default "انظر قسم %s") ("cs" :default "Viz sekce %s") ("da" :default "jævnfør afsnit %s") - ("de" :default "siehe Abschnitt %s") + ("de" :default "Siehe Abschnitt %s") ("es" :ascii "Vea seccion %s" :html "Vea sección %s" :default "Vea sección %s") - ("et" :html "Vaata peatükki %s" :utf-8 "Vaata peatükki %s") + ("et" :default "Vaata peatükki %s" :html "Vaata peatükki %s" :utf-8 "Vaata peatükki %s") ("fa" :default "نمایش بخش %s") ("fr" :default "cf. section %s") ("it" :default "Vedi sezione %s") ("ja" :default "セクション %s を参照") ("nl" :default "Zie sectie %s" :html "Zie sectie %s" :latex "Zie sectie~%s") + ("nn" :default "Sjå del %s") + ("pl" :default "Patrz sekcja %s") ; seems rough ("pt_BR" :html "Veja a seção %s" :default "Veja a seção %s" :ascii "Veja a secao %s") ("ro" :default "Vezi secțiunea %s") ("ru" :html "См. раздел %s" :utf-8 "См. раздел %s") ("sl" :default "Glej poglavje %d") + ("sv" :default "Se avsnitt %s") ("tr" :default "bkz. bölüm %s") ("zh-CN" :html "参见第%s节" :utf-8 "参见第%s节")) ("See table %s" ("cs" :default "Viz tabulka %s") + ("et" :default "Vaata tabelit %s") + ("de" :default "Siehe Tabelle %s") ("fa" :default "نمایش جدول %s") ("fr" :default "cf. tableau %s" :html "cf. tableau %s" :latex "cf.~tableau~%s") ("it" :default "Vedi tabella %s") ("nl" :default "Zie tabel %s" :html "Zie tabel %s" :latex "Zie tabel~%s") + ("nn" :default "Sjå tabell %s") + ("pl" :default "Patrz tabela %s") ("pt_BR" :default "Veja a tabela %s") ("ro" :default "Vezi tabelul %s") ("sl" :default "Glej tabelo %s") + ("sv" :default "Se tabell %s") ("tr" :default "bkz. tablo %s")) ("Table" ("ar" :default "جدول") @@ -6357,35 +6518,39 @@ them." ("it" :default "Tabella") ("ja" :default "表" :html "表") ("nl" :default "Tabel") + ("nn" :default "Tabell") + ("pl" :default "Tabela") ("pt_BR" :default "Tabela") ("ro" :default "Tabel") ("ru" :html "Таблица" :utf-8 "Таблица") + ("sv" :default "Tabell") ("tr" :default "Tablo") ("zh-CN" :html "表" :utf-8 "表")) ("Table %d:" ("ar" :default "جدول %d:") ("cs" :default "Tabulka %d:") - ("da" :default "Tabel %d") - ("de" :default "Tabelle %d") - ("es" :default "Tabla %d") - ("et" :default "Tabel %d") - ("fa" :default "جدول %d") - ("fr" :default "Tableau %d :") - ("is" :default "Tafla %d") + ("da" :default "Tabel %d:") + ("de" :default "Tabelle %d:") + ("es" :default "Tabla %d:") + ("et" :default "Tabel %d:") + ("fa" :default "جدول %d:") + ("fr" :default "Tableau %d:") + ("is" :default "Tafla %d:") ("it" :default "Tabella %d:") ("ja" :default "表%d:" :html "表%d:") ("nl" :default "Tabel %d:" :html "Tabel %d:") - ("no" :default "Tabell %d") - ("nb" :default "Tabell %d") - ("nn" :default "Tabell %d") + ("no" :default "Tabell %d:") + ("nb" :default "Tabell %d:") + ("nn" :default "Tabell %d:") + ("pl" :default "Tabela %d:") ("pt_BR" :default "Tabela %d:") - ("ro" :default "Tabel %d") + ("ro" :default "Tabel %d:") ("ru" :html "Таблица %d.:" :utf-8 "Таблица %d.:") - ("sl" :default "Tabela %d") - ("sv" :default "Tabell %d") - ("tr" :default "Tablo %d") + ("sl" :default "Tabela %d:") + ("sv" :default "Tabell %d:") + ("tr" :default "Tablo %d:") ("zh-CN" :html "表%d " :utf-8 "表%d ")) ("Table of Contents" ("ar" :default "قائمة المحتويات") @@ -6407,13 +6572,13 @@ them." ("no" :default "Innhold") ("nb" :default "Innhold") ("nn" :default "Innhald") - ("pl" :html "Spis treści") + ("pl" :default "Spis treści" :html "Spis treści") ("pt_BR" :html "Índice" :utf-8 "Índice" :ascii "Indice") ("ro" :default "Cuprins") ("ru" :html "Содержание" :utf-8 "Содержание") ("sl" :default "Kazalo") - ("sv" :html "Innehåll") + ("sv" :default "Innehåll") ("tr" :default "İçindekiler") ("uk" :html "Зміст" :utf-8 "Зміст") ("zh-CN" :html "目录" :utf-8 "目录") @@ -6429,11 +6594,14 @@ them." ("it" :default "Riferimento sconosciuto") ("ja" :default "不明な参照先") ("nl" :default "Onbekende verwijzing") + ("nn" :default "Ukjend kjelde") + ("pl" :default "Nieznane odwołanie") ; alternatively "Nieokreślone odwołanie" ("pt_BR" :html "Referência desconhecida" :default "Referência desconhecida" :ascii "Referencia desconhecida") ("ro" :default "Referință necunoscută") ("ru" :html "Неизвестная ссылка" :utf-8 "Неизвестная ссылка") ("sl" :default "Neznana referenca") + ("sv" :default "Okänd referens") ("tr" :default "Bilinmeyen referans") ("zh-CN" :html "未知引用" :utf-8 "未知引用"))) "Dictionary for export engine. @@ -6489,14 +6657,14 @@ to `:default' encoding. If it fails, return S." ;;`org-export-stack-remove', `org-export-stack-view' and ;;`org-export-stack-clear'. ;; -;; For back-ends, `org-export-add-to-stack' add a new source to stack. +;; For backends, `org-export-add-to-stack' add a new source to stack. ;; It should be used whenever `org-export-async-start' is called. (defun org-export-async-start (fun body) "Call function FUN on the results returned by BODY evaluation. FUN is an anonymous function of one argument. BODY should be a valid -ELisp source expression. BODY evaluation happens in an asynchronous process, +Elisp source expression. BODY evaluation happens in an asynchronous process, from a buffer which is an exact copy of the current one. Use `org-export-add-to-stack' in FUN in order to register results @@ -6509,9 +6677,9 @@ and `org-export-to-file' for more specialized functions." ;; buffer to a temporary file, as it may be too long for program ;; args in `start-process'. (with-temp-message "Initializing asynchronous export process" - (let ((copy-fun (org-export--generate-copy-script (current-buffer))) + (let ((copy-fun (org-element--generate-copy-script (current-buffer))) (temp-file (make-temp-file "org-export-process"))) - (let ((coding-system-for-write 'utf-8-emacs-unix)) + (let ((coding-system-for-write 'emacs-internal)) (write-region ;; Null characters (from variable values) are inserted ;; within the file. As a consequence, coding system for @@ -6581,9 +6749,9 @@ and `org-export-to-file' for more specialized functions." post-process) "Call `org-export-as' with output to a specified buffer. -BACKEND is either an export back-end, as returned by, e.g., +BACKEND is either an export backend, as returned by, e.g., `org-export-create-backend', or a symbol referring to -a registered back-end. +a registered backend. BUFFER is the name of the output buffer. If it already exists, it will be erased first, otherwise, it will be created. @@ -6600,7 +6768,7 @@ see. Optional argument POST-PROCESS is a function which should accept no argument. It is always called within the current process, -from BUFFER, with point at its beginning. Export back-ends can +from BUFFER, with point at its beginning. Export backends can use it to set a major mode there, e.g., (defun org-latex-export-as-latex @@ -6608,7 +6776,7 @@ use it to set a major mode there, e.g., (interactive) (org-export-to-buffer \\='latex \"*Org LATEX Export*\" async subtreep visible-only body-only ext-plist - #\\='LaTeX-mode)) + (major-mode-remap \\='latex-mode))) When expressed as an anonymous function, using `lambda', POST-PROCESS needs to be quoted. @@ -6650,9 +6818,9 @@ This function returns BUFFER." post-process) "Call `org-export-as' with output to a specified file. -BACKEND is either an export back-end, as returned by, e.g., +BACKEND is either an export backend, as returned by, e.g., `org-export-create-backend', or a symbol referring to -a registered back-end. FILE is the name of the output file, as +a registered backend. FILE is the name of the output file, as a string. A non-nil optional argument ASYNC means the process should happen @@ -6665,7 +6833,7 @@ see. Optional argument POST-PROCESS is called with FILE as its argument and happens asynchronously when ASYNC is non-nil. It -has to return a file name, or nil. Export back-ends can use this +has to return a file name, or nil. Export backends can use this to send the output file through additional processing, e.g, (defun org-latex-export-to-latex @@ -6701,7 +6869,7 @@ or FILE." ;; non-binary data. (unless (bolp) (insert "\n")) (let ((coding-system-for-write ',encoding)) - (write-region (point-min) (point-max) ,file))) + (write-region nil nil ,file))) (or (ignore-errors (funcall ',post-process ,file)) ,file))) (let ((output (org-export-as backend subtreep visible-only body-only ext-plist))) @@ -6713,7 +6881,7 @@ or FILE." ;; non-binary data. (unless (bolp) (insert "\n")) (let ((coding-system-for-write encoding)) - (write-region (point-min) (point-max) file))) + (write-region nil nil file))) (when (and (org-export--copy-to-kill-ring-p) (org-string-nw-p output)) (org-kill-new output)) ;; Get proper return value. @@ -6748,7 +6916,7 @@ Return file name as a string." (while (re-search-forward "^[ \t]*#\\+EXPORT_FILE_NAME:[ \t]+\\S-" nil t) (let ((element (org-element-at-point))) - (when (eq 'keyword (org-element-type element)) + (when (org-element-type-p element 'keyword) (throw :found (org-element-property :value element)))))))) ;; Extract from buffer's associated file, if any. @@ -6779,7 +6947,7 @@ Return file name as a string." "Add a new result to export stack if not present already. SOURCE is a buffer or a file name containing export results. -BACKEND is a symbol representing export back-end used to generate +BACKEND is a symbol representing export backend used to generate it. Entries already pointing to SOURCE and unavailable entries are @@ -6824,8 +6992,8 @@ within Emacs." (interactive "P") (let ((source (org-export--stack-source-at-point))) (cond ((processp source) - (org-switch-to-buffer-other-window (process-buffer source))) - ((bufferp source) (org-switch-to-buffer-other-window source)) + (switch-to-buffer-other-window (process-buffer source))) + ((bufferp source) (switch-to-buffer-other-window source)) (t (org-open-file source in-emacs))))) (defvar org-export-stack-mode-map @@ -6862,7 +7030,7 @@ or buffers, only display. \\{org-export-stack-mode-map}" (setq tabulated-list-format (vector (list "#" 4 #'org-export--stack-num-predicate) - (list "Back-End" 12 t) + (list "Backend" 12 t) (list "Age" 6 nil) (list "Source" 0 nil))) (setq tabulated-list-sort-key (cons "#" nil)) @@ -6895,7 +7063,7 @@ appropriate for `tabulated-list-print'." (vector ;; Counter. (number-to-string (cl-incf counter)) - ;; Back-End. + ;; Backend. (if (nth 1 entry) (symbol-name (nth 1 entry)) "") ;; Age. (let ((info (nth 2 entry))) @@ -6915,7 +7083,7 @@ appropriate for `tabulated-list-print'." (if (not source) (error "Source unavailable, please refresh buffer") (let ((source-name (if (stringp source) source (buffer-name source)))) (if (save-excursion - (beginning-of-line) + (forward-line 0) (looking-at-p (concat ".* +" (regexp-quote source-name) "$"))) source ;; SOURCE is not consistent with current line. The stack @@ -6958,22 +7126,26 @@ asynchronous export stack." (let* ((input (cond ((equal arg '(16)) '(stack)) ((and arg org-export-dispatch-last-action)) - (t (save-window-excursion - (unwind-protect - (progn - ;; Remember where we are - (move-marker org-export-dispatch-last-position - (point) - (org-base-buffer (current-buffer))) - ;; Get and store an export command - (setq org-export-dispatch-last-action - (org-export--dispatch-ui - (list org-export-initial-scope - (and org-export-in-background 'async)) - nil - org-export-dispatch-use-expert-ui))) - (and (get-buffer "*Org Export Dispatcher*") - (kill-buffer "*Org Export Dispatcher*"))))))) + (t (unwind-protect + (progn + ;; Remember where we are + (move-marker org-export-dispatch-last-position + (point) + (org-base-buffer (current-buffer))) + ;; Get and store an export command + (setq org-export-dispatch-last-action + (org-export--dispatch-ui + (list org-export-initial-scope + (and org-export-body-only 'body) + (and org-export-visible-only 'visible) + (and org-export-force-publishing 'force) + (and org-export-in-background 'async)) + nil + org-export-dispatch-use-expert-ui))) + (and (get-buffer-window "*Org Export Dispatcher*" t) + (quit-window 'kill (get-buffer-window "*Org Export Dispatcher*" t))) + (and (get-buffer "*Org Export Dispatcher*") + (kill-buffer "*Org Export Dispatcher*")))))) (action (car input)) (optns (cdr input))) (unless (memq 'subtree optns) @@ -7045,7 +7217,7 @@ back to standard interface." ;; Fontify VALUE string. (propertize value 'face 'font-lock-variable-name-face))) ;; Prepare menu entries by extracting them from registered - ;; back-ends and sorting them by access key and by ordinal, + ;; backends and sorting them by access key and by ordinal, ;; if any. (entries (sort (sort (delq nil @@ -7097,7 +7269,7 @@ back to standard interface." (funcall fontify-key "C-a" t) (funcall fontify-value (if (memq 'async options) "On " "Off"))) - ;; Display registered back-end entries. When a key + ;; Display registered backend entries. When a key ;; appears for the second time, do not create another ;; entry, but append its sub-menu to existing menu. (let (last-key) @@ -7163,43 +7335,42 @@ back to standard interface." (if expertp (org-export--dispatch-action expert-prompt allowed-keys entries options first-key expertp) - ;; At first call, create frame layout in order to display menu. - (unless (get-buffer "*Org Export Dispatcher*") - (delete-other-windows) - (org-switch-to-buffer-other-window - (get-buffer-create "*Org Export Dispatcher*")) - (setq cursor-type nil) - (setq header-line-format - (let ((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)))) - (apply 'format - (cons "Use %s, %s, %s, or %s to navigate." - (mapcar propertize-help-key - (list "SPC" "DEL" "C-n" "C-p")))))) - ;; Make sure that invisible cursor will not highlight square - ;; brackets. - (set-syntax-table (copy-syntax-table)) - (modify-syntax-entry ?\[ "w")) - ;; At this point, the buffer containing the menu exists and is - ;; visible in the current window. So, refresh it. - (with-current-buffer "*Org Export Dispatcher*" - ;; Refresh help. Maintain display continuity by re-visiting - ;; previous window position. - (let ((pt (point)) - (wstart (window-start))) - (erase-buffer) - (insert help) - (goto-char pt) - (set-window-start nil wstart))) - (org-fit-window-to-buffer) - (org-export--dispatch-action - standard-prompt allowed-keys entries options first-key expertp)))) + (save-window-excursion + ;; At first call, create frame layout in order to display menu. + (unless (get-buffer "*Org Export Dispatcher*") + (pop-to-buffer "*Org Export Dispatcher*" '(org-display-buffer-split)) + (setq cursor-type nil) + (setq header-line-format + (let ((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)))) + (apply 'format + (cons "Use %s, %s, %s, or %s to navigate." + (mapcar propertize-help-key + (list "SPC" "DEL" "C-n" "C-p")))))) + ;; Make sure that invisible cursor will not highlight square + ;; brackets. + (set-syntax-table (copy-syntax-table)) + (modify-syntax-entry ?\[ "w")) + ;; At this point, the buffer containing the menu exists and is + ;; visible in the current window. So, refresh it. + (with-current-buffer "*Org Export Dispatcher*" + ;; Refresh help. Maintain display continuity by re-visiting + ;; previous window position. + (let ((pt (point)) + (wstart (window-start))) + (erase-buffer) + (insert help) + (goto-char pt) + (set-window-start nil wstart))) + (org-fit-window-to-buffer) + (org-export--dispatch-action + standard-prompt allowed-keys entries options first-key expertp))))) (defun org-export--dispatch-action (prompt allowed-keys entries options first-key expertp) diff --git a/lisp/orgit/orgit-pkg.el b/lisp/orgit/orgit-pkg.el index 751d9afb..2975239f 100644 --- a/lisp/orgit/orgit-pkg.el +++ b/lisp/orgit/orgit-pkg.el @@ -1,17 +1,13 @@ -(define-package "orgit" "20250301.2339" "Support for Org links to Magit buffers" - '((emacs "26.1") - (compat "30.0.2.0") - (magit "4.3.1") - (org "9.7.11")) - :commit "6ad0dc35c8df54fae4ef27e5145760e22fbbf890" :authors - '(("Jonas Bernoulli" . "emacs.orgit@jonas.bernoulli.dev")) - :maintainers - '(("Jonas Bernoulli" . "emacs.orgit@jonas.bernoulli.dev")) - :maintainer - '("Jonas Bernoulli" . "emacs.orgit@jonas.bernoulli.dev") - :keywords - '("hypermedia" "vc") - :url "https://github.com/magit/orgit") -;; Local Variables: -;; no-byte-compile: t -;; End: +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "orgit" "20250601.1057" + "Support for Org links to Magit buffers." + '((emacs "27.1") + (compat "30.1") + (magit "4.3.6") + (org "9.7")) + :url "https://github.com/magit/orgit" + :commit "224350397df0987f8cdc770eb7f4618eca34a727" + :revdesc "224350397df0" + :keywords '("hypermedia" "vc") + :authors '(("Jonas Bernoulli" . "emacs.orgit@jonas.bernoulli.dev")) + :maintainers '(("Jonas Bernoulli" . "emacs.orgit@jonas.bernoulli.dev"))) diff --git a/lisp/orgit/orgit.el b/lisp/orgit/orgit.el index 2b09de46..7b8a2b6b 100644 --- a/lisp/orgit/orgit.el +++ b/lisp/orgit/orgit.el @@ -6,12 +6,13 @@ ;; Homepage: https://github.com/magit/orgit ;; Keywords: hypermedia vc -;; Package-Version: 2.0.1 +;; Package-Version: 20250601.1057 +;; Package-Revision: 224350397df0 ;; Package-Requires: ( -;; (emacs "26.1") -;; (compat "30.0.2.0") -;; (magit "4.3.1") -;; (org "9.7.11")) +;; (emacs "27.1") +;; (compat "30.1") +;; (magit "4.3.6") +;; (org "9.7")) ;; SPDX-License-Identifier: GPL-3.0-or-later @@ -118,6 +119,11 @@ "https://gitlab.com/%n" "https://gitlab.com/%n/commits/%r" "https://gitlab.com/%n/commit/%r") + ("codeberg.org\\(/\\|:git@\\)\\(.+?\\)\\(?:\\.git\\)?$" + "https://codeberg.org/%n" + ;; Redirects to commits/branch/%r. + "https://codeberg.org/%n/commits/%r" + "https://codeberg.org/%n/commit/%r") ("git.sr.ht[:/]\\(.+?\\)\\(?:\\.git\\)?$" "https://git.sr.ht/%n" "https://git.sr.ht/%n/log/%r" @@ -126,10 +132,6 @@ "https://bitbucket.org/%n" "https://bitbucket.org/%n/commits/branch/%r" "https://bitbucket.org/%n/commits/%r") - ("code.orgmode.org[:/]\\(.+\\)$" - "https://code.orgmode.org/cgit.cgi/%n" - "https://code.orgmode.org/cgit.cgi/%n/commits/%r" - "https://code.orgmode.org/cgit.cgi/%n/commit/%r") ("git.kernel.org/pub/scm[:/]\\(.+\\)$" "https://git.kernel.org/cgit/%n" "https://git.kernel.org/cgit/%n/log/?h=%r" diff --git a/lisp/ov/ov-pkg.el b/lisp/ov/ov-pkg.el index 0345b51d..7f3caa1e 100644 --- a/lisp/ov/ov-pkg.el +++ b/lisp/ov/ov-pkg.el @@ -1,8 +1,8 @@ -(define-package "ov" "20230522.1117" "Overlay library for Emacs Lisp" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "ov" "20230522.1117" + "Overlay library for Emacs Lisp." '((emacs "24.3")) - :commit "e2971ad986b6ac441e9849031d34c56c980cf40b" :keywords - '("convenience" "overlay") - :url "https://github.com/ShingoFukuyama/ov.el") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/ShingoFukuyama/ov.el" + :commit "e2971ad986b6ac441e9849031d34c56c980cf40b" + :revdesc "e2971ad986b6" + :keywords '("convenience" "overlay")) diff --git a/lisp/ov/ov.el b/lisp/ov/ov.el index a0d5c75d..deedda0d 100644 --- a/lisp/ov/ov.el +++ b/lisp/ov/ov.el @@ -2,7 +2,8 @@ ;; Copyright (C) 2014 by Shingo Fukuyama -;; Version: 1.0.6 +;; Package-Version: 20230522.1117 +;; Package-Revision: e2971ad986b6 ;; Author: Shingo Fukuyama - http://fukuyama.co ;; URL: https://github.com/ShingoFukuyama/ov.el ;; Created: Mar 20 2014 diff --git a/lisp/ox-pandoc/ox-pandoc-pkg.el b/lisp/ox-pandoc/ox-pandoc-pkg.el index 422debb6..a6bb2fd6 100644 --- a/lisp/ox-pandoc/ox-pandoc-pkg.el +++ b/lisp/ox-pandoc/ox-pandoc-pkg.el @@ -1,18 +1,14 @@ -(define-package "ox-pandoc" "20240710.1424" "An Org-mode exporter using pandoc" - '((org "8.2") +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "ox-pandoc" "20250424.908" + "An Org-mode exporter using pandoc." + '((org "8.2") (emacs "24.4") - (dash "2.8") - (ht "2.0")) - :commit "34e6ea97b586e20529d07158a73af3cf33cdd1d5" :authors - '(("Taichi" . "kawabata.taichi@gmail.com") - ("Alex" . "a-fent@github")) - :maintainers - '(("Alex" . "a-fent@github")) - :maintainer - '("Alex" . "a-fent@github") - :keywords - '("tools") - :url "https://github.com/a-fent/ox-pandoc") -;; Local Variables: -;; no-byte-compile: t -;; End: + (dash "2.8") + (ht "2.0")) + :url "https://github.com/a-fent/ox-pandoc" + :commit "5766c70b6db5a553829ccdcf52fcf3c6244e443d" + :revdesc "5766c70b6db5" + :keywords '("tools") + :authors '(("Taichi" . "kawabata.taichi@gmail.com") + ("Alex" . "a-fent@github")) + :maintainers '(("Alex" . "a-fent@github"))) diff --git a/lisp/ox-pandoc/ox-pandoc.el b/lisp/ox-pandoc/ox-pandoc.el index fb4945e1..e1b8e504 100644 --- a/lisp/ox-pandoc/ox-pandoc.el +++ b/lisp/ox-pandoc/ox-pandoc.el @@ -9,7 +9,8 @@ ;; FENTON, Alex ;; Maintainer: FENTON, Alex ;; Created: 2014-07-20 -;; Version: 2.0 +;; Package-Version: 20250424.908 +;; Package-Revision: 5766c70b6db5 ;; Package-Requires: ((org "8.2") (emacs "24.4") (dash "2.8") (ht "2.0")) ;; Keywords: tools ;; URL: https://github.com/a-fent/ox-pandoc @@ -47,23 +48,23 @@ :group 'org-export) (defconst org-pandoc-valid-options - '(abbreviations ascii atx-headers base-header-level bash-completion - biblatex bibliography citation-abbreviations citeproc columns csl css - data-dir default-image-extension defaults dpi dump-args email-obfuscation eol - epub-chapter-level epub-cover-image epub-embed-font epub-metadata - epub-subdirectory extract-media fail-if-warnings file-scope filter - highlight-style html-q-tags id-prefix ignore-args include-after-body - include-before-body include-in-header incremental - indented-code-classes katex list-extensions list-highlight-languages - list-highlight-styles listings log lua-filter mathjax mathml - metadata natbib no-highlight number-offset number-sections - pdf-engine-opt pdf-engine preserve-tabs print-default-data-file - print-default-template quiet reference-doc reference-links - reference-location resource-path section-divs self-contained - shift-heading-level-by slide-level standalone strip-comments - syntax-definition tab-stop table-of-contents template title-prefix - toc top-level-division toc-depth trace track-changes variable - verbose version webtex wrap)) + '( abbreviations ascii atx-headers base-header-level bash-completion + biblatex bibliography citation-abbreviations citeproc columns csl css + data-dir default-image-extension defaults dpi dump-args email-obfuscation eol + epub-chapter-level epub-cover-image epub-embed-font epub-metadata + epub-subdirectory extract-media fail-if-warnings file-scope filter + highlight-style html-q-tags id-prefix ignore-args include-after-body + include-before-body include-in-header incremental + indented-code-classes katex list-extensions list-highlight-languages + list-highlight-styles listings log lua-filter mathjax mathml + metadata metadata-file natbib no-highlight number-offset number-sections + pdf-engine-opt pdf-engine preserve-tabs print-default-data-file + print-default-template quiet reference-doc reference-links + reference-location resource-path section-divs self-contained + shift-heading-level-by slide-level standalone strip-comments + syntax-definition tab-stop table-of-contents template title-prefix + toc top-level-division toc-depth trace track-changes variable + verbose version webtex wrap)) (defconst org-pandoc-colon-separated-options '(abbreviations css include-in-header include-before-body @@ -87,7 +88,7 @@ (markdown_strict . md) (native . hs) (opendocument . xml) (plain . txt) (revealjs . html) (s5 . html) (slideous . html) (slidy . html) (texinfo . texi) - (zimwiki . zim))) + (zimwiki . zim) (typst . typ))) (defconst org-pandoc-option-type `(choice (const t) (const nil) diff --git a/lisp/ox-reveal/ox-reveal-pkg.el b/lisp/ox-reveal/ox-reveal-pkg.el index 117b12e2..344675ba 100644 --- a/lisp/ox-reveal/ox-reveal-pkg.el +++ b/lisp/ox-reveal/ox-reveal-pkg.el @@ -1,13 +1,10 @@ -(define-package "ox-reveal" "20221127.814" "reveal.js Presentation Back-End for Org Export Engine" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "ox-reveal" "20221127.814" + "Reveal.js Presentation Back-End for Org Export Engine." '((org "8.3")) - :commit "f55c851bf6aeb1bb2a7f6cf0f2b7bd0e79c4a5a0" :authors - '(("Yujie Wen" . "yjwen.tyatgmaildotcom")) - :maintainers - '(("Yujie Wen" . "yjwen.tyatgmaildotcom")) - :maintainer - '("Yujie Wen" . "yjwen.tyatgmaildotcom") - :keywords - '("outlines" "hypermedia" "slideshow" "presentation")) -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/yjwen/org-reveal" + :commit "f55c851bf6aeb1bb2a7f6cf0f2b7bd0e79c4a5a0" + :revdesc "f55c851bf6ae" + :keywords '("outlines" "hypermedia" "slideshow" "presentation") + :authors '(("Yujie Wen" . "yjwen.tyatgmaildotcom")) + :maintainers '(("Yujie Wen" . "yjwen.tyatgmaildotcom"))) diff --git a/lisp/ox-reveal/ox-reveal.el b/lisp/ox-reveal/ox-reveal.el index f4d4e947..26530335 100644 --- a/lisp/ox-reveal/ox-reveal.el +++ b/lisp/ox-reveal/ox-reveal.el @@ -4,7 +4,8 @@ ;; Author: Yujie Wen ;; Created: 2013-04-27 -;; Version: 1.0 +;; Package-Version: 20221127.814 +;; Package-Revision: f55c851bf6ae ;; Package-Requires: ((org "8.3")) ;; Keywords: outlines, hypermedia, slideshow, presentation diff --git a/lisp/ox-tufte/ox-tufte-pkg.el b/lisp/ox-tufte/ox-tufte-pkg.el index fdc7af80..7f3b556a 100644 --- a/lisp/ox-tufte/ox-tufte-pkg.el +++ b/lisp/ox-tufte/ox-tufte-pkg.el @@ -1,9 +1,9 @@ -(define-package "ox-tufte" "20240919.1332" "Tufte HTML org-mode export backend" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "ox-tufte" "20240919.1332" + "Tufte HTML org-mode export backend." '((emacs "27.1") - (org "9.5")) - :commit "03e6c9e5e0ee467516139ed6b3f2b4bb13f847ec" :keywords - '("org" "tufte" "html" "outlines" "hypermedia" "calendar" "wp") - :url "https://github.com/ox-tufte/ox-tufte") -;; Local Variables: -;; no-byte-compile: t -;; End: + (org "9.5")) + :url "https://github.com/ox-tufte/ox-tufte" + :commit "03e6c9e5e0ee467516139ed6b3f2b4bb13f847ec" + :revdesc "03e6c9e5e0ee" + :keywords '("org" "tufte" "html" "outlines" "hypermedia" "calendar" "wp")) diff --git a/lisp/ox-tufte/ox-tufte.el b/lisp/ox-tufte/ox-tufte.el index 864006a3..50bd2b1b 100644 --- a/lisp/ox-tufte/ox-tufte.el +++ b/lisp/ox-tufte/ox-tufte.el @@ -8,7 +8,8 @@ ;; Maintainer: The Bayesians Inc. ;; Description: An org exporter for Tufte HTML ;; Keywords: org, tufte, html, outlines, hypermedia, calendar, wp -;; Package-Version: 4.2.1 +;; Package-Version: 20240919.1332 +;; Package-Revision: 03e6c9e5e0ee ;; Package-Requires: ((emacs "27.1") (org "9.5")) ;; URL: https://github.com/ox-tufte/ox-tufte diff --git a/lisp/page-break-lines/page-break-lines-pkg.el b/lisp/page-break-lines/page-break-lines-pkg.el index 214cde11..555ff4a0 100644 --- a/lisp/page-break-lines/page-break-lines-pkg.el +++ b/lisp/page-break-lines/page-break-lines-pkg.el @@ -1,14 +1,10 @@ -(define-package "page-break-lines" "20250218.1607" "Display ^L page breaks as tidy horizontal lines" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "page-break-lines" "20250218.1607" + "Display ^L page breaks as tidy horizontal lines." '((emacs "25.1")) - :commit "982571749c8fe2b5e2997dd043003a1b9fe87b38" :authors - '(("Steve Purcell" . "steve@sanityinc.com")) - :maintainers - '(("Steve Purcell" . "steve@sanityinc.com")) - :maintainer - '("Steve Purcell" . "steve@sanityinc.com") - :keywords - '("convenience" "faces") - :url "https://github.com/purcell/page-break-lines") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/purcell/page-break-lines" + :commit "982571749c8fe2b5e2997dd043003a1b9fe87b38" + :revdesc "982571749c8f" + :keywords '("convenience" "faces") + :authors '(("Steve Purcell" . "steve@sanityinc.com")) + :maintainers '(("Steve Purcell" . "steve@sanityinc.com"))) diff --git a/lisp/page-break-lines/page-break-lines.el b/lisp/page-break-lines/page-break-lines.el index 1a12de12..7746b763 100644 --- a/lisp/page-break-lines/page-break-lines.el +++ b/lisp/page-break-lines/page-break-lines.el @@ -4,7 +4,8 @@ ;; Author: Steve Purcell ;; URL: https://github.com/purcell/page-break-lines -;; Package-Version: 0.15 +;; Package-Version: 20250218.1607 +;; Package-Revision: 982571749c8f ;; Package-Requires: ((emacs "25.1")) ;; Keywords: convenience, faces diff --git a/lisp/parsebib/parsebib-pkg.el b/lisp/parsebib/parsebib-pkg.el index 30bffba6..ab23d836 100644 --- a/lisp/parsebib/parsebib-pkg.el +++ b/lisp/parsebib/parsebib-pkg.el @@ -1,14 +1,10 @@ -(define-package "parsebib" "20250225.840" "A library for parsing bib files" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "parsebib" "20250316.2257" + "A library for parsing bib files." '((emacs "25.1")) - :commit "735e308fc5b7aaed975764f6c7139d1c4bf28d0c" :authors - '(("Joost Kremers" . "joostkremers@fastmail.fm")) - :maintainers - '(("Joost Kremers" . "joostkremers@fastmail.fm")) - :maintainer - '("Joost Kremers" . "joostkremers@fastmail.fm") - :keywords - '("text" "bibtex") - :url "https://github.com/joostkremers/parsebib") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/joostkremers/parsebib" + :commit "7bfde4e4679413424a9a9af099203d5c23e32cd2" + :revdesc "7bfde4e46794" + :keywords '("text" "bibtex") + :authors '(("Joost Kremers" . "joostkremers@fastmail.fm")) + :maintainers '(("Joost Kremers" . "joostkremers@fastmail.fm"))) diff --git a/lisp/parsebib/parsebib.el b/lisp/parsebib/parsebib.el index bd82f980..61c75836 100644 --- a/lisp/parsebib/parsebib.el +++ b/lisp/parsebib/parsebib.el @@ -6,7 +6,8 @@ ;; Author: Joost Kremers ;; Maintainer: Joost Kremers ;; Created: 2014 -;; Version: 6.6 +;; Package-Version: 20250316.2257 +;; Package-Revision: 7bfde4e46794 ;; Keywords: text bibtex ;; URL: https://github.com/joostkremers/parsebib ;; Package-Requires: ((emacs "25.1")) @@ -373,6 +374,10 @@ should be read literally." "Parse text in double quotes." (parsebib--string ?\" ?\\)) +(defun parsebib--key () + "Parse a BibTeX key." + (parsebib--symbol parsebib--bibtex-key-regexp)) + (defun parsebib--identifier () "Parse a BibTeX identifier." (parsebib--symbol parsebib--bibtex-identifier)) @@ -462,7 +467,7 @@ Return the entry as an alist of pairs, where (if-let* ((_ (parsebib--char '(?@))) (type (parsebib--identifier)) (open (parsebib--char '(?\{ ?\( ))) - (key (parsebib--identifier)) + (key (parsebib--key)) (_ (parsebib--char '(?,))) (fields (parsebib--fields)) (_ (parsebib--char (alist-get open '((?\{ ?\}) (?\( ?\))))))) diff --git a/lisp/pdf-tools/pdf-tools-pkg.el b/lisp/pdf-tools/pdf-tools-pkg.el index bc0cdb27..a8c0a00c 100644 --- a/lisp/pdf-tools/pdf-tools-pkg.el +++ b/lisp/pdf-tools/pdf-tools-pkg.el @@ -1,16 +1,12 @@ -(define-package "pdf-tools" "20240429.407" "Support library for PDF documents" - '((emacs "26.3") - (tablist "1.0") +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "pdf-tools" "20240429.407" + "Support library for PDF documents." + '((emacs "26.3") + (tablist "1.0") (let-alist "1.0.4")) - :commit "30b50544e55b8dbf683c2d932d5c33ac73323a16" :authors - '(("Andreas Politz" . "mail@andreas-politz.de")) - :maintainers - '(("Vedang Manerikar" . "vedang.manerikar@gmail.com")) - :maintainer - '("Vedang Manerikar" . "vedang.manerikar@gmail.com") - :keywords - '("files" "multimedia") - :url "http://github.com/vedang/pdf-tools/") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "http://github.com/vedang/pdf-tools/" + :commit "30b50544e55b8dbf683c2d932d5c33ac73323a16" + :revdesc "30b50544e55b" + :keywords '("files" "multimedia") + :authors '(("Andreas Politz" . "mail@andreas-politz.de")) + :maintainers '(("Vedang Manerikar" . "vedang.manerikar@gmail.com"))) diff --git a/lisp/pdf-tools/pdf-tools.el b/lisp/pdf-tools/pdf-tools.el index 670792cb..0b02934e 100644 --- a/lisp/pdf-tools/pdf-tools.el +++ b/lisp/pdf-tools/pdf-tools.el @@ -7,7 +7,8 @@ ;; URL: http://github.com/vedang/pdf-tools/ ;; Keywords: files, multimedia ;; Package: pdf-tools -;; Version: 1.1.0 +;; Package-Version: 20240429.407 +;; Package-Revision: 30b50544e55b ;; Package-Requires: ((emacs "26.3") (tablist "1.0") (let-alist "1.0.4")) ;; This program is free software; you can redistribute it and/or modify diff --git a/lisp/persist/persist-pkg.el b/lisp/persist/persist-pkg.el index bdba96ba..8b6e40fd 100644 --- a/lisp/persist/persist-pkg.el +++ b/lisp/persist/persist-pkg.el @@ -1,2 +1,2 @@ ;; Generated package description from persist.el -*- no-byte-compile: t -*- -(define-package "persist" "0.5" "Persist Variables between Emacs Sessions" 'nil :commit "25d675307c03f720e592c3dc9a5a0ae8db0836eb" :url "https://elpa.gnu.org/packages/persist.html" :authors '(("Phillip Lord" . "phillip.lord@russet.org.uk")) :maintainer '("Phillip Lord" . "phillip.lord@russet.org.uk")) +(define-package "persist" "0.6.1" "Persist Variables between Emacs Sessions" '((emacs "26.1")) :commit "5ea8f32ef50ce2b444d6918e17eedce9f74629af" :url "https://elpa.gnu.org/packages/persist.html" :authors '(("Phillip Lord" . "phillip.lord@russet.org.uk")) :maintainer '("Joseph Turner" . "persist-el@breatheoutbreathe.in")) diff --git a/lisp/persist/persist.el b/lisp/persist/persist.el index d80943d1..49b3e9b5 100644 --- a/lisp/persist/persist.el +++ b/lisp/persist/persist.el @@ -1,11 +1,12 @@ ;;; persist.el --- Persist Variables between Emacs Sessions -*- lexical-binding: t -*- -;; Copyright (C) 2019 Free Software Foundation, Inc. +;; Copyright (C) 2019, 2024 Free Software Foundation, Inc. ;; Author: Phillip Lord -;; Maintainer: Phillip Lord +;; Maintainer: Joseph Turner ;; Package-Type: multi -;; Version: 0.5 +;; Package-Requires: ((emacs "26.1")) +;; Version: 0.6.1 ;; The contents of this file are subject to the GPL License, Version 3.0. @@ -22,7 +23,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see . +;; along with this program. If not, see . ;;; Commentary: @@ -41,6 +42,7 @@ ;; variables. ;;; Code: + (defvar persist--directory-location (locate-user-emacs-file "persist") "The location of persist directory.") @@ -63,14 +65,14 @@ variable is not set to the value.") persist--directory-location))) (defun persist--defvar-1 (symbol location) - "Set symbol up for persistance." + "Set symbol up for persistence." (when location (persist-location symbol location)) (persist-symbol symbol (symbol-value symbol)) (persist-load symbol)) (defmacro persist-defvar (symbol initvalue docstring &optional location) - "Define SYMBOL as a persistant variable and return SYMBOL. + "Define SYMBOL as a persistent variable and return SYMBOL. This form is nearly equivalent to `defvar', except that the variable persists between Emacs sessions. @@ -85,7 +87,9 @@ DOCSTRING need to be given." ;; Don't support 2-arity calls either because we are lazy and ;; because if you want to persist it, you want to doc it. - (declare (debug (symbolp form stringp &optional form)) (doc-string 3)) + (declare (debug (symbolp form stringp &optional form)) + (doc-string 3) + (indent defun)) ;; Define inside progn so the byte compiler sees defvar `(progn (defvar ,symbol ,initvalue ,docstring) @@ -103,7 +107,7 @@ to persist a variable, you will normally need to call (put symbol 'persist-location (expand-file-name directory))) (defun persist-symbol (symbol &optional initvalue) - "Make SYMBOL a persistant variable. + "Make SYMBOL a persistent variable. If non-nil, INITVALUE is the value to which SYMBOL will be set if `persist-reset' is called. Otherwise, the INITVALUE will be the @@ -118,10 +122,10 @@ to load a previously saved location." (let ((initvalue (or initvalue (symbol-value symbol)))) (add-to-list 'persist--symbols symbol) (put symbol 'persist t) - (put symbol 'persist-default initvalue))) + (put symbol 'persist-default (persist-copy initvalue)))) (defun persist--persistant-p (symbol) - "Return non-nil if SYMBOL is a persistant variable." + "Return non-nil if SYMBOL is a persistent variable." (get symbol 'persist)) (defun persist-save (symbol) @@ -131,10 +135,10 @@ Normally, it should not be necessary to call this explicitly, as variables persist automatically when Emacs exits." (unless (persist--persistant-p symbol) (error (format - "Symbol %s is not persistant" symbol))) + "Symbol %s is not persistent" symbol))) (let ((symbol-file-loc (persist--file-location symbol))) - (if (equal (symbol-value symbol) - (persist-default symbol)) + (if (persist-equal (symbol-value symbol) + (persist-default symbol)) (when (file-exists-p symbol-file-loc) (delete-file symbol-file-loc)) (let ((dir-loc @@ -158,8 +162,8 @@ variables persist automatically when Emacs exits." (get symbol 'persist-default)) (defun persist-reset (symbol) - "Reset the value of SYMBOL to the default." - (set symbol (persist-default symbol))) + "Set the value of SYMBOL to a copy of the default." + (set symbol (persist-copy (persist-default symbol)))) (defun persist-load (symbol) "Load the saved value of SYMBOL." @@ -180,12 +184,66 @@ This does not remove any saved value of SYMBOL." (remove symbol persist--symbols))) (defun persist--save-all () - "Save all persistant symbols." + "Save all persistent symbols." (mapc 'persist-save persist--symbols)) ;; Save on kill-emacs-hook anyway (add-hook 'kill-emacs-hook 'persist--save-all) +(defun persist-equal (a b) + "Return non-nil when the values of A and B are equal. +A and B are compared using `equal' unless they are both hash +tables. In that case, the following are compared: + +- hash table count +- hash table predicate +- values, using `persist-equal'" + (if (and (hash-table-p a) (hash-table-p b)) + (and (= (hash-table-count a) (hash-table-count b)) + (eq (hash-table-test a) (hash-table-test b)) + (catch 'done + (maphash + (lambda (key a-value) + (unless (persist-equal a-value (gethash key b (not a-value))) + (throw 'done nil))) + a) + t)) + (equal a b))) + +(defun persist-copy-tree (tree &optional vectors-and-records) + "Make a copy of TREE. +If TREE is a cons cell, this recursively copies both its car and its cdr. +Contrast to `copy-sequence', which copies only along the cdrs. +With the second argument VECTORS-AND-RECORDS non-nil, this +traverses and copies vectors and records as well as conses." + (declare (side-effect-free error-free)) + (if (consp tree) + (let (result) + (while (consp tree) + (let ((newcar (car tree))) + (if (or (consp (car tree)) + (and vectors-and-records + (or (vectorp (car tree)) (recordp (car tree))))) + (setq newcar (persist-copy-tree (car tree) vectors-and-records))) + (push newcar result)) + (setq tree (cdr tree))) + (nconc (nreverse result) + (if (and vectors-and-records (or (vectorp tree) (recordp tree))) + (persist-copy-tree tree vectors-and-records) + tree))) + (if (and vectors-and-records (or (vectorp tree) (recordp tree))) + (let ((i (length (setq tree (copy-sequence tree))))) + (while (>= (setq i (1- i)) 0) + (aset tree i (persist-copy-tree (aref tree i) vectors-and-records))) + tree) + tree))) + +(defun persist-copy (obj) + "Return copy of OBJ." + (if (hash-table-p obj) + (copy-hash-table obj) + (persist-copy-tree obj t))) + (provide 'persist) ;;; persist.el ends here diff --git a/lisp/persist/persist.texi b/lisp/persist/persist.texi index 8cb17a73..99f61a25 100644 --- a/lisp/persist/persist.texi +++ b/lisp/persist/persist.texi @@ -1,10 +1,10 @@ \input texinfo @setfilename persist.info -@settitle persist persistant variables +@settitle persist persistent variables @dircategory Emacs @direntry -* Persist: (persist). Persistant variables for Emacs. +* Persist: (persist). Persistent variables for Emacs. @end direntry @copying @@ -29,7 +29,7 @@ and modified without restriction. @end copying @titlepage -@title Persist -- Persistant Variables for Emacs +@title Persist -- Persistent Variables for Emacs @author by Phillip Lord @page @insertcopying @@ -38,9 +38,9 @@ and modified without restriction. @contents @node Top -@top Persist -- Persistant Variables for Emacs +@top Persist -- Persistent Variables for Emacs -Perist is a library for making variables persistant; that it, their +Persist is a library for making variables persistent; that it, their state can be changed from the default and the new value will remain even after Emacs has been closed and restarted. @@ -68,7 +68,7 @@ not support the lower arity versions of @code{defvar}. Both an (persist-defvar my-persistant-variable 10 "A variable of no purpose. -This variable is persistant between sessions") +This variable is persistent between sessions") @end group @end example @@ -79,15 +79,15 @@ This variable is persistant between sessions") @defmac persist-defvar (var initvalue docstring) body@dots{} This macro is equivalent to @code{defvar} and can be used to make a -variable persistant. +variable persistent. @end defmac @defun persist-symbol (symbol &optional initvalue) -This function takes @code{symbol} for an existing, non-persistant variable -and makes it persistant. If @code{initvalue} is not given, then the +This function takes @code{symbol} for an existing, non-persistent variable +and makes it persistent. If @code{initvalue} is not given, then the current value is used. For package developers, @code{persist-defvar} -would generally be prefered; this function might be useful for making -third-party variables persistant. +would generally be preferred; this function might be useful for making +third-party variables persistent. @end defun @example diff --git a/lisp/persist/test/persist-tests.el b/lisp/persist/test/persist-tests.el index b6645a92..d571325f 100644 --- a/lisp/persist/test/persist-tests.el +++ b/lisp/persist/test/persist-tests.el @@ -25,51 +25,57 @@ :type 'error :exclude-subtypes t)) -(ert-deftest test-persist-save () - (with-local-temp-persist - (let ((sym (cl-gensym))) - ;; precondition - (should-not (file-exists-p (persist--file-location sym))) - (set sym 10) - (persist-symbol sym 10) - (persist-save sym) - (should t) - (should-not (file-exists-p (persist--file-location sym))) - (set sym 20) - (persist-save sym) - (should (file-exists-p (persist--file-location sym))) - (should - (string-match-p - "20" - (with-temp-buffer - (insert-file-contents (persist--file-location sym)) - (buffer-string)))) - (set sym 10) - (persist-save sym) - (should-not (file-exists-p (persist--file-location sym))) - (should-error - (persist-save 'fred))))) +(defmacro persist-test-persist-save (init default change printed-changed) + "Test persisting symbols. +- symbol is not persisted when value is set to INIT and default + value is set to DEFAULT. +- symbol is persisted when value is changed according to CHANGE. +- persisted file contents match PRINTED-CHANGED. +- symbol is not persisted after value is set back to DEFAULT." + `(with-local-temp-persist + (let ((sym (cl-gensym))) + (should-not (file-exists-p (persist--file-location sym))) + (set sym ,init) + (persist-symbol sym ,default) + (persist-save sym) + (should t) + (should-not (file-exists-p (persist--file-location sym))) + ,change + (persist-save sym) + (should (file-exists-p (persist--file-location sym))) + (should + (string-match-p + ,printed-changed + (with-temp-buffer + (insert-file-contents (persist--file-location sym)) + (buffer-string)))) + (set sym ,default) + (persist-save sym) + (should-not (file-exists-p (persist--file-location sym)))))) -(ert-deftest test-persist-save-non-number () - "Test saving something that is not a number. +(ert-deftest test-persist-save-number () + "Test saving number." + (persist-test-persist-save 1 1 (set sym 2) "2")) -`test-persist-save' missed " - (with-local-temp-persist - (let ((sym (cl-gensym))) - (set sym "fred") - (persist-symbol sym "fred") - (persist-save sym) - (should t) - (should-not (file-exists-p (persist--file-location sym))) - (set sym "george") - (persist-save sym) - (should (file-exists-p (persist--file-location sym))) - (should - (string-match-p - "george" - (with-temp-buffer - (insert-file-contents (persist--file-location sym)) - (buffer-string))))))) +(ert-deftest test-persist-save-string () + "Test saving string." + (persist-test-persist-save "foo" "foo" (set sym "bar") "bar")) + +(ert-deftest test-persist-save-hash () + "Test saving hash table." + (let* ((hash (make-hash-table)) + (default (copy-hash-table hash))) + (persist-test-persist-save hash default + (puthash 'foo "bar" (symbol-value sym)) + "#s(hash-table size 65 test eql rehash-size 1.5 rehash-threshold 0.8125 data (foo \"bar\"))"))) + +(ert-deftest test-persist-save-record () + "Test saving record." + (let* ((rec (record 'foo 'a 'b)) + (default (copy-sequence rec))) + (persist-test-persist-save rec default + (setf (aref (symbol-value sym) 2) 'quux) + "#s(foo a quux)"))) (ert-deftest test-persist-load () (with-local-temp-persist @@ -128,3 +134,13 @@ (should-error (persist-save 'fred))) (delete-directory "./persist-defined-location" t))) + +(ert-deftest test-persist-reset () + "Symbol should be reset to a copy of the default." + (with-local-temp-persist + (persist-defvar persist--test-reset-variable (make-hash-table) "docstring") + (should-not (eq persist--test-reset-variable + (persist-default 'persist--test-reset-variable))) + (persist-reset 'persist--test-reset-variable) + (should-not (eq persist--test-reset-variable + (persist-default 'persist--test-reset-variable))))) diff --git a/lisp/pfuture/pfuture-pkg.el b/lisp/pfuture/pfuture-pkg.el index 7a9ad69c..540610c1 100644 --- a/lisp/pfuture/pfuture-pkg.el +++ b/lisp/pfuture/pfuture-pkg.el @@ -1,12 +1,9 @@ -(define-package "pfuture" "20220913.1401" "a simple wrapper around asynchronous processes" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "pfuture" "20220913.1401" + "A simple wrapper around asynchronous processes." '((emacs "25.2")) - :commit "19b53aebbc0f2da31de6326c495038901bffb73c" :authors - '(("Alexander Miller" . "alexanderm@web.de")) - :maintainers - '(("Alexander Miller" . "alexanderm@web.de")) - :maintainer - '("Alexander Miller" . "alexanderm@web.de") - :url "https://github.com/Alexander-Miller/pfuture") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/Alexander-Miller/pfuture" + :commit "19b53aebbc0f2da31de6326c495038901bffb73c" + :revdesc "19b53aebbc0f" + :authors '(("Alexander Miller" . "alexanderm@web.de")) + :maintainers '(("Alexander Miller" . "alexanderm@web.de"))) diff --git a/lisp/pfuture/pfuture.el b/lisp/pfuture/pfuture.el index 525b4d8e..4ce69f60 100644 --- a/lisp/pfuture/pfuture.el +++ b/lisp/pfuture/pfuture.el @@ -5,7 +5,8 @@ ;; Author: Alexander Miller ;; Homepage: https://github.com/Alexander-Miller/pfuture ;; Package-Requires: ((emacs "25.2")) -;; Version: 1.10.3 +;; Package-Version: 20220913.1401 +;; Package-Revision: 19b53aebbc0f ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by diff --git a/lisp/php-mode/php-align.el b/lisp/php-mode/php-align.el index e9acc469..3d6c7595 100644 --- a/lisp/php-mode/php-align.el +++ b/lisp/php-mode/php-align.el @@ -7,7 +7,6 @@ ;; Maintainer: USAMI Kenta ;; Keywords: php languages convenience align ;; Homepage: https://github.com/emacs-php/php-mode -;; Version: 1.26.1 ;; License: GPL-3.0-or-later ;; This program is free software; you can redistribute it and/or modify diff --git a/lisp/php-mode/php-complete.el b/lisp/php-mode/php-complete.el index f2b1aa42..18d018b3 100644 --- a/lisp/php-mode/php-complete.el +++ b/lisp/php-mode/php-complete.el @@ -6,7 +6,6 @@ ;; Author: USAMI Kenta ;; Created: 18 Sep 2022 -;; Version: 1.26.1 ;; Keywords: languages, php ;; This program is free software; you can redistribute it and/or modify diff --git a/lisp/php-mode/php-defs.el b/lisp/php-mode/php-defs.el index 8be83138..153fb8b1 100644 --- a/lisp/php-mode/php-defs.el +++ b/lisp/php-mode/php-defs.el @@ -4,7 +4,6 @@ ;; Author: USAMI Kenta ;; Created: 5 Mar 2022 -;; Version: 1.26.1 ;; Keywords: languages, php ;; This program is free software; you can redistribute it and/or modify diff --git a/lisp/php-mode/php-face.el b/lisp/php-mode/php-face.el index 147fb813..df272238 100644 --- a/lisp/php-mode/php-face.el +++ b/lisp/php-mode/php-face.el @@ -4,7 +4,6 @@ ;; Author: USAMI Kenta ;; Created: 5 May 2019 -;; Version: 1.26.1 ;; Keywords: faces, php ;; Homepage: https://github.com/emacs-php/php-mode ;; License: GPL-3.0-or-later diff --git a/lisp/php-mode/php-flymake.el b/lisp/php-mode/php-flymake.el index 8efad224..4d88c0b7 100644 --- a/lisp/php-mode/php-flymake.el +++ b/lisp/php-mode/php-flymake.el @@ -4,7 +4,6 @@ ;; Author: USAMI Kenta ;; Created: 5 Mar 2022 -;; Version: 1.26.1 ;; Keywords: tools, languages, php ;; This program is free software; you can redistribute it and/or modify diff --git a/lisp/php-mode/php-format.el b/lisp/php-mode/php-format.el index 578ee52b..696eefc3 100644 --- a/lisp/php-mode/php-format.el +++ b/lisp/php-mode/php-format.el @@ -4,7 +4,6 @@ ;; Author: USAMI Kenta ;; Created: 5 Mar 2023 -;; Version: 0.1.0 ;; Keywords: tools, php ;; URL: https://github.com/emacs-php/php-mode.el ;; License: GPL-3.0-or-later diff --git a/lisp/php-mode/php-ide-phpactor.el b/lisp/php-mode/php-ide-phpactor.el index 109cd461..17fc757c 100644 --- a/lisp/php-mode/php-ide-phpactor.el +++ b/lisp/php-mode/php-ide-phpactor.el @@ -5,7 +5,6 @@ ;; Author: USAMI Kenta ;; Keywords: tools, files ;; URL: https://github.com/emacs-php/php-mode -;; Version: 1.26.1 ;; License: GPL-3.0-or-later ;; This program is free software; you can redistribute it and/or modify diff --git a/lisp/php-mode/php-ide.el b/lisp/php-mode/php-ide.el index 4e1ec8b4..f221a028 100644 --- a/lisp/php-mode/php-ide.el +++ b/lisp/php-mode/php-ide.el @@ -5,7 +5,6 @@ ;; Author: USAMI Kenta ;; Keywords: tools, files ;; URL: https://github.com/emacs-php/php-mode -;; Version: 1.26.1 ;; License: GPL-3.0-or-later ;; This program is free software; you can redistribute it and/or modify diff --git a/lisp/php-mode/php-local-manual.el b/lisp/php-mode/php-local-manual.el index ba4f854e..3fb47811 100644 --- a/lisp/php-mode/php-local-manual.el +++ b/lisp/php-mode/php-local-manual.el @@ -6,7 +6,6 @@ ;; Maintainer: USAMI Kenta ;; URL: https://github.com/emacs-php/php-mode/wiki/Local-PHP-Manual ;; Keywords: docs, php -;; Version: 2.0.0 ;; License: GPL-3.0-or-later ;; This program is free software; you can redistribute it and/or modify @@ -194,6 +193,7 @@ current `tags-file-name'." (setq php-local-manual--completion-table php-table)))) (defun php-local-manual-build-table-from-file (filename) + "Build a table of PHP function names from FILENAME." (let ((table (make-vector 1022 0)) (buf (find-file-noselect filename))) (with-current-buffer buf @@ -208,10 +208,11 @@ current `tags-file-name'." (defun php-local-manual-build-table-from-path (path) "Return list of PHP function name from `PATH' directory." - (cl-loop for file in (directory-files path nil "^function\\..+\\.html$") - if (string-match "\\.\\([-a-zA-Z_0-9]+\\)\\.html$" file) - collect (replace-regexp-in-string - "-" "_" (substring file (match-beginning 1) (match-end 1)) t))) + (save-match-data + (cl-loop for file in (directory-files path nil "^function\\..+\\.html$") + if (string-match "\\.\\([-a-zA-Z_0-9]+\\)\\.html$" file) + collect (replace-regexp-in-string + "-" "_" (substring file (match-beginning 1) (match-end 1)) t)))) (provide 'php-local-manual) ;;; php-local-manual.el ends here diff --git a/lisp/php-mode/php-mode-debug.el b/lisp/php-mode/php-mode-debug.el index efe6e48e..80d1a42c 100644 --- a/lisp/php-mode/php-mode-debug.el +++ b/lisp/php-mode/php-mode-debug.el @@ -5,7 +5,6 @@ ;; Author: USAMI Kenta ;; URL: https://github.com/emacs-php/php-mode ;; Keywords: maint -;; Version: 1.26.1 ;; License: GPL-3.0-or-later ;; This program is free software; you can redistribute it and/or modify diff --git a/lisp/php-mode/php-mode-pkg.el b/lisp/php-mode/php-mode-pkg.el index 927c4213..8e086c10 100644 --- a/lisp/php-mode/php-mode-pkg.el +++ b/lisp/php-mode/php-mode-pkg.el @@ -1,12 +1,9 @@ -(define-package "php-mode" "20250109.2103" "Major mode for editing PHP code" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "php-mode" "20250602.1308" + "Major mode for editing PHP code." '((emacs "27.1")) - :commit "0f756a8c0782ebdc00557addc68763305c91ca51" :maintainers - '(("USAMI Kenta" . "tadsan@zonu.me")) - :maintainer - '("USAMI Kenta" . "tadsan@zonu.me") - :keywords - '("languages" "php") - :url "https://github.com/emacs-php/php-mode") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/emacs-php/php-mode" + :commit "40b8abed3079771e060dd99a56703520dabf5be4" + :revdesc "40b8abed3079" + :keywords '("languages" "php") + :maintainers '(("USAMI Kenta" . "tadsan@zonu.me"))) diff --git a/lisp/php-mode/php-mode.el b/lisp/php-mode/php-mode.el index afd51294..a6303b0a 100644 --- a/lisp/php-mode/php-mode.el +++ b/lisp/php-mode/php-mode.el @@ -9,7 +9,8 @@ ;; Maintainer: USAMI Kenta ;; URL: https://github.com/emacs-php/php-mode ;; Keywords: languages php -;; Version: 1.26.1 +;; Package-Version: 20250602.1308 +;; Package-Revision: 40b8abed3079 ;; Package-Requires: ((emacs "27.1")) ;; License: GPL-3.0-or-later diff --git a/lisp/php-mode/php-project.el b/lisp/php-mode/php-project.el index 0b59e2ce..d7ee484b 100644 --- a/lisp/php-mode/php-project.el +++ b/lisp/php-mode/php-project.el @@ -5,7 +5,6 @@ ;; Author: USAMI Kenta ;; Keywords: tools, files ;; URL: https://github.com/emacs-php/php-mode -;; Version: 1.26.1 ;; License: GPL-3.0-or-later ;; This program is free software; you can redistribute it and/or modify diff --git a/lisp/php-mode/php.el b/lisp/php-mode/php.el index 2e05d2a5..3a51d29f 100644 --- a/lisp/php-mode/php.el +++ b/lisp/php-mode/php.el @@ -5,7 +5,6 @@ ;; Author: USAMI Kenta ;; Created: 5 Dec 2018 -;; Version: 1.26.1 ;; Keywords: languages, php ;; Homepage: https://github.com/emacs-php/php-mode ;; License: GPL-3.0-or-later @@ -49,12 +48,24 @@ :link '(url-link :tag "Official Site" "https://github.com/emacs-php/php-mode") :link '(url-link :tag "PHP Mode Wiki" "https://github.com/emacs-php/php-mode/wiki")) -(defcustom php-executable (or (executable-find "php") "/usr/bin/php") +(defcustom php-executable (or (executable-find "php") "php") "The location of the PHP executable." :group 'php :tag "PHP Executable" :type 'string) +(defcustom php-phpdbg-executable (list "phpdbg") + "The location of the PHPDBG executable." + :group 'php + :tag "PHP PHPDBG Executable" + :type '(repeat string)) + +(defcustom php-php-parse-executabe nil + "The location of the php-parse executable." + :group 'php + :tag "PHP php-parse Executable" + :type '(repeat string)) + (defcustom php-site-url "https://www.php.net/" "Default PHP.net site URL. @@ -325,12 +336,18 @@ can be used to match against definitions for that classlike." ;; First see if 'abstract' or 'final' appear, although really these ;; are not valid for all values of `type' that the function ;; accepts. - "^\\s-*\\(?:\\(?:abstract\\|final\\)\\s-+\\)?" + (eval-when-compile + (rx line-start + (* (syntax whitespace)) + (? (or "abstract" "final" "readonly") + (+ (syntax whitespace))))) ;; The classlike type type ;; Its name, which is the first captured group in the regexp. We ;; allow backslashes in the name to handle namespaces, but again ;; this is not necessarily correct for all values of `type'. + ;; (rx (+ (syntax whitespace)) + ;; (group (+ (or (syntax word) "\\" (syntax symbol))))) "\\s-+\\(\\(?:\\sw\\|\\\\\\|\\s_\\)+\\)"))) (defconst php-imenu-generic-expression-default @@ -465,7 +482,7 @@ can be used to match against definitions for that classlike." (defconst php--re-classlike-pattern (eval-when-compile - (php-create-regexp-for-classlike (regexp-opt '("class" "interface" "trait"))))) + (php-create-regexp-for-classlike (regexp-opt '("class" "interface" "trait" "enum"))))) (defvar php--analysis-syntax-table (eval-when-compile @@ -798,5 +815,29 @@ When `DOCUMENT-ROOT' is NIL, the document root is obtained from `ROUTER-OR-DIR'. #'file-exists-p)))) (find-file file)) + +(defun php-phpdbg-disassemble-file (file) + "Read PHP FILE and print opcodes." + (interactive (list (if (or buffer-file-name (zerop (prefix-numeric-value current-prefix-arg))) + buffer-file-name + (expand-file-name + (read-file-name "Select PHP file: " default-directory buffer-file-name))))) + (let ((args `(,@php-phpdbg-executable "-dopcache.enable_cli=1" "-p*" ,file))) + (compile (mapconcat #'shell-quote-argument args " ")))) + +(defun php-parse-file (file) + "Parse PHP FILE and print node tree." + (interactive (list (if (or buffer-file-name (zerop (prefix-numeric-value current-prefix-arg))) + buffer-file-name + (expand-file-name + (read-file-name "Select PHP file: " default-directory buffer-file-name))))) + (let* ((project-dir (php-project-get-root-dir)) + (executable (or php-php-parse-executabe + (file-executable-p (expand-file-name "vendor/bin/php-parse" project-dir)) + (executable-find "php-parse") + (user-error "`php-parse' command not found"))) + (args `(,@(if (listp executable) executable (list executable)) ,file))) + (compile (mapconcat #'shell-quote-argument args " ")))) + (provide 'php) ;;; php.el ends here diff --git a/lisp/pkg-info/pkg-info-pkg.el b/lisp/pkg-info/pkg-info-pkg.el index 6a178d09..28b1c071 100644 --- a/lisp/pkg-info/pkg-info-pkg.el +++ b/lisp/pkg-info/pkg-info-pkg.el @@ -1,14 +1,10 @@ -(define-package "pkg-info" "20150517.1143" "Information about packages" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "pkg-info" "20150517.1143" + "Information about packages." '((epl "0.8")) - :commit "4dbe328c9eced79e0004e3fdcd7bfb997a928be5" :authors - '(("Sebastian Wiesner" . "swiesner@lunaryorn.com")) - :maintainers - '(("Sebastian Wiesner" . "swiesner@lunaryorn.com")) - :maintainer - '("Sebastian Wiesner" . "swiesner@lunaryorn.com") - :keywords - '("convenience") - :url "https://github.com/lunaryorn/pkg-info.el") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/lunaryorn/pkg-info.el" + :commit "4dbe328c9eced79e0004e3fdcd7bfb997a928be5" + :revdesc "4dbe328c9ece" + :keywords '("convenience") + :authors '(("Sebastian Wiesner" . "swiesner@lunaryorn.com")) + :maintainers '(("Sebastian Wiesner" . "swiesner@lunaryorn.com"))) diff --git a/lisp/pkg-info/pkg-info.el b/lisp/pkg-info/pkg-info.el index 27052e4f..d277f764 100644 --- a/lisp/pkg-info/pkg-info.el +++ b/lisp/pkg-info/pkg-info.el @@ -5,7 +5,8 @@ ;; Author: Sebastian Wiesner ;; URL: https://github.com/lunaryorn/pkg-info.el ;; Keywords: convenience -;; Version: 0.7-cvs +;; Package-Version: 20150517.1143 +;; Package-Revision: 4dbe328c9ece ;; Package-Requires: ((epl "0.8")) ;; This file is not part of GNU Emacs. diff --git a/lisp/plantuml-mode/plantuml-mode-pkg.el b/lisp/plantuml-mode/plantuml-mode-pkg.el index 13b53c4a..41dafffa 100644 --- a/lisp/plantuml-mode/plantuml-mode-pkg.el +++ b/lisp/plantuml-mode/plantuml-mode-pkg.el @@ -1,8 +1,9 @@ -(define-package "plantuml-mode" "20191102.2056" "Major mode for PlantUML" - '((dash "2.0.0") +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "plantuml-mode" "20250613.1438" + "Major mode for PlantUML." + '((dash "2.0.0") (emacs "25.0")) - :commit "ea45a13707abd2a70df183f1aec6447197fc9ccc" :keywords - '("uml" "plantuml" "ascii")) -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/skuro/plantuml-mode" + :commit "dc0f497a67ee9b3d2e437e16023011780d0e8b05" + :revdesc "dc0f497a67ee" + :keywords '("uml" "plantuml" "ascii")) diff --git a/lisp/plantuml-mode/plantuml-mode.el b/lisp/plantuml-mode/plantuml-mode.el index e40ba0d0..034c96cd 100644 --- a/lisp/plantuml-mode/plantuml-mode.el +++ b/lisp/plantuml-mode/plantuml-mode.el @@ -6,8 +6,8 @@ ;; Author: Zhang Weize (zwz) ;; Maintainer: Carlo Sciolla (skuro) ;; Keywords: uml plantuml ascii -;; Version: 1.2.9 -;; Package-Version: 1.2.9 +;; Package-Version: 20250613.1438 +;; Package-Revision: dc0f497a67ee ;; Package-Requires: ((dash "2.0.0") (emacs "25.0")) ;; This file is free software; you can redistribute it and/or modify @@ -37,6 +37,8 @@ ;;; Change log: ;; +;; version 1.6.0, 2025-05-15 Fix server exec mode; various indentation enhancements and bug fixes; better preview buffer management +;; version 1.5.0, 2025-05-14 Fixed warnings with new Java versions #157; updated versions to let CI work again ;; version 1.4.1, 2019-09-03 Better indentation; more bugfixing; actually adding `executable' mode ;; version 1.4.0, 2019-08-21 Added `executable' exec mode to use locally installed `plantuml' binaries, various bugfixes ;; version 1.3.1, 2019-08-02 Fixed interactive behavior of `plantuml-set-exec-mode' @@ -76,8 +78,7 @@ (require 'dash) (require 'xml) -(defgroup plantuml-mode nil - "Major mode for editing plantuml file." +(defgroup plantuml-mode nil "Major mode for editing plantuml file." :group 'languages) (defcustom plantuml-jar-path @@ -94,7 +95,7 @@ (defvar plantuml-mode-hook nil "Standard hook for plantuml-mode.") -(defconst plantuml-mode-version "20190905.838" "The plantuml-mode version string.") +(defconst plantuml-mode-version "1.5.0" "The plantuml-mode version string.") (defvar plantuml-mode-debug-enabled nil) @@ -144,7 +145,9 @@ :group 'plantuml) (defcustom plantuml-indent-level 8 - "Indentation level of PlantUML lines") + "Indentation level of PlantUML lines" + :type 'natnum + :group 'plantuml) (defun plantuml-jar-render-command (&rest arguments) "Create a command line to execute PlantUML with arguments (as ARGUMENTS)." @@ -176,7 +179,7 @@ ;; PlantUML execution mode (defvar-local plantuml-exec-mode nil - "The Plantuml execution mode override. See `plantuml-default-exec-mode' for acceptable values.") + "The Plantuml execution mode override. See `plantuml-default-exec-mode' for acceptable values.") (defun plantuml-set-exec-mode (mode) "Set the execution mode MODE for PlantUML." @@ -404,7 +407,8 @@ Window is selected according to PREFIX: (when imagep (with-current-buffer buf (image-mode) - (set-buffer-multibyte t))))) + (set-buffer-multibyte t))) + (set-window-point (get-buffer-window buf 'visible) (point-min)))) (defun plantuml-jar-preview-string (prefix string buf) "Preview the diagram from STRING by running the PlantUML JAR. @@ -426,8 +430,9 @@ Put the result into buffer BUF. Window is selected according to PREFIX: "Encode the string STRING into a URL suitable for PlantUML server interactions." (let* ((coding-system (or buffer-file-coding-system "utf8")) - (encoded-string (base64-encode-string (encode-coding-string string coding-system) t))) - (concat plantuml-server-url "/" plantuml-output-type "/-base64-" encoded-string))) + (str (encode-coding-string string coding-system)) + (encoded-string (mapconcat (lambda(x)(format "%02X" x)) str))) + (concat plantuml-server-url "/" plantuml-output-type "/~h" encoded-string))) (defun plantuml-server-preview-string (prefix string buf) "Preview the diagram from STRING as rendered by the PlantUML server. @@ -482,9 +487,10 @@ Put the result into buffer BUF, selecting the window according to PREFIX: (defun plantuml-preview-string (prefix string) "Preview diagram from PlantUML sources (as STRING), using prefix (as PREFIX) to choose where to display it." - (let ((b (get-buffer plantuml-preview-buffer))) - (when b - (kill-buffer b))) + (when-let ((b (get-buffer plantuml-preview-buffer)) + (inhibit-read-only t)) + (with-current-buffer b + (erase-buffer))) (let* ((imagep (and (display-images-p) (plantuml-is-image-output-p))) @@ -516,8 +522,9 @@ Uses prefix (as PREFIX) to choose where to display it: "\n@enduml"))) (defun plantuml-preview-current-block (prefix) - "Preview diagram from the PlantUML sources from the previous @startuml to the next @enduml. -Uses prefix (as PREFIX) to choose where to display it: + "Preview diagram from the PlantUML sources for the current block. +The block is defined as starting from the previous @startuml to the next +@enduml. Uses prefix (as PREFIX) to choose where to display it: - 4 (when prefixing the command with C-u) -> new window - 16 (when prefixing the command with C-u C-u) -> new frame. - else -> new buffer" @@ -573,7 +580,7 @@ Uses prefix (as PREFIX) to choose where to display it: Plantuml elements like skinparam, rectangle, sprite, package, etc. The opening { has to be the last visible character in the line (whitespace might follow).") - (defvar plantuml-indent-regexp-note-start "^\s*\\(floating\s+\\)?[hr]?note\s+\\(right\\|left\\|top\\|bottom\\|over\\)[^:]*?$" "simplyfied regex; note syntax is especially inconsistent across diagrams") + (defvar plantuml-indent-regexp-note-start "^\s*\\(floating\s+\\)?[hr]?note\s+\\(right\\|left\\|top\\|bottom\\|over\\|as\\)[^:]*\\(\\:\\:[^:]+\\)?$" "simplyfied regex; note syntax is especially inconsistent across diagrams") (defvar plantuml-indent-regexp-group-start "^\s*\\(alt\\|else\\|opt\\|loop\\|par\\|break\\|critical\\|group\\)\\(?:\s+.+\\|$\\)" "Indentation regex for plantuml group elements that are defined for sequence diagrams. Two variants for groups: keyword is either followed by whitespace and some text @@ -589,6 +596,7 @@ or it is followed by line end.") (defvar plantuml-indent-regexp-newif-start "^\s*\\(?:else\\)?if\s+(.*)\s+then\s*.*$") (defvar plantuml-indent-regexp-loop-start "^\s*\\(?:repeat\s*\\|while\s+(.*).*\\)$") (defvar plantuml-indent-regexp-fork-start "^\s*\\(?:fork\\|split\\)\\(?:\s+again\\)?\s*$") + (defvar plantuml-indent-regexp-case-start "^\s*\\(?:switch\\|case\\)\s-*(.*)\s*$") (defvar plantuml-indent-regexp-macro-start "^\s*!definelong.*$") (defvar plantuml-indent-regexp-user-control-start "^.*'.*\s*PLANTUML_MODE_INDENT_INCREASE\s*.*$") (defvar plantuml-indent-regexp-start (list plantuml-indent-regexp-block-start @@ -601,6 +609,7 @@ or it is followed by line end.") plantuml-indent-regexp-newif-start plantuml-indent-regexp-loop-start plantuml-indent-regexp-fork-start + plantuml-indent-regexp-case-start plantuml-indent-regexp-title-start plantuml-indent-regexp-header-start plantuml-indent-regexp-footer-start @@ -620,7 +629,8 @@ or it is followed by line end.") (defvar plantuml-indent-regexp-oldif-end "^\s*\\(endif\\|else\\)\s*\\('.*\\)?$") (defvar plantuml-indent-regexp-newif-end "^\s*\\(endif\\|elseif\\|else\\)\s*.*$") (defvar plantuml-indent-regexp-loop-end "^\s*\\(repeat\s*while\\|endwhile\\)\s*.*$") - (defvar plantuml-indent-regexp-fork-end "^\s*\\(\\(fork\\|split\\)\s+again\\|end\s+\\(fork\\|split\\)\\)\s*$") + (defvar plantuml-indent-regexp-fork-end "^\s*\\(\\(fork\\|split\\)\s+again\\|end\s+\\(fork\\|split\\)\\)\s*\\(\{.*\}\\)?\s*$") + (defvar plantuml-indent-regexp-case-end "^\s*\\(case\s-*(.*)\\|endswitch\\)\s*\\('.*\\)?$") (defvar plantuml-indent-regexp-macro-end "^\s*!enddefinelong\s*\\('.*\\)?$") (defvar plantuml-indent-regexp-user-control-end "^.*'.*\s*PLANTUML_MODE_INDENT_DECREASE\s*.*$") (defvar plantuml-indent-regexp-end (list plantuml-indent-regexp-block-end @@ -633,6 +643,7 @@ or it is followed by line end.") plantuml-indent-regexp-newif-end plantuml-indent-regexp-loop-end plantuml-indent-regexp-fork-end + plantuml-indent-regexp-case-end plantuml-indent-regexp-title-end plantuml-indent-regexp-header-end plantuml-indent-regexp-footer-end @@ -723,12 +734,14 @@ Restore point to same position in text of the line as before indentation." (beginning-of-line) (indent-line-to (* plantuml-indent-level (plantuml-current-block-depth)))) - ;; restore position in text of line - (goto-char (- (line-end-position) original-position-eol)))) + ;; restore position in text of line, but not before the beginning of the + ;; current line + (goto-char (max (line-beginning-position) + (- (line-end-position) original-position-eol))))) ;;;###autoload -(add-to-list 'auto-mode-alist '("\\.\\(plantuml\\|pum\\|plu\\)\\'" . plantuml-mode)) +(add-to-list 'auto-mode-alist '("\\.\\(pu\\|uml\\|plantuml\\|pum\\|plu\\)\\'" . plantuml-mode)) ;;;###autoload (define-derived-mode plantuml-mode prog-mode "plantuml" diff --git a/lisp/polymode/polymode-base.el b/lisp/polymode/polymode-base.el index 1085e201..633913d9 100644 --- a/lisp/polymode/polymode-base.el +++ b/lisp/polymode/polymode-base.el @@ -51,7 +51,9 @@ (define-hostmode poly-js-hostmode :mode 'js-mode) (define-obsolete-variable-alias 'pm-host/latex 'poly-latex-hostmode "v0.2") -(define-hostmode poly-latex-hostmode :mode 'latex-mode) +(define-hostmode poly-latex-hostmode + :mode 'LaTeX-mode + :fallback-mode 'latex-mode) (define-obsolete-variable-alias 'pm-host/html 'poly-html-hostmode "v0.2") (define-hostmode poly-html-hostmode @@ -88,27 +90,27 @@ ;;; ROOT POLYMODES ;; These are simple generic configuration objects. More specialized polymodes -;; should clone these. +;; should extend (aka clone) these. (define-obsolete-variable-alias 'pm-poly/brew 'poly-brew-root-polymode "v0.2") (defvar poly-brew-root-polymode (pm-polymode :name "brew-root" :hostmode 'poly-text-hostmode) - "Brew root configuration.") + "Brew root polymode.") (define-obsolete-variable-alias 'pm-poly/html 'poly-html-root-polymode "v0.2") (defvar poly-html-root-polymode (pm-polymode :name "html-root" :hostmode 'poly-html-hostmode) - "HTML root configuration.") + "HTML root polymode.") (define-obsolete-variable-alias 'pm-poly/C++ 'poly-c++-root-polymode "v0.2") (defvar poly-c++-root-polymode (pm-polymode :name "c++-root" :hostmode 'poly-c++-hostmode) - "C++ root configuration.") + "C++ root polymode.") (define-obsolete-variable-alias 'pm-poly/latex 'poly-latex-root-polymode "v0.2") (defvar poly-latex-root-polymode (pm-polymode :name "latex-root" :hostmode 'poly-latex-hostmode) - "LaTeX root configuration.") + "LaTeX root polymode.") (defvar poly-js-root-polymode (pm-polymode :name "js-root" :hostmode 'poly-js-hostmode) diff --git a/lisp/polymode/polymode-classes.el b/lisp/polymode/polymode-classes.el index fd83341a..696782c9 100644 --- a/lisp/polymode/polymode-classes.el +++ b/lisp/polymode/polymode-classes.el @@ -218,9 +218,9 @@ instantiated from this class or a subclass of this class.") :documentation "Emacs major mode for the chunk's body. If :mode slot is nil (anonymous chunkmodes), use the value of -`polymode-default-inner-mode' is when set, or use the value of +`polymode-default-inner-mode' when set, or use the value of the slot :fallback-mode. A special value 'host means to use the -host mode (useful auto-chunkmodes only).") +host mode (useful for `pm-inner-auto-chunkmode' only).") (fallback-mode :initarg :fallback-mode :initform 'poly-fallback-mode @@ -335,11 +335,12 @@ is of this chunkmode.") :type symbol :custom symbol :documentation - "Major mode to keep in when polymode switches implementation buffers. -When a special symbol 'host, keep in hostmode. The buffer with -this major mode must be installed by one of the innermodes or the -hostmode. If multiple innermodes installed buffers of this mode, -the first buffer is used.") + "Major mode to keep the chunk when the point is inside the chunk. +When a special symbol 'host, keep in hostmode. This is useful when you +want the inner mode to be responsible for font-locking but the host mode +for the edditing capabilities. The buffer with this major mode must be +installed by one of the innermodes or the hostmode. If multiple +innermodes installed buffers of this mode, the first buffer is used.") (-buffer :type (or null buffer) @@ -418,8 +419,8 @@ take either values 1 (forwards search) or -1 (backward search) and behave similarly to how search is performed by `re-search-forward' function. This function must return either nil (no match) or a (cons BEG END) representing the head span. -See the code of `pm-fun-matcher' for how REGEXP and (REGEXP . -SUB-MATCH) are converted to a function internally..") +See `pm-fun-matcher' for how polymode internally converts a REGEXP or +(REGEXP . SUB-MATCH) into such a function.") (tail-matcher :initarg :tail-matcher :type (or string cons function) diff --git a/lisp/polymode/polymode-compat.el b/lisp/polymode/polymode-compat.el index fa392e9f..0ac02f55 100644 --- a/lisp/polymode/polymode-compat.el +++ b/lisp/polymode/polymode-compat.el @@ -3,7 +3,6 @@ ;; Author: Vitalie Spinu ;; Maintainer: Vitalie Spinu ;; Copyright (C) 2013-2022 Free Software Foundation, Inc. -;; Version: 0.1 ;; URL: https://github.com/polymode/polymode ;; Keywords: emacs ;; @@ -72,8 +71,6 @@ Elements of ALIST that are not conses are ignored." ;;; Various Wrappers for Around Advice -(defvar *span* nil) - ;; advice doesn't provide named symbols. So we need to define specialized ;; wrappers for some key functions (unfinished) (defmacro pm-define-wrapp-protected (fun) @@ -215,8 +212,7 @@ are passed to ORIG-FUN." ;; REPLACE: ;; before-change:(obeg,oend)=(50,56) ;; lsp-on-change:(nbeg,nend,olen)=(50,60,6) - -(defun pm--lsp-text-document-content-change-event (beg end len) +(defun pm--lsp-buffer-content-document-content-change-event (beg end len) "Make a TextDocumentContentChangeEvent body for BEG to END, of length LEN." (if (zerop len) ;; insertion @@ -228,7 +224,6 @@ are passed to ORIG-FUN." (pm--lsp-change-event beg end-pos text)) (pm--lsp-full-change-event)))) -(defvar-local pm--lsp-before-change-end-position nil) (defun pm--lsp-position (pos) (save-restriction (widen) @@ -248,42 +243,46 @@ are passed to ORIG-FUN." :text text)) (defun pm--lsp-full-change-event () - (list :text (pm--lsp-text))) + (list :text (pm--lsp-buffer-content))) -(defun pm--lsp-text (&optional beg end) - (save-restriction - (widen) - (setq beg (or beg (point-min))) - (setq end (or end (point-max))) - (let ((cmode major-mode) - (end-eol (save-excursion (goto-char end) - (point-at-eol))) - line-acc acc) - (pm-map-over-modes - (lambda (sbeg send) - (let ((beg1 (max sbeg beg)) - (end1 (min send end)) - (rem)) - (if (eq cmode major-mode) - (progn - (when (eq sbeg beg1) - ;; first line of mode; use line-acc - (setq acc (append line-acc acc)) - (setq line-acc nil)) - ;; if cur-mode follows after end on same line, accumulate the - ;; last line but not the actual text - (when (< beg1 end) - (push (buffer-substring-no-properties beg1 end1) acc))) - (goto-char beg1) - (if (<= end1 (point-at-eol)) - (when (< beg1 end1) ; don't accumulate on last line - (push (make-string (- end1 beg1) ? ) line-acc)) - (while (< (point-at-eol) end1) - (push "\n" acc) - (forward-line 1)) - (setq line-acc (list (make-string (- end1 (point)) ? ))))))) - beg end-eol) - (apply #'concat (reverse acc))))) +(defun pm--lsp-buffer-content (&optional beg end) + "Get text between BEG and END cleaned from non-current mode content. +The text from non-current mode is replaced with whitespaces, thus +preserving locations arriving from LSP intact." + (pm-with-synchronized-points + (save-excursion + (save-restriction + (widen) + (setq beg (or beg (point-min))) + (setq end (or end (point-max))) + (let ((cmode major-mode) + (end-eol (save-excursion (goto-char end) + (line-end-position))) + line-acc acc) + (pm-map-over-modes + (lambda (sbeg send) + (let ((beg1 (max sbeg beg)) + (end1 (min send end))) + (if (eq cmode major-mode) + (progn + (when (eq sbeg beg1) + ;; first line of mode; use line-acc + (setq acc (append line-acc acc)) + (setq line-acc nil)) + ;; if cur-mode follows after end on same line, + ;; accumulate the last line but not the actual text + (when (< beg1 end) + (push (buffer-substring-no-properties beg1 end1) acc))) + (goto-char beg1) + (if (<= end1 (line-end-position)) + (when (< beg1 end1) ; don't accumulate on last line + (push (make-string (- end1 beg1) ? ) line-acc)) + (while (< (line-end-position) end1) + (push "\n" acc) + (forward-line 1)) + (setq line-acc (list (make-string (- end1 (point)) ? ))))))) + beg end-eol) + (apply #'concat (reverse acc))))))) ;; We cannot compute original change location when modifications are complex ;; (aka multiple changes are combined). In those cases we send an entire @@ -294,18 +293,20 @@ are passed to ORIG-FUN." (and (eq beg (car bcr)) (eq len (- (cdr bcr) (car bcr)))))) -;; advises (defun polymode-lsp-buffer-content (orig-fun) + "In polymode buffers, replace other modes' content with whitespaces. +Use as around advice for lsp--buffer-content." (if (and polymode-mode pm/polymode) - (pm--lsp-text) + (pm--lsp-buffer-content) (funcall orig-fun))) (defun polymode-lsp-change-event (orig-fun beg end len) (if (and polymode-mode pm/polymode) - (pm--lsp-text-document-content-change-event beg end len) + (pm--lsp-buffer-content-document-content-change-event beg end len) (funcall orig-fun beg end len))) -(defvar-local polymode-lsp-integration t) +(defvar-local polymode-lsp-integration t + "Non-nil if lsp polymode integration should be enabled for this buffer.") (with-eval-after-load "lsp-mode" (when polymode-lsp-integration @@ -319,9 +320,6 @@ are passed to ORIG-FUN." (pm-around-advice 'lsp--buffer-content #'polymode-lsp-buffer-content) (pm-around-advice 'lsp--text-document-content-change-event #'polymode-lsp-change-event))) -;; (advice-remove 'lsp--buffer-content #'polymode-lsp-buffer-content) -;; (advice-remove 'lsp--text-document-content-change-event #'polymode-lsp-change-event) - ;;; Flyspel (defun pm--flyspel-dont-highlight-in-chunkmodes (beg end _poss) @@ -428,32 +426,29 @@ changes." ;;; DESKTOP SAVE #194 #240 -;; NB: desktop-save will not save indirect buffer. -;; For base buffer, if it's hidden as per #34, we will save it unhide by removing left whitespaces. +;; NB: We advice desktop-save functionality to not save indirect buffers and for base buffers, +;; save the buffers with un-hidden name. (defun polymode-fix-desktop-buffer-info (fn buffer) - "Unhide poly-mode base buffer which is hidden as per #34. -This is done by modifying `uniquify-buffer-base-name' to `pm--core-buffer-name'." + "Unhide poly-mode base buffer which is hidden by removing +the leading spaces from the name." (with-current-buffer buffer (let ((out (funcall fn buffer))) (when (and polymode-mode (not (buffer-base-buffer)) (not (car out))) - (setf (car out) pm--core-buffer-name)) + (setf (car out) (replace-regexp-in-string "^ +" "" (buffer-name buffer)))) out))) -(declare-function desktop-buffer-info "desktop") -(with-eval-after-load "desktop" - (advice-add #'desktop-buffer-info :around #'polymode-fix-desktop-buffer-info)) - (defun polymode-fix-desktop-save-buffer-p (_ bufname &rest _args) "Dont save polymode buffers which are indirect buffers." (with-current-buffer bufname - (not (and polymode-mode - (buffer-base-buffer))))) + (not (and polymode-mode (buffer-base-buffer))))) +(declare-function desktop-buffer-info "desktop") (declare-function desktop-save-buffer-p "desktop") (with-eval-after-load "desktop" + (advice-add #'desktop-buffer-info :around #'polymode-fix-desktop-buffer-info) (advice-add #'desktop-save-buffer-p :before-while #'polymode-fix-desktop-save-buffer-p)) diff --git a/lisp/polymode/polymode-core.el b/lisp/polymode/polymode-core.el index df79188c..4c8e150d 100644 --- a/lisp/polymode/polymode-core.el +++ b/lisp/polymode/polymode-core.el @@ -37,8 +37,11 @@ (require 'cl-lib) (require 'derived)) + ;;; ESSENTIAL DECLARATIONS + +;; fixme: rename into pm-active-span or something similar (defvar *span* nil) (defvar-local pm/polymode nil) (put 'pm/polymode 'permanent-local t) @@ -82,6 +85,23 @@ (with-no-warnings (eieio-object-name-string obj))) + + +;; CORE EMACS COMPATS + +;;; emacs 30 +(unless (fboundp 'major-mode-remap) + (defvar major-mode-remap-alist nil) + (defvar major-mode-remap-defaults nil) + (defalias 'major-mode-remap + (lambda (mode) + "Return the function to use to enable MODE." + (or (cdr (or (assq mode major-mode-remap-alist) + (assq mode major-mode-remap-defaults))) + mode)))) + + + ;; SHIELDS (defvar pm-allow-after-change-hook t) @@ -104,14 +124,22 @@ (defvar pm-initialization-in-progress nil) (defvar pm-hide-implementation-buffers t) -(defvar-local pm--core-buffer-name nil) +(defvar-local pm--base-buffer-name nil + "Local name of the base buffer in the base buffer. +Currently, we only use it to track renames of the buffer.") -(defun pm--hidden-buffer-name () - (generate-new-buffer-name (concat " " pm--core-buffer-name))) -(defun pm--visible-buffer-name () - (generate-new-buffer-name - (replace-regexp-in-string "^ +" "" pm--core-buffer-name))) +(defun pm--buffer-name (&optional hidden) + (let ((name (if-let* ((bbuf (buffer-base-buffer))) + (let ((postfix (replace-regexp-in-string "poly-\\|-mode" "" (symbol-name major-mode))) + (base-name (buffer-local-value 'pm--base-buffer-name bbuf))) + (format "%s[%s]" (replace-regexp-in-string "^ " "" base-name) + (or (cdr (assoc postfix polymode-mode-abbrev-aliases)) + postfix))) + pm--base-buffer-name))) + (when hidden + (setq name (concat " " name))) + (generate-new-buffer-name name))) @@ -186,9 +214,9 @@ inner chunk (such as in markdown mode), the detected symbol might not correspond to the desired mode. This alist maps discovered symbols into desired modes. For example - (add-to-list 'polymode-mode-name-aliases '(julia . ess-julia)) + (add-to-list \\='polymode-mode-name-aliases \\='(julia . ess-julia)) -will cause installation of `ess-julia-mode' in markdown ```julia chunks." +will cause installation of `ess-julia-mode' in markdown julia chunks." :group 'polymode :type 'alist) @@ -229,6 +257,7 @@ The hook is run in chunkmode's body buffer from `pm-initialze' objects provides same functionality for narrower scope. See also `polymode-init-host-hook'.") + ;;; Mode Macros @@ -641,12 +670,12 @@ forward." (block-col (if (< cur-indent cur-col) cur-indent (1- cur-indent))) - (end (point-at-eol))) + (end (line-end-position))) (forward-line 1) (while (and (not (eobp)) (or (looking-at-p "[ \t]*$") (and (> (current-indentation) block-col) - (setq end (point-at-eol))))) + (setq end (line-end-position))))) (forward-line 1)) ;; end at bol for the sake of indentation (setq end (min (point-max) (1+ end))) @@ -866,7 +895,7 @@ forward spans from pos." (cons (point-max) (point-max))))) (when can-overlap (goto-char (cdr head)) - (when-let ((hbeg (car (funcall head-matcher 1)))) + (when-let* ((hbeg (car (funcall head-matcher 1)))) (when (< hbeg (car tail)) (setq tail (cons hbeg hbeg))))) (list (car head) (cdr head) (car tail) (cdr tail)))))))) @@ -918,7 +947,7 @@ TYPE is either a symbol or a list of symbols of span types." (unless pm-initialization-in-progress (when global-hook (run-hooks global-hook)) - (pm--run-hooks object :init-functions (or type 'host)))) + (pm--run-hooks object 'init-functions (or type 'host)))) (defun pm--collect-parent-slots (object slot &optional do-when inclusive) "Descend into parents of OBJECT and return a list of SLOT values. @@ -932,7 +961,7 @@ of the first object for which DO-WHEN failed." (failed nil)) (while inst (if (not (slot-boundp inst slot)) - (setq inst (and (slot-boundp inst :parent-instance) + (setq inst (and (slot-boundp inst 'parent-instance) (eieio-oref inst 'parent-instance))) (push (eieio-oref inst slot) vals) (setq inst (and @@ -942,7 +971,7 @@ of the first object for which DO-WHEN failed." (or (funcall do-when inst) (and inclusive (setq failed t))))) - (slot-boundp inst :parent-instance) + (slot-boundp inst 'parent-instance) (eieio-oref inst 'parent-instance))))) vals)) @@ -1048,7 +1077,7 @@ switch." ((eq mode 'host) (pm-base-buffer)) (mode (or (pm-get-buffer-of-mode mode) ;; not throwing because in auto-modes mode might not - ;; be installed yet and there is no way install it + ;; be installed yet and there is no way to install it ;; from here buffer)))))) ;; no further action if BUFFER is already the current buffer @@ -1056,10 +1085,12 @@ switch." (when (and own visibly) (run-hook-with-args 'polymode-before-switch-buffer-hook cbuf buffer)) - (pm--move-vars polymode-move-these-vars-from-base-buffer - (pm-base-buffer) buffer) - (pm--move-vars polymode-move-these-vars-from-old-buffer - cbuf buffer) + + (pm--move-vars polymode-move-these-vars-from-base-buffer (pm-base-buffer) buffer) + (pm--move-vars polymode-move-these-vars-from-old-buffer cbuf buffer) + + ;; synchronize again just in case + (pm--synchronize-points cbuf) (if visibly ;; Slow, visual selection. Don't perform in foreign indirect buffers. (when own @@ -1078,7 +1109,7 @@ switch." (hlf header-line-format)) (when pm-hide-implementation-buffers - (rename-buffer (pm--hidden-buffer-name))) + (rename-buffer (pm--buffer-name 'hidden))) (setq pm/current nil) @@ -1089,8 +1120,16 @@ switch." (pm--move-overlays old-buffer new-buffer) - (switch-to-buffer new-buffer) + (let ((dedicated-flag (window-dedicated-p))) + (when dedicated-flag + (set-window-dedicated-p nil nil)) + (set-buffer new-buffer) + (set-window-buffer nil new-buffer 'keep-margins) + (when dedicated-flag + (set-window-dedicated-p nil dedicated-flag))) + (bury-buffer-internal old-buffer) + ;; remove old-buffer form window-prev-buffers (set-window-prev-buffers nil (assq-delete-all old-buffer (window-prev-buffers nil))) ;; if header line is active in some modes, make it active everywhere @@ -1100,14 +1139,13 @@ switch." (setq pm/current t) - ;; fixme: what is the right way to do this ... activate-mark-hook? + (set-mark mkt) (if (not ractive) (deactivate-mark) - (set-mark mkt) (activate-mark)) (when pm-hide-implementation-buffers - (rename-buffer (pm--visible-buffer-name))) + (rename-buffer (pm--buffer-name))) ;; avoid display jumps (goto-char point) @@ -1115,16 +1153,62 @@ switch." (set-window-start (get-buffer-window new-buffer t) window-start)) (run-hook-with-args 'polymode-after-switch-buffer-hook old-buffer new-buffer) - (pm--run-hooks pm/polymode :switch-buffer-functions old-buffer new-buffer) - (pm--run-hooks pm/chunkmode :switch-buffer-functions old-buffer new-buffer))) + (pm--run-hooks pm/polymode 'switch-buffer-functions old-buffer new-buffer) + (pm--run-hooks pm/chunkmode 'switch-buffer-functions old-buffer new-buffer))) + + +(defvar polymode-copy-overlays-with-these-properties-from-old-buffer '(invisible) + "Overlays with these non-nil properties should be copied instead of moved. +The overlay is matched if `pm--overlay-match-p' returns non-nil with +any of the properties in the list.") + +(defvar polymode-ignore-overlays-with-these-properties + '(linum-str yas--snippet (face region show-paren-match hl-line)) + "Overlays with these properties should be left untouched when switching polymode buffers. +The overlay is matched if `pm--overlay-match-p' returns non-nil with any +of the properties in the list.") + +(defun pm--overlay-match-p (overlay prop) + "Return non-nil if the overlay's properties match PROP. +When PROP is a symbol, return non-nil if the overlay contains that property +and its value is non-nil. When PROP is a list, return non-nil if the value +of the overlay's property (car PROP) is one of the (cdr PROP). +" + (if (symbolp prop) + (overlay-get overlay prop) + (memq (overlay-get overlay (car prop)) (cdr prop)))) (defun pm--move-overlays (from-buffer to-buffer) + "Delete all overlays in TO-BUFFER, then copy FROM-BUFFER overlays to it." + ;; Some overlays need to be copied to avoid changing the display in other windows + ;; which display same polymode buffer + ;; #348 for an example where overaly with invisible property should be copied + ;; #350 for examples where overlays should be moved (most of them) + + ;; Ensure that the overlays which we will copy are not already in the to-buffer. This + ;; is a rough brush, but there is no way currently to identify the overlays more + ;; precisely, and it's probably not worth the extra effort. + (with-current-buffer to-buffer + (mapc (lambda (o) + (when + (cl-some (lambda (p) (pm--overlay-match-p o p)) + polymode-copy-overlays-with-these-properties-from-old-buffer) + (delete-overlay o))) + (overlays-in 1 (1+ (buffer-size))))) + (with-current-buffer from-buffer (mapc (lambda (o) - (unless (or (overlay-get o 'linum-str) - (overlay-get o 'yas--snippet)) - (move-overlay o (overlay-start o) (overlay-end o) to-buffer))) - (overlays-in 1 (1+ (buffer-size)))))) + (unless (cl-some (lambda (p) (pm--overlay-match-p o p)) + polymode-ignore-overlays-with-these-properties) + (if (cl-some (lambda (p) (pm--overlay-match-p o p)) + polymode-copy-overlays-with-these-properties-from-old-buffer) + (let ((o-copy (copy-overlay o)) + (start (overlay-start o)) + (end (overlay-end o))) + (move-overlay o-copy start end to-buffer)) + (move-overlay o (overlay-start o) (overlay-end o) to-buffer)))) + (overlays-in 1 (1+ (buffer-size))))) + ) (defun pm--move-vars (vars from-buffer &optional to-buffer) (let ((to-buffer (or to-buffer (current-buffer)))) @@ -1198,7 +1282,6 @@ spans. Two adjacent spans might have same major mode, thus (widen) (let* ((hostmode (eieio-oref pm/polymode '-hostmode)) (pos beg) - (ttype 'dummy) (span (pm-innermost-span beg)) (nspan span) (ttype (pm-true-span-type span)) @@ -1395,17 +1478,22 @@ Placed with high priority in `after-change-functions' hook." ;; (remove-hook 'after-change-functions 'jit-lock-after-change t)) )))) -(defun pm--run-other-hooks (allow syms hook &rest args) - (when (and allow polymode-mode pm/polymode) - (dolist (sym syms) +(defun pm--run-hooks-in-other-buffers (function-names hook-name &rest args) + "Run each function in FUNCTION-NAMES in other polymode buffers. +But, only if it is part of the hook HOOK-NAME. Each function is called +witih arguments ARGS." + (when (and polymode-mode pm/polymode) + (let ((cbuf (current-buffer))) (dolist (buf (eieio-oref pm/polymode '-buffers)) (when (buffer-live-p buf) - (unless (eq buf (current-buffer)) + (unless (eq buf cbuf) (with-current-buffer buf - (when (memq sym (symbol-value hook)) - (if args - (apply sym args) - (funcall sym)))))))))) + (let ((hooks (symbol-value hook-name))) + (dolist (sym function-names) + (when (memq sym hooks) + (if args + (apply sym args) + (funcall sym)))))))))))) ;; BUFFER SAVE ;; TOTHINK: add auto-save-hook? @@ -1423,17 +1511,28 @@ declared in the base buffer is triggered.") "Run after-save-hooks in indirect buffers. Only those in `polymode-run-these-after-save-functions-in-other-buffers' are triggered if present." - (pm--run-other-hooks t - polymode-run-these-before-save-functions-in-other-buffers - 'after-save-hook)) + (pm--run-hooks-in-other-buffers + polymode-run-these-before-save-functions-in-other-buffers + 'after-save-hook)) (defun polymode-after-save () "Run after-save-hooks in indirect buffers. Only those in `polymode-run-these-after-save-functions-in-other-buffers' are triggered if present." - (pm--run-other-hooks t - polymode-run-these-after-save-functions-in-other-buffers - 'after-save-hook)) + (let ((new-name (replace-regexp-in-string "^ +" "" (buffer-name)))) + (unless (equal new-name pm--base-buffer-name) + (let ((cbuf (current-buffer))) + ;; Ensure we are in the base-buffer + (cl-assert (eq (buffer-base-buffer) nil)) + (setq pm--base-buffer-name new-name) + ;; Rename indirect buffers (#346) + (dolist (buf (eieio-oref pm/polymode '-buffers)) + (unless (eq buf cbuf) + (with-current-buffer buf + (rename-buffer (pm--buffer-name (not (get-buffer-window buf 'visible)))))))))) + (pm--run-hooks-in-other-buffers + polymode-run-these-after-save-functions-in-other-buffers + 'after-save-hook)) ;; change hooks @@ -1442,30 +1541,36 @@ are triggered if present." (defvar polymode-run-these-after-change-functions-in-other-buffers nil "After-change functions to run in all other buffers.") +;; FIXME: LSP specific; move this to compat somehow +(declare-function pm--lsp-position "polymode-compat") +(defvar-local pm--lsp-before-change-end-position nil) + (defun polymode-before-change (beg end) "Polymode before-change fixes. Run `polymode-run-these-before-change-functions-in-other-buffers'. Placed with low priority in `before-change-functions' hook." (pm--prop-put :before-change-range (cons beg end)) - ;; FIXME: LSP specific move this out somehow (when (boundp 'lsp-mode) (dolist (buf (eieio-oref pm/polymode '-buffers)) (with-current-buffer buf (when lsp-mode (setq pm--lsp-before-change-end-position (pm--lsp-position end)))))) - (pm--run-other-hooks pm-allow-before-change-hook - polymode-run-these-before-change-functions-in-other-buffers - 'before-change-functions - beg end)) + (when pm-allow-before-change-hook + (pm--run-hooks-in-other-buffers + polymode-run-these-before-change-functions-in-other-buffers + 'before-change-functions + beg end))) (defun polymode-after-change (beg end len) "Polymode after-change fixes. Run `polymode-run-these-after-change-functions-in-other-buffers'. Placed with low priority in `after-change-functions' hook." - (pm--run-other-hooks pm-allow-after-change-hook - polymode-run-these-after-change-functions-in-other-buffers - 'after-change-functions - beg end len)) + ;; ensure points are synchronized (after-change runs BEFORE post-command-hook) + (when pm-allow-after-change-hook + (pm--run-hooks-in-other-buffers + polymode-run-these-after-change-functions-in-other-buffers + 'after-change-functions + beg end len))) (defvar polymode-run-these-pre-commands-in-other-buffers nil "These commands, if present in `pre-command-hook', are run in other bufers.") @@ -1477,13 +1582,13 @@ Placed with low priority in `after-change-functions' hook." Currently synchronize points and runs `polymode-run-these-pre-commands-in-other-buffers' if any. Runs in local `pre-command-hook' with very high priority." - (pm--synchronize-points (current-buffer)) - (condition-case err - (pm--run-other-hooks pm-allow-pre-command-hook - polymode-run-these-pre-commands-in-other-buffers - 'pre-command-hook) - (error (message "error polymode-pre-command run other hooks: (%s) %s" - (point) (error-message-string err))))) + (when pm-allow-pre-command-hook + (condition-case err + (pm--run-hooks-in-other-buffers + polymode-run-these-pre-commands-in-other-buffers + 'pre-command-hook) + (error (message "error polymode-pre-command run other hooks: (%s) %s" + (point) (error-message-string err)))))) (defun polymode-post-command () "Select the buffer relevant buffer and run post-commands in other buffers. @@ -1503,9 +1608,10 @@ appropriate. This function is placed into local (condition-case err (if (eq cbuf (current-buffer)) ;; 1. same buffer, run hooks in other buffers - (pm--run-other-hooks pm-allow-post-command-hook - polymode-run-these-post-commands-in-other-buffers - 'post-command-hook) + (when pm-allow-post-command-hook + (pm--run-hooks-in-other-buffers + polymode-run-these-post-commands-in-other-buffers + 'post-command-hook)) ;; 2. Run all hooks in this (newly switched to) buffer (run-hooks 'post-command-hook)) (error (message "error in polymode-post-command run other hooks: (%s) %s" @@ -1916,11 +2022,12 @@ Return FALLBACK if non-nil, otherwise the value of (fboundp polymode-default-inner-mode)) polymode-default-inner-mode) (when (or (eq fallback 'host) - (fboundp fallback)) + (and (fboundp fallback) + (functionp fallback))) fallback) 'poly-fallback-mode)) ;; proper mode symbol - ((and (symbolp name) (fboundp name) name)) + ((and (symbolp name) (and (fboundp name) (functionp name)) name)) ;; compute from name ((let* ((str (pm--symbol-name (or (cdr (assq (intern (pm--symbol-name name)) @@ -1929,28 +2036,30 @@ Return FALLBACK if non-nil, otherwise the value of (mname (if (string-match-p "-mode$" str) str (concat str "-mode")))) - (or - ;; direct search - (let ((mode (intern mname))) - (when (fboundp mode) - mode)) - ;; downcase - (let ((mode (intern (downcase mname)))) - (when (fboundp mode) - mode)) - ;; auto-mode alist - (let ((dummy-file (concat "a." str))) - (cl-loop for (k . v) in auto-mode-alist - if (and (string-match-p k dummy-file) - (not (string-match-p "^poly-" (symbol-name v)))) - return v)) - (when (or (eq polymode-default-inner-mode 'host) - (fboundp polymode-default-inner-mode)) - polymode-default-inner-mode) - (when (or (eq fallback 'host) - (fboundp fallback)) - fallback) - 'poly-fallback-mode)))))) + (major-mode-remap + (or + ;; direct search + (let ((mode (intern mname))) + (when (and (fboundp mode) (functionp mode)) + mode)) + ;; downcase + (let ((mode (intern (downcase mname)))) + (when (and (fboundp mode) (functionp mode)) + mode)) + ;; auto-mode alist + (let ((dummy-file (concat "a." str))) + (cl-loop for (k . v) in auto-mode-alist + if (and (string-match-p k dummy-file) + (not (string-match-p "^poly-" (symbol-name v)))) + return v)) + (when (or (eq polymode-default-inner-mode 'host) + (and (fboundp polymode-default-inner-mode) + (functionp polymode-default-inner-mode))) + polymode-default-inner-mode) + (when (or (eq fallback 'host) + (and (fboundp fallback) (functionp fallback))) + fallback) + 'poly-fallback-mode))))))) (defun pm--oref-with-parents (object slot) "Merge slots SLOT from the OBJECT and all its parent instances." @@ -1959,7 +2068,7 @@ Return FALLBACK if non-nil, otherwise the value of (setq VALS (append (and (slot-boundp object slot) ; don't cascade (eieio-oref object slot)) VALS) - object (and (slot-boundp object :parent-instance) + object (and (slot-boundp object 'parent-instance) (eieio-oref object 'parent-instance)))) VALS)) @@ -2032,18 +2141,21 @@ Elements of LIST can be either strings or symbols." (when (and polymode-mode (buffer-live-p buffer)) (let* ((bufs (eieio-oref pm/polymode '-buffers)) - ;; (buffer (or buffer - ;; (cl-loop for b in bufs - ;; if (and (buffer-live-p b) - ;; (buffer-local-value 'pm/current b)) - ;; return b) - ;; (current-buffer))) (pos (with-current-buffer buffer (point)))) (dolist (b bufs) (when (buffer-live-p b) (with-current-buffer b (goto-char pos))))))) +(defmacro pm-with-synchronized-points (&rest body) + "Run BODY and ensure the points in all polymode buffers are +synchronized before and after BODY." + (declare (indent 0) (debug (body))) + (pm--synchronize-points) + `(prog1 + ,@body + (pm--synchronize-points))) + (defun pm--completing-read (prompt collection &optional predicate require-match initial-input hist def inherit-input-method) ;; Wrapper for `completing-read'. diff --git a/lisp/polymode/polymode-debug.el b/lisp/polymode/polymode-debug.el index 008253c4..c1036fd1 100644 --- a/lisp/polymode/polymode-debug.el +++ b/lisp/polymode/polymode-debug.el @@ -104,9 +104,7 @@ Key bindings: (pm-base-buffer) (with-current-buffer (pm-base-buffer) (point)) (buffer-name) (point) (get-buffer-window (pm-base-buffer)) - (with-current-buffer (pm-base-buffer) (window-point)) - ;; FIXME: This arg is not used. - (window-point)))) + (with-current-buffer (pm-base-buffer) (window-point))))) ;; (defun pm-debug-beore-change (&rest r) ;; (pm--debug-report-point "|before|" this-command)) @@ -420,6 +418,8 @@ currently traced functions." (setq args "[...]")) (funcall orig-fn fn level args context))) +(declare-function trace-entry-message "ext:") +(declare-function trace-exit-message "ext:") (advice-add #'trace-entry-message :around #'pm-trace--fix-args-for-tracing) (advice-add #'trace-exit-message :around #'pm-trace--fix-args-for-tracing) ;; (advice-remove #'trace-entry-message #'pm-trace--fix-args-for-tracing) diff --git a/lisp/polymode/polymode-export.el b/lisp/polymode/polymode-export.el index ac4ce72b..faeca769 100644 --- a/lisp/polymode/polymode-export.el +++ b/lisp/polymode/polymode-export.el @@ -351,7 +351,7 @@ If NO-ASK-IF-1 is non-nil, don't ask if there is only one exporter." (interactive) (unless pm/polymode (error "No pm/polymode object found. Not in polymode buffer?")) - (let* ((weavers (delete-dups (pm--oref-with-parents pm/polymode :weavers))) + (let* ((weavers (delete-dups (pm--oref-with-parents pm/polymode 'weavers))) (exporters (pm--abrev-names "pm-exporter/\\|-exporter" (cl-delete-if-not @@ -368,7 +368,7 @@ If NO-ASK-IF-1 is non-nil, don't ask if there is only one exporter." when (pm--selector-match el (concat "dummy." (nth 2 w))) return t)) return t))) - (delete-dups (pm--oref-with-parents pm/polymode :exporters))))) + (delete-dups (pm--oref-with-parents pm/polymode 'exporters))))) (sel (if exporters (if (and no-ask-if-1 (= (length exporters) 1)) (car exporters) @@ -378,7 +378,7 @@ If NO-ASK-IF-1 is non-nil, don't ask if there is only one exporter." (setq pm--exporter-hist (delete-dups pm--exporter-hist)) (setq-local pm--export:from-last nil) (setq-local pm--export:to-last nil) - (oset pm/polymode :exporter out) + (oset pm/polymode exporter out) out)) (defmacro polymode-register-exporter (exporter default &rest configs) @@ -386,8 +386,8 @@ If NO-ASK-IF-1 is non-nil, don't ask if there is only one exporter." When DEFAULT is non-nil, also make EXPORTER the default exporter for each polymode in CONFIGS." `(dolist (pm ',configs) - (object-add-to-list (symbol-value pm) :exporters ',exporter) - (when ,default (oset (symbol-value pm) :exporter ',exporter)))) + (object-add-to-list (symbol-value pm) 'exporters ',exporter) + (when ,default (oset (symbol-value pm) exporter ',exporter)))) ;;; GLOBAL EXPORTERS diff --git a/lisp/polymode/polymode-methods.el b/lisp/polymode/polymode-methods.el index 05242743..ca6bb32a 100644 --- a/lisp/polymode/polymode-methods.el +++ b/lisp/polymode/polymode-methods.el @@ -63,13 +63,13 @@ Ran by the polymode mode function." ;; Set if nil! This allows unspecified host chunkmodes to be used in ;; minor modes. (host-mode (or (eieio-oref hostmode 'mode) - (oset hostmode :mode major-mode)))) + (oset hostmode mode major-mode)))) ;; FIXME: mode hooks and local var hacking happens here. Need to move it ;; to the end. (pm--mode-setup host-mode) (oset hostmode -buffer (current-buffer)) (oset config -hostmode hostmode) - (setq pm--core-buffer-name (buffer-name) + (setq pm--base-buffer-name (buffer-name) pm/polymode config pm/chunkmode hostmode pm/current t @@ -82,17 +82,13 @@ Ran by the polymode mode function." ;; (run-mode-hooks) ;; FIXME )) + (cl-defmethod pm-initialize ((chunkmode pm-inner-chunkmode) &optional type mode) "Initialization of the innermodes' (indirect) buffers." ;; run in chunkmode indirect buffer (setq mode (or mode (pm--get-innermode-mode chunkmode type))) - (let* ((pm-initialization-in-progress t) - (post-fix (replace-regexp-in-string "poly-\\|-mode" "" (symbol-name mode))) - (core-name (format "%s[%s]" (buffer-name (pm-base-buffer)) - (or (cdr (assoc post-fix polymode-mode-abbrev-aliases)) - post-fix))) - (new-name (generate-new-buffer-name core-name))) - (rename-buffer new-name) + (let* ((pm-initialization-in-progress t)) + (rename-buffer (pm--buffer-name)) ;; FIXME: Mode hooks and local var hacking happens here. Need to move it to ;; the end. But then font-lock is not activated and buffers not installed ;; correctly. @@ -102,8 +98,7 @@ Ran by the polymode mode function." (pm--move-vars '(pm/polymode buffer-file-coding-system) (pm-base-buffer)) ;; FIXME: This breaks if different chunkmodes use same-mode buffer. Even for ;; head/tail the value of pm/type will be wrong for tail - (setq pm--core-buffer-name core-name - pm/chunkmode chunkmode + (setq pm/chunkmode chunkmode pm/type (pm-true-span-type chunkmode type)) ;; FIXME: should not be here? (vc-refresh-state) @@ -115,7 +110,7 @@ Ran by the polymode mode function." ;; If this rename happens before the mode setup font-lock doesn't work in ;; inner buffers. (when pm-hide-implementation-buffers - (rename-buffer (generate-new-buffer-name (concat " " pm--core-buffer-name))))) + (rename-buffer (pm--buffer-name 'hidden)))) (pm--run-init-hooks chunkmode type 'polymode-init-inner-hook) ;; Call polymode mode for the sake of the keymap and hook. Same minor mode ;; which runs in the host buffer but without recursive call to `pm-initialize'. @@ -403,7 +398,7 @@ TAIL-BEG TAIL-END).") (when (stringp matcher) (setq matcher (cons matcher 0))) (cond ((consp matcher) - (re-search-forward (car matcher) (point-at-eol) t) + (re-search-forward (car matcher) (line-end-position) t) (match-string-no-properties (cdr matcher))) ((functionp matcher) (funcall matcher))))) @@ -477,7 +472,7 @@ TAIL-BEG TAIL-END).") (defun pm--indent-line-raw (span) (pm--indent-raw span 'pm--indent-line-function-original) - (pm--reindent-with+-indent span (point-at-bol) (point-at-eol))) + (pm--reindent-with+-indent span (line-beginning-position) (line-end-position))) (defun pm--indent-region-raw (span beg end) (pm--indent-raw span 'pm--indent-region-function-original beg end) @@ -499,7 +494,6 @@ Function used for `indent-region-function'." (let* ((end-span (copy-marker (nth 2 span))) (end1 (min end end-span))) (goto-char beg) - ;; (pm-switch-to-buffer) ;; indent first line separately (pm-indent-line (nth 3 span) span) (beginning-of-line 2) @@ -530,7 +524,7 @@ the chunkmode.") (delta)) (back-to-indentation) (setq delta (- pos (point))) - (let* ((bol (point-at-bol)) + (let* ((bol (line-beginning-position)) (span (or span (pm-innermost-span))) (prev-span-pos) (first-line (save-excursion @@ -603,14 +597,14 @@ to indent." ;; empty line ((looking-at-p "[ \t]*$") 0) ;; inner span starts at bol; honor +-indent cookie - ((= (point) (point-at-bol)) + ((= (point) (line-beginning-position)) (pm--+-indent-offset-on-this-line span)) ;; code after header (t (end-of-line) (skip-chars-forward "\t\n") (pm--indent-line-raw span) - (- (point) (point-at-bol)))))))) + (- (point) (line-beginning-position)))))))) (indent-line-to ;; indent with respect to header line (+ delta (pm--head-indent span))))))))) @@ -628,13 +622,13 @@ to indent." (when (not (bolp)) ; for spans which don't start at bol, first line is next line (forward-line 1)) (skip-chars-forward " \t\n\r") - (when (< (point-at-eol) pos) + (when (< (line-end-position) pos) ;; not on first line -> compute indent of the first line (goto-char (nth 1 span)) (skip-chars-forward " \t\n\r") (back-to-indentation) - (when (< (point-at-eol) pos) - (- (point) (point-at-bol))))))) + (when (< (line-end-position) pos) + (- (point) (line-beginning-position))))))) ;; SPAN is a body span; do nothing if narrowed to body (defun pm--head-indent (&optional span) @@ -658,7 +652,7 @@ to indent." (current-column))))) (defun pm--+-indent-offset-on-this-line (span) - (if (re-search-forward "\\([+-]\\)indent" (point-at-eol) t) + (if (re-search-forward "\\([+-]\\)indent" (line-end-position) t) (let ((basic-offset (pm--oref-value (nth 3 span) 'indent-offset))) (if (string= (match-string 1) "-") (- basic-offset) diff --git a/lisp/polymode/polymode-pkg.el b/lisp/polymode/polymode-pkg.el index 9763009c..908ea71c 100644 --- a/lisp/polymode/polymode-pkg.el +++ b/lisp/polymode/polymode-pkg.el @@ -1,12 +1,9 @@ -(define-package "polymode" "20230317.1218" "Extensible framework for multiple major modes" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "polymode" "20250617.1033" + "Extensible framework for multiple major modes." '((emacs "25")) - :commit "ca060e081a1f849a880732670dc15370ac987b89" :maintainers - '(("Vitalie Spinu" . "spinuvit@gmail.com")) - :maintainer - '("Vitalie Spinu" . "spinuvit@gmail.com") - :keywords - '("languages" "multi-modes" "processes") - :url "https://github.com/polymode/polymode") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/polymode/polymode" + :commit "25ba9463a443f0e904147138f226284e437248d3" + :revdesc "25ba9463a443" + :keywords '("languages" "multi-modes" "processes") + :maintainers '(("Vitalie Spinu" . "spinuvit@gmail.com"))) diff --git a/lisp/polymode/polymode-test-utils.el b/lisp/polymode/polymode-test-utils.el index 6f8141c0..263b4d21 100644 --- a/lisp/polymode/polymode-test-utils.el +++ b/lisp/polymode/polymode-test-utils.el @@ -54,6 +54,10 @@ Look into tests/input directory then in samples directory." if (file-exists-p f) return f) (error "No file with name '%s' found in '%s'" name default-directory)))) +(defun pm-test-running-on-github-p () + (string= (downcase (or (getenv "GITHUB_ACTIONS") "false")) "true")) + + (defun pm-test-matcher (string span-alist matcher &optional dry-run) (with-temp-buffer (insert string) @@ -82,8 +86,8 @@ Look into tests/input directory then in samples directory." (message ")")) nil))) -(defmacro pm-test-run-on-string (mode string &rest body) - "Run BODY in a temporary buffer containing STRING in MODE. +(defmacro pm-test-run-on-string (mode string position &rest body) + "Run BODY in a temporary buffer containing STRING in MODE at POSITION. MODE is a quoted symbol." (declare (indent 1) (debug (form form body))) `(let ((*buf* "*pm-test-string-buffer*")) @@ -98,7 +102,7 @@ MODE is a quoted symbol." (and (bound-and-true-p syntax-propertize-function) (not (local-variable-p 'parse-sexp-lookup-properties)) (setq-local parse-sexp-lookup-properties t)) - (goto-char (point-min)) + (funcall-interactively 'goto-char ,position) (let ((poly-lock-allow-background-adjustment nil)) (when polymode-mode ;; font-lock not activated in batch mode @@ -111,7 +115,7 @@ MODE is a quoted symbol." (defun pm-test-spans (mode string) (declare (indent 1)) (pm-test-run-on-string mode - string + string 1 (pm-map-over-spans (lambda (span) (let ((range0 (pm-span-to-range span))) @@ -190,7 +194,7 @@ MODE is a quoted symbol." (smode major-mode) (stext (buffer-substring-no-properties sbeg send)) ;; other buffer - (ref-buf (pm-test-run-on-string smode stext)) + (ref-buf (pm-test-run-on-string smode stext 1)) (ref-pos 1)) (when pm-verbose (message "---- testing %s ----" (pm-format-span span t))) @@ -243,10 +247,10 @@ MODE is a quoted symbol." :pos pos :ref-pos ref-pos :line (progn (goto-char pos) - (buffer-substring-no-properties (point-at-bol) (point-at-eol))) + (buffer-substring-no-properties (line-beginning-position) (line-end-position))) :ref-line (with-current-buffer ref-buf (goto-char ref-pos) - (buffer-substring-no-properties (point-at-bol) (point-at-eol))) + (buffer-substring-no-properties (line-beginning-position) (line-end-position))) :mode smode)))) ;; for the interactive convenience (switch-to-buffer (current-buffer)) @@ -371,7 +375,7 @@ points." (goto-char (point-min)) (set-buffer-modified-p nil) (while (not (eobp)) - (let ((orig-line (buffer-substring-no-properties (point-at-eol) (point-at-bol)))) + (let ((orig-line (buffer-substring-no-properties (line-end-position) (line-beginning-position)))) (unless (string-match-p "no-indent-test" orig-line) (undo-boundary) ;; (pm-switch-to-buffer) @@ -379,12 +383,12 @@ points." ;; (line-number-at-pos) (point) (current-buffer) ;; (syntax-ppss) syntax-propertize--done) (pm-indent-line-dispatcher) - (unless (equal orig-line (buffer-substring-no-properties (point-at-eol) (point-at-bol))) + (unless (equal orig-line (buffer-substring-no-properties (line-end-position) (line-beginning-position))) (undo-boundary) (pm-switch-to-buffer (point)) (ert-fail (list :pos (point) :line (line-number-at-pos) :mode major-mode - :indent-line (buffer-substring-no-properties (point-at-bol) (point-at-eol))))))) + :indent-line (buffer-substring-no-properties (line-beginning-position) (line-end-position))))))) (forward-line 1)) (let (points1 points2) (pm-map-over-spans (lambda (span) (push (/ (+ (nth 1 span) (nth 2 span)) 2) points1))) @@ -436,10 +440,10 @@ points." :ref (with-temp-buffer (insert right) (goto-char pos) - (buffer-substring-no-properties (point-at-bol) (point-at-eol))) + (buffer-substring-no-properties (line-beginning-position) (line-end-position))) :new (progn (goto-char pos) - (buffer-substring-no-properties (point-at-bol) (point-at-eol))))))))))) + (buffer-substring-no-properties (line-beginning-position) (line-end-position))))))))))) (defmacro pm-test-map-over-modes (mode file) `(pm-test-run-on-file ,mode ,file diff --git a/lisp/polymode/polymode-weave.el b/lisp/polymode/polymode-weave.el index a06d3897..37f31f4b 100644 --- a/lisp/polymode/polymode-weave.el +++ b/lisp/polymode/polymode-weave.el @@ -258,8 +258,8 @@ specification." When DEFAULT is non-nil, also make weaver the default WEAVER for each polymode in CONFIGS." `(dolist (pm ',configs) - (object-add-to-list (symbol-value pm) :weavers ',weaver) - (when ,default (oset (symbol-value pm) :weaver ',weaver)))) + (object-add-to-list (symbol-value pm) 'weavers ',weaver) + (when ,default (oset (symbol-value pm) weaver ',weaver)))) (defun polymode-set-weaver () "Set the current weaver for this polymode." @@ -268,12 +268,12 @@ each polymode in CONFIGS." (error "No pm/polymode object found. Not in polymode buffer?")) (let* ((weavers (pm--abrev-names "pm-weaver/\\|-weaver$" - (delete-dups (pm--oref-with-parents pm/polymode :weavers)))) + (delete-dups (pm--oref-with-parents pm/polymode 'weavers)))) (sel (pm--completing-read "Choose weaver: " weavers nil t nil 'pm--weaver-hist)) (out (intern (cdr sel)))) (setq pm--weaver-hist (delete-dups pm--weaver-hist)) (setq-local pm--weave:fromto-last nil) - (oset pm/polymode :weaver out) + (oset pm/polymode weaver out) out)) (provide 'polymode-weave) diff --git a/lisp/polymode/polymode.el b/lisp/polymode/polymode.el index 6845ebdc..c2be1b3c 100644 --- a/lisp/polymode/polymode.el +++ b/lisp/polymode/polymode.el @@ -3,7 +3,8 @@ ;; Author: Vitalie Spinu ;; Maintainer: Vitalie Spinu ;; Copyright (C) 2013-2022 Free Software Foundation, Inc. -;; Version: 0.2.2 +;; Package-Version: 20250617.1033 +;; Package-Revision: 25ba9463a443 ;; Package-Requires: ((emacs "25")) ;; URL: https://github.com/polymode/polymode ;; Keywords: languages, multi-modes, processes @@ -46,10 +47,17 @@ (require 'easymenu) (require 'derived) -(defvar polymode-prefix-key nil - "[Obsoleted] Prefix key for the polymode mode keymap. -Not effective after loading the polymode library.") -(make-obsolete-variable 'polymode-prefix-key "Unbind in `polymode-mode-map'" "v0.1.6") +(defvar polymode-prefix-key "\M-n" + "Default prefix key in `polymode-minor-mode-map'. +Not effective after loading the polymode library. + +Instead of setting this key you can programatically bind it directly +in `polymode-minor-mode-map` keymap: + + (define-key polymode-minor-mode-map (kbd \"M-n\") nil) + ;unbind the default M-n prefix + (define-key polymode-minor-mode-map (kbd \"C-c n\") polymode-map) +") (defvar polymode-map (let ((map (define-prefix-command 'polymode-map))) @@ -63,23 +71,25 @@ Not effective after loading the polymode library.") ;; chunk manipulation (define-key map "\M-k" #'polymode-kill-chunk) (define-key map "\M-m" #'polymode-mark-or-extend-chunk) + (define-key map "\M-w" #'polymode-kill-ring-save-chunk) (define-key map "\C-t" #'polymode-toggle-chunk-narrowing) ;; backends (define-key map "e" #'polymode-export) (define-key map "E" #'polymode-set-exporter) (define-key map "w" #'polymode-weave) (define-key map "W" #'polymode-set-weaver) - (define-key map "t" #'polymode-tangle) - (define-key map "T" #'polymode-set-tangler) + ;; (define-key map "t" #'polymode-tangle) + ;; (define-key map "T" #'polymode-set-tangler) (define-key map "$" #'polymode-show-process-buffer) map) "Polymode prefix map. -Lives on `polymode-prefix-key' in polymode buffers.") +By default, lives on `polymode-prefix-key' in polymode buffers.") (defvaralias 'polymode-mode-map 'polymode-minor-mode-map) (defvar polymode-minor-mode-map (let ((map (make-sparse-keymap))) - (define-key map (or polymode-prefix-key "\M-n") 'polymode-map) + (when polymode-prefix-key + (define-key map polymode-prefix-key 'polymode-map)) map) "The minor mode keymap which is inherited by all polymodes.") @@ -236,6 +246,23 @@ Return the number of chunks of the same type moved over." (pm-span-to-range span) (pm-chunk-range (1- (nth 1 span)))))))) +(defun polymode-kill-ring-save-chunk () + "Copy current chunk into the kill-ring. +When in the head of chunk, copy the chunk including the head and tail, +otherwise only the body span. +When called interactively, highlight the copie region for `copy-region-blink-delay'." + (interactive) + (let ((span (pm-innermost-span))) + (let ((range (if (memq (car span) '(nil body)) + (pm-span-to-range span) + (pm-chunk-range)))) + (copy-region-as-kill (car range) (cdr range)) + (when (called-interactively-p 'interactive) + (let ((overlay (make-overlay (car range) (cdr range)))) + (overlay-put overlay 'face 'highlight) + (run-with-timer copy-region-blink-delay nil + (lambda () (delete-overlay overlay)))))))) + (defun polymode-mark-or-extend-chunk () "DWIM command to repeatedly mark chunk or extend region. When no region is active, mark the current span if in body of a @@ -435,7 +462,7 @@ non-nil, don't throw if `polymode-eval-region-function' is nil." (pi parent-conf) (parent-map)) (while pi - (let ((map (and (slot-boundp pi :keylist) + (let ((map (and (slot-boundp pi 'keylist) (eieio-oref pi 'keylist)))) (when map (if (and (symbolp map) @@ -445,7 +472,7 @@ non-nil, don't throw if `polymode-eval-region-function' is nil." (setq parent-map map pi nil) ;; list, descend to next parent and append the key list to keylist - (setq pi (and (slot-boundp pi :parent-instance) + (setq pi (and (slot-boundp pi 'parent-instance) (eieio-oref pi 'parent-instance)) keylist (append map keylist)))))) (when (and parent-map (symbolp parent-map)) diff --git a/lisp/popup/popup-pkg.el b/lisp/popup/popup-pkg.el index 729fac94..d5591477 100644 --- a/lisp/popup/popup-pkg.el +++ b/lisp/popup/popup-pkg.el @@ -1,14 +1,10 @@ -(define-package "popup" "20250101.843" "Visual Popup User Interface" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "popup" "20250101.843" + "Visual Popup User Interface." '((emacs "24.3")) - :commit "7a05700a37aae66d2b24f0cd8851f65383a5cf96" :authors - '(("Tomohiro Matsuyama" . "m2ym.pub@gmail.com")) - :maintainers - '(("Jen-Chieh" . "jcs090218@gmail.com")) - :maintainer - '("Jen-Chieh" . "jcs090218@gmail.com") - :keywords - '("lisp") - :url "https://github.com/auto-complete/popup-el") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/auto-complete/popup-el" + :commit "7a05700a37aae66d2b24f0cd8851f65383a5cf96" + :revdesc "7a05700a37aa" + :keywords '("lisp") + :authors '(("Tomohiro Matsuyama" . "m2ym.pub@gmail.com")) + :maintainers '(("Jen-Chieh" . "jcs090218@gmail.com"))) diff --git a/lisp/popup/popup.el b/lisp/popup/popup.el index 6c2f6966..46823b46 100644 --- a/lisp/popup/popup.el +++ b/lisp/popup/popup.el @@ -7,7 +7,8 @@ ;; Maintainer: Shen, Jen-Chieh ;; URL: https://github.com/auto-complete/popup-el ;; Keywords: lisp -;; Version: 0.5.9 +;; Package-Version: 20250101.843 +;; Package-Revision: 7a05700a37aa ;; Package-Requires: ((emacs "24.3")) ;; This program is free software; you can redistribute it and/or modify diff --git a/lisp/popwin/popwin-pkg.el b/lisp/popwin/popwin-pkg.el index 42be9788..ba0a9f9e 100644 --- a/lisp/popwin/popwin-pkg.el +++ b/lisp/popwin/popwin-pkg.el @@ -1,14 +1,10 @@ -(define-package "popwin" "20240925.752" "Popup Window Manager" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "popwin" "20240925.752" + "Popup Window Manager." '((emacs "24.3")) - :commit "58adcd0ca7c3dbd58626ec7019252d64cbc73042" :authors - '(("Tomohiro Matsuyama" . "m2ym.pub@gmail.com")) - :maintainers - '(("Jen-Chieh Shen" . "jcs090218@gmail.com")) - :maintainer - '("Jen-Chieh Shen" . "jcs090218@gmail.com") - :keywords - '("convenience") - :url "https://github.com/emacsorphanage/popwin") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/emacsorphanage/popwin" + :commit "58adcd0ca7c3dbd58626ec7019252d64cbc73042" + :revdesc "58adcd0ca7c3" + :keywords '("convenience") + :authors '(("Tomohiro Matsuyama" . "m2ym.pub@gmail.com")) + :maintainers '(("Jen-Chieh Shen" . "jcs090218@gmail.com"))) diff --git a/lisp/popwin/popwin.el b/lisp/popwin/popwin.el index d8c62fa1..23587ba7 100644 --- a/lisp/popwin/popwin.el +++ b/lisp/popwin/popwin.el @@ -6,7 +6,8 @@ ;; Author: Tomohiro Matsuyama ;; Maintainer: Jen-Chieh Shen ;; Keywords: convenience -;; Version: 1.0.2 +;; Package-Version: 20240925.752 +;; Package-Revision: 58adcd0ca7c3 ;; URL: https://github.com/emacsorphanage/popwin ;; Package-Requires: ((emacs "24.3")) diff --git a/lisp/pos-tip/pos-tip-pkg.el b/lisp/pos-tip/pos-tip-pkg.el index 52a82a9b..66a3f7cb 100644 --- a/lisp/pos-tip/pos-tip-pkg.el +++ b/lisp/pos-tip/pos-tip-pkg.el @@ -1,5 +1,8 @@ -(define-package "pos-tip" "20240209.837" "Show tooltip at point" 'nil :commit "4889e08cf9077c8589ea6fea4e2ce558614dfcde" :keywords - '("tooltip")) -;; Local Variables: -;; no-byte-compile: t -;; End: +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "pos-tip" "20240209.837" + "Show tooltip at point." + () + :url "https://github.com/pitkali/pos-tip" + :commit "4889e08cf9077c8589ea6fea4e2ce558614dfcde" + :revdesc "4889e08cf907" + :keywords '("tooltip")) diff --git a/lisp/pos-tip/pos-tip.el b/lisp/pos-tip/pos-tip.el index b37e2b60..c32c3eda 100644 --- a/lisp/pos-tip/pos-tip.el +++ b/lisp/pos-tip/pos-tip.el @@ -6,7 +6,8 @@ ;; Maintainer: S. Irie ;; Keywords: Tooltip -;; Package-Version: 0.4.7 +;; Package-Version: 20240209.837 +;; Package-Revision: 4889e08cf907 (defconst pos-tip-version "0.4.7") diff --git a/lisp/posframe/posframe-benchmark.el b/lisp/posframe/posframe-benchmark.el index d1d4135c..58b8676c 100644 --- a/lisp/posframe/posframe-benchmark.el +++ b/lisp/posframe/posframe-benchmark.el @@ -5,7 +5,6 @@ ;; Author: Feng Shu ;; Maintainer: Feng Shu ;; URL: https://github.com/tumashu/posframe -;; Version: 1.0.3 ;; Keywords: convenience, tooltip ;; Package-Requires: ((emacs "26")) diff --git a/lisp/posframe/posframe-pkg.el b/lisp/posframe/posframe-pkg.el index b2ede106..721e0b9f 100644 --- a/lisp/posframe/posframe-pkg.el +++ b/lisp/posframe/posframe-pkg.el @@ -1,14 +1,10 @@ -(define-package "posframe" "20250211.110" "Pop a posframe (just a frame) at point" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "posframe" "20250211.110" + "Pop a posframe (just a frame) at point." '((emacs "26.1")) - :commit "12f540c9ad5da09673b2bca1132b41f94c134e82" :authors - '(("Feng Shu" . "tumashu@163.com")) - :maintainers - '(("Feng Shu" . "tumashu@163.com")) - :maintainer - '("Feng Shu" . "tumashu@163.com") - :keywords - '("convenience" "tooltip") - :url "https://github.com/tumashu/posframe") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/tumashu/posframe" + :commit "12f540c9ad5da09673b2bca1132b41f94c134e82" + :revdesc "12f540c9ad5d" + :keywords '("convenience" "tooltip") + :authors '(("Feng Shu" . "tumashu@163.com")) + :maintainers '(("Feng Shu" . "tumashu@163.com"))) diff --git a/lisp/posframe/posframe.el b/lisp/posframe/posframe.el index e75b0811..5fa2fb48 100644 --- a/lisp/posframe/posframe.el +++ b/lisp/posframe/posframe.el @@ -5,7 +5,8 @@ ;; Author: Feng Shu ;; Maintainer: Feng Shu ;; URL: https://github.com/tumashu/posframe -;; Version: 1.4.4 +;; Package-Version: 20250211.110 +;; Package-Revision: 12f540c9ad5d ;; Keywords: convenience, tooltip ;; Package-Requires: ((emacs "26.1")) diff --git a/lisp/powershell/powershell-pkg.el b/lisp/powershell/powershell-pkg.el index 0f7addf2..b8d9697d 100644 --- a/lisp/powershell/powershell-pkg.el +++ b/lisp/powershell/powershell-pkg.el @@ -1,14 +1,10 @@ -(define-package "powershell" "20240825.1440" "Mode for editing PowerShell scripts" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "powershell" "20250614.1529" + "Mode for editing PowerShell scripts." '((emacs "24")) - :commit "38727f1cdaf0c937a62b68ee52ec7196b8149f93" :authors - '(("Frédéric Perrin" . "fredericperrinreselfr")) - :maintainers - '(("Frédéric Perrin" . "fredericperrinreselfr")) - :maintainer - '("Frédéric Perrin" . "fredericperrinreselfr") - :keywords - '("powershell" "languages") - :url "http://github.com/jschaf/powershell.el") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "http://github.com/jschaf/powershell.el" + :commit "99e0e73082fd48314a9825254dac45f318e5bb59" + :revdesc "99e0e73082fd" + :keywords '("powershell" "languages") + :authors '(("Frédéric Perrin" . "fredericperrinreselfr")) + :maintainers '(("Frédéric Perrin" . "fredericperrinreselfr"))) diff --git a/lisp/powershell/powershell.el b/lisp/powershell/powershell.el index 66d9f2ce..20548868 100644 --- a/lisp/powershell/powershell.el +++ b/lisp/powershell/powershell.el @@ -6,7 +6,8 @@ ;; Author: Frédéric Perrin ;; URL: http://github.com/jschaf/powershell.el -;; Version: 0.3 +;; Package-Version: 20250614.1529 +;; Package-Revision: 99e0e73082fd ;; Package-Requires: ((emacs "24")) ;; Keywords: powershell, languages @@ -118,6 +119,15 @@ Value is a list of strings, which may be nil." :type '(repeat (string :tag "Argument")) :group 'powershell) +(defcustom powershell-default-langserver-path + (expand-file-name ".cache/powershell/" user-emacs-directory) + "Default expression used to locate Powershell Languageserver. +If found, added to eglot. Supports environment-variables and glob-pattterns. +Changes may require an Emacs-restart to take effect." + :type 'string + :group 'powershell) + + (defun powershell-continuation-line-p () "Return t is the current line is a continuation line. The current line is a continued line when the previous line ends @@ -781,7 +791,9 @@ that value is non-nil." (powershell-setup-imenu) (powershell-setup-speedbar) (powershell-setup-menu) - (powershell-setup-eldoc)) + (powershell-setup-eldoc) + (with-eval-after-load 'eglot + (powershell--register-langserver))) ;;; PowerShell inferior mode @@ -1387,6 +1399,67 @@ This insures we get and display the prompt." ;; (insert " ")) ;; success))) +(defun powershell--fetch-json-array (url) + "Fetch JSON from URL, parse as if array." + (with-temp-buffer (url-insert-file-contents url) + (json-parse-buffer :array-type 'list))) + +(defun powershell--unzip-file (zip-file destination) + "Unzip ZIP-FILE into DESTINATION directory using the 'unzip' command." + (make-directory destination t) ;; Ensure the destination directory exists + (let ((exit-code (call-process "unzip" nil nil nil "-o" zip-file "-d" destination))) + (if (zerop exit-code) + (message "Successfully unzipped %s to %s" zip-file destination) + (error "Failed to unzip %s (exit code %d)" zip-file exit-code)))) + +(defun powershell--get-latest-release-version () + (let* ((release-json (powershell--fetch-json-array "https://api.github.com/repos/PowerShell/PowerShellEditorServices/releases")) + (first (car release-json)) ;; assume first = latest + (version (gethash "tag_name" first))) + version)) + +(defun powershell--download-langserver () + (let* ((download-dir (expand-file-name "dl" powershell-default-langserver-path)) + (download-file (expand-file-name "powershell-langserver.zip" download-dir))) + (make-directory download-dir :parents) + (let* ((version (powershell--get-latest-release-version)) + (url (format "https://github.com/PowerShell/PowerShellEditorServices/releases/download/%s/PowerShellEditorServices.zip" version))) + (url-copy-file url download-file 't) + (powershell--unzip-file download-file powershell-default-langserver-path) + (delete-directory download-dir t) + ;; make our function respond with something more interesting than nil :) + (message (format "Powershell LangServer version %s downloaded and unpacked to \'%s\'" version powershell-default-langserver-path))))) + +(defun powershell-install-langserver () + "Downloads the lang-server and unpacks it in the default location." + (interactive) + (powershell--download-langserver) + (powershell--register-langserver)) + +(defun powershell--register-langserver () + (defvar eglot-server-programs) + (let* ((langserver-path (powershell-langserver-file-name)) + (langserver-exe (expand-file-name "PowerShellEditorServices/Start-EditorServices.ps1" langserver-path))) + (and (file-exists-p langserver-exe) + (add-to-list 'eglot-server-programs + `(powershell-mode . ("pwsh" + "-OutputFormat" "Text" + "-File" + ,langserver-exe + "-Stdio" + "-HostVersion" "1.0" + "-HostName" "Emacs" + "-HostProfileId" "Emacs.Eglot" + "-SessionDetailsPath" + ,(expand-file-name "eglot-powershell" temporary-file-directory) + "-BundledModulesPath" + ,langserver-path)))))) + + +(defun powershell-langserver-file-name () + (car (file-expand-wildcards + (substitute-in-file-name powershell-default-langserver-path)))) + (provide 'powershell) ;;; powershell.el ends here diff --git a/lisp/pythonic/pythonic-pkg.el b/lisp/pythonic/pythonic-pkg.el index fab14f7d..b56d86ca 100644 --- a/lisp/pythonic/pythonic-pkg.el +++ b/lisp/pythonic/pythonic-pkg.el @@ -1,16 +1,12 @@ -(define-package "pythonic" "20230821.1733" "Utility functions for writing pythonic emacs package" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "pythonic" "20230821.1733" + "Utility functions for writing pythonic emacs package." '((emacs "25.1") - (s "1.9") - (f "0.17.2")) - :commit "f6e0bec552319341f260a5c4740288799c2b3a5b" :authors - '(("Artem Malyshev" . "proofit404@gmail.com")) - :maintainers - '(("Artem Malyshev" . "proofit404@gmail.com")) - :maintainer - '("Artem Malyshev" . "proofit404@gmail.com") - :keywords - '("convenience" "pythonic") - :url "https://github.com/proofit404/pythonic") -;; Local Variables: -;; no-byte-compile: t -;; End: + (s "1.9") + (f "0.17.2")) + :url "https://github.com/proofit404/pythonic" + :commit "f6e0bec552319341f260a5c4740288799c2b3a5b" + :revdesc "f6e0bec55231" + :keywords '("convenience" "pythonic") + :authors '(("Artem Malyshev" . "proofit404@gmail.com")) + :maintainers '(("Artem Malyshev" . "proofit404@gmail.com"))) diff --git a/lisp/pythonic/pythonic.el b/lisp/pythonic/pythonic.el index 83611aa4..c698daac 100644 --- a/lisp/pythonic/pythonic.el +++ b/lisp/pythonic/pythonic.el @@ -4,7 +4,8 @@ ;; Author: Artem Malyshev ;; URL: https://github.com/proofit404/pythonic -;; Version: 0.2 +;; Package-Version: 20230821.1733 +;; Package-Revision: f6e0bec55231 ;; Package-Requires: ((emacs "25.1") (s "1.9") (f "0.17.2")) ;; Keywords: convenience pythonic diff --git a/lisp/restart-emacs/restart-emacs-pkg.el b/lisp/restart-emacs/restart-emacs-pkg.el index 08169aec..3e985000 100644 --- a/lisp/restart-emacs/restart-emacs-pkg.el +++ b/lisp/restart-emacs/restart-emacs-pkg.el @@ -1,12 +1,10 @@ -(define-package "restart-emacs" "20201127.1425" "Restart emacs from within emacs" 'nil :commit "d0fca7fba014b2d0d4dedcb9744a1e73cd9a6409" :authors - '(("Iqbal Ansari" . "iqbalansari02@yahoo.com")) - :maintainers - '(("Iqbal Ansari" . "iqbalansari02@yahoo.com")) - :maintainer - '("Iqbal Ansari" . "iqbalansari02@yahoo.com") - :keywords - '("convenience") - :url "https://github.com/iqbalansari/restart-emacs") -;; Local Variables: -;; no-byte-compile: t -;; End: +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "restart-emacs" "20201127.1425" + "Restart emacs from within emacs." + () + :url "https://github.com/iqbalansari/restart-emacs" + :commit "d0fca7fba014b2d0d4dedcb9744a1e73cd9a6409" + :revdesc "d0fca7fba014" + :keywords '("convenience") + :authors '(("Iqbal Ansari" . "iqbalansari02@yahoo.com")) + :maintainers '(("Iqbal Ansari" . "iqbalansari02@yahoo.com"))) diff --git a/lisp/restart-emacs/restart-emacs.el b/lisp/restart-emacs/restart-emacs.el index 3a95dbba..1a37cf45 100644 --- a/lisp/restart-emacs/restart-emacs.el +++ b/lisp/restart-emacs/restart-emacs.el @@ -5,7 +5,8 @@ ;; Author: Iqbal Ansari ;; Keywords: convenience ;; URL: https://github.com/iqbalansari/restart-emacs -;; Version: 0.1.1 +;; Package-Version: 20201127.1425 +;; Package-Revision: d0fca7fba014 ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by diff --git a/lisp/s/s-pkg.el b/lisp/s/s-pkg.el index de58898d..7c4144cc 100644 --- a/lisp/s/s-pkg.el +++ b/lisp/s/s-pkg.el @@ -1,11 +1,10 @@ -(define-package "s" "20220902.1511" "The long lost Emacs string manipulation library." 'nil :commit "b4b8c03fcef316a27f75633fe4bb990aeff6e705" :authors - '(("Magnar Sveen" . "magnars@gmail.com")) - :maintainers - '(("Jason Milkins" . "jasonm23@gmail.com")) - :maintainer - '("Jason Milkins" . "jasonm23@gmail.com") - :keywords - '("strings")) -;; Local Variables: -;; no-byte-compile: t -;; End: +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "s" "20220902.1511" + "The long lost Emacs string manipulation library." + () + :url "https://github.com/magnars/s.el" + :commit "b4b8c03fcef316a27f75633fe4bb990aeff6e705" + :revdesc "b4b8c03fcef3" + :keywords '("strings") + :authors '(("Magnar Sveen" . "magnars@gmail.com")) + :maintainers '(("Jason Milkins" . "jasonm23@gmail.com"))) diff --git a/lisp/s/s.el b/lisp/s/s.el index cae199b3..582455f6 100644 --- a/lisp/s/s.el +++ b/lisp/s/s.el @@ -4,7 +4,8 @@ ;; Author: Magnar Sveen ;; Maintainer: Jason Milkins -;; Version: 1.13.1 +;; Package-Version: 20220902.1511 +;; Package-Revision: b4b8c03fcef3 ;; Keywords: strings ;; This program is free software; you can redistribute it and/or modify diff --git a/lisp/seq/seq-pkg.el b/lisp/seq/seq-pkg.el index 97504008..d3012dae 100644 --- a/lisp/seq/seq-pkg.el +++ b/lisp/seq/seq-pkg.el @@ -1,2 +1,2 @@ ;; Generated package description from seq.el -*- no-byte-compile: t -*- -(define-package "seq" "2.24" "Sequence manipulation functions" 'nil :commit "9d9f51b0e3ca59e0a488801064512f4878ac910b" :url "https://elpa.gnu.org/packages/seq.html" :authors '(("Nicolas Petton" . "nicolas@petton.fr")) :maintainer '(nil . "emacs-devel@gnu.org") :keywords '("sequences")) +(define-package "seq" "2.24" "Sequence manipulation functions" 'nil :commit "27a90793a13f149121180e864fa53d68b9eac0b3" :url "https://elpa.gnu.org/packages/seq.html" :authors '(("Nicolas Petton" . "nicolas@petton.fr")) :maintainer '(nil . "emacs-devel@gnu.org") :keywords '("sequences")) diff --git a/lisp/simple-httpd/simple-httpd-pkg.el b/lisp/simple-httpd/simple-httpd-pkg.el index bf77f771..5c76bd0e 100644 --- a/lisp/simple-httpd/simple-httpd-pkg.el +++ b/lisp/simple-httpd/simple-httpd-pkg.el @@ -1,12 +1,9 @@ -(define-package "simple-httpd" "20230821.1458" "pure elisp HTTP server" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "simple-httpd" "20230821.1458" + "Pure elisp HTTP server." '((cl-lib "0.3")) - :commit "347c30494d3bcfc79de35e54538f92f4e4a46ecd" :authors - '(("Christopher Wellons" . "wellons@nullprogram.com")) - :maintainers - '(("Christopher Wellons" . "wellons@nullprogram.com")) - :maintainer - '("Christopher Wellons" . "wellons@nullprogram.com") - :url "https://github.com/skeeto/emacs-http-server") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/skeeto/emacs-http-server" + :commit "347c30494d3bcfc79de35e54538f92f4e4a46ecd" + :revdesc "347c30494d3b" + :authors '(("Christopher Wellons" . "wellons@nullprogram.com")) + :maintainers '(("Christopher Wellons" . "wellons@nullprogram.com"))) diff --git a/lisp/simple-httpd/simple-httpd.el b/lisp/simple-httpd/simple-httpd.el index 17bc8d18..de541525 100644 --- a/lisp/simple-httpd/simple-httpd.el +++ b/lisp/simple-httpd/simple-httpd.el @@ -4,7 +4,8 @@ ;; Author: Christopher Wellons ;; URL: https://github.com/skeeto/emacs-http-server -;; Version: 1.5.1 +;; Package-Version: 20230821.1458 +;; Package-Revision: 347c30494d3b ;; Package-Requires: ((cl-lib "0.3")) ;;; Commentary: diff --git a/lisp/spacemacs-theme/spacemacs-dark-theme.el b/lisp/spacemacs-theme/spacemacs-dark-theme.el index 6d54a06c..d8753e5e 100644 --- a/lisp/spacemacs-theme/spacemacs-dark-theme.el +++ b/lisp/spacemacs-theme/spacemacs-dark-theme.el @@ -1,3 +1,4 @@ +;; -*- lexical-binding: t; -*- (require 'spacemacs-theme) (deftheme spacemacs-dark "Spacemacs theme, the dark version") diff --git a/lisp/spacemacs-theme/spacemacs-light-theme.el b/lisp/spacemacs-theme/spacemacs-light-theme.el index 6372aa55..6221f504 100644 --- a/lisp/spacemacs-theme/spacemacs-light-theme.el +++ b/lisp/spacemacs-theme/spacemacs-light-theme.el @@ -1,3 +1,4 @@ +;; -*- lexical-binding: t; -*- (require 'spacemacs-theme) (deftheme spacemacs-light "Spacemacs theme, the light version") diff --git a/lisp/spacemacs-theme/spacemacs-theme-pkg.el b/lisp/spacemacs-theme/spacemacs-theme-pkg.el index a714b927..81a69dfa 100644 --- a/lisp/spacemacs-theme/spacemacs-theme-pkg.el +++ b/lisp/spacemacs-theme/spacemacs-theme-pkg.el @@ -1,6 +1,8 @@ -(define-package "spacemacs-theme" "20241101.1030" "Color theme with a dark and light versions" 'nil :commit "6c74684c4d55713c8359bedf1936e429918a8c33" :keywords - '("color" "theme") - :url "https://github.com/nashamri/spacemacs-theme") -;; Local Variables: -;; no-byte-compile: t -;; End: +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "spacemacs-theme" "20250613.2113" + "Color theme with a dark and light versions." + '((emacs "24")) + :url "https://github.com/nashamri/spacemacs-theme" + :commit "2ffca41e6e9aa55d8de5c40c6fb61e0d47763b5d" + :revdesc "2ffca41e6e9a" + :keywords '("color" "theme")) diff --git a/lisp/spacemacs-theme/spacemacs-theme.el b/lisp/spacemacs-theme/spacemacs-theme.el index d81e03a5..46d05ded 100644 --- a/lisp/spacemacs-theme/spacemacs-theme.el +++ b/lisp/spacemacs-theme/spacemacs-theme.el @@ -1,11 +1,12 @@ -;;; spacemacs-theme.el --- Color theme with a dark and light versions. +;;; spacemacs-theme.el --- Color theme with a dark and light versions. -*- lexical-binding: t; -*- ;; Copyright (C) 2015-2018 Nasser Alshammari ;; Author: Nasser Alshammari ;; URL: ;; -;; Version: 0.2 +;; Package-Version: 20250613.2113 +;; Package-Revision: 2ffca41e6e9a ;; Keywords: color, theme ;; Package-Requires: ((emacs "24")) @@ -58,7 +59,7 @@ Note that if you change this to a non-nil value, you may want to also adjust the value of `org-agenda-tags-column'. If that is set -to 'auto, tags may not be properly aligned. " +to `auto', tags may not be properly aligned. " :type 'boolean :group 'spacemacs-theme) @@ -92,85 +93,90 @@ to 'auto, tags may not be properly aligned. " :type 'boolean :group 'spacemacs-theme) -(defun true-color-p () - (or - (display-graphic-p) - (= (tty-display-color-cells) 16777216))) - (defun create-spacemacs-theme (variant theme-name) - (let ((class '((class color) (min-colors 89))) ;; ~~ Dark ~~ ~~ Light ~~ - ;; GUI TER GUI TER - ;; generic - (act1 (if (eq variant 'dark) (if (true-color-p) "#222226" "#121212") (if (true-color-p) "#e7e5eb" "#d7dfff"))) - (act2 (if (eq variant 'dark) (if (true-color-p) "#5d4d7a" "#444444") (if (true-color-p) "#d3d3e7" "#afafd7"))) - (base (if (eq variant 'dark) (if (true-color-p) "#b2b2b2" "#b2b2b2") (if (true-color-p) "#655370" "#5f5f87"))) - (base-dim (if (eq variant 'dark) (if (true-color-p) "#686868" "#585858") (if (true-color-p) "#a094a2" "#afafd7"))) - (bg1 (if (eq variant 'dark) (if (true-color-p) "#292b2e" "#262626") (if (true-color-p) "#fbf8ef" "#ffffff"))) - (bg2 (if (eq variant 'dark) (if (true-color-p) "#212026" "#1c1c1c") (if (true-color-p) "#efeae9" "#e4e4e4"))) - (bg3 (if (eq variant 'dark) (if (true-color-p) "#100a14" "#121212") (if (true-color-p) "#e3dedd" "#d0d0d0"))) - (bg4 (if (eq variant 'dark) (if (true-color-p) "#0a0814" "#080808") (if (true-color-p) "#d2ceda" "#bcbcbc"))) - (bg-alt (if (eq variant 'dark) (if (true-color-p) "#42444a" "#353535") (if (true-color-p) "#efeae9" "#e4e4e4"))) - (border (if (eq variant 'dark) (if (true-color-p) "#5d4d7a" "#111111") (if (true-color-p) "#b3b9be" "#b3b9be"))) - (cblk (if (eq variant 'dark) (if (true-color-p) "#cbc1d5" "#b2b2b2") (if (true-color-p) "#655370" "#5f5f87"))) - (cblk-bg (if (eq variant 'dark) (if (true-color-p) "#2f2b33" "#262626") (if (true-color-p) "#e8e3f0" "#ffffff"))) - (cblk-ln (if (eq variant 'dark) (if (true-color-p) "#827591" "#af5faf") (if (true-color-p) "#9380b2" "#af5fdf"))) - (cblk-ln-bg (if (eq variant 'dark) (if (true-color-p) "#373040" "#333333") (if (true-color-p) "#ddd8eb" "#dfdfff"))) - (cursor (if (eq variant 'dark) (if (true-color-p) "#e3dedd" "#d0d0d0") (if (true-color-p) "#100a14" "#121212"))) - (const (if (eq variant 'dark) (if (true-color-p) "#a45bad" "#d75fd7") (if (true-color-p) "#4e3163" "#8700af"))) - (comment (if (eq variant 'dark) (if (true-color-p) "#2aa1ae" "#008787") (if (true-color-p) "#2aa1ae" "#008787"))) - (comment-light (if (eq variant 'dark) (if (true-color-p) "#2aa1ae" "#008787") (if (true-color-p) "#a49da5" "#008787"))) - (comment-bg (if (eq variant 'dark) (if (true-color-p) "#292e34" "#262626") (if (true-color-p) "#ecf3ec" "#ffffff"))) - (comp (if (eq variant 'dark) (if (true-color-p) "#c56ec3" "#d75fd7") (if (true-color-p) "#6c4173" "#8700af"))) - (err (if (eq variant 'dark) (if (true-color-p) "#e0211d" "#e0211d") (if (true-color-p) "#e0211d" "#e0211d"))) - (func (if (eq variant 'dark) (if (true-color-p) "#bc6ec5" "#d75fd7") (if (true-color-p) "#6c3163" "#8700af"))) - (head1 (if (eq variant 'dark) (if (true-color-p) "#4f97d7" "#268bd2") (if (true-color-p) "#3a81c3" "#268bd2"))) - (head1-bg (if (eq variant 'dark) (if (true-color-p) "#293239" "#262626") (if (true-color-p) "#edf1ed" "#ffffff"))) - (head2 (if (eq variant 'dark) (if (true-color-p) "#2d9574" "#2aa198") (if (true-color-p) "#2d9574" "#2aa198"))) - (head2-bg (if (eq variant 'dark) (if (true-color-p) "#293235" "#262626") (if (true-color-p) "#edf2e9" "#ffffff"))) - (head3 (if (eq variant 'dark) (if (true-color-p) "#67b11d" "#67b11d") (if (true-color-p) "#67b11d" "#5faf00"))) - (head3-bg (if (eq variant 'dark) (if (true-color-p) "#293235" "#262626") (if (true-color-p) "#edf2e9" "#ffffff"))) - (head4 (if (eq variant 'dark) (if (true-color-p) "#b1951d" "#875f00") (if (true-color-p) "#b1951d" "#875f00"))) - (head4-bg (if (eq variant 'dark) (if (true-color-p) "#32322c" "#262626") (if (true-color-p) "#f6f1e1" "#ffffff"))) - (highlight (if (eq variant 'dark) (if (true-color-p) "#444155" "#444444") (if (true-color-p) "#d3d3e7" "#d7d7ff"))) - (highlight-dim (if (eq variant 'dark) (if (true-color-p) "#3b314d" "#444444") (if (true-color-p) "#e7e7fc" "#d7d7ff"))) - (keyword (if (eq variant 'dark) (if (true-color-p) "#4f97d7" "#268bd2") (if (true-color-p) "#3a81c3" "#268bd2"))) - (lnum (if (eq variant 'dark) (if (true-color-p) "#44505c" "#444444") (if (true-color-p) "#a8a8bf" "#af87af"))) - (mat (if (eq variant 'dark) (if (true-color-p) "#86dc2f" "#86dc2f") (if (true-color-p) "#ba2f59" "#af005f"))) - (meta (if (eq variant 'dark) (if (true-color-p) "#9f8766" "#af875f") (if (true-color-p) "#da8b55" "#df5f5f"))) - (str (if (eq variant 'dark) (if (true-color-p) "#2d9574" "#2aa198") (if (true-color-p) "#2d9574" "#2aa198"))) - (suc (if (eq variant 'dark) (if (true-color-p) "#86dc2f" "#86dc2f") (if (true-color-p) "#42ae2c" "#00af00"))) - (ttip (if (eq variant 'dark) (if (true-color-p) "#9a9aba" "#888888") (if (true-color-p) "#8c799f" "#5f5f87"))) - (ttip-sl (if (eq variant 'dark) (if (true-color-p) "#5e5079" "#333333") (if (true-color-p) "#c8c6dd" "#afafff"))) - (ttip-bg (if (eq variant 'dark) (if (true-color-p) "#34323e" "#444444") (if (true-color-p) "#e2e0ea" "#dfdfff"))) - (type (if (eq variant 'dark) (if (true-color-p) "#ce537a" "#df005f") (if (true-color-p) "#ba2f59" "#af005f"))) - (var (if (eq variant 'dark) (if (true-color-p) "#7590db" "#8787d7") (if (true-color-p) "#715ab1" "#af5fd7"))) - (war (if (eq variant 'dark) (if (true-color-p) "#dc752f" "#dc752f") (if (true-color-p) "#dc752f" "#dc752f"))) + (let* ((true-color-p (lambda () + (or (display-graphic-p) + (= (tty-display-color-cells) 16777216)))) + ;; Helper function to get custom color or default value + (get-color (lambda (color-name default-value) + (or (alist-get color-name spacemacs-theme-custom-colors) + default-value))) + ;; Helper function to pick color based on variant and display capability + (pick-color (lambda (dark-gui dark-ter light-gui light-ter) + (if (eq variant 'dark) + (if (funcall true-color-p) dark-gui dark-ter) + (if (funcall true-color-p) light-gui light-ter)))) + (class '((class color) (min-colors 89))) + ;; --- Dark --- --- Light --- + ;; GUI TER GUI TER + (act1 (funcall get-color 'act1 (funcall pick-color "#222226" "#121212" "#e7e5eb" "#d7dfff"))) + (act2 (funcall get-color 'act2 (funcall pick-color "#5d4d7a" "#444444" "#d3d3e7" "#afafd7"))) + (base (funcall get-color 'base (funcall pick-color "#b2b2b2" "#b2b2b2" "#655370" "#5f5f87"))) + (base-dim (funcall get-color 'base-dim (funcall pick-color "#686868" "#585858" "#a094a2" "#afafd7"))) + (bg1 (funcall get-color 'bg1 (funcall pick-color "#292b2e" "#262626" "#fbf8ef" "#ffffff"))) + (bg2 (funcall get-color 'bg2 (funcall pick-color "#212026" "#1c1c1c" "#efeae9" "#e4e4e4"))) + (bg3 (funcall get-color 'bg3 (funcall pick-color "#100a14" "#121212" "#e3dedd" "#d0d0d0"))) + (bg4 (funcall get-color 'bg4 (funcall pick-color "#0a0814" "#080808" "#d2ceda" "#bcbcbc"))) + (bg-alt (funcall get-color 'bg-alt (funcall pick-color "#42444a" "#353535" "#efeae9" "#e4e4e4"))) + (border (funcall get-color 'border (funcall pick-color "#5d4d7a" "#111111" "#b3b9be" "#b3b9be"))) + (cblk (funcall get-color 'cblk (funcall pick-color "#cbc1d5" "#b2b2b2" "#655370" "#5f5f87"))) + (cblk-bg (funcall get-color 'cblk-bg (funcall pick-color "#2f2b33" "#262626" "#e8e3f0" "#ffffff"))) + (cblk-ln (funcall get-color 'cblk-ln (funcall pick-color "#827591" "#af5faf" "#9380b2" "#af5fdf"))) + (cblk-ln-bg (funcall get-color 'cblk-ln-bg (funcall pick-color "#373040" "#333333" "#ddd8eb" "#dfdfff"))) + (cursor (funcall get-color 'cursor (funcall pick-color "#e3dedd" "#d0d0d0" "#100a14" "#121212"))) + (const (funcall get-color 'const (funcall pick-color "#a45bad" "#d75fd7" "#4e3163" "#8700af"))) + (comment (funcall get-color 'comment (funcall pick-color "#2aa1ae" "#008787" "#2aa1ae" "#008787"))) + (comment-light (funcall get-color 'comment-light (funcall pick-color "#2aa1ae" "#008787" "#a49da5" "#008787"))) + (comment-bg (funcall get-color 'comment-bg (funcall pick-color "#292e34" "#262626" "#ecf3ec" "#ffffff"))) + (comp (funcall get-color 'comp (funcall pick-color "#c56ec3" "#d75fd7" "#6c4173" "#8700af"))) + (err (funcall get-color 'err (funcall pick-color "#e0211d" "#e0211d" "#e0211d" "#e0211d"))) + (func (funcall get-color 'func (funcall pick-color "#bc6ec5" "#d75fd7" "#6c3163" "#8700af"))) + (head1 (funcall get-color 'head1 (funcall pick-color "#4f97d7" "#268bd2" "#3a81c3" "#268bd2"))) + (head1-bg (funcall get-color 'head1-bg (funcall pick-color "#293239" "#262626" "#edf1ed" "#ffffff"))) + (head2 (funcall get-color 'head2 (funcall pick-color "#2d9574" "#2aa198" "#2d9574" "#2aa198"))) + (head2-bg (funcall get-color 'head2-bg (funcall pick-color "#293235" "#262626" "#edf2e9" "#ffffff"))) + (head3 (funcall get-color 'head3 (funcall pick-color "#67b11d" "#67b11d" "#67b11d" "#5faf00"))) + (head3-bg (funcall get-color 'head3-bg (funcall pick-color "#293235" "#262626" "#edf2e9" "#ffffff"))) + (head4 (funcall get-color 'head4 (funcall pick-color "#b1951d" "#875f00" "#b1951d" "#875f00"))) + (head4-bg (funcall get-color 'head4-bg (funcall pick-color "#32322c" "#262626" "#f6f1e1" "#ffffff"))) + (highlight (funcall get-color 'highlight (funcall pick-color "#444155" "#444444" "#d3d3e7" "#d7d7ff"))) + (highlight-dim (funcall get-color 'highlight-dim (funcall pick-color "#3b314d" "#444444" "#e7e7fc" "#d7d7ff"))) + (keyword (funcall get-color 'keyword (funcall pick-color "#4f97d7" "#268bd2" "#3a81c3" "#268bd2"))) + (lnum (funcall get-color 'lnum (funcall pick-color "#44505c" "#444444" "#a8a8bf" "#af87af"))) + (mat (funcall get-color 'mat (funcall pick-color "#86dc2f" "#86dc2f" "#ba2f59" "#af005f"))) + (meta (funcall get-color 'meta (funcall pick-color "#9f8766" "#af875f" "#da8b55" "#df5f5f"))) + (str (funcall get-color 'str (funcall pick-color "#2d9574" "#2aa198" "#2d9574" "#2aa198"))) + (suc (funcall get-color 'suc (funcall pick-color "#86dc2f" "#86dc2f" "#42ae2c" "#00af00"))) + (ttip (funcall get-color 'ttip (funcall pick-color "#9a9aba" "#888888" "#8c799f" "#5f5f87"))) + (ttip-sl (funcall get-color 'ttip-sl (funcall pick-color "#5e5079" "#333333" "#c8c6dd" "#afafff"))) + (ttip-bg (funcall get-color 'ttip-bg (funcall pick-color "#34323e" "#444444" "#e2e0ea" "#dfdfff"))) + (type (funcall get-color 'type (funcall pick-color "#ce537a" "#df005f" "#ba2f59" "#af005f"))) + (var (funcall get-color 'var (funcall pick-color "#7590db" "#8787d7" "#715ab1" "#af5fd7"))) + (war (funcall get-color 'war (funcall pick-color "#dc752f" "#dc752f" "#dc752f" "#dc752f"))) + (aqua (funcall get-color 'aqua (funcall pick-color "#2d9574" "#2aa198" "#2d9574" "#2aa198"))) + (aqua-bg (funcall get-color 'aqua-bg (funcall pick-color "#293235" "#262626" "#edf2e9" "#ffffff"))) + (green (funcall get-color 'green (funcall pick-color "#67b11d" "#67b11d" "#67b11d" "#5faf00"))) + (green-bg (funcall get-color 'green-bg (funcall pick-color "#293235" "#262626" "#edf2e9" "#ffffff"))) + (green-bg-s (funcall get-color 'green-bg-s (funcall pick-color "#29422d" "#262626" "#dae6d0" "#ffffff"))) + (cyan (funcall get-color 'cyan (funcall pick-color "#28def0" "#00ffff" "#21b8c7" "#008080"))) + (red (funcall get-color 'red (funcall pick-color "#f2241f" "#d70000" "#f2241f" "#d70008"))) + (red-bg (funcall get-color 'red-bg (funcall pick-color "#3c2a2c" "#262626" "#faede4" "#ffffff"))) + (red-bg-s (funcall get-color 'red-bg-s (funcall pick-color "#512e31" "#262626" "#eed9d2" "#ffffff"))) + (blue (funcall get-color 'blue (funcall pick-color "#4f97d7" "#268bd2" "#3a81c3" "#268bd2"))) + (blue-bg (funcall get-color 'blue-bg (funcall pick-color "#293239" "#262626" "#edf1ed" "#d7d7ff"))) + (blue-bg-s (funcall get-color 'blue-bg-s (funcall pick-color "#2d4252" "#262626" "#d1dcdf" "#d7d7ff"))) + (magenta (funcall get-color 'magenta (funcall pick-color "#a31db1" "#af00df" "#a31db1" "#800080"))) + (yellow (funcall get-color 'yellow (funcall pick-color "#b1951d" "#875f00" "#b1951d" "#875f00"))) + (yellow-bg (funcall get-color 'yellow-bg (funcall pick-color "#32322c" "#262626" "#f6f1e1" "#ffffff")))) - ;; colors - (aqua (if (eq variant 'dark) (if (true-color-p) "#2d9574" "#2aa198") (if (true-color-p) "#2d9574" "#2aa198"))) - (aqua-bg (if (eq variant 'dark) (if (true-color-p) "#293235" "#262626") (if (true-color-p) "#edf2e9" "#ffffff"))) - (green (if (eq variant 'dark) (if (true-color-p) "#67b11d" "#67b11d") (if (true-color-p) "#67b11d" "#5faf00"))) - (green-bg (if (eq variant 'dark) (if (true-color-p) "#293235" "#262626") (if (true-color-p) "#edf2e9" "#ffffff"))) - (green-bg-s (if (eq variant 'dark) (if (true-color-p) "#29422d" "#262626") (if (true-color-p) "#dae6d0" "#ffffff"))) - (cyan (if (eq variant 'dark) (if (true-color-p) "#28def0" "#00ffff") (if (true-color-p) "#21b8c7" "#008080"))) - (red (if (eq variant 'dark) (if (true-color-p) "#f2241f" "#d70000") (if (true-color-p) "#f2241f" "#d70008"))) - (red-bg (if (eq variant 'dark) (if (true-color-p) "#3c2a2c" "#262626") (if (true-color-p) "#faede4" "#ffffff"))) - (red-bg-s (if (eq variant 'dark) (if (true-color-p) "#512e31" "#262626") (if (true-color-p) "#eed9d2" "#ffffff"))) - (blue (if (eq variant 'dark) (if (true-color-p) "#4f97d7" "#268bd2") (if (true-color-p) "#3a81c3" "#268bd2"))) - (blue-bg (if (eq variant 'dark) (if (true-color-p) "#293239" "#262626") (if (true-color-p) "#edf1ed" "#d7d7ff"))) - (blue-bg-s (if (eq variant 'dark) (if (true-color-p) "#2d4252" "#262626") (if (true-color-p) "#d1dcdf" "#d7d7ff"))) - (magenta (if (eq variant 'dark) (if (true-color-p) "#a31db1" "#af00df") (if (true-color-p) "#a31db1" "#800080"))) - (yellow (if (eq variant 'dark) (if (true-color-p) "#b1951d" "#875f00") (if (true-color-p) "#b1951d" "#875f00"))) - (yellow-bg (if (eq variant 'dark) (if (true-color-p) "#32322c" "#262626") (if (true-color-p) "#f6f1e1" "#ffffff")))) - (cl-loop for (cvar . val) in spacemacs-theme-custom-colors - do (set cvar val)) (custom-theme-set-faces theme-name ;;;;; basics `(completions-common-part ((,class (:foreground ,keyword :weight bold)))) + `(completions-annotations ((,class (:foreground ,base-dim :italic nil)))) `(cursor ((,class (:background ,cursor)))) `(custom-button ((,class :background ,bg2 :foreground ,base :box (:line-width 2 :style released-button)))) `(default ((,class (:background ,bg1 :foreground ,base)))) @@ -198,8 +204,8 @@ to 'auto, tags may not be properly aligned. " `(hl-line ((,class (:background ,bg2 :extend t)))) `(isearch ((,class (:foreground ,bg1 :background ,mat)))) `(lazy-highlight ((,class (:background ,green-bg-s)))) - `(link ((,class (:foreground ,comment :underline t)))) - `(link-visited ((,class (:foreground ,comp :underline t)))) + `(link ((,class (:foreground ,blue :underline t)))) + `(link-visited ((,class (:foreground ,magenta :underline t)))) `(match ((,class (:background ,highlight :foreground ,mat)))) `(minibuffer-prompt ((,class (:inherit bold :foreground ,keyword)))) `(page-break-lines ((,class (:foreground ,act2)))) @@ -270,10 +276,8 @@ to 'auto, tags may not be properly aligned. " `(centaur-tabs-default ((,class (:background ,bg1 :foreground ,bg1)))) `(centaur-tabs-selected ((,class (:background ,bg1 :foreground ,base :weight bold)))) `(centaur-tabs-unselected ((,class (:background ,bg2 :foreground ,base-dim :weight light)))) - `(centaur-tabs-selected-modified ((,class (:background ,bg1 - :foreground ,blue :weight bold)))) - `(centaur-tabs-unselected-modified ((,class (:background ,bg2 :weight light - :foreground ,blue)))) + `(centaur-tabs-selected-modified ((,class (:background ,bg1 :foreground ,blue :weight bold)))) + `(centaur-tabs-unselected-modified ((,class (:background ,bg2 :weight light :foreground ,blue)))) `(centaur-tabs-active-bar-face ((,class (:background ,keyword)))) `(centaur-tabs-modified-marker-selected ((,class (:inherit 'centaur-tabs-selected :foreground,keyword)))) `(centaur-tabs-modified-marker-unselected ((,class (:inherit 'centaur-tabs-unselected :foreground,keyword)))) @@ -305,6 +309,11 @@ to 'auto, tags may not be properly aligned. " `(company-tooltip-search ((,class (:inherit match)))) `(company-tooltip-selection ((,class (:background ,ttip-sl :foreground ,base)))) +;;;;; corfu + `(corfu-annotations ((,class (:foreground ,var :italic nil)))) + `(corfu-default ((,class (:background ,ttip-bg :foreground ,ttip)))) + `(corfu-current ((,class (:background ,ttip-sl :foreground ,base)))) + ;;;;; diff `(diff-added ((,class :background unspecified :foreground ,green :extend t))) `(diff-changed ((,class :background unspecified :foreground ,blue))) @@ -427,30 +436,30 @@ to 'auto, tags may not be properly aligned. " `(evil-ex-substitute-replacement ((,class (:background ,green-bg :foreground ,green)))) ;;;;; evil-goggles - `(evil-goggles--pulse-face ((,class (:background ,yellow-bg :foreground ,yellow)))) - `(evil-goggles-change-face ((,class (:background ,blue-bg-s :foreground ,blue)))) - `(evil-goggles-commentary-face ((,class (:background ,aqua-bg :foreground ,aqua)))) - `(evil-goggles-delete-face ((,class (:background ,red-bg-s :foreground ,red)))) - `(evil-goggles-fill-and-move-face ((,class (:background ,green-bg-s :foreground ,green)))) - `(evil-goggles-indent-face ((,class (:background ,green-bg-s :foreground ,green)))) - `(evil-goggles-join-face ((,class (:background ,green-bg-s :foreground ,green)))) - `(evil-goggles-nerd-commenter-face ((,class (:background ,aqua-bg :foreground ,aqua)))) - `(evil-goggles-paste-face ((,class (:background ,green-bg-s :foreground ,green)))) - `(evil-goggles-record-macro-face ((,class (:background ,blue-bg-s :foreground ,blue)))) - `(evil-goggles-replace-with-register-face ((,class (:background ,yellow-bg :foreground ,yellow)))) - `(evil-goggles-set-marker-face ((,class (:background ,blue-bg-s :foreground ,blue)))) - `(evil-goggles-shift-face ((,class (:background ,blue-bg-s :foreground ,blue)))) - `(evil-goggles-surround-face ((,class (:background ,blue-bg-s :foreground ,blue)))) - `(evil-goggles-yank-face ((,class (:background ,blue-bg-s :foreground ,blue)))) - `(evil-goggles-undo-redo-add-face ((,class (:background ,green-bg-s :foreground ,green)))) - `(evil-goggles-undo-redo-change-face ((,class (:background ,blue-bg-s :foreground ,blue)))) - `(evil-goggles-undo-redo-remove-face ((,class (:background ,red-bg-s :foreground ,red)))) + `(evil-goggles--pulse-face ((,class (:background ,yellow-bg :foreground ,yellow)))) + `(evil-goggles-change-face ((,class (:background ,blue-bg-s :foreground ,blue)))) + `(evil-goggles-commentary-face ((,class (:background ,aqua-bg :foreground ,aqua)))) + `(evil-goggles-delete-face ((,class (:background ,red-bg-s :foreground ,red)))) + `(evil-goggles-fill-and-move-face ((,class (:background ,green-bg-s :foreground ,green)))) + `(evil-goggles-indent-face ((,class (:background ,green-bg-s :foreground ,green)))) + `(evil-goggles-join-face ((,class (:background ,green-bg-s :foreground ,green)))) + `(evil-goggles-nerd-commenter-face ((,class (:background ,aqua-bg :foreground ,aqua)))) + `(evil-goggles-paste-face ((,class (:background ,green-bg-s :foreground ,green)))) + `(evil-goggles-record-macro-face ((,class (:background ,blue-bg-s :foreground ,blue)))) + `(evil-goggles-replace-with-register-face ((,class (:background ,yellow-bg :foreground ,yellow)))) + `(evil-goggles-set-marker-face ((,class (:background ,blue-bg-s :foreground ,blue)))) + `(evil-goggles-shift-face ((,class (:background ,blue-bg-s :foreground ,blue)))) + `(evil-goggles-surround-face ((,class (:background ,blue-bg-s :foreground ,blue)))) + `(evil-goggles-yank-face ((,class (:background ,blue-bg-s :foreground ,blue)))) + `(evil-goggles-undo-redo-add-face ((,class (:background ,green-bg-s :foreground ,green)))) + `(evil-goggles-undo-redo-change-face ((,class (:background ,blue-bg-s :foreground ,blue)))) + `(evil-goggles-undo-redo-remove-face ((,class (:background ,red-bg-s :foreground ,red)))) ;;;;; evil-mc - `(evil-mc-cursor-bar-face ((,class (:foreground ,aqua)))) - `(evil-mc-cursor-default-face ((,class (:background ,aqua :foreground ,bg4)))) - `(evil-mc-cursor-hbar-face ((,class (:foreground ,aqua)))) - `(evil-mc-region-face ((,class (:inherit highlight)))) + `(evil-mc-cursor-bar-face ((,class (:foreground ,aqua)))) + `(evil-mc-cursor-default-face ((,class (:background ,aqua :foreground ,bg4)))) + `(evil-mc-cursor-hbar-face ((,class (:foreground ,aqua)))) + `(evil-mc-region-face ((,class (:inherit highlight)))) ;;;;; flycheck `(flycheck-error @@ -573,6 +582,20 @@ to 'auto, tags may not be properly aligned. " `(helm-time-zone-home ((,class (:foreground ,comp :background ,bg1)))) `(helm-visible-mark ((,class (:foreground ,keyword :background ,bg3)))) +;;;;; helm-ls-git + `(helm-ls-git-added-copied-face ((,class (:foreground ,green)))) + `(helm-ls-git-added-modified-face ((,class (:foreground ,cyan)))) + `(helm-ls-git-branches-current ((,class (:foreground ,yellow)))) + `(helm-ls-git-branches-name ((,class (:foreground ,red)))) + `(helm-ls-git-branches-name-current ((,class (:foreground ,green)))) + `(helm-ls-git-conflict-face ((,class (:foreground ,magenta)))) + `(helm-ls-git-deleted-and-staged-face ((,class (:foreground ,comment)))) + `(helm-ls-git-deleted-not-staged-face ((,class (:foreground ,war)))) + `(helm-ls-git-modified-and-staged-face ((,class (:foreground ,war)))) + `(helm-ls-git-modified-not-staged-face ((,class (:foreground ,yellow)))) + `(helm-ls-git-renamed-modified-face ((,class (:foreground ,war)))) + `(helm-ls-git-untracked-face ((,class (:foreground ,red)))) + ;;;;; helm-swoop `(helm-swoop-target-line-block-face ((,class (:foreground ,base :background ,highlight)))) `(helm-swoop-target-line-face ((,class (:background ,highlight)))) @@ -614,6 +637,16 @@ to 'auto, tags may not be properly aligned. " `(ido-subdir ((,class (:foreground ,keyword)))) `(ido-vertical-match-face ((,class (:foreground ,comp :underline nil)))) +;;;;; imenu + `(imenu-list-entry-face-0 ((,class (:foreground ,head1)))) + `(imenu-list-entry-face-1 ((,class (:foreground ,head2)))) + `(imenu-list-entry-face-2 ((,class (:foreground ,head3)))) + `(imenu-list-entry-face-3 ((,class (:foreground ,head4)))) + `(imenu-list-entry-subalist-face-0 ((,class (:foreground ,head1 :inherit bold)))) + `(imenu-list-entry-subalist-face-1 ((,class (:foreground ,head2 :inherit bold)))) + `(imenu-list-entry-subalist-face-2 ((,class (:foreground ,head3 :inherit bold)))) + `(imenu-list-entry-subalist-face-3 ((,class (:foreground ,head4 :inherit bold)))) + ;;;;; info `(info-header-xref ((,class (:foreground ,func :underline t)))) `(info-menu ((,class (:foreground ,suc)))) @@ -667,10 +700,14 @@ to 'auto, tags may not be properly aligned. " ;;;;; linum-relative `(linum-relative-current-face ((,class (:foreground ,comp)))) -;;;;; lsp +;;;;; lsp-mode + `(lsp-face-highlight-read ((,class (:background ,yellow-bg)))) + `(lsp-face-highlight-write ((,class (:background ,green-bg-s)))) + `(lsp-face-highlight-textual ((,class (:background ,green-bg)))) + +;;;;; lsp-ui `(lsp-ui-doc-background ((,class (:background ,bg2)))) `(lsp-ui-doc-header ((,class (:foreground ,head1 :background ,head1-bg)))) - `(lsp-ui-sideline-code-action ((,class (:foreground ,comp)))) ;;;;; magit @@ -811,7 +848,7 @@ to 'auto, tags may not be properly aligned. " `(org-level-6 ((,class (:weight normal :foreground ,head2)))) `(org-level-7 ((,class (:weight normal :foreground ,head3)))) `(org-level-8 ((,class (:weight normal :foreground ,head4)))) - `(org-link ((,class (:underline t :foreground ,comment)))) + `(org-link ((,class (:underline t :foreground ,blue)))) `(org-meta-line ((,class (:foreground ,meta)))) `(org-mode-line-clock-overrun ((,class (:foreground ,err)))) `(org-priority ((,class (:foreground ,war :inherit bold :weight ,(if spacemacs-theme-org-priority-bold 'unspecified 'normal))))) @@ -832,14 +869,14 @@ to 'auto, tags may not be properly aligned. " `(org-warning ((,class (:foreground ,err :inherit org-priority)))) ;;;;; outline - `(outline-1 ((,class (:inherit org-level-1)))) - `(outline-2 ((,class (:inherit org-level-2)))) - `(outline-3 ((,class (:inherit org-level-3)))) - `(outline-4 ((,class (:inherit org-level-4)))) - `(outline-5 ((,class (:inherit org-level-5)))) - `(outline-6 ((,class (:inherit org-level-6)))) - `(outline-7 ((,class (:inherit org-level-7)))) - `(outline-8 ((,class (:inherit org-level-8)))) + `(outline-1 ((,class (:foreground ,head1)))) + `(outline-2 ((,class (:foreground ,head2)))) + `(outline-3 ((,class (:foreground ,head3)))) + `(outline-4 ((,class (:foreground ,head4)))) + `(outline-5 ((,class (:foreground ,head1)))) + `(outline-6 ((,class (:foreground ,head2)))) + `(outline-7 ((,class (:foreground ,head3)))) + `(outline-8 ((,class (:foreground ,head4)))) ;;;;; parinfer `(parinfer-pretty-parens:dim-paren-face ((,class (:foreground ,base-dim)))) @@ -973,6 +1010,15 @@ to 'auto, tags may not be properly aligned. " ;;;;; tide `(tide-hl-identifier-face ((,class (:foreground ,yellow :background ,yellow-bg)))) +;;;;; transient + `(transient-key ((,class (:foreground ,keyword)))) + `(transient-key-exit ((,class (:foreground ,type)))) + `(transient-key-noop ((,class (:foreground ,base-dim)))) + `(transient-key-recurse ((,class (:foreground ,blue)))) + `(transient-key-return ((,class (:foreground ,mat)))) + `(transient-key-stack ((,class (:foreground ,func)))) + `(transient-key-stay ((,class (:foreground ,green)))) + ;;;;; treemacs `(treemacs-git-added-face ((,class (:foreground ,green :background ,green-bg)))) `(treemacs-git-conflict-face ((,class (:foreground ,red :background ,red-bg)))) @@ -1084,8 +1130,8 @@ to 'auto, tags may not be properly aligned. " `(org-fontify-todo-headline nil) ;;;;; pdf-tools - `(pdf-view-midnight-colors '(,base . ,bg1))) - )) + `(pdf-view-midnight-colors '(,base . ,bg1)) + ))) ;;;###autoload @@ -1095,8 +1141,4 @@ to 'auto, tags may not be properly aligned. " (provide 'spacemacs-theme) -;; Local Variables: -;; no-byte-compile: t -;; End: - ;;; spacemacs-theme.el ends here diff --git a/lisp/sphinx-doc/sphinx-doc-pkg.el b/lisp/sphinx-doc/sphinx-doc-pkg.el index 1ca6c207..9299aeaa 100644 --- a/lisp/sphinx-doc/sphinx-doc-pkg.el +++ b/lisp/sphinx-doc/sphinx-doc-pkg.el @@ -1,16 +1,12 @@ -(define-package "sphinx-doc" "20210213.1250" "Sphinx friendly docstrings for Python functions" - '((s "1.9.0") +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "sphinx-doc" "20210213.1250" + "Sphinx friendly docstrings for Python functions." + '((s "1.9.0") (cl-lib "0.5") - (dash "2.10.0")) - :commit "1eda612a44ef027e5229895daa77db99a21b8801" :authors - '(("Vineet Naik" . "naikvin@gmail.com")) - :maintainers - '(("Vineet Naik" . "naikvin@gmail.com")) - :maintainer - '("Vineet Naik" . "naikvin@gmail.com") - :keywords - '("sphinx" "python") - :url "https://github.com/naiquevin/sphinx-doc.el") -;; Local Variables: -;; no-byte-compile: t -;; End: + (dash "2.10.0")) + :url "https://github.com/naiquevin/sphinx-doc.el" + :commit "1eda612a44ef027e5229895daa77db99a21b8801" + :revdesc "1eda612a44ef" + :keywords '("sphinx" "python") + :authors '(("Vineet Naik" . "naikvin@gmail.com")) + :maintainers '(("Vineet Naik" . "naikvin@gmail.com"))) diff --git a/lisp/sphinx-doc/sphinx-doc.el b/lisp/sphinx-doc/sphinx-doc.el index 1d048a01..ab92d209 100755 --- a/lisp/sphinx-doc/sphinx-doc.el +++ b/lisp/sphinx-doc/sphinx-doc.el @@ -4,7 +4,8 @@ ;; Author: Vineet Naik ;; URL: https://github.com/naiquevin/sphinx-doc.el -;; Version: 0.3.0 +;; Package-Version: 20210213.1250 +;; Package-Revision: 1eda612a44ef ;; Keywords: Sphinx, Python ;; Package-Requires: ((s "1.9.0") (cl-lib "0.5") (dash "2.10.0")) diff --git a/lisp/srefactor/srefactor-lisp.el b/lisp/srefactor/srefactor-lisp.el index 4a3f9414..00c75433 100644 --- a/lisp/srefactor/srefactor-lisp.el +++ b/lisp/srefactor/srefactor-lisp.el @@ -6,7 +6,6 @@ ;; URL : https://github.com/tuhdo/semantic-refactor ;; Maintainer: Tu, Do Hoang ;; Created: Wed Feb 11 21:25:51 2015 (+0700) -;; Version: 0.3 ;; Package-Requires: ((emacs "24.3+")) ;; Last-Updated: Wed Feb 11 21:25:51 2015 (+0700) ;; By: Tu, Do Hoang diff --git a/lisp/srefactor/srefactor-pkg.el b/lisp/srefactor/srefactor-pkg.el index 6e34c3d1..9767fea5 100644 --- a/lisp/srefactor/srefactor-pkg.el +++ b/lisp/srefactor/srefactor-pkg.el @@ -1,10 +1,9 @@ -(define-package "srefactor" "20230504.617" "A refactoring tool based on Semantic parser framework" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "srefactor" "20230504.617" + "A refactoring tool based on Semantic parser framework." '((emacs "24.4")) - :commit "95c70a94b5aad4c85b35569e2f2325047791153a" :authors - '(("Do Hoang" . "tuhdo1710@gmail.com")) - :keywords - '("c" "languages" "tools") - :url "https://github.com/tuhdo/semantic-refactor") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/tuhdo/semantic-refactor" + :commit "95c70a94b5aad4c85b35569e2f2325047791153a" + :revdesc "95c70a94b5aa" + :keywords '("c" "languages" "tools") + :authors '(("Do Hoang" . "tuhdo1710@gmail.com"))) diff --git a/lisp/srefactor/srefactor-ui.el b/lisp/srefactor/srefactor-ui.el index e6a9b5aa..ffd77bb9 100644 --- a/lisp/srefactor/srefactor-ui.el +++ b/lisp/srefactor/srefactor-ui.el @@ -5,7 +5,6 @@ ;; Author: Tu, Do Hoang UPCASE -> CamelCase -> lowerCamelCase conversion of names" 'nil :commit "4cc92e1ecd3d165b55235b51ae65ac09a0364958" :authors - '(("akicho8" . "akicho8@gmail.com")) - :maintainers - '(("akicho8" . "akicho8@gmail.com")) - :maintainer - '("akicho8" . "akicho8@gmail.com") - :keywords - '("elisp")) -;; Local Variables: -;; no-byte-compile: t -;; End: +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "string-inflection" "20240816.523" + "Underscore -> UPCASE -> CamelCase -> lowerCamelCase conversion of names." + () + :url "https://github.com/akicho8/string-inflection" + :commit "4cc92e1ecd3d165b55235b51ae65ac09a0364958" + :revdesc "4cc92e1ecd3d" + :keywords '("elisp") + :authors '(("akicho8" . "akicho8@gmail.com")) + :maintainers '(("akicho8" . "akicho8@gmail.com"))) diff --git a/lisp/string-inflection/string-inflection.el b/lisp/string-inflection/string-inflection.el index 66889916..c48a166f 100644 --- a/lisp/string-inflection/string-inflection.el +++ b/lisp/string-inflection/string-inflection.el @@ -4,7 +4,8 @@ ;; Author: akicho8 ;; Keywords: elisp -;; Version: 1.1.0 +;; Package-Version: 20240816.523 +;; Package-Revision: 4cc92e1ecd3d ;; This file is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by diff --git a/lisp/swiper/swiper-pkg.el b/lisp/swiper/swiper-pkg.el index 5fc9ba11..1e7736ab 100644 --- a/lisp/swiper/swiper-pkg.el +++ b/lisp/swiper/swiper-pkg.el @@ -1,15 +1,11 @@ -(define-package "swiper" "20250224.2125" "Isearch with an overview. Oh, man!" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "swiper" "20250329.1401" + "Isearch with an overview. Oh, man!." '((emacs "24.5") - (ivy "0.15.0")) - :commit "7a0d554aaf4ebbb2c45f2451d77747df4f7e2742" :authors - '(("Oleh Krehel" . "ohwoeowho@gmail.com")) - :maintainers - '(("Basil L. Contovounesios" . "basil@contovou.net")) - :maintainer - '("Basil L. Contovounesios" . "basil@contovou.net") - :keywords - '("matching") - :url "https://github.com/abo-abo/swiper") -;; Local Variables: -;; no-byte-compile: t -;; End: + (ivy "0.15.1")) + :url "https://github.com/abo-abo/swiper" + :commit "e33b028ed4b1258a211c87fd5fe801bed25de429" + :revdesc "e33b028ed4b1" + :keywords '("matching") + :authors '(("Oleh Krehel" . "ohwoeowho@gmail.com")) + :maintainers '(("Basil L. Contovounesios" . "basil@contovou.net"))) diff --git a/lisp/swiper/swiper.el b/lisp/swiper/swiper.el index edeee0e9..aea48b27 100644 --- a/lisp/swiper/swiper.el +++ b/lisp/swiper/swiper.el @@ -5,8 +5,9 @@ ;; Author: Oleh Krehel ;; Maintainer: Basil L. Contovounesios ;; URL: https://github.com/abo-abo/swiper -;; Version: 0.15.0 -;; Package-Requires: ((emacs "24.5") (ivy "0.15.0")) +;; Package-Version: 20250329.1401 +;; Package-Revision: e33b028ed4b1 +;; Package-Requires: ((emacs "24.5") (ivy "0.15.1")) ;; Keywords: matching ;; This file is part of GNU Emacs. @@ -155,12 +156,12 @@ If the input is empty, select the previous history element instead." (defvar swiper-map (let ((map (make-sparse-keymap))) - (define-key map (kbd "C-s") 'swiper-C-s) - (define-key map (kbd "M-q") 'swiper-query-replace) - (define-key map (kbd "C-l") 'swiper-recenter-top-bottom) - (define-key map (kbd "C-'") 'swiper-avy) - (define-key map (kbd "C-7") 'swiper-mc) - (define-key map (kbd "C-c C-f") 'swiper-toggle-face-matching) + (define-key map (kbd "C-s") #'swiper-C-s) + (define-key map (kbd "M-q") #'swiper-query-replace) + (define-key map (kbd "C-l") #'swiper-recenter-top-bottom) + (define-key map (kbd "C-'") #'swiper-avy) + (define-key map (kbd "C-7") #'swiper-mc) + (define-key map (kbd "C-c C-f") #'swiper-toggle-face-matching) map) "Keymap for swiper.") @@ -247,7 +248,7 @@ If the input is empty, select the previous history element instead." (ivy-configure 'swiper-query-replace :update-fn #'swiper--query-replace-updatefn) -(put 'swiper-query-replace 'no-counsel-M-x t) +(function-put #'swiper-query-replace 'no-counsel-M-x t) (defvar inhibit-message) @@ -272,7 +273,7 @@ If the input is empty, select the previous history element instead." (goto-char (point-min)) (perform-replace from to t t nil))) (set-window-configuration wnd-conf)))))))) -(put 'swiper-all-query-replace 'no-counsel-M-x t) +(function-put #'swiper-all-query-replace 'no-counsel-M-x t) (defvar avy-all-windows) (defvar avy-style) @@ -481,7 +482,7 @@ such as `scroll-conservatively' are set to a high value.") "List of major-modes that are incompatible with `font-lock-ensure'.") (defun swiper-font-lock-ensure-p () - "Return non-nil if we should `font-lock-ensure'." + "Return non-nil if we should not `font-lock-ensure'." (or (derived-mode-p 'magit-mode) (bound-and-true-p magit-blame-mode) (memq major-mode swiper-font-lock-exclude) @@ -489,12 +490,13 @@ such as `scroll-conservatively' are set to a high value.") (defun swiper-font-lock-ensure () "Ensure the entire buffer is highlighted." - (unless (swiper-font-lock-ensure-p) - (unless (or (> (buffer-size) 100000) (null font-lock-mode)) - (if (fboundp 'font-lock-ensure) - ;; Added in Emacs 25.1. - (font-lock-ensure) - (with-no-warnings (font-lock-fontify-buffer)))))) + (unless (or (swiper-font-lock-ensure-p) + (> (buffer-size) 100000) + (not font-lock-mode)) + (static-if (fboundp 'font-lock-ensure) + ;; Added in Emacs 25.1. + (font-lock-ensure) + (font-lock-fontify-buffer)))) (defvar swiper--format-spec "" "Store the current candidates format spec.") @@ -857,6 +859,9 @@ When non-nil, INITIAL-INPUT is the initial search pattern." :unwind-fn #'swiper--cleanup :index-fn #'ivy-recompute-index-swiper) +(ivy-add-actions 'swiper + `(("w" ,#'swiper-action-copy "copy"))) + (defun swiper-toggle-face-matching () "Toggle matching only the candidates with `swiper-invocation-face'." (interactive) @@ -1085,7 +1090,7 @@ WND, when specified is the window." (defvar evil-ex-search-pattern) (defvar evil-ex-search-persistent-highlight) (defvar evil-ex-search-direction) -(declare-function evil-ex-search-activate-highlight "evil-ex") +(declare-function evil-ex-search-activate-highlight "ext:evil-search") (defun swiper--maybe-recenter () (cond (swiper-action-recenter @@ -1259,8 +1264,9 @@ otherwise continue prompting for buffers." ((eq mode 'gnus-article-mode) t) ;; Otherwise, only consider the file if it's backed by a file. (t (buffer-file-name buffer))))) + +;;; `swiper-all' -;;* `swiper-all' (defun swiper-all-function (str) "Search in all open buffers for STR." (or @@ -1331,7 +1337,7 @@ See `ivy-format-functions-alist' for further information." (defvar swiper-all-map (let ((map (make-sparse-keymap))) - (define-key map (kbd "M-q") 'swiper-all-query-replace) + (define-key map (kbd "M-q") #'swiper-all-query-replace) map) "Keymap for `swiper-all'.") @@ -1379,8 +1385,9 @@ See `ivy-format-functions-alist' for further information." (swiper--candidates 4)) res)))) res)) + +;;; `swiper-isearch' -;;* `swiper-isearch' (defun swiper-isearch-function (str) "Collect STR matches in the current buffer for `swiper-isearch'." (with-ivy-window @@ -1564,10 +1571,6 @@ completion." ;; In case of unexpected error. (goto-char swiper--opoint))) -(ivy-add-actions 'swiper-isearch '(("w" swiper-isearch-action-copy "copy"))) -(ivy-add-actions 'swiper-isearch '(("i" swiper-isearch-action-insert "insert"))) -(ivy-add-actions 'swiper '(("w" swiper-action-copy "copy"))) - (defun swiper--isearch-insert-current () "Replace minibuffer contents with the current candidate. Like `ivy-insert-current', but tailored for `swiper-isearch'." @@ -1576,6 +1579,16 @@ Like `ivy-insert-current', but tailored for `swiper-isearch'." (let ((cur (ivy-state-current ivy-last))) (insert (with-ivy-window (swiper--isearch-candidate-string cur))))) +(defun swiper--isearch-kill-ring-save () + "Save the current candidates in the kill ring. +If the region is active, forward to `kill-ring-save' instead. +Like `ivy-kill-ring-save', but tailored for `swiper-isearch'." + (interactive) + (if (use-region-p) + (call-interactively #'kill-ring-save) + (kill-new (with-ivy-window + (mapconcat #'swiper--line-at-point ivy--old-cands "\n"))))) + (defun swiper-isearch-thing-at-point () "Insert `symbol-at-point' into the minibuffer of `swiper-isearch'. When not running `swiper-isearch' already, start it." @@ -1616,7 +1629,12 @@ When the input is empty, browse the search history instead." (defvar swiper-isearch-map (let ((map (make-sparse-keymap))) (set-keymap-parent map swiper-map) - (define-key map [remap ivy-insert-current] #'swiper--isearch-insert-current) + (define-key map `[remap ,#'ivy-insert-current] + #'swiper--isearch-insert-current) + (define-key map `[remap ,#'ivy-kill-ring-save] + #'swiper--isearch-kill-ring-save) + (define-key map `[remap ,#'kill-ring-save] + #'swiper--isearch-kill-ring-save) (define-key map (kbd "M-n") #'swiper-isearch-thing-at-point) (define-key map (kbd "C-r") #'swiper-isearch-C-r) map) @@ -1765,6 +1783,10 @@ When the input is empty, browse the search history instead." :unwind-fn #'swiper--isearch-unwind :format-fn #'swiper-isearch-format-function) +(ivy-add-actions 'swiper-isearch + `(("w" ,#'swiper-isearch-action-copy "copy") + ("i" ,#'swiper-isearch-action-insert "insert"))) + ;;;###autoload (defun swiper-isearch-backward (&optional initial-input) "Like `swiper-isearch' but the first result is before the point." diff --git a/lisp/systemd/systemd-pkg.el b/lisp/systemd/systemd-pkg.el index db80f48c..48ec7daa 100644 --- a/lisp/systemd/systemd-pkg.el +++ b/lisp/systemd/systemd-pkg.el @@ -1,13 +1,10 @@ -(define-package "systemd" "20230201.302" "Major mode for editing systemd units" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "systemd" "20230201.302" + "Major mode for editing systemd units." '((emacs "24.4")) - :commit "8742607120fbc440821acbc351fda1e8e68a8806" :authors - '(("Mark Oteiza" . "mvoteiza@udel.edu")) - :maintainers - '(("Mark Oteiza" . "mvoteiza@udel.edu")) - :maintainer - '("Mark Oteiza" . "mvoteiza@udel.edu") - :keywords - '("tools" "unix")) -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/holomorph/systemd-mode" + :commit "8742607120fbc440821acbc351fda1e8e68a8806" + :revdesc "8742607120fb" + :keywords '("tools" "unix") + :authors '(("Mark Oteiza" . "mvoteiza@udel.edu")) + :maintainers '(("Mark Oteiza" . "mvoteiza@udel.edu"))) diff --git a/lisp/systemd/systemd.el b/lisp/systemd/systemd.el index 6db04038..c04a46ed 100644 --- a/lisp/systemd/systemd.el +++ b/lisp/systemd/systemd.el @@ -3,7 +3,8 @@ ;; Copyright (C) 2014-2023 Mark Oteiza ;; Author: Mark Oteiza -;; Version: 1.6.1 +;; Package-Version: 20230201.302 +;; Package-Revision: 8742607120fb ;; Package-Requires: ((emacs "24.4")) ;; Keywords: tools, unix diff --git a/lisp/tablist/tablist-pkg.el b/lisp/tablist/tablist-pkg.el index fa9665ad..9ea7ff06 100644 --- a/lisp/tablist/tablist-pkg.el +++ b/lisp/tablist/tablist-pkg.el @@ -1,13 +1,10 @@ -(define-package "tablist" "20231019.1126" "Extended tabulated-list-mode" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "tablist" "20231019.1126" + "Extended tabulated-list-mode." '((emacs "24.3")) - :commit "fcd37147121fabdf003a70279cf86fbe08cfac6f" :authors - '(("Andreas Politz" . "politza@fh-trier.de")) - :maintainers - '(("Andreas Politz" . "politza@fh-trier.de")) - :maintainer - '("Andreas Politz" . "politza@fh-trier.de") - :keywords - '("extensions" "lisp")) -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/emacsorphanage/tablist" + :commit "fcd37147121fabdf003a70279cf86fbe08cfac6f" + :revdesc "fcd37147121f" + :keywords '("extensions" "lisp") + :authors '(("Andreas Politz" . "politza@fh-trier.de")) + :maintainers '(("Andreas Politz" . "politza@fh-trier.de"))) diff --git a/lisp/tablist/tablist.el b/lisp/tablist/tablist.el index 46e0693b..d2f9ae80 100644 --- a/lisp/tablist/tablist.el +++ b/lisp/tablist/tablist.el @@ -5,7 +5,8 @@ ;; Author: Andreas Politz ;; Keywords: extensions, lisp ;; Package: tablist -;; Version: 1.1 +;; Package-Version: 20231019.1126 +;; Package-Revision: fcd37147121f ;; Package-Requires: ((emacs "24.3")) ;; This program is free software; you can redistribute it and/or modify diff --git a/lisp/transient/transient-pkg.el b/lisp/transient/transient-pkg.el index acfb546f..67cf7ac1 100644 --- a/lisp/transient/transient-pkg.el +++ b/lisp/transient/transient-pkg.el @@ -1,16 +1,12 @@ -(define-package "transient" "20250306.1916" "Transient commands" - '((emacs "26.1") - (compat "30.0.0.0") - (seq "2.24")) - :commit "4030862396130b3dcfedabe509a4fc6cb218c49f" :authors - '(("Jonas Bernoulli" . "emacs.transient@jonas.bernoulli.dev")) - :maintainers - '(("Jonas Bernoulli" . "emacs.transient@jonas.bernoulli.dev")) - :maintainer - '("Jonas Bernoulli" . "emacs.transient@jonas.bernoulli.dev") - :keywords - '("extensions") - :url "https://github.com/magit/transient") -;; Local Variables: -;; no-byte-compile: t -;; End: +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "transient" "20250616.1830" + "Transient commands." + '((emacs "26.1") + (compat "30.1") + (seq "2.24")) + :url "https://github.com/magit/transient" + :commit "415f74bf97f6dd8e76131cd5cb3a9a8f77c273e5" + :revdesc "415f74bf97f6" + :keywords '("extensions") + :authors '(("Jonas Bernoulli" . "emacs.transient@jonas.bernoulli.dev")) + :maintainers '(("Jonas Bernoulli" . "emacs.transient@jonas.bernoulli.dev"))) diff --git a/lisp/transient/transient.el b/lisp/transient/transient.el index 4aeba018..693d9a1f 100644 --- a/lisp/transient/transient.el +++ b/lisp/transient/transient.el @@ -6,8 +6,9 @@ ;; Homepage: https://github.com/magit/transient ;; Keywords: extensions -;; Package-Version: 0.8.5 -;; Package-Requires: ((emacs "26.1") (compat "30.0.0.0") (seq "2.24")) +;; Package-Version: 20250616.1830 +;; Package-Revision: 415f74bf97f6 +;; Package-Requires: ((emacs "26.1") (compat "30.1") (seq "2.24")) ;; SPDX-License-Identifier: GPL-3.0-or-later @@ -34,7 +35,7 @@ ;;; Code: -(defconst transient-version "0.8.5") +(defconst transient-version "0.9.2") (require 'cl-lib) (require 'compat) @@ -105,6 +106,8 @@ TYPE is a type descriptor as accepted by `cl-typep', which see." (make-obsolete-variable 'transient-hide-during-minibuffer-read 'transient-show-during-minibuffer-read "0.8.0") +(defvar transient-common-command-prefix) + (defmacro transient--with-emergency-exit (id &rest body) (declare (indent defun)) (unless (keywordp id) @@ -128,35 +131,35 @@ TYPE is a type descriptor as accepted by `cl-typep', which see." :group 'extensions) (defcustom transient-show-popup t - "Whether to show the current transient in a popup buffer. + "Whether and when to show transient's menu in a buffer. \\ -- If t, then show the popup as soon as a transient prefix command +- If t, then show the buffer as soon as a transient prefix command is invoked. -- If nil, then do not show the popup unless the user explicitly +- If nil, then do not show the buffer unless the user explicitly requests it, by pressing \\[transient-show] or a prefix key. -- If a number, then delay displaying the popup and instead show +- If a number, then delay displaying the buffer and instead show a brief one-line summary. If zero or negative, then suppress even showing that summary and display the pressed key only. - Show the popup when the user explicitly requests it by pressing - \\[transient-show] or a prefix key. Unless zero, then also show the popup + Show the buffer once the user explicitly requests it by pressing + \\[transient-show] or a prefix key. Unless zero, then also show the buffer after that many seconds of inactivity (using the absolute value)." :package-version '(transient . "0.1.0") :group 'transient - :type '(choice (const :tag "instantly" t) - (const :tag "on demand" nil) - (const :tag "on demand (no summary)" 0) - (number :tag "after delay" 1))) + :type '(choice (const :tag "Instantly" t) + (const :tag "On demand" nil) + (const :tag "On demand (no summary)" 0) + (number :tag "After delay" 1))) (defcustom transient-enable-popup-navigation 'verbose - "Whether navigation commands are enabled in the transient popup. + "Whether navigation commands are enabled in the menu buffer. If the value is `verbose', additionally show brief documentation about the command under point in the echo area. -While a transient is active the transient popup buffer is not the +While a transient is active transient's menu buffer is not the current buffer, making it necessary to use dedicated commands to act on that buffer itself. If this is non-nil, then the following bindings are available: @@ -169,7 +172,7 @@ bindings are available: - \\`' and \\`' invoke the clicked on suffix. \\\ - \\[transient-isearch-backward]\ - and \\[transient-isearch-forward] start isearch in the popup buffer. + and \\[transient-isearch-forward] start isearch in the menu buffer. \\`' and \\`' are bound in `transient-push-button'. All other bindings are in `transient-popup-navigation-map'. @@ -180,18 +183,18 @@ then it is likely, that you would want \\`RET' to do what it would do if no transient were active." :package-version '(transient . "0.7.8") :group 'transient - :type '(choice (const :tag "enable navigation and echo summary" verbose) - (const :tag "enable navigation commands" t) - (const :tag "disable navigation commands" nil))) + :type '(choice (const :tag "Enable navigation and echo summary" verbose) + (const :tag "Enable navigation commands" t) + (const :tag "Disable navigation commands" nil))) (defcustom transient-display-buffer-action '(display-buffer-in-side-window (side . bottom) (dedicated . t) (inhibit-same-window . t)) - "The action used to display the transient popup buffer. + "The action used to display transient's menu buffer. -The transient popup buffer is displayed in a window using +The transient menu buffer is displayed in a window using (display-buffer BUFFER transient-display-buffer-action) @@ -251,7 +254,7 @@ is in characters." :type 'natnum) (defcustom transient-mode-line-format 'line - "The mode-line format for the transient popup buffer. + "The mode-line format for transient's menu buffer. If nil, then the buffer has no mode-line. If the buffer is not displayed right above the echo area, then this probably is not @@ -273,20 +276,25 @@ Otherwise this can be any mode-line format. See `mode-line-format' for details." :package-version '(transient . "0.2.0") :group 'transient - :type '(choice (const :tag "hide mode-line" nil) - (const :tag "substitute thin line" line) - (number :tag "substitute line with thickness") - (const :tag "name of prefix command" + :type '(choice (const :tag "Hide mode-line" nil) + (const :tag "Substitute thin line" line) + (number :tag "Substitute line with thickness") + (const :tag "Name of prefix command" ("%e" mode-line-front-space mode-line-buffer-identification)) - (sexp :tag "custom mode-line format"))) + (sexp :tag "Custom mode-line format"))) (defcustom transient-show-common-commands nil - "Whether to show common transient suffixes in the popup buffer. + "Whether to permanently show common suffix commands in transient menus. -These commands are always shown after typing the prefix key -\\`C-x' when a transient command is active. To toggle the value -of this variable use \\`C-x t' when a transient is active." +By default these commands are only temporarily shown after typing their +shared prefix key \ +\\\\[transient-common-command-prefix], \ +while a transient menu is active. When the value +of this option is non-nil, then these commands are permanently shown. +To toggle the value for the current Emacs session only type \ +\\\\[transient-toggle-common] while +any transient menu is active." :package-version '(transient . "0.1.0") :group 'transient :type 'boolean) @@ -416,7 +424,7 @@ using a layout optimized for Lisp. If non-nil, then the key binding of each suffix is colorized to indicate whether it exits the transient state or not, and the -line that is drawn below the transient popup buffer is used to +line that is drawn below transient's menu buffer is used to indicate the behavior of non-suffix commands." :package-version '(transient . "0.5.0") :group 'transient @@ -432,8 +440,18 @@ used." :group 'transient :type 'boolean) +(defcustom transient-error-on-insert-failure nil + "Whether to signal an error when failing to insert a suffix. + +When `transient-insert-suffix' and `transient-append-suffix' fail +to insert a suffix into an existing prefix, they usually just show +a warning. If this is non-nil, they signal an error instead." + :package-version '(transient . "0.8.8") + :group 'transient + :type 'boolean) + (defcustom transient-align-variable-pitch nil - "Whether to align columns pixel-wise in the popup buffer. + "Whether to align columns pixel-wise in the menu buffer. If this is non-nil, then columns are aligned pixel-wise to support variable-pitch fonts. Keys are not aligned, so you @@ -450,11 +468,11 @@ See also `transient-force-fixed-pitch'." :type 'boolean) (defcustom transient-force-fixed-pitch nil - "Whether to force use of monospaced font in the popup buffer. + "Whether to force use of monospaced font in the menu buffer. Even if you use a proportional font for the `default' face, you might still want to use a monospaced font in transient's -popup buffer. Setting this option to t causes `default' to +menu buffer. Setting this option to t causes `default' to be remapped to `fixed-pitch' in that buffer. See also `transient-align-variable-pitch'." @@ -484,7 +502,7 @@ Integers between 1 and 7 (inclusive) are valid levels. The levels of individual transients and/or their individual suffixes can be changed individually, by invoking the prefix and -then pressing \\`C-x l'. +then pressing \\\\[transient-set-level]. The default level for both transients and their suffixes is 4. This option only controls the default for transients. The default @@ -1014,7 +1032,7 @@ argument supported by the constructor of that class. The explicitly. GROUPs add key bindings for infix and suffix commands and specify -how these bindings are presented in the popup buffer. At least +how these bindings are presented in the menu buffer. At least one GROUP has to be specified. See info node `(transient)Binding Suffix and Infix Commands'. @@ -1049,7 +1067,7 @@ to the setup function: (indent defun) (doc-string 3)) (pcase-let - ((`(,class ,slots ,suffixes ,docstr ,body ,interactive-only) + ((`(,class ,slots ,groups ,docstr ,body ,interactive-only) (transient--expand-define-args args arglist 'transient-define-prefix))) `(progn (defalias ',name @@ -1062,9 +1080,22 @@ to the setup function: (put ',name 'function-documentation ,docstr) (put ',name 'transient--prefix (,(or class 'transient-prefix) :command ',name ,@slots)) - (put ',name 'transient--layout - (list ,@(mapcan (lambda (s) (transient--parse-child name s)) - suffixes)))))) + (transient--set-layout + ',name + (list ,@(mapcan (lambda (s) (transient--parse-child name s)) groups)))))) + +(defmacro transient-define-group (name &rest groups) + "Define one or more groups and store them in symbol NAME. + +Groups defined using this macro, can be used inside the +definition of transient prefix commands, by using the symbol +NAME where a group vector is expected. GROUPS has the same +form as for `transient-define-prefix'." + (declare (debug (&define name [&rest vectorp])) + (indent defun)) + `(transient--set-layout + ',name + (list ,@(mapcan (lambda (s) (transient--parse-child name s)) groups)))) (defmacro transient-define-suffix (name arglist &rest args) "Define NAME as a transient suffix command. @@ -1211,6 +1242,8 @@ commands are aliases for." ;; ARGLIST and FORM are only optional for backward compatibility. ;; This is necessary because "emoji.el" from Emacs 29 calls this ;; function directly, with just one argument. + (declare (advertised-calling-convention + (args arglist form &optional nobody) "0.7.1")) (unless (listp arglist) (error "Mandatory ARGLIST is missing")) (let (class keys suffixes docstr declare (interactive-only t)) @@ -1223,10 +1256,19 @@ commands are aliases for." (setq class v) (push k keys) (push v keys)))) - (while (let ((arg (car args))) - (or (vectorp arg) - (and arg (symbolp arg)))) - (push (pop args) suffixes)) + (while-let + ((arg (car args)) + (arg (cond + ;; Inline group definition. + ((vectorp arg) + (pop args)) + ;; Quoted include, as one would expect. + ((eq (car-safe arg) 'quote) + (cadr (pop args))) + ;; Unquoted include, for compatibility. + ((and arg (symbolp arg)) + (pop args))))) + (push arg suffixes)) (when (eq (car-safe (car args)) 'declare) (setq declare (car args)) (setq args (cdr args)) @@ -1253,34 +1295,19 @@ commands are aliases for." (defun transient--parse-child (prefix spec) (cl-typecase spec (null (error "Invalid transient--parse-child spec: %s" spec)) - (symbol (let ((value (symbol-value spec))) - (if (and (listp value) - (or (listp (car value)) - (vectorp (car value)))) - (mapcan (lambda (s) (transient--parse-child prefix s)) value) - (transient--parse-child prefix value)))) + (symbol (list `',spec)) (vector (and-let* ((c (transient--parse-group prefix spec))) (list c))) (list (and-let* ((c (transient--parse-suffix prefix spec))) (list c))) (string (list spec)) (t (error "Invalid transient--parse-child spec: %s" spec)))) (defun transient--parse-group (prefix spec) - (let ((spec (append spec nil)) - level class args) + (let (class args) + (setq spec (append spec nil)) (when (integerp (car spec)) - (setq level (pop spec))) + (setq args (plist-put args :level (pop spec)))) (when (stringp (car spec)) (setq args (plist-put args :description (pop spec)))) - ;; Merge value of [... GROUP-VARIABLE], if any. - (let ((spec* spec)) - (while (keywordp (car spec*)) - (setq spec* (cddr spec*))) - (when (and (length= spec* 1) (symbolp (car spec*))) - (let ((rest (append (symbol-value (car spec*)) nil)) - (args nil)) - (while (keywordp (car rest)) - (setq args (nconc (list (pop rest) (pop rest)) args))) - (setq spec (nconc args (butlast spec) rest))))) (while (keywordp (car spec)) (let* ((key (pop spec)) (val (if spec (pop spec) (error "No value for `%s'" key)))) @@ -1295,7 +1322,6 @@ commands are aliases for." (message "WARNING: %s: When %s is used, %s must also be specified" 'transient-define-prefix :setup-children :class)) (list 'vector - level (list 'quote (cond (class) ((cl-typep (car spec) @@ -1307,12 +1333,12 @@ commands are aliases for." (mapcan (lambda (s) (transient--parse-child prefix s)) spec))))) (defun transient--parse-suffix (prefix spec) - (let (level class args) + (let (class args) (cl-flet ((use (prop value) (setq args (plist-put args prop value)))) (pcase (car spec) ((cl-type integer) - (setq level (pop spec)))) + (use :level (pop spec)))) (pcase (car spec) ((cl-type (or string vector)) (use :key (pop spec)))) @@ -1325,9 +1351,10 @@ commands are aliases for." (guard (commandp (cadr spec)))) (use :description (macroexp-quote (pop spec))))) (pcase (car spec) - ((or :info :info*)) + ((or :info :info* :cons)) ((and (cl-type keyword) invalid) - (error "Need command, argument, `:info' or `:info*'; got `%s'" invalid)) + (error "Need command, argument, `:info', `:info*' or `:cons'; got `%s'" + invalid)) ((cl-type symbol) (use :command (macroexp-quote (pop spec)))) ;; During macro-expansion this is expected to be a `lambda' @@ -1378,11 +1405,19 @@ commands are aliases for." (val (if spec (pop spec) (error "No value for `%s'" key)))) (pcase key (:class (setq class val)) - (:level (setq level val)) (:info (setq class 'transient-information) (use :description val)) (:info* (setq class 'transient-information*) (use :description val)) + (:cons + (setq class 'transient-cons-option) + (use :command + (let ((sym (intern (format "transient:%s:%s" prefix val)))) + `(prog1 ',sym + (put ',sym 'interactive-only t) + (put ',sym 'completion-predicate #'transient--suffix-only) + (defalias ',sym #'transient--default-infix-command)))) + (use :argument val)) ((guard (eq (car-safe val) '\,)) (use key (cadr val))) ((guard (or (symbolp val) @@ -1392,11 +1427,13 @@ commands are aliases for." (_ (use key val))))) (when spec (error "Need keyword, got %S" (car spec))) - (when-let* (((not (plist-get args :key))) - (shortarg (plist-get args :shortarg))) - (use :key shortarg))) - (list 'list - level + (if-let ((key (plist-get args :key))) + (when (string-match "\\`\\({p}\\)" key) + (use :key + (replace-match transient-common-command-prefix t t key 1))) + (when-let ((shortarg (plist-get args :shortarg))) + (use :key shortarg)))) + (list 'cons (macroexp-quote (or class 'transient-suffix)) (cons 'list args)))) @@ -1425,63 +1462,121 @@ symbol property.") (setq read-extended-command-predicate #'transient-command-completion-not-suffix-only-p)) +(defun transient--set-layout (prefix layout) + (put prefix 'transient--layout (vector 2 nil layout))) + +(defun transient--get-layout (prefix) + (if-let* + ((layout + (or (get prefix 'transient--layout) + ;; Migrate unparsed legacy group definition. + (condition-case-unless-debug err + (and-let* ((value (symbol-value prefix))) + (transient--set-layout + prefix + (if (and (listp value) + (or (listp (car value)) + (vectorp (car value)))) + (transient-parse-suffixes prefix value) + (list (transient-parse-suffix prefix value))))) + (error + (message "Not a legacy group definition: %s: %S" prefix err) + nil))))) + (if (vectorp layout) + (let ((version (aref layout 0))) + (if (= version 2) + layout + (error "Unsupported layout version %s for %s" version prefix))) + ;; Upgrade from version 1. + (cl-labels + ((upgrade (spec) + (cond + ((vectorp spec) + (pcase-let ((`[,level ,class ,args ,children] spec)) + (when level + (setq args (plist-put args :level level))) + (vector class args (mapcar #'upgrade children)))) + ((and (listp spec) + (length= spec 3) + (or (null (car spec)) + (natnump (car spec))) + (symbolp (cadr spec))) + (pcase-let ((`(,level ,class ,args) spec)) + (when level + (setq args (plist-put args :level level))) + (cons class args))) + ((listp spec) + (mapcar #'upgrade spec)) + (t spec)))) + (transient--set-layout prefix (upgrade layout)))) + (error "Not a transient prefix command or group definition: %s" prefix))) + +(defun transient--get-children (prefix) + (aref (transient--get-layout prefix) 2)) + (defun transient-parse-suffix (prefix suffix) "Parse SUFFIX, to be added to PREFIX. -PREFIX is a prefix command, a symbol. +PREFIX is a prefix command symbol or object. SUFFIX is a suffix command or a group specification (of the same forms as expected by `transient-define-prefix'). Intended for use in a group's `:setup-children' function." - (cl-assert (and prefix (symbolp prefix))) + (when (cl-typep prefix 'transient-prefix) + (setq prefix (oref prefix command))) (eval (car (transient--parse-child prefix suffix)) t)) (defun transient-parse-suffixes (prefix suffixes) "Parse SUFFIXES, to be added to PREFIX. -PREFIX is a prefix command, a symbol. +PREFIX is a prefix command symbol or object. SUFFIXES is a list of suffix command or a group specification (of the same forms as expected by `transient-define-prefix'). Intended for use in a group's `:setup-children' function." - (cl-assert (and prefix (symbolp prefix))) + (when (cl-typep prefix 'transient-prefix) + (setq prefix (oref prefix command))) (mapcar (apply-partially #'transient-parse-suffix prefix) suffixes)) ;;; Edit (defun transient--insert-suffix (prefix loc suffix action &optional keep-other) - (let* ((suf (cl-etypecase suffix - (vector (transient--parse-group prefix suffix)) - (list (transient--parse-suffix prefix suffix)) - (string suffix))) - (mem (transient--layout-member loc prefix)) - (elt (car mem))) - (setq suf (eval suf t)) + (pcase-let* ((suf (cl-etypecase suffix + (vector (eval (transient--parse-group prefix suffix) t)) + (list (eval (transient--parse-suffix prefix suffix) t)) + (string suffix) + (symbol suffix))) + (`(,elt ,group) (transient--locate-child prefix loc))) (cond - ((not mem) - (message "Cannot insert %S into %s; %s not found" + ((not elt) + (funcall (if transient-error-on-insert-failure #'error #'message) + "Cannot insert %S into %s; %s not found" suffix prefix loc)) ((or (and (vectorp suffix) (not (vectorp elt))) (and (listp suffix) (vectorp elt)) (and (stringp suffix) (vectorp elt))) - (message "Cannot place %S into %s at %s; %s" + (funcall (if transient-error-on-insert-failure #'error #'message) + "Cannot place %S into %s at %s; %s" suffix prefix loc "suffixes and groups cannot be siblings")) (t (when-let* (((not (eq keep-other 'always))) (bindingp (listp suf)) - (key (transient--spec-key suf)) - (conflict (car (transient--layout-member key prefix))) + (key (transient--suffix-key suf)) + (conflict (car (transient--locate-child prefix key))) (conflictp (and (not (and (eq action 'replace) (eq conflict elt))) (or (not keep-other) - (eq (plist-get (nth 2 suf) :command) - (plist-get (nth 2 conflict) :command))) + (eq (plist-get (transient--suffix-props suf) + :command) + (plist-get (transient--suffix-props conflict) + :command))) (equal (transient--suffix-predicate suf) (transient--suffix-predicate conflict))))) (transient-remove-suffix prefix key)) - (pcase-exhaustive action - ('insert (setcdr mem (cons elt (cdr mem))) - (setcar mem suf)) - ('append (setcdr mem (cons suf (cdr mem)))) - ('replace (setcar mem suf))))))) + (let ((mem (memq elt (aref group 2)))) + (pcase-exhaustive action + ('insert (setcdr mem (cons elt (cdr mem))) + (setcar mem suf)) + ('append (setcdr mem (cons suf (cdr mem)))) + ('replace (setcar mem suf)))))))) ;;;###autoload (defun transient-insert-suffix (prefix loc suffix &optional keep-other) @@ -1530,6 +1625,22 @@ See info node `(transient)Modifying Existing Transients'." (declare (indent defun)) (transient--insert-suffix prefix loc suffix 'replace)) +;;;###autoload +(defun transient-inline-group (prefix group) + "Inline the included GROUP into PREFIX. +Replace the symbol GROUP with its expanded layout in the +layout of PREFIX." + (declare (indent defun)) + (cl-assert (symbolp group)) + (pcase-let ((`(,suffix ,parent) (transient--locate-child prefix group))) + (when suffix + (let* ((siblings (aref parent 2)) + (pos (cl-position group siblings))) + (aset parent 2 + (nconc (seq-take siblings pos) + (transient--get-children group) + (seq-drop siblings (1+ pos)))))))) + ;;;###autoload (defun transient-remove-suffix (prefix loc) "Remove the suffix or group at LOC in PREFIX. @@ -1539,18 +1650,9 @@ LOC is a command, a key vector, a key description (a string (whose last element may also be a command or key). See info node `(transient)Modifying Existing Transients'." (declare (indent defun)) - (transient--layout-member loc prefix 'remove)) - -(defun transient-get-suffix (prefix loc) - "Return the suffix or group at LOC in PREFIX. -PREFIX is a prefix command, a symbol. -LOC is a command, a key vector, a key description (a string - as returned by `key-description'), or a coordination list - (whose last element may also be a command or key). -See info node `(transient)Modifying Existing Transients'." - (if-let ((mem (transient--layout-member loc prefix))) - (car mem) - (error "%s not found in %s" loc prefix))) + (pcase-let ((`(,suffix ,group) (transient--locate-child prefix loc))) + (when suffix + (aset group 2 (delq suffix (aref group 2)))))) (defun transient-suffix-put (prefix loc prop value) "Edit the suffix at LOC in PREFIX, setting PROP to VALUE. @@ -1561,68 +1663,69 @@ LOC is a command, a key vector, a key description (a string as returned by `key-description'), or a coordination list (whose last element may also be a command or key). See info node `(transient)Modifying Existing Transients'." - (let ((suf (transient-get-suffix prefix loc))) - (setf (elt suf 2) - (plist-put (elt suf 2) prop value)))) + (let ((child (transient-get-suffix prefix loc))) + (if (vectorp child) + (aset child 1 (plist-put (aref child 1) prop value)) + (setcdr child (plist-put (transient--suffix-props child) prop value))))) -(defun transient--layout-member (loc prefix &optional remove) - (let ((val (or (get prefix 'transient--layout) - (error "%s is not a transient command" prefix)))) - (when (listp loc) - (while (integerp (car loc)) - (let* ((children (if (vectorp val) (aref val 3) val)) - (mem (transient--nthcdr (pop loc) children))) - (if (and remove (not loc)) - (let ((rest (delq (car mem) children))) - (if (vectorp val) - (aset val 3 rest) - (put prefix 'transient--layout rest)) - (setq val nil)) - (setq val (if loc (car mem) mem))))) - (setq loc (car loc))) - (if loc - (transient--layout-member-1 (transient--kbd loc) val remove) - val))) +(defalias 'transient--suffix-props #'cdr) -(defun transient--layout-member-1 (loc layout remove) - (cond ((listp layout) - (seq-some (lambda (elt) (transient--layout-member-1 loc elt remove)) - layout)) - ((vectorp (car (aref layout 3))) - (seq-some (lambda (elt) (transient--layout-member-1 loc elt remove)) - (aref layout 3))) - (remove - (aset layout 3 - (delq (car (transient--group-member loc layout)) - (aref layout 3))) - nil) - ((transient--group-member loc layout)))) +(defun transient-get-suffix (prefix loc) + "Return the suffix or group at LOC in PREFIX. +PREFIX is a prefix command, a symbol. +LOC is a command, a key vector, a key description (a string + as returned by `key-description'), or a coordination list + (whose last element may also be a command or key). +See info node `(transient)Modifying Existing Transients'." + (or (car (transient--locate-child prefix loc)) + (error "%s not found in %s" loc prefix))) -(defun transient--group-member (loc group) - (cl-member-if (lambda (suffix) - (and (listp suffix) - (let* ((def (nth 2 suffix)) - (cmd (plist-get def :command))) - (if (symbolp loc) - (eq cmd loc) - (equal (transient--kbd - (or (plist-get def :key) - (transient--command-key cmd))) - loc))))) - (aref group 3))) +(defun transient--locate-child (group loc) + (when (symbolp group) + (setq group (transient--get-layout group))) + (when (vectorp loc) + (setq loc (append loc nil))) + (if (listp loc) + (and-let* ((match (transient--nth (pop loc) (aref group 2)))) + (if loc + (transient--locate-child + match (cond ((or (stringp (car loc)) + (symbolp (car loc))) + (car loc)) + ((symbolp match) + (vconcat (cons 0 loc))) + ((vconcat loc)))) + (list match group))) + (seq-some (lambda (child) + (transient--match-child group loc child)) + (aref group 2)))) -(defun transient--kbd (keys) - (when (vectorp keys) - (setq keys (key-description keys))) - (when (stringp keys) - (setq keys (kbd keys))) - keys) +(defun transient--match-child (group loc child) + (cl-etypecase child + (string nil) + (symbol (if (symbolp loc) + (and (eq child loc) + (list child group)) + (and-let* ((include (transient--get-layout child))) + (transient--locate-child include loc)))) + (vector (seq-some (lambda (subgroup) + (transient--locate-child subgroup loc)) + (aref group 2))) + (list (and (if (symbolp loc) + (eq (plist-get (transient--suffix-props child) :command) + loc) + (equal (kbd (transient--suffix-key child)) + (kbd loc))) + (list child group))))) -(defun transient--spec-key (spec) - (let ((plist (nth 2 spec))) - (or (plist-get plist :key) +(defun transient--nth (n list) + (nth (if (< n 0) (- (length list) (abs n)) n) list)) + +(defun transient--suffix-key (spec) + (let ((props (transient--suffix-props spec))) + (or (plist-get props :key) (transient--command-key - (plist-get plist :command))))) + (plist-get props :command))))) (defun transient--command-key (cmd) (and-let* ((obj (transient--suffix-prototype cmd))) @@ -1633,9 +1736,6 @@ See info node `(transient)Modifying Existing Transients'." (oref obj shortarg) (transient--derive-shortarg (oref obj argument))))))) -(defun transient--nthcdr (n list) - (nthcdr (if (< n 0) (- (length list) (abs n)) n) list)) - (defun transient-set-default-level (command level) "Set the default level of suffix COMMAND to LEVEL. @@ -1671,7 +1771,14 @@ values. In complex cases it might be necessary to use this variable instead.") (defvar transient-exit-hook nil - "Hook run after exiting a transient.") + "Hook run after exiting a transient menu. +Unlike `transient-post-exit-hook', this runs even if another transient +menu becomes active at the same time. ") + +(defvar transient-post-exit-hook nil + "Hook run after exiting all transient menus. +Unlike `transient-exit-hook', this does not run if another transient +menu becomes active at the same time.") (defvar transient-setup-buffer-hook nil "Hook run when setting up the transient buffer. @@ -1685,7 +1792,7 @@ That buffer is current and empty when this hook runs.") (defconst transient--exit nil "Do exit the transient.") (defvar transient--exitp nil "Whether to exit the transient.") -(defvar transient--showp nil "Whether to show the transient popup buffer.") +(defvar transient--showp nil "Whether to show the transient menu buffer.") (defvar transient--helpp nil "Whether help-mode is active.") (defvar transient--docsp nil "Whether docstring-mode is active.") (defvar transient--editp nil "Whether edit-mode is active.") @@ -1709,7 +1816,7 @@ That buffer is current and empty when this hook runs.") "The transient menu buffer.") (defvar transient--window nil - "The window used to display the transient popup buffer.") + "The window used to display transient's menu buffer.") (defvar transient--original-window nil "The window that was selected before the transient was invoked. @@ -1732,6 +1839,10 @@ drawing in the transient buffer.") This is bound while the suffix predicate is being evaluated, and while functions that return faces are being evaluated.") +(defvar transient--current-suffix nil + "The suffix currently being invoked using a mouse event. +Do not use this; instead use function `transient-suffix-object'.") + (defvar transient--pending-group nil "The group that is currently being processed. This is bound while the suffixes are drawn in the transient buffer.") @@ -1840,6 +1951,7 @@ probably use this instead: (cl-check-type command command)) (cond (transient--pending-suffix) + (transient--current-suffix) ((or transient--prefix transient-current-prefix) (let ((suffixes @@ -1854,22 +1966,24 @@ probably use this instead: this-command)))) (or transient--suffixes transient-current-suffixes)))) - (or (if (cdr suffixes) - (cl-find-if - (lambda (obj) - (equal (listify-key-sequence (transient--kbd (oref obj key))) - (listify-key-sequence (this-command-keys)))) - suffixes) - (car suffixes)) - ;; COMMAND is only provided if `this-command' is meaningless, in - ;; which case `this-command-keys' is also meaningless, making it - ;; impossible to disambiguate redundant bindings. - (if command - (car suffixes) - ;; TODO Decide whether it is legimate to use this function - ;; as a predicate, and also whether to return an object for - ;; suffixes common to all prefixes. See #29 and #337. - (error "BUG: Cannot determine suffix object"))))) + (cond + ((length= suffixes 1) + (car suffixes)) + ((cl-find-if (lambda (obj) + (equal (listify-key-sequence (kbd (oref obj key))) + (listify-key-sequence (this-command-keys)))) + suffixes)) + ;; COMMAND is only provided if `this-command' is meaningless, in + ;; which case `this-command-keys' is also meaningless, making it + ;; impossible to disambiguate bindings for the same command. + (command (car suffixes)) + ;; If COMMAND is nil, then failure to disambiguate likely means + ;; that there is a bug somewhere. + ((length> suffixes 1) + (error "BUG: Cannot unambiguously determine suffix object")) + ;; It is legimate to use this function as a predicate of sorts. + ;; `transient--pre-command' and `transient-help' are examples. + (t nil)))) ((and-let* ((obj (transient--suffix-prototype (or command this-command))) (obj (clone obj))) (progn @@ -1916,7 +2030,7 @@ to `transient-predicate-map'." (keymap-set map "C-t" #'transient-show) (keymap-set map "?" #'transient-help) (keymap-set map "C-h" #'transient-help) - ;; Also bound to "C-x p" and "C-x n" in transient-common-commands. + ;; Next two have additional bindings in transient-common-commands. (keymap-set map "C-M-p" #'transient-history-prev) (keymap-set map "C-M-n" #'transient-history-next) (when (fboundp 'other-frame-prefix) ;Emacs >= 28.1 @@ -1931,53 +2045,84 @@ to `transient-predicate-map'. See also `transient-base-map'.") (defvar-keymap transient-edit-map :doc "Keymap that is active while a transient in is in \"edit mode\"." :parent transient-base-map - "?" #'transient-help - "C-h" #'transient-help - "C-x l" #'transient-set-level) + "?" #'transient-help + "C-h" #'transient-help) (defvar-keymap transient-sticky-map :doc "Keymap that is active while an incomplete key sequence is active." :parent transient-base-map "C-g" #'transient-quit-seq) -(defvar transient--common-command-prefixes '(?\C-x)) +(defvar transient-common-commands + [:hide (lambda () + (defvar transient--redisplay-key) + (and (not (equal (vconcat transient--redisplay-key) + (read-kbd-macro transient-common-command-prefix))) + (not transient-show-common-commands))) + ["Value commands" + ("{p} s " "Set" transient-set) + ("{p} C-s" "Save" transient-save) + ("{p} C-k" "Reset" transient-reset) + ("{p} p " "Previous value" transient-history-prev) + ("{p} n " "Next value" transient-history-next)] + ["Sticky commands" + ;; Like `transient-sticky-map' except that + ;; "C-g" has to be bound to a different command. + ("C-g" "Quit prefix or transient" transient-quit-one) + ("C-q" "Quit transient stack" transient-quit-all) + ("C-z" "Suspend transient stack" transient-suspend)] + ["Customize" + ("{p} t" transient-toggle-common) + ("{p} l" "Show/hide suffixes" transient-set-level) + ("{p} a" transient-toggle-level-limit)]] + "Commands available in all transient menus. -(put 'transient-common-commands - 'transient--layout - (list - (eval - (car (transient--parse-child - 'transient-common-commands - (vector - :hide - (lambda () - (and (not (memq - (car (bound-and-true-p transient--redisplay-key)) - transient--common-command-prefixes)) - (not transient-show-common-commands))) - (vector - "Value commands" - (list "C-x s " "Set" #'transient-set) - (list "C-x C-s" "Save" #'transient-save) - (list "C-x C-k" "Reset" #'transient-reset) - (list "C-x p " "Previous value" #'transient-history-prev) - (list "C-x n " "Next value" #'transient-history-next)) - (vector - "Sticky commands" - ;; Like `transient-sticky-map' except that - ;; "C-g" has to be bound to a different command. - (list "C-g" "Quit prefix or transient" #'transient-quit-one) - (list "C-q" "Quit transient stack" #'transient-quit-all) - (list "C-z" "Suspend transient stack" #'transient-suspend)) - (vector - "Customize" - (list "C-x t" #'transient-toggle-common) - (list "C-x l" "Show/hide suffixes" #'transient-set-level) - (list "C-x a" #'transient-toggle-level-limit))))) - t))) +The same functions, that are used to change bindings in transient prefix +commands and transient groups (defined using `transient-define-group'), +should be used to modify these bindings as well. The actual layout is +stored in the symbol's `transient--layout' property. The variable value +is only used when customizing `transient-common-command-prefix', which +resets the value of `transient--layout' based on the values of that +option and this variable.") + +(defun transient--init-common-commands () + (transient--set-layout + 'transient-common-commands + (list (eval (car (transient--parse-child 'transient-common-commands + transient-common-commands)) + t))) + (defvar transient-common-command-prefix) + (defvar transient--docstr-hint-1) + (defvar transient--docstr-hint-2) + (setq transient--docstr-hint-1 + (define-keymap transient-common-command-prefix + 'transient-common-command-prefix)) + (setq transient--docstr-hint-2 + (define-keymap (concat transient-common-command-prefix " t") + 'transient-toggle-common))) + +(defcustom transient-common-command-prefix "C-x" + "The prefix key used for most commands common to all menus. + +Some shared commands are available in all transient menus, most of +which share a common prefix specified by this option. By default the +bindings for these shared commands are only shown after pressing that +prefix key and before following that up with a valid key binding. + +For historic reasons \\`C-x' is used by default, but users are +encouraged to pick another key, preferably one that is not commonly used +in Emacs but is still convenient to them. See info node `(transient) +Common Suffix Commands'." + :type 'key + :initialize (lambda (symbol exp) + (custom-initialize-default symbol exp) + (transient--init-common-commands)) + :set (lambda (symbol value) + (set-default symbol value) + (transient--init-common-commands))) (defvar-keymap transient-popup-navigation-map - :doc "One of the keymaps used when popup navigation is enabled. + :doc "One of the keymaps used when menu navigation is enabled. See `transient-enable-popup-navigation'." "" #'transient-noop "" #'transient-backward-button @@ -1987,7 +2132,7 @@ See `transient-enable-popup-navigation'." "M-RET" #'transient-push-button) (defvar-keymap transient-button-map - :doc "One of the keymaps used when popup navigation is enabled. + :doc "One of the keymaps used when menu navigation is enabled. See `transient-enable-popup-navigation'." "" #'transient-push-button "" #'transient-push-button) @@ -2087,9 +2232,11 @@ of the corresponding object." (defun transient--make-transient-map () (let ((map (make-sparse-keymap))) - (set-keymap-parent map (if transient--editp - transient-edit-map - transient-map)) + (cond (transient--editp + (keymap-set map (concat transient-common-command-prefix " l") + #'transient-set-level) + (set-keymap-parent map transient-edit-map)) + ((set-keymap-parent map transient-map))) (dolist (obj transient--suffixes) (let ((key (oref obj key))) (when (vectorp key) @@ -2253,6 +2400,7 @@ EDIT may be non-nil." (setq transient--minibuffer-depth (minibuffer-depth)) (transient--redisplay)) (get name 'transient--prefix)) + (transient--suspend-text-conversion-style) (transient--setup-transient) (transient--suspend-which-key-mode))) @@ -2313,10 +2461,9 @@ value. Otherwise return CHILDREN as is.") (defun transient--init-suffixes (name) (let ((levels (alist-get name transient-levels))) (mapcan (lambda (c) (transient--init-child levels c nil)) - (append (get name 'transient--layout) + (append (transient--get-children name) (and (not transient--editp) - (get 'transient-common-commands - 'transient--layout)))))) + (transient--get-children 'transient-common-commands)))))) (defun transient--flatten-suffixes (layout) (cl-labels ((s (def) @@ -2332,13 +2479,16 @@ value. Otherwise return CHILDREN as is.") (defun transient--init-child (levels spec parent) (cl-etypecase spec + (symbol (mapcan (lambda (c) (transient--init-child levels c parent)) + (transient--get-children spec))) (vector (transient--init-group levels spec parent)) (list (transient--init-suffix levels spec parent)) (string (list spec)))) (defun transient--init-group (levels spec parent) - (pcase-let* ((`(,level ,class ,args ,children) (append spec nil)) - (level (or level transient--default-child-level))) + (pcase-let* ((`[,class ,args ,children] spec) + (level (or (plist-get args :level) + transient--default-child-level))) (and-let* (((transient--use-level-p level)) (obj (apply class :parent parent :level level args)) ((transient--use-suffix-p obj)) @@ -2352,25 +2502,26 @@ value. Otherwise return CHILDREN as is.") (list obj))))) (defun transient--init-suffix (levels spec parent) - (pcase-let* ((`(,level ,class ,args) spec) + (pcase-let* ((`(,class . ,args) spec) (cmd (plist-get args :command)) - (key (transient--kbd (plist-get args :key))) + (_ (transient--load-command-if-autoload cmd)) + (key (plist-get args :key)) + (key (and key (kbd key))) (proto (and cmd (transient--suffix-prototype cmd))) (level (or (alist-get (cons cmd key) levels nil nil #'equal) (alist-get cmd levels) - level + (plist-get args :level) (and proto (oref proto level)) - transient--default-child-level))) - (transient--load-command-if-autoload cmd) + transient--default-child-level)) + (args (plist-put (copy-sequence args) :level level))) (when (transient--use-level-p level) (let ((obj (if (child-of-class-p class 'transient-information) - (apply class :parent parent :level level args) + (apply class :parent parent args) (unless (and cmd (symbolp cmd)) (error "BUG: Non-symbolic suffix command: %s" cmd)) (if proto - (apply #'clone proto :parent parent :level level args) - (apply class :command cmd :parent parent :level level - args))))) + (apply #'clone proto :parent parent args) + (apply class :command cmd :parent parent args))))) (cond ((not cmd)) ((commandp cmd)) ((or (cl-typep obj 'transient-switch) @@ -2398,7 +2549,9 @@ value. Otherwise return CHILDREN as is.") (if (transient-switches--eieio-childp obj) (cl-call-next-method obj) (when-let* (((not (slot-boundp obj 'shortarg))) - (shortarg (transient--derive-shortarg (oref obj argument)))) + (argument (oref obj argument)) + ((stringp argument)) + (shortarg (transient--derive-shortarg argument))) (oset obj shortarg shortarg)) (unless (slot-boundp obj 'key) (if (slot-boundp obj 'shortarg) @@ -2466,9 +2619,9 @@ value. Otherwise return CHILDREN as is.") (default))) (defun transient--suffix-predicate (spec) - (let ((plist (nth 2 spec))) + (let ((props (transient--suffix-props spec))) (seq-some (lambda (prop) - (and-let* ((pred (plist-get plist prop))) + (and-let* ((pred (plist-get props prop))) (list prop pred))) '( :if :if-not :if-nil :if-non-nil @@ -2495,6 +2648,7 @@ value. Otherwise return CHILDREN as is.") (add-hook 'pre-command-hook #'transient--pre-command 99) (add-hook 'post-command-hook #'transient--post-command) (advice-add 'recursive-edit :around #'transient--recursive-edit) + (transient--quit-kludge 'enable) (when transient--exitp ;; This prefix command was invoked as the suffix of another. ;; Prevent `transient--post-command' from removing the hooks @@ -2536,8 +2690,7 @@ value. Otherwise return CHILDREN as is.") ((not (transient--edebug-command-p)) (setq this-command 'transient-undefined)))) ((and transient--editp - ;; See TODO in that function. - (ignore-errors (transient-suffix-object)) + (transient-suffix-object) (not (memq this-command '(transient-quit-one transient-quit-all transient-help)))) @@ -2801,7 +2954,8 @@ value. Otherwise return CHILDREN as is.") (transient--env-apply #'transient--redisplay))))) (setq transient-current-prefix nil) (setq transient-current-command nil) - (setq transient-current-suffixes nil))) + (setq transient-current-suffixes nil) + (setq transient--current-suffix nil))) (defun transient--post-exit (&optional command) (transient--debug 'post-exit) @@ -2824,9 +2978,10 @@ value. Otherwise return CHILDREN as is.") (remove-hook 'pre-command-hook #'transient--pre-command) (remove-hook 'post-command-hook #'transient--post-command) (advice-remove 'recursive-edit #'transient--recursive-edit)) - (let ((resume (and transient--stack + (let ((replace (eq transient--exitp 'replace)) + (resume (and transient--stack (not (memq transient--exitp '(replace suspend)))))) - (unless (or resume (eq transient--exitp 'replace)) + (unless (or resume replace) (setq transient--showp nil)) (setq transient--exitp nil) (setq transient--helpp nil) @@ -2837,9 +2992,12 @@ value. Otherwise return CHILDREN as is.") (when command (setq transient-current-prefix nil) (setq transient-current-command nil) - (setq transient-current-suffixes nil)) - (when resume - (transient--stack-pop)))) + (setq transient-current-suffixes nil) + (setq transient--current-suffix nil)) + (cond (resume (transient--stack-pop)) + ((not replace) + (transient--quit-kludge 'disable) + (run-hooks 'transient-post-exit-hook))))) (defun transient--stack-push () (transient--debug 'stack-push) @@ -2918,15 +3076,38 @@ value. Otherwise return CHILDREN as is.") (defun transient--emergency-exit (&optional id) "Exit the current transient command after an error occurred. When no transient is active (i.e., when `transient--prefix' is -nil) then do nothing. Optional ID is a keyword identifying the -exit." +nil) then only reset `inhibit-quit'. Optional ID is a keyword +identifying the exit." (transient--debug 'emergency-exit id) + (transient--quit-kludge 'disable) (when transient--prefix (setq transient--stack nil) (setq transient--exitp t) (transient--pre-exit) (transient--post-exit this-command))) +(defun transient--quit-kludge (action) + (static-if (boundp 'redisplay-can-quit) ;Emacs 31 + action + (pcase-exhaustive action + ('enable + (add-function + :around command-error-function + (let (unreadp) + (lambda (orig data context fn) + (cond ((not (eq (car data) 'quit)) + (funcall orig data context fn) + (setq unreadp nil)) + (unreadp + (remove-function command-error-function "inhibit-quit") + (funcall orig data context fn)) + (t + (push ?\C-g unread-command-events) + (setq unreadp t))))) + '((name . "inhibit-quit")))) + ('disable + (remove-function command-error-function "inhibit-quit"))))) + ;;; Pre-Commands (defun transient--call-pre-command () @@ -3020,12 +3201,12 @@ Use that command's pre-command to determine transient behavior." (not (eq (posn-window (event-start last-command-event)) transient--window))) transient--stay - (setq this-command - (with-selected-window transient--window - (get-text-property (if (mouse-event-p last-command-event) - (posn-point (event-start last-command-event)) - (point)) - 'command))) + (with-selected-window transient--window + (let ((pos (if (mouse-event-p last-command-event) + (posn-point (event-start last-command-event)) + (point)))) + (setq this-command (get-text-property pos 'command)) + (setq transient--current-suffix (get-text-property pos 'suffix)))) (transient--call-pre-command))) (defun transient--do-recurse () @@ -3153,7 +3334,7 @@ This should never happen. Please open an issue and post the shown command log." :error))) (defun transient-inhibit-move () - "Warn the user that popup navigation is disabled." + "Warn the user that menu navigation is disabled." (interactive) (message "To enable use of `%s', please customize `%s'" this-original-command @@ -3174,12 +3355,12 @@ Please open an issue and post the shown command log." :error))) (interactive)) (defun transient-update () - "Redraw the transient's state in the popup buffer." + "Redraw the transient's state in the menu buffer." (interactive) (setq prefix-arg current-prefix-arg)) (defun transient-show () - "Show the transient's state in the popup buffer." + "Show the transient's state in the menu buffer." (interactive) (setq transient--showp t)) @@ -3423,14 +3604,15 @@ such as when suggesting a new feature or reporting an issue." :description "Echo arguments" :key "x" (interactive (list (transient-args transient-current-command))) - (message "%s: %s" - (key-description (this-command-keys)) - (mapconcat (lambda (arg) - (propertize (if (string-match-p " " arg) - (format "%S" arg) - arg) - 'face 'transient-argument)) - arguments " "))) + (if (seq-every-p #'stringp arguments) + (message "%s: %s" (key-description (this-command-keys)) + (mapconcat (lambda (arg) + (propertize (if (string-match-p " " arg) + (format "%S" arg) + arg) + 'face 'transient-argument)) + arguments " ")) + (message "%s: %S" (key-description (this-command-keys)) arguments))) ;;; Value ;;;; Init @@ -3719,15 +3901,14 @@ prompt." prompt))) (if (stringp prompt) prompt - "(BUG: no prompt): ")) - (or (and-let* ((arg (and (slot-boundp obj 'argument) (oref obj argument)))) - (if (and (stringp arg) (string-suffix-p "=" arg)) - arg - (concat arg ": "))) - (and-let* ((var (and (slot-boundp obj 'variable) (oref obj variable)))) - (and (stringp var) - (concat var ": "))) - "(BUG: no prompt): "))) + "[BUG: invalid prompt]: ")) + (if-let* ((name (or (and (slot-boundp obj 'argument) (oref obj argument)) + (and (slot-boundp obj 'variable) (oref obj variable))))) + (if (and (stringp name) + (string-suffix-p "=" name)) + name + (format "%s: " name)) + "[BUG: no prompt]: "))) ;;;; Set @@ -4537,7 +4718,7 @@ apply the face `transient-unreachable' to the complete string." 'transient-inactive-argument))) (cl-defmethod transient-format-value ((obj transient-option)) - (let ((argument (oref obj argument))) + (let ((argument (prin1-to-string (oref obj argument) t))) (if-let ((value (oref obj value))) (pcase-exhaustive (oref obj multi-value) ('nil @@ -4840,7 +5021,8 @@ Type %s and then %s to describe the respective suffix command.\n" (propertize "" 'face 'transient-key) (propertize "" 'face 'transient-key) (propertize " N " 'face 'transient-enabled-suffix) - (propertize "C-x l" 'face 'transient-key) + (propertize (concat transient-common-command-prefix " l") + 'face 'transient-key) (propertize "" 'face 'transient-key) (propertize " N " 'face 'transient-enabled-suffix) (propertize "C-h" 'face 'transient-key) @@ -4891,10 +5073,10 @@ This is used when a tooltip is needed.") (let ((message-log-max nil)) (message "%s" doc)))))) -;;; Popup Navigation +;;; Menu Navigation (defun transient-scroll-up (&optional arg) - "Scroll text of transient popup window upward ARG lines. + "Scroll text of transient's menu window upward ARG lines. If ARG is nil scroll near full screen. This is a wrapper around `scroll-up-command' (which see)." (interactive "^P") @@ -4902,7 +5084,7 @@ around `scroll-up-command' (which see)." (scroll-up-command arg))) (defun transient-scroll-down (&optional arg) - "Scroll text of transient popup window down ARG lines. + "Scroll text of transient's menu window down ARG lines. If ARG is nil scroll near full screen. This is a wrapper around `scroll-down-command' (which see)." (interactive "^P") @@ -4910,7 +5092,7 @@ around `scroll-down-command' (which see)." (scroll-down-command arg))) (defun transient-backward-button (n) - "Move to the previous button in the transient popup buffer. + "Move to the previous button in transient's menu buffer. See `backward-button' for information about N." (interactive "p") (with-selected-window transient--window @@ -4919,7 +5101,7 @@ See `backward-button' for information about N." (transient-show-summary (get-text-property (point) 'suffix))))) (defun transient-forward-button (n) - "Move to the next button in the transient popup buffer. + "Move to the next button in transient's menu buffer. See `forward-button' for information about N." (interactive "p") (with-selected-window transient--window @@ -4959,7 +5141,7 @@ See `forward-button' for information about N." beg 'face nil (line-end-position)))))) ;;; Compatibility -;;;; Popup Isearch +;;;; Menu Isearch (defvar-keymap transient--isearch-mode-map :parent isearch-mode-map @@ -5037,6 +5219,16 @@ search instead." 2) lisp-imenu-generic-expression :test #'equal) +(defun transient--suspend-text-conversion-style () + (static-if (boundp 'overriding-text-conversion-style) ; since Emacs 30.1 + (when text-conversion-style + (letrec ((suspended overriding-text-conversion-style) + (fn (lambda () + (setq overriding-text-conversion-style nil) + (remove-hook 'transient-exit-hook fn)))) + (setq overriding-text-conversion-style suspended) + (add-hook 'transient-exit-hook fn))))) + (declare-function which-key-mode "ext:which-key" (&optional arg)) (defun transient--suspend-which-key-mode () @@ -5110,6 +5302,7 @@ as stand-in for elements of exhausted lists." (eval-when-compile `((,(concat "(" (regexp-opt (list "transient-define-prefix" + "transient-define-group" "transient-define-infix" "transient-define-argument" "transient-define-suffix") @@ -5155,6 +5348,29 @@ as stand-in for elements of exhausted lists." (defun transient-lisp-variable--reader (prompt initial-input _history) (read--expression prompt initial-input)) +;;;; `transient-cons-option' + +(defclass transient-cons-option (transient-option) + ((format :initform " %k %d: %v")) + "[Experimental] Class used for unencoded key-value pairs.") + +(cl-defmethod transient-infix-value ((obj transient-cons-option)) + "Return ARGUMENT and VALUE as a cons-cell or nil if the latter is nil." + (and-let* ((value (oref obj value))) + (cons (oref obj argument) value))) + +(cl-defmethod transient-format-description ((obj transient-cons-option)) + (or (oref obj description) + (let ((description (prin1-to-string (oref obj argument) t))) + (if (string-prefix-p ":" description) + (substring description 1) + description)))) + +(cl-defmethod transient-format-value ((obj transient-cons-option)) + (let ((value (oref obj value))) + (propertize (prin1-to-string value t) 'face + (if value 'transient-value 'transient-inactive-value)))) + ;;; _ (provide 'transient) ;; Local Variables: diff --git a/lisp/transient/transient.info b/lisp/transient/transient.info index 8c443e4b..e12a37b1 100644 --- a/lisp/transient/transient.info +++ b/lisp/transient/transient.info @@ -32,7 +32,7 @@ used to implement similar menus in other packages. resource to get over that hurdle is Psionic K's interactive tutorial, available at . -This manual is for Transient version 0.8.5. +This manual is for Transient version 0.9.2. Copyright (C) 2018-2025 Free Software Foundation, Inc. @@ -200,14 +200,15 @@ A transient prefix command is invoked like any other command by pressing the key that is bound to that command. The main difference to other commands is that a transient prefix command activates a transient keymap, which temporarily binds the transient's infix and suffix -commands, and that those bindings are displayed in a transient menu, -displayed in a popup buffer. Bindings from other keymaps may, or may -not, be disabled while the transient state is in effect. +commands, and that those bindings are shown in menu buffer, which is +displayed in a new window, until the menu is exited. Bindings from +other keymaps may, or may not, be disabled while the transient state is +in effect. There are two kinds of commands that are available after invoking a transient prefix command; infix and suffix commands. Infix commands set -some value (which is then shown in the popup buffer), without leaving -the transient. Suffix commands, on the other hand, usually quit the +some value (which is then shown in the menu buffer), without leaving the +transient. Suffix commands, on the other hand, usually quit the transient and they may use the values set by the infix commands, i.e., the infix *arguments*. @@ -232,7 +233,7 @@ prefix key, but not the complete transient). A transient prefix command can be bound as a suffix of another transient. Invoking such a suffix replaces the current transient state with a new transient state, i.e., the available bindings change and the -information displayed in the popup buffer is updated accordingly. +information displayed in the menu buffer is updated accordingly. Pressing ‘C-g’ while a nested transient is active only quits the innermost transient, causing a return to the previous transient. @@ -278,31 +279,53 @@ File: transient.info, Node: Common Suffix Commands, Next: Saving Values, Prev ========================== A few shared suffix commands are available in all transients. These -suffix commands are not shown in the popup buffer by default. - - This includes the aborting commands mentioned in the previous -section, as well as some other commands that are all bound to ‘C-x KEY’. -After ‘C-x’ is pressed, a section featuring all these common commands is -temporarily shown in the popup buffer. After invoking one of them, the -section disappears again. Note, however, that one of these commands is -described as "Show common permanently"; invoke that if you want the -common commands to always be shown for all transients. - -‘C-x t’ (‘transient-toggle-common’) - This command toggles whether the generic commands that are common - to all transients are always displayed or only after typing the - incomplete prefix key sequence ‘C-x’. This only affects the - current Emacs session. +suffix commands are not shown permanently in every menu by default. +Most of these commands share a common prefix key and pressing that key +causes the common commands to be temporarily shown in the active menu. -- User Option: transient-show-common-commands - This option controls whether shared suffix commands are shown - alongside the transient-specific infix and suffix commands. By - default, the shared commands are not shown to avoid overwhelming - the user with too many options. + This option controls whether shared suffix commands are permanently + shown alongside the menu-specific infix and suffix commands. By + default, the shared commands are not permanently shown to avoid + wasting precious space and overwhelming the user with too many + choices. - While a transient is active, pressing ‘C-x’ always shows the common - commands. The value of this option can be changed for the current - Emacs session by typing ‘C-x t’ while a transient is active. + If you prefer to always see these commands, then set this option to + a non-‘nil’ value. Alternatively the value can be toggled for the + current Emacs session only, using ‘transient-toggle-common’, + described below. + + -- User Option: transient-common-command-prefix + This option specifies the prefix key used in all transient menus to + invoke most of the shared commands, which are available in all + transient menus. By default these bindings are only shown after + pressing that prefix key and before following that up with a valid + key binding (but see the previous option). + + For historic reasons ‘C-x’ is used by default, but users are + encouraged to pick another key, preferably one that is not commonly + used in Emacs but is still convenient to them. + + Usually, while a transient menu is active, the user cannot invoke + commands that are not bound in the menu itself. For those menus it + does not matter, if ‘C-x’ or another commonly used prefix key is + used for common menu commands. However, certain other, newer menus + do not suppress key bindings established outside the menu itself, + and in those cases a binding for a common menu command could shadow + an external binding. For example, ‘C-x C-s’ could not be used to + invoke ‘save-buffer’, if that binding is shadowed by the menu + binding for ‘transient-save’. + + Which key is most suitable depends on the user's preferences, but + good choices may include function keys and ‘C-z’ (for many keyboard + layouts ‘z’ is right next to ‘x’, and invoking ‘suspend-frame’, + while a transient menu is active, would not be a good idea anyway). + +‘C-x t’ (‘transient-toggle-common’) + This command toggles whether the generic commands, that are common + to all transients, are permanently displayed or only after typing + the incomplete prefix key sequence‘’. This only affects the + current Emacs session. The other common commands are described in either the previous or in one of the following sections. @@ -327,6 +350,10 @@ suffix command, then the value is merely saved to the transient's history. That value won't be used when the transient is next invoked, but it is easily accessible (see *note Using History::). + Option ‘transient-common-command-prefix’ controls the prefix key used +in the following bindings. For simplicity's sake the default, ‘C-x’, is +shown below. + ‘C-x s’ (‘transient-set’) This command saves the value of the active transient for this Emacs session. @@ -360,6 +387,10 @@ value is saved to its history. These values can be cycled through, the same way one can cycle through the history of commands that read user-input in the minibuffer. + Option ‘transient-common-command-prefix’ controls the prefix key used +in the following bindings. For simplicity's sake the default, ‘C-x’, is +shown below. + ‘C-M-p’ (‘transient-history-prev’) ‘C-x p’ This command switches to the previous value used for the active @@ -444,8 +475,8 @@ For suffixes, 0 is also valid; it means that the suffix is not displayed at any level. The levels of individual transients and/or their individual suffixes -can be changed interactively, by invoking the transient and then -pressing ‘C-x l’ to enter the "edit" mode, see below. +can be changed interactively, by invoking the menu and entering its +"edit" mode using the command ‘transient-set-level’, as described below. The default level for both transients and their suffixes is 4. The ‘transient-default-level’ option only controls the default for @@ -464,6 +495,10 @@ if the user lowers the transient level. This option names the file that is used to persist the levels of transients and their suffixes between Emacs sessions. + Option ‘transient-common-command-prefix’ controls the prefix key used +in the following bindings. For simplicity's sake the default, ‘C-x’, is +shown below. + ‘C-x l’ (‘transient-set-level’) This command enters edit mode. When edit mode is active, then all infixes and suffixes that are currently usable are displayed along @@ -546,14 +581,14 @@ window, and the key bindings are the same as for ‘scroll-up-command’ and ‘scroll-down-command’ in other buffers. -- Command: transient-scroll-up arg - This command scrolls text of transient popup window upward ARG + This command scrolls text of transient's menu window upward ARG lines. If ARG is ‘nil’, then it scrolls near full screen. This is a wrapper around ‘scroll-up-command’ (which see). -- Command: transient-scroll-down arg - This command scrolls text of transient popup window down ARG lines. - If ARG is ‘nil’, then it scrolls near full screen. This is a - wrapper around ‘scroll-down-command’ (which see). + This command scrolls text of transient's menu window down ARG + lines. If ARG is ‘nil’, then it scrolls near full screen. This is + a wrapper around ‘scroll-down-command’ (which see). The following commands are not available by default. If you would like to use them for all menus, bind them in ‘transient-map’. @@ -583,39 +618,30 @@ Disabling Suffixes::. Essential Options ----------------- -Also see *note Common Suffix Commands::. +Two more essential options are documented in *note Common Suffix +Commands::. -- User Option: transient-show-popup - This option controls whether the current transient's infix and - suffix commands are shown in the popup buffer. + This option controls whether and when transient's menu buffer is + shown. - • If ‘t’ (the default) then the popup buffer is shown as soon as - a transient prefix command is invoked. + • If ‘t’ (the default), then the buffer is shown as soon as a + transient prefix command is invoked. - • If ‘nil’, then the popup buffer is not shown unless the user + • If ‘nil’, then the buffer is not shown unless the user explicitly requests it, by pressing an incomplete prefix key sequence. • If a number, then the a brief one-line summary is shown - instead of the popup buffer. If zero or negative, then not + instead of the menu buffer. If zero or negative, then not even that summary is shown; only the pressed key itself is shown. - The popup is shown when the user explicitly requests it by + The buffer is shown once the user explicitly requests it by pressing an incomplete prefix key sequence. Unless this is - zero, the popup is shown after that many seconds of inactivity + zero, the menu is shown after that many seconds of inactivity (using the absolute value). - -- User Option: transient-show-common-commands - This option controls whether shared suffix commands are shown - alongside the transient-specific infix and suffix commands. By - default, the shared commands are not shown to avoid overwhelming - the user with too many options. - - While a transient is active, pressing ‘C-x’ always shows the common - commands. The value of this option can be changed for the current - Emacs session by typing ‘C-x t’ while a transient is active. - -- User Option: transient-show-during-minibuffer-read This option controls whether the transient menu continues to be displayed while the minibuffer is used to read user input. @@ -661,21 +687,21 @@ Also see *note Common Suffix Commands::. elements. -- User Option: transient-enable-popup-navigation - This option controls whether navigation commands are enabled in the - transient popup buffer. If the value is ‘verbose’ (the default), + This option controls whether navigation commands are enabled in + transient's menu buffer. If the value is ‘verbose’ (the default), brief documentation about the command under point is additionally show in the echo area. - While a transient is active the transient popup buffer is not the - current buffer, making it necessary to use dedicated commands to - act on that buffer itself. If this option is non-‘nil’, then the + While a transient is active the menu buffer is not the current + buffer, making it necessary to use dedicated commands to act on + that buffer itself. If this option is non-‘nil’, then the following features are available: • ‘’ moves the cursor to the previous suffix. • ‘’ moves the cursor to the next suffix. • ‘M-’ invokes the suffix the cursor is on. • ‘mouse-1’ invokes the clicked on suffix. - • ‘C-s’ and ‘C-r’ start isearch in the popup buffer. + • ‘C-s’ and ‘C-r’ start isearch in the menu buffer. By default ‘M-’ is bound to ‘transient-push-button’, instead of ‘’, because if a transient allows the invocation of @@ -683,9 +709,9 @@ Also see *note Common Suffix Commands::. what it would do if no transient were active." -- User Option: transient-display-buffer-action - This option specifies the action used to display the transient - popup buffer. The transient popup buffer is displayed in a window - using ‘(display-buffer BUFFER transient-display-buffer-action)’. + This option specifies the action used to display the transient's + menu buffer. The menu buffer is displayed in a window using + ‘(display-buffer BUFFER transient-display-buffer-action)’. The value of this option has the form ‘(FUNCTION . ALIST)’, where FUNCTION is a function or a list of functions. Each such function @@ -740,7 +766,7 @@ Auxiliary Options ----------------- -- User Option: transient-mode-line-format - This option controls whether the transient popup buffer has a + This option controls whether transient's menu buffer has a mode-line, separator line, or neither. If ‘nil’, then the buffer has no mode-line. If the buffer is not @@ -816,7 +842,7 @@ Auxiliary Options -- User Option: transient-align-variable-pitch This option controls whether columns are aligned pixel-wise in the - popup buffer. + menu buffer. If this is non-‘nil’, then columns are aligned pixel-wise to support variable-pitch fonts. Keys are not aligned, so you should @@ -829,10 +855,10 @@ Auxiliary Options -- User Option: transient-force-fixed-pitch This option controls whether to force the use of a monospaced font - in popup buffer. Even if you use a proportional font for the + in menu buffer. Even if you use a proportional font for the ‘default’ face, you might still want to use a monospaced font in - transient's popup buffer. Setting this option to ‘t’ causes - ‘default’ to be remapped to ‘fixed-pitch’ in that buffer. + the menu buffer. Setting this option to ‘t’ causes ‘default’ to be + remapped to ‘fixed-pitch’ in that buffer. Developer Options ----------------- @@ -852,6 +878,12 @@ These options are mainly intended for developers. predicates of those suffixes prevent that more than one of them is enabled at a time. + -- User Option: transient-error-on-insert-failure + This option controls whether to signal an error when + ‘transient-insert-suffix’ or ‘transient-append-suffix’ failed to + insert a suffix into an existing prefix. By default a warning is + shown instead. + -- User Option: transient-highlight-higher-levels This option controls whether suffixes that would not be available by default are highlighted. @@ -866,7 +898,12 @@ Hook Variables -------------- -- Variable: transient-exit-hook - This hook is run after a transient is exited. + This hook is run after a transient menu is exited, even if another + transient menu becomes active at the same time. + + -- Variable: transient-post-exit-hook + This hook is run after a transient menu is exited, provided no + other transient menu becomes active at the same time. -- Variable: transient-setup-buffer-hook This hook is run when the transient buffer is being setup. That @@ -887,12 +924,15 @@ an example: '("-R" "Apply in reverse" "--reverse")) This inserts a new infix argument to toggle the ‘--reverse’ argument -after the infix argument that toggles ‘-3’ in ‘magit-patch-apply’. +after the infix argument that is bound to ‘-3’ in ‘magit-patch-apply’. The following functions share a few arguments: • PREFIX is a transient prefix command, a symbol. + PREFIX may also by a symbol identifying a separately defined group, + which can be included in multiple prefixes. See TODO. + • SUFFIX is a transient infix or suffix specification in the same form as expected by ‘transient-define-prefix’. Note that an infix is a special kind of suffix. Depending on context "suffixes" means @@ -902,24 +942,33 @@ after the infix argument that toggles ‘-3’ in ‘magit-patch-apply’. SUFFIX may also be a group in the same form as expected by ‘transient-define-prefix’. See *note Group Specifications::. - • LOC is a command, a key vector, a key description (a string as - returned by ‘key-description’), or a list specifying coordinates - (the last element may also be a command or key). For example ‘(1 0 - -1)’ identifies the last suffix (‘-1’) of the first subgroup (‘0’) - of the second group (‘1’). + • LOC is a key description (a string as returned by ‘key-description’ + and understood by ‘kbd’), a command, a symbol identifying an + included group, or a vector specifying coordinates. For example, + ‘[1 0 -1]’ identifies the last suffix (‘-1’) of the first subgroup + (‘0’) of the second group (‘1’). - If LOC is a list of coordinates, then it can be used to identify a - group, not just an individual suffix command. + If LOC is a vector, then it can be used to identify a group, not + just an individual suffix command. The last element in a vector + may also be a symbol or key, in which case the preceding elements + must match a group and the last element is looked up within that + group. The function ‘transient-get-suffix’ can be useful to determine - whether a certain coordination list identifies the suffix or group + whether a certain coordinate vector identifies the suffix or group that you expect it to identify. In hairy cases it may be necessary - to look at the definition of the transient prefix command. + to look at the internal layout representation, which you can access + using the function ‘transient--get-layout’. These functions operate on the information stored in the -‘transient--layout’ property of the PREFIX symbol. Suffix entries in -that tree are not objects but have the form ‘(LEVEL CLASS PLIST)’, where -PLIST should set at least ‘:key’, ‘:description’ and ‘:command’. +‘transient--layout’ property of the PREFIX symbol. Elements in that +tree are not objects but have the form ‘(CLASS PLIST) for suffixes’ and +[CLASS PLIST CHILDREN] for groups. At the root of the tree is an +element [N nil CHILDREN], where N is the version of the layout format, +currently and hopefully for a long time 2. While that element looks +like a group vector, that element does not count when identifying a +group using a coordinate vector, i.e., [0] is its first child, not the +root element itself. -- Function: transient-insert-suffix prefix loc suffix &optional keep-other @@ -935,8 +984,8 @@ PLIST should set at least ‘:key’, ‘:description’ and ‘:command’. Predicate Slots::. Unfortunately both false-positives and false-negatives are - possible. To deal with the former use non-‘nil’ KEEP-OTHER. The - symbol ‘always’ prevents the removal of a false-positive in some + possible. To deal with the former, use non-‘nil’ KEEP-OTHER. The + symbol ‘always’ prevents the removal of a false-positive, in some cases where other non-‘nil’ values would fail. To deal with false-negatives remove the conflicting binding separately, using ‘transient-remove-suffix’. @@ -956,14 +1005,27 @@ PLIST should set at least ‘:key’, ‘:description’ and ‘:command’. This function edits the suffix or group at LOC in PREFIX, by setting the PROP of its plist to VALUE. + Some prefix commands share suffixes, which are separately and then +included in each prefix when it is defined. The inclusion is done by +reference, the included suffix groups are not inlined by default. So if +you change, for example, the key binding for an argument in ‘magit-diff’ +(‘d’) the same change also applies to ‘magit-diff-refresh’ (‘D’). In +the rare case that this is not desirable use ‘transient-inline-group’ +before making changes to included suffixes. + + -- Function: transient-inline-group PREFIX GROUP + This function inlines the included GROUP into PREFIX, by replacing + the symbol GROUP with its expanded layout in the layout of PREFIX. + Most of these functions do not signal an error if they cannot perform the requested modification. The functions that insert new suffixes show a warning if LOC cannot be found in PREFIX without signaling an error. The reason for doing it like this is that establishing a key binding (and that is what we essentially are trying to do here) should not prevent the rest of the configuration from loading. Among these -functions only ‘transient-get-suffix’ and ‘transient-suffix-put’ may -signal an error. +functions only ‘transient-get-suffix’ and ‘transient-suffix-put’ signal +an error by default. If you really want the insert functions to also +signal an error, set ‘transient-error-on-insert-failure’ to ‘t’.  File: transient.info, Node: Defining New Commands, Next: Classes and Methods, Prev: Modifying Existing Transients, Up: Top @@ -997,7 +1059,7 @@ arguments and suffix commands. (temporary) keymap is activated, which binds the transient's infix and suffix commands, and functions that control the transient state are added to ‘pre-command-hook’ and ‘post-command-hook’. The available -suffix and infix commands and their state are shown in a popup buffer +suffix and infix commands and their state are shown in a menu buffer until the transient state is exited by invoking a suffix command. Calling an infix command causes its value to be changed. How that is @@ -1008,8 +1070,8 @@ on or off. More complex infix commands may read a value from the user, using the minibuffer. Calling a suffix command usually causes the transient to be exited; -the transient keymaps and hook functions are removed, the popup buffer -no longer shows information about the (no longer bound) suffix commands, +the transient keymaps and hook functions are removed, the menu buffer no +longer shows information about the (no longer bound) suffix commands, the values of some public global variables are set, while some internal global variables are unset, and finally the command is actually called. Suffix commands can also be configured to not exit the transient. @@ -1024,11 +1086,11 @@ arguments have been set using a command such as ‘universal-argument’. Transient can be used to implement simple "command dispatchers". The main benefit then is that the user can see all the available commands in -a popup buffer, which can be thought of as a "menu". That is useful by -itself because it frees the user from having to remember all the keys -that are valid after a certain prefix key or command. Magit's -‘magit-dispatch’ (on ‘C-x M-g’) command is an example of using Transient -to merely implement a command dispatcher. +a temporarily shown buffer, which can be thought of as a "menu". That +is useful by itself because it frees the user from having to remember +all the keys that are valid after a certain prefix key or command. +Magit's ‘magit-dispatch’ (on ‘C-x M-g’) command is an example of using +Transient to merely implement a command dispatcher. In addition to that, Transient also allows users to interactively pass arguments to commands. These arguments can be much more complex @@ -1111,7 +1173,7 @@ that is used to invoke that transient. explicitly. GROUPs add key bindings for infix and suffix commands and specify - how these bindings are presented in the popup buffer. At least one + how these bindings are presented in the menu buffer. At least one GROUP has to be specified. See *note Binding Suffix and Infix Commands::. @@ -1138,6 +1200,21 @@ that is used to invoke that transient. For example, the scope of the ‘magit-branch-configure’ transient is the branch whose variables are being configured. + Sometimes multiple prefix commands share a common set of suffixes. +For example, while ‘magit-diff’ (‘d’) and ‘magit-diff-refresh’ (‘D’) +offer different suffixes to actually create or update a diff, they both +offer the same infix arguments to control how that diff is formatted. +Such shared groups should be defined using ‘transient-define-group’ and +then included in multiple prefixes, by using the symbol that identifies +the group in the prefix definition, in a location where you would +otherwise use a group vector. If an included group is placed at the +top-level of a prefix (as opposed of inside inside a vector as a child +group), then the symbol should be quoted. + + -- Macro: transient-define-group name group... + This macro define one or more groups and stores them in symbol + NAME. GROUPs have the same form as for ‘transient-define-prefix’. +  File: transient.info, Node: Binding Suffix and Infix Commands, Next: Defining Suffix and Infix Commands, Prev: Defining Transients, Up: Defining New Commands @@ -1328,7 +1405,16 @@ transient. • LEVEL is the suffix level, an integer between 1 and 7. See *note Enabling and Disabling Suffixes::. - • KEY is the key binding, either a vector or key description string. + • KEY is the key binding, a string in the format returned by + ‘describe-key’ and understood by ‘kbd’. + + That format is more permissive than the one accepted by + ‘key-valid-p’. Being more permissive makes it possible, for + example, to write the key binding, which toggles the ‘-a’ command + line argument, as "-a", instead of having to write "- a". Likewise + additional spaces can be added, which is not removed when + displaying the binding in the menu, which is useful for alignment + purposes. • DESCRIPTION is the description, either a string or a function that takes zero or one arguments (the suffix object) and returns a @@ -1374,7 +1460,7 @@ only argument that is mandatory in all cases. can also be specified using ‘:shortarg’) and the second as the long argument (which can also be specified using ‘:argument’). - Only the long argument is displayed in the popup buffer. See + Only the long argument is displayed in the menu buffer. See ‘transient-detect-key-conflicts’ for how the short argument may be used. @@ -1999,7 +2085,7 @@ File: transient.info, Node: Group Methods, Next: Prefix Classes, Prev: Group This generic function formats the group and its elements and inserts the result into the current buffer, which is a temporary buffer. The contents of that buffer are later inserted into the - popup buffer. + menu buffer. Functions that are called by this function may need to operate in the buffer from which the transient was called. To do so they can @@ -2075,8 +2161,8 @@ File: transient.info, Node: Suffix Classes, Next: Prefix Methods, Prev: Prefi that anywhere a suffix can appear. Display-only suffix specifications take these form: - ([LEVEL] :info DESCRIPTION [KEYWORD VALUE]...) - ([LEVEL] :info* DESCRIPTION [KEYWORD VALUE]...) + (:info DESCRIPTION [KEYWORD VALUE]...) + (:info* DESCRIPTION [KEYWORD VALUE]...) The ‘:info’ and ‘:info*’ keyword arguments replaces the ‘:description’ keyword used for other suffix classes. Other @@ -2096,6 +2182,23 @@ File: transient.info, Node: Suffix Classes, Next: Prefix Methods, Prev: Prefi and it is somewhat likely that future improvements won't be fully backward compatible. + • The ‘transient-cons-option’ class is intended for situations where + ‘transient-args’ should return an alist, instead of a list of + strings (arguments). Such suffixes can be specified in prefix + definitions like so: + + (:cons OPTION :key KEY [KEYWORD VALUE]...) + + OPTION may be something other than a string, likely a keyword or + some other symbol, it is used as the ‘car’ of the cons-cell. When + using such an inline definition ‘:key’ has to be specified. In + most cases ‘:reader’ should also be specified. When defining such + a suffix separately, the "alist key" has to be specified using the + ‘:variable’ keyword argument. + + This class is still experimental it is somewhat likely that future + improvements won't be fully backward compatible. + • The ‘transient-describe-target’ class is used by the command ‘transient-describe’. @@ -2464,14 +2567,23 @@ Slots of transient-suffix::) are defined. Slots of ‘transient-suffix’ --------------------------- - • ‘key’ The key, a key vector or a key description string. + • ‘key’ is the key binding, a string in the format returned by + ‘describe-key’ and understood by ‘kbd’. + + That format is more permissive than the one accepted by + ‘key-valid-p’. Being more permissive makes it possible, for + example, to write the key binding, which toggles the ‘-a’ command + line argument, as "-a", instead of having to write "- a". Likewise + additional spaces can be added, which is not removed when + displaying the binding in the menu, which is useful for alignment + purposes. • ‘command’ The command, a symbol. • ‘transient’ Whether to stay transient. See *note Transient State::. - • ‘format’ The format used to display the suffix in the popup buffer. + • ‘format’ The format used to display the suffix in the menu buffer. It must contain the following %-placeholders: • ‘%k’ For the key. @@ -2659,25 +2771,31 @@ File: transient.info, Node: FAQ, Next: Keystroke Index, Prev: Classes and Met Appendix A FAQ ************** -A.1 Can I control how the popup buffer is displayed? -==================================================== +A.1 Can I control how the menu buffer is displayed? +=================================================== Yes, see ‘transient-display-buffer-action’ in *note Configuration::. -You can also control how the popup buffer is displayed on a case-by-case +You can also control how the menu buffer is displayed on a case-by-case basis by passing ‘:display-action’ to ‘transient-define-prefix’. -A.2 How can I copy text from the popup buffer? -============================================== +A.2 How can I copy text from the menu buffer? +============================================= -To be able to mark text in Transient's popup buffer using the mouse, you +To be able to mark text in Transient's menu buffer using the mouse, you have to add the below binding. Note that for technical reasons, the region won't be visualized, while doing so. After you have quit the -transient popup, you will be able to yank it in another buffer. +transient menu, you will be able to yank it in another buffer. (keymap-set transient-predicate-map "" #'transient--do-stay) + Copying the region while not seeing the region is a bit fiddly, so a +dedicated command, ‘transient-copy-menu-text’, was added. You have to +add a binding for this command in ‘transient-map’. + + (keymap-set transient-map "C-c C-w" #'transient-copy-menu-text) + A.3 How can I autoload prefix and suffix commands? ================================================== @@ -2702,50 +2820,7 @@ A.5 How does Transient compare to Magit-Popup and Hydra? See . -A.6 Why did some of the key bindings change? -============================================ - -You may have noticed that the bindings for some of the common commands -do *not* have the prefix ‘C-x’ and that furthermore some of these -commands are grayed out while others are not. That unfortunately is a -bit confusing if the section of common commands is not shown -permanently, making the following explanation necessary. - - The purpose of usually hiding that section but showing it after the -user pressed the respective prefix key is to conserve space and not -overwhelm users with too much noise, while allowing the user to quickly -list common bindings on demand. - - That however should not keep us from using the best possible key -bindings. The bindings that do use a prefix do so to avoid wasting too -many non-prefix bindings, keeping them available for use in individual -transients. The bindings that do not use a prefix and that are *not* -grayed out are very important bindings that are *always* available, even -when invoking the "common command key prefix" or *any other* -transient-specific prefix. The non-prefix keys that *are* grayed out -however, are not available when any incomplete prefix key sequence is -active. They do not use the "common command key prefix" because it is -likely that users want to invoke them several times in a row and e.g., -‘M-p M-p M-p’ is much more convenient than ‘C-x M-p C-x M-p C-x M-p’. - - You may also have noticed that the "Set" command is bound to ‘C-x s’, -while Magit-Popup used to bind ‘C-c C-c’ instead. I have seen several -users praise the latter binding (sic), so I did not change it -willy-nilly. The reason that I changed it is that using different -prefix keys for different common commands, would have made the temporary -display of the common commands even more confusing, i.e., after pressing -‘C-c’ all the bindings that begin with the ‘C-x’ prefix would be grayed -out. - - Using a single prefix for common commands key means that all other -potential prefix keys can be used for transient-specific commands -*without* the section of common commands also popping up. ‘C-c’ in -particular is a prefix that I want to (and already do) use for Magit, -and also using that for a common command would prevent me from doing so. - - (See also the next question.) - -A.7 Why does ‘q’ not quit popups anymore? +A.6 Why does ‘q’ not quit popups anymore? ========================================= I agree that ‘q’ is a good binding for commands that quit something. @@ -2781,21 +2856,21 @@ Appendix B Keystroke Index (line 27) * C-h: Getting Help for Suffix Commands. (line 11) -* C-M-n: Using History. (line 18) -* C-M-p: Using History. (line 13) +* C-M-n: Using History. (line 22) +* C-M-p: Using History. (line 17) * C-q: Aborting and Resuming Transients. (line 36) * C-x a: Enabling and Disabling Suffixes. - (line 68) -* C-x C-k: Saving Values. (line 29) -* C-x C-s: Saving Values. (line 25) + (line 72) +* C-x C-k: Saving Values. (line 33) +* C-x C-s: Saving Values. (line 29) * C-x l: Enabling and Disabling Suffixes. - (line 43) -* C-x n: Using History. (line 18) -* C-x p: Using History. (line 13) -* C-x s: Saving Values. (line 21) + (line 47) +* C-x n: Using History. (line 22) +* C-x p: Using History. (line 17) +* C-x s: Saving Values. (line 25) * C-x t: Common Suffix Commands. - (line 18) + (line 50) * C-z: Aborting and Resuming Transients. (line 41) @@ -2826,7 +2901,7 @@ Appendix C Command and Function Index * transient-active-prefix: Current Prefix Command. (line 39) * transient-append-suffix: Modifying Existing Transients. - (line 51) + (line 63) * transient-arg-value: Using Infix Arguments. (line 39) * transient-args: Using Infix Arguments. @@ -2836,6 +2911,7 @@ Appendix C Command and Function Index * transient-default-value <1>: Suffix Methods. (line 30) * transient-define-argument: Defining Suffix and Infix Commands. (line 57) +* transient-define-group: Defining Transients. (line 66) * transient-define-infix: Defining Suffix and Infix Commands. (line 26) * transient-define-prefix: Defining Transients. (line 13) @@ -2846,13 +2922,13 @@ Appendix C Command and Function Index * transient-format-key: Suffix Methods. (line 95) * transient-format-value: Suffix Methods. (line 103) * transient-get-suffix: Modifying Existing Transients. - (line 76) + (line 88) * transient-get-value: Using Infix Arguments. (line 31) * transient-help: Getting Help for Suffix Commands. (line 11) -* transient-history-next: Using History. (line 18) -* transient-history-prev: Using History. (line 13) +* transient-history-next: Using History. (line 22) +* transient-history-prev: Using History. (line 17) * transient-infix-read: Suffix Methods. (line 34) * transient-infix-set: Suffix Methods. (line 54) * transient-infix-value: Suffix Methods. (line 57) @@ -2860,8 +2936,10 @@ Appendix C Command and Function Index * transient-init-scope <1>: Suffix Methods. (line 70) * transient-init-value: Prefix Methods. (line 9) * transient-init-value <1>: Suffix Methods. (line 12) +* transient-inline-group: Modifying Existing Transients. + (line 104) * transient-insert-suffix: Modifying Existing Transients. - (line 49) + (line 61) * transient-prefix-object: Current Prefix Command. (line 6) * transient-prefix-value: Prefix Methods. (line 32) @@ -2873,37 +2951,37 @@ Appendix C Command and Function Index * transient-quit-seq: Aborting and Resuming Transients. (line 27) * transient-remove-suffix: Modifying Existing Transients. - (line 73) + (line 85) * transient-replace-suffix: Modifying Existing Transients. - (line 69) -* transient-reset: Saving Values. (line 29) + (line 81) +* transient-reset: Saving Values. (line 33) * transient-resume: Aborting and Resuming Transients. (line 53) -* transient-save: Saving Values. (line 25) +* transient-save: Saving Values. (line 29) * transient-scope: Using Prefix Scope. (line 10) * transient-scroll-down: Other Commands. (line 17) * transient-scroll-up: Other Commands. (line 12) -* transient-set: Saving Values. (line 21) +* transient-set: Saving Values. (line 25) * transient-set-default-level: Enabling and Disabling Suffixes. - (line 72) + (line 76) * transient-set-level: Enabling and Disabling Suffixes. - (line 43) + (line 47) * transient-setup-children: Group Methods. (line 6) * transient-show-help: Suffix Methods. (line 107) * transient-show-summary: Suffix Methods. (line 132) * transient-suffix-object: Current Suffix Command. (line 6) * transient-suffix-put: Modifying Existing Transients. - (line 80) + (line 92) * transient-suffixes: Using Infix Arguments. (line 46) * transient-suspend: Aborting and Resuming Transients. (line 41) * transient-toggle-common: Common Suffix Commands. - (line 18) + (line 50) * transient-toggle-docstrings: Other Commands. (line 29) * transient-toggle-level-limit: Enabling and Disabling Suffixes. - (line 68) + (line 72) * transient-with-help-window: Suffix Methods. (line 127)  @@ -2915,7 +2993,9 @@ Appendix D Variable Index [index] * Menu: -* transient-align-variable-pitch: Configuration. (line 244) +* transient-align-variable-pitch: Configuration. (line 235) +* transient-common-command-prefix: Common Suffix Commands. + (line 23) * transient-current-command: Current Prefix Command. (line 35) * transient-current-prefix: Current Prefix Command. @@ -2924,30 +3004,31 @@ Appendix D Variable Index (line 45) * transient-default-level: Enabling and Disabling Suffixes. (line 33) -* transient-detect-key-conflicts: Configuration. (line 269) -* transient-display-buffer-action: Configuration. (line 112) -* transient-enable-popup-navigation: Configuration. (line 90) -* transient-exit-hook: Configuration. (line 295) -* transient-force-fixed-pitch: Configuration. (line 257) -* transient-force-single-column: Configuration. (line 160) -* transient-highlight-higher-levels: Configuration. (line 282) -* transient-highlight-mismatched-keys: Configuration. (line 205) -* transient-history-file: Using History. (line 37) -* transient-history-limit: Using History. (line 41) +* transient-detect-key-conflicts: Configuration. (line 260) +* transient-display-buffer-action: Configuration. (line 103) +* transient-enable-popup-navigation: Configuration. (line 81) +* transient-error-on-insert-failure: Configuration. (line 273) +* transient-exit-hook: Configuration. (line 292) +* transient-force-fixed-pitch: Configuration. (line 248) +* transient-force-single-column: Configuration. (line 151) +* transient-highlight-higher-levels: Configuration. (line 279) +* transient-highlight-mismatched-keys: Configuration. (line 196) +* transient-history-file: Using History. (line 41) +* transient-history-limit: Using History. (line 45) * transient-levels-file: Enabling and Disabling Suffixes. (line 38) -* transient-mode-line-format: Configuration. (line 169) -* transient-read-with-initial-input: Configuration. (line 83) -* transient-save-history: Using History. (line 33) -* transient-semantic-coloring: Configuration. (line 196) -* transient-setup-buffer-hook: Configuration. (line 298) +* transient-mode-line-format: Configuration. (line 160) +* transient-post-exit-hook: Configuration. (line 296) +* transient-read-with-initial-input: Configuration. (line 74) +* transient-save-history: Using History. (line 37) +* transient-semantic-coloring: Configuration. (line 187) +* transient-setup-buffer-hook: Configuration. (line 300) * transient-show-common-commands: Common Suffix Commands. - (line 23) -* transient-show-common-commands <1>: Configuration. (line 36) -* transient-show-during-minibuffer-read: Configuration. (line 46) -* transient-show-popup: Configuration. (line 15) -* transient-substitute-key-function: Configuration. (line 223) -* transient-values-file: Saving Values. (line 32) + (line 11) +* transient-show-during-minibuffer-read: Configuration. (line 37) +* transient-show-popup: Configuration. (line 16) +* transient-substitute-key-function: Configuration. (line 214) +* transient-values-file: Saving Values. (line 36)  File: transient.info, Node: Concept Index, Next: GNU General Public License, Prev: Variable Index, Up: Top @@ -3721,72 +3802,71 @@ Ref: Complexity in CLI programs3784 Ref: Using Transient for composing interactive commands4385 Node: Usage6615 Node: Invoking Transients6983 -Node: Aborting and Resuming Transients8150 -Node: Common Suffix Commands10763 -Node: Saving Values12466 -Ref: Saving Values-Footnote-113866 -Node: Using History14059 -Node: Getting Help for Suffix Commands15763 -Node: Enabling and Disabling Suffixes17139 -Node: Other Commands22303 -Node: Configuration23978 -Ref: Essential Options24258 -Ref: Accessibility Options31345 -Ref: Auxiliary Options31668 -Ref: Developer Options36242 -Ref: Hook Variables37488 -Node: Modifying Existing Transients37775 -Node: Defining New Commands42135 -Node: Technical Introduction42575 -Node: Defining Transients48257 -Node: Binding Suffix and Infix Commands50714 -Ref: Group Specifications51505 -Ref: Suffix Specifications58312 -Node: Defining Suffix and Infix Commands62737 -Node: Using Infix Arguments65773 -Node: Using Prefix Scope68158 -Node: Current Suffix Command70158 -Node: Current Prefix Command72515 -Node: Transient State75067 -Ref: Pre-commands for Infixes79370 -Ref: Pre-commands for Suffixes79886 -Ref: Pre-commands for Non-Suffixes82335 -Ref: Special Pre-Commands83471 -Node: Classes and Methods83979 -Node: Group Classes86066 -Node: Group Methods87979 -Node: Prefix Classes89239 -Node: Suffix Classes90080 -Node: Prefix Methods94058 -Node: Suffix Methods96449 -Ref: Suffix Value Methods96709 -Ref: Suffix Format Methods99948 -Node: Prefix Slots102830 -Ref: Value and Scope102980 -Ref: Behavior104449 -Ref: Appearance105790 -Ref: Documentation106474 -Ref: Internal107094 -Node: Suffix Slots108445 -Ref: Slots of transient-child108813 -Ref: Slots of transient-suffix109271 -Ref: Slots of transient-infix111637 -Ref: Slots of transient-variable114925 -Ref: Slots of transient-switches115027 -Node: Predicate Slots115390 -Node: FAQ117727 -Ref: Can I control how the popup buffer is displayed?117856 -Ref: How can I copy text from the popup buffer?118183 -Ref: How can I autoload prefix and suffix commands?118673 -Ref: How does Transient compare to prefix keys and universal arguments?119147 -Ref: How does Transient compare to Magit-Popup and Hydra?119390 -Ref: Why did some of the key bindings change?119584 -Ref: Why does q not quit popups anymore?121925 -Node: Keystroke Index123026 -Node: Command and Function Index124891 -Node: Variable Index132140 -Node: Concept Index134708 -Node: GNU General Public License137532 +Node: Aborting and Resuming Transients8173 +Node: Common Suffix Commands10785 +Node: Saving Values13726 +Ref: Saving Values-Footnote-115294 +Node: Using History15487 +Node: Getting Help for Suffix Commands17359 +Node: Enabling and Disabling Suffixes18735 +Node: Other Commands24089 +Node: Configuration25767 +Ref: Essential Options26047 +Ref: Accessibility Options32583 +Ref: Auxiliary Options32906 +Ref: Developer Options37466 +Ref: Hook Variables38991 +Node: Modifying Existing Transients39519 +Node: Defining New Commands45362 +Node: Technical Introduction45802 +Node: Defining Transients51493 +Node: Binding Suffix and Infix Commands54836 +Ref: Group Specifications55627 +Ref: Suffix Specifications62434 +Node: Defining Suffix and Infix Commands67332 +Node: Using Infix Arguments70368 +Node: Using Prefix Scope72753 +Node: Current Suffix Command74753 +Node: Current Prefix Command77110 +Node: Transient State79662 +Ref: Pre-commands for Infixes83965 +Ref: Pre-commands for Suffixes84481 +Ref: Pre-commands for Non-Suffixes86930 +Ref: Special Pre-Commands88066 +Node: Classes and Methods88574 +Node: Group Classes90661 +Node: Group Methods92574 +Node: Prefix Classes93833 +Node: Suffix Classes94674 +Node: Prefix Methods99468 +Node: Suffix Methods101859 +Ref: Suffix Value Methods102119 +Ref: Suffix Format Methods105358 +Node: Prefix Slots108240 +Ref: Value and Scope108390 +Ref: Behavior109859 +Ref: Appearance111200 +Ref: Documentation111884 +Ref: Internal112504 +Node: Suffix Slots113855 +Ref: Slots of transient-child114223 +Ref: Slots of transient-suffix114681 +Ref: Slots of transient-infix117532 +Ref: Slots of transient-variable120820 +Ref: Slots of transient-switches120922 +Node: Predicate Slots121285 +Node: FAQ123622 +Ref: Can I control how the menu buffer is displayed?123751 +Ref: How can I copy text from the menu buffer?124075 +Ref: How can I autoload prefix and suffix commands?124834 +Ref: How does Transient compare to prefix keys and universal arguments?125308 +Ref: How does Transient compare to Magit-Popup and Hydra?125551 +Ref: Why does q not quit popups anymore?125745 +Node: Keystroke Index126846 +Node: Command and Function Index128711 +Node: Variable Index136178 +Node: Concept Index138957 +Node: GNU General Public License141781  End Tag Table diff --git a/lisp/treemacs-magit/treemacs-magit-pkg.el b/lisp/treemacs-magit/treemacs-magit-pkg.el index bfaa6764..510c0a81 100644 --- a/lisp/treemacs-magit/treemacs-magit-pkg.el +++ b/lisp/treemacs-magit/treemacs-magit-pkg.el @@ -1,15 +1,12 @@ -(define-package "treemacs-magit" "20240131.2042" "Magit integration for treemacs" - '((emacs "26.1") +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "treemacs-magit" "20250320.2145" + "Magit integration for treemacs." + '((emacs "26.1") (treemacs "0.0") - (pfuture "1.3") - (magit "2.90.0")) - :commit "bcba09c1581c4bd93ff0217d464aead04f6d26d4" :authors - '(("Alexander Miller" . "alexanderm@web.de")) - :maintainers - '(("Alexander Miller" . "alexanderm@web.de")) - :maintainer - '("Alexander Miller" . "alexanderm@web.de") - :url "https://github.com/Alexander-Miller/treemacs") -;; Local Variables: -;; no-byte-compile: t -;; End: + (pfuture "1.3") + (magit "2.90.0")) + :url "https://github.com/Alexander-Miller/treemacs" + :commit "55079b017fb821a34ace398cd3d8c5b556a22f6d" + :revdesc "55079b017fb8" + :authors '(("Alexander Miller" . "alexanderm@web.de")) + :maintainers '(("Alexander Miller" . "alexanderm@web.de"))) diff --git a/lisp/treemacs-magit/treemacs-magit.el b/lisp/treemacs-magit/treemacs-magit.el index c9c10c26..55588ff4 100644 --- a/lisp/treemacs-magit/treemacs-magit.el +++ b/lisp/treemacs-magit/treemacs-magit.el @@ -4,7 +4,8 @@ ;; Author: Alexander Miller ;; Package-Requires: ((emacs "26.1") (treemacs "0.0") (pfuture "1.3" ) (magit "2.90.0")) -;; Version: 0 +;; Package-Version: 20250320.2145 +;; Package-Revision: 55079b017fb8 ;; Homepage: https://github.com/Alexander-Miller/treemacs ;; This program is free software; you can redistribute it and/or modify diff --git a/lisp/treemacs/Changelog.org b/lisp/treemacs/Changelog.org index 63ad609d..901e38d2 100644 --- a/lisp/treemacs/Changelog.org +++ b/lisp/treemacs/Changelog.org @@ -3,6 +3,9 @@ * Changelog ** current master +*** Added ~treemacs-buffer-name-function~ +*** Added ~treemacs-file-follow-ignore-functions~ +** v3.1 - Deprecated ~treemacs-window-background-color~ in favour of ~treemacs-window-background-face~ and ~treemacs-hl-line-face~ - Added ~treemacs-copy-absolute-path-at-point~ diff --git a/lisp/treemacs/treemacs-compatibility.el b/lisp/treemacs/treemacs-compatibility.el index ea0e0bd7..3a0ed36f 100644 --- a/lisp/treemacs/treemacs-compatibility.el +++ b/lisp/treemacs/treemacs-compatibility.el @@ -83,7 +83,7 @@ For all other cases ORIGINAL-FN is called with original ARGS." (with-eval-after-load 'winum (when (boundp 'winum-ignored-buffers-regexp) - (add-to-list 'winum-ignored-buffers-regexp (regexp-quote (format "%sScoped-Buffer-" treemacs--buffer-name-prefix))))) + (add-to-list 'winum-ignored-buffers-regexp (regexp-quote treemacs--buffer-name-prefix)))) (with-eval-after-load 'ace-window (when (boundp 'aw-ignored-buffers) diff --git a/lisp/treemacs/treemacs-core-utils.el b/lisp/treemacs/treemacs-core-utils.el index 95c8bb3e..9b6d88f4 100644 --- a/lisp/treemacs/treemacs-core-utils.el +++ b/lisp/treemacs/treemacs-core-utils.el @@ -100,6 +100,7 @@ treemacs-dom-node->position) (treemacs-import-functions-from "treemacs-workspaces" + treemacs--next-project-pos treemacs--find-workspace treemacs-current-workspace treemacs-workspace->projects @@ -204,7 +205,7 @@ PATH: File Path" (file-name-directory) (treemacs--unslash))))) -(defconst treemacs--buffer-name-prefix " *Treemacs-") +(defconst treemacs--buffer-name-prefix " *Treemacs-Buffer-") (defconst treemacs-dir ;; locally we're in src/elisp, installed from melpa we're at the package root @@ -376,6 +377,16 @@ EXCLUDE-PREFIX: File Path" project (treemacs-button-get node :project))) project)) +(defun treemacs-last-node-of-project (project) + "Find the last node in given PROJECT. +Returns nil if the project is not expanded." + (declare (side-effect-free t)) + (let ((node (treemacs-project->position project))) + (when (treemacs-is-node-expanded? node) + (save-excursion + (goto-char node) + (previous-button (treemacs--next-project-pos)))))) + (define-inline treemacs--prop-at-point (prop) "Grab property PROP of the button at point. Returns nil when there is no button at point." diff --git a/lisp/treemacs/treemacs-customization.el b/lisp/treemacs/treemacs-customization.el index 6c2e09f9..7def9b9b 100644 --- a/lisp/treemacs/treemacs-customization.el +++ b/lisp/treemacs/treemacs-customization.el @@ -24,6 +24,10 @@ (require 's) (require 'widget) (require 'dash) +(require 'treemacs-macros) + +(treemacs-import-functions-from "treemacs-scope" + treemacs-default-buffer-name) (eval-when-compile (require 'cl-lib)) @@ -127,6 +131,20 @@ indentation will be a space INTEGER pixels wide." (const :tag "" px))) :group 'treemacs) +(defcustom treemacs-buffer-name-function #'treemacs-default-buffer-name + "The function used to create the name of a treemacs buffer. + +Value must be a function which takes a single argument - the current scope - and +returns the buffer name as a string. By default the scope is going to be the +current frame, however with packages like `treemacs-persp' it is also possible +for it to be the current perspective. + +In addition, the buffer name will *always* be prefixed with +`treemacs--buffer-name-prefix', which is necessary to properly recognise +treemacs buffers and maintain compatibility with some packages like winum." + :type 'function + :group 'treemacs) + (defcustom treemacs-litter-directories '("/node_modules" "/.venv" "/.cask") "List of directories affected by `treemacs-cleanup-litter'. Every item in the list is a regular expression, to be recognised a directory @@ -746,6 +764,15 @@ fallback." :type 'boolean :group 'treemacs-follow) +(defcustom treemacs-file-follow-ignore-functions nil + "Functions which determine if a file should not be followed. + +Content should be a list of functions which take one argument - the path of the +file that might be followed - and return non-nil if the file should *not* be +followed." + :type '(list function) + :group 'treemacs-follow) + (defcustom treemacs-move-files-by-mouse-dragging t "When non-nil treemacs will move files by dragging with the mouse." :group 'treemacs-mouse diff --git a/lisp/treemacs/treemacs-diagnostics.el b/lisp/treemacs/treemacs-diagnostics.el deleted file mode 100644 index 8292b24a..00000000 --- a/lisp/treemacs/treemacs-diagnostics.el +++ /dev/null @@ -1,102 +0,0 @@ -;;; treemacs-diagnostics.el --- A tree style file viewer package -*- lexical-binding: t -*- - -;; Copyright (C) 2024 Alexander Miller - -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see . - -;;; Commentary: - -;; WIP implementation of diagnostics display. - -;;; Code: - -(require 'ht) -(require 'thunk) -(require 'dash) -(require 'overlay) -(require 'treemacs-dom) -(require 'treemacs-scope) -(require 'treemacs-workspaces) -(require 'treemacs-core-utils) - -(eval-when-compile - (require 'treemacs-macros)) - -(defconst treemacs--diag-store (make-hash-table :size 50 :test 'equal)) - -(defvar treemacs--diagnostic-timer nil - "Debounce guard for the application of diagnostics.") - -(defconst treemacs--apply-diagnostics-delay 3 - "Debounce delay for the application of diagnostics.") - -(defface treemacs-diagnostic-error-face - '((t :underline "red")) - "TODO." - :group 'treemacs-faces) - -(defface treemacs-diagnostic-warning-face - '((t :underline "yellow")) - "TODO." - :group 'treemacs-faces) - -(defun treemacs--reset-and-save-diagnosics (path diagnostics) - "TODO PATH DIAGNOSTICS." - (-let [ht (ht-get treemacs--diag-store path)] - (if ht - (ht-clear! ht) - (setf ht (make-hash-table :size 100 :test 'equal)) - (ht-set! treemacs--diag-store path ht)) - (while diagnostics - (ht-set! ht (pop diagnostics) (pop diagnostics))))) - -(defun treemacs-apply-diagnostics (provider) - "Display diagnostics based on the given arguments PROVIDER. -PROVIDER should be a `thunk' (see thunk.el) that, when evaluated, returns a flat -list of consecutive path and face items. - -File paths should use treemacs' canonical format - they should be absolute, -expanded and *not* have a trailing slash. - -The diagnostic faces could be any face symbols or raw face literals. Treemacs -features several pre-made faces named `treemacs-diagnostic-*-face'. - -This method is debounced, it will never run more often than once every 3 -seconds. In addition the use of a lazy thunk ensures that potentially expensive -transformations happen only once and only when required. Performance is thus -not expected to be a major issue. - -A basic example use would look like this: - -\(treemacs-apply-diagnostics - (thunk-delay \\='(\"/path/to/file/x\" \\='treemacs-diagnostic-warning-face - \"/path/to/file/y\" \\='treemacs-diagnostic-error-face - \"/path/to/file/z\" \\='((:underline \"green\")))))" - (treemacs-debounce treemacs--diagnostic-timer treemacs--apply-diagnostics-delay - (treemacs-run-in-every-buffer - (save-excursion - (-each (overlays-in (point-min) (point-max)) #'delete-overlay) - (-let [diagnostics (thunk-force provider)] - (while diagnostics - (let ((path (pop diagnostics)) - (state (pop diagnostics))) - (when (treemacs-is-path-visible? path) - (-let [btn (treemacs-find-file-node path)] - (-doto (make-overlay (treemacs-button-start btn) (treemacs-button-end btn)) - (overlay-put 'face state)))))))) - (hl-line-highlight)))) - -(provide 'treemacs-diagnostics) - -;;; treemacs-diagnostics.el ends here diff --git a/lisp/treemacs/treemacs-follow-mode.el b/lisp/treemacs/treemacs-follow-mode.el index a63f53ff..5625e7d7 100644 --- a/lisp/treemacs/treemacs-follow-mode.el +++ b/lisp/treemacs/treemacs-follow-mode.el @@ -65,7 +65,10 @@ not visible." current-file (not (s-starts-with? treemacs--buffer-name-prefix buffer-name)) (file-exists-p current-file) - (not (string= buffer-name "COMMIT_EDITMSG"))) + (not (string= buffer-name "COMMIT_EDITMSG")) + (--none? + (funcall it current-file) + treemacs-file-follow-ignore-functions)) (-when-let (project-for-file (treemacs--find-project-for-buffer current-file)) (with-selected-window treemacs-window (-let [selected-file (--if-let (treemacs-current-button) diff --git a/lisp/treemacs/treemacs-icons.el b/lisp/treemacs/treemacs-icons.el index e3b7fab9..34631aff 100644 --- a/lisp/treemacs/treemacs-icons.el +++ b/lisp/treemacs/treemacs-icons.el @@ -297,6 +297,8 @@ Necessary since root icons are not rectangular." (treemacs-create-icon :file "svgrepo/list.png" :extensions (elfeed-search-mode)) (treemacs-create-icon :file "vsc/deps.png" :extensions (cask-mode)) (treemacs-create-icon :file "yaml.png" :extensions (yaml-mode)) + (treemacs-create-icon :file "css.png" :extensions (css-mode)) + (treemacs-create-icon :file "markdown.png" :extensions (markdown-mode)) ;; file icons (treemacs-create-icon :file "txt.png" :extensions (fallback)) diff --git a/lisp/treemacs/treemacs-macros.el b/lisp/treemacs/treemacs-macros.el index 0e5eef13..37119c18 100644 --- a/lisp/treemacs/treemacs-macros.el +++ b/lisp/treemacs/treemacs-macros.el @@ -308,7 +308,7 @@ not work keep it on the same line." ((and prev-path (can-move-to prev-path)) (treemacs-goto-file-node prev-path)) (t - (-let [detour (treemacs--parent curr-file)] + (-when-let (detour (treemacs--parent curr-file)) (while (not (can-move-to detour)) (setf detour (treemacs--parent detour))) (treemacs-goto-file-node detour))))))) @@ -318,10 +318,18 @@ not work keep it on the same line." (goto-char curr-point)) (_ ;; point is on a custom node - ;; TODO(2018/10/30): custom node exists predicate? - (condition-case _ - (treemacs-goto-node curr-node-path) - (error (ignore))))) + (cond + ((treemacs-is-path-visible? curr-node-path) + (treemacs-goto-extension-node curr-node-path)) + ((and next-path (treemacs-is-path-visible? next-path)) + (treemacs-goto-extension-node next-path)) + ((and prev-path (treemacs-is-path-visible? prev-path)) + (treemacs-goto-extension-node prev-path)) + (t + (-when-let (detour (treemacs--parent curr-file)) + (while (not (treemacs-is-path-visible? detour)) + (setf detour (treemacs--parent detour))) + (treemacs-goto-extension-node detour)))))) (treemacs--evade-image) (when (get-text-property (point) 'invisible) (goto-char (or diff --git a/lisp/treemacs/treemacs-mode.el b/lisp/treemacs/treemacs-mode.el index 0a3478da..8d0b1ec9 100644 --- a/lisp/treemacs/treemacs-mode.el +++ b/lisp/treemacs/treemacs-mode.el @@ -373,8 +373,11 @@ Will simply return `treemacs--eldoc-msg'." (unless (member #'treemacs--on-window-config-change (default-value 'window-configuration-change-hook)) (treemacs--on-window-config-change)) ;; set the parameter immediately so it can take effect when `treemacs' is called programatically - ;; alongside other window layout chaning commands that might delete it again - (set-window-parameter (selected-window) 'no-delete-other-windows treemacs-no-delete-other-windows) + ;; alongside other window layout chaning commands that might delete it again. + ;; also check that the buffer has a window as other packages might call `treemacs-mode' on buffers + ;; that have no window yet + (when (get-buffer-window (current-buffer)) + (set-window-parameter (selected-window) 'no-delete-other-windows treemacs-no-delete-other-windows)) (face-remap-add-relative 'default 'treemacs-window-background-face) (face-remap-add-relative 'fringe 'treemacs-window-background-face) diff --git a/lisp/treemacs/treemacs-pkg.el b/lisp/treemacs/treemacs-pkg.el index 1e546f2c..ad7ed7d4 100644 --- a/lisp/treemacs/treemacs-pkg.el +++ b/lisp/treemacs/treemacs-pkg.el @@ -1,20 +1,17 @@ -(define-package "treemacs" "20250105.1321" "A tree style file explorer package" - '((emacs "26.1") - (cl-lib "0.5") - (dash "2.11.0") - (s "1.12.0") +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "treemacs" "20250617.1934" + "A tree style file explorer package." + '((emacs "26.1") + (cl-lib "0.5") + (dash "2.11.0") + (s "1.12.0") (ace-window "0.9.0") - (pfuture "1.7") - (hydra "0.13.2") - (ht "2.2") - (cfrs "1.3.2")) - :commit "32bb3dd02ddfca85661614b3b227e770fab821e2" :authors - '(("Alexander Miller" . "alexanderm@web.de")) - :maintainers - '(("Alexander Miller" . "alexanderm@web.de")) - :maintainer - '("Alexander Miller" . "alexanderm@web.de") - :url "https://github.com/Alexander-Miller/treemacs") -;; Local Variables: -;; no-byte-compile: t -;; End: + (pfuture "1.7") + (hydra "0.13.2") + (ht "2.2") + (cfrs "1.3.2")) + :url "https://github.com/Alexander-Miller/treemacs" + :commit "7109ce99853b18435a77267a15c5dd06715b54e4" + :revdesc "7109ce99853b" + :authors '(("Alexander Miller" . "alexanderm@web.de")) + :maintainers '(("Alexander Miller" . "alexanderm@web.de"))) diff --git a/lisp/treemacs/treemacs-scope.el b/lisp/treemacs/treemacs-scope.el index 293acd6d..992f7893 100644 --- a/lisp/treemacs/treemacs-scope.el +++ b/lisp/treemacs/treemacs-scope.el @@ -32,6 +32,7 @@ (require 'dash) (require 'eieio) (require 'treemacs-core-utils) +(require 'treemacs-customization) (require 's) (require 'inline) @@ -199,13 +200,21 @@ NEW-SCOPE-TYPE: T: treemacs-scope" (push (cons scope shelf) treemacs--scope-storage) (treemacs--find-workspace (buffer-file-name))) (treemacs-scope-shelf->kill-buffer shelf) - (let* ((name-suffix (or (treemacs-scope->current-scope-name treemacs--current-scope-type scope) - (prin1-to-string scope))) - (name (format "%sScoped-Buffer-%s*" treemacs--buffer-name-prefix name-suffix)) + (let* ((name (format "%s%s" + treemacs--buffer-name-prefix + (or (funcall treemacs-buffer-name-function scope) + (treemacs-default-buffer-name scope)))) (buffer (get-buffer-create name))) (setf (treemacs-scope-shelf->buffer shelf) buffer) buffer))) +(defun treemacs-default-buffer-name (scope) + "Default buffer name implementation for a given SCOPE. +Appends the name of the given scope to the mandatory +`treemacs--buffer-name-prefix'." + (or (treemacs-scope->current-scope-name treemacs--current-scope-type scope) + (prin1-to-string scope))) + (defun treemacs--change-buffer-on-scope-change (&rest _) "Switch the treemacs buffer after the current scope was changed." (--when-let (treemacs-get-local-window) diff --git a/lisp/treemacs/treemacs-single-file-git-status.py b/lisp/treemacs/treemacs-single-file-git-status.py index dc341d8e..a441384b 100644 --- a/lisp/treemacs/treemacs-single-file-git-status.py +++ b/lisp/treemacs/treemacs-single-file-git-status.py @@ -40,10 +40,9 @@ def main(): sys.exit(2) new_state = determine_file_git_state() - old_state = face_for_status(FILE, OLD_FACE) # nothing to do - if old_state == new_state: + if OLD_FACE == face_for_status(FILE, new_state): sys.exit(2) proc_list = [] @@ -74,7 +73,7 @@ def main(): propagate_state = "?" result_list.append((path, propagate_state)) break - elif changed_proc.communicate() != b'' and changed_proc.returncode == 0: + elif changed_proc.communicate()[0] != b'' and changed_proc.returncode == 0: result_list.append((path, "M")) else: result_list.append((path, "0")) @@ -98,8 +97,8 @@ def add_git_processes(status_listings, path): status_listings.append((path, ignored_proc, tracked_proc, changed_proc)) def determine_file_git_state(): - proc = Popen(FILE_STATE_CMD + FILE, shell=True, stdout=PIPE, stderr=DEVNULL) - line = proc.stdout.readline() + proc = Popen(FILE_STATE_CMD + FILE, shell=True, stdout=PIPE, stderr=DEVNULL) + line = proc.stdout.readline() if line: state = line.lstrip().split(b" ")[0] return state.decode('utf-8').strip()[0] diff --git a/lisp/treemacs/treemacs.el b/lisp/treemacs/treemacs.el index 8511e269..99ce4325 100644 --- a/lisp/treemacs/treemacs.el +++ b/lisp/treemacs/treemacs.el @@ -5,7 +5,8 @@ ;; Author: Alexander Miller ;; Package-Requires: ((emacs "26.1") (cl-lib "0.5") (dash "2.11.0") (s "1.12.0") (ace-window "0.9.0") (pfuture "1.7") (hydra "0.13.2") (ht "2.2") (cfrs "1.3.2")) ;; Homepage: https://github.com/Alexander-Miller/treemacs -;; Version: 3.1 +;; Package-Version: 20250617.1934 +;; Package-Revision: 7109ce99853b ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -51,7 +52,7 @@ (defconst treemacs-version (eval-when-compile - (format "v3.1 (installed %s) @ Emacs %s" + (format "v3.2 (installed %s) @ Emacs %s" (format-time-string "%Y.%m.%d" (current-time)) emacs-version))) diff --git a/lisp/virtual-auto-fill/virtual-auto-fill-pkg.el b/lisp/virtual-auto-fill/virtual-auto-fill-pkg.el index 9a8d0b24..353fd7a0 100644 --- a/lisp/virtual-auto-fill/virtual-auto-fill-pkg.el +++ b/lisp/virtual-auto-fill/virtual-auto-fill-pkg.el @@ -1,16 +1,12 @@ -(define-package "virtual-auto-fill" "20200906.2038" "Readably display text without adding line breaks" - '((emacs "25.2") - (adaptive-wrap "0.7") +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "virtual-auto-fill" "20200906.2038" + "Readably display text without adding line breaks." + '((emacs "25.2") + (adaptive-wrap "0.7") (visual-fill-column "1.9")) - :commit "a3991ce02d9a6a1624a3f04da80f4ac966a44092" :authors - '(("Luis Gerhorst" . "virtual-auto-fill@luisgerhorst.de")) - :maintainers - '(("Luis Gerhorst" . "virtual-auto-fill@luisgerhorst.de")) - :maintainer - '("Luis Gerhorst" . "virtual-auto-fill@luisgerhorst.de") - :keywords - '("convenience" "mail" "outlines" "files" "wp") - :url "https://github.com/luisgerhorst/virtual-auto-fill") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/luisgerhorst/virtual-auto-fill" + :commit "a3991ce02d9a6a1624a3f04da80f4ac966a44092" + :revdesc "a3991ce02d9a" + :keywords '("convenience" "mail" "outlines" "files" "wp") + :authors '(("Luis Gerhorst" . "virtual-auto-fill@luisgerhorst.de")) + :maintainers '(("Luis Gerhorst" . "virtual-auto-fill@luisgerhorst.de"))) diff --git a/lisp/virtual-auto-fill/virtual-auto-fill.el b/lisp/virtual-auto-fill/virtual-auto-fill.el index b07d18ff..2fd262b0 100644 --- a/lisp/virtual-auto-fill/virtual-auto-fill.el +++ b/lisp/virtual-auto-fill/virtual-auto-fill.el @@ -7,7 +7,8 @@ ;; URL: https://github.com/luisgerhorst/virtual-auto-fill ;; Keywords: convenience, mail, outlines, files, wp ;; Created: Sun 26. Jan 2020 -;; Version: 0.1 +;; Package-Version: 20200906.2038 +;; Package-Revision: a3991ce02d9a ;; Package-Requires: ((emacs "25.2") (adaptive-wrap "0.7") (visual-fill-column "1.9")) ;; This file is NOT part of GNU Emacs. diff --git a/lisp/visual-fill-column/visual-fill-column-pkg.el b/lisp/visual-fill-column/visual-fill-column-pkg.el index c0480db5..3164d815 100644 --- a/lisp/visual-fill-column/visual-fill-column-pkg.el +++ b/lisp/visual-fill-column/visual-fill-column-pkg.el @@ -1,12 +1,9 @@ -(define-package "visual-fill-column" "20250204.2336" "fill-column for visual-line-mode" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "visual-fill-column" "20250323.1529" + "Fill-column for visual-line-mode." '((emacs "25.1")) - :commit "d4464130a21733671a53f915a697dea65888473f" :authors - '(("Joost Kremers" . "joostkremers@fastmail.fm")) - :maintainers - '(("Joost Kremers" . "joostkremers@fastmail.fm")) - :maintainer - '("Joost Kremers" . "joostkremers@fastmail.fm") - :url "https://codeberg.org/joostkremers/visual-fill-column") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://codeberg.org/joostkremers/visual-fill-column" + :commit "30fc3e4ea9aa415eccc873e5d7c4f1bbc0491495" + :revdesc "30fc3e4ea9aa" + :authors '(("Joost Kremers" . "joostkremers@fastmail.fm")) + :maintainers '(("Joost Kremers" . "joostkremers@fastmail.fm"))) diff --git a/lisp/visual-fill-column/visual-fill-column.el b/lisp/visual-fill-column/visual-fill-column.el index e06876f6..45454c07 100644 --- a/lisp/visual-fill-column/visual-fill-column.el +++ b/lisp/visual-fill-column/visual-fill-column.el @@ -8,7 +8,8 @@ ;; Maintainer: Joost Kremers ;; URL: https://codeberg.org/joostkremers/visual-fill-column ;; Created: 2015 -;; Version: 2.6.3 +;; Package-Version: 20250323.1529 +;; Package-Revision: 30fc3e4ea9aa ;; Package-Requires: ((emacs "25.1")) ;; This file is NOT part of GNU Emacs. @@ -173,6 +174,12 @@ Use this mode to activate and deactivate `visual-line-mode' and (visual-fill-column-mode -1) (visual-line-mode -1)))) +(defun visual-fill-column-toggle-center-text () + "Toggle centering of text in the current buffer." + (interactive) + (setq visual-fill-column-center-text (not visual-fill-column-center-text)) + (visual-fill-column-adjust)) + (defun turn-on-visual-fill-column-mode () "Turn on `visual-fill-column-mode'. Note that `visual-fill-column-mode' is only turned on in buffers diff --git a/lisp/vterm/vterm-pkg.el b/lisp/vterm/vterm-pkg.el index 70fa1308..945d6e20 100644 --- a/lisp/vterm/vterm-pkg.el +++ b/lisp/vterm/vterm-pkg.el @@ -1,14 +1,10 @@ -(define-package "vterm" "20241218.331" "Fully-featured terminal emulator" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "vterm" "20241218.331" + "Fully-featured terminal emulator." '((emacs "25.1")) - :commit "f64729ed8b59e46ce827d28222c4087c538de562" :authors - '(("Lukas Fürmetz" . "fuermetz@mailbox.org")) - :maintainers - '(("Lukas Fürmetz" . "fuermetz@mailbox.org")) - :maintainer - '("Lukas Fürmetz" . "fuermetz@mailbox.org") - :keywords - '("terminals") - :url "https://github.com/akermu/emacs-libvterm") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/akermu/emacs-libvterm" + :commit "f64729ed8b59e46ce827d28222c4087c538de562" + :revdesc "f64729ed8b59" + :keywords '("terminals") + :authors '(("Lukas Fürmetz" . "fuermetz@mailbox.org")) + :maintainers '(("Lukas Fürmetz" . "fuermetz@mailbox.org"))) diff --git a/lisp/vterm/vterm.el b/lisp/vterm/vterm.el index 9bc0d161..ee452b23 100644 --- a/lisp/vterm/vterm.el +++ b/lisp/vterm/vterm.el @@ -3,7 +3,8 @@ ;; Copyright (C) 2017-2020 by Lukas Fürmetz & Contributors ;; ;; Author: Lukas Fürmetz -;; Version: 0.0.2 +;; Package-Version: 20241218.331 +;; Package-Revision: f64729ed8b59 ;; URL: https://github.com/akermu/emacs-libvterm ;; Keywords: terminals ;; Package-Requires: ((emacs "25.1")) diff --git a/lisp/web-completion-data/web-completion-data-pkg.el b/lisp/web-completion-data/web-completion-data-pkg.el index c590c50c..6ed43b6c 100644 --- a/lisp/web-completion-data/web-completion-data-pkg.el +++ b/lisp/web-completion-data/web-completion-data-pkg.el @@ -1,12 +1,10 @@ -(define-package "web-completion-data" "20160318.848" "Shared completion data for ac-html and company-web" 'nil :commit "c272c94e8a71b779c29653a532f619acad433a4f" :authors - '(("Olexandr Sydorchuk" . "olexandr.syd@gmail.com")) - :maintainers - '(("Olexandr Sydorchuk" . "olexandr.syd@gmail.com")) - :maintainer - '("Olexandr Sydorchuk" . "olexandr.syd@gmail.com") - :keywords - '("html" "auto-complete" "company") - :url "https://github.com/osv/web-completion-data") -;; Local Variables: -;; no-byte-compile: t -;; End: +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "web-completion-data" "20160318.848" + "Shared completion data for ac-html and company-web." + () + :url "https://github.com/osv/web-completion-data" + :commit "c272c94e8a71b779c29653a532f619acad433a4f" + :revdesc "c272c94e8a71" + :keywords '("html" "auto-complete" "company") + :authors '(("Olexandr Sydorchuk" . "olexandr.syd@gmail.com")) + :maintainers '(("Olexandr Sydorchuk" . "olexandr.syd@gmail.com"))) diff --git a/lisp/web-completion-data/web-completion-data.el b/lisp/web-completion-data/web-completion-data.el index 271aa0b9..15ed4c93 100644 --- a/lisp/web-completion-data/web-completion-data.el +++ b/lisp/web-completion-data/web-completion-data.el @@ -3,7 +3,8 @@ ;; Copyright (C) 2015 Zhang Kai Yu, Olexandr Sydorchuk ;; Author: Olexandr Sydorchuk -;; Version: 0.2 +;; Package-Version: 20160318.848 +;; Package-Revision: c272c94e8a71 ;; Keywords: html, auto-complete, company ;; URL: https://github.com/osv/web-completion-data diff --git a/lisp/web-mode/web-mode-pkg.el b/lisp/web-mode/web-mode-pkg.el index 0b07c0e2..09959482 100644 --- a/lisp/web-mode/web-mode-pkg.el +++ b/lisp/web-mode/web-mode-pkg.el @@ -1,12 +1,9 @@ -(define-package "web-mode" "20241227.530" "major mode for editing web templates" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "web-mode" "20250619.1334" + "Major mode for editing web templates." '((emacs "23.1")) - :commit "be2d59c8fa02b1a45ae54ce4079e502e659cefe6" :maintainers - '(("François-Xavier Bois" . "fxbois@gmail.com")) - :maintainer - '("François-Xavier Bois" . "fxbois@gmail.com") - :keywords - '("languages") - :url "https://web-mode.org") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://web-mode.org" + :commit "994cb350bceeebb031406112cf6da119e066ef8e" + :revdesc "994cb350bcee" + :keywords '("languages") + :maintainers '(("François-Xavier Bois" . "fxbois@gmail.com"))) diff --git a/lisp/web-mode/web-mode.el b/lisp/web-mode/web-mode.el index 8e1ab230..8aa2c5fe 100644 --- a/lisp/web-mode/web-mode.el +++ b/lisp/web-mode/web-mode.el @@ -2,7 +2,8 @@ ;; Copyright 2011-2024 François-Xavier Bois -;; Version: 17.3.21 +;; Package-Version: 20250619.1334 +;; Package-Revision: 994cb350bcee ;; Author: François-Xavier Bois ;; Maintainer: François-Xavier Bois ;; Package-Requires: ((emacs "23.1")) @@ -5478,7 +5479,8 @@ Also return non-nil if it is the command `self-insert-command' is remapped to." ;;(message "%S: %S (%S %S)" (point) (match-string-no-properties 0) reg-beg reg-end) (setq flags 0 - tname (downcase (match-string-no-properties 1)) + tnameraw (match-string-no-properties 1) + tname (downcase tnameraw) char (aref tname 0) tbeg (match-beginning 0) tend nil @@ -5507,7 +5509,9 @@ Also return non-nil if it is the command `self-insert-command' is remapped to." ((not (member char '(?\! ?\?))) (cond - ((string-match-p "-" tname) + ((or (string-match-p "-" tname) + (let ((case-fold-search nil)) + (string-match-p "^/?[[:upper:]][[:lower:]]" tnameraw))) (setq flags (logior flags 2))) ;;((string-match-p ":" tname) ;; (setq flags (logior flags 32))) @@ -8682,7 +8686,7 @@ Also return non-nil if it is the command `self-insert-command' is remapped to." (cond ((string= web-mode-engine "blade") (save-excursion - (when (web-mode-rsf "{[{!]+[ ]*") + (when (web-mode-rsf "{[{!]+[ ]*\\|@props[ ]*[(]") ;; #1318 (setq reg-col (current-column)))) (setq reg-beg (+ reg-beg 2)) ) @@ -9647,7 +9651,10 @@ Also return non-nil if it is the command `self-insert-command' is remapped to." reg-beg)))) (t - (when debug (message "I430(%S) bracket-indentation" pos)) + (when debug + (message "I430(%S) bracket-indentation" pos) + ;;(message "reg-col=%S curr-ind=%S lang=%S reg-beg=%S" reg-col curr-indentation language reg-beg) + ) (setq offset (car (web-mode-bracket-indentation pos reg-col curr-indentation diff --git a/lisp/websocket/websocket-pkg.el b/lisp/websocket/websocket-pkg.el index fd5fbdd7..ebffb145 100644 --- a/lisp/websocket/websocket-pkg.el +++ b/lisp/websocket/websocket-pkg.el @@ -1,14 +1,10 @@ -(define-package "websocket" "20230809.305" "Emacs WebSocket client and server" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "websocket" "20230809.305" + "Emacs WebSocket client and server." '((cl-lib "0.5")) - :commit "40c208eaab99999d7c1e4bea883648da24c03be3" :authors - '(("Andrew Hyatt" . "ahyatt@gmail.com")) - :maintainers - '(("Andrew Hyatt" . "ahyatt@gmail.com")) - :maintainer - '("Andrew Hyatt" . "ahyatt@gmail.com") - :keywords - '("communication" "websocket" "server") - :url "https://github.com/ahyatt/emacs-websocket") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/ahyatt/emacs-websocket" + :commit "40c208eaab99999d7c1e4bea883648da24c03be3" + :revdesc "40c208eaab99" + :keywords '("communication" "websocket" "server") + :authors '(("Andrew Hyatt" . "ahyatt@gmail.com")) + :maintainers '(("Andrew Hyatt" . "ahyatt@gmail.com"))) diff --git a/lisp/websocket/websocket.el b/lisp/websocket/websocket.el index a5c0591d..025a50e6 100644 --- a/lisp/websocket/websocket.el +++ b/lisp/websocket/websocket.el @@ -5,7 +5,8 @@ ;; Author: Andrew Hyatt ;; Homepage: https://github.com/ahyatt/emacs-websocket ;; Keywords: Communication, Websocket, Server -;; Version: 1.15 +;; Package-Version: 20230809.305 +;; Package-Revision: 40c208eaab99 ;; Package-Requires: ((cl-lib "0.5")) ;; ;; This program is free software; you can redistribute it and/or diff --git a/lisp/with-editor/with-editor-pkg.el b/lisp/with-editor/with-editor-pkg.el index faccf11d..05a53bb8 100644 --- a/lisp/with-editor/with-editor-pkg.el +++ b/lisp/with-editor/with-editor-pkg.el @@ -1,15 +1,11 @@ -(define-package "with-editor" "20241201.1419" "Use the Emacsclient as $EDITOR" - '((emacs "26.1") - (compat "30.0.0.0")) - :commit "ca902ae02972bdd6919a902be2593d8cb6bd991b" :authors - '(("Jonas Bernoulli" . "emacs.with-editor@jonas.bernoulli.dev")) - :maintainers - '(("Jonas Bernoulli" . "emacs.with-editor@jonas.bernoulli.dev")) - :maintainer - '("Jonas Bernoulli" . "emacs.with-editor@jonas.bernoulli.dev") - :keywords - '("processes" "terminals") - :url "https://github.com/magit/with-editor") -;; Local Variables: -;; no-byte-compile: t -;; End: +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "with-editor" "20250531.2230" + "Use the Emacsclient as $EDITOR." + '((emacs "26.1") + (compat "30.1")) + :url "https://github.com/magit/with-editor" + :commit "f32cd7b09d518b629bfaa3eeb92b539891c6b9bc" + :revdesc "f32cd7b09d51" + :keywords '("processes" "terminals") + :authors '(("Jonas Bernoulli" . "emacs.with-editor@jonas.bernoulli.dev")) + :maintainers '(("Jonas Bernoulli" . "emacs.with-editor@jonas.bernoulli.dev"))) diff --git a/lisp/with-editor/with-editor.el b/lisp/with-editor/with-editor.el index 3c971f38..9fa3bbdc 100644 --- a/lisp/with-editor/with-editor.el +++ b/lisp/with-editor/with-editor.el @@ -1,13 +1,14 @@ ;;; with-editor.el --- Use the Emacsclient as $EDITOR -*- lexical-binding:t -*- -;; Copyright (C) 2014-2024 The Magit Project Contributors +;; Copyright (C) 2014-2025 The Magit Project Contributors ;; Author: Jonas Bernoulli ;; Homepage: https://github.com/magit/with-editor ;; Keywords: processes terminals -;; Package-Version: 3.4.3 -;; Package-Requires: ((emacs "26.1") (compat "30.0.0.0")) +;; Package-Version: 20250531.2230 +;; Package-Revision: f32cd7b09d51 +;; Package-Requires: ((emacs "26.1") (compat "30.1")) ;; SPDX-License-Identifier: GPL-3.0-or-later @@ -158,10 +159,15 @@ please see https://github.com/magit/magit/wiki/Emacsclient.")))) (let ((dir (expand-file-name "bin" invocation-directory))) (when (file-directory-p dir) (push dir path))) - (when (string-search "Cellar" invocation-directory) + (cond + ((string-search "Cellar" invocation-directory) (let ((dir (expand-file-name "../../../bin" invocation-directory))) (when (file-directory-p dir) - (push dir path)))))) + (push dir path)))) + ((string-search "Emacs.app" invocation-directory) + (let ((dir (expand-file-name "../../../../bin" invocation-directory))) + (when (file-directory-p dir) + (push dir path))))))) (cl-remove-duplicates path :test #'equal))) (defcustom with-editor-emacsclient-executable (with-editor-locate-emacsclient) diff --git a/lisp/with-editor/with-editor.info b/lisp/with-editor/with-editor.info index 742ed1c7..48fb05c2 100644 --- a/lisp/with-editor/with-editor.info +++ b/lisp/with-editor/with-editor.info @@ -1,7 +1,7 @@ This is with-editor.info, produced by makeinfo version 7.1.1 from with-editor.texi. - Copyright (C) 2015-2024 Jonas Bernoulli + Copyright (C) 2015-2025 Jonas Bernoulli You can redistribute this document and/or modify it under the terms @@ -40,9 +40,9 @@ library is made available as a separate package. It also defines some additional functionality which makes it useful even for end-users, who don't use Magit or another package which uses it internally. -This manual is for With-Editor version 3.4.3. +This manual is for With-Editor version 3.4.4. - Copyright (C) 2015-2024 Jonas Bernoulli + Copyright (C) 2015-2025 Jonas Bernoulli You can redistribute this document and/or modify it under the terms diff --git a/lisp/yasnippet-snippets/snippets/python-mode/.yas-setup.el b/lisp/yasnippet-snippets/snippets/python-mode/.yas-setup.el index e9145efd..3029c80e 100644 --- a/lisp/yasnippet-snippets/snippets/python-mode/.yas-setup.el +++ b/lisp/yasnippet-snippets/snippets/python-mode/.yas-setup.el @@ -1,22 +1,71 @@ ;;; -*- lexical-binding: t -*- + +; Copyright (C) miscellaneous contributors, see git history +; Copyright (C) 2024 Daniel Hornung +; +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as +; published by the Free Software Foundation, either version 3 of the +; License, or (at your option) any later version. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see . + (require 'yasnippet) (defvar yas-text) -(defvar python-split-arg-arg-regex -"\\([[:alnum:]*]+\\)\\(:[[:blank:]]*[[:alpha:]]*\\)?\\([[:blank:]]*=[[:blank:]]*[[:alnum:]]*\\)?" +(defvar yas-python-regex-identifier "[[:alnum:]_]+" "Simplified Python identifier.") +(defvar yas-python-regex-quoted-or-identifier (concat + "\\(" + yas-python-regex-identifier + "\\)" + "\\|" "\".*\"" + "\\|" "'.*'" + ) + "Simplified Python identifier or quoted string. +Does not work well with multiple or escaped quotes") + +(defvar python-split-arg-regex + (concat + "\\(" yas-python-regex-identifier "\\)" ; name + "\\(:[[:blank:]]*\\([][:alpha:]_[]*\\)\\)?" ; type + "\\([[:blank:]]*=[[:blank:]]*\\(" + yas-python-regex-quoted-or-identifier ; default + "\\)\\)?" + ) "Regular expression matching an argument of a python function. -First group should give the argument name.") +Groups: +- 1: the argument name +- 3: the type +- 5: the default value") (defvar python-split-arg-separator "[[:space:]]*,[[:space:]]*" "Regular expression matching the separator in a list of argument.") (defun python-split-args (arg-string) - "Split a python argument string ARG-STRING into a tuple of argument names." - (mapcar (lambda (x) - (when (string-match python-split-arg-arg-regex x) - (match-string-no-properties 1 x))) - (split-string arg-string python-split-arg-separator t))) + "Split python argument string ARG-STRING. + +The result is a list ((name, type, default), ...) of argument names, types and +default values. An argument named `self` is omitted." + (remove + nil + (mapcar (lambda (x) ; organize output + (when (and + (not (equal "self" x)) + (string-match python-split-arg-regex x) + ) + (list + (match-string-no-properties 1 x) ; name + (match-string-no-properties 3 x) ; type + (match-string-no-properties 5 x) ; default + ))) + (split-string arg-string python-split-arg-separator t)))) (defun python-args-to-docstring () "Return docstring format for the python arguments in yas-text." @@ -26,7 +75,9 @@ First group should give the argument name.") (formatted-args (mapconcat (lambda (x) (concat (nth 0 x) (make-string (- max-len (length (nth 0 x))) ? ) " -- " - (if (nth 1 x) (concat "\(default " (nth 1 x) "\)")))) + (if (nth 1 x) (concat (nth 1 x) ": ")) + (if (nth 2 x) (concat "\(default " (nth 2 x) "\)")) + )) args indent))) (unless (string= formatted-args "") @@ -36,7 +87,11 @@ First group should give the argument name.") "return docstring format for the python arguments in yas-text" (let* ((args (python-split-args yas-text)) (format-arg (lambda(arg) - (concat (nth 0 arg) " : " (if (nth 1 arg) ", optional") "\n"))) + (concat (nth 0 arg) " : " ; name + (if (nth 1 arg) (nth 1 arg)) ; type TODO handle Optional[Foo] correctly + (if (nth 2 arg) (concat (when (nth 1 arg) ", ") + "default=" (nth 2 arg))) ; default + "\n"))) (formatted-params (mapconcat format-arg args "\n")) (formatted-ret (mapconcat format-arg (list (list "out")) "\n"))) (unless (string= formatted-params "") @@ -44,3 +99,38 @@ First group should give the argument name.") (list "\nParameters\n----------" formatted-params "\nReturns\n-------" formatted-ret) "\n")))) + + +;; Tests +;; (ert-deftest test-split () +;; "For starters, only test a single string for expected output." +;; (should (equal +;; (python-split-args "_foo='this', bar: int = 2, baz: Optional[My_Type], foobar") +;; (list '("_foo" nil "'this'") +;; '("bar" "int" "2") +;; '("baz" "Optional[My_Type]" nil) +;; '("foobar" nil nil))) +;; )) + +;; (ert-deftest test-argument-self () +;; "If an argument is called `self`, it must be omitted" +;; (should (equal +;; (python-split-args "self, _foo=\"this\"") +;; (list '("_foo" nil "\"this\"") +;; )) +;; )) + +;; For manual testing and development: + +;; (setq yas-text "foo=3, bar: int = 2, baz: Optional[MyType], foobar") +;; (split-string yas-text python-split-arg-separator t) +;; +;; (save-match-data +;; (setq my-string "_foo: my_bar = 'this'") +;; (string-match python-split-arg-regex my-string) +;; (match-string 5 my-string) +;; ) +;; +;; (python-split-args yas-text) +;; (python-args-to-docstring) +;; (python-args-to-docstring-numpy) diff --git a/lisp/yasnippet-snippets/yasnippet-snippets-pkg.el b/lisp/yasnippet-snippets/yasnippet-snippets-pkg.el index 40024165..34ae3c0e 100644 --- a/lisp/yasnippet-snippets/yasnippet-snippets-pkg.el +++ b/lisp/yasnippet-snippets/yasnippet-snippets-pkg.el @@ -1,14 +1,10 @@ -(define-package "yasnippet-snippets" "20250225.950" "Collection of yasnippet snippets" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "yasnippet-snippets" "20250507.2002" + "Collection of yasnippet snippets." '((yasnippet "0.8.0")) - :commit "46945ccf63122190dc564af4ec26f828eaa29b43" :authors - '(("Andrea Crotti" . "andrea.crotti.0@gmail.com")) - :maintainers - '(("Andrea Crotti" . "andrea.crotti.0@gmail.com")) - :maintainer - '("Andrea Crotti" . "andrea.crotti.0@gmail.com") - :keywords - '("snippets") - :url "https://github.com/AndreaCrotti/yasnippet-snippets") -;; Local Variables: -;; no-byte-compile: t -;; End: + :url "https://github.com/AndreaCrotti/yasnippet-snippets" + :commit "48e968d555afe8bf64829da364d5c8915980cc32" + :revdesc "48e968d555af" + :keywords '("snippets") + :authors '(("Andrea Crotti" . "andrea.crotti.0@gmail.com")) + :maintainers '(("Andrea Crotti" . "andrea.crotti.0@gmail.com"))) diff --git a/lisp/yasnippet-snippets/yasnippet-snippets.el b/lisp/yasnippet-snippets/yasnippet-snippets.el index 958f6da5..c754123f 100644 --- a/lisp/yasnippet-snippets/yasnippet-snippets.el +++ b/lisp/yasnippet-snippets/yasnippet-snippets.el @@ -4,7 +4,8 @@ ;; Author: Andrea Crotti ;; Keywords: snippets -;; Version: 1.0 +;; Package-Version: 20250507.2002 +;; Package-Revision: 48e968d555af ;; Package-Requires: ((yasnippet "0.8.0")) ;; Keywords: convenience, snippets ;; Homepage: https://github.com/AndreaCrotti/yasnippet-snippets diff --git a/lisp/yasnippet/yasnippet-pkg.el b/lisp/yasnippet/yasnippet-pkg.el index 30d30e27..9d5fa764 100644 --- a/lisp/yasnippet/yasnippet-pkg.el +++ b/lisp/yasnippet/yasnippet-pkg.el @@ -1,13 +1,10 @@ -(define-package "yasnippet" "20250112.1504" "Yet another snippet extension for Emacs" +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "yasnippet" "20250602.1342" + "Yet another snippet extension for Emacs." '((cl-lib "0.5") - (emacs "24.4")) - :commit "03b1b11547eab76851574eadd18e2ad186b2a080" :maintainers - '(("Noam Postavsky" . "npostavs@gmail.com")) - :maintainer - '("Noam Postavsky" . "npostavs@gmail.com") - :keywords - '("convenience" "emulation") - :url "http://github.com/joaotavora/yasnippet") -;; Local Variables: -;; no-byte-compile: t -;; End: + (emacs "24.4")) + :url "http://github.com/joaotavora/yasnippet" + :commit "dd570a6b22364212fff9769cbf4376bdbd7a63c5" + :revdesc "dd570a6b2236" + :keywords '("convenience" "emulation") + :maintainers '(("Noam Postavsky" . "npostavs@gmail.com"))) diff --git a/lisp/yasnippet/yasnippet.el b/lisp/yasnippet/yasnippet.el index 602e74ee..296bc801 100644 --- a/lisp/yasnippet/yasnippet.el +++ b/lisp/yasnippet/yasnippet.el @@ -5,7 +5,8 @@ ;; João Távora , ;; Noam Postavsky ;; Maintainer: Noam Postavsky -;; Version: 0.14.1 +;; Package-Version: 20250602.1342 +;; Package-Revision: dd570a6b2236 ;; X-URL: http://github.com/joaotavora/yasnippet ;; Keywords: convenience, emulation ;; URL: http://github.com/joaotavora/yasnippet @@ -588,8 +589,6 @@ can be useful." ;;; Internal variables -(defconst yas--version "0.14.0") - (defvar yas--menu-table (make-hash-table) "A hash table of MAJOR-MODE symbols to menu keymaps.") @@ -891,18 +890,10 @@ which decides on the snippet to expand.") ;;;###autoload (define-minor-mode yas-minor-mode - "Toggle YASnippet mode. + "YASnippet minor mode. When YASnippet mode is enabled, `yas-expand', normally bound to -the TAB key, expands snippets of code depending on the major -mode. - -With no argument, this command toggles the mode. -positive prefix argument turns on the mode. -Negative prefix argument turns off the mode. - -Key bindings: -\\{yas-minor-mode-map}" +the TAB key, expands snippets of code depending on the major mode." :lighter " yas" ;; The indicator for the mode line. (cond ((and yas-minor-mode (featurep 'yasnippet)) ;; Install the direct keymaps in `emulation-mode-map-alists' @@ -1463,7 +1454,7 @@ Returns (TEMPLATES START END). This function respects (defun yas--remove-misc-free-from-undo (old-undo-list) "Tries to work around Emacs Bug#30931. Helper function for `yas--save-restriction-and-widen'." - ;; If Bug#30931 is unfixed, we get (# . INTEGER) + ;; If Bug#30931 is unfixed (Emacs<26.2), we get (# . INTEGER) ;; entries in the undo list. If we call `type-of' on the ;; Lisp_Misc_Free object then Emacs aborts, so try to find it by ;; checking that its type is none of the expected ones. @@ -1487,15 +1478,16 @@ Helper function for `yas--save-restriction-and-widen'." (defmacro yas--save-restriction-and-widen (&rest body) "Equivalent to (save-restriction (widen) BODY). -Also tries to work around Emacs Bug#30931." +Also tries to work around Emacs Bug#30931, fixed in Emacs-26.2." (declare (debug (body)) (indent 0)) - ;; Disable garbage collection, since it could cause an abort. - `(let ((gc-cons-threshold most-positive-fixnum) - (old-undo-list buffer-undo-list)) - (prog1 (save-restriction - (widen) - ,@body) - (yas--remove-misc-free-from-undo old-undo-list)))) + (let ((main `(save-restriction (widen) ,@body))) + (if (< emacs-major-version 27) + ;; Disable garbage collection, since it could cause an abort. + `(let ((gc-cons-threshold most-positive-fixnum) + (old-undo-list buffer-undo-list)) + (prog1 ,main + (yas--remove-misc-free-from-undo old-undo-list))) + main))) (defun yas--eval-for-string (form) "Evaluate FORM and convert the result to string." @@ -1679,8 +1671,9 @@ Here's a list of currently recognized directives: (directory-files directory t))) (defun yas--make-menu-binding (template) - (let ((mode (yas--table-mode (yas--template-table template)))) - `(lambda () (interactive) (yas--expand-or-visit-from-menu ',mode ,(yas--template-uuid template))))) + (let ((mode (yas--table-mode (yas--template-table template))) + (uuid (yas--template-uuid template))) + (lambda () (interactive) (yas--expand-or-visit-from-menu mode uuid)))) (defun yas--expand-or-visit-from-menu (mode uuid) (let* ((table (yas--table-get-create mode)) @@ -1941,16 +1934,18 @@ With prefix argument USE-JIT do jit-loading of snippets." (let ((output-file (expand-file-name ".yas-compiled-snippets.el" directory))) (with-temp-file output-file - (insert (format ";;; Compiled snippets and support files for `%s'\n" + (insert (format ";;; \"Compiled\" snippets and support files for `%S' -*- lexical-binding:t -*-\n" mode-sym)) (yas--load-directory-2 directory mode-sym) (insert (format ";;; Do not edit! File generated at %s\n" (current-time-string))))) ;; Normal case. (unless (file-exists-p (expand-file-name ".yas-skip" directory)) - (unless (and (load (expand-file-name ".yas-compiled-snippets" directory) - 'noerror (<= yas-verbosity 3)) - (progn (yas--message 4 "Loaded compiled snippets from %s" directory) t)) + (if (let ((warning-inhibit-types + '((files missing-lexbind-cookie)))) + (load (expand-file-name ".yas-compiled-snippets" directory) + 'noerror (<= yas-verbosity 3))) + (yas--message 4 "Loaded compiled snippets from %s" directory) (yas--message 4 "Loading snippet files from %s" directory) (yas--load-directory-2 directory mode-sym))))) @@ -2127,27 +2122,23 @@ This works by stubbing a few functions, then calling (defun yas-about () (interactive) (message "yasnippet (version %s) -- pluskid/joaotavora/npostavs" - (or (ignore-errors (car (let ((default-directory yas--loaddir)) - (process-lines "git" "describe" - "--tags" "--dirty")))) - (eval-when-compile + (or (eval-when-compile (and (fboundp 'package-get-version) (package-get-version))) - (when (and (featurep 'package) + (when (and (boundp 'package-alist) (fboundp 'package-desc-version) (fboundp 'package-version-join)) - (defvar package-alist) (ignore-errors - (let* ((yas-pkg (cdr (assq 'yasnippet package-alist))) - (version (package-version-join - (package-desc-version (car yas-pkg))))) - ;; Special case for MELPA's bogus version numbers. - (if (string-match "\\`20..[01][0-9][0-3][0-9][.][0-9]\\{3,4\\}\\'" - version) - (concat yas--version "-snapshot" version) - version)))) - yas--version))) - + (let* ((yas-pkg (cdr (assq 'yasnippet package-alist)))) + (when yas-pkg + (package-version-join + (package-desc-version (car yas-pkg))))))) + ;; The Git description can be misleading, for lack of + ;; recent tags, so we prefer package version info. + (ignore-errors (car (let ((default-directory yas--loaddir)) + (process-lines "git" "describe" + "--tags" "--dirty")))) + "unknown"))) ;;; Apropos snippet menu: ;; @@ -3212,12 +3203,13 @@ ENV is a lisp expression that evaluates to list of elements with the form (VAR FORM), where VAR is a symbol and FORM is a lisp expression that evaluates to its value." (declare (debug (form body)) (indent 1)) - (let ((envvar (make-symbol "envvar"))) - `(let ((,envvar ,env)) - (cl-progv - (mapcar #'car ,envvar) - (mapcar (lambda (v-f) (eval (cadr v-f) t)) ,envvar) - ,@body)))) + `(yas--letenv-f ,env (lambda () ,@body))) + +(defun yas--letenv-f (env body-fun) + (cl-progv + (mapcar #'car env) + (mapcar (lambda (v-f) (eval (cadr v-f) t)) env) + (funcall body-fun))) (defun yas--snippet-map-markers (fun snippet) "Apply FUN to all marker (sub)fields in SNIPPET. @@ -4133,7 +4125,7 @@ Returns the newly created snippet." (unwind-protect (let ((buffer-undo-list t)) (goto-char begin) - (if (> emacs-major-version 29) + (if (< emacs-major-version 27) ;; Don't use the workaround for CC-mode's cache, ;; since it was presumably a bug in CC-mode, so either ;; it's fixed already, or it should get fixed. @@ -4161,6 +4153,7 @@ Returns the newly created snippet." (run-hook-with-args 'after-change-functions (point-min) (point-max) (- end begin)))) + ;; FIXME: Use `undo-amalgamate-change-group'? (when (listp buffer-undo-list) (push (cons (point-min) (point-max)) buffer-undo-list))) @@ -5056,7 +5049,7 @@ object satisfying `yas--field-p' to restrict the expansion to."))) (define-button-type 'help-snippet-def :supertype 'help-xref 'help-function (lambda (template) (yas--visit-snippet-file-1 template)) - 'help-echo (purecopy "mouse-2, RET: find snippets's definition")) + 'help-echo "mouse-2, RET: find snippets's definition") (defun yas--snippet-description-finish-runonce () "Final adjustments for the help buffer when snippets are concerned."