From 8de00e5202be70f2be66c02a153fa4edac16f8d2 Mon Sep 17 00:00:00 2001 From: Daniel Weschke Date: Tue, 4 Jan 2022 21:35:17 +0100 Subject: [PATCH] update packages --- lisp/gnuplot/gnuplot-context.el | 112 +- lisp/gnuplot/gnuplot-gui.el | 213 +- lisp/gnuplot/gnuplot-pkg.el | 4 +- lisp/gnuplot/gnuplot.el | 455 +- lisp/ht.el | 11 +- lisp/htmlize.el | 32 +- lisp/hydra/hydra-pkg.el | 4 +- lisp/hydra/hydra.el | 14 +- lisp/indent-guide.el | 13 +- lisp/ivy-bibtex.el | 75 +- lisp/js2-mode/js2-imenu-extras.el | 172 + lisp/js2-mode/js2-mode-pkg.el | 4 +- lisp/js2-mode/js2-mode.el | 236 +- lisp/ledger-mode/ledger-commodities.el | 2 +- lisp/ledger-mode/ledger-complete.el | 11 +- lisp/ledger-mode/ledger-context.el | 4 +- lisp/ledger-mode/ledger-exec.el | 3 +- lisp/ledger-mode/ledger-fonts.el | 6 +- lisp/ledger-mode/ledger-init.el | 26 +- lisp/ledger-mode/ledger-mode-pkg.el | 4 +- lisp/ledger-mode/ledger-mode.info | 111 +- lisp/ledger-mode/ledger-occur.el | 9 +- lisp/ledger-mode/ledger-post.el | 6 +- lisp/ledger-mode/ledger-reconcile.el | 15 +- lisp/ledger-mode/ledger-regex.el | 357 +- lisp/ledger-mode/ledger-report.el | 4 +- lisp/ledger-mode/ledger-texi.el | 5 +- lisp/ledger-mode/ledger-xact.el | 37 +- lisp/magit/AUTHORS.md | 25 +- lisp/magit/LICENSE | 26 +- lisp/magit/git-rebase.el | 53 +- lisp/magit/magit-apply.el | 108 +- lisp/magit/magit-autorevert.el | 7 +- lisp/magit/magit-bisect.el | 19 +- lisp/magit/magit-blame.el | 58 +- lisp/magit/magit-bookmark.el | 16 +- lisp/magit/magit-branch.el | 132 +- lisp/magit/magit-bundle.el | 135 + lisp/magit/magit-clone.el | 26 +- lisp/magit/magit-commit.el | 124 +- lisp/magit/magit-core.el | 7 +- lisp/magit/magit-diff.el | 322 +- lisp/magit/magit-ediff.el | 231 +- lisp/magit/magit-extras.el | 133 +- lisp/magit/magit-fetch.el | 62 +- lisp/magit/magit-files.el | 44 +- lisp/magit/magit-git.el | 313 +- lisp/magit/magit-gitignore.el | 13 +- lisp/magit/magit-imenu.el | 40 +- lisp/magit/magit-log.el | 173 +- lisp/magit/magit-margin.el | 9 +- lisp/magit/magit-merge.el | 22 +- lisp/magit/magit-mode.el | 160 +- lisp/magit/magit-notes.el | 16 +- lisp/magit/magit-obsolete.el | 7 +- lisp/magit/magit-patch.el | 16 +- lisp/magit/magit-pkg.el | 17 +- lisp/magit/magit-process.el | 132 +- lisp/magit/magit-pull.el | 6 +- lisp/magit/magit-push.el | 34 +- lisp/magit/magit-reflog.el | 11 +- lisp/magit/magit-refs.el | 38 +- lisp/magit/magit-remote.el | 25 +- lisp/magit/magit-repos.el | 165 +- lisp/magit/magit-reset.el | 4 +- lisp/magit/magit-section.el | 1776 ---- lisp/magit/magit-sequence.el | 96 +- lisp/magit/magit-stash.el | 33 +- lisp/magit/magit-status.el | 90 +- lisp/magit/magit-submodule.el | 93 +- lisp/magit/magit-subtree.el | 4 +- lisp/magit/magit-tag.el | 6 +- lisp/magit/magit-transient.el | 12 +- lisp/magit/magit-utils.el | 287 +- lisp/magit/magit-version.el | 2 +- lisp/magit/magit-wip.el | 65 +- lisp/magit/magit-worktree.el | 13 +- lisp/magit/magit.el | 158 +- lisp/magit/magit.info | 334 +- lisp/magit/magit.info-1 | 1787 ++-- lisp/magit/magit.info-2 | 2751 +++--- lisp/markdown-mode.el | 683 +- lisp/multiple-cursors/mc-cycle-cursors.el | 6 +- lisp/multiple-cursors/mc-mark-more.el | 6 +- .../mc-separate-operations.el | 3 +- .../multiple-cursors/multiple-cursors-core.el | 13 +- lisp/multiple-cursors/multiple-cursors-pkg.el | 7 +- lisp/multiple-cursors/multiple-cursors.el | 1 + lisp/ob-async.el | 15 +- lisp/org-brain.el | 144 +- lisp/org-contrib/COPYING | 674 ++ lisp/org-contrib/README.org | 143 + lisp/{org/lisp => org-contrib}/ob-J.el | 6 +- lisp/{org/lisp => org-contrib}/ob-abc.el | 12 +- .../lisp => org-contrib}/ob-arduino.el | 20 +- .../{org/lisp => org-contrib}/ob-asymptote.el | 5 +- .../ob-clojure-literate.el | 18 +- lisp/{org/lisp => org-contrib}/ob-coq.el | 5 +- .../contrib/lisp => org-contrib}/ob-csharp.el | 4 +- lisp/{org/lisp => org-contrib}/ob-ebnf.el | 12 +- .../lisp => org-contrib}/ob-eukleides.el | 6 +- .../contrib/lisp => org-contrib}/ob-fomus.el | 2 +- lisp/{org/lisp => org-contrib}/ob-hledger.el | 6 +- lisp/{org/lisp => org-contrib}/ob-io.el | 10 +- lisp/{org/lisp => org-contrib}/ob-ledger.el | 9 +- .../lisp => org-contrib}/ob-mathematica.el | 20 +- .../lisp => org-contrib}/ob-mathomatic.el | 4 +- lisp/{org/lisp => org-contrib}/ob-mscgen.el | 11 +- .../contrib/lisp => org-contrib}/ob-oz.el | 2 +- .../contrib/lisp => org-contrib}/ob-php.el | 22 +- lisp/{org/lisp => org-contrib}/ob-picolisp.el | 16 +- .../contrib/lisp => org-contrib}/ob-redis.el | 21 +- .../contrib/lisp => org-contrib}/ob-sclang.el | 7 +- lisp/{org/lisp => org-contrib}/ob-shen.el | 4 +- lisp/org-contrib/ob-smiles.el | 71 + .../contrib/lisp => org-contrib}/ob-spice.el | 8 +- lisp/{org/lisp => org-contrib}/ob-stan.el | 6 +- .../contrib/lisp => org-contrib}/ob-stata.el | 7 +- .../contrib/lisp => org-contrib}/ob-tcl.el | 4 +- lisp/{org/lisp => org-contrib}/ob-vala.el | 8 +- .../contrib/lisp => org-contrib}/ob-vbnet.el | 4 +- .../lisp => org-contrib}/ol-bookmark.el | 5 +- .../lisp => org-contrib}/ol-elisp-symbol.el | 8 +- .../lisp => org-contrib}/ol-git-link.el | 4 +- .../contrib/lisp => org-contrib}/ol-mew.el | 4 +- .../lisp => org-contrib}/ol-notmuch.el | 9 +- .../contrib/lisp => org-contrib}/ol-vm.el | 8 +- .../contrib/lisp => org-contrib}/ol-wl.el | 6 +- .../lisp => org-contrib}/org-annotate-file.el | 4 +- .../org-attach-embedded-images.el | 5 +- .../lisp => org-contrib}/org-bibtex-extras.el | 6 +- .../lisp => org-contrib}/org-checklist.el | 4 +- .../lisp => org-contrib}/org-choose.el | 40 +- .../lisp => org-contrib}/org-collector.el | 6 +- .../lisp => org-contrib}/org-contacts.el | 124 +- lisp/org-contrib/org-contrib-pkg.el | 2 + lisp/org-contrib/org-contrib.el | 55 + .../lisp => org-contrib}/org-contribdir.el | 6 +- .../lisp => org-contrib}/org-depend.el | 6 +- .../lisp => org-contrib}/org-effectiveness.el | 6 +- .../contrib/lisp => org-contrib}/org-eldoc.el | 12 +- .../lisp => org-contrib}/org-eval-light.el | 8 +- .../contrib/lisp => org-contrib}/org-eval.el | 8 +- .../lisp => org-contrib}/org-expiry.el | 9 +- .../org-interactive-query.el | 7 +- .../lisp => org-contrib}/org-invoice.el | 36 +- .../contrib/lisp => org-contrib}/org-learn.el | 8 +- .../lisp => org-contrib}/org-license.el | 170 +- .../lisp => org-contrib}/org-link-edit.el | 4 +- .../lisp => org-contrib}/org-mac-iCal.el | 4 +- .../lisp => org-contrib}/org-mac-link.el | 111 +- .../lisp => org-contrib}/org-mairix.el | 8 +- .../lisp => org-contrib}/org-notify.el | 5 +- .../contrib/lisp => org-contrib}/org-panel.el | 40 +- .../lisp => org-contrib}/org-passwords.el | 5 +- .../lisp => org-contrib}/org-registry.el | 6 +- .../lisp => org-contrib}/org-screen.el | 9 +- .../lisp => org-contrib}/org-screenshot.el | 6 +- .../lisp => org-contrib}/org-secretary.el | 7 +- .../org-static-mathjax.el | 5 +- .../lisp => org-contrib}/org-sudoku.el | 9 +- .../contrib/lisp => org-contrib}/org-toc.el | 8 +- .../contrib/lisp => org-contrib}/org-track.el | 9 +- .../lisp => org-contrib}/org-velocity.el | 22 +- .../lisp => org-contrib}/org-wikinodes.el | 7 +- .../lisp => org-contrib}/orgtbl-sqlinsert.el | 4 +- .../contrib/lisp => org-contrib}/ox-bibtex.el | 10 +- .../lisp => org-contrib}/ox-confluence.el | 4 +- .../contrib/lisp => org-contrib}/ox-deck.el | 8 +- .../contrib/lisp => org-contrib}/ox-extra.el | 4 +- .../lisp => org-contrib}/ox-freemind.el | 4 +- .../contrib/lisp => org-contrib}/ox-groff.el | 4 +- .../contrib/lisp => org-contrib}/ox-rss.el | 16 +- .../contrib/lisp => org-contrib}/ox-s5.el | 8 +- .../lisp => org-contrib}/ox-taskjuggler.el | 11 +- lisp/org-drill.el | 7 +- lisp/org-fancy-priorities.el | 18 +- .../citeproc/csl-locales/locales-en-US.xml | 357 + .../citeproc/csl-styles/apa-5th-edition.csl | 341 + .../apa-numeric-superscript-brackets.csl | 1711 ++++ .../chicago-author-date-16th-edition.csl | 657 ++ .../citeproc/csl-styles/elsevier-harvard.csl | 239 + .../csl-styles/elsevier-with-titles.csl | 149 + lisp/org-ref/citeproc/csl/acs-nano.csl | 214 - lisp/org-ref/citeproc/csl/author-year.el | 92 - lisp/org-ref/citeproc/csl/unsrt-footnote.el | 86 - lisp/org-ref/citeproc/csl/unsrt-paren.el | 107 - lisp/org-ref/citeproc/csl/unsrt.el | 111 - lisp/org-ref/citeproc/readme-author-year.org | 92 - lisp/org-ref/citeproc/readme-unsrt.org | 93 - lisp/org-ref/citeproc/readme.bib | 203 - lisp/org-ref/citeproc/readme.org | 1676 ---- lisp/org-ref/doi-utils.el | 441 +- lisp/org-ref/nist-webbook.el | 12 +- lisp/org-ref/org-ref-arxiv.el | 141 +- lisp/org-ref/org-ref-bibliography-links.el | 312 + lisp/org-ref/org-ref-bibtex.el | 1660 ++-- lisp/org-ref/org-ref-citation-links.el | 1339 +++ lisp/org-ref/org-ref-citeproc.el | 919 -- lisp/org-ref/org-ref-core.el | 4238 +-------- lisp/org-ref/org-ref-export.el | 594 ++ lisp/org-ref/org-ref-glossary.el | 793 +- lisp/org-ref/org-ref-helm-bibtex.el | 750 -- lisp/org-ref/org-ref-helm-cite.el | 771 -- lisp/org-ref/org-ref-helm.el | 538 +- lisp/org-ref/org-ref-isbn.el | 3 +- lisp/org-ref/org-ref-ivy-cite.el | 561 -- lisp/org-ref/org-ref-ivy.el | 127 +- lisp/org-ref/org-ref-label-link.el | 60 + lisp/org-ref/org-ref-latex.el | 152 +- lisp/org-ref/org-ref-misc-links.el | 304 + lisp/org-ref/org-ref-natbib-bbl-citeproc.el | 518 ++ lisp/org-ref/org-ref-pdf.el | 198 +- lisp/org-ref/org-ref-pgk.el | 22 +- lisp/org-ref/org-ref-pkg.el | 23 +- lisp/org-ref/org-ref-pubmed.el | 136 +- lisp/org-ref/org-ref-ref-links.el | 555 ++ lisp/org-ref/org-ref-refproc.el | 467 + lisp/org-ref/org-ref-reftex.el | 274 - lisp/org-ref/org-ref-sci-id.el | 38 +- lisp/org-ref/org-ref-scopus.el | 106 +- lisp/org-ref/org-ref-url-utils.el | 167 +- lisp/org-ref/org-ref-utils.el | 997 +- lisp/org-ref/org-ref-wos.el | 48 +- lisp/org-ref/org-ref.bib | 5 +- lisp/org-ref/org-ref.el | 26 +- lisp/org-ref/org-ref.org | 819 +- lisp/org-ref/x2bib.el | 2 + lisp/org-superstar.el | 149 +- lisp/org/.dir-locals.el | 22 + lisp/org/CONTRIBUTE | 71 + lisp/org/COPYING | 8 +- lisp/org/Makefile | 182 +- lisp/org/README | 44 +- lisp/org/README_ELPA | 38 + lisp/org/contrib/README | 100 - lisp/org/contrib/lisp/ob-smiles.el | 54 - lisp/org/contrib/scripts/.gitignore | 1 - lisp/org/contrib/scripts/StartOzServer.oz | 231 - lisp/org/contrib/scripts/dir2org.zsh | 56 - lisp/org/contrib/scripts/ditaa.jar | Bin 186095 -> 0 bytes lisp/org/contrib/scripts/docco.css | 185 - lisp/org/contrib/scripts/org-docco.org | 206 - lisp/org/contrib/scripts/org2hpda | 106 - .../contrib/scripts/staticmathjax/.gitignore | 1 - .../contrib/scripts/staticmathjax/README.org | 79 - .../scripts/staticmathjax/application.ini | 11 - .../staticmathjax/chrome/chrome.manifest | 1 - .../staticmathjax/chrome/content/main.js | 198 - .../staticmathjax/chrome/content/main.xul | 11 - .../defaults/preferences/prefs.js | 1 - lisp/org/contrib/scripts/x11idle.c | 28 - lisp/org/dir | 19 + lisp/org/doc/.aspell.org.conf | 81 + lisp/org/doc/.nosearch | 1 + lisp/org/doc/Makefile | 43 +- lisp/org/doc/doc-setup.org | 19 +- lisp/org/doc/fdl.org | 4 +- lisp/org/doc/htmlxref.cnf | 4 +- lisp/org/doc/org-guide.org | 24 +- lisp/org/doc/org-manual.org | 943 +- lisp/org/doc/org-version.inc | 4 +- lisp/org/doc/org-version.tex | 4 - lisp/org/doc/org.pdf | Bin 1259816 -> 0 bytes lisp/org/doc/org.texi | 963 +- lisp/org/doc/orgcard.pdf | Bin 118610 -> 0 bytes lisp/org/doc/orgcard.tex | 2 +- lisp/org/doc/orgcard_letter.pdf | Bin 119042 -> 0 bytes lisp/org/doc/orgguide.pdf | Bin 293802 -> 0 bytes lisp/org/doc/orgguide.texi | 27 +- lisp/org/doc/pdflayout.sty | 2 +- lisp/org/doc/texinfo.tex | 12 +- lisp/org/etc/Makefile | 2 +- lisp/org/etc/ORG-NEWS | 705 +- lisp/org/etc/csl/README | 10 + lisp/org/etc/csl/chicago-author-date.csl | 658 ++ lisp/org/etc/csl/locales-en-US.xml | 357 + .../etc/schema/od-manifest-schema-v1.2-os.rnc | 88 - lisp/org/etc/schema/od-schema-v1.2-os.rnc | 6280 ------------- lisp/org/etc/schema/schemas.xml | 7 - lisp/org/etc/styles/README | 2 +- lisp/org/lisp/Makefile | 93 - lisp/org/lisp/ob-comint.el | 154 - lisp/org/lisp/ob-core.el.orig | 3234 ------- lisp/org/lisp/ob-java.el | 84 - lisp/org/lisp/org-install.el | 17 - lisp/org/lisp/org-plot.el | 348 - lisp/org/local.mk | 52 + lisp/org/mk/default.mk | 176 - lisp/org/mk/org-fixup.el | 200 - lisp/org/mk/targets.mk | 168 - lisp/org/mk/version.mk | 2 - lisp/org/{lisp => }/ob-C.el | 118 +- lisp/org/{lisp => }/ob-R.el | 126 +- lisp/org/{lisp => }/ob-awk.el | 15 +- lisp/org/{lisp => }/ob-calc.el | 5 +- lisp/org/{lisp => }/ob-clojure.el | 5 +- lisp/org/ob-comint.el | 312 + lisp/org/{lisp => }/ob-core.el | 151 +- lisp/org/{lisp => }/ob-css.el | 2 +- lisp/org/{lisp => }/ob-ditaa.el | 2 +- lisp/org/{lisp => }/ob-dot.el | 5 +- lisp/org/{lisp => }/ob-emacs-lisp.el | 2 +- lisp/org/{lisp => }/ob-eshell.el | 5 +- lisp/org/{lisp => }/ob-eval.el | 89 +- lisp/org/{lisp => }/ob-exp.el | 32 +- lisp/org/{lisp => }/ob-forth.el | 6 +- lisp/org/{lisp => }/ob-fortran.el | 12 +- lisp/org/{lisp => }/ob-gnuplot.el | 28 +- lisp/org/{lisp => }/ob-groovy.el | 5 +- lisp/org/{lisp => }/ob-haskell.el | 13 +- lisp/org/ob-java.el | 490 + lisp/org/{lisp => }/ob-js.el | 6 +- lisp/org/{contrib/lisp => }/ob-julia.el | 232 +- lisp/org/{lisp => }/ob-latex.el | 65 +- lisp/org/{lisp => }/ob-lilypond.el | 34 +- lisp/org/{lisp => }/ob-lisp.el | 4 +- lisp/org/{lisp => }/ob-lob.el | 2 +- lisp/org/{lisp => }/ob-lua.el | 8 +- lisp/org/{lisp => }/ob-makefile.el | 5 +- lisp/org/{lisp => }/ob-matlab.el | 2 +- lisp/org/{lisp => }/ob-maxima.el | 2 +- lisp/org/{lisp => }/ob-ocaml.el | 8 +- lisp/org/{lisp => }/ob-octave.el | 20 +- lisp/org/{lisp => }/ob-org.el | 2 +- lisp/org/{lisp => }/ob-perl.el | 3 +- lisp/org/{lisp => }/ob-plantuml.el | 17 +- lisp/org/{lisp => }/ob-processing.el | 4 +- lisp/org/{lisp => }/ob-python.el | 71 +- lisp/org/{lisp => }/ob-ref.el | 2 +- lisp/org/{lisp => }/ob-ruby.el | 4 +- lisp/org/{lisp => }/ob-sass.el | 4 +- lisp/org/{lisp => }/ob-scheme.el | 4 +- lisp/org/{lisp => }/ob-screen.el | 5 +- lisp/org/{lisp => }/ob-sed.el | 14 +- lisp/org/{lisp => }/ob-shell.el | 2 +- lisp/org/{lisp => }/ob-sql.el | 87 +- lisp/org/{lisp => }/ob-sqlite.el | 32 +- lisp/org/{lisp => }/ob-table.el | 5 +- lisp/org/{lisp => }/ob-tangle.el | 222 +- lisp/org/{lisp => }/ob.el | 2 +- lisp/org/oc-basic.el | 789 ++ lisp/org/oc-biblatex.el | 318 + lisp/org/oc-csl.el | 631 ++ lisp/org/oc-natbib.el | 193 + lisp/org/oc.el | 1650 ++++ lisp/org/{lisp => }/ol-bbdb.el | 8 +- lisp/org/{lisp => }/ol-bibtex.el | 40 +- lisp/org/{lisp => }/ol-docview.el | 2 +- lisp/org/ol-doi.el | 72 + lisp/org/{lisp => }/ol-eshell.el | 12 +- lisp/org/{lisp => }/ol-eww.el | 2 +- lisp/org/{lisp => }/ol-gnus.el | 10 +- lisp/org/{lisp => }/ol-info.el | 8 +- lisp/org/{lisp => }/ol-irc.el | 8 +- lisp/org/{contrib/lisp => }/ol-man.el | 11 +- lisp/org/{lisp => }/ol-mhe.el | 2 +- lisp/org/{lisp => }/ol-rmail.el | 4 +- lisp/org/{lisp => }/ol-w3m.el | 113 +- lisp/org/{lisp => }/ol.el | 190 +- lisp/org/{lisp => }/org-agenda.el | 1250 +-- lisp/org/{lisp => }/org-archive.el | 4 +- lisp/org/{lisp => }/org-attach-git.el | 35 +- lisp/org/{lisp => }/org-attach.el | 97 +- lisp/org/{lisp => }/org-capture.el | 331 +- lisp/org/{lisp => }/org-clock.el | 191 +- lisp/org/{lisp => }/org-colview.el | 100 +- lisp/org/{lisp => }/org-compat.el | 355 +- lisp/org/{lisp => }/org-crypt.el | 12 +- lisp/org/{lisp => }/org-ctags.el | 14 +- lisp/org/{lisp => }/org-datetree.el | 8 +- lisp/org/{lisp => }/org-duration.el | 8 +- lisp/org/{lisp => }/org-element.el | 272 +- lisp/org/{lisp => }/org-entities.el | 6 +- lisp/org/{lisp => }/org-faces.el | 76 +- lisp/org/{lisp => }/org-feed.el | 4 +- lisp/org/{lisp => }/org-footnote.el | 17 +- lisp/org/{lisp => }/org-goto.el | 73 +- lisp/org/{lisp => }/org-habit.el | 14 +- lisp/org/{lisp => }/org-id.el | 176 +- lisp/org/{lisp => }/org-indent.el | 61 +- lisp/org/{lisp => }/org-inlinetask.el | 28 +- lisp/org/{lisp => }/org-keys.el | 111 +- lisp/org/{lisp => }/org-lint.el | 106 +- lisp/org/{lisp => }/org-list.el | 341 +- lisp/org/{lisp => }/org-loaddefs.el | 728 +- lisp/org/{lisp => }/org-macro.el | 135 +- lisp/org/{lisp => }/org-macs.el | 134 +- lisp/org/{lisp => }/org-mobile.el | 4 +- lisp/org/{lisp => }/org-mouse.el | 206 +- lisp/org/{lisp => }/org-num.el | 12 +- lisp/org/{lisp => }/org-pcomplete.el | 20 +- lisp/org/org-pkg.el | 2 + lisp/org/org-plot.el | 730 ++ lisp/org/{lisp => }/org-protocol.el | 81 +- lisp/org/{lisp => }/org-refile.el | 48 +- lisp/org/{lisp => }/org-src.el | 112 +- lisp/org/{lisp => }/org-table.el | 329 +- lisp/org/{lisp => }/org-tempo.el | 4 +- lisp/org/{lisp => }/org-timer.el | 27 +- lisp/org/{lisp => }/org-version.el | 6 +- lisp/org/{lisp => }/org.el | 1415 +-- lisp/org/{doc/org => org.info} | 2963 +++--- lisp/org/{doc/orgguide => orgguide.info} | 346 +- lisp/org/{lisp => }/ox-ascii.el | 67 +- lisp/org/{lisp => }/ox-beamer.el | 77 +- lisp/org/{lisp => }/ox-html.el | 379 +- lisp/org/{lisp => }/ox-icalendar.el | 22 +- lisp/org/{contrib/lisp => }/ox-koma-letter.el | 53 +- lisp/org/{lisp => }/ox-latex.el | 261 +- lisp/org/{lisp => }/ox-man.el | 38 +- lisp/org/{lisp => }/ox-md.el | 55 +- lisp/org/{lisp => }/ox-odt.el | 93 +- lisp/org/{lisp => }/ox-org.el | 21 +- lisp/org/{lisp => }/ox-publish.el | 62 +- lisp/org/{lisp => }/ox-texinfo.el | 131 +- lisp/org/{lisp => }/ox.el | 496 +- lisp/org/testing/README | 157 - lisp/org/testing/examples/agenda-file.org | 8 - lisp/org/testing/examples/att1/fileA | 1 - lisp/org/testing/examples/att1/fileB | 1 - lisp/org/testing/examples/att2/fileC | 1 - lisp/org/testing/examples/att2/fileD | 1 - lisp/org/testing/examples/attachments.org | 32 - lisp/org/testing/examples/babel-dangerous.org | 15 - lisp/org/testing/examples/babel.el | 5 - lisp/org/testing/examples/babel.org | 503 - lisp/org/testing/examples/data/ab/cd123/fileE | 1 - lisp/org/testing/examples/diary-file | 1 - lisp/org/testing/examples/include.html | 1 - lisp/org/testing/examples/include.org | 35 - lisp/org/testing/examples/include2.org | 1 - lisp/org/testing/examples/link-in-heading.org | 10 - lisp/org/testing/examples/links.org | 28 - lisp/org/testing/examples/macro-templates.org | 2 - lisp/org/testing/examples/no-heading.org | 9 - lisp/org/testing/examples/normal.org | 28 - lisp/org/testing/examples/ob-C-test.org | 164 - lisp/org/testing/examples/ob-awk-test.in | 2 - lisp/org/testing/examples/ob-awk-test.org | 46 - lisp/org/testing/examples/ob-fortran-test.org | 108 - .../examples/ob-header-arg-defaults.org | 112 - .../testing/examples/ob-lilypond-broken.ly | 31 - .../testing/examples/ob-lilypond-broken.org | 39 - .../testing/examples/ob-lilypond-test.error | 15 - lisp/org/testing/examples/ob-lilypond-test.ly | 30 - .../org/testing/examples/ob-lilypond-test.org | 37 - lisp/org/testing/examples/ob-maxima-test.org | 91 - lisp/org/testing/examples/ob-octave-test.org | 55 - lisp/org/testing/examples/ob-screen-test.org | 5 - lisp/org/testing/examples/ob-sed-test.org | 35 - lisp/org/testing/examples/ob-shell-test.org | 88 - lisp/org/testing/examples/org-exp.org | 14 - .../testing/examples/property-inheritance.org | 27 - .../org/testing/examples/pub-symlink/link.org | 1 - lisp/org/testing/examples/pub/a.org | 9 - lisp/org/testing/examples/pub/b.org | 9 - lisp/org/testing/examples/pub/file.txt | 1 - lisp/org/testing/examples/pub/link | 1 - lisp/org/testing/examples/pub/noextension | 1 - lisp/org/testing/examples/pub/sub/c.org | 2 - lisp/org/testing/examples/setupfile.org | 1 - lisp/org/testing/examples/setupfile3.org | 6 - .../testing/examples/subdir/setupfile2.org | 1 - lisp/org/testing/lisp/test-ob-C.el | 186 - lisp/org/testing/lisp/test-ob-R.el | 102 - lisp/org/testing/lisp/test-ob-awk.el | 48 - lisp/org/testing/lisp/test-ob-clojure.el | 91 - lisp/org/testing/lisp/test-ob-emacs-lisp.el | 170 - lisp/org/testing/lisp/test-ob-eshell.el | 73 - lisp/org/testing/lisp/test-ob-exp.el | 591 -- lisp/org/testing/lisp/test-ob-fortran.el | 113 - .../lisp/test-ob-header-arg-defaults.el | 83 - lisp/org/testing/lisp/test-ob-lilypond.el | 391 - lisp/org/testing/lisp/test-ob-lob.el | 283 - lisp/org/testing/lisp/test-ob-lua.el | 141 - lisp/org/testing/lisp/test-ob-maxima.el | 74 - lisp/org/testing/lisp/test-ob-octave.el | 65 - lisp/org/testing/lisp/test-ob-perl.el | 78 - lisp/org/testing/lisp/test-ob-plantuml.el | 73 - lisp/org/testing/lisp/test-ob-python.el | 212 - lisp/org/testing/lisp/test-ob-ruby.el | 81 - lisp/org/testing/lisp/test-ob-scheme.el | 111 - lisp/org/testing/lisp/test-ob-sed.el | 62 - lisp/org/testing/lisp/test-ob-shell.el | 111 - lisp/org/testing/lisp/test-ob-sqlite.el | 46 - lisp/org/testing/lisp/test-ob-table.el | 35 - lisp/org/testing/lisp/test-ob-tangle.el | 471 - lisp/org/testing/lisp/test-ob-vala.el | 104 - lisp/org/testing/lisp/test-ob.el | 2305 ----- lisp/org/testing/lisp/test-ol-bbdb.el | 36 - lisp/org/testing/lisp/test-ol.el | 495 - lisp/org/testing/lisp/test-org-agenda.el | 186 - lisp/org/testing/lisp/test-org-archive.el | 180 - lisp/org/testing/lisp/test-org-attach-git.el | 95 - lisp/org/testing/lisp/test-org-attach.el | 174 - lisp/org/testing/lisp/test-org-capture.el | 758 -- lisp/org/testing/lisp/test-org-clock.el | 1203 --- lisp/org/testing/lisp/test-org-colview.el | 1542 --- lisp/org/testing/lisp/test-org-datetree.el | 220 - lisp/org/testing/lisp/test-org-duration.el | 170 - lisp/org/testing/lisp/test-org-element.el | 3890 -------- lisp/org/testing/lisp/test-org-feed.el | 112 - lisp/org/testing/lisp/test-org-footnote.el | 682 -- lisp/org/testing/lisp/test-org-info.el | 64 - lisp/org/testing/lisp/test-org-inlinetask.el | 162 - lisp/org/testing/lisp/test-org-lint.el | 569 -- lisp/org/testing/lisp/test-org-list.el | 1553 ---- lisp/org/testing/lisp/test-org-macro.el | 399 - lisp/org/testing/lisp/test-org-macs.el | 107 - lisp/org/testing/lisp/test-org-num.el | 280 - lisp/org/testing/lisp/test-org-pcomplete.el | 185 - lisp/org/testing/lisp/test-org-protocol.el | 206 - lisp/org/testing/lisp/test-org-src.el | 496 - lisp/org/testing/lisp/test-org-table.el | 3359 ------- lisp/org/testing/lisp/test-org-tempo.el | 115 - lisp/org/testing/lisp/test-org-timer.el | 300 - lisp/org/testing/lisp/test-org.el | 8241 ----------------- lisp/org/testing/lisp/test-ox-publish.el | 558 -- lisp/org/testing/lisp/test-ox.el | 5028 ---------- .../testing/lisp/test-property-inheritance.el | 50 - lisp/org/testing/org-batch-test-init.el | 20 - lisp/org/testing/org-test.el | 491 - lisp/orgit.el | 136 +- lisp/ox-reveal.el | 448 +- lisp/parsebib.el | 717 +- lisp/pdf-tools/README | 706 +- lisp/pdf-tools/build/Makefile | 12 +- lisp/pdf-tools/build/server/autobuild | 60 +- lisp/pdf-tools/build/server/epdfinfo.c | 8 +- lisp/pdf-tools/build/server/install_test.cpp | 7 + lisp/pdf-tools/build/server/synctex_parser.c | 6 +- .../test/docker/templates/arch.Dockerfile.in | 4 +- ....Dockerfile.in => debian-10.Dockerfile.in} | 3 +- ....Dockerfile.in => fedora-32.Dockerfile.in} | 4 +- ....Dockerfile.in => fedora-33.Dockerfile.in} | 4 +- ....Dockerfile.in => fedora-34.Dockerfile.in} | 4 +- .../docker/templates/fedora-35.Dockerfile.in | 3 + .../docker/templates/ubuntu-18.Dockerfile.in | 3 + .../templates/ubuntu-20.10.Dockerfile.in | 3 + .../docker/templates/ubuntu-20.Dockerfile.in | 3 + .../docker/templates/ubuntu-21.Dockerfile.in | 3 + lisp/pdf-tools/pdf-annot.el | 270 +- lisp/pdf-tools/pdf-cache.el | 101 +- lisp/pdf-tools/pdf-dev.el | 10 +- lisp/pdf-tools/pdf-history.el | 16 +- lisp/pdf-tools/pdf-info.el | 149 +- lisp/pdf-tools/pdf-isearch.el | 7 +- lisp/pdf-tools/pdf-links.el | 9 +- lisp/pdf-tools/pdf-macs.el | 51 + lisp/pdf-tools/pdf-misc.el | 51 +- lisp/pdf-tools/pdf-occur.el | 79 +- lisp/pdf-tools/pdf-outline.el | 81 +- lisp/pdf-tools/pdf-sync.el | 65 +- lisp/pdf-tools/pdf-tools-pkg.el | 14 +- lisp/pdf-tools/pdf-tools.el | 40 +- lisp/pdf-tools/pdf-util.el | 228 +- lisp/pdf-tools/pdf-view.el | 153 +- lisp/pdf-tools/pdf-virtual.el | 9 +- lisp/pfuture.el | 96 +- lisp/php-mode/php-align.el | 2 +- lisp/php-mode/php-face.el | 6 +- lisp/php-mode/php-local-manual.el | 190 +- lisp/php-mode/php-mode-debug.el | 2 +- lisp/php-mode/php-mode-pkg.el | 6 +- lisp/php-mode/php-mode.el | 448 +- lisp/php-mode/php-project.el | 5 +- lisp/php-mode/php.el | 255 +- lisp/polymode/polymode-compat.el | 27 +- lisp/polymode/polymode-core.el | 27 +- lisp/polymode/polymode-debug.el | 3 +- lisp/polymode/polymode-methods.el | 4 +- lisp/polymode/polymode-pkg.el | 8 +- lisp/polymode/polymode.el | 8 +- lisp/popup.el | 40 +- lisp/popwin.el | 9 +- lisp/powershell.el | 11 +- lisp/pythonic.el | 8 +- lisp/s.el | 18 +- lisp/spacemacs-theme/spacemacs-common.el | 19 +- lisp/spacemacs-theme/spacemacs-theme-pkg.el | 2 +- lisp/sphinx-doc.el | 108 +- lisp/sql-indent/.github/workflows/main.yml | 22 - lisp/sql-indent/ChangeLog | 998 -- lisp/sql-indent/sql-indent-pkg.el | 2 +- lisp/sql-indent/sql-indent.el | 67 +- lisp/sql-indent/sql-indent.org | 4 +- lisp/systemd/systemd-pkg.el | 10 +- lisp/systemd/systemd.el | 36 +- lisp/transient/transient-pkg.el | 4 +- lisp/transient/transient.el | 1245 ++- lisp/transient/transient.info | 767 +- lisp/treemacs-magit.el | 29 +- lisp/treemacs/Changelog.org | 24 + lisp/treemacs/icons/default/gradle.png | Bin 0 -> 9474 bytes lisp/treemacs/treemacs-async.el | 143 +- lisp/treemacs/treemacs-bookmarks.el | 19 +- lisp/treemacs/treemacs-compatibility.el | 39 +- lisp/treemacs/treemacs-core-utils.el | 277 +- lisp/treemacs/treemacs-customization.el | 243 +- lisp/treemacs/treemacs-diagnostics.el | 11 +- lisp/treemacs/treemacs-dom.el | 18 +- lisp/treemacs/treemacs-extensions.el | 40 +- lisp/treemacs/treemacs-faces.el | 13 +- lisp/treemacs/treemacs-file-management.el | 304 + lisp/treemacs/treemacs-filewatch-mode.el | 37 +- lisp/treemacs/treemacs-find-ignored-files.py | 49 + lisp/treemacs/treemacs-follow-mode.el | 8 +- lisp/treemacs/treemacs-fringe-indicator.el | 7 +- lisp/treemacs/treemacs-header-line.el | 3 +- lisp/treemacs/treemacs-hydras.el | 126 +- lisp/treemacs/treemacs-icons.el | 100 +- lisp/treemacs/treemacs-interface.el | 450 +- lisp/treemacs/treemacs-logging.el | 11 +- lisp/treemacs/treemacs-macros.el | 59 +- lisp/treemacs/treemacs-mode.el | 289 +- lisp/treemacs/treemacs-mouse-interface.el | 65 +- lisp/treemacs/treemacs-peek-mode.el | 149 + lisp/treemacs/treemacs-persistence.el | 20 +- lisp/treemacs/treemacs-pkg.el | 5 +- lisp/treemacs/treemacs-project-follow-mode.el | 121 + lisp/treemacs/treemacs-rendering.el | 258 +- lisp/treemacs/treemacs-scope.el | 18 +- lisp/treemacs/treemacs-tag-follow-mode.el | 91 +- lisp/treemacs/treemacs-tags.el | 25 +- lisp/treemacs/treemacs-themes.el | 5 +- lisp/treemacs/treemacs-visuals.el | 68 +- lisp/treemacs/treemacs-workspaces.el | 103 +- lisp/treemacs/treemacs.el | 116 +- lisp/use-package/use-package-core.el | 57 +- lisp/use-package/use-package-pkg.el | 4 +- lisp/use-package/use-package.info | 2 +- lisp/versions | 228 +- lisp/visual-fill-column.el | 99 +- lisp/web-mode.el | 28 +- lisp/which-key.el | 688 +- lisp/with-editor/with-editor-pkg.el | 7 +- lisp/with-editor/with-editor.el | 115 +- lisp/with-editor/with-editor.info | 95 +- .../snippets/bibtex-mode/.yas-setup.el | 1 + .../snippets/bibtex-mode/mvproceedings | 19 - lisp/yasnippet-snippets/snippets/c++-mode/acl | 8 - .../snippets/c++-mode/d_operator_ostream | 5 - lisp/yasnippet-snippets/snippets/c++-mode/oit | 8 - lisp/yasnippet-snippets/snippets/c++-mode/rmv | 9 - lisp/yasnippet-snippets/snippets/c++-mode/sti | 6 - lisp/yasnippet-snippets/snippets/c++-mode/sto | 6 - lisp/yasnippet-snippets/snippets/c++-mode/stv | 6 - lisp/yasnippet-snippets/snippets/c++-mode/trm | 6 - lisp/yasnippet-snippets/snippets/c++-mode/upr | 9 - lisp/yasnippet-snippets/snippets/cc-mode/do | 3 +- .../snippets/cc-mode/file_description | 2 +- lisp/yasnippet-snippets/snippets/cc-mode/for | 2 +- .../yasnippet-snippets/snippets/cc-mode/for_n | 2 +- lisp/yasnippet-snippets/snippets/cc-mode/if | 4 +- .../snippets/csharp-mode/comment.2 | 3 +- .../snippets/emacs-lisp-mode/.read_me | 8 - .../snippets/emacs-lisp-mode/delete-directory | 2 +- .../snippets/emacs-lisp-mode/find-replace | 18 - .../snippets/emacs-lisp-mode/grabthing | 1 + .../snippets/emacs-lisp-mode/header | 10 +- .../snippets/emacs-lisp-mode/traverse_dir | 7 - .../emacs-lisp-mode/x-dired.process_marked | 18 - .../snippets/emacs-lisp-mode/x-file.process | 19 - .../emacs-lisp-mode/x-file.read-lines | 19 - .../snippets/emacs-lisp-mode/x-find-replace | 19 - .../snippets/emacs-lisp-mode/x-grabstring | 6 - .../snippets/emacs-lisp-mode/x-grabthing | 6 - .../snippets/emacs-lisp-mode/x-traverse_dir | 8 - .../snippets/emacs-lisp-mode/x-word-or-region | 29 - .../snippets/fundamental-mode/current-date | 6 + .../fundamental-mode/current-date-and-time | 5 + .../snippets/html-mode/form | 4 +- .../snippets/html-mode/script.javascript | 4 +- .../snippets/html-mode/script.javascript-src | 4 +- .../yasnippet-snippets/snippets/js-mode/class | 2 +- .../snippets/js-mode/console/clo | 4 +- .../yasnippet-snippets/snippets/js-mode/error | 5 + lisp/yasnippet-snippets/snippets/js-mode/fin | 2 +- lisp/yasnippet-snippets/snippets/js-mode/fof | 2 +- lisp/yasnippet-snippets/snippets/js-mode/fre | 2 +- lisp/yasnippet-snippets/snippets/js-mode/metb | 2 +- lisp/yasnippet-snippets/snippets/js-mode/pge | 2 +- lisp/yasnippet-snippets/snippets/js-mode/pse | 2 +- .../snippets/js-mode/type-multiline-comment | 2 +- .../yasnippet-snippets/snippets/lisp-mode/for | 2 +- .../snippets/lisp-mode/foreach | 2 +- .../snippets/markdown-mode/hyphen | 2 +- .../snippets/markdown-mode/plus | 2 +- .../snippets/nxml-mode/form | 4 +- lisp/yasnippet-snippets/snippets/org-mode/src | 4 +- .../snippets/php-mode/method-doc | 8 - .../snippets/python-mode/assertRaises.with | 4 +- lisp/yasnippet-snippets/snippets/sh-mode/args | 2 +- lisp/yasnippet-snippets/snippets/sh-mode/case | 2 +- .../snippets/sh-mode/select | 2 +- .../snippets/web-mode/.yas-parents | 1 + .../yasnippet-snippets-pkg.el | 14 +- lisp/yasnippet-snippets/yasnippet-snippets.el | 5 +- settings/org-settings.el | 9 +- 700 files changed, 42441 insertions(+), 85378 deletions(-) create mode 100644 lisp/magit/magit-bundle.el delete mode 100644 lisp/magit/magit-section.el create mode 100644 lisp/org-contrib/COPYING create mode 100644 lisp/org-contrib/README.org rename lisp/{org/lisp => org-contrib}/ob-J.el (97%) rename lisp/{org/lisp => org-contrib}/ob-abc.el (93%) rename lisp/{org/contrib/lisp => org-contrib}/ob-arduino.el (79%) rename lisp/{org/lisp => org-contrib}/ob-asymptote.el (96%) rename lisp/{org/contrib/lisp => org-contrib}/ob-clojure-literate.el (95%) rename lisp/{org/lisp => org-contrib}/ob-coq.el (94%) rename lisp/{org/contrib/lisp => org-contrib}/ob-csharp.el (95%) rename lisp/{org/lisp => org-contrib}/ob-ebnf.el (87%) rename lisp/{org/contrib/lisp => org-contrib}/ob-eukleides.el (94%) rename lisp/{org/contrib/lisp => org-contrib}/ob-fomus.el (98%) rename lisp/{org/lisp => org-contrib}/ob-hledger.el (94%) rename lisp/{org/lisp => org-contrib}/ob-io.el (93%) rename lisp/{org/lisp => org-contrib}/ob-ledger.el (90%) rename lisp/{org/contrib/lisp => org-contrib}/ob-mathematica.el (78%) rename lisp/{org/contrib/lisp => org-contrib}/ob-mathomatic.el (97%) rename lisp/{org/lisp => org-contrib}/ob-mscgen.el (90%) rename lisp/{org/contrib/lisp => org-contrib}/ob-oz.el (99%) rename lisp/{org/contrib/lisp => org-contrib}/ob-php.el (59%) rename lisp/{org/lisp => org-contrib}/ob-picolisp.el (93%) rename lisp/{org/contrib/lisp => org-contrib}/ob-redis.el (55%) rename lisp/{org/contrib/lisp => org-contrib}/ob-sclang.el (93%) rename lisp/{org/lisp => org-contrib}/ob-shen.el (96%) create mode 100644 lisp/org-contrib/ob-smiles.el rename lisp/{org/contrib/lisp => org-contrib}/ob-spice.el (96%) rename lisp/{org/lisp => org-contrib}/ob-stan.el (95%) rename lisp/{org/contrib/lisp => org-contrib}/ob-stata.el (99%) rename lisp/{org/contrib/lisp => org-contrib}/ob-tcl.el (96%) rename lisp/{org/lisp => org-contrib}/ob-vala.el (95%) rename lisp/{org/contrib/lisp => org-contrib}/ob-vbnet.el (95%) rename lisp/{org/contrib/lisp => org-contrib}/ol-bookmark.el (96%) rename lisp/{org/contrib/lisp => org-contrib}/ol-elisp-symbol.el (96%) rename lisp/{org/contrib/lisp => org-contrib}/ol-git-link.el (98%) rename lisp/{org/contrib/lisp => org-contrib}/ol-mew.el (99%) rename lisp/{org/contrib/lisp => org-contrib}/ol-notmuch.el (94%) rename lisp/{org/contrib/lisp => org-contrib}/ol-vm.el (96%) rename lisp/{org/contrib/lisp => org-contrib}/ol-wl.el (98%) rename lisp/{org/contrib/lisp => org-contrib}/org-annotate-file.el (98%) rename lisp/{org/contrib/lisp => org-contrib}/org-attach-embedded-images.el (95%) rename lisp/{org/contrib/lisp => org-contrib}/org-bibtex-extras.el (96%) rename lisp/{org/contrib/lisp => org-contrib}/org-checklist.el (97%) rename lisp/{org/contrib/lisp => org-contrib}/org-choose.el (94%) rename lisp/{org/contrib/lisp => org-contrib}/org-collector.el (98%) rename lisp/{org/contrib/lisp => org-contrib}/org-contacts.el (90%) create mode 100644 lisp/org-contrib/org-contrib-pkg.el create mode 100644 lisp/org-contrib/org-contrib.el rename lisp/{org/contrib/lisp => org-contrib}/org-contribdir.el (89%) rename lisp/{org/contrib/lisp => org-contrib}/org-depend.el (98%) rename lisp/{org/contrib/lisp => org-contrib}/org-effectiveness.el (98%) rename lisp/{org/contrib/lisp => org-contrib}/org-eldoc.el (94%) rename lisp/{org/contrib/lisp => org-contrib}/org-eval-light.el (96%) rename lisp/{org/contrib/lisp => org-contrib}/org-eval.el (96%) rename lisp/{org/contrib/lisp => org-contrib}/org-expiry.el (98%) rename lisp/{org/contrib/lisp => org-contrib}/org-interactive-query.el (97%) rename lisp/{org/contrib/lisp => org-contrib}/org-invoice.el (92%) rename lisp/{org/contrib/lisp => org-contrib}/org-learn.el (95%) rename lisp/{org/contrib/lisp => org-contrib}/org-license.el (74%) rename lisp/{org/contrib/lisp => org-contrib}/org-link-edit.el (99%) rename lisp/{org/contrib/lisp => org-contrib}/org-mac-iCal.el (98%) rename lisp/{org/contrib/lisp => org-contrib}/org-mac-link.el (92%) rename lisp/{org/contrib/lisp => org-contrib}/org-mairix.el (99%) rename lisp/{org/contrib/lisp => org-contrib}/org-notify.el (98%) rename lisp/{org/contrib/lisp => org-contrib}/org-panel.el (97%) rename lisp/{org/contrib/lisp => org-contrib}/org-passwords.el (98%) rename lisp/{org/contrib/lisp => org-contrib}/org-registry.el (98%) rename lisp/{org/contrib/lisp => org-contrib}/org-screen.el (92%) rename lisp/{org/contrib/lisp => org-contrib}/org-screenshot.el (99%) rename lisp/{org/contrib/lisp => org-contrib}/org-secretary.el (97%) rename lisp/{org/contrib/lisp => org-contrib}/org-static-mathjax.el (98%) rename lisp/{org/contrib/lisp => org-contrib}/org-sudoku.el (96%) rename lisp/{org/contrib/lisp => org-contrib}/org-toc.el (98%) rename lisp/{org/contrib/lisp => org-contrib}/org-track.el (96%) rename lisp/{org/contrib/lisp => org-contrib}/org-velocity.el (98%) rename lisp/{org/contrib/lisp => org-contrib}/org-wikinodes.el (97%) rename lisp/{org/contrib/lisp => org-contrib}/orgtbl-sqlinsert.el (96%) rename lisp/{org/contrib/lisp => org-contrib}/ox-bibtex.el (98%) rename lisp/{org/contrib/lisp => org-contrib}/ox-confluence.el (98%) rename lisp/{org/contrib/lisp => org-contrib}/ox-deck.el (99%) rename lisp/{org/contrib/lisp => org-contrib}/ox-extra.el (98%) rename lisp/{org/contrib/lisp => org-contrib}/ox-freemind.el (99%) rename lisp/{org/contrib/lisp => org-contrib}/ox-groff.el (99%) rename lisp/{org/contrib/lisp => org-contrib}/ox-rss.el (96%) rename lisp/{org/contrib/lisp => org-contrib}/ox-s5.el (98%) rename lisp/{org/contrib/lisp => org-contrib}/ox-taskjuggler.el (99%) create mode 100644 lisp/org-ref/citeproc/csl-locales/locales-en-US.xml create mode 100644 lisp/org-ref/citeproc/csl-styles/apa-5th-edition.csl create mode 100644 lisp/org-ref/citeproc/csl-styles/apa-numeric-superscript-brackets.csl create mode 100644 lisp/org-ref/citeproc/csl-styles/chicago-author-date-16th-edition.csl create mode 100644 lisp/org-ref/citeproc/csl-styles/elsevier-harvard.csl create mode 100644 lisp/org-ref/citeproc/csl-styles/elsevier-with-titles.csl delete mode 100644 lisp/org-ref/citeproc/csl/acs-nano.csl delete mode 100644 lisp/org-ref/citeproc/csl/author-year.el delete mode 100644 lisp/org-ref/citeproc/csl/unsrt-footnote.el delete mode 100644 lisp/org-ref/citeproc/csl/unsrt-paren.el delete mode 100644 lisp/org-ref/citeproc/csl/unsrt.el delete mode 100644 lisp/org-ref/citeproc/readme-author-year.org delete mode 100644 lisp/org-ref/citeproc/readme-unsrt.org delete mode 100644 lisp/org-ref/citeproc/readme.bib delete mode 100644 lisp/org-ref/citeproc/readme.org create mode 100644 lisp/org-ref/org-ref-bibliography-links.el create mode 100644 lisp/org-ref/org-ref-citation-links.el delete mode 100644 lisp/org-ref/org-ref-citeproc.el create mode 100644 lisp/org-ref/org-ref-export.el delete mode 100644 lisp/org-ref/org-ref-helm-bibtex.el delete mode 100644 lisp/org-ref/org-ref-helm-cite.el delete mode 100644 lisp/org-ref/org-ref-ivy-cite.el create mode 100644 lisp/org-ref/org-ref-label-link.el create mode 100644 lisp/org-ref/org-ref-misc-links.el create mode 100644 lisp/org-ref/org-ref-natbib-bbl-citeproc.el create mode 100644 lisp/org-ref/org-ref-ref-links.el create mode 100644 lisp/org-ref/org-ref-refproc.el delete mode 100644 lisp/org-ref/org-ref-reftex.el create mode 100644 lisp/org/.dir-locals.el create mode 100644 lisp/org/CONTRIBUTE create mode 100644 lisp/org/README_ELPA delete mode 100644 lisp/org/contrib/README delete mode 100644 lisp/org/contrib/lisp/ob-smiles.el delete mode 100644 lisp/org/contrib/scripts/.gitignore delete mode 100644 lisp/org/contrib/scripts/StartOzServer.oz delete mode 100755 lisp/org/contrib/scripts/dir2org.zsh delete mode 100644 lisp/org/contrib/scripts/ditaa.jar delete mode 100644 lisp/org/contrib/scripts/docco.css delete mode 100644 lisp/org/contrib/scripts/org-docco.org delete mode 100755 lisp/org/contrib/scripts/org2hpda delete mode 100644 lisp/org/contrib/scripts/staticmathjax/.gitignore delete mode 100644 lisp/org/contrib/scripts/staticmathjax/README.org delete mode 100644 lisp/org/contrib/scripts/staticmathjax/application.ini delete mode 100644 lisp/org/contrib/scripts/staticmathjax/chrome/chrome.manifest delete mode 100644 lisp/org/contrib/scripts/staticmathjax/chrome/content/main.js delete mode 100644 lisp/org/contrib/scripts/staticmathjax/chrome/content/main.xul delete mode 100644 lisp/org/contrib/scripts/staticmathjax/defaults/preferences/prefs.js delete mode 100644 lisp/org/contrib/scripts/x11idle.c create mode 100644 lisp/org/dir create mode 100644 lisp/org/doc/.aspell.org.conf create mode 100644 lisp/org/doc/.nosearch delete mode 100644 lisp/org/doc/org-version.tex delete mode 100644 lisp/org/doc/org.pdf delete mode 100644 lisp/org/doc/orgcard.pdf delete mode 100644 lisp/org/doc/orgcard_letter.pdf delete mode 100644 lisp/org/doc/orgguide.pdf create mode 100644 lisp/org/etc/csl/README create mode 100644 lisp/org/etc/csl/chicago-author-date.csl create mode 100644 lisp/org/etc/csl/locales-en-US.xml delete mode 100644 lisp/org/etc/schema/od-manifest-schema-v1.2-os.rnc delete mode 100644 lisp/org/etc/schema/od-schema-v1.2-os.rnc delete mode 100644 lisp/org/etc/schema/schemas.xml delete mode 100644 lisp/org/lisp/Makefile delete mode 100644 lisp/org/lisp/ob-comint.el delete mode 100644 lisp/org/lisp/ob-core.el.orig delete mode 100644 lisp/org/lisp/ob-java.el delete mode 100644 lisp/org/lisp/org-install.el delete mode 100644 lisp/org/lisp/org-plot.el create mode 100644 lisp/org/local.mk delete mode 100644 lisp/org/mk/default.mk delete mode 100644 lisp/org/mk/org-fixup.el delete mode 100644 lisp/org/mk/targets.mk delete mode 100644 lisp/org/mk/version.mk rename lisp/org/{lisp => }/ob-C.el (79%) rename lisp/org/{lisp => }/ob-R.el (78%) rename lisp/org/{lisp => }/ob-awk.el (92%) rename lisp/org/{lisp => }/ob-calc.el (96%) rename lisp/org/{lisp => }/ob-clojure.el (98%) create mode 100644 lisp/org/ob-comint.el rename lisp/org/{lisp => }/ob-core.el (97%) rename lisp/org/{lisp => }/ob-css.el (96%) rename lisp/org/{lisp => }/ob-ditaa.el (98%) rename lisp/org/{lisp => }/ob-dot.el (95%) rename lisp/org/{lisp => }/ob-emacs-lisp.el (98%) rename lisp/org/{lisp => }/ob-eshell.el (95%) rename lisp/org/{lisp => }/ob-eval.el (65%) rename lisp/org/{lisp => }/ob-exp.el (94%) rename lisp/org/{lisp => }/ob-forth.el (93%) rename lisp/org/{lisp => }/ob-fortran.el (95%) rename lisp/org/{lisp => }/ob-gnuplot.el (91%) rename lisp/org/{lisp => }/ob-groovy.el (96%) rename lisp/org/{lisp => }/ob-haskell.el (96%) create mode 100644 lisp/org/ob-java.el rename lisp/org/{lisp => }/ob-js.el (98%) rename lisp/org/{contrib/lisp => }/ob-julia.el (56%) rename lisp/org/{lisp => }/ob-latex.el (79%) rename lisp/org/{lisp => }/ob-lilypond.el (93%) rename lisp/org/{lisp => }/ob-lisp.el (97%) rename lisp/org/{lisp => }/ob-lob.el (99%) rename lisp/org/{lisp => }/ob-lua.el (99%) rename lisp/org/{lisp => }/ob-makefile.el (90%) rename lisp/org/{lisp => }/ob-matlab.el (95%) rename lisp/org/{lisp => }/ob-maxima.el (98%) rename lisp/org/{lisp => }/ob-ocaml.el (96%) rename lisp/org/{lisp => }/ob-octave.el (95%) rename lisp/org/{lisp => }/ob-org.el (97%) rename lisp/org/{lisp => }/ob-perl.el (98%) rename lisp/org/{lisp => }/ob-plantuml.el (90%) rename lisp/org/{lisp => }/ob-processing.el (98%) rename lisp/org/{lisp => }/ob-python.el (84%) rename lisp/org/{lisp => }/ob-ref.el (99%) rename lisp/org/{lisp => }/ob-ruby.el (98%) rename lisp/org/{lisp => }/ob-sass.el (95%) rename lisp/org/{lisp => }/ob-scheme.el (98%) rename lisp/org/{lisp => }/ob-screen.el (97%) rename lisp/org/{lisp => }/ob-sed.el (93%) rename lisp/org/{lisp => }/ob-shell.el (99%) rename lisp/org/{lisp => }/ob-sql.el (80%) rename lisp/org/{lisp => }/ob-sqlite.el (86%) rename lisp/org/{lisp => }/ob-table.el (98%) rename lisp/org/{lisp => }/ob-tangle.el (76%) rename lisp/org/{lisp => }/ob.el (95%) create mode 100644 lisp/org/oc-basic.el create mode 100644 lisp/org/oc-biblatex.el create mode 100644 lisp/org/oc-csl.el create mode 100644 lisp/org/oc-natbib.el create mode 100644 lisp/org/oc.el rename lisp/org/{lisp => }/ol-bbdb.el (98%) rename lisp/org/{lisp => }/ol-bibtex.el (96%) rename lisp/org/{lisp => }/ol-docview.el (98%) create mode 100644 lisp/org/ol-doi.el rename lisp/org/{lisp => }/ol-eshell.el (85%) rename lisp/org/{lisp => }/ol-eww.el (99%) rename lisp/org/{lisp => }/ol-gnus.el (97%) rename lisp/org/{lisp => }/ol-info.el (96%) rename lisp/org/{lisp => }/ol-irc.el (97%) rename lisp/org/{contrib/lisp => }/ol-man.el (89%) rename lisp/org/{lisp => }/ol-mhe.el (99%) rename lisp/org/{lisp => }/ol-rmail.el (97%) rename lisp/org/{lisp => }/ol-w3m.el (59%) rename lisp/org/{lisp => }/ol.el (94%) rename lisp/org/{lisp => }/org-agenda.el (93%) rename lisp/org/{lisp => }/org-archive.el (99%) rename lisp/org/{lisp => }/org-attach-git.el (75%) rename lisp/org/{lisp => }/org-attach.el (91%) rename lisp/org/{lisp => }/org-capture.el (90%) rename lisp/org/{lisp => }/org-clock.el (96%) rename lisp/org/{lisp => }/org-colview.el (95%) rename lisp/org/{lisp => }/org-compat.el (85%) rename lisp/org/{lisp => }/org-crypt.el (98%) rename lisp/org/{lisp => }/org-ctags.el (99%) rename lisp/org/{lisp => }/org-datetree.el (97%) rename lisp/org/{lisp => }/org-duration.el (98%) rename lisp/org/{lisp => }/org-element.el (96%) rename lisp/org/{lisp => }/org-entities.el (99%) rename lisp/org/{lisp => }/org-faces.el (90%) rename lisp/org/{lisp => }/org-feed.el (99%) rename lisp/org/{lisp => }/org-footnote.el (98%) rename lisp/org/{lisp => }/org-goto.el (84%) rename lisp/org/{lisp => }/org-habit.el (97%) rename lisp/org/{lisp => }/org-id.el (84%) rename lisp/org/{lisp => }/org-indent.el (92%) rename lisp/org/{lisp => }/org-inlinetask.el (94%) rename lisp/org/{lisp => }/org-keys.el (94%) rename lisp/org/{lisp => }/org-lint.el (93%) rename lisp/org/{lisp => }/org-list.el (95%) rename lisp/org/{lisp => }/org-loaddefs.el (92%) rename lisp/org/{lisp => }/org-macro.el (77%) rename lisp/org/{lisp => }/org-macs.el (92%) rename lisp/org/{lisp => }/org-mobile.el (99%) rename lisp/org/{lisp => }/org-mouse.el (87%) rename lisp/org/{lisp => }/org-num.el (98%) rename lisp/org/{lisp => }/org-pcomplete.el (96%) create mode 100644 lisp/org/org-pkg.el create mode 100644 lisp/org/org-plot.el rename lisp/org/{lisp => }/org-protocol.el (91%) rename lisp/org/{lisp => }/org-refile.el (94%) rename lisp/org/{lisp => }/org-src.el (92%) rename lisp/org/{lisp => }/org-table.el (96%) rename lisp/org/{lisp => }/org-tempo.el (98%) rename lisp/org/{lisp => }/org-timer.el (96%) rename lisp/org/{lisp => }/org-version.el (74%) rename lisp/org/{lisp => }/org.el (95%) rename lisp/org/{doc/org => org.info} (92%) rename lisp/org/{doc/orgguide => orgguide.info} (90%) rename lisp/org/{lisp => }/ox-ascii.el (98%) rename lisp/org/{lisp => }/ox-beamer.el (96%) rename lisp/org/{lisp => }/ox-html.el (94%) rename lisp/org/{lisp => }/ox-icalendar.el (98%) rename lisp/org/{contrib/lisp => }/ox-koma-letter.el (96%) rename lisp/org/{lisp => }/ox-latex.el (94%) rename lisp/org/{lisp => }/ox-man.el (97%) rename lisp/org/{lisp => }/ox-md.el (92%) rename lisp/org/{lisp => }/ox-odt.el (98%) rename lisp/org/{lisp => }/ox-org.el (95%) rename lisp/org/{lisp => }/ox-publish.el (97%) rename lisp/org/{lisp => }/ox-texinfo.el (94%) rename lisp/org/{lisp => }/ox.el (95%) delete mode 100644 lisp/org/testing/README delete mode 100644 lisp/org/testing/examples/agenda-file.org delete mode 100644 lisp/org/testing/examples/att1/fileA delete mode 100644 lisp/org/testing/examples/att1/fileB delete mode 100644 lisp/org/testing/examples/att2/fileC delete mode 100644 lisp/org/testing/examples/att2/fileD delete mode 100644 lisp/org/testing/examples/attachments.org delete mode 100644 lisp/org/testing/examples/babel-dangerous.org delete mode 100644 lisp/org/testing/examples/babel.el delete mode 100644 lisp/org/testing/examples/babel.org delete mode 100644 lisp/org/testing/examples/data/ab/cd123/fileE delete mode 100644 lisp/org/testing/examples/diary-file delete mode 100644 lisp/org/testing/examples/include.html delete mode 100644 lisp/org/testing/examples/include.org delete mode 100644 lisp/org/testing/examples/include2.org delete mode 100644 lisp/org/testing/examples/link-in-heading.org delete mode 100644 lisp/org/testing/examples/links.org delete mode 100644 lisp/org/testing/examples/macro-templates.org delete mode 100644 lisp/org/testing/examples/no-heading.org delete mode 100644 lisp/org/testing/examples/normal.org delete mode 100644 lisp/org/testing/examples/ob-C-test.org delete mode 100644 lisp/org/testing/examples/ob-awk-test.in delete mode 100644 lisp/org/testing/examples/ob-awk-test.org delete mode 100644 lisp/org/testing/examples/ob-fortran-test.org delete mode 100644 lisp/org/testing/examples/ob-header-arg-defaults.org delete mode 100644 lisp/org/testing/examples/ob-lilypond-broken.ly delete mode 100644 lisp/org/testing/examples/ob-lilypond-broken.org delete mode 100644 lisp/org/testing/examples/ob-lilypond-test.error delete mode 100644 lisp/org/testing/examples/ob-lilypond-test.ly delete mode 100644 lisp/org/testing/examples/ob-lilypond-test.org delete mode 100644 lisp/org/testing/examples/ob-maxima-test.org delete mode 100644 lisp/org/testing/examples/ob-octave-test.org delete mode 100644 lisp/org/testing/examples/ob-screen-test.org delete mode 100644 lisp/org/testing/examples/ob-sed-test.org delete mode 100644 lisp/org/testing/examples/ob-shell-test.org delete mode 100644 lisp/org/testing/examples/org-exp.org delete mode 100644 lisp/org/testing/examples/property-inheritance.org delete mode 100644 lisp/org/testing/examples/pub-symlink/link.org delete mode 100644 lisp/org/testing/examples/pub/a.org delete mode 100644 lisp/org/testing/examples/pub/b.org delete mode 100644 lisp/org/testing/examples/pub/file.txt delete mode 120000 lisp/org/testing/examples/pub/link delete mode 100644 lisp/org/testing/examples/pub/noextension delete mode 100644 lisp/org/testing/examples/pub/sub/c.org delete mode 100644 lisp/org/testing/examples/setupfile.org delete mode 100644 lisp/org/testing/examples/setupfile3.org delete mode 100644 lisp/org/testing/examples/subdir/setupfile2.org delete mode 100644 lisp/org/testing/lisp/test-ob-C.el delete mode 100644 lisp/org/testing/lisp/test-ob-R.el delete mode 100644 lisp/org/testing/lisp/test-ob-awk.el delete mode 100644 lisp/org/testing/lisp/test-ob-clojure.el delete mode 100644 lisp/org/testing/lisp/test-ob-emacs-lisp.el delete mode 100644 lisp/org/testing/lisp/test-ob-eshell.el delete mode 100644 lisp/org/testing/lisp/test-ob-exp.el delete mode 100644 lisp/org/testing/lisp/test-ob-fortran.el delete mode 100644 lisp/org/testing/lisp/test-ob-header-arg-defaults.el delete mode 100644 lisp/org/testing/lisp/test-ob-lilypond.el delete mode 100644 lisp/org/testing/lisp/test-ob-lob.el delete mode 100644 lisp/org/testing/lisp/test-ob-lua.el delete mode 100644 lisp/org/testing/lisp/test-ob-maxima.el delete mode 100644 lisp/org/testing/lisp/test-ob-octave.el delete mode 100644 lisp/org/testing/lisp/test-ob-perl.el delete mode 100644 lisp/org/testing/lisp/test-ob-plantuml.el delete mode 100644 lisp/org/testing/lisp/test-ob-python.el delete mode 100644 lisp/org/testing/lisp/test-ob-ruby.el delete mode 100644 lisp/org/testing/lisp/test-ob-scheme.el delete mode 100644 lisp/org/testing/lisp/test-ob-sed.el delete mode 100644 lisp/org/testing/lisp/test-ob-shell.el delete mode 100644 lisp/org/testing/lisp/test-ob-sqlite.el delete mode 100644 lisp/org/testing/lisp/test-ob-table.el delete mode 100644 lisp/org/testing/lisp/test-ob-tangle.el delete mode 100644 lisp/org/testing/lisp/test-ob-vala.el delete mode 100644 lisp/org/testing/lisp/test-ob.el delete mode 100644 lisp/org/testing/lisp/test-ol-bbdb.el delete mode 100644 lisp/org/testing/lisp/test-ol.el delete mode 100644 lisp/org/testing/lisp/test-org-agenda.el delete mode 100644 lisp/org/testing/lisp/test-org-archive.el delete mode 100644 lisp/org/testing/lisp/test-org-attach-git.el delete mode 100644 lisp/org/testing/lisp/test-org-attach.el delete mode 100644 lisp/org/testing/lisp/test-org-capture.el delete mode 100644 lisp/org/testing/lisp/test-org-clock.el delete mode 100644 lisp/org/testing/lisp/test-org-colview.el delete mode 100644 lisp/org/testing/lisp/test-org-datetree.el delete mode 100644 lisp/org/testing/lisp/test-org-duration.el delete mode 100644 lisp/org/testing/lisp/test-org-element.el delete mode 100644 lisp/org/testing/lisp/test-org-feed.el delete mode 100644 lisp/org/testing/lisp/test-org-footnote.el delete mode 100644 lisp/org/testing/lisp/test-org-info.el delete mode 100644 lisp/org/testing/lisp/test-org-inlinetask.el delete mode 100644 lisp/org/testing/lisp/test-org-lint.el delete mode 100644 lisp/org/testing/lisp/test-org-list.el delete mode 100644 lisp/org/testing/lisp/test-org-macro.el delete mode 100644 lisp/org/testing/lisp/test-org-macs.el delete mode 100644 lisp/org/testing/lisp/test-org-num.el delete mode 100644 lisp/org/testing/lisp/test-org-pcomplete.el delete mode 100644 lisp/org/testing/lisp/test-org-protocol.el delete mode 100644 lisp/org/testing/lisp/test-org-src.el delete mode 100644 lisp/org/testing/lisp/test-org-table.el delete mode 100644 lisp/org/testing/lisp/test-org-tempo.el delete mode 100644 lisp/org/testing/lisp/test-org-timer.el delete mode 100644 lisp/org/testing/lisp/test-org.el delete mode 100644 lisp/org/testing/lisp/test-ox-publish.el delete mode 100644 lisp/org/testing/lisp/test-ox.el delete mode 100644 lisp/org/testing/lisp/test-property-inheritance.el delete mode 100644 lisp/org/testing/org-batch-test-init.el delete mode 100644 lisp/org/testing/org-test.el create mode 100644 lisp/pdf-tools/build/server/install_test.cpp rename lisp/pdf-tools/build/server/test/docker/templates/{ubuntu-17.Dockerfile.in => debian-10.Dockerfile.in} (82%) rename lisp/pdf-tools/build/server/test/docker/templates/{fedora-24.Dockerfile.in => fedora-32.Dockerfile.in} (83%) rename lisp/pdf-tools/build/server/test/docker/templates/{fedora-25.Dockerfile.in => fedora-33.Dockerfile.in} (83%) rename lisp/pdf-tools/build/server/test/docker/templates/{fedora-26.Dockerfile.in => fedora-34.Dockerfile.in} (83%) create mode 100644 lisp/pdf-tools/build/server/test/docker/templates/fedora-35.Dockerfile.in create mode 100644 lisp/pdf-tools/build/server/test/docker/templates/ubuntu-18.Dockerfile.in create mode 100644 lisp/pdf-tools/build/server/test/docker/templates/ubuntu-20.10.Dockerfile.in create mode 100644 lisp/pdf-tools/build/server/test/docker/templates/ubuntu-20.Dockerfile.in create mode 100644 lisp/pdf-tools/build/server/test/docker/templates/ubuntu-21.Dockerfile.in create mode 100644 lisp/pdf-tools/pdf-macs.el delete mode 100644 lisp/sql-indent/.github/workflows/main.yml delete mode 100644 lisp/sql-indent/ChangeLog create mode 100644 lisp/treemacs/icons/default/gradle.png create mode 100644 lisp/treemacs/treemacs-file-management.el create mode 100644 lisp/treemacs/treemacs-find-ignored-files.py create mode 100644 lisp/treemacs/treemacs-peek-mode.el create mode 100644 lisp/treemacs/treemacs-project-follow-mode.el delete mode 100644 lisp/yasnippet-snippets/snippets/bibtex-mode/mvproceedings delete mode 100644 lisp/yasnippet-snippets/snippets/c++-mode/acl delete mode 100644 lisp/yasnippet-snippets/snippets/c++-mode/d_operator_ostream delete mode 100644 lisp/yasnippet-snippets/snippets/c++-mode/oit delete mode 100644 lisp/yasnippet-snippets/snippets/c++-mode/rmv delete mode 100644 lisp/yasnippet-snippets/snippets/c++-mode/sti delete mode 100644 lisp/yasnippet-snippets/snippets/c++-mode/sto delete mode 100644 lisp/yasnippet-snippets/snippets/c++-mode/stv delete mode 100644 lisp/yasnippet-snippets/snippets/c++-mode/trm delete mode 100644 lisp/yasnippet-snippets/snippets/c++-mode/upr delete mode 100644 lisp/yasnippet-snippets/snippets/emacs-lisp-mode/.read_me delete mode 100644 lisp/yasnippet-snippets/snippets/emacs-lisp-mode/find-replace delete mode 100644 lisp/yasnippet-snippets/snippets/emacs-lisp-mode/traverse_dir delete mode 100644 lisp/yasnippet-snippets/snippets/emacs-lisp-mode/x-dired.process_marked delete mode 100644 lisp/yasnippet-snippets/snippets/emacs-lisp-mode/x-file.process delete mode 100644 lisp/yasnippet-snippets/snippets/emacs-lisp-mode/x-file.read-lines delete mode 100644 lisp/yasnippet-snippets/snippets/emacs-lisp-mode/x-find-replace delete mode 100644 lisp/yasnippet-snippets/snippets/emacs-lisp-mode/x-grabstring delete mode 100644 lisp/yasnippet-snippets/snippets/emacs-lisp-mode/x-grabthing delete mode 100644 lisp/yasnippet-snippets/snippets/emacs-lisp-mode/x-traverse_dir delete mode 100644 lisp/yasnippet-snippets/snippets/emacs-lisp-mode/x-word-or-region create mode 100644 lisp/yasnippet-snippets/snippets/fundamental-mode/current-date create mode 100644 lisp/yasnippet-snippets/snippets/fundamental-mode/current-date-and-time create mode 100644 lisp/yasnippet-snippets/snippets/js-mode/error delete mode 100644 lisp/yasnippet-snippets/snippets/php-mode/method-doc diff --git a/lisp/gnuplot/gnuplot-context.el b/lisp/gnuplot/gnuplot-context.el index 8911003e..67f15b0a 100644 --- a/lisp/gnuplot/gnuplot-context.el +++ b/lisp/gnuplot/gnuplot-context.el @@ -1,4 +1,4 @@ -;;; gnuplot-context.el -- context-sensitive help and completion for gnuplot +;;; gnuplot-context.el -- context-sensitive help and completion for gnuplot -*- lexical-binding: t -*- ;; Copyright (C) 2012-2013 Jon Oddie @@ -1721,9 +1721,9 @@ 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 args) "No-op." '(progn nil)) - (defmacro gnuplot-trace (&rest args) "No-op." '(progn nil)) - (defmacro gnuplot-debug (&rest args) "No-op." '(progn nil)))) + (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)))) @@ -1755,6 +1755,12 @@ name specified in the (capture NAME PATTERN) form in the 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. + +These have to be compiled from the Gnuplot source tree using +`doc2texi.el'.") + ;;;; The pattern matching machine (defun gnuplot-match-pattern (instructions tokens completing-p @@ -1984,7 +1990,7 @@ there." (defun gnuplot-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)) + (gnuplot-debug (gnuplot-backtrace stack)) (gnuplot-debug (gnuplot-dump-captures)) (catch 'no-scan @@ -2054,23 +2060,11 @@ there." (defun gnuplot-context-completion-at-point () "Return completions of keyword preceding point, using context." - (let* ((end (point)) - (beg - (save-excursion - (skip-syntax-backward "w_" (gnuplot-point-at-beginning-of-command)) - (point))) - (word nil) - (completions (gnuplot-completions))) - - (setq word (buffer-substring beg end) - completions (all-completions word completions)) - - (if completions - (list beg end completions) - (if (not (equal "" word)) - (message "No gnuplot keywords complete '%s'" word) - (message "No completions at point")) - nil))) + (list (save-excursion + (skip-syntax-backward "w_" (gnuplot-point-at-beginning-of-command)) + (point)) + (point) + (gnuplot-completions))) ;; Eldoc help (defun gnuplot-eldoc-function () @@ -2192,6 +2186,80 @@ command." nil))) +;;;###autoload +(define-minor-mode gnuplot-context-sensitive-mode + "Use context-sensitive completion and help in gnuplot-mode. + +When context-sensitive mode is enabled, gnuplot-mode tries to +provide more useful completions and help suggestions for built-in +keywords and functions by parsing each command as you type. It +attempts to take into account Gnuplot's many abbreviated +keywords. For example, with point at the end of a line reading +\"plot 'datafile' w \", typing \\[completion-at-point] will pop +up a list of plotting styles. + +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. + +\\[gnuplot-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 +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'. + +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." + :keymap + `((,(kbd "C-c C-/") . gnuplot-help-function) + (,(kbd "C-c C-d") . gnuplot-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) + + ;; 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) diff --git a/lisp/gnuplot/gnuplot-gui.el b/lisp/gnuplot/gnuplot-gui.el index 45020a99..061284e9 100644 --- a/lisp/gnuplot/gnuplot-gui.el +++ b/lisp/gnuplot/gnuplot-gui.el @@ -1,4 +1,4 @@ -;;;; gnuplot-gui.el -- GUI interface to setting options in gnuplot-mode +;;;; gnuplot-gui.el -- GUI interface to setting options in gnuplot-mode -*- lexical-binding: t -*- ;; Copyright (C) 1998-2000 Bruce Ravel @@ -58,37 +58,9 @@ ;;; Code: (require 'gnuplot) -(eval-and-compile - (condition-case () - (progn - (require 'widget) - (require 'wid-edit)) - (error nil))) +(require 'widget) +(require 'wid-edit) (require 'cl-lib) -(eval-when-compile ; suppress some compiler warnings - (defvar gnuplot-quote-character nil) - (defvar gnuplot-info-display nil) - (defvar gnuplot-mode-map nil)) - -;; (eval-when-compile -;; (require 'wid-edit)) - -(eval-and-compile ; I need this! - (if (fboundp 'split-string) - () - (defun split-string (string &optional pattern) - "Return a list of substrings of STRING which are separated by PATTERN. -If PATTERN is omitted, it defaults to \"[ \\f\\t\\n\\r\\v]+\"." - (or pattern - (setq pattern "[ \f\t\n\r\v]+")) - ;; The FSF version of this function takes care not to cons in case - ;; of infloop. Maybe we should synch? - (let (parts (start 0)) - (while (string-match pattern string start) - (setq parts (cons (substring string start (match-beginning 0)) parts) - start (match-end 0))) - (nreverse (cons (substring string start) parts)))) )) - ;;; customizable variables @@ -833,6 +805,7 @@ This alist is formed at load time by appending together gnuplot-gui-test-type)) +;;;###autoload (defun gnuplot-gui-swap-simple-complete () (interactive) (setq gnuplot-gui-plot-splot-fit-style @@ -854,16 +827,16 @@ This alist is formed at load time by appending together ;;; user interface to the widget-y stuff +;;;###autoload (defun gnuplot-gui-mouse-set (event) "Use the mouse to begin setting options using a GUI interface. EVENT is a mouse event. Bound to \\[gnuplot-gui-mouse-set] Note that \"plot\", \"splot\", \"fit\", and \"cntrparam\" are not currently supported." (interactive "@e") - (when (fboundp 'widget-create) - (save-excursion - (mouse-set-point event) - (gnuplot-gui-set-options-and-insert)))) + (save-excursion + (mouse-set-point event) + (gnuplot-gui-set-options-and-insert))) (defun gnuplot-gui-get-frame-param (param) (cdr (assoc param gnuplot-gui-frame-parameters))) @@ -871,88 +844,89 @@ currently supported." (defun gnuplot-gui-set-frame-param (param value) (setcdr (assoc param gnuplot-gui-frame-parameters) value)) +;;;###autoload (defun gnuplot-gui-set-options-and-insert () "Insert arguments using a GUI interface. Determine contents of current line and set up the appropriate GUI frame. Bound to \\[gnuplot-gui-set-options-and-insert] Note that \"cntrparam\" is not currently supported." (interactive) - (when (fboundp 'widget-create) - (let ((begin (gnuplot-point-at-beginning-of-command)) - (end (save-excursion (end-of-line) (point-marker))) - (termin (concat "\\(,\\s-*" (regexp-quote "\\") "\\|;\\)")) - (set nil) (term nil)) - (save-excursion - ;; there can be more then one command per line - (if (re-search-forward termin end "to_limit") - (progn (backward-char (length (match-string 1))) - (setq end (point-marker)))) - (goto-char begin) - (skip-syntax-forward "-" end) - ;; various constructions are recognized here. at the end of this - ;; cond, point should be just after the word whose arguments are - ;; to be set - (cond ((looking-at "set\\s-+") - (setq set t) - (goto-char (match-end 0)) - (if (looking-at "\\sw+") (goto-char (match-end 0))) - (when (string-match "^ter" (gnuplot-this-word)) ; terminal? - (setq term t) - (forward-word 1)) - (when (string-match "^\\(da\\|fu\\)" (gnuplot-this-word)) - (unless (looking-at "\\s-+st") - (insert " style") (forward-word 1)) - (forward-word 1))) - ((looking-at (concat "\\(cd\\|ca\\|lo\\|pa\\|pr\\|sa\\|u\\)" - "\\w*" - "[\\s-\\']")) + (let ((begin (gnuplot-point-at-beginning-of-command)) + (end (save-excursion (end-of-line) (point-marker))) + (termin (concat "\\(,\\s-*" (regexp-quote "\\") "\\|;\\)")) + (set nil) (term nil)) + (save-excursion + ;; there can be more then one command per line + (if (re-search-forward termin end "to_limit") + (progn (backward-char (length (match-string 1))) + (setq end (point-marker)))) + (goto-char begin) + (skip-syntax-forward "-" end) + ;; various constructions are recognized here. at the end of this + ;; cond, point should be just after the word whose arguments are + ;; to be set + (cond ((looking-at "set\\s-+") + (setq set t) + (goto-char (match-end 0)) + (if (looking-at "\\sw+") (goto-char (match-end 0))) + (when (string-match "^ter" (gnuplot-this-word)) ; terminal? + (setq term t) (forward-word 1)) - ;;(goto-char (match-end 0))) - (t + (when (string-match "^\\(da\\|fu\\)" (gnuplot-this-word)) + (unless (looking-at "\\s-+st") + (insert " style") (forward-word 1)) (forward-word 1))) - (if (> (point) end) (goto-char end)) - (let* ((w (gnuplot-this-word)) - (wd (try-completion w gnuplot-gui-all-types)) - (word "") wrd list) - (cond ((equal wd t) (setq word w)) - ((equal wd nil) (setq word w)) - ((assoc wd gnuplot-gui-all-types) (setq word wd)) - (t (setq wd nil))) - (cond ((equal (string-match "^\\s-*$" w) 0) - (message "Blank line")) - ((and wd (stringp word)) - (gnuplot-gui-correct-command word set term begin) - (setq gnuplot-gui-alist nil - gnuplot-gui-current-string - (buffer-substring-no-properties (point) end)) - (gnuplot-gui-set-alist word gnuplot-gui-current-string) - (let* ((old-height (gnuplot-gui-get-frame-param 'height)) - (old-top (gnuplot-gui-get-frame-param 'top))) - (when (or - (and (equal gnuplot-gui-plot-splot-fit-style 'complete) - (cl-member word '("plot" "splot" "fit") + ((looking-at (concat "\\(cd\\|ca\\|lo\\|pa\\|pr\\|sa\\|u\\)" + "\\w*" + "[\\s-\\']")) + (forward-word 1)) + ;;(goto-char (match-end 0))) + (t + (forward-word 1))) + (if (> (point) end) (goto-char end)) + (let* ((w (gnuplot-this-word)) + (wd (try-completion w gnuplot-gui-all-types)) + (word "") wrd list) + (cond ((equal wd t) (setq word w)) + ((equal wd nil) (setq word w)) + ((assoc wd gnuplot-gui-all-types) (setq word wd)) + (t (setq wd nil))) + (cond ((equal (string-match "^\\s-*$" w) 0) + (message "Blank line")) + ((and wd (stringp word)) + (gnuplot-gui-correct-command word set term begin) + (setq gnuplot-gui-alist nil + gnuplot-gui-current-string + (buffer-substring-no-properties (point) end)) + (gnuplot-gui-set-alist word gnuplot-gui-current-string) + (let* ((old-height (gnuplot-gui-get-frame-param 'height)) + (old-top (gnuplot-gui-get-frame-param 'top))) + (when (or + (and (equal gnuplot-gui-plot-splot-fit-style 'complete) + (cl-member word '("plot" "splot" "fit") :test 'string=)) - (equal word "test")) - (gnuplot-gui-set-frame-param 'height 32) - (gnuplot-gui-set-frame-param 'top 50)) - (gnuplot-gui-prompt-for-frame word) - (when (or - (and (equal gnuplot-gui-plot-splot-fit-style 'complete) - (cl-member word '("plot" "splot" "fit") + (equal word "test")) + (gnuplot-gui-set-frame-param 'height 32) + (gnuplot-gui-set-frame-param 'top 50)) + (gnuplot-gui-prompt-for-frame word) + (when (or + (and (equal gnuplot-gui-plot-splot-fit-style 'complete) + (cl-member word '("plot" "splot" "fit") :test 'string=)) - (equal word "test")) - (gnuplot-gui-set-frame-param 'height old-height) - (gnuplot-gui-set-frame-param 'top old-top)) )) - ((setq wrd (car (all-completions w '(("cntrparam"))))) - (message - "Setting arguments for %S is currently unsuported in gnuplot-mode" - wrd)) - ((setq list (all-completions w gnuplot-gui-all-types)) - (message "%S could be one of %S" w list)) - (t - (message - "%S is not a gnuplot command which takes options" w)))) )))) + (equal word "test")) + (gnuplot-gui-set-frame-param 'height old-height) + (gnuplot-gui-set-frame-param 'top old-top)) )) + ((setq wrd (car (all-completions w '(("cntrparam"))))) + (message + "Setting arguments for %S is currently unsuported in gnuplot-mode" + wrd)) + ((setq list (all-completions w gnuplot-gui-all-types)) + (message "%S could be one of %S" w list)) + (t + (message + "%S is not a gnuplot command which takes options" w)))) ))) +;;;###autoload (defun gnuplot-gui-toggle-popup () (interactive) (setq gnuplot-gui-popup-flag (not gnuplot-gui-popup-flag)) @@ -961,7 +935,6 @@ Note that \"cntrparam\" is not currently supported." "Argument popup will no longer appear after insertions."))) -(defun gnuplot-gui-y-n (foo)) (defalias 'gnuplot-gui-y-n 'y-or-n-p) (defun gnuplot-gui-correct-command (word set term begin) @@ -1342,7 +1315,7 @@ SAVE-FRAME is non-nil when the widgets are being reset." :button-face 'gnuplot-gui-button-face :help-echo "Push this button to set options" :notify - (lambda (widget &rest ignore) + (lambda (widget &rest _ignore) (kill-buffer (get-buffer-create "*Gnuplot GUI*")) (delete-frame) (select-frame gnuplot-current-frame) @@ -1382,7 +1355,7 @@ SAVE-FRAME is non-nil when the widgets are being reset." :button-face 'gnuplot-gui-button-face :doc item :notify - (lambda (widget &rest ignore) + (lambda (widget &rest _ignore) (let ((word (widget-get widget :doc))) (gnuplot-gui-set-alist word gnuplot-gui-current-string) (gnuplot-gui-prompt-for-frame word t)))) @@ -1392,7 +1365,7 @@ SAVE-FRAME is non-nil when the widgets are being reset." :button-face 'gnuplot-gui-button-face :doc item :notify - (lambda (widget &rest ignore) + (lambda (widget &rest _ignore) (let* ((word (widget-get widget :doc)) (alist (cdr (assoc word gnuplot-gui-all-types)))) (while alist @@ -1405,7 +1378,7 @@ SAVE-FRAME is non-nil when the widgets are being reset." (widget-create 'push-button :value "Cancel" :help-echo "Quit setting options and dismiss frame" :button-face 'gnuplot-gui-button-face - :notify (lambda (widget &rest ignore) + :notify (lambda (_widget &rest _ignore) (kill-buffer (get-buffer-create "*Gnuplot GUI*")) (setq gnuplot-gui-alist nil gnuplot-gui-current-string nil) @@ -1455,7 +1428,7 @@ menu. STARRED is true if this a 'list* widget." :button-prefix "[" :button-suffix "]" :help-echo (format "Mouse-2 to view the %S menu" (downcase item)) :notify - (lambda (widget &rest ignore) + (lambda (widget &rest _ignore) (let ((lab (if (widget-get widget :doc) (concat (downcase (widget-get widget :tag)) " ") "" ))) @@ -1480,7 +1453,7 @@ the numerical argument." (widget-create 'editable-field :size 2 :tag item :value default :doc prefix :help-echo (format "Insert new value of %S here" help-label) - :notify (lambda (widget &rest ignore) + :notify (lambda (widget &rest _ignore) (let ((val (widget-value widget)) (pre (concat (widget-get widget :doc) " "))) (setcdr (assoc (widget-get widget :tag) @@ -1516,7 +1489,7 @@ prefix for the string. STARRED is t if quotes are not to be used." 'editable-field :size width :tag item :doc prefix :value default :help-echo (format "Insert new value of %S here" help-label) - :notify (lambda (widget &rest ignore) + :notify (lambda (widget &rest _ignore) (let ((val (widget-value widget)) (q gnuplot-quote-character) (p (widget-get widget :doc)) ) @@ -1550,7 +1523,7 @@ prefix for the string." (widget-create 'editable-field :size (/ (frame-width) 3) :tag item :value default :help-echo (format "Insert new format string here") - :notify (lambda (widget &rest ignore) + :notify (lambda (widget &rest _ignore) (let ((val (widget-value widget))) (setcdr (assoc (widget-get widget :tag) gnuplot-gui-alist) @@ -1604,7 +1577,7 @@ the default value for the argument. TAG is non-nil if ITEM rather than :doc item :help-echo "Insert a filename here" :complete 'gnuplot-gui-file-completion :notify - (lambda (widget &rest ignore) + (lambda (widget &rest _ignore) (setcdr (assoc (widget-get widget :doc) gnuplot-gui-alist) (format "%s%s%s" gnuplot-quote-character (widget-value widget) @@ -1614,7 +1587,7 @@ the default value for the argument. TAG is non-nil if ITEM rather than 'push-button :value "Browse" :doc item :help-echo "Browse directories for a filename." :parent widg - :notify (lambda (widget &rest ignore) + :notify (lambda (widget &rest _ignore) (let ((fname (file-relative-name (read-file-name "File: ") default-directory)) (q gnuplot-quote-character)) @@ -1640,7 +1613,7 @@ the default value for the argument." :format "%{%t%}:\n%v\t %i\n" :entry-format "\t %i %d %v\n" :button-face 'gnuplot-gui-labels-face - :notify (lambda (widget &rest ignore) + :notify (lambda (widget &rest _ignore) (setcdr (assoc (upcase (widget-get widget :tag)) gnuplot-gui-alist) (widget-value widget))))) @@ -1657,7 +1630,7 @@ is non-nil if this is a 'range widget." :size 4 :tag item :value (car default) :help-echo (format "Insert the first value of the %S here" (downcase item)) - :notify (lambda (widget &rest ignore) + :notify (lambda (widget &rest _ignore) (setcar (cdr (assoc (widget-get widget :tag) gnuplot-gui-alist)) (format "%s" (widget-value widget))))) @@ -1666,7 +1639,7 @@ is non-nil if this is a 'range widget." :size 4 :tag item :value (cdr default) :help-echo (format "Insert the second value of the %S here" (downcase item)) - :notify (lambda (widget &rest ignore) + :notify (lambda (widget &rest _ignore) (setcdr (cdr (assoc (widget-get widget :tag) gnuplot-gui-alist)) (format "%s" (widget-value widget))))) diff --git a/lisp/gnuplot/gnuplot-pkg.el b/lisp/gnuplot/gnuplot-pkg.el index f2b8d44c..24bc4981 100644 --- a/lisp/gnuplot/gnuplot-pkg.el +++ b/lisp/gnuplot/gnuplot-pkg.el @@ -1,6 +1,6 @@ -(define-package "gnuplot" "20210104.1052" "Major-mode and interactive frontend for gnuplot" +(define-package "gnuplot" "20220102.1637" "Major-mode and interactive frontend for gnuplot" '((emacs "24.3")) - :commit "116cad8e09024223f97e81b0a4503cef20de9bf5" :authors + :commit "d1a6a606dcb389a7c91a6b0d9fb995434df561be" :authors '(("Jon Oddie") ("Bruce Ravel") ("Phil Type")) diff --git a/lisp/gnuplot/gnuplot.el b/lisp/gnuplot/gnuplot.el index 5345b26f..a7d48652 100644 --- a/lisp/gnuplot/gnuplot.el +++ b/lisp/gnuplot/gnuplot.el @@ -1,4 +1,4 @@ -;;; gnuplot.el --- Major-mode and interactive frontend for gnuplot +;;; gnuplot.el --- Major-mode and interactive frontend for gnuplot -*- lexical-binding: t -*- ;; Copyright (C) 1998, 2011 Phil Type and Bruce Ravel, 1999-2012 Bruce Ravel @@ -114,12 +114,13 @@ :group 'gnuplot-hooks :type 'hook) -(defcustom gnuplot-load-hook nil - "Hook run when gnuplot.el is first loaded." - :group 'gnuplot-hooks - :type 'hook) +(defvar gnuplot-load-hook nil) +(make-obsolete-variable + 'gnuplot-load-hook + "The package loading hook has been removed, use `with-eval-after-load' instead." + "8.0") -(defcustom gnuplot-after-plot-hook nil +(defcustom gnuplot-after-plot-hook (list #'gnuplot-trim-gnuplot-buffer) "Hook run after gnuplot plots something. This is the last thing done by the functions for plotting a line, a region, a buffer, or a file." @@ -184,11 +185,10 @@ for backward compatibility." :group 'gnuplot-hooks :type 'hook) -(defvar gnuplot-recently-sent nil +(defvar-local gnuplot-recently-sent nil "This is a record of the most recent kind of text sent to gnuplot. It takes as its value nil, 'line, 'region, 'buffer, or 'file. It is useful for functions included in `gnuplot-after-plot-hook'.") -(make-variable-buffer-local 'gnuplot-recently-sent) (defcustom gnuplot-program "gnuplot" "The name of the gnuplot executable." @@ -304,9 +304,6 @@ beginning the continued command." :type 'integer) (defvar gnuplot-info-frame nil) -(defvar gnuplot-info-nodes '()) - -(defvar gnuplot-first-call t) ;; with info-look, there is no need to carry this list around -- it ;; can be generated on the fly appropriate to the currently installed @@ -315,7 +312,6 @@ beginning the continued command." "A list of keywords used in GNUPLOT. These are set by `gnuplot-set-keywords-list' from the values in `info-lookup-cache'.") -(defvar gnuplot-keywords-alist nil) ;; For all-completions (defvar gnuplot-keywords-pending t ;; "A boolean which gets toggled when the info file is probed.") (defcustom gnuplot-keywords-when 'deferred ;; 'immediately @@ -335,13 +331,20 @@ command line to provide smarter completion and documentation suggestions." :group 'gnuplot :type 'boolean - :initialize 'custom-set-default :set (lambda (sym value) + (set sym value) + (cond + (value + (add-hook 'gnuplot-mode-hook 'gnuplot-context-sensitive-mode nil nil) + (add-hook 'gnuplot-comint-mode-hook 'gnuplot-context-sensitive-mode nil nil)) + (t + (remove-hook 'gnuplot-mode-hook 'gnuplot-context-sensitive-mode) + (remove-hook 'gnuplot-comint-mode-hook 'gnuplot-context-sensitive-mode))) (dolist (buffer (buffer-list)) (with-current-buffer buffer - (when (derived-mode-p 'gnuplot-mode 'gnuplot-comint-mode) - (gnuplot-context-sensitive-mode - (if value 1 0)))))) + (when (and (derived-mode-p 'gnuplot-mode 'gnuplot-comint-mode) + (fboundp 'gnuplot-context-sensitive-mode)) + (gnuplot-context-sensitive-mode (if value 1 0)))))) :link '(emacs-commentary-link "gnuplot-context")) (defcustom gnuplot-eldoc-mode nil @@ -359,12 +362,12 @@ symbol `complete' in gnuplot-mode buffers." :group 'gnuplot :type 'boolean) -(defun gnuplot-set-display-mode (variable value &rest args) +(defun gnuplot-set-display-mode (variable value &rest _args) "Customize :set function for `gnuplot-inline-image-mode'. Set VARIABLE to VALUE. ARGS is optional args." (if (and (eq variable 'gnuplot-inline-image-mode) value - (not (gnuplot-display-images-p))) + (not (display-images-p))) (progn (message "Displaying images is not supported.") (set variable nil)) @@ -390,8 +393,8 @@ and `gnuplot-dedicated-display-mode'." (const :tag "No" nil) (const :tag "In Comint buffer" inline) (const :tag "In dedicated buffer" dedicated)) - :initialize 'custom-initialize-default - :set 'gnuplot-set-display-mode) + :initialize #'custom-initialize-default + :set #'gnuplot-set-display-mode) (defcustom gnuplot-image-format "png" "Image format to use for displaying images within Emacs. @@ -404,8 +407,8 @@ This only has an effect when `gnuplot-inline-image-mode' is non-nil." :group 'gnuplot :type 'string - :initialize 'custom-initialize-default - :set 'gnuplot-set-display-mode) + :initialize #'custom-initialize-default + :set #'gnuplot-set-display-mode) (defgroup gnuplot-faces nil "Text faces used by gnuplot-mode." @@ -424,27 +427,26 @@ non-nil." (defvar gnuplot-mode-map (let ((map (make-sparse-keymap))) - (define-key map "\C-c\C-b" 'gnuplot-send-buffer-to-gnuplot) - (define-key map "\C-c\C-c" 'comment-region) ; + (define-key map "\C-c\C-b" #'gnuplot-send-buffer-to-gnuplot) + (define-key map "\C-c\C-c" #'comment-region) ; (define-key map "\C-c\C-o" 'gnuplot-gui-set-options-and-insert) - (define-key map "\C-c\C-e" 'gnuplot-show-gnuplot-buffer) - (define-key map "\C-c\C-f" 'gnuplot-send-file-to-gnuplot) - (define-key map "\C-c\C-d" 'gnuplot-info-lookup-symbol) - (define-key map "\C-c\C-i" 'gnuplot-insert-filename) - (define-key map "\C-c\C-j" 'gnuplot-forward-script-line) - (define-key map "\C-c\C-k" 'gnuplot-kill-gnuplot-buffer) - (define-key map "\C-c\C-l" 'gnuplot-send-line-to-gnuplot) - (define-key map "\C-c\C-n" 'gnuplot-negate-option) - (define-key map "\C-c\C-r" 'gnuplot-send-region-to-gnuplot) - (define-key map (kbd "C-M-x") 'gnuplot-send-line-to-gnuplot) - (define-key map "\C-c\C-v" 'gnuplot-send-line-and-forward) - (define-key map "\C-c\C-z" 'gnuplot-customize) - (define-key map "\C-i" 'indent-for-tab-command) - (define-key map "\C-m" 'newline-and-indent) - (define-key map "\C-c\M-i" 'gnuplot-inline-image-mode) - (define-key map (kbd "}") 'gnuplot-electric-insert) - (define-key map "\M-\r" 'completion-at-point) - (define-key map "\M-\t" 'completion-at-point) + (define-key map "\C-c\C-e" #'gnuplot-show-gnuplot-buffer) + (define-key map "\C-c\C-f" #'gnuplot-send-file-to-gnuplot) + (define-key map "\C-c\C-d" #'gnuplot-info-lookup-symbol) + (define-key map "\C-c\C-i" #'gnuplot-insert-filename) + (define-key map "\C-c\C-j" #'gnuplot-forward-script-line) + (define-key map "\C-c\C-k" #'gnuplot-kill-gnuplot-buffer) + (define-key map "\C-c\C-l" #'gnuplot-send-line-to-gnuplot) + (define-key map "\C-c\C-n" #'gnuplot-negate-option) + (define-key map "\C-c\C-r" #'gnuplot-send-region-to-gnuplot) + (define-key map (kbd "C-M-x") #'gnuplot-send-line-to-gnuplot) + (define-key map "\C-c\C-v" #'gnuplot-send-line-and-forward) + (define-key map "\C-c\C-z" #'gnuplot-customize) + (define-key map "\C-i" #'indent-for-tab-command) + (define-key map "\C-m" #'newline-and-indent) + (define-key map (kbd "}") #'gnuplot-electric-insert) + (define-key map "\M-\r" #'completion-at-point) + (define-key map "\M-\t" #'completion-at-point) (define-key map [S-mouse-2] 'gnuplot-gui-mouse-set) map)) @@ -462,7 +464,7 @@ non-nil." :style toggle :selected (null gnuplot-inline-image-mode)] ["In Comint buffer" gnuplot-inline-display-mode - :active (gnuplot-display-images-p) + :active (display-images-p) :style toggle :selected (eq gnuplot-inline-image-mode 'comint)] ["In dedicated buffer" gnuplot-dedicated-display-mode @@ -501,10 +503,8 @@ non-nil." gnuplot-info-at-point gnuplot-context-sensitive-mode] ["Show gnuplot process buffer" gnuplot-show-gnuplot-buffer t] - ["Set arguments at point" gnuplot-gui-set-options-and-insert - (fboundp 'gnuplot-gui-set-options-and-insert)] - ["Swap plot/splot/fit lists in GUI" gnuplot-gui-swap-simple-complete - (fboundp 'gnuplot-gui-swap-simple-complete)] + ["Set arguments at point" gnuplot-gui-set-options-and-insert t] + ["Swap plot/splot/fit lists in GUI" gnuplot-gui-swap-simple-complete t] "---" ["Customize gnuplot" gnuplot-customize t] "---" @@ -515,7 +515,6 @@ non-nil." ;;; --- insertions variables and menus -;;(load-library "gnuplot-insertions") (defvar gnuplot-mode-insertions-menu nil) (defvar gnuplot-insertions-menu nil "Menu for insertions in `gnuplot-mode'. @@ -547,18 +546,16 @@ The easiest way to customize the submenus is to use the custom package. Just type \\[gnuplot-customize] and follow your nose. You can also add new items to any of these sub-menus by adding to the -`gnuplot-load-hook' in your .emacs file. Here is an example of adding -the \"regis\" terminal type to the terminal sub-menu: +`with-eval-after-load' blocks in your .emacs file. Here is an example of +adding the \"regis\" terminal type to the terminal sub-menu: - (add-hook - 'gnuplot-load-hook - '(lambda () + (with-eval-after-load 'gnuplot (setq gnuplot-insertions-terminal (append gnuplot-insertions-terminal (list [\"regis\" (gnuplot-insert \"set terminal regis\") - t])))))") + t]))))") (defvar gnuplot-insertions-top () "Top part of insertions menu. @@ -840,19 +837,16 @@ create a `gnuplot-mode' buffer." (boolean :tag "Enabled" t))))) -(defvar gnuplot-gui-popup-flag) -(defvar gnuplot-insertions-bottom () +(defvar gnuplot-insertions-bottom + '("---" + ["Display of info with insertion" gnuplot-toggle-info-display + :style toggle :selected gnuplot-insertions-show-help-flag] + ["Display GUI popup with insertion" gnuplot-gui-toggle-popup + :active t + :style toggle :selected gnuplot-gui-popup-flag]) "Bottom part of the insertions menu. This part contains the toggle buttons for displaying info or opening an argument-setting popup.") -(setq gnuplot-insertions-bottom - '("---" - ["Display of info with insertion" gnuplot-toggle-info-display - :style toggle :selected gnuplot-insertions-show-help-flag] - ["Display GUI popup with insertion" gnuplot-gui-toggle-popup - :active (fboundp 'gnuplot-gui-toggle-popup) - :style toggle :selected (and (fboundp 'gnuplot-gui-toggle-popup) - gnuplot-gui-popup-flag)])) (defun gnuplot-setup-menubar () "Initial setup of gnuplot and insertions menus." @@ -991,48 +985,43 @@ These are highlighted using `font-lock-constant-face'.") (gnuplot-make-regexp gnuplot-keywords-negatable-options)) ;; Set up colorization for gnuplot. -(defvar gnuplot-font-lock-keywords nil) -(defvar gnuplot-font-lock-syntactic-keywords nil) -(defvar gnuplot-font-lock-defaults nil) +(defvar gnuplot-font-lock-keywords + (list + ;; stuff in brackets, sugg. by + '("\\[\\([^]]+\\)\\]" 1 font-lock-constant-face) -(when (featurep 'font-lock) ; - (setq gnuplot-font-lock-keywords - (list - ;; stuff in brackets, sugg. by - '("\\[\\([^]]+\\)\\]" 1 font-lock-constant-face) + ;; variable/function definitions + '("\\(\\(\\sw\\|\\s_\\)+\\s-*\\((\\s-*\\(\\sw\\|\\s_\\)*\\s-*\\(,\\s-*\\sw*\\)*\\s-*)\\)?\\s-*=\\)[^=]" + 1 font-lock-variable-name-face) - ;; variable/function definitions - '("\\(\\(\\sw\\|\\s_\\)+\\s-*\\((\\s-*\\(\\sw\\|\\s_\\)*\\s-*\\(,\\s-*\\sw*\\)*\\s-*)\\)?\\s-*=\\)[^=]" - 1 font-lock-variable-name-face) + ;; built-in function names + (cons (gnuplot-make-regexp gnuplot-keywords-builtin-functions) + font-lock-function-name-face) - ;; built-in function names - (cons (gnuplot-make-regexp gnuplot-keywords-builtin-functions) - font-lock-function-name-face) + ;; reserved words associated with plotting + (cons (gnuplot-make-regexp gnuplot-keywords-plotting) + font-lock-type-face) + (cons (gnuplot-make-regexp gnuplot-keywords-plotting-styles) + font-lock-function-name-face) - ;; reserved words associated with plotting - (cons (gnuplot-make-regexp gnuplot-keywords-plotting) - font-lock-type-face) - (cons (gnuplot-make-regexp gnuplot-keywords-plotting-styles) - font-lock-function-name-face) + ;; (s)plot -- also thing (s)plotted + '("\\" . font-lock-keyword-face) + ;; '("\\" . font-lock-keyword-face) - ;; '("\\ gnuplot-buffer-max-size 0) (with-current-buffer gnuplot-buffer - (let ((nlines (count-lines (point-min) (point-max))) - (kill-whole-line t)) - (while (> nlines gnuplot-buffer-max-size) + (let ((gnuplot-lines (count-lines (point-min) (point-max)))) + (dotimes (_n (- gnuplot-lines gnuplot-buffer-max-size)) (goto-char (point-min)) - (kill-line) - (setq nlines (1- nlines))) + (delete-region (line-beginning-position) (1+ (line-end-position)))) (goto-char (point-max)))))) -(add-hook 'gnuplot-after-plot-hook 'gnuplot-trim-gnuplot-buffer nil nil) ;;; --- functions controlling the gnuplot process @@ -1412,17 +1397,16 @@ buffer." (set-syntax-table gnuplot-mode-syntax-table) (setq font-lock-defaults gnuplot-font-lock-defaults) - (set (make-local-variable 'parse-sexp-lookup-properties) t) - (set (make-local-variable 'syntax-propertize-function) - #'gnuplot-syntax-propertize) + (setq-local parse-sexp-lookup-properties t) + (setq-local syntax-propertize-function #'gnuplot-syntax-propertize) - (add-hook 'kill-buffer-hook 'gnuplot-close-down nil t) + (add-hook 'kill-buffer-hook #'gnuplot-close-down nil t) (add-hook 'comint-output-filter-functions - 'comint-postoutput-scroll-to-bottom + #'comint-postoutput-scroll-to-bottom nil t) (add-hook 'comint-output-filter-functions - 'gnuplot-protect-prompt-fn + #'gnuplot-protect-prompt-fn nil t) ;; Set up completion, using completion-at-point @@ -1436,17 +1420,16 @@ buffer." (easy-menu-add gnuplot-comint-mode-menu gnuplot-comint-mode-map)) ;; Key bindings for gnuplot-comint-mode -(define-key gnuplot-comint-mode-map "\M-\C-p" 'gnuplot-plot-from-comint) -(define-key gnuplot-comint-mode-map "\M-\C-f" 'gnuplot-save-and-plot-from-comint) -(define-key gnuplot-comint-mode-map "\C-d" 'gnuplot-delchar-or-maybe-eof) -(define-key gnuplot-comint-mode-map "\M-\r" 'completion-at-point) -(define-key gnuplot-comint-mode-map "\M-\t" 'completion-at-point) -(define-key gnuplot-comint-mode-map "\C-c\C-d" 'gnuplot-info-lookup-symbol) -(define-key gnuplot-comint-mode-map "\C-c\C-i" 'gnuplot-insert-filename) -(define-key gnuplot-comint-mode-map "\C-c\C-n" 'gnuplot-negate-option) -(define-key gnuplot-comint-mode-map "\C-c\C-z" 'gnuplot-customize) -(define-key gnuplot-comint-mode-map "\C-c\C-e" 'gnuplot-pop-to-recent-buffer) -(define-key gnuplot-comint-mode-map "\C-c\M-i" 'gnuplot-inline-image-mode) +(define-key gnuplot-comint-mode-map "\M-\C-p" #'gnuplot-plot-from-comint) +(define-key gnuplot-comint-mode-map "\M-\C-f" #'gnuplot-save-and-plot-from-comint) +(define-key gnuplot-comint-mode-map "\C-d" #'gnuplot-delchar-or-maybe-eof) +(define-key gnuplot-comint-mode-map "\M-\r" #'completion-at-point) +(define-key gnuplot-comint-mode-map "\M-\t" #'completion-at-point) +(define-key gnuplot-comint-mode-map "\C-c\C-d" #'gnuplot-info-lookup-symbol) +(define-key gnuplot-comint-mode-map "\C-c\C-i" #'gnuplot-insert-filename) +(define-key gnuplot-comint-mode-map "\C-c\C-n" #'gnuplot-negate-option) +(define-key gnuplot-comint-mode-map "\C-c\C-z" #'gnuplot-customize) +(define-key gnuplot-comint-mode-map "\C-c\C-e" #'gnuplot-pop-to-recent-buffer) ;; Menu for gnuplot-comint-mode (defvar gnuplot-comint-mode-menu nil @@ -1458,7 +1441,7 @@ buffer." (unless (and gnuplot-process (eq (process-status gnuplot-process) 'run) gnuplot-buffer (buffer-live-p gnuplot-buffer)) (message "Starting gnuplot plotting program...") - (let ((gnuplot-cmd (list 'make-comint gnuplot-process-name gnuplot-program))) + (let ((gnuplot-cmd (list #'make-comint gnuplot-process-name gnuplot-program))) (when gnuplot-program-args (setq gnuplot-cmd (append gnuplot-cmd '(nil) (split-string gnuplot-program-args)))) (setq gnuplot-buffer (eval gnuplot-cmd) @@ -1475,7 +1458,7 @@ buffer." (regexp-opt '("gnuplot> " "multiplot> ")) "Regexp for recognizing the GNUPLOT prompt.") -(defun gnuplot-protect-prompt-fn (string) +(defun gnuplot-protect-prompt-fn (_string) "Prevent the Gnuplot prompt from being deleted or overwritten. STRING is the text as originally inserted in the comint buffer." (save-excursion @@ -1552,11 +1535,6 @@ gnuplot process buffer will be displayed in a window." (defvar gnuplot-image-buffer-name "*gnuplot output*") -(defun gnuplot-display-images-p () - "Inline images require GNU Emacs." - (and (fboundp 'display-images-p) - (display-images-p))) - (defun gnuplot-external-display-mode () "Display image in external." (interactive) @@ -1590,10 +1568,10 @@ gnuplot process buffer will be displayed in a window." (format "set terminal %s\n" gnuplot-image-format)) (gnuplot-inline-image-set-output) (add-hook 'comint-output-filter-functions - 'gnuplot-insert-inline-image-output nil t)) + #'gnuplot-insert-inline-image-output nil t)) (gnuplot-send-hiding-output "set terminal pop\n") (remove-hook 'comint-output-filter-functions - 'gnuplot-insert-inline-image-output t))))) + #'gnuplot-insert-inline-image-output t))))) (defun gnuplot-inline-image-set-output () "Set Gnuplot's output file to `gnuplot-inline-image-filename'." @@ -1601,9 +1579,9 @@ gnuplot process buffer will be displayed in a window." (setq gnuplot-inline-image-filename tmp) (gnuplot-send-hiding-output (format "set output '%s'\n" tmp)))) -(defvar gnuplot-inhibit-filter nil) +(defvar gnuplot--inhibit-filter nil) -(defun gnuplot-insert-inline-image-output (string) +(defun gnuplot-insert-inline-image-output (_string) "Insert Gnuplot graphical output STRING in the gnuplot-comint buffer. Called via `comint-preoutput-filter-functions' hook when @@ -1612,8 +1590,8 @@ file `gnuplot-inline-image-filename'; if it exists and has nonzero size, inserts it as an inline image, stores a new temporary filename in `gnuplot-inline-image-filename', and updates Gnuplot with the appropriate 'set output' command." - (unless gnuplot-inhibit-filter ; Prevent recursively entering this filter - (let ((gnuplot-inhibit-filter t)) ; (causing an infinite loop) + (unless gnuplot--inhibit-filter ; Prevent recursively entering this filter + (let ((gnuplot--inhibit-filter t)) ; (causing an infinite loop) (save-excursion (goto-char (point-max)) (beginning-of-line) @@ -1649,7 +1627,7 @@ updates Gnuplot with the appropriate 'set output' command." "Send STRING to the running Gnuplot process invisibly." (with-current-buffer gnuplot-buffer (add-hook 'comint-preoutput-filter-functions - 'gnuplot-discard-output nil t)) + #'gnuplot-discard-output nil t)) (with-current-buffer (get-buffer-create gnuplot-hidden-output-buffer) (erase-buffer)) (comint-send-string (get-buffer-process gnuplot-buffer) string)) @@ -1801,7 +1779,7 @@ ARG is optional arg." (if (not arg) (setq arg 1)) (if (> arg 0) (catch 'bob ; go to beginning of ARGth prev. defun - (dotimes (n arg) + (dotimes (_n arg) (when (= (point) (gnuplot-point-at-beginning-of-continuation)) (forward-line -1) @@ -1813,7 +1791,7 @@ ARG is optional arg." t) (catch 'eob ; find beginning of (-ARG)th following defun - (dotimes (n (- arg)) + (dotimes (_n (- arg)) (gnuplot-end-of-continuation) (forward-line) (if (eobp) (throw 'eob t)) @@ -1899,9 +1877,7 @@ Negatable options are defined in `gnuplot-keywords-negatable-options'." (defun gnuplot-customize () "Customize `gnuplot-mode'." (interactive) - (if (fboundp 'customize-group) - (customize-group "gnuplot") - (message "The Custom library is not installed."))) + (customize-group "gnuplot")) @@ -1945,8 +1921,7 @@ See the comments in `gnuplot-info-hook'." ;; user will not want them lying around (and (get-buffer "info dir") (kill-buffer "info dir")) (and (get-buffer "info dir<2>") (kill-buffer "info dir<2>"))) - (setq gnuplot-keywords (gnuplot-set-keywords-list)) - (setq gnuplot-keywords-alist (mapcar 'list gnuplot-keywords))) + (setq gnuplot-keywords (gnuplot-set-keywords-list))) (defun gnuplot-set-keywords-list () "Set `gnuplot-keywords' from `info-lookup-cache'. @@ -1980,94 +1955,6 @@ Return a list of keywords." "Perform completion in Gnuplot buffers." (funcall gnuplot-completion-at-point-function)) -(defvar gnuplot-eldoc-hash nil - "ElDoc strings for gnuplot-mode. - -These have to be compiled from the Gnuplot source tree using -`doc2texi.el'.") - -;; Enable and disable context-sensitive completion -(define-minor-mode gnuplot-context-sensitive-mode - "Use context-sensitive completion and help in gnuplot-mode. - -When context-sensitive mode is enabled, gnuplot-mode tries to -provide more useful completions and help suggestions for built-in -keywords and functions by parsing each command as you type. It -attempts to take into account Gnuplot's many abbreviated -keywords. For example, with point at the end of a line reading -\"plot 'datafile' w \", typing \\[completion-at-point] will pop -up a list of plotting styles. - -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. - -\\[gnuplot-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 -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'. - -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." - :keymap - `((,(kbd "C-c C-/") . gnuplot-help-function) - (,(kbd "C-c C-d") . gnuplot-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 - (load-library "gnuplot-context") - (load-library "eldoc") - (setq gnuplot-completion-at-point-function #'gnuplot-context-completion-at-point) - - ;; Setup Eldoc - (set (make-local-variable 'eldoc-documentation-function) - 'gnuplot-eldoc-function) - (eldoc-add-command 'completion-at-point) ; Check for eldoc after completion - (when (fboundp 'comint-dynamic-complete) - (eldoc-add-command 'comint-dynamic-complete)) - - ;; 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 - (set (make-local-variable 'tab-always-indent) 'complete)) - - (message "Gnuplot context-sensitive help & completion enabled.")) - - ;; Turn off - (setq gnuplot-completion-at-point-function #'gnuplot-completion-at-point-info-look) - (setq eldoc-documentation-function nil) - (eldoc-mode 0) - (message "Gnuplot context-sensitive help & completion disabled."))) - ;; Older completion method using info-look (defun gnuplot-completion-at-point-info-look () "Return completions of keyword preceding point. @@ -2079,18 +1966,10 @@ positions and COMPLETIONS is a list." (if gnuplot-keywords-pending ; (gnuplot-setup-info-look)) - (let* ((end (point)) - (beg (condition-case _err - (save-excursion (backward-sexp 1) (point)) - (error (point)))) - (patt (buffer-substring beg end)) - (pattern (if (string-match "\\([^ \t]*\\)\\s-+$" patt) - (match-string 1 patt) patt)) - (completions (all-completions pattern gnuplot-keywords-alist))) - (if completions - (list beg end completions) - (message "No gnuplot keywords complete '%s'" pattern) - nil))) + (list (condition-case _err + (save-excursion (backward-sexp 1) (point)) + (error (point))) + (point) gnuplot-keywords)) (defun gnuplot-info-lookup-symbol (symbol &optional mode) @@ -2109,7 +1988,7 @@ according to the value of `gnuplot-info-display'." (list nil (message "Help is not available. The gnuplot info file could not be found."))))) - (when (and (featurep 'info-look) gnuplot-keywords) + (when gnuplot-keywords (unless symbol (setq symbol "Commands")) (save-window-excursion (info-lookup-symbol symbol mode)) @@ -2164,8 +2043,8 @@ shown." (setq topic (downcase (match-string 2 string)) term (match-string 4 string)) (if (string= topic "terminal") (setq topic (downcase term))))) - (cond ((and (fboundp 'gnuplot-gui-set-options-and-insert) - gnuplot-gui-popup-flag) + (cond ((and (bound-and-true-p gnuplot-gui-popup-flag) + (fboundp 'gnuplot-gui-set-options-and-insert)) (gnuplot-gui-set-options-and-insert)) (gnuplot-insertions-show-help-flag (if gnuplot-keywords-pending ; @@ -2241,16 +2120,16 @@ a list: (use-local-map gnuplot-mode-map) (setq major-mode 'gnuplot-mode mode-name "Gnuplot") - (set (make-local-variable 'comment-start) "# ") - (set (make-local-variable 'comment-end) "") - (set (make-local-variable 'comment-column) 32) - (set (make-local-variable 'comment-start-skip) "#[ \t]*") - (set (make-local-variable 'indent-line-function) 'gnuplot-indent-line) + (setq-local comment-start "# ") + (setq-local comment-end "") + (setq-local comment-column 32) + (setq-local comment-start-skip "#[ \t]*") + (setq-local indent-line-function #'gnuplot-indent-line) - (set (make-local-variable 'beginning-of-defun-function) 'gnuplot-beginning-of-defun) - (set (make-local-variable 'end-of-defun-function) 'gnuplot-end-of-continuation) + (setq-local beginning-of-defun-function #'gnuplot-beginning-of-defun) + (setq-local end-of-defun-function #'gnuplot-end-of-continuation) - (add-hook 'completion-at-point-functions 'gnuplot-completion-at-point nil t) + (add-hook 'completion-at-point-functions #'gnuplot-completion-at-point nil t) (set-syntax-table gnuplot-mode-syntax-table) @@ -2258,22 +2137,16 @@ a list: (gnuplot-setup-info-look)) ;; ;; Add syntax-propertizing functions to search for strings and comments - (set (make-local-variable 'syntax-propertize-function) - #'gnuplot-syntax-propertize) + (setq-local syntax-propertize-function #'gnuplot-syntax-propertize) (add-hook 'syntax-propertize-extend-region-functions #'gnuplot-syntax-propertize-extend-region nil t) ;; Set up font-lock (setq font-lock-defaults gnuplot-font-lock-defaults) - (set (make-local-variable 'font-lock-multiline) t) - (set (make-local-variable 'parse-sexp-lookup-properties) t) + (setq-local font-lock-multiline t) + (setq-local parse-sexp-lookup-properties t) - (if (fboundp 'widget-create) ; gnuplot-gui - (condition-case () - (require 'gnuplot-gui) - (error nil))) - (setq gnuplot-first-call nil ; a few more details ... - gnuplot-comint-recent-buffer (current-buffer)) + (setq gnuplot-comint-recent-buffer (current-buffer)) (setq-local comint-process-echoes gnuplot-echo-command-line-flag) (run-hooks 'gnuplot-mode-hook) (gnuplot-setup-menubar)) @@ -2304,11 +2177,7 @@ following in your .emacs file: ;;; That's it! ---------------------------------------------------------------- - -;;; --- final chores: provide 'gnuplot and run load-hook -;; provide before run-hooks suggested by (provide 'gnuplot) -(run-hooks 'gnuplot-load-hook) ;; Local Variables: ;; indent-tabs-mode: nil diff --git a/lisp/ht.el b/lisp/ht.el index bda5d622..0809ef17 100644 --- a/lisp/ht.el +++ b/lisp/ht.el @@ -3,9 +3,9 @@ ;; Copyright (C) 2013 Wilfred Hughes ;; Author: Wilfred Hughes -;; Version: 2.3 -;; Package-Version: 20201119.518 -;; Package-Commit: 2850301d19176b8d3bb6cc8d95af6ab7e529bd56 +;; Version: 2.4 +;; Package-Version: 20210119.741 +;; Package-Commit: c4c1be487d6ecb353d07881526db05d7fc90ea87 ;; Keywords: hash table, hash map, hash ;; Package-Requires: ((dash "2.12.0")) @@ -116,9 +116,10 @@ for the final key, which may return any value." (declare (side-effect-free t)) (inline-letevals (table keys) (inline-quote - (prog1 ,table + (progn (while ,keys - (setf ,table (ht-get table (pop ,keys)))))))) + (setf ,table (ht-get ,table (pop ,keys)))) + ,table)))) (put 'ht-get* 'compiler-macro (lambda (_ table &rest keys) diff --git a/lisp/htmlize.el b/lisp/htmlize.el index 3547e5be..39e92ccd 100644 --- a/lisp/htmlize.el +++ b/lisp/htmlize.el @@ -1,13 +1,13 @@ ;;; htmlize.el --- Convert buffer text and decorations to HTML. -*- lexical-binding: t -*- -;; Copyright (C) 1997-2003,2005,2006,2009,2011,2012,2014,2017,2018 Hrvoje Niksic +;; Copyright (C) 1997-2003,2005,2006,2009,2011,2012,2014,2017,2018,2020 Hrvoje Niksic ;; Author: Hrvoje Niksic ;; Homepage: https://github.com/hniksic/emacs-htmlize ;; Keywords: hypermedia, extensions -;; Package-Version: 20200816.746 -;; Package-Commit: 49205105898ba8993b5253beec55d8bddd820a70 -;; Version: 1.56 +;; Package-Version: 20210825.2150 +;; Package-Commit: dd27bc3f26efd728f2b1f01f9e4ac4f61f2ffbf9 +;; Version: 1.57 ;; 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 @@ -90,7 +90,7 @@ (defvar font-lock-support-mode) (defvar global-font-lock-mode)) -(defconst htmlize-version "1.56") +(defconst htmlize-version "1.57") (defgroup htmlize nil "Convert buffer text and faces to HTML." @@ -1047,7 +1047,7 @@ If no rgb.txt file is found, return nil." (let ((size-list (cl-loop for f in face-list - for h = (face-attribute f :height) + for h = (and (facep f) (face-attribute f :height)) collect (if (eq h 'unspecified) nil h)))) (cl-reduce 'htmlize-merge-size (cons nil size-list))))) @@ -1275,24 +1275,6 @@ overlays that specify `face'." faces :test 'equal)))) faces)) -(if (>= emacs-major-version 25) - (defun htmlize-sorted-overlays-at (pos) - (overlays-at pos t)) - - (defun htmlize-sorted-overlays-at (pos) - ;; Like OVERLAYS-AT with the SORTED argument, for older Emacsen. - (let ((overlays (overlays-at pos))) - (setq overlays (cl-sort overlays #'< - :key (lambda (o) - (- (overlay-end o) (overlay-start o))))) - (setq overlays - (cl-stable-sort overlays #'< - :key (lambda (o) - (let ((prio (overlay-get o 'priority))) - (if (numberp prio) prio 0))))) - (nreverse overlays)))) - - ;; htmlize-faces-at-point returns the faces in use at point. The ;; faces are sorted by increasing priority, i.e. the last face takes ;; precedence. @@ -1312,7 +1294,7 @@ overlays that specify `face'." ;; Collect overlays at point that specify `face'. (cl-delete-if-not (lambda (o) (overlay-get o 'face)) - (nreverse (htmlize-sorted-overlays-at (point))))) + (nreverse (overlays-at (point) t)))) list face-prop) (dolist (overlay overlays) (setq face-prop (overlay-get overlay 'face) diff --git a/lisp/hydra/hydra-pkg.el b/lisp/hydra/hydra-pkg.el index 2f9c6b2d..f940b9d7 100644 --- a/lisp/hydra/hydra-pkg.el +++ b/lisp/hydra/hydra-pkg.el @@ -1,7 +1,7 @@ -(define-package "hydra" "20201115.1055" "Make bindings that stick around." +(define-package "hydra" "20220102.803" "Make bindings that stick around." '((cl-lib "0.5") (lv "0")) - :commit "2d553787aca1aceb3e6927e426200e9bb9f056f1" :authors + :commit "9e9e00cb240ea1903ffd36a54956b3902c379d29" :authors '(("Oleh Krehel" . "ohwoeowho@gmail.com")) :maintainer '("Oleh Krehel" . "ohwoeowho@gmail.com") diff --git a/lisp/hydra/hydra.el b/lisp/hydra/hydra.el index d8770019..f7c60dff 100644 --- a/lisp/hydra/hydra.el +++ b/lisp/hydra/hydra.el @@ -352,6 +352,7 @@ Exitable only through a blue head.") ;;* Universal Argument (defvar hydra-base-map (let ((map (make-sparse-keymap))) + (define-key map (kbd " k") 'hydra--describe-key) (define-key map [?\C-u] 'hydra--universal-argument) (define-key map [?-] 'hydra--negative-argument) (define-key map [?0] 'hydra--digit-argument) @@ -413,6 +414,15 @@ Exitable only through a blue head.") ((eq arg '-) nil) (t '-)))) +(defun hydra--describe-key () + "Forward to `describe-key'. +Call order: the hydra body, `hydra--describe-key', the head." + (interactive) + (lv-delete-window) + (let ((hydra-hint-display-type 'message)) + (call-interactively 'describe-key) + (hydra-keyboard-quit))) + ;;* Repeat (defvar hydra-repeat--prefix-arg nil "Prefix arg to use with `hydra-repeat'.") @@ -838,7 +848,9 @@ HEADS is a list of heads." "The heads for the associated hydra are:\n\n%s\n\n%s%s." (mapconcat (lambda (x) - (format "\"%s\": `%S'" (car x) (cadr x))) + (format "\"%s\": %s" + (car x) + (if (cadr x) (format "`%S'" (cadr x)) "nil"))) heads ",\n") (format "The body can be accessed via `%S'" body-name) (if body-key diff --git a/lisp/indent-guide.el b/lisp/indent-guide.el index 853f33b1..6c6d508b 100644 --- a/lisp/indent-guide.el +++ b/lisp/indent-guide.el @@ -18,8 +18,8 @@ ;; Author: zk_phi ;; URL: http://hins11.yu-yake.com/ -;; Package-Version: 20191106.240 -;; Package-Commit: 7fc710748f9e5a086acfe77970f117df89ee9749 +;; Package-Version: 20210115.400 +;; Package-Commit: d388c3387781a370ca13233ff445d03f3c5cf12f ;; Version: 2.3.1 ;;; Commentary: @@ -150,9 +150,12 @@ blocks are NOT placed at beginning of line." (cond ((<= level 0) (list "")) ((>= level tab-width) - (cons (concat "\t" (make-string (- level tab-width) ?\s)) - (cons (make-string level ?\s) - (indent-guide--indentation-candidates (1- level))))) + (let ((ntabs (/ level tab-width)) + (nspaces (mod level tab-width))) + (cons (concat (make-string ntabs ?\t) + (make-string nspaces ?\s)) + (cons (make-string level ?\s) + (indent-guide--indentation-candidates (1- level)))))) (t (cons (make-string level ?\s) (indent-guide--indentation-candidates (1- level)))))) diff --git a/lisp/ivy-bibtex.el b/lisp/ivy-bibtex.el index c16bcf9b..0b8f5fdb 100644 --- a/lisp/ivy-bibtex.el +++ b/lisp/ivy-bibtex.el @@ -3,10 +3,10 @@ ;; Author: Justin Burkett ;; Maintainer: Titus von der Malsburg ;; URL: https://github.com/tmalsburg/helm-bibtex -;; Package-Version: 20201014.803 -;; Package-Commit: 1bb81d77e08296a50de7ebfe5cf5b0c715b7f3d6 +;; Package-Version: 20210927.1205 +;; Package-Commit: aa775340ba691d2322948bfdc6a88158568a1399 ;; Version: 1.0.1 -;; Package-Requires: ((bibtex-completion "1.0.0") (swiper "0.7.0") (cl-lib "0.5")) +;; Package-Requires: ((bibtex-completion "1.0.0") (ivy "0.13.0") (cl-lib "0.5")) ;; 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 @@ -88,19 +88,42 @@ "The default action for the `ivy-bibtex` command." :group 'bibtex-completion :type 'function) + +(defvar ivy-bibtex-default-multi-action 'ivy-bibtex-open-any + "The default multi-action for the `ivy-bibtex` command.") + +(defvar ivy-bibtex-use-extra-keymap t + "Non-nil if `ivy-bibtex' has keys for marking candidates.") + +(defvar ivy-bibtex-extra-keymap + (let ((map (make-sparse-keymap))) + (define-key map (kbd "C-SPC") 'ivy-mark) + (define-key map (kbd "S-SPC") 'ivy-unmark) + map) + "Optional extra keymap for `ivy-bibtex'.") (defun ivy-bibtex-display-transformer (candidate) "Prepare bib entry CANDIDATE for display." - (let* ((width (1- (frame-width))) - (idx (get-text-property 0 'idx candidate)) - (entry (cdr (nth idx (ivy-state-collection ivy-last))))) - (bibtex-completion-format-entry entry width))) + (let* ((width (- (frame-width) 2)) + (idx (get-text-property 1 'idx candidate)) + (entry (cdr (nth idx (ivy-state-collection ivy-last))))) + (s-concat (if (s-starts-with-p ivy-mark-prefix candidate) ivy-mark-prefix "") + (bibtex-completion-format-entry entry width)))) (defmacro ivy-bibtex-ivify-action (action name) - "Wraps the function ACTION in another function named NAME which extracts the key from the candidate selected in ivy and passes it to ACTION." - `(defun ,name (candidate) - (let ((key (cdr (assoc "=key=" (cdr candidate))))) - (,action (list key))))) + "Wraps the function ACTION in two other functions named NAME and NAME-multi. + +The first extracts the key from the candidate selected in ivy and +passes it to ACTION. + +The second extracts the list of keys in mark candidates selected +in ivy and passes it to ACTION." + `(defun ,name (candidates) + ,(format "Ivy wrapper for `%s' applied to one or more CANDIDATES." action) + (let ((keys (if (consp (car candidates)) + (--map (cdr (assoc "=key=" (cdr it))) candidates) + (list (cdr (assoc "=key=" (cdr candidates))))))) + (,action keys)))) (ivy-bibtex-ivify-action bibtex-completion-open-any ivy-bibtex-open-any) (ivy-bibtex-ivify-action bibtex-completion-open-pdf ivy-bibtex-open-pdf) @@ -124,7 +147,7 @@ This is meant to be used as an action in `ivy-read`, with :action (lambda (candidate) (bibtex-completion-fallback-action (cdr candidate) search-expression)))) (defvar ivy-bibtex-history nil - "Search history for `ivy-bibtex'") + "Search history for `ivy-bibtex'.") ;;;###autoload (defun ivy-bibtex (&optional arg local-bib) @@ -152,7 +175,9 @@ from the local bibliography. This is set internally by :preselect preselect :caller 'ivy-bibtex :history 'ivy-bibtex-history - :action ivy-bibtex-default-action))) + :action ivy-bibtex-default-action + :multi-action ivy-bibtex-default-multi-action + :keymap (when ivy-bibtex-use-extra-keymap ivy-bibtex-extra-keymap)))) ;;;###autoload (defun ivy-bibtex-with-local-bibliography (&optional arg) @@ -176,9 +201,7 @@ reread." (cl-letf* ((candidates (bibtex-completion-candidates)) ((symbol-function 'bibtex-completion-candidates) (lambda () - (seq-filter - (lambda (candidate) (assoc "=has-note=" candidate)) - candidates)))) + (--filter (assoc "=has-note=" it) candidates)))) (ivy-bibtex arg))) (ivy-set-display-transformer @@ -187,16 +210,16 @@ reread." (ivy-set-actions 'ivy-bibtex - '(("p" ivy-bibtex-open-pdf "Open PDF file (if present)") - ("u" ivy-bibtex-open-url-or-doi "Open URL or DOI in browser") - ("c" ivy-bibtex-insert-citation "Insert citation") - ("r" ivy-bibtex-insert-reference "Insert reference") - ("k" ivy-bibtex-insert-key "Insert BibTeX key") - ("b" ivy-bibtex-insert-bibtex "Insert BibTeX entry") - ("a" ivy-bibtex-add-PDF-attachment "Attach PDF to email") - ("e" ivy-bibtex-edit-notes "Edit notes") - ("s" ivy-bibtex-show-entry "Show entry") - ("l" ivy-bibtex-add-pdf-to-library "Add PDF to library") + '(("p" ivy-bibtex-open-pdf "Open PDF file (if present)" ivy-bibtex-open-pdf) + ("u" ivy-bibtex-open-url-or-doi "Open URL or DOI in browser" ivy-bibtex-open-url-or-doi) + ("c" ivy-bibtex-insert-citation "Insert citation" ivy-bibtex-insert-citation) + ("r" ivy-bibtex-insert-reference "Insert reference" ivy-bibtex-insert-reference) + ("k" ivy-bibtex-insert-key "Insert BibTeX key" ivy-bibtex-insert-key) + ("b" ivy-bibtex-insert-bibtex "Insert BibTeX entry" ivy-bibtex-insert-bibtex) + ("a" ivy-bibtex-add-PDF-attachment "Attach PDF to email" ivy-bibtex-add-PDF-attachment) + ("e" ivy-bibtex-edit-notes "Edit notes" ivy-bibtex-edit-notes) + ("s" ivy-bibtex-show-entry "Show entry" ivy-bibtex-show-entry) + ("l" ivy-bibtex-add-pdf-to-library "Add PDF to library" ivy-bibtex-add-pdf-to-library) ("f" (lambda (_candidate) (ivy-bibtex-fallback ivy-text)) "Fallback options"))) (provide 'ivy-bibtex) diff --git a/lisp/js2-mode/js2-imenu-extras.el b/lisp/js2-mode/js2-imenu-extras.el index 4859befc..3ec1ba84 100644 --- a/lisp/js2-mode/js2-imenu-extras.el +++ b/lisp/js2-mode/js2-imenu-extras.el @@ -35,6 +35,10 @@ (require 'cl-lib) (require 'js2-mode) +(eval-when-compile + (when (<= emacs-major-version 26) + (require 'subr-x))) + (defvar js2-imenu-extension-styles `((:framework jquery :call-re "\\_<\\(?:jQuery\\|\\$\\|_\\)\\.extend\\s-*(" @@ -60,6 +64,14 @@ :call-re "\\_ ;; mooz ;; Dmitry Gutov ;; URL: https://github.com/mooz/js2-mode/ ;; http://code.google.com/p/js2-mode/ -;; Version: 20201220 +;; Version: 20211229 ;; Keywords: languages, javascript ;; Package-Requires: ((emacs "24.1") (cl-lib "0.5")) @@ -657,7 +657,9 @@ which doesn't seem particularly useful, but Rhino permits it." (defvar js2-EXPON 175) (defvar js2-NULLISH-COALESCING 176) ; nullish coalescing (obj.value ?? obj.defaultValue ?? 0)) -(defconst js2-num-tokens (1+ js2-NULLISH-COALESCING)) +(defvar js2-PRIVATE_NAME 177) ; this.#bar(); + +(defconst js2-num-tokens (1+ js2-PRIVATE_NAME)) (defconst js2-debug-print-trees nil) @@ -2651,14 +2653,17 @@ so many of its properties will be nil. object in-pos each-pos - foreach-p forof-p + await-pos + foreach-p forof-p forawait-p lp rp))) "AST node for a for..in loop." iterator ; [var] foo in ... object ; object over which we're iterating in-pos ; buffer position of 'in' keyword each-pos ; buffer position of 'each' keyword, if foreach-p + await-pos ; buffer position of 'await' keyword, if forawait-p foreach-p ; t if it's a for-each loop + forawait-p ; t if it's a for-await loop forof-p) ; t if it's a for-of loop (js2--struct-put 'js2-for-in-node 'js2-visitor 'js2-visit-for-in-node) @@ -2672,10 +2677,13 @@ so many of its properties will be nil. (defun js2-print-for-in-node (n i) (let ((pad (js2-make-pad i)) (foreach (js2-for-in-node-foreach-p n)) + (forawait (js2-for-in-node-forawait-p n)) (forof (js2-for-in-node-forof-p n))) (insert pad "for ") (if foreach (insert "each ")) + (if forawait + (insert "await ")) (insert "(") (js2-print-ast (js2-for-in-node-iterator n) 0) (insert (if forof " of " " in ")) @@ -3009,12 +3017,15 @@ modules metadata itself." (let ((pad (js2-make-pad i)) (guard-kwd (js2-catch-node-guard-kwd n)) (guard-expr (js2-catch-node-guard-expr n))) - (insert " catch (") - (js2-print-ast (js2-catch-node-param n) 0) - (when guard-kwd - (insert " if ") - (js2-print-ast guard-expr 0)) - (insert ") {\n") + (insert " catch ") + (when (js2-catch-node-lp n) + (insert "(") + (js2-print-ast (js2-catch-node-param n) 0) + (when guard-kwd + (insert " if ") + (js2-print-ast guard-expr 0)) + (insert ") ")) + (insert "{\n") (js2-print-body n (1+ i)) (insert pad "}"))) @@ -5892,6 +5903,7 @@ the token is flagged as such." During operation, creates an instance of `js2-token' struct, sets its relevant fields and puts it into `js2-ti-tokens'." (let (identifier-start + identifier-private is-unicode-escape-start c contains-escape escape-val str result base look-for-slash continue tt legacy-octal @@ -5937,7 +5949,10 @@ its relevant fields and puts it into `js2-ti-tokens'." (js2-unget-char) (setq c ?\\))) (t - (when (setq identifier-start (js2-identifier-start-p c)) + (when (setq identifier-start (or (js2-identifier-start-p c) + (and + (eq c ?#) + (setq identifier-private t)))) (setq js2-ts-string-buffer nil) (js2-add-to-string c)))) (when identifier-start @@ -5997,7 +6012,11 @@ its relevant fields and puts it into `js2-ti-tokens'." (throw 'return (js2-tt-code result)))) ;; If we want to intern these as Rhino does, just use (intern str) (setf (js2-token-string token) str) - (throw 'return js2-NAME)) ; end identifier/kwd check + (throw 'return + (if identifier-private + js2-PRIVATE_NAME + js2-NAME) + )) ; end identifier/kwd check ;; is it a number? (when (or (js2-digit-p c) (and (eq c ?.) (js2-digit-p (js2-peek-char)))) @@ -8015,7 +8034,7 @@ string is NAME. Returns nil and keeps current token otherwise." "Consume token and return t if next token is a valid property name. If `js2-language-version' is >= 180, a keyword or reserved word is considered valid name as well." - (if (eq js2-NAME (js2-get-prop-name-token)) + (if (memq (js2-get-prop-name-token) `(,js2-NAME ,js2-PRIVATE_NAME)) t (js2-unget-token) nil)) @@ -8606,7 +8625,7 @@ node are given relative start positions and correct lengths." (aset parsers js2-FOR #'js2-parse-for) (aset parsers js2-FUNCTION #'js2-parse-function-stmt) (aset parsers js2-IF #'js2-parse-if) - (aset parsers js2-IMPORT #'js2-parse-import) + (aset parsers js2-IMPORT #'js2-parse-import-declaration-or-expr) (aset parsers js2-LC #'js2-parse-block) (aset parsers js2-LET #'js2-parse-let-stmt) (aset parsers js2-NAME #'js2-parse-name-or-label) @@ -8736,6 +8755,11 @@ Return value is a list (EXPR LP RP), with absolute paren positions." (js2-node-add-children pn (car cond) if-true if-false) pn)) +(defun js2-parse-import-declaration-or-expr () + (if (memq (js2-peek-token) `(,js2-LP ,js2-DOT)) + (js2-parse-expr-stmt) + (js2-parse-import))) + (defun js2-parse-import () "Parse import statement. The current token must be js2-IMPORT." (unless (js2-ast-root-p js2-current-scope) @@ -9133,24 +9157,31 @@ invalid export statements." node))) (defun js2-parse-for () - "Parse a for, for-in or for each-in statement. + "Parse a for, for-in, for each-in or for await-in statement. Last matched token must be js2-FOR." (let ((for-pos (js2-current-token-beg)) (tmp-scope (make-js2-scope)) - pn is-for-each is-for-in-or-of is-for-of - in-pos each-pos tmp-pos + pn is-for-each is-for-in-or-of is-for-of is-for-await + in-pos each-pos tmp-pos await-pos init ; Node init is also foo in 'foo in object'. cond ; Node cond is also object in 'foo in object'. incr ; 3rd section of for-loop initializer. body tt lp rp) - ;; See if this is a for each () instead of just a for () (when (js2-match-token js2-NAME) - (if (string= "each" (js2-current-token-string)) - (progn - (setq is-for-each t - each-pos (- (js2-current-token-beg) for-pos)) ; relative - (js2-record-face 'font-lock-keyword-face)) - (js2-report-error "msg.no.paren.for"))) + (cond + ;; See if this is a for each () instead of just a for () + ((string= "each" (js2-current-token-string)) + (progn + (setq is-for-each t + each-pos (- (js2-current-token-beg) for-pos)) ; relative + (js2-record-face 'font-lock-keyword-face))) + ;; See if this is a for await () instead of just a for () + ((string= "await" (js2-current-token-string)) + (progn + (setq is-for-await t + await-pos (- (js2-current-token-beg) for-pos)) ; relative + (js2-record-face 'font-lock-keyword-face))) + (t (js2-report-error "msg.no.paren.for")))) (if (js2-must-match js2-LP "msg.no.paren.for") (setq lp (- (js2-current-token-beg) for-pos))) (setq tt (js2-get-token)) @@ -9212,6 +9243,8 @@ Last matched token must be js2-FOR." :in-pos in-pos :foreach-p is-for-each :each-pos each-pos + :forawait-p is-for-await + :await-pos await-pos :forof-p is-for-of :lp lp :rp rp))) @@ -9258,30 +9291,30 @@ Last matched token must be js2-FOR." lp rp) (if saw-default-catch (js2-report-error "msg.catch.unreachable")) - (if (js2-must-match js2-LP "msg.no.paren.catch") - (setq lp (- (js2-current-token-beg) catch-pos))) (js2-push-scope catch-node) - (let ((tt (js2-peek-token))) - (cond - ;; Destructuring pattern: - ;; catch ({ message, file }) { ... } - ((or (= tt js2-LB) (= tt js2-LC)) - (js2-get-token) - (setq param (js2-parse-destruct-primary-expr)) - (js2-define-destruct-symbols param js2-LET nil)) - ;; Simple name. - (t - (js2-must-match-name "msg.bad.catchcond") - (setq param (js2-create-name-node)) - (js2-define-symbol js2-LET (js2-current-token-string) param) - (js2-check-strict-identifier param)))) - ;; Catch condition. - (if (js2-match-token js2-IF) - (setq guard-kwd (- (js2-current-token-beg) catch-pos) - catch-cond (js2-parse-expr)) - (setq saw-default-catch t)) - (if (js2-must-match js2-RP "msg.bad.catchcond") - (setq rp (- (js2-current-token-beg) catch-pos))) + (when (js2-match-token js2-LP) + (setq lp (- (js2-current-token-beg) catch-pos)) + (let ((tt (js2-peek-token))) + (cond + ;; Destructuring pattern: + ;; catch ({ message, file }) { ... } + ((or (= tt js2-LB) (= tt js2-LC)) + (js2-get-token) + (setq param (js2-parse-destruct-primary-expr)) + (js2-define-destruct-symbols param js2-LET nil)) + ;; Simple name. + (t + (js2-must-match-name "msg.bad.catchcond") + (setq param (js2-create-name-node)) + (js2-define-symbol js2-LET (js2-current-token-string) param) + (js2-check-strict-identifier param)))) + ;; Catch condition. + (if (js2-match-token js2-IF) + (setq guard-kwd (- (js2-current-token-beg) catch-pos) + catch-cond (js2-parse-expr)) + (setq saw-default-catch t)) + (if (js2-must-match js2-RP "msg.bad.catchcond") + (setq rp (- (js2-current-token-beg) catch-pos)))) (js2-must-match js2-LC "msg.no.brace.catchblock") (js2-parse-statements catch-node) (if (js2-must-match js2-RC "msg.no.brace.after.body") @@ -9877,15 +9910,20 @@ If NODE is non-nil, it is the AST node associated with the symbol." (while (and (not oneshot) (js2-match-token js2-COMMA)) (setq op-pos (- (js2-current-token-beg) pos)) ; relative - (setq right (js2-parse-assign-expr) - left pn - pn (make-js2-infix-node :type js2-COMMA - :pos pos - :len (- js2-ts-cursor pos) - :op-pos op-pos - :left left - :right right)) - (js2-node-add-children pn left right)) + (if (eq (js2-peek-token) js2-RP) + ;; Stop the parser from scanning too far: it's actually + ;; valid syntax in arrow fun arguments, and we don't want + ;; the RP token to get consumed. + (js2-report-error "msg.syntax") + (setq right (js2-parse-assign-expr) + left pn + pn (make-js2-infix-node :type js2-COMMA + :pos pos + :len (- js2-ts-cursor pos) + :op-pos op-pos + :left left + :right right)) + (js2-node-add-children pn left right))) pn)) (defun js2-parse-assign-expr () @@ -10489,7 +10527,7 @@ Last token parsed must be `js2-RB'." tt (js2-get-prop-name-token)) (cond ;; handles: name, ns::name, ns::*, ns::[expr] - ((= tt js2-NAME) + ((or (= tt js2-NAME) (= tt js2-PRIVATE_NAME)) (setq ref (js2-parse-property-name -1 nil member-type-flags))) ;; handles: *, *::name, *::*, *::[expr] ((= tt js2-MUL) @@ -10631,6 +10669,8 @@ array-literals, array comprehensions and regular expressions." (js2-parse-attribute-access)) ((= tt js2-NAME) (js2-parse-name tt)) + ((= tt js2-IMPORT) + (js2-create-name-node nil nil "import")) ((= tt js2-NUMBER) (setq node (make-js2-number-node)) (when (and js2-in-use-strict-directive @@ -11034,8 +11074,8 @@ expression)." (when (and (>= js2-language-version 200) (= js2-NAME tt) (member prop '("get" "set" "async")) - (member (js2-peek-token 'KEYWORD_IS_NAME) - (list js2-NAME js2-STRING js2-NUMBER js2-LB))) + (memq (js2-peek-token 'KEYWORD_IS_NAME) + `(,js2-NAME ,js2-PRIVATE_NAME ,js2-STRING ,js2-NUMBER ,js2-LB))) (setq previous-token (js2-current-token) tt (js2-get-prop-name-token)))) (cond @@ -11046,7 +11086,7 @@ expression)." (setq after-comma nil elem (js2-make-unary nil js2-TRIPLEDOT 'js2-parse-assign-expr))) ;; Found a key/value property (of any sort) - ((member tt (list js2-NAME js2-STRING js2-NUMBER js2-LB)) + ((memq tt `(,js2-NAME ,js2-PRIVATE_NAME ,js2-STRING ,js2-NUMBER ,js2-LB)) (setq after-comma nil elem (js2-parse-named-prop tt previous-token class-p)) (if (and (null elem) @@ -11110,7 +11150,7 @@ expression)." (defun js2-parse-named-prop (tt previous-token &optional class-p) "Parse a name, string, or getter/setter object property. When `js2-is-in-destructuring' is t, forms like {a, b, c} will be permitted." - (let ((key (js2-parse-prop-name tt)) + (let ((key (js2-parse-prop-name tt class-p)) (prop (and previous-token (js2-token-string previous-token))) (property-type (when previous-token (if (= (js2-token-type previous-token) js2-MUL) @@ -11162,7 +11202,7 @@ When `js2-is-in-destructuring' is t, forms like {a, b, c} will be permitted." (when (js2-match-token js2-ASSIGN) (js2-make-binary js2-ASSIGN name 'js2-parse-assign-expr t))) -(defun js2-parse-prop-name (tt) +(defun js2-parse-prop-name (tt allow-private) (cond ;; Literal string keys: {'foo': 'bar'} ((= tt js2-STRING) @@ -11180,6 +11220,9 @@ When `js2-is-in-destructuring' is t, forms like {a, b, c} will be permitted." ;; Unquoted names: {foo: 12} ((= tt js2-NAME) (js2-create-name-node)) + ((and allow-private + (= tt js2-PRIVATE_NAME)) + (js2-create-name-node)) ;; Anything else is an error (t (js2-report-error "msg.bad.prop")))) @@ -11195,9 +11238,9 @@ string or expression." ((and (>= js2-language-version 200) (if class-p (and (setq tt (js2-peek-token-or-eol)) - (member tt (list js2-EOL js2-RC js2-SEMI))) + (memq tt `(,js2-EOL ,js2-RC ,js2-SEMI))) (and (setq tt (js2-peek-token)) - (member tt (list js2-COMMA js2-RC)) + (memq tt `(,js2-COMMA ,js2-RC)) (js2-name-node-p prop)))) (setq result (make-js2-object-prop-node :pos pos @@ -11269,7 +11312,7 @@ And, if CHECK-ACTIVATION-P is non-nil, use the value of TOKEN." (let* ((beg (js2-current-token-beg)) (tt (js2-current-token-type)) (s (or string - (if (= js2-NAME tt) + (if (or (= js2-NAME tt) (= js2-PRIVATE_NAME tt)) (js2-current-token-string) (js2-tt-name tt)))) name) @@ -12569,7 +12612,7 @@ move backward across N balanced expressions." (setq pos (js2-node-abs-pos child))) ;; Before both parens. (setq pos lp))) - (let ((state (parse-partial-sexp start pos))) + (let ((state (parse-partial-sexp pos start))) (goto-char (if (not (zerop (car state))) ;; Stumble at the unbalanced paren if < 0, or ;; jump a bit further if > 0. @@ -12910,7 +12953,7 @@ it marks the next defun after the ones already marked." (cl-assert (js2-object-node-p node)) ;; Only support name-node and nodes for the time being (cl-loop for elem in (js2-object-node-elems node) - for left = (js2-object-prop-node-left elem) + for left = (js2-infix-node-left elem) if (or (and (js2-name-node-p left) (equal (js2-name-node-name name-node) (js2-name-node-name left))) @@ -12930,28 +12973,43 @@ i.e. (\\='name\\=' \\='value\\=') = {name : { value: 3}}" (while (and temp names (js2-object-node-p temp-object)) (setq temp (js2-search-object temp-object (pop names))) (and (setq node temp) - (setq temp-object (js2-object-prop-node-right temp)))) + (setq temp-object (js2-infix-node-right temp)))) (unless names node))) (defun js2-search-scope (node names) "Searches NODE scope for jump location matching NAMES. NAMES is a list of property values to search for. For functions and variables NAMES will contain one element." - (let (node-init - (val (js2-name-node-name (car names)))) - (setq node-init (js2-get-symbol-declaration node val)) + (let (node-init val) + (cond + ((js2-name-node-p (car names)) + (setq val (js2-name-node-name (car names))) + (setq node-init (js2-get-symbol-declaration node val))) + ((and (js2-keyword-node-p (car names)) + (equal (js2-keyword-node-type (car names)) + js2-THIS)) + (let* ((scope (js2-node-get-enclosing-scope node)) + (parent (js2-node-parent scope))) + (when (or (js2-method-node-p parent) + (js2-object-prop-node-p parent)) + ;; class or object + (setq node-init (js2-node-parent parent)))))) (when (> (length names) 1) - - ;; Check var declarations - (when (and node-init (string= val (js2-name-node-name node-init))) - (let ((parent (js2-node-parent node-init)) - (temp-names names)) - (pop temp-names) ;; First element is var name - (setq node-init (when (js2-var-init-node-p parent) - (js2-search-object-for-prop - (js2-var-init-node-initializer parent) - temp-names))))) + (when node-init + (cond + ((js2-name-node-p (car names)) + ;; Check var declarations + (when (string= val (js2-name-node-name node-init)) + (let ((parent (js2-node-parent node-init))) + (setq node-init (when (js2-var-init-node-p parent) + (js2-search-object-for-prop + (js2-var-init-node-initializer parent) + (cdr names))))))) + ((js2-object-node-p node-init) + (setq node-init (js2-search-object-for-prop + node-init + (cdr names)))))) ;; Check all assign nodes (js2-visit-ast @@ -12964,11 +13022,17 @@ and variables NAMES will contain one element." (temp-names names)) (when (js2-prop-get-node-p left) (let* ((prop-list (js2-compute-nested-prop-get left)) - (found (cl-loop for prop in prop-list - until (not (string= (js2-name-node-name - (pop temp-names)) - (js2-name-node-name prop))) - if (not temp-names) return prop)) + ;; 'this' or 'super' + (target-is-keyword (js2-keyword-node-p (car temp-names))) + (_ (when target-is-keyword + (pop temp-names))) + (found (unless target-is-keyword + (cl-loop for prop in prop-list + until (not (string= (js2-name-node-name + (pop temp-names)) + (and (js2-name-node-p prop) + (js2-name-node-name prop)))) + if (not temp-names) return prop))) (found-node (or found (when (js2-object-node-p right) (js2-search-object-for-prop right diff --git a/lisp/ledger-mode/ledger-commodities.el b/lisp/ledger-mode/ledger-commodities.el index 50453dc8..bd0c51da 100644 --- a/lisp/ledger-mode/ledger-commodities.el +++ b/lisp/ledger-mode/ledger-commodities.el @@ -119,7 +119,7 @@ See `ledger-environment-alist' for DECIMAL-COMMA." (assoc "decimal-comma" ledger-environment-alist)) (ledger-strip str "[.]") (ledger-strip str ",")))) - (while (string-match "," nstr) ;if there is a comma now, it is a thousands separator + (while (string-match "," nstr) ;if there is a comma now, it is a decimal point (setq nstr (replace-match "." nil nil nstr))) (string-to-number nstr))) diff --git a/lisp/ledger-mode/ledger-complete.el b/lisp/ledger-mode/ledger-complete.el index 2bf2cec1..34bd38c7 100644 --- a/lisp/ledger-mode/ledger-complete.el +++ b/lisp/ledger-mode/ledger-complete.el @@ -295,12 +295,11 @@ Looks in `ledger-accounts-file' if set, otherwise the current buffer." (setq start (save-excursion (backward-word) (point))) (setq collection #'ledger-payees-in-buffer)) (;; Accounts - (looking-back (rx-to-string `(seq bol (one-or-more space) - (optional (any ?\( ?\[ )) ;; for virtual accounts - (group (zero-or-more (not space))))) - (line-beginning-position)) - (setq start (match-beginning 1) - delete-suffix (save-excursion + (save-excursion + (back-to-indentation) + (skip-chars-forward "([") ;; for virtual accounts + (setq start (point))) + (setq delete-suffix (save-excursion (when (search-forward-regexp (rx (or eol (repeat 2 space))) (line-end-position) t) (- (match-beginning 0) end))) realign-after t diff --git a/lisp/ledger-mode/ledger-context.el b/lisp/ledger-mode/ledger-context.el index 6485020d..b34e37b1 100644 --- a/lisp/ledger-mode/ledger-context.el +++ b/lisp/ledger-mode/ledger-context.el @@ -37,11 +37,11 @@ (defconst ledger-amount-string ledger-amount-regexp) (defconst ledger-commoditized-amount-string ledger-commoditized-amount-regexp) (defconst ledger-balance-assertion-string ledger-balance-assertion-regexp) -(defconst ledger-comment-string "[ \t]*;[ \t]*\\(.*?\\)") +(defconst ledger-comment-string "\\(?:[ \t]*\n\\)?[ \t]*;[ \t]*\\(.*?\\)") (defconst ledger-nil-string "\\([ \t]+\\)") (defconst ledger-date-string "^\\([0-9]\\{4\\}[/-][01]?[0-9][/-][0123]?[0-9]\\)\\(?:=[0-9]\\{4\\}[/-][01]?[0-9][/-][0123]?[0-9]\\)?") (defconst ledger-code-string "\\((.*)\\)?") -(defconst ledger-payee-string "\\(.*[^[:space:]]\\)") +(defconst ledger-payee-string "\\(.*[^[:space:]\n]\\)") (defun ledger-get-regex-str (name) diff --git a/lisp/ledger-mode/ledger-exec.el b/lisp/ledger-mode/ledger-exec.el index 8568854c..41a9dac7 100644 --- a/lisp/ledger-mode/ledger-exec.el +++ b/lisp/ledger-mode/ledger-exec.el @@ -31,7 +31,7 @@ "The version of ledger executable needed for interactive features.") (defvar ledger-works nil - "Flag showing whether the ledger binary can support `ledger-mode' interactive features.") + "Non-nil if the ledger binary can support `ledger-mode' interactive features.") (defgroup ledger-exec nil "Interface to the Ledger command-line accounting program." @@ -89,6 +89,7 @@ otherwise the error output is displayed and an error is raised." (apply #'call-process-region (append (list (point-min) (point-max) ledger-binary-path nil (list outbuf errfile) nil "-f" "-") + (list "--date-format" ledger-default-date-format) args))))) (if (ledger-exec-success-p exit-code outbuf) outbuf diff --git a/lisp/ledger-mode/ledger-fonts.el b/lisp/ledger-mode/ledger-fonts.el index 93cea883..90dd81c6 100644 --- a/lisp/ledger-mode/ledger-fonts.el +++ b/lisp/ledger-mode/ledger-fonts.el @@ -360,7 +360,7 @@ :group 'ledger-faces) (defface ledger-font-posting-account-face - `((t :inherit ledger-font-default-face)) + `((t :inherit ledger-font-default-directive-face)) "Face for Ledger accounts" :group 'ledger-faces) @@ -599,7 +599,7 @@ See `font-lock-keywords' for the full description." (,(concat "^\\(P\\)" "\\(?:[[:blank:]]+\\([^[:blank:]\n]+" "\\(?:[[:blank:]]+[[:digit:]][^[:blank:]\n]*\\)?\\)" - "\\(?:[[:blank:]]+\\([^[:blank:]\n]+\\)" + "\\(?:[[:blank:]]+\\(\".*?\"\\|[^[:blank:]\n]+\\)" "\\(?:[[:blank:]]+\\(.*\\)\\)?\\)?\\)?$") (1 'ledger-font-price-directive-face) (2 'ledger-font-price-date-face nil :lax) @@ -653,7 +653,7 @@ See `font-lock-keywords' for the full description." ledger-xact-after-date-regex "\\)") ; mark 4, code 5, desc 6, comment 7 (1 (cond ((equal "=" (match-string 2)) 'ledger-font-auto-xact-face) ((equal "~" (match-string 2)) 'ledger-font-periodic-xact-face) - (t 'ledger-font-default-face)) + (t 'ledger-font-default-directive-face)) nil :lax) (3 'ledger-font-posting-date-face nil :lax) (5 'ledger-font-code-face nil :lax) diff --git a/lisp/ledger-mode/ledger-init.el b/lisp/ledger-mode/ledger-init.el index ce39066c..ad0cbab8 100644 --- a/lisp/ledger-mode/ledger-init.el +++ b/lisp/ledger-mode/ledger-init.el @@ -37,6 +37,9 @@ Adding the dotted pair (\"decimal-comma\" . t) will tell ledger to treat commas as decimal separator.") +(defconst ledger-iso-date-format "%Y-%m-%d" + "The format for ISO 8601 dates.") + (defcustom ledger-default-date-format "%Y/%m/%d" "The date format that ledger uses throughout. Set this to the value of `ledger-iso-date-format' if you prefer @@ -45,9 +48,6 @@ ISO 8601 dates." :package-version '(ledger-mode . "4.0.0") :group 'ledger) -(defconst ledger-iso-date-format "%Y-%m-%d" - "The format for ISO 8601 dates.") - (defun ledger-format-date (&optional date) "Format DATE according to the current preferred date format. Returns the current date if DATE is nil or not supplied." @@ -81,17 +81,17 @@ Returns the current date if DATE is nil or not supplied." (defun ledger-init-load-init-file () "Load and parse the .ledgerrc file." (interactive) - (let ((init-base-name (file-name-nondirectory ledger-init-file-name))) - (if (get-buffer init-base-name) ;; init file already loaded, parse it and leave it - (setq ledger-environment-alist - (ledger-init-parse-initialization init-base-name)) - (when (and ledger-init-file-name - (file-exists-p ledger-init-file-name) - (file-readable-p ledger-init-file-name)) - (let ((init-buffer (find-file-noselect ledger-init-file-name))) + (when ledger-init-file-name + (let ((init-base-name (file-name-nondirectory ledger-init-file-name))) + (if (get-buffer init-base-name) ;; init file already loaded, parse it and leave it (setq ledger-environment-alist - (ledger-init-parse-initialization init-buffer)) - (kill-buffer init-buffer)))))) + (ledger-init-parse-initialization init-base-name)) + (when (and (file-exists-p ledger-init-file-name) + (file-readable-p ledger-init-file-name)) + (let ((init-buffer (find-file-noselect ledger-init-file-name))) + (setq ledger-environment-alist + (ledger-init-parse-initialization init-buffer)) + (kill-buffer init-buffer))))))) (provide 'ledger-init) diff --git a/lisp/ledger-mode/ledger-mode-pkg.el b/lisp/ledger-mode/ledger-mode-pkg.el index 032170cd..aaf89d66 100644 --- a/lisp/ledger-mode/ledger-mode-pkg.el +++ b/lisp/ledger-mode/ledger-mode-pkg.el @@ -1,6 +1,6 @@ -(define-package "ledger-mode" "20210106.227" "Helper code for use with the \"ledger\" command-line tool" +(define-package "ledger-mode" "20211214.1449" "Helper code for use with the \"ledger\" command-line tool" '((emacs "25.1")) - :commit "bcd8cefb720702db88986a52bb66e08e2e451c05") + :commit "3ec65b8931e8989ac590e95921e46f9e2fac6821") ;; Local Variables: ;; no-byte-compile: t ;; End: diff --git a/lisp/ledger-mode/ledger-mode.info b/lisp/ledger-mode/ledger-mode.info index 909de943..5a2a49f2 100644 --- a/lisp/ledger-mode/ledger-mode.info +++ b/lisp/ledger-mode/ledger-mode.info @@ -1,4 +1,4 @@ -This is ledger-mode.info, produced by makeinfo version 6.5 from +This is ledger-mode.info, produced by makeinfo version 6.7 from ledger-mode.texi. Copyright © 2013, Craig Earls. All rights reserved. @@ -147,9 +147,8 @@ entry. ‘C-c C-a’ or using ‘Add Transaction’ menu entry. Then typing a close match to the payee. Ledger-mode will call ‘ledger xact’ with the data you enter and place the transaction in the proper chronological place in -the ledger. Subsequent calls to ‘C-c C-a’ remember the last date so -entering many dates in the past is easy. The date format can be changed -by modifying ‘ledger-default-date-format’. +the ledger. The date format can be changed by modifying +‘ledger-default-date-format’.  File: ledger-mode.info, Node: Reconciliation, Next: Reports, Prev: Quick Add, Up: Quick Demo @@ -1494,58 +1493,58 @@ Node: Quick Installation2785 Node: Menus3717 Node: Quick Demo4032 Node: Quick Add4462 -Node: Reconciliation5662 -Node: Reports7346 -Node: Narrowing8376 -Node: The Ledger Buffer8960 -Node: Navigating Transactions9366 -Node: Adding Transactions9914 -Node: Setting a Transactions Effective Date11413 -Node: Quick Balance Display12313 -Node: Copying Transactions12845 -Node: Editing Amounts13447 -Node: Marking Transactions14518 -Node: Formatting Transactions16213 -Node: Deleting Transactions16811 -Node: Sorting Transactions17251 -Node: Narrowing Transactions18803 -Node: The Reconcile Buffer20653 -Node: Basics of Reconciliation21118 -Node: Starting a Reconciliation22067 -Node: Mark Transactions Pending23916 -Node: Edit Transactions During Reconciliation24585 -Node: Finalize Reconciliation25228 -Node: Adding and Deleting Transactions during Reconciliation25885 -Node: Changing Reconciliation Account26469 -Node: Changing Reconciliation Target27019 -Node: The Report Buffer27337 -Node: Running Basic Reports27595 -Node: Adding and Editing Reports29028 -Node: Expansion Formats30415 -Node: Make Report Transactions Active32056 -Node: Reversing Report Order32763 -Node: Scheduling Transactions33456 -Node: Specifying Upcoming Transactions34312 -Node: Transactions that occur on specific dates34886 -Node: Transactions that occur on specific days35927 -Node: Customizing Ledger-mode37056 -Node: Ledger-mode Customization37320 -Node: Customization Variables38005 -Node: Ledger Customization Group38485 -Node: Ledger Reconcile Customization Group39125 -Node: Ledger Report Customization Group42068 -Node: Ledger Faces Customization Group42787 -Node: Ledger Post Customization Group44534 -Node: Ledger Exec Customization Group45361 -Node: Ledger Test Customization Group45860 -Node: Ledger Texi Customization Group46262 -Node: Generating Ledger Regression Tests46754 -Node: Embedding Example results in Ledger Documentation47017 -Node: Hacking Ledger-mode47306 -Node: Use org-like outlines47531 -Node: Concept Index48196 -Node: Command & Variable Index53712 -Node: Keystroke Index61822 +Node: Reconciliation5560 +Node: Reports7244 +Node: Narrowing8274 +Node: The Ledger Buffer8858 +Node: Navigating Transactions9264 +Node: Adding Transactions9812 +Node: Setting a Transactions Effective Date11311 +Node: Quick Balance Display12211 +Node: Copying Transactions12743 +Node: Editing Amounts13345 +Node: Marking Transactions14416 +Node: Formatting Transactions16111 +Node: Deleting Transactions16709 +Node: Sorting Transactions17149 +Node: Narrowing Transactions18701 +Node: The Reconcile Buffer20551 +Node: Basics of Reconciliation21016 +Node: Starting a Reconciliation21965 +Node: Mark Transactions Pending23814 +Node: Edit Transactions During Reconciliation24483 +Node: Finalize Reconciliation25126 +Node: Adding and Deleting Transactions during Reconciliation25783 +Node: Changing Reconciliation Account26367 +Node: Changing Reconciliation Target26917 +Node: The Report Buffer27235 +Node: Running Basic Reports27493 +Node: Adding and Editing Reports28926 +Node: Expansion Formats30313 +Node: Make Report Transactions Active31954 +Node: Reversing Report Order32661 +Node: Scheduling Transactions33354 +Node: Specifying Upcoming Transactions34210 +Node: Transactions that occur on specific dates34784 +Node: Transactions that occur on specific days35825 +Node: Customizing Ledger-mode36954 +Node: Ledger-mode Customization37218 +Node: Customization Variables37903 +Node: Ledger Customization Group38383 +Node: Ledger Reconcile Customization Group39023 +Node: Ledger Report Customization Group41966 +Node: Ledger Faces Customization Group42685 +Node: Ledger Post Customization Group44432 +Node: Ledger Exec Customization Group45259 +Node: Ledger Test Customization Group45758 +Node: Ledger Texi Customization Group46160 +Node: Generating Ledger Regression Tests46652 +Node: Embedding Example results in Ledger Documentation46915 +Node: Hacking Ledger-mode47204 +Node: Use org-like outlines47429 +Node: Concept Index48094 +Node: Command & Variable Index53610 +Node: Keystroke Index61720  End Tag Table diff --git a/lisp/ledger-mode/ledger-occur.el b/lisp/ledger-mode/ledger-occur.el index bfd006e8..a412c25d 100644 --- a/lisp/ledger-mode/ledger-occur.el +++ b/lisp/ledger-mode/ledger-occur.el @@ -35,7 +35,8 @@ (defconst ledger-occur-overlay-property-name 'ledger-occur-custom-buffer-grep) (defcustom ledger-occur-use-face-shown t - "If non-nil, use a custom face for xacts shown in `ledger-occur' mode using ledger-occur-xact-face." + "If non-nil, use a custom face for xacts shown in `ledger-occur' mode. +This uses `ledger-occur-xact-face'." :type 'boolean :group 'ledger) (make-variable-buffer-local 'ledger-occur-use-face-shown) @@ -52,9 +53,9 @@ (define-minor-mode ledger-occur-mode "A minor mode which display only transactions matching `ledger-occur-current-regex'." - nil - (:eval (format " Ledger-Narrow(%s)" ledger-occur-current-regex)) - ledger-occur-mode-map + :init-value nil + :lighter (:eval (format " Ledger-Narrow(%s)" ledger-occur-current-regex)) + :keymap ledger-occur-mode-map (if (and ledger-occur-current-regex ledger-occur-mode) (ledger-occur-refresh) (ledger-occur-remove-overlays) diff --git a/lisp/ledger-mode/ledger-post.el b/lisp/ledger-mode/ledger-post.el index 6cfaa7a5..932127a0 100644 --- a/lisp/ledger-mode/ledger-post.el +++ b/lisp/ledger-mode/ledger-post.el @@ -26,6 +26,8 @@ (require 'ledger-regex) (require 'ledger-navigate) +(declare-function ledger-string-to-number "ledger-commodities" (str &optional decimal-comma)) + ;;; Code: (defgroup ledger-post nil @@ -168,7 +170,9 @@ regular text." (delete-region (match-beginning 0) (match-end 0)) (push-mark) (calc) - (calc-eval val-string 'push)) ;; edit the amount + ;; edit the amount, first removing thousands separators and + ;; converting decimal commas to calc's input format + (calc-eval (number-to-string (ledger-string-to-number val-string)) 'push)) (progn ;;make sure there are two spaces after the account name and go to calc (if (search-backward " " (- (point) 3) t) (goto-char (line-end-position)) diff --git a/lisp/ledger-mode/ledger-reconcile.el b/lisp/ledger-mode/ledger-reconcile.el index 6452cb2b..b6a33a6d 100644 --- a/lisp/ledger-mode/ledger-reconcile.el +++ b/lisp/ledger-mode/ledger-reconcile.el @@ -55,7 +55,7 @@ :group 'ledger-reconcile) (defcustom ledger-narrow-on-reconcile t - "If t, limit transactions shown in main buffer to those matching the reconcile regex." + "If t, show only transactions matching the reconcile regex in the main buffer." :type 'boolean :group 'ledger-reconcile) @@ -67,7 +67,7 @@ buffer then that transaction will be shown in its source buffer." :group 'ledger-reconcile) (defcustom ledger-reconcile-force-window-bottom nil - "If t, make the reconcile window appear along the bottom of the register window and resize." + "If t, show the reconcile window below the register window and resize." :type 'boolean :group 'ledger-reconcile) @@ -121,12 +121,13 @@ if string is longer, it is not truncated unless (defcustom ledger-reconcile-sort-key "(0)" "Key for sorting reconcile buffer. -Possible values are '(date)', '(amount)', '(payee)' or '(0)' for no sorting, i.e. using ledger file order." +Possible values are '(date)', '(amount)', '(payee)' or '(0)' for +no sorting, i.e. using ledger file order." :type 'string :group 'ledger-reconcile) (defcustom ledger-reconcile-insert-effective-date nil - "If t, prompt for effective date when clearing transactions during reconciliation." + "If t, prompt for effective date when clearing transactions." :type 'boolean :group 'ledger-reconcile) @@ -553,10 +554,10 @@ moved and recentered. If they aren't strange things happen." (add-hook 'after-save-hook 'ledger-reconcile-refresh-after-save nil t) ;; Narrow the ledger buffer + (if ledger-narrow-on-reconcile + (ledger-occur (regexp-quote account))) + (with-current-buffer rbuf - (save-excursion - (if ledger-narrow-on-reconcile - (ledger-occur account))) (if (> (ledger-reconcile-refresh) 0) (ledger-reconcile-change-target target)) (ledger-display-balance))))) diff --git a/lisp/ledger-mode/ledger-regex.el b/lisp/ledger-mode/ledger-regex.el index 6b0db98e..cd317a7c 100644 --- a/lisp/ledger-mode/ledger-regex.el +++ b/lisp/ledger-mode/ledger-regex.el @@ -28,7 +28,7 @@ (require 'rx) (require 'cl-lib) -(defvar ledger-iso-date-regex) +(defvar ledger-iso-date-regexp) (defconst ledger-amount-decimal-comma-regex "-?[1-9][0-9.]*[,]?[0-9]*") @@ -89,43 +89,49 @@ (defmacro ledger-define-regexp (name regex docs &rest args) "Simplify the creation of a Ledger regex and helper functions." - (let ((defs - (list - `(defconst - ,(intern (concat "ledger-" (symbol-name name) "-regexp")) - ,(eval regex) - ,docs))) - (addend 0) last-group) - (if (null args) - (progn - (nconc - defs + (let* ((regex (eval regex)) + (group-count (regexp-opt-depth regex)) + (defs (list `(defconst - ,(intern - (concat "ledger-regex-" (symbol-name name) "-group")) - 1))) - (nconc - defs - (list + ,(intern (concat "ledger-" (symbol-name name) "-regexp")) + ,regex + ,docs) `(defconst ,(intern (concat "ledger-regex-" (symbol-name name) "-group--count")) - 1))) - (nconc - defs - (list - `(defmacro - ,(intern (concat "ledger-regex-" (symbol-name name))) - (&optional string) - ,(format "Return the match string for the %s" name) - (match-string - ,(intern (concat "ledger-regex-" (symbol-name name) - "-group")) - string))))) + ,group-count))) + (addend 0) last-group) + (if (null args) + (progn + (when (cl-plusp group-count) + (nconc + defs + (list + `(defconst + ,(intern + (concat "ledger-regex-" (symbol-name name) "-group")) + 1))) + (nconc + defs + (list + `(defmacro + ,(intern (concat "ledger-regex-" (symbol-name name))) + (&optional string) + ,(format "Return the match string for the %s" name) + (match-string + ,(intern (concat "ledger-regex-" (symbol-name name) + "-group")) + string)))))) + + (while args + (let (arg var grouping target force-increment) + (setq arg (pop args)) + + (when (eq arg :separate) + (setq arg (pop args)) + (setq force-increment t)) - (dolist (arg args) - (let (var grouping target) (if (symbolp arg) (setq var arg target arg) (cl-assert (listp arg)) @@ -137,7 +143,8 @@ target (cl-caddr arg)))) (if (and last-group - (not (eq last-group (or grouping target)))) + (or (not (eq last-group (or grouping target))) + force-increment)) (cl-incf addend (symbol-value (intern-soft (concat "ledger-regex-" @@ -171,189 +178,170 @@ "-group-" (symbol-name var))) string)))) - (setq last-group (or grouping target)))) - - (nconc defs - (list - `(defconst ,(intern (concat "ledger-regex-" (symbol-name name) - "-group--count")) - ,(length args))))) + (setq last-group (or grouping target))))) (cons 'eval-and-compile defs))) (put 'ledger-define-regexp 'lisp-indent-function 1) (ledger-define-regexp iso-date - ( let ((sep '(or ?- ?/))) - (rx (group - (and (group (= 4 num)) - (eval sep) - (group (and num (? num))) - (eval sep) - (group (and num (? num))))))) - "Match a single date, in its 'written' form.") + (let ((sep '(or ?- ?/))) + (rx (group + (and (group (= 4 num)) + (eval sep) + (group (and num (? num))) + (eval sep) + (group (and num (? num))))))) + "Match a single date, in its 'written' form.") (ledger-define-regexp full-date - (macroexpand - `(rx (and (regexp ,ledger-iso-date-regexp) - (? (and ?= (regexp ,ledger-iso-date-regexp)))))) - "Match a compound date, of the form ACTUAL=EFFECTIVE" - (actual iso-date) - (effective iso-date)) + (macroexpand + `(rx (and (regexp ,ledger-iso-date-regexp) + (? (and ?= (regexp ,ledger-iso-date-regexp)))))) + "Match a compound date, of the form ACTUAL=EFFECTIVE" + (actual iso-date) + :separate + (effective iso-date)) (ledger-define-regexp state - (rx (group (any ?! ?*))) - "Match a transaction or posting's \"state\" character.") + (rx (group (any ?! ?*))) + "Match a transaction or posting's \"state\" character.") (ledger-define-regexp code - (rx (and ?\( (group (+? (not (any ?\))))) ?\))) - "Match the transaction code.") + (rx (and ?\( (group (+? (not (any ?\))))) ?\))) + "Match the transaction code.") (ledger-define-regexp long-space - (rx (and (*? blank) - (or (and ? (or ? ?\t)) ?\t))) - "Match a \"long space\".") + (rx (and (*? blank) + (or (and ? (or ? ?\t)) ?\t))) + "Match a \"long space\".") (ledger-define-regexp note - (rx (group (+ nonl))) - "") + (rx (group (+ nonl))) + "") (ledger-define-regexp end-note - (macroexpand - `(rx (and (regexp ,ledger-long-space-regexp) ?\; - (regexp ,ledger-note-regexp)))) - "") + (macroexpand + `(rx (and (regexp ,ledger-long-space-regexp) ?\; + (regexp ,ledger-note-regexp)))) + "") (ledger-define-regexp full-note - (macroexpand - `(rx (and line-start (+ blank) - ?\; (regexp ,ledger-note-regexp)))) - "") + (macroexpand + `(rx (and line-start (+ blank) + ?\; (regexp ,ledger-note-regexp)))) + "") (ledger-define-regexp xact-line - (macroexpand - `(rx (and line-start - (regexp ,ledger-full-date-regexp) - (? (and (+ blank) (regexp ,ledger-state-regexp))) - (? (and (+ blank) (regexp ,ledger-code-regexp))) - (+ blank) (+? nonl) - (? (regexp ,ledger-end-note-regexp)) - line-end))) - "Match a transaction's first line (and optional notes)." - (actual-date full-date actual) - (effective-date full-date effective) - state - code - (note end-note)) - -(ledger-define-regexp recurring-line - (macroexpand - `(rx (and line-start - (regexp "\\[.+/.+/.+\\]") - (? (and (+ blank) (regexp ,ledger-state-regexp))) - (? (and (+ blank) (regexp ,ledger-code-regexp))) - (+ blank) (+? nonl) - (? (regexp ,ledger-end-note-regexp)) - line-end))) - "Match a transaction's first line (and optional notes)." - (actual-date full-date actual) - (effective-date full-date effective) - state - code - (note end-note)) + (macroexpand + `(rx (and line-start + (regexp ,ledger-full-date-regexp) + (? (and (+ blank) (regexp ,ledger-state-regexp))) + (? (and (+ blank) (regexp ,ledger-code-regexp))) + (+ blank) (+? nonl) + (? (regexp ,ledger-end-note-regexp)) + line-end))) + "Match a transaction's first line (and optional notes)." + (actual-date full-date actual) + (effective-date full-date effective) + state + code + (note end-note)) (ledger-define-regexp account - (rx (group (and (not (any blank ?\[ ?\( ?: ?\;)) (*? nonl)))) - "") + (rx (group (and (not (any blank ?\[ ?\( ?: ?\;)) (*? nonl)))) + "") (ledger-define-regexp account-kind - (rx (group (? (any ?\[ ?\()))) - "") + (rx (group (? (any ?\[ ?\()))) + "") (ledger-define-regexp full-account - (macroexpand - `(rx (and (regexp ,ledger-account-kind-regexp) - (regexp ,ledger-account-regexp) - (? (any ?\] ?\)))))) - "" - (kind account-kind) - (name account)) + (macroexpand + `(rx (and (regexp ,ledger-account-kind-regexp) + (regexp ,ledger-account-regexp) + (? (any ?\] ?\)))))) + "" + (kind account-kind) + (name account)) (ledger-define-regexp commodity-no-group - (rx (or (and ?\" (+ (not (any ?\"))) ?\") - (+ (not (any blank ?\n - digit - ?- ?\[ ?\] - ?. ?, ?\; ?+ ?* ?/ ?^ ?? ?: ?& ?| ?! ?= - ?\< ?\> ?\{ ?\} ?\( ?\) ?@))))) - "") + (rx (or (and ?\" (+ (not (any ?\"))) ?\") + (+ (not (any blank ?\n + digit + ?- ?\[ ?\] + ?. ?, ?\; ?+ ?* ?/ ?^ ?? ?: ?& ?| ?! ?= + ?\< ?\> ?\{ ?\} ?\( ?\) ?@))))) + "") (ledger-define-regexp commodity - (macroexpand - `(rx (group (regexp ,ledger-commodity-no-group-regexp)))) - "") + (macroexpand + `(rx (group (regexp ,ledger-commodity-no-group-regexp)))) + "") (ledger-define-regexp amount-no-group - (rx (and (? ?-) - (+ digit) - (*? (and (any ?. ?,) (+ digit))))) - "") + (rx (and (? ?-) + (+ digit) + (*? (and (any ?. ?,) (+ digit))))) + "") (ledger-define-regexp amount - (macroexpand - `(rx (group (regexp ,ledger-amount-no-group-regexp)))) - "") + (macroexpand + `(rx (group (regexp ,ledger-amount-no-group-regexp)))) + "") (ledger-define-regexp commoditized-amount - (macroexpand - `(rx (group - (or (and (regexp ,ledger-commodity-no-group-regexp) - (*? blank) - (regexp ,ledger-amount-no-group-regexp)) - (and (regexp ,ledger-amount-no-group-regexp) - (*? blank) - (regexp ,ledger-commodity-no-group-regexp)))))) - "") + (macroexpand + `(rx (group + (or (and (regexp ,ledger-commodity-no-group-regexp) + (*? blank) + (regexp ,ledger-amount-no-group-regexp)) + (and (regexp ,ledger-amount-no-group-regexp) + (*? blank) + (regexp ,ledger-commodity-no-group-regexp)))))) + "") (ledger-define-regexp commodity-annotations - (macroexpand - `(rx (* (+ blank) - (or (and ?\{ (regexp ,ledger-commoditized-amount-regexp) ?\}) - (and ?\[ (regexp ,ledger-iso-date-regexp) ?\]) - (and ?\( (not (any ?\))) ?\)))))) - "") + (macroexpand + `(rx (* (+ blank) + (or (and ?\{ (regexp ,ledger-commoditized-amount-regexp) ?\}) + (and ?\[ (regexp ,ledger-iso-date-regexp) ?\]) + (and ?\( (not (any ?\))) ?\)))))) + "" + commoditized-amount + iso-date) (ledger-define-regexp cost - (macroexpand - `(rx (and (or "@" "@@") (+ blank) - (regexp ,ledger-commoditized-amount-regexp)))) - "") + (macroexpand + `(rx (and (or "@" "@@") (+ blank) + (regexp ,ledger-commoditized-amount-regexp)))) + "") (ledger-define-regexp balance-assertion - (macroexpand - `(rx (and ?= (+ blank) - (regexp ,ledger-commoditized-amount-regexp)))) - "") + (macroexpand + `(rx (and ?= (+ blank) + (regexp ,ledger-commoditized-amount-regexp)))) + "") (ledger-define-regexp full-amount - (macroexpand `(rx (group (+? (not (any ?\;)))))) - "") + (rx (group (+? (not (any ?\;))))) + "") (ledger-define-regexp post-line - (macroexpand - `(rx (and line-start (+ blank) - (? (and (regexp ,ledger-state-regexp) (* blank))) - (regexp ,ledger-full-account-regexp) - (? (and (regexp ,ledger-long-space-regexp) - (regexp ,ledger-full-amount-regexp))) - (? (regexp ,ledger-end-note-regexp)) - line-end))) - "" - state - (account-kind full-account kind) - (account full-account name) - (amount full-amount) - (note end-note)) + (macroexpand + `(rx (and line-start (+ blank) + (? (and (regexp ,ledger-state-regexp) (* blank))) + (regexp ,ledger-full-account-regexp) + (? (and (regexp ,ledger-long-space-regexp) + (regexp ,ledger-full-amount-regexp))) + (? (regexp ,ledger-end-note-regexp)) + line-end))) + "" + state + (account-kind full-account kind) + (account full-account name) + (amount full-amount) + (note end-note)) (defconst ledger-amount-regex (concat "\\( \\|\t\\| \t\\)[ \t]*-?" @@ -370,13 +358,32 @@ "\\([ \t]*[@={]@?[^\n;]+?\\)?" "\\([ \t]+;.+?\\|[ \t]*\\)?$")) -(defconst ledger-iterate-regex - (concat "\\(\\(?:Y\\|year\\)\\s-+\\([0-9]+\\)\\|" ;; Catches a Y/year directive - ledger-iso-date-regexp - "\\([ *!]+\\)" ;; mark - "\\((.*)\\)?" ;; code - "\\([[:word:] ]+\\)" ;; desc - "\\)")) +(ledger-define-regexp year + (rx (group (+ (any "0-9")))) + "") + +(ledger-define-regexp payee + (rx (group (+? nonl))) + "") + +(ledger-define-regexp iterate + (macroexpand `(rx (or (and (or "Y" "year") + (+ (syntax ?-)) + (regexp ,ledger-year-regexp)) + (and (regexp ,ledger-full-date-regexp) + (? (and (+ blank) (regexp ,ledger-state-regexp))) + (? (and (+ blank) (regexp ,ledger-code-regexp))) + (+ blank) + (regexp ,ledger-payee-regexp) + (? (regexp ,ledger-end-note-regexp)))))) + "" + year + (actual-date full-date actual) + (effective-date full-date effective) + state + code + payee + (note end-note)) (defconst ledger-incomplete-date-regexp "\\(?:\\([0-9]\\{1,2\\}\\)[-/]\\)?\\([0-9]\\{1,2\\}\\)") diff --git a/lisp/ledger-mode/ledger-report.el b/lisp/ledger-mode/ledger-report.el index 4f91dbf8..f11d9eb4 100644 --- a/lisp/ledger-mode/ledger-report.el +++ b/lisp/ledger-mode/ledger-report.el @@ -87,7 +87,7 @@ simply concatenated (no quoting)." :group 'ledger-report) (defcustom ledger-report-auto-refresh-sticky-cursor nil - "If non-nil, place cursor at same relative position as it was before auto-refresh." + "If non-nil, keep cursor's relative position after auto-refresh." :type 'boolean :group 'ledger-report) @@ -103,7 +103,7 @@ simply concatenated (no quoting)." :group 'ledger-report) (defcustom ledger-report-native-highlighting-arguments '("--color" "--force-color") - "List of strings to pass to ledger when `ledger-report-use-native-highlighting' is non-nil. + "List of ledger args needed by `ledger-report-use-native-highlighting'. If you are using hledger instead of ledger, you might want to set this variable to `(\"--color=always\")'." diff --git a/lisp/ledger-mode/ledger-texi.el b/lisp/ledger-mode/ledger-texi.el index 45eb281b..61254f02 100644 --- a/lisp/ledger-mode/ledger-texi.el +++ b/lisp/ledger-mode/ledger-texi.el @@ -137,8 +137,7 @@ (let ((section (match-string 1)) (example-name (match-string 2)) (command (match-string 3)) - (data-file ledger-texi-sample-doc-path) - input output) + (data-file ledger-texi-sample-doc-path)) (goto-char (match-end 0)) (forward-line) (when (looking-at "@\\(\\(?:small\\)?example\\)") @@ -171,7 +170,7 @@ "@end " section-name ?\n)) ;; Update the regression test associated with this example - (ledger-texi-write-test example-name command input output + (ledger-texi-write-test example-name command nil nil "../test/manual"))))) (provide 'ledger-texi) diff --git a/lisp/ledger-mode/ledger-xact.el b/lisp/ledger-mode/ledger-xact.el index b0b4dc16..ff4bb421 100644 --- a/lisp/ledger-mode/ledger-xact.el +++ b/lisp/ledger-mode/ledger-xact.el @@ -40,6 +40,13 @@ :type 'boolean :group 'ledger) +(defcustom ledger-add-transaction-prompt-for-text t + "When non-nil, use ledger xact to format transaction. +When nil, `ledger-add-transaction' will not prompt twice." + :type 'boolean + :package-version '(ledger-mode . "4.0.1") + :group 'ledger) + (defvar-local ledger-xact-highlight-overlay (list)) (defun ledger-highlight-make-overlay () @@ -117,26 +124,26 @@ MOMENT is an encoded date" (let* ((now (current-time)) (current-year (nth 5 (decode-time now)))) (while (not (eobp)) - (when (looking-at ledger-iterate-regex) - (let ((found-y-p (match-string 2))) + (when (looking-at ledger-iterate-regexp) + (let ((found-y-p (match-string 1))) (if found-y-p (setq current-year (string-to-number found-y-p)) ;; a Y directive was found (let ((start (match-beginning 0)) - (year (match-string 4)) - (month (string-to-number (match-string 5))) - (day (string-to-number (match-string 6))) - (mark (match-string 7)) - (desc (match-string 9))) + (year (match-string (+ ledger-regex-iterate-group-actual-date 1))) + (month (string-to-number (match-string (+ ledger-regex-iterate-group-actual-date 2)))) + (day (string-to-number (match-string (+ ledger-regex-iterate-group-actual-date 3)))) + (state (match-string ledger-regex-iterate-group-state)) + (payee (match-string ledger-regex-iterate-group-payee))) (if (and year (> (length year) 0)) (setq year (string-to-number year))) (funcall callback start (encode-time 0 0 0 day month (or year current-year)) - mark desc))))) + state payee))))) (forward-line)))) (defcustom ledger-copy-transaction-insert-blank-line-after nil - "Non-nil means insert blank line after a transaction inserted with ‘ledger-copy-transaction-at-point’." + "When non-nil, insert a blank line after `ledger-copy-transaction-at-point'." :type 'boolean :group 'ledger) @@ -172,14 +179,10 @@ MOMENT is an encoded date" (defun ledger-read-transaction () "Read the text of a transaction, which is at least the current date." - (let* ((reference-date (or ledger-add-transaction-last-date (current-time))) - (full-date-string (ledger-format-date reference-date)) - ;; Pre-fill year and month, but not day: this assumes DD is the last format arg. - (initial-string (replace-regexp-in-string "[0-9]+$" "" full-date-string)) - (entered-string (ledger-read-date "Date: "))) - (if (string= initial-string entered-string) - full-date-string - entered-string))) + (let ((date (ledger-read-date "Date: "))) + (concat date " " + (when ledger-add-transaction-prompt-for-text + (read-string (concat "xact " date ": ") nil 'ledger-minibuffer-history))))) (defun ledger-parse-iso-date (date) "Try to parse DATE using `ledger-iso-date-regexp' and return a time value or nil." diff --git a/lisp/magit/AUTHORS.md b/lisp/magit/AUTHORS.md index f80e262f..44343b63 100644 --- a/lisp/magit/AUTHORS.md +++ b/lisp/magit/AUTHORS.md @@ -57,7 +57,6 @@ Contributors - Alexey Voinov - Alex Kost - Alex Ott -- Allen - Allen Li - Andreas Fuchs - Andreas Liljeqvist @@ -65,6 +64,7 @@ Contributors - Andrei Chițu - Andrew Eggenberger - Andrew Kirkpatrick +- Andrew Psaltis - Andrew Schwartzmeyer - Andrey Smirnov - Andriy Kmit' @@ -72,15 +72,18 @@ Contributors - Aria Edmonds - Arialdo Martini - Arnau Roig Ninerola +- Ashlynn Anderson - Barak A. Pearlmutter - Bar Magal - Bart Bakker - Basil L. Contovounesios - Bastian Beischer +- Bastian Beranek - Benjamin Motz - Ben North - Ben Walton - Bob Uhl +- Boruch Baum - Bradley Wright - Brandon W Maister - Brian Leung @@ -108,17 +111,18 @@ Contributors - Dan Erikson - Daniel Brockman - Daniel Farina +- Daniel Fleischer - Daniel Gröber - Daniel Hackney - Daniel Kraus - Daniel Mai - Daniel Martín +- Daniel Nagy - Dan LaManna - Danny Zhu - Dato Simó - David Abrahams - David Ellison -- David Ellison - David Hull - David L. Rager - David Wallin @@ -126,7 +130,6 @@ Contributors - Dennis Paskorz - Divye Kapoor - Dominique Quatravaux -- Dominique Quatravaux - Duianto Vebotci - Eli Barzilay - Eric Davis @@ -142,6 +145,8 @@ Contributors - Felix Yan - Feng Li - Florian Ragwitz +- Franklin Delehelle +- Frédéric Giquel - Fritz Grabo - Fritz Stelzer - Geoff Shannon @@ -158,6 +163,8 @@ Contributors - Hussein Ait-Lahcen - Ian Eure - Ian Milligan +- Ilya Grigoriev +- Ingmar Sittl - Ingo Lohmar - Ioan-Adrian Ratiu - Ivan Brennan @@ -180,6 +187,7 @@ Contributors - Jonathan del Strother - Jonathan Leech-Pepin - Jonathan Roes +- Jonathon McKitrick - Jon Vanderwijk - Jordan Galby - Jordan Greenberg @@ -207,6 +215,7 @@ Contributors - Leonardo Etcheverry - Leo Vivier - Lingchao Xin +- Lin Sun - Li-Yun Chang - Lluís Vilanova - Loic Dachary @@ -228,6 +237,8 @@ Contributors - Mark Hepburn - Mark Karpov - Mark Oteiza +- Martin Joerg +- Martin Polden - Matthew Fluet - Matthew Kraai - Matthieu Hauglustaine @@ -256,10 +267,12 @@ Contributors - Nikolay Martynov - Noam Postavsky - N. Troy de Freitas +- Ola x Nilsson - Ole Arndt - Oleh Krehel - Orivej Desh - Óscar Fuentes +- Pancho Horrillo - Paul Stadig - Pavel Holejsovsky - Pekka Pessi @@ -267,6 +280,7 @@ Contributors - Peter Jaros - Peter J. Weisberg - Peter Vasil +- Philippe Cavalaria - Philippe Vaucher - Philipp Fehre - Philipp Haselwarter @@ -277,6 +291,7 @@ Contributors - Pierre Neidhardt - Pieter Praet - Prathamesh Sonpatki +- Pritam Baral - rabio - Radon Rosborough - Rafael Laboissiere @@ -296,6 +311,7 @@ Contributors - Rüdiger Sonderfeld - Russell Black - Ryan C. Thompson +- Sam Cedarbaum - Samuel Bronson - Samuel W. Flint - Sanjoy Das @@ -308,6 +324,7 @@ Contributors - Sergey Pashinin - Sergey Vinokurov - Servilio Afre Puentes +- Siavash Askari Nasr - Silent Sphere - Simon Pintarelli - Štěpán Němec @@ -322,6 +339,7 @@ Contributors - Szunti - Takafumi Arakaki - Tassilo Horn +- TEC - Teemu Likonen - Teruki Shigitani - Thierry Volpiatto @@ -336,6 +354,7 @@ Contributors - Tim Wraight - Ting-Yu Lin - Tom Feist +- Toon Claes - Topi Miettinen - Troy Hinckley - Tsuyoshi Kitamoto diff --git a/lisp/magit/LICENSE b/lisp/magit/LICENSE index 44325404..f288702d 100644 --- a/lisp/magit/LICENSE +++ b/lisp/magit/LICENSE @@ -1,12 +1,11 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. - Preamble + Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. @@ -69,7 +68,7 @@ patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. - TERMS AND CONDITIONS + TERMS AND CONDITIONS 0. Definitions. @@ -77,7 +76,7 @@ modification follow. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. - + "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. @@ -510,7 +509,7 @@ actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. - + If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties @@ -619,9 +618,9 @@ an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. - END OF TERMS AND CONDITIONS + END OF TERMS AND CONDITIONS - How to Apply These Terms to Your New Programs + How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it @@ -646,7 +645,7 @@ the "copyright" line and a pointer to where the full notice is found. 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 . Also add information on how to contact you by electronic and paper mail. @@ -665,12 +664,11 @@ might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see -. +. The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read -. - +. diff --git a/lisp/magit/git-rebase.el b/lisp/magit/git-rebase.el index b4e209e5..a893a64d 100644 --- a/lisp/magit/git-rebase.el +++ b/lisp/magit/git-rebase.el @@ -1,6 +1,6 @@ ;;; git-rebase.el --- Edit Git rebase files -*- lexical-binding: t -*- -;; Copyright (C) 2010-2021 The Magit Project Contributors +;; Copyright (C) 2010-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,7 +8,7 @@ ;; Author: Phil Jackson ;; Maintainer: Jonas Bernoulli -;; This file is not part of GNU Emacs. +;; SPDX-License-Identifier: GPL-3.0-or-later ;; 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 @@ -74,21 +74,13 @@ ;;; Code: -(require 'dash) +(require 'magit) + (require 'easymenu) (require 'server) (require 'with-editor) -(require 'magit) -(and (require 'async-bytecomp nil t) - (let ((pkgs (bound-and-true-p async-bytecomp-allowed-packages))) - (if (consp pkgs) - (cl-intersection '(all magit) pkgs) - (memq pkgs '(all t)))) - (fboundp 'async-bytecomp-package-mode) - (async-bytecomp-package-mode 1)) - -(eval-when-compile (require 'recentf)) +(defvar recentf-exclude) ;;; Options ;;;; Variables @@ -120,32 +112,37 @@ :group 'faces :group 'git-rebase) -(defface git-rebase-hash '((t (:inherit magit-hash))) +(defface git-rebase-hash '((t :inherit magit-hash)) "Face for commit hashes." :group 'git-rebase-faces) -(defface git-rebase-label '((t (:inherit magit-refname))) +(defface git-rebase-label '((t :inherit magit-refname)) "Face for labels in label, merge, and reset lines." :group 'git-rebase-faces) -(defface git-rebase-description nil +(defface git-rebase-description '((t nil)) "Face for commit descriptions." :group 'git-rebase-faces) +(defface git-rebase-action + '((t :inherit font-lock-keyword-face)) + "Face for action keywords." + :group 'git-rebase-faces) + (defface git-rebase-killed-action - '((t (:inherit font-lock-comment-face :strike-through t))) + '((t :inherit font-lock-comment-face :strike-through t)) "Face for commented commit action lines." :group 'git-rebase-faces) (defface git-rebase-comment-hash - '((t (:inherit git-rebase-hash :weight bold))) + '((t :inherit git-rebase-hash :weight bold)) "Face for commit hashes in commit message comments." :group 'git-rebase-faces) (defface git-rebase-comment-heading '((t :inherit font-lock-keyword-face)) "Face for headings in rebase message comments." - :group 'git-commit-faces) + :group 'git-rebase-faces) ;;; Keymaps @@ -451,7 +448,7 @@ current line." (when bounds (magit-section-make-overlay (car bounds) (cadr bounds) 'magit-section-heading-selection)) - (if (and bounds (not magit-keep-region-overlay)) + (if (and bounds (not magit-section-keep-region-overlay)) (funcall (default-value 'redisplay-unhighlight-region-function) rol) (funcall (default-value 'redisplay-highlight-region-function) start end window rol)))) @@ -739,25 +736,25 @@ running 'man git-rebase' at the command line) for details." (defun git-rebase-mode-font-lock-keywords () "Font lock keywords for Git-Rebase mode." `((,(concat "^" (cdr (assq 'commit git-rebase-line-regexps))) - (1 'font-lock-keyword-face) + (1 'git-rebase-action) (3 'git-rebase-hash) (4 'git-rebase-description)) (,(concat "^" (cdr (assq 'exec git-rebase-line-regexps))) - (1 'font-lock-keyword-face) + (1 'git-rebase-action) (3 'git-rebase-description)) (,(concat "^" (cdr (assq 'bare git-rebase-line-regexps))) - (1 'font-lock-keyword-face)) + (1 'git-rebase-action)) (,(concat "^" (cdr (assq 'label git-rebase-line-regexps))) - (1 'font-lock-keyword-face) + (1 'git-rebase-action) (3 'git-rebase-label) (4 'font-lock-comment-face)) ("^\\(m\\(?:erge\\)?\\) -[Cc] \\([^ \n]+\\) \\([^ \n]+\\)\\( #.*\\)?" - (1 'font-lock-keyword-face) + (1 'git-rebase-action) (2 'git-rebase-hash) (3 'git-rebase-label) (4 'font-lock-comment-face)) ("^\\(m\\(?:erge\\)?\\) \\([^ \n]+\\)" - (1 'font-lock-keyword-face) + (1 'git-rebase-action) (2 'git-rebase-label)) (,(concat git-rebase-comment-re " *" (cdr (assq 'commit git-rebase-line-regexps))) @@ -826,8 +823,8 @@ By default, this is the same except for the \"pick\" command." (add-to-list 'with-editor-server-window-alist (cons git-rebase-filename-regexp 'switch-to-buffer)) -(eval-after-load 'recentf - '(add-to-list 'recentf-exclude git-rebase-filename-regexp)) +(with-eval-after-load 'recentf + (add-to-list 'recentf-exclude git-rebase-filename-regexp)) (add-to-list 'with-editor-file-name-history-exclude git-rebase-filename-regexp) diff --git a/lisp/magit/magit-apply.el b/lisp/magit/magit-apply.el index 884913a1..3edae33c 100644 --- a/lisp/magit/magit-apply.el +++ b/lisp/magit/magit-apply.el @@ -1,6 +1,6 @@ ;;; magit-apply.el --- apply Git diffs -*- lexical-binding: t -*- -;; Copyright (C) 2010-2021 The Magit Project Contributors +;; Copyright (C) 2010-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -30,9 +32,6 @@ ;;; Code: -(eval-when-compile - (require 'subr-x)) - (require 'magit-core) (require 'magit-diff) (require 'magit-wip) @@ -40,8 +39,8 @@ (require 'transient) ; See #3732. ;; For `magit-apply' -(declare-function magit-am "magit-sequence" ()) -(declare-function magit-patch-apply "magit-files" ()) +(declare-function magit-am "magit-sequence" () t) +(declare-function magit-patch-apply "magit-patch" () t) ;; For `magit-discard-files' (declare-function magit-checkout-stage "magit-merge" (file arg)) (declare-function magit-checkout-read-stage "magit-merge" (file)) @@ -56,6 +55,11 @@ (declare-function borg-assimilate "borg" (package url &optional partially)) (defvar borg-user-emacs-directory) +(cl-eval-when (compile load) + (when (< emacs-major-version 26) + (defalias 'smerge-keep-upper 'smerge-keep-mine) + (defalias 'smerge-keep-lower 'smerge-keep-other))) + ;;; Options (defcustom magit-delete-by-moving-to-trash t @@ -178,7 +182,7 @@ adjusted as \"@@ -10,6 +10,7 @@\" and \"@@ -18,6 +19,7 @@\"." (offset (if (string-match diff-hunk-header-re-unified first-hunk) (- (string-to-number (match-string 3 first-hunk)) (string-to-number (match-string 1 first-hunk))) - (error "Hunk does not have expected header")))) + (error "Header hunks have to be applied individually")))) (if (= offset 0) hunks (mapcar (lambda (hunk) @@ -208,10 +212,15 @@ adjusted as \"@@ -10,6 +10,7 @@\" and \"@@ -18,6 +19,7 @@\"." (defun magit-apply-hunk (section &rest args) (when (string-match "^diff --cc" (magit-section-parent-value section)) (user-error "Cannot un-/stage resolution hunks. Stage the whole file")) - (magit-apply-patch (oref section parent) args - (concat (magit-diff-file-header section) - (magit-apply--adjust-hunk-new-start - (magit-apply--section-content section))))) + (let* ((header (car (oref section value))) + (header (and (symbolp header) header)) + (content (magit-apply--section-content section))) + (magit-apply-patch + (oref section parent) args + (concat (magit-diff-file-header section (not (eq header 'rename))) + (if header + content + (magit-apply--adjust-hunk-new-start content)))))) (defun magit-apply-region (section &rest args) (when (string-match "^diff --cc" (magit-section-parent-value section)) @@ -232,7 +241,7 @@ adjusted as \"@@ -10,6 +10,7 @@\" and \"@@ -18,6 +19,7 @@\"." (ignore-context (magit-diff-ignore-any-space-p))) (unless (magit-diff-context-p) (user-error "Not enough context to apply patch. Increase the context")) - (when (and magit-wip-before-change-mode (not inhibit-magit-refresh)) + (when (and magit-wip-before-change-mode (not magit-inhibit-refresh)) (magit-wip-commit-before-change files (concat " before " command))) (with-temp-buffer (insert patch) @@ -240,7 +249,7 @@ adjusted as \"@@ -10,6 +10,7 @@\" and \"@@ -18,6 +19,7 @@\"." "apply" args "-p0" (and ignore-context "-C0") "--ignore-space-change" "-")) - (unless inhibit-magit-refresh + (unless magit-inhibit-refresh (when magit-wip-after-apply-mode (magit-wip-commit-after-apply files (concat " after " command))) (magit-refresh)))) @@ -445,6 +454,8 @@ without requiring confirmation." (defun magit-unstage-all () "Remove all changes from the staging area." (interactive) + (unless (magit-anything-staged-p) + (user-error "Nothing to unstage")) (when (or (magit-anything-unstaged-p) (magit-untracked-files)) (magit-confirm 'unstage-all-changes)) @@ -455,7 +466,11 @@ without requiring confirmation." ;;;; Discard (defun magit-discard () - "Remove the change at point." + "Remove the change at point. + +On a hunk or file with unresolved conflicts prompt which side to +keep (while discarding the other). If point is within the text +of a side, then keep that side without prompting." (interactive) (--when-let (magit-apply--get-selection) (pcase (list (magit-diff-type) (magit-diff-scope)) @@ -474,7 +489,10 @@ without requiring confirmation." (defun magit-discard-hunk (section) (magit-confirm 'discard "Discard hunk") - (magit-discard-apply section 'magit-apply-hunk)) + (let ((file (magit-section-parent-value section))) + (pcase (cddr (car (magit-file-status file))) + (`(?U ?U) (magit-smerge-keep-current)) + (_ (magit-discard-apply section 'magit-apply-hunk))))) (defun magit-discard-apply (section apply) (if (eq (magit-diff-type section) 'unstaged) @@ -483,7 +501,7 @@ without requiring confirmation." nil (if (magit-file-section-p section) (oref section value) (magit-section-parent-value section))) - (progn (let ((inhibit-magit-refresh t)) + (progn (let ((magit-inhibit-refresh t)) (funcall apply section "--reverse" "--cached") (funcall apply section "--reverse" "--reject")) (magit-refresh)) @@ -503,7 +521,7 @@ without requiring confirmation." nil (if (magit-file-section-p section) (oref section value) (magit-section-parent-value section))) - (progn (let ((inhibit-magit-refresh t)) + (progn (let ((magit-inhibit-refresh t)) (funcall apply sections "--reverse" "--cached") (funcall apply sections "--reverse" "--reject")) (magit-refresh)) @@ -541,7 +559,7 @@ without requiring confirmation." (`(?Y ,_ ?D ) (push file resurrect)) (`(?X ?R ,(or ? ?M ?D)) (push file rename))))) (unwind-protect - (let ((inhibit-magit-refresh t)) + (let ((magit-inhibit-refresh t)) (magit-wip-commit-before-change files " before discard") (when resolve (magit-discard-files--resolve (nreverse resolve))) @@ -731,6 +749,60 @@ a separate commit. A typical workflow would be: (interactive) (magit-reverse (cons "--cached" args))) +;;; Smerge Support + +(defun magit-smerge-keep-current () + "Keep the current version of the conflict at point." + (interactive) + (magit-call-smerge #'smerge-keep-current)) + +(defun magit-smerge-keep-upper () + "Keep the upper/our version of the conflict at point." + (interactive) + (magit-call-smerge #'smerge-keep-upper)) + +(defun magit-smerge-keep-base () + "Keep the base version of the conflict at point." + (interactive) + (magit-call-smerge #'smerge-keep-base)) + +(defun magit-smerge-keep-lower () + "Keep the lower/their version of the conflict at point." + (interactive) + (magit-call-smerge #'smerge-keep-lower)) + +(defun magit-call-smerge (fn) + (pcase-let* ((file (magit-file-at-point t t)) + (keep (get-file-buffer file)) + (`(,buf ,pos) + (let ((magit-diff-visit-jump-to-change nil)) + (magit-diff-visit-file--noselect file)))) + (with-current-buffer buf + (save-excursion + (save-restriction + (unless (<= (point-min) pos (point-max)) + (widen)) + (goto-char pos) + (condition-case nil + (smerge-match-conflict) + (error + (if (eq fn 'smerge-keep-current) + (when (eq this-command 'magit-discard) + (re-search-forward smerge-begin-re nil t) + (setq fn + (magit-read-char-case "Keep side: " t + (?o "[o]urs/upper" #'smerge-keep-upper) + (?b "[b]ase" #'smerge-keep-base) + (?t "[t]heirs/lower" #'smerge-keep-lower)))) + (re-search-forward smerge-begin-re nil t)))) + (funcall fn))) + (when (and keep (magit-anything-unmerged-p file)) + (smerge-start-session)) + (save-buffer)) + (unless keep + (kill-buffer buf)) + (magit-refresh))) + ;;; _ (provide 'magit-apply) ;;; magit-apply.el ends here diff --git a/lisp/magit/magit-autorevert.el b/lisp/magit/magit-autorevert.el index a4952183..c998d7a6 100644 --- a/lisp/magit/magit-autorevert.el +++ b/lisp/magit/magit-autorevert.el @@ -1,6 +1,6 @@ ;;; magit-autorevert.el --- revert buffers when files in repository change -*- lexical-binding: t -*- -;; Copyright (C) 2010-2021 The Magit Project Contributors +;; Copyright (C) 2010-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -23,9 +25,6 @@ ;;; Code: -(require 'cl-lib) -(require 'dash) - (require 'magit-git) (require 'autorevert) diff --git a/lisp/magit/magit-bisect.el b/lisp/magit/magit-bisect.el index 8bb263c7..8f9fa408 100644 --- a/lisp/magit/magit-bisect.el +++ b/lisp/magit/magit-bisect.el @@ -1,6 +1,6 @@ ;;; magit-bisect.el --- bisect support for Magit -*- lexical-binding: t -*- -;; Copyright (C) 2011-2021 The Magit Project Contributors +;; Copyright (C) 2011-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -65,9 +67,9 @@ ("-p" "Follow only first parent of a merge" "--first-parent" :if (lambda () (version<= "2.29" (magit-git-version)))) (6 magit-bisect:--term-old - :if (lambda () (version<= "2.7" (magit-git-version)))) + :if (lambda () (version<= "2.7" (magit-git-version)))) (6 magit-bisect:--term-new - :if (lambda () (version<= "2.7" (magit-git-version))))] + :if (lambda () (version<= "2.7" (magit-git-version))))] ["Actions" ("B" "Start" magit-bisect-start) ("s" "Start script" magit-bisect-run)]] @@ -76,7 +78,7 @@ ("B" "Bad" magit-bisect-bad) ("g" "Good" magit-bisect-good) (6 "m" "Mark" magit-bisect-mark - :if (lambda () (version<= "2.7" (magit-git-version)))) + :if (lambda () (version<= "2.7" (magit-git-version)))) ("k" "Skip" magit-bisect-skip) ("r" "Reset" magit-bisect-reset) ("s" "Run script" magit-bisect-run)]) @@ -194,7 +196,14 @@ bisect run'." (magit-bisect-start-read-args)))) (cons (read-shell-command "Bisect shell command: ") args))) (when (and bad good) - (magit-bisect-start bad good args)) + ;; Avoid `magit-git-bisect' because it's asynchronous, but the + ;; next `git bisect run' call requires the bisect to be started. + (magit-with-toplevel + (magit-process-git + (list :file (magit-git-dir "BISECT_CMD_OUTPUT")) + (magit-process-git-arguments + (list "bisect" "start" bad good args))) + (magit-refresh))) (magit-git-bisect "run" (list shell-file-name shell-command-switch cmdline))) (defun magit-git-bisect (subcommand &optional args no-assert) diff --git a/lisp/magit/magit-blame.el b/lisp/magit/magit-blame.el index 87405ade..81c6219e 100644 --- a/lisp/magit/magit-blame.el +++ b/lisp/magit/magit-blame.el @@ -1,6 +1,6 @@ ;;; magit-blame.el --- blame support for Magit -*- lexical-binding: t -*- -;; Copyright (C) 2012-2021 The Magit Project Contributors +;; Copyright (C) 2012-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -28,9 +30,6 @@ ;;; Code: -(eval-when-compile - (require 'subr-x)) - (require 'magit) ;;; Options @@ -198,19 +197,19 @@ Also see option `magit-blame-styles'." Also see option `magit-blame-styles'." :group 'magit-faces) -(defface magit-blame-summary nil +(defface magit-blame-summary '((t nil)) "Face used for commit summaries when blaming." :group 'magit-faces) -(defface magit-blame-hash nil +(defface magit-blame-hash '((t nil)) "Face used for commit hashes when blaming." :group 'magit-faces) -(defface magit-blame-name nil +(defface magit-blame-name '((t nil)) "Face used for author and committer names when blaming." :group 'magit-faces) -(defface magit-blame-date nil +(defface magit-blame-date '((t nil)) "Face used for dates when blaming." :group 'magit-faces) @@ -228,25 +227,27 @@ Also see option `magit-blame-styles'." ;; filename (orig-file))) -(defun magit-current-blame-chunk (&optional type) +(defun magit-current-blame-chunk (&optional type noerror) (or (and (not (and type (not (eq type magit-blame-type)))) (magit-blame-chunk-at (point))) (and type (let ((rev (or magit-buffer-refname magit-buffer-revision)) - (file (magit-file-relative-name nil (not magit-buffer-file-name))) + (file (and (not (derived-mode-p 'dired-mode)) + (magit-file-relative-name + nil (not magit-buffer-file-name)))) (line (format "%i,+1" (line-number-at-pos)))) - (unless file - (error "Buffer does not visit a tracked file")) - (with-temp-buffer - (magit-with-toplevel - (magit-git-insert - "blame" "--porcelain" - (if (memq magit-blame-type '(final removal)) - (cons "--reverse" (magit-blame-arguments)) - (magit-blame-arguments)) - "-L" line rev "--" file) - (goto-char (point-min)) - (car (magit-blame--parse-chunk type)))))))) + (cond (file (with-temp-buffer + (magit-with-toplevel + (magit-git-insert + "blame" "--porcelain" + (if (memq magit-blame-type '(final removal)) + (cons "--reverse" (magit-blame-arguments)) + (magit-blame-arguments)) + "-L" line rev "--" file) + (goto-char (point-min)) + (car (magit-blame--parse-chunk type))))) + (noerror nil) + (t (error "Buffer does not visit a tracked file"))))))) (defun magit-blame-chunk-at (pos) (--some (overlay-get it 'magit-blame-chunk) @@ -489,10 +490,10 @@ modes is toggled, then this mode also gets toggled automatically. (while (not done) (cond ((looking-at "^filename \\(.+\\)") (setq done t) - (setf orig-file (match-string 1))) + (setf orig-file (magit-decode-git-path (match-string 1)))) ((looking-at "^previous \\(.\\{40\\}\\) \\(.+\\)") (setf prev-rev (match-string 1)) - (setf prev-file (match-string 2))) + (setf prev-file (magit-decode-git-path (match-string 2)))) ((looking-at "^\\([^ ]+\\) \\(.+\\)") (push (cons (match-string 1) (match-string 2)) revinfo))) @@ -702,9 +703,9 @@ modes is toggled, then this mode also gets toggled automatically. (when (magit-blame--style-get 'show-message) (let ((message-log-max 0)) (if-let ((msg (cdr (assoc "summary" - (gethash (oref (magit-current-blame-chunk) - orig-rev) - magit-blame-cache))))) + (gethash (oref (magit-current-blame-chunk) + orig-rev) + magit-blame-cache))))) (progn (set-text-properties 0 (length msg) nil msg) (message msg)) (message "Commit data not available yet. Still blaming."))))) @@ -896,6 +897,7 @@ instead of the hash, like `kill-ring-save' would." ["Arguments" ("-w" "Ignore whitespace" "-w") ("-r" "Do not treat root commits as boundaries" "--root") + ("-P" "Follow only first parent" "--first-parent") (magit-blame:-M) (magit-blame:-C)] ["Actions" @@ -915,12 +917,14 @@ instead of the hash, like `kill-ring-save' would." :description "Detect lines moved or copied within a file" :class 'transient-option :argument "-M" + :allow-empty t :reader 'transient-read-number-N+) (transient-define-argument magit-blame:-C () :description "Detect lines moved or copied between files" :class 'transient-option :argument "-C" + :allow-empty t :reader 'transient-read-number-N+) ;;; Utilities diff --git a/lisp/magit/magit-bookmark.el b/lisp/magit/magit-bookmark.el index 650dfc37..b65b3ace 100644 --- a/lisp/magit/magit-bookmark.el +++ b/lisp/magit/magit-bookmark.el @@ -1,6 +1,6 @@ ;;; magit-bookmark.el --- bookmark support for Magit -*- lexical-binding: t -*- -;; Copyright (C) 2010-2021 The Magit Project Contributors +;; Copyright (C) 2010-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -10,6 +10,8 @@ ;; Inspired by an earlier implementation by Yuri Khan. +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -29,9 +31,6 @@ ;;; Code: -(eval-when-compile - (require 'subr-x)) - (require 'magit) (require 'bookmark) @@ -43,7 +42,11 @@ Input values are the major-mode's `magit-bookmark-name' method, and the buffer-local values of the variables referenced in its `magit-bookmark-variables' property." (if (plist-member (symbol-plist major-mode) 'magit-bookmark-variables) - (let ((bookmark (bookmark-make-record-default 'no-file))) + ;; `bookmark-make-record-default's return value does not match + ;; (NAME . ALIST), even though it is used as the default value + ;; of `bookmark-make-record-function', which states that such + ;; functions must do that. See #4356. + (let ((bookmark (cons nil (bookmark-make-record-default 'no-file)))) (bookmark-prop-set bookmark 'handler 'magit--handle-bookmark) (bookmark-prop-set bookmark 'mode major-mode) (bookmark-prop-set bookmark 'filename (magit-toplevel)) @@ -87,6 +90,9 @@ with the variables' values as arguments, which were recorded by hidden) (magit-section-hide child) (magit-section-show child))))) + ;; Compatibility with `bookmark+' package. See #4356. + (when (bound-and-true-p bmkp-jump-display-function) + (funcall bmkp-jump-display-function (current-buffer))) nil)) (cl-defgeneric magit-bookmark-name () diff --git a/lisp/magit/magit-branch.el b/lisp/magit/magit-branch.el index e1cbc855..d3db6774 100644 --- a/lisp/magit/magit-branch.el +++ b/lisp/magit/magit-branch.el @@ -1,6 +1,6 @@ ;;; magit-branch.el --- branch support -*- lexical-binding: t -*- -;; Copyright (C) 2010-2021 The Magit Project Contributors +;; Copyright (C) 2010-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -31,9 +33,6 @@ ;;; Code: -(eval-when-compile - (require 'subr-x)) - (require 'magit) (require 'magit-reset) @@ -115,7 +114,8 @@ should be used as the upstream. This option allows specifying the branch that should be used as the upstream when branching certain remote branches. The value is an alist of the form ((UPSTREAM . RULE)...). The first -matching element is used, the following elements are ignored. +element is used whose UPSTREAM exists and whose RULE matches +the name of the new branch. Subsequent elements are ignored. UPSTREAM is the branch to be used as the upstream for branches specified by RULE. It can be a local or a remote branch. @@ -129,7 +129,7 @@ part of the name of the branch that is being branched from. If you use a finite set of non-ephemeral branches across all your repositories, then you might use something like: - ((\"origin/master\" \"master\" \"next\" \"maint\")) + ((\"origin/master\" . (\"master\" \"next\" \"maint\"))) Or if the names of all your ephemeral branches contain a slash, at least in some repositories, then a good value could be: @@ -141,6 +141,16 @@ Of course you can also fine-tune: ((\"origin/maint\" . \"\\\\\\=`hotfix/\") (\"origin/master\" . \"\\\\\\=`feature/\")) +UPSTREAM can be a local branch: + + ((\"master\" . (\"master\" \"next\" \"maint\"))) + +Because the main branch is no longer almost always named \"master\" +you should also account for other common names: + + ((\"main\" . (\"main\" \"master\" \"next\" \"maint\")) + (\"master\" . (\"main\" \"master\" \"next\" \"maint\"))) + If you use remote branches as UPSTREAM, then you might also want to set `magit-branch-prefer-remote-upstream' to a non-nil value. However, I recommend that you use local branches as UPSTREAM." @@ -204,6 +214,10 @@ has to be used to view and change branch related variables." (transient-define-prefix magit-branch (branch) "Add, configure or remove a branch." :man-page "git-branch" + ["Arguments" + (7 "-r" "Recurse submodules when checking out an existing branch" + "--recurse-submodules" + :if (lambda () (version<= "2.13" (magit-git-version))))] ["Variables" :if (lambda () (and magit-branch-direct-configure @@ -235,18 +249,22 @@ has to be used to view and change branch related variables." (interactive (list (magit-get-current-branch))) (transient-setup 'magit-branch nil nil :scope branch)) +(defun magit-branch-arguments () + (transient-args 'magit-branch)) + ;;;###autoload -(defun magit-checkout (revision) +(defun magit-checkout (revision &optional args) "Checkout REVISION, updating the index and the working tree. If REVISION is a local branch, then that becomes the current branch. If it is something else, then `HEAD' becomes detached. Checkout fails if the working tree or the staging area contain changes. \n(git checkout REVISION)." - (interactive (list (magit-read-other-branch-or-commit "Checkout"))) + (interactive (list (magit-read-other-branch-or-commit "Checkout") + (magit-branch-arguments))) (when (string-match "\\`heads/\\(.+\\)" revision) (setq revision (match-string 1 revision))) - (magit-run-git "checkout" revision)) + (magit-run-git "checkout" args revision)) ;;;###autoload (defun magit-branch-create (branch start-point) @@ -257,12 +275,13 @@ changes. (magit-refresh)) ;;;###autoload -(defun magit-branch-and-checkout (branch start-point) +(defun magit-branch-and-checkout (branch start-point &optional args) "Create and checkout BRANCH at branch or revision START-POINT." - (interactive (magit-branch-read-args "Create and checkout branch")) + (interactive (append (magit-branch-read-args "Create and checkout branch") + (list (magit-branch-arguments)))) (if (string-match-p "^stash@{[0-9]+}$" start-point) (magit-run-git "stash" "branch" branch start-point) - (magit-call-git "checkout" "-b" branch start-point) + (magit-call-git "checkout" args "-b" branch start-point) (magit-branch-maybe-adjust-upstream branch start-point) (magit-refresh))) @@ -339,16 +358,18 @@ when using `magit-branch-and-checkout'." (t (list choice (magit-read-starting-point "Create" choice)))))) (if (not start-point) - (magit-checkout branch) + (magit-checkout branch (magit-branch-arguments)) (when (magit-anything-modified-p t) (user-error "Cannot checkout when there are uncommitted changes")) - (magit-branch-and-checkout branch start-point) + (let ((magit-inhibit-refresh t)) + (magit-branch-and-checkout branch start-point)) (when (magit-remote-branch-p start-point) (pcase-let ((`(,remote . ,remote-branch) (magit-split-branch-name start-point))) (when (and (equal branch remote-branch) (not (equal remote (magit-get "remote.pushDefault")))) - (magit-set remote "branch" branch "pushRemote")))))) + (magit-set remote "branch" branch "pushRemote")))) + (magit-refresh))) (defun magit-branch-maybe-adjust-upstream (branch start-point) (--when-let @@ -356,10 +377,13 @@ when using `magit-branch-and-checkout'." (magit-get-indirect-upstream-branch start-point)) (and (magit-remote-branch-p start-point) (let ((name (cdr (magit-split-branch-name start-point)))) - (car (--first (if (listp (cdr it)) - (not (member name (cdr it))) - (string-match-p (cdr it) name)) - magit-branch-adjust-remote-upstream-alist))))) + (-some (pcase-lambda (`(,upstream . ,rule)) + (and (magit-branch-p upstream) + (if (listp rule) + (not (member name rule)) + (string-match-p rule name)) + upstream)) + magit-branch-adjust-remote-upstream-alist)))) (magit-call-git "branch" (concat "--set-upstream-to=" it) branch))) ;;;###autoload @@ -498,7 +522,7 @@ that is being reset." (or (and (not (equal branch atpoint)) atpoint) (magit-get-upstream-branch branch))) current-prefix-arg))) - (let ((inhibit-magit-refresh t)) + (let ((magit-inhibit-refresh t)) (if (equal branch (magit-get-current-branch)) (if (and (magit-anything-modified-p) (not (yes-or-no-p @@ -562,16 +586,32 @@ defaulting to the branch at point." ((string-match "^refs/remotes/\\([^/]+\\)" (car refs)) (let* ((remote (match-string 1 (car refs))) (offset (1+ (length remote)))) - ;; Assume the branches actually still exists on the remote. - (magit-run-git-async - "push" - (and (or force magit-branch-delete-never-verify) "--no-verify") - remote - (--map (concat ":" (substring it offset)) branches)) - ;; If that is not the case, then this deletes the tracking branches. - (set-process-sentinel - magit-this-process - (apply-partially 'magit-delete-remote-branch-sentinel remote refs)))) + (cond + ((magit-confirm 'delete-branch-on-remote + "Delete %s on the remote (not just locally)" + "Delete %i branches on the remote (not just locally)" + 'noabort branches) + ;; The ref may actually point at another rev on the remote, + ;; but this is better than nothing. + (dolist (ref refs) + (message "Delete %s (was %s)" ref + (magit-rev-parse "--short" ref))) + ;; Assume the branches actually still exist on the remote. + (magit-run-git-async + "push" + (and (or force magit-branch-delete-never-verify) "--no-verify") + remote + (--map (concat ":" (substring it offset)) branches)) + ;; If that is not the case, then this deletes the tracking branches. + (set-process-sentinel + magit-this-process + (apply-partially 'magit-delete-remote-branch-sentinel remote refs))) + (t + (dolist (ref refs) + (message "Delete %s (was %s)" ref + (magit-rev-parse "--short" ref)) + (magit-call-git "update-ref" "-d" ref)) + (magit-refresh))))) ((> (length branches) 1) (setq branches (delete (magit-get-current-branch) branches)) (mapc 'magit-branch-maybe-delete-pr-remote branches) @@ -579,17 +619,21 @@ defaulting to the branch at point." (magit-run-git "branch" (if force "-D" "-d") branches)) (t ; And now for something completely different. (let* ((branch (car branches)) - (prompt (format "Branch %s is checked out. " branch))) + (prompt (format "Branch %s is checked out. " branch)) + (target (magit-get-upstream-branch))) (when (equal branch (magit-get-current-branch)) - (pcase (if (or (equal branch "master") - (not (magit-rev-verify "master"))) + (when (or (equal branch target) + (not target)) + (setq target (magit-main-branch))) + (pcase (if (or (equal branch target) + (not target)) (magit-read-char-case prompt nil (?d "[d]etach HEAD & delete" 'detach) (?a "[a]bort" 'abort)) (magit-read-char-case prompt nil - (?d "[d]etach HEAD & delete" 'detach) - (?c "[c]heckout master & delete" 'master) - (?a "[a]bort" 'abort))) + (?d "[d]etach HEAD & delete" 'detach) + (?c (format "[c]heckout %s & delete" target) 'target) + (?a "[a]bort" 'abort))) (`detach (unless (or (equal force '(4)) (member branch force) (magit-branch-merged-p branch t)) @@ -597,13 +641,13 @@ defaulting to the branch at point." "Delete unmerged branch %s" "" nil (list branch))) (magit-call-git "checkout" "--detach")) - (`master (unless (or (equal force '(4)) + (`target (unless (or (equal force '(4)) (member branch force) - (magit-branch-merged-p branch "master")) + (magit-branch-merged-p branch target)) (magit-confirm 'delete-unmerged-branch "Delete unmerged branch %s" "" nil (list branch))) - (magit-call-git "checkout" "master")) + (magit-call-git "checkout" target)) (`abort (user-error "Abort"))) (setq force t)) (magit-branch-maybe-delete-pr-remote branch) @@ -686,15 +730,15 @@ the remote." (magit-call-git "branch" (if force "-M" "-m") old new) (when magit-branch-rename-push-target (let ((remote (magit-get-push-remote old)) - (old-specific (magit-get "branch" old "pushRemote")) - (new-specific (magit-get "branch" new "pushRemote"))) - (when (and old-specific (or force (not new-specific))) - ;; Keep the target setting branch specific, even if that is + (old-specified (magit-get "branch" old "pushRemote")) + (new-specified (magit-get "branch" new "pushRemote"))) + (when (and old-specified (or force (not new-specified))) + ;; Keep the target setting branch specified, even if that is ;; redundant. But if a branch by the same name existed before ;; and the rename isn't forced, then do not change a leftover ;; setting. Such a leftover setting may or may not conform to ;; what we expect here... - (magit-set old-specific "branch" new "pushRemote")) + (magit-set old-specified "branch" new "pushRemote")) (when (and (equal (magit-get-push-remote new) remote) ;; ...and if it does not, then we must abort. (not (eq magit-branch-rename-push-target 'local-only)) diff --git a/lisp/magit/magit-bundle.el b/lisp/magit/magit-bundle.el new file mode 100644 index 00000000..8afa7ffc --- /dev/null +++ b/lisp/magit/magit-bundle.el @@ -0,0 +1,135 @@ +;;; magit-bundle.el --- bundle support for Magit -*- lexical-binding: t -*- + +;; Copyright (C) 2011-2022 The Magit Project Contributors +;; +;; You should have received a copy of the AUTHORS.md file which +;; lists all contributors. If not, see http://magit.vc/authors. + +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; SPDX-License-Identifier: GPL-3.0-or-later + +;; Magit 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, or (at your option) +;; any later version. +;; +;; Magit 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 Magit. If not, see http://www.gnu.org/licenses. + +;;; Code: + +(require 'magit) + +;;; Commands + +;;;###autoload (autoload 'magit-bundle "magit-bundle" nil t) +(transient-define-prefix magit-bundle () + "Create or verify Git bundles." + :man-page "git-bundle" + ["Actions" + ("c" "create" magit-bundle-create) + ("v" "verify" magit-bundle-verify) + ("l" "list-heads" magit-bundle-list-heads)]) + +;;;###autoload (autoload 'magit-bundle-import "magit-bundle" nil t) +(transient-define-prefix magit-bundle-create (&optional file refs args) + "Create a bundle." + :man-page "git-bundle" + ["Arguments" + ("-a" "Include all refs" "--all") + ("-b" "Include branches" "--branches=" :allow-empty t) + ("-t" "Include tags" "--tags=" :allow-empty t) + ("-r" "Include remotes" "--remotes=" :allow-empty t) + ("-g" "Include refs" "--glob=") + ("-e" "Exclude refs" "--exclude=") + (magit-log:-n) + (magit-log:--since) + (magit-log:--until)] + ["Actions" + ("c" "create regular bundle" magit-bundle-create) + ("t" "create tracked bundle" magit-bundle-create-tracked) + ("u" "update tracked bundle" magit-bundle-update-tracked)] + (interactive + (and (eq transient-current-command 'magit-bundle-create) + (list (read-file-name "Create bundle: " nil nil nil + (concat (file-name-nondirectory + (directory-file-name (magit-toplevel))) + ".bundle")) + (magit-completing-read-multiple* "Refnames (zero or more): " + (magit-list-refnames)) + (transient-args 'magit-bundle-create)))) + (if file + (magit-git-bundle "create" file refs args) + (transient-setup 'magit-bundle-create))) + +;;;###autoload +(defun magit-bundle-create-tracked (file tag branch refs args) + "Create and track a new bundle." + (interactive + (let ((tag (magit-read-tag "Track bundle using tag")) + (branch (magit-read-branch "Bundle branch")) + (refs (magit-completing-read-multiple* + "Additional refnames (zero or more): " + (magit-list-refnames)))) + (list (read-file-name "File: " nil nil nil (concat tag ".bundle")) + tag branch + (if (equal branch (magit-get-current-branch)) + (cons "HEAD" refs) + refs) + (transient-args 'magit-bundle-create)))) + (magit-git-bundle "create" file (cons branch refs) args) + (magit-git "tag" "--force" tag branch + "-m" (concat ";; git-bundle tracking\n" + (pp-to-string `((file . ,file) + (branch . ,branch) + (refs . ,refs) + (args . ,args)))))) + +;;;###autoload +(defun magit-bundle-update-tracked (tag) + "Update a bundle that is being tracked using TAG." + (interactive (list (magit-read-tag "Update bundle tracked by tag" t))) + (let (msg) + (let-alist (magit--with-temp-process-buffer + (save-excursion + (magit-git-insert "for-each-ref" "--format=%(contents)" + (concat "refs/tags/" tag))) + (setq msg (buffer-string)) + (ignore-errors (read (current-buffer)))) + (unless (and .file .branch) + (error "Tag %s does not appear to track a bundle" tag)) + (magit-git-bundle "create" .file + (cons (concat tag ".." .branch) .refs) + .args) + (magit-git "tag" "--force" tag .branch "-m" msg)))) + +;;;###autoload +(defun magit-bundle-verify (file) + "Check whether FILE is valid and applies to the current repository." + (interactive (list (magit-bundle--read-file-name "Verify bundle: "))) + (magit-process-buffer) + (magit-git-bundle "verify" file)) + +;;;###autoload +(defun magit-bundle-list-heads (file) + "List the refs in FILE." + (interactive (list (magit-bundle--read-file-name "List heads of bundle: "))) + (magit-process-buffer) + (magit-git-bundle "list-heads" file)) + +(defun magit-bundle--read-file-name (prompt) + (read-file-name prompt nil nil t (magit-file-at-point) #'file-regular-p)) + +(defun magit-git-bundle (command file &optional refs args) + (magit-git "bundle" command (magit-convert-filename-for-git file) refs args)) + +;;; _ +(provide 'magit-bundle) +;;; magit-bundle.el ends here diff --git a/lisp/magit/magit-clone.el b/lisp/magit/magit-clone.el index 3aee1a85..f2813cb8 100644 --- a/lisp/magit/magit-clone.el +++ b/lisp/magit/magit-clone.el @@ -1,6 +1,6 @@ ;;; magit-clone.el --- clone a repository -*- lexical-binding: t -*- -;; Copyright (C) 2008-2021 The Magit Project Contributors +;; Copyright (C) 2008-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -193,11 +195,15 @@ Then show the status buffer for the new repository." (defun magit-clone-internal (repository directory args) (let* ((checkout (not (memq (car args) '("--bare" "--mirror")))) + (remote (or (transient-arg-value "--origin" args) + (magit-get "clone.defaultRemote") + "origin")) (set-push-default (and checkout (or (eq magit-clone-set-remote.pushDefault t) (and magit-clone-set-remote.pushDefault - (y-or-n-p "Set `remote.pushDefault' to \"origin\"? ")))))) + (y-or-n-p (format "Set `remote.pushDefault' to %S? " + remote))))))) (run-hooks 'magit-credential-hook) (setq directory (file-name-as-directory (expand-file-name directory))) (when (file-exists-p directory) @@ -225,9 +231,9 @@ Then show the status buffer for the new repository." (when checkout (let ((default-directory directory)) (when set-push-default - (setf (magit-get "remote.pushDefault") "origin")) + (setf (magit-get "remote.pushDefault") remote)) (unless magit-clone-set-remote-head - (magit-remote-unset-head "origin")))) + (magit-remote-unset-head remote)))) (with-current-buffer (process-get process 'command-buf) (magit-status-setup-buffer directory))))))) @@ -251,9 +257,15 @@ Then show the status buffer for the new repository." str (magit-clone--name-to-url str)))) (?p "[p]ath" - (read-directory-name "Clone repository: ")) - (?l "or [l]ocal url" - (concat "file://" (read-directory-name "Clone repository: file://"))))) + (magit-convert-filename-for-git + (read-directory-name "Clone repository: "))) + (?l "[l]ocal url" + (concat "file://" + (magit-convert-filename-for-git + (read-directory-name "Clone repository: file://")))) + (?b "or [b]undle" + (magit-convert-filename-for-git + (read-file-name "Clone from bundle: "))))) (defun magit-clone--url-to-name (url) (and (string-match "\\([^/:]+?\\)\\(/?\\.git\\)?$" url) diff --git a/lisp/magit/magit-commit.el b/lisp/magit/magit-commit.el index 3039180f..c2b5a429 100644 --- a/lisp/magit/magit-commit.el +++ b/lisp/magit/magit-commit.el @@ -1,6 +1,6 @@ ;;; magit-commit.el --- create Git commits -*- lexical-binding: t -*- -;; Copyright (C) 2008-2021 The Magit Project Contributors +;; Copyright (C) 2008-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -34,7 +36,6 @@ (eval-when-compile (require 'epa)) ; for `epa-protocol' (eval-when-compile (require 'epg)) -(eval-when-compile (require 'subr-x)) ;;; Options @@ -90,6 +91,34 @@ Also see `git-commit-post-finish-hook'." :group 'magit-commands :type 'hook) +(defcustom magit-commit-diff-inhibit-same-window nil + "Whether to inhibit use of same window when showing diff while committing. + +When writing a commit, then a diff of the changes to be committed +is automatically shown. The idea is that the diff is shown in a +different window of the same frame and for most users that just +works. In other words most users can completely ignore this +option because its value doesn't make a difference for them. + +However for users who configured Emacs to never create a new +window even when the package explicitly tries to do so, then +displaying two new buffers necessarily means that the first is +immediately replaced by the second. In our case the message +buffer is immediately replaced by the diff buffer, which is of +course highly undesirable. + +A workaround is to suppress this user configuration in this +particular case. Users have to explicitly opt-in by toggling +this option. We cannot enable the workaround unconditionally +because that again causes issues for other users: if the frame +is too tiny or the relevant settings too aggressive, then the +diff buffer would end up being displayed in a new frame. + +Also see https://github.com/magit/magit/issues/4132." + :package-version '(magit . "3.3.0") + :group 'magit-commands + :type 'boolean) + (defvar magit-post-commit-hook-commands '(magit-commit-extend magit-commit-fixup @@ -145,28 +174,46 @@ Also see `git-commit-post-finish-hook'." :shortarg "-S" :argument "--gpg-sign=" :allow-empty t - :reader 'magit-read-gpg-secret-key) + :reader 'magit-read-gpg-signing-key) (defvar magit-gpg-secret-key-hist nil) -(defun magit-read-gpg-secret-key (prompt &optional initial-input history) +(defun magit-read-gpg-secret-key + (prompt &optional initial-input history predicate) (require 'epa) - (let* ((keys (mapcar - (lambda (obj) - (let ((key (epg-sub-key-id (car (epg-key-sub-key-list obj)))) - (author - (when-let ((id-obj (car (epg-key-user-id-list obj)))) - (let ((id-str (epg-user-id-string id-obj))) - (if (stringp id-str) - id-str - (epg-decode-dn id-obj)))))) - (propertize key 'display (concat key " " author)))) + (let* ((keys (cl-mapcan + (lambda (cert) + (and (or (not predicate) + (funcall predicate cert)) + (let* ((key (car (epg-key-sub-key-list cert))) + (fpr (epg-sub-key-fingerprint key)) + (id (epg-sub-key-id key)) + (author + (when-let ((id-obj + (car (epg-key-user-id-list cert)))) + (let ((id-str (epg-user-id-string id-obj))) + (if (stringp id-str) + id-str + (epg-decode-dn id-obj)))))) + (list + (propertize fpr 'display + (concat (substring fpr 0 (- (length id))) + (propertize id 'face 'highlight) + " " author)))))) (epg-list-keys (epg-make-context epa-protocol) nil t))) (choice (completing-read prompt keys nil nil nil history nil initial-input))) (set-text-properties 0 (length choice) nil choice) choice)) +(defun magit-read-gpg-signing-key (prompt &optional initial-input history) + (magit-read-gpg-secret-key + prompt initial-input history + (lambda (cert) + (cl-some (lambda (key) + (memq 'sign (epg-sub-key-capability key))) + (epg-key-sub-key-list cert))))) + (transient-define-argument magit-commit:--reuse-message () :description "Reuse commit message" :class 'transient-option @@ -264,7 +311,10 @@ depending on the value of option `magit-commit-squash-confirm'." With a prefix argument the target COMMIT has to be confirmed. Otherwise the commit at point may be used without confirmation -depending on the value of option `magit-commit-squash-confirm'." +depending on the value of option `magit-commit-squash-confirm'. + +If you want to immediately add a message to the squash commit, +then use `magit-commit-augment' instead of this command." (interactive (list (magit-commit-at-point) (magit-commit-arguments))) (magit-commit-squash-internal "--squash" commit args)) @@ -296,7 +346,7 @@ depending on the value of option `magit-commit-squash-confirm'." (defun magit-commit-squash-internal (option commit &optional args rebase edit confirmed) - (when-let ((args (magit-commit-assert args t))) + (when-let ((args (magit-commit-assert args (not edit)))) (when commit (when (and rebase (not (magit-rev-ancestor-p commit "HEAD"))) (magit-read-char-case @@ -360,9 +410,9 @@ depending on the value of option `magit-commit-squash-confirm'." (or (member "--amend" args) (member "--allow-empty" args) (member "--reset-author" args) - (member "--author" args) (member "--signoff" args) - (cl-find-if (lambda (a) (string-match-p "\\`--date=" a)) args)))) + (transient-arg-value "--author=" args) + (transient-arg-value "--date=" args)))) (or args (list "--"))) ((and (magit-rebase-in-progress-p) (not (magit-anything-unstaged-p)) @@ -391,29 +441,37 @@ depending on the value of option `magit-commit-squash-confirm'." (defvar magit--reshelve-history nil) ;;;###autoload -(defun magit-commit-reshelve (date) +(defun magit-commit-reshelve (date update-author &optional args) "Change the committer date and possibly the author date of `HEAD'. -If you are the author of `HEAD', then both dates are changed, -otherwise only the committer date. The current time is used -as the initial minibuffer input and the original author (if -that is you) or committer date is available as the previous -history element." +The current time is used as the initial minibuffer input and the +original author or committer date is available as the previous +history element. + +Both the author and the committer dates are changes, unless one +of the following is true, in which case only the committer date +is updated: +- You are not the author of the commit that is being reshelved. +- The command was invoked with a prefix argument. +- Non-interactively if UPDATE-AUTHOR is nil." (interactive - (let ((author-p (magit-rev-author-p "HEAD"))) - (push (magit-rev-format (if author-p "%ad" "%cd") "HEAD" + (let ((update-author (and (magit-rev-author-p "HEAD") + (not current-prefix-arg)))) + (push (magit-rev-format (if update-author "%ad" "%cd") "HEAD" (concat "--date=format:%F %T %z")) magit--reshelve-history) - (list (read-string (if author-p + (list (read-string (if update-author "Change author and committer dates to: " "Change committer date to: ") (cons (format-time-string "%F %T %z") 17) - 'magit--reshelve-history)))) + 'magit--reshelve-history) + update-author + (magit-commit-arguments)))) (let ((process-environment process-environment)) (push (concat "GIT_COMMITTER_DATE=" date) process-environment) (magit-run-git "commit" "--amend" "--no-edit" - (and (magit-rev-author-p "HEAD") - (concat "--date=" date))))) + (and update-author (concat "--date=" date)) + args))) ;;;###autoload (defun magit-commit-absorb-modules (phase commit) @@ -544,7 +602,11 @@ See `magit-commit-absorb' for an alternative implementation." (magit-inhibit-save-previous-winconf 'unset) (magit-display-buffer-noselect t) (inhibit-quit nil) - (display-buffer-overriding-action '(nil (inhibit-same-window t)))) + (display-buffer-overriding-action + display-buffer-overriding-action)) + (when magit-commit-diff-inhibit-same-window + (setq display-buffer-overriding-action + '(nil (inhibit-same-window t)))) (message "Diffing changes to be committed (C-g to abort diffing)") (cl-case last-command (magit-commit diff --git a/lisp/magit/magit-core.el b/lisp/magit/magit-core.el index aac74643..c0873a98 100644 --- a/lisp/magit/magit-core.el +++ b/lisp/magit/magit-core.el @@ -1,6 +1,6 @@ ;;; magit-core.el --- core functionality -*- lexical-binding: t -*- -;; Copyright (C) 2010-2021 The Magit Project Contributors +;; Copyright (C) 2010-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -94,6 +96,9 @@ Each of these options falls into one or more of these categories: :group 'magit :group 'faces) +(custom-add-to-group 'magit-faces 'diff-refine-added 'custom-face) +(custom-add-to-group 'magit-faces 'diff-refine-removed 'custom-face) + (defgroup magit-extensions nil "Extensions to Magit." :group 'magit) diff --git a/lisp/magit/magit-diff.el b/lisp/magit/magit-diff.el index 0ae9d545..9a128db0 100644 --- a/lisp/magit/magit-diff.el +++ b/lisp/magit/magit-diff.el @@ -1,6 +1,6 @@ ;;; magit-diff.el --- inspect Git diffs -*- lexical-binding: t -*- -;; Copyright (C) 2010-2021 The Magit Project Contributors +;; Copyright (C) 2010-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -28,25 +30,27 @@ ;;; Code: -(eval-when-compile - (require 'ansi-color) - (require 'subr-x)) - -(require 'git-commit) (require 'magit-core) +(require 'git-commit) + +(eval-when-compile (require 'ansi-color)) +(require 'diff-mode) +(require 'image) +(require 'smerge-mode) ;; For `magit-diff-popup' (declare-function magit-stash-show "magit-stash" (stash &optional args files)) ;; For `magit-diff-visit-file' -(declare-function dired-jump "dired-x" (&optional other-window file-name)) +(declare-function dired-jump "dired" ; dired-x before 27.1 + (&optional other-window file-name)) (declare-function magit-find-file-noselect "magit-files" (rev file)) -(declare-function magit-status-setup-buffer "magit-status" (directory)) +(declare-function magit-status-setup-buffer "magit-status" (&optional directory)) ;; For `magit-diff-while-committing' (declare-function magit-commit-message-buffer "magit-commit" ()) ;; For `magit-insert-revision-gravatar' (defvar gravatar-size) ;; For `magit-show-commit' and `magit-diff-show-or-scroll' -(declare-function magit-current-blame-chunk "magit-blame" ()) +(declare-function magit-current-blame-chunk "magit-blame" (&optional type noerror)) (declare-function magit-blame-mode "magit-blame" (&optional arg)) (defvar magit-blame-mode) ;; For `magit-diff-show-or-scroll' @@ -59,16 +63,13 @@ (pullreq &optional endpoints)) (declare-function forge--pullreq-ref "forge-pullreq" (pullreq)) ;; For `magit-diff-wash-diff' -(declare-function ansi-color-apply-on-region "ansi-color" (begin end)) +(declare-function ansi-color-apply-on-region "ansi-color") (eval-when-compile (cl-pushnew 'orig-rev eieio--known-slot-names) (cl-pushnew 'action-type eieio--known-slot-names) (cl-pushnew 'target eieio--known-slot-names)) -(require 'diff-mode) -(require 'smerge-mode) - ;;; Options ;;;; Diff Mode @@ -94,10 +95,10 @@ (defcustom magit-diff-expansion-threshold 60 "After how many seconds not to expand anymore diffs. -Except in status buffers, diffs are usually start out fully -expanded. Because that can take a long time, all diffs that -haven't been fontified during a refresh before the threshold -defined here are instead displayed with their bodies collapsed. +Except in status buffers, diffs usually start out fully expanded. +Because that can take a long time, all diffs that haven't been +fontified during a refresh before the threshold defined here are +instead displayed with their bodies collapsed. Note that this can cause sections that were previously expanded to be collapsed. So you should not pick a very low value here. @@ -283,6 +284,20 @@ that many spaces. Otherwise, highlight neither." :group 'magit-diff :type 'boolean) +(defcustom magit-diff-extra-stat-arguments nil + "Additional arguments to be used alongside `--stat'. + +A list of zero or more arguments or a function that takes no +argument and returns such a list. These arguments are allowed +here: `--stat-width', `--stat-name-width', `--stat-graph-width' +and `--compact-summary'. See the git-diff(1) manpage." + :package-version '(magit . "3.0.0") + :group 'magit-diff + :type '(radio (function-item magit-diff-use-window-width-as-stat-width) + function + (list string) + (const :tag "None" nil))) + ;;;; File Diff (defcustom magit-diff-buffer-file-locked t @@ -821,15 +836,15 @@ and `:slant'." ;;; Section Classes (defclass magit-file-section (magit-section) - ((keymap :initform magit-file-section-map) + ((keymap :initform 'magit-file-section-map) (source :initform nil) (header :initform nil))) (defclass magit-module-section (magit-file-section) - ((keymap :initform magit-hunk-section-map))) + ((keymap :initform 'magit-hunk-section-map))) (defclass magit-hunk-section (magit-section) - ((keymap :initform magit-hunk-section-map) + ((keymap :initform 'magit-hunk-section-map) (refined :initform nil) (combined :initform nil) (from-range :initform nil) @@ -865,6 +880,7 @@ and `:slant'." ("-x" "Disallow external diff drivers" "--no-ext-diff") ("-s" "Show stats" "--stat") ("=g" "Show signature" "--show-signature") + (5 "-R" "Reverse sides" "-R") (5 magit-diff:--color-moved) (5 magit-diff:--color-moved-ws)] ["Actions" @@ -900,6 +916,8 @@ and `:slant'." :if-derived magit-diff-mode) ("=g" "Show signature" "--show-signature" :if-derived magit-diff-mode) + (5 "-R" "Reverse sides" "-R" + :if-derived magit-diff-mode) (5 magit-diff:--color-moved) (5 magit-diff:--color-moved-ws)] [["Refresh" @@ -951,12 +969,14 @@ and `:slant'." :description "Detect renames" :class 'transient-option :argument "-M" + :allow-empty t :reader 'transient-read-number-N+) (transient-define-argument magit-diff:-C () :description "Detect copies" :class 'transient-option :argument "-C" + :allow-empty t :reader 'transient-read-number-N+) (transient-define-argument magit-diff:--diff-algorithm () @@ -1081,8 +1101,8 @@ If no DWIM context is found, nil is returned." ([* unstaged] 'unstaged) ([* staged] 'staged) (unmerged 'unmerged) - (unpushed (oref it value)) - (unpulled (oref it value)) + (unpushed (magit-diff--range-to-endpoints (oref it value))) + (unpulled (magit-diff--range-to-endpoints (oref it value))) (branch (let ((current (magit-get-current-branch)) (atpoint (oref it value))) (if (equal atpoint current) @@ -1095,9 +1115,17 @@ If no DWIM context is found, nil is returned." (or current "HEAD") atpoint)))) (commit (cons 'commit (oref it value))) + ([file commit] (cons 'commit (oref (oref it parent) value))) + ([hunk file commit] + (cons 'commit (oref (oref (oref it parent) parent) value))) (stash (cons 'stash (oref it value))) (pullreq (forge--pullreq-range (oref it value) t)))))) +(defun magit-diff--range-to-endpoints (range) + (cond ((string-match "\\.\\.\\." range) (replace-match ".." nil nil range)) + ((string-match "\\.\\." range) (replace-match "..." nil nil range)) + (t range))) + (defun magit-diff-read-range-or-commit (prompt &optional secondary-default mbase) "Read range or revision with special diff range treatment. If MBASE is non-nil, prompt for which rev to place at the end of @@ -1271,9 +1299,7 @@ If there is no revision at point or with a prefix argument prompt for a revision." (interactive (pcase-let* ((mcommit (magit-section-value-if 'module-commit)) - (atpoint (or (and (bound-and-true-p magit-blame-mode) - (oref (magit-current-blame-chunk) orig-rev)) - mcommit + (atpoint (or mcommit (thing-at-point 'git-revision t) (magit-branch-or-commit-at-point))) (`(,args ,files) (magit-show-commit--arguments))) @@ -1308,11 +1334,12 @@ for a revision." (let (hunk (hunks (oref diff children))) (cl-block nil (while (setq hunk (pop hunks)) - (pcase-let* ((`(,beg ,len) (oref hunk to-range)) - (end (+ beg len))) - (cond ((> beg line) (cl-return (list diff nil))) - ((<= beg line end) (cl-return (list hunk t))) - ((null hunks) (cl-return (list hunk nil)))))))))) + (when-let ((range (oref hunk to-range))) + (pcase-let* ((`(,beg ,len) range) + (end (+ beg len))) + (cond ((> beg line) (cl-return (list diff nil))) + ((<= beg line end) (cl-return (list hunk t))) + ((null hunks) (cl-return (list hunk nil))))))))))) (defun magit-diff--goto-position (file line column &optional parent) (when-let ((pos (magit-diff--locate-hunk file line parent))) @@ -1399,12 +1426,12 @@ instead." (defun magit-diff-less-context (&optional count) "Decrease the context for diff hunks by COUNT lines." (interactive "p") - (magit-diff-set-context `(lambda (cur) (max 0 (- (or cur 0) ,count))))) + (magit-diff-set-context (lambda (cur) (max 0 (- (or cur 0) count))))) (defun magit-diff-more-context (&optional count) "Increase the context for diff hunks by COUNT lines." (interactive "p") - (magit-diff-set-context `(lambda (cur) (+ (or cur 0) ,count)))) + (magit-diff-set-context (lambda (cur) (+ (or cur 0) count)))) (defun magit-diff-default-context () "Reset context for diff hunks to the default height." @@ -1490,8 +1517,8 @@ The visited version depends on what changes the diff is about. In the file-visiting buffer also go to the line that corresponds to the line that point is on in the diff. -Note that this command only works if point is inside a diff. In -other cases `magit-find-file' (which see) had to be used." +Note that this command only works if point is inside a diff. +In other cases `magit-find-file' (which see) has to be used." (interactive (list (magit-file-at-point t t) current-prefix-arg)) (magit-diff-visit-file--internal file nil (if other-window @@ -1658,11 +1685,13 @@ the Magit-Status buffer for DIRECTORY." (not (< (point) (oref section content))) (= (char-after (line-beginning-position)) ?-))) +(defvar magit-diff-visit-jump-to-change t) + (defun magit-diff-hunk-line (section goto-from) (save-excursion (goto-char (line-beginning-position)) (with-slots (content combined from-ranges from-range to-range) section - (when (< (point) content) + (when (and magit-diff-visit-jump-to-change (< (point) content)) (goto-char content) (re-search-forward "^[-+]")) (+ (car (if goto-from from-range to-range)) @@ -1896,10 +1925,14 @@ Staging and applying changes is documented in info node (if (equal magit-buffer-typearg "--no-index") (apply #'format "Differences between %s and %s" magit-buffer-diff-files) (concat (if magit-buffer-range - (if (string-match-p "\\(\\.\\.\\|\\^-\\)" - magit-buffer-range) - (format "Changes in %s" magit-buffer-range) - (format "Changes from %s to working tree" magit-buffer-range)) + (cond + ((string-match-p "\\(\\.\\.\\|\\^-\\)" + magit-buffer-range) + (format "Changes in %s" magit-buffer-range)) + ((member "-R" magit-buffer-diff-args) + (format "Changes from working tree to %s" magit-buffer-range)) + (t + (format "Changes from %s to working tree" magit-buffer-range))) (if (equal magit-buffer-typearg "--cached") "Staged changes" "Unstaged changes")) @@ -1924,8 +1957,10 @@ Staging and applying changes is documented in info node (defvar magit-diff-section-base-map (let ((map (make-sparse-keymap))) - (define-key map (kbd "C-j") 'magit-diff-visit-worktree-file) - (define-key map [C-return] 'magit-diff-visit-worktree-file) + (define-key map (kbd "C-j") 'magit-diff-visit-worktree-file) + (define-key map (kbd "C-") 'magit-diff-visit-worktree-file) + (define-key map (kbd "C-x 4 ") 'magit-diff-visit-file-other-window) + (define-key map (kbd "C-x 5 ") 'magit-diff-visit-file-other-frame) (define-key map [remap magit-visit-thing] 'magit-diff-visit-file) (define-key map [remap magit-delete-thing] 'magit-discard) (define-key map [remap magit-revert-no-commit] 'magit-reverse) @@ -1950,6 +1985,12 @@ Staging and applying changes is documented in info node (defvar magit-hunk-section-map (let ((map (make-sparse-keymap))) (set-keymap-parent map magit-diff-section-base-map) + (let ((m (make-sparse-keymap))) + (define-key m (kbd "RET") 'magit-smerge-keep-current) + (define-key m (kbd "u") 'magit-smerge-keep-upper) + (define-key m (kbd "b") 'magit-smerge-keep-base) + (define-key m (kbd "l") 'magit-smerge-keep-lower) + (define-key map smerge-command-prefix m)) map) "Keymap for `hunk' sections.") @@ -2006,27 +2047,42 @@ Staging and applying changes is documented in info node (defun magit--insert-diff (&rest args) (declare (indent 0)) - (let ((magit-git-global-arguments - (remove "--literal-pathspecs" magit-git-global-arguments))) - (setq args (-flatten args)) + (pcase-let ((`(,cmd . ,args) + (-flatten args)) + (magit-git-global-arguments + (remove "--literal-pathspecs" magit-git-global-arguments))) ;; As of Git 2.19.0, we need to generate diffs with ;; --ita-visible-in-index so that `magit-stage' can work with ;; intent-to-add files (see #4026). Cache the result for each ;; repo to avoid a `git version' call for every diff insertion. - (when (and (not (equal (car args) "merge-tree")) + (when (and (not (equal cmd "merge-tree")) (pcase (magit-repository-local-get 'diff-ita-kludge-p 'unset) (`unset (let ((val (version<= "2.19.0" (magit-git-version)))) (magit-repository-local-set 'diff-ita-kludge-p val) val)) (val val))) - (push "--ita-visible-in-index" (cdr args))) + (push "--ita-visible-in-index" args)) + (setq args (magit-diff--maybe-add-stat-arguments args)) (when (cl-member-if (lambda (arg) (string-prefix-p "--color-moved" arg)) args) - (push "--color=always" (cdr args)) + (push "--color=always" args) (setq magit-git-global-arguments (append magit-diff--reset-non-color-moved magit-git-global-arguments))) - (magit-git-wash #'magit-diff-wash-diffs args))) + (magit-git-wash #'magit-diff-wash-diffs cmd args))) + +(defun magit-diff--maybe-add-stat-arguments (args) + (if (member "--stat" args) + (append (if (functionp magit-diff-extra-stat-arguments) + (funcall magit-diff-extra-stat-arguments) + magit-diff-extra-stat-arguments) + args) + args)) + +(defun magit-diff-use-window-width-as-stat-width () + "Use the `window-width' as the value of `--stat-width'." + (when-let ((window (get-buffer-window (current-buffer) 'visible))) + (list (format "--stat-width=%d" (window-width window))))) (defun magit-diff-wash-diffs (args &optional limit) (run-hooks 'magit-diff-wash-diffs-hook) @@ -2056,10 +2112,25 @@ section or a child thereof." (defun magit-diff-wash-signature () (when (looking-at "^gpg: ") - (magit-insert-section (signature) - (while (looking-at "^gpg: ") - (forward-line)) - (insert "\n")))) + (let (title end) + (save-excursion + (while (looking-at "^gpg: ") + (cond + ((looking-at "^gpg: Good signature from") + (setq title (propertize + (buffer-substring (point) (line-end-position)) + 'face 'magit-signature-good))) + ((looking-at "^gpg: Can't check signature") + (setq title (propertize + (buffer-substring (point) (line-end-position)) + 'face '(italic bold))))) + (forward-line)) + (setq end (point-marker))) + (magit-insert-section (signature magit-buffer-revision title) + (when title + (magit-insert-heading title)) + (goto-char end) + (insert "\n"))))) (defun magit-diff-wash-diffstat () (let (heading (beg (point))) @@ -2136,7 +2207,7 @@ section or a child thereof." ((looking-at magit-diff-conflict-headline-re) (let ((long-status (match-string 0)) (status "BUG") - file orig base modes) + file orig base) (if (equal long-status "merged") (progn (setq status long-status) (setq long-status nil)) @@ -2161,52 +2232,79 @@ section or a child thereof." (when orig (setq orig (magit-decode-git-path orig))) (when file (setq file (magit-decode-git-path file))) (magit-diff-insert-file-section - (or file base) orig status modes nil long-status))) - ((looking-at - "^diff --\\(?:\\(git\\) \\(?:\\(.+?\\) \\2\\)?\\|\\(cc\\|combined\\) \\(.+\\)\\)") + (or file base) orig status nil nil nil long-status))) + ;; The files on this line may be ambiguous due to whitespace. + ;; That's okay. We can get their names from subsequent headers. + ((looking-at "^diff --\ +\\(?:\\(?1:git\\) \\(?:\\(?2:.+?\\) \\2\\)?\ +\\|\\(?:cc\\|combined\\) \\(?3:.+\\)\\)") (let ((status (cond ((equal (match-string 1) "git") "modified") ((derived-mode-p 'magit-revision-mode) "resolved") (t "unmerged"))) - (file (or (match-string 2) (match-string 4))) - (beg (point)) - orig header modes) - (save-excursion - (forward-line 1) - (setq header (buffer-substring - beg (if (re-search-forward magit-diff-headline-re nil t) - (match-beginning 0) - (point-max))))) + (orig nil) + (file (or (match-string 2) (match-string 3))) + (header (list (buffer-substring-no-properties + (line-beginning-position) (1+ (line-end-position))))) + (modes nil) + (rename nil)) (magit-delete-line) (while (not (or (eobp) (looking-at magit-diff-headline-re))) - (if (looking-at "^old mode \\([^\n]+\\)\nnew mode \\([^\n]+\\)\n") - (progn (setq modes (match-string 0)) - (magit-delete-match)) - (cond - ((looking-at "^--- \\([^/].*?\\)\t?$") ; i.e. not /dev/null - (setq orig (match-string 1))) - ((looking-at "^\\+\\+\\+ \\([^/].*?\\)\t?$") - (setq file (match-string 1))) - ((looking-at "^\\(copy\\|rename\\) from \\(.+\\)$") - (setq orig (match-string 2))) - ((looking-at "^\\(copy\\|rename\\) to \\(.+\\)$") - (setq file (match-string 2)) - (setq status (if (equal (match-string 1) "copy") "new file" "renamed"))) - ((looking-at "^\\(new file\\|deleted\\)") - (setq status (match-string 1)))) - (magit-delete-line))) + (cond + ((looking-at "old mode \\(?:[^\n]+\\)\nnew mode \\(?:[^\n]+\\)\n") + (setq modes (match-string 0))) + ((looking-at "deleted file .+\n") + (setq status "deleted")) + ((looking-at "new file .+\n") + (setq status "new file")) + ((looking-at "rename from \\(.+\\)\nrename to \\(.+\\)\n") + (setq rename (match-string 0)) + (setq orig (match-string 1)) + (setq file (match-string 2)) + (setq status "renamed")) + ((looking-at "copy from \\(.+\\)\ncopy to \\(.+\\)\n") + (setq orig (match-string 1)) + (setq file (match-string 2)) + (setq status "new file")) + ((looking-at "similarity index .+\n")) + ((looking-at "dissimilarity index .+\n")) + ((looking-at "index .+\n")) + ((looking-at "--- \\(.+?\\)\t?\n") + (unless (equal (match-string 1) "/dev/null") + (setq orig (match-string 1)))) + ((looking-at "\\+\\+\\+ \\(.+?\\)\t?\n") + (unless (equal (match-string 1) "/dev/null") + (setq file (match-string 1)))) + ((looking-at "Binary files .+ and .+ differ\n")) + ((looking-at "Binary files differ\n")) + ;; TODO Use all combined diff extended headers. + ((looking-at "mode .+\n")) + (t + (error "BUG: Unknown extended header: %S" + (buffer-substring (point) (line-end-position))))) + ;; These headers are treated as some sort of special hunk. + (unless (or (string-prefix-p "old mode" (match-string 0)) + (string-prefix-p "rename" (match-string 0))) + (push (match-string 0) header)) + (magit-delete-match)) + (setq header (mapconcat #'identity (nreverse header) "")) (when orig (setq orig (magit-decode-git-path orig))) (setq file (magit-decode-git-path file)) - ;; KLUDGE `git-log' ignores `--no-prefix' when `-L' is used. - (when (and (derived-mode-p 'magit-log-mode) - (--first (string-match-p "\\`-L" it) magit-buffer-log-args)) + ;; KLUDGE `git-diff' ignores `--no-prefix' for new files and renames at + ;; least. And `git-log' ignores `--no-prefix' when `-L' is used. + (when (or (and file orig + (string-prefix-p "a/" orig) + (string-prefix-p "b/" file)) + (and (derived-mode-p 'magit-log-mode) + (--first (string-match-p "\\`-L" it) + magit-buffer-log-args))) (setq file (substring file 2)) (when orig (setq orig (substring orig 2)))) - (magit-diff-insert-file-section file orig status modes header))))) + (magit-diff-insert-file-section file orig status modes rename header))))) (defun magit-diff-insert-file-section - (file orig status modes header &optional long-status) + (file orig status modes rename header &optional long-status) (magit-insert-section section (file file (or (equal status "deleted") (derived-mode-p 'magit-status-mode))) @@ -2222,9 +2320,13 @@ section or a child thereof." (oset section source orig)) (oset section header header) (when modes - (magit-insert-section (hunk) + (magit-insert-section (hunk '(chmod)) (insert modes) (magit-insert-heading))) + (when rename + (magit-insert-section (hunk '(rename)) + (insert rename) + (magit-insert-heading))) (magit-wash-sequence #'magit-diff-wash-hunk))) (defun magit-diff-wash-submodule () @@ -2243,7 +2345,7 @@ section or a child thereof." (equal (match-string 1) module)) (magit-bind-match-strings (_module range rewind) nil (magit-delete-line) - (while (looking-at "^ \\([<>]\\) \\(.+\\)$") + (while (looking-at "^ \\([<>]\\) \\(.*\\)$") (magit-delete-line)) (when rewind (setq range (replace-regexp-in-string "[^.]\\(\\.\\.\\)[^.]" @@ -2293,7 +2395,7 @@ section or a child thereof." (when (looking-at "^@\\{2,\\} \\(.+?\\) @\\{2,\\}\\(?: \\(.*\\)\\)?") (let* ((heading (match-string 0)) (ranges (mapcar (lambda (str) - (mapcar (lambda (n) (string-to-number n)) + (mapcar #'string-to-number (split-string (substring str 1) ","))) (split-string (match-string 1)))) (about (match-string 2)) @@ -2363,15 +2465,15 @@ Staging and applying changes is documented in info node (magit-buffer-diff-files-suspended nil))) (defun magit-revision-refresh-buffer () + (setq magit-buffer-revision-hash (magit-rev-parse magit-buffer-revision)) (magit-set-header-line-format - (concat (capitalize (magit-object-type magit-buffer-revision)) + (concat (magit-object-type magit-buffer-revision-hash) " " magit-buffer-revision (pcase (length magit-buffer-diff-files) (0) (1 (concat " limited to file " (car magit-buffer-diff-files))) (_ (concat " limited to files " (mapconcat #'identity magit-buffer-diff-files ", ")))))) - (setq magit-buffer-revision-hash (magit-rev-parse magit-buffer-revision)) (magit-insert-section (commitbuf) (magit-run-section-hook 'magit-revision-sections-hook))) @@ -2420,8 +2522,7 @@ or a ref which is not a branch, then it inserts nothing." (re-search-forward "-----END PGP SIGNATURE-----") (delete-region beg (point))) (insert ?\n) - (process-file magit-git-executable nil t nil - "verify-tag" magit-buffer-revision)) + (magit-process-git t "verify-tag" magit-buffer-revision)) (goto-char (point-max))) (insert ?\n)))) @@ -2625,9 +2726,11 @@ or a ref which is not a branch, then it inserts nothing." (gravatar-size (- size 2))) (ignore-errors ; service may be unreachable (gravatar-retrieve email 'magit-insert-revision-gravatar-cb - (list rev (point-marker) align-to column)))))))) + (list gravatar-size rev + (point-marker) + align-to column)))))))) -(defun magit-insert-revision-gravatar-cb (image rev marker align-to column) +(defun magit-insert-revision-gravatar-cb (image size rev marker align-to column) (unless (eq image 'error) (when-let ((buffer (marker-buffer marker))) (with-current-buffer buffer @@ -2641,10 +2744,13 @@ or a ref which is not a branch, then it inserts nothing." (car-safe (get-text-property (point) 'display))) 'image))) - (let ((top `((,@image :ascent center :relief 1) - (slice 0.0 0.0 1.0 0.5))) - (bot `((,@image :ascent center :relief 1) - (slice 0.0 0.5 1.0 1.0))) + ;; `image-property' wasn't added until 26.1. + (setcdr image (plist-put (cdr image) :ascent 'center)) + (setcdr image (plist-put (cdr image) :relief 1)) + (setcdr image (plist-put (cdr image) :scale 1)) + (setcdr image (plist-put (cdr image) :height size)) + (let ((top (list image '(slice 0.0 0.0 1.0 0.5))) + (bot (list image '(slice 0.0 0.5 1.0 1.0))) (align `((space :align-to ,align-to)))) (when magit-revision-use-gravatar-kludge (cl-rotatef top bot)) @@ -2822,7 +2928,7 @@ Do not confuse this with `magit-diff-scope' (which see)." (oref section children)) (magit-section-match [* file commit] section)) 'committed - 'undefined)) + 'undefined)) (t 'undefined)))) (cl-defun magit-diff-scope (&optional (section nil ssection) strict) @@ -2866,8 +2972,7 @@ actually a `diff' but a `diffstat' section." (`(file ,_ ,_ ,_) 'file) (`(module t t nil) 'files) (`(module ,_ ,_ ,_) 'file) - (`(,(or `staged `unstaged `untracked) - nil ,_ ,_) 'list))))) + (`(,(or `staged `unstaged `untracked) nil ,_ ,_) 'list))))) (defun magit-diff-use-hunk-region-p () (and (region-active-p) @@ -3144,7 +3249,8 @@ are highlighted." (defun magit-diff-update-hunk-region (section) "Highlight the hunk-internal region if any." - (when (eq (magit-diff-scope section t) 'region) + (when (and (eq (oref section type) 'hunk) + (eq (magit-diff-scope section t) 'region)) (magit-diff--make-hunk-overlay (oref section start) (1- (oref section content)) @@ -3249,11 +3355,15 @@ last (visual) lines of the region." ;;; Diff Extract -(defun magit-diff-file-header (section) +(defun magit-diff-file-header (section &optional no-rename) (when (magit-hunk-section-p section) (setq section (oref section parent))) - (when (magit-file-section-p section) - (oref section header))) + (and (magit-file-section-p section) + (let ((header (oref section header))) + (if no-rename + (replace-regexp-in-string + "^--- \\(.+\\)" (oref section value) header t t 1) + header)))) (defun magit-diff-hunk-region-header (section) (let ((patch (magit-diff-hunk-region-patch section))) diff --git a/lisp/magit/magit-ediff.el b/lisp/magit/magit-ediff.el index 208ac843..97b49cc8 100644 --- a/lisp/magit/magit-ediff.el +++ b/lisp/magit/magit-ediff.el @@ -1,6 +1,6 @@ ;;; magit-ediff.el --- Ediff extension for Magit -*- lexical-binding: t -*- -;; Copyright (C) 2010-2021 The Magit Project Contributors +;; Copyright (C) 2010-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -99,6 +101,12 @@ tree at the time of stashing." :group 'magit-ediff :type 'boolean) +(defcustom magit-ediff-use-indirect-buffers nil + "Whether to use indirect buffers." + :package-version '(magit . "3.1.0") + :group 'magit-ediff + :type 'boolean) + ;;; Commands (defvar magit-ediff-previous-winconf nil) @@ -155,6 +163,45 @@ conflicts, including those already resolved by Git, use (let ((magit-ediff-previous-winconf smerge-ediff-windows)) (run-hooks 'magit-ediff-quit-hook))))))) +(defmacro magit-ediff-buffers (quit &rest spec) + (declare (indent 1)) + (let ((fn (if (= (length spec) 3) 'ediff-buffers3 'ediff-buffers)) + (char ?@) + get make kill) + (pcase-dolist (`(,g ,m) spec) + (let ((b (intern (format "buf%c" (cl-incf char))))) + (push `(,b ,g) get) + (push `(if ,b + (if magit-ediff-use-indirect-buffers + (prog1 + (make-indirect-buffer + ,b (generate-new-buffer-name (buffer-name ,b)) t) + (setq ,b nil)) + ,b) + ,m) + make) + (push `(unless ,b + (ediff-kill-buffer-carefully + ,(intern (format "ediff-buffer-%c" char)))) + kill))) + (setq get (nreverse get)) + (setq make (nreverse make)) + (setq kill (nreverse kill)) + `(magit-with-toplevel + (let ((conf (current-window-configuration)) + ,@get) + (,fn + ,@make + (list (lambda () + (setq-local + ediff-quit-hook + (list ,@(and quit (list quit)) + (lambda () + ,@kill + (let ((magit-ediff-previous-winconf conf)) + (run-hooks 'magit-ediff-quit-hook))))))) + ',fn))))) + ;;;###autoload (defun magit-ediff-stage (file) "Stage and unstage changes to FILE using Ediff. @@ -164,43 +211,34 @@ FILE has to be relative to the top directory of the repository." (list (magit-completing-read "Selectively stage file" files nil t nil nil (car (member (magit-current-file) files)))))) (magit-with-toplevel - (let* ((conf (current-window-configuration)) - (bufA (magit-get-revision-buffer "HEAD" file)) - (bufB (magit-get-revision-buffer "{index}" file)) - (bufBrw (and bufB (with-current-buffer bufB (not buffer-read-only)))) - (bufC (get-file-buffer file)) - (fileBufC (or bufC (find-file-noselect file))) + (let* ((bufA (magit-get-revision-buffer "HEAD" file)) + (bufB (magit-get-revision-buffer "{index}" file)) + (lockB (and bufB (buffer-local-value 'buffer-read-only bufB))) + (bufC (get-file-buffer file)) + ;; Use the same encoding for all three buffers or we + ;; may end up changing the file in an unintended way. + (bufC* (or bufC (find-file-noselect file))) (coding-system-for-read - (with-current-buffer fileBufC buffer-file-coding-system))) - (ediff-buffers3 - (or bufA (magit-find-file-noselect "HEAD" file)) - (with-current-buffer (magit-find-file-index-noselect file t) - (setq buffer-read-only nil) - (current-buffer)) - fileBufC - `((lambda () - (setq-local - ediff-quit-hook - (lambda () - (and (buffer-live-p ediff-buffer-B) - (buffer-modified-p ediff-buffer-B) - (with-current-buffer ediff-buffer-B - (magit-update-index))) - (and (buffer-live-p ediff-buffer-C) - (buffer-modified-p ediff-buffer-C) - (with-current-buffer ediff-buffer-C - (when (y-or-n-p - (format "Save file %s? " buffer-file-name)) - (save-buffer)))) - ,@(unless bufA '((ediff-kill-buffer-carefully ediff-buffer-A))) - ,@(if bufB - (unless bufBrw '((with-current-buffer ediff-buffer-B - (setq buffer-read-only t)))) - '((ediff-kill-buffer-carefully ediff-buffer-B))) - ,@(unless bufC '((ediff-kill-buffer-carefully ediff-buffer-C))) - (let ((magit-ediff-previous-winconf ,conf)) - (run-hooks 'magit-ediff-quit-hook)))))) - 'ediff-buffers3)))) + (buffer-local-value 'buffer-file-coding-system bufC*)) + (bufA* (magit-find-file-noselect-1 "HEAD" file t)) + (bufB* (magit-find-file-index-noselect file t))) + (setf (buffer-local-value 'buffer-read-only bufB*) nil) + (magit-ediff-buffers + (lambda () + (when (buffer-live-p ediff-buffer-B) + (when lockB + (setf (buffer-local-value 'buffer-read-only bufB) t)) + (when (buffer-modified-p ediff-buffer-B) + (with-current-buffer ediff-buffer-B + (magit-update-index)))) + (when (and (buffer-live-p ediff-buffer-C) + (buffer-modified-p ediff-buffer-C)) + (with-current-buffer ediff-buffer-C + (when (y-or-n-p (format "Save file %s? " buffer-file-name)) + (save-buffer))))) + (bufA bufA*) + (bufB bufB*) + (bufC bufC*))))) ;;;###autoload (defun magit-ediff-compare (revA revB fileA fileB) @@ -220,30 +258,11 @@ range)." nil current-prefix-arg))) (nconc (list revA revB) (magit-ediff-read-files revA revB)))) - (magit-with-toplevel - (let ((conf (current-window-configuration)) - (bufA (if revA - (magit-get-revision-buffer revA fileA) - (get-file-buffer fileA))) - (bufB (if revB - (magit-get-revision-buffer revB fileB) - (get-file-buffer fileB)))) - (ediff-buffers - (or bufA (if revA - (magit-find-file-noselect revA fileA) - (find-file-noselect fileA))) - (or bufB (if revB - (magit-find-file-noselect revB fileB) - (find-file-noselect fileB))) - `((lambda () - (setq-local - ediff-quit-hook - (lambda () - ,@(unless bufA '((ediff-kill-buffer-carefully ediff-buffer-A))) - ,@(unless bufB '((ediff-kill-buffer-carefully ediff-buffer-B))) - (let ((magit-ediff-previous-winconf ,conf)) - (run-hooks 'magit-ediff-quit-hook)))))) - 'ediff-revision)))) + (magit-ediff-buffers nil + ((if revA (magit-get-revision-buffer revA fileA) (get-file-buffer fileA)) + (if revA (magit-find-file-noselect revA fileA) (find-file-noselect fileA))) + ((if revB (magit-get-revision-buffer revB fileB) (get-file-buffer fileB)) + (if revB (magit-find-file-noselect revB fileB) (find-file-noselect fileB))))) (defun magit-ediff-compare--read-revisions (&optional arg mbase) (let ((input (or arg (magit-diff-read-range-or-commit @@ -358,21 +377,11 @@ FILE must be relative to the top directory of the repository." (list (magit-read-file-choice "Show staged changes for file" (magit-staged-files) "No staged files"))) - (let ((conf (current-window-configuration)) - (bufA (magit-get-revision-buffer "HEAD" file)) - (bufB (get-buffer (concat file ".~{index}~")))) - (ediff-buffers - (or bufA (magit-find-file-noselect "HEAD" file)) - (or bufB (magit-find-file-index-noselect file t)) - `((lambda () - (setq-local - ediff-quit-hook - (lambda () - ,@(unless bufA '((ediff-kill-buffer-carefully ediff-buffer-A))) - ,@(unless bufB '((ediff-kill-buffer-carefully ediff-buffer-B))) - (let ((magit-ediff-previous-winconf ,conf)) - (run-hooks 'magit-ediff-quit-hook)))))) - 'ediff-buffers))) + (magit-ediff-buffers nil + ((magit-get-revision-buffer "HEAD" file) + (magit-find-file-noselect "HEAD" file)) + ((get-buffer (concat file ".~{index}~")) + (magit-find-file-index-noselect file t)))) ;;;###autoload (defun magit-ediff-show-unstaged (file) @@ -386,22 +395,11 @@ FILE must be relative to the top directory of the repository." (list (magit-read-file-choice "Show unstaged changes for file" (magit-unstaged-files) "No unstaged files"))) - (magit-with-toplevel - (let ((conf (current-window-configuration)) - (bufA (get-buffer (concat file ".~{index}~"))) - (bufB (get-file-buffer file))) - (ediff-buffers - (or bufA (magit-find-file-index-noselect file t)) - (or bufB (find-file-noselect file)) - `((lambda () - (setq-local - ediff-quit-hook - (lambda () - ,@(unless bufA '((ediff-kill-buffer-carefully ediff-buffer-A))) - ,@(unless bufB '((ediff-kill-buffer-carefully ediff-buffer-B))) - (let ((magit-ediff-previous-winconf ,conf)) - (run-hooks 'magit-ediff-quit-hook)))))) - 'ediff-buffers)))) + (magit-ediff-buffers nil + ((get-buffer (concat file ".~{index}~")) + (magit-find-file-index-noselect file t)) + ((get-file-buffer file) + (find-file-noselect file)))) ;;;###autoload (defun magit-ediff-show-working-tree (file) @@ -411,22 +409,11 @@ FILE must be relative to the top directory of the repository." (list (magit-read-file-choice "Show changes in file" (magit-changed-files "HEAD") "No changed files"))) - (magit-with-toplevel - (let ((conf (current-window-configuration)) - (bufA (magit-get-revision-buffer "HEAD" file)) - (bufB (get-file-buffer file))) - (ediff-buffers - (or bufA (magit-find-file-noselect "HEAD" file)) - (or bufB (find-file-noselect file)) - `((lambda () - (setq-local - ediff-quit-hook - (lambda () - ,@(unless bufA '((ediff-kill-buffer-carefully ediff-buffer-A))) - ,@(unless bufB '((ediff-kill-buffer-carefully ediff-buffer-B))) - (let ((magit-ediff-previous-winconf ,conf)) - (run-hooks 'magit-ediff-quit-hook)))))) - 'ediff-buffers)))) + (magit-ediff-buffers nil + ((magit-get-revision-buffer "HEAD" file) + (magit-find-file-noselect "HEAD" file)) + ((get-file-buffer file) + (find-file-noselect file)))) ;;;###autoload (defun magit-ediff-show-commit (commit) @@ -452,27 +439,13 @@ stash that were staged." (fileB fileC)) (if (and magit-ediff-show-stash-with-index (member fileA (magit-changed-files revB revA))) - (let ((conf (current-window-configuration)) - (bufA (magit-get-revision-buffer revA fileA)) - (bufB (magit-get-revision-buffer revB fileB)) - (bufC (magit-get-revision-buffer revC fileC))) - (ediff-buffers3 - (or bufA (magit-find-file-noselect revA fileA)) - (or bufB (magit-find-file-noselect revB fileB)) - (or bufC (magit-find-file-noselect revC fileC)) - `((lambda () - (setq-local - ediff-quit-hook - (lambda () - ,@(unless bufA - '((ediff-kill-buffer-carefully ediff-buffer-A))) - ,@(unless bufB - '((ediff-kill-buffer-carefully ediff-buffer-B))) - ,@(unless bufC - '((ediff-kill-buffer-carefully ediff-buffer-C))) - (let ((magit-ediff-previous-winconf ,conf)) - (run-hooks 'magit-ediff-quit-hook)))))) - 'ediff-buffers3)) + (magit-ediff-buffers nil + ((magit-get-revision-buffer revA fileA) + (magit-find-file-noselect revA fileA)) + ((magit-get-revision-buffer revB fileB) + (magit-find-file-noselect revB fileB)) + ((magit-get-revision-buffer revC fileC) + (magit-find-file-noselect revC fileC))) (magit-ediff-compare revA revC fileA fileC)))) (defun magit-ediff-cleanup-auxiliary-buffers () diff --git a/lisp/magit/magit-extras.el b/lisp/magit/magit-extras.el index 0201a40f..0e73a032 100644 --- a/lisp/magit/magit-extras.el +++ b/lisp/magit/magit-extras.el @@ -1,10 +1,15 @@ ;;; magit-extras.el --- additional functionality for Magit -*- lexical-binding: t -*- -;; Copyright (C) 2008-2021 The Magit Project Contributors +;; Copyright (C) 2008-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. +;; Author: Jonas Bernoulli +;; Maintainer: Jonas Bernoulli + +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -24,11 +29,10 @@ ;;; Code: -(eval-when-compile - (require 'subr-x)) - (require 'magit) +(declare-function change-log-insert-entries "add-log" (changelogs)) +(declare-function diff-add-log-current-defuns "diff-mode" ()) (declare-function dired-read-shell-command "dired-aux" (prompt arg files)) ;; For `magit-project-status'. (declare-function project-root "project" (project)) @@ -61,8 +65,7 @@ (defun magit-run-git-gui () "Run `git gui' for the current git repository." (interactive) - (magit-with-toplevel - (magit-process-file magit-git-executable nil 0 nil "gui"))) + (magit-with-toplevel (magit-process-git 0 "gui"))) ;;;###autoload (defun magit-run-git-gui-blame (commit filename &optional linenum) @@ -84,10 +87,10 @@ blame to center around the line point is on." (magit-file-relative-name buffer-file-name))) (line-number-at-pos))))) (magit-with-toplevel - (apply #'magit-process-file magit-git-executable nil 0 nil "gui" "blame" - `(,@(and linenum (list (format "--line=%d" linenum))) - ,commit - ,filename)))) + (magit-process-git 0 "gui" "blame" + (and linenum (list (format "--line=%d" linenum))) + commit + filename))) ;;;###autoload (defun magit-run-gitk () @@ -142,13 +145,23 @@ like pretty much every other keymap: (interactive) (magit-status-setup-buffer (project-root (project-current t)))) +(defvar magit-bind-magit-project-status t + "Whether to bind \"m\" to `magit-project-status' in `project-prefix-map'. +If so, then an entry is added to `project-switch-commands' as +well. If you want to use another key, then you must set this +to nil before loading Magit to prevent \"m\" from being bound.") + (with-eval-after-load 'project ;; Only more recent versions of project.el have `project-prefix-map' and ;; `project-switch-commands', though project.el is available in Emacs 25. - (when (boundp 'project-prefix-map) - (define-key project-prefix-map "m" #'magit-project-status)) - (when (boundp 'project-switch-commands) - (add-to-list 'project-switch-commands '(?m "Magit" magit-status)))) + (when (and magit-bind-magit-project-status + (boundp 'project-prefix-map) + ;; Only modify if it hasn't already been modified. + (equal project-switch-commands + (eval (car (get 'project-switch-commands 'standard-value)) + t))) + (define-key project-prefix-map "m" #'magit-project-status) + (add-to-list 'project-switch-commands '(magit-project-status "Magit") t))) ;;;###autoload (defun magit-dired-jump (&optional other-window) @@ -183,6 +196,21 @@ is no file at point, then instead visit `default-directory'." magit-log-buffer-file-locked)) (magit--not-inside-repository-error))) +;;;###autoload +(defun magit-dired-am-apply-patches (repo &optional arg) + "In Dired, apply the marked (or next ARG) files as patches. +If inside a repository, then apply in that. Otherwise prompt +for a repository." + (interactive (list (or (magit-toplevel) + (magit-read-repository t)) + current-prefix-arg)) + ;; Note: The ERROR argument of `dired-get-marked-files' isn't + ;; available until Emacs 27. + (let ((files (or (dired-get-marked-files nil arg) + (user-error "No files specified")))) + (magit-status-setup-buffer repo) + (magit-am-apply-patches files))) + ;;;###autoload (defun magit-do-async-shell-command (file) "Open FILE with `dired-do-async-shell-command'. @@ -413,7 +441,7 @@ Otherwise the author dates are also changed." :type 'boolean) ;;;###autoload -(defun magit-reshelve-since (rev) +(defun magit-reshelve-since (rev keyid) "Change the author and committer dates of the commits since REV. Ask the user for the first reachable commit whose dates should @@ -423,8 +451,14 @@ values. The next commit will be created one minute later and so on. This command is only intended for interactive use and should only -be used on highly rearranged and unpublished history." - (interactive (list nil)) +be used on highly rearranged and unpublished history. + +If KEYID is non-nil, then use that to sign all reshelved commits. +Interactively use the value of the \"--gpg-sign\" option in the +list returned by `magit-rebase-arguments'." + (interactive (list nil + (transient-arg-value "--gpg-sign=" + (magit-rebase-arguments)))) (let* ((current (or (magit-get-current-branch) (user-error "Refusing to reshelve detached head"))) (backup (concat "refs/original/refs/heads/" current))) @@ -434,7 +468,9 @@ be used on highly rearranged and unpublished history." (not (magit-y-or-n-p (format "Backup ref %s already exists. Override? " backup)))) (user-error "Abort")) - (magit-log-select 'magit-reshelve-since + (magit-log-select + (lambda (rev) + (magit-reshelve-since rev keyid)) "Type %p on a commit to reshelve it and the commits above it,")) (t (cl-flet ((adjust (time offset) @@ -474,7 +510,11 @@ be used on highly rearranged and unpublished history." (format "export GIT_COMMITTER_DATE=\"%s\";;" date)) (cl-incf date 60))) (magit-git-lines "rev-list" "--reverse" range) - " ")) + " ")) + (and keyid + (list "--commit-filter" + (format "git commit-tree --gpg-sign=%s \"$@\";" + keyid))) range "--")) (set-process-sentinel magit-this-process @@ -491,7 +531,9 @@ be used on highly rearranged and unpublished history." (defvar magit-revision-stack nil) (defcustom magit-pop-revision-stack-format - '("[%N: %h] " "%N: %H\n %s\n" "\\[\\([0-9]+\\)[]:]") + '("[%N: %h] " + "%N: %cs %H\n %s\n" + "\\[\\([0-9]+\\)[]:]") "Control how `magit-pop-revision-stack' inserts a revision. The command `magit-pop-revision-stack' inserts a representation @@ -522,7 +564,7 @@ The expansion of POINT-FORMAT is inserted at point, and the expansion of EOB-FORMAT is inserted at the end of the buffer (if the buffer ends with a comment, then it is inserted right before that)." - :package-version '(magit . "2.3.0") + :package-version '(magit . "3.2.0") :group 'magit-commands :type '(list (choice (string :tag "Insert at point format") (cons (string :tag "Insert at point format") @@ -726,6 +768,55 @@ abbreviated revision to the `kill-ring' and the (push (list rev default-directory) magit-revision-stack) (kill-new (message "%s" rev)))))) +;;; Buffer Switching + +;;;###autoload +(defun magit-display-repository-buffer (buffer) + "Display a Magit buffer belonging to the current Git repository. +The buffer is displayed using `magit-display-buffer', which see." + (interactive (list (magit--read-repository-buffer + "Display magit buffer: "))) + (magit-display-buffer buffer)) + +;;;###autoload +(defun magit-switch-to-repository-buffer (buffer) + "Switch to a Magit buffer belonging to the current Git repository." + (interactive (list (magit--read-repository-buffer + "Switch to magit buffer: "))) + (switch-to-buffer buffer)) + +;;;###autoload +(defun magit-switch-to-repository-buffer-other-window (buffer) + "Switch to a Magit buffer belonging to the current Git repository." + (interactive (list (magit--read-repository-buffer + "Switch to magit buffer in another window: "))) + (switch-to-buffer-other-window buffer)) + +;;;###autoload +(defun magit-switch-to-repository-buffer-other-frame (buffer) + "Switch to a Magit buffer belonging to the current Git repository." + (interactive (list (magit--read-repository-buffer + "Switch to magit buffer in another frame: "))) + (switch-to-buffer-other-frame buffer)) + +(defun magit--read-repository-buffer (prompt) + (if-let ((topdir (magit-rev-parse-safe "--show-toplevel"))) + (read-buffer + prompt (magit-get-mode-buffer 'magit-status-mode) t + (pcase-lambda (`(,_ . ,buf)) + (and buf + (with-current-buffer buf + (and (or (derived-mode-p 'magit-mode + 'magit-repolist-mode + 'magit-submodule-list-mode + 'git-rebase-mode) + (and buffer-file-name + (string-match-p git-commit-filename-regexp + buffer-file-name))) + (equal (magit-rev-parse-safe "--show-toplevel") + topdir)))))) + (user-error "Not inside a Git repository"))) + ;;; Miscellaneous ;;;###autoload diff --git a/lisp/magit/magit-fetch.el b/lisp/magit/magit-fetch.el index 557749ee..432030d1 100644 --- a/lisp/magit/magit-fetch.el +++ b/lisp/magit/magit-fetch.el @@ -1,6 +1,6 @@ ;;; magit-fetch.el --- download objects and refs -*- lexical-binding: t -*- -;; Copyright (C) 2008-2021 The Magit Project Contributors +;; Copyright (C) 2008-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -29,14 +31,11 @@ (require 'magit) -;;; Options - -(defcustom magit-fetch-modules-jobs 4 - "Number of submodules to fetch in parallel. -Ignored for Git versions before v2.8.0." - :package-version '(magit . "2.12.0") - :group 'magit-commands - :type '(choice (const :tag "one at a time" nil) number)) +(defvar magit-fetch-modules-jobs nil) +(make-obsolete-variable + 'magit-fetch-modules-jobs + "invoke `magit-fetch-modules' with a prefix argument instead." + "Magit 3.0.0") ;;; Commands @@ -165,22 +164,39 @@ removed on the respective remote." (run-hooks 'magit-credential-hook) (magit-run-git-async "remote" "update")) -;;;###autoload -(defun magit-fetch-modules (&optional all) +;;;###autoload (autoload 'magit-fetch-modules "magit-fetch" nil t) +(transient-define-prefix magit-fetch-modules (&optional transient args) "Fetch all submodules. -Option `magit-fetch-modules-jobs' controls how many submodules -are being fetched in parallel. Also fetch the super-repository, -because `git-fetch' does not support not doing that. With a -prefix argument fetch all remotes." - (interactive "P") - (magit-with-toplevel - (magit-run-git-async - "fetch" "--verbose" "--recurse-submodules" - (and magit-fetch-modules-jobs - (version<= "2.8.0" (magit-git-version)) - (list "-j" (number-to-string magit-fetch-modules-jobs))) - (and all "--all")))) +Fetching is done using \"git fetch --recurse-submodules\", which +means that the super-repository and recursively all submodules +are also fetched. + +To set and potentially save other arguments invoke this command +with a prefix argument." + :man-page "git-fetch" + :value (list "--verbose" + (cond (magit-fetch-modules-jobs + (format "--jobs=%s" magit-fetch-modules-jobs)) + (t "--jobs=4"))) + ["Arguments" + ("-v" "verbose" "--verbose") + ("-a" "all remotes" "--all") + ("-j" "number of jobs" "--jobs=" :reader transient-read-number-N+)] + ["Action" + ("m" "fetch modules" magit-fetch-modules)] + (interactive (if current-prefix-arg + (list t) + (list nil (transient-args 'magit-fetch-modules)))) + (if transient + (transient-setup 'magit-fetch-modules) + (let ((git-version (magit-git-version))) + (when (version< git-version "2.8.0") + (when-let ((value (transient-arg-value "--jobs=" args))) + (message "Dropping --jobs; not supported by Git v%s" git-version) + (setq args (remove (format "--jobs=%s" value) args))))) + (magit-with-toplevel + (magit-run-git-async "fetch" "--recurse-submodules" args)))) ;;; _ (provide 'magit-fetch) diff --git a/lisp/magit/magit-files.el b/lisp/magit/magit-files.el index 57312cf7..2b91c8ef 100644 --- a/lisp/magit/magit-files.el +++ b/lisp/magit/magit-files.el @@ -1,6 +1,6 @@ ;;; magit-files.el --- finding files -*- lexical-binding: t -*- -;; Copyright (C) 2010-2021 The Magit Project Contributors +;; Copyright (C) 2010-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -30,9 +32,6 @@ ;;; Code: -(eval-when-compile - (require 'subr-x)) - (require 'magit) ;;; Find Blob @@ -206,21 +205,25 @@ is done using `magit-find-index-noselect'." (unless (equal magit-buffer-refname "{index}") (user-error "%s isn't visiting the index" file)) (if (y-or-n-p (format "Update index with contents of %s" (buffer-name))) - (let ((index (make-temp-file "index")) + (let ((index (make-temp-name (magit-git-dir "magit-update-index-"))) (buffer (current-buffer))) (when magit-wip-before-change-mode (magit-wip-commit-before-change (list file) " before un-/stage")) - (let ((coding-system-for-write buffer-file-coding-system)) - (with-temp-file index - (insert-buffer-substring buffer))) - (magit-with-toplevel - (magit-call-git "update-index" "--cacheinfo" - (substring (magit-git-string "ls-files" "-s" file) - 0 6) - (magit-git-string "hash-object" "-t" "blob" "-w" - (concat "--path=" file) - "--" index) - file)) + (unwind-protect + (progn + (let ((coding-system-for-write buffer-file-coding-system)) + (with-temp-file index + (insert-buffer-substring buffer))) + (magit-with-toplevel + (magit-call-git + "update-index" "--cacheinfo" + (substring (magit-git-string "ls-files" "-s" file) + 0 6) + (magit-git-string "hash-object" "-t" "blob" "-w" + (concat "--path=" file) + "--" (magit-convert-filename-for-git index)) + file))) + (ignore-errors (delete-file index))) (set-buffer-modified-p nil) (when magit-wip-after-apply-mode (magit-wip-commit-after-apply (list file) " after un-/stage"))) @@ -248,7 +251,7 @@ reading the FILENAME." (find-file filename wildcards)) (defun magit-find-git-config-file-other-window (filename &optional wildcards) - "Edit a file located in the current repository's git directory, in another window. + "Edit a file located in the current repo's git directory, in another window. When \".git\", located at the root of the working tree, is a regular file, then that makes it cumbersome to open a file @@ -264,7 +267,7 @@ directory, while reading the FILENAME." (find-file-other-window filename wildcards)) (defun magit-find-git-config-file-other-frame (filename &optional wildcards) - "Edit a file located in the current repository's git directory, in another frame. + "Edit a file located in the current repo's git directory, in another frame. When \".git\", located at the root of the working tree, is a regular file, then that makes it cumbersome to open a file @@ -297,7 +300,8 @@ to `magit-dispatch'." ("g" "Status" magit-status-here)] [("L" "Log..." magit-log) ("l" "Log" magit-log-buffer-file) - ("t" "Trace" magit-log-trace-definition)] + ("t" "Trace" magit-log-trace-definition) + (7 "M" "Merged" magit-log-merged)] [("B" "Blame..." magit-blame) ("b" "Blame" magit-blame-addition) ("r" "...removal" magit-blame-removal) @@ -314,7 +318,7 @@ to `magit-dispatch'." (5 "C-c c" "Checkout file" magit-file-checkout)]] (interactive) (transient-setup - (if (or buffer-file-name magit-buffer-file-name) + (if (magit-file-relative-name) 'magit-file-dispatch 'magit-dispatch))) diff --git a/lisp/magit/magit-git.el b/lisp/magit/magit-git.el index 6e985c72..ff5f0323 100644 --- a/lisp/magit/magit-git.el +++ b/lisp/magit/magit-git.el @@ -1,6 +1,6 @@ ;;; magit-git.el --- Git functionality -*- lexical-binding: t -*- -;; Copyright (C) 2010-2021 The Magit Project Contributors +;; Copyright (C) 2010-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -27,12 +29,6 @@ ;;; Code: -(require 'cl-lib) -(require 'dash) - -(eval-when-compile - (require 'subr-x)) - (require 'magit-utils) (require 'magit-section) @@ -57,7 +53,9 @@ ;; From `magit-process'. (declare-function magit-call-git "magit-process" (&rest args)) (declare-function magit-process-buffer "magit-process" (&optional nodisplay)) -(declare-function magit-process-file "magit-process" (&rest args)) +(declare-function magit-process-file "magit-process" + (process &optional infile buffer display &rest args)) +(declare-function magit-process-git "magit-process" (destination &rest args)) (declare-function magit-process-insert-section "magit-process" (pwd program args &optional errcode errlog)) (defvar magit-this-error) @@ -66,7 +64,12 @@ ;; From later in `magit-git'. (defvar magit-tramp-process-environment nil) +;; From `magit-blame'. +(declare-function magit-current-blame-chunk "magit-blame" + (&optional type noerror)) + (eval-when-compile + (cl-pushnew 'orig-rev eieio--known-slot-names) (cl-pushnew 'number eieio--known-slot-names)) ;;; Git implementations @@ -74,12 +77,12 @@ (defvar magit-inhibit-libgit nil "Whether to inhibit the use of libgit.") -(defvar magit--libgit-available-p eieio-unbound +(defvar magit--libgit-available-p 'unknown "Whether libgit is available. Use the function by the same name instead of this variable.") (defun magit--libgit-available-p () - (if (eq magit--libgit-available-p eieio-unbound) + (if (eq magit--libgit-available-p 'unknown) (setq magit--libgit-available-p (and module-file-suffix (let ((libgit (locate-library "libgit"))) @@ -131,12 +134,9 @@ the environment in order to run the non-wrapper git executables successfully.") (defcustom magit-git-executable - ;; Git might be installed in a different location on a remote, so - ;; it is better not to use the full path to the executable, except - ;; on Window where we would otherwise end up using one of the - ;; wrappers "cmd/git.exe" or "cmd/git.cmd", which are much slower - ;; than using "bin/git.exe" directly. (or (and (eq system-type 'windows-nt) + ;; Avoid the wrappers "cmd/git.exe" and "cmd/git.cmd", + ;; which are much slower than using "bin/git.exe" directly. (--when-let (executable-find "git") (ignore-errors ;; Git for Windows 2.x provides cygpath so we can @@ -163,8 +163,21 @@ successfully.") (setcdr hack-entry path-hack) (push (cons core-exe path-hack) magit-git-w32-path-hack)) core-exe)))) + (and (eq system-type 'darwin) + (executable-find "git")) "git") - "The Git executable used by Magit." + "The Git executable used by Magit on the local host. +On remote machines `magit-remote-git-executable' is used instead." + :package-version '(magit . "3.2.0") + :group 'magit-process + :type 'string) + +(defcustom magit-remote-git-executable "git" + "The Git executable used by Magit on remote machines. +On the local host `magit-git-executable' is used instead. +Consider customizing `tramp-remote-path' instead of this +option." + :package-version '(magit . "3.2.0") :group 'magit-process :type 'string) @@ -210,8 +223,9 @@ option is non-nil and git returns with a non-zero exit status, then at least its standard error is inserted into this buffer. This is only intended for debugging purposes. Do not enable this -permanently, that would negatively affect performance.") +permanently, that would negatively affect performance. +Also see `magit-process-extreme-logging'.") (defcustom magit-prefer-remote-upstream nil "Whether to favor remote branches when reading the upstream branch. @@ -227,6 +241,20 @@ that change the upstream and many that create new branches." :group 'magit-commands :type 'boolean) +(defcustom magit-list-refs-namespaces + '("refs/heads" + "refs/remotes" + "refs/tags" + "refs/pullreqs") + "List of ref namespaces considered when reading a ref. + +This controls the order of refs returned by `magit-list-refs', +which is called by functions like `magit-list-branch-names' to +generate the collection of refs." + :package-version '(magit . "3.1.0") + :group 'magit-commands + :type '(repeat string)) + (defcustom magit-list-refs-sortby nil "How to sort the ref collection in the prompt. @@ -310,6 +338,14 @@ as for that macro." (setq-local process-environment ,p) ,@body)))) +(defsubst magit-git-executable () + "Return value of `magit-git-executable' or `magit-remote-git-executable'. +The variable is chosen depending on whether `default-directory' +is remote." + (if (file-remote-p default-directory) + magit-remote-git-executable + magit-git-executable)) + (defun magit-process-git-arguments (args) "Prepare ARGS for a function that invokes Git. @@ -332,8 +368,7 @@ to do the following. (defun magit-git-exit-code (&rest args) "Execute Git with ARGS, returning its exit code." - (apply #'magit-process-file magit-git-executable nil nil nil - (magit-process-git-arguments args))) + (magit-process-git nil args)) (defun magit-git-success (&rest args) "Execute Git with ARGS, returning t if its exit code is 0." @@ -353,8 +388,7 @@ This is an experimental replacement for `magit-git-string', and still subject to major changes." (magit--with-refresh-cache (cons default-directory args) (magit--with-temp-process-buffer - (and (zerop (apply #'magit-process-file magit-git-executable nil t nil - (magit-process-git-arguments args))) + (and (zerop (magit-process-git t args)) (not (bobp)) (progn (goto-char (point-min)) @@ -374,8 +408,7 @@ still subject to major changes. Also see `magit-git-string-p'." (list default-directory 'magit-git-string-ng args) (magit--with-temp-process-buffer (let* ((args (magit-process-git-arguments args)) - (status (apply #'magit-process-file magit-git-executable - nil t nil args))) + (status (magit-process-git t args))) (if (zerop status) (and (not (bobp)) (progn @@ -401,8 +434,7 @@ ignore `magit-git-debug'." (setq args (-flatten args)) (magit--with-refresh-cache (cons default-directory args) (magit--with-temp-process-buffer - (apply #'magit-process-file magit-git-executable nil (list t nil) nil - (magit-process-git-arguments args)) + (magit-process-git (list t nil) args) (unless (bobp) (goto-char (point-min)) (buffer-substring-no-properties (point) (line-end-position)))))) @@ -412,8 +444,7 @@ ignore `magit-git-debug'." (setq args (-flatten args)) (magit--with-refresh-cache (cons default-directory args) (magit--with-temp-process-buffer - (apply #'magit-process-file magit-git-executable nil (list t nil) nil - (magit-process-git-arguments args)) + (magit-process-git (list t nil) args) (buffer-substring-no-properties (point-min) (point-max))))) (define-error 'magit-invalid-git-boolean "Not a Git boolean") @@ -425,7 +456,7 @@ signal `magit-invalid-git-boolean'." (pcase (magit-git-output args) ((or "true" "true\n") t) ((or "false" "false\n") nil) - (output (signal 'magit-invalid-git-boolean output)))) + (output (signal 'magit-invalid-git-boolean (list output))))) (defun magit-git-false (&rest args) "Execute Git with ARGS, returning t if it prints \"false\". @@ -434,7 +465,22 @@ signal `magit-invalid-git-boolean'." (pcase (magit-git-output args) ((or "true" "true\n") nil) ((or "false" "false\n") t) - (output (signal 'magit-invalid-git-boolean output)))) + (output (signal 'magit-invalid-git-boolean (list output))))) + +(defun magit-git-config-p (variable &optional default) + "Return the boolean value of the Git variable VARIABLE. +VARIABLE has to be specified as a string. Return DEFAULT (which +defaults to nil) if VARIABLE is unset. If VARIABLE's value isn't +a boolean, then raise an error." + (let ((args (list "config" "--bool" "--default" (if default "true" "false") + variable))) + (magit--with-refresh-cache (cons default-directory args) + (magit--with-temp-process-buffer + (let ((status (magit-process-git t args)) + (output (buffer-substring (point-min) (1- (point-max))))) + (if (zerop status) + (equal output "true") + (signal 'magit-invalid-git-boolean (list output)))))))) (defun magit-git-insert (&rest args) "Execute Git with ARGS, inserting its output at point. @@ -447,8 +493,7 @@ add a section in the respective process buffer." (progn (setq log (make-temp-file "magit-stderr")) (delete-file log) - (let ((exit (apply #'magit-process-file magit-git-executable - nil (list t log) nil args))) + (let ((exit (magit-process-git (list t log) args))) (when (> exit 0) (let ((msg "Git failed")) (when (file-exists-p log) @@ -466,8 +511,7 @@ add a section in the respective process buffer." (message "%s" msg))) exit)) (ignore-errors (delete-file log)))) - (apply #'magit-process-file magit-git-executable - nil (list t nil) nil args))) + (magit-process-git (list t nil) args))) (defun magit--locate-error-message () (goto-char (point-max)) @@ -542,8 +586,8 @@ call function WASHER with ARGS as its sole argument." (gethash ;; `git config --list' downcases first and last components of the key. (--> key - (replace-regexp-in-string "\\`[^.]+" #'downcase it t t) - (replace-regexp-in-string "[^.]+\\'" #'downcase it t t)) + (replace-regexp-in-string "\\`[^.]+" #'downcase it t t) + (replace-regexp-in-string "[^.]+\\'" #'downcase it t t)) (magit--with-refresh-cache (cons (magit-toplevel) 'config) (let ((configs (make-hash-table :test 'equal))) (dolist (conf (magit-git-items "config" "--list" "-z")) @@ -569,11 +613,13 @@ call function WASHER with ARGS as its sole argument." (magit-git-items "config" arg "-z" "--get-all" key)))) (defun magit-get-boolean (&rest keys) - "Return the boolean value of the Git variable specified by KEYS." + "Return the boolean value of the Git variable specified by KEYS. +Also see `magit-git-config-p'." (let ((key (mapconcat 'identity keys "."))) - (if magit--refresh-cache - (equal "true" (car (last (magit-config-get-from-cached-list key)))) - (equal (magit-git-str "config" "--bool" key) "true")))) + (equal (if magit--refresh-cache + (car (last (magit-config-get-from-cached-list key))) + (magit-git-str "config" "--bool" key)) + "true"))) (defun magit-set (value &rest keys) "Set the value of the Git variable specified by KEYS to VALUE." @@ -752,13 +798,27 @@ returning the truename." (magit--not-inside-repository-error))))) (define-error 'magit-outside-git-repo "Not inside Git repository") +(define-error 'magit-corrupt-git-config "Corrupt Git configuration") (define-error 'magit-git-executable-not-found "Git executable cannot be found (see https://magit.vc/goto/e6a78ed2)") +(defun magit--assert-usable-git () + (if (not (executable-find (magit-git-executable))) + (signal 'magit-git-executable-not-found (magit-git-executable)) + (let ((magit-git-debug + (lambda (err) + (signal 'magit-corrupt-git-config + (format "%s: %s" default-directory err))))) + ;; This should always succeed unless there's a corrupt config + ;; (or at least a similarly severe failing state). Note that + ;; git-config's --default is avoided because it's not available + ;; until Git 2.18. + (magit-git-string "config" "--get-color" "" "reset")) + nil)) + (defun magit--not-inside-repository-error () - (if (executable-find magit-git-executable) - (signal 'magit-outside-git-repo default-directory) - (signal 'magit-git-executable-not-found magit-git-executable))) + (magit--assert-usable-git) + (signal 'magit-outside-git-repo default-directory)) (defun magit-inside-gitdir-p (&optional noerror) "Return t if `default-directory' is below the repository directory. @@ -959,15 +1019,18 @@ Sorted from longest to shortest CYGWIN name." (defun magit-convert-filename-for-git (filename) "Convert FILENAME so that it can be passed to git. -1. If it's a remote filename, then remove the remote part. -2. Deal with an `windows-nt' Emacs vs. Cygwin Git incompatibility." +1. If it's a absolute filename, then pass through `expand-file-name' + to replace things such as \"~/\" that Git does not understand. +2. If it's a remote filename, then remove the remote part. +3. Deal with an `windows-nt' Emacs vs. Cygwin Git incompatibility." (if (file-name-absolute-p filename) (-if-let ((cyg . win) (cl-rassoc filename magit-cygwin-mount-points :test (lambda (f win) (string-prefix-p win f)))) (concat cyg (substring filename (length win))) - (or (file-remote-p filename 'localname) - filename)) + (let ((expanded (expand-file-name filename))) + (or (file-remote-p expanded 'localname) + expanded))) filename)) (defun magit-decode-git-path (path) @@ -1191,9 +1254,11 @@ Git." (substring it 8)))) (defun magit-name-tag (rev &optional lax) - (--when-let (magit-rev-name rev "refs/tags/*") - (and (or lax (not (string-match-p "[~^]" it))) - (substring it 5)))) + (when-let ((name (magit-rev-name rev "refs/tags/*"))) + (when (string-suffix-p "^0" name) + (setq name (substring name 0 -2))) + (and (or lax (not (string-match-p "[~^]" name))) + (substring name 5)))) (defun magit-ref-abbrev (refname) "Return an unambiguous abbreviation of REFNAME." @@ -1247,7 +1312,7 @@ to, or to some other symbolic-ref that points to the same ref." (magit-ref-equal a b))))) (defun magit-headish () - "Return \"HEAD\" or if that doesn't exist the hash of the empty tree." + "Return the `HEAD' or if that doesn't exist the hash of the empty tree." (if (magit-no-commit-p) (magit-git-string "mktree") "HEAD")) @@ -1289,15 +1354,16 @@ to, or to some other symbolic-ref that points to the same ref." (defun magit-commit-at-point () (or (magit-section-value-if 'commit) + (thing-at-point 'git-revision t) + (when-let ((chunk (magit-current-blame-chunk 'addition t))) + (oref chunk orig-rev)) (and (derived-mode-p 'magit-stash-mode 'magit-merge-preview-mode 'magit-revision-mode) magit-buffer-revision))) (defun magit-branch-or-commit-at-point () - (or (and magit-buffer-file-name - magit-buffer-refname) - (magit-section-case + (or (magit-section-case (branch (magit-ref-maybe-qualify (oref it value))) (commit (or (magit--painted-branch-at-point) (let ((rev (oref it value))) @@ -1309,6 +1375,10 @@ to, or to some other symbolic-ref that points to the same ref." (magit-ref-p (format "refs/pullreqs/%s" (oref (oref it value) number)))))) (thing-at-point 'git-revision t) + (when-let ((chunk (magit-current-blame-chunk 'addition t))) + (oref chunk orig-rev)) + (and magit-buffer-file-name + magit-buffer-refname) (and (derived-mode-p 'magit-stash-mode 'magit-merge-preview-mode 'magit-revision-mode) @@ -1325,7 +1395,7 @@ to, or to some other symbolic-ref that points to the same ref." (defun magit-remote-at-point () (magit-section-case (remote (oref it value)) - (branch (magit-section-parent-value it)))) + ([branch remote] (magit-section-parent-value it)))) (defun magit-module-at-point (&optional predicate) (when (magit-section-match 'magit-module-section) @@ -1383,7 +1453,7 @@ remote-tracking branch ref." It BRANCH is nil, then return the upstream of the current branch if any, nil otherwise. If the upstream is not configured, the configured remote is an url, or the named branch does not exist, -then return nil. I.e. return the name of an existing local or +then return nil. I.e. return the name of an existing local or remote-tracking branch. The returned string is colorized according to the branch type." (magit--with-refresh-cache (list 'magit-get-upstream-branch branch) @@ -1445,7 +1515,7 @@ according to the branch type." (when-let ((remotes (magit-list-remotes)) (remote (if (= (length remotes) 1) (car remotes) - (car (member "origin" remotes))))) + (magit-primary-remote)))) (magit--propertize-face remote 'magit-branch-remote)))) (defun magit-get-push-remote (&optional branch) @@ -1478,11 +1548,36 @@ according to the branch type." (defun magit-get-some-remote (&optional branch) (or (magit-get-remote branch) - (and (magit-branch-p "master") - (magit-get-remote "master")) - (let ((remotes (magit-list-remotes))) - (or (car (member "origin" remotes)) - (car remotes))))) + (when-let ((main (magit-main-branch))) + (magit-get-remote main)) + (magit-primary-remote) + (car (magit-list-remotes)))) + +(defvar magit-primary-remote-names + '("upstream" "origin")) + +(defun magit-primary-remote () + "Return the primary remote. + +The primary remote is the remote that tracks the repository that +other repositories are forked from. It often is called \"origin\" +but because many people name their own fork \"origin\", using that +term would be ambiguous. Likewise we avoid the term \"upstream\" +because a branch's @{upstream} branch may be a local branch or a +branch from a remote other than the primary remote. + +If a remote exists whose name matches `magit.primaryRemote', then +that is considered the primary remote. If no remote by that name +exists, then remotes in `magit-primary-remote-names' are tried in +order and the first remote from that list that actually exists in +the current repository is considered its primary remote." + (let ((remotes (magit-list-remotes))) + (seq-find (lambda (name) + (member name remotes)) + (delete-dups + (delq nil + (cons (magit-get "magit.primaryRemote") + magit-primary-remote-names)))))) (defun magit-branch-merged-p (branch &optional target) "Return non-nil if BRANCH is merged into its upstream and TARGET. @@ -1574,9 +1669,6 @@ where COMMITS is the number of commits in TAG but not in REV." (list it (car (magit-rev-diff-count it rev))) it)))))) -(defvar magit-list-refs-namespaces - '("refs/heads" "refs/remotes" "refs/tags" "refs/pull")) - (defun magit-list-refs (&optional namespaces format sortby) "Return list of references. @@ -1585,7 +1677,7 @@ rather than those from `magit-list-refs-namespaces'. FORMAT is passed to the `--format' flag of `git for-each-ref' and defaults to \"%(refname)\". If the format is \"%(refname)\" -or \"%(refname:short)\", then drop the symbolic-ref \"HEAD\". +or \"%(refname:short)\", then drop the symbolic-ref `HEAD'. SORTBY is a key or list of keys to pass to the `--sort' flag of `git for-each-ref'. When nil, use `magit-list-refs-sortby'" @@ -1636,7 +1728,7 @@ SORTBY is a key or list of keys to pass to the `--sort' flag of (defun magit-list-branches-pointing-at (commit) (let ((re (format "\\`%s refs/\\(heads\\|remotes\\)/\\(.*\\)\\'" - (magit-rev-verify commit)))) + (magit-rev-verify commit)))) (--keep (and (string-match re it) (let ((name (match-string 2 it))) (and (not (string-suffix-p "HEAD" name)) @@ -1732,14 +1824,23 @@ PATH has to be relative to the super-repository." (magit-git-string "submodule--helper" "name" path)) (defun magit-list-worktrees () - (let (worktrees worktree) + (let ((remote (file-remote-p default-directory)) + worktrees worktree) (dolist (line (let ((magit-git-global-arguments ;; KLUDGE At least in v2.8.3 this triggers a segfault. (remove "--no-pager" magit-git-global-arguments))) (magit-git-lines "worktree" "list" "--porcelain"))) (cond ((string-prefix-p "worktree" line) - (push (setq worktree (list (substring line 9) nil nil nil)) - worktrees)) + (let ((path (substring line 9))) + (when remote + (setq path (concat remote path))) + ;; If the git directory is separate from the main + ;; worktree, then "git worktree" returns the git + ;; directory instead of the worktree, which isn't + ;; what it is supposed to do and not what we want. + (setq path (magit-toplevel path)) + (setq worktree (list path nil nil nil)) + (push worktree worktrees))) ((string-equal line "bare") (let* ((default-directory (car worktree)) (wt (and (not (magit-get-boolean "core.bare")) @@ -1786,6 +1887,27 @@ PATH has to be relative to the super-repository." (defun magit-remote-p (string) (car (member string (magit-list-remotes)))) +(defvar magit-main-branch-names + ;; These are the names that Git suggests + ;; if `init.defaultBranch' is undefined. + '("main" "master" "trunk" "development")) + +(defun magit-main-branch () + "Return the main branch. + +If a branch exists whose name matches `init.defaultBranch', then +that is considered the main branch. If no branch by that name +exists, then the branch names in `magit-main-branch-names' are +tried in order. The first branch from that list that actually +exists in the current repository is considered its main branch." + (let ((branches (magit-list-local-branch-names))) + (seq-find (lambda (name) + (member name branches)) + (delete-dups + (delq nil + (cons (magit-get "init.defaultBranch") + magit-main-branch-names)))))) + (defun magit-rev-diff-count (a b) "Return the commits in A but not B and vice versa. Return a list of two integers: (A>B B>A)." @@ -1840,7 +1962,7 @@ Return a list of two integers: (A>B B>A)." (magit--with-temp-process-buffer (magit-process-file shell-file-name nil '(t nil) nil shell-command-switch - (let ((exec (shell-quote-argument magit-git-executable))) + (let ((exec (shell-quote-argument (magit-git-executable)))) (format "%s diff-tree -u %s | %s patch-id" exec rev exec))) (car (split-string (buffer-string))))) @@ -2092,12 +2214,23 @@ and this option only controls what face is used.") (re-search-forward (format "\\=[^%s]*" c) nil t)))) (bounds-of-thing-at-point 'git-revision))) (let ((text (buffer-substring-no-properties (car it) (cdr it)))) - (and (magit-commit-p text) text)))) + (and (>= (length text) 7) + (string-match-p "[a-z]" text) + (magit-commit-p text) + text)))) ;;; Completion (defvar magit-revision-history nil) +(defun magit--minibuf-default-add-commit () + (let ((fn minibuffer-default-add-function)) + (lambda () + (if-let ((commit (with-selected-window (minibuffer-selected-window) + (magit-commit-at-point)))) + (cons commit (delete commit (funcall fn))) + (funcall fn))))) + (defun magit-read-branch (prompt &optional secondary-default) (magit-completing-read prompt (magit-list-branch-names) nil t nil 'magit-revision-history @@ -2106,12 +2239,13 @@ and this option only controls what face is used.") (magit-get-current-branch)))) (defun magit-read-branch-or-commit (prompt &optional secondary-default) - (or (magit-completing-read prompt (magit-list-refnames nil t) - nil nil nil 'magit-revision-history - (or (magit-branch-or-commit-at-point) - secondary-default - (magit-get-current-branch))) - (user-error "Nothing selected"))) + (let ((minibuffer-default-add-function (magit--minibuf-default-add-commit))) + (or (magit-completing-read prompt (magit-list-refnames nil t) + nil nil nil 'magit-revision-history + (or (magit-branch-or-commit-at-point) + secondary-default + (magit-get-current-branch))) + (user-error "Nothing selected")))) (defun magit-read-range-or-commit (prompt &optional secondary-default) (magit-read-range @@ -2124,10 +2258,12 @@ and this option only controls what face is used.") (magit-get-current-branch)))) (defun magit-read-range (prompt &optional default) - (magit-completing-read-multiple prompt - (magit-list-refnames) - "\\.\\.\\.?" - default 'magit-revision-history)) + (let ((minibuffer-default-add-function (magit--minibuf-default-add-commit)) + (crm-separator "\\.\\.\\.?")) + (magit-completing-read-multiple* + (concat prompt ": ") + (magit-list-refnames) + nil nil nil 'magit-revision-history default nil t))) (defun magit-read-remote-branch (prompt &optional remote default local-branch require-match) @@ -2158,7 +2294,8 @@ and this option only controls what face is used.") (magit-get-current-branch)))) (defun magit-read-local-branch-or-commit (prompt) - (let ((choices (nconc (magit-list-local-branch-names) + (let ((minibuffer-default-add-function (magit--minibuf-default-add-commit)) + (choices (nconc (magit-list-local-branch-names) (magit-list-special-refnames))) (commit (magit-commit-at-point))) (when commit @@ -2166,7 +2303,7 @@ and this option only controls what face is used.") (or (magit-completing-read prompt choices nil nil nil 'magit-revision-history (or (magit-local-branch-at-point) commit)) - (user-error "Nothing selected")))) + (user-error "Nothing selected")))) (defun magit-read-local-branch-or-ref (prompt &optional secondary-default) (magit-completing-read prompt (nconc (magit-list-local-branch-names) @@ -2191,7 +2328,8 @@ and this option only controls what face is used.") (defun magit-read-other-branch-or-commit (prompt &optional exclude secondary-default) - (let* ((current (magit-get-current-branch)) + (let* ((minibuffer-default-add-function (magit--minibuf-default-add-commit)) + (current (magit-get-current-branch)) (atpoint (magit-branch-or-commit-at-point)) (exclude (or exclude current)) (default (or (and (not (equal atpoint exclude)) @@ -2248,9 +2386,10 @@ out. Only existing branches can be selected." (or (let ((r (car (member (magit-remote-branch-at-point) branches))) (l (car (member (magit-local-branch-at-point) branches)))) (if magit-prefer-remote-upstream (or r l) (or l r))) - (let ((r (car (member "origin/master" branches))) - (l (car (member "master" branches)))) - (if magit-prefer-remote-upstream (or r l) (or l r))) + (when-let ((main (magit-main-branch))) + (let ((r (car (member (concat "origin/" main) branches))) + (l (car (member main branches)))) + (if magit-prefer-remote-upstream (or r l) (or l r)))) (car (member (magit-get-previous-branch) branches)))))) (defun magit-read-starting-point (prompt &optional branch default) diff --git a/lisp/magit/magit-gitignore.el b/lisp/magit/magit-gitignore.el index e92f959c..634c9e28 100644 --- a/lisp/magit/magit-gitignore.el +++ b/lisp/magit/magit-gitignore.el @@ -1,6 +1,6 @@ ;;; magit-gitignore.el --- intentionally untracked files -*- lexical-binding: t -*- -;; Copyright (C) 2008-2021 The Magit Project Contributors +;; Copyright (C) 2008-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -27,9 +29,6 @@ ;;; Code: -(eval-when-compile - (require 'subr-x)) - (require 'magit) ;;; Transient @@ -71,8 +70,8 @@ repository. Also stage the file." ;;;###autoload (defun magit-gitignore-in-subdir (rule directory) - "Add the Git ignore RULE to a \".gitignore\" file. -Prompted the user for a directory and add the rule to the + "Add the Git ignore RULE to a \".gitignore\" file in DIRECTORY. +Prompt the user for a directory and add the rule to the \".gitignore\" file in that directory. Since such files are tracked, they are shared with other clones of the repository. Also stage the file." @@ -81,7 +80,7 @@ Also stage the file." (magit-with-toplevel (let ((file (expand-file-name ".gitignore" directory))) (magit--gitignore rule file) - (magit-run-git "add" file)))) + (magit-run-git "add" (magit-convert-filename-for-git file))))) ;;;###autoload (defun magit-gitignore-in-gitdir (rule) diff --git a/lisp/magit/magit-imenu.el b/lisp/magit/magit-imenu.el index 00ebc3db..fad04dec 100644 --- a/lisp/magit/magit-imenu.el +++ b/lisp/magit/magit-imenu.el @@ -1,6 +1,6 @@ ;;; magit-imenu.el --- Integrate Imenu in magit major modes -*- lexical-binding: t -*- -;; Copyright (C) 2010-2021 The Magit Project Contributors +;; Copyright (C) 2010-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Damien Cassou ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -33,9 +35,6 @@ ;;; Code: -(eval-when-compile - (require 'subr-x)) - (require 'magit) (require 'git-rebase) @@ -48,21 +47,28 @@ ENTRY-TYPES is a list of section types to be selected through `imenu'. MENU-TYPES is a list of section types containing elements of -ENTRY-TYPES. Elements of MENU-TYPES are are used to categories +ENTRY-TYPES. Elements of MENU-TYPES are used to categorize elements of ENTRY-TYPES. This function is used as a helper for functions set as `imenu-create-index-function'." - (let ((entries (make-hash-table :test 'equal))) + ;; If `which-function-mode' is active, then the create-index + ;; function is called at the time the major-mode is being enabled. + ;; Modes that derive from `magit-mode' have not populated the buffer + ;; at that time yet, so we have to abort. + (when-let ((section (magit-current-section)) + (entries (make-hash-table :test 'equal))) (goto-char (point-max)) + (unless (oref section parent) + (forward-line -1)) (while (magit-section--backward-find (lambda () (let* ((section (magit-current-section)) (type (oref section type)) (parent (oref section parent)) (parent-type (oref parent type))) - (and (-contains-p entry-types type) - (-contains-p menu-types parent-type))))) + (and (memq type entry-types) + (memq parent-type menu-types))))) (let* ((section (magit-current-section)) (name (buffer-substring-no-properties (line-beginning-position) @@ -71,6 +77,8 @@ This function is used as a helper for functions set as (parent-title (buffer-substring-no-properties (oref parent start) (1- (oref parent content))))) + (when (string-match " ([0-9]*)\\'" parent-title) + (setq parent-title (substring parent-title 0 (match-beginning 0)))) (puthash parent-title (cons (cons name (point)) (gethash parent-title entries (list))) @@ -134,10 +142,10 @@ beginning of the line." This function is used as a value for `imenu-create-index-function'." (magit-imenu--index-function - '(file commit stash) - '(unpushed unstaged unpulled untracked staged stashes))) + '(file commit stash pullreq issue) + '(unpushed unstaged unpulled untracked staged stashes pullreqs issues))) -;;;; Refs mode +;;; Refs mode ;;;###autoload (defun magit-imenu--refs-create-index-function () @@ -148,7 +156,7 @@ This function is used as a value for '(branch commit tag) '(local remote tags))) -;;;; Cherry mode +;;; Cherry mode ;;;###autoload (defun magit-imenu--cherry-create-index-function () @@ -159,7 +167,7 @@ This function is used as a value for '(commit) '(cherries))) -;;;; Submodule list mode +;;; Submodule list mode ;;;###autoload (defun magit-imenu--submodule-prev-index-position-function () @@ -177,7 +185,7 @@ This function is used as a value for beginning of the line." (elt (tabulated-list-get-entry) 0)) -;;;; Repolist mode +;;; Repolist mode ;;;###autoload (defun magit-imenu--repolist-prev-index-position-function () @@ -198,7 +206,7 @@ beginning of the line." (elt entry 0) (elt entry (1- (length entry)))))) -;;;; Process mode +;;; Process mode ;;;###autoload (defun magit-imenu--process-prev-index-position-function () @@ -218,7 +226,7 @@ beginning of the line." (buffer-substring-no-properties (line-beginning-position) (line-end-position))) -;;;; Rebase mode +;;; Rebase mode ;;;###autoload (defun magit-imenu--rebase-prev-index-position-function () diff --git a/lisp/magit/magit-log.el b/lisp/magit/magit-log.el index 350a86ce..3c9a12c1 100644 --- a/lisp/magit/magit-log.el +++ b/lisp/magit/magit-log.el @@ -1,6 +1,6 @@ ;;; magit-log.el --- inspect Git history -*- lexical-binding: t -*- -;; Copyright (C) 2010-2021 The Magit Project Contributors +;; Copyright (C) 2010-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -32,7 +34,7 @@ (require 'magit-core) (require 'magit-diff) -(declare-function magit-blob-visit "magit-files" (blob-or-file line)) +(declare-function magit-blob-visit "magit-files" (blob-or-file)) (declare-function magit-insert-head-branch-header "magit-status" (&optional branch)) (declare-function magit-insert-upstream-branch-header "magit-status" @@ -53,9 +55,6 @@ (require 'crm) (require 'which-func) -(eval-when-compile - (require 'subr-x)) - ;;; Options ;;;; Log Mode @@ -78,11 +77,11 @@ :options '("--follow" "--grep" "-G" "-S" "-L")) (defcustom magit-log-revision-headers-format "\ -%+b +%+b%+N Author: %aN <%aE> Committer: %cN <%cE>" "Additional format string used with the `++header' argument." - :package-version '(magit . "2.3.0") + :package-version '(magit . "3.2.0") :group 'magit-log :type 'string) @@ -407,10 +406,11 @@ the upstream isn't ahead of the current branch) show." ["Commit limiting" (magit-log:-n) (magit:--author) - (7 "=s" "Limit to commits since" "--since=" transient-read-date) - (7 "=u" "Limit to commits until" "--until=" transient-read-date) + (7 magit-log:--since) + (7 magit-log:--until) (magit-log:--grep) - (7 "-I" "Invert search pattern" "--invert-grep") + (7 "-i" "Search case-insensitive" ("-i" "--regexp-ignore-case")) + (7 "-I" "Invert search pattern" "--invert-grep") (magit-log:-G) ;2 (magit-log:-S) ;2 (magit-log:-L) ;2 @@ -471,7 +471,8 @@ the upstream isn't ahead of the current branch) show." (magit-log:-n) (magit:--author) (magit-log:--grep) - (7 "-I" "Invert search pattern" "--invert-grep") + (7 "-i" "Search case-insensitive" ("-i" "--regexp-ignore-case")) + (7 "-I" "Invert search pattern" "--invert-grep") (magit-log:-G) (magit-log:-S) (magit-log:-L)] @@ -549,6 +550,20 @@ the upstream isn't ahead of the current branch) show." :argument "--author=" :reader 'magit-transient-read-person) +(transient-define-argument magit-log:--since () + :description "Limit to commits since" + :class 'transient-option + :key "=s" + :argument "--since=" + :reader 'transient-read-date) + +(transient-define-argument magit-log:--until () + :description "Limit to commits until" + :class 'transient-option + :key "=u" + :argument "--until=" + :reader 'transient-read-date) + (transient-define-argument magit-log:--*-order () :description "Order commits by" :class 'transient-switches @@ -594,16 +609,17 @@ the upstream isn't ahead of the current branch) show." (defun magit-log-read-revs (&optional use-current) (or (and use-current (--when-let (magit-get-current-branch) (list it))) - (let ((collection (magit-list-refnames nil t))) - (split-string - (magit-completing-read-multiple "Log rev,s" collection - "\\(\\.\\.\\.?\\|[, ]\\)" - (or (magit-branch-or-commit-at-point) - (unless use-current - (magit-get-previous-branch))) - 'magit-revision-history - magit-log-read-revs-map) - "[, ]" t)))) + (let ((crm-separator "\\(\\.\\.\\.?\\|[, ]\\)") + (crm-local-completion-map magit-log-read-revs-map)) + (split-string (magit-completing-read-multiple* + "Log rev,s: " + (magit-list-refnames nil t) + nil nil nil 'magit-revision-history + (or (magit-branch-or-commit-at-point) + (unless use-current + (magit-get-previous-branch))) + nil t) + "[, ]" t)))) (defun magit-log-read-pattern (option) "Read a string from the user to pass as parameter to OPTION." @@ -768,7 +784,7 @@ commits instead. This command requires git-when-merged, which is available from https://github.com/mhagger/git-when-merged." (interactive - (append (let ((commit (magit-read-branch-or-commit "Commit"))) + (append (let ((commit (magit-read-branch-or-commit "Log merge of commit"))) (list commit (magit-read-other-branch "Merged into" commit))) (magit-log-arguments))) @@ -778,11 +794,9 @@ https://github.com/mhagger/git-when-merged." (let (exit m) (with-temp-buffer (save-excursion - (setq exit (magit-process-file - magit-git-executable nil t nil - "when-merged" "-c" - "--abbrev" (number-to-string (magit-abbrev-length)) - commit branch))) + (setq exit (magit-process-git t "when-merged" "-c" + (magit-abbrev-arg) + commit branch))) (setq m (buffer-substring-no-properties (point) (line-end-position)))) (if (zerop exit) (magit-log-setup-buffer (list (format "%s^1..%s" m m)) @@ -876,6 +890,26 @@ is displayed in the current frame." "\\[magit-log-double-commit-limit] first")))) (user-error "Parent %s does not exist" parent-rev)))))) +(defun magit-log-move-to-revision (rev) + "Read a revision and move to it in current log buffer. + +If the chosen reference or revision isn't being displayed in +the current log buffer, then inform the user about that and do +nothing else. + +If invoked outside any log buffer, then display the log buffer +of the current repository first; creating it if necessary." + (interactive (list (magit-read-branch-or-commit "In log, jump to"))) + (with-current-buffer + (cond ((derived-mode-p 'magit-log-mode) + (current-buffer)) + ((when-let ((buf (magit-get-mode-buffer 'magit-log-mode))) + (pop-to-buffer-same-window buf))) + (t + (apply #'magit-log-all-branches (magit-log-arguments)))) + (unless (magit-log-goto-commit-section (magit-rev-abbrev rev)) + (user-error "%s isn't visible in the current log buffer" rev)))) + ;;;; Shortlog Commands ;;;###autoload (autoload 'magit-shortlog "magit-log" nil t) @@ -896,11 +930,15 @@ is displayed in the current frame." ("r" "range" magit-shortlog-range)]) (defun magit-git-shortlog (rev args) - (with-current-buffer (get-buffer-create "*magit-shortlog*") - (erase-buffer) - (save-excursion - (magit-git-insert "shortlog" args rev)) - (switch-to-buffer-other-window (current-buffer)))) + (let ((dir default-directory)) + (with-current-buffer (get-buffer-create "*magit-shortlog*") + (setq default-directory dir) + (setq buffer-read-only t) + (let ((inhibit-read-only t)) + (erase-buffer) + (save-excursion + (magit-git-insert "shortlog" args rev)) + (switch-to-buffer-other-window (current-buffer)))))) ;;;###autoload (defun magit-shortlog-since (rev args) @@ -927,9 +965,10 @@ is displayed in the current frame." (defvar magit-log-mode-map (let ((map (make-sparse-keymap))) (set-keymap-parent map magit-mode-map) - (define-key map "\C-c\C-b" 'magit-go-backward) - (define-key map "\C-c\C-f" 'magit-go-forward) - (define-key map "\C-c\C-n" 'magit-log-move-to-parent) + (define-key map (kbd "C-c C-b") 'magit-go-backward) + (define-key map (kbd "C-c C-f") 'magit-go-forward) + (define-key map (kbd "C-c C-n") 'magit-log-move-to-parent) + (define-key map "j" 'magit-log-move-to-revision) (define-key map "=" 'magit-log-toggle-commit-limit) (define-key map "+" 'magit-log-double-commit-limit) (define-key map "-" 'magit-log-half-commit-limit) @@ -982,9 +1021,7 @@ Type \\[magit-reset] to reset `HEAD' to the commit at point. (files magit-buffer-log-files)) (magit-set-header-line-format (funcall magit-log-header-line-function revs args files)) - (if (= (length files) 1) - (unless (magit-file-tracked-p (car files)) - (setq args (cons "--full-history" args))) + (unless (= (length files) 1) (setq args (remove "--follow" args))) (when (and (car magit-log-remove-graph-args) (--any-p (string-match-p @@ -1069,6 +1106,7 @@ Do not add this to a hook variable." (setq args (cons "--decorate=full" (remove "--decorate" args)))) (when (member "--reverse" args) (setq args (remove "--graph" args))) + (setq args (magit-diff--maybe-add-stat-arguments args)) args) "--use-mailmap" "--no-prefix" revs "--" files))) @@ -1211,6 +1249,17 @@ Do not add this to a hook variable." (`stash (oset section type 'stash)) (`module (oset section type 'module-commit)) (`bisect-log (setq hash (magit-rev-parse "--short" hash)))) + (setq hash (propertize hash 'font-lock-face + (pcase (and gpg (aref gpg 0)) + (?G 'magit-signature-good) + (?B 'magit-signature-bad) + (?U 'magit-signature-untrusted) + (?X 'magit-signature-expired) + (?Y 'magit-signature-expired-key) + (?R 'magit-signature-revoked) + (?E 'magit-signature-error) + (?N 'magit-hash) + (_ 'magit-hash)))) (when cherry (when (and (derived-mode-p 'magit-refs-mode) magit-refs-show-commit-count) @@ -1227,11 +1276,11 @@ Do not add this to a hook variable." 'magit-cherry-unmatched))) (insert ?\s)) (when align - (insert (propertize hash 'font-lock-face 'magit-hash) ?\s)) + (insert hash ?\s)) (when graph (insert graph)) (unless align - (insert (propertize hash 'font-lock-face 'magit-hash) ?\s)) + (insert hash ?\s)) (when (and refs (not magit-log-show-refname-after-summary)) (insert (magit-format-ref-labels refs) ?\s)) (when (eq style 'reflog) @@ -1240,16 +1289,6 @@ Do not add this to a hook variable." (insert (magit-reflog-format-subject (substring refsub 0 (if (string-match-p ":" refsub) -2 -1)))))) (when msg - (when gpg - (setq msg (propertize msg 'font-lock-face - (pcase (aref gpg 0) - (?G 'magit-signature-good) - (?B 'magit-signature-bad) - (?U 'magit-signature-untrusted) - (?X 'magit-signature-expired) - (?Y 'magit-signature-expired-key) - (?R 'magit-signature-revoked) - (?E 'magit-signature-error))))) (insert (funcall magit-log-format-message-function hash msg))) (when (and refs magit-log-show-refname-after-summary) (insert ?\s) @@ -1363,9 +1402,8 @@ If there is no revision buffer in the same frame, then do nothing." (setq magit--update-revision-buffer (list commit buffer)) (run-with-idle-timer magit-update-other-window-delay nil - (let ((args (with-current-buffer buffer - (let ((magit-direct-use-buffer-arguments 'selected)) - (magit-show-commit--arguments))))) + (let ((args (let ((magit-direct-use-buffer-arguments 'selected)) + (magit-show-commit--arguments)))) (lambda () (pcase-let ((`(,rev ,buf) magit--update-revision-buffer)) (setq magit--update-revision-buffer nil) @@ -1402,8 +1440,7 @@ If there is no blob buffer in the same frame, then do nothing." (save-excursion (magit-blob-visit (list (magit-rev-parse rev) (magit-file-relative-name - magit-buffer-file-name)) - (line-number-at-pos)))))))))))) + magit-buffer-file-name))))))))))))) (defun magit-log-goto-commit-section (rev) (let ((abbrev (magit-rev-format "%h" rev))) @@ -1445,7 +1482,8 @@ The shortstat style is experimental and rather slow." (truncate-string-to-width (or author "") details-width - nil ?\s (make-string 1 magit-ellipsis)) + nil ?\s + (if (char-displayable-p ?…) "…" ">")) 'magit-log-author) " ")) (magit--propertize-face @@ -1504,13 +1542,13 @@ The shortstat style is experimental and rather slow." (defvar magit-log-select-mode-map (let ((map (make-sparse-keymap))) (set-keymap-parent map magit-log-mode-map) - (define-key map "\C-c\C-b" 'undefined) - (define-key map "\C-c\C-f" 'undefined) - (define-key map "." 'magit-log-select-pick) - (define-key map "e" 'magit-log-select-pick) - (define-key map "\C-c\C-c" 'magit-log-select-pick) - (define-key map "q" 'magit-log-select-quit) - (define-key map "\C-c\C-k" 'magit-log-select-quit) + (define-key map (kbd "C-c C-b") 'undefined) + (define-key map (kbd "C-c C-f") 'undefined) + (define-key map (kbd ".") 'magit-log-select-pick) + (define-key map (kbd "e") 'magit-log-select-pick) + (define-key map (kbd "C-c C-c") 'magit-log-select-pick) + (define-key map (kbd "q") 'magit-log-select-quit) + (define-key map (kbd "C-c C-k") 'magit-log-select-quit) map) "Keymap for `magit-log-select-mode'.") @@ -1600,11 +1638,12 @@ commit as argument." (funcall fun rev))) (defun magit-log-select-quit () - "Abort selecting a commit, don't act on any commit." + "Abort selecting a commit, don't act on any commit. +Call `magit-log-select-quit-function' if set." (interactive) - (magit-mode-bury-buffer 'kill) - (when magit-log-select-quit-function - (funcall magit-log-select-quit-function))) + (let ((fun magit-log-select-quit-function)) + (magit-mode-bury-buffer 'kill) + (when fun (funcall fun)))) ;;; Cherry Mode diff --git a/lisp/magit/magit-margin.el b/lisp/magit/magit-margin.el index 6d9adced..4cd8074f 100644 --- a/lisp/magit/magit-margin.el +++ b/lisp/magit/magit-margin.el @@ -1,6 +1,6 @@ ;;; magit-margin.el --- margins in Magit buffers -*- lexical-binding: t -*- -;; Copyright (C) 2010-2021 The Magit Project Contributors +;; Copyright (C) 2010-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -30,11 +32,6 @@ ;;; Code: -(require 'dash) - -(eval-when-compile - (require 'subr-x)) - (require 'magit-section) (require 'magit-transient) (require 'magit-mode) diff --git a/lisp/magit/magit-merge.el b/lisp/magit/magit-merge.el index c4f6dfe8..470cac96 100644 --- a/lisp/magit/magit-merge.el +++ b/lisp/magit/magit-merge.el @@ -1,6 +1,6 @@ ;;; magit-merge.el --- merge functionality -*- lexical-binding: t -*- -;; Copyright (C) 2010-2021 The Magit Project Contributors +;; Copyright (C) 2010-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -27,9 +29,6 @@ ;;; Code: -(eval-when-compile - (require 'subr-x)) - (require 'magit) (require 'magit-diff) @@ -48,6 +47,8 @@ ("-n" "No fast-forward" "--no-ff") (magit-merge:--strategy) (5 magit-merge:--strategy-option) + (5 "-b" "Ignore changes in amount of whitespace" "-Xignore-space-change") + (5 "-w" "Ignore whitespace when comparing lines" "-Xignore-all-space") (5 magit-diff:--diff-algorithm :argument "-Xdiff-algorithm=") (5 magit:--gpg-sign)] ["Actions" @@ -59,7 +60,7 @@ [("p" "Preview merge" magit-merge-preview) "" ("s" "Squash merge" magit-merge-squash) - ("i" "Merge into" magit-merge-into)]] + ("i" "Dissolve" magit-merge-into)]] ["Actions" :if magit-merge-in-progress-p ("m" "Commit merge" magit-commit-create) @@ -138,7 +139,7 @@ provided the respective remote branch already exists, ensuring that the respective pull-request (if any) won't get stuck on some obsolete version of the commits that are being merged. Finally if `forge-branch-pullreq' was used to create the merged branch, -branch, then also remove the respective remote branch." +then also remove the respective remote branch." (interactive (list (magit-read-other-local-branch (format "Merge `%s' into" @@ -171,9 +172,10 @@ then also remove the respective remote branch." (magit--merge-absorb branch args)) (defun magit--merge-absorb (branch args) - (when (equal branch "master") + (when (equal branch (magit-main-branch)) (unless (yes-or-no-p - "Do you really want to merge `master' into another branch? ") + (format "Do you really want to merge `%s' into another branch? " + branch)) (user-error "Abort"))) (if-let ((target (magit-get-push-branch branch t))) (progn @@ -196,7 +198,9 @@ then also remove the respective remote branch." (format "Merge branch '%s'%s [#%s]" branch (let ((current (magit-get-current-branch))) - (if (equal current "master") "" (format " into %s" current))) + (if (equal current (magit-main-branch)) + "" + (format " into %s" current))) pr) branch) (magit-run-git-async "merge" args "--no-edit" branch)) diff --git a/lisp/magit/magit-mode.el b/lisp/magit/magit-mode.el index bfd9cbda..f32bf0d7 100644 --- a/lisp/magit/magit-mode.el +++ b/lisp/magit/magit-mode.el @@ -1,6 +1,6 @@ ;;; magit-mode.el --- create and refresh Magit buffers -*- lexical-binding: t -*- -;; Copyright (C) 2010-2021 The Magit Project Contributors +;; Copyright (C) 2010-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -29,17 +31,13 @@ ;;; Code: -(require 'cl-lib) -(require 'dash) - -(eval-when-compile - (require 'subr-x)) - -(require 'transient) - (require 'magit-section) (require 'magit-git) +(require 'format-spec) +(require 'help-mode) +(require 'transient) + ;; For `magit-display-buffer-fullcolumn-most-v1' from `git-commit' (defvar git-commit-mode) ;; For `magit-refresh' @@ -51,15 +49,12 @@ ;; For `magit-refresh-buffer' (declare-function magit-process-unset-mode-line-error-status "magit-process" ()) ;; For `magit-refresh-get-relative-position' -(declare-function magit-hunk-section-p "magit-diff" (obj)) +(declare-function magit-hunk-section-p "magit-diff" (section) t) ;; For `magit-mode-setup-internal' (declare-function magit-status-goto-initial-section "magit-status" ()) ;; For `magit-mode' from `bookmark' (defvar bookmark-make-record-function) -(require 'format-spec) -(require 'help-mode) - ;;; Options (defcustom magit-mode-hook @@ -115,7 +110,7 @@ inside your function." :type 'hook) (defcustom magit-display-buffer-function 'magit-display-buffer-traditional - "The function used display a Magit buffer. + "The function used to display a Magit buffer. All Magit buffers (buffers whose major-modes derive from `magit-mode') are displayed using `magit-display-buffer', @@ -202,9 +197,9 @@ support additional %-sequences." :group 'magit-buffers :type 'boolean) -(defcustom magit-bury-buffer-function 'magit-restore-window-configuration +(defcustom magit-bury-buffer-function 'magit-mode-quit-window "The function used to bury or kill the current Magit buffer." - :package-version '(magit . "2.3.0") + :package-version '(magit . "3.2.0") :group 'magit-buffers :type '(radio (function-item quit-window) (function-item magit-mode-quit-window) @@ -231,7 +226,7 @@ Valid values are: buffer. For more information see info node `(magit)Transient Arguments -and Buffer Arguments'." +and Buffer Variables'." :package-version '(magit . "3.0.0") :group 'magit-buffers :group 'magit-commands @@ -264,7 +259,7 @@ Valid values are: buffer. For more information see info node `(magit)Transient Arguments -and Buffer Arguments'." +and Buffer Variables'." :package-version '(magit . "3.0.0") :group 'magit-buffers :group 'magit-commands @@ -341,23 +336,16 @@ recommended value." (defvar magit-mode-map (let ((map (make-sparse-keymap))) (set-keymap-parent map magit-section-mode-map) - (define-key map [C-return] 'magit-visit-thing) - (define-key map (kbd "C-m") 'magit-visit-thing) - (define-key map (kbd "C-M-i") 'magit-dired-jump) - (define-key map [M-tab] 'magit-section-cycle-diffs) - (define-key map (kbd "P") 'magit-push) - (define-key map (kbd "k") 'magit-delete-thing) - (define-key map (kbd "K") 'magit-file-untrack) - (define-key map (kbd "i") 'magit-gitignore) - (define-key map (kbd "I") 'magit-gitignore) - (define-key map (kbd "SPC") 'magit-diff-show-or-scroll-up) + (define-key map [C-return] 'magit-visit-thing) + (define-key map (kbd "RET") 'magit-visit-thing) + (define-key map (kbd "M-TAB") 'magit-dired-jump) + (define-key map [M-tab] 'magit-section-cycle-diffs) + (define-key map (kbd "SPC") 'magit-diff-show-or-scroll-up) (define-key map (kbd "S-SPC") 'magit-diff-show-or-scroll-down) - (define-key map (kbd "DEL") 'magit-diff-show-or-scroll-down) - (define-key map "+" 'magit-diff-more-context) - (define-key map "-" 'magit-diff-less-context) - (define-key map "0" 'magit-diff-default-context) - (define-key map "$" 'magit-process-buffer) - (define-key map "%" 'magit-worktree) + (define-key map (kbd "DEL") 'magit-diff-show-or-scroll-down) + (define-key map "+" 'magit-diff-more-context) + (define-key map "-" 'magit-diff-less-context) + (define-key map "0" 'magit-diff-default-context) (define-key map "a" 'magit-cherry-apply) (define-key map "A" 'magit-cherry-pick) (define-key map "b" 'magit-branch) @@ -374,13 +362,26 @@ recommended value." (define-key map "G" 'magit-refresh-all) (define-key map "h" 'magit-dispatch) (define-key map "?" 'magit-dispatch) + (define-key map "H" 'magit-describe-section) + (define-key map "i" 'magit-gitignore) + (define-key map "I" 'magit-init) + (define-key map "j" 'magit-status-quick) + (define-key map "J" 'magit-display-repository-buffer) + (define-key map "k" 'magit-delete-thing) + (define-key map "K" 'magit-file-untrack) (define-key map "l" 'magit-log) (define-key map "L" 'magit-log-refresh) (define-key map "m" 'magit-merge) (define-key map "M" 'magit-remote) + ;; section-map "n" magit-section-forward + ;; reserved "N" forge-dispatch (define-key map "o" 'magit-submodule) (define-key map "O" 'magit-subtree) + ;; section-map "p" magit-section-backward + (define-key map "P" 'magit-push) (define-key map "q" 'magit-mode-bury-buffer) + (define-key map "Q" 'magit-git-command) + (define-key map ":" 'magit-git-command) (define-key map "r" 'magit-rebase) (define-key map "R" 'magit-file-rename) (define-key map "s" 'magit-stage-file) @@ -398,8 +399,9 @@ recommended value." (define-key map "y" 'magit-show-refs) (define-key map "Y" 'magit-cherry) (define-key map "z" 'magit-stash) - (define-key map "Z" 'magit-stash) - (define-key map ":" 'magit-git-command) + (define-key map "Z" 'magit-worktree) + (define-key map "%" 'magit-worktree) + (define-key map "$" 'magit-process-buffer) (define-key map "!" 'magit-run) (define-key map (kbd "C-c C-c") 'magit-dispatch) (define-key map (kbd "C-c C-e") 'magit-edit-thing) @@ -446,6 +448,11 @@ which visits the thing at point using `browse-url'." (interactive) (user-error "There is no thing at point that could be browsed")) +(defun magit-help () + "Visit the Magit manual." + (interactive) + (info "magit")) + (defvar bug-reference-map) (with-eval-after-load 'bug-reference (define-key bug-reference-map [remap magit-visit-thing] @@ -475,8 +482,8 @@ which visits the thing at point using `browse-url'." ["Cherry pick" magit-cherry-pick t] ["Revert commit" magit-revert t] "---" - ["Ignore globally" magit-gitignore-globally t] - ["Ignore locally" magit-gitignore-locally t] + ["Ignore at toplevel" magit-gitignore-in-topdir t] + ["Ignore in subdirectory" magit-gitignore-in-subdir t] ["Discard" magit-discard t] ["Reset head and index" magit-reset-mixed t] ["Stash" magit-stash-both t] @@ -518,6 +525,7 @@ Magit is documented in info node `(magit)'." (hack-dir-local-variables-non-file-buffer) (face-remap-add-relative 'header-line 'magit-header-line) (setq mode-line-process (magit-repository-local-get 'mode-line-process)) + (setq-local revert-buffer-function 'magit-refresh-buffer) (setq-local bookmark-make-record-function 'magit--make-bookmark) (setq-local isearch-filter-predicate 'magit-section--open-temporarily)) @@ -827,11 +835,11 @@ into thinking a buffer belongs to a repo that it doesn't.") If no such buffer exists then return nil. Multiple buffers with the same major-mode may exist for a repository but only one can -exist that hasn't been looked to its value. Return that buffer +exist that hasn't been locked to its value. Return that buffer \(or nil if there is no such buffer) unless VALUE is non-nil, in -which case return the buffer that has been looked to that value. +which case return the buffer that has been locked to that value. -If FRAME nil or omitted, then consider all buffers. Otherwise +If FRAME is nil or omitted, then consider all buffers. Otherwise only consider buffers that are displayed in some live window on some frame. If `all', then consider all buffers on all frames. @@ -999,7 +1007,7 @@ window." ;;; Refresh Buffers -(defvar inhibit-magit-refresh nil) +(defvar magit-inhibit-refresh nil) (defun magit-refresh () "Refresh some buffers belonging to the current repository. @@ -1009,7 +1017,7 @@ Refresh the current buffer if its major mode derives from Run hooks `magit-pre-refresh-hook' and `magit-post-refresh-hook'." (interactive) - (unless inhibit-magit-refresh + (unless magit-inhibit-refresh (unwind-protect (let ((start (current-time)) (magit--refresh-cache (or magit--refresh-cache @@ -1061,7 +1069,7 @@ Run hooks `magit-pre-refresh-hook' and `magit-post-refresh-hook'." (defvar-local magit-refresh-start-time nil) -(defun magit-refresh-buffer () +(defun magit-refresh-buffer (&rest _ignore) "Refresh the current Magit buffer." (setq magit-refresh-start-time (current-time)) (let ((refresh (intern (format "%s-refresh-buffer" @@ -1071,18 +1079,23 @@ Run hooks `magit-pre-refresh-hook' and `magit-post-refresh-hook'." (when magit-refresh-verbose (message "Refreshing buffer `%s'..." (buffer-name))) (let* ((buffer (current-buffer)) - (windows - (--mapcat (with-selected-window it - (with-current-buffer buffer - (when-let ((section (magit-current-section))) - (list - (nconc (list it section) - (magit-refresh-get-relative-position)))))) - (or (get-buffer-window-list buffer nil t) - (list (selected-window)))))) + (windows (cl-mapcan + (lambda (window) + (with-selected-window window + (with-current-buffer buffer + (when-let ((section (magit-current-section))) + `(( ,window + ,section + ,@(magit-refresh-get-relative-position))))))) + ;; If it qualifies, then the selected window + ;; comes first, but we want to handle it last + ;; so that its `magit-section-movement-hook' + ;; run can override the effects of other runs. + (or (nreverse (get-buffer-window-list buffer nil t)) + (list (selected-window)))))) (deactivate-mark) + (setq magit-section-pre-command-section nil) (setq magit-section-highlight-overlays nil) - (setq magit-section-highlighted-section nil) (setq magit-section-highlighted-sections nil) (setq magit-section-unhighlight-sections nil) (magit-process-unset-mode-line-error-status) @@ -1091,9 +1104,12 @@ Run hooks `magit-pre-refresh-hook' and `magit-post-refresh-hook'." (save-excursion (apply refresh (with-no-warnings magit-refresh-args)))) (pcase-dolist (`(,window . ,args) windows) - (with-selected-window window + (if (eq buffer (window-buffer window)) + (with-selected-window window + (apply #'magit-section-goto-successor args)) (with-current-buffer buffer - (apply #'magit-section-goto-successor args)))) + (let ((magit-section-movement-hook nil)) + (apply #'magit-section-goto-successor args))))) (run-hooks 'magit-refresh-buffer-hook) (magit-section-update-highlight) (set-buffer-modified-p nil)) @@ -1105,7 +1121,8 @@ Run hooks `magit-pre-refresh-hook' and `magit-post-refresh-hook'." (defun magit-refresh-get-relative-position () (when-let ((section (magit-current-section))) (let ((start (oref section start))) - (list (count-lines start (point)) + (list (- (line-number-at-pos (point)) + (line-number-at-pos start)) (- (point) (line-beginning-position)) (and (magit-hunk-section-p section) (region-active-p) @@ -1189,7 +1206,7 @@ buffer which visits a file in the current repository. Optional argument (the prefix) non-nil means save all with no questions." (interactive "P") (when-let ((topdir (magit-rev-parse-safe "--show-toplevel"))) - (let ((remote (file-remote-p topdir)) + (let ((remote (file-remote-p default-directory)) (save-some-buffers-action-alist `((?Y (lambda (buffer) (with-current-buffer buffer @@ -1203,18 +1220,19 @@ argument (the prefix) non-nil means save all with no questions." ,@save-some-buffers-action-alist))) (save-some-buffers arg (lambda () - (and (not magit-inhibit-refresh-save) - buffer-file-name - ;; Avoid needlessly connecting to unrelated remotes. - (equal (file-remote-p buffer-file-name) - remote) - ;; For remote files this makes network requests and - ;; therefore has to come after the above to avoid - ;; unnecessarily waiting for unrelated hosts. - (file-exists-p (file-name-directory buffer-file-name)) - (string-prefix-p topdir (file-truename buffer-file-name)) - (equal (magit-rev-parse-safe "--show-toplevel") - topdir))))))) + (and buffer-file-name + ;; - Check whether refreshing is disabled. + (not magit-inhibit-refresh-save) + ;; - Check whether the visited file is either on the + ;; same remote as the repository, or both are on + ;; the local system. + (equal (file-remote-p buffer-file-name) remote) + ;; Delayed checks that are more expensive for remote + ;; repositories, due to the required network access. + ;; - Check whether the file is inside the repository. + (equal (magit-rev-parse-safe "--show-toplevel") topdir) + ;; - Check whether the file is actually writable. + (file-writable-p buffer-file-name))))))) ;;; Restore Window Configuration @@ -1416,7 +1434,7 @@ repository's Magit buffers." (dolist (buffer (magit-mode-get-buffers)) (with-current-buffer buffer (setq magit-section-visibility-cache nil))) - (setq magit--libgit-available-p eieio-unbound)) + (setq magit--libgit-available-p 'unknown)) ;;; Utilities diff --git a/lisp/magit/magit-notes.el b/lisp/magit/magit-notes.el index aaddf7a7..30bbc5f9 100644 --- a/lisp/magit/magit-notes.el +++ b/lisp/magit/magit-notes.el @@ -1,6 +1,6 @@ ;;; magit-notes.el --- notes support -*- lexical-binding: t -*- -;; Copyright (C) 2010-2021 The Magit Project Contributors +;; Copyright (C) 2010-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -93,7 +95,7 @@ :prompt "Set global notes.displayRef") (transient-define-argument magit-notes:--ref () - :description "Merge strategy" + :description "Manipulate ref" :class 'transient-option :key "-r" :argument "--ref=" @@ -174,7 +176,7 @@ Also see `magit-notes-merge'." it (concat "refs/notes/" it)))) -(defun magit-notes-read-refs (prompt) +(defun magit-notes-read-refs (prompt &optional _initial-input _history) (mapcar (lambda (ref) (if (string-prefix-p "refs/" ref) ref @@ -190,10 +192,10 @@ Also see `magit-notes-merge'." ",")))) (defun magit-notes-read-args (prompt) - (list (magit-read-branch-or-commit prompt (magit-stash-at-point)) - (--when-let (--first (string-match "^--ref=\\(.+\\)" it) - (transient-args 'magit-notes)) - (match-string 1 it)))) + (list (magit-read-branch-or-commit prompt (magit-stash-at-point)) + (--when-let (--first (string-match "^--ref=\\(.+\\)" it) + (transient-args 'magit-notes)) + (match-string 1 it)))) ;;; _ (provide 'magit-notes) diff --git a/lisp/magit/magit-obsolete.el b/lisp/magit/magit-obsolete.el index de73c4aa..e6605f34 100644 --- a/lisp/magit/magit-obsolete.el +++ b/lisp/magit/magit-obsolete.el @@ -1,6 +1,6 @@ ;;; magit-obsolete.el --- obsolete definitions -*- lexical-binding: t -*- -;; Copyright (C) 2010-2021 The Magit Project Contributors +;; Copyright (C) 2010-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -52,6 +54,9 @@ (define-obsolete-variable-alias 'magit-disable-line-numbers 'magit-section-disable-line-numbers "Magit 3.0.0") +(define-obsolete-variable-alias 'inhibit-magit-refresh + 'magit-inhibit-refresh "Magit 3.0.0") + (defun magit--magit-popup-warning () (display-warning 'magit "\ Magit no longer uses Magit-Popup. diff --git a/lisp/magit/magit-patch.el b/lisp/magit/magit-patch.el index 7bbadce6..e526bead 100644 --- a/lisp/magit/magit-patch.el +++ b/lisp/magit/magit-patch.el @@ -1,6 +1,6 @@ ;;; magit-patch.el --- creating and applying patches -*- lexical-binding: t -*- -;; Copyright (C) 2008-2021 The Magit Project Contributors +;; Copyright (C) 2008-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -27,9 +29,6 @@ ;;; Code: -(eval-when-compile - (require 'subr-x)) - (require 'magit) ;;; Options @@ -58,10 +57,11 @@ the prefix argument." (transient-define-prefix magit-patch () "Create or apply patches." ["Actions" - ("c" "Create patches" magit-patch-create) - ("a" "Apply patch" magit-patch-apply) - ("s" "Save diff as patch" magit-patch-save) - ("r" "Request pull" magit-request-pull)]) + [("c" "Create patches" magit-patch-create) + ("w" "Apply patches" magit-am)] + [("a" "Apply plain patch" magit-patch-apply) + ("s" "Save diff as patch" magit-patch-save)] + [("r" "Request pull" magit-request-pull)]]) ;;;###autoload (autoload 'magit-patch-create "magit-patch" nil t) (transient-define-prefix magit-patch-create (range args files) diff --git a/lisp/magit/magit-pkg.el b/lisp/magit/magit-pkg.el index b59cebd5..82f91f0a 100644 --- a/lisp/magit/magit-pkg.el +++ b/lisp/magit/magit-pkg.el @@ -1,12 +1,13 @@ -(define-package "magit" "20210105.1030" "A Git porcelain inside Emacs." +(define-package "magit" "20220102.1825" "A Git porcelain inside Emacs." '((emacs "25.1") - (async "20200113") - (dash "20200524") - (git-commit "20200516") - (transient "20200601") - (with-editor "20200522")) - :commit "25f432551347468ce97b8b03987e59092e91f8f0" :authors - '(("Marius Vollmer" . "marius.vollmer@gmail.com")) + (dash "20210826") + (git-commit "20211004") + (magit-section "20211004") + (transient "20210920") + (with-editor "20211001")) + :commit "2e73b66c2980abb9211d9881a8710c8ac5a33184" :authors + '(("Marius Vollmer" . "marius.vollmer@gmail.com") + ("Jonas Bernoulli" . "jonas@bernoul.li")) :maintainer '("Jonas Bernoulli" . "jonas@bernoul.li") :keywords diff --git a/lisp/magit/magit-process.el b/lisp/magit/magit-process.el index 535531a1..165bd162 100644 --- a/lisp/magit/magit-process.el +++ b/lisp/magit/magit-process.el @@ -1,6 +1,6 @@ ;;; magit-process.el --- process functionality -*- lexical-binding: t -*- -;; Copyright (C) 2010-2021 The Magit Project Contributors +;; Copyright (C) 2010-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -31,19 +33,14 @@ ;;; Code: -(require 'ansi-color) -(require 'cl-lib) -(require 'dash) - -(eval-when-compile - (require 'subr-x)) - -(require 'with-editor) (require 'magit-utils) (require 'magit-section) (require 'magit-git) (require 'magit-mode) +(require 'ansi-color) +(require 'with-editor) + (declare-function auth-source-search "auth-source" (&rest spec &key max require create delete &allow-other-keys)) @@ -100,11 +97,14 @@ When this is nil, no sections are ever removed." :type '(choice (const :tag "Never remove old sections" nil) integer)) (defvar magit-process-extreme-logging nil - "Whether `magit-process-file' logs to *Messages* buffer. + "Whether `magit-process-file' logs to the *Messages* buffer. + Only intended for temporary use when you try to figure out how Magit uses Git behind the scene. Output that normally goes to the magit-process buffer continues to go there. Not all output -goes to either of these two buffers.") +goes to either of these two buffers. + +Also see `magit-git-debug'.") (defcustom magit-process-error-tooltip-max-lines 20 "The number of lines for `magit-process-error-lines' to return. @@ -176,11 +176,12 @@ itself from the hook, to avoid further futile attempts." "Please enter the passphrase for the ssh key" "Please enter the passphrase to unlock the OpenPGP secret key" "^.*'s password: ?$" + "^Token: $" ; For git-credential-manager-core (#4318). "^Yubikey for .*: ?$" "^Enter PIN for .*: ?$") "List of regexps matching password prompts of Git and its subprocesses. Also see `magit-process-find-password-functions'." - :package-version '(magit . "2.8.0") + :package-version '(magit . "3.0.0") :group 'magit-process :type '(repeat (regexp))) @@ -355,7 +356,7 @@ then raise an error." (defun magit-run-git (&rest args) "Call Git synchronously in a separate process, and refresh. -Option `magit-git-executable' specifies the Git executable and +Function `magit-git-executable' specifies the Git executable and option `magit-git-global-arguments' specifies constant arguments. The arguments ARGS specify arguments to Git, they are flattened before use. @@ -377,7 +378,7 @@ Process output goes into a new section in the buffer returned by (defun magit-call-git (&rest args) "Call Git synchronously in a separate process. -Option `magit-git-executable' specifies the Git executable and +Function `magit-git-executable' specifies the Git executable and option `magit-git-global-arguments' specifies constant arguments. The arguments ARGS specify arguments to Git, they are flattened before use. @@ -386,7 +387,8 @@ Process output goes into a new section in the buffer returned by `magit-process-buffer'." (run-hooks 'magit-pre-call-git-hook) (let ((default-process-coding-system (magit--process-coding-system))) - (apply #'magit-call-process magit-git-executable + (apply #'magit-call-process + (magit-git-executable) (magit-process-git-arguments args)))) (defun magit-call-process (program &rest args) @@ -400,6 +402,17 @@ Process output goes into a new section in the buffer returned by (apply #'magit-process-file program nil process-buf nil args)) process-buf (current-buffer) default-directory section))) +(defun magit-process-git (destination &rest args) + "Call Git synchronously in a separate process, returning its exit code. +DESTINATION specifies how to handle the output, like for +`call-process', except that file handlers are supported. +Enable Cygwin's \"noglob\" option during the call and +ensure unix eol conversion." + (apply #'magit-process-file + (magit-git-executable) + nil destination nil + (magit-process-git-arguments args))) + (defun magit-process-file (process &optional infile buffer display &rest args) "Process files synchronously in a separate process. Identical to `process-file' but temporarily enable Cygwin's @@ -437,9 +450,10 @@ conversion." ARGS is flattened and then used as arguments to Git. The current buffer's content is used as the process's standard -input. +input. The buffer is assumed to be temporary and thus OK to +modify. -Option `magit-git-executable' specifies the Git executable and +Function `magit-git-executable' specifies the Git executable and option `magit-git-global-arguments' specifies constant arguments. The remaining arguments ARGS specify arguments to Git, they are flattened before use." @@ -460,11 +474,11 @@ flattened before use." (default-process-coding-system (magit--process-coding-system)) (flat-args (magit-process-git-arguments args)) (`(,process-buf . ,section) - (magit-process-setup magit-git-executable flat-args)) + (magit-process-setup (magit-git-executable) flat-args)) (inhibit-read-only t)) (magit-process-finish (apply #'call-process-region (point-min) (point-max) - magit-git-executable nil process-buf nil flat-args) + (magit-git-executable) nil process-buf nil flat-args) process-buf nil default-directory section)))) ;;; Asynchronous Processes @@ -480,7 +494,7 @@ current when this function was called (if it is a Magit buffer and still alive), as well as the respective Magit status buffer. See `magit-start-process' for more information." - (message "Running %s %s" magit-git-executable + (message "Running %s %s" (magit-git-executable) (let ((m (mapconcat #'identity (-flatten args) " "))) (remove-list-of-text-properties 0 (length m) '(face) m) m)) @@ -528,7 +542,7 @@ If INPUT is non-nil, it has to be a buffer or the name of an existing buffer. The buffer content becomes the processes standard input. -Option `magit-git-executable' specifies the Git executable and +Function `magit-git-executable' specifies the Git executable and option `magit-git-global-arguments' specifies constant arguments. The remaining arguments ARGS specify arguments to Git, they are flattened before use. @@ -540,7 +554,7 @@ and still alive), as well as the respective Magit status buffer. See `magit-start-process' for more information." (run-hooks 'magit-pre-start-git-hook) (let ((default-process-coding-system (magit--process-coding-system))) - (apply #'magit-start-process magit-git-executable input + (apply #'magit-start-process (magit-git-executable) input (magit-process-git-arguments args)))) (defun magit-start-process (program &optional input &rest args) @@ -580,11 +594,11 @@ Magit status buffer." (when (eq system-type 'windows-nt) ;; On w32, git expects UTF-8 encoded input, ignore any user ;; configuration telling us otherwise. - (set-process-coding-system process 'utf-8-unix)) + (set-process-coding-system process nil 'utf-8-unix)) (process-put process 'section section) (process-put process 'command-buf (current-buffer)) (process-put process 'default-dir default-directory) - (when inhibit-magit-refresh + (when magit-inhibit-refresh (process-put process 'inhibit-refresh t)) (oset section process process) (with-current-buffer process-buf @@ -611,7 +625,7 @@ Magit status buffer." (default-process-coding-system (magit--process-coding-system))) (apply #'start-file-process "git" process-buf - magit-git-executable args)))) + (magit-git-executable) args)))) (process-put process 'command-buf command-buf) (process-put process 'parsed (point)) (setq magit-this-process process) @@ -652,12 +666,15 @@ Magit status buffer." (defun magit-process--format-arguments (program args) (cond - ((and args (equal program magit-git-executable)) + ((and args (equal program (magit-git-executable))) (setq args (-split-at (length magit-git-global-arguments) args)) (concat (propertize (file-name-nondirectory program) 'font-lock-face 'magit-section-heading) " " - (propertize (char-to-string magit-ellipsis) + (propertize (if (stringp magit-ellipsis) + magit-ellipsis + ;; For backward compatibility. + (char-to-string magit-ellipsis)) 'font-lock-face 'magit-section-heading 'help-echo (mapconcat #'identity (car args) " ")) " " @@ -758,7 +775,9 @@ Magit status buffer." (let ((map (cl-gensym))) `(let ((,map (make-sparse-keymap))) (set-keymap-parent ,map minibuffer-local-map) - (define-key ,map "\C-g" + ;; Note: Leaving (kbd ...) unevaluated leads to the + ;; magit-process:password-prompt test failing. + (define-key ,map ,(kbd "C-g") (lambda () (interactive) (ignore-errors (kill-process ,proc)) @@ -790,13 +809,38 @@ To use this function add it to the appropriate hook 'magit-process-password-auth-source) KEY typically derives from a prompt such as: - Password for 'https://tarsius@bitbucket.org' + Password for 'https://yourname@github.com' in which case it would be the string - tarsius@bitbucket.org + yourname@github.com which matches the ~/.authinfo.gpg entry - machine bitbucket.org login tarsius password 12345 + machine github.com login yourname password 12345 or iff that is undefined, for backward compatibility - machine tarsius@bitbucket.org password 12345" + machine yourname@github.com password 12345 + +On github.com you should not use your password but a +personal access token, see [1]. For information about +the peculiarities of other forges, please consult the +respective documentation. + +After manually editing ~/.authinfo.gpg you must reset +the cache using + M-x auth-source-forget-all-cached RET + +The above will save you from having to repeatedly type +your token or password, but you might still repeatedly +be asked for your username. To prevent that, change an +URL like + https://github.com/foo/bar.git +to + https://yourname@github.com/foo/bar.git + +Instead of changing all such URLs manually, they can +be translated on the fly by doing this once + git config --global \ + url.https://yourname@github.com.insteadOf \ + https://github.com + +[1]: https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token." (require 'auth-source) (and (string-match "\\`\\(.+\\)@\\([^@]+\\)\\'" key) (let* ((user (match-string 1 key)) @@ -810,12 +854,26 @@ or iff that is undefined, for backward compatibility (funcall secret) secret)))) +(defun magit-process-git-credential-manager-core (process string) + "Authenticate using `git-credential-manager-core'. + +To use this function add it to the appropriate hook + (add-hook \\='magit-process-prompt-functions + \\='magit-process-git-credential-manager-core)" + (and (string-match "^option (enter for default): $" string) + (progn + (magit-process-buffer) + (let ((option (format "%c\n" + (read-char-choice "Option: " '(?\r ?\j ?1 ?2))))) + (insert-before-markers-and-inherit option) + (process-send-string process option))))) + (defun magit-process-password-prompt (process string) "Find a password based on prompt STRING and send it to git. Use `magit-process-password-prompt-regexps' to find a known prompt. If and only if one is found, then call functions in `magit-process-find-password-functions' until one of them returns -the password. If all function return nil, then read the password +the password. If all functions return nil, then read the password from the user." (when-let ((prompt (magit-process-match-prompt magit-process-password-prompt-regexps string))) @@ -879,7 +937,7 @@ as argument." (condition-case nil (start-process "git-credential-cache--daemon" " *git-credential-cache--daemon*" - magit-git-executable + (magit-git-executable) "credential-cache--daemon" magit-credential-cache-daemon-socket) ;; Some Git implementations (e.g. Windows) won't have @@ -922,7 +980,7 @@ as argument." (defun magit-process-set-mode-line (program args) "Display the git command (sans arguments) in the mode line." - (when (equal program magit-git-executable) + (when (equal program (magit-git-executable)) (setq args (nthcdr (length magit-git-global-arguments) args))) (let ((str (concat " " (propertize (concat (file-name-nondirectory program) @@ -971,8 +1029,8 @@ If STR is supplied, it replaces the `mode-line-process' text." ;; The following closure captures the repokey value, and is ;; added to `pre-command-hook'. (cl-labels ((enable-magit-process-unset-mode-line - () ;; Remove ourself from the hook variable, so - ;; that we only run once. + () ;;; Remove ourself from the hook variable, so + ;;; that we only run once. (remove-hook 'pre-command-hook #'enable-magit-process-unset-mode-line) ;; Clear the inhibit flag for the repository in diff --git a/lisp/magit/magit-pull.el b/lisp/magit/magit-pull.el index ad530724..db8783f3 100644 --- a/lisp/magit/magit-pull.el +++ b/lisp/magit/magit-pull.el @@ -1,6 +1,6 @@ ;;; magit-pull.el --- update local objects and refs -*- lexical-binding: t -*- -;; Copyright (C) 2008-2021 The Magit Project Contributors +;; Copyright (C) 2008-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -43,8 +45,10 @@ (transient-define-prefix magit-pull () "Pull from another repository." :man-page "git-pull" + :incompatible '(("--ff-only" "--rebase")) [:description (lambda () (if magit-pull-or-fetch "Pull arguments" "Arguments")) + ("-f" "Fast-forward only" "--ff-only") ("-r" "Rebase local commits" ("-r" "--rebase")) ("-A" "Autostash" "--autostash" :level 7)] [:description diff --git a/lisp/magit/magit-push.el b/lisp/magit/magit-push.el index 5127d0da..918053ba 100644 --- a/lisp/magit/magit-push.el +++ b/lisp/magit/magit-push.el @@ -1,6 +1,6 @@ ;;; magit-push.el --- update remote objects and refs -*- lexical-binding: t -*- -;; Copyright (C) 2008-2021 The Magit Project Contributors +;; Copyright (C) 2008-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -27,9 +29,6 @@ ;;; Code: -(eval-when-compile - (require 'subr-x)) - (require 'magit) ;;; Commands @@ -91,8 +90,10 @@ argument the push-remote can be changed before pushed to it." (magit--select-push-remote "push there"))) (when changed (magit-confirm 'set-and-push - (format "Really use \"%s\" as push-remote and push \"%s\" there" - remote branch))) + (replace-regexp-in-string + "%" "%%" + (format "Really use \"%s\" as push-remote and push \"%s\" there" + remote branch)))) (run-hooks 'magit-credential-hook) (magit-run-git-async "push" "-v" args remote (format "refs/heads/%s:refs/heads/%s" @@ -151,8 +152,10 @@ the upstream." ;; is what the user wants to happen. (setq merge (concat "refs/heads/" merge))) (magit-confirm 'set-and-push - (format "Really use \"%s\" as upstream and push \"%s\" there" - upstream branch))) + (replace-regexp-in-string + "%" "%%" + (format "Really use \"%s\" as upstream and push \"%s\" there" + upstream branch)))) (cl-pushnew "--set-upstream" args :test #'equal)) (run-hooks 'magit-credential-hook) (magit-run-git-async "push" "-v" args remote (concat branch ":" merge)))) @@ -218,11 +221,10 @@ only available for the part before the colon, or when no colon is used." (interactive (list (magit-read-remote "Push to remote") - (split-string (magit-completing-read-multiple - "Push refspec,s" - (cons "HEAD" (magit-list-local-branch-names)) - nil nil 'magit-push-refspecs-history) - crm-default-separator t) + (magit-completing-read-multiple* + "Push refspec,s: " + (cons "HEAD" (magit-list-local-branch-names)) + nil nil nil 'magit-push-refspecs-history) (magit-push-arguments))) (run-hooks 'magit-credential-hook) (magit-run-git-async "push" "-v" args remote refspecs)) @@ -284,8 +286,8 @@ If you add this suffix to a transient prefix without explicitly specifying the description, then an attempt is made to predict what this command will do. For example: - (transient-insert-suffix 'magit-push \"p\" - '(\"i\" magit-push-implicitly))" + (transient-insert-suffix \\='magit-push \"p\" + \\='(\"i\" magit-push-implicitly))" :description 'magit-push-implicitly--desc (interactive (list (magit-push-arguments))) (run-hooks 'magit-credential-hook) @@ -295,7 +297,7 @@ what this command will do. For example: (let ((default (magit-get "push.default"))) (unless (equal default "nothing") (or (when-let ((remote (or (magit-get-remote) - (magit-remote-p "origin"))) + (magit-primary-remote))) (refspec (magit-get "remote" remote "push"))) (format "%s using %s" (magit--propertize-face remote 'magit-branch-remote) diff --git a/lisp/magit/magit-reflog.el b/lisp/magit/magit-reflog.el index 03caa59a..fb79d8ef 100644 --- a/lisp/magit/magit-reflog.el +++ b/lisp/magit/magit-reflog.el @@ -1,6 +1,6 @@ ;;; magit-reflog.el --- inspect ref history -*- lexical-binding: t -*- -;; Copyright (C) 2010-2021 The Magit Project Contributors +;; Copyright (C) 2010-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -30,9 +32,6 @@ (require 'magit-core) (require 'magit-log) -(eval-when-compile - (require 'subr-x)) - ;;; Options (defcustom magit-reflog-limit 256 @@ -137,8 +136,8 @@ If `HEAD' is detached, then show the reflog for that instead." (defvar magit-reflog-mode-map (let ((map (make-sparse-keymap))) (set-keymap-parent map magit-log-mode-map) - (define-key map "\C-c\C-n" 'undefined) - (define-key map "L" 'magit-margin-settings) + (define-key map (kbd "C-c C-n") 'undefined) + (define-key map (kbd "L") 'magit-margin-settings) map) "Keymap for `magit-reflog-mode'.") diff --git a/lisp/magit/magit-refs.el b/lisp/magit/magit-refs.el index 5dd8e95b..0117e083 100644 --- a/lisp/magit/magit-refs.el +++ b/lisp/magit/magit-refs.el @@ -1,6 +1,6 @@ ;;; magit-refs.el --- listing references -*- lexical-binding: t -*- -;; Copyright (C) 2010-2021 The Magit Project Contributors +;; Copyright (C) 2010-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -27,9 +29,6 @@ ;;; Code: -(eval-when-compile - (require 'subr-x)) - (require 'magit) ;;; Options @@ -64,7 +63,7 @@ branch Show counts for branches only. nil Never show counts. To change the value in an existing buffer use the command -`magit-refs-show-commit-count'" +`magit-refs-set-show-commit-count'." :package-version '(magit . "2.1.0") :group 'magit-refs :safe (lambda (val) (memq val '(all branch nil))) @@ -278,8 +277,8 @@ the outcome. (defvar magit-refs-mode-map (let ((map (make-sparse-keymap))) (set-keymap-parent map magit-mode-map) - (define-key map "\C-y" 'magit-refs-set-show-commit-count) - (define-key map "L" 'magit-margin-settings) + (define-key map (kbd "C-y") 'magit-refs-set-show-commit-count) + (define-key map (kbd "L") 'magit-margin-settings) map) "Keymap for `magit-refs-mode'.") @@ -342,7 +341,9 @@ Type \\[magit-reset] to reset `HEAD' to the commit at point. ["Actions" ("y" "Show refs, comparing them with HEAD" magit-show-refs-head) ("c" "Show refs, comparing them with current branch" magit-show-refs-current) - ("o" "Show refs, comparing them with other branch" magit-show-refs-other)] + ("o" "Show refs, comparing them with other branch" magit-show-refs-other) + ("r" "Show refs, changing commit count display" + magit-refs-set-show-commit-count)] (interactive (list (or (derived-mode-p 'magit-refs-mode) current-prefix-arg))) (if transient @@ -528,9 +529,12 @@ line is inserted at all." (magit-insert-heading (magit-refs--format-focus-column tag 'tag) (propertize tag 'font-lock-face 'magit-tag) - (make-string (max 1 (- magit-refs-primary-column-width - (length tag))) - ?\s) + (make-string + (max 1 (- (if (consp magit-refs-primary-column-width) + (car magit-refs-primary-column-width) + magit-refs-primary-column-width) + (length tag))) + ?\s) (and msg (magit-log-propertize-keywords nil msg))) (when (and magit-refs-margin-for-tags (magit-buffer-margin-p)) (magit-refs--format-margin tag)) @@ -569,9 +573,12 @@ line is inserted at all." (magit-refs--format-focus-column branch) (magit-refs--propertize-branch abbrev ref (and headp 'magit-branch-remote-head)) - (make-string (max 1 (- magit-refs-primary-column-width - (length abbrev))) - ?\s) + (make-string + (max 1 (- (if (consp magit-refs-primary-column-width) + (car magit-refs-primary-column-width) + magit-refs-primary-column-width) + (length abbrev))) + ?\s) (and msg (magit-log-propertize-keywords nil msg)))) (when (magit-buffer-margin-p) (magit-refs--format-margin branch)) @@ -646,8 +653,7 @@ line is inserted at all." (if branch (magit-refs--propertize-branch branch ref (and headp 'magit-branch-current)) - (magit--propertize-face "(detached)" - 'font-lock-warning-face))) + (magit--propertize-face "(detached)" 'magit-branch-warning))) (u:ahead (and u:track (string-match "ahead \\([0-9]+\\)" u:track) (magit--propertize-face diff --git a/lisp/magit/magit-remote.el b/lisp/magit/magit-remote.el index 057c904b..4be41fcf 100644 --- a/lisp/magit/magit-remote.el +++ b/lisp/magit/magit-remote.el @@ -1,6 +1,6 @@ ;;; magit-remote.el --- transfer Git commits -*- lexical-binding: t -*- -;; Copyright (C) 2008-2021 The Magit Project Contributors +;; Copyright (C) 2008-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -85,7 +87,8 @@ has to be used to view and change remote related variables." ("k" "Remove" magit-remote-remove)] [("C" "Configure..." magit-remote-configure) ("p" "Prune stale branches" magit-remote-prune) - ("P" "Prune stale refspecs" magit-remote-prune-refspecs)]] + ("P" "Prune stale refspecs" magit-remote-prune-refspecs) + (7 "z" "Unshallow remote" magit-remote-unshallow)]] (interactive (list (magit-get-current-remote))) (transient-setup 'magit-remote nil nil :scope remote)) @@ -255,6 +258,24 @@ Delete the symbolic-ref \"refs/remotes//HEAD\"." (interactive (list (magit-read-remote "Unset HEAD for remote"))) (magit-run-git "remote" "set-head" remote "--delete")) +;;;###autoload +(defun magit-remote-unshallow (remote) + "Convert a shallow remote into a full one. +If only a single refspec is set and it does not contain a +wildcard, then also offer to replace it with the standard +refspec." + (interactive (list (or (magit-get-current-remote) + (magit-read-remote "Delete remote")))) + (let ((refspecs (magit-get-all "remote" remote "fetch")) + (standard (format "+refs/heads/*:refs/remotes/%s/*" remote))) + (when (and (= (length refspecs) 1) + (not (string-match-p "\\*" (car refspecs))) + (yes-or-no-p (format "Also replace refspec %s with %s? " + (car refspecs) + standard))) + (magit-set standard "remote" remote "fetch")) + (magit-git-fetch "--unshallow" remote))) + ;;; Configure ;;;###autoload (autoload 'magit-remote-configure "magit-remote" nil t) diff --git a/lisp/magit/magit-repos.el b/lisp/magit/magit-repos.el index d54e1f78..123c2edb 100644 --- a/lisp/magit/magit-repos.el +++ b/lisp/magit/magit-repos.el @@ -1,6 +1,6 @@ ;;; magit-repos.el --- listing repositories -*- lexical-binding: t -*- -;; Copyright (C) 2010-2021 The Magit Project Contributors +;; Copyright (C) 2010-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -29,12 +31,9 @@ ;;; Code: -(eval-when-compile - (require 'subr-x)) - (require 'magit-core) -(declare-function magit-status-setup-buffer "magit-status" (directory)) +(declare-function magit-status-setup-buffer "magit-status" (&optional directory)) (defvar x-stretch-cursor) @@ -89,10 +88,16 @@ and with `default-directory' bound to the toplevel of its working tree. It has to return a string to be inserted or nil. PROPS is an alist that supports the keys `:right-align' and `:pad-right'. Some entries also use `:help-echo', but `tabulated-list' does not -actually support that yet." +actually support that yet. + +You may wish to display a range of numeric columns using just one +character per column and without any padding between columns, in +which case you should use an appropriat HEADER, set WIDTH to 1, +and set `:pad-right' to 0. \"+\" is substituted for numbers higher +than 9." :package-version '(magit . "2.12.0") :group 'magit-repolist - :type `(repeat (list :tag "Column" + :type '(repeat (list :tag "Column" (string :tag "Header Label") (integer :tag "Column Width") (function :tag "Inserter Function") @@ -119,6 +124,18 @@ as the value of `magit-repolist-column-flag'." :type '(alist :key-type (function :tag "Predicate Function") :value-type (string :tag "Flag"))) +(defcustom magit-repolist-sort-key '("Path" . nil) + "Initial sort key for buffer created by `magit-list-repositories'. +If nil, no additional sorting is performed. Otherwise, this +should be a cons cell (NAME . FLIP). NAME is a string matching +one of the column names in `magit-repolist-columns'. FLIP, if +non-nil, means to invert the resulting sort." + :package-version '(magit . "3.2.0") + :group 'magit-repolist + :type '(choice (const nil) + (cons (string :tag "Column name") + (boolean :tag "Flip order")))) + ;;; List Repositories ;;;; Command ;;;###autoload @@ -128,14 +145,7 @@ as the value of `magit-repolist-column-flag'." Use the options `magit-repository-directories' to control which repositories are displayed." (interactive) - (if magit-repository-directories - (with-current-buffer (get-buffer-create "*Magit Repositories*") - (magit-repolist-mode) - (magit-repolist-refresh) - (tabulated-list-print) - (switch-to-buffer (current-buffer))) - (message "You need to customize `magit-repository-directories' %s" - "before you can list repositories"))) + (magit-repolist-setup (default-value 'magit-repolist-columns))) ;;;; Mode @@ -157,64 +167,98 @@ repositories are displayed." "Major mode for browsing a list of Git repositories." (setq-local x-stretch-cursor nil) (setq tabulated-list-padding 0) - (setq tabulated-list-sort-key (cons "Path" nil)) - (setq tabulated-list-format - (vconcat (mapcar (pcase-lambda (`(,title ,width ,_fn ,props)) - (nconc (list title width t) - (-flatten props))) - magit-repolist-columns))) - (tabulated-list-init-header) (add-hook 'tabulated-list-revert-hook 'magit-repolist-refresh nil t) (setq imenu-prev-index-position-function 'magit-imenu--repolist-prev-index-position-function) (setq imenu-extract-index-name-function 'magit-imenu--repolist-extract-index-name-function)) +(defun magit-repolist-setup (columns) + (unless magit-repository-directories + (user-error "You need to customize `magit-repository-directories' %s" + "before you can list repositories")) + (with-current-buffer (get-buffer-create "*Magit Repositories*") + (magit-repolist-mode) + (setq-local magit-repolist-columns columns) + (magit-repolist-refresh) + (switch-to-buffer (current-buffer)))) + (defun magit-repolist-refresh () + (unless tabulated-list-sort-key + (setq tabulated-list-sort-key + (pcase-let ((`(,column . ,flip) magit-repolist-sort-key)) + (cons (or (car (assoc column magit-repolist-columns)) + (caar magit-repolist-columns)) + flip)))) + (setq tabulated-list-format + (vconcat (mapcar (pcase-lambda (`(,title ,width ,_fn ,props)) + (nconc (list title width t) + (-flatten props))) + magit-repolist-columns))) (setq tabulated-list-entries (mapcar (pcase-lambda (`(,id . ,path)) (let ((default-directory path)) (list path - (vconcat (--map (or (funcall (nth 2 it) id) "") - magit-repolist-columns))))) + (vconcat + (mapcar (pcase-lambda (`(,title ,width ,fn ,props)) + (or (funcall fn `((:id ,id) + (:title ,title) + (:width ,width) + ,@props)) + "")) + magit-repolist-columns))))) (magit-list-repos-uniquify (--map (cons (file-name-nondirectory (directory-file-name it)) it) - (magit-list-repos)))))) + (magit-list-repos))))) + (message "Listing repositories...") + (tabulated-list-init-header) + (tabulated-list-print t) + (message "Listing repositories...done")) ;;;; Columns -(defun magit-repolist-column-ident (id) +(defun magit-repolist-column-ident (spec) "Insert the identification of the repository. Usually this is just its basename." - id) + (cadr (assq :id spec))) -(defun magit-repolist-column-path (_id) +(defun magit-repolist-column-path (_) "Insert the absolute path of the repository." (abbreviate-file-name default-directory)) -(defun magit-repolist-column-version (_id) +(defun magit-repolist-column-version (_) "Insert a description of the repository's `HEAD' revision." (when-let ((v (or (magit-git-string "describe" "--tags" "--dirty") ;; If there are no tags, use the date in MELPA format. (magit-git-string "show" "--no-patch" "--format=%cd-g%h" "--date=format:%Y%m%d.%H%M")))) (save-match-data - (when (string-match "-dirty\\'" v) - (magit--put-face (1+ (match-beginning 0)) (length v) 'error v)) + (when (string-match + "\\(?:-\\([0-9]*\\)-g[a-z0-9]*\\)?\\(?:-\\(dirty\\)\\)?\\'" v) + (magit--put-face (match-beginning 0) (match-end 0) 'shadow v) + (when (match-end 1) + (magit--put-face (match-beginning 1) (match-end 1) 'bold v)) + (when (match-end 2) + (magit--put-face (match-beginning 2) (match-end 2) 'error v))) (if (and v (string-match "\\`[0-9]" v)) (concat " " v) + (when (and v (string-match "\\`[^0-9]+" v)) + (magit--put-face 0 (match-end 0) 'shadow v)) v)))) -(defun magit-repolist-column-branch (_id) +(defun magit-repolist-column-branch (_) "Insert the current branch." - (magit-get-current-branch)) + (let ((branch (magit-get-current-branch))) + (if (member branch magit-main-branch-names) + (magit--propertize-face branch 'shadow) + branch))) -(defun magit-repolist-column-upstream (_id) +(defun magit-repolist-column-upstream (_) "Insert the upstream branch of the current branch." (magit-get-upstream-branch)) -(defun magit-repolist-column-flag (_id) +(defun magit-repolist-column-flag (_) "Insert a flag as specified by `magit-repolist-column-flag-alist'. By default this indicates whether there are uncommitted changes. @@ -226,43 +270,50 @@ Only one letter is shown, the first that applies." (and (funcall fun) flag)) magit-repolist-column-flag-alist)) -(defun magit-repolist-column-unpulled-from-upstream (_id) +(defun magit-repolist-column-flags (_) + "Insert all flags as specified by `magit-repolist-column-flag-alist'. +This is an alternative to function `magit-repolist-column-flag', +which only lists the first one found." + (mapconcat (pcase-lambda (`(,fun . ,flag)) + (if (funcall fun) flag " ")) + magit-repolist-column-flag-alist + "")) + +(defun magit-repolist-column-unpulled-from-upstream (spec) "Insert number of upstream commits not in the current branch." (--when-let (magit-get-upstream-branch) - (let ((n (cadr (magit-rev-diff-count "HEAD" it)))) - (magit--propertize-face - (number-to-string n) (if (> n 0) 'bold 'shadow))))) + (magit-repolist-insert-count (cadr (magit-rev-diff-count "HEAD" it)) spec))) -(defun magit-repolist-column-unpulled-from-pushremote (_id) +(defun magit-repolist-column-unpulled-from-pushremote (spec) "Insert number of commits in the push branch but not the current branch." (--when-let (magit-get-push-branch nil t) - (let ((n (cadr (magit-rev-diff-count "HEAD" it)))) - (magit--propertize-face - (number-to-string n) (if (> n 0) 'bold 'shadow))))) + (magit-repolist-insert-count (cadr (magit-rev-diff-count "HEAD" it)) spec))) -(defun magit-repolist-column-unpushed-to-upstream (_id) +(defun magit-repolist-column-unpushed-to-upstream (spec) "Insert number of commits in the current branch but not its upstream." (--when-let (magit-get-upstream-branch) - (let ((n (car (magit-rev-diff-count "HEAD" it)))) - (magit--propertize-face - (number-to-string n) (if (> n 0) 'bold 'shadow))))) + (magit-repolist-insert-count (car (magit-rev-diff-count "HEAD" it)) spec))) -(defun magit-repolist-column-unpushed-to-pushremote (_id) +(defun magit-repolist-column-unpushed-to-pushremote (spec) "Insert number of commits in the current branch but not its push branch." (--when-let (magit-get-push-branch nil t) - (let ((n (car (magit-rev-diff-count "HEAD" it)))) - (magit--propertize-face - (number-to-string n) (if (> n 0) 'bold 'shadow))))) + (magit-repolist-insert-count (car (magit-rev-diff-count "HEAD" it)) spec))) -(defun magit-repolist-column-branches (_id) +(defun magit-repolist-column-branches (spec) "Insert number of branches." - (let ((n (length (magit-list-local-branches)))) - (magit--propertize-face (number-to-string n) (if (> n 1) 'bold 'shadow)))) + (magit-repolist-insert-count (length (magit-list-local-branches)) + `((:normal-count 1) ,@spec))) -(defun magit-repolist-column-stashes (_id) +(defun magit-repolist-column-stashes (spec) "Insert number of stashes." - (let ((n (length (magit-list-stashes)))) - (magit--propertize-face (number-to-string n) (if (> n 0) 'bold 'shadow)))) + (magit-repolist-insert-count (length (magit-list-stashes)) spec)) + +(defun magit-repolist-insert-count (n spec) + (magit--propertize-face + (if (and (> n 9) (= (cadr (assq :width spec)) 1)) + "+" + (number-to-string n)) + (if (> n (or (cadr (assq :normal-count spec)) 0)) 'bold 'shadow))) ;;; Read Repository diff --git a/lisp/magit/magit-reset.el b/lisp/magit/magit-reset.el index 5a6e5389..6203a69e 100644 --- a/lisp/magit/magit-reset.el +++ b/lisp/magit/magit-reset.el @@ -1,6 +1,6 @@ ;;; magit-reset.el --- reset fuctionality -*- lexical-binding: t -*- -;; Copyright (C) 2010-2021 The Magit Project Contributors +;; Copyright (C) 2010-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) diff --git a/lisp/magit/magit-section.el b/lisp/magit/magit-section.el deleted file mode 100644 index ae05134c..00000000 --- a/lisp/magit/magit-section.el +++ /dev/null @@ -1,1776 +0,0 @@ -;;; magit-section.el --- Sections for read-only buffers -*- lexical-binding: t -*- - -;; Copyright (C) 2010-2021 The Magit Project Contributors -;; -;; You should have received a copy of the AUTHORS.md file which -;; lists all contributors. If not, see http://magit.vc/authors. - -;; Author: Jonas Bernoulli -;; Maintainer: Jonas Bernoulli - -;; Package-Requires: ((emacs "25.1") (dash "20200524")) -;; Keywords: tools -;; Homepage: https://github.com/magit/magit - -;; Magit-Section 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, or (at your option) -;; any later version. -;; -;; Magit-Section 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 Magit. If not, see http://www.gnu.org/licenses. - -;;; Commentary: - -;; This package implements the main user interface of Magit — the -;; collapsible sections that make up its buffers. This package used -;; to be distributed as part of Magit but now it can also be used by -;; other packages that have nothing to do with Magit or Git. - -;;; Code: - -(require 'cl-lib) -(require 'dash) -(require 'eieio) - -(eval-when-compile - (require 'benchmark) - (require 'subr-x)) - -;;; Hooks - -(defvar magit-section-movement-hook nil - "Hook run by `magit-section-goto'. -That function in turn is used by all section movement commands.") - -(defvar magit-section-highlight-hook - '(magit-section-highlight - magit-section-highlight-selection) - "Functions used to highlight the current section. -Each function is run with the current section as only argument -until one of them returns non-nil.") - -(defvar magit-section-unhighlight-hook nil - "Functions used to unhighlight the previously current section. -Each function is run with the current section as only argument -until one of them returns non-nil. Most sections are properly -unhighlighted without requiring a specialized unhighlighter, -diff-related sections being the only exception.") - -(defvar magit-section-set-visibility-hook - '(magit-section-cached-visibility) - "Hook used to set the initial visibility of a section. -Stop at the first function that returns non-nil. The returned -value should be `show', `hide' or nil. If no function returns -non-nil, determine the visibility as usual, i.e. use the -hardcoded section specific default (see `magit-insert-section').") - -(defvar magit-section-goto-successor-hook nil - "Hook used to go to the same section as was current before a refresh. -This is only used if the standard mechanism for doing so did not -succeed.") - -;;; Options - -(defgroup magit-section nil - "Expandable sections." - :link '(info-link "(magit)Sections") - :group 'extensions) - -(defcustom magit-section-show-child-count t - "Whether to append the number of children to section headings. -This only applies to sections for which doing so makes sense." - :package-version '(magit . "2.1.0") - :group 'magit-section - :type 'boolean) - -(defcustom magit-section-cache-visibility t - "Whether to cache visibility of sections. - -Sections always retain their visibility state when they are being -recreated during a refresh. But if a section disappears and then -later reappears again, then this option controls whether this is -the case. - -If t, then cache the visibility of all sections. If a list of -section types, then only do so for matching sections. If nil, -then don't do so for any sections." - :package-version '(magit . "2.12.0") - :group 'magit-section - :type '(choice (const :tag "Don't cache visibility" nil) - (const :tag "Cache visibility of all sections" t) - (repeat :tag "Cache visibility for section types" symbol))) - -(defcustom magit-section-initial-visibility-alist - '((stashes . hide)) - "Alist controlling the initial visibility of sections. - -Each element maps a section type or lineage to the initial -visibility state for such sections. The state has to be one of -`show' or `hide', or a function that returns one of these symbols. -A function is called with the section as the only argument. - -Use the command `magit-describe-section' to determine a section's -lineage or type. The vector in the output is the section lineage -and the type is the first element of that vector. Wildcards can -be used, see `magit-section-match'. - -Currently this option is only used to override hardcoded defaults, -but in the future it will also be used set the defaults. - -An entry whose key is `magit-status-initial-section' specifies -the visibility of the section `magit-status-goto-initial-section' -jumps to. This does not only override defaults, but also other -entries of this alist." - :package-version '(magit . "2.12.0") - :group 'magit-section - :type '(alist :key-type (sexp :tag "Section type/lineage") - :value-type (choice (const hide) - (const show) - function))) - -(defcustom magit-section-visibility-indicator - (if (window-system) - '(magit-fringe-bitmap> . magit-fringe-bitmapv) - '("…" . t)) - "Whether and how to indicate that a section can be expanded/collapsed. - -If nil, then don't show any indicators. -Otherwise the value has to have one of these two forms: - -\(EXPANDABLE-BITMAP . COLLAPSIBLE-BITMAP) - - Both values have to be variables whose values are fringe - bitmaps. In this case every section that can be expanded or - collapsed gets an indicator in the left fringe. - - To provide extra padding around the indicator, set - `left-fringe-width' in `magit-mode-hook'. - -\(STRING . BOOLEAN) - - In this case STRING (usually an ellipsis) is shown at the end - of the heading of every collapsed section. Expanded sections - get no indicator. The cdr controls whether the appearance of - these ellipsis take section highlighting into account. Doing - so might potentially have an impact on performance, while not - doing so is kinda ugly." - :package-version '(magit . "3.0.0") - :group 'magit-section - :type '(choice (const :tag "No indicators" nil) - (cons :tag "Use +- fringe indicators" - (const magit-fringe-bitmap+) - (const magit-fringe-bitmap-)) - (cons :tag "Use >v fringe indicators" - (const magit-fringe-bitmap>) - (const magit-fringe-bitmapv)) - (cons :tag "Use bold >v fringe indicators)" - (const magit-fringe-bitmap-bold>) - (const magit-fringe-bitmap-boldv)) - (cons :tag "Use custom fringe indicators" - (variable :tag "Expandable bitmap variable") - (variable :tag "Collapsible bitmap variable")) - (cons :tag "Use ellipses at end of headings" - (string :tag "Ellipsis" "…") - (choice :tag "Use face kludge" - (const :tag "Yes (potentially slow)" t) - (const :tag "No (kinda ugly)" nil))))) - -(defcustom magit-keep-region-overlay nil - "Whether to keep the region overlay when there is a valid selection. - -By default Magit removes the regular region overlay if, and only -if, that region constitutes a valid selection as understood by -Magit commands. Otherwise it does not remove that overlay, and -the region looks like it would in other buffers. - -There are two types of such valid selections: hunk-internal -regions and regions that select two or more sibling sections. -In such cases Magit removes the region overlay and instead -highlights a slightly larger range. All text (for hunk-internal -regions) or the headings of all sections (for sibling selections) -that are inside that range (not just inside the region) are acted -on by commands such as the staging command. This buffer range -begins at the beginning of the line on which the region begins -and ends at the end of the line on which the region ends. - -Because Magit acts on this larger range and not the region, it is -actually quite important to visualize that larger range. If we -don't do that, then one might think that these commands act on -the region instead. If you want to *also* visualize the region, -then set this option to t. But please note that when the region -does *not* constitute a valid selection, then the region is -*always* visualized as usual, and that it is usually under such -circumstances that you want to use a non-magit command to act on -the region. - -Besides keeping the region overlay, setting this option to t also -causes all face properties, except for `:foreground', to be -ignored for the faces used to highlight headings of selected -sections. This avoids the worst conflicts that result from -displaying the region and the selection overlays at the same -time. We are not interested in dealing with other conflicts. -In fact we *already* provide a way to avoid all of these -conflicts: *not* changing the value of this option. - -It should be clear by now that we consider it a mistake to set -this to display the region when the Magit selection is also -visualized, but since it has been requested a few times and -because it doesn't cost much to offer this option we do so. -However that might change. If the existence of this option -starts complicating other things, then it will be removed." - :package-version '(magit . "2.3.0") - :group 'magit-section - :type 'boolean) - -(defcustom magit-section-disable-line-numbers t - "In Magit buffers, whether to disable modes that display line numbers. - -Some users who turn on `global-display-line-numbers-mode' (or -`global-nlinum-mode' or `global-linum-mode') expect line numbers -to be displayed everywhere except in Magit buffers. Other users -do not expect Magit buffers to be treated differently. At least -in theory users in the first group should not use the global mode, -but that ship has sailed, thus this option." - :package-version '(magit . "3.0.0") - :group 'magit-section - :type 'boolean) - -;;; Faces - -(defgroup magit-section-faces nil - "Faces used by Magit-Section." - :group 'magit-section - :group 'faces) - -(defface magit-section-highlight - `((((class color) (background light)) - ,@(and (>= emacs-major-version 27) '(:extend t)) - :background "grey95") - (((class color) (background dark)) - ,@(and (>= emacs-major-version 27) '(:extend t)) - :background "grey20")) - "Face for highlighting the current section." - :group 'magit-section-faces) - -(defface magit-section-heading - `((((class color) (background light)) - ,@(and (>= emacs-major-version 27) '(:extend t)) - :foreground "DarkGoldenrod4" - :weight bold) - (((class color) (background dark)) - ,@(and (>= emacs-major-version 27) '(:extend t)) - :foreground "LightGoldenrod2" - :weight bold)) - "Face for section headings." - :group 'magit-section-faces) - -(defface magit-section-secondary-heading - `((t ,@(and (>= emacs-major-version 27) '(:extend t)) - :weight bold)) - "Face for section headings of some secondary headings." - :group 'magit-section-faces) - -(defface magit-section-heading-selection - `((((class color) (background light)) - ,@(and (>= emacs-major-version 27) '(:extend t)) - :foreground "salmon4") - (((class color) (background dark)) - ,@(and (>= emacs-major-version 27) '(:extend t)) - :foreground "LightSalmon3")) - "Face for selected section headings." - :group 'magit-section-faces) - -;;; Classes - -(defvar magit--current-section-hook nil - "Internal variable used for `magit-describe-section'.") - -(defvar magit--section-type-alist nil) - -(defclass magit-section () - ((keymap :initform nil :allocation :class) - (type :initform nil :initarg :type) - (value :initform nil :initarg :value) - (start :initform nil :initarg :start) - (content :initform nil) - (end :initform nil) - (hidden :initform nil) - (washer :initform nil) - (process :initform nil) - (heading-highlight-face :initform nil) - (inserter :initform (symbol-value 'magit--current-section-hook)) - (parent :initform nil :initarg :parent) - (children :initform nil))) - -;;; Mode - -(defvar symbol-overlay-inhibit-map) - -(defvar magit-section-mode-map - (let ((map (make-keymap))) - (suppress-keymap map t) - (define-key map (kbd "C-i") 'magit-section-toggle) - (define-key map [C-tab] 'magit-section-cycle) - (define-key map [M-tab] 'magit-section-cycle) - ;; [backtab] is the most portable binding for Shift+Tab. - (define-key map [backtab] 'magit-section-cycle-global) - (define-key map (kbd "^") 'magit-section-up) - (define-key map (kbd "p") 'magit-section-backward) - (define-key map (kbd "n") 'magit-section-forward) - (define-key map (kbd "M-p") 'magit-section-backward-sibling) - (define-key map (kbd "M-n") 'magit-section-forward-sibling) - (define-key map "1" 'magit-section-show-level-1) - (define-key map "2" 'magit-section-show-level-2) - (define-key map "3" 'magit-section-show-level-3) - (define-key map "4" 'magit-section-show-level-4) - (define-key map (kbd "M-1") 'magit-section-show-level-1-all) - (define-key map (kbd "M-2") 'magit-section-show-level-2-all) - (define-key map (kbd "M-3") 'magit-section-show-level-3-all) - (define-key map (kbd "M-4") 'magit-section-show-level-4-all) - map)) - -(define-derived-mode magit-section-mode special-mode "Magit-Sections" - "Parent major mode from which major modes with Magit-like sections inherit. - -Magit-Section is documented in info node `(magit-section)'." - :group 'magit-section - (buffer-disable-undo) - (setq truncate-lines t) - (setq buffer-read-only t) - (setq-local line-move-visual t) ; see #1771 - ;; Turn off syntactic font locking, but not by setting - ;; `font-lock-defaults' because that would enable font locking, and - ;; not all magit plugins may be ready for that (see #3950). - (setq-local font-lock-syntactic-face-function #'ignore) - (setq show-trailing-whitespace nil) - (setq-local symbol-overlay-inhibit-map t) - (setq list-buffers-directory (abbreviate-file-name default-directory)) - ;; (hack-dir-local-variables-non-file-buffer) - (make-local-variable 'text-property-default-nonsticky) - (push (cons 'keymap t) text-property-default-nonsticky) - (add-hook 'post-command-hook #'magit-section-update-highlight t t) - (add-hook 'deactivate-mark-hook #'magit-section-update-highlight t t) - (setq-local redisplay-highlight-region-function - 'magit-section--highlight-region) - (setq-local redisplay-unhighlight-region-function - 'magit-section--unhighlight-region) - (when magit-section-disable-line-numbers - (when (bound-and-true-p global-linum-mode) - (linum-mode -1)) - (when (and (fboundp 'nlinum-mode) - (bound-and-true-p global-nlinum-mode)) - (nlinum-mode -1)) - (when (and (fboundp 'display-line-numbers-mode) - (bound-and-true-p global-display-line-numbers-mode)) - (display-line-numbers-mode -1))) - (when (fboundp 'magit-preserve-section-visibility-cache) - (add-hook 'kill-buffer-hook #'magit-preserve-section-visibility-cache))) - -;;; Core - -(defvar-local magit-root-section nil - "The root section in the current buffer. -All other sections are descendants of this section. The value -of this variable is set by `magit-insert-section' and you should -never modify it.") -(put 'magit-root-section 'permanent-local t) - -(defun magit-current-section () - "Return the section at point." - (or (get-text-property (point) 'magit-section) magit-root-section)) - -(defun magit-section-ident (section) - "Return an unique identifier for SECTION. -The return value has the form ((TYPE . VALUE)...)." - (with-slots (type value parent) section - (cons (cons type - (cond ((eieio-object-p value) - (magit-section-ident-value value)) - ((not (memq type '(unpulled unpushed))) value) - ((string-match-p "@{upstream}" value) value) - ;; Unfortunately Git chokes on "@{push}" when - ;; the value of `push.default' does not allow a - ;; 1:1 mapping. Arbitrary commands may consult - ;; the section value so we cannot use "@{push}". - ;; But `unpushed' and `unpulled' sections should - ;; keep their identity when switching branches - ;; so we have to use another value here. - ((string-match-p "\\`\\.\\." value) "..@{push}") - (t "@{push}.."))) - (and parent - (magit-section-ident parent))))) - -(cl-defgeneric magit-section-ident-value (value) - "Return a constant representation of VALUE. -VALUE is the value of a `magit-section' object. If that is an -object itself, then that is not suitable to be used to identify -the section because two objects may represent the same thing but -not be equal. If possible a method should be added for such -objects, which returns a value that is equal. Otherwise the -catch-all method is used, which just returns the argument -itself.") - -(cl-defmethod magit-section-ident-value (arg) arg) - -(defun magit-get-section (ident &optional root) - "Return the section identified by IDENT. -IDENT has to be a list as returned by `magit-section-ident'. -If optional ROOT is non-nil, then search in that section tree -instead of in the one whose root `magit-root-section' is." - (setq ident (reverse ident)) - (let ((section (or root magit-root-section))) - (when (eq (car (pop ident)) - (oref section type)) - (while (and ident - (pcase-let* ((`(,type . ,value) (car ident)) - (value (magit-section-ident-value value))) - (setq section - (cl-find-if (lambda (section) - (and (eq (oref section type) type) - (equal (magit-section-ident-value - (oref section value)) - value))) - (oref section children))))) - (pop ident)) - section))) - -(defun magit-section-lineage (section) - "Return the lineage of SECTION. -The return value has the form (TYPE...)." - (cons (oref section type) - (when-let ((parent (oref section parent))) - (magit-section-lineage parent)))) - -(defvar magit-insert-section--current nil "For internal use only.") -(defvar magit-insert-section--parent nil "For internal use only.") -(defvar magit-insert-section--oldroot nil "For internal use only.") - -;;; Commands -;;;; Movement - -(defun magit-section-forward () - "Move to the beginning of the next visible section." - (interactive) - (if (eobp) - (user-error "No next section") - (let ((section (magit-current-section))) - (if (oref section parent) - (let ((next (and (not (oref section hidden)) - (not (= (oref section end) - (1+ (point)))) - (car (oref section children))))) - (while (and section (not next)) - (unless (setq next (car (magit-section-siblings section 'next))) - (setq section (oref section parent)))) - (if next - (magit-section-goto next) - (user-error "No next section"))) - (magit-section-goto 1))))) - -(defun magit-section-backward () - "Move to the beginning of the current or the previous visible section. -When point is at the beginning of a section then move to the -beginning of the previous visible section. Otherwise move to -the beginning of the current section." - (interactive) - (if (bobp) - (user-error "No previous section") - (let ((section (magit-current-section)) children) - (cond - ((and (= (point) - (1- (oref section end))) - (setq children (oref section children))) - (magit-section-goto (car (last children)))) - ((and (oref section parent) - (not (= (point) - (oref section start)))) - (magit-section-goto section)) - (t - (let ((prev (car (magit-section-siblings section 'prev)))) - (if prev - (while (and (not (oref prev hidden)) - (setq children (oref prev children))) - (setq prev (car (last children)))) - (setq prev (oref section parent))) - (cond (prev - (magit-section-goto prev)) - ((oref section parent) - (user-error "No previous section")) - ;; Eob special cases. - ((not (get-text-property (1- (point)) 'invisible)) - (magit-section-goto -1)) - (t - (goto-char (previous-single-property-change - (1- (point)) 'invisible)) - (forward-line -1) - (magit-section-goto (magit-current-section)))))))))) - -(defun magit-section-up () - "Move to the beginning of the parent section." - (interactive) - (--if-let (oref (magit-current-section) parent) - (magit-section-goto it) - (user-error "No parent section"))) - -(defun magit-section-forward-sibling () - "Move to the beginning of the next sibling section. -If there is no next sibling section, then move to the parent." - (interactive) - (let ((current (magit-current-section))) - (if (oref current parent) - (--if-let (car (magit-section-siblings current 'next)) - (magit-section-goto it) - (magit-section-forward)) - (magit-section-goto 1)))) - -(defun magit-section-backward-sibling () - "Move to the beginning of the previous sibling section. -If there is no previous sibling section, then move to the parent." - (interactive) - (let ((current (magit-current-section))) - (if (oref current parent) - (--if-let (car (magit-section-siblings current 'prev)) - (magit-section-goto it) - (magit-section-backward)) - (magit-section-goto -1)))) - -(defun magit-section-goto (arg) - (if (integerp arg) - (progn (forward-line arg) - (setq arg (magit-current-section))) - (goto-char (oref arg start))) - (run-hook-with-args 'magit-section-movement-hook arg)) - -(defun magit-section-set-window-start (section) - "Ensure the beginning of SECTION is visible." - (unless (pos-visible-in-window-p (oref section end)) - (set-window-start (selected-window) (oref section start)))) - -(defmacro magit-define-section-jumper (name heading type &optional value) - "Define an interactive function to go some section. -Together TYPE and VALUE identify the section. -HEADING is the displayed heading of the section." - (declare (indent defun)) - `(defun ,name (&optional expand) ,(format "\ -Jump to the section \"%s\". -With a prefix argument also expand it." heading) - (interactive "P") - (--if-let (magit-get-section - (cons (cons ',type ,value) - (magit-section-ident magit-root-section))) - (progn (goto-char (oref it start)) - (when expand - (with-local-quit (magit-section-show it)) - (recenter 0))) - (message ,(format "Section \"%s\" wasn't found" heading))))) - -;;;; Visibility - -(defun magit-section-show (section) - "Show the body of the current section." - (interactive (list (magit-current-section))) - (oset section hidden nil) - (magit-section--maybe-wash section) - (when-let ((beg (oref section content))) - (remove-overlays beg (oref section end) 'invisible t)) - (magit-section-maybe-update-visibility-indicator section) - (magit-section-maybe-cache-visibility section) - (dolist (child (oref section children)) - (if (oref child hidden) - (magit-section-hide child) - (magit-section-show child)))) - -(defun magit-section--maybe-wash (section) - (when-let ((washer (oref section washer))) - (oset section washer nil) - (let ((inhibit-read-only t) - (magit-insert-section--parent section) - (content (oref section content))) - (save-excursion - (if (and content (< content (oref section end))) - (funcall washer section) ; already partially washed (hunk) - (goto-char (oref section end)) - (oset section content (point-marker)) - (funcall washer) - (oset section end (point-marker))))) - (magit-section-update-highlight))) - -(defun magit-section-hide (section) - "Hide the body of the current section." - (interactive (list (magit-current-section))) - (if (eq section magit-root-section) - (user-error "Cannot hide root section") - (oset section hidden t) - (when-let ((beg (oref section content))) - (let ((end (oref section end))) - (remove-overlays beg end 'invisible t) - (let ((o (make-overlay beg end))) - (overlay-put o 'evaporate t) - (overlay-put o 'invisible t)))) - (magit-section-maybe-update-visibility-indicator section) - (magit-section-maybe-cache-visibility section))) - -(defun magit-section-toggle (section) - "Toggle visibility of the body of the current section." - (interactive (list (magit-current-section))) - (if (eq section magit-root-section) - (user-error "Cannot hide root section") - (goto-char (oref section start)) - (if (oref section hidden) - (magit-section-show section) - (magit-section-hide section)))) - -(defun magit-section-toggle-children (section) - "Toggle visibility of bodies of children of the current section." - (interactive (list (magit-current-section))) - (goto-char (oref section start)) - (let* ((children (oref section children)) - (show (--any-p (oref it hidden) children))) - (dolist (c children) - (oset c hidden show))) - (magit-section-show section)) - -(defun magit-section-show-children (section &optional depth) - "Recursively show the bodies of children of the current section. -With a prefix argument show children that deep and hide deeper -children." - (interactive (list (magit-current-section))) - (magit-section-show-children-1 section depth) - (magit-section-show section)) - -(defun magit-section-show-children-1 (section &optional depth) - (dolist (child (oref section children)) - (oset child hidden nil) - (if depth - (if (> depth 0) - (magit-section-show-children-1 child (1- depth)) - (magit-section-hide child)) - (magit-section-show-children-1 child)))) - -(defun magit-section-hide-children (section) - "Recursively hide the bodies of children of the current section." - (interactive (list (magit-current-section))) - (mapc 'magit-section-hide (oref section children))) - -(defun magit-section-show-headings (section) - "Recursively show headings of children of the current section. -Only show the headings, previously shown text-only bodies are -hidden." - (interactive (list (magit-current-section))) - (magit-section-show-headings-1 section) - (magit-section-show section)) - -(defun magit-section-show-headings-1 (section) - (dolist (child (oref section children)) - (oset child hidden nil) - (when (or (oref child children) - (not (oref child content))) - (magit-section-show-headings-1 child)))) - -(defun magit-section-cycle (section) - "Cycle visibility of current section and its children." - (interactive (list (magit-current-section))) - (goto-char (oref section start)) - (if (oref section hidden) - (progn (magit-section-show section) - (magit-section-hide-children section)) - (let ((children (oref section children))) - (cond ((and (--any-p (oref it hidden) children) - (--any-p (oref it children) children)) - (magit-section-show-headings section)) - ((seq-some 'magit-section-hidden-body children) - (magit-section-show-children section)) - (t - (magit-section-hide section)))))) - -(defun magit-section-cycle-global () - "Cycle visibility of all sections in the current buffer." - (interactive) - (let ((children (oref magit-root-section children))) - (cond ((and (--any-p (oref it hidden) children) - (--any-p (oref it children) children)) - (magit-section-show-headings magit-root-section)) - ((seq-some 'magit-section-hidden-body children) - (magit-section-show-children magit-root-section)) - (t - (mapc 'magit-section-hide children))))) - -(defun magit-section-hidden-body (section &optional pred) - (--if-let (oref section children) - (funcall (or pred '-any-p) 'magit-section-hidden-body it) - (and (oref section content) - (oref section hidden)))) - -(defun magit-section-invisible-p (section) - "Return t if the SECTION's body is invisible. -When the body of an ancestor of SECTION is collapsed then -SECTION's body (and heading) obviously cannot be visible." - (or (oref section hidden) - (--when-let (oref section parent) - (magit-section-invisible-p it)))) - -(defun magit-section-show-level (level) - "Show surrounding sections up to LEVEL. -If LEVEL is negative, show up to the absolute value. -Sections at higher levels are hidden." - (if (< level 0) - (let ((s (magit-current-section))) - (setq level (- level)) - (while (> (1- (length (magit-section-ident s))) level) - (setq s (oref s parent)) - (goto-char (oref s start))) - (magit-section-show-children magit-root-section (1- level))) - (cl-do* ((s (magit-current-section) - (oref s parent)) - (i (1- (length (magit-section-ident s))) - (cl-decf i))) - ((cond ((< i level) (magit-section-show-children s (- level i 1)) t) - ((= i level) (magit-section-hide s) t)) - (magit-section-goto s))))) - -(defun magit-section-show-level-1 () - "Show surrounding sections on first level." - (interactive) - (magit-section-show-level 1)) - -(defun magit-section-show-level-1-all () - "Show all sections on first level." - (interactive) - (magit-section-show-level -1)) - -(defun magit-section-show-level-2 () - "Show surrounding sections up to second level." - (interactive) - (magit-section-show-level 2)) - -(defun magit-section-show-level-2-all () - "Show all sections up to second level." - (interactive) - (magit-section-show-level -2)) - -(defun magit-section-show-level-3 () - "Show surrounding sections up to third level." - (interactive) - (magit-section-show-level 3)) - -(defun magit-section-show-level-3-all () - "Show all sections up to third level." - (interactive) - (magit-section-show-level -3)) - -(defun magit-section-show-level-4 () - "Show surrounding sections up to fourth level." - (interactive) - (magit-section-show-level 4)) - -(defun magit-section-show-level-4-all () - "Show all sections up to fourth level." - (interactive) - (magit-section-show-level -4)) - -;;;; Auxiliary - -(defun magit-describe-section-briefly (section &optional ident) - "Show information about the section at point. -With a prefix argument show the section identity instead of the -section lineage. This command is intended for debugging purposes." - (interactive (list (magit-current-section) current-prefix-arg)) - (let ((str (format "#<%s %S %S %s-%s%s>" - (eieio-object-class section) - (let ((val (oref section value))) - (cond ((stringp val) - (substring-no-properties val)) - ((and (eieio-object-p val) - (fboundp 'cl-prin1-to-string)) - (cl-prin1-to-string val)) - (t - val))) - (if ident - (magit-section-ident section) - (apply #'vector (magit-section-lineage section))) - (when-let ((m (oref section start))) - (marker-position m)) - (if-let ((m (oref section content))) - (format "[%s-]" (marker-position m)) - "") - (when-let ((m (oref section end))) - (marker-position m))))) - (if (called-interactively-p 'any) - (message "%s" str) - str))) - -(cl-defmethod cl-print-object ((section magit-section) stream) - "Print `magit-describe-section' result of SECTION." - ;; Used by debug and edebug as of Emacs 26. - (princ (magit-describe-section-briefly section) stream)) - -(defun magit-describe-section (section &optional interactive-p) - "Show information about the section at point." - (interactive (list (magit-current-section) t)) - (let ((inserter-section section)) - (while (and inserter-section (not (oref inserter-section inserter))) - (setq inserter-section (oref inserter-section parent))) - (when (and inserter-section (oref inserter-section inserter)) - (setq section inserter-section))) - (pcase (oref section inserter) - (`((,hook ,fun) . ,src-src) - (help-setup-xref `(magit-describe-section ,section) interactive-p) - (with-help-window (help-buffer) - (with-current-buffer standard-output - (insert (format-message - "%s\n is inserted by `%s'\n from `%s'" - (magit-describe-section-briefly section) - (make-text-button (symbol-name fun) nil - :type 'help-function - 'help-args (list fun)) - (make-text-button (symbol-name hook) nil - :type 'help-variable - 'help-args (list hook)))) - (pcase-dolist (`(,hook ,fun) src-src) - (insert (format-message - ",\n called by `%s'\n from `%s'" - (make-text-button (symbol-name fun) nil - :type 'help-function - 'help-args (list fun)) - (make-text-button (symbol-name hook) nil - :type 'help-variable - 'help-args (list hook))))) - (insert ".\n\n") - (insert - (format-message - "`%s' is " - (make-text-button (symbol-name fun) nil - :type 'help-function 'help-args (list fun)))) - (describe-function-1 fun)))) - (_ (message "%s, inserter unknown" - (magit-describe-section-briefly section))))) - -;;; Match - -(cl-defun magit-section-match - (condition &optional (section (magit-current-section))) - "Return t if SECTION matches CONDITION. - -SECTION defaults to the section at point. If SECTION is not -specified and there also is no section at point, then return -nil. - -CONDITION can take the following forms: - (CONDITION...) matches if any of the CONDITIONs matches. - [CLASS...] matches if the section's class is the same - as the first CLASS or a subclass of that; - the section's parent class matches the - second CLASS; and so on. - [* CLASS...] matches sections that match [CLASS...] and - also recursively all their child sections. - CLASS matches if the section's class is the same - as CLASS or a subclass of that; regardless - of the classes of the parent sections. - -Each CLASS should be a class symbol, identifying a class that -derives from `magit-section'. For backward compatibility CLASS -can also be a \"type symbol\". A section matches such a symbol -if the value of its `type' slot is `eq'. If a type symbol has -an entry in `magit--section-type-alist', then a section also -matches that type if its class is a subclass of the class that -corresponds to the type as per that alist. - -Note that it is not necessary to specify the complete section -lineage as printed by `magit-describe-section-briefly', unless -of course you want to be that precise." - (and section (magit-section-match-1 condition section))) - -(defun magit-section-match-1 (condition section) - (cl-assert condition) - (and section - (if (listp condition) - (--first (magit-section-match-1 it section) condition) - (magit-section-match-2 (if (symbolp condition) - (list condition) - (cl-coerce condition 'list)) - section)))) - -(defun magit-section-match-2 (condition section) - (if (eq (car condition) '*) - (or (magit-section-match-2 (cdr condition) section) - (when-let ((parent (oref section parent))) - (magit-section-match-2 condition parent))) - (and (let ((c (car condition))) - (if (class-p c) - (cl-typep section c) - (if-let ((class (cdr (assq c magit--section-type-alist)))) - (cl-typep section class) - (eq (oref section type) c)))) - (or (not (setq condition (cdr condition))) - (when-let ((parent (oref section parent))) - (magit-section-match-2 condition parent)))))) - -(defun magit-section-value-if (condition &optional section) - "If the section at point matches CONDITION, then return its value. - -If optional SECTION is non-nil then test whether that matches -instead. If there is no section at point and SECTION is nil, -then return nil. If the section does not match, then return -nil. - -See `magit-section-match' for the forms CONDITION can take." - (when-let ((section (or section (magit-current-section)))) - (and (magit-section-match condition section) - (oref section value)))) - -(defmacro magit-section-when (condition &rest body) - "If the section at point matches CONDITION, evaluate BODY. - -If the section matches, then evaluate BODY forms sequentially -with `it' bound to the section and return the value of the last -form. If there are no BODY forms, then return the value of the -section. If the section does not match or if there is no section -at point, then return nil. - -See `magit-section-match' for the forms CONDITION can take." - (declare (obsolete - "instead use `magit-section-match' or `magit-section-value-if'." - "Magit 2.90.0") - (indent 1) - (debug (sexp body))) - `(--when-let (magit-current-section) - ;; Quoting CONDITION here often leads to double-quotes, which - ;; isn't an issue because `magit-section-match-1' implicitly - ;; deals with that. We shouldn't force users of this function - ;; to not quote CONDITION because that would needlessly break - ;; backward compatibility. - (when (magit-section-match ',condition it) - ,@(or body '((oref it value)))))) - -(defmacro magit-section-case (&rest clauses) - "Choose among clauses on the type of the section at point. - -Each clause looks like (CONDITION BODY...). The type of the -section is compared against each CONDITION; the BODY forms of the -first match are evaluated sequentially and the value of the last -form is returned. Inside BODY the symbol `it' is bound to the -section at point. If no clause succeeds or if there is no -section at point, return nil. - -See `magit-section-match' for the forms CONDITION can take. -Additionally a CONDITION of t is allowed in the final clause, and -matches if no other CONDITION match, even if there is no section -at point." - (declare (indent 0) - (debug (&rest (sexp body)))) - `(let* ((it (magit-current-section))) - (cond ,@(mapcar (lambda (clause) - `(,(or (eq (car clause) t) - `(and it - (magit-section-match-1 ',(car clause) it))) - ,@(cdr clause))) - clauses)))) - -(defun magit-section-match-assoc (section alist) - "Return the value associated with SECTION's type or lineage in ALIST." - (seq-some (pcase-lambda (`(,key . ,val)) - (and (magit-section-match-1 key section) val)) - alist)) - -;;; Create - -(defvar magit-insert-section-hook nil - "Hook run after `magit-insert-section's BODY. -Avoid using this hook and only ever do so if you know -what you are doing and are sure there is no other way.") - -(defmacro magit-insert-section (&rest args) - "Insert a section at point. - -Create a section object of type CLASS, storing VALUE in its -`value' slot, and insert the section at point. CLASS is a -subclass of `magit-section' or has the form `(eval FORM)', in -which case FORM is evaluated at runtime and should return a -subclass. In other places a sections class is oftern referred -to as its \"type\". - -Many commands behave differently depending on the class of the -current section and sections of a certain class can have their -own keymap, which is specified using the `keymap' class slot. -The value of that slot should be a variable whose value is a -keymap. - -For historic reasons Magit and Forge in most cases use symbols -as CLASS that don't actually identify a class and that lack the -appropriate package prefix. This works due to some undocumented -kludges, which are not available to other packages. - -When optional HIDE is non-nil collapse the section body by -default, i.e. when first creating the section, but not when -refreshing the buffer. Else expand it by default. This can be -overwritten using `magit-section-set-visibility-hook'. When a -section is recreated during a refresh, then the visibility of -predecessor is inherited and HIDE is ignored (but the hook is -still honored). - -BODY is any number of forms that actually insert the section's -heading and body. Optional NAME, if specified, has to be a -symbol, which is then bound to the object of the section being -inserted. - -Before BODY is evaluated the `start' of the section object is set -to the value of `point' and after BODY was evaluated its `end' is -set to the new value of `point'; BODY is responsible for moving -`point' forward. - -If it turns out inside BODY that the section is empty, then -`magit-cancel-section' can be used to abort and remove all traces -of the partially inserted section. This can happen when creating -a section by washing Git's output and Git didn't actually output -anything this time around. - -\(fn [NAME] (CLASS &optional VALUE HIDE) &rest BODY)" - (declare (indent defun) - (debug ([&optional symbolp] - (&or [("eval" form) &optional form form] - [symbolp &optional form form]) - body))) - (let ((tp (cl-gensym "type")) - (s* (and (symbolp (car args)) - (pop args))) - (s (cl-gensym "section"))) - `(let* ((,tp ,(let ((type (nth 0 (car args)))) - (if (eq (car-safe type) 'eval) - (cadr type) - `',type))) - (,s (funcall (if (class-p ,tp) - ,tp - (or (cdr (assq ,tp magit--section-type-alist)) - 'magit-section)) - :type - (or (and (class-p ,tp) - (car (rassq ,tp magit--section-type-alist))) - ,tp) - :value ,(nth 1 (car args)) - :start (point-marker) - :parent magit-insert-section--parent))) - (oset ,s hidden - (let ((value (run-hook-with-args-until-success - 'magit-section-set-visibility-hook ,s))) - (if value - (eq value 'hide) - (let ((incarnation (and magit-insert-section--oldroot - (magit-get-section - (magit-section-ident ,s) - magit-insert-section--oldroot)))) - (if incarnation - (oref incarnation hidden) - (let ((value (magit-section-match-assoc - ,s magit-section-initial-visibility-alist))) - (if value - (progn - (when (functionp value) - (setq value (funcall value ,s))) - (eq value 'hide)) - ,(nth 2 (car args))))))))) - (let ((magit-insert-section--current ,s) - (magit-insert-section--parent ,s) - (magit-insert-section--oldroot - (or magit-insert-section--oldroot - (unless magit-insert-section--parent - (prog1 magit-root-section - (setq magit-root-section ,s)))))) - (catch 'cancel-section - ,@(if s* - `((let ((,s* ,s)) - ,@(cdr args))) - (cdr args)) - ;; `magit-insert-section-hook' should *not* be run with - ;; `magit-run-section-hook' because it's a hook that runs - ;; on section insertion, not a section inserting hook. - (run-hooks 'magit-insert-section-hook) - (magit-insert-child-count ,s) - (set-marker-insertion-type (oref ,s start) t) - (let* ((end (oset ,s end (point-marker))) - (class-map (oref-default ,s keymap)) - (magit-map (intern (format "magit-%s-section-map" - (oref ,s type)))) - (forge-map (intern (format "forge-%s-section-map" - (oref ,s type)))) - (map (or (and class-map (symbol-value class-map)) - (and (boundp magit-map) (symbol-value magit-map)) - (and (boundp forge-map) (symbol-value forge-map))))) - (save-excursion - (goto-char (oref ,s start)) - (while (< (point) end) - (let ((next (or (next-single-property-change - (point) 'magit-section) - end))) - (unless (get-text-property (point) 'magit-section) - (put-text-property (point) next 'magit-section ,s) - (when map - (put-text-property (point) next 'keymap map))) - (goto-char next))))) - (if (eq ,s magit-root-section) - (let ((magit-section-cache-visibility nil)) - (magit-section-show ,s)) - (oset (oref ,s parent) children - (nconc (oref (oref ,s parent) children) - (list ,s))))) - ,s)))) - -(defun magit-cancel-section () - "Cancel inserting the section that is currently being inserted. -Remove all traces of that section." - (when magit-insert-section--current - (if (not (oref magit-insert-section--current parent)) - (insert "(empty)\n") - (delete-region (oref magit-insert-section--current start) - (point)) - (setq magit-insert-section--current nil) - (throw 'cancel-section nil)))) - -(defun magit-insert-heading (&rest args) - "Insert the heading for the section currently being inserted. - -This function should only be used inside `magit-insert-section'. - -When called without any arguments, then just set the `content' -slot of the object representing the section being inserted to -a marker at `point'. The section should only contain a single -line when this function is used like this. - -When called with arguments ARGS, which have to be strings, or -nil, then insert those strings at point. The section should not -contain any text before this happens and afterwards it should -again only contain a single line. If the `face' property is set -anywhere inside any of these strings, then insert all of them -unchanged. Otherwise use the `magit-section-heading' face for -all inserted text. - -The `content' property of the section object is the end of the -heading (which lasts from `start' to `content') and the beginning -of the the body (which lasts from `content' to `end'). If the -value of `content' is nil, then the section has no heading and -its body cannot be collapsed. If a section does have a heading, -then its height must be exactly one line, including a trailing -newline character. This isn't enforced, you are responsible for -getting it right. The only exception is that this function does -insert a newline character if necessary." - (declare (indent defun)) - (when args - (let ((heading (apply #'concat args))) - (insert (if (or (text-property-not-all 0 (length heading) - 'font-lock-face nil heading) - (text-property-not-all 0 (length heading) - 'face nil heading)) - heading - (propertize heading 'font-lock-face 'magit-section-heading))))) - (unless (bolp) - (insert ?\n)) - (when (fboundp 'magit-maybe-make-margin-overlay) - (magit-maybe-make-margin-overlay)) - (oset magit-insert-section--current content (point-marker))) - -(defmacro magit-insert-section-body (&rest body) - "Use BODY to insert the section body, once the section is expanded. -If the section is expanded when it is created, then this is -like `progn'. Otherwise BODY isn't evaluated until the section -is explicitly expanded." - (declare (indent 0)) - (let ((f (cl-gensym)) - (s (cl-gensym))) - `(let ((,f (lambda () ,@body)) - (,s magit-insert-section--current)) - (if (oref ,s hidden) - (oset ,s washer - (lambda () - (funcall ,f) - (magit-section-maybe-remove-visibility-indicator ,s))) - (funcall ,f))))) - -(defun magit-insert-headers (hook) - (let* ((header-sections nil) - (magit-insert-section-hook - (cons (lambda () - (push magit-insert-section--current - header-sections)) - (if (listp magit-insert-section-hook) - magit-insert-section-hook - (list magit-insert-section-hook))))) - (magit-run-section-hook hook) - (when header-sections - (insert "\n") - ;; Make the first header into the parent of the rest. - (when (cdr header-sections) - (cl-callf nreverse header-sections) - (let* ((1st-header (pop header-sections)) - (header-parent (oref 1st-header parent))) - (oset header-parent children (list 1st-header)) - (oset 1st-header children header-sections) - (oset 1st-header content (oref (car header-sections) start)) - (oset 1st-header end (oref (car (last header-sections)) end)) - (dolist (sub-header header-sections) - (oset sub-header parent 1st-header))))))) - -(defun magit-insert-child-count (section) - "Modify SECTION's heading to contain number of child sections. - -If `magit-section-show-child-count' is non-nil and the SECTION -has children and its heading ends with \":\", then replace that -with \" (N)\", where N is the number of child sections. - -This function is called by `magit-insert-section' after that has -evaluated its BODY. Admittedly that's a bit of a hack." - ;; This has to be fast, not pretty! - (let (content count) - (when (and magit-section-show-child-count - (setq count (length (oref section children))) - (> count 0) - (setq content (oref section content)) - (eq (char-before (1- content)) ?:)) - (save-excursion - (goto-char (- content 2)) - (insert (format " (%s)" count)) - (delete-char 1))))) - -;;; Highlight - -(defvar-local magit-section-highlight-overlays nil) -(defvar-local magit-section-highlighted-section nil) -(defvar-local magit-section-highlighted-sections nil) -(defvar-local magit-section-unhighlight-sections nil) -(defun magit-section-update-highlight () - (let ((section (magit-current-section))) - (unless (eq section magit-section-highlighted-section) - (let ((inhibit-read-only t) - (deactivate-mark nil) - (selection (magit-region-sections))) - (mapc #'delete-overlay magit-section-highlight-overlays) - (setq magit-section-highlight-overlays nil) - (setq magit-section-unhighlight-sections - magit-section-highlighted-sections) - (setq magit-section-highlighted-sections nil) - (unless (eq section magit-root-section) - (run-hook-with-args-until-success - 'magit-section-highlight-hook section selection)) - (dolist (s magit-section-unhighlight-sections) - (run-hook-with-args-until-success - 'magit-section-unhighlight-hook s selection)) - (restore-buffer-modified-p nil) - (unless (eq magit-section-highlighted-section section) - (setq magit-section-highlighted-section - (and (not (oref section hidden)) - section))))) - (magit-section-maybe-paint-visibility-ellipses))) - -(defun magit-section-highlight (section selection) - "Highlight SECTION and if non-nil all sections in SELECTION. -This function works for any section but produces undesirable -effects for diff related sections, which by default are -highlighted using `magit-diff-highlight'. Return t." - (when-let ((face (oref section heading-highlight-face))) - (dolist (section (or selection (list section))) - (magit-section-make-overlay - (oref section start) - (or (oref section content) - (oref section end)) - face))) - (cond (selection - (magit-section-make-overlay (oref (car selection) start) - (oref (car (last selection)) end) - 'magit-section-highlight) - (magit-section-highlight-selection nil selection)) - (t - (magit-section-make-overlay (oref section start) - (oref section end) - 'magit-section-highlight))) - t) - -(defun magit-section-highlight-selection (_ selection) - "Highlight the section-selection region. -If SELECTION is non-nil, then it is a list of sections selected by -the region. The headings of these sections are then highlighted. - -This is a fallback for people who don't want to highlight the -current section and therefore removed `magit-section-highlight' -from `magit-section-highlight-hook'. - -This function is necessary to ensure that a representation of -such a region is visible. If neither of these functions were -part of the hook variable, then such a region would be -invisible." - (when (and selection - (not (and (eq this-command 'mouse-drag-region)))) - (dolist (section selection) - (magit-section-make-overlay (oref section start) - (or (oref section content) - (oref section end)) - 'magit-section-heading-selection)) - t)) - -(defun magit-section-make-overlay (start end face) - ;; Yes, this doesn't belong here. But the alternative of - ;; spreading this hack across the code base is even worse. - (when (and magit-keep-region-overlay - (memq face '(magit-section-heading-selection - magit-diff-file-heading-selection - magit-diff-hunk-heading-selection))) - (setq face (list :foreground (face-foreground face)))) - (let ((ov (make-overlay start end nil t))) - (overlay-put ov 'font-lock-face face) - (overlay-put ov 'evaporate t) - (push ov magit-section-highlight-overlays) - ov)) - -(defun magit-section-goto-successor (section line char arg) - (let ((ident (magit-section-ident section))) - (--if-let (magit-get-section ident) - (let ((start (oref it start))) - (goto-char start) - (unless (eq it magit-root-section) - (ignore-errors - (forward-line line) - (forward-char char)) - (unless (eq (magit-current-section) it) - (goto-char start)))) - (or (run-hook-with-args-until-success - 'magit-section-goto-successor-hook section arg) - (goto-char (--if-let (magit-section-goto-successor-1 section) - (if (eq (oref it type) 'button) - (point-min) - (oref it start)) - (point-min))))))) - -(defun magit-section-goto-successor-1 (section) - (or (--when-let (pcase (oref section type) - (`staged 'unstaged) - (`unstaged 'staged) - (`unpushed 'unpulled) - (`unpulled 'unpushed)) - (magit-get-section `((,it) (status)))) - (--when-let (car (magit-section-siblings section 'next)) - (magit-get-section (magit-section-ident it))) - (--when-let (car (magit-section-siblings section 'prev)) - (magit-get-section (magit-section-ident it))) - (--when-let (oref section parent) - (or (magit-get-section (magit-section-ident it)) - (magit-section-goto-successor-1 it))))) - -;;; Region - -(defvar-local magit-section--region-overlays nil) - -(defun magit-section--delete-region-overlays () - (mapc #'delete-overlay magit-section--region-overlays) - (setq magit-section--region-overlays nil)) - -(defun magit-section--highlight-region (start end window rol) - (magit-section--delete-region-overlays) - (if (and (not magit-keep-region-overlay) - (or (magit-region-sections) - (run-hook-with-args-until-success 'magit-region-highlight-hook - (magit-current-section))) - (not (= (line-number-at-pos start) - (line-number-at-pos end))) - ;; (not (eq (car-safe last-command-event) 'mouse-movement)) - ) - (funcall (default-value 'redisplay-unhighlight-region-function) rol) - (funcall (default-value 'redisplay-highlight-region-function) - start end window rol))) - -(defun magit-section--unhighlight-region (rol) - (setq magit-section-highlighted-section nil) - (magit-section--delete-region-overlays) - (funcall (default-value 'redisplay-unhighlight-region-function) rol)) - -;;; Visibility - -(defvar-local magit-section-visibility-cache nil) -(put 'magit-section-visibility-cache 'permanent-local t) - -(defun magit-section-cached-visibility (section) - "Set SECTION's visibility to the cached value." - (cdr (assoc (magit-section-ident section) - magit-section-visibility-cache))) - -(cl-defun magit-section-cache-visibility - (&optional (section magit-insert-section--current)) - ;; Emacs 25's `alist-get' lacks TESTFN. - (let* ((id (magit-section-ident section)) - (elt (assoc id magit-section-visibility-cache)) - (val (if (oref section hidden) 'hide 'show))) - (if elt - (setcdr elt val) - (push (cons id val) magit-section-visibility-cache)))) - -(cl-defun magit-section-maybe-cache-visibility - (&optional (section magit-insert-section--current)) - (when (or (eq magit-section-cache-visibility t) - (memq (oref section type) - magit-section-cache-visibility)) - (magit-section-cache-visibility section))) - -(defun magit-section-maybe-update-visibility-indicator (section) - (when magit-section-visibility-indicator - (let ((beg (oref section start)) - (cnt (oref section content)) - (end (oref section end))) - (when (and cnt (or (not (= cnt end)) (oref section washer))) - (let ((eoh (save-excursion - (goto-char beg) - (line-end-position)))) - (cond - ((symbolp (car-safe magit-section-visibility-indicator)) - ;; It would make more sense to put the overlay only on the - ;; location we actually don't put it on, but then inserting - ;; before that location (while taking care not to mess with - ;; the overlay) would cause the fringe bitmap to disappear - ;; (but not other effects of the overlay). - (let ((ov (magit--overlay-at (1+ beg) 'magit-vis-indicator 'fringe))) - (unless ov - (setq ov (make-overlay (1+ beg) eoh)) - (overlay-put ov 'evaporate t) - (overlay-put ov 'magit-vis-indicator 'fringe)) - (overlay-put - ov 'before-string - (propertize "fringe" 'display - (list 'left-fringe - (if (oref section hidden) - (car magit-section-visibility-indicator) - (cdr magit-section-visibility-indicator)) - 'fringe))))) - ((stringp (car-safe magit-section-visibility-indicator)) - (let ((ov (magit--overlay-at (1- eoh) 'magit-vis-indicator 'eoh))) - (cond ((oref section hidden) - (unless ov - (setq ov (make-overlay (1- eoh) eoh)) - (overlay-put ov 'evaporate t) - (overlay-put ov 'magit-vis-indicator 'eoh)) - (overlay-put ov 'after-string - (car magit-section-visibility-indicator))) - (ov - (delete-overlay ov))))))))))) - -(defvar-local magit--ellipses-sections nil) - -(defun magit-section-maybe-paint-visibility-ellipses () - ;; This is needed because we hide the body instead of "the body - ;; except the final newline and additionally the newline before - ;; the body"; otherwise we could use `buffer-invisibility-spec'. - (when (stringp (car-safe magit-section-visibility-indicator)) - (let* ((sections (append magit--ellipses-sections - (setq magit--ellipses-sections - (or (magit-region-sections) - (list (magit-current-section)))))) - (beg (--map (oref it start) sections)) - (end (--map (oref it end) sections))) - (when (region-active-p) - ;; This ensures that the region face is removed from ellipses - ;; when the region becomes inactive, but fails to ensure that - ;; all ellipses within the active region use the region face, - ;; because the respective overlay has not yet been updated at - ;; this time. The magit-selection face is always applied. - (push (region-beginning) beg) - (push (region-end) end)) - (setq beg (apply #'min beg)) - (setq end (apply #'max end)) - (dolist (ov (overlays-in beg end)) - (when (eq (overlay-get ov 'magit-vis-indicator) 'eoh) - (overlay-put - ov 'after-string - (propertize - (car magit-section-visibility-indicator) 'font-lock-face - (let ((pos (overlay-start ov))) - (delq nil (nconc (--map (overlay-get it 'font-lock-face) - (overlays-at pos)) - (list (get-char-property - pos 'font-lock-face)))))))))))) - -(defun magit-section-maybe-remove-visibility-indicator (section) - (when (and magit-section-visibility-indicator - (= (oref section content) - (oref section end))) - (dolist (o (overlays-in (oref section start) - (save-excursion - (goto-char (oref section start)) - (1+ (line-end-position))))) - (when (overlay-get o 'magit-vis-indicator) - (delete-overlay o))))) - -(defvar-local magit-section--opened-sections nil) - -(defun magit-section--open-temporarily (beg end) - (save-excursion - (goto-char beg) - (let ((section (magit-current-section))) - (while section - (let ((content (oref section content))) - (if (and (magit-section-invisible-p section) - (<= (or content (oref section start)) - beg - (oref section end))) - (progn - (when content - (magit-section-show section) - (push section magit-section--opened-sections)) - (setq section (oref section parent))) - (setq section nil)))))) - (or (eq search-invisible t) - (not (isearch-range-invisible beg end)))) - -(defun isearch-clean-overlays@magit-mode (fn) - (if (derived-mode-p 'magit-mode) - (let ((pos (point))) - (dolist (section magit-section--opened-sections) - (unless (<= (oref section content) pos (oref section end)) - (magit-section-hide section))) - (setq magit-section--opened-sections nil)) - (funcall fn))) - -(advice-add 'isearch-clean-overlays :around - 'isearch-clean-overlays@magit-mode) - -;;; Utilities - -(cl-defun magit-section-selected-p (section &optional (selection nil sselection)) - (and (not (eq section magit-root-section)) - (or (eq section (magit-current-section)) - (memq section (if sselection - selection - (setq selection (magit-region-sections)))) - (--when-let (oref section parent) - (magit-section-selected-p it selection))))) - -(defun magit-section-parent-value (section) - (when-let ((parent (oref section parent))) - (oref parent value))) - -(defun magit-section-siblings (section &optional direction) - "Return a list of the sibling sections of SECTION. - -If optional DIRECTION is `prev', then return siblings that come -before SECTION. If it is `next', then return siblings that come -after SECTION. For all other values, return all siblings -excluding SECTION itself." - (when-let ((parent (oref section parent))) - (let ((siblings (oref parent children))) - (pcase direction - (`prev (cdr (member section (reverse siblings)))) - (`next (cdr (member section siblings))) - (_ (remq section siblings)))))) - -(defun magit-region-values (&optional condition multiple) - "Return a list of the values of the selected sections. - -Return the values that themselves would be returned by -`magit-region-sections' (which see)." - (--map (oref it value) - (magit-region-sections condition multiple))) - -(defun magit-region-sections (&optional condition multiple) - "Return a list of the selected sections. - -When the region is active and constitutes a valid section -selection, then return a list of all selected sections. This is -the case when the region begins in the heading of a section and -ends in the heading of the same section or in that of a sibling -section. If optional MULTIPLE is non-nil, then the region cannot -begin and end in the same section. - -When the selection is not valid, then return nil. In this case, -most commands that can act on the selected sections will instead -act on the section at point. - -When the region looks like it would in any other buffer then -the selection is invalid. When the selection is valid then the -region uses the `magit-section-highlight' face. This does not -apply to diffs where things get a bit more complicated, but even -here if the region looks like it usually does, then that's not -a valid selection as far as this function is concerned. - -If optional CONDITION is non-nil, then the selection not only -has to be valid; all selected sections additionally have to match -CONDITION, or nil is returned. See `magit-section-match' for the -forms CONDITION can take." - (when (region-active-p) - (let* ((rbeg (region-beginning)) - (rend (region-end)) - (sbeg (get-text-property rbeg 'magit-section)) - (send (get-text-property rend 'magit-section))) - (when (and send - (not (eq send magit-root-section)) - (not (and multiple (eq send sbeg)))) - (let ((siblings (cons sbeg (magit-section-siblings sbeg 'next))) - sections) - (when (and (memq send siblings) - (magit-section-position-in-heading-p sbeg rbeg) - (magit-section-position-in-heading-p send rend)) - (while siblings - (push (car siblings) sections) - (when (eq (pop siblings) send) - (setq siblings nil))) - (setq sections (nreverse sections)) - (when (or (not condition) - (--all-p (magit-section-match condition it) sections)) - sections))))))) - -(defun magit-section-position-in-heading-p (&optional section pos) - "Return t if POSITION is inside the heading of SECTION. -POSITION defaults to point and SECTION defaults to the -current section." - (unless section - (setq section (magit-current-section))) - (unless pos - (setq pos (point))) - (and section - (>= pos (oref section start)) - (< pos (or (oref section content) - (oref section end))) - t)) - -(defun magit-section-internal-region-p (&optional section) - "Return t if the region is active and inside SECTION's body. -If optional SECTION is nil, use the current section." - (and (region-active-p) - (or section (setq section (magit-current-section))) - (let ((beg (get-text-property (region-beginning) 'magit-section))) - (and (eq beg (get-text-property (region-end) 'magit-section)) - (eq beg section))) - (not (or (magit-section-position-in-heading-p section (region-beginning)) - (magit-section-position-in-heading-p section (region-end)))) - t)) - -(defun magit-section--backward-protected () - "Move to the beginning of the current or the previous visible section. -Same as `magit-section-backward' but for non-interactive use. -Suppress `magit-section-movement-hook', and return a boolean to -indicate whether a section was found, instead of raising an error -if not." - (condition-case nil - (let ((magit-section-movement-hook nil)) - (magit-section-backward) - t) - (user-error nil))) - -(defun magit-section--backward-find (predicate) - "Move to the first previous section satisfying PREDICATE. -PREDICATE does not take any parameter and should not move -point." - (let (found) - (while (and (setq found (magit-section--backward-protected)) - (not (funcall predicate)))) - found)) - -(defun magit-wash-sequence (function) - "Repeatedly call FUNCTION until it returns nil or eob is reached. -FUNCTION has to move point forward or return nil." - (while (and (not (eobp)) (funcall function)))) - -(defun magit-add-section-hook (hook function &optional at append local) - "Add to the value of section hook HOOK the function FUNCTION. - -Add FUNCTION at the beginning of the hook list unless optional -APPEND is non-nil, in which case FUNCTION is added at the end. -If FUNCTION already is a member, then move it to the new location. - -If optional AT is non-nil and a member of the hook list, then -add FUNCTION next to that instead. Add before or after AT, or -replace AT with FUNCTION depending on APPEND. If APPEND is the -symbol `replace', then replace AT with FUNCTION. For any other -non-nil value place FUNCTION right after AT. If nil, then place -FUNCTION right before AT. If FUNCTION already is a member of the -list but AT is not, then leave FUNCTION where ever it already is. - -If optional LOCAL is non-nil, then modify the hook's buffer-local -value rather than its global value. This makes the hook local by -copying the default value. That copy is then modified. - -HOOK should be a symbol. If HOOK is void, it is first set to nil. -HOOK's value must not be a single hook function. FUNCTION should -be a function that takes no arguments and inserts one or multiple -sections at point, moving point forward. FUNCTION may choose not -to insert its section(s), when doing so would not make sense. It -should not be abused for other side-effects. To remove FUNCTION -again use `remove-hook'." - (unless (boundp hook) - (error "Cannot add function to undefined hook variable %s" hook)) - (unless (default-boundp hook) - (set-default hook nil)) - (let ((value (if local - (if (local-variable-p hook) - (symbol-value hook) - (unless (local-variable-if-set-p hook) - (make-local-variable hook)) - (copy-sequence (default-value hook))) - (default-value hook)))) - (if at - (when (setq at (member at value)) - (setq value (delq function value)) - (cond ((eq append 'replace) - (setcar at function)) - (append - (push function (cdr at))) - (t - (push (car at) (cdr at)) - (setcar at function)))) - (setq value (delq function value))) - (unless (member function value) - (setq value (if append - (append value (list function)) - (cons function value)))) - (when (eq append 'replace) - (setq value (delq at value))) - (if local - (set hook value) - (set-default hook value)))) - -(defvar-local magit-disabled-section-inserters nil) - -(defun magit-disable-section-inserter (fn) - "Disable the section inserter FN in the current repository. -It is only intended for use in \".dir-locals.el\" and -\".dir-locals-2.el\". Also see info node `(magit)Per-Repository -Configuration'." - (cl-pushnew fn magit-disabled-section-inserters)) - -(put 'magit-disable-section-inserter 'safe-local-eval-function t) - -(defun magit-run-section-hook (hook &rest args) - "Run HOOK with ARGS, warning about invalid entries." - (let ((entries (symbol-value hook))) - (unless (listp entries) - (setq entries (list entries))) - (--when-let (-remove #'functionp entries) - (message "`%s' contains entries that are no longer valid. -%s\nUsing standard value instead. Please re-configure hook variable." - hook - (mapconcat (lambda (sym) (format " `%s'" sym)) it "\n")) - (sit-for 5) - (setq entries (eval (car (get hook 'standard-value))))) - (dolist (entry entries) - (let ((magit--current-section-hook (cons (list hook entry) - magit--current-section-hook))) - (unless (memq entry magit-disabled-section-inserters) - (if (bound-and-true-p magit-refresh-verbose) - (let ((time (benchmark-elapse (apply entry args)))) - (message " %-50s %s %s" entry time - (cond ((> time 0.03) "!!") - ((> time 0.01) "!") - (t "")))) - (apply entry args))))))) - -(cl-defun magit--overlay-at (pos prop &optional (val nil sval) testfn) - (cl-find-if (lambda (o) - (let ((p (overlay-properties o))) - (and (plist-member p prop) - (or (not sval) - (funcall (or testfn #'eql) - (plist-get p prop) - val))))) - (overlays-at pos t))) - -;;; _ -(provide 'magit-section) -;;; magit-section.el ends here diff --git a/lisp/magit/magit-sequence.el b/lisp/magit/magit-sequence.el index b38090a4..20b8146e 100644 --- a/lisp/magit/magit-sequence.el +++ b/lisp/magit/magit-sequence.el @@ -1,6 +1,6 @@ ;;; magit-sequence.el --- history manipulation in Magit -*- lexical-binding: t -*- -;; Copyright (C) 2011-2021 The Magit Project Contributors +;; Copyright (C) 2011-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -29,9 +31,6 @@ ;;; Code: -(eval-when-compile - (require 'subr-x)) - (require 'magit) ;; For `magit-rebase--todo'. @@ -149,7 +148,8 @@ This discards all changes made since the sequence started." ["Apply here" ("A" "Pick" magit-cherry-copy) ("a" "Apply" magit-cherry-apply) - ("h" "Harvest" magit-cherry-harvest)] + ("h" "Harvest" magit-cherry-harvest) + ("m" "Squash" magit-merge-squash)] ["Apply elsewhere" ("d" "Donate" magit-cherry-donate) ("n" "Spinout" magit-cherry-spinout) @@ -172,24 +172,25 @@ This discards all changes made since the sequence started." (magit-read-other-branch-or-commit prompt)) (transient-args 'magit-cherry-pick))) -(defun magit--cherry-move-read-args (verb away fn) +(defun magit--cherry-move-read-args (verb away fn &optional allow-detached) (declare (indent defun)) - (let ((commits (or (nreverse (magit-region-values 'commit)) - (list (funcall (if away - 'magit-read-branch-or-commit - 'magit-read-other-branch-or-commit) - (format "%s cherry" (capitalize verb)))))) - (current (magit-get-current-branch))) - (unless current - (user-error "Cannot %s cherries while HEAD is detached" verb)) - (let ((reachable (magit-rev-ancestor-p (car commits) current)) - (msg "Cannot %s cherries that %s reachable from HEAD")) - (pcase (list away reachable) - (`(nil t) (user-error msg verb "are")) - (`(t nil) (user-error msg verb "are not")))) - `(,commits - ,@(funcall fn commits) - ,(transient-args 'magit-cherry-pick)))) + (let ((commits (or (nreverse (magit-region-values 'commit)) + (list (funcall (if away + 'magit-read-branch-or-commit + 'magit-read-other-branch-or-commit) + (format "%s cherry" (capitalize verb)))))) + (current (or (magit-get-current-branch) + (and allow-detached (magit-rev-parse "HEAD"))))) + (unless current + (user-error "Cannot %s cherries while HEAD is detached" verb)) + (let ((reachable (magit-rev-ancestor-p (car commits) current)) + (msg "Cannot %s cherries that %s reachable from HEAD")) + (pcase (list away reachable) + (`(nil t) (user-error msg verb "are")) + (`(t nil) (user-error msg verb "are not")))) + `(,commits + ,@(funcall fn commits) + ,(transient-args 'magit-cherry-pick)))) (defun magit--cherry-spinoff-read-args (verb) (magit--cherry-move-read-args verb t @@ -230,7 +231,10 @@ process manually." (0 nil) (1 (car branches)) (_ (magit-completing-read - (format "Remove %s cherries from branch" (length commits)) + (let ((len (length commits))) + (if (= len 1) + "Remove 1 cherry from branch" + (format "Remove %s cherries from branch" len))) branches nil t)))))))) (magit--cherry-move commits branch (magit-get-current-branch) args nil t)) @@ -239,13 +243,20 @@ process manually." "Move COMMITS from the current branch onto another existing BRANCH. Remove COMMITS from the current branch and stay on that branch. If a conflict occurs, then you have to fix that and finish the -process manually." +process manually. `HEAD' is allowed to be detached initially." (interactive (magit--cherry-move-read-args "donate" t (lambda (commits) - (list (magit-read-other-branch (format "Move %s cherries to branch" - (length commits))))))) - (magit--cherry-move commits (magit-get-current-branch) branch args)) + (list (magit-read-other-branch + (let ((len (length commits))) + (if (= len 1) + "Move 1 cherry to branch" + (format "Move %s cherries to branch" len)))))) + 'allow-detached)) + (magit--cherry-move commits + (or (magit-get-current-branch) + (magit-rev-parse "HEAD")) + branch args)) ;;;###autoload (defun magit-cherry-spinout (commits branch start-point &optional args) @@ -436,6 +447,7 @@ without prompting." :description "Remove leading slashes from paths" :class 'transient-option :argument "-p" + :allow-empty t :reader 'transient-read-number-N+) ;;;###autoload @@ -498,6 +510,7 @@ This discards all changes made since the sequence started." (transient-define-prefix magit-rebase () "Transplant commits and/or modify existing commits." :man-page "git-rebase" + :value '("--autostash") ["Arguments" :if-not magit-rebase-in-progress-p ("-k" "Keep empty commits" "--keep-empty") @@ -669,8 +682,13 @@ START has to be selected from a list of recent commits." (unless (member "--root" args) commit))) (magit-log-select `(lambda (commit) - (magit-rebase-interactive-1 commit (list ,@args) - ,message ,editor ,delay-edit-confirm ,noassert)) + ;; In some cases (currently just magit-rebase-remove-commit), "-c + ;; commentChar=#" is added to the global arguments for git. Ensure + ;; that the same happens when we chose the commit via + ;; magit-log-select, below. + (let ((magit-git-global-arguments (list ,@magit-git-global-arguments))) + (magit-rebase-interactive-1 commit (list ,@args) + ,message ,editor ,delay-edit-confirm ,noassert))) message))) (defvar magit--rebase-published-symbol nil) @@ -755,10 +773,14 @@ START has to be selected from a list of recent commits." "Remove a single older commit using rebase." (interactive (list (magit-commit-at-point) (magit-rebase-arguments))) - (magit-rebase-interactive-1 commit args - "Type %p on a commit to remove it," - (apply-partially #'magit-rebase--perl-editor 'remove) - nil nil t)) + ;; magit-rebase--perl-editor assumes that the comment character is "#". + (let ((magit-git-global-arguments + (nconc (list "-c" "core.commentChar=#") + magit-git-global-arguments))) + (magit-rebase-interactive-1 commit args + "Type %p on a commit to remove it," + (apply-partially #'magit-rebase--perl-editor 'remove) + nil nil t))) (defun magit-rebase--perl-editor (action since) (let ((commit (magit-rev-abbrev (magit-rebase--target-commit since)))) @@ -1033,12 +1055,12 @@ status buffer (i.e. the reverse of how they will be applied)." (t (list "done" rev 'magit-sequence-done))))) (magit-sequence-insert-commit "onto" onto - (if (equal onto head) - 'magit-sequence-head - 'magit-sequence-onto)))) + (if (equal onto head) + 'magit-sequence-head + 'magit-sequence-onto)))) (defun magit-sequence-insert-commit (type hash face) - (magit-insert-section (commit hash) + (magit-insert-section (commit hash) (magit-insert-heading (propertize type 'font-lock-face face) "\s" (magit-format-rev-summary hash) "\n"))) diff --git a/lisp/magit/magit-stash.el b/lisp/magit/magit-stash.el index 3d35e296..2b80fc87 100644 --- a/lisp/magit/magit-stash.el +++ b/lisp/magit/magit-stash.el @@ -1,6 +1,6 @@ ;;; magit-stash.el --- stash support for Magit -*- lexical-binding: t -*- -;; Copyright (C) 2008-2021 The Magit Project Contributors +;; Copyright (C) 2008-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -27,15 +29,9 @@ ;;; Code: -(eval-when-compile - (require 'subr-x)) - (require 'magit) (require 'magit-reflog) -;; For `magit-stash-drop'. -(defvar helm-comp-read-use-marked) - ;;; Options (defgroup magit-stash nil @@ -126,7 +122,14 @@ AUTHOR-WIDTH has to be an integer. When the name of the author Untracked files are included according to infix arguments. One prefix argument is equivalent to `--include-untracked' while two prefix arguments are equivalent to `--all'." - (interactive (magit-stash-read-args)) + (interactive + (progn (when (and (magit-merge-in-progress-p) + (not (magit-y-or-n-p "\ +Stashing and resetting during a merge conflict. \ +Applying the resulting stash won't restore the merge state. \ +Proceed anyway? "))) + (user-error "Abort")) + (magit-stash-read-args))) (magit-stash-save message t t include-untracked t)) ;;;###autoload @@ -217,6 +220,7 @@ are staged changes, apply without preserving the stash index." (magit-refresh) (magit-run-git "stash" "apply" stash))) +;;;###autoload (defun magit-stash-pop (stash) "Apply a stash to the working tree and remove it from stash list. Try to preserve the stash index. If that fails because there @@ -234,21 +238,14 @@ When the region is active offer to drop all contained stashes." (interactive (list (--if-let (magit-region-values 'stash) (magit-confirm 'drop-stashes nil "Drop %i stashes" nil it) - (let ((helm-comp-read-use-marked t)) - (magit-read-stash "Drop stash"))))) + (magit-read-stash "Drop stash")))) (dolist (stash (if (listp stash) (nreverse (prog1 stash (setq stash (car stash)))) (list stash))) (message "Deleted refs/%s (was %s)" stash (magit-rev-parse "--short" stash)) (magit-call-git "rev-parse" stash) - (magit-call-git "reflog" "delete" "--updateref" "--rewrite" stash)) - (when-let ((ref (and (string-match "\\(.+\\)@{[0-9]+}$" stash) - (match-string 1 stash)))) - (unless (string-match "^refs/" ref) - (setq ref (concat "refs/" ref))) - (unless (magit-rev-verify (concat ref "@{0}")) - (magit-run-git "update-ref" "-d" ref))) + (magit-call-git "stash" "drop" stash)) (magit-refresh)) ;;;###autoload @@ -273,7 +270,7 @@ The branch is created using `magit-branch-and-checkout', using the current branch or `HEAD' as the start-point." (interactive (list (magit-read-stash "Branch stash") (magit-read-string-ns "Branch name"))) - (let ((inhibit-magit-refresh t)) + (let ((magit-inhibit-refresh t)) (magit-branch-and-checkout branch (or (magit-get-current-branch) "HEAD"))) (magit-stash-apply stash)) diff --git a/lisp/magit/magit-status.el b/lisp/magit/magit-status.el index 032218bf..f4048435 100644 --- a/lisp/magit/magit-status.el +++ b/lisp/magit/magit-status.el @@ -1,6 +1,6 @@ ;;; magit-status.el --- the grand overview -*- lexical-binding: t -*- -;; Copyright (C) 2010-2021 The Magit Project Contributors +;; Copyright (C) 2010-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -27,9 +29,6 @@ ;;; Code: -(eval-when-compile - (require 'subr-x)) - (require 'magit) ;;; Options @@ -269,8 +268,9 @@ prefix arguments: (interactive (let ((magit--refresh-cache (list (cons 0 0)))) (list (and (or current-prefix-arg (not (magit-toplevel))) - (magit-read-repository - (>= (prefix-numeric-value current-prefix-arg) 16))) + (progn (magit--assert-usable-git) + (magit-read-repository + (>= (prefix-numeric-value current-prefix-arg) 16)))) magit--refresh-cache))) (let ((magit--refresh-cache (or cache (list (cons 0 0))))) (if directory @@ -309,6 +309,30 @@ also contains other useful hints.") (put 'magit-status-here 'interactive-only 'magit-status-setup-buffer) +;;;###autoload +(defun magit-status-quick () + "Show the status of the current Git repository, maybe without refreshing. + +If the status buffer of the current Git repository exists but +isn't being displayed in the selected frame, then display it +without refreshing it. + +If the status buffer is being displayed in the selected frame, +then also refresh it. + +Prefix arguments have the same meaning as for `magit-status', +and additionally cause the buffer to be refresh. + +To use this function instead of `magit-status', add this to your +init file: (global-set-key (kbd \"C-x g\") 'magit-status-quick)." + (interactive) + (if-let ((buffer + (and (not current-prefix-arg) + (not (magit-get-mode-buffer 'magit-status-mode nil 'selected)) + (magit-get-mode-buffer 'magit-status-mode)))) + (magit-display-buffer buffer) + (call-interactively #'magit-status))) + (defvar magit--remotes-using-recent-git nil) (defun magit--tramp-asserts (directory) @@ -324,25 +348,14 @@ Magit requires Git >= %s, but on %s the version is %s. If multiple Git versions are installed on the host, then the problem might be that TRAMP uses the wrong executable. -First check the value of `magit-git-executable'. Its value is -used when running git locally as well as when running it on a -remote host. The default value is \"git\", except on Windows -where an absolute path is used for performance reasons. - -If the value already is just \"git\" but TRAMP never-the-less -doesn't use the correct executable, then consult the info node -`(tramp)Remote programs'.\n" magit--minimal-git remote version) :error)) +Check the value of `magit-remote-git-executable' and consult +the info node `(tramp)Remote programs'. +" magit--minimal-git remote version) :error)) (display-warning 'magit (format "\ Magit cannot find Git on %s. -First check the value of `magit-git-executable'. Its value is -used when running git locally as well as when running it on a -remote host. The default value is \"git\", except on Windows -where an absolute path is used for performance reasons. - -If the value already is just \"git\" but TRAMP never-the-less -doesn't find the executable, then consult the info node -`(tramp)Remote programs'.\n" remote) :error))))) +Check the value of `magit-remote-git-executable' and consult +the info node `(tramp)Remote programs'." remote) :error))))) ;;; Mode @@ -386,7 +399,8 @@ doesn't find the executable, then consult the info node ("a " "Assumed unstaged" magit-jump-to-assume-unchanged :if (lambda () (memq 'magit-insert-assume-unchanged-files magit-status-sections-hook))) ("w " "Skip worktree" magit-jump-to-skip-worktree - :if (lambda () (memq 'magit-insert-skip-worktree-files magit-status-sections-hook)))]]) + :if (lambda () (memq 'magit-insert-skip-worktree-files magit-status-sections-hook)))] + [("i" "Using Imenu" imenu)]]) (define-derived-mode magit-status-mode magit-mode "Magit" "Mode for looking at Git status. @@ -537,8 +551,7 @@ the status buffer causes this section to disappear again." (magit-insert-section (error 'git) (insert (propertize (format "%-10s" "GitError! ") 'font-lock-face 'magit-section-heading)) - (insert (propertize magit-this-error - 'font-lock-face 'font-lock-warning-face)) + (insert (propertize magit-this-error 'font-lock-face 'error)) (when-let ((key (car (where-is-internal 'magit-process-buffer)))) (insert (format " [Type `%s' for details]" (key-description key)))) (insert ?\n)) @@ -623,17 +636,18 @@ arguments are for internal use only." ((magit--valid-upstream-p remote merge) (if (equal remote ".") (concat - (propertize merge 'font-lock-face 'magit-branch-local) - (propertize " does not exist" - 'font-lock-face 'font-lock-warning-face)) - (concat + (propertize merge 'font-lock-face 'magit-branch-local) " " + (propertize "does not exist" + 'font-lock-face 'magit-branch-warning)) + (format + "%s %s %s" (propertize merge 'font-lock-face 'magit-branch-remote) - (propertize " does not exist on " - 'font-lock-face 'font-lock-warning-face) + (propertize "does not exist on" + 'font-lock-face 'magit-branch-warning) (propertize remote 'font-lock-face 'magit-branch-remote)))) (t (propertize "invalid upstream configuration" - 'font-lock-face 'font-lock-warning-face))))) + 'font-lock-face 'magit-branch-warning))))) (insert ?\n)))))) (defun magit-insert-push-branch-header () @@ -655,12 +669,12 @@ arguments are for internal use only." "(no commit message)")))) (let ((remote (magit-get-push-remote branch))) (if (magit-remote-p remote) - (concat target - (propertize " does not exist" - 'font-lock-face 'font-lock-warning-face)) - (concat remote - (propertize " remote does not exist" - 'font-lock-face 'font-lock-warning-face)))))) + (concat target " " + (propertize "does not exist" + 'font-lock-face 'magit-branch-warning)) + (concat remote " " + (propertize "remote does not exist" + 'font-lock-face 'magit-branch-warning)))))) (insert ?\n)))) (defun magit-insert-tags-header () diff --git a/lisp/magit/magit-submodule.el b/lisp/magit/magit-submodule.el index 3453a87f..f14337a2 100644 --- a/lisp/magit/magit-submodule.el +++ b/lisp/magit/magit-submodule.el @@ -1,6 +1,6 @@ ;;; magit-submodule.el --- submodule support for Magit -*- lexical-binding: t -*- -;; Copyright (C) 2011-2021 The Magit Project Contributors +;; Copyright (C) 2011-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -23,12 +25,10 @@ ;;; Code: -(eval-when-compile - (require 'subr-x)) - (require 'magit) (defvar x-stretch-cursor) + ;;; Options (defcustom magit-module-sections-hook @@ -83,9 +83,15 @@ of the column. FORMAT is a function that is called with one argument, the repository identification (usually its basename), and with `default-directory' bound to the toplevel of its working tree. It has to return a string to be inserted or nil. PROPS is -an alist that supports the keys `:right-align' and `:pad-right'." +an alist that supports the keys `:right-align' and `:pad-right'. + +You may wish to display a range of numeric columns using just one +character per column and without any padding between columns, in +which case you should use an appropriat HEADER, set WIDTH to 1, +and set `:pad-right' to 0. \"+\" is substituted for numbers higher +than 9." :package-version '(magit . "2.8.0") - :group 'magit-repolist-mode + :group 'magit-repolist :type `(repeat (list :tag "Column" (string :tag "Header Label") (integer :tag "Column Width") @@ -97,6 +103,18 @@ an alist that supports the keys `:right-align' and `:pad-right'." (symbol)) (sexp :tag "Value")))))) +(defcustom magit-submodule-list-sort-key '("Path" . nil) + "Initial sort key for buffer created by `magit-list-submodules'. +If nil, no additional sorting is performed. Otherwise, this +should be a cons cell (NAME . FLIP). NAME is a string matching +one of the column names in `magit-submodule-list-columns'. FLIP, +if non-nil, means to invert the resulting sort." + :package-version '(magit . "3.2.0") + :group 'magit-repolist + :type '(choice (const nil) + (cons (string :tag "Column name") + (boolean :tag "Flip order")))) + (defcustom magit-submodule-remove-trash-gitdirs nil "Whether `magit-submodule-remove' offers to trash module gitdirs. @@ -584,13 +602,7 @@ These sections can be expanded to show the respective commits." (defun magit-list-submodules () "Display a list of the current repository's submodules." (interactive) - (magit-display-buffer - (or (magit-get-mode-buffer 'magit-submodule-list-mode) - (magit-with-toplevel - (magit-generate-new-buffer 'magit-submodule-list-mode)))) - (magit-submodule-list-mode) - (magit-submodule-list-refresh) - (tabulated-list-print)) + (magit-submodule-list-setup magit-submodule-list-columns)) (defvar magit-submodule-list-mode-map (let ((map (make-sparse-keymap))) @@ -601,36 +613,63 @@ These sections can be expanded to show the respective commits." (define-derived-mode magit-submodule-list-mode tabulated-list-mode "Modules" "Major mode for browsing a list of Git submodules." :group 'magit-repolist-mode - (setq-local x-stretch-cursor nil) - (setq tabulated-list-padding 0) - (setq tabulated-list-sort-key (cons "Path" nil)) - (setq tabulated-list-format - (vconcat (mapcar (pcase-lambda (`(,title ,width ,_fn ,props)) - (nconc (list title width t) - (-flatten props))) - magit-submodule-list-columns))) - (tabulated-list-init-header) + (setq-local x-stretch-cursor nil) + (setq tabulated-list-padding 0) (add-hook 'tabulated-list-revert-hook 'magit-submodule-list-refresh nil t) (setq imenu-prev-index-position-function #'magit-imenu--submodule-prev-index-position-function) (setq imenu-extract-index-name-function #'magit-imenu--submodule-extract-index-name-function)) +(defvar-local magit-submodule-list-predicate nil) + +(defun magit-submodule-list-setup (columns &optional predicate) + (magit-display-buffer + (or (magit-get-mode-buffer 'magit-submodule-list-mode) + (magit-with-toplevel + (magit-generate-new-buffer 'magit-submodule-list-mode)))) + (magit-submodule-list-mode) + (setq-local magit-repolist-columns columns) + (setq-local magit-submodule-list-predicate predicate) + (magit-submodule-list-refresh)) + (defun magit-submodule-list-refresh () + (unless tabulated-list-sort-key + (setq tabulated-list-sort-key + (pcase-let ((`(,column . ,flip) magit-submodule-list-sort-key)) + (cons (or (car (assoc column magit-submodule-list-columns)) + (caar magit-submodule-list-columns)) + flip)))) + (setq tabulated-list-format + (vconcat (mapcar (pcase-lambda (`(,title ,width ,_fn ,props)) + (nconc (list title width t) + (-flatten props))) + magit-repolist-columns))) (setq tabulated-list-entries (-keep (lambda (module) (let ((default-directory (expand-file-name (file-name-as-directory module)))) (and (file-exists-p ".git") + (or (not magit-submodule-list-predicate) + (funcall magit-submodule-list-predicate module)) (list module (vconcat - (--map (or (funcall (nth 2 it) module) "") - magit-submodule-list-columns)))))) - (magit-list-module-paths)))) + (mapcar (pcase-lambda (`(,title ,width ,fn ,props)) + (or (funcall fn `((:path ,module) + (:title ,title) + (:width ,width) + ,@props)) + "")) + magit-repolist-columns)))))) + (magit-list-module-paths))) + (message "Listing submodules...") + (tabulated-list-init-header) + (tabulated-list-print t) + (message "Listing submodules...done")) -(defun magit-modulelist-column-path (path) +(defun magit-modulelist-column-path (spec) "Insert the relative path of the submodule." - path) + (cadr (assq :path spec))) ;;; Utilities diff --git a/lisp/magit/magit-subtree.el b/lisp/magit/magit-subtree.el index 05f44672..3d0514ed 100644 --- a/lisp/magit/magit-subtree.el +++ b/lisp/magit/magit-subtree.el @@ -1,6 +1,6 @@ ;;; magit-subtree.el --- subtree support for Magit -*- lexical-binding: t -*- -;; Copyright (C) 2011-2021 The Magit Project Contributors +;; Copyright (C) 2011-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) diff --git a/lisp/magit/magit-tag.el b/lisp/magit/magit-tag.el index dbec9393..c10a46c8 100644 --- a/lisp/magit/magit-tag.el +++ b/lisp/magit/magit-tag.el @@ -1,6 +1,6 @@ ;;; magit-tag.el --- tag functionality -*- lexical-binding: t -*- -;; Copyright (C) 2010-2021 The Magit Project Contributors +;; Copyright (C) 2010-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -56,7 +58,7 @@ :class 'transient-option :shortarg "-u" :argument "--local-user=" - :reader 'magit-read-gpg-secret-key + :reader 'magit-read-gpg-signing-key :history-key 'magit:--gpg-sign) ;;;###autoload diff --git a/lisp/magit/magit-transient.el b/lisp/magit/magit-transient.el index eb76ca1a..8d6d582f 100644 --- a/lisp/magit/magit-transient.el +++ b/lisp/magit/magit-transient.el @@ -1,6 +1,6 @@ ;;; magit-transient.el --- support for transients -*- lexical-binding: t -*- -;; Copyright (C) 2008-2021 The Magit Project Contributors +;; Copyright (C) 2008-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -28,15 +30,12 @@ ;;; Code: -(eval-when-compile - (require 'subr-x)) - -(require 'transient) - (require 'magit-git) (require 'magit-mode) (require 'magit-process) +(require 'transient) + ;;; Classes (defclass magit--git-variable (transient-variable) @@ -199,4 +198,3 @@ ;;; _ (provide 'magit-transient) ;;; magit-transient.el ends here - diff --git a/lisp/magit/magit-utils.el b/lisp/magit/magit-utils.el index 0a8e8ae2..75b4393c 100644 --- a/lisp/magit/magit-utils.el +++ b/lisp/magit/magit-utils.el @@ -1,6 +1,6 @@ ;;; magit-utils.el --- various utilities -*- lexical-binding: t; coding: utf-8 -*- -;; Copyright (C) 2010-2021 The Magit Project Contributors +;; Copyright (C) 2010-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -11,6 +11,8 @@ ;; Contains code from GNU Emacs https://www.gnu.org/software/emacs, ;; released under the GNU General Public License version 3 or later. +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -40,17 +42,13 @@ (require 'cl-lib) (require 'dash) - -(eval-when-compile - (require 'subr-x)) +(require 'eieio) +(require 'seq) +(require 'subr-x) (require 'crm) (eval-when-compile (require 'ido)) -(declare-function ido-completing-read+ "ido-completing-read+" - (prompt collection &optional predicate - require-match initial-input - hist def inherit-input-method)) (declare-function Info-get-token "info" (pos start all &optional errorstring)) (eval-when-compile (require 'vc-git)) @@ -108,7 +106,8 @@ alphabetical order, depending on your version of Ivy." (forge-edit-topic-note nil t) (forge-pull-pullreq nil t) (forge-visit-issue nil t) - (forge-visit-pullreq nil t)) + (forge-visit-pullreq nil t) + (forge-visit-topic nil t)) "When not to offer alternatives and ask for confirmation. Many commands by default ask the user to select from a list of @@ -161,6 +160,7 @@ The value has the form ((COMMAND nil|PROMPT DEFAULT)...). (const abort-merge) (const merge-dirty) (const delete-unmerged-branch) + (const delete-branch-on-remote) (const delete-pr-remote) (const drop-stashes) (const set-and-push) @@ -241,6 +241,13 @@ References: choice (or selecting another branch), but when a branch has not been merged yet, also make sure the user is aware of that. + `delete-branch-on-remote' Deleting a \"remote branch\" may mean + deleting the (local) \"remote-tracking\" branch only, or also + removing it from the remote itself. The latter often makes more + sense because otherwise simply fetching from the remote would + restore the remote-tracking branch, but doing that can be + surprising and hard to recover from, so we ask. + `delete-pr-remote' When deleting a branch that was created from a pull-request and if no other branches still exist on that remote, then `magit-branch-delete' offers to delete the remote @@ -271,11 +278,11 @@ Edit published history: editing commits that have already been pushed to one of the branches listed in `magit-published-branches'. - `amend-published' Affects most commands that amend to \"HEAD\". + `amend-published' Affects most commands that amend to `HEAD'. `rebase-published' Affects commands that perform interactive rebases. This includes commands from the commit popup that - modify a commit other than \"HEAD\", namely the various fixup + modify a commit other than `HEAD', namely the various fixup and squash variants. `edit-published' Affects the commands `magit-edit-line-commit' @@ -379,14 +386,21 @@ Messages which can currently be suppressed using this option are: :group 'magit-miscellaneous :type '(repeat string)) -(defcustom magit-ellipsis ?… - "Character used to abbreviate text. +(defcustom magit-ellipsis (if (char-displayable-p ?…) "…" "...") + "String used to abbreviate text in process buffers. -Currently this is used to abbreviate author names in the margin -and in process buffers to elide `magit-git-global-arguments'." - :package-version '(magit . "2.1.0") +Currently this is only used to elide `magit-git-global-arguments' +in process buffers. In the future it may be used in other places +as well, but not the following: + +- Author names in the log margin are always abbreviated using + \"…\" or if that is not displayable, then \">\". + +- Whether collapsed sections are indicated using ellipsis is + controlled by `magit-section-visibility-indicator'." + :package-version '(magit . "3.0.0") :group 'magit-miscellaneous - :type 'character) + :type 'string) (defcustom magit-update-other-window-delay 0.2 "Delay before automatically updating the other window. @@ -516,21 +530,27 @@ acts similarly to `completing-read', except for the following: (complete-with-action action collection string pred)))) (defun magit-builtin-completing-read - (prompt choices &optional predicate require-match initial-input hist def) + (prompt choices &optional predicate require-match initial-input hist def) "Magit wrapper for standard `completing-read' function." + (unless (or (bound-and-true-p helm-mode) + (bound-and-true-p ivy-mode) + (bound-and-true-p vertico-mode) + (bound-and-true-p selectrum-mode)) + (setq prompt (magit-prompt-with-default prompt def))) (unless (or (bound-and-true-p helm-mode) (bound-and-true-p ivy-mode)) - (setq prompt (magit-prompt-with-default prompt def)) (setq choices (magit--completion-table choices))) - (cl-letf (((symbol-function 'completion-pcm--all-completions) - #'magit-completion-pcm--all-completions)) + (cl-letf (((symbol-function 'completion-pcm--all-completions))) + (when (< emacs-major-version 26) + (fset 'completion-pcm--all-completions + 'magit-completion-pcm--all-completions)) (let ((ivy-sort-functions-alist nil)) (completing-read prompt choices predicate require-match initial-input hist def)))) (defun magit-completing-read-multiple - (prompt choices &optional sep default hist keymap) + (prompt choices &optional sep default hist keymap) "Read multiple items from CHOICES, separated by SEP. Set up the `crm' variables needed to read multiple values with @@ -543,6 +563,7 @@ When KEYMAP is nil, it defaults to `crm-local-completion-map'. Unlike `completing-read-multiple', the return value is not split into a list." + (declare (obsolete magit-completing-read-multiple* "Magit 3.1.0")) (let* ((crm-separator (or sep crm-default-separator)) (crm-completion-table (magit--completion-table choices)) (choose-completion-string-functions @@ -553,8 +574,10 @@ into a list." (helm-crm-default-separator nil) (ivy-sort-matches-functions-alist nil) (input - (cl-letf (((symbol-function 'completion-pcm--all-completions) - #'magit-completion-pcm--all-completions)) + (cl-letf (((symbol-function 'completion-pcm--all-completions))) + (when (< emacs-major-version 26) + (fset 'completion-pcm--all-completions + 'magit-completion-pcm--all-completions)) (read-from-minibuffer (concat prompt (and default (format " (%s)" default)) ": ") nil (or keymap crm-local-completion-map) @@ -566,47 +589,78 @@ into a list." (defun magit-completing-read-multiple* (prompt table &optional predicate require-match initial-input - hist def inherit-input-method) + hist def inherit-input-method + no-split) "Read multiple strings in the minibuffer, with completion. Like `completing-read-multiple' but don't mess with order of -TABLE. Also bind `helm-completion-in-region-default-sort-fn' -to nil." - (unwind-protect - (cl-letf (((symbol-function 'completion-pcm--all-completions) - #'magit-completion-pcm--all-completions)) - (add-hook 'choose-completion-string-functions - 'crm--choose-completion-string) - (let* ((minibuffer-completion-table #'crm--collection-fn) - (minibuffer-completion-predicate predicate) - ;; see completing_read in src/minibuf.c - (minibuffer-completion-confirm - (unless (eq require-match t) require-match)) - (crm-completion-table (magit--completion-table table)) - (map (if require-match - crm-local-must-match-map - crm-local-completion-map)) - (helm-completion-in-region-default-sort-fn nil) - (ivy-sort-matches-functions-alist nil) - ;; If the user enters empty input, `read-from-minibuffer' - ;; returns the empty string, not DEF. - (input (read-from-minibuffer - prompt initial-input map - nil hist def inherit-input-method))) - (and def (string-equal input "") (setq input def)) - ;; Remove empty strings in the list of read strings. - (split-string input crm-separator t))) - (remove-hook 'choose-completion-string-functions - 'crm--choose-completion-string))) +TABLE and take an additional argument NO-SPLIT, which causes +the user input to be returned as a single unmodified string. +Also work around various incompatible features of various +third-party completion frameworks." + (cl-letf* + (;; To implement NO-SPLIT we have to manipulate the respective + ;; `split-string' invocation. We cannot simply advice it to + ;; return the input string because `SELECTRUM' would choke on + ;; that string. Use a variable to pass along the raw user + ;; input string. aa5f098ab + (input nil) + (split-string (symbol-function 'split-string)) + ((symbol-function 'split-string) + (lambda (string &optional separators omit-nulls trim) + (when (and no-split + (equal separators crm-separator) + (equal omit-nulls t)) + (setq input string)) + (funcall split-string string separators omit-nulls trim))) + ;; In Emacs 25 this function has a bug, so we use a copy of the + ;; version from Emacs 26. bef9c7aa3 + ((symbol-function 'completion-pcm--all-completions) + (if (< emacs-major-version 26) + 'magit-completion-pcm--all-completions + (symbol-function 'completion-pcm--all-completions))) + ;; Prevent `BUILT-IN' completion from messing up our existing + ;; order of the completion candidates. aa5f098ab + (table (magit--completion-table table)) + ;; Prevent `IVY' from messing up our existing order. c7af78726 + (ivy-sort-matches-functions-alist nil) + ;; Prevent `HELM' from messing up our existing order. 6fcf994bd + (helm-completion-in-region-default-sort-fn nil) + ;; Prevent `HELM' from automatically appending the separator, + ;; which is counterproductive when NO-SPLIT is non-nil and/or + ;; when reading commit ranges. 798aff564 + (helm-crm-default-separator + (if no-split nil (bound-and-true-p helm-crm-default-separator))) + (values + (if (and no-split + (advice-member-p 'consult-completing-read-multiple + 'completing-read-multiple)) + ;; Our NO-SPLIT hack is not compatible with `CONSULT's + ;; implemenation so fall back to the original function. + ;; #4437 + (unwind-protect + (progn + (advice-remove 'completing-read-multiple + 'consult-completing-read-multiple) + (completing-read-multiple + prompt table predicate require-match initial-input + hist def inherit-input-method)) + (advice-add 'completing-read-multiple :override + 'consult-completing-read-multiple)) + (completing-read-multiple + prompt table predicate require-match initial-input + hist def inherit-input-method)))) + (if no-split input values))) (defun magit-ido-completing-read - (prompt choices &optional predicate require-match initial-input hist def) + (prompt choices &optional predicate require-match initial-input hist def) "Ido-based `completing-read' almost-replacement. Unfortunately `ido-completing-read' is not suitable as a drop-in replacement for `completing-read', instead we use `ido-completing-read+' from the third-party package by the same name." - (if (require 'ido-completing-read+ nil t) + (if (and (require 'ido-completing-read+ nil t) + (fboundp 'ido-completing-read+)) (ido-completing-read+ prompt choices predicate require-match initial-input hist (or def (and require-match (car choices)))) @@ -687,9 +741,11 @@ This is similar to `read-string', but (debug (form form &rest (characterp form body)))) `(prog1 (pcase (read-char-choice (concat ,prompt - ,(concat (mapconcat 'cadr clauses ", ") - (and verbose ", or [C-g] to abort") " ")) - ',(mapcar 'car clauses)) + (mapconcat #'identity + (list ,@(mapcar #'cadr clauses)) + ", ") + ,(if verbose ", or [C-g] to abort " " ")) + ',(mapcar #'car clauses)) ,@(--map `(,(car it) ,@(cddr it)) clauses)) (message ""))) @@ -786,11 +842,10 @@ See info node `(magit)Debugging Tools' for more information." "with-editor" ;; Obviously `magit' itself is needed too. "magit" - ;; While this is part of the Magit repository, - ;; it is distributed as a separate package. + ;; While these are part of the Magit repository, + ;; they are distributed as separate packages. + "magit-section" "git-commit" - ;; Even though `async' is a dependency of the - ;; `magit' package, it is not required here. )))) ;; Avoid Emacs bug#16406 by using full path. "-l" ,(file-name-sans-extension (locate-library "magit"))) @@ -812,7 +867,11 @@ as STRING." (i 0)) `(let ((,s ,string)) (let ,(save-match-data - (--map (list it (list 'match-string (cl-incf i) s)) varlist)) + (cl-mapcan (lambda (sym) + (cl-incf i) + (and (not (eq (aref (symbol-name sym) 0) ?_)) + (list (list sym (list 'match-string i s))))) + varlist)) ,@body)))) (defun magit-delete-line () @@ -1001,27 +1060,26 @@ and https://github.com/magit/magit/issues/2295." (advice-add 'auto-revert-handler :around 'auto-revert-handler@bug21559) ) -;; `completion-pcm--all-completions' reverses the completion list. To -;; preserve the order of our pre-sorted completions, we'll temporarily -;; override it with the function below. bug#24676 -(defun magit-completion-pcm--all-completions (prefix pattern table pred) - (if (completion-pcm--pattern-trivial-p pattern) - (all-completions (concat prefix (car pattern)) table pred) - (let* ((regex (completion-pcm--pattern->regex pattern)) - (case-fold-search completion-ignore-case) - (completion-regexp-list (cons regex completion-regexp-list)) - (compl (all-completions - (concat prefix - (if (stringp (car pattern)) (car pattern) "")) - table pred))) - (if (not (functionp table)) - compl - (let ((poss ())) - (dolist (c compl) - (when (string-match-p regex c) (push c poss))) - ;; This `nreverse' call is the only code change made to the - ;; `completion-pcm--all-completions' that shipped with Emacs 25.1. - (nreverse poss)))))) +(when (< emacs-major-version 26) + ;; In Emacs 25 `completion-pcm--all-completions' reverses the + ;; completion list. This is the version from Emacs 26, which + ;; fixes that issue. bug#24676 + (defun magit-completion-pcm--all-completions (prefix pattern table pred) + (if (completion-pcm--pattern-trivial-p pattern) + (all-completions (concat prefix (car pattern)) table pred) + (let* ((regex (completion-pcm--pattern->regex pattern)) + (case-fold-search completion-ignore-case) + (completion-regexp-list (cons regex completion-regexp-list)) + (compl (all-completions + (concat prefix + (if (stringp (car pattern)) (car pattern) "")) + table pred))) + (if (not (functionp table)) + compl + (let ((poss ())) + (dolist (c compl) + (when (string-match-p regex c) (push c poss))) + (nreverse poss))))))) (defun magit-which-function () "Return current function name based on point. @@ -1140,67 +1198,6 @@ See ." (setq filename target)))) (file-chase-links filename)) -;;; Bitmaps - -(when (fboundp 'define-fringe-bitmap) - (define-fringe-bitmap 'magit-fringe-bitmap+ - [#b00000000 - #b00011000 - #b00011000 - #b01111110 - #b01111110 - #b00011000 - #b00011000 - #b00000000]) - (define-fringe-bitmap 'magit-fringe-bitmap- - [#b00000000 - #b00000000 - #b00000000 - #b01111110 - #b01111110 - #b00000000 - #b00000000 - #b00000000]) - - (define-fringe-bitmap 'magit-fringe-bitmap> - [#b01100000 - #b00110000 - #b00011000 - #b00001100 - #b00011000 - #b00110000 - #b01100000 - #b00000000]) - (define-fringe-bitmap 'magit-fringe-bitmapv - [#b00000000 - #b10000010 - #b11000110 - #b01101100 - #b00111000 - #b00010000 - #b00000000 - #b00000000]) - - (define-fringe-bitmap 'magit-fringe-bitmap-bold> - [#b11100000 - #b01110000 - #b00111000 - #b00011100 - #b00011100 - #b00111000 - #b01110000 - #b11100000]) - (define-fringe-bitmap 'magit-fringe-bitmap-boldv - [#b10000001 - #b11000011 - #b11100111 - #b01111110 - #b00111100 - #b00011000 - #b00000000 - #b00000000]) - ) - ;;; Miscellaneous (defun magit-message (format-string &rest args) diff --git a/lisp/magit/magit-version.el b/lisp/magit/magit-version.el index 427cf101..0ae1c072 100644 --- a/lisp/magit/magit-version.el +++ b/lisp/magit/magit-version.el @@ -1,6 +1,6 @@ ;;; magit-version.el --- the Magit version you are using -(setq magit-version "20210105.1030") +(setq magit-version "3.3.0") (provide 'migit-version) diff --git a/lisp/magit/magit-wip.el b/lisp/magit/magit-wip.el index 23a97647..70952a5c 100644 --- a/lisp/magit/magit-wip.el +++ b/lisp/magit/magit-wip.el @@ -1,6 +1,6 @@ ;;; magit-wip.el --- commit snapshots to work-in-progress refs -*- lexical-binding: t -*- -;; Copyright (C) 2010-2021 The Magit Project Contributors +;; Copyright (C) 2010-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -30,9 +32,6 @@ ;;; Code: -(eval-when-compile - (require 'subr-x)) - (require 'magit-core) (require 'magit-log) @@ -288,30 +287,35 @@ commit message." (magit-wip-update-wipref ref wipref tree parent files msg "index"))) (defun magit-wip-commit-worktree (ref files msg) - (let* ((wipref (magit--wip-wtree-ref ref)) - (parent (magit-wip-get-parent ref wipref)) - (tree (magit-with-temp-index parent (list "--reset" "-i") - (if files - ;; Note: `update-index' is used instead of `add' - ;; because `add' will fail if a file is already - ;; deleted in the temporary index. - (magit-call-git - "update-index" "--add" "--remove" - (and (pcase (magit-repository-local-get - 'update-index-has-ignore-sw-p 'unset) - (`unset - (let ((val (version<= "2.25.0" - (magit-git-version)))) - (magit-repository-local-set - 'update-index-has-ignore-sw-p val) - val)) - (val val)) - "--ignore-skip-worktree-entries") - "--" files) - (magit-with-toplevel - (magit-call-git "add" "-u" "."))) - (magit-git-string "write-tree")))) - (magit-wip-update-wipref ref wipref tree parent files msg "worktree"))) + (when (or (not files) + ;; `update-index' will either ignore (before Git v2.32.0) + ;; or fail when passed directories (relevant for the + ;; untracked files code paths). + (setq files (seq-remove #'file-directory-p files))) + (let* ((wipref (magit--wip-wtree-ref ref)) + (parent (magit-wip-get-parent ref wipref)) + (tree (magit-with-temp-index parent (list "--reset" "-i") + (if files + ;; Note: `update-index' is used instead of `add' + ;; because `add' will fail if a file is already + ;; deleted in the temporary index. + (magit-call-git + "update-index" "--add" "--remove" + (and (pcase (magit-repository-local-get + 'update-index-has-ignore-sw-p 'unset) + (`unset + (let ((val (version<= "2.25.0" + (magit-git-version)))) + (magit-repository-local-set + 'update-index-has-ignore-sw-p val) + val)) + (val val)) + "--ignore-skip-worktree-entries") + "--" files) + (magit-with-toplevel + (magit-call-git "add" "-u" "."))) + (magit-git-string "write-tree")))) + (magit-wip-update-wipref ref wipref tree parent files msg "worktree")))) (defun magit-wip-update-wipref (ref wipref tree parent files msg start-msg) (cond @@ -443,7 +447,10 @@ many \"branches\" of each wip ref are shown." (when-let ((reflog (magit-git-lines "reflog" wipref))) (let (tips) (while (and reflog (> count 1)) - (setq reflog (cl-member "^[^ ]+ [^:]+: restart autosaving" + ;; "start autosaving ..." is the current message, but it used + ;; to be "restart autosaving ...", and those messages may + ;; still be around (e.g., if gc.reflogExpire is to "never"). + (setq reflog (cl-member "^[^ ]+ [^:]+: \\(?:re\\)?start autosaving" reflog :test #'string-match-p)) (when (and (cadr reflog) (string-match "^[^ ]+ \\([^:]+\\)" (cadr reflog))) diff --git a/lisp/magit/magit-worktree.el b/lisp/magit/magit-worktree.el index 0d95e5d3..3e176e35 100644 --- a/lisp/magit/magit-worktree.el +++ b/lisp/magit/magit-worktree.el @@ -1,6 +1,6 @@ ;;; magit-worktree.el --- worktree support -*- lexical-binding: t -*- -;; Copyright (C) 2010-2021 The Magit Project Contributors +;; Copyright (C) 2010-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. @@ -8,6 +8,8 @@ ;; Author: Jonas Bernoulli ;; Maintainer: Jonas Bernoulli +;; SPDX-License-Identifier: GPL-3.0-or-later + ;; Magit 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, or (at your option) @@ -62,7 +64,7 @@ Used by `magit-worktree-checkout' and `magit-worktree-branch'." (list (funcall magit-worktree-read-directory-name-function (format "Checkout %s in new worktree: " branch)) branch))) - (magit-run-git "worktree" "add" (expand-file-name path) branch) + (magit-run-git "worktree" "add" (magit--expand-worktree path) branch) (magit-diff-visit-directory path)) ;;;###autoload @@ -74,7 +76,7 @@ Used by `magit-worktree-checkout' and `magit-worktree-branch'." ,@(magit-branch-read-args "Create and checkout branch") ,current-prefix-arg)) (magit-run-git "worktree" "add" (if force "-B" "-b") - branch (expand-file-name path) start-point) + branch (magit--expand-worktree path) start-point) (magit-diff-visit-directory path)) ;;;###autoload @@ -91,7 +93,7 @@ Used by `magit-worktree-checkout' and `magit-worktree-branch'." (user-error "You may not move the main working tree") (let ((preexisting-directory (file-directory-p path))) (when (and (zerop (magit-call-git "worktree" "move" worktree - (expand-file-name path))) + (magit--expand-worktree path))) (not (file-exists-p default-directory)) (derived-mode-p 'magit-status-mode)) (kill-buffer) @@ -141,6 +143,9 @@ then show it in Dired instead." :test #'equal :key #'car))))) (magit-diff-visit-directory worktree)) +(defun magit--expand-worktree (path) + (magit-convert-filename-for-git (expand-file-name path))) + ;;; Sections (defvar magit-worktree-section-map diff --git a/lisp/magit/magit.el b/lisp/magit/magit.el index a3157015..f79828d6 100644 --- a/lisp/magit/magit.el +++ b/lisp/magit/magit.el @@ -1,25 +1,27 @@ ;;; magit.el --- A Git porcelain inside Emacs -*- lexical-binding: t; coding: utf-8 -*- -;; Copyright (C) 2008-2021 The Magit Project Contributors +;; Copyright (C) 2008-2022 The Magit Project Contributors ;; ;; You should have received a copy of the AUTHORS.md file which ;; lists all contributors. If not, see http://magit.vc/authors. ;; Author: Marius Vollmer +;; Jonas Bernoulli ;; Maintainer: Jonas Bernoulli -;; Kyle Meyer -;; Noam Postavsky +;; Kyle Meyer +;; Noam Postavsky ;; Former-Maintainers: -;; Nicolas Dudebout -;; Peter J. Weisberg -;; Phil Jackson -;; Rémi Vanicat -;; Yann Hodique +;; Nicolas Dudebout +;; Peter J. Weisberg +;; Phil Jackson +;; Rémi Vanicat +;; Yann Hodique ;; Keywords: git tools vc ;; Homepage: https://github.com/magit/magit - -;; Magit requires at least GNU Emacs 25.1 and Git 2.2.0. +;; Package-Requires: ((emacs "25.1") (dash "2.19.1") (git-commit "3.3.0") (magit-section "3.3.0") (transient "0.3.6") (with-editor "3.0.5")) +;; Package-Version: 3.3.0 +;; SPDX-License-Identifier: GPL-3.0-or-later ;; Magit is free software; you can redistribute it and/or modify it ;; under the terms of the GNU General Public License as published by @@ -34,35 +36,34 @@ ;; You should have received a copy of the GNU General Public License ;; along with Magit. If not, see http://www.gnu.org/licenses. +;; Magit requires at least GNU Emacs 25.1 and Git 2.2.0. + ;;; Commentary: -;; Magit is an interface to the version control system Git, -;; implemented as an Emacs package. Magit aspires to be a complete -;; Git porcelain. While we cannot (yet) claim, that Magit wraps and -;; improves upon each and every Git command, it is complete enough to -;; allow even experienced Git users to perform almost all of their -;; daily version control tasks directly from within Emacs. While many -;; fine Git clients exist, only Magit and Git itself deserve to be -;; called porcelains. +;; Magit is a text-based Git user interface that puts an unmatched focus +;; on streamlining workflows. Commands are invoked using short mnemonic +;; key sequences that take the cursor’s position in the highly actionable +;; interface into account to provide context-sensitive behavior. + +;; With Magit you can do nearly everything that you can do when using Git +;; on the command-line, but at greater speed and while taking advantage +;; of advanced features that previously seemed too daunting to use on a +;; daily basis. Many users will find that by using Magit they can become +;; more effective Git user. ;;; Code: -(require 'cl-lib) -(require 'dash) - -(require 'subr-x) - -(require 'with-editor) -(require 'git-commit) (require 'magit-core) (require 'magit-diff) (require 'magit-log) (require 'magit-wip) (require 'magit-apply) (require 'magit-repos) +(require 'git-commit) (require 'format-spec) (require 'package nil t) ; used in `magit-version' +(require 'with-editor) (defconst magit--minimal-git "2.2.0") (defconst magit--minimal-emacs "25.1") @@ -107,8 +108,8 @@ own faces for the `header-line', or for parts of the :group 'magit-faces) (defface magit-branch-remote-head - '((((class color) (background light)) :inherit magit-branch-remote :box t) - (((class color) (background dark)) :inherit magit-branch-remote :box t)) + '((((supports (:box t))) :inherit magit-branch-remote :box t) + (t :inherit magit-branch-remote :inverse-video t)) "Face for current branch." :group 'magit-faces) @@ -119,8 +120,8 @@ own faces for the `header-line', or for parts of the :group 'magit-faces) (defface magit-branch-current - '((((class color) (background light)) :inherit magit-branch-local :box t) - (((class color) (background dark)) :inherit magit-branch-local :box t)) + '((((supports (:box t))) :inherit magit-branch-local :box t) + (t :inherit magit-branch-local :inverse-video t)) "Face for current branch." :group 'magit-faces) @@ -132,6 +133,11 @@ This face is only used in logs and it gets combined and/or `magit-branch-remote-head'." :group 'magit-faces) +(defface magit-branch-warning + '((t :inherit warning)) + "Face for warning about (missing) branch." + :group 'magit-faces) + (defface magit-head '((((class color) (background light)) :inherit magit-branch-local) (((class color) (background dark)) :inherit magit-branch-local)) @@ -180,7 +186,7 @@ and/or `magit-branch-remote-head'." :group 'magit-faces) (defface magit-signature-untrusted - '((t :foreground "cyan")) + '((t :foreground "medium aquamarine")) "Face for good untrusted signatures." :group 'magit-faces) @@ -200,7 +206,7 @@ and/or `magit-branch-remote-head'." :group 'magit-faces) (defface magit-signature-error - '((t :foreground "firebrick3")) + '((t :foreground "light blue")) "Face for signatures that cannot be checked (e.g. missing key)." :group 'magit-faces) @@ -238,7 +244,7 @@ C-x g magit-status C-x M-g magit-dispatch C-c M-g magit-file-dispatch -These bindings may be added when `after-init-hook' is called. +These bindings may be added when `after-init-hook' is run. Each binding is added if and only if at that time no other key is bound to the same command and no other command is bound to the same key. In other words we try to avoid adding bindings @@ -252,8 +258,14 @@ is loaded or autoloaded) and to increase the likelihood that all the potentially conflicting user bindings have already been added. -Setting this variable after the hook has already been called -has no effect. +To set this variable use either `setq' or the Custom interface. +Do not use the function `customize-set-variable' because doing +that would cause Magit to be loaded immediately when that form +is evaluated (this differs from `custom-set-variables', which +doesn't load the libraries that define the customized variables). + +Setting this variable to nil has no effect if that is done after +the key bindings have already been added. We recommend that you bind \"C-c g\" instead of \"C-c M-g\" to `magit-file-dispatch'. The former is a much better binding @@ -289,7 +301,10 @@ Also see info node `(magit)Commands for Buffers Visiting Files'." "Invoke a Magit command from a list of available commands." :info-manual "(magit)Top" ["Transient and dwim commands" + ;; → bound in magit-mode-map or magit-section-mode-map + ;; ↓ bound below [("A" "Apply" magit-cherry-pick) + ;; a ↓ ("b" "Branch" magit-branch) ("B" "Bisect" magit-bisect) ("c" "Commit" magit-commit) @@ -297,28 +312,51 @@ Also see info node `(magit)Commands for Buffers Visiting Files'." ("d" "Diff" magit-diff) ("D" "Diff (change)" magit-diff-refresh) ("e" "Ediff (dwim)" magit-ediff-dwim) - ("E" "Ediff" magit-ediff)] - [("f" "Fetch" magit-fetch) + ("E" "Ediff" magit-ediff) + ("f" "Fetch" magit-fetch) ("F" "Pull" magit-pull) + ;; g ↓ + ;; G → magit-refresh-all + ("h" "Help" magit-help) + ("H" "Section info" magit-describe-section :if-derived magit-mode)] + [("i" "Ignore" magit-gitignore) + ("I" "Init" magit-init) + ("j" "Jump to section"magit-status-jump :if-mode magit-status-mode) + ("j" "Display status" magit-status-quick :if-not-mode magit-status-mode) + ("J" "Display buffer" magit-display-repository-buffer) + ;; k ↓ + ;; K → magit-file-untrack ("l" "Log" magit-log) ("L" "Log (change)" magit-log-refresh) ("m" "Merge" magit-merge) ("M" "Remote" magit-remote) + ;; n → magit-section-forward + ;; N reserved → forge-dispatch ("o" "Submodule" magit-submodule) - ("O" "Subtree" magit-subtree)] - [("P" "Push" magit-push) - ("r" "Rebase" magit-rebase) + ("O" "Subtree" magit-subtree) + ;; p → magit-section-backward + ("P" "Push" magit-push) + ;; q → magit-mode-bury-buffer + ("Q" "Command" magit-git-command)] + [("r" "Rebase" magit-rebase) + ;; R → magit-file-rename + ;; s ↓ + ;; S ↓ ("t" "Tag" magit-tag) ("T" "Note" magit-notes) + ;; u ↓ + ;; U ↓ + ;; v ↓ ("V" "Revert" magit-revert) ("w" "Apply patches" magit-am) ("W" "Format patches" magit-patch) - ("X" "Reset" magit-reset)] - [("y" "Show Refs" magit-show-refs) + ;; x → magit-reset-quickly + ("X" "Reset" magit-reset) + ("y" "Show Refs" magit-show-refs) ("Y" "Cherries" magit-cherry) ("z" "Stash" magit-stash) - ("!" "Run" magit-run) - ("%" "Worktree" magit-worktree)]] + ("Z" "Worktree" magit-worktree) + ("!" "Run" magit-run)]] ["Applying changes" :if-derived magit-mode [("a" "Apply" magit-apply) @@ -333,7 +371,7 @@ Also see info node `(magit)Commands for Buffers Visiting Files'." ("g" " refresh current buffer" magit-refresh) ("" " toggle section at point" magit-section-toggle) ("" "visit thing at point" magit-visit-thing) - ("C-h m" " show all key bindings" describe-mode)]) + ("C-x m" " show all key bindings" describe-mode)]) ;;; Git Popup @@ -350,8 +388,6 @@ This affects `magit-git-command', `magit-git-command-topdir', ;;;###autoload (autoload 'magit-run "magit" nil t) (transient-define-prefix magit-run () "Run git or another command, or launch a graphical utility." - - [["Run git subcommand" ("!" "in repository root" magit-git-command-topdir) ("p" "in working directory" magit-git-command)] @@ -465,8 +501,10 @@ and Emacs to it." (toplib (or load-file-name buffer-file-name)) debug) (unless (and toplib - (equal (file-name-nondirectory toplib) "magit.el")) - (setq toplib (locate-library "magit.el"))) + (member (file-name-nondirectory toplib) + '("magit.el" "magit.el.gz"))) + (let ((load-suffixes (reverse load-suffixes))) ; prefer .el than .elc + (setq toplib (locate-library "magit")))) (setq toplib (and toplib (magit--straight-chase-links toplib))) (push toplib debug) (when toplib @@ -526,8 +564,19 @@ and Emacs to it." (magit-git-string "rev-parse" "HEAD")))))))) (if (stringp magit-version) (when print-dest - (princ (format "Magit %s, Git %s, Emacs %s, %s" + (princ (format "Magit %s%s, Git %s, Emacs %s, %s" (or magit-version "(unknown)") + (or (and (ignore-errors (version< "2008" magit-version)) + (ignore-errors + (require 'lisp-mnt) + (and (fboundp 'lm-header) + (format + " [>= %s]" + (with-temp-buffer + (insert-file-contents + (locate-library "magit.el" t)) + (lm-header "Package-Version")))))) + "") (or (let ((magit-git-debug (lambda (err) (display-warning '(magit git) @@ -541,7 +590,7 @@ and Emacs to it." (setq magit-version 'error) (when magit-version (push magit-version debug)) - (unless (equal (getenv "TRAVIS") "true") + (unless (equal (getenv "CI") "true") ;; The repository is a sparse clone. (message "Cannot determine Magit's version %S" debug))) magit-version)) @@ -550,11 +599,14 @@ and Emacs to it." (defun magit-debug-git-executable () "Display a buffer with information about `magit-git-executable'. +Also include information about `magit-remote-git-executable'. See info node `(magit)Debugging Tools' for more information." (interactive) (with-current-buffer (get-buffer-create "*magit-git-debug*") (pop-to-buffer (current-buffer)) (erase-buffer) + (insert (format "magit-remote-git-executable: %S\n" + magit-remote-git-executable)) (insert (concat (format "magit-git-executable: %S" magit-git-executable) (and (not (file-name-absolute-p magit-git-executable)) @@ -596,7 +648,7 @@ https://github.com/magit/magit/wiki/Don't-set-$GIT_DIR-and-alike" val)) (let ((version (magit-git-version))) (when (and version (version< version magit--minimal-git) - (not (equal (getenv "TRAVIS") "true"))) + (not (equal (getenv "CI") "true"))) (display-warning 'magit (format "\ Magit requires Git >= %s, you are using %s. @@ -663,8 +715,8 @@ For X11 something like ~/.xinitrc should work.\n" (require 'magit-imenu) (require 'magit-bookmark))) -(eval-after-load 'bookmark - '(require 'magit-bookmark)) +(with-eval-after-load 'bookmark + (require 'magit-bookmark)) (if after-init-time (progn (magit-startup-asserts) diff --git a/lisp/magit/magit.info b/lisp/magit/magit.info index 6c9943dd..353f80cd 100644 --- a/lisp/magit/magit.info +++ b/lisp/magit/magit.info @@ -1,6 +1,6 @@ -This is magit.info, produced by makeinfo version 6.5 from magit.texi. +This is magit.info, produced by makeinfo version 6.7 from magit.texi. - Copyright (C) 2015-2021 Jonas Bernoulli + Copyright (C) 2015-2022 Jonas Bernoulli You can redistribute this document and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -20,172 +20,178 @@ END-INFO-DIR-ENTRY  Indirect: magit.info-1: 754 -magit.info-2: 301793 +magit.info-2: 301526  Tag Table: (Indirect) Node: Top754 -Node: Introduction6512 -Node: Installation11235 -Node: Installing from Melpa11565 -Node: Installing from the Git Repository12638 -Node: Post-Installation Tasks15370 -Node: Getting Started16655 -Node: Interface Concepts21895 -Node: Modes and Buffers22256 -Node: Switching Buffers24005 -Node: Naming Buffers28756 -Node: Quitting Windows32063 -Node: Automatic Refreshing of Magit Buffers33809 -Node: Automatic Saving of File-Visiting Buffers36661 -Node: Automatic Reverting of File-Visiting Buffers37846 -Node: Risk of Reverting Automatically42841 -Node: Sections45223 -Node: Section Movement46149 -Node: Section Visibility51059 -Node: Section Hooks57136 -Node: Section Types and Values59543 -Node: Section Options60846 -Node: Transient Commands61318 -Node: Transient Arguments and Buffer Variables62555 -Node: Completion Confirmation and the Selection69573 -Node: Action Confirmation70017 -Node: Completion and Confirmation77833 -Node: The Selection81019 -Node: The hunk-internal region83918 -Node: Support for Completion Frameworks85007 -Node: Additional Completion Options89914 -Node: Running Git90513 -Node: Viewing Git Output90786 -Node: Git Process Status91919 -Node: Running Git Manually92884 -Node: Git Executable95354 -Node: Global Git Arguments97636 -Node: Inspecting98442 -Node: Status Buffer99599 -Node: Status Sections103589 -Node: Status Header Sections109141 -Node: Status Module Sections111771 -Node: Status Options114276 -Node: Repository List115745 -Node: Logging118783 -Node: Refreshing Logs121344 -Node: Log Buffer122790 -Node: Log Margin126646 -Node: Select from Log129825 -Node: Reflog132050 -Node: Cherries133707 -Node: Diffing135555 -Node: Refreshing Diffs138634 -Node: Commands Available in Diffs142213 -Node: Diff Options144749 -Node: Revision Buffer149787 -Node: Ediffing153117 -Node: References Buffer156765 -Node: References Sections167285 -Node: Bisecting168146 -Node: Visiting Files and Blobs170498 -Node: General-Purpose Visit Commands170968 -Node: Visiting Files and Blobs from a Diff171924 -Node: Blaming175383 -Node: Manipulating181724 -Node: Creating Repository182066 -Node: Cloning Repository182621 -Node: Staging and Unstaging188026 -Node: Staging from File-Visiting Buffers192109 -Node: Applying193277 -Node: Committing195170 -Node: Initiating a Commit195753 -Node: Editing Commit Messages199138 -Node: Using the Revision Stack201941 -Node: Commit Pseudo Headers204992 -Node: Commit Mode and Hooks206328 -Node: Commit Message Conventions209266 -Node: Branching211394 -Node: The Two Remotes211620 -Node: Branch Commands214273 -Node: Branch Git Variables226654 -Node: Auxiliary Branch Commands232045 -Node: Merging233163 -Node: Resolving Conflicts237171 -Node: Rebasing242172 -Node: Editing Rebase Sequences247031 -Node: Information About In-Progress Rebase251359 -Ref: Information About In-Progress Rebase-Footnote-1260241 -Node: Cherry Picking260837 -Node: Reverting265168 -Node: Resetting266617 -Node: Stashing268483 -Node: Transferring273184 -Node: Remotes273406 -Node: Remote Commands273558 -Node: Remote Git Variables277639 -Node: Fetching278918 -Node: Pulling281405 -Node: Pushing282451 -Node: Plain Patches286204 -Node: Maildir Patches287695 -Node: Miscellaneous289209 -Node: Tagging289523 -Node: Notes291440 -Node: Submodules293812 -Node: Listing Submodules294030 -Node: Submodule Transient295436 -Node: Subtree297958 -Node: Worktree299934 -Node: Common Commands301793 -Node: Wip Modes303916 -Node: Wip Graph308847 -Node: Legacy Wip Modes311161 -Node: Commands for Buffers Visiting Files314056 -Node: Minor Mode for Buffers Visiting Blobs319678 -Node: Customizing320489 -Node: Per-Repository Configuration322085 -Node: Essential Settings324340 -Node: Safety324685 -Node: Performance326446 -Node: Microsoft Windows Performance333614 -Node: MacOS Performance334805 -Ref: MacOS Performance-Footnote-1335982 -Node: Default Bindings336064 -Node: Plumbing337919 -Node: Calling Git338748 -Node: Getting a Value from Git340273 -Node: Calling Git for Effect343359 -Node: Section Plumbing349881 -Node: Creating Sections350109 -Node: Section Selection354009 -Node: Matching Sections355808 -Node: Refreshing Buffers361781 -Node: Conventions364929 -Node: Theming Faces365121 -Node: FAQ373236 -Node: FAQ - How to ...?373678 -Node: How to pronounce Magit?374091 -Node: How to show git's output?374893 -Node: How to install the gitman info manual?375679 -Node: How to show diffs for gpg-encrypted files?376649 -Node: How does branching and pushing work?377245 -Node: Can Magit be used as ediff-version-control-package?377608 -Node: Should I disable VC?379626 -Node: FAQ - Issues and Errors380244 -Node: Magit is slow381140 -Node: I changed several thousand files at once and now Magit is unusable381354 -Node: I am having problems committing382083 -Node: I am using MS Windows and cannot push with Magit382564 -Node: I am using OS X and SOMETHING works in shell but not in Magit383181 -Node: Expanding a file to show the diff causes it to disappear384012 -Node: Point is wrong in the COMMIT_EDITMSG buffer384593 -Node: The mode-line information isn't always up-to-date385639 -Node: A branch and tag sharing the same name breaks SOMETHING386702 -Node: My Git hooks work on the command-line but not inside Magit387588 -Node: git-commit-mode isn't used when committing from the command-line388434 -Node: Point ends up inside invisible text when jumping to a file-visiting buffer390705 -Node: Debugging Tools391503 -Node: Keystroke Index393682 -Node: Command Index427788 -Node: Function Index464927 -Node: Variable Index481198 +Node: Introduction6610 +Node: Installation11326 +Node: Installing from Melpa11656 +Node: Installing from the Git Repository12729 +Node: Post-Installation Tasks15461 +Node: Getting Started16746 +Node: Interface Concepts21986 +Node: Modes and Buffers22347 +Node: Switching Buffers24058 +Node: Naming Buffers28797 +Node: Quitting Windows32100 +Node: Automatic Refreshing of Magit Buffers33838 +Node: Automatic Saving of File-Visiting Buffers36719 +Node: Automatic Reverting of File-Visiting Buffers37903 +Node: Risk of Reverting Automatically42888 +Node: Sections45270 +Node: Section Movement46196 +Node: Section Visibility51070 +Node: Section Hooks57085 +Node: Section Types and Values59491 +Node: Section Options60906 +Node: Transient Commands61377 +Node: Transient Arguments and Buffer Variables62609 +Node: Completion Confirmation and the Selection69620 +Node: Action Confirmation70064 +Node: Completion and Confirmation77916 +Node: The Selection81101 +Node: The hunk-internal region83999 +Node: Support for Completion Frameworks85088 +Node: Additional Completion Options89991 +Node: Running Git90589 +Node: Viewing Git Output90862 +Node: Git Process Status92956 +Node: Running Git Manually93921 +Node: Git Executable96354 +Node: Global Git Arguments99362 +Node: Inspecting100167 +Node: Status Buffer101324 +Node: Status Sections106334 +Node: Status Header Sections111861 +Node: Status Module Sections114480 +Node: Status Options116977 +Node: Repository List118440 +Node: Logging121766 +Node: Refreshing Logs124292 +Node: Log Buffer125713 +Node: Log Margin129911 +Node: Select from Log133064 +Node: Reflog135274 +Node: Cherries136911 +Node: Diffing138749 +Node: Refreshing Diffs141783 +Node: Commands Available in Diffs145292 +Node: Diff Options147804 +Node: Revision Buffer153268 +Node: Ediffing156588 +Node: References Buffer160183 +Node: References Sections170777 +Node: Bisecting171634 +Node: Visiting Files and Blobs173945 +Node: General-Purpose Visit Commands174415 +Node: Visiting Files and Blobs from a Diff175368 +Node: Blaming178812 +Node: Manipulating184949 +Node: Creating Repository185291 +Node: Cloning Repository185828 +Node: Staging and Unstaging191188 +Node: Staging from File-Visiting Buffers195169 +Node: Applying196275 +Node: Committing198348 +Node: Initiating a Commit198931 +Node: Editing Commit Messages204120 +Node: Using the Revision Stack206893 +Node: Commit Pseudo Headers209938 +Node: Commit Mode and Hooks211233 +Node: Commit Message Conventions214161 +Node: Branching216284 +Node: The Two Remotes216510 +Node: Branch Commands219163 +Node: Branch Git Variables231708 +Node: Auxiliary Branch Commands237081 +Node: Merging238197 +Node: Resolving Conflicts242155 +Node: Rebasing247526 +Node: Editing Rebase Sequences252315 +Node: Information About In-Progress Rebase256529 +Ref: Information About In-Progress Rebase-Footnote-1265411 +Node: Cherry Picking266007 +Node: Reverting270341 +Node: Resetting271760 +Node: Stashing273586 +Node: Transferring278197 +Node: Remotes278419 +Node: Remote Commands278571 +Node: Remote Git Variables282610 +Node: Fetching283884 +Node: Pulling286330 +Node: Pushing287356 +Node: Plain Patches291647 +Node: Maildir Patches293118 +Node: Miscellaneous294597 +Node: Tagging294922 +Node: Notes296815 +Node: Submodules299150 +Node: Listing Submodules299368 +Node: Submodule Transient301526 +Node: Subtree304003 +Node: Worktree305934 +Node: Bundle307000 +Node: Common Commands307367 +Node: Wip Modes309995 +Node: Wip Graph314886 +Node: Legacy Wip Modes317199 +Node: Commands for Buffers Visiting Files320086 +Node: Minor Mode for Buffers Visiting Blobs325642 +Node: Customizing326440 +Node: Per-Repository Configuration328036 +Node: Essential Settings330290 +Node: Safety330635 +Node: Performance332396 +Ref: Log Performance335425 +Ref: Diff Performance336735 +Ref: Refs Buffer Performance338076 +Ref: Committing Performance338651 +Node: Microsoft Windows Performance339564 +Node: MacOS Performance340755 +Ref: MacOS Performance-Footnote-1341460 +Node: Default Bindings341542 +Node: Plumbing343783 +Node: Calling Git344612 +Node: Getting a Value from Git346137 +Node: Calling Git for Effect349865 +Node: Section Plumbing355759 +Node: Creating Sections355987 +Node: Section Selection359883 +Node: Matching Sections361679 +Node: Refreshing Buffers367600 +Node: Conventions370744 +Node: Theming Faces370936 +Node: FAQ379041 +Node: FAQ - How to ...?379483 +Node: How to pronounce Magit?379896 +Node: How to show git's output?380698 +Node: How to install the gitman info manual?381484 +Node: How to show diffs for gpg-encrypted files?382454 +Node: How does branching and pushing work?383050 +Node: Can Magit be used as ediff-version-control-package?383413 +Node: Should I disable VC?385431 +Node: FAQ - Issues and Errors386049 +Node: Magit is slow387050 +Node: I changed several thousand files at once and now Magit is unusable387264 +Node: I am having problems committing387993 +Node: I am using MS Windows and cannot push with Magit388474 +Node: I am using OS X and SOMETHING works in shell but not in Magit389091 +Node: Expanding a file to show the diff causes it to disappear389922 +Node: Point is wrong in the COMMIT_EDITMSG buffer390503 +Node: The mode-line information isn't always up-to-date391549 +Node: A branch and tag sharing the same name breaks SOMETHING392612 +Node: My Git hooks work on the command-line but not inside Magit393498 +Node: git-commit-mode isn't used when committing from the command-line394344 +Node: Point ends up inside invisible text when jumping to a file-visiting buffer396615 +Node: I am unable to stage when using Tramp from MS Windows397475 +Node: I am no longer able to save popup defaults398382 +Node: Debugging Tools399342 +Node: Keystroke Index401346 +Node: Function and Command Index434443 +Node: Variable Index485169  End Tag Table diff --git a/lisp/magit/magit.info-1 b/lisp/magit/magit.info-1 index f236c028..97bd1d16 100644 --- a/lisp/magit/magit.info-1 +++ b/lisp/magit/magit.info-1 @@ -1,6 +1,6 @@ -This is magit.info, produced by makeinfo version 6.5 from magit.texi. +This is magit.info, produced by makeinfo version 6.7 from magit.texi. - Copyright (C) 2015-2021 Jonas Bernoulli + Copyright (C) 2015-2022 Jonas Bernoulli You can redistribute this document and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -31,9 +31,9 @@ to perform almost all of their daily version control tasks directly from within Emacs. While many fine Git clients exist, only Magit and Git itself deserve to be called porcelains. -This manual is for Magit version 2.90.1 (v2.90.1-1138-gd583ea35d+1). +This manual is for Magit version v3.3.0-73-g03f495f35+1. - Copyright (C) 2015-2021 Jonas Bernoulli + Copyright (C) 2015-2022 Jonas Bernoulli You can redistribute this document and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -60,8 +60,7 @@ This manual is for Magit version 2.90.1 (v2.90.1-1138-gd583ea35d+1). * FAQ:: * Debugging Tools:: * Keystroke Index:: -* Command Index:: -* Function Index:: +* Function and Command Index:: * Variable Index:: — The Detailed Node Listing — @@ -235,6 +234,7 @@ Miscellaneous * Submodules:: * Subtree:: * Worktree:: +* Bundle:: * Common Commands:: * Wip Modes:: * Commands for Buffers Visiting Files:: @@ -319,6 +319,8 @@ FAQ - Issues and Errors * My Git hooks work on the command-line but not inside Magit:: * git-commit-mode isn't used when committing from the command-line:: * Point ends up inside invisible text when jumping to a file-visiting buffer:: +* I am unable to stage when using Tramp from MS Windows:: +* I am no longer able to save popup defaults:: @@ -375,7 +377,7 @@ on Magit earlier. While one has to know the basic features of Emacs to be able to make full use of Magit, acquiring just enough Emacs skills doesn’t take long and is worth it, even for users who prefer other editors. Vim users are -advised to give Evil (https://bitbucket.org/lyro/evil/wiki/Home), the +advised to give Evil (https://github.com/emacs-evil/evil), the "Extensible VI Layer for Emacs", and Spacemacs (https://github.com/syl20bnr/spacemacs), an "Emacs starter-kit focused on Evil" a try. @@ -695,8 +697,7 @@ the user invokes Git commands, or creates or visits other buffers. In this manual we often speak about "Magit buffers". By that we mean buffers whose major-modes derive from ‘magit-mode’. -‘M-x magit-toggle-buffer-lock’ (‘magit-toggle-buffer-lock’) - +‘M-x magit-toggle-buffer-lock’ This command locks the current buffer to its value or if the buffer is already locked, then it unlocks it. @@ -730,7 +731,6 @@ File: magit.info, Node: Switching Buffers, Next: Naming Buffers, Up: Modes an ----------------------- -- Function: magit-display-buffer buffer &optional display-function - This function is a wrapper around ‘display-buffer’ and is used to display any Magit buffer. It displays BUFFER in some window and, unlike ‘display-buffer’, also selects that window, provided @@ -742,7 +742,6 @@ File: magit.info, Node: Switching Buffers, Next: Naming Buffers, Up: Modes an specified by ‘magit-display-buffer-function’ is used. -- Variable: magit-display-buffer-noselect - When this is non-nil, then ‘magit-display-buffer’ only displays the buffer but forgoes also selecting the window. This variable should not be set globally, it is only intended to be let-bound, by code @@ -751,7 +750,6 @@ File: magit.info, Node: Switching Buffers, Next: Naming Buffers, Up: Modes an the log buffer. -- User Option: magit-display-buffer-function - The function specified here is called by ‘magit-display-buffer’ with one argument, a buffer, to actually display that buffer. This function should call ‘display-buffer’ with that buffer as first and @@ -769,7 +767,6 @@ File: magit.info, Node: Switching Buffers, Next: Naming Buffers, Up: Modes an To learn about display actions, see *note (elisp)Choosing Window::. -- Function: magit-display-buffer-traditional buffer - This function is the current default value of the option ‘magit-display-buffer-function’. Before that option and this function were added, the behavior was hard-coded in many places all @@ -777,19 +774,16 @@ File: magit.info, Node: Switching Buffers, Next: Naming Buffers, Up: Modes an function (except for the "noselect" special case mentioned above). -- Function: magit-display-buffer-same-window-except-diff-v1 - This function displays most buffers in the currently selected window. If a buffer’s mode derives from ‘magit-diff-mode’ or ‘magit-process-mode’, it is displayed in another window. -- Function: magit-display-buffer-fullframe-status-v1 - This function fills the entire frame when displaying a status buffer. Otherwise, it behaves like ‘magit-display-buffer-traditional’. -- Function: magit-display-buffer-fullframe-status-topleft-v1 - This function fills the entire frame when displaying a status buffer. It behaves like ‘magit-display-buffer-fullframe-status-v1’ except that it displays buffers that derive from ‘magit-diff-mode’ @@ -799,7 +793,6 @@ File: magit.info, Node: Switching Buffers, Next: Naming Buffers, Up: Modes an ‘magit-display-buffer-traditional’ were in use. -- Function: magit-display-buffer-fullcolumn-most-v1 - This function displays most buffers so that they fill the entire height of the frame. However, the buffer is displayed in another window if (1) the buffer’s mode derives from ‘magit-process-mode’, @@ -808,23 +801,19 @@ File: magit.info, Node: Switching Buffers, Next: Naming Buffers, Up: Modes an or ‘magit-cherry-mode’. -- User Option: magit-pre-display-buffer-hook - This hook is run by ‘magit-display-buffer’ before displaying the buffer. -- Function: magit-save-window-configuration - This function saves the current window configuration. Later when the buffer is buried, it may be restored by ‘magit-restore-window-configuration’. -- User Option: magit-post-display-buffer-hook - This hook is run by ‘magit-display-buffer’ after displaying the buffer. -- Function: magit-maybe-set-dedicated - This function remembers if a new window had to be created to display the buffer, or whether an existing window was reused. This information is later used by ‘magit-mode-quit-window’, to determine @@ -838,7 +827,6 @@ File: magit.info, Node: Naming Buffers, Next: Quitting Windows, Prev: Switchi -------------------- -- User Option: magit-generate-buffer-name-function - The function used to generate the names of Magit buffers. Such a function should take the options @@ -849,7 +837,6 @@ File: magit.info, Node: Naming Buffers, Next: Quitting Windows, Prev: Switchi its own doc-string should describe the additions. -- Function: magit-generate-buffer-name-default-function mode - This function returns a buffer name suitable for a buffer whose major-mode is MODE and which shows information about the repository in which ‘default-directory’ is located. @@ -859,7 +846,6 @@ File: magit.info, Node: Naming Buffers, Next: Quitting Windows, Prev: Switchi also respects the option ‘magit-uniquify-buffer-names’. -- User Option: magit-buffer-name-format - The format string used to name Magit buffers. At least the following %-sequences are supported: @@ -906,7 +892,6 @@ File: magit.info, Node: Naming Buffers, Next: Quitting Windows, Prev: Switchi obsolete ‘%T’). See issue #2841. -- User Option: magit-uniquify-buffer-names - This option controls whether the names of Magit buffers are uniquified. If the names are not being uniquified, then they contain the full path of the top-level of the working tree of the @@ -924,8 +909,7 @@ File: magit.info, Node: Quitting Windows, Next: Automatic Refreshing of Magit 4.1.3 Quitting Windows ---------------------- -‘q’ (‘magit-mode-bury-buffer’) - +‘q’ (‘magit-mode-bury-buffer’) This command buries the current Magit buffer. With a prefix argument, it instead kills the buffer. With a double @@ -933,7 +917,6 @@ File: magit.info, Node: Quitting Windows, Next: Automatic Refreshing of Magit the current project. -- User Option: magit-bury-buffer-function - The function used to actually bury or kill the current buffer. ‘magit-mode-bury-buffer’ calls this function with one argument. If @@ -942,7 +925,6 @@ File: magit.info, Node: Quitting Windows, Next: Automatic Refreshing of Magit currently is ‘magit-restore-window-configuration’. -- Function: magit-restore-window-configuration kill-buffer - Bury or kill the current buffer using ‘quit-window’, which is called with KILL-BUFFER as first and the selected window as second argument. @@ -953,7 +935,6 @@ File: magit.info, Node: Quitting Windows, Next: Automatic Refreshing of Magit are being displayed in the selected frame. -- Function: magit-mode-quit-window kill-buffer - Bury or kill the current buffer using ‘quit-window’, which is called with KILL-BUFFER as first and the selected window as second argument. @@ -974,7 +955,8 @@ are refreshed. The status buffer can be automatically refreshed whenever a buffer is saved to a file inside the respective repository by adding a hook, like so: - (add-hook 'after-save-hook 'magit-after-save-refresh-status t) + (with-eval-after-load 'magit-mode + (add-hook 'after-save-hook 'magit-after-save-refresh-status t)) Automatically refreshing Magit buffers ensures that the displayed information is up-to-date most of the time but can lead to a noticeable @@ -986,8 +968,7 @@ undesirable. that weren’t current during the last refresh and after changes were made to the repository outside of Magit. -‘g’ (‘magit-refresh’) - +‘g’ (‘magit-refresh’) This command refreshes the current buffer if its major mode derives from ‘magit-mode’ as well as the corresponding status buffer. @@ -995,8 +976,7 @@ to the repository outside of Magit. reverts all unmodified buffers that visit files being tracked in the current repository. -‘G’ (‘magit-refresh-all’) - +‘G’ (‘magit-refresh-all’) This command refreshes all Magit buffers belonging to the current repository and also reverts all unmodified buffers that visit files being tracked in the current repository. @@ -1005,13 +985,11 @@ to the repository outside of Magit. ‘magit-revert-buffers’ is nil. -- User Option: magit-refresh-buffer-hook - This hook is run in each Magit buffer that was refreshed during the current refresh - normally the current buffer and the status buffer. -- User Option: magit-refresh-status-buffer - When this option is non-nil, then the status buffer is automatically refreshed after running git for side-effects, in addition to the current Magit buffer, which is always refreshed @@ -1021,7 +999,6 @@ to the repository outside of Magit. performance. -- Function: magit-after-save-refresh-status - This function is intended to be added to ‘after-save-hook’. After doing that the corresponding status buffer is refreshed whenever a buffer is saved to a file inside a repository. @@ -1045,7 +1022,6 @@ or after outside changes, type ‘g’ (‘magit-refresh’) to save and refresh explicitly. -- User Option: magit-save-repository-buffers - This option controls whether file-visiting buffers are saved before certain events. @@ -1074,12 +1050,10 @@ the buffer, then you would have to type ‘M-x revert-buffer RET RET’ in the visiting buffer before you could continue making changes. -- User Option: magit-auto-revert-mode - When this mode is enabled, then buffers that visit tracked files are automatically reverted after the visited files change on disk. -- User Option: global-auto-revert-mode - When this mode is enabled, then any file-visiting buffer is automatically reverted after the visited file changes on disk. @@ -1089,7 +1063,6 @@ the visiting buffer before you could continue making changes. enable this mode _instead of_ ‘magit-auto-revert-mode’. -- User Option: magit-auto-revert-immediately - This option controls whether Magit reverts buffers immediately. If this is non-nil and either ‘global-auto-revert-mode’ or @@ -1106,20 +1079,17 @@ the visiting buffer before you could continue making changes. seconds of user inactivity. That is not desirable. -- User Option: auto-revert-use-notify - This option controls whether file notification functions should be used. Note that this variable unfortunately defaults to ‘t’ even on systems on which file notifications cannot be used. -- User Option: magit-auto-revert-tracked-only - This option controls whether ‘magit-auto-revert-mode’ only reverts tracked files or all files that are located inside Git repositories, including untracked files and files located inside Git’s control directory. -- User Option: auto-revert-mode - The global mode ‘magit-auto-revert-mode’ works by turning on this local mode in the appropriate buffers (but ‘global-auto-revert-mode’ is implemented differently). You can @@ -1128,17 +1098,14 @@ the visiting buffer before you could continue making changes. tracked or vice-versa. -- User Option: auto-revert-stop-on-user-input - This option controls whether the arrival of user input suspends the automatic reverts for ‘auto-revert-interval’ seconds. -- User Option: auto-revert-interval - This option controls how many seconds Emacs waits for before resuming suspended reverts. -- User Option: auto-revert-buffer-list-filter - This option specifies an additional filter used by ‘auto-revert-buffers’ to determine whether a buffer should be reverted or not. @@ -1160,7 +1127,6 @@ the visiting buffer before you could continue making changes. enabled. -- User Option: auto-revert-verbose - This option controls whether Emacs reports when a buffer has been reverted. @@ -1253,29 +1219,24 @@ To move within a section use the usual keys (‘C-p’, ‘C-n’, ‘C-b’, etc), whose global bindings are not shadowed. To move to another section use the following commands. -‘p’ (‘magit-section-backward’) - +‘p’ (‘magit-section-backward’) When not at the beginning of a section, then move to the beginning of the current section. At the beginning of a section, instead move to the beginning of the previous visible section. -‘n’ (‘magit-section-forward’) - +‘n’ (‘magit-section-forward’) Move to the beginning of the next visible section. -‘M-p’ (‘magit-section-backward-siblings’) - +‘M-p’ (‘magit-section-backward-siblings’) Move to the beginning of the previous sibling section. If there is no previous sibling section, then move to the parent section instead. -‘M-n’ (‘magit-section-forward-siblings’) - +‘M-n’ (‘magit-section-forward-siblings’) Move to the beginning of the next sibling section. If there is no next sibling section, then move to the parent section instead. -‘^’ (‘magit-section-up’) - +‘^’ (‘magit-section-up’) Move to the beginning of the parent of the current section. The above commands all call the hook ‘magit-section-movement-hook’. @@ -1290,12 +1251,10 @@ remove function that haven’t even been added yet, for example: 'magit-hunk-set-window-start)) -- Variable: magit-section-movement-hook - This hook is run by all of the above movement commands, after arriving at the destination. -- Function: magit-hunk-set-window-start - This hook function ensures that the beginning of the current section is visible, provided it is a ‘hunk’ section. Otherwise, it does nothing. @@ -1303,14 +1262,12 @@ remove function that haven’t even been added yet, for example: Loading ‘magit-diff’ adds this function to the hook. -- Function: magit-section-set-window-start - This hook function ensures that the beginning of the current section is visible, regardless of the section’s type. If you add this to ‘magit-section-movement-hook’, then you must remove the hunk-only variant in turn. -- Function: magit-log-maybe-show-more-commits - This hook function only has an effect in log buffers, and ‘point’ is on the "show more" section. If that is the case, then it doubles the number of commits that are being shown. @@ -1318,7 +1275,6 @@ remove function that haven’t even been added yet, for example: Loading ‘magit-log’ adds this function to the hook. -- Function: magit-log-maybe-update-revision-buffer - When moving inside a log buffer, then this function updates the revision buffer, provided it is already being displayed in another window of the same frame. @@ -1326,37 +1282,31 @@ remove function that haven’t even been added yet, for example: Loading ‘magit-log’ adds this function to the hook. -- Function: magit-log-maybe-update-blob-buffer - When moving inside a log buffer and another window of the same frame displays a blob buffer, then this function instead displays the blob buffer for the commit at point in that window. -- Function: magit-status-maybe-update-revision-buffer - When moving inside a status buffer, then this function updates the revision buffer, provided it is already being displayed in another window of the same frame. -- Function: magit-status-maybe-update-stash-buffer - When moving inside a status buffer, then this function updates the stash buffer, provided it is already being displayed in another window of the same frame. -- Function: magit-status-maybe-update-blob-buffer - When moving inside a status buffer and another window of the same frame displays a blob buffer, then this function instead displays the blob buffer for the commit at point in that window. -- Function: magit-stashes-maybe-update-stash-buffer - When moving inside a buffer listing stashes, then this function updates the stash buffer, provided it is already being displayed in another window of the same frame. -- User Option: magit-update-other-window-delay - Delay before automatically updating the other window. When moving around in certain buffers, then certain other buffers, @@ -1379,35 +1329,29 @@ File: magit.info, Node: Section Visibility, Next: Section Hooks, Prev: Sectio Magit provides many commands for changing the visibility of sections, but all you need to get started are the next two. -‘TAB’ (‘magit-section-toggle’) - +‘’ (‘magit-section-toggle’) Toggle the visibility of the body of the current section. -‘C-’ (‘magit-section-cycle’) - +‘C-’ (‘magit-section-cycle’) Cycle the visibility of current section and its children. -‘M-’ (‘magit-section-cycle-diffs’) - +‘M-’ (‘magit-section-cycle-diffs’) Cycle the visibility of diff-related sections in the current buffer. -‘S-’ (‘magit-section-cycle-global’) - +‘S-’ (‘magit-section-cycle-global’) Cycle the visibility of all sections in the current buffer. -‘1’ (‘magit-section-show-level-1’) -‘2’ (‘magit-section-show-level-2’) -‘3’ (‘magit-section-show-level-3’) -‘4’ (‘magit-section-show-level-4’) - +‘1’ (‘magit-section-show-level-1’) +‘2’ (‘magit-section-show-level-2’) +‘3’ (‘magit-section-show-level-3’) +‘4’ (‘magit-section-show-level-4’) Show sections surrounding the current section up to level N. -‘M-1’ (‘magit-section-show-level-1-all’) -‘M-2’ (‘magit-section-show-level-2-all’) -‘M-3’ (‘magit-section-show-level-3-all’) -‘M-4’ (‘magit-section-show-level-4-all’) - +‘M-1’ (‘magit-section-show-level-1-all’) +‘M-2’ (‘magit-section-show-level-2-all’) +‘M-3’ (‘magit-section-show-level-3-all’) +‘M-4’ (‘magit-section-show-level-4-all’) Show all sections up to level N. Some functions, which are used to implement the above commands, are @@ -1416,30 +1360,24 @@ these commands, as they are generally perceived to be much less useful. But your mileage may vary. -- Command: magit-section-show - Show the body of the current section. -- Command: magit-section-hide - Hide the body of the current section. -- Command: magit-section-show-headings - Recursively show headings of children of the current section. Only show the headings. Previously shown text-only bodies are hidden. -- Command: magit-section-show-children - Recursively show the bodies of children of the current section. With a prefix argument show children down to the level of the current section, and hide deeper children. -- Command: magit-section-hide-children - Recursively hide the bodies of children of the current section. -- Command: magit-section-toggle-children - Toggle visibility of bodies of children of the current section. When a buffer is first created then some sections are shown expanded @@ -1449,7 +1387,6 @@ certain sections can also be overwritten using the hook ‘magit-section-set-visibility-hook’. -- User Option: magit-section-initial-visibility-alist - This options can be used to override the initial visibility of sections. In the future it will also be used to define the defaults, but currently a section’s default is still hardcoded. @@ -1466,7 +1403,6 @@ certain sections can also be overwritten using the hook Wildcards can be used, see ‘magit-section-match’. -- User Option: magit-section-cache-visibility - This option controls for which sections the previous visibility state should be restored if a section disappears and later appears again. The value is a boolean or a list of section types. If t, @@ -1477,7 +1413,6 @@ certain sections can also be overwritten using the hook is a member of ‘magit-section-set-visibility-hook’. -- Variable: magit-section-set-visibility-hook - This hook is run when first creating a buffer and also when refreshing an existing buffer, and is used to determine the visibility of the section currently being inserted. @@ -1495,7 +1430,6 @@ certain sections can also be overwritten using the hook should immediately return ‘nil’. -- User Option: magit-section-visibility-indicator - This option controls whether and how to indicate that a section can be expanded/collapsed. @@ -1545,7 +1479,6 @@ this manual along with the appropriate "section inserter functions". -- Function: magit-add-section-hook hook function &optional at append local - Add the function FUNCTION to the value of section hook HOOK. Add FUNCTION at the beginning of the hook list unless optional @@ -1586,10 +1519,14 @@ section of type ‘file’, for example, is a file name. Users usually do not have to worry about a section’s type and value, but knowing them can be handy at times. -‘M-x magit-describe-section-briefly’ (‘magit-describe-section-briefly’) +‘H’ (‘magit-describe-section’) + This command shows information about the section at point in a + separate buffer. - Show information about the section at point in the echo area, as - "#". + -- Command: magit-describe-section-briefly + This command shows information about the section at point in the + echo area, as ‘#’. Many commands behave differently depending on the type of the section at point and/or somehow consume the value of that section. But that is @@ -1612,7 +1549,6 @@ This section describes options that have an effect on more than just a certain type of sections. As you can see there are not many of those. -- User Option: magit-section-show-child-count - Whether to append the number of children to section headings. This only affects sections that could benefit from this information. @@ -1634,8 +1570,7 @@ library ‘magit-key-mode’. Transient is documented in *note (transient)Top::. -‘C-c C-c’ (‘magit-dispatch’) - +‘C-c C-c’ (‘magit-dispatch’) This transient prefix command binds most of Magit’s other prefix commands as suffix commands and displays them in a temporary buffer until one of them is invoked. Invoking such a sub-prefix causes @@ -1712,7 +1647,6 @@ arguments are reset to the default. Not cool; so Magit does not do that by default. -- User Option: magit-prefix-use-buffer-arguments - This option controls whether the infix arguments initially shown in certain transient prefix commands are based on the arguments that are currently in effect in the buffer that their suffixes update. @@ -1721,7 +1655,6 @@ by default. affected by this option. -- User Option: magit-direct-use-buffer-arguments - This option controls whether certain commands, when invoked directly (i.e. not as the suffix of a transient prefix command), use the arguments that are currently active in the buffer that they @@ -1733,19 +1666,16 @@ Valid values for both of the above options are: • ‘always’: Always use the set of arguments that is currently active in the respective buffer, provided that buffer exists of course. - • ‘selected’ or ‘t’: Use the set of arguments from the respective buffer, but only if it is displayed in a window of the current frame. This is the default for both variables. - • ‘current’: Use the set of arguments from the respective buffer, but only if it is the current buffer. - • ‘never’: Never use the set of arguments from the respective buffer. I am afraid it gets more complicated still: - • The global diff and log arguments are set for each support mode + • The global diff and log arguments are set for each supported mode individually. The diff arguments for example have different values in ‘magit-diff-mode’, ‘magit-revision-mode’, ‘magit-merge-preview-mode’ and ‘magit-status-mode’ buffers. @@ -1754,7 +1684,7 @@ I am afraid it gets more complicated still: • When ‘magit-show-commit’ is invoked directly from a log buffer, then the file filter is picked up from that buffer, not from the - revision buffer and or the mode’s global diff arguments. + revision buffer or the mode’s global diff arguments. • Even though they are suffixes of the diff prefix ‘magit-show-commit’ and ‘magit-stash-show’ do not use the diff @@ -1815,7 +1745,6 @@ specific set of actions, the next section explains another way of telling Magit to ask fewer questions. -- User Option: magit-no-confirm - The value of this option is a list of symbols, representing actions that do not have to be confirmed by the user before being carried out. @@ -1910,13 +1839,13 @@ telling Magit to ask fewer questions. • Publishing: - ‘set-and-push’ When pushing to the upstream or the push-remote - and that isn’t actually configured yet, then the user can - first set the target. If s/he confirms the default too - quickly, then s/he might end up pushing to the wrong branch - and if the remote repository is configured to disallow fixing - such mistakes, then that can be quite embarrassing and - annoying. + • ‘set-and-push’ When pushing to the upstream or the + push-remote and that isn’t actually configured yet, then + the user can first set the target. If s/he confirms the + default too quickly, then s/he might end up pushing to + the wrong branch and if the remote repository is + configured to disallow fixing such mistakes, then that + can be quite embarrassing and annoying. • Edit published history: @@ -2007,7 +1936,6 @@ also not affected by this option and are described in the previous section. -- User Option: magit-dwim-selection - This option can be used to tell certain commands to use the thing at point instead of asking the user to select a candidate to act on, with or without confirmation. @@ -2083,7 +2011,6 @@ current section always is part of the selection, then that cannot happen. -- Variable: magit-keep-region-overlay - This variable controls whether the region is visualized as usual even when a valid Magit selection or a hunk-internal region exists. See the doc-string for more information. @@ -2140,7 +2067,6 @@ You will also have to install the ‘ido-completing-read+’ package and use ‘magit-ido-completing-read’ as ‘magit-completing-read-function’. -- User Option: magit-completing-read-function - The value of this variable is the low-level function used to perform completion by code that uses ‘magit-completing-read’ (as opposed to the built-in ‘completing-read’). @@ -2156,13 +2082,11 @@ You will also have to install the ‘ido-completing-read+’ package and use -- Function: magit-builtin-completing-read prompt choices &optional predicate require-match initial-input hist def - This function performs completion using the built-in ‘completing-read’ and does some additional magit-specific work. -- Function: magit-ido-completing-read prompt choices &optional predicate require-match initial-input hist def - This function performs completion using ‘ido-completing-read+’ from the package by the same name (which you have to explicitly install) and does some additional magit-specific work. @@ -2174,7 +2098,6 @@ You will also have to install the ‘ido-completing-read+’ package and use -- Function: magit-completing-read prompt choices &optional predicate require-match initial-input hist def fallback - This is the function that Magit commands use when they need the user to select a single thing to act on. The arguments have the same meaning as for ‘completing-read’, except for FALLBACK, which @@ -2220,7 +2143,6 @@ File: magit.info, Node: Additional Completion Options, Prev: Support for Compl ----------------------------------- -- User Option: magit-list-refs-sortby - For many commands that read a ref or refs from the user, the value of this option can be used to control the order of the refs. Valid values include any key accepted by the ‘--sort’ flag of ‘git @@ -2257,23 +2179,42 @@ per-repository log buffer, which can be consulted using the The output/errors for up to ‘magit-process-log-max’ Git commands are retained. -‘$’ (‘magit-process’) - +‘$’ (‘magit-process’) This commands displays the process buffer for the current repository. Inside that buffer, the usual key bindings for navigating and showing sections are available. There is one additional command. -‘k’ (‘magit-process-kill’) - +‘k’ (‘magit-process-kill’) This command kills the process represented by the section at point. - -- User Option: magit-git-debug + -- Variable: magit-git-debug + This option controls whether additional reporting of git errors is + enabled. - When this is non-nil then the output of all calls to git are logged - in the process buffer. This is useful when debugging, otherwise it - just negatively affects performance. + Magit basically calls git for one of these two reasons: for + side-effects or to do something with its standard output. + + When git is run for side-effects then its output, including error + messages, go into the process buffer which is shown when using ‘$’. + + When git’s output is consumed in some way, then it would be too + expensive to also insert it into this buffer, but when this option + is non-nil and git returns with a non-zero exit status, then at + least its standard error is inserted into this buffer. + + This is only intended for debugging purposes. Do not enable this + permanently, that would negatively affect performance. + + -- Variable: magit-process-extreme-logging + This option controls whether ‘magit-process-file’ logs to the + ‘*Messages*’ buffer. + + Only intended for temporary use when you try to figure out how + Magit uses Git behind the scene. Output that normally goes to the + magit-process buffer continues to go there. Not all output goes to + either of these two buffers.  File: magit.info, Node: Git Process Status, Next: Running Git Manually, Prev: Viewing Git Output, Up: Running Git @@ -2311,21 +2252,20 @@ come in handy. Magit provides some commands for running arbitrary Git commands by typing them into the minibuffer, instead of having to switch to a shell. -‘!’ (‘magit-run’) - +‘!’ (‘magit-run’) This transient prefix command binds the following suffix commands and displays them in a temporary buffer until a suffix is invoked. -‘! !’ (‘magit-git-command-topdir’) - +‘! !’ (‘magit-git-command-topdir’) This command reads a command from the user and executes it in the top-level directory of the current working tree. The string "git " is used as initial input when prompting the user for the command. It can be removed to run another command. -‘! p’ (‘magit-git-command’) +‘:’ (‘magit-git-command’) +‘! p’ This command reads a command from the user and executes it in ‘default-directory’. With a prefix argument the command is executed in the top-level directory of the current working tree @@ -2334,39 +2274,32 @@ to a shell. The string "git " is used as initial input when prompting the user for the command. It can be removed to run another command. -‘! s’ (‘magit-shell-command-topdir’) - +‘! s’ (‘magit-shell-command-topdir’) This command reads a command from the user and executes it in the top-level directory of the current working tree. -‘! S’ (‘magit-shell-command’) - +‘! S’ (‘magit-shell-command’) This command reads a command from the user and executes it in ‘default-directory’. With a prefix argument the command is executed in the top-level directory of the current working tree instead. -- User Option: magit-shell-command-verbose-prompt - Whether the prompt, used by the above commands when reading a shell command, shows the directory in which it will be run. These suffix commands start external gui tools. -‘! k’ (‘magit-run-gitk’) - +‘! k’ (‘magit-run-gitk’) This command runs ‘gitk’ in the current repository. -‘! a’ (‘magit-run-gitk-all’) - +‘! a’ (‘magit-run-gitk-all’) This command runs ‘gitk --all’ in the current repository. -‘! b’ (‘magit-run-gitk-branches’) - +‘! b’ (‘magit-run-gitk-branches’) This command runs ‘gitk --branches’ in the current repository. -‘! g’ (‘magit-run-git-gui’) - +‘! g’ (‘magit-run-git-gui’) This command runs ‘git gui’ in the current repository.  @@ -2375,49 +2308,63 @@ File: magit.info, Node: Git Executable, Next: Global Git Arguments, Prev: Run 4.6.4 Git Executable -------------------- -Except on MS Windows, Magit defaults to running Git without specifying -the path to the git executable. Instead the first executable found by -Emacs on ‘exec-path’ is used (whose value in turn is set based on the -value of the environment variable ‘$PATH’ when Emacs was started). +When Magit calls Git, then it may do so using the absolute path to the +‘git’ executable, or using just its name. - This has the advantage that it continues to work even when using -Tramp to connect to a remote machine on which the executable is found in -a different place. The downside is that if you have multiple versions -of Git installed, then you might end up using another version than the -one you think you are using. + When running ‘git’ locally and the ‘system-type’ is ‘windows-nt’ (any +Windows version) or ‘darwin’ (macOS) then ‘magit-git-executable’ is set +to an absolute path when Magit is loaded. -‘M-x magit-version’ (‘magit-version’) + On Windows it is necessary to use an absolute path because Git comes +with several wrapper scripts for the actual ‘git’ binary, which are also +placed on ‘$PATH’, and using one of these wrappers instead of the binary +would degrade performance horribly. For some macOS users using just the +name of the executable also performs horribly, so we avoid doing that on +that platform as well. On other platforms, using just the name seems to +work just fine. + Using an absolute path when running ‘git’ on a remote machine over +Tramp, would be problematic to use an absolute path that is suitable on +the local machine, so a separate option is used to control the name or +path that is used on remote machines. + + -- User Option: magit-git-executable + The ‘git’ executable used by Magit on the local host. This should + be either the absolute path to the executable, or the string "git" + to let Emacs find the executable itself, using the standard + mechanism for doing such things. + + -- User Option: magit-remote-git-executable + The ‘git’ executable used by Magit on remote machines over Tramp. + Normally this should be just the string "git". Consider + customizing ‘tramp-remote-path’ instead of this option. + + If Emacs is unable to find the correct executable, then you can work +around that by explicitly setting the value of one of these two options. +Doing that should be considered a kludge; it is better to make sure that +the order in ‘exec-path’ or ‘tramp-remote-path’ is correct. + + Note that ‘exec-path’ is set based on the value of the ‘PATH’ +environment variable that is in effect when Emacs is started. If you +set ‘PATH’ in your shell’s init files, then that only has an effect on +Emacs if you start it from that shell (because the environment of a +process is only passed to its child processes, not to arbitrary other +processes). If that is not how you start Emacs, then the +‘exec-path-from-shell’ package can help; though honestly I consider that +a kludge too. + + The command ‘magit-debug-git-executable’ can be useful to find out +where Emacs is searching for ‘git’. + +‘M-x magit-debug-git-executable’ + This command displays a buffer with information about + ‘magit-git-executable’ and ‘magit-remote-git-executable’. + +‘M-x magit-version’ This command shows the currently used versions of Magit, Git, and Emacs in the echo area. Non-interactively this just returns the Magit version. - When the ‘system-type’ is ‘windows-nt’, then ‘magit-git-executable’ -is set to an absolute path when Magit is first loaded. This is -necessary because Git on that platform comes with several wrapper -scripts for the actual git binary, which are also placed on ‘$PATH’, and -using one of these wrappers instead of the binary would degrade -performance horribly. - - If Magit doesn’t find the correct executable then you *can* work -around that by setting ‘magit-git-executable’ to an absolute path. But -note that doing so is a kludge. It is better to make sure the order in -the environment variable ‘$PATH’ is correct, and that Emacs is started -with that environment in effect. The command -‘magit-debug-git-executable’ can be useful to find out where Emacs is -searching for git. If you have to connect from Windows to a non-Windows -machine, then you must change the value to "git". - - -- User Option: magit-git-executable - - The git executable used by Magit, either the full path to the - executable or the string "git" to let Emacs find the executable - itself, using the standard mechanism for doing such things. - -‘M-x magit-debug-git-executable’ (‘magit-debug-git-executable’) - - Display a buffer with information about ‘magit-git-executable’. -  File: magit.info, Node: Global Git Arguments, Prev: Git Executable, Up: Running Git @@ -2425,7 +2372,6 @@ File: magit.info, Node: Global Git Arguments, Prev: Git Executable, Up: Runni -------------------------- -- User Option: magit-git-global-arguments - The arguments set here are used every time the git executable is run as a subprocess. They are placed right after the executable itself and before the git command - as in ‘git HERE... COMMAND @@ -2493,8 +2439,7 @@ that it should be bound globally. We recommend using ‘C-x g’: (global-set-key (kbd "C-x g") 'magit-status) -‘C-x g’ (‘magit-status’) - +‘C-x g’ (‘magit-status’) When invoked from within an existing Git repository, then this command shows the status of that repository in a buffer. @@ -2530,7 +2475,6 @@ that it should be bound globally. We recommend using ‘C-x g’: the same as with two prefix arguments. -- User Option: magit-repository-directories - List of directories that are Git repositories or contain Git repositories. @@ -2543,8 +2487,33 @@ that it should be bound globally. We recommend using ‘C-x g’: ‘magit-list-repositories’. It also affects ‘magit-status’ (which see) in potentially surprising ways (see above). - -- Command: ido-enter-magit-status + -- Command: magit-status-quick + This command is an alternative to ‘magit-status’ that usually + avoids refreshing the status buffer. + If the status buffer of the current Git repository exists but isn’t + being displayed in the selected frame, then it is displayed without + being refreshed. + + If the status buffer is being displayed in the selected frame, then + this command refreshes it. + + Prefix arguments have the same meaning as for ‘magit-status’, and + additionally cause the buffer to be refresh. + + To use this command add this to your init file: + + (global-set-key (kbd "C-x g") 'magit-status-quick). + + If you do that and then for once want to redisplay the buffer and + also immediately refresh it, then type ‘C-x g’ followed by ‘g’. + + A possible alternative command is + ‘magit-display-repository-buffer’. It supports displaying any + existing Magit buffer that belongs to the current repository; not + just the status buffer. + + -- Command: ido-enter-magit-status From an Ido prompt used to open a file, instead drop into ‘magit-status’. This is similar to ‘ido-magic-delete-char’, which, despite its name, usually causes a Dired buffer to be created. @@ -2581,7 +2550,6 @@ The contents of status buffers is controlled using the hook such hooks and how to customize them. -- User Option: magit-status-sections-hook - Hook run to insert sections into a status buffer. The first function on that hook by default is @@ -2589,39 +2557,31 @@ such hooks and how to customize them. default the following functions are also members of that hook: -- Function: magit-insert-merge-log - Insert section for the on-going merge. Display the heads that are being merged. If no merge is in progress, do nothing. -- Function: magit-insert-rebase-sequence - Insert section for the on-going rebase sequence. If no such sequence is in progress, do nothing. -- Function: magit-insert-am-sequence - Insert section for the on-going patch applying sequence. If no such sequence is in progress, do nothing. -- Function: magit-insert-sequencer-sequence - Insert section for the on-going cherry-pick or revert sequence. If no such sequence is in progress, do nothing. -- Function: magit-insert-bisect-output - While bisecting, insert section with output from ‘git bisect’. -- Function: magit-insert-bisect-rest - While bisecting, insert section visualizing the bisect state. -- Function: magit-insert-bisect-log - While bisecting, insert section logging bisect progress. -- Function: magit-insert-untracked-files - Maybe insert a list or tree of untracked files. Do so depending on the value of ‘status.showUntrackedFiles’. Note @@ -2630,48 +2590,39 @@ default the following functions are also members of that hook: ‘TAB’. -- Function: magit-insert-unstaged-changes - Insert section showing unstaged changes. -- Function: magit-insert-staged-changes - Insert section showing staged changes. -- Function: magit-insert-stashes &optional ref heading - Insert the ‘stashes’ section showing reflog for "refs/stash". If optional REF is non-nil show reflog for that instead. If optional HEADING is non-nil use that as section heading instead of "Stashes:". -- Function: magit-insert-unpulled-from-upstream - Insert section showing commits that haven’t been pulled from the upstream branch yet. -- Function: magit-insert-unpulled-from-pushremote - Insert section showing commits that haven’t been pulled from the push-remote branch yet. -- Function: magit-insert-unpushed-to-upstream - Insert section showing commits that haven’t been pushed to the upstream yet. -- Function: magit-insert-unpushed-to-pushremote - Insert section showing commits that haven’t been pushed to the push-remote yet. The following functions can also be added to the above hook: -- Function: magit-insert-tracked-files - Insert a tree of tracked files. -- Function: magit-insert-ignored-files - Insert a tree of ignored files. Its possible to limit the logs in the current buffer to a certain directory using ‘D = f RET g’. If you do that, then that that also affects this command. @@ -2681,46 +2632,39 @@ default the following functions are also members of that hook: it is a directory. -- Function: magit-insert-skip-worktree-files - Insert a tree of skip-worktree files. If the first element of ‘magit-buffer-diff-files’ is a directory, then limit the list to files below that. The value of that variable can be set using ‘D -- DIRECTORY RET g’. -- Function: magit-insert-assumed-unchanged-files - Insert a tree of files that are assumed to be unchanged. If the first element of ‘magit-buffer-diff-files’ is a directory, then limit the list to files below that. The value of that variable can be set using ‘D -- DIRECTORY RET g’. -- Function: magit-insert-unpulled-or-recent-commits - Insert section showing unpulled or recent commits. If an upstream is configured for the current branch and it is ahead of the current branch, then show the missing commits. Otherwise, show the last ‘magit-log-section-commit-count’ commits. -- Function: magit-insert-recent-commits - Insert section showing the last ‘magit-log-section-commit-count’ commits. -- User Option: magit-log-section-commit-count - How many recent commits ‘magit-insert-recent-commits’ and ‘magit-insert-unpulled-or-recent-commits’ (provided there are no unpulled commits) show. -- Function: magit-insert-unpulled-cherries - Insert section showing unpulled commits. Like ‘magit-insert-unpulled-commits’ but prefix each commit that has not been applied yet (i.e. a commit with a patch-id not shared with any local commit) with "+", and all others with "-". -- Function: magit-insert-unpushed-cherries - Insert section showing unpushed commits. Like ‘magit-insert-unpushed-commits’ but prefix each commit which has not been applied to upstream yet (i.e. a commit with a patch-id @@ -2743,13 +2687,11 @@ The contents of status buffers is controlled using the hook hook variable. -- Function: magit-insert-status-headers - Insert headers sections appropriate for ‘magit-status-mode’ buffers. The sections are inserted by running the functions on the hook ‘magit-status-headers-hook’. -- User Option: magit-status-headers-hook - Hook run to insert headers sections into the status buffer. This hook is run by ‘magit-insert-status-headers’, which in turn @@ -2759,7 +2701,6 @@ hook variable. By default the following functions are members of the above hook: -- Function: magit-insert-error-header - Insert a header line showing the message about the Git error that just occurred. @@ -2769,36 +2710,29 @@ hook variable. the status buffer causes this section to disappear again. -- Function: magit-insert-diff-filter-header - Insert a header line showing the effective diff filters. -- Function: magit-insert-head-branch-header - Insert a header line about the current branch or detached ‘HEAD’. -- Function: magit-insert-upstream-branch-header - Insert a header line about the branch that is usually pulled into the current branch. -- Function: magit-insert-push-branch-header - Insert a header line about the branch that the current branch is usually pushed to. -- Function: magit-insert-tags-header - Insert a header line about the current and/or next tag, along with the number of commits between the tag and ‘HEAD’. The following functions can also be added to the above hook: -- Function: magit-insert-repo-header - Insert a header line showing the path to the repository top-level. -- Function: magit-insert-remote-header - Insert a header line about the remote of the current branch. If no remote is configured for the current branch, then fall back @@ -2806,7 +2740,6 @@ hook variable. remote in alphabetic order. -- Function: magit-insert-user-header - Insert a header line about the current user.  @@ -2822,7 +2755,6 @@ The contents of status buffers is controlled using the hook variable. -- Function: magit-insert-modules - Insert submodule sections. Hook ‘magit-module-sections-hook’ controls which module sections @@ -2830,11 +2762,9 @@ variable. whether they are wrapped in an additional section. -- User Option: magit-module-sections-hook - Hook run by ‘magit-insert-modules’. -- User Option: magit-module-sections-nested - This option controls whether ‘magit-insert-modules’ wraps inserted sections in an additional section. @@ -2843,7 +2773,6 @@ variable. ‘magit-module-sections-hook’ become top-level sections. -- Function: magit-insert-modules-overview - Insert sections for all submodules. For each section insert the path, the branch, and the output of ‘git describe --tags’, or, failing that, the abbreviated HEAD commit hash. @@ -2854,25 +2783,21 @@ variable. not displayed in the super-repository’s status buffer. -- Function: magit-insert-modules-unpulled-from-upstream - Insert sections for modules that haven’t been pulled from the upstream yet. These sections can be expanded to show the respective commits. -- Function: magit-insert-modules-unpulled-from-pushremote - Insert sections for modules that haven’t been pulled from the push-remote yet. These sections can be expanded to show the respective commits. -- Function: magit-insert-modules-unpushed-to-upstream - Insert sections for modules that haven’t been pushed to the upstream yet. These sections can be expanded to show the respective commits. -- Function: magit-insert-modules-unpushed-to-pushremote - Insert sections for modules that haven’t been pushed to the push-remote yet. These sections can be expanded to show the respective commits. @@ -2884,18 +2809,15 @@ File: magit.info, Node: Status Options, Prev: Status Module Sections, Up: Sta -------------------- -- User Option: magit-status-refresh-hook - Hook run after a status buffer has been refreshed. -- User Option: magit-status-margin - This option specifies whether the margin is initially shown in Magit-Status mode buffers and how it is formatted. The value has the form ‘(INIT STYLE WIDTH AUTHOR AUTHOR-WIDTH)’. • If INIT is non-nil, then the margin is shown initially. - • STYLE controls how to format the author or committer date. It can be one of ‘age’ (to show the age of the commit), ‘age-abbreviated’ (to abbreviate the time unit to a @@ -2903,14 +2825,11 @@ File: magit.info, Node: Status Options, Prev: Status Module Sections, Up: Sta show the actual date. Option ‘magit-log-margin-show-committer-date’ controls which date is being displayed. - • WIDTH controls the width of the margin. This exists for forward compatibility and currently the value should not be changed. - • AUTHOR controls whether the name of the author is also shown by default. - • AUTHOR-WIDTH has to be an integer. When the name of the author is shown, then this specifies how much space is used to do so. @@ -2925,7 +2844,6 @@ File: magit.info, Node: Repository List, Next: Logging, Prev: Status Buffer, =================== -- Command: magit-list-repositories - This command displays a list of repositories in a separate buffer. The options ‘magit-repository-directories’ and @@ -2933,7 +2851,6 @@ File: magit.info, Node: Repository List, Next: Logging, Prev: Status Buffer, displayed. -- User Option: magit-repolist-columns - This option controls what columns are displayed by the command ‘magit-list-repositories’ and how they are displayed. @@ -2946,71 +2863,63 @@ File: magit.info, Node: Repository List, Next: Logging, Prev: Status Buffer, It has to return a string to be inserted or nil. PROPS is an alist that supports the keys ‘:right-align’ and ‘:pad-right’. + You may wish to display a range of numeric columns using just one + character per column and without any padding between columns, in + which case you should use an appropriate HEADER, set WIDTH to 1, + and set ‘:pad-right’ to 0. ‘+’ is substituted for numbers higher + than 9. + The following functions can be added to the above option: -- Function: magit-repolist-column-ident - This function inserts the identification of the repository. Usually this is just its basename. -- Function: magit-repolist-column-path - This function inserts the absolute path of the repository. -- Function: magit-repolist-column-version - This function inserts a description of the repository’s ‘HEAD’ revision. -- Function: magit-repolist-column-branch - This function inserts the name of the current branch. -- Function: magit-repolist-column-upstream - This function inserts the name of the upstream branch of the current branch. -- Function: magit-repolist-column-branches - This function inserts the number of branches. -- Function: magit-repolist-column-stashes - This function inserts the number of stashes. -- Function: magit-repolist-column-flag - This function inserts a flag as specified by ‘magit-repolist-column-flag-alist’. By default this indicates whether there are uncommitted changes. • ‘N’ if there is at least one untracked file. - • ‘U’ if there is at least one unstaged file. - • ‘S’ if there is at least one staged file. Only the first one of these that applies is shown. -- Function: magit-repolist-column-unpulled-from-upstream - This function inserts the number of upstream commits not in the current branch. -- Function: magit-repolist-column-unpulled-from-pushremote - This function inserts the number of commits in the push branch but not the current branch. -- Function: magit-repolist-column-unpushed-to-upstream - This function inserts the number of commits in the current branch but not its upstream. -- Function: magit-repolist-column-unpushed-to-pushremote - This function inserts the number of commits in the current branch but not its push branch. @@ -3043,39 +2952,32 @@ passed to ‘git log’. The log transient also features several reflog commands. See *note Reflog::. -‘l’ (‘magit-log’) - +‘l’ (‘magit-log’) This transient prefix command binds the following suffix commands along with the appropriate infix arguments and displays them in a temporary buffer until a suffix is invoked. -‘l l’ (‘magit-log-current’) - +‘l l’ (‘magit-log-current’) Show log for the current branch. When ‘HEAD’ is detached or with a prefix argument, show log for one or more revs read from the minibuffer. -‘l o’ (‘magit-log-other’) - +‘l o’ (‘magit-log-other’) Show log for one or more revs read from the minibuffer. The user can input any revision or revisions separated by a space, or even ranges, but only branches, tags, and a representation of the commit at point are available as completion candidates. -‘l h’ (‘magit-log-head’) - +‘l h’ (‘magit-log-head’) Show log for ‘HEAD’. -‘l L’ (‘magit-log-branches’) - +‘l L’ (‘magit-log-branches’) Show log for all local branches and ‘HEAD’. -‘l b’ (‘magit-log-all-branches’) - +‘l b’ (‘magit-log-all-branches’) Show log for all local and remote branches and ‘HEAD’. -‘l a’ (‘magit-log-all’) - +‘l a’ (‘magit-log-all’) Show log for all references and ‘HEAD’. Two additional commands that show the log for the file or blob that @@ -3103,34 +3005,29 @@ change the log arguments used in the current buffer, without changing which log is shown. This works in dedicated log buffers, but also in the status buffer. -‘L’ (‘magit-log-refresh’) - +‘L’ (‘magit-log-refresh’) This transient prefix command binds the following suffix commands along with the appropriate infix arguments and displays them in a temporary buffer until a suffix is invoked. -‘L g’ (‘magit-log-refresh’) - +‘L g’ (‘magit-log-refresh’) This suffix command sets the local log arguments for the current buffer. -‘L s’ (‘magit-log-set-default-arguments’) - +‘L s’ (‘magit-log-set-default-arguments’) This suffix command sets the default log arguments for buffers of the same type as that of the current buffer. Other existing buffers of the same type are not affected because their local values have already been initialized. -‘L w’ (‘magit-log-save-default-arguments’) - +‘L w’ (‘magit-log-save-default-arguments’) This suffix command sets the default log arguments for buffers of the same type as that of the current buffer, and saves the value for future sessions. Other existing buffers of the same type are not affected because their local values have already been initialized. -‘L t’ (‘magit-toggle-margin’) - +‘L t’ (‘magit-toggle-margin’) Show or hide the margin.  @@ -3139,37 +3036,41 @@ File: magit.info, Node: Log Buffer, Next: Log Margin, Prev: Refreshing Logs, 5.3.2 Log Buffer ---------------- -‘L’ (‘magit-log-refresh’) - +‘L’ (‘magit-log-refresh’) This transient prefix command binds the following suffix commands along with the appropriate infix arguments and displays them in a temporary buffer until a suffix is invoked. See *note Refreshing Logs::. -‘q’ (‘magit-log-bury-buffer’) - +‘q’ (‘magit-log-bury-buffer’) Bury the current buffer or the revision buffer in the same frame. Like ‘magit-mode-bury-buffer’ (which see) but with a negative prefix argument instead bury the revision buffer, provided it is displayed in the current frame. -‘C-c C-b’ (‘magit-go-backward’) - +‘C-c C-b’ (‘magit-go-backward’) Move backward in current buffer’s history. -‘C-c C-f’ (‘magit-go-forward’) - +‘C-c C-f’ (‘magit-go-forward’) Move forward in current buffer’s history. -‘C-c C-n’ (‘magit-log-move-to-parent’) - +‘C-c C-n’ (‘magit-log-move-to-parent’) Move to a parent of the current commit. By default, this is the first parent, but a numeric prefix can be used to specify another parent. -‘SPC’ (‘magit-diff-show-or-scroll-up’) +‘j’ (‘magit-log-move-to-revision’) + Read a revision and move to it in current log buffer. + If the chosen reference or revision isn’t being displayed in the + current log buffer, then inform the user about that and do nothing + else. + + If invoked outside any log buffer, then display the log buffer of + the current repository first; creating it if necessary. + +‘’ (‘magit-diff-show-or-scroll-up’) Update the commit or diff buffer for the thing at point. Either show the commit or stash at point in the appropriate buffer, @@ -3178,8 +3079,7 @@ File: magit.info, Node: Log Buffer, Next: Log Margin, Prev: Refreshing Logs, scroll the buffer up. If there is no commit or stash at point, then prompt for a commit. -‘DEL’ (‘magit-diff-show-or-scroll-down’) - +‘DEL’ (‘magit-diff-show-or-scroll-down’) Update the commit or diff buffer for the thing at point. Either show the commit or stash at point in the appropriate buffer, @@ -3188,28 +3088,23 @@ File: magit.info, Node: Log Buffer, Next: Log Margin, Prev: Refreshing Logs, scroll the buffer down. If there is no commit or stash at point, then prompt for a commit. -‘=’ (‘magit-log-toggle-commit-limit’) - +‘=’ (‘magit-log-toggle-commit-limit’) Toggle the number of commits the current log buffer is limited to. If the number of commits is currently limited, then remove that limit. Otherwise set it to 256. -‘+’ (‘magit-log-double-commit-limit’) - +‘+’ (‘magit-log-double-commit-limit’) Double the number of commits the current log buffer is limited to. -‘-’ (‘magit-log-half-commit-limit’) - +‘-’ (‘magit-log-half-commit-limit’) Half the number of commits the current log buffer is limited to. -- User Option: magit-log-auto-more - Insert more log entries automatically when moving past the last entry. Only considered when moving past the last entry with ‘magit-goto-*-section’ commands. -- User Option: magit-log-show-refname-after-summary - Whether to show the refnames after the commit summaries. This is useful if you use really long branch names. @@ -3254,14 +3149,12 @@ is the same as in the respective major-mode ‘magit-INFIX-mode’. In regular log buffers that would be ‘magit-log-margin’. -- User Option: magit-log-margin - This option specifies whether the margin is initially shown in Magit-Log mode buffers and how it is formatted. The value has the form ‘(INIT STYLE WIDTH AUTHOR AUTHOR-WIDTH)’. • If INIT is non-nil, then the margin is shown initially. - • STYLE controls how to format the author or committer date. It can be one of ‘age’ (to show the age of the commit), ‘age-abbreviated’ (to abbreviate the time unit to a @@ -3269,14 +3162,11 @@ regular log buffers that would be ‘magit-log-margin’. show the actual date. Option ‘magit-log-margin-show-committer-date’ controls which date is being displayed. - • WIDTH controls the width of the margin. This exists for forward compatibility and currently the value should not be changed. - • AUTHOR controls whether the name of the author is also shown by default. - • AUTHOR-WIDTH has to be an integer. When the name of the author is shown, then this specifies how much space is used to do so. @@ -3291,15 +3181,13 @@ re-enforcing the default for that option, does not carry to other options. -- User Option: magit-log-margin-show-committer-date - This option specifies whether to show the committer date in the margin. This option only controls whether the committer date is displayed instead of the author date. Whether some date is displayed in the margin and whether the margin is displayed at all is controlled by other options. -‘L’ (‘magit-margin-settings’) - +‘L’ (‘magit-margin-settings’) This transient prefix command binds the following suffix commands, each of which changes the appearance of the margin in some way. @@ -3307,16 +3195,13 @@ options. ‘magit-log-refresh’, but that transient features the same commands, and then some other unrelated commands. -‘L L’ (‘magit-toggle-margin’) - +‘L L’ (‘magit-toggle-margin’) This command shows or hides the margin. -‘L l’ (‘magit-cycle-margin-style’) - +‘L l’ (‘magit-cycle-margin-style’) This command cycles the style used for the margin. -‘L d’ (‘magit-toggle-margin-details’) - +‘L d’ (‘magit-toggle-margin-details’) This command shows or hides details in the margin.  @@ -3339,25 +3224,21 @@ and when selecting the commit to be squashed into. following additional key bindings are available in selection log buffers: -‘C-c C-c’ (‘magit-log-select-pick’) - +‘C-c C-c’ (‘magit-log-select-pick’) Select the commit at point and act on it. Call ‘magit-log-select-pick-function’ with the selected commit as argument. -‘C-c C-k’ (‘magit-log-select-quit’) - +‘C-c C-k’ (‘magit-log-select-quit’) Abort selecting a commit, don’t act on any commit. -- User Option: magit-log-select-margin - This option specifies whether the margin is initially shown in Magit-Log-Select mode buffers and how it is formatted. The value has the form ‘(INIT STYLE WIDTH AUTHOR AUTHOR-WIDTH)’. • If INIT is non-nil, then the margin is shown initially. - • STYLE controls how to format the author or committer date. It can be one of ‘age’ (to show the age of the commit), ‘age-abbreviated’ (to abbreviate the time unit to a @@ -3365,14 +3246,11 @@ buffers: show the actual date. Option ‘magit-log-margin-show-committer-date’ controls which date is being displayed. - • WIDTH controls the width of the margin. This exists for forward compatibility and currently the value should not be changed. - • AUTHOR controls whether the name of the author is also shown by default. - • AUTHOR-WIDTH has to be an integer. When the name of the author is shown, then this specifies how much space is used to do so. @@ -3388,27 +3266,22 @@ Also see *note (gitman)git-reflog::. These reflog commands are available from the log transient. See *note Logging::. -‘l r’ (‘magit-reflog-current’) - +‘l r’ (‘magit-reflog-current’) Display the reflog of the current branch. -‘l O’ (‘magit-reflog-other’) - +‘l O’ (‘magit-reflog-other’) Display the reflog of a branch or another ref. -‘l H’ (‘magit-reflog-head’) - +‘l H’ (‘magit-reflog-head’) Display the ‘HEAD’ reflog. -- User Option: magit-reflog-margin - This option specifies whether the margin is initially shown in Magit-Reflog mode buffers and how it is formatted. The value has the form ‘(INIT STYLE WIDTH AUTHOR AUTHOR-WIDTH)’. • If INIT is non-nil, then the margin is shown initially. - • STYLE controls how to format the author or committer date. It can be one of ‘age’ (to show the age of the commit), ‘age-abbreviated’ (to abbreviate the time unit to a @@ -3416,14 +3289,11 @@ Also see *note (gitman)git-reflog::. show the actual date. Option ‘magit-log-margin-show-committer-date’ controls which date is being displayed. - • WIDTH controls the width of the margin. This exists for forward compatibility and currently the value should not be changed. - • AUTHOR controls whether the name of the author is also shown by default. - • AUTHOR-WIDTH has to be an integer. When the name of the author is shown, then this specifies how much space is used to do so. @@ -3445,20 +3315,17 @@ for multiple "upstreams" at once. Also see *note (gitman)git-reflog::. -‘Y’ (‘magit-cherry’) - +‘Y’ (‘magit-cherry’) Show commits that are in a certain branch but that have not been merged in the upstream branch. -- User Option: magit-cherry-margin - This option specifies whether the margin is initially shown in Magit-Cherry mode buffers and how it is formatted. The value has the form ‘(INIT STYLE WIDTH AUTHOR AUTHOR-WIDTH)’. • If INIT is non-nil, then the margin is shown initially. - • STYLE controls how to format the author or committer date. It can be one of ‘age’ (to show the age of the commit), ‘age-abbreviated’ (to abbreviate the time unit to a @@ -3466,14 +3333,11 @@ for multiple "upstreams" at once. show the actual date. Option ‘magit-log-margin-show-committer-date’ controls which date is being displayed. - • WIDTH controls the width of the margin. This exists for forward compatibility and currently the value should not be changed. - • AUTHOR controls whether the name of the author is also shown by default. - • AUTHOR-WIDTH has to be an integer. When the name of the author is shown, then this specifies how much space is used to do so. @@ -3499,18 +3363,15 @@ Buffer Variables::). Also see *note (gitman)git-diff::. -‘d’ (‘magit-diff’) - +‘d’ (‘magit-diff’) This transient prefix command binds the following suffix commands along with the appropriate infix arguments and displays them in a temporary buffer until a suffix is invoked. -‘d d’ (‘magit-diff-dwim’) - +‘d d’ (‘magit-diff-dwim’) Show changes for the thing at point. -‘d r’ (‘magit-diff-range’) - +‘d r’ (‘magit-diff-range’) Show differences between two commits. RANGE should be a range (A..B or A...B) but can also be a single @@ -3523,37 +3384,31 @@ Buffer Variables::). revisions, choose a revision to view changes along, starting at the common ancestor of both revisions (i.e., use a "..." range). -‘d w’ (‘magit-diff-working-tree’) - +‘d w’ (‘magit-diff-working-tree’) Show changes between the current working tree and the ‘HEAD’ commit. With a prefix argument show changes between the working tree and a commit read from the minibuffer. -‘d s’ (‘magit-diff-staged’) - +‘d s’ (‘magit-diff-staged’) Show changes between the index and the ‘HEAD’ commit. With a prefix argument show changes between the index and a commit read from the minibuffer. -‘d u’ (‘magit-diff-unstaged’) - +‘d u’ (‘magit-diff-unstaged’) Show changes between the working tree and the index. -‘d p’ (‘magit-diff-paths’) - +‘d p’ (‘magit-diff-paths’) Show changes between any two files on disk. All of the above suffix commands update the repository’s diff buffer. The diff transient also features two commands which show differences in another buffer: -‘d c’ (‘magit-show-commit’) - +‘d c’ (‘magit-show-commit’) Show the commit at point. If there is no commit at point or with a prefix argument, prompt for a commit. -‘d t’ (‘magit-stash-show’) - +‘d t’ (‘magit-stash-show’) Show all diffs of a stash in a buffer. Two additional commands that show the diff for the file or blob that @@ -3578,48 +3433,40 @@ to change the diff arguments used in the current buffer, without changing which diff is shown. This works in dedicated diff buffers, but also in the status buffer. -‘D’ (‘magit-diff-refresh’) - +‘D’ (‘magit-diff-refresh’) This transient prefix command binds the following suffix commands along with the appropriate infix arguments and displays them in a temporary buffer until a suffix is invoked. -‘D g’ (‘magit-diff-refresh’) - +‘D g’ (‘magit-diff-refresh’) This suffix command sets the local diff arguments for the current buffer. -‘D s’ (‘magit-diff-set-default-arguments’) - +‘D s’ (‘magit-diff-set-default-arguments’) This suffix command sets the default diff arguments for buffers of the same type as that of the current buffer. Other existing buffers of the same type are not affected because their local values have already been initialized. -‘D w’ (‘magit-diff-save-default-arguments’) - +‘D w’ (‘magit-diff-save-default-arguments’) This suffix command sets the default diff arguments for buffers of the same type as that of the current buffer, and saves the value for future sessions. Other existing buffers of the same type are not affected because their local values have already been initialized. -‘D t’ (‘magit-diff-toggle-refine-hunk’) - +‘D t’ (‘magit-diff-toggle-refine-hunk’) This command toggles hunk refinement on or off. -‘D r’ (‘magit-diff-switch-range-type’) - +‘D r’ (‘magit-diff-switch-range-type’) This command converts the diff range type from "revA..revB" to "revB...revA", or vice versa. -‘D f’ (‘magit-diff-flip-revs’) - +‘D f’ (‘magit-diff-flip-revs’) This command swaps revisions in the diff range from "revA..revB" to "revB..revA", or vice versa. -‘D F’ (‘magit-diff-toggle-file-filter’) - +‘D F’ (‘magit-diff-toggle-file-filter’) This command toggles the file restriction of the diffs in the current buffer, allowing you to quickly switch between viewing all the changes in the commit and the restricted subset. As a special @@ -3632,24 +3479,20 @@ also in the status buffer. supported arguments, there also exist some commands that change only a particular argument. -‘-’ (‘magit-diff-less-context’) - +‘-’ (‘magit-diff-less-context’) This command decreases the context for diff hunks by COUNT lines. -‘+’ (‘magit-diff-more-context’) - +‘+’ (‘magit-diff-more-context’) This command increases the context for diff hunks by COUNT lines. -‘0’ (‘magit-diff-default-context’) - +‘0’ (‘magit-diff-default-context’) This command resets the context for diff hunks to the default height. The following commands quickly change what diff is being displayed without having to using one of the diff transient. -‘C-c C-d’ (‘magit-diff-while-committing’) - +‘C-c C-d’ (‘magit-diff-while-committing’) While committing, this command shows the changes that are about to be committed. While amending, invoking the command again toggles between showing just the new changes or all the changes that will @@ -3658,12 +3501,10 @@ without having to using one of the diff transient. This binding is available in the diff buffer as well as the commit message buffer. -‘C-c C-b’ (‘magit-go-backward’) - +‘C-c C-b’ (‘magit-go-backward’) This command moves backward in current buffer’s history. -‘C-c C-f’ (‘magit-go-forward’) - +‘C-c C-f’ (‘magit-go-forward’) This command moves forward in current buffer’s history.  @@ -3680,19 +3521,16 @@ version of the file that the diff at point is about. Likewise version of the file that the diff at point is about. See *note Visiting Files and Blobs from a Diff:: for more information and the key bindings. -‘C-c C-t’ (‘magit-diff-trace-definition’) - +‘C-c C-t’ (‘magit-diff-trace-definition’) This command shows a log for the definition at point. -- User Option: magit-log-trace-definition-function - The function specified by this option is used by ‘magit-log-trace-definition’ to determine the function at point. For major-modes that have special needs, you could set the local value using the mode’s hook. -‘C-c C-e’ (‘magit-diff-edit-hunk-commit’) - +‘C-c C-e’ (‘magit-diff-edit-hunk-commit’) From a hunk, this command edits the respective commit and visits the file. @@ -3711,8 +3549,7 @@ Files and Blobs from a Diff:: for more information and the key bindings. rebase. If that is undesirable, then it might be better to use ‘magit-rebase-edit-command’ instead of this command. -‘j’ (‘magit-jump-to-diffstat-or-diff’) - +‘j’ (‘magit-jump-to-diffstat-or-diff’) This command jumps to the diffstat or diff. When point is on a file inside the diffstat section, then jump to the respective diff section. Otherwise, jump to the diffstat section or a child @@ -3722,12 +3559,10 @@ Files and Blobs from a Diff:: for more information and the key bindings. Magit buffer for that matter), but it might be worth pointing out that they are available here too. -‘SPC’ (‘scroll-up’) - +‘’ (‘scroll-up’) This command scrolls text upward. -‘DEL’ (‘scroll-down’) - +‘DEL’ (‘scroll-down’) This command scrolls text downward.  @@ -3737,22 +3572,17 @@ File: magit.info, Node: Diff Options, Next: Revision Buffer, Prev: Commands A ------------------ -- User Option: magit-diff-refine-hunk - Whether to show word-granularity differences within diff hunks. • ‘nil’ Never show fine differences. - • ‘t’ Show fine differences for the current diff hunk only. - • ‘all’ Show fine differences for all displayed diff hunks. -- User Option: magit-diff-refine-ignore-whitespace - Whether to ignore whitespace changes in word-granularity differences. -- User Option: magit-diff-adjust-tab-width - Whether to adjust the width of tabs in diffs. Determining the correct width can be expensive if it requires @@ -3774,7 +3604,6 @@ File: magit.info, Node: Diff Options, Next: Revision Buffer, Prev: Commands A bytes. -- User Option: magit-diff-paint-whitespace - Specify where to highlight whitespace errors. See ‘magit-diff-highlight-trailing’, @@ -3783,30 +3612,23 @@ File: magit.info, Node: Diff Options, Next: Revision Buffer, Prev: Commands A nowhere. • ‘nil’ Never highlight whitespace errors. - • ‘t’ Highlight whitespace errors everywhere. - • ‘uncommitted’ Only highlight whitespace errors in diffs showing uncommitted changes. For backward compatibility ‘status’ is treated as a synonym. -- User Option: magit-diff-paint-whitespace-lines - Specify in what kind of lines to highlight whitespace errors. • ‘t’ Highlight only in added lines. - • ‘both’ Highlight in added and removed lines. - • ‘all’ Highlight in added, removed and context lines. -- User Option: magit-diff-highlight-trailing - Whether to highlight whitespace at the end of a line in diffs. Used only when ‘magit-diff-paint-whitespace’ is non-nil. -- User Option: magit-diff-highlight-indentation - This option controls whether to highlight the indentation in case it used the "wrong" indentation style. Indentation is only highlighted if ‘magit-diff-paint-whitespace’ is also non-nil. @@ -3821,11 +3643,9 @@ File: magit.info, Node: Diff Options, Next: Revision Buffer, Prev: Commands A spaces. Otherwise, highlight neither. -- User Option: magit-diff-hide-trailing-cr-characters - Whether to hide ^M characters at the end of a line in diffs. -- User Option: magit-diff-highlight-hunk-region-functions - This option specifies the functions used to highlight the hunk-internal region. @@ -3851,13 +3671,22 @@ File: magit.info, Node: Diff Options, Next: Revision Buffer, Prev: Commands A calling the face function instead. -- User Option: magit-diff-unmarked-lines-keep-foreground - This option controls whether added and removed lines outside the hunk-internal region only lose their distinct background color or also the foreground color. Whether the outside of the region is dimmed at all depends on ‘magit-diff-highlight-hunk-region-functions’. + -- User Option: magit-diff-extra-stat-arguments + This option specifies additional arguments to be used alongside + ‘--stat’. + + The value is a list of zero or more arguments or a function that + takes no argument and returns such a list. These arguments are + allowed here: ‘--stat-width’, ‘--stat-name-width’, + ‘--stat-graph-width’ and ‘--compact-summary’. Also see *note + (gitman)git-diff::. +  File: magit.info, Node: Revision Buffer, Prev: Diff Options, Up: Diffing @@ -3865,20 +3694,15 @@ File: magit.info, Node: Revision Buffer, Prev: Diff Options, Up: Diffing --------------------- -- User Option: magit-revision-insert-related-refs - Whether to show related branches in revision buffers. • ‘nil’ Don’t show any related branches. - • ‘t’ Show related local branches. - • ‘all’ Show related local and remote branches. - • ‘mixed’ Show all containing branches and local merged branches. -- User Option: magit-revision-show-gravatars - Whether to show gravatar images in revision buffers. If ‘nil’, then don’t insert any gravatar images. If ‘t’, then @@ -3895,7 +3719,6 @@ File: magit.info, Node: Revision Buffer, Prev: Diff Options, Up: Diffing accordingly. Either the car or the cdr may be nil." -- User Option: magit-revision-use-hash-sections - Whether to turn hashes inside the commit message into sections. If non-nil, then hashes inside the commit message are turned into @@ -3903,12 +3726,9 @@ File: magit.info, Node: Revision Buffer, Prev: Diff Options, Up: Diffing performance and reliability: • ‘slow’ calls git for every word to be absolutely sure. - • ‘quick’ skips words less than seven characters long. - • ‘quicker’ additionally skips words that don’t contain a number. - • ‘quickest’ uses all words that are at least seven characters long and which contain at least one number as well as at least one letter. @@ -3923,7 +3743,6 @@ file restriction as that log buffer (also see the command ‘magit-diff-toggle-file-filter’). -- User Option: magit-revision-filter-files-on-follow - Whether showing a commit from a log buffer honors the log’s file filter when the log arguments include ‘--follow’. @@ -3950,8 +3769,7 @@ File: magit.info, Node: Ediffing, Next: References Buffer, Prev: Diffing, Up This section describes how to enter Ediff from Magit buffers. For information on how to use Ediff itself, see *note (ediff)Top::. -‘e’ (‘magit-ediff-dwim’) - +‘e’ (‘magit-ediff-dwim’) Compare, stage, or resolve using Ediff. This command tries to guess what file, and what commit or range the @@ -3962,13 +3780,11 @@ information on how to use Ediff itself, see *note (ediff)Top::. be used explicitly. If it cannot read the user’s mind at all, then it asks the user for a command to run. -‘E’ (‘magit-ediff’) - +‘E’ (‘magit-ediff’) This transient prefix command binds the following suffix commands and displays them in a temporary buffer until a suffix is invoked. -‘E r’ (‘magit-ediff-compare’) - +‘E r’ (‘magit-ediff-compare’) Compare two revisions of a file using Ediff. If the region is active, use the revisions on the first and last @@ -3976,8 +3792,7 @@ information on how to use Ediff itself, see *note (ediff)Top::. revisions, choose a revision to view changes along, starting at the common ancestor of both revisions (i.e., use a "..." range). -‘E m’ (‘magit-ediff-resolve’) - +‘E m’ (‘magit-ediff-resolve’) Resolve outstanding conflicts in a file using Ediff, defaulting to the file at point. @@ -3989,33 +3804,26 @@ information on how to use Ediff itself, see *note (ediff)Top::. including those already resolved by Git, use ‘ediff-merge-revisions-with-ancestor’. -‘E s’ (‘magit-ediff-stage’) - +‘E s’ (‘magit-ediff-stage’) Stage and unstage changes to a file using Ediff, defaulting to the file at point. -‘E u’ (‘magit-ediff-show-unstaged’) - +‘E u’ (‘magit-ediff-show-unstaged’) Show unstaged changes to a file using Ediff. -‘E i’ (‘magit-ediff-show-staged’) - +‘E i’ (‘magit-ediff-show-staged’) Show staged changes to a file using Ediff. -‘E w’ (‘magit-ediff-show-working-tree’) - +‘E w’ (‘magit-ediff-show-working-tree’) Show changes in a file between ‘HEAD’ and working tree using Ediff. -‘E c’ (‘magit-ediff-show-commit’) - +‘E c’ (‘magit-ediff-show-commit’) Show changes to a file introduced by a commit using Ediff. -‘E z’ (‘magit-ediff-show-stash’) - +‘E z’ (‘magit-ediff-show-stash’) Show changes to a file introduced by a stash using Ediff. -- User Option: magit-ediff-dwim-show-on-hunks - This option controls what command ‘magit-ediff-dwim’ calls when point is on uncommitted hunks. When nil, always run ‘magit-ediff-stage’. Otherwise, use ‘magit-ediff-show-staged’ and @@ -4023,14 +3831,12 @@ information on how to use Ediff itself, see *note (ediff)Top::. respectively. -- User Option: magit-ediff-show-stash-with-index - This option controls whether ‘magit-ediff-show-stash’ includes a buffer containing the file’s state in the index at the time the stash was created. This makes it possible to tell which changes in the stash were staged. -- User Option: magit-ediff-quit-hook - This hook is run after quitting an Ediff session that was created using a Magit command. The hook functions are run inside the Ediff control buffer, and should not change the current buffer. @@ -4045,8 +3851,7 @@ File: magit.info, Node: References Buffer, Next: Bisecting, Prev: Ediffing, 5.6 References Buffer ===================== -‘y’ (‘magit-show-refs’) - +‘y’ (‘magit-show-refs’) This command lists branches and tags in a dedicated buffer. However if this command is invoked again from this buffer or if it @@ -4060,36 +3865,32 @@ by changing the value of ‘magit-refs-show-commit-count’ (see below). These commands specify a different branch or commit against which all the other references are compared. -‘y y’ (‘magit-show-refs-head’) - +‘y y’ (‘magit-show-refs-head’) This command lists branches and tags in a dedicated buffer. Each reference is being compared with ‘HEAD’. -‘y c’ (‘magit-show-refs-current’) - +‘y c’ (‘magit-show-refs-current’) This command lists branches and tags in a dedicated buffer. Each reference is being compared with the current branch or ‘HEAD’ if it is detached. -‘y o’ (‘magit-show-refs-other’) - +‘y o’ (‘magit-show-refs-other’) This command lists branches and tags in a dedicated buffer. Each reference is being compared with a branch read from the user. - -- User Option: magit-refs-show-commit-count +‘y r’ (‘magit-refs-set-show-commit-count’) + This command changes for which refs the commit count is shown. + -- User Option: magit-refs-show-commit-count Whether to show commit counts in Magit-Refs mode buffers. • ‘all’ Show counts for branches and tags. - • ‘branch’ Show counts for branches only. - • ‘nil’ Never show counts. The default is ‘nil’ because anything else can be very expensive. -- User Option: magit-refs-pad-commit-counts - Whether to pad all commit counts on all sides in Magit-Refs mode buffers. @@ -4102,14 +3903,12 @@ the other references are compared. commit counts. -- User Option: magit-refs-show-remote-prefix - Whether to show the remote prefix in lists of remote branches. Showing the prefix is redundant because the name of the remote is already shown in the heading preceding the list of its branches. -- User Option: magit-refs-primary-column-width - Width of the primary column in ‘magit-refs-mode’ buffers. The primary column is the column that contains the name of the branch that the current row is about. @@ -4122,7 +3921,6 @@ the other references are compared. taken into account when calculating to optimal width.) -- User Option: magit-refs-focus-column-width - Width of the focus column in ‘magit-refs-mode’ buffers. The focus column is the first column, which marks one branch @@ -4137,14 +3935,12 @@ the other references are compared. the verbosity of this column. -- User Option: magit-refs-margin - This option specifies whether the margin is initially shown in Magit-Refs mode buffers and how it is formatted. The value has the form ‘(INIT STYLE WIDTH AUTHOR AUTHOR-WIDTH)’. • If INIT is non-nil, then the margin is shown initially. - • STYLE controls how to format the author or committer date. It can be one of ‘age’ (to show the age of the commit), ‘age-abbreviated’ (to abbreviate the time unit to a @@ -4152,20 +3948,16 @@ the other references are compared. show the actual date. Option ‘magit-log-margin-show-committer-date’ controls which date is being displayed. - • WIDTH controls the width of the margin. This exists for forward compatibility and currently the value should not be changed. - • AUTHOR controls whether the name of the author is also shown by default. - • AUTHOR-WIDTH has to be an integer. When the name of the author is shown, then this specifies how much space is used to do so. -- User Option: magit-refs-margin-for-tags - This option specifies whether to show information about tags in the margin. This is disabled by default because it is slow if there are many tags. @@ -4176,30 +3968,21 @@ you should also change the others to keep things aligned. The following %-sequences are supported: • ‘%a’ Number of commits this ref has over the one we compare to. - • ‘%b’ Number of commits the ref we compare to has over this one. - • ‘%c’ Number of commits this ref has over the one we compare to. For the ref which all other refs are compared this is instead "@", if it is the current branch, or "#" otherwise. - • ‘%C’ For the ref which all other refs are compared this is "@", if it is the current branch, or "#" otherwise. For all other refs " ". - • ‘%h’ Hash of this ref’s tip. - • ‘%m’ Commit summary of the tip of this ref. - • ‘%n’ Name of this ref. - • ‘%u’ Upstream of this local branch. - • ‘%U’ Upstream of this local branch and additional local vs. upstream information. -- User Option: magit-refs-filter-alist - The purpose of this option is to forgo displaying certain refs based on their name. If you want to not display any refs of a certain type, then you should remove the appropriate function from @@ -4220,8 +4003,7 @@ you should also change the others to keep things aligned. The following displayed as just "master", however for this comparison the former is used. -‘RET’ (‘magit-visit-ref’) - +‘’ (‘magit-visit-ref’) This command visits the reference or revision at point in another buffer. If there is no revision at point or with a prefix argument then it prompts for a revision. @@ -4232,7 +4014,6 @@ you should also change the others to keep things aligned. The following you have customized the option ‘magit-visit-ref-behavior’. -- User Option: magit-visit-ref-behavior - This option controls how ‘magit-visit-ref’ behaves in ‘magit-refs-mode’ buffers. @@ -4313,19 +4094,15 @@ customize this hook than it does for the respective hook used for the status buffer. -- User Option: magit-refs-sections-hook - Hook run to insert sections into a references buffer. -- Function: magit-insert-local-branches - Insert sections showing all local branches. -- Function: magit-insert-remote-branches - Insert sections showing all remote-tracking branches. -- Function: magit-insert-tags - Insert sections showing all tags.  @@ -4336,16 +4113,14 @@ File: magit.info, Node: Bisecting, Next: Visiting Files and Blobs, Prev: Refe Also see *note (gitman)git-bisect::. -‘B’ (‘magit-bisect’) - +‘B’ (‘magit-bisect’) This transient prefix command binds the following suffix commands and displays them in a temporary buffer until a suffix is invoked. When bisecting is not in progress, then the transient features the following suffix commands. -‘B B’ (‘magit-bisect-start’) - +‘B B’ (‘magit-bisect-start’) Start a bisect session. Bisecting a bug means to find the commit that introduced it. This @@ -4355,38 +4130,32 @@ following suffix commands. conceptually more fitting than "bad" and "good", but the infix arguments to do so are disabled by default. -‘B s’ (‘magit-bisect-run’) - +‘B s’ (‘magit-bisect-run’) Bisect automatically by running commands after each step. When bisecting in progress, then the transient instead features the following suffix commands. -‘B b’ (‘magit-bisect-bad’) - +‘B b’ (‘magit-bisect-bad’) Mark the current commit as bad. Use this after you have asserted that the commit does contain the bug in question. -‘B g’ (‘magit-bisect-good’) - +‘B g’ (‘magit-bisect-good’) Mark the current commit as good. Use this after you have asserted that the commit does not contain the bug in question. -‘B m’ (‘magit-bisect-mark’) - +‘B m’ (‘magit-bisect-mark’) Mark the current commit with one of the bisect terms. This command provides an alternative to ‘magit-bisect-bad’ and ‘magit-bisect-good’ and is useful when using terms other than "bad" and "good". This suffix is disabled by default. -‘B k’ (‘magit-bisect-skip’) - +‘B k’ (‘magit-bisect-skip’) Skip the current commit. Use this if for some reason the current commit is not a good one to test. This command lets Git choose a different one. -‘B r’ (‘magit-bisect-reset’) - +‘B r’ (‘magit-bisect-reset’) After bisecting, cleanup bisection state and return to original ‘HEAD’. @@ -4394,7 +4163,6 @@ following suffix commands. bisect session. -- User Option: magit-bisect-show-graph - This option controls whether a graph is displayed for the log of commits that still have to be bisected. @@ -4424,19 +4192,16 @@ These commands can be used anywhere to open any blob. Currently no keys are bound to these commands by default, but that is likely to change. -- Command: magit-find-file - This command reads a filename and revision from the user and visits the respective blob in a buffer. The buffer is displayed in the selected window. -- Command: magit-find-file-other-window - This command reads a filename and revision from the user and visits the respective blob in a buffer. The buffer is displayed in another window. -- Command: magit-find-file-other-frame - This command reads a filename and revision from the user and visits the respective blob in a buffer. The buffer is displayed in another frame. @@ -4449,8 +4214,7 @@ File: magit.info, Node: Visiting Files and Blobs from a Diff, Prev: General-Pu These commands can only be used when point is inside a diff. -‘RET’ (‘magit-diff-visit-file’) - +‘’ (‘magit-diff-visit-file’) This command visits the appropriate version of the file that the diff at point is about. @@ -4459,17 +4223,17 @@ These commands can only be used when point is inside a diff. being visited. The visited version depends on what changes the diff is about. - • If the diff shows uncommitted changes (i.e. staged or + 1. If the diff shows uncommitted changes (i.e. staged or unstaged changes), then visit the file in the working tree (i.e. the same "real" file that ‘find-file’ would visit. In all other cases visit a "blob" (i.e. the version of a file as stored in some commit). - • If point is on a removed line, then visit the blob for the + 2. If point is on a removed line, then visit the blob for the first parent of the commit that removed that line, i.e. the last commit where that line still exists. - • If point is on an added or context line, then visit the blob + 3. If point is on an added or context line, then visit the blob that adds that line, or if the diff shows from more than a single commit, then visit the blob from the last of these commits. @@ -4481,7 +4245,6 @@ These commands can only be used when point is inside a diff. argument the buffer is displayed in another window instead. -- User Option: magit-diff-visit-previous-blob - This option controls whether ‘magit-diff-visit-file’ may visit the previous blob. When this is ‘t’ (the default) and point is on a removed line in a diff for a committed change, then @@ -4492,8 +4255,7 @@ These commands can only be used when point is inside a diff. and unstaged changes ‘magit-diff-visit-file’ always visits the file in the working tree. -‘C-’ (‘magit-diff-visit-file-worktree’) - +‘C-’ (‘magit-diff-visit-file-worktree’) This command visits the worktree version of the appropriate file. The location of point inside the diff determines which file is being visited. Unlike ‘magit-diff-visit-file’ it always visits the @@ -4537,8 +4299,7 @@ to enter the blaming sub-transient first. The key bindings shown below assume that you enter the dispatch transient using the default binding. -‘C-c M-g B’ (‘magit-blame’) - +‘C-c M-g B’ (‘magit-blame’) This transient prefix command binds the following suffix commands along with the appropriate infix arguments and displays them in a temporary buffer until a suffix is invoked. @@ -4548,9 +4309,9 @@ times. For example if ‘magit-blame-mode’ is not enabled, then the command whose purpose is to turn off that mode would not be of any use and therefore isn’t available. -‘C-c M-g b’ (‘magit-blame-addition’) -‘C-c M-g B b’ (‘magit-blame-addition’) +‘C-c M-g b’ (‘magit-blame-addition’) +‘C-c M-g B b’ This command augments each line or chunk of lines in the current file-visiting or blob-visiting buffer with information about what commits last touched these lines. @@ -4564,27 +4325,27 @@ and therefore isn’t available. ‘magit-find-file’), where REVISION is a parent of the revision that added the current line or chunk of lines. -‘C-c M-g r’ (‘magit-blame-removal’) -‘C-c M-g B r’ (‘magit-blame-removal’) +‘C-c M-g r’ (‘magit-blame-removal’) +‘C-c M-g B r’ This command augments each line or chunk of lines in the current blob-visiting buffer with information about the revision that removes it. It cannot be used in file-visiting buffers. Like ‘magit-blame-addition’, this command can be used recursively. -‘C-c M-g f’ (‘magit-blame-reverse’) -‘C-c M-g B f’ (‘magit-blame-reverse’) +‘C-c M-g f’ (‘magit-blame-reverse’) +‘C-c M-g B f’ This command augments each line or chunk of lines in the current file-visiting or blob-visiting buffer with information about the last revision in which a line still existed. Like ‘magit-blame-addition’, this command can be used recursively. -‘C-c M-g e’ (‘magit-blame-echo’) -‘C-c M-g B e’ (‘magit-blame-echo’) +‘C-c M-g e’ (‘magit-blame-echo’) +‘C-c M-g B e’ This command is like ‘magit-blame-addition’ except that it doesn’t turn on ‘read-only-mode’ and that it initially uses the visualization style specified by option ‘magit-blame-echo-style’. @@ -4594,12 +4355,10 @@ enabled and Read-Only mode is not enabled. These commands are also available in other buffers; here only the behavior is described that is relevant in file-visiting buffers that are being blamed. -‘RET’ (‘magit-show-commit’) - +‘’ (‘magit-show-commit’) This command shows the commit that last touched the line at point. -‘SPC’ (‘magit-diff-show-or-scroll-up’) - +‘’ (‘magit-diff-show-or-scroll-up’) This command updates the commit buffer. This either shows the commit that last touched the line at point in @@ -4608,8 +4367,7 @@ relevant in file-visiting buffers that are being blamed. information about that commit, then the buffer is scrolled up instead. -‘DEL’ (‘magit-diff-show-or-scroll-down’) - +‘DEL’ (‘magit-diff-show-or-scroll-down’) This command updates the commit buffer. This either shows the commit that last touched the line at point in @@ -4621,41 +4379,33 @@ relevant in file-visiting buffers that are being blamed. The following key bindings are available when both Magit-Blame mode and Read-Only mode are enabled. -‘b’ (‘magit-blame’) - +‘b’ (‘magit-blame’) See above. -‘n’ (‘magit-blame-next-chunk’) - +‘n’ (‘magit-blame-next-chunk’) This command moves to the next chunk. -‘N’ (‘magit-blame-next-chunk-same-commit’) - +‘N’ (‘magit-blame-next-chunk-same-commit’) This command moves to the next chunk from the same commit. -‘p’ (‘magit-blame-previous-chunk’) - +‘p’ (‘magit-blame-previous-chunk’) This command moves to the previous chunk. -‘P’ (‘magit-blame-previous-chunk-same-commit’) - +‘P’ (‘magit-blame-previous-chunk-same-commit’) This command moves to the previous chunk from the same commit. -‘q’ (‘magit-blame-quit’) - +‘q’ (‘magit-blame-quit’) This command turns off Magit-Blame mode. If the buffer was created during a recursive blame, then it also kills the buffer. -‘M-w’ (‘magit-blame-copy-hash’) - +‘M-w’ (‘magit-blame-copy-hash’) This command saves the hash of the current chunk’s commit to the kill ring. When the region is active, the command saves the region’s content instead of the hash, like ‘kill-ring-save’ would. -‘c’ (‘magit-blame-cycle-style’) - +‘c’ (‘magit-blame-cycle-style’) This command changes how blame information is visualized in the current buffer by cycling through the styles specified using the option ‘magit-blame-styles’. @@ -4663,35 +4413,29 @@ and Read-Only mode are enabled. Blaming is also controlled using the following options. -- User Option: magit-blame-styles - This option defines a list of styles used to visualize blame information. For now see its doc-string to learn more. -- User Option: magit-blame-echo-style - This option specifies the blame visualization style used by the command ‘magit-blame-echo’. This must be a symbol that is used as the identifier for one of the styles defined in ‘magit-blame-styles’. -- User Option: magit-blame-time-format - This option specifies the format string used to display times when showing blame information. -- User Option: magit-blame-read-only - This option controls whether blaming a buffer also makes temporarily read-only. -- User Option: magit-blame-disable-modes - This option lists incompatible minor-modes that should be disabled temporarily when a buffer contains blame information. They are enabled again when the buffer no longer shows blame information. -- User Option: magit-blame-goto-chunk-hook - This hook is run when moving between chunks.  @@ -4721,8 +4465,7 @@ File: magit.info, Node: Creating Repository, Next: Cloning Repository, Up: Ma 6.1 Creating Repository ======================= -‘M-x magit-init’ (‘magit-init’) - +‘I’ (‘magit-init’) This command initializes a repository and then shows the status buffer for the new repository. @@ -4744,15 +4487,13 @@ can invoke ‘git clone’ directly, depending on whether a prefix argument is used and on the value of ‘magit-clone-always-transient’. -- User Option: magit-clone-always-transient - This option controls whether the command ‘magit-clone’ always acts as a transient prefix command, regardless of whether a prefix argument is used or not. If ‘t’, then that command always acts as a transient prefix. If ‘nil’, then a prefix argument has to be used for it to act as a transient. -‘C’ (‘magit-clone’) - +‘C’ (‘magit-clone’) This command either acts as a transient prefix command as described above or does the same thing as ‘transient-clone-regular’ as described below. @@ -4760,47 +4501,40 @@ is used and on the value of ‘magit-clone-always-transient’. If it acts as a transient prefix, then it binds the following suffix commands and several infix arguments. -‘C C’ (‘magit-clone-regular’) - +‘C C’ (‘magit-clone-regular’) This command creates a regular clone of an existing repository. The repository and the target directory are read from the user. -‘C s’ (‘magit-clone-shallow’) - +‘C s’ (‘magit-clone-shallow’) This command creates a shallow clone of an existing repository. The repository and the target directory are read from the user. By default the depth of the cloned history is a single commit, but with a prefix argument the depth is read from the user. -‘C b’ (‘magit-clone-bare’) - +‘C b’ (‘magit-clone-bare’) This command creates a bare clone of an existing repository. The repository and the target directory are read from the user. -‘C m’ (‘magit-clone-mirror’) - +‘C m’ (‘magit-clone-mirror’) This command creates a mirror of an existing repository. The repository and the target directory are read from the user. The following suffixes are disabled by default. See *note (transient)Enabling and Disabling Suffixes:: for how to enable them. -‘C d’ (‘magit-clone-shallow-since’) - +‘C d’ (‘magit-clone-shallow-since’) This command creates a shallow clone of an existing repository. Only commits that were committed after a date are cloned, which is read from the user. The repository and the target directory are also read from the user. -‘C e’ (‘magit-clone-shallow-exclude’) - +‘C e’ (‘magit-clone-shallow-exclude’) This command creates a shallow clone of an existing repository. This reads a branch or tag from the user. Commits that are reachable from that are not cloned. The repository and the target directory are also read from the user. -- User Option: magit-clone-set-remote-head - This option controls whether cloning causes the reference ‘refs/remotes//HEAD’ to be created in the clone. The default is to delete the reference after running ‘git clone’, which @@ -4810,32 +4544,25 @@ is used and on the value of ‘magit-clone-always-transient’. preserves Git’s default behavior of creating the reference. -- User Option: magit-clone-set-remote.pushDefault - This option controls whether the value of the Git variable ‘remote.pushDefault’ is set after cloning. • If ‘t’, then it is always set without asking. - • If ‘ask’, then the users are asked every time they clone a repository. - • If ‘nil’, then it is never set. -- User Option: magit-clone-default-directory - This option control the default directory name used when reading the destination for a cloning operation. • If ‘nil’ (the default), then the value of ‘default-directory’ is used. - • If a directory, then that is used. - • If a function, then that is called with the remote url as the only argument and the returned value is used. -- User Option: magit-clone-name-alist - This option maps regular expressions, which match repository names, to repository urls, making it possible for users to enter short names instead of urls when cloning repositories. @@ -4856,7 +4583,6 @@ is used and on the value of ‘magit-clone-always-transient’. the username itself. -- User Option: magit-clone-url-format - The format specified by this option is used when turning repository names into urls. ‘%h’ is the hostname and ‘%n’ is the repository name, including the name of the owner. @@ -4889,23 +4615,20 @@ apply variants are described in the next section. You can also use Ediff to stage and unstage. See *note Ediffing::. -‘s’ (‘magit-stage’) - +‘s’ (‘magit-stage’) Add the change at point to the staging area. With a prefix argument and an untracked file (or files) at point, stage the file but not its content. This makes it possible to stage only a subset of the new file’s changes. -‘S’ (‘magit-stage-modified’) - +‘S’ (‘magit-stage-modified’) Stage all changes to files modified in the worktree. Stage all new content of tracked files and remove tracked files that no longer exist in the working tree from the index also. With a prefix argument also stage previously untracked (but not ignored) files. -‘u’ (‘magit-unstage’) - +‘u’ (‘magit-unstage’) Remove the change at point from the staging area. Only staged changes can be unstaged. But by default this command @@ -4913,18 +4636,15 @@ apply variants are described in the next section. is called on a committed change: it reverses the change in the index but not in the working tree. -‘U’ (‘magit-unstage-all’) - +‘U’ (‘magit-unstage-all’) Remove all changes from the staging area. -- User Option: magit-unstage-committed - This option controls whether ‘magit-unstage’ "unstages" committed changes by reversing them in the index but not the working tree. The alternative is to raise an error. -‘M-x magit-reverse-in-index’ (‘magit-reverse-in-index’) - +‘M-x magit-reverse-in-index’ This command reverses the committed change at point in the index but not the working tree. By default no key is bound directly to this command, but it is indirectly called when ‘u’ @@ -4934,22 +4654,17 @@ apply variants are described in the next section. the working tree, so that it can later be committed using a separate commit. A typical workflow would be: - • Optionally make sure that there are no uncommitted changes. - - • Visit the ‘HEAD’ commit and navigate to the change that should + 1. Optionally make sure that there are no uncommitted changes. + 2. Visit the ‘HEAD’ commit and navigate to the change that should not have been included in that commit. - - • Type ‘u’ (‘magit-unstage’) to reverse it in the index. This + 3. Type ‘u’ (‘magit-unstage’) to reverse it in the index. This assumes that ‘magit-unstage-committed-changes’ is non-nil. - - • Type ‘c e’ to extend ‘HEAD’ with the staged changes, including + 4. Type ‘c e’ to extend ‘HEAD’ with the staged changes, including those that were already staged before. - - • Optionally stage the remaining changes using ‘s’ or ‘S’ and + 5. Optionally stage the remaining changes using ‘s’ or ‘S’ and then type ‘c c’ to create a new commit. -‘M-x magit-reset-index’ (‘magit-reset-index’) - +‘M-x magit-reset-index’ Reset the index to some commit. The commit is read from the user and defaults to the commit at point. If there is no commit at point, then it defaults to ‘HEAD’. @@ -4968,16 +4683,14 @@ Fine-grained un-/staging has to be done from the status or a diff buffer, but it’s also possible to un-/stage all changes made to the file visited in the current buffer right from inside that buffer. -‘M-x magit-stage-file’ (‘magit-stage-file’) - +‘M-x magit-stage-file’ When invoked inside a file-visiting buffer, then stage all changes to that file. In a Magit buffer, stage the file at point if any. Otherwise prompt for a file to be staged. With a prefix argument always prompt the user for a file, even in a file-visiting buffer or when there is a file section at point. -‘M-x magit-unstage-file’ (‘magit-unstage-file’) - +‘M-x magit-unstage-file’ When invoked inside a file-visiting buffer, then unstage all changes to that file. In a Magit buffer, unstage the file at point if any. Otherwise prompt for a file to be unstaged. With a prefix @@ -5017,19 +4730,20 @@ are all implemented using ‘git apply’, which is why they are called What follows are the commands which implement the remaining apply variants. -‘a’ (‘magit-apply’) - +‘a’ (‘magit-apply’) Apply the change at point to the working tree. With a prefix argument fallback to a 3-way merge. Doing so causes the change to be applied to the index as well. -‘k’ (‘magit-discard’) - +‘k’ (‘magit-discard’) Remove the change at point from the working tree. -‘v’ (‘magit-reverse’) + On a hunk or file with unresolved conflicts prompt which side to + keep (while discarding the other). If point is within the text of + a side, then keep that side without prompting. +‘v’ (‘magit-reverse’) Reverse the change at point in the working tree. With a prefix argument fallback to a 3-way merge. Doing so causes @@ -5064,23 +4778,19 @@ File: magit.info, Node: Initiating a Commit, Next: Editing Commit Messages, U Also see *note (gitman)git-commit::. -‘c’ (‘magit-commit’) - +‘c’ (‘magit-commit’) This transient prefix command binds the following suffix commands along with the appropriate infix arguments and displays them in a temporary buffer until a suffix is invoked. -‘c c’ (‘magit-commit-create’) - +‘c c’ (‘magit-commit-create’) Create a new commit on ‘HEAD’. With a prefix argument amend to the commit at ‘HEAD’ instead. -‘c a’ (‘magit-commit-amend’) - +‘c a’ (‘magit-commit-amend’) Amend the last commit. -‘c e’ (‘magit-commit-extend’) - +‘c e’ (‘magit-commit-extend’) Amend the last commit, without editing the message. With a prefix argument keep the committer date, otherwise change it. The option ‘magit-commit-extend-override-date’ can be used to inverse the @@ -5089,8 +4799,7 @@ Also see *note (gitman)git-commit::. Non-interactively respect the optional OVERRIDE-DATE argument and ignore the option. -‘c w’ (‘magit-commit-reword’) - +‘c w’ (‘magit-commit-reword’) Reword the last commit, ignoring staged changes. With a prefix argument keep the committer date, otherwise change it. The option ‘magit-commit-reword-override-date’ can be used to inverse the @@ -5099,32 +4808,27 @@ Also see *note (gitman)git-commit::. Non-interactively respect the optional OVERRIDE-DATE argument and ignore the option. -‘c f’ (‘magit-commit-fixup’) - +‘c f’ (‘magit-commit-fixup’) Create a fixup commit. With a prefix argument the target commit has to be confirmed. Otherwise the commit at point may be used without confirmation depending on the value of option ‘magit-commit-squash-confirm’. -‘c F’ (‘magit-commit-instant-fixup’) - +‘c F’ (‘magit-commit-instant-fixup’) Create a fixup commit and instantly rebase. -‘c s’ (‘magit-commit-squash’) - +‘c s’ (‘magit-commit-squash’) Create a squash commit, without editing the squash message. With a prefix argument the target commit has to be confirmed. Otherwise the commit at point may be used without confirmation depending on the value of option ‘magit-commit-squash-confirm’. -‘c S’ (‘magit-commit-instant-squash’) - +‘c S’ (‘magit-commit-instant-squash’) Create a squash commit and instantly rebase. -‘c A’ (‘magit-commit-augment’) - +‘c A’ (‘magit-commit-augment’) Create a squash commit, editing the squash message. With a prefix argument the target commit has to be confirmed. @@ -5132,20 +4836,19 @@ Also see *note (gitman)git-commit::. depending on the value of option ‘magit-commit-squash-confirm’. -- User Option: magit-commit-ask-to-stage - Whether to ask to stage all unstaged changes when committing and nothing is staged. - -- User Option: magit-commit-extend-override-date + -- User Option: magit-commit-show-diff + Whether the relevant diff is automatically shown when committing. + -- User Option: magit-commit-extend-override-date Whether using ‘magit-commit-extend’ changes the committer date. -- User Option: magit-commit-reword-override-date - Whether using ‘magit-commit-reword’ changes the committer date. -- User Option: magit-commit-squash-confirm - Whether the commit targeted by squash and fixup has to be confirmed. When non-nil then the commit at point (if any) is used as default choice. Otherwise it has to be confirmed. This option @@ -5153,6 +4856,43 @@ Also see *note (gitman)git-commit::. "instant" variants always require confirmation because making an error while using those is harder to recover from. + -- User Option: magit-post-commit-hook + Hook run after creating a commit without the user editing a + message. + + This hook is run by ‘magit-refresh’ if ‘this-command’ is a member + of ‘magit-post-stage-hook-commands’. This only includes commands + named ‘magit-commit-*’ that do *not* require that the user edits + the commit message in a buffer. + + Also see ‘git-commit-post-finish-hook’. + + -- User Option: magit-commit-diff-inhibit-same-window + Whether to inhibit use of same window when showing diff while + committing. + + When writing a commit, then a diff of the changes to be committed + is automatically shown. The idea is that the diff is shown in a + different window of the same frame and for most users that just + works. In other words most users can completely ignore this option + because its value doesn’t make a difference for them. + + However for users who configured Emacs to never create a new window + even when the package explicitly tries to do so, then displaying + two new buffers necessarily means that the first is immediately + replaced by the second. In our case the message buffer is + immediately replaced by the diff buffer, which is of course highly + undesirable. + + A workaround is to suppress this user configuration in this + particular case. Users have to explicitly opt-in by toggling this + option. We cannot enable the workaround unconditionally because + that again causes issues for other users: if the frame is too tiny + or the relevant settings too aggressive, then the diff buffer would + end up being displayed in a new frame. + + Also see . +  File: magit.info, Node: Editing Commit Messages, Prev: Initiating a Commit, Up: Committing @@ -5170,13 +4910,11 @@ return. If the editor returns with a non-zero exit status then ‘git’ does not create the commit. So the most important commands are those for finishing and aborting the commit. -‘C-c C-c’ (‘with-editor-finish’) - +‘C-c C-c’ (‘with-editor-finish’) Finish the current editing session by returning with exit code 0. Git then creates the commit using the message it finds in the file. -‘C-c C-k’ (‘with-editor-cancel’) - +‘C-c C-k’ (‘with-editor-cancel’) Cancel the current editing session by returning with exit code 1. Git then cancels the commit, but leaves the file untouched. @@ -5187,18 +4925,15 @@ message is stored at the beginning and the end of an edit session canceled). It is sometimes useful to bring back messages from that ring. -‘C-c M-s’ (‘git-commit-save-message’) - +‘C-c M-s’ (‘git-commit-save-message’) Save the current buffer content to the commit message ring. -‘M-p’ (‘git-commit-prev-message’) - +‘M-p’ (‘git-commit-prev-message’) Cycle backward through the commit message ring, after saving the current message to the ring. With a numeric prefix ARG, go back ARG comments. -‘M-n’ (‘git-commit-next-message’) - +‘M-n’ (‘git-commit-next-message’) Cycle forward through the commit message ring, after saving the current message to the ring. With a numeric prefix ARG, go back ARG comments. @@ -5211,8 +4946,7 @@ remove ‘magit-commit-diff’ from ‘server-switch-hook’. the changes that are about to be added to that commit or to show those changes alongside those that have already been committed. -‘C-c C-d’ (‘magit-diff-while-committing’) - +‘C-c C-d’ (‘magit-diff-while-committing’) While committing, show the changes that are about to be committed. While amending, invoking the command again toggles between showing just the new changes or all the changes that will be committed. @@ -5230,8 +4964,7 @@ File: magit.info, Node: Using the Revision Stack, Next: Commit Pseudo Headers, Using the Revision Stack ........................ -‘C-c C-w’ (‘magit-pop-revision-stack’) - +‘C-c C-w’ (‘magit-pop-revision-stack’) This command inserts a representation of a revision into the current buffer. It can be used inside buffers used to write commit messages but also in other buffers such as buffers used to edit @@ -5260,7 +4993,6 @@ Using the Revision Stack the minibuffer too. -- User Option: magit-pop-revision-stack-format - This option controls how the command ‘magit-pop-revision-stack’ inserts a revision into the current buffer. @@ -5298,40 +5030,31 @@ Some projects use pseudo headers in commit messages. Magit colorizes such headers and provides some commands to insert such headers. -- User Option: git-commit-known-pseudo-headers - A list of Git pseudo headers to be highlighted. -‘C-c C-i’ (‘git-commit-insert-pseudo-header’) - +‘C-c C-i’ (‘git-commit-insert-pseudo-header’) Insert a commit message pseudo header. -‘C-c C-a’ (‘git-commit-ack’) - +‘C-c C-a’ (‘git-commit-ack’) Insert a header acknowledging that you have looked at the commit. -‘C-c C-r’ (‘git-commit-review’) - +‘C-c C-r’ (‘git-commit-review’) Insert a header acknowledging that you have reviewed the commit. -‘C-c C-s’ (‘git-commit-signoff’) - +‘C-c C-s’ (‘git-commit-signoff’) Insert a header to sign off the commit. -‘C-c C-t’ (‘git-commit-test’) - +‘C-c C-t’ (‘git-commit-test’) Insert a header acknowledging that you have tested the commit. -‘C-c C-o’ (‘git-commit-cc’) - +‘C-c C-o’ (‘git-commit-cc’) Insert a header mentioning someone who might be interested. -‘C-c C-p’ (‘git-commit-reported’) - +‘C-c C-p’ (‘git-commit-reported’) Insert a header mentioning the person who reported the issue being fixed by the commit. -‘C-c M-i’ (‘git-commit-suggested’) - +‘C-c M-i’ (‘git-commit-suggested’) Insert a header mentioning the person who suggested the change.  @@ -5347,7 +5070,6 @@ different major modes in different repositories, which is useful when different projects impose different commit message conventions. -- User Option: git-commit-major-mode - The value of this option is the major mode used to edit Git commit messages. @@ -5357,32 +5079,26 @@ happens in the function ‘git-commit-setup’, which among other things runs the hook ‘git-commit-setup-hook’. -- User Option: git-commit-setup-hook - Hook run at the end of ‘git-commit-setup’. The following functions are suitable for this hook: -- Function: git-commit-save-message - Save the current buffer content to the commit message ring. -- Function: git-commit-setup-changelog-support - After this function is called, ChangeLog entries are treated as paragraphs. -- Function: git-commit-turn-on-auto-fill - Turn on ‘auto-fill-mode’ and set ‘fill-column’ to the value of ‘git-commit-fill-column’. -- Function: git-commit-turn-on-flyspell - Turn on Flyspell mode. Also prevent comments from being checked and finally check current non-comment text. -- Function: git-commit-propertize-diff - Propertize the diff shown inside the commit message buffer. Git inserts such diffs into the commit message template when the ‘--verbose’ argument is used. ‘magit-commit’ by default does not @@ -5391,15 +5107,12 @@ The following functions are suitable for this hook: function exists. -- Function: bug-reference-mode - Hyperlink bug references in the buffer. -- Function: with-editor-usage-message - Show usage information in the echo area. -- User Option: git-commit-setup-hook - Hook run after the user finished writing a commit message. This hook is only run after pressing ‘C-c C-c’ in a buffer used to @@ -5429,18 +5142,15 @@ instead of some code it’s now the human who is reviewing your commits who has to waste some time telling you to fix your commits. -- User Option: git-commit-summary-max-length - The intended maximal length of the summary line of commit messages. Characters beyond this column are colorized to indicate that this preference has been violated. -- User Option: git-commit-fill-column - Column beyond which automatic line-wrapping should happen in commit message buffers. -- User Option: git-commit-finish-query-functions - List of functions called to query before performing commit. The commit message buffer is current while the functions are @@ -5456,13 +5166,11 @@ who has to waste some time telling you to fix your commits. By default the only member is ‘git-commit-check-style-conventions’. -- Function: git-commit-check-style-conventions - This function checks for violations of certain basic style conventions. For each violation it asks users if they want to proceed anyway. -- User Option: git-commit-style-convention-checks - This option controls what conventions the function by the same name tries to enforce. The value is a list of self-explanatory symbols identifying certain conventions; ‘non-empty-second-line’ and @@ -5543,8 +5251,7 @@ used to fetch, pull, merge, rebase, or push branches, i.e. this command deals with branches themselves, not with the commits reachable from them. Those features are available from separate transient command. -‘b’ (‘magit-branch’) - +‘b’ (‘magit-branch’) This transient prefix command binds the following suffix commands and displays them in a temporary buffer until a suffix is invoked. @@ -5552,19 +5259,17 @@ them. Those features are available from separate transient command. branch-related Git variables and allows changing their values. -- User Option: magit-branch-direct-configure - This option controls whether the transient command ‘magit-branch’ - can be used directly change the values Git variables. This + can be used to directly change the values of Git variables. This defaults to ‘t’ (to avoid changing key bindings). When set to ‘nil’, then no variables are displayed by that transient command, and its suffix command ‘magit-branch-configure’ has to be used instead to view and change branch related variables. -‘b C’ (‘magit-branch-configure’) -‘f C’ (‘magit-branch-configure’) -‘F C’ (‘magit-branch-configure’) -‘P C’ (‘magit-branch-configure’) - +‘b C’ (‘magit-branch-configure’) +‘f C’ +‘F C’ +‘P C’ This transient prefix command binds commands that set the value of branch-related variables and displays them in a temporary buffer until the transient is exited. @@ -5580,16 +5285,14 @@ them. Those features are available from separate transient command. The variables are described in *note Branch Git Variables::. -‘b b’ (‘magit-checkout’) - +‘b b’ (‘magit-checkout’) Checkout a revision read in the minibuffer and defaulting to the branch or arbitrary revision at point. If the revision is a local branch then that becomes the current branch. If it is something else then ‘HEAD’ becomes detached. Checkout fails if the working tree or the staging area contain changes. -‘b n’ (‘magit-branch-create’) - +‘b n’ (‘magit-branch-create’) Create a new branch. The user is asked for a branch or arbitrary revision to use as the starting point of the new branch. When a branch name is provided, then that becomes the upstream branch of @@ -5598,15 +5301,13 @@ them. Those features are available from separate transient command. Also see option ‘magit-branch-prefer-remote-upstream’. -‘b c’ (‘magit-branch-and-checkout’) - - This command creates a new branch like ‘magit-branch’, but then - also checks it out. +‘b c’ (‘magit-branch-and-checkout’) + This command creates a new branch like ‘magit-branch-create’, but + then also checks it out. Also see option ‘magit-branch-prefer-remote-upstream’. -‘b l’ (‘magit-branch-checkout’) - +‘b l’ (‘magit-branch-checkout’) This command checks out an existing or new local branch. It reads a branch name from the user offering all local branches and a subset of remote branches as candidates. Remote branches for which @@ -5628,8 +5329,7 @@ them. Those features are available from separate transient command. set to the chosen starting point or something else depends on the value of ‘magit-branch-adjust-remote-upstream-alist’. -‘b s’ (‘magit-branch-spinoff’) - +‘b s’ (‘magit-branch-spinoff’) This command creates and checks out a new branch starting at and tracking the current branch. That branch in turn is reset to the last commit it shares with its upstream. If the current branch has @@ -5656,14 +5356,12 @@ them. Those features are available from separate transient command. branch. If FROM is not reachable from ‘HEAD’ or is reachable from the source branch’s upstream, then an error is raised. -‘b S’ (‘magit-branch-spinout’) - +‘b S’ (‘magit-branch-spinout’) This command behaves like ‘magit-branch-spinoff’, except that it does not change the current branch. If there are any uncommitted changes, then it behaves exactly like ‘magit-branch-spinoff’. -‘b x’ (‘magit-branch-reset’) - +‘b x’ (‘magit-branch-reset’) This command resets a branch, defaulting to the branch at point, to the tip of another branch or any other commit. @@ -5678,26 +5376,22 @@ them. Those features are available from separate transient command. then the target branch is set as the upstream of the branch that is being reset. -‘b k’ (‘magit-branch-delete’) - +‘b k’ (‘magit-branch-delete’) Delete one or multiple branches. If the region marks multiple branches, then offer to delete those. Otherwise, prompt for a single branch to be deleted, defaulting to the branch at point. -‘b r’ (‘magit-branch-rename’) - +‘b r’ (‘magit-branch-rename’) Rename a branch. The branch and the new name are read in the minibuffer. With prefix argument the branch is renamed even if that name conflicts with an existing branch. -- User Option: magit-branch-read-upstream-first - When creating a branch, whether to read the upstream branch before the name of the branch that is to be created. The default is ‘t’, and I recommend you leave it at that. -- User Option: magit-branch-prefer-remote-upstream - This option specifies whether remote upstreams are favored over local upstreams when creating new branches. @@ -5742,7 +5436,6 @@ them. Those features are available from separate transient command. ‘next’, and ‘maint’ to the value of this options. -- User Option: magit-branch-adjust-remote-upstream-alist - The value of this option is an alist of branches to be used as the upstream when branching a remote branch. @@ -5771,7 +5464,7 @@ them. Those features are available from separate transient command. If you use a finite set of non-ephemeral branches across all your repositories, then you might use something like: - (("origin/master" "master" "next" "maint")) + (("origin/master" . ("master" "next" "maint"))) Or if the names of all your ephemeral branches contain a slash, at least in some repositories, then a good value could be: @@ -5783,13 +5476,21 @@ them. Those features are available from separate transient command. (("origin/maint" . "\\`hotfix/") ("origin/master" . "\\`feature/")) - -- Command: magit-branch-orphan + UPSTREAM can be a local branch: + (("master" . ("master" "next" "maint"))) + + Because the main branch is no longer almost always named "master" you +should also account for other common names: + + (("main" . ("main" "master" "next" "maint")) + ("master" . ("main" "master" "next" "maint"))) + + -- Command: magit-branch-orphan This command creates and checks out a new orphan branch with contents from a given revision. -- Command: magit-branch-or-checkout - This command is a hybrid between ‘magit-checkout’ and ‘magit-branch-and-checkout’ and is intended as a replacement for the former in ‘magit-branch’. @@ -5819,31 +5520,25 @@ These variables can be set from the transient prefix command ‘magit-branch’. See *note Branch Commands::. -- Variable: branch.NAME.merge - Together with ‘branch.NAME.remote’ this variable defines the upstream branch of the local branch named NAME. The value of this variable is the full reference of the upstream _branch_. -- Variable: branch.NAME.remote - Together with ‘branch.NAME.merge’ this variable defines the upstream branch of the local branch named NAME. The value of this variable is the name of the upstream _remote_. -- Variable: branch.NAME.rebase - This variable controls whether pulling into the branch named NAME is done by rebasing or by merging the fetched branch. • When ‘true’ then pulling is done by rebasing. - • When ‘false’ then pulling is done by merging. - • When undefined then the value of ‘pull.rebase’ is used. The default of that variable is ‘false’. -- Variable: branch.NAME.pushRemote - This variable specifies the remote that the branch named NAME is usually pushed to. The value has to be the name of an existing remote. @@ -5857,7 +5552,6 @@ These variables can be set from the transient prefix command ‘remote.pushDefault’ is undefined. -- Variable: branch.NAME.description - This variable can be used to describe the branch named NAME. That description is used e.g. when turning the branch into a series of patches. @@ -5866,12 +5560,10 @@ These variables can be set from the transient prefix command branch-specific variables are not set. -- Variable: pull.rebase - This variable specifies whether pulling is done by rebasing or by merging. It can be overwritten using ‘branch.NAME.rebase’. • When ‘true’ then pulling is done by rebasing. - • When ‘false’ (the default) then pulling is done by merging. Since it is never a good idea to merge the upstream branch into a @@ -5880,7 +5572,6 @@ branch-specific variables are not set. to ‘false’. -- Variable: remote.pushDefault - This variable specifies what remote the local branches are usually pushed to. This can be overwritten per branch using ‘branch.NAME.pushRemote’. @@ -5890,7 +5581,6 @@ control whether the various branch-specific variables are automatically set at this time. -- Variable: branch.autoSetupMerge - This variable specifies under what circumstances creating a branch NAME should result in the variables ‘branch.NAME.merge’ and ‘branch.NAME.remote’ being set according to the starting point used @@ -5899,27 +5589,21 @@ set at this time. • When ‘always’ then the variables are set regardless of whether the starting point is a local or a remote branch. - • When ‘true’ (the default) then the variables are set when the starting point is a remote branch, but not when it is a local branch. - • When ‘false’ then the variables are never set. -- Variable: branch.autoSetupRebase - This variable specifies whether creating a branch NAME should result in the variable ‘branch.NAME.rebase’ being set to ‘true’. • When ‘always’ then the variable is set regardless of whether the starting point is a local or a remote branch. - • When ‘local’ then the variable are set when the starting point is a local branch, but not when it is a remote branch. - • When ‘remote’ then the variable are set when the starting point is a remote branch, but not when it is a local branch. - • When ‘never’ (the default) then the variable is never set. Note that the respective commands always change the repository-local @@ -5935,7 +5619,6 @@ e.g.: *note (gitman)git-checkout::. and *note Pushing::. -- User Option: magit-prefer-remote-upstream - This option controls whether commands that read a branch from the user and then set it as the upstream branch, offer a local or a remote branch as default completion candidate, when they have the @@ -5955,7 +5638,6 @@ These commands are not available from the transient ‘magit-branch’ by default. -- Command: magit-branch-shelve - This command shelves a branch. This is done by deleting the branch, and creating a new reference "refs/shelved/BRANCH-NAME" pointing at the same commit as the branch pointed at. If the @@ -5966,7 +5648,6 @@ default. not ready to completely discard it yet. -- Command: magit-branch-unshelve - This command unshelves a branch that was previously shelved using ‘magit-branch-shelve’. This is done by deleting the reference "refs/shelved/BRANCH-NAME" and creating a branch "BRANCH-NAME" @@ -5983,8 +5664,7 @@ File: magit.info, Node: Merging, Next: Resolving Conflicts, Prev: Branching, Also see *note (gitman)git-merge::. For information on how to resolve merge conflicts see the next section. -‘m’ (‘magit-merge’) - +‘m’ (‘magit-merge’) This transient prefix command binds the following suffix commands along with the appropriate infix arguments and displays them in a temporary buffer until a suffix is invoked. @@ -5992,8 +5672,7 @@ merge conflicts see the next section. When no merge is in progress, then the transient features the following suffix commands. -‘m m’ (‘magit-merge-plain’) - +‘m m’ (‘magit-merge-plain’) This command merges another branch or an arbitrary revision into the current branch. The branch or revision to be merged is read in the minibuffer and defaults to the branch at point. @@ -6005,22 +5684,19 @@ following suffix commands. merge commit, which makes it possible to inspect how conflicts were resolved and to adjust the commit message. -‘m e’ (‘magit-merge-editmsg’) - +‘m e’ (‘magit-merge-editmsg’) This command merges another branch or an arbitrary revision into the current branch and opens a commit message buffer, so that the user can make adjustments. The commit is not actually created until the user finishes with ‘C-c C-c’. -‘m n’ (‘magit-merge-nocommit’) - +‘m n’ (‘magit-merge-nocommit’) This command merges another branch or an arbitrary revision into the current branch, but does not actually create the merge commit. The user can then further adjust the merge, even when automatic conflict resolution succeeded and/or adjust the commit message. -‘m a’ (‘magit-merge-absorb’) - +‘m a’ (‘magit-merge-absorb’) This command merges another local branch into the current branch and then removes the former. @@ -6032,8 +5708,7 @@ following suffix commands. the merged branch, then the respective remote branch is also removed. -‘m i’ (‘magit-merge-into’) - +‘m i’ (‘magit-merge-into’) This command merges the current branch into another local branch and then removes the former. The latter becomes the new current branch. @@ -6046,8 +5721,7 @@ following suffix commands. the merged branch, then the respective remote branch is also removed. -‘m s’ (‘magit-merge-squash’) - +‘m s’ (‘magit-merge-squash’) This command squashes the changes introduced by another branch or an arbitrary revision into the current branch. This only applies the changes made by the squashed commits. No information is @@ -6055,22 +5729,19 @@ following suffix commands. Instead of this command you should probably use a command from the apply transient. -‘m p’ (‘magit-merge-preview’) - +‘m p’ (‘magit-merge-preview’) This command shows a preview of merging another branch or an arbitrary revision into the current branch. When a merge is in progress, then the transient instead features the following suffix commands. -‘m m’ (‘magit-merge’) - +‘m m’ (‘magit-merge’) After the user resolved conflicts, this command proceeds with the merge. If some conflicts weren’t resolved, then this command fails. -‘m a’ (‘magit-merge-abort’) - +‘m a’ (‘magit-merge-abort’) This command aborts the current merge operation.  @@ -6168,6 +5839,13 @@ the Magit status buffer. The file should now be shown as "modified", no longer as "unmerged", because Smerge automatically stages the file when you save the buffer after resolving the last conflict. + Magit now wraps the mentioned Smerge commands, allowing you to use +these key bindings without having to go to the file-visiting buffer. +Additionally ‘k’ (‘magit-discard’) on a hunk with unresolved conflicts +asks which side to keep or, if point is on a side, then it keeps it +without prompting. Similarly ‘k’ on a unresolved file ask which side to +keep. + Alternatively you could use Ediff, which uses separate buffers for the different versions of the file. To resolve conflicts in a file using Ediff press ‘e’ while point is on such a file in the status @@ -6191,8 +5869,7 @@ File: magit.info, Node: Rebasing, Next: Cherry Picking, Prev: Resolving Confl Also see *note (gitman)git-rebase::. For information on how to resolve conflicts that occur during rebases see the preceding section. -‘r’ (‘magit-rebase’) - +‘r’ (‘magit-rebase’) This transient prefix command binds the following suffix commands along with the appropriate infix arguments and displays them in a temporary buffer until a suffix is invoked. @@ -6210,30 +5887,26 @@ See *note Information About In-Progress Rebase::. For information about the upstream and the push-remote, see *note The Two Remotes::. -‘r p’ (‘magit-rebase-onto-pushremote’) - +‘r p’ (‘magit-rebase-onto-pushremote’) This command rebases the current branch onto its push-remote. With a prefix argument or when the push-remote is either not configured or unusable, then let the user first configure the push-remote. -‘r u’ (‘magit-rebase-onto-upstream’) - +‘r u’ (‘magit-rebase-onto-upstream’) This command rebases the current branch onto its upstream branch. With a prefix argument or when the upstream is either not configured or unusable, then let the user first configure the upstream. -‘r e’ (‘magit-rebase-branch’) - +‘r e’ (‘magit-rebase-branch’) This command rebases the current branch onto a branch read in the minibuffer. All commits that are reachable from head but not from the selected branch TARGET are being rebased. -‘r s’ (‘magit-rebase-subset’) - +‘r s’ (‘magit-rebase-subset’) This command starts a non-interactive rebase sequence to transfer commits from START to ‘HEAD’ onto NEWBASE. START has to be selected from a list of recent commits. @@ -6262,51 +5935,42 @@ only have to redo half the work. following commands as they always use that argument anyway, even if it is not enabled in the transient. -‘r i’ (‘magit-rebase-interactive’) - +‘r i’ (‘magit-rebase-interactive’) This command starts an interactive rebase sequence. -‘r f’ (‘magit-rebase-autosquash’) - +‘r f’ (‘magit-rebase-autosquash’) This command combines squash and fixup commits with their intended targets. -‘r m’ (‘magit-rebase-edit-commit’) - +‘r m’ (‘magit-rebase-edit-commit’) This command starts an interactive rebase sequence that lets the user edit a single older commit. -‘r w’ (‘magit-rebase-reword-commit’) - +‘r w’ (‘magit-rebase-reword-commit’) This command starts an interactive rebase sequence that lets the user reword a single older commit. -‘r k’ (‘magit-rebase-remove-commit’) - +‘r k’ (‘magit-rebase-remove-commit’) This command removes a single older commit using rebase. When a rebase is in progress, then the transient instead features the following suffix commands. -‘r r’ (‘magit-rebase-continue’) - +‘r r’ (‘magit-rebase-continue’) This command restart the current rebasing operation. In some cases this pops up a commit message buffer for you do edit. With a prefix argument the old message is reused as-is. -‘r s’ (‘magit-rebase-skip’) - +‘r s’ (‘magit-rebase-skip’) This command skips the current commit and restarts the current rebase operation. -‘r e’ (‘magit-rebase-edit’) - +‘r e’ (‘magit-rebase-edit’) This command lets the user edit the todo list of the current rebase operation. -‘r a’ (‘magit-rebase-abort’) - +‘r a’ (‘magit-rebase-abort’) This command aborts the current rebase operation, restoring the original branch. @@ -6321,78 +5985,62 @@ File: magit.info, Node: Editing Rebase Sequences, Next: Information About In-P 6.9.1 Editing Rebase Sequences ------------------------------ -‘C-c C-c’ (‘with-editor-finish’) - +‘C-c C-c’ (‘with-editor-finish’) Finish the current editing session by returning with exit code 0. Git then uses the rebase instructions it finds in the file. -‘C-c C-k’ (‘with-editor-cancel’) - +‘C-c C-k’ (‘with-editor-cancel’) Cancel the current editing session by returning with exit code 1. Git then forgoes starting the rebase sequence. -‘RET’ (‘git-rebase-show-commit’) - +‘’ (‘git-rebase-show-commit’) Show the commit on the current line in another buffer and select that buffer. -‘SPC’ (‘git-rebase-show-or-scroll-up’) - +‘’ (‘git-rebase-show-or-scroll-up’) Show the commit on the current line in another buffer without selecting that buffer. If the revision buffer is already visible in another window of the current frame, then instead scroll that window up. -‘DEL’ (‘git-rebase-show-or-scroll-down’) - +‘DEL’ (‘git-rebase-show-or-scroll-down’) Show the commit on the current line in another buffer without selecting that buffer. If the revision buffer is already visible in another window of the current frame, then instead scroll that window down. -‘p’ (‘git-rebase-backward-line’) - +‘p’ (‘git-rebase-backward-line’) Move to previous line. -‘n’ (‘forward-line’) - +‘n’ (‘forward-line’) Move to next line. -‘M-p’ (‘git-rebase-move-line-up’) - +‘M-p’ (‘git-rebase-move-line-up’) Move the current commit (or command) up. -‘M-n’ (‘git-rebase-move-line-down’) - +‘M-n’ (‘git-rebase-move-line-down’) Move the current commit (or command) down. -‘r’ (‘git-rebase-reword’) - +‘r’ (‘git-rebase-reword’) Edit message of commit on current line. -‘e’ (‘git-rebase-edit’) - +‘e’ (‘git-rebase-edit’) Stop at the commit on the current line. -‘s’ (‘git-rebase-squash’) - +‘s’ (‘git-rebase-squash’) Meld commit on current line into previous commit, and edit message. -‘f’ (‘git-rebase-fixup’) - +‘f’ (‘git-rebase-fixup’) Meld commit on current line into previous commit, discarding the current commit’s message. -‘k’ (‘git-rebase-kill-line’) - +‘k’ (‘git-rebase-kill-line’) Kill the current action line. -‘c’ (‘git-rebase-pick’) - +‘c’ (‘git-rebase-pick’) Use commit on current line. -‘x’ (‘git-rebase-exec’) - +‘x’ (‘git-rebase-exec’) Insert a shell command to be run after the proceeding commit. If there already is such a command on the current line, then edit @@ -6400,55 +6048,45 @@ File: magit.info, Node: Editing Rebase Sequences, Next: Information About In-P when there already is one on the current line. With empty input remove the command on the current line, if any. -‘b’ (‘git-rebase-break’) - +‘b’ (‘git-rebase-break’) Insert a break action before the current line, instructing Git to return control to the user. -‘y’ (‘git-rebase-insert’) - +‘y’ (‘git-rebase-insert’) Read an arbitrary commit and insert it below current line. -‘C-x u’ (‘git-rebase-undo’) - +‘C-x u’ (‘git-rebase-undo’) Undo some previous changes. Like ‘undo’ but works in read-only buffers. -- User Option: git-rebase-auto-advance - Whether to move to next line after changing a line. -- User Option: git-rebase-show-instructions - Whether to show usage instructions inside the rebase buffer. -- User Option: git-rebase-confirm-cancel - Whether confirmation is required to cancel. When a rebase is performed with the ‘--rebase-merges’ option, the sequence will include a few other types of actions and the following commands become relevant. -‘l’ (‘git-rebase-label’) - +‘l’ (‘git-rebase-label’) This commands inserts a label action or edits the one at point. -‘t’ (‘git-rebase-reset’) - +‘t’ (‘git-rebase-reset’) This command inserts a reset action or edits the one at point. The prompt will offer the labels that are currently present in the buffer. -‘MM’ (‘git-rebase-merge’) - +‘MM’ (‘git-rebase-merge’) The command inserts a merge action or edits the one at point. The prompt will offer the labels that are currently present in the buffer. Specifying a message to reuse via ‘-c’ or ‘-C’ is not supported; an editor will always be invoked for the merge. -‘Mt’ (‘git-rebase-merge-toggle-editmsg’) - +‘Mt’ (‘git-rebase-merge-toggle-editmsg’) This command toggles between the ‘-C’ and ‘-c’ options of the merge action at point. These options both specify a commit whose message should be reused. The lower-case variant instructs Git to invoke @@ -6644,8 +6282,7 @@ File: magit.info, Node: Cherry Picking, Next: Resetting, Prev: Rebasing, Up: Also see *note (gitman)git-cherry-pick::. -‘A’ (‘magit-cherry-pick’) - +‘A’ (‘magit-cherry-pick’) This transient prefix command binds the following suffix commands along with the appropriate infix arguments and displays them in a temporary buffer until a suffix is invoked. @@ -6653,15 +6290,13 @@ Also see *note (gitman)git-cherry-pick::. When no cherry-pick or revert is in progress, then the transient features the following suffix commands. -‘A A’ (‘magit-cherry-copy’) - +‘A A’ (‘magit-cherry-copy’) This command copies COMMITS from another branch onto the current branch. If the region selects multiple commits, then those are copied, without prompting. Otherwise the user is prompted for a commit or range, defaulting to the commit at point. -‘A a’ (‘magit-cherry-apply’) - +‘A a’ (‘magit-cherry-apply’) This command applies the changes in COMMITS from another branch onto the current branch. If the region selects multiple commits, then those are used, without prompting. Otherwise the user is @@ -6678,8 +6313,7 @@ conflicts. If that happens, then these commands abort and you not only have to resolve the conflicts but also finish the process the same way you would have to if these commands didn’t exist at all. -‘A h’ (‘magit-cherry-harvest’) - +‘A h’ (‘magit-cherry-harvest’) This command moves the selected COMMITS that must be located on another BRANCH onto the current branch instead, removing them from the former. When this command succeeds, then the same branch is @@ -6690,19 +6324,18 @@ you would have to if these commands didn’t exist at all. this command stops and you have to resolve the conflicts and then finish the process manually. -‘A d’ (‘magit-cherry-donate’) - +‘A d’ (‘magit-cherry-donate’) This command moves the selected COMMITS from the current branch onto another existing BRANCH, removing them from the former. When this command succeeds, then the same branch is current as before. + ‘HEAD’ is allowed to be detached initially. Applying the commits on the other branch or removing them from the current branch can lead to conflicts. When that happens, then this command stops and you have to resolve the conflicts and then finish the process manually. -‘A n’ (‘magit-cherry-spinout’) - +‘A n’ (‘magit-cherry-spinout’) This command moves the selected COMMITS from the current branch onto a new branch BRANCH, removing them from the former. When this command succeeds, then the same branch is current as before. @@ -6712,8 +6345,7 @@ you would have to if these commands didn’t exist at all. command stops and you have to resolve the conflicts and then finish the process manually. -‘A s’ (‘magit-cherry-spinoff’) - +‘A s’ (‘magit-cherry-spinoff’) This command moves the selected COMMITS from the current branch onto a new branch BRANCH, removing them from the former. When this command succeeds, then the new branch is checked out. @@ -6726,16 +6358,13 @@ you would have to if these commands didn’t exist at all. When a cherry-pick or revert is in progress, then the transient instead features the following suffix commands. -‘A A’ (‘magit-sequence-continue’) - +‘A A’ (‘magit-sequence-continue’) Resume the current cherry-pick or revert sequence. -‘A s’ (‘magit-sequence-skip’) - +‘A s’ (‘magit-sequence-skip’) Skip the stopped at commit during a cherry-pick or revert sequence. -‘A a’ (‘magit-sequence-abort’) - +‘A a’ (‘magit-sequence-abort’) Abort the current cherry-pick or revert sequence. This discards all changes made since the sequence started. @@ -6749,8 +6378,7 @@ File: magit.info, Node: Reverting, Up: Cherry Picking 6.10.1 Reverting ---------------- -‘V’ (‘magit-revert’) - +‘V’ (‘magit-revert’) This transient prefix command binds the following suffix commands along with the appropriate infix arguments and displays them in a temporary buffer until a suffix is invoked. @@ -6758,14 +6386,12 @@ File: magit.info, Node: Reverting, Up: Cherry Picking When no cherry-pick or revert is in progress, then the transient features the following suffix commands. -‘V V’ (‘magit-revert-and-commit’) - +‘V V’ (‘magit-revert-and-commit’) Revert a commit by creating a new commit. Prompt for a commit, defaulting to the commit at point. If the region selects multiple commits, then revert all of them, without prompting. -‘V v’ (‘magit-revert-no-commit’) - +‘V v’ (‘magit-revert-no-commit’) Revert a commit by applying it in reverse to the working tree. Prompt for a commit, defaulting to the commit at point. If the region selects multiple commits, then revert all of them, without @@ -6774,16 +6400,13 @@ features the following suffix commands. When a cherry-pick or revert is in progress, then the transient instead features the following suffix commands. -‘V A’ (‘magit-sequence-continue’) - +‘V A’ (‘magit-sequence-continue’) Resume the current cherry-pick or revert sequence. -‘V s’ (‘magit-sequence-skip’) - +‘V s’ (‘magit-sequence-skip’) Skip the stopped at commit during a cherry-pick or revert sequence. -‘V a’ (‘magit-sequence-abort’) - +‘V a’ (‘magit-sequence-abort’) Abort the current cherry-pick or revert sequence. This discards all changes made since the sequence started. @@ -6795,50 +6418,42 @@ File: magit.info, Node: Resetting, Next: Stashing, Prev: Cherry Picking, Up: Also see *note (gitman)git-reset::. -‘x’ (‘magit-reset-quickly’) - +‘x’ (‘magit-reset-quickly’) Reset the ‘HEAD’ and index to some commit read from the user and defaulting to the commit at point, and possibly also reset the working tree. With a prefix argument reset the working tree otherwise don’t. -‘X m’ (‘magit-reset-mixed’) - +‘X m’ (‘magit-reset-mixed’) Reset the ‘HEAD’ and index to some commit read from the user and defaulting to the commit at point. The working tree is kept as-is. -‘X s’ (‘magit-reset-soft’) - +‘X s’ (‘magit-reset-soft’) Reset the ‘HEAD’ to some commit read from the user and defaulting to the commit at point. The index and the working tree are kept as-is. -‘X h’ (‘magit-reset-hard’) - +‘X h’ (‘magit-reset-hard’) Reset the ‘HEAD’, index, and working tree to some commit read from the user and defaulting to the commit at point. -‘X k’ (‘magit-reset-keep’) - +‘X k’ (‘magit-reset-keep’) Reset the ‘HEAD’, index, and working tree to some commit read from the user and defaulting to the commit at point. Uncommitted changes are kept as-is. -‘X i’ (‘magit-reset-index’) - +‘X i’ (‘magit-reset-index’) Reset the index to some commit read from the user and defaulting to the commit at point. Keep the ‘HEAD’ and working tree as-is, so if the commit refers to the ‘HEAD’, then this effectively unstages all changes. -‘X w’ (‘magit-reset-worktree’) - +‘X w’ (‘magit-reset-worktree’) Reset the working tree to some commit read from the user and defaulting to the commit at point. Keep the ‘HEAD’ and index as-is. -‘X f’ (‘magit-file-checkout’) - +‘X f’ (‘magit-file-checkout’) Update file in the working tree and index to the contents from a revision. Both the revision and file are read from the user. @@ -6850,111 +6465,92 @@ File: magit.info, Node: Stashing, Prev: Resetting, Up: Manipulating Also see *note (gitman)git-stash::. -‘z’ (‘magit-stash’) - +‘z’ (‘magit-stash’) This transient prefix command binds the following suffix commands along with the appropriate infix arguments and displays them in a temporary buffer until a suffix is invoked. -‘z z’ (‘magit-stash-both’) - +‘z z’ (‘magit-stash-both’) Create a stash of the index and working tree. Untracked files are included according to infix arguments. One prefix argument is equivalent to ‘--include-untracked’ while two prefix arguments are equivalent to ‘--all’. -‘z i’ (‘magit-stash-index’) - +‘z i’ (‘magit-stash-index’) Create a stash of the index only. Unstaged and untracked changes are not stashed. -‘z w’ (‘magit-stash-worktree’) - +‘z w’ (‘magit-stash-worktree’) Create a stash of unstaged changes in the working tree. Untracked files are included according to infix arguments. One prefix argument is equivalent to ‘--include-untracked’ while two prefix arguments are equivalent to ‘--all’. -‘z x’ (‘magit-stash-keep-index’) - +‘z x’ (‘magit-stash-keep-index’) Create a stash of the index and working tree, keeping index intact. Untracked files are included according to infix arguments. One prefix argument is equivalent to ‘--include-untracked’ while two prefix arguments are equivalent to ‘--all’. -‘z Z’ (‘magit-snapshot-both’) - +‘z Z’ (‘magit-snapshot-both’) Create a snapshot of the index and working tree. Untracked files are included according to infix arguments. One prefix argument is equivalent to ‘--include-untracked’ while two prefix arguments are equivalent to ‘--all’. -‘z I’ (‘magit-snapshot-index’) - +‘z I’ (‘magit-snapshot-index’) Create a snapshot of the index only. Unstaged and untracked changes are not stashed. -‘z W’ (‘magit-snapshot-worktree’) - +‘z W’ (‘magit-snapshot-worktree’) Create a snapshot of unstaged changes in the working tree. Untracked files are included according to infix arguments. One prefix argument is equivalent to ‘--include-untracked’ while two prefix arguments are equivalent to ‘--all’-. -‘z a’ (‘magit-stash-apply’) - +‘z a’ (‘magit-stash-apply’) Apply a stash to the working tree. Try to preserve the stash index. If that fails because there are staged changes, apply without preserving the stash index. -‘z p’ (‘magit-stash-pop’) - +‘z p’ (‘magit-stash-pop’) Apply a stash to the working tree and remove it from stash list. Try to preserve the stash index. If that fails because there are staged changes, apply without preserving the stash index and forgo removing the stash. -‘z k’ (‘magit-stash-drop’) - +‘z k’ (‘magit-stash-drop’) Remove a stash from the stash list. When the region is active, offer to drop all contained stashes. -‘z v’ (‘magit-stash-show’) - +‘z v’ (‘magit-stash-show’) Show all diffs of a stash in a buffer. -‘z b’ (‘magit-stash-branch’) - +‘z b’ (‘magit-stash-branch’) Create and checkout a new BRANCH from STASH. The branch starts at the commit that was current when the stash was created. -‘z B’ (‘magit-stash-branch-here’) - +‘z B’ (‘magit-stash-branch-here’) Create and checkout a new BRANCH using ‘magit-branch’ with the current branch or ‘HEAD’ as the starting-point. Then apply STASH, dropping it if it applies cleanly. -‘z f’ (‘magit-stash-format-patch’) - +‘z f’ (‘magit-stash-format-patch’) Create a patch from STASH. -‘k’ (‘magit-stash-clear’) - +‘k’ (‘magit-stash-clear’) Remove all stashes saved in REF’s reflog by deleting REF. -‘z l’ (‘magit-stash-list’) - +‘z l’ (‘magit-stash-list’) List all stashes in a buffer. -- User Option: magit-stashes-margin - This option specifies whether the margin is initially shown in stashes buffers and how it is formatted. The value has the form ‘(INIT STYLE WIDTH AUTHOR AUTHOR-WIDTH)’. • If INIT is non-nil, then the margin is shown initially. - • STYLE controls how to format the author or committer date. It can be one of ‘age’ (to show the age of the commit), ‘age-abbreviated’ (to abbreviate the time unit to a @@ -6962,14 +6558,11 @@ Also see *note (gitman)git-stash::. show the actual date. Option ‘magit-log-margin-show-committer-date’ controls which date is being displayed. - • WIDTH controls the width of the margin. This exists for forward compatibility and currently the value should not be changed. - • AUTHOR controls whether the name of the author is also shown by default. - • AUTHOR-WIDTH has to be an integer. When the name of the author is shown, then this specifies how much space is used to do so. @@ -7013,8 +6606,7 @@ features are available from separate transient commands. Also see *note (gitman)git-remote::. -‘M’ (‘magit-remote’) - +‘M’ (‘magit-remote’) This transient prefix command binds the following suffix commands and displays them in a temporary buffer until a suffix is invoked. @@ -7022,7 +6614,6 @@ features are available from separate transient commands. remote-related Git variables and allows changing their values. -- User Option: magit-remote-direct-configure - This option controls whether remote-related Git variables are accessible directly from the transient ‘magit-remote’. @@ -7033,8 +6624,7 @@ features are available from separate transient commands. If ‘nil’, then ‘magit-remote-configure’ has to be used to do so. -‘M C’ (‘magit-remote-configure’) - +‘M C’ (‘magit-remote-configure’) This transient prefix command binds commands that set the value of remote-related variables and displays them in a temporary buffer until the transient is exited. @@ -7050,32 +6640,26 @@ features are available from separate transient commands. The variables are described in *note Remote Git Variables::. -‘M a’ (‘magit-remote-add’) - +‘M a’ (‘magit-remote-add’) This command add a remote and fetches it. The remote name and url are read in the minibuffer. -‘M r’ (‘magit-remote-rename’) - +‘M r’ (‘magit-remote-rename’) This command renames a remote. Both the old and the new names are read in the minibuffer. -‘M u’ (‘magit-remote-set-url’) - +‘M u’ (‘magit-remote-set-url’) This command changes the url of a remote. Both the remote and the new url are read in the minibuffer. -‘M k’ (‘magit-remote-remove’) - +‘M k’ (‘magit-remote-remove’) This command deletes a remote, read in the minibuffer. -‘M p’ (‘magit-remote-prune’) - +‘M p’ (‘magit-remote-prune’) This command removes stale remote-tracking branches for a remote read in the minibuffer. -‘M P’ (‘magit-remote-prune-refspecs’) - +‘M P’ (‘magit-remote-prune-refspecs’) This command removes stale refspecs for a remote read in the minibuffer. @@ -7093,7 +6677,6 @@ features are available from separate transient commands. not removed. -- User Option: magit-remote-add-set-remote.pushDefault - This option controls whether the user is asked whether they want to set ‘remote.pushDefault’ after adding a remote. @@ -7115,28 +6698,23 @@ These variables can be set from the transient prefix command ‘magit-remote’. See *note Remote Commands::. -- Variable: remote.NAME.url - This variable specifies the url of the remote named NAME. It can have multiple values. -- Variable: remote.NAME.fetch - The refspec used when fetching from the remote named NAME. It can have multiple values. -- Variable: remote.NAME.pushurl - This variable specifies the url used for fetching from the remote named NAME. If it is not specified, then ‘remote.NAME.url’ is used instead. It can have multiple values. -- Variable: remote.NAME.push - The refspec used when pushing to the remote named NAME. It can have multiple values. -- Variable: remote.NAME.tagOpts - This variable specifies what tags are fetched by default. If the value is ‘--no-tags’ then no tags are fetched. If the value is ‘--tags’, then all tags are fetched. If this variable has no @@ -7152,22 +6730,19 @@ File: magit.info, Node: Fetching, Next: Pulling, Prev: Remotes, Up: Transfer Also see *note (gitman)git-fetch::. For information about the upstream and the push-remote, see *note The Two Remotes::. -‘f’ (‘magit-fetch’) - +‘f’ (‘magit-fetch’) This transient prefix command binds the following suffix commands along with the appropriate infix arguments and displays them in a temporary buffer until a suffix is invoked. -‘f p’ (‘magit-fetch-from-pushremote’) - +‘f p’ (‘magit-fetch-from-pushremote’) This command fetches from the current push-remote. With a prefix argument or when the push-remote is either not configured or unusable, then let the user first configure the push-remote. -‘f u’ (‘magit-fetch-from-upstream’) - +‘f u’ (‘magit-fetch-from-upstream’) This command fetch from the upstream of the current branch. If the upstream is configured for the current branch and names an @@ -7179,31 +6754,25 @@ and the push-remote, see *note The Two Remotes::. from the ‘magit-fetch’ transient prefix and invoking it directly results in an error. -‘f e’ (‘magit-fetch-other’) - +‘f e’ (‘magit-fetch-other’) This command fetch from a repository read from the minibuffer. -‘f o’ (‘magit-fetch-branch’) - +‘f o’ (‘magit-fetch-branch’) This command fetches a branch from a remote, both of which are read from the minibuffer. -‘f r’ (‘magit-fetch-refspec’) - +‘f r’ (‘magit-fetch-refspec’) This command fetches from a remote using an explicit refspec, both of which are read from the minibuffer. -‘f a’ (‘magit-fetch-all’) - +‘f a’ (‘magit-fetch-all’) This command fetches from all remotes. -‘f m’ (‘magit-submodule-fetch’) - +‘f m’ (‘magit-submodule-fetch’) This command fetches all submodules. With a prefix argument it fetches all remotes of all submodules. -- User Option: magit-pull-or-fetch - By default fetch and pull commands are available from separate transient prefix command. Setting this to ‘t’ adds some (but not all) of the above suffix commands to the ‘magit-pull’ transient. @@ -7224,29 +6793,25 @@ File: magit.info, Node: Pulling, Next: Pushing, Prev: Fetching, Up: Transfer Also see *note (gitman)git-pull::. For information about the upstream and the push-remote, see *note The Two Remotes::. -‘F’ (‘magit-pull’) - +‘F’ (‘magit-pull’) This transient prefix command binds the following suffix commands and displays them in a temporary buffer until a suffix is invoked. -‘F p’ (‘magit-pull-from-pushremote’) - +‘F p’ (‘magit-pull-from-pushremote’) This command pulls from the push-remote of the current branch. With a prefix argument or when the push-remote is either not configured or unusable, then let the user first configure the push-remote. -‘F u’ (‘magit-pull-from-upstream’) - +‘F u’ (‘magit-pull-from-upstream’) This command pulls from the upstream of the current branch. With a prefix argument or when the upstream is either not configured or unusable, then let the user first configure the upstream. -‘F e’ (‘magit-pull-branch’) - +‘F e’ (‘magit-pull-branch’) This command pulls from a branch read in the minibuffer.  @@ -7258,40 +6823,34 @@ File: magit.info, Node: Pushing, Next: Plain Patches, Prev: Pulling, Up: Tra Also see *note (gitman)git-push::. For information about the upstream and the push-remote, see *note The Two Remotes::. -‘P’ (‘magit-push’) - +‘P’ (‘magit-push’) This transient prefix command binds the following suffix commands along with the appropriate infix arguments and displays them in a temporary buffer until a suffix is invoked. -‘P p’ (‘magit-push-current-to-pushremote’) - +‘P p’ (‘magit-push-current-to-pushremote’) This command pushes the current branch to its push-remote. With a prefix argument or when the push-remote is either not configured or unusable, then let the user first configure the push-remote. -‘P u’ (‘magit-push-current-to-upstream’) - +‘P u’ (‘magit-push-current-to-upstream’) This command pushes the current branch to its upstream branch. With a prefix argument or when the upstream is either not configured or unusable, then let the user first configure the upstream. -‘P e’ (‘magit-push-current’) - +‘P e’ (‘magit-push-current’) This command pushes the current branch to a branch read in the minibuffer. -‘P o’ (‘magit-push-other’) - +‘P o’ (‘magit-push-other’) This command pushes an arbitrary branch or commit somewhere. Both the source and the target are read in the minibuffer. -‘P r’ (‘magit-push-refspecs’) - +‘P r’ (‘magit-push-refspecs’) This command pushes one or multiple refspecs to a remote, both of which are read in the minibuffer. @@ -7299,32 +6858,37 @@ and the push-remote, see *note The Two Remotes::. only available for the part before the colon, or when no colon is used. -‘P m’ (‘magit-push-matching’) - +‘P m’ (‘magit-push-matching’) This command pushes all matching branches to another repository. If only one remote exists, then push to that. Otherwise prompt for a remote, offering the remote configured for the current branch as default. -‘P t’ (‘magit-push-tags’) - +‘P t’ (‘magit-push-tags’) This command pushes all tags to another repository. If only one remote exists, then push to that. Otherwise prompt for a remote, offering the remote configured for the current branch as default. -‘P T’ (‘magit-push-tag’) - +‘P T’ (‘magit-push-tag’) This command pushes a tag to another repository. + One of the infix arguments, ‘--force-with-lease’, deserves a word of +caution. It is passed without a value, which means "permit a force push +as long as the remote-tracking branches match their counterparts on the +remote end". If you’ve set up a tool to do automatic fetches (Magit +itself does not provide such functionality), using ‘--force-with-lease’ +can be dangerous because you don’t actually control or know the state of +the remote-tracking refs. In that case, you should consider setting +‘push.useForceIfIncludes’ to ‘true’ (available since Git 2.30). + Two more push commands exist, which by default are not available from the push transient. See their doc-strings for instructions on how to add them to the transient. -- Command: magit-push-implicitly args - This command pushes somewhere without using an explicit refspec. This command simply runs ‘git push -v [ARGS]’. ARGS are the infix @@ -7342,7 +6906,6 @@ add them to the transient. '(\"i\" magit-push-implicitly))" -- Command: magit-push-to-remote remote args - This command pushes to the remote REMOTE without using an explicit refspec. The remote is read in the minibuffer. @@ -7359,14 +6922,12 @@ File: magit.info, Node: Plain Patches, Next: Maildir Patches, Prev: Pushing, 7.5 Plain Patches ================= -‘W’ (‘magit-patch’) - +‘W’ (‘magit-patch’) This transient prefix command binds the following suffix commands along with the appropriate infix arguments and displays them in a temporary buffer until a suffix is invoked. -‘W c’ (‘magit-patch-create’) - +‘W c’ (‘magit-patch-create’) This command creates patches for a set commits. If the region marks several commits, then it creates patches for all of them. Otherwise it functions as a transient prefix command, which @@ -7374,15 +6935,13 @@ File: magit.info, Node: Plain Patches, Next: Maildir Patches, Prev: Pushing, command. When this command is invoked as a suffix of itself, then it creates a patch using the specified infix arguments. -‘w a’ (‘magit-patch-apply’) - +‘w a’ (‘magit-patch-apply’) This command applies a patch. This is a transient prefix command, which features several infix arguments and binds itself as a suffix command. When this command is invoked as a suffix of itself, then it applies a patch using the specified infix arguments. -‘W s’ (‘magit-patch-save’) - +‘W s’ (‘magit-patch-save’) This command creates a patch from the current diff. Inside ‘magit-diff-mode’ or ‘magit-revision-mode’ buffers, ‘C-x @@ -7399,25 +6958,21 @@ File: magit.info, Node: Maildir Patches, Prev: Plain Patches, Up: Transferrin Also see *note (gitman)git-am::. and *note (gitman)git-apply::. -‘w’ (‘magit-am’) - +‘w’ (‘magit-am’) This transient prefix command binds the following suffix commands along with the appropriate infix arguments and displays them in a temporary buffer until a suffix is invoked. -‘w w’ (‘magit-am-apply-patches’) - +‘w w’ (‘magit-am-apply-patches’) This command applies one or more patches. If the region marks files, then those are applied as patches. Otherwise this command reads a file-name in the minibuffer, defaulting to the file at point. -‘w m’ (‘magit-am-apply-maildir’) - +‘w m’ (‘magit-am-apply-maildir’) This command applies patches from a maildir. -‘w a’ (‘magit-patch-apply’) - +‘w a’ (‘magit-patch-apply’) This command applies a plain patch. For a longer description see *note Plain Patches::. This command is only available from the ‘magit-am’ transient for historic reasons. @@ -7425,17 +6980,14 @@ Also see *note (gitman)git-am::. and *note (gitman)git-apply::. When an "am" operation is in progress, then the transient instead features the following suffix commands. -‘w w’ (‘magit-am-continue’) - +‘w w’ (‘magit-am-continue’) This command resumes the current patch applying sequence. -‘w s’ (‘magit-am-skip’) - +‘w s’ (‘magit-am-skip’) This command skips the stopped at patch during a patch applying sequence. -‘w a’ (‘magit-am-abort’) - +‘w a’ (‘magit-am-abort’) This command aborts the current patch applying sequence. This discards all changes made since the sequence started. @@ -7452,6 +7004,7 @@ File: magit.info, Node: Miscellaneous, Next: Customizing, Prev: Transferring, * Submodules:: * Subtree:: * Worktree:: +* Bundle:: * Common Commands:: * Wip Modes:: * Commands for Buffers Visiting Files:: @@ -7465,19 +7018,16 @@ File: magit.info, Node: Tagging, Next: Notes, Up: Miscellaneous Also see *note (gitman)git-tag::. -‘t’ (‘magit-tag’) - +‘t’ (‘magit-tag’) This transient prefix command binds the following suffix commands along with the appropriate infix arguments and displays them in a temporary buffer until a suffix is invoked. -‘t t’ (‘magit-tag-create’) - +‘t t’ (‘magit-tag-create’) This command creates a new tag with the given NAME at REV. With a - prefix argument it creates an annotate tag. - -‘t r’ (‘magit-tag-release’) + prefix argument it creates an annotated tag. +‘t r’ (‘magit-tag-release’) This commands creates a release tag. It assumes that release tags match ‘magit-release-tag-regexp’. @@ -7496,15 +7046,13 @@ Also see *note (gitman)git-tag::. TAG "v1.2.3" and a repository located at something like "/path/to/foo-bar". -‘t k’ (‘magit-tag-delete’) - +‘t k’ (‘magit-tag-delete’) This command deletes one or more tags. If the region marks multiple tags (and nothing else), then it offers to delete those. Otherwise, it prompts for a single tag to be deleted, defaulting to the tag at point. -‘t p’ (‘magit-tag-prune’) - +‘t p’ (‘magit-tag-prune’) This command offers to delete tags missing locally from REMOTE, and vice versa. @@ -7516,38 +7064,33 @@ File: magit.info, Node: Notes, Next: Submodules, Prev: Tagging, Up: Miscella Also see *note (gitman)git-notes::. -‘T’ (‘magit-notes’) - +‘T’ (‘magit-notes’) This transient prefix command binds the following suffix commands along with the appropriate infix arguments and displays them in a temporary buffer until a suffix is invoked. -‘T T’ (‘magit-notes-edit’) - +‘T T’ (‘magit-notes-edit’) Edit the note attached to a commit, defaulting to the commit at point. By default use the value of Git variable ‘core.notesRef’ or "refs/notes/commits" if that is undefined. -‘T r’ (‘magit-notes-remove’) - +‘T r’ (‘magit-notes-remove’) Remove the note attached to a commit, defaulting to the commit at point. By default use the value of Git variable ‘core.notesRef’ or "refs/notes/commits" if that is undefined. -‘T p’ (‘magit-notes-prune’) - +‘T p’ (‘magit-notes-prune’) Remove notes about unreachable commits. It is possible to merge one note ref into another. That may result in conflicts which have to resolved in the temporary worktree ".git/NOTES_MERGE_WORKTREE". -‘T m’ (‘magit-notes-merge’) - +‘T m’ (‘magit-notes-merge’) Merge the notes of a ref read from the user into the current notes ref. The current notes ref is the value of Git variable ‘core.notesRef’ or "refs/notes/commits" if that is undefined. @@ -7555,13 +7098,11 @@ in conflicts which have to resolved in the temporary worktree When a notes merge is in progress then the transient features the following suffix commands, instead of those listed above. -‘T c’ (‘magit-notes-merge-commit’) - +‘T c’ (‘magit-notes-merge-commit’) Commit the current notes ref merge, after manually resolving conflicts. -‘T a’ (‘magit-notes-merge-abort’) - +‘T a’ (‘magit-notes-merge-abort’) Abort the current notes ref merge. The following variables control what notes reference ‘magit-notes-*’, @@ -7569,12 +7110,10 @@ following suffix commands, instead of those listed above. global values are displayed and can be modified. -- Variable: core.notesRef - This variable specifies the notes ref that is displayed by default and which commands act on by default. -- Variable: notes.displayRef - This variable specifies additional notes ref to be displayed in addition to the ref specified by ‘core.notesRef’. It can have multiple values and may end with ‘*’ to display all refs in the @@ -7607,7 +7146,6 @@ the super-repository by adding ‘magit-insert-modules’ to the hook Sections::. -- Command: magit-list-submodules - This command displays a list of the current repository’s submodules in a separate buffer. @@ -7615,7 +7153,6 @@ Sections::. "Modules". -- User Option: magit-submodule-list-columns - This option controls what columns are displayed by the command ‘magit-list-submodules’ and how they are displayed. @@ -7628,171 +7165,3 @@ Sections::. It has to return a string to be inserted or nil. PROPS is an alist that supports the keys ‘:right-align’ and ‘:pad-right’. - -File: magit.info, Node: Submodule Transient, Prev: Listing Submodules, Up: Submodules - -8.3.2 Submodule Transient -------------------------- - -‘o’ (‘magit-submodule’) - - This transient prefix command binds the following suffix commands - along with the appropriate infix arguments and displays them in a - temporary buffer until a suffix is invoked. - - Some of the below commands default to act on the modules that are -selected using the region. For brevity their description talk about -"the selected modules", but if no modules are selected, then they act on -the current module instead, or if point isn’t on a module, then the read -a single module to act on. With a prefix argument these commands ignore -the selection and the current module and instead act on all suitable -modules. - -‘o a’ (‘magit-submodule-add’) - - This commands adds the repository at URL as a module. Optional - PATH is the path to the module relative to the root of the - super-project. If it is nil then the path is determined based on - URL. - -‘o r’ (‘magit-submodule-register’) - - This command registers the selected modules by copying their urls - from ".gitmodules" to "$GIT_DIR/config". These values can then be - edited before running ‘magit-submodule-populate’. If you don’t - need to edit any urls, then use the latter directly. - -‘o p’ (‘magit-submodule-populate’) - - This command creates the working directory or directories of the - selected modules, checking out the recorded commits. - -‘o u’ (‘magit-submodule-update’) - - This command updates the selected modules checking out the recorded - commits. - -‘o s’ (‘magit-submodule-synchronize’) - - This command synchronizes the urls of the selected modules, copying - the values from ".gitmodules" to the ".git/config" of the - super-project as well those of the modules. - -‘o d’ (‘magit-submodule-unpopulate’) - - This command removes the working directory of the selected modules. - -‘o l’ (‘magit-list-submodules’) - - This command displays a list of the current repository’s modules. - -‘o f’ (‘magit-fetch-modules’) - - This command fetches all modules. - - Option ‘magit-fetch-modules-jobs’ controls how many submodules are - being fetched in parallel. Also fetch the super-repository, - because ‘git fetch’ does not support not doing that. With a prefix - argument fetch all remotes. - - -File: magit.info, Node: Subtree, Next: Worktree, Prev: Submodules, Up: Miscellaneous - -8.4 Subtree -=========== - -Also see *note (gitman)git-subtree::. - -‘O’ (‘magit-subtree’) - - This transient prefix command binds the two sub-transients; one for - importing a subtree and one for exporting a subtree. - -‘O i’ (‘magit-subtree-import’) - - This transient prefix command binds the following suffix commands - along with the appropriate infix arguments and displays them in a - temporary buffer until a suffix is invoked. - - The suffixes of this command import subtrees. - - If the ‘--prefix’ argument is set, then the suffix commands use - that prefix without prompting the user. If it is unset, then they - read the prefix in the minibuffer. - -‘O i a’ (‘magit-subtree-add’) - - This command adds COMMIT from REPOSITORY as a new subtree at - PREFIX. - -‘O i c’ (‘magit-subtree-add-commit’) - - This command add COMMIT as a new subtree at PREFIX. - -‘O i m’ (‘magit-subtree-merge’) - - This command merges COMMIT into the PREFIX subtree. - -‘O i f’ (‘magit-subtree-pull’) - - This command pulls COMMIT from REPOSITORY into the PREFIX subtree. - -‘O e’ (‘magit-subtree-export’) - - This transient prefix command binds the following suffix commands - along with the appropriate infix arguments and displays them in a - temporary buffer until a suffix is invoked. - - The suffixes of this command export subtrees. - - If the ‘--prefix’ argument is set, then the suffix commands use - that prefix without prompting the user. If it is unset, then they - read the prefix in the minibuffer. - -‘O e p’ (‘magit-subtree-push’) - - This command extract the history of the subtree PREFIX and pushes - it to REF on REPOSITORY. - -‘O e s’ (‘magit-subtree-split’) - - This command extracts the history of the subtree PREFIX. - - -File: magit.info, Node: Worktree, Next: Common Commands, Prev: Subtree, Up: Miscellaneous - -8.5 Worktree -============ - -Also see *note (gitman)git-worktree::. - -‘%’ (‘magit-worktree’) - - This transient prefix command binds the following suffix commands - and displays them in a temporary buffer until a suffix is invoked. - -‘% b’ (‘magit-worktree-checkout’) - - Checkout BRANCH in a new worktree at PATH. - -‘% c’ (‘magit-worktree-branch’) - - Create a new BRANCH and check it out in a new worktree at PATH. - -‘% m’ (‘magit-worktree-move’) - - Move an existing worktree to a new PATH. - -‘% k’ (‘magit-worktree-delete’) - - Delete a worktree, defaulting to the worktree at point. The - primary worktree cannot be deleted. - -‘% g’ (‘magit-worktree-status’) - - Show the status for the worktree at point. - - If there is no worktree at point, then read one in the minibuffer. - If the worktree at point is the one whose status is already being - displayed in the current buffer, then show it in Dired instead. - diff --git a/lisp/magit/magit.info-2 b/lisp/magit/magit.info-2 index 7d82a04b..1834f378 100644 --- a/lisp/magit/magit.info-2 +++ b/lisp/magit/magit.info-2 @@ -1,6 +1,6 @@ -This is magit.info, produced by makeinfo version 6.5 from magit.texi. +This is magit.info, produced by makeinfo version 6.7 from magit.texi. - Copyright (C) 2015-2021 Jonas Bernoulli + Copyright (C) 2015-2022 Jonas Bernoulli You can redistribute this document and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -18,17 +18,184 @@ START-INFO-DIR-ENTRY END-INFO-DIR-ENTRY  -File: magit.info, Node: Common Commands, Next: Wip Modes, Prev: Worktree, Up: Miscellaneous +File: magit.info, Node: Submodule Transient, Prev: Listing Submodules, Up: Submodules -8.6 Common Commands +8.3.2 Submodule Transient +------------------------- + +‘o’ (‘magit-submodule’) + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. + + Some of the below commands default to act on the modules that are +selected using the region. For brevity their description talk about +"the selected modules", but if no modules are selected, then they act on +the current module instead, or if point isn’t on a module, then the read +a single module to act on. With a prefix argument these commands ignore +the selection and the current module and instead act on all suitable +modules. + +‘o a’ (‘magit-submodule-add’) + This commands adds the repository at URL as a module. Optional + PATH is the path to the module relative to the root of the + super-project. If it is nil then the path is determined based on + URL. + +‘o r’ (‘magit-submodule-register’) + This command registers the selected modules by copying their urls + from ".gitmodules" to "$GIT_DIR/config". These values can then be + edited before running ‘magit-submodule-populate’. If you don’t + need to edit any urls, then use the latter directly. + +‘o p’ (‘magit-submodule-populate’) + This command creates the working directory or directories of the + selected modules, checking out the recorded commits. + +‘o u’ (‘magit-submodule-update’) + This command updates the selected modules checking out the recorded + commits. + +‘o s’ (‘magit-submodule-synchronize’) + This command synchronizes the urls of the selected modules, copying + the values from ".gitmodules" to the ".git/config" of the + super-project as well those of the modules. + +‘o d’ (‘magit-submodule-unpopulate’) + This command removes the working directory of the selected modules. + +‘o l’ (‘magit-list-submodules’) + This command displays a list of the current repository’s modules. + +‘o f’ (‘magit-fetch-modules’) + This command fetches all modules. + + Option ‘magit-fetch-modules-jobs’ controls how many submodules are + being fetched in parallel. Also fetch the super-repository, + because ‘git fetch’ does not support not doing that. With a prefix + argument fetch all remotes. + + +File: magit.info, Node: Subtree, Next: Worktree, Prev: Submodules, Up: Miscellaneous + +8.4 Subtree +=========== + +Also see *note (gitman)git-subtree::. + +‘O’ (‘magit-subtree’) + This transient prefix command binds the two sub-transients; one for + importing a subtree and one for exporting a subtree. + +‘O i’ (‘magit-subtree-import’) + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. + + The suffixes of this command import subtrees. + + If the ‘--prefix’ argument is set, then the suffix commands use + that prefix without prompting the user. If it is unset, then they + read the prefix in the minibuffer. + +‘O i a’ (‘magit-subtree-add’) + This command adds COMMIT from REPOSITORY as a new subtree at + PREFIX. + +‘O i c’ (‘magit-subtree-add-commit’) + This command add COMMIT as a new subtree at PREFIX. + +‘O i m’ (‘magit-subtree-merge’) + This command merges COMMIT into the PREFIX subtree. + +‘O i f’ (‘magit-subtree-pull’) + This command pulls COMMIT from REPOSITORY into the PREFIX subtree. + +‘O e’ (‘magit-subtree-export’) + This transient prefix command binds the following suffix commands + along with the appropriate infix arguments and displays them in a + temporary buffer until a suffix is invoked. + + The suffixes of this command export subtrees. + + If the ‘--prefix’ argument is set, then the suffix commands use + that prefix without prompting the user. If it is unset, then they + read the prefix in the minibuffer. + +‘O e p’ (‘magit-subtree-push’) + This command extract the history of the subtree PREFIX and pushes + it to REF on REPOSITORY. + +‘O e s’ (‘magit-subtree-split’) + This command extracts the history of the subtree PREFIX. + + +File: magit.info, Node: Worktree, Next: Bundle, Prev: Subtree, Up: Miscellaneous + +8.5 Worktree +============ + +Also see *note (gitman)git-worktree::. + +‘Z’ (‘magit-worktree’) + This transient prefix command binds the following suffix commands + and displays them in a temporary buffer until a suffix is invoked. + +‘Z b’ (‘magit-worktree-checkout’) + Checkout BRANCH in a new worktree at PATH. + +‘Z c’ (‘magit-worktree-branch’) + Create a new BRANCH and check it out in a new worktree at PATH. + +‘Z m’ (‘magit-worktree-move’) + Move an existing worktree to a new PATH. + +‘Z k’ (‘magit-worktree-delete’) + Delete a worktree, defaulting to the worktree at point. The + primary worktree cannot be deleted. + +‘Z g’ (‘magit-worktree-status’) + Show the status for the worktree at point. + + If there is no worktree at point, then read one in the minibuffer. + If the worktree at point is the one whose status is already being + displayed in the current buffer, then show it in Dired instead. + + +File: magit.info, Node: Bundle, Next: Common Commands, Prev: Worktree, Up: Miscellaneous + +8.6 Bundle +========== + +Also see *note (gitman)git-bundle::. + + -- Command: magit-bundle + This transient prefix command binds several suffix commands for + running ‘git bundle’ subcommands and displays them in a temporary + buffer until a suffix is invoked. + + +File: magit.info, Node: Common Commands, Next: Wip Modes, Prev: Bundle, Up: Miscellaneous + +8.7 Common Commands =================== -These are some of the commands that can be used in all buffers whose + -- Command: magit-switch-to-repository-buffer + -- Command: magit-switch-to-repository-buffer-other-window + -- Command: magit-switch-to-repository-buffer-other-frame + -- Command: magit-display-repository-buffer + These commands read any existing Magit buffer that belongs to the + current repository from the user and then switch to the selected + buffer (without refreshing it). + + The last variant uses ‘magit-display-buffer’ to do so and thus + respects ‘magit-display-buffer-function’. + + These are some of the commands that can be used in all buffers whose major-modes derive from ‘magit-mode’. There are other common commands beside the ones below, but these didn’t fit well anywhere else. -‘C-w’ (‘magit-copy-section-value’) - +‘C-w’ (‘magit-copy-section-value’) This command saves the value of the current section to the ‘kill-ring’, and, provided that the current section is a commit, branch, or tag section, it also pushes the (referenced) revision to @@ -45,8 +212,7 @@ beside the ones below, but these didn’t fit well anywhere else. either the added or removed lines, depending on the sign of the prefix argument. -‘M-w’ (‘magit-copy-buffer-revision’) - +‘M-w’ (‘magit-copy-buffer-revision’) This command saves the revision being displayed in the current buffer to the ‘kill-ring’ and also pushes it to the ‘magit-revision-stack’. It is mainly intended for use in @@ -67,7 +233,7 @@ above.  File: magit.info, Node: Wip Modes, Next: Commands for Buffers Visiting Files, Prev: Common Commands, Up: Miscellaneous -8.7 Wip Modes +8.8 Wip Modes ============= Git keeps *committed* changes around long enough for users to recover @@ -95,7 +261,6 @@ then ‘HEAD’ is used in place of ‘’. different wip refs for subsequent changes. -- User Option: magit-wip-mode - When this mode is enabled, then uncommitted changes are committed to dedicated work-in-progress refs whenever appropriate (i.e. when dataloss would be a possibility otherwise). @@ -113,7 +278,6 @@ different wip refs for subsequent changes. when using these commands. -- Command: magit-wip-log - This command shows the log for a branch and its wip refs. With a negative prefix argument only the worktree wip ref is shown. @@ -122,7 +286,6 @@ when using these commands. value of ‘magit-wip-merge-branch’ is ‘nil’. -- Command: magit-wip-log-current - This command shows the log for the current branch and its wip refs. With a negative prefix argument only the worktree wip ref is shown. @@ -130,8 +293,7 @@ when using these commands. "branches" of each wip ref are shown. This is only relevant if the value of ‘magit-wip-merge-branch’ is ‘nil’. -‘X w’ (‘magit-reset-worktree’) - +‘X w’ (‘magit-reset-worktree’) This command resets the working tree to some commit read from the user and defaulting to the commit at point, while keeping the ‘HEAD’ and index as-is. @@ -152,8 +314,7 @@ yourself in the foot. refs, then you can explicitly request that all changes to all tracked files are being committed. -‘M-x magit-wip-commit’ (‘magit-wip-commit’) - +‘M-x magit-wip-commit’ This command commits all changes to all tracked files to the index and working tree work-in-progress refs. Like the modes described above, it does not commit untracked files, but it does check all @@ -161,7 +322,6 @@ files are being committed. the modes might have overlooked a change made outside Emacs/Magit. -- User Option: magit-wip-namespace - The namespace used for work-in-progress refs. It has to end with a slash. The wip refs are named ‘index/’ and ‘wtree/’. When snapshots are created while @@ -169,7 +329,6 @@ files are being committed. ‘’. -- User Option: magit-wip-mode-lighter - Mode-line lighter for ‘magit-wip--mode’. * Menu: @@ -180,11 +339,10 @@ files are being committed.  File: magit.info, Node: Wip Graph, Next: Legacy Wip Modes, Up: Wip Modes -8.7.1 Wip Graph +8.8.1 Wip Graph --------------- -- User Option: magit-wip-merge-branch - This option controls whether the current branch is merged into the wip refs after a new commit was created on the branch. @@ -240,7 +398,7 @@ should be committed to the respective wip ref.  File: magit.info, Node: Legacy Wip Modes, Prev: Wip Graph, Up: Wip Modes -8.7.2 Legacy Wip Modes +8.8.2 Legacy Wip Modes ---------------------- It is recommended that you use the mode ‘magit-wip-mode’ (which see) and @@ -251,13 +409,11 @@ historic reasons. use the Custom interface to do so or call the respective mode functions. -- User Option: magit-wip-after-save-mode - When this mode is enabled, then saving a buffer that visits a file tracked in a Git repository causes its current state to be committed to the working tree wip ref for the current branch. -- User Option: magit-wip-after-apply-mode - When this mode is enabled, then applying (i.e. staging, unstaging, discarding, reversing, and regularly applying) a change to a file tracked in a Git repository causes its current state to be @@ -271,12 +427,10 @@ that. Two additional modes exists that do commit to the wip refs before making changes that could cause the loss of earlier changes. -- User Option: magit-wip-before-change-mode - When this mode is enabled, then certain commands commit the existing changes to the files they are about to make changes to. -- User Option: magit-wip-initial-backup-mode - When this mode is enabled, then the current version of a file is committed to the worktree wip ref before the buffer visiting that file is saved for the first time since the buffer was created. @@ -293,25 +447,21 @@ making changes that could cause the loss of earlier changes. only backs up files that are tracked in a Git repository. -- User Option: magit-wip-after-save-local-mode-lighter - Mode-line lighter for ‘magit-wip-after-save-local-mode’. -- User Option: magit-wip-after-apply-mode-lighter - Mode-line lighter for ‘magit-wip-after-apply-mode’. -- User Option: magit-wip-before-change-mode-lighter - Mode-line lighter for ‘magit-wip-before-change-mode’. -- User Option: magit-wip-initial-backup-mode-lighter - Mode-line lighter for ‘magit-wip-initial-backup-mode’.  File: magit.info, Node: Commands for Buffers Visiting Files, Next: Minor Mode for Buffers Visiting Blobs, Prev: Wip Modes, Up: Miscellaneous -8.8 Commands for Buffers Visiting Files +8.9 Commands for Buffers Visiting Files ======================================= Magit defines a few global key bindings unless the user sets @@ -329,32 +479,27 @@ Bindings:: and *note (elisp)Key Binding Conventions::. The key bindings shown below assume that you have not improved the binding for ‘magit-file-dispatch’. -‘C-c M-g’ (‘magit-file-dispatch’) - +‘C-c M-g’ (‘magit-file-dispatch’) This transient prefix command binds the following suffix commands and displays them in a temporary buffer until a suffix is invoked. When invoked in a buffer that does not visit a file, then it falls back to regular ‘magit-dispatch’. -‘C-c M-g s’ (‘magit-stage-file’) - +‘C-c M-g s’ (‘magit-stage-file’) Stage all changes to the file being visited in the current buffer. -‘C-c M-g u’ (‘magit-unstage-file’) - +‘C-c M-g u’ (‘magit-unstage-file’) Unstage all changes to the file being visited in the current buffer. -‘C-c M-g c’ (‘magit-commit’) - +‘C-c M-g c’ (‘magit-commit’) This transient prefix command binds the following suffix commands along with the appropriate infix arguments and displays them in a temporary buffer until a suffix is invoked. See *note Initiating a Commit::. -‘C-c M-g D’ (‘magit-diff’) - +‘C-c M-g D’ (‘magit-diff’) This transient prefix command binds several diff suffix commands and infix arguments and displays them in a temporary buffer until a suffix is invoked. See *note Diffing::. @@ -364,18 +509,15 @@ binding for ‘magit-file-dispatch’. initial value of the option (‘--’) that limits the diff to certain file(s) is set to the visited file. -‘C-c M-g d’ (‘magit-diff-buffer-file’) - +‘C-c M-g d’ (‘magit-diff-buffer-file’) This command shows the diff for the file of blob that the current buffer visits. -- User Option: magit-diff-buffer-file-locked - This option controls whether ‘magit-diff-buffer-file’ uses a dedicated buffer. See *note Modes and Buffers::. -‘C-c M-g L’ (‘magit-log’) - +‘C-c M-g L’ (‘magit-log’) This transient prefix command binds several log suffix commands and infix arguments and displays them in a temporary buffer until a suffix is invoked. See *note Logging::. @@ -385,24 +527,20 @@ binding for ‘magit-file-dispatch’. initial value of the option (‘--’) that limits the log to certain file(s) is set to the visited file. -‘C-c M-g l’ (‘magit-log-buffer-file’) - +‘C-c M-g l’ (‘magit-log-buffer-file’) This command shows the log for the file of blob that the current buffer visits. Renames are followed when a prefix argument is used or when ‘--follow’ is an active log argument. When the region is active, the log is restricted to the selected line range. -‘C-c M-g t’ (‘magit-log-trace-definition’) - +‘C-c M-g t’ (‘magit-log-trace-definition’) This command shows the log for the definition at point. -- User Option: magit-log-buffer-file-locked - This option controls whether ‘magit-log-buffer-file’ uses a dedicated buffer. See *note Modes and Buffers::. -‘C-c M-g B’ (‘magit-blame’) - +‘C-c M-g B’ (‘magit-blame’) This transient prefix command binds all blaming suffix commands along with the appropriate infix arguments and displays them in a temporary buffer until a suffix is invoked. @@ -414,8 +552,7 @@ binding for ‘magit-file-dispatch’. transient also binds several blaming suffix commands directly. See *note Blaming:: for information about those commands and bindings. -‘C-c M-g e’ (‘magit-edit-line-commit’) - +‘C-c M-g e’ (‘magit-edit-line-commit’) This command makes the commit editable that added the current line. With a prefix argument it makes the commit editable that removes @@ -424,27 +561,22 @@ transient also binds several blaming suffix commands directly. See from ‘HEAD’, or by checking out the commit (or a branch that points at it) otherwise. -‘C-c M-g p’ (‘magit-blob-previous’) - +‘C-c M-g p’ (‘magit-blob-previous’) Visit the previous blob which modified the current file. There are a few additional commands that operate on a single file but are not enabled in the file transient command by default: -- Command: magit-file-rename - This command renames a file read from the user. -- Command: magit-file-delete - This command deletes a file read from the user. -- Command: magit-file-untrack - This command untracks a file read from the user. -- Command: magit-file-checkout - This command updates a file in the working tree and index to the contents from a revision. Both the revision and file are read from the user. @@ -457,8 +589,8 @@ Disabling Suffixes::.  File: magit.info, Node: Minor Mode for Buffers Visiting Blobs, Prev: Commands for Buffers Visiting Files, Up: Miscellaneous -8.9 Minor Mode for Buffers Visiting Blobs -========================================= +8.10 Minor Mode for Buffers Visiting Blobs +========================================== The ‘magit-blob-mode’ enables certain Magit features in blob-visiting buffers. Such buffers can be created using ‘magit-find-file’ and some @@ -466,16 +598,13 @@ of the commands mentioned below, which also take care of turning on this minor mode. Currently this mode only establishes a few key bindings, but this might be extended. -‘p’ (‘magit-blob-previous’) - +‘p’ (‘magit-blob-previous’) Visit the previous blob which modified the current file. -‘n’ (‘magit-blob-next’) - +‘n’ (‘magit-blob-next’) Visit the next blob which modified the current file. -‘q’ (‘magit-kill-this-buffer’) - +‘q’ (‘magit-kill-this-buffer’) Kill the current buffer.  @@ -548,7 +677,6 @@ can disable the respective section inserters just for that repository: . ((eval . (magit-disable-section-inserter 'magit-insert-tags-header))))) -- Function: magit-disable-section-inserter fn - This function disables the section inserter FN in the current repository. It is only intended for use in ‘.dir-locals.el’ and ‘.dir-locals-2.el’. @@ -832,14 +960,6 @@ the faster ‘vfork’ will be used. (The creation of child processes still takes about twice as long on Darwin compared to Linux.) See (1) for more information. - On Catalina, and potentially other macOS releases, there may be a -performance problem where any action takes 20 times longer on Darwin -than on Linux. This can be worked around by setting -‘magit-git-executable’ to the absolute path of the ‘git’ executable, -instead of relying on resolving the ‘$PATH’. You should not do that if -you want to use Magit on remote machines using Tramp and if ‘git’ is not -installed in the same location on those machines. - ---------- Footnotes ---------- (1) @@ -852,7 +972,6 @@ File: magit.info, Node: Default Bindings, Prev: Performance, Up: Essential Se ---------------------- -- User Option: magit-define-global-key-bindings - This option controls whether some Magit commands are automatically bound in the global keymap even before Magit is used for the first time in the current session. @@ -864,7 +983,7 @@ File: magit.info, Node: Default Bindings, Prev: Performance, Up: Essential Se ‘C-x M-g’ ‘magit-dispatch’ ‘C-c M-g’ ‘magit-file-dispatch’ - These bindings may be added when ‘after-init-hook’ is called. Each + These bindings may be added when ‘after-init-hook’ is run. Each binding is added if and only if at that time no other key is bound to the same command and no other command is bound to the same key. In other words we try to avoid adding bindings that are @@ -876,8 +995,14 @@ File: magit.info, Node: Default Bindings, Prev: Performance, Up: Essential Se or autoloaded) and to increase the likelihood that all the potentially conflicting user bindings have already been added. - Setting this variable after the hook has already been called has no - effect. + To set this variable use either ‘setq’ or the Custom interface. Do + not use the function ‘customize-set-variable’ because doing that + would cause Magit to be loaded immediately when that form is + evaluated (this differs from ‘custom-set-variables’, which doesn’t + load the libraries that define the customized variables). + + Setting this variable to nil has no effect if that is done after + the key bindings have already been added. We recommend that you bind ‘C-c g’ instead of ‘C-c M-g’ to ‘magit-file-dispatch’. The former is a much better binding but the @@ -961,46 +1086,37 @@ output. Of course you could also use them to run Git commands that have side-effects, but that should be avoided. -- Function: magit-git-exit-code &rest args - Executes git with ARGS and returns its exit code. -- Function: magit-git-success &rest args - Executes git with ARGS and returns ‘t’ if the exit code is ‘0’, ‘nil’ otherwise. -- Function: magit-git-failure &rest args - Executes git with ARGS and returns ‘t’ if the exit code is ‘1’, ‘nil’ otherwise. -- Function: magit-git-true &rest args - Executes git with ARGS and returns ‘t’ if the first line printed by git is the string "true", ‘nil’ otherwise. -- Function: magit-git-false &rest args - Executes git with ARGS and returns ‘t’ if the first line printed by git is the string "false", ‘nil’ otherwise. -- Function: magit-git-insert &rest args - Executes git with ARGS and inserts its output at point. -- Function: magit-git-string &rest args - Executes git with ARGS and returns the first line of its output. If there is no output or if it begins with a newline character, then this returns ‘nil’. -- Function: magit-git-lines &rest args - Executes git with ARGS and returns its output as a list of lines. Empty lines anywhere in the output are omitted. -- Function: magit-git-items &rest args - Executes git with ARGS and returns its null-separated output as a list. Empty items anywhere in the output are omitted. @@ -1009,13 +1125,25 @@ side-effects, but that should be avoided. and add a section containing git’s standard error in the current repository’s process buffer. + -- Function: magit-process-git destination &rest args + Calls Git synchronously in a separate process, returning its exit + code. DESTINATION specifies how to handle the output, like for + ‘call-process’, except that file handlers are supported. Enables + Cygwin’s "noglob" option during the call and ensures unix eol + conversion. + + -- Function: magit-process-file process &optional infile buffer display + &rest args + Processes files synchronously in a separate process. Identical to + ‘process-file’ but temporarily enables Cygwin’s "noglob" option + during the call and ensures unix eol conversion. + If an error occurs when using one of the above functions, then that is usually due to a bug, i.e. using an argument which is not actually supported. Such errors are usually not reported, but when they occur we need to be able to debug them. -- User Option: magit-git-debug - Whether to report errors that occur when using ‘magit-git-insert’, ‘magit-git-string’, ‘magit-git-lines’, or ‘magit-git-items’. This does not actually raise an error. Instead a message is shown in @@ -1023,7 +1151,6 @@ need to be able to debug them. section in the current repository’s process buffer. -- Function: magit-git-str &rest args - This is a variant of ‘magit-git-string’ that ignores the option ‘magit-git-debug’. It is mainly intended to be used while handling errors in functions that do respect that option. Using such a @@ -1060,49 +1187,28 @@ example after staging a change it is useful to wait until after the refresh because that also automatically moves to the next change. -- Function: magit-call-git &rest args - Calls git synchronously with ARGS. -- Function: magit-call-process program &rest args - Calls PROGRAM synchronously with ARGS. -- Function: magit-run-git &rest args - Calls git synchronously with ARGS and then refreshes. - -- Function: magit-run-git-with-input input &rest args + -- Function: magit-run-git-with-input &rest args + Calls git synchronously with ARGS and sends it the content of the + current buffer on standard input. - Calls git synchronously with ARGS and sends it INPUT on standard - input. - - INPUT should be a buffer or the name of an existing buffer. The - content of that buffer is used as the process’s standard input. - After the process returns a refresh is performed. - - As a special case, INPUT may also be nil. In that case the content - of the current buffer is used as standard input and *no* refresh is - performed. - - This function actually runs git asynchronously. But then it waits - for the process to return, so the function itself is synchronous. - - -- Function: magit-run-git-with-logfile file &rest args - - Calls git synchronously with ARGS. The process’s output is saved - in FILE. This is rarely useful and so this function might be - removed in the future. - - This function actually runs git asynchronously. But then it waits - for the process to return, so the function itself is synchronous. + If the current buffer’s ‘default-directory’ is on a remote + filesystem, this function actually runs git asynchronously. But + then it waits for the process to return, so the function itself is + synchronous. -- Function: magit-git &rest args - Calls git synchronously with ARGS for side-effects only. This function does not refresh the buffer. -- Function: magit-git-wash washer &rest args - Execute Git with ARGS, inserting washed output at point. Actually first insert the raw output at point. If there is no output call ‘magit-cancel-section’. Otherwise temporarily narrow the buffer to @@ -1112,7 +1218,6 @@ refresh because that also automatically moves to the next change. And now for the asynchronous variants. -- Function: magit-run-git-async &rest args - Start Git, prepare for refresh, and return the process object. ARGS is flattened and then used as arguments to Git. @@ -1125,7 +1230,6 @@ refresh because that also automatically moves to the next change. repository are reverted if ‘magit-revert-buffers’ is non-nil. -- Function: magit-run-git-with-editor &rest args - Export GIT_EDITOR and start Git. Also prepare for refresh and return the process object. ARGS is flattened and then used as arguments to Git. @@ -1136,8 +1240,7 @@ refresh because that also automatically moves to the next change. current when this function was called (if it is a Magit buffer and still alive), as well as the respective Magit status buffer. - -- Function: magit-start-git &rest args - + -- Function: magit-start-git input &rest args Start Git, prepare for refresh, and return the process object. If INPUT is non-nil, it has to be a buffer or the name of an @@ -1156,7 +1259,6 @@ refresh because that also automatically moves to the next change. repository are reverted if ‘magit-revert-buffers’ is non-nil. -- Function: magit-start-process &rest args - Start PROGRAM, prepare for refresh, and return the process object. If optional argument INPUT is non-nil, it has to be a buffer or the @@ -1178,12 +1280,10 @@ refresh because that also automatically moves to the next change. ‘magit-revert-buffers’ is non-nil. -- Variable: magit-this-process - The child process which is about to start. This can be used to change the filter and sentinel. -- Variable: magit-process-raise-error - When this is non-nil, then ‘magit-process-sentinel’ raises an error if git exits with a non-zero exit status. For debugging purposes. @@ -1206,7 +1306,6 @@ File: magit.info, Node: Creating Sections, Next: Section Selection, Up: Secti ------------------------ -- Macro: magit-insert-section &rest args - Insert a section at point. TYPE is the section type, a symbol. Many commands that act on the @@ -1242,7 +1341,6 @@ File: magit.info, Node: Creating Sections, Next: Section Selection, Up: Secti anything this time around. -- Function: magit-insert-heading &rest args - Insert the heading for the section currently being inserted. This function should only be used inside ‘magit-insert-section’. @@ -1271,13 +1369,11 @@ File: magit.info, Node: Creating Sections, Next: Section Selection, Up: Secti newline character if necessary. -- Function: magit-cancel-section - Cancel the section currently being inserted. This exits the innermost call to ‘magit-insert-section’ and removes all traces of what has already happened inside that call. -- Function: magit-define-section-jumper sym title &optional value - Define an interactive function to go to section SYM. TITLE is the displayed title of the section. @@ -1288,11 +1384,9 @@ File: magit.info, Node: Section Selection, Next: Matching Sections, Prev: Cre ------------------------ -- Function: magit-current-section - Return the section at point. -- Function: magit-region-sections &optional condition multiple - Return a list of the selected sections. When the region is active and constitutes a valid section @@ -1319,7 +1413,6 @@ File: magit.info, Node: Section Selection, Next: Matching Sections, Prev: Cre forms CONDITION can take. -- Function: magit-region-values &optional condition multiple - Return a list of the values of the selected sections. Return the values that themselves would be returned by @@ -1331,23 +1424,19 @@ File: magit.info, Node: Matching Sections, Prev: Section Selection, Up: Secti 10.2.3 Matching Sections ------------------------ -‘M-x magit-describe-section-briefly’ (‘magit-describe-section-briefly’) - +‘M-x magit-describe-section-briefly’ Show information about the section at point. This command is intended for debugging purposes. -- Function: magit-section-ident section - Return an unique identifier for SECTION. The return value has the form ‘((TYPE . VALUE)...)’. -- Function: magit-get-section ident &optional root - Return the section identified by IDENT. IDENT has to be a list as returned by ‘magit-section-ident’. -- Function: magit-section-match condition &optional section - Return ‘t’ if SECTION matches CONDITION. SECTION defaults to the section at point. If SECTION is not specified and there also is no section at point, then return ‘nil’. @@ -1387,7 +1476,6 @@ File: magit.info, Node: Matching Sections, Prev: Section Selection, Up: Secti course you want to be that precise. -- Function: magit-section-value-if condition &optional section - If the section at point matches CONDITION, then return its value. If optional SECTION is non-nil then test whether that matches @@ -1397,7 +1485,6 @@ File: magit.info, Node: Matching Sections, Prev: Section Selection, Up: Secti See ‘magit-section-match’ for the forms CONDITION can take. -- Function: magit-section-case &rest clauses - Choose among clauses on the type of the section at point. Each clause looks like (CONDITION BODY...). The type of the @@ -1413,7 +1500,6 @@ File: magit.info, Node: Matching Sections, Prev: Section Selection, Up: Secti point. -- Variable: magit-root-section - The root section in the current buffer. All other sections are descendants of this section. The value of this variable is set by ‘magit-insert-section’ and you should never modify it. @@ -1421,7 +1507,6 @@ File: magit.info, Node: Matching Sections, Prev: Section Selection, Up: Secti For diff related sections a few additional tools exist. -- Function: magit-diff-type &optional section - Return the diff type of SECTION. The returned type is one of the symbols ‘staged’, ‘unstaged’, @@ -1444,7 +1529,6 @@ File: magit.info, Node: Matching Sections, Prev: Section Selection, Up: Secti type is always ‘committed’. -- Function: magit-diff-scope &optional section strict - Return the diff scope of SECTION or the selected section(s). A diff’s "scope" describes what part of a diff is selected, it is a @@ -1483,7 +1567,6 @@ where ‘*’ may be something like ‘diff’) with the value of -- Macro: magit-mode-setup buffer switch-func mode refresh-func &optional refresh-args - This function displays and selects BUFFER, turns on MODE, and refreshes a first time. @@ -1499,7 +1582,6 @@ where ‘*’ may be something like ‘diff’) with the value of -- Function: magit-mode-display-buffer buffer mode &optional switch-function - This function display BUFFER in some window and select it. BUFFER may be a buffer or a string, the name of a buffer. The buffer is returned. @@ -1514,13 +1596,11 @@ where ‘*’ may be something like ‘diff’) with the value of is used. -- Variable: magit-refresh-function - The value of this buffer-local variable is the function used to refresh the current buffer. It is called with ‘magit-refresh-args’ as arguments. -- Variable: magit-refresh-args - The list of arguments used by ‘magit-refresh-function’ to refresh the current buffer. ‘magit-refresh-function’ is called with these arguments. @@ -1655,18 +1735,17 @@ cater to that. ‘magit-diff-highlight-trailing’, and ‘magit-diff-paint-whitespace’; and insert some whitespace errors into the code you use for testing.) - For e.g. "added lines" you have to adjust three faces: -‘magit-diff-added’, ‘magit-diff-added-highlight’, and -‘smerge-refined-added’. Make sure that the latter works well with both -of the former, as well as ‘smerge-other’ and ‘diff-added’. Then do the -same for the removed lines, context lines, lines added by us, and lines -added by them. Also make sure the respective added, removed, and -context faces use approximately the same saturation for both the -highlighted and unhighlighted variants. Also make sure the file and -diff headings work nicely with context lines (e.g. make them look -different). Line faces should set both the foreground and the -background color. For example, for added lines use two different -greens. + For added lines you have to adjust three faces: ‘magit-diff-added’, +‘magit-diff-added-highlight’, and ‘diff-refined-added’. Make sure that +the latter works well with both of the former, as well as ‘smerge-other’ +and ‘diff-added’. Then do the same for the removed lines, context +lines, lines added by us, and lines added by them. Also make sure the +respective added, removed, and context faces use approximately the same +saturation for both the highlighted and unhighlighted variants. Also +make sure the file and diff headings work nicely with context lines +(e.g. make them look different). Line faces should set both the +foreground and the background color. For example, for added lines use +two different greens. It’s best if the foreground color of both the highlighted and the unhighlighted variants are the same, so you will need to have to find a @@ -1876,6 +1955,8 @@ A.2 FAQ - Issues and Errors * My Git hooks work on the command-line but not inside Magit:: * git-commit-mode isn't used when committing from the command-line:: * Point ends up inside invisible text when jumping to a file-visiting buffer:: +* I am unable to stage when using Tramp from MS Windows:: +* I am no longer able to save popup defaults::  File: magit.info, Node: Magit is slow, Next: I changed several thousand files at once and now Magit is unusable, Up: FAQ - Issues and Errors @@ -2081,7 +2162,7 @@ that succeeds, do nothing else. Otherwise start ‘emacs &’ (and ‘init.el’ must call ‘server-start’) and try to use ‘emacsclient’ again.  -File: magit.info, Node: Point ends up inside invisible text when jumping to a file-visiting buffer, Prev: git-commit-mode isn't used when committing from the command-line, Up: FAQ - Issues and Errors +File: magit.info, Node: Point ends up inside invisible text when jumping to a file-visiting buffer, Next: I am unable to stage when using Tramp from MS Windows, Prev: git-commit-mode isn't used when committing from the command-line, Up: FAQ - Issues and Errors A.2.12 Point ends up inside invisible text when jumping to a file-visiting buffer --------------------------------------------------------------------------------- @@ -2093,6 +2174,43 @@ visible. If that is too drastic for your taste, then you may instead use ‘magit-diff-visit-file-hook’ to reveal the text, possibly using ‘reveal-post-command’ or for Org buffers ‘org-reveal’. + +File: magit.info, Node: I am unable to stage when using Tramp from MS Windows, Next: I am no longer able to save popup defaults, Prev: Point ends up inside invisible text when jumping to a file-visiting buffer, Up: FAQ - Issues and Errors + +A.2.13 I am unable to stage when using Tramp from MS Windows +------------------------------------------------------------ + +Magit may be unable to stage (or otherwise apply) individual hunks when +you are connected to remote machine using Tramp and the local machine +uses MS Windows. + + There appears to be a problem with ‘process-send-eof’ in this +scenario, as mentioned at the end of ‘tramp-tests.el’. I have contacted +the Tramp maintainer about this. For now this unfortunately means that +it just doesn’t work and we cannot do anything about it. If you have +more information, then please comment on +. + + +File: magit.info, Node: I am no longer able to save popup defaults, Prev: I am unable to stage when using Tramp from MS Windows, Up: FAQ - Issues and Errors + +A.2.14 I am no longer able to save popup defaults +------------------------------------------------- + +Magit used to use Magit-Popup to implement the transient popup menus. +Now it used Transient instead, which is Magit-Popup’s successor. + + In the older Magit-Popup menus, it was possible to save user settings +(e.g. setting the gpg signing key for commits) by using ‘C-c C-c’ in +the popup buffer. This would dismiss the popup, but save the settings +as the defaults for future popups. + + When switching to Transient menus, this functionality is now +available via ‘C-x C-s’ instead; the ‘C-x’ prefix has other options as +well when using Transient, which will be displayed when it is typed. +See +for more details. +  File: magit.info, Node: Debugging Tools, Next: Keystroke Index, Prev: FAQ, Up: Top @@ -2103,14 +2221,12 @@ Magit and its dependencies provide a few debugging tools, and we appreciate it very much if you use those tools before reporting an issue. Please include all relevant output when reporting an issue. -‘M-x magit-version’ (‘magit-version’) - +‘M-x magit-version’ This command shows the currently used versions of Magit, Git, and Emacs in the echo area. Non-interactively this just returns the Magit version. -‘M-x magit-emacs-Q-command’ (‘magit-emacs-Q-command’) - +‘M-x magit-emacs-Q-command’ This command shows a debugging shell command in the echo area and adds it to the kill ring. Paste that command into a shell and run it. @@ -2123,22 +2239,19 @@ issue. Please include all relevant output when reporting an issue. If you run Magit from its Git repository, then you should be able to use ‘make emacs-Q’ instead of the output of this command. -‘M-x magit-toggle-verbose-refresh’ (‘magit-toggle-verbose-refresh’) - +‘M-x magit-toggle-verbose-refresh’ This command toggles whether Magit refreshes buffers verbosely. Enabling this helps figuring out which sections are bottlenecks. The additional output can be found in the ‘*Messages*’ buffer. -‘M-x magit-debug-git-executable’ (‘magit-debug-git-executable’) - +‘M-x magit-debug-git-executable’ This command displays a buffer containing information about the available and used ‘git’ executable(s), and can be useful when investigating ‘exec-path’ issues. Also see *note Git Executable::. -‘M-x with-editor-debug’ (‘with-editor-debug’) - +‘M-x with-editor-debug’ This command displays a buffer containing information about the available and used ‘emacsclient’ executable(s), and can be useful when investigating why Magit (or rather ‘with-editor’) cannot find @@ -2149,7 +2262,7 @@ issue. Please include all relevant output when reporting an issue. Please also see the *note FAQ::.  -File: magit.info, Node: Keystroke Index, Next: Command Index, Prev: Debugging Tools, Up: Top +File: magit.info, Node: Keystroke Index, Next: Function and Command Index, Prev: Debugging Tools, Up: Top Appendix C Keystroke Index ************************** @@ -2158,114 +2271,110 @@ Appendix C Keystroke Index * Menu: * !: Running Git Manually. - (line 12) + (line 13) * ! !: Running Git Manually. (line 17) * ! a: Running Git Manually. - (line 58) -* ! b: Running Git Manually. - (line 62) -* ! g: Running Git Manually. - (line 66) -* ! k: Running Git Manually. (line 54) +* ! b: Running Git Manually. + (line 57) +* ! g: Running Git Manually. + (line 60) +* ! k: Running Git Manually. + (line 51) * ! p: Running Git Manually. - (line 25) + (line 26) * ! s: Running Git Manually. (line 35) * ! S: Running Git Manually. - (line 40) -* $: Viewing Git Output. (line 16) -* %: Worktree. (line 8) -* % b: Worktree. (line 13) -* % c: Worktree. (line 17) -* % g: Worktree. (line 30) -* % k: Worktree. (line 25) -* % m: Worktree. (line 21) -* +: Log Buffer. (line 61) -* + <1>: Refreshing Diffs. (line 69) -* -: Log Buffer. (line 65) -* - <1>: Refreshing Diffs. (line 65) -* 0: Refreshing Diffs. (line 73) + (line 39) +* $: Viewing Git Output. (line 17) +* +: Log Buffer. (line 64) +* + <1>: Refreshing Diffs. (line 61) +* -: Log Buffer. (line 67) +* - <1>: Refreshing Diffs. (line 58) +* 0: Refreshing Diffs. (line 64) * 1: Section Visibility. (line 26) -* 2: Section Visibility. (line 27) -* 3: Section Visibility. (line 28) -* 4: Section Visibility. (line 29) -* =: Log Buffer. (line 55) -* ^: Section Movement. (line 31) -* a: Applying. (line 33) -* A: Cherry Picking. (line 8) +* 2: Section Visibility. (line 26) +* 3: Section Visibility. (line 26) +* 4: Section Visibility. (line 26) +* :: Running Git Manually. + (line 24) +* =: Log Buffer. (line 59) +* ^: Section Movement. (line 28) +* a: Applying. (line 34) +* A: Cherry Picking. (line 9) * A A: Cherry Picking. (line 17) -* A a: Cherry Picking. (line 24) -* A A <1>: Cherry Picking. (line 90) -* A a <1>: Cherry Picking. (line 98) -* A d: Cherry Picking. (line 54) -* A h: Cherry Picking. (line 42) -* A n: Cherry Picking. (line 65) -* A s: Cherry Picking. (line 76) -* A s <1>: Cherry Picking. (line 94) -* B: Bisecting. (line 8) -* b: Blaming. (line 102) -* b <1>: Branch Commands. (line 12) +* A a: Cherry Picking. (line 23) +* A A <1>: Cherry Picking. (line 85) +* A a <1>: Cherry Picking. (line 91) +* A d: Cherry Picking. (line 51) +* A h: Cherry Picking. (line 40) +* A n: Cherry Picking. (line 62) +* A s: Cherry Picking. (line 72) +* A s <1>: Cherry Picking. (line 88) +* B: Bisecting. (line 9) +* b: Blaming. (line 99) +* b <1>: Branch Commands. (line 13) * b <2>: Editing Rebase Sequences. - (line 85) + (line 70) * B B: Bisecting. (line 16) -* B b: Bisecting. (line 34) -* b b: Branch Commands. (line 49) -* b C: Branch Commands. (line 29) -* b c: Branch Commands. (line 67) -* B g: Bisecting. (line 39) -* B k: Bisecting. (line 51) -* b k: Branch Commands. (line 147) -* b l: Branch Commands. (line 74) -* B m: Bisecting. (line 44) -* b n: Branch Commands. (line 57) -* B r: Bisecting. (line 57) -* b r: Branch Commands. (line 153) -* B s: Bisecting. (line 27) -* b s: Branch Commands. (line 97) -* b S: Branch Commands. (line 125) -* b x: Branch Commands. (line 131) -* c: Blaming. (line 135) +* B b: Bisecting. (line 32) +* b b: Branch Commands. (line 47) +* b C: Branch Commands. (line 31) +* b c: Branch Commands. (line 63) +* B g: Bisecting. (line 36) +* B k: Bisecting. (line 46) +* b k: Branch Commands. (line 138) +* b l: Branch Commands. (line 69) +* B m: Bisecting. (line 40) +* b n: Branch Commands. (line 54) +* B r: Bisecting. (line 51) +* b r: Branch Commands. (line 143) +* B s: Bisecting. (line 26) +* b s: Branch Commands. (line 91) +* b S: Branch Commands. (line 118) +* b x: Branch Commands. (line 123) +* c: Blaming. (line 125) * C: Cloning Repository. (line 20) -* c <1>: Initiating a Commit. (line 8) +* c <1>: Initiating a Commit. (line 9) * c <2>: Editing Rebase Sequences. - (line 72) -* c a: Initiating a Commit. (line 19) -* c A: Initiating a Commit. (line 67) -* C b: Cloning Repository. (line 41) -* C C: Cloning Repository. (line 29) + (line 59) +* c a: Initiating a Commit. (line 18) +* c A: Initiating a Commit. (line 59) +* C b: Cloning Repository. (line 38) +* C C: Cloning Repository. (line 28) * c c: Initiating a Commit. (line 14) -* C d: Cloning Repository. (line 54) -* C e: Cloning Repository. (line 61) -* c e: Initiating a Commit. (line 23) -* c f: Initiating a Commit. (line 43) -* c F: Initiating a Commit. (line 51) -* C m: Cloning Repository. (line 46) -* C s: Cloning Repository. (line 34) -* c s: Initiating a Commit. (line 55) -* c S: Initiating a Commit. (line 63) -* c w: Initiating a Commit. (line 33) +* C d: Cloning Repository. (line 49) +* C e: Cloning Repository. (line 55) +* c e: Initiating a Commit. (line 21) +* c f: Initiating a Commit. (line 39) +* c F: Initiating a Commit. (line 46) +* C m: Cloning Repository. (line 42) +* C s: Cloning Repository. (line 32) +* c s: Initiating a Commit. (line 49) +* c S: Initiating a Commit. (line 56) +* c w: Initiating a Commit. (line 30) * C-: Visiting Files and Blobs from a Diff. - (line 51) + (line 50) * C-: Section Visibility. (line 13) * C-c C-a: Commit Pseudo Headers. - (line 17) -* C-c C-b: Log Buffer. (line 21) -* C-c C-b <1>: Refreshing Diffs. (line 91) -* C-c C-c: Transient Commands. (line 18) -* C-c C-c <1>: Select from Log. (line 20) + (line 16) +* C-c C-b: Log Buffer. (line 20) +* C-c C-b <1>: Refreshing Diffs. (line 80) +* C-c C-c: Transient Commands. (line 19) +* C-c C-c <1>: Select from Log. (line 21) * C-c C-c <2>: Editing Commit Messages. - (line 17) + (line 18) * C-c C-c <3>: Editing Rebase Sequences. - (line 6) -* C-c C-d: Refreshing Diffs. (line 81) + (line 7) +* C-c C-d: Refreshing Diffs. (line 71) * C-c C-d <1>: Editing Commit Messages. - (line 58) + (line 54) * C-c C-e: Commands Available in Diffs. - (line 25) -* C-c C-f: Log Buffer. (line 25) -* C-c C-f <1>: Refreshing Diffs. (line 95) + (line 24) +* C-c C-f: Log Buffer. (line 23) +* C-c C-f <1>: Refreshing Diffs. (line 83) * C-c C-i: Commit Pseudo Headers. (line 13) * C-c C-k: Select from Log. (line 26) @@ -2273,1236 +2382,1185 @@ Appendix C Keystroke Index (line 22) * C-c C-k <2>: Editing Rebase Sequences. (line 11) -* C-c C-n: Log Buffer. (line 29) +* C-c C-n: Log Buffer. (line 26) * C-c C-o: Commit Pseudo Headers. - (line 33) + (line 28) * C-c C-p: Commit Pseudo Headers. - (line 37) + (line 31) * C-c C-r: Commit Pseudo Headers. - (line 21) + (line 19) * C-c C-s: Commit Pseudo Headers. - (line 25) + (line 22) * C-c C-t: Commands Available in Diffs. - (line 14) + (line 15) * C-c C-t <1>: Commit Pseudo Headers. - (line 29) + (line 25) * C-c C-w: Using the Revision Stack. - (line 6) + (line 7) * C-c M-g: Commands for Buffers Visiting Files. - (line 21) -* C-c M-g B: Blaming. (line 18) + (line 22) +* C-c M-g B: Blaming. (line 19) * C-c M-g b: Blaming. (line 29) * C-c M-g B <1>: Commands for Buffers Visiting Files. - (line 93) -* C-c M-g B b: Blaming. (line 30) -* C-c M-g B e: Blaming. (line 64) -* C-c M-g B f: Blaming. (line 55) -* C-c M-g B r: Blaming. (line 46) + (line 83) +* C-c M-g B b: Blaming. (line 31) +* C-c M-g B e: Blaming. (line 65) +* C-c M-g B f: Blaming. (line 56) +* C-c M-g B r: Blaming. (line 47) * C-c M-g c: Commands for Buffers Visiting Files. - (line 38) + (line 36) * C-c M-g D: Commands for Buffers Visiting Files. - (line 45) + (line 42) * C-c M-g d: Commands for Buffers Visiting Files. - (line 56) + (line 52) * C-c M-g e: Blaming. (line 63) * C-c M-g e <1>: Commands for Buffers Visiting Files. - (line 106) + (line 95) * C-c M-g f: Blaming. (line 54) * C-c M-g L: Commands for Buffers Visiting Files. - (line 66) + (line 60) * C-c M-g l: Commands for Buffers Visiting Files. - (line 77) + (line 70) * C-c M-g p: Commands for Buffers Visiting Files. - (line 116) + (line 104) * C-c M-g r: Blaming. (line 45) * C-c M-g s: Commands for Buffers Visiting Files. (line 29) * C-c M-g t: Commands for Buffers Visiting Files. - (line 84) + (line 76) * C-c M-g u: Commands for Buffers Visiting Files. - (line 33) + (line 32) * C-c M-i: Commit Pseudo Headers. - (line 42) + (line 35) * C-c M-s: Editing Commit Messages. - (line 34) -* C-w: Common Commands. (line 10) -* C-x g: Status Buffer. (line 22) + (line 33) +* C-w: Common Commands. (line 22) +* C-x g: Status Buffer. (line 23) * C-x u: Editing Rebase Sequences. - (line 94) -* d: Diffing. (line 21) -* D: Refreshing Diffs. (line 11) -* d c: Diffing. (line 69) + (line 77) +* d: Diffing. (line 22) +* D: Refreshing Diffs. (line 12) +* d c: Diffing. (line 63) * d d: Diffing. (line 27) -* D f: Refreshing Diffs. (line 46) -* D F: Refreshing Diffs. (line 51) +* D f: Refreshing Diffs. (line 41) +* D F: Refreshing Diffs. (line 45) * D g: Refreshing Diffs. (line 17) -* d p: Diffing. (line 61) -* d r: Diffing. (line 31) -* D r: Refreshing Diffs. (line 41) -* d s: Diffing. (line 51) -* D s: Refreshing Diffs. (line 22) -* d t: Diffing. (line 74) -* D t: Refreshing Diffs. (line 37) -* d u: Diffing. (line 57) -* d w: Diffing. (line 45) -* D w: Refreshing Diffs. (line 29) -* DEL: Log Buffer. (line 45) +* d p: Diffing. (line 56) +* d r: Diffing. (line 30) +* D r: Refreshing Diffs. (line 37) +* d s: Diffing. (line 48) +* D s: Refreshing Diffs. (line 21) +* d t: Diffing. (line 67) +* D t: Refreshing Diffs. (line 34) +* d u: Diffing. (line 53) +* d w: Diffing. (line 43) +* D w: Refreshing Diffs. (line 27) +* DEL: Log Buffer. (line 50) * DEL <1>: Commands Available in Diffs. - (line 60) -* DEL <2>: Blaming. (line 89) + (line 56) +* DEL <2>: Blaming. (line 87) * DEL <3>: Editing Rebase Sequences. - (line 28) -* e: Ediffing. (line 9) + (line 25) +* e: Ediffing. (line 10) * E: Ediffing. (line 21) * e <1>: Editing Rebase Sequences. - (line 55) -* E c: Ediffing. (line 65) -* E i: Ediffing. (line 57) -* E m: Ediffing. (line 35) -* E r: Ediffing. (line 26) -* E s: Ediffing. (line 48) -* E u: Ediffing. (line 53) -* E w: Ediffing. (line 61) -* E z: Ediffing. (line 69) + (line 46) +* E c: Ediffing. (line 58) +* E i: Ediffing. (line 52) +* E m: Ediffing. (line 33) +* E r: Ediffing. (line 25) +* E s: Ediffing. (line 45) +* E u: Ediffing. (line 49) +* E w: Ediffing. (line 55) +* E z: Ediffing. (line 61) * f: Editing Rebase Sequences. - (line 63) -* f <1>: Fetching. (line 9) -* F: Pulling. (line 9) -* f a: Fetching. (line 50) -* f C: Branch Commands. (line 30) + (line 52) +* f <1>: Fetching. (line 10) +* F: Pulling. (line 10) +* f a: Fetching. (line 45) +* f C: Branch Commands. (line 31) * F C: Branch Commands. (line 31) -* f e: Fetching. (line 36) -* F e: Pulling. (line 30) -* f m: Fetching. (line 54) -* f o: Fetching. (line 40) +* f e: Fetching. (line 34) +* F e: Pulling. (line 28) +* f m: Fetching. (line 48) +* f o: Fetching. (line 37) * f p: Fetching. (line 15) * F p: Pulling. (line 14) -* f r: Fetching. (line 45) -* f u: Fetching. (line 23) -* F u: Pulling. (line 22) +* f r: Fetching. (line 41) +* f u: Fetching. (line 22) +* F u: Pulling. (line 21) * g: Automatic Refreshing of Magit Buffers. - (line 24) + (line 26) * G: Automatic Refreshing of Magit Buffers. - (line 33) -* j: Commands Available in Diffs. - (line 45) + (line 34) +* H: Section Types and Values. + (line 14) +* I: Creating Repository. (line 7) +* j: Log Buffer. (line 31) +* j <1>: Commands Available in Diffs. + (line 43) * k: Viewing Git Output. (line 24) * k <1>: Applying. (line 40) * k <2>: Editing Rebase Sequences. - (line 68) -* k <3>: Stashing. (line 96) -* l: Logging. (line 29) -* L: Refreshing Logs. (line 11) -* L <1>: Log Buffer. (line 6) -* L <2>: Log Margin. (line 57) + (line 56) +* k <3>: Stashing. (line 82) +* l: Logging. (line 30) +* L: Refreshing Logs. (line 12) +* L <1>: Log Buffer. (line 7) +* L <2>: Log Margin. (line 52) * l <1>: Editing Rebase Sequences. - (line 115) -* l a: Logging. (line 60) -* l b: Logging. (line 56) -* L d: Log Margin. (line 74) + (line 94) +* l a: Logging. (line 55) +* l b: Logging. (line 52) +* L d: Log Margin. (line 66) * L g: Refreshing Logs. (line 17) -* l h: Logging. (line 48) -* l H: Reflog. (line 19) +* l h: Logging. (line 46) +* l H: Reflog. (line 18) * l l: Logging. (line 35) -* l L: Logging. (line 52) -* L L: Log Margin. (line 66) -* L l: Log Margin. (line 70) -* l o: Logging. (line 41) +* l L: Logging. (line 49) +* L L: Log Margin. (line 60) +* L l: Log Margin. (line 63) +* l o: Logging. (line 40) * l O: Reflog. (line 15) -* l r: Reflog. (line 11) -* L s: Refreshing Logs. (line 22) -* L t: Refreshing Logs. (line 37) -* L w: Refreshing Logs. (line 29) -* m: Merging. (line 9) -* M: Remote Commands. (line 13) -* m a: Merging. (line 45) -* m a <1>: Merging. (line 95) -* M a: Remote Commands. (line 50) -* M C: Remote Commands. (line 33) -* m e: Merging. (line 31) -* m i: Merging. (line 58) -* M k: Remote Commands. (line 65) +* l r: Reflog. (line 12) +* L s: Refreshing Logs. (line 21) +* L t: Refreshing Logs. (line 34) +* L w: Refreshing Logs. (line 27) +* m: Merging. (line 10) +* M: Remote Commands. (line 14) +* m a: Merging. (line 42) +* m a <1>: Merging. (line 87) +* M a: Remote Commands. (line 48) +* M C: Remote Commands. (line 32) +* m e: Merging. (line 30) +* m i: Merging. (line 54) +* M k: Remote Commands. (line 60) * m m: Merging. (line 18) -* m m <1>: Merging. (line 89) -* m n: Merging. (line 38) -* m p: Merging. (line 81) -* M p: Remote Commands. (line 69) -* M P: Remote Commands. (line 74) -* M r: Remote Commands. (line 55) -* m s: Merging. (line 72) -* M u: Remote Commands. (line 60) -* M-1: Section Visibility. (line 33) -* M-2: Section Visibility. (line 34) -* M-3: Section Visibility. (line 35) -* M-4: Section Visibility. (line 36) -* M-: Section Visibility. (line 17) -* M-n: Section Movement. (line 26) +* m m <1>: Merging. (line 82) +* m n: Merging. (line 36) +* m p: Merging. (line 75) +* M p: Remote Commands. (line 63) +* M P: Remote Commands. (line 67) +* M r: Remote Commands. (line 52) +* m s: Merging. (line 67) +* M u: Remote Commands. (line 56) +* M-1: Section Visibility. (line 32) +* M-2: Section Visibility. (line 32) +* M-3: Section Visibility. (line 32) +* M-4: Section Visibility. (line 32) +* M-: Section Visibility. (line 16) +* M-n: Section Movement. (line 24) * M-n <1>: Editing Commit Messages. - (line 44) + (line 41) * M-n <2>: Editing Rebase Sequences. - (line 47) -* M-p: Section Movement. (line 20) + (line 40) +* M-p: Section Movement. (line 19) * M-p <1>: Editing Commit Messages. - (line 38) + (line 36) * M-p <2>: Editing Rebase Sequences. - (line 43) -* M-w: Blaming. (line 127) -* M-w <1>: Common Commands. (line 28) -* M-x magit-debug-git-executable: Git Executable. (line 45) -* M-x magit-debug-git-executable <1>: Debugging Tools. (line 36) -* M-x magit-describe-section-briefly: Section Types and Values. - (line 13) -* M-x magit-describe-section-briefly <1>: Matching Sections. (line 6) -* M-x magit-emacs-Q-command: Debugging Tools. (line 16) -* M-x magit-init: Creating Repository. (line 6) -* M-x magit-reset-index: Staging and Unstaging. - (line 87) -* M-x magit-reverse-in-index: Staging and Unstaging. - (line 62) -* M-x magit-stage-file: Staging from File-Visiting Buffers. - (line 10) -* M-x magit-toggle-buffer-lock: Modes and Buffers. (line 17) -* M-x magit-toggle-verbose-refresh: Debugging Tools. (line 30) -* M-x magit-unstage-file: Staging from File-Visiting Buffers. - (line 18) -* M-x magit-version: Git Executable. (line 17) -* M-x magit-version <1>: Debugging Tools. (line 10) -* M-x magit-wip-commit: Wip Modes. (line 88) -* M-x with-editor-debug: Debugging Tools. (line 44) + (line 37) +* M-w: Blaming. (line 118) +* M-w <1>: Common Commands. (line 39) * MM: Editing Rebase Sequences. - (line 125) + (line 102) * Mt: Editing Rebase Sequences. - (line 132) + (line 108) * n: Section Movement. (line 16) -* n <1>: Blaming. (line 106) -* N: Blaming. (line 110) +* n <1>: Blaming. (line 102) +* N: Blaming. (line 105) * n <2>: Editing Rebase Sequences. - (line 39) + (line 34) * n <3>: Minor Mode for Buffers Visiting Blobs. (line 16) -* o: Submodule Transient. (line 6) -* O: Subtree. (line 8) +* o: Submodule Transient. (line 7) +* O: Subtree. (line 9) * o a: Submodule Transient. (line 20) -* o d: Submodule Transient. (line 50) -* O e: Subtree. (line 42) -* O e p: Subtree. (line 54) -* O e s: Subtree. (line 59) -* o f: Submodule Transient. (line 58) +* o d: Submodule Transient. (line 45) +* O e: Subtree. (line 37) +* O e p: Subtree. (line 48) +* O e s: Subtree. (line 52) +* o f: Submodule Transient. (line 51) * O i: Subtree. (line 13) -* O i a: Subtree. (line 25) -* O i c: Subtree. (line 30) -* O i f: Subtree. (line 38) -* O i m: Subtree. (line 34) -* o l: Submodule Transient. (line 54) -* o p: Submodule Transient. (line 34) -* o r: Submodule Transient. (line 27) -* o s: Submodule Transient. (line 44) -* o u: Submodule Transient. (line 39) -* p: Section Movement. (line 10) -* p <1>: Blaming. (line 114) -* P: Blaming. (line 118) +* O i a: Subtree. (line 24) +* O i c: Subtree. (line 28) +* O i f: Subtree. (line 34) +* O i m: Subtree. (line 31) +* o l: Submodule Transient. (line 48) +* o p: Submodule Transient. (line 32) +* o r: Submodule Transient. (line 26) +* o s: Submodule Transient. (line 40) +* o u: Submodule Transient. (line 36) +* p: Section Movement. (line 11) +* p <1>: Blaming. (line 108) +* P: Blaming. (line 111) * p <2>: Editing Rebase Sequences. - (line 35) -* P <1>: Pushing. (line 9) + (line 31) +* P <1>: Pushing. (line 10) * p <3>: Minor Mode for Buffers Visiting Blobs. - (line 12) -* P C: Branch Commands. (line 32) -* P e: Pushing. (line 31) -* P m: Pushing. (line 50) -* P o: Pushing. (line 36) + (line 13) +* P C: Branch Commands. (line 31) +* P e: Pushing. (line 29) +* P m: Pushing. (line 45) +* P o: Pushing. (line 33) * P p: Pushing. (line 15) -* P r: Pushing. (line 41) -* P t: Pushing. (line 58) -* P T: Pushing. (line 66) -* P u: Pushing. (line 23) -* q: Quitting Windows. (line 6) +* P r: Pushing. (line 37) +* P t: Pushing. (line 52) +* P T: Pushing. (line 59) +* P u: Pushing. (line 22) +* q: Quitting Windows. (line 7) * q <1>: Log Buffer. (line 14) -* q <2>: Blaming. (line 122) +* q <2>: Blaming. (line 114) * q <3>: Minor Mode for Buffers Visiting Blobs. - (line 20) -* r: Rebasing. (line 9) + (line 19) +* r: Rebasing. (line 10) * r <1>: Editing Rebase Sequences. - (line 51) -* r a: Rebasing. (line 123) -* r e: Rebasing. (line 44) -* r e <1>: Rebasing. (line 118) -* r f: Rebasing. (line 84) -* r i: Rebasing. (line 80) -* r k: Rebasing. (line 99) -* r m: Rebasing. (line 89) + (line 43) +* r a: Rebasing. (line 111) +* r e: Rebasing. (line 42) +* r e <1>: Rebasing. (line 107) +* r f: Rebasing. (line 79) +* r i: Rebasing. (line 76) +* r k: Rebasing. (line 91) +* r m: Rebasing. (line 83) * r p: Rebasing. (line 28) -* r r: Rebasing. (line 106) -* r s: Rebasing. (line 50) -* r s <1>: Rebasing. (line 113) -* r u: Rebasing. (line 36) -* r w: Rebasing. (line 94) -* RET: References Buffer. (line 181) +* r r: Rebasing. (line 97) +* r s: Rebasing. (line 47) +* r s <1>: Rebasing. (line 103) +* r u: Rebasing. (line 35) +* r w: Rebasing. (line 87) +* RET: References Buffer. (line 159) * RET <1>: Visiting Files and Blobs from a Diff. - (line 8) + (line 9) * RET <2>: Blaming. (line 75) * RET <3>: Editing Rebase Sequences. - (line 16) + (line 15) * s: Staging and Unstaging. - (line 28) + (line 29) * S: Staging and Unstaging. (line 36) * s <1>: Editing Rebase Sequences. - (line 59) -* S-: Section Visibility. (line 22) -* SPC: Log Buffer. (line 35) + (line 49) +* S-: Section Visibility. (line 20) +* SPC: Log Buffer. (line 41) * SPC <1>: Commands Available in Diffs. - (line 56) -* SPC <2>: Blaming. (line 79) + (line 53) +* SPC <2>: Blaming. (line 78) * SPC <3>: Editing Rebase Sequences. - (line 21) + (line 19) * t: Editing Rebase Sequences. - (line 119) -* t <1>: Tagging. (line 8) -* T: Notes. (line 8) -* T a: Notes. (line 52) -* T c: Notes. (line 47) -* t k: Tagging. (line 39) -* T m: Notes. (line 38) -* t p: Tagging. (line 46) -* T p: Notes. (line 30) -* t r: Tagging. (line 19) -* T r: Notes. (line 22) + (line 97) +* t <1>: Tagging. (line 9) +* T: Notes. (line 9) +* T a: Notes. (line 47) +* T c: Notes. (line 43) +* t k: Tagging. (line 37) +* T m: Notes. (line 35) +* t p: Tagging. (line 43) +* T p: Notes. (line 28) +* t r: Tagging. (line 18) +* T r: Notes. (line 21) * t t: Tagging. (line 14) * T T: Notes. (line 14) -* TAB: Section Visibility. (line 9) +* TAB: Section Visibility. (line 10) * u: Staging and Unstaging. - (line 43) -* U: Staging and Unstaging. - (line 52) -* v: Applying. (line 44) -* V: Reverting. (line 6) -* V A: Reverting. (line 31) -* V a: Reverting. (line 39) -* V s: Reverting. (line 35) -* V V: Reverting. (line 15) -* V v: Reverting. (line 21) -* W: Plain Patches. (line 6) -* w: Maildir Patches. (line 8) -* w a: Plain Patches. (line 21) -* w a <1>: Maildir Patches. (line 25) -* w a <2>: Maildir Patches. (line 43) -* W c: Plain Patches. (line 12) -* w m: Maildir Patches. (line 21) -* W s: Plain Patches. (line 28) -* w s: Maildir Patches. (line 38) -* w w: Maildir Patches. (line 14) -* w w <1>: Maildir Patches. (line 34) -* x: Editing Rebase Sequences. - (line 76) -* x <1>: Resetting. (line 8) -* X f: Resetting. (line 50) -* X h: Resetting. (line 26) -* X i: Resetting. (line 37) -* X k: Resetting. (line 31) -* X m: Resetting. (line 15) -* X s: Resetting. (line 20) -* X w: Resetting. (line 44) -* X w <1>: Wip Modes. (line 66) -* Y: Cherries. (line 17) -* y: References Buffer. (line 6) -* y <1>: Editing Rebase Sequences. - (line 90) -* y c: References Buffer. (line 26) -* y o: References Buffer. (line 32) -* y y: References Buffer. (line 21) -* z: Stashing. (line 8) -* z a: Stashing. (line 59) -* z b: Stashing. (line 81) -* z B: Stashing. (line 86) -* z f: Stashing. (line 92) -* z i: Stashing. (line 21) -* z I: Stashing. (line 47) -* z k: Stashing. (line 72) -* z l: Stashing. (line 100) -* z p: Stashing. (line 65) -* z v: Stashing. (line 77) -* z w: Stashing. (line 26) -* z W: Stashing. (line 52) -* z x: Stashing. (line 33) -* z z: Stashing. (line 14) -* z Z: Stashing. (line 40) - - -File: magit.info, Node: Command Index, Next: Function Index, Prev: Keystroke Index, Up: Top - -Appendix D Command Index -************************ - -[index] -* Menu: - -* forward-line: Editing Rebase Sequences. - (line 39) -* git-commit-ack: Commit Pseudo Headers. - (line 17) -* git-commit-cc: Commit Pseudo Headers. - (line 33) -* git-commit-insert-pseudo-header: Commit Pseudo Headers. - (line 13) -* git-commit-next-message: Editing Commit Messages. - (line 44) -* git-commit-prev-message: Editing Commit Messages. - (line 38) -* git-commit-reported: Commit Pseudo Headers. - (line 37) -* git-commit-review: Commit Pseudo Headers. - (line 21) -* git-commit-save-message: Editing Commit Messages. - (line 34) -* git-commit-signoff: Commit Pseudo Headers. - (line 25) -* git-commit-suggested: Commit Pseudo Headers. (line 42) -* git-commit-test: Commit Pseudo Headers. - (line 29) -* git-rebase-backward-line: Editing Rebase Sequences. - (line 35) -* git-rebase-break: Editing Rebase Sequences. - (line 85) -* git-rebase-edit: Editing Rebase Sequences. - (line 55) -* git-rebase-exec: Editing Rebase Sequences. - (line 76) -* git-rebase-fixup: Editing Rebase Sequences. - (line 63) -* git-rebase-insert: Editing Rebase Sequences. - (line 90) -* git-rebase-kill-line: Editing Rebase Sequences. - (line 68) -* git-rebase-label: Editing Rebase Sequences. - (line 115) -* git-rebase-merge: Editing Rebase Sequences. - (line 125) -* git-rebase-merge-toggle-editmsg: Editing Rebase Sequences. - (line 132) -* git-rebase-move-line-down: Editing Rebase Sequences. - (line 47) -* git-rebase-move-line-up: Editing Rebase Sequences. - (line 43) -* git-rebase-pick: Editing Rebase Sequences. - (line 72) -* git-rebase-reset: Editing Rebase Sequences. - (line 119) -* git-rebase-reword: Editing Rebase Sequences. - (line 51) -* git-rebase-show-commit: Editing Rebase Sequences. - (line 16) -* git-rebase-show-or-scroll-down: Editing Rebase Sequences. - (line 28) -* git-rebase-show-or-scroll-up: Editing Rebase Sequences. - (line 21) -* git-rebase-squash: Editing Rebase Sequences. - (line 59) -* git-rebase-undo: Editing Rebase Sequences. - (line 94) -* ido-enter-magit-status: Status Buffer. (line 72) -* magit-am: Maildir Patches. (line 8) -* magit-am-abort: Maildir Patches. (line 43) -* magit-am-apply-maildir: Maildir Patches. (line 21) -* magit-am-apply-patches: Maildir Patches. (line 14) -* magit-am-continue: Maildir Patches. (line 34) -* magit-am-skip: Maildir Patches. (line 38) -* magit-apply: Applying. (line 33) -* magit-bisect: Bisecting. (line 8) -* magit-bisect-bad: Bisecting. (line 34) -* magit-bisect-good: Bisecting. (line 39) -* magit-bisect-mark: Bisecting. (line 44) -* magit-bisect-reset: Bisecting. (line 57) -* magit-bisect-run: Bisecting. (line 27) -* magit-bisect-skip: Bisecting. (line 51) -* magit-bisect-start: Bisecting. (line 16) -* magit-blame: Blaming. (line 18) -* magit-blame <1>: Blaming. (line 102) -* magit-blame <2>: Commands for Buffers Visiting Files. - (line 93) -* magit-blame-addition: Blaming. (line 29) -* magit-blame-addition <1>: Blaming. (line 30) -* magit-blame-copy-hash: Blaming. (line 127) -* magit-blame-cycle-style: Blaming. (line 135) -* magit-blame-echo: Blaming. (line 63) -* magit-blame-echo <1>: Blaming. (line 64) -* magit-blame-next-chunk: Blaming. (line 106) -* magit-blame-next-chunk-same-commit: Blaming. (line 110) -* magit-blame-previous-chunk: Blaming. (line 114) -* magit-blame-previous-chunk-same-commit: Blaming. (line 118) -* magit-blame-quit: Blaming. (line 122) -* magit-blame-removal: Blaming. (line 45) -* magit-blame-removal <1>: Blaming. (line 46) -* magit-blame-reverse: Blaming. (line 54) -* magit-blame-reverse <1>: Blaming. (line 55) -* magit-blob-next: Minor Mode for Buffers Visiting Blobs. - (line 16) -* magit-blob-previous: Commands for Buffers Visiting Files. - (line 116) -* magit-blob-previous <1>: Minor Mode for Buffers Visiting Blobs. - (line 12) -* magit-branch: Branch Commands. (line 12) -* magit-branch-and-checkout: Branch Commands. (line 67) -* magit-branch-checkout: Branch Commands. (line 74) -* magit-branch-configure: Branch Commands. (line 29) -* magit-branch-configure <1>: Branch Commands. (line 30) -* magit-branch-configure <2>: Branch Commands. (line 31) -* magit-branch-configure <3>: Branch Commands. (line 32) -* magit-branch-create: Branch Commands. (line 57) -* magit-branch-delete: Branch Commands. (line 147) -* magit-branch-or-checkout: Branch Commands. (line 257) -* magit-branch-orphan: Branch Commands. (line 252) -* magit-branch-rename: Branch Commands. (line 153) -* magit-branch-reset: Branch Commands. (line 131) -* magit-branch-shelve: Auxiliary Branch Commands. - (line 9) -* magit-branch-spinoff: Branch Commands. (line 97) -* magit-branch-spinout: Branch Commands. (line 125) -* magit-branch-unshelve: Auxiliary Branch Commands. - (line 20) -* magit-checkout: Branch Commands. (line 49) -* magit-cherry: Cherries. (line 17) -* magit-cherry-apply: Cherry Picking. (line 24) -* magit-cherry-copy: Cherry Picking. (line 17) -* magit-cherry-donate: Cherry Picking. (line 54) -* magit-cherry-harvest: Cherry Picking. (line 42) -* magit-cherry-pick: Cherry Picking. (line 8) -* magit-cherry-spinoff: Cherry Picking. (line 76) -* magit-cherry-spinout: Cherry Picking. (line 65) -* magit-clone: Cloning Repository. (line 20) -* magit-clone-bare: Cloning Repository. (line 41) -* magit-clone-mirror: Cloning Repository. (line 46) -* magit-clone-regular: Cloning Repository. (line 29) -* magit-clone-shallow: Cloning Repository. (line 34) -* magit-clone-shallow-exclude: Cloning Repository. (line 61) -* magit-clone-shallow-since: Cloning Repository. (line 54) -* magit-commit: Initiating a Commit. (line 8) -* magit-commit <1>: Commands for Buffers Visiting Files. - (line 38) -* magit-commit-amend: Initiating a Commit. (line 19) -* magit-commit-augment: Initiating a Commit. (line 67) -* magit-commit-create: Initiating a Commit. (line 14) -* magit-commit-extend: Initiating a Commit. (line 23) -* magit-commit-fixup: Initiating a Commit. (line 43) -* magit-commit-instant-fixup: Initiating a Commit. (line 51) -* magit-commit-instant-squash: Initiating a Commit. (line 63) -* magit-commit-reword: Initiating a Commit. (line 33) -* magit-commit-squash: Initiating a Commit. (line 55) -* magit-copy-buffer-revision: Common Commands. (line 28) -* magit-copy-section-value: Common Commands. (line 10) -* magit-cycle-margin-style: Log Margin. (line 70) -* magit-debug-git-executable: Git Executable. (line 45) -* magit-debug-git-executable <1>: Debugging Tools. (line 36) -* magit-describe-section-briefly: Section Types and Values. - (line 13) -* magit-describe-section-briefly <1>: Matching Sections. (line 6) -* magit-diff: Diffing. (line 21) -* magit-diff <1>: Commands for Buffers Visiting Files. - (line 45) -* magit-diff-buffer-file: Commands for Buffers Visiting Files. - (line 56) -* magit-diff-default-context: Refreshing Diffs. (line 73) -* magit-diff-dwim: Diffing. (line 27) -* magit-diff-edit-hunk-commit: Commands Available in Diffs. - (line 25) -* magit-diff-flip-revs: Refreshing Diffs. (line 46) -* magit-diff-less-context: Refreshing Diffs. (line 65) -* magit-diff-more-context: Refreshing Diffs. (line 69) -* magit-diff-paths: Diffing. (line 61) -* magit-diff-range: Diffing. (line 31) -* magit-diff-refresh: Refreshing Diffs. (line 11) -* magit-diff-refresh <1>: Refreshing Diffs. (line 17) -* magit-diff-save-default-arguments: Refreshing Diffs. (line 29) -* magit-diff-set-default-arguments: Refreshing Diffs. (line 22) -* magit-diff-show-or-scroll-down: Log Buffer. (line 45) -* magit-diff-show-or-scroll-down <1>: Blaming. (line 89) -* magit-diff-show-or-scroll-up: Log Buffer. (line 35) -* magit-diff-show-or-scroll-up <1>: Blaming. (line 79) -* magit-diff-staged: Diffing. (line 51) -* magit-diff-switch-range-type: Refreshing Diffs. (line 41) -* magit-diff-toggle-file-filter: Refreshing Diffs. (line 51) -* magit-diff-toggle-refine-hunk: Refreshing Diffs. (line 37) -* magit-diff-trace-definition: Commands Available in Diffs. - (line 14) -* magit-diff-unstaged: Diffing. (line 57) -* magit-diff-visit-file: Visiting Files and Blobs from a Diff. - (line 8) -* magit-diff-visit-file-other-frame: Visiting Files and Blobs from a Diff. +* U: Staging and Unstaging. + (line 50) +* v: Applying. (line 47) +* V: Reverting. (line 7) +* V A: Reverting. (line 29) +* V a: Reverting. (line 35) +* V s: Reverting. (line 32) +* V V: Reverting. (line 15) +* V v: Reverting. (line 20) +* W: Plain Patches. (line 7) +* w: Maildir Patches. (line 9) +* w a: Plain Patches. (line 20) +* w a <1>: Maildir Patches. (line 23) +* w a <2>: Maildir Patches. (line 38) +* W c: Plain Patches. (line 12) +* w m: Maildir Patches. (line 20) +* W s: Plain Patches. (line 26) +* w s: Maildir Patches. (line 34) +* w w: Maildir Patches. (line 14) +* w w <1>: Maildir Patches. (line 31) +* x: Editing Rebase Sequences. + (line 62) +* x <1>: Resetting. (line 9) +* X f: Resetting. (line 44) +* X h: Resetting. (line 24) +* X i: Resetting. (line 33) +* X k: Resetting. (line 28) +* X m: Resetting. (line 15) +* X s: Resetting. (line 19) +* X w: Resetting. (line 39) +* X w <1>: Wip Modes. (line 64) +* Y: Cherries. (line 18) +* y: References Buffer. (line 7) +* y <1>: Editing Rebase Sequences. (line 74) -* magit-diff-visit-file-other-window: Visiting Files and Blobs from a Diff. - (line 73) -* magit-diff-visit-file-worktree: Visiting Files and Blobs from a Diff. - (line 51) -* magit-diff-visit-worktree-file-other-frame: Visiting Files and Blobs from a Diff. - (line 76) -* magit-diff-visit-worktree-file-other-window: Visiting Files and Blobs from a Diff. - (line 75) -* magit-diff-while-committing: Refreshing Diffs. (line 81) -* magit-diff-while-committing <1>: Editing Commit Messages. - (line 58) -* magit-diff-working-tree: Diffing. (line 45) -* magit-discard: Applying. (line 40) -* magit-dispatch: Transient Commands. (line 18) -* magit-ediff: Ediffing. (line 21) -* magit-ediff-compare: Ediffing. (line 26) -* magit-ediff-dwim: Ediffing. (line 9) -* magit-ediff-resolve: Ediffing. (line 35) -* magit-ediff-show-commit: Ediffing. (line 65) -* magit-ediff-show-staged: Ediffing. (line 57) -* magit-ediff-show-stash: Ediffing. (line 69) -* magit-ediff-show-unstaged: Ediffing. (line 53) -* magit-ediff-show-working-tree: Ediffing. (line 61) -* magit-ediff-stage: Ediffing. (line 48) -* magit-edit-line-commit: Commands for Buffers Visiting Files. - (line 106) -* magit-emacs-Q-command: Debugging Tools. (line 16) -* magit-fetch: Fetching. (line 9) -* magit-fetch-all: Fetching. (line 50) -* magit-fetch-branch: Fetching. (line 40) -* magit-fetch-from-pushremote: Fetching. (line 15) -* magit-fetch-from-upstream: Fetching. (line 23) -* magit-fetch-modules: Submodule Transient. (line 58) -* magit-fetch-other: Fetching. (line 36) -* magit-fetch-refspec: Fetching. (line 45) -* magit-file-checkout: Resetting. (line 50) -* magit-file-checkout <1>: Commands for Buffers Visiting Files. - (line 135) -* magit-file-delete: Commands for Buffers Visiting Files. - (line 127) -* magit-file-dispatch: Commands for Buffers Visiting Files. - (line 21) -* magit-file-rename: Commands for Buffers Visiting Files. - (line 123) -* magit-file-untrack: Commands for Buffers Visiting Files. - (line 131) -* magit-find-file: General-Purpose Visit Commands. - (line 9) -* magit-find-file-other-frame: General-Purpose Visit Commands. - (line 21) -* magit-find-file-other-window: General-Purpose Visit Commands. - (line 15) -* magit-git-command: Running Git Manually. - (line 25) -* magit-git-command-topdir: Running Git Manually. - (line 17) -* magit-go-backward: Log Buffer. (line 21) -* magit-go-backward <1>: Refreshing Diffs. (line 91) -* magit-go-forward: Log Buffer. (line 25) -* magit-go-forward <1>: Refreshing Diffs. (line 95) -* magit-init: Creating Repository. (line 6) -* magit-jump-to-diffstat-or-diff: Commands Available in Diffs. - (line 45) -* magit-kill-this-buffer: Minor Mode for Buffers Visiting Blobs. - (line 20) -* magit-list-repositories: Repository List. (line 6) -* magit-list-submodules: Listing Submodules. (line 13) -* magit-list-submodules <1>: Submodule Transient. (line 54) -* magit-log: Logging. (line 29) -* magit-log <1>: Commands for Buffers Visiting Files. - (line 66) -* magit-log-all: Logging. (line 60) -* magit-log-all-branches: Logging. (line 56) -* magit-log-branches: Logging. (line 52) -* magit-log-buffer-file: Commands for Buffers Visiting Files. - (line 77) -* magit-log-bury-buffer: Log Buffer. (line 14) -* magit-log-current: Logging. (line 35) -* magit-log-double-commit-limit: Log Buffer. (line 61) -* magit-log-half-commit-limit: Log Buffer. (line 65) -* magit-log-head: Logging. (line 48) -* magit-log-move-to-parent: Log Buffer. (line 29) -* magit-log-other: Logging. (line 41) -* magit-log-refresh: Refreshing Logs. (line 11) -* magit-log-refresh <1>: Refreshing Logs. (line 17) -* magit-log-refresh <2>: Log Buffer. (line 6) -* magit-log-save-default-arguments: Refreshing Logs. (line 29) -* magit-log-select-pick: Select from Log. (line 20) -* magit-log-select-quit: Select from Log. (line 26) -* magit-log-set-default-arguments: Refreshing Logs. (line 22) -* magit-log-toggle-commit-limit: Log Buffer. (line 55) -* magit-log-trace-definition: Commands for Buffers Visiting Files. - (line 84) -* magit-margin-settings: Log Margin. (line 57) -* magit-merge: Merging. (line 9) -* magit-merge <1>: Merging. (line 89) -* magit-merge-abort: Merging. (line 95) -* magit-merge-absorb: Merging. (line 45) -* magit-merge-editmsg: Merging. (line 31) -* magit-merge-into: Merging. (line 58) -* magit-merge-nocommit: Merging. (line 38) -* magit-merge-plain: Merging. (line 18) -* magit-merge-preview: Merging. (line 81) -* magit-merge-squash: Merging. (line 72) -* magit-mode-bury-buffer: Quitting Windows. (line 6) -* magit-notes: Notes. (line 8) -* magit-notes-edit: Notes. (line 14) -* magit-notes-merge: Notes. (line 38) -* magit-notes-merge-abort: Notes. (line 52) -* magit-notes-merge-commit: Notes. (line 47) -* magit-notes-prune: Notes. (line 30) -* magit-notes-remove: Notes. (line 22) -* magit-patch: Plain Patches. (line 6) -* magit-patch-apply: Plain Patches. (line 21) -* magit-patch-apply <1>: Maildir Patches. (line 25) -* magit-patch-create: Plain Patches. (line 12) -* magit-patch-save: Plain Patches. (line 28) -* magit-pop-revision-stack: Using the Revision Stack. - (line 6) -* magit-process: Viewing Git Output. (line 16) -* magit-process-kill: Viewing Git Output. (line 24) -* magit-pull: Pulling. (line 9) -* magit-pull-branch: Pulling. (line 30) -* magit-pull-from-pushremote: Pulling. (line 14) -* magit-pull-from-upstream: Pulling. (line 22) -* magit-push: Pushing. (line 9) -* magit-push-current: Pushing. (line 31) -* magit-push-current-to-pushremote: Pushing. (line 15) -* magit-push-current-to-upstream: Pushing. (line 23) -* magit-push-implicitly args: Pushing. (line 74) -* magit-push-matching: Pushing. (line 50) -* magit-push-other: Pushing. (line 36) -* magit-push-refspecs: Pushing. (line 41) -* magit-push-tag: Pushing. (line 66) -* magit-push-tags: Pushing. (line 58) -* magit-push-to-remote remote args: Pushing. (line 92) -* magit-rebase: Rebasing. (line 9) -* magit-rebase-abort: Rebasing. (line 123) -* magit-rebase-autosquash: Rebasing. (line 84) -* magit-rebase-branch: Rebasing. (line 44) -* magit-rebase-continue: Rebasing. (line 106) -* magit-rebase-edit: Rebasing. (line 118) -* magit-rebase-edit-commit: Rebasing. (line 89) -* magit-rebase-interactive: Rebasing. (line 80) -* magit-rebase-onto-pushremote: Rebasing. (line 28) -* magit-rebase-onto-upstream: Rebasing. (line 36) -* magit-rebase-remove-commit: Rebasing. (line 99) -* magit-rebase-reword-commit: Rebasing. (line 94) -* magit-rebase-skip: Rebasing. (line 113) -* magit-rebase-subset: Rebasing. (line 50) -* magit-reflog-current: Reflog. (line 11) -* magit-reflog-head: Reflog. (line 19) -* magit-reflog-other: Reflog. (line 15) -* magit-refresh: Automatic Refreshing of Magit Buffers. - (line 24) -* magit-refresh-all: Automatic Refreshing of Magit Buffers. - (line 33) -* magit-remote: Remote Commands. (line 13) -* magit-remote-add: Remote Commands. (line 50) -* magit-remote-configure: Remote Commands. (line 33) -* magit-remote-prune: Remote Commands. (line 69) -* magit-remote-prune-refspecs: Remote Commands. (line 74) -* magit-remote-remove: Remote Commands. (line 65) -* magit-remote-rename: Remote Commands. (line 55) -* magit-remote-set-url: Remote Commands. (line 60) -* magit-reset-hard: Resetting. (line 26) -* magit-reset-index: Staging and Unstaging. - (line 87) -* magit-reset-index <1>: Resetting. (line 37) -* magit-reset-keep: Resetting. (line 31) -* magit-reset-mixed: Resetting. (line 15) -* magit-reset-quickly: Resetting. (line 8) -* magit-reset-soft: Resetting. (line 20) -* magit-reset-worktree: Resetting. (line 44) -* magit-reset-worktree <1>: Wip Modes. (line 66) -* magit-reverse: Applying. (line 44) -* magit-reverse-in-index: Staging and Unstaging. - (line 62) -* magit-revert: Reverting. (line 6) -* magit-revert-and-commit: Reverting. (line 15) -* magit-revert-no-commit: Reverting. (line 21) -* magit-run: Running Git Manually. - (line 12) -* magit-run-git-gui: Running Git Manually. - (line 66) -* magit-run-gitk: Running Git Manually. - (line 54) -* magit-run-gitk-all: Running Git Manually. - (line 58) -* magit-run-gitk-branches: Running Git Manually. - (line 62) -* magit-section-backward: Section Movement. (line 10) -* magit-section-backward-siblings: Section Movement. (line 20) -* magit-section-cycle: Section Visibility. (line 13) -* magit-section-cycle-diffs: Section Visibility. (line 17) -* magit-section-cycle-global: Section Visibility. (line 22) -* magit-section-forward: Section Movement. (line 16) -* magit-section-forward-siblings: Section Movement. (line 26) -* magit-section-hide: Section Visibility. (line 49) -* magit-section-hide-children: Section Visibility. (line 64) -* magit-section-show: Section Visibility. (line 45) -* magit-section-show-children: Section Visibility. (line 58) -* magit-section-show-headings: Section Visibility. (line 53) -* magit-section-show-level-1: Section Visibility. (line 26) -* magit-section-show-level-1-all: Section Visibility. (line 33) -* magit-section-show-level-2: Section Visibility. (line 27) -* magit-section-show-level-2-all: Section Visibility. (line 34) -* magit-section-show-level-3: Section Visibility. (line 28) -* magit-section-show-level-3-all: Section Visibility. (line 35) -* magit-section-show-level-4: Section Visibility. (line 29) -* magit-section-show-level-4-all: Section Visibility. (line 36) -* magit-section-toggle: Section Visibility. (line 9) -* magit-section-toggle-children: Section Visibility. (line 68) -* magit-section-up: Section Movement. (line 31) -* magit-sequence-abort: Cherry Picking. (line 98) -* magit-sequence-abort <1>: Reverting. (line 39) -* magit-sequence-continue: Cherry Picking. (line 90) -* magit-sequence-continue <1>: Reverting. (line 31) -* magit-sequence-skip: Cherry Picking. (line 94) -* magit-sequence-skip <1>: Reverting. (line 35) -* magit-shell-command: Running Git Manually. - (line 40) -* magit-shell-command-topdir: Running Git Manually. - (line 35) -* magit-show-commit: Diffing. (line 69) -* magit-show-commit <1>: Blaming. (line 75) -* magit-show-refs: References Buffer. (line 6) -* magit-show-refs-current: References Buffer. (line 26) -* magit-show-refs-head: References Buffer. (line 21) -* magit-show-refs-other: References Buffer. (line 32) -* magit-snapshot-both: Stashing. (line 40) -* magit-snapshot-index: Stashing. (line 47) -* magit-snapshot-worktree: Stashing. (line 52) -* magit-stage: Staging and Unstaging. - (line 28) -* magit-stage-file: Staging from File-Visiting Buffers. - (line 10) -* magit-stage-file <1>: Commands for Buffers Visiting Files. - (line 29) -* magit-stage-modified: Staging and Unstaging. - (line 36) -* magit-stash: Stashing. (line 8) -* magit-stash-apply: Stashing. (line 59) -* magit-stash-both: Stashing. (line 14) -* magit-stash-branch: Stashing. (line 81) -* magit-stash-branch-here: Stashing. (line 86) -* magit-stash-clear: Stashing. (line 96) -* magit-stash-drop: Stashing. (line 72) -* magit-stash-format-patch: Stashing. (line 92) -* magit-stash-index: Stashing. (line 21) -* magit-stash-keep-index: Stashing. (line 33) -* magit-stash-list: Stashing. (line 100) -* magit-stash-pop: Stashing. (line 65) -* magit-stash-show: Diffing. (line 74) -* magit-stash-show <1>: Stashing. (line 77) -* magit-stash-worktree: Stashing. (line 26) -* magit-status: Status Buffer. (line 22) -* magit-submodule: Submodule Transient. (line 6) -* magit-submodule-add: Submodule Transient. (line 20) -* magit-submodule-fetch: Fetching. (line 54) -* magit-submodule-populate: Submodule Transient. (line 34) -* magit-submodule-register: Submodule Transient. (line 27) -* magit-submodule-synchronize: Submodule Transient. (line 44) -* magit-submodule-unpopulate: Submodule Transient. (line 50) -* magit-submodule-update: Submodule Transient. (line 39) -* magit-subtree: Subtree. (line 8) -* magit-subtree-add: Subtree. (line 25) -* magit-subtree-add-commit: Subtree. (line 30) -* magit-subtree-export: Subtree. (line 42) -* magit-subtree-import: Subtree. (line 13) -* magit-subtree-merge: Subtree. (line 34) -* magit-subtree-pull: Subtree. (line 38) -* magit-subtree-push: Subtree. (line 54) -* magit-subtree-split: Subtree. (line 59) -* magit-tag: Tagging. (line 8) -* magit-tag-create: Tagging. (line 14) -* magit-tag-delete: Tagging. (line 39) -* magit-tag-prune: Tagging. (line 46) -* magit-tag-release: Tagging. (line 19) -* magit-toggle-buffer-lock: Modes and Buffers. (line 17) -* magit-toggle-margin: Refreshing Logs. (line 37) -* magit-toggle-margin <1>: Log Margin. (line 66) -* magit-toggle-margin-details: Log Margin. (line 74) -* magit-toggle-verbose-refresh: Debugging Tools. (line 30) -* magit-unstage: Staging and Unstaging. - (line 43) -* magit-unstage-all: Staging and Unstaging. - (line 52) -* magit-unstage-file: Staging from File-Visiting Buffers. - (line 18) -* magit-unstage-file <1>: Commands for Buffers Visiting Files. - (line 33) -* magit-version: Git Executable. (line 17) -* magit-version <1>: Debugging Tools. (line 10) -* magit-visit-ref: References Buffer. (line 181) -* magit-wip-commit: Wip Modes. (line 88) -* magit-wip-log: Wip Modes. (line 48) -* magit-wip-log-current: Wip Modes. (line 57) -* magit-worktree: Worktree. (line 8) -* magit-worktree-branch: Worktree. (line 17) -* magit-worktree-checkout: Worktree. (line 13) -* magit-worktree-delete: Worktree. (line 25) -* magit-worktree-move: Worktree. (line 21) -* magit-worktree-status: Worktree. (line 30) -* scroll-down: Commands Available in Diffs. - (line 60) -* scroll-up: Commands Available in Diffs. - (line 56) -* with-editor-cancel: Editing Commit Messages. - (line 22) -* with-editor-cancel <1>: Editing Rebase Sequences. - (line 11) -* with-editor-debug: Debugging Tools. (line 44) -* with-editor-finish: Editing Commit Messages. - (line 17) -* with-editor-finish <1>: Editing Rebase Sequences. - (line 6) +* y c: References Buffer. (line 25) +* y o: References Buffer. (line 30) +* y r: References Buffer. (line 34) +* y y: References Buffer. (line 21) +* z: Stashing. (line 9) +* Z: Worktree. (line 9) +* z a: Stashing. (line 52) +* z b: Stashing. (line 70) +* z B: Stashing. (line 74) +* Z b: Worktree. (line 13) +* Z c: Worktree. (line 16) +* z f: Stashing. (line 79) +* Z g: Worktree. (line 26) +* z i: Stashing. (line 20) +* z I: Stashing. (line 42) +* z k: Stashing. (line 63) +* Z k: Worktree. (line 22) +* z l: Stashing. (line 85) +* Z m: Worktree. (line 19) +* z p: Stashing. (line 57) +* z v: Stashing. (line 67) +* z w: Stashing. (line 24) +* z W: Stashing. (line 46) +* z x: Stashing. (line 30) +* z z: Stashing. (line 14) +* z Z: Stashing. (line 36)  -File: magit.info, Node: Function Index, Next: Variable Index, Prev: Command Index, Up: Top +File: magit.info, Node: Function and Command Index, Next: Variable Index, Prev: Keystroke Index, Up: Top -Appendix E Function Index -************************* +Appendix D Function and Command Index +************************************* [index] * Menu: * bug-reference-mode: Commit Mode and Hooks. - (line 56) -* git-commit-check-style-conventions: Commit Message Conventions. - (line 40) -* git-commit-propertize-diff: Commit Mode and Hooks. - (line 47) -* git-commit-save-message: Commit Mode and Hooks. + (line 49) +* forward-line: Editing Rebase Sequences. + (line 34) +* git-commit-ack: Commit Pseudo Headers. + (line 16) +* git-commit-cc: Commit Pseudo Headers. (line 28) -* git-commit-setup-changelog-support: Commit Mode and Hooks. - (line 32) -* git-commit-turn-on-auto-fill: Commit Mode and Hooks. +* git-commit-check-style-conventions: Commit Message Conventions. (line 37) +* git-commit-insert-pseudo-header: Commit Pseudo Headers. + (line 13) +* git-commit-next-message: Editing Commit Messages. + (line 41) +* git-commit-prev-message: Editing Commit Messages. + (line 36) +* git-commit-propertize-diff: Commit Mode and Hooks. + (line 41) +* git-commit-reported: Commit Pseudo Headers. + (line 31) +* git-commit-review: Commit Pseudo Headers. + (line 19) +* git-commit-save-message: Editing Commit Messages. + (line 33) +* git-commit-save-message <1>: Commit Mode and Hooks. + (line 26) +* git-commit-setup-changelog-support: Commit Mode and Hooks. + (line 29) +* git-commit-signoff: Commit Pseudo Headers. + (line 22) +* git-commit-suggested: Commit Pseudo Headers. + (line 35) +* git-commit-test: Commit Pseudo Headers. + (line 25) +* git-commit-turn-on-auto-fill: Commit Mode and Hooks. + (line 33) * git-commit-turn-on-flyspell: Commit Mode and Hooks. - (line 42) -* ido-enter-magit-status: Status Buffer. (line 72) + (line 37) +* git-rebase-backward-line: Editing Rebase Sequences. + (line 31) +* git-rebase-break: Editing Rebase Sequences. + (line 70) +* git-rebase-edit: Editing Rebase Sequences. + (line 46) +* git-rebase-exec: Editing Rebase Sequences. + (line 62) +* git-rebase-fixup: Editing Rebase Sequences. + (line 52) +* git-rebase-insert: Editing Rebase Sequences. + (line 74) +* git-rebase-kill-line: Editing Rebase Sequences. + (line 56) +* git-rebase-label: Editing Rebase Sequences. + (line 94) +* git-rebase-merge: Editing Rebase Sequences. + (line 102) +* git-rebase-merge-toggle-editmsg: Editing Rebase Sequences. + (line 108) +* git-rebase-move-line-down: Editing Rebase Sequences. + (line 40) +* git-rebase-move-line-up: Editing Rebase Sequences. + (line 37) +* git-rebase-pick: Editing Rebase Sequences. + (line 59) +* git-rebase-reset: Editing Rebase Sequences. + (line 97) +* git-rebase-reword: Editing Rebase Sequences. + (line 43) +* git-rebase-show-commit: Editing Rebase Sequences. + (line 15) +* git-rebase-show-or-scroll-down: Editing Rebase Sequences. + (line 25) +* git-rebase-show-or-scroll-up: Editing Rebase Sequences. + (line 19) +* git-rebase-squash: Editing Rebase Sequences. + (line 49) +* git-rebase-undo: Editing Rebase Sequences. + (line 77) +* ido-enter-magit-status: Status Buffer. (line 96) * magit-add-section-hook: Section Hooks. (line 20) * magit-after-save-refresh-status: Automatic Refreshing of Magit Buffers. - (line 58) -* magit-branch-or-checkout: Branch Commands. (line 257) -* magit-branch-orphan: Branch Commands. (line 252) + (line 55) +* magit-am: Maildir Patches. (line 9) +* magit-am-abort: Maildir Patches. (line 38) +* magit-am-apply-maildir: Maildir Patches. (line 20) +* magit-am-apply-patches: Maildir Patches. (line 14) +* magit-am-continue: Maildir Patches. (line 31) +* magit-am-skip: Maildir Patches. (line 34) +* magit-apply: Applying. (line 34) +* magit-bisect: Bisecting. (line 9) +* magit-bisect-bad: Bisecting. (line 32) +* magit-bisect-good: Bisecting. (line 36) +* magit-bisect-mark: Bisecting. (line 40) +* magit-bisect-reset: Bisecting. (line 51) +* magit-bisect-run: Bisecting. (line 26) +* magit-bisect-skip: Bisecting. (line 46) +* magit-bisect-start: Bisecting. (line 16) +* magit-blame: Blaming. (line 19) +* magit-blame <1>: Blaming. (line 99) +* magit-blame <2>: Commands for Buffers Visiting Files. + (line 83) +* magit-blame-addition: Blaming. (line 29) +* magit-blame-copy-hash: Blaming. (line 118) +* magit-blame-cycle-style: Blaming. (line 125) +* magit-blame-echo: Blaming. (line 63) +* magit-blame-next-chunk: Blaming. (line 102) +* magit-blame-next-chunk-same-commit: Blaming. (line 105) +* magit-blame-previous-chunk: Blaming. (line 108) +* magit-blame-previous-chunk-same-commit: Blaming. (line 111) +* magit-blame-quit: Blaming. (line 114) +* magit-blame-removal: Blaming. (line 45) +* magit-blame-reverse: Blaming. (line 54) +* magit-blob-next: Minor Mode for Buffers Visiting Blobs. + (line 16) +* magit-blob-previous: Commands for Buffers Visiting Files. + (line 104) +* magit-blob-previous <1>: Minor Mode for Buffers Visiting Blobs. + (line 13) +* magit-branch: Branch Commands. (line 13) +* magit-branch-and-checkout: Branch Commands. (line 63) +* magit-branch-checkout: Branch Commands. (line 69) +* magit-branch-configure: Branch Commands. (line 31) +* magit-branch-create: Branch Commands. (line 54) +* magit-branch-delete: Branch Commands. (line 138) +* magit-branch-or-checkout: Branch Commands. (line 251) +* magit-branch-orphan: Branch Commands. (line 247) +* magit-branch-rename: Branch Commands. (line 143) +* magit-branch-reset: Branch Commands. (line 123) * magit-branch-shelve: Auxiliary Branch Commands. (line 9) +* magit-branch-spinoff: Branch Commands. (line 91) +* magit-branch-spinout: Branch Commands. (line 118) * magit-branch-unshelve: Auxiliary Branch Commands. - (line 20) + (line 19) * magit-builtin-completing-read: Support for Completion Frameworks. - (line 42) + (line 41) +* magit-bundle: Bundle. (line 8) * magit-call-git: Calling Git for Effect. (line 28) * magit-call-process: Calling Git for Effect. - (line 32) -* magit-cancel-section: Creating Sections. (line 71) + (line 31) +* magit-cancel-section: Creating Sections. (line 69) +* magit-checkout: Branch Commands. (line 47) +* magit-cherry: Cherries. (line 18) +* magit-cherry-apply: Cherry Picking. (line 23) +* magit-cherry-copy: Cherry Picking. (line 17) +* magit-cherry-donate: Cherry Picking. (line 51) +* magit-cherry-harvest: Cherry Picking. (line 40) +* magit-cherry-pick: Cherry Picking. (line 9) +* magit-cherry-spinoff: Cherry Picking. (line 72) +* magit-cherry-spinout: Cherry Picking. (line 62) +* magit-clone: Cloning Repository. (line 20) +* magit-clone-bare: Cloning Repository. (line 38) +* magit-clone-mirror: Cloning Repository. (line 42) +* magit-clone-regular: Cloning Repository. (line 28) +* magit-clone-shallow: Cloning Repository. (line 32) +* magit-clone-shallow-exclude: Cloning Repository. (line 55) +* magit-clone-shallow-since: Cloning Repository. (line 49) +* magit-commit: Initiating a Commit. (line 9) +* magit-commit <1>: Commands for Buffers Visiting Files. + (line 36) +* magit-commit-amend: Initiating a Commit. (line 18) +* magit-commit-augment: Initiating a Commit. (line 59) +* magit-commit-create: Initiating a Commit. (line 14) +* magit-commit-extend: Initiating a Commit. (line 21) +* magit-commit-fixup: Initiating a Commit. (line 39) +* magit-commit-instant-fixup: Initiating a Commit. (line 46) +* magit-commit-instant-squash: Initiating a Commit. (line 56) +* magit-commit-reword: Initiating a Commit. (line 30) +* magit-commit-squash: Initiating a Commit. (line 49) * magit-completing-read: Support for Completion Frameworks. - (line 60) + (line 57) +* magit-copy-buffer-revision: Common Commands. (line 39) +* magit-copy-section-value: Common Commands. (line 22) * magit-current-section: Section Selection. (line 6) -* magit-define-section-jumper: Creating Sections. (line 77) -* magit-diff-scope: Matching Sections. (line 118) -* magit-diff-type: Matching Sections. (line 95) +* magit-cycle-margin-style: Log Margin. (line 63) +* magit-debug-git-executable: Git Executable. (line 55) +* magit-debug-git-executable <1>: Debugging Tools. (line 34) +* magit-define-section-jumper: Creating Sections. (line 74) +* magit-describe-section: Section Types and Values. + (line 14) +* magit-describe-section-briefly: Section Types and Values. + (line 17) +* magit-describe-section-briefly <1>: Matching Sections. (line 7) +* magit-diff: Diffing. (line 22) +* magit-diff <1>: Commands for Buffers Visiting Files. + (line 42) +* magit-diff-buffer-file: Commands for Buffers Visiting Files. + (line 52) +* magit-diff-default-context: Refreshing Diffs. (line 64) +* magit-diff-dwim: Diffing. (line 27) +* magit-diff-edit-hunk-commit: Commands Available in Diffs. + (line 24) +* magit-diff-flip-revs: Refreshing Diffs. (line 41) +* magit-diff-less-context: Refreshing Diffs. (line 58) +* magit-diff-more-context: Refreshing Diffs. (line 61) +* magit-diff-paths: Diffing. (line 56) +* magit-diff-range: Diffing. (line 30) +* magit-diff-refresh: Refreshing Diffs. (line 12) +* magit-diff-refresh <1>: Refreshing Diffs. (line 17) +* magit-diff-save-default-arguments: Refreshing Diffs. (line 27) +* magit-diff-scope: Matching Sections. (line 110) +* magit-diff-set-default-arguments: Refreshing Diffs. (line 21) +* magit-diff-show-or-scroll-down: Log Buffer. (line 50) +* magit-diff-show-or-scroll-down <1>: Blaming. (line 87) +* magit-diff-show-or-scroll-up: Log Buffer. (line 41) +* magit-diff-show-or-scroll-up <1>: Blaming. (line 78) +* magit-diff-staged: Diffing. (line 48) +* magit-diff-switch-range-type: Refreshing Diffs. (line 37) +* magit-diff-toggle-file-filter: Refreshing Diffs. (line 45) +* magit-diff-toggle-refine-hunk: Refreshing Diffs. (line 34) +* magit-diff-trace-definition: Commands Available in Diffs. + (line 15) +* magit-diff-type: Matching Sections. (line 88) +* magit-diff-unstaged: Diffing. (line 53) +* magit-diff-visit-file: Visiting Files and Blobs from a Diff. + (line 9) * magit-diff-visit-file-other-frame: Visiting Files and Blobs from a Diff. - (line 74) + (line 71) * magit-diff-visit-file-other-window: Visiting Files and Blobs from a Diff. - (line 73) + (line 70) +* magit-diff-visit-file-worktree: Visiting Files and Blobs from a Diff. + (line 50) * magit-diff-visit-worktree-file-other-frame: Visiting Files and Blobs from a Diff. - (line 76) + (line 73) * magit-diff-visit-worktree-file-other-window: Visiting Files and Blobs from a Diff. - (line 75) + (line 72) +* magit-diff-while-committing: Refreshing Diffs. (line 71) +* magit-diff-while-committing <1>: Editing Commit Messages. + (line 54) +* magit-diff-working-tree: Diffing. (line 43) * magit-disable-section-inserter: Per-Repository Configuration. (line 31) +* magit-discard: Applying. (line 40) +* magit-dispatch: Transient Commands. (line 19) * magit-display-buffer: Switching Buffers. (line 6) -* magit-display-buffer-fullcolumn-most-v1: Switching Buffers. (line 75) +* magit-display-buffer-fullcolumn-most-v1: Switching Buffers. (line 68) * magit-display-buffer-fullframe-status-topleft-v1: Switching Buffers. - (line 65) -* magit-display-buffer-fullframe-status-v1: Switching Buffers. (line 59) +* magit-display-buffer-fullframe-status-v1: Switching Buffers. + (line 54) * magit-display-buffer-same-window-except-diff-v1: Switching Buffers. - (line 53) -* magit-display-buffer-traditional: Switching Buffers. (line 45) -* magit-file-checkout: Commands for Buffers Visiting Files. - (line 135) + (line 49) +* magit-display-buffer-traditional: Switching Buffers. (line 42) +* magit-display-repository-buffer: Common Commands. (line 9) +* magit-ediff: Ediffing. (line 21) +* magit-ediff-compare: Ediffing. (line 25) +* magit-ediff-dwim: Ediffing. (line 10) +* magit-ediff-resolve: Ediffing. (line 33) +* magit-ediff-show-commit: Ediffing. (line 58) +* magit-ediff-show-staged: Ediffing. (line 52) +* magit-ediff-show-stash: Ediffing. (line 61) +* magit-ediff-show-unstaged: Ediffing. (line 49) +* magit-ediff-show-working-tree: Ediffing. (line 55) +* magit-ediff-stage: Ediffing. (line 45) +* magit-edit-line-commit: Commands for Buffers Visiting Files. + (line 95) +* magit-emacs-Q-command: Debugging Tools. (line 16) +* magit-fetch: Fetching. (line 10) +* magit-fetch-all: Fetching. (line 45) +* magit-fetch-branch: Fetching. (line 37) +* magit-fetch-from-pushremote: Fetching. (line 15) +* magit-fetch-from-upstream: Fetching. (line 22) +* magit-fetch-modules: Submodule Transient. (line 51) +* magit-fetch-other: Fetching. (line 34) +* magit-fetch-refspec: Fetching. (line 41) +* magit-file-checkout: Resetting. (line 44) +* magit-file-checkout <1>: Commands for Buffers Visiting Files. + (line 118) * magit-file-delete: Commands for Buffers Visiting Files. - (line 127) + (line 112) +* magit-file-dispatch: Commands for Buffers Visiting Files. + (line 22) * magit-file-rename: Commands for Buffers Visiting Files. - (line 123) + (line 109) * magit-file-untrack: Commands for Buffers Visiting Files. - (line 131) + (line 115) * magit-find-file: General-Purpose Visit Commands. (line 9) * magit-find-file-other-frame: General-Purpose Visit Commands. - (line 21) + (line 19) * magit-find-file-other-window: General-Purpose Visit Commands. - (line 15) + (line 14) * magit-generate-buffer-name-default-function: Naming Buffers. - (line 17) -* magit-get-section: Matching Sections. (line 16) + (line 16) +* magit-get-section: Matching Sections. (line 14) * magit-git: Calling Git for Effect. - (line 65) + (line 46) +* magit-git-command: Running Git Manually. + (line 24) +* magit-git-command-topdir: Running Git Manually. + (line 17) * magit-git-exit-code: Getting a Value from Git. (line 10) * magit-git-failure: Getting a Value from Git. - (line 19) + (line 17) * magit-git-false: Getting a Value from Git. - (line 29) + (line 25) * magit-git-insert: Getting a Value from Git. - (line 34) + (line 29) * magit-git-items: Getting a Value from Git. - (line 49) + (line 41) * magit-git-lines: Getting a Value from Git. - (line 44) + (line 37) * magit-git-str: Getting a Value from Git. - (line 72) + (line 75) * magit-git-string: Getting a Value from Git. - (line 38) + (line 32) * magit-git-success: Getting a Value from Git. - (line 14) + (line 13) * magit-git-true: Getting a Value from Git. - (line 24) + (line 21) * magit-git-wash: Calling Git for Effect. - (line 70) -* magit-hunk-set-window-start: Section Movement. (line 51) + (line 50) +* magit-go-backward: Log Buffer. (line 20) +* magit-go-backward <1>: Refreshing Diffs. (line 80) +* magit-go-forward: Log Buffer. (line 23) +* magit-go-forward <1>: Refreshing Diffs. (line 83) +* magit-hunk-set-window-start: Section Movement. (line 45) * magit-ido-completing-read: Support for Completion Frameworks. - (line 48) -* magit-insert-am-sequence: Status Sections. (line 28) -* magit-insert-assumed-unchanged-files: Status Sections. (line 117) -* magit-insert-bisect-log: Status Sections. (line 46) -* magit-insert-bisect-output: Status Sections. (line 38) -* magit-insert-bisect-rest: Status Sections. (line 42) + (line 46) +* magit-init: Creating Repository. (line 7) +* magit-insert-am-sequence: Status Sections. (line 25) +* magit-insert-assumed-unchanged-files: Status Sections. (line 98) +* magit-insert-bisect-log: Status Sections. (line 39) +* magit-insert-bisect-output: Status Sections. (line 33) +* magit-insert-bisect-rest: Status Sections. (line 36) * magit-insert-diff-filter-header: Status Header Sections. - (line 38) + (line 35) * magit-insert-error-header: Status Header Sections. - (line 28) + (line 26) * magit-insert-head-branch-header: Status Header Sections. - (line 42) -* magit-insert-heading: Creating Sections. (line 42) -* magit-insert-ignored-files: Status Sections. (line 100) -* magit-insert-local-branches: References Sections. (line 17) -* magit-insert-merge-log: Status Sections. (line 18) + (line 38) +* magit-insert-heading: Creating Sections. (line 41) +* magit-insert-ignored-files: Status Sections. (line 83) +* magit-insert-local-branches: References Sections. (line 16) +* magit-insert-merge-log: Status Sections. (line 17) * magit-insert-modules: Status Module Sections. (line 12) * magit-insert-modules-overview: Status Module Sections. - (line 33) + (line 30) * magit-insert-modules-unpulled-from-pushremote: Status Module Sections. - (line 50) + (line 45) * magit-insert-modules-unpulled-from-upstream: Status Module Sections. - (line 44) + (line 40) * magit-insert-modules-unpushed-to-pushremote: Status Module Sections. - (line 62) + (line 55) * magit-insert-modules-unpushed-to-upstream: Status Module Sections. - (line 56) + (line 50) * magit-insert-push-branch-header: Status Header Sections. - (line 51) -* magit-insert-rebase-sequence: Status Sections. (line 23) -* magit-insert-recent-commits: Status Sections. (line 131) -* magit-insert-remote-branches: References Sections. (line 21) + (line 45) +* magit-insert-rebase-sequence: Status Sections. (line 21) +* magit-insert-recent-commits: Status Sections. (line 110) +* magit-insert-remote-branches: References Sections. (line 19) * magit-insert-remote-header: Status Header Sections. - (line 67) + (line 58) * magit-insert-repo-header: Status Header Sections. - (line 63) + (line 55) * magit-insert-section: Creating Sections. (line 6) -* magit-insert-sequencer-sequence: Status Sections. (line 33) -* magit-insert-skip-worktree-files: Status Sections. (line 110) -* magit-insert-staged-changes: Status Sections. (line 63) -* magit-insert-stashes: Status Sections. (line 67) +* magit-insert-sequencer-sequence: Status Sections. (line 29) +* magit-insert-skip-worktree-files: Status Sections. (line 92) +* magit-insert-staged-changes: Status Sections. (line 53) +* magit-insert-stashes: Status Sections. (line 56) * magit-insert-status-headers: Status Header Sections. (line 12) -* magit-insert-tags: References Sections. (line 25) +* magit-insert-tags: References Sections. (line 22) * magit-insert-tags-header: Status Header Sections. - (line 56) -* magit-insert-tracked-files: Status Sections. (line 96) -* magit-insert-unpulled-cherries: Status Sections. (line 142) -* magit-insert-unpulled-from-pushremote: Status Sections. (line 79) -* magit-insert-unpulled-from-upstream: Status Sections. (line 74) -* magit-insert-unpulled-or-recent-commits: Status Sections. (line 124) -* magit-insert-unpushed-cherries: Status Sections. (line 149) -* magit-insert-unpushed-to-pushremote: Status Sections. (line 89) -* magit-insert-unpushed-to-upstream: Status Sections. (line 84) -* magit-insert-unstaged-changes: Status Sections. (line 59) -* magit-insert-untracked-files: Status Sections. (line 50) + (line 49) +* magit-insert-tracked-files: Status Sections. (line 80) +* magit-insert-unpulled-cherries: Status Sections. (line 119) +* magit-insert-unpulled-from-pushremote: Status Sections. (line 66) +* magit-insert-unpulled-from-upstream: Status Sections. (line 62) +* magit-insert-unpulled-or-recent-commits: Status Sections. (line 104) +* magit-insert-unpushed-cherries: Status Sections. (line 125) +* magit-insert-unpushed-to-pushremote: Status Sections. (line 74) +* magit-insert-unpushed-to-upstream: Status Sections. (line 70) +* magit-insert-unstaged-changes: Status Sections. (line 50) +* magit-insert-untracked-files: Status Sections. (line 42) * magit-insert-upstream-branch-header: Status Header Sections. - (line 46) + (line 41) * magit-insert-user-header: Status Header Sections. - (line 75) + (line 65) +* magit-jump-to-diffstat-or-diff: Commands Available in Diffs. + (line 43) +* magit-kill-this-buffer: Minor Mode for Buffers Visiting Blobs. + (line 19) * magit-list-repositories: Repository List. (line 6) * magit-list-submodules: Listing Submodules. (line 13) -* magit-log-maybe-show-more-commits: Section Movement. (line 66) -* magit-log-maybe-update-blob-buffer: Section Movement. (line 82) -* magit-log-maybe-update-revision-buffer: Section Movement. (line 74) -* magit-maybe-set-dedicated: Switching Buffers. (line 100) -* magit-mode-display-buffer: Refreshing Buffers. (line 33) -* magit-mode-quit-window: Quitting Windows. (line 34) -* magit-mode-setup: Refreshing Buffers. (line 17) -* magit-push-implicitly: Pushing. (line 74) -* magit-push-to-remote: Pushing. (line 92) -* magit-region-sections: Section Selection. (line 10) -* magit-region-values: Section Selection. (line 37) -* magit-repolist-column-branch: Repository List. (line 44) -* magit-repolist-column-branches: Repository List. (line 53) -* magit-repolist-column-flag: Repository List. (line 61) -* magit-repolist-column-ident: Repository List. (line 30) -* magit-repolist-column-path: Repository List. (line 35) -* magit-repolist-column-stashes: Repository List. (line 57) -* magit-repolist-column-unpulled-from-pushremote: Repository List. - (line 81) -* magit-repolist-column-unpulled-from-upstream: Repository List. - (line 76) -* magit-repolist-column-unpushed-to-pushremote: Repository List. - (line 91) -* magit-repolist-column-unpushed-to-upstream: Repository List. - (line 86) -* magit-repolist-column-upstream: Repository List. (line 48) -* magit-repolist-column-version: Repository List. (line 39) -* magit-restore-window-configuration: Quitting Windows. (line 23) -* magit-run-git: Calling Git for Effect. - (line 36) -* magit-run-git-async: Calling Git for Effect. - (line 80) -* magit-run-git-with-editor: Calling Git for Effect. - (line 93) -* magit-run-git-with-input: Calling Git for Effect. - (line 40) -* magit-run-git-with-logfile: Calling Git for Effect. - (line 56) -* magit-save-window-configuration: Switching Buffers. (line 89) -* magit-section-case: Matching Sections. (line 71) -* magit-section-hide: Section Visibility. (line 49) -* magit-section-hide-children: Section Visibility. (line 64) -* magit-section-ident: Matching Sections. (line 11) -* magit-section-match: Matching Sections. (line 21) -* magit-section-set-window-start: Section Movement. (line 59) -* magit-section-show: Section Visibility. (line 45) -* magit-section-show-children: Section Visibility. (line 58) -* magit-section-show-headings: Section Visibility. (line 53) -* magit-section-toggle-children: Section Visibility. (line 68) -* magit-section-value-if: Matching Sections. (line 61) -* magit-start-git: Calling Git for Effect. - (line 105) -* magit-start-process: Calling Git for Effect. - (line 124) -* magit-stashes-maybe-update-stash-buffer: Section Movement. (line 106) -* magit-status-maybe-update-blob-buffer: Section Movement. (line 100) -* magit-status-maybe-update-revision-buffer: Section Movement. - (line 88) -* magit-status-maybe-update-stash-buffer: Section Movement. (line 94) -* magit-wip-log: Wip Modes. (line 48) -* magit-wip-log-current: Wip Modes. (line 57) -* with-editor-usage-message: Commit Mode and Hooks. +* magit-list-submodules <1>: Submodule Transient. (line 48) +* magit-log: Logging. (line 30) +* magit-log <1>: Commands for Buffers Visiting Files. (line 60) +* magit-log-all: Logging. (line 55) +* magit-log-all-branches: Logging. (line 52) +* magit-log-branches: Logging. (line 49) +* magit-log-buffer-file: Commands for Buffers Visiting Files. + (line 70) +* magit-log-bury-buffer: Log Buffer. (line 14) +* magit-log-current: Logging. (line 35) +* magit-log-double-commit-limit: Log Buffer. (line 64) +* magit-log-half-commit-limit: Log Buffer. (line 67) +* magit-log-head: Logging. (line 46) +* magit-log-maybe-show-more-commits: Section Movement. (line 58) +* magit-log-maybe-update-blob-buffer: Section Movement. (line 72) +* magit-log-maybe-update-revision-buffer: Section Movement. (line 65) +* magit-log-move-to-parent: Log Buffer. (line 26) +* magit-log-move-to-revision: Log Buffer. (line 31) +* magit-log-other: Logging. (line 40) +* magit-log-refresh: Refreshing Logs. (line 12) +* magit-log-refresh <1>: Refreshing Logs. (line 17) +* magit-log-refresh <2>: Log Buffer. (line 7) +* magit-log-save-default-arguments: Refreshing Logs. (line 27) +* magit-log-select-pick: Select from Log. (line 21) +* magit-log-select-quit: Select from Log. (line 26) +* magit-log-set-default-arguments: Refreshing Logs. (line 21) +* magit-log-toggle-commit-limit: Log Buffer. (line 59) +* magit-log-trace-definition: Commands for Buffers Visiting Files. + (line 76) +* magit-margin-settings: Log Margin. (line 52) +* magit-maybe-set-dedicated: Switching Buffers. (line 89) +* magit-merge: Merging. (line 10) +* magit-merge <1>: Merging. (line 82) +* magit-merge-abort: Merging. (line 87) +* magit-merge-absorb: Merging. (line 42) +* magit-merge-editmsg: Merging. (line 30) +* magit-merge-into: Merging. (line 54) +* magit-merge-nocommit: Merging. (line 36) +* magit-merge-plain: Merging. (line 18) +* magit-merge-preview: Merging. (line 75) +* magit-merge-squash: Merging. (line 67) +* magit-mode-bury-buffer: Quitting Windows. (line 7) +* magit-mode-display-buffer: Refreshing Buffers. (line 32) +* magit-mode-quit-window: Quitting Windows. (line 31) +* magit-mode-setup: Refreshing Buffers. (line 17) +* magit-notes: Notes. (line 9) +* magit-notes-edit: Notes. (line 14) +* magit-notes-merge: Notes. (line 35) +* magit-notes-merge-abort: Notes. (line 47) +* magit-notes-merge-commit: Notes. (line 43) +* magit-notes-prune: Notes. (line 28) +* magit-notes-remove: Notes. (line 21) +* magit-patch: Plain Patches. (line 7) +* magit-patch-apply: Plain Patches. (line 20) +* magit-patch-apply <1>: Maildir Patches. (line 23) +* magit-patch-create: Plain Patches. (line 12) +* magit-patch-save: Plain Patches. (line 26) +* magit-pop-revision-stack: Using the Revision Stack. + (line 7) +* magit-process: Viewing Git Output. (line 17) +* magit-process-file: Getting a Value from Git. + (line 57) +* magit-process-git: Getting a Value from Git. + (line 50) +* magit-process-kill: Viewing Git Output. (line 24) +* magit-pull: Pulling. (line 10) +* magit-pull-branch: Pulling. (line 28) +* magit-pull-from-pushremote: Pulling. (line 14) +* magit-pull-from-upstream: Pulling. (line 21) +* magit-push: Pushing. (line 10) +* magit-push-current: Pushing. (line 29) +* magit-push-current-to-pushremote: Pushing. (line 15) +* magit-push-current-to-upstream: Pushing. (line 22) +* magit-push-implicitly: Pushing. (line 74) +* magit-push-matching: Pushing. (line 45) +* magit-push-other: Pushing. (line 33) +* magit-push-refspecs: Pushing. (line 37) +* magit-push-tag: Pushing. (line 59) +* magit-push-tags: Pushing. (line 52) +* magit-push-to-remote: Pushing. (line 91) +* magit-rebase: Rebasing. (line 10) +* magit-rebase-abort: Rebasing. (line 111) +* magit-rebase-autosquash: Rebasing. (line 79) +* magit-rebase-branch: Rebasing. (line 42) +* magit-rebase-continue: Rebasing. (line 97) +* magit-rebase-edit: Rebasing. (line 107) +* magit-rebase-edit-commit: Rebasing. (line 83) +* magit-rebase-interactive: Rebasing. (line 76) +* magit-rebase-onto-pushremote: Rebasing. (line 28) +* magit-rebase-onto-upstream: Rebasing. (line 35) +* magit-rebase-remove-commit: Rebasing. (line 91) +* magit-rebase-reword-commit: Rebasing. (line 87) +* magit-rebase-skip: Rebasing. (line 103) +* magit-rebase-subset: Rebasing. (line 47) +* magit-reflog-current: Reflog. (line 12) +* magit-reflog-head: Reflog. (line 18) +* magit-reflog-other: Reflog. (line 15) +* magit-refresh: Automatic Refreshing of Magit Buffers. + (line 26) +* magit-refresh-all: Automatic Refreshing of Magit Buffers. + (line 34) +* magit-refs-set-show-commit-count: References Buffer. (line 34) +* magit-region-sections: Section Selection. (line 9) +* magit-region-values: Section Selection. (line 35) +* magit-remote: Remote Commands. (line 14) +* magit-remote-add: Remote Commands. (line 48) +* magit-remote-configure: Remote Commands. (line 32) +* magit-remote-prune: Remote Commands. (line 63) +* magit-remote-prune-refspecs: Remote Commands. (line 67) +* magit-remote-remove: Remote Commands. (line 60) +* magit-remote-rename: Remote Commands. (line 52) +* magit-remote-set-url: Remote Commands. (line 56) +* magit-repolist-column-branch: Repository List. (line 45) +* magit-repolist-column-branches: Repository List. (line 52) +* magit-repolist-column-flag: Repository List. (line 58) +* magit-repolist-column-ident: Repository List. (line 34) +* magit-repolist-column-path: Repository List. (line 38) +* magit-repolist-column-stashes: Repository List. (line 55) +* magit-repolist-column-unpulled-from-pushremote: Repository List. + (line 74) +* magit-repolist-column-unpulled-from-upstream: Repository List. + (line 70) +* magit-repolist-column-unpushed-to-pushremote: Repository List. + (line 82) +* magit-repolist-column-unpushed-to-upstream: Repository List. + (line 78) +* magit-repolist-column-upstream: Repository List. (line 48) +* magit-repolist-column-version: Repository List. (line 41) +* magit-reset-hard: Resetting. (line 24) +* magit-reset-index: Staging and Unstaging. + (line 78) +* magit-reset-index <1>: Resetting. (line 33) +* magit-reset-keep: Resetting. (line 28) +* magit-reset-mixed: Resetting. (line 15) +* magit-reset-quickly: Resetting. (line 9) +* magit-reset-soft: Resetting. (line 19) +* magit-reset-worktree: Resetting. (line 39) +* magit-reset-worktree <1>: Wip Modes. (line 64) +* magit-restore-window-configuration: Quitting Windows. (line 21) +* magit-reverse: Applying. (line 47) +* magit-reverse-in-index: Staging and Unstaging. + (line 58) +* magit-revert: Reverting. (line 7) +* magit-revert-and-commit: Reverting. (line 15) +* magit-revert-no-commit: Reverting. (line 20) +* magit-run: Running Git Manually. + (line 13) +* magit-run-git: Calling Git for Effect. + (line 34) +* magit-run-git-async: Calling Git for Effect. + (line 59) +* magit-run-git-gui: Running Git Manually. + (line 60) +* magit-run-git-with-editor: Calling Git for Effect. + (line 71) +* magit-run-git-with-input: Calling Git for Effect. + (line 37) +* magit-run-gitk: Running Git Manually. + (line 51) +* magit-run-gitk-all: Running Git Manually. + (line 54) +* magit-run-gitk-branches: Running Git Manually. + (line 57) +* magit-save-window-configuration: Switching Buffers. (line 80) +* magit-section-backward: Section Movement. (line 11) +* magit-section-backward-siblings: Section Movement. (line 19) +* magit-section-case: Matching Sections. (line 66) +* magit-section-cycle: Section Visibility. (line 13) +* magit-section-cycle-diffs: Section Visibility. (line 16) +* magit-section-cycle-global: Section Visibility. (line 20) +* magit-section-forward: Section Movement. (line 16) +* magit-section-forward-siblings: Section Movement. (line 24) +* magit-section-hide: Section Visibility. (line 42) +* magit-section-hide-children: Section Visibility. (line 54) +* magit-section-ident: Matching Sections. (line 10) +* magit-section-match: Matching Sections. (line 18) +* magit-section-set-window-start: Section Movement. (line 52) +* magit-section-show: Section Visibility. (line 39) +* magit-section-show-children: Section Visibility. (line 49) +* magit-section-show-headings: Section Visibility. (line 45) +* magit-section-show-level-1: Section Visibility. (line 26) +* magit-section-show-level-1-all: Section Visibility. (line 32) +* magit-section-show-level-2: Section Visibility. (line 26) +* magit-section-show-level-2-all: Section Visibility. (line 32) +* magit-section-show-level-3: Section Visibility. (line 26) +* magit-section-show-level-3-all: Section Visibility. (line 32) +* magit-section-show-level-4: Section Visibility. (line 26) +* magit-section-show-level-4-all: Section Visibility. (line 32) +* magit-section-toggle: Section Visibility. (line 10) +* magit-section-toggle-children: Section Visibility. (line 57) +* magit-section-up: Section Movement. (line 28) +* magit-section-value-if: Matching Sections. (line 57) +* magit-sequence-abort: Cherry Picking. (line 91) +* magit-sequence-abort <1>: Reverting. (line 35) +* magit-sequence-continue: Cherry Picking. (line 85) +* magit-sequence-continue <1>: Reverting. (line 29) +* magit-sequence-skip: Cherry Picking. (line 88) +* magit-sequence-skip <1>: Reverting. (line 32) +* magit-shell-command: Running Git Manually. + (line 39) +* magit-shell-command-topdir: Running Git Manually. + (line 35) +* magit-show-commit: Diffing. (line 63) +* magit-show-commit <1>: Blaming. (line 75) +* magit-show-refs: References Buffer. (line 7) +* magit-show-refs-current: References Buffer. (line 25) +* magit-show-refs-head: References Buffer. (line 21) +* magit-show-refs-other: References Buffer. (line 30) +* magit-snapshot-both: Stashing. (line 36) +* magit-snapshot-index: Stashing. (line 42) +* magit-snapshot-worktree: Stashing. (line 46) +* magit-stage: Staging and Unstaging. + (line 29) +* magit-stage-file: Staging from File-Visiting Buffers. + (line 11) +* magit-stage-file <1>: Commands for Buffers Visiting Files. + (line 29) +* magit-stage-modified: Staging and Unstaging. + (line 36) +* magit-start-git: Calling Git for Effect. + (line 82) +* magit-start-process: Calling Git for Effect. + (line 100) +* magit-stash: Stashing. (line 9) +* magit-stash-apply: Stashing. (line 52) +* magit-stash-both: Stashing. (line 14) +* magit-stash-branch: Stashing. (line 70) +* magit-stash-branch-here: Stashing. (line 74) +* magit-stash-clear: Stashing. (line 82) +* magit-stash-drop: Stashing. (line 63) +* magit-stash-format-patch: Stashing. (line 79) +* magit-stash-index: Stashing. (line 20) +* magit-stash-keep-index: Stashing. (line 30) +* magit-stash-list: Stashing. (line 85) +* magit-stash-pop: Stashing. (line 57) +* magit-stash-show: Diffing. (line 67) +* magit-stash-show <1>: Stashing. (line 67) +* magit-stash-worktree: Stashing. (line 24) +* magit-stashes-maybe-update-stash-buffer: Section Movement. (line 92) +* magit-status: Status Buffer. (line 23) +* magit-status-maybe-update-blob-buffer: Section Movement. (line 87) +* magit-status-maybe-update-revision-buffer: Section Movement. + (line 77) +* magit-status-maybe-update-stash-buffer: Section Movement. (line 82) +* magit-status-quick: Status Buffer. (line 70) +* magit-submodule: Submodule Transient. (line 7) +* magit-submodule-add: Submodule Transient. (line 20) +* magit-submodule-fetch: Fetching. (line 48) +* magit-submodule-populate: Submodule Transient. (line 32) +* magit-submodule-register: Submodule Transient. (line 26) +* magit-submodule-synchronize: Submodule Transient. (line 40) +* magit-submodule-unpopulate: Submodule Transient. (line 45) +* magit-submodule-update: Submodule Transient. (line 36) +* magit-subtree: Subtree. (line 9) +* magit-subtree-add: Subtree. (line 24) +* magit-subtree-add-commit: Subtree. (line 28) +* magit-subtree-export: Subtree. (line 37) +* magit-subtree-import: Subtree. (line 13) +* magit-subtree-merge: Subtree. (line 31) +* magit-subtree-pull: Subtree. (line 34) +* magit-subtree-push: Subtree. (line 48) +* magit-subtree-split: Subtree. (line 52) +* magit-switch-to-repository-buffer: Common Commands. (line 6) +* magit-switch-to-repository-buffer-other-frame: Common Commands. + (line 8) +* magit-switch-to-repository-buffer-other-window: Common Commands. + (line 7) +* magit-tag: Tagging. (line 9) +* magit-tag-create: Tagging. (line 14) +* magit-tag-delete: Tagging. (line 37) +* magit-tag-prune: Tagging. (line 43) +* magit-tag-release: Tagging. (line 18) +* magit-toggle-buffer-lock: Modes and Buffers. (line 18) +* magit-toggle-margin: Refreshing Logs. (line 34) +* magit-toggle-margin <1>: Log Margin. (line 60) +* magit-toggle-margin-details: Log Margin. (line 66) +* magit-toggle-verbose-refresh: Debugging Tools. (line 29) +* magit-unstage: Staging and Unstaging. + (line 42) +* magit-unstage-all: Staging and Unstaging. + (line 50) +* magit-unstage-file: Staging from File-Visiting Buffers. + (line 18) +* magit-unstage-file <1>: Commands for Buffers Visiting Files. + (line 32) +* magit-version: Git Executable. (line 59) +* magit-version <1>: Debugging Tools. (line 11) +* magit-visit-ref: References Buffer. (line 159) +* magit-wip-commit: Wip Modes. (line 85) +* magit-wip-log: Wip Modes. (line 47) +* magit-wip-log-current: Wip Modes. (line 55) +* magit-worktree: Worktree. (line 9) +* magit-worktree-branch: Worktree. (line 16) +* magit-worktree-checkout: Worktree. (line 13) +* magit-worktree-delete: Worktree. (line 22) +* magit-worktree-move: Worktree. (line 19) +* magit-worktree-status: Worktree. (line 26) +* scroll-down: Commands Available in Diffs. + (line 56) +* scroll-up: Commands Available in Diffs. + (line 53) +* with-editor-cancel: Editing Commit Messages. + (line 22) +* with-editor-cancel <1>: Editing Rebase Sequences. + (line 11) +* with-editor-debug: Debugging Tools. (line 41) +* with-editor-finish: Editing Commit Messages. + (line 18) +* with-editor-finish <1>: Editing Rebase Sequences. + (line 7) +* with-editor-usage-message: Commit Mode and Hooks. + (line 52)  -File: magit.info, Node: Variable Index, Prev: Function Index, Up: Top +File: magit.info, Node: Variable Index, Prev: Function and Command Index, Up: Top -Appendix F Variable Index +Appendix E Variable Index ************************* [index] * Menu: * auto-revert-buffer-list-filter: Automatic Reverting of File-Visiting Buffers. - (line 81) + (line 73) * auto-revert-interval: Automatic Reverting of File-Visiting Buffers. - (line 76) + (line 69) * auto-revert-mode: Automatic Reverting of File-Visiting Buffers. - (line 62) + (line 57) * auto-revert-stop-on-user-input: Automatic Reverting of File-Visiting Buffers. - (line 71) + (line 65) * auto-revert-use-notify: Automatic Reverting of File-Visiting Buffers. - (line 49) + (line 46) * auto-revert-verbose: Automatic Reverting of File-Visiting Buffers. - (line 103) + (line 94) * branch.autoSetupMerge: Branch Git Variables. - (line 81) + (line 71) * branch.autoSetupRebase: Branch Git Variables. - (line 98) + (line 85) * branch.NAME.description: Branch Git Variables. - (line 48) + (line 42) * branch.NAME.merge: Branch Git Variables. (line 10) * branch.NAME.pushRemote: Branch Git Variables. - (line 34) + (line 29) * branch.NAME.rebase: Branch Git Variables. - (line 22) + (line 20) * branch.NAME.remote: Branch Git Variables. - (line 16) -* core.notesRef: Notes. (line 60) + (line 15) +* core.notesRef: Notes. (line 53) * git-commit-fill-column: Commit Message Conventions. - (line 19) + (line 18) * git-commit-finish-query-functions: Commit Message Conventions. - (line 24) + (line 22) * git-commit-known-pseudo-headers: Commit Pseudo Headers. (line 9) * git-commit-major-mode: Commit Mode and Hooks. (line 12) * git-commit-setup-hook: Commit Mode and Hooks. - (line 22) + (line 21) * git-commit-setup-hook <1>: Commit Mode and Hooks. - (line 64) + (line 55) * git-commit-style-convention-checks: Commit Message Conventions. - (line 46) + (line 42) * git-commit-summary-max-length: Commit Message Conventions. (line 13) * git-rebase-auto-advance: Editing Rebase Sequences. - (line 99) + (line 80) * git-rebase-confirm-cancel: Editing Rebase Sequences. - (line 107) + (line 86) * git-rebase-show-instructions: Editing Rebase Sequences. - (line 103) + (line 83) * global-auto-revert-mode: Automatic Reverting of File-Visiting Buffers. - (line 22) + (line 21) * magit-auto-revert-immediately: Automatic Reverting of File-Visiting Buffers. - (line 32) + (line 30) * magit-auto-revert-mode: Automatic Reverting of File-Visiting Buffers. (line 17) * magit-auto-revert-tracked-only: Automatic Reverting of File-Visiting Buffers. - (line 55) -* magit-bisect-show-graph: Bisecting. (line 65) -* magit-blame-disable-modes: Blaming. (line 165) -* magit-blame-echo-style: Blaming. (line 148) -* magit-blame-goto-chunk-hook: Blaming. (line 171) -* magit-blame-read-only: Blaming. (line 160) -* magit-blame-styles: Blaming. (line 143) -* magit-blame-time-format: Blaming. (line 155) -* magit-branch-adjust-remote-upstream-alist: Branch Commands. (line 210) -* magit-branch-direct-configure: Branch Commands. (line 20) -* magit-branch-prefer-remote-upstream: Branch Commands. (line 165) -* magit-branch-read-upstream-first: Branch Commands. (line 159) -* magit-buffer-name-format: Naming Buffers. (line 27) -* magit-bury-buffer-function: Quitting Windows. (line 14) -* magit-cherry-margin: Cherries. (line 22) + (line 51) +* magit-bisect-show-graph: Bisecting. (line 57) +* magit-blame-disable-modes: Blaming. (line 149) +* magit-blame-echo-style: Blaming. (line 135) +* magit-blame-goto-chunk-hook: Blaming. (line 154) +* magit-blame-read-only: Blaming. (line 145) +* magit-blame-styles: Blaming. (line 131) +* magit-blame-time-format: Blaming. (line 141) +* magit-branch-adjust-remote-upstream-alist: Branch Commands. (line 196) +* magit-branch-direct-configure: Branch Commands. (line 19) +* magit-branch-prefer-remote-upstream: Branch Commands. (line 152) +* magit-branch-read-upstream-first: Branch Commands. (line 147) +* magit-buffer-name-format: Naming Buffers. (line 25) +* magit-bury-buffer-function: Quitting Windows. (line 13) +* magit-cherry-margin: Cherries. (line 21) * magit-clone-always-transient: Cloning Repository. (line 12) -* magit-clone-default-directory: Cloning Repository. (line 90) -* magit-clone-name-alist: Cloning Repository. (line 103) -* magit-clone-set-remote-head: Cloning Repository. (line 68) -* magit-clone-set-remote.pushDefault: Cloning Repository. (line 78) -* magit-clone-url-format: Cloning Repository. (line 124) -* magit-commit-ask-to-stage: Initiating a Commit. (line 75) -* magit-commit-extend-override-date: Initiating a Commit. (line 80) -* magit-commit-reword-override-date: Initiating a Commit. (line 84) -* magit-commit-squash-confirm: Initiating a Commit. (line 88) +* magit-clone-default-directory: Cloning Repository. (line 78) +* magit-clone-name-alist: Cloning Repository. (line 88) +* magit-clone-set-remote-head: Cloning Repository. (line 60) +* magit-clone-set-remote.pushDefault: Cloning Repository. (line 69) +* magit-clone-url-format: Cloning Repository. (line 108) +* magit-commit-ask-to-stage: Initiating a Commit. (line 65) +* magit-commit-diff-inhibit-same-window: Initiating a Commit. (line 97) +* magit-commit-extend-override-date: Initiating a Commit. (line 72) +* magit-commit-reword-override-date: Initiating a Commit. (line 75) +* magit-commit-show-diff: Initiating a Commit. (line 69) +* magit-commit-squash-confirm: Initiating a Commit. (line 78) * magit-completing-read-function: Support for Completion Frameworks. (line 27) * magit-define-global-key-bindings: Default Bindings. (line 6) -* magit-diff-adjust-tab-width: Diff Options. (line 21) +* magit-diff-adjust-tab-width: Diff Options. (line 17) * magit-diff-buffer-file-locked: Commands for Buffers Visiting Files. - (line 61) -* magit-diff-hide-trailing-cr-characters: Diff Options. (line 90) -* magit-diff-highlight-hunk-region-functions: Diff Options. (line 94) -* magit-diff-highlight-indentation: Diff Options. (line 75) -* magit-diff-highlight-trailing: Diff Options. (line 70) -* magit-diff-paint-whitespace: Diff Options. (line 43) -* magit-diff-paint-whitespace-lines: Diff Options. (line 60) + (line 55) +* magit-diff-extra-stat-arguments: Diff Options. (line 112) +* magit-diff-hide-trailing-cr-characters: Diff Options. (line 77) +* magit-diff-highlight-hunk-region-functions: Diff Options. (line 80) +* magit-diff-highlight-indentation: Diff Options. (line 63) +* magit-diff-highlight-trailing: Diff Options. (line 59) +* magit-diff-paint-whitespace: Diff Options. (line 38) +* magit-diff-paint-whitespace-lines: Diff Options. (line 52) * magit-diff-refine-hunk: Diff Options. (line 6) -* magit-diff-refine-ignore-whitespace: Diff Options. (line 16) -* magit-diff-unmarked-lines-keep-foreground: Diff Options. (line 120) +* magit-diff-refine-ignore-whitespace: Diff Options. (line 13) +* magit-diff-unmarked-lines-keep-foreground: Diff Options. (line 105) * magit-diff-visit-previous-blob: Visiting Files and Blobs from a Diff. - (line 39) + (line 38) * magit-direct-use-buffer-arguments: Transient Arguments and Buffer Variables. - (line 73) -* magit-display-buffer-function: Switching Buffers. (line 27) -* magit-display-buffer-noselect: Switching Buffers. (line 18) + (line 72) +* magit-display-buffer-function: Switching Buffers. (line 25) +* magit-display-buffer-noselect: Switching Buffers. (line 17) * magit-dwim-selection: Completion and Confirmation. (line 42) -* magit-ediff-dwim-show-on-hunks: Ediffing. (line 73) -* magit-ediff-quit-hook: Ediffing. (line 88) -* magit-ediff-show-stash-with-index: Ediffing. (line 81) +* magit-ediff-dwim-show-on-hunks: Ediffing. (line 63) +* magit-ediff-quit-hook: Ediffing. (line 76) +* magit-ediff-show-stash-with-index: Ediffing. (line 70) * magit-generate-buffer-name-function: Naming Buffers. (line 6) -* magit-git-debug: Viewing Git Output. (line 28) +* magit-git-debug: Viewing Git Output. (line 26) * magit-git-debug <1>: Getting a Value from Git. - (line 64) -* magit-git-executable: Git Executable. (line 39) + (line 68) +* magit-git-executable: Git Executable. (line 26) * magit-git-global-arguments: Global Git Arguments. (line 6) * magit-keep-region-overlay: The Selection. (line 52) @@ -3510,104 +3568,107 @@ Appendix F Variable Index (line 6) * magit-log-auto-more: Log Buffer. (line 69) * magit-log-buffer-file-locked: Commands for Buffers Visiting Files. - (line 88) + (line 78) * magit-log-margin: Log Margin. (line 12) -* magit-log-margin-show-committer-date: Log Margin. (line 49) -* magit-log-section-commit-count: Status Sections. (line 136) -* magit-log-select-margin: Select from Log. (line 30) -* magit-log-show-refname-after-summary: Log Buffer. (line 75) +* magit-log-margin-show-committer-date: Log Margin. (line 44) +* magit-log-section-commit-count: Status Sections. (line 114) +* magit-log-select-margin: Select from Log. (line 28) +* magit-log-show-refname-after-summary: Log Buffer. (line 74) * magit-log-trace-definition-function: Commands Available in Diffs. - (line 18) + (line 17) * magit-module-sections-hook: Status Module Sections. - (line 20) + (line 19) * magit-module-sections-nested: Status Module Sections. - (line 24) + (line 22) * magit-no-confirm: Action Confirmation. (line 18) * magit-pop-revision-stack-format: Using the Revision Stack. - (line 35) -* magit-post-display-buffer-hook: Switching Buffers. (line 95) -* magit-pre-display-buffer-hook: Switching Buffers. (line 84) + (line 34) +* magit-post-commit-hook: Initiating a Commit. (line 86) +* magit-post-display-buffer-hook: Switching Buffers. (line 85) +* magit-pre-display-buffer-hook: Switching Buffers. (line 76) * magit-prefer-remote-upstream: Branch Git Variables. - (line 126) + (line 109) * magit-prefix-use-buffer-arguments: Transient Arguments and Buffer Variables. (line 64) +* magit-process-extreme-logging: Viewing Git Output. (line 44) * magit-process-raise-error: Calling Git for Effect. - (line 151) -* magit-pull-or-fetch: Fetching. (line 59) -* magit-reflog-margin: Reflog. (line 23) -* magit-refresh-args: Refreshing Buffers. (line 55) + (line 125) +* magit-pull-or-fetch: Fetching. (line 51) +* magit-reflog-margin: Reflog. (line 20) +* magit-refresh-args: Refreshing Buffers. (line 52) * magit-refresh-buffer-hook: Automatic Refreshing of Magit Buffers. - (line 42) -* magit-refresh-function: Refreshing Buffers. (line 49) + (line 41) +* magit-refresh-function: Refreshing Buffers. (line 47) * magit-refresh-status-buffer: Automatic Refreshing of Magit Buffers. - (line 48) -* magit-refs-filter-alist: References Buffer. (line 159) -* magit-refs-focus-column-width: References Buffer. (line 82) -* magit-refs-margin: References Buffer. (line 97) -* magit-refs-margin-for-tags: References Buffer. (line 125) -* magit-refs-pad-commit-counts: References Buffer. (line 49) -* magit-refs-primary-column-width: References Buffer. (line 69) + (line 46) +* magit-refs-filter-alist: References Buffer. (line 137) +* magit-refs-focus-column-width: References Buffer. (line 75) +* magit-refs-margin: References Buffer. (line 89) +* magit-refs-margin-for-tags: References Buffer. (line 112) +* magit-refs-pad-commit-counts: References Buffer. (line 45) +* magit-refs-primary-column-width: References Buffer. (line 63) * magit-refs-sections-hook: References Sections. (line 13) -* magit-refs-show-commit-count: References Buffer. (line 37) -* magit-refs-show-remote-prefix: References Buffer. (line 62) -* magit-remote-add-set-remote.pushDefault: Remote Commands. (line 92) -* magit-remote-direct-configure: Remote Commands. (line 21) -* magit-repolist-columns: Repository List. (line 14) -* magit-repository-directories: Status Buffer. (line 58) -* magit-revision-filter-files-on-follow: Revision Buffer. (line 64) +* magit-refs-show-commit-count: References Buffer. (line 36) +* magit-refs-show-remote-prefix: References Buffer. (line 57) +* magit-remote-add-set-remote.pushDefault: Remote Commands. (line 83) +* magit-remote-direct-configure: Remote Commands. (line 20) +* magit-remote-git-executable: Git Executable. (line 32) +* magit-repolist-columns: Repository List. (line 13) +* magit-repository-directories: Status Buffer. (line 57) +* magit-revision-filter-files-on-follow: Revision Buffer. (line 55) * magit-revision-insert-related-refs: Revision Buffer. (line 6) -* magit-revision-show-gravatars: Revision Buffer. (line 19) -* magit-revision-use-hash-sections: Revision Buffer. (line 36) -* magit-root-section: Matching Sections. (line 87) +* magit-revision-show-gravatars: Revision Buffer. (line 15) +* magit-revision-use-hash-sections: Revision Buffer. (line 31) +* magit-root-section: Matching Sections. (line 81) * magit-save-repository-buffers: Automatic Saving of File-Visiting Buffers. (line 13) -* magit-section-cache-visibility: Section Visibility. (line 95) -* magit-section-initial-visibility-alist: Section Visibility. (line 78) -* magit-section-movement-hook: Section Movement. (line 46) -* magit-section-set-visibility-hook: Section Visibility. (line 106) +* magit-section-cache-visibility: Section Visibility. (line 82) +* magit-section-initial-visibility-alist: Section Visibility. (line 66) +* magit-section-movement-hook: Section Movement. (line 41) +* magit-section-set-visibility-hook: Section Visibility. (line 92) * magit-section-show-child-count: Section Options. (line 9) -* magit-section-visibility-indicator: Section Visibility. (line 124) +* magit-section-visibility-indicator: Section Visibility. (line 109) * magit-shell-command-verbose-prompt: Running Git Manually. - (line 47) -* magit-stashes-margin: Stashing. (line 104) + (line 44) +* magit-stashes-margin: Stashing. (line 87) * magit-status-headers-hook: Status Header Sections. - (line 18) -* magit-status-margin: Status Options. (line 10) + (line 17) +* magit-status-margin: Status Options. (line 9) * magit-status-refresh-hook: Status Options. (line 6) * magit-status-sections-hook: Status Sections. (line 10) -* magit-submodule-list-columns: Listing Submodules. (line 21) +* magit-submodule-list-columns: Listing Submodules. (line 20) * magit-this-process: Calling Git for Effect. - (line 146) -* magit-uniquify-buffer-names: Naming Buffers. (line 74) + (line 121) +* magit-uniquify-buffer-names: Naming Buffers. (line 71) * magit-unstage-committed: Staging and Unstaging. - (line 56) -* magit-update-other-window-delay: Section Movement. (line 112) -* magit-visit-ref-behavior: References Buffer. (line 192) -* magit-wip-after-apply-mode: Legacy Wip Modes. (line 19) -* magit-wip-after-apply-mode-lighter: Legacy Wip Modes. (line 59) -* magit-wip-after-save-local-mode-lighter: Legacy Wip Modes. (line 55) + (line 52) +* magit-update-other-window-delay: Section Movement. (line 97) +* magit-visit-ref-behavior: References Buffer. (line 168) +* magit-wip-after-apply-mode: Legacy Wip Modes. (line 18) +* magit-wip-after-apply-mode-lighter: Legacy Wip Modes. (line 54) +* magit-wip-after-save-local-mode-lighter: Legacy Wip Modes. (line 51) * magit-wip-after-save-mode: Legacy Wip Modes. (line 13) -* magit-wip-before-change-mode: Legacy Wip Modes. (line 33) -* magit-wip-before-change-mode-lighter: Legacy Wip Modes. (line 63) -* magit-wip-initial-backup-mode: Legacy Wip Modes. (line 38) -* magit-wip-initial-backup-mode-lighter: Legacy Wip Modes. (line 67) +* magit-wip-before-change-mode: Legacy Wip Modes. (line 31) +* magit-wip-before-change-mode-lighter: Legacy Wip Modes. (line 57) +* magit-wip-initial-backup-mode: Legacy Wip Modes. (line 35) +* magit-wip-initial-backup-mode-lighter: Legacy Wip Modes. (line 60) * magit-wip-merge-branch: Wip Graph. (line 6) * magit-wip-mode: Wip Modes. (line 30) -* magit-wip-mode-lighter: Wip Modes. (line 104) -* magit-wip-namespace: Wip Modes. (line 96) -* notes.displayRef: Notes. (line 65) +* magit-wip-mode-lighter: Wip Modes. (line 98) +* magit-wip-namespace: Wip Modes. (line 91) +* notes.displayRef: Notes. (line 57) * pull.rebase: Branch Git Variables. - (line 57) + (line 50) * remote.NAME.fetch: Remote Git Variables. - (line 15) + (line 14) * remote.NAME.push: Remote Git Variables. - (line 26) + (line 23) * remote.NAME.pushurl: Remote Git Variables. - (line 20) + (line 18) * remote.NAME.tagOpts: Remote Git Variables. - (line 31) + (line 27) * remote.NAME.url: Remote Git Variables. (line 10) * remote.pushDefault: Branch Git Variables. - (line 71) + (line 62) diff --git a/lisp/markdown-mode.el b/lisp/markdown-mode.el index 3abc381c..89b117ed 100644 --- a/lisp/markdown-mode.el +++ b/lisp/markdown-mode.el @@ -7,8 +7,8 @@ ;; Maintainer: Jason R. Blevins ;; Created: May 24, 2007 ;; Version: 2.5-dev -;; Package-Version: 20210107.101 -;; Package-Commit: 6d64f9e96203b1e76e3f0adfd2f545b5b02f5ffb +;; Package-Version: 20211022.55 +;; Package-Commit: 4469553a7395359e96b8796e1fac4de73cb6ccc4 ;; Package-Requires: ((emacs "25.1")) ;; Keywords: Markdown, GitHub Flavored Markdown, itex ;; URL: https://jblevins.org/projects/markdown-mode/ @@ -49,6 +49,10 @@ (defvar jit-lock-end) (defvar flyspell-generic-check-word-predicate) (defvar electric-pair-pairs) +(defvar sh-ancestor-alist) + +(declare-function project-roots "project") +(declare-function sh-set-shell "sh-script") ;;; Constants ================================================================= @@ -92,7 +96,7 @@ Any changes to the output buffer made by this hook will be saved.") :group 'text :link '(url-link "https://jblevins.org/projects/markdown-mode/")) -(defcustom markdown-command (let ((command (cl-loop for cmd in '("markdown" "pandoc") +(defcustom markdown-command (let ((command (cl-loop for cmd in '("markdown" "pandoc" "markdown_py") when (executable-find cmd) return (file-name-nondirectory it)))) (or command "markdown")) @@ -245,6 +249,22 @@ This is the default search behavior of Ikiwiki." :safe 'booleanp :package-version '(markdown-mode . "2.2")) +(defcustom markdown-wiki-link-search-type nil + "Searching type for markdown wiki link. + +sub-directories: search for wiki link targets in sub directories +parent-directories: search for wiki link targets in parent directories +project: search for wiki link targets under project root" + :group 'markdown + :type '(set + (const :tag "search wiki link from subdirectories" sub-directories) + (const :tag "search wiki link from parent directories" parent-directories) + (const :tag "search wiki link under project root" project)) + :package-version '(markdown-mode . "2.5")) + +(make-obsolete-variable 'markdown-wiki-link-search-subdirectories 'markdown-wiki-link-search-type "2.5") +(make-obsolete-variable 'markdown-wiki-link-search-parent-directories 'markdown-wiki-link-search-type "2.5") + (defcustom markdown-wiki-link-fontify-missing nil "When non-nil, change wiki link face according to existence of target files. This is expensive because it requires checking for the file each time the buffer @@ -329,6 +349,13 @@ Math support can be enabled, disabled, or toggled later using :safe 'booleanp :package-version '(markdown-mode . "2.4")) +(defcustom markdown-enable-highlighting-syntax nil + "Enable highlighting syntax." + :group 'markdown + :type 'boolean + :safe 'booleanp + :package-version '(markdown-mode . "2.5")) + (defcustom markdown-css-paths nil "List of URLs of CSS files to link to in the output XHTML." :group 'markdown @@ -429,6 +456,13 @@ The car is used for subscript, the cdr is used for superscripts." :group 'markdown :type 'string) +(defcustom markdown-ordered-list-enumeration t + "When non-nil, use enumerated numbers(1. 2. 3. etc.) for ordered list marker. +While nil, always uses '1.' for the marker" + :group 'markdown + :type 'boolean + :package-version '(markdown-mode . "2.5")) + (defcustom markdown-nested-imenu-heading-index t "Use nested or flat imenu heading index. A nested index may provide more natural browsing from the menu, @@ -475,7 +509,7 @@ If this value is 'any and `display-buffer-alist' is set then :package-version '(markdown-mode . "2.2")) (defcustom markdown-live-preview-window-function - 'markdown-live-preview-window-eww + #'markdown-live-preview-window-eww "Function to display preview of Markdown output within Emacs. Function must update the buffer containing the preview and return the buffer." @@ -594,7 +628,14 @@ requires Emacs to be built with ImageMagick support." "Non-nil means mouse on a link will follow the link. This variable must be set before loading markdown-mode." :group 'markdown - :type 'bool + :type 'boolean + :safe 'booleanp + :package-version '(markdown-mode . "2.5")) + +(defcustom markdown-table-align-p t + "Non-nil means that table is aligned after table operation." + :group 'markdown + :type 'boolean :safe 'booleanp :package-version '(markdown-mode . "2.5")) @@ -742,8 +783,8 @@ Group 5 matches the closing brace (optional), whitespace, and newline. Groups need to agree with `markdown-regex-tilde-fence-begin'.") (defconst markdown-regex-gfm-code-block-close - "^[[:blank:]]*\\(?1:```\\)\\(?2:\\s *?\\)$" - "Regular expression matching closing of GFM code blocks. + "^[[:blank:]]*\\(?1:```\\)\\(?2:\\s *?\\)$" + "Regular expression matching closing of GFM code blocks. Group 1 matches the closing three backquotes. Group 2 matches any whitespace and the final newline.") @@ -810,7 +851,7 @@ Group 2 matches the separating whitespace. Group 3 matches the text.") (defconst markdown-regex-line-break - "[^ \n\t][ \t]*\\( \\)$" + "[^ \n\t][ \t]*\\( \\)\n" "Regular expression for matching line breaks.") (defconst markdown-regex-wiki-link @@ -829,7 +870,7 @@ Group 5 matches the second component of the wiki link, when present. Group 6 matches the closing square brackets.") (defconst markdown-regex-uri - (concat "\\(" (regexp-opt markdown-uri-types) ":[^]\t\n\r<>,;() ]+\\)") + (concat "\\(" (regexp-opt markdown-uri-types) ":[^]\t\n\r<>; ]+\\)") "Regular expression for matching inline URIs.") (defconst markdown-regex-angle-uri @@ -1011,6 +1052,15 @@ Group 3 matches all attributes and whitespace following the tag name.") "\\(&#?[[:alnum:]]+;\\)" "Regular expression for matching HTML entities.") +(defconst markdown-regex-highlighting + "\\(?1:^\\|[^\\]\\)\\(?2:\\(?3:==\\)\\(?4:[^ \n\t\\]\\|[^ \n\t]\\(?:.\\|\n[^\n]\\)*?[^\\ ]\\)\\(?5:==\\)\\)" +"Regular expression for matching highlighting text. +Group 1 matches the character before the opening equal, if any, +ensuring that it is not a backslash escape. +Group 2 matches the entire expression, including delimiters. +Groups 3 and 5 matches the opening and closing delimiters. +Group 4 matches the text inside the delimiters.") + ;;; Syntax ==================================================================== @@ -1075,9 +1125,16 @@ Function is called repeatedly until it returns nil. For details, see (max end (match-beginning 0)) (point-max)))) (code-match (markdown-code-block-at-pos new-start)) - (new-start (or (and code-match (cl-first code-match)) new-start)) - (code-match (and (< end (point-max)) (markdown-code-block-at-pos end))) - (new-end (or (and code-match (cl-second code-match)) new-end))) + ;; FIXME: The `code-match' can return bogus values + ;; when text has been inserted/deleted! + (new-start (min (or (and code-match (cl-first code-match)) + (point-max)) + new-start)) + (code-match (and (< end (point-max)) + (markdown-code-block-at-pos end))) + (new-end (max (or (and code-match (cl-second code-match)) 0) + new-end))) + (unless (and (eq new-start start) (eq new-end end)) (cons new-start (min new-end (point-max)))))))) @@ -1187,9 +1244,9 @@ giving the bounds of the current and parent list items." (marker (cl-fifth cur-bounds))) (setq bounds (markdown--append-list-item-bounds marker indent cur-bounds bounds)) - (when (and (<= start (point)) (<= (point) end)) - (setq prev-list-line (line-number-at-pos first)) - (put-text-property first last 'markdown-list-item bounds))))) + (when (and (<= start (point)) (<= (point) end)) + (setq prev-list-line (line-number-at-pos first)) + (put-text-property first last 'markdown-list-item bounds))))) (end-of-line))))) (defun markdown-syntax-propertize-pre-blocks (start end) @@ -1513,7 +1570,8 @@ MIDDLE-BEGIN is the start of the \"middle\" section of the block." (cl-third fence-spec) (list middle-begin close-begin)) ;; If the block is a YAML block, propertize the declarations inside - (markdown-syntax-propertize-yaml-metadata middle-begin close-begin) + (when (< middle-begin close-begin) ;; workaround #634 + (markdown-syntax-propertize-yaml-metadata middle-begin close-begin)) ;; Propertize closing line of fenced block. (put-text-property close-begin close-end (cl-cadadr fence-spec) close-data)))) @@ -1670,7 +1728,7 @@ region of a YAML metadata block as propertized by markdown--syntax-properties) (put-text-property comment-begin comment-end 'markdown-comment (list comment-begin comment-end)) - (goto-char (min (1+ comment-end) end (point-max))))) + (goto-char (min comment-end end (point-max))))) ;; Nothing found (t (setq finish t))))) nil)) @@ -1754,7 +1812,7 @@ See `markdown-hide-markup' for additional details." (require 'font-lock) (defgroup markdown-faces nil - "Faces used in Markdown Mode" + "Faces used in Markdown Mode." :group 'markdown :group 'faces) @@ -1939,6 +1997,11 @@ For example, this applies to plain angle bracket URLs: "Face for HTML entities." :group 'markdown-faces) +(defface markdown-highlighting-face + '((t (:background "yellow" :foreground "black"))) + "Face for highlighting." + :group 'markdown-faces) + (defcustom markdown-header-scaling nil "Whether to use variable-height faces for headers. When non-nil, `markdown-header-face' will inherit from @@ -1946,7 +2009,7 @@ When non-nil, `markdown-header-face' will inherit from `markdown-header-scaling-values' will be applied to headers of levels one through six respectively." :type 'boolean - :initialize 'custom-initialize-default + :initialize #'custom-initialize-default :set (lambda (symbol value) (set-default symbol value) (markdown-update-header-faces value)) @@ -1958,37 +2021,39 @@ headers of levels one through six respectively." "List of scaling values for headers of level one through six. Used when `markdown-header-scaling' is non-nil." :type 'list - :initialize 'custom-initialize-default + :initialize #'custom-initialize-default :set (lambda (symbol value) (set-default symbol value) - (markdown-update-header-faces markdown-header-scaling value)) - :group 'markdown-faces) + (markdown-update-header-faces markdown-header-scaling value))) -(defun markdown-make-header-faces () - "Build the faces used for Markdown headers." - (let ((inherit-faces '(font-lock-function-name-face))) - (when markdown-header-scaling - (setq inherit-faces (cons 'variable-pitch inherit-faces))) - (defface markdown-header-face - `((t (:inherit ,inherit-faces :weight bold))) - "Base face for headers." - :group 'markdown-faces)) - (dotimes (num 6) - (let* ((num1 (1+ num)) - (face-name (intern (format "markdown-header-face-%s" num1))) - (scale (if markdown-header-scaling - (float (nth num markdown-header-scaling-values)) - 1.0))) - (eval - `(defface ,face-name - '((t (:inherit markdown-header-face :height ,scale))) - (format "Face for level %s headers. +(defmacro markdown--dotimes-when-compile (i-n body) + (declare (indent 1) (debug ((symbolp form) form))) + (let ((var (car i-n)) + (n (cadr i-n)) + (code ())) + (dotimes (i (eval n t)) + (push (eval body `((,var . ,i))) code)) + `(progn ,@(nreverse code)))) + +(defface markdown-header-face + `((t (:inherit (,@(when markdown-header-scaling '(variable-pitch)) + font-lock-function-name-face) + :weight bold))) + "Base face for headers.") + +(markdown--dotimes-when-compile (num 6) + (let* ((num1 (1+ num)) + (face-name (intern (format "markdown-header-face-%s" num1)))) + `(defface ,face-name + (,'\` ((t (:inherit markdown-header-face + :height + (,'\, (if markdown-header-scaling + (float (nth ,num markdown-header-scaling-values)) + 1.0)))))) + (format "Face for level %s headers. You probably don't want to customize this face directly. Instead you can customize the base face `markdown-header-face' or the -variable-height variable `markdown-header-scaling'." ,num1) - :group 'markdown-faces))))) - -(markdown-make-header-faces) +variable-height variable `markdown-header-scaling'." ,num1)))) (defun markdown-update-header-faces (&optional scaling scaling-values) "Update header faces, depending on if header SCALING is desired. @@ -2056,8 +2121,8 @@ Depending on your font, some reasonable choices are: (markdown-match-pre-blocks . ((0 'markdown-pre-face))) (markdown-fontify-headings) (markdown-match-declarative-metadata . ((1 'markdown-metadata-key-face) - (2 'markdown-markup-face) - (3 'markdown-metadata-value-face))) + (2 'markdown-markup-face) + (3 'markdown-metadata-value-face))) (markdown-match-pandoc-metadata . ((1 'markdown-markup-face) (2 'markdown-markup-face) (3 'markdown-metadata-value-face))) @@ -2129,6 +2194,9 @@ Depending on your font, some reasonable choices are: (,markdown-regex-strike-through . ((3 markdown-markup-properties) (4 'markdown-strike-through-face) (5 markdown-markup-properties))) + (markdown--match-highlighting . ((3 markdown-markup-properties) + (4 'markdown-highlighting-face) + (5 markdown-markup-properties))) (,markdown-regex-line-break . (1 'markdown-line-break-face prepend)) (markdown-fontify-sub-superscripts) (markdown-match-inline-attributes . ((0 markdown-markup-properties prepend))) @@ -2590,7 +2658,8 @@ intact additional processing." (match-beginning 5) (match-end 5))))))))) (defun markdown-get-defined-references () - "Return all defined reference labels and their line numbers (not including square brackets)." + "Return all defined reference labels and their line numbers. +They does not include square brackets)." (save-excursion (goto-char (point-min)) (let (refs) @@ -2768,12 +2837,12 @@ When FACELESS is non-nil, do not return matches where faces have been applied." (not (markdown-in-comment-p (match-end 1))) (not (markdown-code-block-at-pos (match-beginning 1))))) markdown-regex-code last t) - (set-match-data (list (match-beginning 1) (match-end 1) - (match-beginning 2) (match-end 2) - (match-beginning 3) (match-end 3) - (match-beginning 4) (match-end 4))) - (goto-char (min (1+ (match-end 0)) last (point-max))) - t)) + (set-match-data (list (match-beginning 1) (match-end 1) + (match-beginning 2) (match-end 2) + (match-beginning 3) (match-end 3) + (match-beginning 4) (match-end 4))) + (goto-char (min (1+ (match-end 0)) last (point-max))) + t)) (defun markdown--gfm-markup-underscore-p (begin end) (let ((is-underscore (eql (char-after begin) ?_))) @@ -2849,6 +2918,10 @@ When FACELESS is non-nil, do not return matches where faces have been applied." (match-beginning 4) (match-end 4))) t))))) +(defun markdown--match-highlighting (last) + (when markdown-enable-highlighting-syntax + (re-search-forward markdown-regex-highlighting last t))) + (defun markdown-match-math-generic (regex last) "Match REGEX from point to LAST. REGEX is either `markdown-regex-math-inline-single' for matching @@ -3028,9 +3101,9 @@ processed elements." ;; Move over balanced expressions to closing right bracket. ;; Catch unbalanced expression errors and return nil. (first-end (condition-case nil - (and (goto-char first-begin) - (scan-sexps (point) 1)) - (error nil))) + (and (goto-char first-begin) + (scan-sexps (point) 1)) + (error nil))) ;; Continue with point at CONT-POINT upon failure. (cont-point (min (1+ first-begin) last)) second-begin second-end url-begin url-end @@ -3041,8 +3114,8 @@ processed elements." ;; Scan across balanced expressions for closing parenthesis/bracket. (setq second-begin (point) second-end (condition-case nil - (scan-sexps (point) 1) - (error nil))) + (scan-sexps (point) 1) + (error nil))) ;; Check that closing parenthesis/bracket is in range. (if (and second-end (<= second-end end-of-block) (<= second-end last)) (progn @@ -3276,24 +3349,31 @@ Group 7: closing filename delimiter" ;;; Markdown Font Fontification Functions ===================================== +(defvar markdown--first-displayable-cache (make-hash-table :test #'equal)) + (defun markdown--first-displayable (seq) "Return the first displayable character or string in SEQ. SEQ may be an atom or a sequence." - (let ((seq (if (listp seq) seq (list seq)))) - (cond ((stringp (car seq)) - (cl-find-if - (lambda (str) - (and (mapcar #'char-displayable-p (string-to-list str)))) - seq)) - ((characterp (car seq)) - (cl-find-if #'char-displayable-p seq))))) + (let ((c (gethash seq markdown--first-displayable-cache t))) + (if (not (eq c t)) + c + (puthash seq + (let ((seq (if (listp seq) seq (list seq)))) + (cond ((stringp (car seq)) + (cl-find-if + (lambda (str) + (and (mapcar #'char-displayable-p (string-to-list str)))) + seq)) + ((characterp (car seq)) + (cl-find-if #'char-displayable-p seq)))) + markdown--first-displayable-cache)))) (defun markdown--marginalize-string (level) "Generate atx markup string of given LEVEL for left margin." (let ((margin-left-space-count (- markdown-marginalize-headers-margin-width level))) (concat (make-string margin-left-space-count ? ) - (make-string level ?#)))) + (make-string level ?#)))) (defun markdown-marginalize-update-current () "Update the window configuration to create a left margin." @@ -3371,7 +3451,8 @@ SEQ may be an atom or a sequence." (defun markdown-fontify-list-items (last) "Apply font-lock properties to list markers from point to LAST." - (when (markdown-match-list-items last) + (when (and (markdown-match-list-items last) + (not (markdown-code-block-at-point-p (match-beginning 2)))) (let* ((indent (length (match-string-no-properties 1))) (level (/ indent markdown-list-indent-width)) ;; level = 0, 1, 2, ... (bullet (nth (mod level (length markdown-list-item-bullets)) @@ -3403,7 +3484,7 @@ SEQ may be an atom or a sequence." font-lock-multiline t ,@(when (and markdown-hide-markup hr-char) `(display ,(make-string - (window-body-width) hr-char))))) + (1- (window-body-width)) hr-char))))) t))) (defun markdown-fontify-sub-superscripts (last) @@ -3562,13 +3643,26 @@ prefixed with an integer from 1 to the length of (insert (car markdown-hr-strings)))) (markdown-ensure-blank-line-after)) -(defun markdown--insert-common (start-delim end-delim regex start-group end-group face) +(defun markdown--insert-common (start-delim end-delim regex start-group end-group face + &optional skip-space) (if (use-region-p) ;; Active region - (let ((bounds (markdown-unwrap-things-in-region - (region-beginning) (region-end) - regex start-group end-group))) - (markdown-wrap-or-insert start-delim end-delim nil (car bounds) (cdr bounds))) + (let* ((bounds (markdown-unwrap-things-in-region + (region-beginning) (region-end) + regex start-group end-group)) + (beg (car bounds)) + (end (cdr bounds))) + (when (and beg skip-space) + (save-excursion + (goto-char beg) + (skip-chars-forward "[ \t]") + (setq beg (point)))) + (when (and end skip-space) + (save-excursion + (goto-char end) + (skip-chars-backward "[ \t]") + (setq end (point)))) + (markdown-wrap-or-insert start-delim end-delim nil beg end)) (if (markdown--face-p (point) (list face)) (save-excursion (while (and (markdown--face-p (point) (list face)) (not (bobp))) @@ -3590,7 +3684,7 @@ bold word or phrase, remove the bold markup. Otherwise, simply insert bold delimiters and place the point in between them." (interactive) (let ((delim (if markdown-bold-underscore "__" "**"))) - (markdown--insert-common delim delim markdown-regex-bold 2 4 'markdown-bold-face))) + (markdown--insert-common delim delim markdown-regex-bold 2 4 'markdown-bold-face t))) (defun markdown-insert-italic () "Insert markup to make a region or word italic. @@ -3600,7 +3694,7 @@ italic word or phrase, remove the italic markup. Otherwise, simply insert italic delimiters and place the point in between them." (interactive) (let ((delim (if markdown-italic-underscore "_" "*"))) - (markdown--insert-common delim delim markdown-regex-italic 1 3 'markdown-italic-face))) + (markdown--insert-common delim delim markdown-regex-italic 1 3 'markdown-italic-face t))) (defun markdown-insert-strike-through () "Insert markup to make a region or word strikethrough. @@ -3610,7 +3704,7 @@ strikethrough word or phrase, remove the strikethrough markup. Otherwise, simply insert bold delimiters and place the point in between them." (interactive) (markdown--insert-common - "~~" "~~" markdown-regex-strike-through 2 4 'markdown-strike-through-face)) + "~~" "~~" markdown-regex-strike-through 2 4 'markdown-strike-through-face t)) (defun markdown-insert-code () "Insert markup to make a region or word an inline code fragment. @@ -3825,7 +3919,7 @@ This is an internal function called by (markdown-insert-uri uri)))))) (defun markdown-insert-link () - "Insert new or update an existing link, with interactive prompts. + "Insert new or update an existing link, with interactive prompt. If the point is at an existing link or URL, update the link text, URL, reference label, and/or title. Otherwise, insert a new link. The type of link inserted (inline, reference, or plain URL) @@ -3860,7 +3954,7 @@ selectively adding or removing information via the prompts." (markdown--insert-link-or-image nil)) (defun markdown-insert-image () - "Insert new or update an existing image, with interactive prompts. + "Insert new or update an existing image, with interactive prompt. If the point is at an existing image, update the alt text, URL, reference label, and/or title. Otherwise, insert a new image. The type of image inserted (inline or reference) depends on which @@ -4293,7 +4387,7 @@ if three backquotes inserted at the beginning of line." (defun markdown-gfm-add-used-language (lang) "Clean LANG and add to list of used languages." (setq markdown-gfm-used-languages - (cons lang (remove lang markdown-gfm-used-languages)))) + (cons lang (remove lang markdown-gfm-used-languages)))) (defcustom markdown-spaces-after-code-fence 1 "Number of space characters to insert after a code fence. @@ -4412,6 +4506,49 @@ at the beginning of the block." do (progn (when lang (markdown-gfm-add-used-language lang)) (goto-char (next-single-property-change (point) prop))))))) +(defun markdown-insert-foldable-block () + "Insert details disclosure element to make content foldable. +If a region is active, wrap this region with the disclosure +element. More detais here 'https://developer.mozilla.org/en-US/docs/Web/HTML/Element/details'." + (interactive) + (let ((details-open-tag "
") + (details-close-tag "
") + (summary-open-tag "") + (summary-close-tag " ")) + (if (use-region-p) + (let* ((b (region-beginning)) + (e (region-end)) + (indent (progn (goto-char b) (current-indentation)))) + (goto-char e) + ;; if we're on a blank line, don't newline, otherwise the tags + ;; should go on its own line + (unless (looking-back "\n" nil) + (newline)) + (indent-to indent) + (insert details-close-tag) + (markdown-ensure-blank-line-after) + (goto-char b) + ;; if we're on a blank line, insert the quotes here, otherwise + ;; add a new line first + (unless (looking-at-p "\n") + (newline) + (forward-line -1)) + (markdown-ensure-blank-line-before) + (indent-to indent) + (insert details-open-tag "\n") + (insert summary-open-tag summary-close-tag) + (search-backward summary-close-tag)) + (let ((indent (current-indentation))) + (delete-horizontal-space :backward-only) + (markdown-ensure-blank-line-before) + (indent-to indent) + (insert details-open-tag "\n") + (insert summary-open-tag summary-close-tag "\n") + (insert details-close-tag) + (indent-to indent) + (markdown-ensure-blank-line-after) + (search-backward summary-close-tag))))) + ;;; Footnotes ================================================================= @@ -4811,7 +4948,7 @@ duplicate positions, which are handled up by calling functions." ;; Return reversed list (reverse positions))) -(defun markdown-enter-key () +(defun markdown-enter-key () ;FIXME: Partly obsoleted by electric-indent "Handle RET depending on the context. If the point is at a table, move to the next row. Otherwise, indent according to value of `markdown-indent-on-enter'. @@ -5018,7 +5155,7 @@ Handle all elements of `markdown-complete-alist' in order." (interactive "*") (let ((list markdown-complete-alist) found changed) (while list - (let ((regexp (eval (caar list))) + (let ((regexp (eval (caar list) t)) ;FIXME: Why `eval'? (function (cdar list))) (setq list (cdr list)) (when (thing-at-point-looking-at regexp) @@ -5038,7 +5175,7 @@ match." (let ((end-marker (set-marker (make-marker) end)) previous) (dolist (element markdown-complete-alist) - (let ((regexp (eval (car element))) + (let ((regexp (eval (car element) t)) ;FIXME: Why `eval'? (function (cdr element))) (goto-char beg) (while (re-search-forward regexp end-marker 'limit) @@ -5157,6 +5294,7 @@ Assumes match data is available for `markdown-regex-italic'." (propertize "C = GFM code" 'face 'markdown-code-face) ", " (propertize "pre" 'face 'markdown-pre-face) ", " (propertize "footnote" 'face 'markdown-footnote-text-face) ", " + (propertize "F = foldable" 'face 'markdown-bold-face) ", " (propertize "q = blockquote" 'face 'markdown-blockquote-face) ", " (propertize "h & 1-6 = heading" 'face 'markdown-header-face) ", " (propertize "- = hr" 'face 'markdown-hr-face) ", " @@ -5190,6 +5328,7 @@ Assumes match data is available for `markdown-regex-italic'." (define-key map (kbd "c") 'markdown-insert-code) (define-key map (kbd "C") 'markdown-insert-gfm-code-block) (define-key map (kbd "f") 'markdown-insert-footnote) + (define-key map (kbd "F") 'markdown-insert-foldable-block) (define-key map (kbd "h") 'markdown-insert-header-dwim) (define-key map (kbd "H") 'markdown-insert-header-setext-dwim) (define-key map (kbd "i") 'markdown-insert-italic) @@ -5243,14 +5382,16 @@ Assumes match data is available for `markdown-regex-italic'." (define-key map (kbd "C-c C-d") 'markdown-do) (define-key map (kbd "C-c '") 'markdown-edit-code-block) ;; Indentation - (define-key map (kbd "C-m") 'markdown-enter-key) + (define-key map (kbd "RET") 'markdown-enter-key) (define-key map (kbd "DEL") 'markdown-outdent-or-delete) (define-key map (kbd "C-c >") 'markdown-indent-region) (define-key map (kbd "C-c <") 'markdown-outdent-region) ;; Visibility cycling (define-key map (kbd "TAB") 'markdown-cycle) - (define-key map (kbd "") 'markdown-shifttab) - (define-key map (kbd "") 'markdown-shifttab) + ;; S-iso-lefttab and S-tab should both be mapped to `backtab' by + ;; (local-)function-key-map. + ;;(define-key map (kbd "") 'markdown-shifttab) + ;;(define-key map (kbd "") 'markdown-shifttab) (define-key map (kbd "") 'markdown-shifttab) ;; Heading and list navigation (define-key map (kbd "C-c C-n") 'markdown-outline-next) @@ -5348,7 +5489,7 @@ See also `markdown-mode-map'.") ;;; Menu ====================================================================== (easy-menu-define markdown-mode-menu markdown-mode-map - "Menu for Markdown mode" + "Menu for Markdown mode." '("Markdown" "---" ("Movement" @@ -5432,10 +5573,10 @@ See also `markdown-mode-map'.") ["Move Row Down" markdown-move-down :enable (markdown-table-at-point-p) :keys "C-c "] - ["Move Column Left" markdown-demote + ["Move Column Left" markdown-promote :enable (markdown-table-at-point-p) :keys "C-c "] - ["Move Column Right" markdown-promote + ["Move Column Right" markdown-demote :enable (markdown-table-at-point-p) :keys "C-c "] ["Delete Row" markdown-table-delete-row @@ -5501,6 +5642,7 @@ See also `markdown-mode-map'.") ["GFM Code Block" markdown-insert-gfm-code-block] ["Edit Code Block" markdown-edit-code-block :enable (markdown-code-block-at-point-p)] + ["Foldable Block" markdown-insert-foldable-block] "---" ["Blockquote Region" markdown-blockquote-region] ["Preformatted Region" markdown-pre-region] @@ -5600,6 +5742,7 @@ See `imenu-create-index-function' and `imenu--index-alist' for details." (setcdr sibling-alist alist) (setq cur-alist alist)) (setq cur-level level))))) + (setq root (copy-tree root)) ;; Footnotes (let ((fn (markdown-get-defined-footnotes))) (if (or (zerop (length fn)) @@ -5675,7 +5818,7 @@ the link, and line is the line number on which the link appears." (let* ((text (match-string-no-properties 3)) (reference (match-string-no-properties 6)) (target (downcase (if (string= reference "") text reference)))) - (,f text target result)))) + (,f text target result)))) (reverse result))) (defmacro markdown-collect-always (_ target result) @@ -6050,7 +6193,7 @@ increase the indentation by one level." (>= (forward-line -1) 0)))) (let* ((old-prefix (match-string 1)) (old-spacing (match-string 2)) - (new-prefix (if old-prefix + (new-prefix (if (and old-prefix markdown-ordered-list-enumeration) (int-to-string (1+ (string-to-number old-prefix))) "1")) (space-adjust (- (length old-prefix) (length new-prefix))) @@ -6175,7 +6318,10 @@ a list." (= (length cur-item) (length prev-item))) (save-excursion (replace-match - (concat pfx (number-to-string (setq idx (1+ idx))) ". "))) + (if (not markdown-ordered-list-enumeration) + (concat pfx "1. ") + (cl-incf idx) + (concat pfx (number-to-string idx) ". ")))) (setq sep nil)) ;; indented a level ((< (length pfx) (length cpfx)) @@ -6312,9 +6458,9 @@ means move forward N blocks." (beginning-of-line) ;; Skip over code block endings. (when (markdown-range-properties-exist - (point-at-bol) (point-at-eol) - '(markdown-gfm-block-end - markdown-tilde-fence-end)) + (point-at-bol) (point-at-eol) + '(markdown-gfm-block-end + markdown-tilde-fence-end)) (forward-line -1)) ;; Skip over blank lines inside blockquotes. (while (and (not (eobp)) @@ -6345,9 +6491,9 @@ means move forward N blocks." '(markdown-gfm-block-end markdown-tilde-fence-end)))) (setq skip (markdown-range-properties-exist - (point-at-bol) (point-at-eol) - '(markdown-gfm-block-begin - markdown-tilde-fence-begin))) + (point-at-bol) (point-at-eol) + '(markdown-gfm-block-begin + markdown-tilde-fence-begin))) (forward-line -1)) (unless (bobp) (forward-line 1)))))))) @@ -6923,7 +7069,7 @@ demote." (markdown-backward-same-level 1)))) (defun markdown-outline-up () - "Move to previous list item, when in a list, or next heading." + "Move to previous list item, when in a list, or previous heading." (interactive) (unless (markdown-up-list) (markdown-up-heading 1))) @@ -6946,8 +7092,8 @@ ones already marked." (goto-char (mark)) (markdown-forward-paragraph) (point))) - (let ((beginning-of-defun-function 'markdown-backward-paragraph) - (end-of-defun-function 'markdown-forward-paragraph)) + (let ((beginning-of-defun-function #'markdown-backward-paragraph) + (end-of-defun-function #'markdown-forward-paragraph)) (mark-defun)))) (defun markdown-mark-block () @@ -6965,16 +7111,16 @@ ones already marked." (goto-char (mark)) (markdown-forward-block) (point))) - (let ((beginning-of-defun-function 'markdown-backward-block) - (end-of-defun-function 'markdown-forward-block)) + (let ((beginning-of-defun-function #'markdown-backward-block) + (end-of-defun-function #'markdown-forward-block)) (mark-defun)))) (defun markdown-narrow-to-block () "Make text outside current block invisible. The current block is the one that contains point or follows point." (interactive) - (let ((beginning-of-defun-function 'markdown-backward-block) - (end-of-defun-function 'markdown-forward-block)) + (let ((beginning-of-defun-function #'markdown-backward-block) + (end-of-defun-function #'markdown-forward-block)) (narrow-to-defun))) (defun markdown-mark-text-block () @@ -6992,8 +7138,8 @@ ones already marked." (goto-char (mark)) (markdown-end-of-text-block) (point))) - (let ((beginning-of-defun-function 'markdown-beginning-of-text-block) - (end-of-defun-function 'markdown-end-of-text-block)) + (let ((beginning-of-defun-function #'markdown-beginning-of-text-block) + (end-of-defun-function #'markdown-end-of-text-block)) (mark-defun)))) (defun markdown-mark-page () @@ -7012,16 +7158,16 @@ ones already marked." (goto-char (mark)) (markdown-forward-page) (point))) - (let ((beginning-of-defun-function 'markdown-backward-page) - (end-of-defun-function 'markdown-forward-page)) + (let ((beginning-of-defun-function #'markdown-backward-page) + (end-of-defun-function #'markdown-forward-page)) (mark-defun)))) (defun markdown-narrow-to-page () "Make text outside current top level section invisible. The current section is the one that contains point or follows point." (interactive) - (let ((beginning-of-defun-function 'markdown-backward-page) - (end-of-defun-function 'markdown-forward-page)) + (let ((beginning-of-defun-function #'markdown-backward-page) + (end-of-defun-function #'markdown-forward-page)) (narrow-to-defun))) (defun markdown-mark-subtree () @@ -7045,9 +7191,9 @@ This puts point at the start of the current subtree, and mark at the end." (narrow-to-region (progn (markdown-back-to-heading-over-code-block t) (point)) (progn (markdown-end-of-subtree) - (if (and (markdown-heading-at-point) (not (eobp))) - (backward-char 1)) - (point)))))) + (if (and (markdown-heading-at-point) (not (eobp))) + (backward-char 1)) + (point)))))) ;;; Generic Structure Editing, Completion, and Cycling Commands =============== @@ -7506,7 +7652,7 @@ displaying the rendered output." output buffer in another window." (if markdown-live-preview-mode (markdown-display-buffer-other-window (markdown-live-preview-export))) - (markdown-live-preview-mode)) + (markdown-live-preview-mode)) (defun markdown-live-preview-re-export () "Re export source buffer." @@ -7646,15 +7792,17 @@ returns nil." (process-file markdown-open-image-command nil nil nil link-file)) (find-file link-file))))))) -(defun markdown-follow-link-at-point () - "Open the current non-wiki link. +(defun markdown-follow-link-at-point (&optional event) + "Open the non-wiki link at point or EVENT. If the link is a complete URL, open in browser with `browse-url'. Otherwise, open with `find-file' after stripping anchor and/or query string. Translate filenames using `markdown-filename-translate-function'." - (interactive) - (if (markdown-link-p) - (markdown--browse-url (markdown-link-url)) - (user-error "Point is not at a Markdown link or URL"))) + (interactive (list last-command-event)) + (save-excursion + (if event (posn-set-point (event-start event))) + (if (markdown-link-p) + (markdown--browse-url (markdown-link-url)) + (user-error "Point is not at a Markdown link or URL")))) (defun markdown-fontify-inline-links (last) "Add text properties to next inline link from point to LAST." @@ -7822,6 +7970,29 @@ The location of the alias component depends on the value of (match-string-no-properties 3) (or (match-string-no-properties 5) (match-string-no-properties 3)))) +(defun markdown--wiki-link-search-types () + (let ((ret (and markdown-wiki-link-search-type + (cl-copy-list markdown-wiki-link-search-type)))) + (when (and markdown-wiki-link-search-subdirectories + (not (memq 'sub-directories markdown-wiki-link-search-type))) + (push 'sub-directories ret)) + (when (and markdown-wiki-link-search-parent-directories + (not (memq 'parent-directories markdown-wiki-link-search-type))) + (push 'parent-directories ret)) + ret)) + +(defun markdown--project-root () + (or (cl-loop for dir in '(".git" ".hg" ".svn") + when (locate-dominating-file default-directory dir) + return it) + (progn + (require 'project) + (let ((project (project-current t))) + (with-no-warnings + (if (fboundp 'project-root) + (project-root project) + (car (project-roots project)))))))) + (defun markdown-convert-wiki-link-to-filename (name) "Generate a filename from the wiki link NAME. Spaces in NAME are replaced with `markdown-link-space-sub-char'. @@ -7831,35 +8002,43 @@ directory first, then in subdirectories if `markdown-wiki-link-search-subdirectories' is non-nil, and then in parent directories if `markdown-wiki-link-search-parent-directories' is non-nil." - (let* ((basename (replace-regexp-in-string - "[[:space:]\n]" markdown-link-space-sub-char name)) - (basename (if (derived-mode-p 'gfm-mode) - (concat (upcase (substring basename 0 1)) - (downcase (substring basename 1 nil))) - basename)) - directory extension default candidates dir) - (when buffer-file-name - (setq directory (file-name-directory buffer-file-name) - extension (file-name-extension buffer-file-name))) - (setq default (concat basename - (when extension (concat "." extension)))) - (cond - ;; Look in current directory first. - ((or (null buffer-file-name) - (file-exists-p default)) - default) - ;; Possibly search in subdirectories, next. - ((and markdown-wiki-link-search-subdirectories - (setq candidates - (directory-files-recursively - directory (concat "^" default "$")))) - (car candidates)) - ;; Possibly search in parent directories as a last resort. - ((and markdown-wiki-link-search-parent-directories - (setq dir (locate-dominating-file directory default))) - (concat dir default)) - ;; If nothing is found, return default in current directory. - (t default)))) + (save-match-data + ;; This function must not overwrite match data(PR #590) + (let* ((basename (replace-regexp-in-string + "[[:space:]\n]" markdown-link-space-sub-char name)) + (basename (if (derived-mode-p 'gfm-mode) + (concat (upcase (substring basename 0 1)) + (downcase (substring basename 1 nil))) + basename)) + (search-types (markdown--wiki-link-search-types)) + directory extension default candidates dir) + (when buffer-file-name + (setq directory (file-name-directory buffer-file-name) + extension (file-name-extension buffer-file-name))) + (setq default (concat basename + (when extension (concat "." extension)))) + (cond + ;; Look in current directory first. + ((or (null buffer-file-name) + (file-exists-p default)) + default) + ;; Possibly search in subdirectories, next. + ((and (memq 'sub-directories search-types) + (setq candidates + (directory-files-recursively + directory (concat "^" default "$")))) + (car candidates)) + ;; Possibly search in parent directories as a last resort. + ((and (memq 'parent-directories search-types) + (setq dir (locate-dominating-file directory default))) + (concat dir default)) + ((and (memq 'project search-types) + (setq candidates + (directory-files-recursively + (markdown--project-root) (concat "^" default "$")))) + (car candidates)) + ;; If nothing is found, return default in current directory. + (t default))))) (defun markdown-follow-wiki-link (name &optional other) "Follow the wiki link NAME. @@ -7971,7 +8150,7 @@ newline after." (set-buffer-modified-p nil))))) (defun markdown-check-change-for-wiki-link-after-change (from to _) - "Check region between FROM and TO for wiki links and re-fontify as needed. + "Check region between FROM and TO for wiki links and re-fontify as needed. Designed to be used with the `after-change-functions' hook." (markdown-check-change-for-wiki-link from to)) @@ -8001,9 +8180,9 @@ These are only enabled when `markdown-wiki-link-fontify-missing' is non-nil." (if (and markdown-enable-wiki-links markdown-wiki-link-fontify-missing) (add-hook 'after-change-functions - 'markdown-check-change-for-wiki-link-after-change t t) + #'markdown-check-change-for-wiki-link-after-change t t) (remove-hook 'after-change-functions - 'markdown-check-change-for-wiki-link-after-change t)) + #'markdown-check-change-for-wiki-link-after-change t)) ;; If we left the buffer there is a really good chance we were ;; creating one of the wiki link documents. Make sure we get ;; refontified when we come back. @@ -8011,11 +8190,11 @@ These are only enabled when `markdown-wiki-link-fontify-missing' is non-nil." markdown-wiki-link-fontify-missing) (progn (add-hook 'window-configuration-change-hook - 'markdown-fontify-buffer-wiki-links t t) + #'markdown-fontify-buffer-wiki-links t t) (markdown-fontify-buffer-wiki-links)) (remove-hook 'window-configuration-change-hook - 'markdown-fontify-buffer-wiki-links t) - (markdown-unfontify-region-wiki-links (point-min) (point-max)))) + #'markdown-fontify-buffer-wiki-links t) + (markdown-unfontify-region-wiki-links (point-min) (point-max)))) ;;; Following & Doing ========================================================= @@ -8057,6 +8236,9 @@ markers and footnote text." ;; Reference definition ((thing-at-point-looking-at markdown-regex-reference-definition) (markdown-reference-goto-link (match-string-no-properties 2))) + ;; Link + ((or (markdown-link-p) (markdown-wiki-link-p)) + (markdown-follow-thing-at-point nil)) ;; GFM task list item ((markdown-gfm-task-list-item-at-point) (markdown-toggle-gfm-checkbox)) @@ -8274,41 +8456,41 @@ is found, the return value is the same value returned by Returns t if added. Returns nil if non-applicable." (interactive) - (let ((bounds (markdown-cur-list-item-bounds))) - (if bounds - (unless (cl-sixth bounds) - (let ((pos (+ (cl-first bounds) (cl-fourth bounds))) - (markup "[ ] ")) - (if (< pos (point)) - (save-excursion - (goto-char pos) - (insert markup)) - (goto-char pos) - (insert markup)) - (syntax-propertize (+ (cl-second bounds) 4)) - t)) - (unless (save-excursion - (back-to-indentation) - (or (markdown-list-item-at-point-p) - (markdown-heading-at-point) - (markdown-in-comment-p) - (markdown-code-block-at-point-p))) - (let ((pos (save-excursion - (back-to-indentation) - (point))) - (markup (concat (or (save-excursion - (beginning-of-line 0) - (cl-fifth (markdown-cur-list-item-bounds))) - markdown-unordered-list-item-prefix) - "[ ] "))) + (let ((bounds (markdown-cur-list-item-bounds))) + (if bounds + (unless (cl-sixth bounds) + (let ((pos (+ (cl-first bounds) (cl-fourth bounds))) + (markup "[ ] ")) (if (< pos (point)) (save-excursion (goto-char pos) (insert markup)) (goto-char pos) (insert markup)) - (syntax-propertize (point-at-eol)) - t))))) + (syntax-propertize (+ (cl-second bounds) 4)) + t)) + (unless (save-excursion + (back-to-indentation) + (or (markdown-list-item-at-point-p) + (markdown-heading-at-point) + (markdown-in-comment-p) + (markdown-code-block-at-point-p))) + (let ((pos (save-excursion + (back-to-indentation) + (point))) + (markup (concat (or (save-excursion + (beginning-of-line 0) + (cl-fifth (markdown-cur-list-item-bounds))) + markdown-unordered-list-item-prefix) + "[ ] "))) + (if (< pos (point)) + (save-excursion + (goto-char pos) + (insert markup)) + (goto-char pos) + (insert markup)) + (syntax-propertize (point-at-eol)) + t))))) (defun markdown-toggle-gfm-checkbox () "Toggle GFM checkbox at point. @@ -8420,13 +8602,12 @@ or \\[markdown-toggle-inline-images]." (goto-char (point-min)) (while (re-search-forward markdown-regex-link-inline nil t) (let* ((start (match-beginning 0)) - (imagep (match-beginning 1)) - (end (match-end 0)) - (file (match-string-no-properties 6)) - (unhex_file (url-unhex-string file))) + (imagep (match-beginning 1)) + (end (match-end 0)) + (file (match-string-no-properties 6))) (when (and imagep (not (zerop (length file)))) - (unless (file-exists-p unhex_file) + (unless (file-exists-p file) (let* ((download-file (funcall markdown-translate-filename-function file)) (valid-url (ignore-errors (member (downcase (url-type (url-generic-parse-url download-file))) @@ -8435,14 +8616,16 @@ or \\[markdown-toggle-inline-images]." (setq file (markdown--get-remote-image download-file)) (when (not valid-url) ;; strip query parameter - (setq file (replace-regexp-in-string "?.+\\'" "" file)))))) - (when (file-exists-p unhex_file) - (let* ((abspath (if (file-name-absolute-p unhex_file) - unhex_file - (concat default-directory unhex_file))) + (setq file (replace-regexp-in-string "?.+\\'" "" file)) + (unless (file-exists-p file) + (setq file (url-unhex-string file))))))) + (when (file-exists-p file) + (let* ((abspath (if (file-name-absolute-p file) + file + (concat default-directory file))) (image (cond ((and markdown-max-image-size - (image-type-available-p 'imagemagick)) + (image-type-available-p 'imagemagick)) (create-image abspath 'imagemagick nil :max-width (car markdown-max-image-size) @@ -8476,7 +8659,7 @@ mode to use. The language to mode mapping may be customized by setting the variable `markdown-code-lang-modes'." :group 'markdown :type 'boolean - :safe 'booleanp + :safe #'booleanp :package-version '(markdown-mode . "2.3")) (defcustom markdown-fontify-code-block-default-mode nil @@ -8620,7 +8803,8 @@ at the END of code blocks." (goto-char (- beg 1)) (let ((block-indentation (current-indentation))) (when (> block-indentation 0) - (indent-rigidly beg end block-indentation)))) + (indent-rigidly beg end block-indentation))) + (font-lock-ensure)) (defun markdown-edit-code-block () "Edit Markdown code block in an indirect buffer." @@ -8628,8 +8812,8 @@ at the END of code blocks." (save-excursion (if (fboundp 'edit-indirect-region) (let* ((bounds (markdown-get-enclosing-fenced-block-construct)) - (begin (and bounds (goto-char (nth 0 bounds)) (point-at-bol 2))) - (end (and bounds (goto-char (nth 1 bounds)) (point-at-bol 1)))) + (begin (and bounds (not (null (nth 0 bounds))) (goto-char (nth 0 bounds)) (point-at-bol 2))) + (end (and bounds(not (null (nth 1 bounds))) (goto-char (nth 1 bounds)) (point-at-bol 1)))) (if (and begin end) (let* ((indentation (and (goto-char (nth 0 bounds)) (current-indentation))) (lang (markdown-code-block-lang)) @@ -8639,6 +8823,15 @@ at the END of code blocks." (lambda (_parent-buffer _beg _end) (funcall mode))) (indirect-buf (edit-indirect-region begin end 'display-buffer))) + ;; reset `sh-shell' when indirect buffer + (when (and (not (member system-type '(ms-dos windows-nt))) + (member mode '(shell-script-mode sh-mode)) + (member lang (append + (mapcar (lambda (e) (symbol-name (car e))) + sh-ancestor-alist) + '("csh" "rc" "sh")))) + (with-current-buffer indirect-buf + (sh-set-shell lang))) (when (> indentation 0) ;; un-indent in edit-indirect buffer (with-current-buffer indirect-buf (indent-rigidly (point-min) (point-max) (- indentation))))) @@ -8720,7 +8913,7 @@ This version removes characters with invisibility property ;; Functions for maintaining tables -(defvar markdown-table-at-point-p-function nil +(defvar markdown-table-at-point-p-function #'markdown--table-at-point-p "Function to decide if point is inside a table. The indirection serves to differentiate between standard markdown @@ -8737,9 +8930,7 @@ tables and gfm tables which are less strict about the markup.") (defun markdown-table-at-point-p () "Return non-nil when point is inside a table." - (if (functionp markdown-table-at-point-p-function) - (funcall markdown-table-at-point-p-function) - (markdown--table-at-point-p))) + (funcall markdown-table-at-point-p-function)) (defun markdown--table-at-point-p () "Return non-nil when point is inside a table." @@ -8844,7 +9035,8 @@ This function assumes point is on a table." (save-excursion (beginning-of-line) (while (search-forward "|" pos t) - (unless (markdown--thing-at-wiki-link (match-beginning 0)) + (when (and (not (looking-back "\\\\|" (line-beginning-position))) + (not (markdown--thing-at-wiki-link (match-beginning 0)))) (setq cnt (1+ cnt))))) cnt)) @@ -8883,7 +9075,8 @@ table." (beginning-of-line 1) (when (> n 0) (while (and (> n 0) (search-forward "|" (point-at-eol) t)) - (unless (markdown--thing-at-wiki-link (match-beginning 0)) + (when (and (not (looking-back "\\\\|" (line-beginning-position))) + (not (markdown--thing-at-wiki-link (match-beginning 0)))) (cl-decf n))) (if on-delim (backward-char 1) @@ -8970,7 +9163,7 @@ This function assumes point is on a table." (indent (progn (looking-at "[ \t]*") (match-string 0))) ;; Split table in lines and save column format specifier (lines (mapcar (lambda (l) - (if (string-match-p "\\`[ \t]*|[-:]" l) + (if (string-match-p "\\`[ \t]*|[ \t]*[-:]" l) (progn (setq fmtspec (or fmtspec l)) nil) l)) (markdown--split-string (buffer-substring begin end) "\n"))) ;; Split lines in cells @@ -9086,7 +9279,8 @@ With optional argument UP, move it up." (insert "| ")) (forward-line))) (set-marker end nil) - (markdown-table-align))) + (when markdown-table-align-p + (markdown-table-align)))) (defun markdown-table-delete-column () "Delete column at point from table." @@ -9100,12 +9294,13 @@ With optional argument UP, move it up." (goto-char begin) (while (< (point) end) (markdown-table-goto-column col t) - (and (looking-at "|[^|\n]+|") + (and (looking-at "|\\(?:\\\\|\\|[^|\n]\\)+|") (replace-match "|")) (forward-line))) (set-marker end nil) (markdown-table-goto-column (max 1 (1- col))) - (markdown-table-align))) + (when markdown-table-align-p + (markdown-table-align)))) (defun markdown-table-move-column (&optional left) "Move table column at point to the right. @@ -9126,12 +9321,13 @@ With optional argument LEFT, move it to the left." (goto-char begin) (while (< (point) end) (markdown-table-goto-column col1 t) - (when (looking-at "|\\([^|\n]+\\)|\\([^|\n]+\\)|") + (when (looking-at "|\\(\\(?:\\\\|\\|[^|\n]\\|\\)+\\)|\\(\\(?:\\\\|\\|[^|\n]\\|\\)+\\)|") (replace-match "|\\2|\\1|")) (forward-line))) (set-marker end nil) (markdown-table-goto-column colpos) - (markdown-table-align))) + (when markdown-table-align-p + (markdown-table-align)))) (defun markdown-table-move-column-left () "Move table column at point to the left." @@ -9152,7 +9348,8 @@ Create new table lines if required." (if (or (looking-at "[ \t]*$") (save-excursion (skip-chars-backward " \t") (bolp))) (newline) - (markdown-table-align) + (when markdown-table-align-p + (markdown-table-align)) (let ((col (markdown-table-get-column))) (beginning-of-line 2) (if (or (not (markdown-table-at-point-p)) @@ -9170,7 +9367,8 @@ Create new table lines if required." (interactive) (unless (markdown-table-at-point-p) (user-error "Not at a table")) - (markdown-table-align) + (when markdown-table-align-p + (markdown-table-align)) (let ((end (markdown-table-end))) (when (markdown-table-hline-at-point-p) (end-of-line 1)) (condition-case nil @@ -9193,16 +9391,25 @@ Create new table lines if required." (interactive) (unless (markdown-table-at-point-p) (user-error "Not at a table")) - (markdown-table-align) - (when (markdown-table-hline-at-point-p) (end-of-line 1)) + (when markdown-table-align-p + (markdown-table-align)) + (when (markdown-table-hline-at-point-p) (beginning-of-line 1)) (condition-case nil (progn (re-search-backward "\\(?:^\\|[^\\]\\)|" (markdown-table-begin)) + ;; When this function is called while in the first cell in a + ;; table, the point will now be at the beginning of a line. In + ;; this case, we need to move past one additional table + ;; boundary, the end of the table on the previous line. + (when (= (point) (line-beginning-position)) + (re-search-backward "\\(?:^\\|[^\\]\\)|" (markdown-table-begin))) (re-search-backward "\\(?:^\\|[^\\]\\)|" (markdown-table-begin))) (error (user-error "Cannot move to previous table cell"))) - (while (looking-at "|\\([-:]\\|[ \t]*$\\)") - (re-search-backward "\\(?:^\\|[^\\]\\)|" (markdown-table-begin))) - (when (looking-at "| ?") (goto-char (match-end 0)))) + (when (looking-at "\\(?:^\\|[^\\]\\)| ?") (goto-char (match-end 0))) + + ;; This may have dropped point on the hline. + (when (markdown-table-hline-at-point-p) + (markdown-table-backward-cell))) (defun markdown-table-transpose () "Transpose table at point. @@ -9241,7 +9448,8 @@ Horizontal separator lines will be eliminated." contents ""))) (markdown-table-goto-dline col_old) (markdown-table-goto-column dline_old)) - (markdown-table-align)) + (when markdown-table-align-p + (markdown-table-align))) (defun markdown-table-sort-lines (&optional sorting-type) "Sort table lines according to the column at point. @@ -9273,8 +9481,12 @@ indicate that sorting should be done in reverse order." (t 1)))) (sorting-type (or sorting-type - (read-char-exclusive - "Sort type: [a]lpha [n]umeric (A/N means reversed): ")))) + (progn + ;; workaround #641 + ;; Emacs < 28 hides prompt message by another message. This erases it. + (message "") + (read-char-exclusive + "Sort type: [a]lpha [n]umeric (A/N means reversed): "))))) (save-restriction ;; Narrow buffer to appropriate sorting area (if (region-active-p) @@ -9375,12 +9587,21 @@ spaces, or alternatively a TAB should be used as the separator." ((integerp separator) (if (< separator 1) (user-error "Cell separator must contain one or more spaces") - (format "^ *\\| *\t *\\| \\{%d,\\}" separator))) + (format "^ *\\| *\t *\\| \\{%d,\\}\\|$" separator))) ((stringp separator) (format "^ *\\|%s" separator)) (t (error "Invalid cell separator")))) - (while (re-search-forward re end t) (replace-match "| " t t))) + (let (finish) + (while (and (not finish) (re-search-forward re end t)) + (if (eolp) + (progn + (replace-match "|" t t) + (forward-line 1) + (when (eobp) + (setq finish t))) + (replace-match "| " t t))))) (goto-char begin) - (markdown-table-align))) + (when markdown-table-align-p + (markdown-table-align)))) (defun markdown-insert-table (&optional rows columns align) "Insert an empty pipe table. @@ -9469,6 +9690,9 @@ rows and columns and the column alignment." ;;;###autoload (define-derived-mode markdown-mode text-mode "Markdown" "Major mode for editing Markdown files." + (when buffer-read-only + (when (or (not (buffer-file-name)) (file-writable-p (buffer-file-name))) + (setq-local buffer-read-only nil))) ;; Natural Markdown tab width (setq tab-width 4) ;; Comments @@ -9482,7 +9706,7 @@ rows and columns and the column alignment." (setq-local sentence-end-base "[.?!…‽][]\"'”’)}»›*_`~]*") ;; Syntax (add-hook 'syntax-propertize-extend-region-functions - #'markdown-syntax-propertize-extend-region) + #'markdown-syntax-propertize-extend-region nil t) (add-hook 'jit-lock-after-change-extend-region-functions #'markdown-font-lock-extend-region-function t t) (setq-local syntax-propertize-function #'markdown-syntax-propertize) @@ -9541,6 +9765,7 @@ rows and columns and the column alignment." ;; not paragraph-ending suffixes: ".* $" ; line ending in two spaces "^#+" + "^\\(?: \\)?[-=]+[ \t]*$" ;; setext "[ \t]*\\[\\^\\S-*\\]:[ \t]*$") ; just the start of a footnote def "\\|")) (setq-local adaptive-fill-first-line-regexp "\\`[ \t]*[A-Z]?>[ \t]*?\\'") @@ -9621,7 +9846,7 @@ rows and columns and the column alignment." "Major mode for editing GitHub Flavored Markdown files." (setq markdown-link-space-sub-char "-") (setq markdown-wiki-link-search-subdirectories t) - (setq-local markdown-table-at-point-p-function 'gfm--table-at-point-p) + (setq-local markdown-table-at-point-p-function #'gfm--table-at-point-p) (add-hook 'post-self-insert-hook #'gfm--electric-pair-fence-code-block 'append t) (markdown-gfm-parse-buffer-for-languages)) @@ -9632,7 +9857,7 @@ rows and columns and the column alignment." "Enable hidden markup mode in `markdown-view-mode' and `gfm-view-mode'." :group 'markdown :type 'boolean - :safe 'booleanp) + :safe #'booleanp) (defvar markdown-view-mode-map (let ((map (make-sparse-keymap))) diff --git a/lisp/multiple-cursors/mc-cycle-cursors.el b/lisp/multiple-cursors/mc-cycle-cursors.el index 85af3529..08178eb5 100644 --- a/lisp/multiple-cursors/mc-cycle-cursors.el +++ b/lisp/multiple-cursors/mc-cycle-cursors.el @@ -88,7 +88,11 @@ (cl-defun mc/cycle (next-cursor fallback-cursor loop-message) (when (null next-cursor) (when (eql 'stop (mc/handle-loop-condition loop-message)) - (return-from mc/cycle nil)) + (cond + ((fboundp 'cl-return-from) + (cl-return-from mc/cycle nil)) + ((fboundp 'return-from) + (return-from mc/cycle nil)))) (setf next-cursor fallback-cursor)) (mc/create-fake-cursor-at-point) (mc/pop-state-from-overlay next-cursor) diff --git a/lisp/multiple-cursors/mc-mark-more.el b/lisp/multiple-cursors/mc-mark-more.el index 6c0276ce..f0c23b07 100644 --- a/lisp/multiple-cursors/mc-mark-more.el +++ b/lisp/multiple-cursors/mc-mark-more.el @@ -355,7 +355,7 @@ With zero ARG, skip the last one and mark next." (when point-first (exchange-point-and-mark))))) (if (> (mc/num-cursors) 1) (multiple-cursors-mode 1) - (multiple-cursors-mode 0))) + (mc/disable-multiple-cursors-mode))) (defun mc--select-thing-at-point (thing) (let ((bound (bounds-of-thing-at-point thing))) @@ -402,7 +402,7 @@ With zero ARG, skip the last one and mark next." (mc/pop-state-from-overlay first))) (if (> (mc/num-cursors) 1) (multiple-cursors-mode 1) - (multiple-cursors-mode 0)))))) + (mc/disable-multiple-cursors-mode)))))) ;;;###autoload (defun mc/mark-all-in-region-regexp (beg end) @@ -427,7 +427,7 @@ With zero ARG, skip the last one and mark next." (error "Search failed for %S" search))) (goto-char (match-end 0)) (if (< (mc/num-cursors) 3) - (multiple-cursors-mode 0) + (mc/disable-multiple-cursors-mode) (mc/pop-state-from-overlay (mc/furthest-cursor-before-point)) (multiple-cursors-mode 1)))))) diff --git a/lisp/multiple-cursors/mc-separate-operations.el b/lisp/multiple-cursors/mc-separate-operations.el index f123ccaa..ddc7395b 100644 --- a/lisp/multiple-cursors/mc-separate-operations.el +++ b/lisp/multiple-cursors/mc-separate-operations.el @@ -106,7 +106,8 @@ (progn (mc/mark-next-lines 1) (mc/reverse-regions) - (multiple-cursors-mode 0)) + (mc/disable-multiple-cursors-mode) + ) (unless (use-region-p) (mc/execute-command-for-all-cursors 'mark-sexp)) (setq mc--strings-to-replace (nreverse (mc--ordered-region-strings))) diff --git a/lisp/multiple-cursors/multiple-cursors-core.el b/lisp/multiple-cursors/multiple-cursors-core.el index 6db87a85..ab4ee52b 100644 --- a/lisp/multiple-cursors/multiple-cursors-core.el +++ b/lisp/multiple-cursors/multiple-cursors-core.el @@ -433,7 +433,7 @@ the original cursor, to inform about the lack of support." (unless mc--executing-command-for-fake-cursor (if (eq 1 (mc/num-cursors)) ;; no fake cursors? disable mc-mode - (multiple-cursors-mode 0) + (mc/disable-multiple-cursors-mode) (when this-original-command (let ((original-command (or mc--this-command (command-remapping this-original-command) @@ -487,7 +487,7 @@ you should disable multiple-cursors-mode." "Deactivate mark if there are any active, otherwise exit multiple-cursors-mode." (interactive) (if (not (use-region-p)) - (multiple-cursors-mode 0) + (mc/disable-multiple-cursors-mode) (deactivate-mark))) (defun mc/repeat-command () @@ -588,13 +588,18 @@ They are temporarily disabled when multiple-cursors are active.") (mc/enable-temporarily-disabled-minor-modes) (run-hooks 'multiple-cursors-mode-disabled-hook))) -(add-hook 'after-revert-hook #'(lambda () (multiple-cursors-mode 0))) +(defun mc/disable-multiple-cursors-mode () + "Disable multiple-cursors-mode and run the corresponding hook." + (multiple-cursors-mode 0) + (run-hooks 'multiple-cursors-mode-disabled-hook)) + +(add-hook 'after-revert-hook 'mc/disable-multiple-cursors-mode) (defun mc/maybe-multiple-cursors-mode () "Enable multiple-cursors-mode if there is more than one currently active cursor." (if (> (mc/num-cursors) 1) (multiple-cursors-mode 1) - (multiple-cursors-mode 0))) + (mc/disable-multiple-cursors-mode))) (defmacro unsupported-cmd (cmd msg) "Adds command to list of unsupported commands and prevents it diff --git a/lisp/multiple-cursors/multiple-cursors-pkg.el b/lisp/multiple-cursors/multiple-cursors-pkg.el index c61a2730..81c7bd7c 100644 --- a/lisp/multiple-cursors/multiple-cursors-pkg.el +++ b/lisp/multiple-cursors/multiple-cursors-pkg.el @@ -1,11 +1,12 @@ -(define-package "multiple-cursors" "20201215.1559" "Multiple cursors for Emacs." +(define-package "multiple-cursors" "20211112.2223" "Multiple cursors for Emacs." '((cl-lib "0.5")) - :commit "a9d7764f80b241978f3d4e76bc981ef10bab5d70" :authors + :commit "8a60fc7ef0ae6e5ca089a7c95264cd0ae83e7274" :authors '(("Magnar Sveen" . "magnars@gmail.com")) :maintainer '("Magnar Sveen" . "magnars@gmail.com") :keywords - '("editing" "cursors")) + '("editing" "cursors") + :url "https://github.com/magnars/multiple-cursors.el") ;; Local Variables: ;; no-byte-compile: t ;; End: diff --git a/lisp/multiple-cursors/multiple-cursors.el b/lisp/multiple-cursors/multiple-cursors.el index 47f63385..22430a5d 100644 --- a/lisp/multiple-cursors/multiple-cursors.el +++ b/lisp/multiple-cursors/multiple-cursors.el @@ -5,6 +5,7 @@ ;; Author: Magnar Sveen ;; Version: 1.4.0 ;; Keywords: editing cursors +;; Homepage: https://github.com/magnars/multiple-cursors.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 diff --git a/lisp/ob-async.el b/lisp/ob-async.el index 926f62fc..e723cd8b 100644 --- a/lisp/ob-async.el +++ b/lisp/ob-async.el @@ -5,7 +5,8 @@ ;; Author: Andrew Stahlman ;; Created: 10 Feb 2017 ;; Version: 0.1 -;; Package-Version: 20190916.1537 +;; Package-Version: 20210428.2052 +;; Package-Commit: 9aac486073f5c356ada20e716571be33a350a982 ;; Keywords: tools ;; Homepage: https://github.com/astahlman/ob-async @@ -49,6 +50,11 @@ functionality may be implemented separately.") block. You can use this hook to perform language-specific initialization which would normally execute in your init file.") +(defvar ob-async-inject-variables "\\borg-babel.+" + "Regex of variables that should be injected into the async process. +It's a good idea to include any variables that are prefixed with `org-babel'. +Add additional variables like \"\\(\\borg-babel.+\\|sql-connection-alist\\)\".") + ;;;###autoload (defalias 'org-babel-execute-src-block:async 'ob-async-org-babel-execute-src-block) @@ -141,6 +147,8 @@ block." (or (and dir (file-name-as-directory (expand-file-name dir))) default-directory)) (cmd (intern (concat "org-babel-execute:" lang))) + (org-babel-async-content + (buffer-substring-no-properties (point-min) (point-max))) result) (unless (fboundp cmd) (error "No org-babel-execute function for %s!" lang)) @@ -155,12 +163,15 @@ block." ;; Initialize the new Emacs process with org-babel functions (setq exec-path ',exec-path) (setq load-path ',load-path) + ,(async-inject-variables ob-async-inject-variables) (package-initialize) (setq ob-async-pre-execute-src-block-hook ',ob-async-pre-execute-src-block-hook) (run-hooks 'ob-async-pre-execute-src-block-hook) (org-babel-do-load-languages 'org-babel-load-languages ',org-babel-load-languages) (let ((default-directory ,default-directory)) - (,cmd ,body ',params))) + (with-temp-buffer + (insert org-babel-async-content) + (,cmd ,body ',params)))) `(lambda (result) (with-current-buffer ,(current-buffer) (let ((default-directory ,default-directory)) diff --git a/lisp/org-brain.el b/lisp/org-brain.el index b8de0b27..ffff7c31 100644 --- a/lisp/org-brain.el +++ b/lisp/org-brain.el @@ -5,8 +5,8 @@ ;; Author: Erik Sjöstrand ;; URL: http://github.com/Kungsgeten/org-brain -;; Package-Version: 20201214.822 -;; Package-Commit: 2f36f303e96e384e17d156e0d6489211808d4a36 +;; Package-Version: 20210706.1519 +;; Package-Commit: 46ca9f766322cff31279ecdf02251ff24a0e9431 ;; Keywords: outlines hypermedia ;; Package-Requires: ((emacs "25.1") (org "9.2")) ;; Version: 0.94 @@ -2266,14 +2266,18 @@ If interactive, also prompt for ENTRY." ;;;###autoload (defun org-brain-ensure-ids-in-buffer () - "Run `org-brain-get-id' on all headlines in current buffer. + "Run `org-brain-get-id' on all headlines in current buffer +taking into account the ignore tags such as :childess: Only works if in an `org-mode' buffer inside `org-brain-path'. Suitable for use with `before-save-hook'." (interactive) (and (eq major-mode 'org-mode) (string-prefix-p (file-truename org-brain-path) (file-truename (buffer-file-name))) - (org-map-entries #'org-brain-get-id t 'file))) + (let ((match (format "-%s-%s|-%s+TAGS={%s}" ; "-nobrain-childless|-nobrain+TAGS={childless}" + org-brain-exclude-tree-tag org-brain-exclude-children-tag + org-brain-exclude-tree-tag org-brain-exclude-children-tag))) + (org-map-entries #'org-brain-get-id match 'file)))) ;;;###autoload (defun org-brain-agenda () @@ -2382,6 +2386,7 @@ Unless WANDER is t, `org-brain-stop-wandering' will be run." (setq-local indent-tabs-mode nil) (read-only-mode 1) (setq-local default-directory (file-name-directory (org-brain-entry-path entry))) + (setq list-buffers-directory (org-brain-vis-title entry)) (org-brain-maybe-switch-brain) (unless (eq org-brain--vis-entry entry) (setq org-brain--vis-entry entry) @@ -2434,6 +2439,19 @@ Unless WANDER is t, `org-brain-stop-wandering' will be run." (pop-to-buffer "*org-brain*") (pop-to-buffer-same-window "*org-brain*"))))) +;;;###autoload +(defun org-brain-visualize-dwim () + "Switch to the *org-brain* buffer. +If there's no such buffer, or if already there, run `org-brain-visualize'." + (interactive) + (if (and (not (org-brain-maybe-switch-brain)) + (not (eq major-mode 'org-brain-visualize-mode)) + (get-buffer "*org-brain*")) + (if org-brain-open-same-window + (pop-to-buffer "*org-brain*") + (pop-to-buffer-same-window "*org-brain*")) + (call-interactively #'org-brain-visualize))) + ;;;###autoload (defun org-brain-visualize-entry-at-pt () "Use `org-brain-visualize' on the `org-brain-entry-at-pt'. @@ -2779,11 +2797,26 @@ point before the buffer was reverted." (revert-buffer) (when button-entry (org-brain-jump-to-visualize-button button-entry))))) +(defun org-brain--bookmark-handler (bookmark) + "Visualize the entry stored in BOOKMARK." + (org-brain-visualize (cdr (assoc 'brain-entry bookmark)) nil) + (switch-to-buffer "*org-brain*")) + +(defun org-brain-make-bookmark-record () + "Make a bookmark out of `org-brain--vis-entry'. +Used as `bookmark-make-record-function' in `org-brain-visualize-mode'." + (if-let ((entry org-brain--vis-entry)) + (cons (org-brain-title org-brain--vis-entry) + `((handler . org-brain--bookmark-handler) + (brain-entry . ,org-brain--vis-entry))) + (user-error "For some reason `org-brain--vis-entry' is nil"))) + (define-derived-mode org-brain-visualize-mode special-mode "Org-brain Visualize" "Major mode for `org-brain-visualize'. \\{org-brain-visualize-mode-map}" - (setq-local revert-buffer-function #'org-brain-visualize-revert)) + (setq-local revert-buffer-function #'org-brain-visualize-revert) + (setq-local bookmark-make-record-function #'org-brain-make-bookmark-record)) ;;;;; Keybindings @@ -2859,11 +2892,60 @@ point before the buffer was reverted." ;;;;; Drawing helpers +(defun org-brain--visually-sort (lst) + "Sort LST destructively according to org-brain-visualize-sort-function." + (sort lst org-brain-visualize-sort-function)) + +(defun org-brain--visually-sorted (lst) + "Sorted LST according to org-brain-visualize-sort-function." + (org-brain--visually-sort (copy-sequence lst))) + +(defun org-brain--maybe-visually-sort (entry lst) + "Sorted LST unless ENTRY has a :nosort: tag." + (if (member org-brain-no-sort-children-tag (org-brain-get-tags entry)) + lst + (org-brain--visually-sort lst))) + +(defun org-brain--visually-sorted-parents (entry) + "List of parents, sorted unless ENTRY has a :nosort: tag." + (org-brain--maybe-visually-sort entry (org-brain-parents entry))) + +(defun org-brain--visually-sorted-children (entry) + "List of children, sorted unless ENTRY has a :nosort: tag." + (org-brain--maybe-visually-sort entry (org-brain-children entry))) + +(defun org-brain--visually-sorted-friends (entry) + "List of friends, sorted unless ENTRY has a :nosort: tag." + (org-brain--maybe-visually-sort entry (org-brain-friends entry))) + +(defun org-brain--visually-sorted-siblings (entry) + "List of siblings, sorted unless ENTRY has a :nosort: tag." + (let ((siblings (org-brain-siblings entry))) + (if (member org-brain-no-sort-children-tag (org-brain-get-tags entry)) + siblings + (sort siblings (lambda (x y) + (funcall org-brain-visualize-sort-function + (car x) (car y))))))) + +(defun org-brain--visually-sorted-siblings-from (pair) + "List of siblings for a parent, sorted unless the parent in PAIR has a :nosort: tag, or empty list if the parent has a :nosiblings: tag." + (let ((parent (car pair))) + (unless (member org-brain-exclude-siblings-tag (org-brain-get-tags parent)) + (org-brain--maybe-visually-sort parent (cdr pair))))) + +(defun org-brain--visually-sorted-pins () + "List of pins visually sorted." + (org-brain--visually-sorted org-brain-pins)) + +(defun org-brain--visually-sorted-selected () + "Visually sorted selection list." + (org-brain--visually-sorted org-brain-selected)) + (defun org-brain--vis-pinned () "Insert pinned entries. Helper function for `org-brain-visualize'." (insert "PINNED:") - (dolist (pin (sort (copy-sequence org-brain-pins) org-brain-visualize-sort-function)) + (dolist (pin (org-brain--visually-sorted-pins)) (insert " ") (org-brain-insert-visualize-button pin 'org-brain-pinned 'pinned)) (insert "\n")) @@ -2873,7 +2955,7 @@ Helper function for `org-brain-visualize'." Helper function for `org-brain-visualize'." (unless (null org-brain-selected) (insert "SELECTED:") - (dolist (selection (sort (copy-sequence org-brain-selected) org-brain-visualize-sort-function)) + (dolist (selection (org-brain--visually-sorted-selected)) (insert " ") (org-brain-insert-visualize-button selection 'org-brain-selected-list)) (insert "\n"))) @@ -2910,15 +2992,11 @@ Helper function for `org-brain-visualize'." (defun org-brain--vis-parents-siblings (entry) "Insert parents and siblings of ENTRY. Helper function for `org-brain-visualize'." - (when-let ((siblings (org-brain-siblings entry))) + (when-let ((siblings (org-brain--visually-sorted-siblings entry))) (let ((parent-positions nil) (max-width 0)) - (dolist (parent (sort siblings (lambda (x y) - (funcall org-brain-visualize-sort-function - (car x) (car y))))) - (let* ((parent-tags (org-brain-get-tags (car parent))) - (children-links (unless (member org-brain-exclude-siblings-tag parent-tags) - (cdr parent))) + (dolist (parent siblings) + (let* ((children-links (org-brain--visually-sorted-siblings-from parent)) (sibling-middle (ceiling (/ (length children-links) 2.0))) (base-line (if org-brain-show-history 5 4)) (col-start (+ 3 max-width)) @@ -2936,9 +3014,7 @@ Helper function for `org-brain-visualize'." 'org-brain-sibling) 'sibling) (setq max-width (max max-width (current-column))) (newline (forward-line 1))) - (if (member org-brain-no-sort-children-tag parent-tags) - children-links - (sort children-links org-brain-visualize-sort-function))) + children-links) (org-goto-line base-line) (forward-line (1- sibling-middle)) (picture-forward-column col-start) @@ -2996,15 +3072,13 @@ Helper function for `org-brain-visualize'." "Insert children of ENTRY. Helper function for `org-brain-visualize'." (let ((tags (org-brain-get-tags entry t))) - (when-let ((children (org-brain-children entry)) + (when-let ((children (org-brain--visually-sorted-children entry)) (fill-col (if (member org-brain-each-child-on-own-line-tag (org-brain-get-tags entry)) 0 (eval org-brain-child-linebreak-sexp)))) (insert "\n\n") - (dolist (child (if (member org-brain-no-sort-children-tag tags) - children - (sort children org-brain-visualize-sort-function))) + (dolist (child children) (let ((child-title (org-brain-title child)) (face (if (member entry (org-brain-local-parent child)) 'org-brain-local-child @@ -3017,9 +3091,9 @@ Helper function for `org-brain-visualize'." (defun org-brain--vis-friends (entry) "Insert friends of ENTRY. Helper function for `org-brain-visualize'." - (when-let ((friends (org-brain-friends entry))) + (when-let ((friends (org-brain--visually-sorted-friends entry))) (org-brain--insert-wire " <-> ") - (dolist (friend (sort friends org-brain-visualize-sort-function)) + (dolist (friend friends) (let ((column (current-column))) (org-brain-insert-visualize-button friend 'org-brain-friend 'friend) (picture-move-down 1) @@ -3075,7 +3149,8 @@ Each button is indented, starting at level determined by INDENT." (insert (org-brain-map-create-indentation indent)) (org-brain-insert-visualize-button entry 'org-brain-child (if (> max-level 0) 'grandchild 'child)) (insert "\n") - (dolist (child (and (> max-level 0) (sort (org-brain-children entry) org-brain-visualize-sort-function))) + (dolist (child (and (> max-level 0) + (org-brain--visually-sorted-children entry))) (org-brain-insert-recursive-child-buttons child (1- max-level) (1+ indent)))) (defun org-brain-tree-depth (tree) @@ -3109,7 +3184,7 @@ raw entry data." Also insert buttons for grand-parents, up to MAX-LEVEL. Each button is indented, starting at level determined by INDENT." (dolist (parent (and (> max-level 0) - (sort (org-brain-parents entry) org-brain-visualize-sort-function))) + (org-brain--visually-sorted-parents entry))) (org-brain-insert-recursive-parent-buttons parent (1- max-level) (1- indent))) (insert (org-brain-map-create-indentation indent)) (org-brain-insert-visualize-button entry 'org-brain-parent (if (> max-level 0) 'grandparent 'parent)) @@ -3122,30 +3197,25 @@ Will also insert grand-parents up to PARENT-MAX-LEVEL, and children up to CHILDREN-MAX-LEVEL. Return the position of ENTRY in the buffer." (insert "FRIENDS:") - (dolist (friend (sort (org-brain-friends entry) org-brain-visualize-sort-function)) + (dolist (friend (org-brain--visually-sorted-friends entry)) (insert " ") (org-brain-insert-visualize-button friend 'org-brain-friend 'friend)) (setq-local org-brain--visualize-header-end-pos (point)) (insert "\n\n") (let ((indent (1- (org-brain-tree-depth (org-brain-recursive-parents entry parent-max-level)))) (entry-pos)) - (dolist (parent (sort (org-brain-siblings entry) (lambda (x y) - (funcall org-brain-visualize-sort-function - (car x) (car y))))) + (dolist (parent (org-brain--visually-sorted-siblings entry)) (org-brain-insert-recursive-parent-buttons (car parent) (1- parent-max-level) (1- indent)) - (let* ((parent-tags (org-brain-get-tags (car parent))) - (children-links (unless (member org-brain-exclude-siblings-tag parent-tags) - (cdr parent)))) - (dolist (sibling (sort children-links org-brain-visualize-sort-function)) - (insert (org-brain-map-create-indentation indent)) - (org-brain-insert-visualize-button sibling 'org-brain-sibling 'sibling) - (insert "\n")))) + (dolist (sibling (org-brain--visually-sorted-siblings-from parent)) + (insert (org-brain-map-create-indentation indent)) + (org-brain-insert-visualize-button sibling 'org-brain-sibling 'sibling) + (insert "\n"))) (insert (org-brain-map-create-indentation indent)) (setq entry-pos (point)) (insert (propertize (org-brain-title entry) 'face 'org-brain-title 'aa2u-text t) "\n") - (dolist (child (sort (org-brain-children entry) org-brain-visualize-sort-function)) + (dolist (child (org-brain--visually-sorted-children entry)) (org-brain-insert-recursive-child-buttons child (1- children-max-level) (1+ indent))) entry-pos)) diff --git a/lisp/org-contrib/COPYING b/lisp/org-contrib/COPYING new file mode 100644 index 00000000..e6000869 --- /dev/null +++ b/lisp/org-contrib/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/lisp/org-contrib/README.org b/lisp/org-contrib/README.org new file mode 100644 index 00000000..9c06ccf3 --- /dev/null +++ b/lisp/org-contrib/README.org @@ -0,0 +1,143 @@ +This repository contains add-ons to Org. + +You can use them by installing the =org-contrib= NonGNU ELPA package +from https://elpa.nongnu.org/nongnu/. + +** Please help maintaining these add-ons + +Files in this repository used to live in the Org repository but have +been filtered out of the Org 9.5 release. The =contrib/= directory used +to contain a =scripts/= directory that now lives on [[https://code.orgmode.org/bzg/worg/src/master/code][the Worg repository]]. + +*Files in this repository receive little if no maintainance and there +is no guaranty that they are compatible with the Org stable version.* + +For files a =Maintainer= header and a =Homepage= pointing outside of this +repository are in transition: they are maintained and will be removed +from the next release of this repository. As a user, please carefully +track the new URL where the add-on is now maintained. + +If you want to maintain some of these add-ons, please send me an email +at =bzg@gnu.org= once you set up a separate repository for them. + +** License + +All files in this repository are licensed under the GNU General Public +License, either version 3 of the License, or (at your option) any +later version. See [[file:COPYING][COPYING]]. + +** Files to remove from the next release + +These files are maintained in a separate repository, which you can +find after the "Homepage:" keyword in the files themselves: + +- ob-arduino.el :: Org-mode Babel support for Arduino +- ob-clojure-literate.el :: Clojure's Org-mode Literate Programming +- ob-mathematica.el :: org-babel functions for Mathematica evaluation +- ob-php.el :: Execute PHP within org-mode blocks +- ob-redis.el :: Execute Redis queries within org-mode blocks +- ob-sclang.el :: SCLang support for Org-mode Babel +- ob-smiles.el :: Org-mode Babel support for SMILES +- ob-spice.el :: org-babel functions for spice evaluation +- ol-notmuch.el :: Links to notmuch messages +- org-attach-embedded-images.el :: Transmute images to attachments +- org-link-edit.el :: Slurp and barf with Org links +- org-mac-link.el :: Insert org-mode links to items selected in various Mac apps +- org-notify.el :: Notifications for Org-mode +- org-passwords.el :: org derived mode for managing passwords +- org-velocity.el :: something like Notational Velocity for Org +- ox-rss.el :: RSS 2.0 Back-End for Org Export Engine + +** Other files +*** Org utils + +- org-annotate-file.el :: Annotate a file with org syntax +- org-attach-embedded-images.el :: Transmute images to attachments +- org-bibtex-extras.el :: Extras for working with org-bibtex entries +- org-checklist.el :: org functions for checklist handling +- org-choose.el :: Use TODO keywords to mark decision states +- org-collector.el :: Collect properties into tables +- org-contacts.el :: Contacts management +- org-contribdir.el :: Dummy file to mark the org contrib Lisp directory +- org-depend.el :: TODO dependencies for Org-mode +- org-effectiveness.el :: Measuring your personal effectiveness +- org-eldoc.el :: Eldoc documentation for SRC blocks +- org-eval.el :: The tag, adapted from Muse +- org-eval-light.el :: Evaluate in-buffer code on demand +- org-expiry.el :: Expiry mechanism for Org entries +- org-git-link.el :: Provide org links to specific file version +- org-interactive-query.el :: Interactive modification of tags query +- org-invoice.el :: Help manage client invoices in OrgMode +- org-learn.el :: SuperMemo's incremental learning algorithm +- org-license.el :: Insert free licenses to your org documents +- org-link-edit.el :: Slurp and barf with Org links +- org-mac-iCal.el :: Imports events from iCal.app to the Emacs diary +- org-mac-link.el :: Grab links and URLs from various Mac applications +- org-mairix.el :: Hook mairix search into Org for different MUAs +- org-notify.el :: Notifications for Org-mode +- org-panel.el :: Simple routines for us with bad memory +- org-passwords.el :: Org derived mode for managing passwords +- org-registry.el :: A registry for Org links +- org-screen.el :: Visit screen sessions through Org-mode links +- org-screenshot.el :: Take and manage screenshots in Org-mode files +- org-secretary.el :: Team management with org-mode +- org-static-mathjax.el :: Muse-like tags in Org-mode +- org-sudoku.el :: Create and solve SUDOKU puzzles in Org tables +- org-toc.el :: Table of contents for Org-mode buffer +- org-track.el :: Keep up with Org development +- org-velocity.el :: something like Notational Velocity for Org +- org-wikinodes.el :: CamelCase wiki-like links for Org + +*** Org exporters + +- ox-bibtex.el :: Export bibtex fragments +- ox-confluence.el :: Confluence Wiki exporter +- ox-deck.el :: deck.js presentations exporter +- ox-extra.el :: Convenience functions for org export +- ox-freemind.el :: Freemind exporter +- ox-groff.el :: Groff exporter +- ox-rss.el :: RSS 2.0 exporter +- ox-s5.el :: S5 presentations exporter +- ox-taskjuggler.el :: TaskJuggler exporter + +*** Org link + +- ol-bookmark.el :: Links to bookmarks +- ol-elisp-symbol.el :: Links to Emacs-lisp symbols +- ol-git-link.el :: Links to specific file version +- ol-mew.el :: Links to Mew messages +- ol-notmuch.el :: Links to notmuch messages +- ol-vm.el :: Support for links to VM messages +- ol-wl.el :: Support for links to Wanderlust messages + +*** Org Babel languages + +- ob-abc.el :: Org-mode Babel Functions for ABC +- ob-arduino.el :: Org-mode Babel Functions for Arduino +- ob-asymptote.el :: Org-mode Babel Functions for Asymptote +- ob-clojure-literate.el :: Clojure's Org-mode Literate Programming +- ob-coq.el :: Org-mode Babel Functions for Coq +- ob-csharp.el :: Org-mode Babel Functions for csharp evaluation +- ob-ebnf.el :: Org-mode Babel Functions for EBNF +- ob-eukleides.el :: Org-mode Babel Functions for eukleides evaluation +- ob-fomus.el :: Org-mode Babel Functions for fomus evaluation +- ob-hledger.el :: Org-mode Babel Functions for hledger +- ob-io.el :: Org-mode Babel Functions for Io +- ob-J.el :: Org-mode Babel Functions for J +- ob-ledger.el :: Org-mode Babel Functions for Ledger +- ob-mathematica.el :: Org-mode Babel Functions for Mathematica evaluation +- ob-mathomatic.el :: Org-mode Babel Functions for mathomatic evaluation +- ob-mscgen.el :: Org-mode Babel Functions for Mscgen +- ob-oz.el :: Org-mode Babel Functions for Oz evaluation +- ob-php.el :: Execute PHP within org-mode blocks +- ob-picolisp.el :: Org-mode Babel Functions for Picolisp +- ob-redis.el :: Execute Redis queries within org-mode blocks +- ob-sclang.el :: SCLang support for Org-mode Babel +- ob-shen.el :: Org-mode Babel Functions for Shen +- ob-smiles.el :: Org-mode Babel support for SMILES +- ob-spice.el :: Org-mode Babel Functions for spice evaluation +- ob-stan.el :: Babel Functions for Stan +- ob-stata.el :: Org-mode Babel Functions for Stata evaluation +- ob-tcl.el :: Org-mode Babel Functions for tcl evaluation +- ob-vala.el :: Org-mode Babel Functions for Vala +- ob-vbnet.el :: Org-mode Babel Functions for VB.Net evaluation diff --git a/lisp/org/lisp/ob-J.el b/lisp/org-contrib/ob-J.el similarity index 97% rename from lisp/org/lisp/ob-J.el rename to lisp/org-contrib/ob-J.el index e66227b8..8dc6ba73 100644 --- a/lisp/org/lisp/ob-J.el +++ b/lisp/org-contrib/ob-J.el @@ -1,13 +1,13 @@ ;;; ob-J.el --- Babel Functions for J -*- lexical-binding: t; -*- -;; Copyright (C) 2011-2020 Free Software Foundation, Inc. +;; Copyright (C) 2011-2021 Free Software Foundation, Inc. ;; Author: Oleh Krehel ;; Maintainer: Joseph Novakovich ;; Keywords: literate programming, reproducible research ;; Homepage: https://orgmode.org -;; This file is part of GNU Emacs. +;; This file is not part of GNU Emacs. ;; GNU Emacs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -92,7 +92,7 @@ This function is called by `org-babel-execute-src-block'." (org-babel-J-eval-string full-body sit-time))))) (defun org-babel-J-eval-string (str sit-time) - "Sends STR to the `j-console-cmd' session and executes it." + "Sends STR to the `j-console-cmd' session and execute it." (let ((session (j-console-ensure-session))) (with-current-buffer (process-buffer session) (goto-char (point-max)) diff --git a/lisp/org/lisp/ob-abc.el b/lisp/org-contrib/ob-abc.el similarity index 93% rename from lisp/org/lisp/ob-abc.el rename to lisp/org-contrib/ob-abc.el index 4c9e8352..837feaff 100644 --- a/lisp/org/lisp/ob-abc.el +++ b/lisp/org-contrib/ob-abc.el @@ -1,12 +1,13 @@ ;;; ob-abc.el --- Org Babel Functions for ABC -*- lexical-binding: t; -*- -;; Copyright (C) 2013-2020 Free Software Foundation, Inc. +;; Copyright (C) 2013-2021 Free Software Foundation, Inc. ;; Author: William Waites +;; Maintainer: William Waites ;; Keywords: literate programming, music ;; Homepage: https://www.tardis.ed.ac.uk/~wwaites -;; This file is part of GNU Emacs. +;; This file is not part of GNU Emacs. ;; GNU Emacs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -27,9 +28,12 @@ ;;; It requires that the abcm2ps program is installed. ;;; See http://moinejf.free.fr/ +;;; Code: + (require 'ob) ;; optionally define a file extension for this language + (add-to-list 'org-babel-tangle-lang-exts '("abc" . "abc")) ;; optionally declare default header arguments for this language @@ -53,8 +57,8 @@ body)) (defun org-babel-execute:abc (body params) - "Execute a block of ABC code with org-babel. This function is - called by `org-babel-execute-src-block'" + "Execute a block of ABC code with org-babel. +This function is called by `org-babel-execute-src-block'." (message "executing Abc source code block") (let* ((cmdline (cdr (assq :cmdline params))) (out-file (let ((file (cdr (assq :file params)))) diff --git a/lisp/org/contrib/lisp/ob-arduino.el b/lisp/org-contrib/ob-arduino.el similarity index 79% rename from lisp/org/contrib/lisp/ob-arduino.el rename to lisp/org-contrib/ob-arduino.el index 57a15ffa..76054e85 100644 --- a/lisp/org/contrib/lisp/ob-arduino.el +++ b/lisp/org-contrib/ob-arduino.el @@ -1,13 +1,25 @@ -;;; ob-arduino.el --- Org-mode Babel support for Arduino. +;;; ob-arduino.el --- Org-mode Babel support for Arduino ;; ;; Authors: stardiviner ;; Package-Requires: ((emacs "24.4") (org "24.1")) ;; Package-Version: 1.0 ;; Keywords: arduino org babel -;; homepage: https://github.com/stardiviner/arduino-mode +;; homepage: https://github.com/stardiviner/arduino-mode/blob/master/ob-arduino.el +;; +;; This file is not part of GNU Emacs. +;; +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;; ;;; Commentary: ;; @@ -33,7 +45,7 @@ (require 'org) (require 'ob) -(require 'arduino-mode) +(require 'arduino-mode nil t) (defgroup ob-arduino nil "org-mode blocks for Arduino." diff --git a/lisp/org/lisp/ob-asymptote.el b/lisp/org-contrib/ob-asymptote.el similarity index 96% rename from lisp/org/lisp/ob-asymptote.el rename to lisp/org-contrib/ob-asymptote.el index da7f870d..86f77734 100644 --- a/lisp/org/lisp/ob-asymptote.el +++ b/lisp/org-contrib/ob-asymptote.el @@ -1,12 +1,13 @@ ;;; ob-asymptote.el --- Babel Functions for Asymptote -*- lexical-binding: t; -*- -;; Copyright (C) 2009-2020 Free Software Foundation, Inc. +;; Copyright (C) 2009-2021 Free Software Foundation, Inc. ;; Author: Eric Schulte +;; Maintainer: Luc Pellissier ;; Keywords: literate programming, reproducible research ;; Homepage: https://orgmode.org -;; This file is part of GNU Emacs. +;; This file is not part of GNU Emacs. ;; GNU Emacs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by diff --git a/lisp/org/contrib/lisp/ob-clojure-literate.el b/lisp/org-contrib/ob-clojure-literate.el similarity index 95% rename from lisp/org/contrib/lisp/ob-clojure-literate.el rename to lisp/org-contrib/ob-clojure-literate.el index b1cc386e..39e4f394 100644 --- a/lisp/org/contrib/lisp/ob-clojure-literate.el +++ b/lisp/org-contrib/ob-clojure-literate.el @@ -1,4 +1,4 @@ -;;; ob-clojure-literate.el --- Clojure's Org-mode Literate Programming. +;;; ob-clojure-literate.el --- Clojure's Org-mode Literate Programming ;; Authors: stardiviner ;; Package-Requires: ((emacs "24.4") (org "9") (cider "0.16.0") (dash "2.12.0")) @@ -6,8 +6,20 @@ ;; Keywords: tools ;; homepage: https://github.com/stardiviner/ob-clojure-literate +;; This file is not part of GNU Emacs. +;; +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;;; Commentary: ;; @@ -20,7 +32,7 @@ ;;; Code: (require 'ob-clojure) -(require 'cider) +(require 'cider nil t) (defgroup ob-clojure-literate nil "Clojure's Org-mode Literate Programming." diff --git a/lisp/org/lisp/ob-coq.el b/lisp/org-contrib/ob-coq.el similarity index 94% rename from lisp/org/lisp/ob-coq.el rename to lisp/org-contrib/ob-coq.el index e473eac3..16143beb 100644 --- a/lisp/org/lisp/ob-coq.el +++ b/lisp/org-contrib/ob-coq.el @@ -1,12 +1,13 @@ ;;; ob-coq.el --- Babel Functions for Coq -*- lexical-binding: t; -*- -;; Copyright (C) 2010-2020 Free Software Foundation, Inc. +;; Copyright (C) 2010-2021 Free Software Foundation, Inc. ;; Author: Eric Schulte +;; Maintainer: Luc Pellissier ;; Keywords: literate programming, reproducible research ;; Homepage: https://orgmode.org -;; This file is part of GNU Emacs. +;; This file is not part of GNU Emacs. ;; GNU Emacs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by diff --git a/lisp/org/contrib/lisp/ob-csharp.el b/lisp/org-contrib/ob-csharp.el similarity index 95% rename from lisp/org/contrib/lisp/ob-csharp.el rename to lisp/org-contrib/ob-csharp.el index d3aab5d9..1a0be158 100644 --- a/lisp/org/contrib/lisp/ob-csharp.el +++ b/lisp/org-contrib/ob-csharp.el @@ -1,6 +1,6 @@ ;;; ob-csharp.el --- org-babel functions for csharp evaluation -;; Copyright (C) 2011-2020 Free Software Foundation, Inc. +;; Copyright (C) 2011-2021 Free Software Foundation, Inc. ;; Author: thomas "at" friendlyvillagers.com based on ob-java.el by Eric Schulte ;; Keywords: literate programming, reproducible research @@ -19,7 +19,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;;; Commentary: diff --git a/lisp/org/lisp/ob-ebnf.el b/lisp/org-contrib/ob-ebnf.el similarity index 87% rename from lisp/org/lisp/ob-ebnf.el rename to lisp/org-contrib/ob-ebnf.el index 773edded..2f5f3303 100644 --- a/lisp/org/lisp/ob-ebnf.el +++ b/lisp/org-contrib/ob-ebnf.el @@ -1,12 +1,12 @@ ;;; ob-ebnf.el --- Babel Functions for EBNF -*- lexical-binding: t; -*- -;; Copyright (C) 2013-2020 Free Software Foundation, Inc. +;; Copyright (C) 2013-2021 Free Software Foundation, Inc. ;; Author: Michael Gauland ;; Keywords: literate programming, reproducible research ;; Homepage: https://orgmode.org -;; This file is part of GNU Emacs. +;; This file is not part of GNU Emacs. ;; GNU Emacs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -24,15 +24,15 @@ ;;; Commentary: ;; Org-Babel support for using ebnf2ps to generate encapsulated postscript -;; railroad diagrams. It recognizes these arguments: +;; railroad diagrams. It recognizes these arguments: ;; ;; :file is required; it must include the extension '.eps.' All the rules -;; in the block will be drawn in the same file. This is done by +;; in the block will be drawn in the same file. This is done by ;; inserting a '[' comment at the start of the block (see the ;; documentation for ebnf-eps-buffer for more information). ;; -;; :style specifies a value in ebnf-style-database. This provides the -;; ability to customize the output. The style can also specify the +;; :style specifies a value in ebnf-style-database. This provides the +;; ability to customize the output. The style can also specify the ;; grammar syntax (by setting ebnf-syntax); note that only ebnf, ;; iso-ebnf, and yacc are supported by this file. diff --git a/lisp/org/contrib/lisp/ob-eukleides.el b/lisp/org-contrib/ob-eukleides.el similarity index 94% rename from lisp/org/contrib/lisp/ob-eukleides.el rename to lisp/org-contrib/ob-eukleides.el index 5ce85c46..be3f1fd1 100644 --- a/lisp/org/contrib/lisp/ob-eukleides.el +++ b/lisp/org-contrib/ob-eukleides.el @@ -1,6 +1,6 @@ ;;; ob-eukleides.el --- Org-babel functions for eukleides evaluation -;; Copyright (C) 2010-2020 Free Software Foundation, Inc. +;; Copyright (C) 2010-2021 Free Software Foundation, Inc. ;; Author: Luis Anaya ;; Keywords: literate programming, reproducible research @@ -19,14 +19,14 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;;; Commentary: ;; Org-Babel support for evaluating eukleides script. ;; ;; Inspired by Ian Yang's org-export-blocks-format-eukleides -;; http://www.emacswiki.org/emacs/org-export-blocks-format-eukleides.el +;; https://www.emacswiki.org/emacs/org-export-blocks-format-eukleides.el ;;; Requirements: diff --git a/lisp/org/contrib/lisp/ob-fomus.el b/lisp/org-contrib/ob-fomus.el similarity index 98% rename from lisp/org/contrib/lisp/ob-fomus.el rename to lisp/org-contrib/ob-fomus.el index 6ff27b60..52797141 100644 --- a/lisp/org/contrib/lisp/ob-fomus.el +++ b/lisp/org-contrib/ob-fomus.el @@ -1,6 +1,6 @@ ;;; ob-fomus.el --- Org-babel functions for fomus evaluation -;; Copyright (C) 2011-2014 Torsten Anders +;; Copyright (C) 2011-2014, 2021 Torsten Anders ;; Author: Torsten Anders ;; Keywords: literate programming, reproducible research diff --git a/lisp/org/lisp/ob-hledger.el b/lisp/org-contrib/ob-hledger.el similarity index 94% rename from lisp/org/lisp/ob-hledger.el rename to lisp/org-contrib/ob-hledger.el index ff451bef..79afa626 100644 --- a/lisp/org/lisp/ob-hledger.el +++ b/lisp/org-contrib/ob-hledger.el @@ -1,12 +1,12 @@ -;; ob-hledger.el --- Babel Functions for hledger -*- lexical-binding: t; -*- +;;; ob-hledger.el --- Babel Functions for hledger -*- lexical-binding: t; -*- -;; Copyright (C) 2010-2020 Free Software Foundation, Inc. +;; Copyright (C) 2010-2021 Free Software Foundation, Inc. ;; Author: Simon Michael ;; Keywords: literate programming, reproducible research, plain text accounting ;; Homepage: https://orgmode.org -;; This file is part of GNU Emacs. +;; This file is not part of GNU Emacs. ;; GNU Emacs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by diff --git a/lisp/org/lisp/ob-io.el b/lisp/org-contrib/ob-io.el similarity index 93% rename from lisp/org/lisp/ob-io.el rename to lisp/org-contrib/ob-io.el index 46e721b7..3a2fea2c 100644 --- a/lisp/org/lisp/ob-io.el +++ b/lisp/org-contrib/ob-io.el @@ -1,12 +1,12 @@ ;;; ob-io.el --- Babel Functions for Io -*- lexical-binding: t; -*- -;; Copyright (C) 2012-2020 Free Software Foundation, Inc. +;; Copyright (C) 2012-2021 Free Software Foundation, Inc. ;; Author: Andrzej Lichnerowicz ;; Keywords: literate programming, reproducible research ;; Homepage: https://orgmode.org -;; This file is part of GNU Emacs. +;; This file is not part of GNU Emacs. ;; GNU Emacs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -27,7 +27,7 @@ ;; :results output repl -- runs in repl mode ;;; Requirements: -;; - Io language :: http://iolanguage.org/ +;; - Io language :: https://iolanguage.org/ ;; - Io major mode :: Can be installed from Io sources ;; https://github.com/stevedekorte/io/blob/master/extras/SyntaxHighlighters/Emacs/io-mode.el @@ -95,8 +95,8 @@ in BODY as elisp." (error "Sessions are not (yet) supported for Io")) (defun org-babel-io-initiate-session (&optional _session) - "If there is not a current inferior-process-buffer in SESSION -then create. Return the initialized session. Sessions are not + "If there is not a current inferior-process-buffer in SESSION then create. +Return the initialized session. Sessions are not supported in Io." nil) diff --git a/lisp/org/lisp/ob-ledger.el b/lisp/org-contrib/ob-ledger.el similarity index 90% rename from lisp/org/lisp/ob-ledger.el rename to lisp/org-contrib/ob-ledger.el index 2be1a39a..b1812ac3 100644 --- a/lisp/org/lisp/ob-ledger.el +++ b/lisp/org-contrib/ob-ledger.el @@ -1,12 +1,13 @@ ;;; ob-ledger.el --- Babel Functions for Ledger -*- lexical-binding: t; -*- -;; Copyright (C) 2010-2020 Free Software Foundation, Inc. +;; Copyright (C) 2010-2021 Free Software Foundation, Inc. ;; Author: Eric S Fraga +;; Maintainer: Eric S Fraga ;; Keywords: literate programming, reproducible research, accounting ;; Homepage: https://orgmode.org -;; This file is part of GNU Emacs. +;; This file is not part of GNU Emacs. ;; GNU Emacs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -43,8 +44,8 @@ "Default arguments to use when evaluating a ledger source block.") (defun org-babel-execute:ledger (body params) - "Execute a block of Ledger entries with org-babel. This function is -called by `org-babel-execute-src-block'." + "Execute a block of Ledger entries with org-babel. +This function is called by `org-babel-execute-src-block'." (message "executing Ledger source code block") (let ((cmdline (cdr (assq :cmdline params))) (in-file (org-babel-temp-file "ledger-")) diff --git a/lisp/org/contrib/lisp/ob-mathematica.el b/lisp/org-contrib/ob-mathematica.el similarity index 78% rename from lisp/org/contrib/lisp/ob-mathematica.el rename to lisp/org-contrib/ob-mathematica.el index cb35dec0..2b703da6 100644 --- a/lisp/org/contrib/lisp/ob-mathematica.el +++ b/lisp/org-contrib/ob-mathematica.el @@ -1,11 +1,25 @@ ;;; ob-mathematica.el --- org-babel functions for Mathematica evaluation -;; Copyright (C) 2014 Yi Wang +;; Copyright (C) 2014, 2021 Yi Wang ;; Authors: Yi Wang ;; Keywords: literate programming, reproducible research -;; Homepage: https://github.com/tririver/wy-els/blob/master/ob-mathematica.el -;; Distributed under the GNU GPL v2 or later +;; Homepage: https://github.com/tririver/ob-mathematica/ + +;; This file is not part of GNU Emacs. +;; +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . ;; Org-Babel support for evaluating Mathematica source code. diff --git a/lisp/org/contrib/lisp/ob-mathomatic.el b/lisp/org-contrib/ob-mathomatic.el similarity index 97% rename from lisp/org/contrib/lisp/ob-mathomatic.el rename to lisp/org-contrib/ob-mathomatic.el index 2baff2bd..adc7c376 100644 --- a/lisp/org/contrib/lisp/ob-mathomatic.el +++ b/lisp/org-contrib/ob-mathomatic.el @@ -1,6 +1,6 @@ ;;; ob-mathomatic.el --- Org-babel functions for mathomatic evaluation -;; Copyright (C) 2009-2020 Free Software Foundation, Inc. +;; Copyright (C) 2009-2021 Free Software Foundation, Inc. ;; Author: Eric S Fraga ;; Eric Schulte @@ -22,7 +22,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;;; Commentary: diff --git a/lisp/org/lisp/ob-mscgen.el b/lisp/org-contrib/ob-mscgen.el similarity index 90% rename from lisp/org/lisp/ob-mscgen.el rename to lisp/org-contrib/ob-mscgen.el index 2bd9144f..09f20c2e 100644 --- a/lisp/org/lisp/ob-mscgen.el +++ b/lisp/org-contrib/ob-mscgen.el @@ -1,12 +1,13 @@ -;;; ob-msc.el --- Babel Functions for Mscgen -*- lexical-binding: t; -*- +;;; ob-mscgen.el --- Babel Functions for Mscgen -*- lexical-binding: t; -*- -;; Copyright (C) 2010-2020 Free Software Foundation, Inc. +;; Copyright (C) 2010-2021 Free Software Foundation, Inc. ;; Author: Juan Pechiar +;; Maintainer: Justin Abrahms ;; Keywords: literate programming, reproducible research ;; Homepage: https://orgmode.org -;; This file is part of GNU Emacs. +;; This file is not part of GNU Emacs. ;; GNU Emacs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -28,7 +29,7 @@ ;; sequence definition, and must therefore be installed in the system. ;; ;; Mscgen is available and documented at -;; http://www.mcternan.me.uk/mscgen/index.html +;; https://www.mcternan.me.uk/mscgen/index.html ;; ;; This code is directly inspired by Eric Schulte's ob-dot.el ;; @@ -78,4 +79,4 @@ mscgen supported formats." (provide 'ob-mscgen) -;;; ob-msc.el ends here +;;; ob-mscgen.el ends here diff --git a/lisp/org/contrib/lisp/ob-oz.el b/lisp/org-contrib/ob-oz.el similarity index 99% rename from lisp/org/contrib/lisp/ob-oz.el rename to lisp/org-contrib/ob-oz.el index 46bf536f..434e0dba 100644 --- a/lisp/org/contrib/lisp/ob-oz.el +++ b/lisp/org-contrib/ob-oz.el @@ -1,6 +1,6 @@ ;;; ob-oz.el --- Org-babel functions for Oz evaluation -;; Copyright (C) 2009-2014 Torsten Anders and Eric Schulte +;; Copyright (C) 2009-2014, 2021 Torsten Anders and Eric Schulte ;; Author: Torsten Anders and Eric Schulte ;; Keywords: literate programming, reproducible research diff --git a/lisp/org/contrib/lisp/ob-php.el b/lisp/org-contrib/ob-php.el similarity index 59% rename from lisp/org/contrib/lisp/ob-php.el rename to lisp/org-contrib/ob-php.el index 99b084cf..9b0b990e 100644 --- a/lisp/org/contrib/lisp/ob-php.el +++ b/lisp/org-contrib/ob-php.el @@ -1,14 +1,30 @@ -;;; ob-php.el --- Execute PHP within org-mode blocks. -;; Copyright 2016 stardiviner +;;; ob-php.el --- Execute PHP within org-mode blocks +;; Copyright 2016, 2021 stardiviner ;; Author: stardiviner ;; Maintainer: stardiviner +;; Homepage: https://github.com/stardiviner/ob-php ;; Keywords: org babel php -;; URL: https://github.com/stardiviner/ob-php +;; Homepage: https://github.com/stardiviner/ob-php ;; Created: 04th May 2016 ;; Version: 0.0.1 ;; Package-Requires: ((org "8")) +;; This file is not part of GNU Emacs. +;; +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + ;;; Commentary: ;; ;; Execute PHP within org-mode blocks. diff --git a/lisp/org/lisp/ob-picolisp.el b/lisp/org-contrib/ob-picolisp.el similarity index 93% rename from lisp/org/lisp/ob-picolisp.el rename to lisp/org-contrib/ob-picolisp.el index 96fee36f..f7faff00 100644 --- a/lisp/org/lisp/ob-picolisp.el +++ b/lisp/org-contrib/ob-picolisp.el @@ -1,13 +1,13 @@ ;;; ob-picolisp.el --- Babel Functions for Picolisp -*- lexical-binding: t; -*- -;; Copyright (C) 2010-2020 Free Software Foundation, Inc. +;; Copyright (C) 2010-2021 Free Software Foundation, Inc. ;; Authors: Thorsten Jolitz ;; Eric Schulte ;; Keywords: literate programming, reproducible research ;; Homepage: https://orgmode.org -;; This file is part of GNU Emacs. +;; This file is not part of GNU Emacs. ;; GNU Emacs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -26,15 +26,15 @@ ;; This library enables the use of PicoLisp in the multi-language ;; programming framework Org-Babel. PicoLisp is a minimal yet -;; fascinating lisp dialect and a highly productive application +;; fascinating Lisp dialect and a highly productive application ;; framework for web-based client-server applications on top of ;; object-oriented databases. A good way to learn PicoLisp is to first ;; read Paul Grahams essay "The hundred year language" ;; (http://www.paulgraham.com/hundred.html) and then study the various ;; documents and essays published in the PicoLisp wiki -;; (http://picolisp.com/5000/-2.html). PicoLisp is included in some +;; (https://picolisp.com/5000/-2.html). PicoLisp is included in some ;; GNU/Linux Distributions, and can be downloaded here: -;; http://software-lab.de/down.html. It ships with a picolisp-mode and +;; https://software-lab.de/down.html. It ships with a picolisp-mode and ;; an inferior-picolisp-mode for Emacs (to be found in the /lib/el/ ;; directory). @@ -44,7 +44,7 @@ ;; make it a valuable addition to Org Babel: ;; PicoLisp _is_ an object-oriented database with a Prolog-based query -;; language implemented in PicoLisp (Pilog). Database objects are +;; language implemented in PicoLisp (Pilog). Database objects are ;; first-class members of the language. ;; PicoLisp is an extremely productive framework for the development @@ -166,8 +166,8 @@ This function is called by `org-babel-execute-src-block'." (read result)))) (defun org-babel-picolisp-initiate-session (&optional session-name) - "If there is not a current inferior-process-buffer in SESSION -then create. Return the initialized session." + "If there is not a current inferior-process-buffer in SESSION then create. +Return the initialized session." (unless (string= session-name "none") (require 'inferior-picolisp) ;; provide a reasonable default session name diff --git a/lisp/org/contrib/lisp/ob-redis.el b/lisp/org-contrib/ob-redis.el similarity index 55% rename from lisp/org/contrib/lisp/ob-redis.el rename to lisp/org-contrib/ob-redis.el index 086b4cd6..204f5d40 100644 --- a/lisp/org/contrib/lisp/ob-redis.el +++ b/lisp/org-contrib/ob-redis.el @@ -1,14 +1,29 @@ -;;; ob-redis.el --- Execute Redis queries within org-mode blocks. -;; Copyright 2016 stardiviner +;;; ob-redis.el --- Execute Redis queries within org-mode blocks +;; Copyright 2016-2021 stardiviner ;; Author: stardiviner ;; Maintainer: stardiviner ;; Keywords: org babel redis -;; URL: https://github.com/stardiviner/ob-redis +;; Homepage: https://github.com/stardiviner/ob-redis ;; Created: 28th Feb 2016 ;; Version: 0.0.1 ;; Package-Requires: ((org "8")) +;; This file is not part of GNU Emacs. +;; +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + ;;; Commentary: ;; ;; Execute Redis queries within org-mode blocks. diff --git a/lisp/org/contrib/lisp/ob-sclang.el b/lisp/org-contrib/ob-sclang.el similarity index 93% rename from lisp/org/contrib/lisp/ob-sclang.el rename to lisp/org-contrib/ob-sclang.el index 0092ab39..861ef37d 100644 --- a/lisp/org/contrib/lisp/ob-sclang.el +++ b/lisp/org-contrib/ob-sclang.el @@ -1,9 +1,10 @@ ;;; ob-sclang.el --- SCLang support for Org-mode Babel ;;; -*- coding: utf-8 -*- -;; Copyright (C) 2017-2020 Free Software Foundation, Inc. +;; Copyright (C) 2017-2021 Free Software Foundation, Inc. ;; Authors: stardiviner +;; Homepage: https://github.com/stardiviner/ob-sclang ;; Package-Version: 0.1 ;; Keywords: babel sclang @@ -20,7 +21,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;;; Commentary: @@ -60,7 +61,7 @@ (require 'org) (require 'ob) -(require 'sclang) +(require 'sclang nil t) (defgroup ob-sclang nil "org-mode blocks for SuperCollider SCLang." diff --git a/lisp/org/lisp/ob-shen.el b/lisp/org-contrib/ob-shen.el similarity index 96% rename from lisp/org/lisp/ob-shen.el rename to lisp/org-contrib/ob-shen.el index 0e012ac8..6eccce11 100644 --- a/lisp/org/lisp/ob-shen.el +++ b/lisp/org-contrib/ob-shen.el @@ -1,12 +1,12 @@ ;;; ob-shen.el --- Babel Functions for Shen -*- lexical-binding: t; -*- -;; Copyright (C) 2010-2020 Free Software Foundation, Inc. +;; Copyright (C) 2010-2021 Free Software Foundation, Inc. ;; Author: Eric Schulte ;; Keywords: literate programming, reproducible research, shen ;; Homepage: https://orgmode.org -;; This file is part of GNU Emacs. +;; This file is not part of GNU Emacs. ;; GNU Emacs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by diff --git a/lisp/org-contrib/ob-smiles.el b/lisp/org-contrib/ob-smiles.el new file mode 100644 index 00000000..1e61a00b --- /dev/null +++ b/lisp/org-contrib/ob-smiles.el @@ -0,0 +1,71 @@ +;;; ob-smiles.el --- Org-mode Babel support for SMILES + +;; Author: John Kitchin +;; Maintainer: stardiviner +;; Homepage: https://github.com/stardiviner/ob-smiles +;; Keywords: org babel SMILES +;; Version: 0.0.1 +;; Package-Requires: ((smiles-mode "0.0.1") (org "8")) + +;; This file is not part of GNU Emacs. +;; +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: + +;;; I copy code from: +;;; https://kitchingroup.cheme.cmu.edu/blog/2016/03/26/A-molecule-link-for-org-mode + +;;; Code: + +(require 'ob) +(require 'org-element) + +;; Org-mode Babel +(defun org-babel-execute:smiles (body params) + "Execute SMILES babel `BODY' with `PARAMS'." + (shell-command-to-string + (format "obabel -:\"%s\" -osvg 2> /dev/null" body))) + +;; Org-mode link +(defun molecule-jump (name) + "Jump to molecule `NAME' definition." + (org-mark-ring-push) + (org-link-open-from-string (format "[[%s]]" name))) + +(defun molecule-export (path desc backend) + "Export molecule to HTML format on `PATH' with `DESC' and `BACKEND'." + (let ((name (save-window-excursion + (molecule-jump path) + (org-element-property :name (org-element-context))))) + (cond + ((eq 'html backend) + (format "%s" name name))))) + +(org-link-set-parameters + "molecule" + :follow 'molecule-jump + :export 'molecule-export) + +;; org-mode element +(org-element-map (org-element-parse-buffer) + 'src-block + (lambda (src) + (when (string= "smiles" (org-element-property :language src)) + (org-element-property :name src)))) + + +(provide 'ob-smiles) + +;;; ob-smiles.el ends here diff --git a/lisp/org/contrib/lisp/ob-spice.el b/lisp/org-contrib/ob-spice.el similarity index 96% rename from lisp/org/contrib/lisp/ob-spice.el rename to lisp/org-contrib/ob-spice.el index c452c993..3b732a56 100644 --- a/lisp/org/contrib/lisp/ob-spice.el +++ b/lisp/org-contrib/ob-spice.el @@ -2,10 +2,10 @@ ;;; -*- coding: utf-8 -*- ;; Author: Tiago Oliveira Weber -;; Maintainer: stardiviner (numbchild@gmail.com) +;; Maintainer: stardiviner +;; Homepage: https://github.com/stardiviner/ob-spice ;; Version: 0.4 ;; Package-Requires: ((spice-mode "0.0.1") (org "8")) -;; Homepage: http://tiagoweber.github.io ;; License: GPL v3, or any later version ;; @@ -20,12 +20,12 @@ ;; 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: ;; Org-Babel support for evaluating spice script. -;; Inspired by Ian Yang's org-export-blocks-format-plantuml (http://www.emacswiki.org/emacs/org-export-blocks-format-plantuml.el) +;; Inspired by Ian Yang's org-export-blocks-format-plantuml (https://www.emacswiki.org/emacs/org-export-blocks-format-plantuml.el) ;;; Requirements: ;; diff --git a/lisp/org/lisp/ob-stan.el b/lisp/org-contrib/ob-stan.el similarity index 95% rename from lisp/org/lisp/ob-stan.el rename to lisp/org-contrib/ob-stan.el index 00aa8fb2..398ccecc 100644 --- a/lisp/org/lisp/ob-stan.el +++ b/lisp/org-contrib/ob-stan.el @@ -1,12 +1,12 @@ ;;; ob-stan.el --- Babel Functions for Stan -*- lexical-binding: t; -*- -;; Copyright (C) 2015-2020 Free Software Foundation, Inc. +;; Copyright (C) 2015-2021 Free Software Foundation, Inc. ;; Author: Kyle Meyer ;; Keywords: literate programming, reproducible research -;; Homepage: https://orgmode.org +;; Homepage: https://git.kyleam.com/ob-stan -;; This file is part of GNU Emacs. +;; This file is not part of GNU Emacs. ;; GNU Emacs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by diff --git a/lisp/org/contrib/lisp/ob-stata.el b/lisp/org-contrib/ob-stata.el similarity index 99% rename from lisp/org/contrib/lisp/ob-stata.el rename to lisp/org-contrib/ob-stata.el index d8cf52a3..13f9e091 100644 --- a/lisp/org/contrib/lisp/ob-stata.el +++ b/lisp/org-contrib/ob-stata.el @@ -1,12 +1,11 @@ ;;; ob-stata.el --- org-babel functions for stata code evaluation -;; Copyright (C) 2014 Ista Zahn +;; Copyright (C) 2014, 2021 Ista Zahn ;; Author: Ista Zahn istazahn@gmail.com ;; G. Jay Kerns ;; Eric Schulte ;; Dan Davison - ;; This file is not part of GNU Emacs. ;; This program is free software; you can redistribute it and/or modify @@ -37,8 +36,8 @@ ;; --Ista, 07/30/2014 ;;; Requirements: -;; Stata: http://stata.com -;; ESS: http://ess.r-project.org +;; Stata: https://stata.com +;; ESS: https://ess.r-project.org ;;; Code: (require 'ob) diff --git a/lisp/org/contrib/lisp/ob-tcl.el b/lisp/org-contrib/ob-tcl.el similarity index 96% rename from lisp/org/contrib/lisp/ob-tcl.el rename to lisp/org-contrib/ob-tcl.el index 091eb5d0..62700473 100644 --- a/lisp/org/contrib/lisp/ob-tcl.el +++ b/lisp/org-contrib/ob-tcl.el @@ -1,6 +1,6 @@ ;;; ob-tcl.el --- Org-babel functions for tcl evaluation -;; Copyright (C) 2009-2020 Free Software Foundation, Inc. +;; Copyright (C) 2009-2021 Free Software Foundation, Inc. ;; Authors: Dan Davison ;; Eric Schulte @@ -22,7 +22,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;;; Commentary: diff --git a/lisp/org/lisp/ob-vala.el b/lisp/org-contrib/ob-vala.el similarity index 95% rename from lisp/org/lisp/ob-vala.el rename to lisp/org-contrib/ob-vala.el index b1c22756..826d32f0 100644 --- a/lisp/org/lisp/ob-vala.el +++ b/lisp/org-contrib/ob-vala.el @@ -1,14 +1,12 @@ -;;; ob-vala.el --- Babel functions for Vala evaluation -*- lexical-binding: t; -*- +;;; ob-vala.el --- Babel functions for Vala -*- lexical-binding: t; -*- -;; Copyright (C) 2017-2020 Free Software Foundation, Inc. +;; Copyright (C) 2017-2021 Free Software Foundation, Inc. ;; Author: Christian Garbs ;; Keywords: literate programming, reproducible research ;; Homepage: https://orgmode.org -;;; License: - -;; This file is part of GNU Emacs. +;; This file is not part of GNU Emacs. ;; GNU Emacs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by diff --git a/lisp/org/contrib/lisp/ob-vbnet.el b/lisp/org-contrib/ob-vbnet.el similarity index 95% rename from lisp/org/contrib/lisp/ob-vbnet.el rename to lisp/org-contrib/ob-vbnet.el index 77498f89..1ea572d5 100644 --- a/lisp/org/contrib/lisp/ob-vbnet.el +++ b/lisp/org-contrib/ob-vbnet.el @@ -1,6 +1,6 @@ ;;; ob-vbnet.el --- org-babel functions for VB.Net evaluation -;; Copyright (C) 2011-2020 Free Software Foundation, Inc. +;; Copyright (C) 2011-2021 Free Software Foundation, Inc. ;; Author: thomas "at" friendlyvillagers.com based on ob-java.el by Eric Schulte ;; Keywords: literate programming, reproducible research @@ -19,7 +19,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;;; Commentary: diff --git a/lisp/org/contrib/lisp/ol-bookmark.el b/lisp/org-contrib/ol-bookmark.el similarity index 96% rename from lisp/org/contrib/lisp/ol-bookmark.el rename to lisp/org-contrib/ol-bookmark.el index db975e4f..f4b22055 100644 --- a/lisp/org/contrib/lisp/ol-bookmark.el +++ b/lisp/org-contrib/ol-bookmark.el @@ -1,5 +1,6 @@ -;;; ol-bookmark.el - Links to bookmarks -;; Copyright (C) 2008-2020 Free Software Foundation, Inc. +;;; ol-bookmark.el --- Links to bookmarks + +;; Copyright (C) 2008-2021 Free Software Foundation, Inc. ;; ;; Author: Tokuya Kameshima ;; Version: 1.0 diff --git a/lisp/org/contrib/lisp/ol-elisp-symbol.el b/lisp/org-contrib/ol-elisp-symbol.el similarity index 96% rename from lisp/org/contrib/lisp/ol-elisp-symbol.el rename to lisp/org-contrib/ol-elisp-symbol.el index d9c83085..42874c3f 100644 --- a/lisp/org/contrib/lisp/ol-elisp-symbol.el +++ b/lisp/org-contrib/ol-elisp-symbol.el @@ -1,11 +1,11 @@ ;;; ol-elisp-symbol.el --- Links to Emacs-lisp symbols ;; -;; Copyright 2007-2020 Free Software Foundation, Inc. +;; Copyright 2007-2021 Free Software Foundation, Inc. ;; -;; Author: Bastien Guerry +;; Author: Bastien Guerry ;; Version: 0.2 ;; Keywords: org, remember, lisp -;; URL: http://www.cognition.ens.fr/~guerry/u/org-elisp-symbol.el +;; Homepage: https://git.sr.ht/~bzg/org-contrib ;; ;; This file is not part of GNU Emacs. ;; @@ -20,7 +20,7 @@ ;; GNU General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;; ;;; Commentary: ;; diff --git a/lisp/org/contrib/lisp/ol-git-link.el b/lisp/org-contrib/ol-git-link.el similarity index 98% rename from lisp/org/contrib/lisp/ol-git-link.el rename to lisp/org-contrib/ol-git-link.el index 4076e24c..a6e90439 100644 --- a/lisp/org/contrib/lisp/ol-git-link.el +++ b/lisp/org-contrib/ol-git-link.el @@ -1,6 +1,6 @@ ;;; ol-git-link.el --- Links to specific file version -;; Copyright (C) 2009-2014 Reimar Finken +;; Copyright (C) 2009-2014, 2021 Reimar Finken ;; Author: Reimar Finken ;; Keywords: files, calendar, hypermedia @@ -18,7 +18,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: diff --git a/lisp/org/contrib/lisp/ol-mew.el b/lisp/org-contrib/ol-mew.el similarity index 99% rename from lisp/org/contrib/lisp/ol-mew.el rename to lisp/org-contrib/ol-mew.el index 3ce6244d..a8aa5d0a 100644 --- a/lisp/org/contrib/lisp/ol-mew.el +++ b/lisp/org-contrib/ol-mew.el @@ -1,6 +1,6 @@ ;;; ol-mew.el --- Links to Mew messages -;; Copyright (C) 2008-2020 Free Software Foundation, Inc. +;; Copyright (C) 2008-2021 Free Software Foundation, Inc. ;; Author: Tokuya Kameshima ;; Keywords: outlines, hypermedia, calendar, wp @@ -19,7 +19,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;;; Commentary: diff --git a/lisp/org/contrib/lisp/ol-notmuch.el b/lisp/org-contrib/ol-notmuch.el similarity index 94% rename from lisp/org/contrib/lisp/ol-notmuch.el rename to lisp/org-contrib/ol-notmuch.el index 0fa0c5a2..7d959727 100644 --- a/lisp/org/contrib/lisp/ol-notmuch.el +++ b/lisp/org-contrib/ol-notmuch.el @@ -1,16 +1,17 @@ ;;; ol-notmuch.el --- Links to notmuch messages -;; Copyright (C) 2010-2014 Matthieu Lemerre +;; Copyright (C) 2010-2014, 2021 Matthieu Lemerre ;; Author: Matthieu Lemerre +;; Maintainer: Jonas Bernoulli ;; Keywords: outlines, hypermedia, calendar, wp -;; Homepage: https://orgmode.org +;; Homepage: https://git.sr.ht/~tarsius/ol-notmuch ;; This file is not part of GNU Emacs. ;; 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 -;; the Free Software Foundation; either version 2, or (at your option) +;; the Free Software Foundation; either version 3, or (at your option) ;; any later version. ;; This file is distributed in the hope that it will be useful, @@ -19,7 +20,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;;; Commentary: diff --git a/lisp/org/contrib/lisp/ol-vm.el b/lisp/org-contrib/ol-vm.el similarity index 96% rename from lisp/org/contrib/lisp/ol-vm.el rename to lisp/org-contrib/ol-vm.el index bf820ce6..57201888 100644 --- a/lisp/org/contrib/lisp/ol-vm.el +++ b/lisp/org-contrib/ol-vm.el @@ -1,8 +1,8 @@ ;;; ol-vm.el --- Links to VM messages -;; Copyright (C) 2004-2020 Free Software Foundation, Inc. +;; Copyright (C) 2004-2021 Free Software Foundation, Inc. -;; Author: Carsten Dominik +;; Author: Carsten Dominik ;; Keywords: outlines, hypermedia, calendar, wp ;; Homepage: https://orgmode.org ;; @@ -23,7 +23,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;;; Commentary: @@ -155,7 +155,7 @@ (let ((case-fold-search t)) (goto-char (point-min)) (if (not (re-search-forward - (concat "^" "message-id: *" (regexp-quote message-id)))) + (concat "^" "message-id:\\s-*" (regexp-quote message-id)))) (error "Could not find the specified message in this folder")) (vm-isearch-update) (vm-isearch-narrow) diff --git a/lisp/org/contrib/lisp/ol-wl.el b/lisp/org-contrib/ol-wl.el similarity index 98% rename from lisp/org/contrib/lisp/ol-wl.el rename to lisp/org-contrib/ol-wl.el index bf945312..cc122c55 100644 --- a/lisp/org/contrib/lisp/ol-wl.el +++ b/lisp/org-contrib/ol-wl.el @@ -1,6 +1,6 @@ ;;; ol-wl.el --- Links to Wanderlust messages -;; Copyright (C) 2004-2020 Free Software Foundation, Inc. +;; Copyright (C) 2004-2021 Free Software Foundation, Inc. ;; Author: Tokuya Kameshima ;; David Maus @@ -20,7 +20,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;;; Commentary: @@ -225,7 +225,7 @@ ENTITY is a message entity." (format (if (string-match-p "gmane\\." folder-name) "http://mid.gmane.org/%s" - "http://groups.google.com/groups/search?as_umsgid=%s") + "https://groups.google.com/groups/search?as_umsgid=%s") (url-encode-url message-id))) (org-store-link-props :type "http" :link link :description subject :from from :to to :message-id message-id diff --git a/lisp/org/contrib/lisp/org-annotate-file.el b/lisp/org-contrib/org-annotate-file.el similarity index 98% rename from lisp/org/contrib/lisp/org-annotate-file.el rename to lisp/org-contrib/org-annotate-file.el index e1f1f13c..f932cac2 100644 --- a/lisp/org/contrib/lisp/org-annotate-file.el +++ b/lisp/org-contrib/org-annotate-file.el @@ -1,6 +1,6 @@ ;;; org-annotate-file.el --- Annotate a file with org syntax -;; Copyright (C) 2008-2014 Philip Jackson +;; Copyright (C) 2008-2014, 2021 Philip Jackson ;; Author: Philip Jackson ;; Version: 0.2 @@ -9,7 +9,7 @@ ;; 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 2, or (at +;; published by the Free Software Foundation; either version 3, or (at ;; your option) any later version. ;; This program is distributed in the hope that it will be useful, but diff --git a/lisp/org/contrib/lisp/org-attach-embedded-images.el b/lisp/org-contrib/org-attach-embedded-images.el similarity index 95% rename from lisp/org/contrib/lisp/org-attach-embedded-images.el rename to lisp/org-contrib/org-attach-embedded-images.el index 20c5e427..5beb37ab 100644 --- a/lisp/org/contrib/lisp/org-attach-embedded-images.el +++ b/lisp/org-contrib/org-attach-embedded-images.el @@ -1,8 +1,9 @@ ;;; org-attach-embedded-images.el --- Transmute images to attachments ;; -;; Copyright 2018-2020 Free Software Foundation, Inc. +;; Copyright 2018-2021 Free Software Foundation, Inc. ;; ;; Author: Marco Wahl +;; Homepage: https://gitlab.com/marcowahl/org-attach-embedded-imagse ;; Version: 0.1 ;; Keywords: org, media ;; @@ -19,7 +20,7 @@ ;; GNU General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;;; Commentary: ;; diff --git a/lisp/org/contrib/lisp/org-bibtex-extras.el b/lisp/org-contrib/org-bibtex-extras.el similarity index 96% rename from lisp/org/contrib/lisp/org-bibtex-extras.el rename to lisp/org-contrib/org-bibtex-extras.el index 8745dc3b..1374c997 100644 --- a/lisp/org/contrib/lisp/org-bibtex-extras.el +++ b/lisp/org-contrib/org-bibtex-extras.el @@ -1,13 +1,13 @@ ;;; org-bibtex-extras --- extras for working with org-bibtex entries -;; Copyright (C) 2008-2020 Free Software Foundation, Inc. +;; Copyright (C) 2008-2021 Free Software Foundation, Inc. ;; Author: Eric Schulte ;; Keywords: outlines, hypermedia, bibtex, d3 ;; Homepage: https://orgmode.org ;; Version: 0.01 -;; This file is not yet part of GNU Emacs. +;; This file is not part of GNU Emacs. ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -20,7 +20,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;;; Commentary: diff --git a/lisp/org/contrib/lisp/org-checklist.el b/lisp/org-contrib/org-checklist.el similarity index 97% rename from lisp/org/contrib/lisp/org-checklist.el rename to lisp/org-contrib/org-checklist.el index 2bc00c0b..b813c882 100644 --- a/lisp/org/contrib/lisp/org-checklist.el +++ b/lisp/org-contrib/org-checklist.el @@ -1,6 +1,6 @@ ;;; org-checklist.el --- org functions for checklist handling -;; Copyright (C) 2008-2014 James TD Smith +;; Copyright (C) 2008-2014, 2021 James TD Smith ;; Author: James TD Smith (@ ahktenzero (. mohorovi cc)) ;; Version: 1.0 @@ -19,7 +19,7 @@ ;; GNU General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;;; Commentary: diff --git a/lisp/org/contrib/lisp/org-choose.el b/lisp/org-contrib/org-choose.el similarity index 94% rename from lisp/org/contrib/lisp/org-choose.el rename to lisp/org-contrib/org-choose.el index c791a862..ef5eca49 100644 --- a/lisp/org/contrib/lisp/org-choose.el +++ b/lisp/org-contrib/org-choose.el @@ -1,6 +1,6 @@ ;;; org-choose.el --- decision management for org-mode -;; Copyright (C) 2009-2014 Tom Breton (Tehom) +;; Copyright (C) 2009-2014, 2021 Tom Breton (Tehom) ;; This file is not part of GNU Emacs. @@ -9,7 +9,7 @@ ;; 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 -;; the Free Software Foundation; either version 2, or (at your option) +;; the Free Software Foundation; either version 3, or (at your option) ;; any later version. ;; This file is distributed in the hope that it will be useful, @@ -175,8 +175,8 @@ Each entry is an `org-choose-mark-data.'" ) (pushnew (cons text tail) org-choose-mark-data :test - #'(lambda (a b) - (equal (car a) (car b))))))) + (lambda (a b) + (equal (car a) (car b))))))) ;;; org-choose-filter-tail (defun org-choose-filter-tail (raw) @@ -347,8 +347,8 @@ setting was changed." org-todo-log-states) ;;Map over group (funcall map-over-entries - #'(lambda () - (apply func-d473 args-46k)))))))) + (lambda () + (apply func-d473 args-46k)))))))) ;;Remove the marker (set-marker entry-pos nil))) @@ -371,18 +371,18 @@ setting was changed." (defun org-choose-get-fn-map-group () "Return a function to map over the group" - #'(lambda (fn) - (require 'org-agenda) ;; `org-map-entries' seems to need it. - (save-excursion - (unless (org-up-heading-safe) - (error "Choosing is only supported between siblings in a tree, not on top level")) - (let - ((level (org-reduced-level (org-outline-level)))) - (save-restriction - (org-map-entries - fn - (format "LEVEL=%d" level) - 'tree)))))) + (lambda (fn) + (require 'org-agenda) ;; `org-map-entries' seems to need it. + (save-excursion + (unless (org-up-heading-safe) + (error "Choosing is only supported between siblings in a tree, not on top level")) + (let + ((level (org-reduced-level (org-outline-level)))) + (save-restriction + (org-map-entries + fn + (format "LEVEL=%d" level) + 'tree)))))) ;;; org-choose-get-highest-mark-index @@ -396,8 +396,8 @@ If there is none, return 0" (indexes-list (remove nil (funcall map-over-entries - #'(lambda () - (org-choose-get-entry-index keywords)))))) + (lambda () + (org-choose-get-entry-index keywords)))))) (if indexes-list (apply #'max indexes-list) diff --git a/lisp/org/contrib/lisp/org-collector.el b/lisp/org-contrib/org-collector.el similarity index 98% rename from lisp/org/contrib/lisp/org-collector.el rename to lisp/org-contrib/org-collector.el index d0369238..876cda9a 100644 --- a/lisp/org/contrib/lisp/org-collector.el +++ b/lisp/org-contrib/org-collector.el @@ -1,6 +1,6 @@ ;;; org-collector --- collect properties into tables -;; Copyright (C) 2008-2020 Free Software Foundation, Inc. +;; Copyright (C) 2008-2021 Free Software Foundation, Inc. ;; Author: Eric Schulte ;; Keywords: outlines, hypermedia, calendar, wp, experimentation, @@ -8,7 +8,7 @@ ;; Homepage: https://orgmode.org ;; Version: 0.01 -;; This file is not yet part of GNU Emacs. +;; This file is not part of GNU Emacs. ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -21,7 +21,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;;; Commentary: diff --git a/lisp/org/contrib/lisp/org-contacts.el b/lisp/org-contrib/org-contacts.el similarity index 90% rename from lisp/org/contrib/lisp/org-contacts.el rename to lisp/org-contrib/org-contacts.el index 4b3693a0..2a4ac10c 100644 --- a/lisp/org/contrib/lisp/org-contacts.el +++ b/lisp/org-contrib/org-contacts.el @@ -1,11 +1,12 @@ ;;; org-contacts.el --- Contacts management -;; Copyright (C) 2010-2014 Julien Danjou +;; Copyright (C) 2010-2014, 2021 Julien Danjou ;; Author: Julien Danjou +;; Maintainer: stardiviner ;; Keywords: outlines, hypermedia, calendar ;; -;; This file is NOT part of GNU Emacs. +;; This file is not part of GNU Emacs. ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -18,7 +19,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;;; Commentary: @@ -49,7 +50,14 @@ ;; :ADDRESS: ;; :BIRTHDAY: ;; :END:"))) -;; + +;;;; Usage: + +;;; How to search? +;;; +;;; You can use `org-sparse-tree' [C-c / p] to filter based on a +;;; specific property. Or other matcher on `org-sparse-tree'. + ;;; Code: (require 'cl-lib) @@ -915,11 +923,11 @@ address." (email-list (org-entry-get pom org-contacts-email-property)) (gravatar (when email-list - (loop for email in (org-contacts-split-property email-list) - for gravatar = (gravatar-retrieve-synchronously (org-contacts-strip-link email)) - if (and gravatar - (not (eq gravatar 'error))) - return gravatar)))) + (cl-loop for email in (org-contacts-split-property email-list) + for gravatar = (gravatar-retrieve-synchronously (org-contacts-strip-link email)) + if (and gravatar + (not (eq gravatar 'error))) + return gravatar)))) (when gravatar (throw 'icon gravatar)))))) (defun org-contacts-irc-buffer (&optional pom) @@ -957,10 +965,10 @@ address." (defun erc-nicknames-list () "Return all nicknames of all ERC buffers." - (loop for buffer in (erc-buffer-list) - nconc (with-current-buffer buffer - (loop for user-entry in (mapcar 'car (erc-get-channel-user-list)) - collect (elt user-entry 1))))) + (cl-loop for buffer in (erc-buffer-list) + nconc (with-current-buffer buffer + (cl-loop for user-entry in (mapcar 'car (erc-get-channel-user-list)) + collect (elt user-entry 1))))) (add-to-list 'org-property-set-functions-alist `(,org-contacts-nickname-property . org-contacts-completing-read-nickname)) @@ -968,7 +976,7 @@ address." (defun org-contacts-vcard-escape (str) "Escape ; , and \n in STR for the VCard format." ;; Thanks to this library for the regexp: - ;; http://www.emacswiki.org/cgi-bin/wiki/bbdb-vcard-export.el + ;; https://www.emacswiki.org/cgi-bin/wiki/bbdb-vcard-export.el (when str (replace-regexp-in-string "\n" "\\\\n" @@ -1071,8 +1079,8 @@ is created and the VCard is written into that buffer." (fundamental-mode) (when (fboundp 'set-buffer-file-coding-system) (set-buffer-file-coding-system coding-system-for-write)) - (loop for contact in (org-contacts-filter name) - do (insert (org-contacts-vcard-format contact))) + (cl-loop for contact in (org-contacts-filter name) + do (insert (org-contacts-vcard-format contact))) (if to-buffer (current-buffer) (progn (save-buffer) (kill-buffer))))) @@ -1146,6 +1154,90 @@ are effectively trimmed). If nil, all zero-length substrings are retained." (setq proplist (cons bufferstring proplist)))) (cdr (reverse proplist)))) +;;; Add an Org link type `org-contact:' for easy jump to or searching org-contacts headline. +;;; link spec: [[org-contact:query][desc]] +(org-link-set-parameters "org-contact" + :follow 'org-contacts-link-open + :complete 'org-contacts-link-complete + :store 'org-contacts-link-store + :face 'org-contacts-link-face) + +(defun org-contacts-link-store () + "Store the contact in `org-contacts-files' with a link." + (when (and (eq major-mode 'org-mode) + (member (buffer-file-name) (mapcar 'expand-file-name org-contacts-files))) + (if (bound-and-true-p org-id-link-to-org-use-id) + (org-id-store-link) + (let ((headline-str (substring-no-properties (org-get-heading t t t t)))) + (org-store-link-props + :type "org-contact" + :link headline-str + :description headline-str) + (setq desc headline-str) + (setq link (concat "org-contact:" headline-str)) + (org-add-link-props :link link :description desc) + link)))) + +(defun org-contacts--all-contacts () + "Return an alist (name . (file . position)) of all contacts in `org-contacts-files'." + (car (mapcar + (lambda (file) + (unless (buffer-live-p (get-buffer (file-name-nondirectory file))) + (find-file file)) + (with-current-buffer (get-buffer (file-name-nondirectory file)) + (org-map-entries + (lambda () + (let ((name (substring-no-properties (org-get-heading t t t t))) + (file (buffer-file-name)) + (position (point))) + `(:name ,name :file ,file :position ,position)))))) + org-contacts-files))) + +(defun org-contacts-link-open (path) + "Open contacts: link type with jumping or searching." + (let ((query path)) + (cond + ;; /query/ format searching + ((string-match "/.*/" query) + (let* ((f (car org-contacts-files)) + (buf (get-buffer (file-name-nondirectory f)))) + (unless (buffer-live-p buf) (find-file f)) + (with-current-buffer buf + (string-match "/\\(.*\\)/" query) + (occur (match-string 1 query))))) + ;; jump to contact headline directly + (t + (let* ((f (car org-contacts-files)) + (buf (get-buffer (file-name-nondirectory f)))) + (unless (buffer-live-p buf) (find-file f)) + (with-current-buffer buf + (goto-char (marker-position (org-find-exact-headline-in-buffer query)))) + (display-buffer buf '(display-buffer-below-selected))) + ;; FIXME + ;; (let* ((contact-entry (plist-get (org-contacts--all-contacts) query)) + ;; (contact-name (plist-get contact-entry :name)) + ;; (file (plist-get contact-entry :file)) + ;; (position (plist-get contact-entry :position)) + ;; (buf (get-buffer (file-name-nondirectory file)))) + ;; (unless (buffer-live-p buf) (find-file file)) + ;; (with-current-buffer buf (goto-char position))) + )))) + +(defun org-contacts-link-complete (&optional arg) + "Create a org-contacts link using completion." + (let ((name (completing-read "org-contact Name: " + (mapcar + (lambda (plist) (plist-get plist :name)) + (org-contacts--all-contacts))))) + (concat "org-contact:" name))) + +(defun org-contacts-link-face (path) + "Different face color for different org-contacts link query." + (cond + ((string-match "/.*/" path) + '(:background "sky blue" :overline t :slant 'italic)) + (t '(:inherit 'org-link)))) + (provide 'org-contacts) ;;; org-contacts.el ends here diff --git a/lisp/org-contrib/org-contrib-pkg.el b/lisp/org-contrib/org-contrib-pkg.el new file mode 100644 index 00000000..64aabcec --- /dev/null +++ b/lisp/org-contrib/org-contrib-pkg.el @@ -0,0 +1,2 @@ +;; Generated package description from org-contrib.el -*- no-byte-compile: t -*- +(define-package "org-contrib" "0.3" "Unmaintained add-ons for Org-mode" '((emacs "25.1") (org "9.4.6")) :authors '(("Bastien Guerry" . "bzg@gnu.org")) :maintainer '("Bastien Guerry" . "bzg@gnu.org") :keywords '("org") :url "https://git.sr.ht/~bzg/org-contrib") diff --git a/lisp/org-contrib/org-contrib.el b/lisp/org-contrib/org-contrib.el new file mode 100644 index 00000000..46d5577c --- /dev/null +++ b/lisp/org-contrib/org-contrib.el @@ -0,0 +1,55 @@ +;;; org-contrib.el --- Unmaintained add-ons for Org-mode + +;; Copyright (C) 2021 Bastien Guerry + +;; Author: Bastien Guerry +;; Homepage: https://git.sr.ht/~bzg/org-contrib +;; Package-Requires: ((emacs "25.1") (org "9.4.6")) +;; Version: 0.3 +;; Keywords: org +;; SPDX-License-Identifier: GPL-3.0-or-later + +;; This file is not part of GNU Emacs. + +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary + +;; This package contains add-ons to Org-mode which are not part of GNU +;; Emacs or of the official Org package. + +;; ** This package receive little if no maintainance. ** + +;; Especially, there is no guaranty that it is compatible with the latest +;; Org stable version. Would you would like to volunteer maintaining it? +;; If so, please send me an email at bzg@gnu.org. + +;; If you want to maintain only one or some of these add-ons please send +;; me an email and consider hosting the add-ons on a separate repository. + +;; These files used to live in the Org repository but have been filtered +;; out of the Org 9.5 release and are stored here for archival purpose. +;; The contrib/ directory used to contain a scripts/ directory that now +;; lives on Worg: . + +;;; Note: + +;; This file, org-contrib.el, provides metadata for the (future) +;; org-contrib GNU ELPA package. + +;;; Code: + +(provide 'org-contrib) + +;;; org-contrib.el ends here diff --git a/lisp/org/contrib/lisp/org-contribdir.el b/lisp/org-contrib/org-contribdir.el similarity index 89% rename from lisp/org/contrib/lisp/org-contribdir.el rename to lisp/org-contrib/org-contribdir.el index 42181af4..cd221584 100644 --- a/lisp/org/contrib/lisp/org-contribdir.el +++ b/lisp/org-contrib/org-contribdir.el @@ -1,12 +1,12 @@ ;;; org-contribdir.el --- Mark the location of the contrib directory -;; Copyright (C) 2009-2020 Free Software Foundation, Inc. +;; Copyright (C) 2009-2021 Free Software Foundation, Inc. ;; -;; Author: Carsten Dominik +;; Author: Carsten Dominik ;; Keywords: outlines, hypermedia, calendar, wp ;; Homepage: https://orgmode.org ;; Version: 0.01 ;; -;; This file is not yet part of GNU Emacs. +;; This file is not part of GNU Emacs. ;; ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by diff --git a/lisp/org/contrib/lisp/org-depend.el b/lisp/org-contrib/org-depend.el similarity index 98% rename from lisp/org/contrib/lisp/org-depend.el rename to lisp/org-contrib/org-depend.el index 263cd717..8306184b 100644 --- a/lisp/org/contrib/lisp/org-depend.el +++ b/lisp/org-contrib/org-depend.el @@ -1,7 +1,7 @@ ;;; org-depend.el --- TODO dependencies for Org-mode -;; Copyright (C) 2008-2020 Free Software Foundation, Inc. +;; Copyright (C) 2008-2021 Free Software Foundation, Inc. ;; -;; Author: Carsten Dominik +;; Author: Carsten Dominik ;; Keywords: outlines, hypermedia, calendar, wp ;; Homepage: https://orgmode.org ;; Version: 0.08 @@ -19,7 +19,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;;; Commentary: diff --git a/lisp/org/contrib/lisp/org-effectiveness.el b/lisp/org-contrib/org-effectiveness.el similarity index 98% rename from lisp/org/contrib/lisp/org-effectiveness.el rename to lisp/org-contrib/org-effectiveness.el index 03158e2b..dad56c77 100644 --- a/lisp/org/contrib/lisp/org-effectiveness.el +++ b/lisp/org-contrib/org-effectiveness.el @@ -1,12 +1,12 @@ ;;; org-effectiveness.el --- Measuring the personal effectiveness -;; Copyright (C) 2013-2020 Free Software Foundation, Inc. +;; Copyright (C) 2013-2021 Free Software Foundation, Inc. ;; Author: David Arroyo Menéndez ;; Keywords: effectiveness, plot ;; Homepage: https://orgmode.org ;; -;; This file is not part of GNU Emacs, yet. +;; This file is not part of GNU Emacs. ;; ;; GNU Emacs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -19,7 +19,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;;; Commentary: diff --git a/lisp/org/contrib/lisp/org-eldoc.el b/lisp/org-contrib/org-eldoc.el similarity index 94% rename from lisp/org/contrib/lisp/org-eldoc.el rename to lisp/org-contrib/org-eldoc.el index 946a5727..e662b504 100644 --- a/lisp/org/contrib/lisp/org-eldoc.el +++ b/lisp/org-contrib/org-eldoc.el @@ -1,12 +1,12 @@ ;;; org-eldoc.el --- display org header and src block info using eldoc -*- lexical-binding: t; -*- -;; Copyright (c) 2014-2020 Free Software Foundation, Inc. +;; Copyright (c) 2014-2021 Free Software Foundation, Inc. ;; Author: Łukasz Gruner ;; Maintainer: Łukasz Gruner ;; Version: 6 ;; Package-Requires: ((org "8")) -;; URL: https://bitbucket.org/ukaszg/org-eldoc +;; Homepage: https://bitbucket.org/ukaszg/org-eldoc ;; Created: 25/05/2014 ;; Keywords: eldoc, outline, breadcrumb, org, babel, minibuffer @@ -23,7 +23,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;;; Commentary: @@ -144,7 +144,9 @@ (cond ((or (string= lang "emacs-lisp") (string= lang "elisp")) - (cond ((boundp 'eldoc-documentation-functions) ; Emacs>=28 + (cond ((and (boundp 'eldoc-documentation-functions) ; Emacs>=28 + (fboundp 'elisp-eldoc-var-docstring) + (fboundp 'elisp-eldoc-funcall)) (let ((eldoc-documentation-functions '(elisp-eldoc-var-docstring elisp-eldoc-funcall))) (eldoc-print-current-symbol-info))) @@ -154,7 +156,7 @@ (let (eldoc-documentation-function) (eldoc-print-current-symbol-info))))) ((or - (string= lang "c") ;; http://github.com/nflath/c-eldoc + (string= lang "c") ;; https://github.com/nflath/c-eldoc (string= lang "C")) (when (require 'c-eldoc nil t) (c-eldoc-print-current-symbol-info))) ;; https://github.com/zenozeng/css-eldoc diff --git a/lisp/org/contrib/lisp/org-eval-light.el b/lisp/org-contrib/org-eval-light.el similarity index 96% rename from lisp/org/contrib/lisp/org-eval-light.el rename to lisp/org-contrib/org-eval-light.el index 31016534..7f135571 100644 --- a/lisp/org/contrib/lisp/org-eval-light.el +++ b/lisp/org-contrib/org-eval-light.el @@ -1,15 +1,15 @@ ;;; org-eval-light.el --- Display result of evaluating code in various languages (light) -;; Copyright (C) 2008-2020 Free Software Foundation, Inc. +;; Copyright (C) 2008-2021 Free Software Foundation, Inc. -;; Author: Carsten Dominik , +;; Author: Carsten Dominik , ;; Eric Schulte ;; Keywords: outlines, hypermedia, calendar, wp, literate programming, ;; reproducible research ;; Homepage: https://orgmode.org ;; Version: 0.04 -;; This file is not yet part of GNU Emacs. +;; This file is not part of GNU Emacs. ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -22,7 +22,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;;; Commentary: diff --git a/lisp/org/contrib/lisp/org-eval.el b/lisp/org-contrib/org-eval.el similarity index 96% rename from lisp/org/contrib/lisp/org-eval.el rename to lisp/org-contrib/org-eval.el index 79553c55..f11443ce 100644 --- a/lisp/org/contrib/lisp/org-eval.el +++ b/lisp/org-contrib/org-eval.el @@ -1,12 +1,12 @@ ;;; org-eval.el --- Display result of evaluating code in various languages -;; Copyright (C) 2008-2020 Free Software Foundation, Inc. +;; Copyright (C) 2008-2021 Free Software Foundation, Inc. ;; -;; Author: Carsten Dominik +;; Author: Carsten Dominik ;; Keywords: outlines, hypermedia, calendar, wp ;; Homepage: https://orgmode.org ;; Version: 0.04 ;; -;; This file is not yet part of GNU Emacs. +;; This file is not part of GNU Emacs. ;; ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -19,7 +19,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;;; Commentary: diff --git a/lisp/org/contrib/lisp/org-expiry.el b/lisp/org-contrib/org-expiry.el similarity index 98% rename from lisp/org/contrib/lisp/org-expiry.el rename to lisp/org-contrib/org-expiry.el index c2aca623..98ad58a3 100644 --- a/lisp/org/contrib/lisp/org-expiry.el +++ b/lisp/org-contrib/org-expiry.el @@ -1,10 +1,11 @@ ;;; org-expiry.el --- expiry mechanism for Org entries ;; -;; Copyright 2007-2020 Free Software Foundation, Inc. +;; Copyright 2007-2021 Free Software Foundation, Inc. ;; -;; Author: Bastien Guerry +;; Author: Bastien Guerry ;; Version: 0.2 -;; Keywords: org expiry +;; Keywords: org, expiry +;; Homepage: https://git.sr.ht/~bzg/org-contrib ;; This file is not part of GNU Emacs. @@ -19,7 +20,7 @@ ;; GNU General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;; ;;; Commentary: ;; diff --git a/lisp/org/contrib/lisp/org-interactive-query.el b/lisp/org-contrib/org-interactive-query.el similarity index 97% rename from lisp/org/contrib/lisp/org-interactive-query.el rename to lisp/org-contrib/org-interactive-query.el index 0a5388b2..d23583b6 100644 --- a/lisp/org/contrib/lisp/org-interactive-query.el +++ b/lisp/org-contrib/org-interactive-query.el @@ -1,6 +1,6 @@ ;;; org-interactive-query.el --- Interactive modification of agenda query ;; -;; Copyright 2007-2020 Free Software Foundation, Inc. +;; Copyright 2007-2021 Free Software Foundation, Inc. ;; ;; Author: Christopher League ;; Version: 1.0 @@ -19,10 +19,13 @@ ;; GNU General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;; ;;; Commentary: ;; +;; This file is DEPRECATED. The functionality here has been mostly subsumed by +;; features added to Org agenda, especially commands that begin with +;; org-agenda-filter*. ;; This library implements interactive modification of a tags/todo query ;; in the org-agenda. It adds 4 keys to the agenda diff --git a/lisp/org/contrib/lisp/org-invoice.el b/lisp/org-contrib/org-invoice.el similarity index 92% rename from lisp/org/contrib/lisp/org-invoice.el rename to lisp/org-contrib/org-invoice.el index 68688941..6daa156b 100644 --- a/lisp/org/contrib/lisp/org-invoice.el +++ b/lisp/org-contrib/org-invoice.el @@ -1,28 +1,22 @@ ;;; org-invoice.el --- Help manage client invoices in OrgMode ;; -;; Copyright (C) 2008-2014 pmade inc. (Peter Jones pjones@pmade.com) +;; Copyright (C) 2008-2014, 2021 pmade inc. (Peter Jones pjones@pmade.com) ;; ;; This file is not part of GNU Emacs. -;; -;; Permission is hereby granted, free of charge, to any person obtaining -;; a copy of this software and associated documentation files (the -;; "Software"), to deal in the Software without restriction, including -;; without limitation the rights to use, copy, modify, merge, publish, -;; distribute, sublicense, and/or sell copies of the Software, and to -;; permit persons to whom the Software is furnished to do so, subject to -;; the following conditions: -;; -;; The above copyright notice and this permission notice shall be -;; included in all copies or substantial portions of the Software. -;; -;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -;; LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -;; OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -;; WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -;; + +;; 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 GNU Emacs. If not, see . + ;;; Commentary: ;; ;; Building on top of the terrific OrgMode, org-invoice tries to diff --git a/lisp/org/contrib/lisp/org-learn.el b/lisp/org-contrib/org-learn.el similarity index 95% rename from lisp/org/contrib/lisp/org-learn.el rename to lisp/org-contrib/org-learn.el index dfce196b..897216dc 100644 --- a/lisp/org/contrib/lisp/org-learn.el +++ b/lisp/org-contrib/org-learn.el @@ -1,6 +1,6 @@ ;;; org-learn.el --- Implements SuperMemo's incremental learning algorithm -;; Copyright (C) 2009-2020 Free Software Foundation, Inc. +;; Copyright (C) 2009-2021 Free Software Foundation, Inc. ;; Author: John Wiegley ;; Keywords: outlines, hypermedia, calendar, wp @@ -20,15 +20,15 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;;; Commentary: ;; The file implements the learning algorithm described at -;; http://supermemo.com/english/ol/sm5.htm, which is a system for reading +;; https://supermemo.com/english/ol/sm5.htm, which is a system for reading ;; material according to "spaced repetition". See -;; http://en.wikipedia.org/wiki/Spaced_repetition for more details. +;; https://en.wikipedia.org/wiki/Spaced_repetition for more details. ;; ;; To use, turn on state logging and schedule some piece of information you ;; want to read. Then in the agenda buffer type diff --git a/lisp/org/contrib/lisp/org-license.el b/lisp/org-contrib/org-license.el similarity index 74% rename from lisp/org/contrib/lisp/org-license.el rename to lisp/org-contrib/org-license.el index d39ab6c4..0c3ed6d0 100644 --- a/lisp/org/contrib/lisp/org-license.el +++ b/lisp/org-contrib/org-license.el @@ -1,12 +1,12 @@ ;;; org-license.el --- Add a license to your org files -;; Copyright (C) 2013-2020 Free Software Foundation, Inc. +;; Copyright (C) 2013-2021 Free Software Foundation, Inc. ;; Author: David Arroyo Menéndez ;; Keywords: licenses, creative commons ;; Homepage: https://orgmode.org ;; -;; This file is not part of GNU Emacs, yet. +;; This file is not part of GNU Emacs. ;; ;; GNU Emacs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -19,7 +19,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;;; Commentary: @@ -57,51 +57,51 @@ El text està disponible sota la [[" org-license-cc-url "][Reconeixement 3.0 Esp (insert (concat "* Lizenz Dieses Werk bzw. Inhalt steht unter einer [[" org-license-cc-url "][Lizenz Creative Commons Namensnennung 3.0 Deutschland]]\n"))) ((equal language "eo") - (setq org-license-cc-url "http://creativecommons.org/licenses/by/3.0/eo/deed.eo") + (setq org-license-cc-url "https://creativecommons.org/licenses/by/3.0/eo/deed.eo") (insert (concat "* Licenco Ĉi tiu verko estas disponebla laŭ la permesilo [[" org-license-cc-url "][Krea Komunaĵo Atribuite 3.0 Neadaptita]]\n"))) ((equal language "es") - (setq org-license-cc-url "http://creativecommons.org/licenses/by/3.0/es/deed.es") + (setq org-license-cc-url "https://creativecommons.org/licenses/by/3.0/es/deed.es") (insert (concat "* Licencia Este documento está bajo una [[" org-license-cc-url "][Licencia Creative Commons Atribución 3.0 España]]\n"))) ((equal language "eu") - (setq org-license-cc-url "http://creativecommons.org/licenses/by/3.0/es/deed.eu") + (setq org-license-cc-url "https://creativecommons.org/licenses/by/3.0/es/deed.eu") (insert (concat "* Licenzua Testua [[" org-license-cc-url "][Aitortu 3.0 Espainia]] lizentziari jarraituz erabil daiteke\n"))) ((equal language "fi") - (setq org-license-cc-url "http://creativecommons.org/licenses/by/1.0/fi/deed.fi") + (setq org-license-cc-url "https://creativecommons.org/licenses/by/1.0/fi/deed.fi") (insert (concat "* Lisenssi Teksti on saatavilla [[" org-license-cc-url "][Nimeä 1.0 Suomi]] lisenssillä\n"))) ((equal language "fr") - (setq org-license-cc-url "http://creativecommons.org/licenses/by/3.0/fr/deed.fr") + (setq org-license-cc-url "https://creativecommons.org/licenses/by/3.0/fr/deed.fr") (insert (concat "* Licence Ce(tte) œuvre est mise à disposition selon les termes de la [[" org-license-cc-url "][Licence Creative Commons Attribution 3.0 France]]\n"))) ((equal language "gl") - (setq org-license-cc-url "http://creativecommons.org/licenses/by/3.0/es/deed.gl") + (setq org-license-cc-url "https://creativecommons.org/licenses/by/3.0/es/deed.gl") (insert (concat "* Licenza Todo o texto está dispoñible baixo a [[" org-license-cc-url "][licenza Creative Commons recoñecemento compartir igual 3.0]].\n"))) ((equal language "it") - (setq org-license-cc-url "http://creativecommons.org/licenses/by/3.0/it/deed.it") + (setq org-license-cc-url "https://creativecommons.org/licenses/by/3.0/it/deed.it") (insert (concat "* Licenza Quest'opera e distribuita con Licenza [[" org-license-cc-url "][Licenza Creative Commons Attribuzione 3.0 Italia]]\n"))) ((equal language "jp") - (setq org-license-cc-url "http://creativecommons.org/licenses/by/2.1/jp/deed.en") + (setq org-license-cc-url "https://creativecommons.org/licenses/by/2.1/jp/deed.en") (insert (concat "* ライセンス この文書は [[" org-license-cc-url "][Creative Commons Attribution 2.1 ]] ライセンスの下である\n"))) ((equal language "nl") - (setq org-license-cc-url "http://creativecommons.org/licenses/by/3.0/nl/deed.nl") + (setq org-license-cc-url "https://creativecommons.org/licenses/by/3.0/nl/deed.nl") (insert (concat "* Licentie Dit werk is valt onder een [[" org-license-cc-url "][Creative Commons Naamsvermelding 3.0 Nederland]]\n"))) ((equal language "pt") - (setq org-license-cc-url "http://creativecommons.org/licenses/by/3.0/pt/deed.pt") + (setq org-license-cc-url "https://creativecommons.org/licenses/by/3.0/pt/deed.pt") (insert (concat "* Licença Este texto é disponibilizado nos termos da licença [[" org-license-cc-url "][Atribuição 3.0 Portugal]]\n"))) (t - (setq org-license-cc-url "http://creativecommons.org/licenses/by/4.0/deed") + (setq org-license-cc-url "https://creativecommons.org/licenses/by/4.0/deed") (concat (insert "* License This document is under a [[" org-license-cc-url "][Creative Commons Attribution 4.0 International]]\n")))) (if (string= "" org-license-images-directory) - (insert (concat "\n[[" org-license-cc-url "][file:http://i.creativecommons.org/l/by/3.0/80x15.png]]\n")) + (insert (concat "\n[[" org-license-cc-url "][file:https://i.creativecommons.org/l/by/3.0/80x15.png]]\n")) (insert (concat "\n[[" org-license-cc-url "][file:" org-license-images-directory "/by/3.0/80x15.png]]\n")))) (defun org-license-cc-by-sa (language) @@ -111,55 +111,55 @@ This document is under a [[" org-license-cc-url "][Creative Commons Attribution (concat (insert "* Licença Este texto é disponibilizado nos termos da licença [[" org-license-cc-url "][Atribuição Compartil ha Igual 3.0 Brasil]]\n"))) ((equal language "ca") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-sa/3.0/es/deed.ca") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-sa/3.0/es/deed.ca") (insert (concat "* Licència El text està disponible sota la [[" org-license-cc-url "][Reconeixement-CompartirIgual 3.0 Espanya]]\n"))) ((equal language "de") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-sa/3.0/de/deed.de") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-sa/3.0/de/deed.de") (insert (concat "* Lizenz Dieses Werk bzw. Inhalt steht unter einer [[" org-license-cc-url "][Namensnennung - Weitergabe unter gleichen Bedingungen 3.0 Deutschland]]\n"))) ((equal language "es") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-sa/3.0/es/deed.es") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-sa/3.0/es/deed.es") (concat (insert "* Licencia Este documento está bajo una [[" org-license-cc-url "][Licencia Creative Commons Atribución Compartir por Igual 3.0 España]]\n"))) ((equal language "eu") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-sa/3.0/es/deed.eu") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-sa/3.0/es/deed.eu") (concat (insert "* Licenzua Testua [[" org-license-cc-url "][Aitortu-PartekatuBerdin 3.0 Espainia]] lizentziari jarraituz erabil daiteke\n"))) ((equal language "fi") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-sa/1.0/fi/deed.fi") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-sa/1.0/fi/deed.fi") (insert (concat "* Lisenssi Teksti on saatavilla [[" org-license-cc-url "][Nimeä-JaaSamoin 1.0 Suomi]] lisenssillä\n"))) ((equal language "fr") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-sa/3.0/fr/deed.fr") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-sa/3.0/fr/deed.fr") (concat (insert "* Licence Ce(tte) œuvre est mise à disposition selon les termes de la [[" org-license-cc-url "][Licence Creative Commons Attribution - Partage dans les Mêmes Conditions 3.0 France]]\n"))) ((equal language "gl") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-sa/3.0/es/deed.gl") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-sa/3.0/es/deed.gl") (insert (concat "* Licenza Todo o texto está dispoñible baixo a [[" org-license-cc-url "][licenza Creative Commons recoñecemento compartir igual 3.0]].\n"))) ((equal language "it") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-sa/3.0/it/deed.it") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-sa/3.0/it/deed.it") (insert (concat "* Licenza Quest'opera e distribuita con Licenza [[" org-license-cc-url "][Licenza Creative Commons Attribuzione - Condividi allo stesso modo 3.0 Italia]]\n"))) ((equal language "jp") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-sa/2.1/jp/deed.en") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-sa/2.1/jp/deed.en") (insert (concat "* ライセンス この文書は、[[" org-license-cc-url "][Creative Commons Attribution 2.1 ]] ライセンスの下である\n"))) ((equal language "nl") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-sa/3.0/nl/deed.nl") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-sa/3.0/nl/deed.nl") (insert (concat "* Licentie Dit werk is valt onder een [[" org-license-cc-url "][Creative Commons Naamsvermelding Gelijk Delen 3.0 Nederland]]\n"))) ((equal language "pt") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-sa/3.0/pt/deed.pt") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-sa/3.0/pt/deed.pt") (insert (concat "* Licença Este texto é disponibilizado nos termos da licença [[" org-license-cc-url "][Atribuição-CompartilhaIgual 3.0 Portugal]]\n"))) (t - (setq org-license-cc-url "http://creativecommons.org/licenses/by-sa/4.0/deed") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-sa/4.0/deed") (insert (concat "* License This document is under a [[" org-license-cc-url "][Creative Commons Attribution-ShareAlike 4.0 International]]\n")))) (if (string= "" org-license-images-directory) - (insert (concat "\n[[" org-license-cc-url "][file:http://i.creativecommons.org/l/by-sa/3.0/80x15.png]]\n")) + (insert (concat "\n[[" org-license-cc-url "][file:https://i.creativecommons.org/l/by-sa/3.0/80x15.png]]\n")) (insert (concat "\n[[" org-license-cc-url "][file:" org-license-images-directory "/by-sa/3.0/80x15.png]]\n")))) (defun org-license-cc-by-nd (language) @@ -169,55 +169,55 @@ This document is under a [[" org-license-cc-url "][Creative Commons Attribution- (insert (concat "* Licença Este texto é disponibilizado nos termos da licença [[" org-license-cc-url "][Atribuição Compartil ha Igual 3.0 Brasil]]\n"))) ((equal language "ca") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nd/3.0/es/deed.ca") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nd/3.0/es/deed.ca") (insert (concat "* Licència El text està disponible sota la [[" org-license-cc-url "][Reconeixement-SenseObraDerivada 3.0 Espanya]]\n"))) ((equal language "de") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nd/3.0/de/deed.de") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nd/3.0/de/deed.de") (insert (concat "* Lizenz Dieses Werk bzw. Inhalt steht unter einer [[" org-license-cc-url "][Namensnennung-Keine Bearbeitung 3.0 Deutschland]]\n"))) ((equal language "es") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nd/3.0/es/deed.es") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nd/3.0/es/deed.es") (insert (concat "* Licencia Este documento está bajo una [[" org-license-cc-url "][Licencia Creative Commons Atribución-SinDerivadas 3.0]]\n"))) ((equal language "eu") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nd/3.0/es/deed.eu") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nd/3.0/es/deed.eu") (insert (concat "* Licenzua Testua [[" org-license-cc-url "][Aitortu-LanEratorririkGabe 3.0 Espainia]] lizentziari jarraituz erabil daiteke\n"))) ((equal language "fi") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nd/1.0/fi/deed.fi") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nd/1.0/fi/deed.fi") (insert (concat "* Lisenssi Teksti on saatavilla [[" org-license-cc-url "][Nimeä-JaaSamoin 1.0 Suomi]] lisenssillä\n"))) ((equal language "fr") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nd/3.0/fr/deed.fr") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nd/3.0/fr/deed.fr") (insert (concat "* Licence Ce(tte) œuvre est mise à disposition selon les termes de la [[" org-license-cc-url "][Licence Creative Commons Attribution - Pas de Modification 3.0 France]]\n"))) ((equal language "gl") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nd/3.0/es/deed.gl") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nd/3.0/es/deed.gl") (insert (concat "* Licenza Todo o texto está dispoñible baixo a [[" org-license-cc-url "][licenza Creative Commons recoñecemento compartir igual 3.0]].\n"))) ((equal language "it") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nd/3.0/it/deed.it") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nd/3.0/it/deed.it") (insert (concat "* Licenza Quest'opera e distribuita con Licenza [[" org-license-cc-url "][Licenza Creative Commons Attribuzione - Non opere derivate 3.0 Italia]]\n"))) ((equal language "jp") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nd/2.1/jp/deed.en") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nd/2.1/jp/deed.en") (insert (concat "* ライセンス この文書は、[[" org-license-cc-url "][Creative Commons No Derivatives 2.1]] ライセンスの下である\n"))) ((equal language "nl") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nd/3.0/nl/deed.nl") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nd/3.0/nl/deed.nl") (insert (concat "* Licentie Dit werk is valt onder een [[" org-license-cc-url "][Creative Commons Naamsvermelding GeenAfgeleideWerken 3.0 Nederland]]\n"))) ((equal language "pt") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nd/3.0/pt/deed.pt") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nd/3.0/pt/deed.pt") (insert (concat "* Licença Este texto é disponibilizado nos termos da licença [[" org-license-cc-url "][Atribuição Sem Derivados 3.0 Portugal]]\n"))) (t - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nd/4.0/deed") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nd/4.0/deed") (insert (concat "* License This document is under a [[" org-license-cc-url "][Creative Commons No Derivatives 4.0 International]]\n")))) (if (string= "" org-license-images-directory) - (insert (concat "\n[[" org-license-cc-url "][file:http://i.creativecommons.org/l/by-nd/3.0/80x15.png]]\n")) + (insert (concat "\n[[" org-license-cc-url "][file:https://i.creativecommons.org/l/by-nd/3.0/80x15.png]]\n")) (insert (concat "\n[[" org-license-cc-url "][file:" org-license-images-directory "/by-nd/3.0/80x15.png]]\n")))) @@ -228,55 +228,55 @@ This document is under a [[" org-license-cc-url "][Creative Commons No Derivativ (insert (concat "* Licença Este texto é disponibilizado nos termos da licença [[" org-license-cc-url "][Atribuição Não Comercial 3.0 Brasil]]\n"))) ((equal language "ca") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc/3.0/es/deed.ca") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc/3.0/es/deed.ca") (insert (concat "* Licència El text està disponible sota la [[" org-license-cc-url "][Reconeixement-NoComercial 3.0 Espanya]]\n"))) ((equal language "de") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc/3.0/de/deed.de") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc/3.0/de/deed.de") (insert (concat "* Lizenz Dieses Werk bzw. Inhalt steht unter einer [[" org-license-cc-url "][Namensnennung-Nicht-kommerziell 3.0 Deutschland]]\n"))) ((equal language "es") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc/3.0/es/deed.es") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc/3.0/es/deed.es") (insert (concat "* Licencia Este documento está bajo una [[" org-license-cc-url "][Licencia Creative Commons Reconocimiento-NoComercial 3.0]]\n"))) ((equal language "eu") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc/3.0/es/deed.eu") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc/3.0/es/deed.eu") (insert "* Licenzua Testua [[" org-license-cc-url "][Aitortu-EzKomertziala 3.0 Espainia]] lizentziari jarraituz erabil daiteke\n")) ((equal language "fi") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc/1.0/fi/deed.fi") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc/1.0/fi/deed.fi") (insert (concat "* Lisenssi Teksti on saatavilla [[" org-license-cc-url "][Nimeä-Epäkaupallinen 1.0 Suomi]] lisenssillä\n"))) ((equal language "fr") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc/3.0/fr/deed.fr") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc/3.0/fr/deed.fr") (insert (concat "* Licence Ce(tte) œuvre est mise à disposition selon les termes de la [[" org-license-cc-url "][Licence Creative Commons Attribution - Pas d'Utilisation Commerciale 3.0 France]]\n"))) ((equal language "gl") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc/3.0/es/deed.gl") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc/3.0/es/deed.gl") (insert (concat "* Licenza Todo o texto está dispoñible baixo a [[" org-license-cc-url "][licenza Creative Commons recoñecemento compartir igual 3.0]].\n"))) ((equal language "it") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc/3.0/it/deed.it") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc/3.0/it/deed.it") (insert (concat "* Licenza Quest'opera e distribuita con Licenza [[" org-license-cc-url "][Licenza Creative Commons Attribuzione - Non commerciale 3.0 Italia]]\n"))) ((equal language "jp") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc/2.1/jp/deed.en") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc/2.1/jp/deed.en") (insert (concat "* ライセンス この文書は、[[" org-license-cc-url "][Creative Commons Attribution-NonCommercial 2.1 ]] ライセンスの下である\n"))) ((equal language "nl") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc/3.0/nl/deed.nl") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc/3.0/nl/deed.nl") (insert (concat "* Licentie Dit werk is valt onder een [[" org-license-cc-url "][Creative Commons Naamsvermelding NietCommercieel 3.0 Nederland 3.0 Nederland]]\n"))) ((equal language "pt") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc/3.0/pt/deed.pt") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc/3.0/pt/deed.pt") (insert (concat "* Licença Este texto é disponibilizado nos termos da licença [[" org-license-cc-url "][Atribuição Não Comercial 3.0 Portugal]]\n"))) (t - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc/4.0/deed") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc/4.0/deed") (insert (concat "* License This document is under a [[" org-license-cc-url "][Creative Commons Attribution-NonCommercial 4.0 International]]\n")))) (if (string= "" org-license-images-directory) - (insert (concat "\n[[" org-license-cc-url "][file:http://i.creativecommons.org/l/by-nc/3.0/80x15.png]]\n")) + (insert (concat "\n[[" org-license-cc-url "][file:https://i.creativecommons.org/l/by-nc/3.0/80x15.png]]\n")) (insert (concat "\n[[" org-license-cc-url "][file:" org-license-images-directory "/by-nc/3.0/80x15.png]]\n")))) (defun org-license-cc-by-nc-sa (language) @@ -286,113 +286,113 @@ This document is under a [[" org-license-cc-url "][Creative Commons Attribution- (insert (concat "* Licença Este texto é disponibilizado nos termos da licença [[" org-license-cc-url "][Atribuição Não Comercial - Compartil ha Igual 3.0 Brasil]]\n"))) ((equal language "ca") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-sa/3.0/es/deed.ca") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc-sa/3.0/es/deed.ca") (insert (concat "* Licència El text està disponible sota la [[" org-license-cc-url "][Reconeixement-NoComercial 3.0 Espanya]]\n"))) ((equal language "de") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-sa/3.0/de/deed.de") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc-sa/3.0/de/deed.de") (insert (concat "* Lizenz Dieses Werk bzw. Inhalt steht unter einer [[" org-license-cc-url "][Namensnennung - Weitergabe unter gleichen Bedingungen 3.0 Deutschland]]\n"))) ((equal language "es") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-sa/3.0/es/deed.es") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc-sa/3.0/es/deed.es") (insert (concat "* Licencia Este documento está bajo una [[" org-license-cc-url "][Licencia Creative Commons Reconocimiento-NoComercial 3.0]]\n"))) ((equal language "eu") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-sa/3.0/es/deed.eu") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc-sa/3.0/es/deed.eu") (insert "* Licenzua Testua [[" org-license-cc-url "][Aitortu-EzKomertziala-PartekatuBerdin 3.0 Espainia]] lizentziari jarraituz erabil daiteke\n")) ((equal language "fi") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-sa/1.0/fi/deed.fi") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc-sa/1.0/fi/deed.fi") (insert (concat "* Lisenssi Teksti on saatavilla [[" org-license-cc-url "][Nimeä-Epäkaupallinen-JaaSamoin 1.0 Suomi]] lisenssillä\n"))) ((equal language "fr") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-sa/3.0/fr/deed.fr") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc-sa/3.0/fr/deed.fr") (insert (concat "* Licence Ce(tte) œuvre est mise à disposition selon les termes de la [[" org-license-cc-url "][Licence Creative Commons Attribution - Pas d’Utilisation Commerciale - Partage dans les Mêmes Conditions 3.0 France]]\n"))) ((equal language "gl") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-sa/3.0/es/deed.gl") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc-sa/3.0/es/deed.gl") (insert (concat "* Licenza Todo o texto está dispoñible baixo a [[" org-license-cc-url "][licenza Creative Commons recoñecemento compartir igual 3.0]].\n"))) ((equal language "it") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-sa/3.0/it/deed.it") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc-sa/3.0/it/deed.it") (insert (concat "* Licenza Quest'opera e distribuita con Licenza [[" org-license-cc-url "][Licenza Creative Commons Attribuzione - Non opere derivate 3.0 Italia]]\n"))) ((equal language "jp") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-sa/2.1/jp/deed.en") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc-sa/2.1/jp/deed.en") (insert (concat "* ライセンス この文書は、[[" org-license-cc-url "][License Creative Commons Attribution Non Commercial Share Alike 2.1 ]] ライセンスの下である\n"))) ((equal language "nl") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-sa/3.0/nl/deed.nl") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc-sa/3.0/nl/deed.nl") (insert (concat "* Licentie Dit werk is valt onder een [[" org-license-cc-url "][Creative Commons Naamsvermelding NietCommercieel GelijkDelen 3.0 Nederland]]\n"))) ((equal language "pt") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc/3.0/pt/deed.pt") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc/3.0/pt/deed.pt") (insert (concat "* Licença Este texto é disponibilizado nos termos da licença [[" org-license-cc-url "][Atribuição NãoComercial Compartil ha Igual 3.0 Portugal]]\n"))) (t - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-sa/4.0/deed") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc-sa/4.0/deed") (insert (concat "* License This document is under a [[" org-license-cc-url "][License Creative Commons Attribution Non Commercial Share Alike 4.0 International]]\n")))) (if (string= "" org-license-images-directory) - (insert (concat "\n[[" org-license-cc-url "][file:http://i.creativecommons.org/l/by-nc-sa/3.0/80x15.png]]\n")) + (insert (concat "\n[[" org-license-cc-url "][file:https://i.creativecommons.org/l/by-nc-sa/3.0/80x15.png]]\n")) (insert (concat "\n[[" org-license-cc-url "][file:" org-license-images-directory "/by-nc-sa/3.0/80x15.png]]\n")))) (defun org-license-cc-by-nc-nd (language) (interactive "MLanguage ( br | ca | de | en | es | eu | fi | fr | gl | it | pt ): " language) (cond ((equal language "br") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-nd/3.0/pt/deed.pt") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc-nd/3.0/pt/deed.pt") (insert (concat "* Licença Este texto é disponibilizado nos termos da licença [[" org-license-cc-url "][Atribuição Não Comercial Sem Derivados 3.0 Brasil]]\n"))) ((equal language "ca") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-nd/3.0/es/deed.ca") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc-nd/3.0/es/deed.ca") (insert (concat "* Licència El text està disponible sota la [[" org-license-cc-url "][Reconeixement-NoComercial-SenseObraDerivada 3.0 Espanya]]\n"))) ((equal language "de") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-nd/3.0/de/deed.de") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc-nd/3.0/de/deed.de") (insert (concat "* Lizenz Dieses Werk bzw. Inhalt steht unter einer [[" org-license-cc-url "][Namensnennung-NichtKommerziell-KeineBearbeitung 3.0 Deutschland]]\n"))) ((equal language "es") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-nd/3.0/es/deed.es") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc-nd/3.0/es/deed.es") (insert (concat "* Licencia Este documento está bajo una [[" org-license-cc-url "][Licencia Creative Commons Reconocimiento-NoComercial-SinObraDerivada 3.0]]\n"))) ((equal language "eu") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-nd/3.0/es/deed.eu") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc-nd/3.0/es/deed.eu") (insert (concat "* Licenzua Testua [[" org-license-cc-url "][Aitortu-LanEratorririkGabe 3.0 Espainia]] lizentziari jarraituz erabil daiteke\n"))) ((equal language "fi") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-nd/1.0/fi/deed.fi") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc-nd/1.0/fi/deed.fi") (insert (concat "* Lisenssi Teksti on saatavilla [[" org-license-cc-url "][Nimeä-Ei muutoksia-Epäkaupallinen 1.0 Suomi]] lisenssillä\n"))) ((equal language "fr") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-nd/3.0/fr/deed.fr") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc-nd/3.0/fr/deed.fr") (insert (concat "* Licence Ce(tte) œuvre est mise à disposition selon les termes de la [[" org-license-cc-url "][Licence Creative Commons Attribution - Pas de Modification 3.0 France]]\n"))) ((equal language "gl") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-nd/3.0/es/deed.gl") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc-nd/3.0/es/deed.gl") (insert (concat "* Licenza Todo o texto está dispoñible baixo a [[" org-license-cc-url "][licenza Creative Commons recoñecemento compartir igual 3.0]].\n"))) ((equal language "it") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-nd/3.0/it/deed.it") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc-nd/3.0/it/deed.it") (insert (concat "* Licenza Quest'opera e distribuita con Licenza [[" org-license-cc-url "][Licenza Creative Commons Attribuzione - Non opere derivate 3.0 Italia]]\n"))) ((equal language "jp") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-nd/2.1/jp/deed.en") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc-nd/2.1/jp/deed.en") (insert (concat "* ライセンス この文書は [[" org-license-cc-url "][License Creative Commons Attribution Non Commercial - No Derivs 2.1]] ライセンスの下である\n"))) ((equal language "nl") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-nd/3.0/nl/deed.nl") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc-nd/3.0/nl/deed.nl") (insert (concat "* Licentie Dit werk is valt onder een [[" org-license-cc-url "][Creative Commons Naamsvermelding NietCommercieel GeenAfgeleideWerken 3.0 Nederland]]\n"))) ((equal language "pt") - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-nd/3.0/pt/deed.pt") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc-nd/3.0/pt/deed.pt") (insert (concat "* Licença Este texto é disponibilizado nos termos da licença [[" org-license-cc-url "][Atribuição Não Comercial Sem Derivados 3.0 Portugal]]\n"))) (t - (setq org-license-cc-url "http://creativecommons.org/licenses/by-nc-nd/4.0/deed") + (setq org-license-cc-url "https://creativecommons.org/licenses/by-nc-nd/4.0/deed") (insert (concat "* License This document is under a [[" org-license-cc-url "][License Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International]]\n")))) (if (string= "" org-license-images-directory) - (insert (concat "\n[[" org-license-cc-url "][file:http://i.creativecommons.org/l/by-nc-nd/3.0/80x15.png]]\n")) + (insert (concat "\n[[" org-license-cc-url "][file:https://i.creativecommons.org/l/by-nc-nd/3.0/80x15.png]]\n")) (insert (concat "\n[[" org-license-cc-url "][file:" org-license-images-directory "/by-nc-nd/3.0/80x15.png]]\n")))) (defun org-license-gfdl (language) @@ -418,7 +418,7 @@ Copyright (C) " (format-time-string "%Y") " " user-full-name (defun org-license-publicdomain-zero (language) (interactive "MLanguage ( en | es ): " language) - (setq org-license-pd-url "http://creativecommons.org/publicdomain/zero/1.0/") + (setq org-license-pd-url "https://creativecommons.org/publicdomain/zero/1.0/") (setq org-license-pd-file "zero/1.0/80x15.png") (if (equal language "es") (insert (concat "* Licencia @@ -426,12 +426,12 @@ Este documento está bajo una licencia [[" org-license-pd-url "][Public Domain Z (insert (concat "* License This documento is under a [[" org-license-pd-url "][Public Domain Zero]] license\n"))) (if (string= "" org-license-images-directory) - (insert (concat "\n[[" org-license-pd-url "][file:http://i.creativecommons.org/p/zero/1.0/80x15.png]]\n")) + (insert (concat "\n[[" org-license-pd-url "][file:https://i.creativecommons.org/p/zero/1.0/80x15.png]]\n")) (insert (concat "\n[[" org-license-pd-url "][file:" org-license-images-directory org-license-pd-file "]]\n")))) (defun org-license-publicdomain-mark (language) (interactive "MLanguage ( en | es ): " language) - (setq org-license-pd-url "http://creativecommons.org/publicdomain/mark/1.0/") + (setq org-license-pd-url "https://creativecommons.org/publicdomain/mark/1.0/") (setq org-license-pd-file "mark/1.0/80x15.png") (if (equal language "es") (insert (concat "* Licencia @@ -439,7 +439,7 @@ Este documento está bajo una licencia [[" org-license-pd-url "][Etiqueta de Dom (insert (concat "* License This documento is under a [[" org-license-pd-url "][Public Domain Mark]] license\n"))) (if (string= "" org-license-images-directory) - (insert (concat "\n[[" org-license-pd-url "][file:http://i.creativecommons.org/p/mark/1.0/80x15.png]]\n")) + (insert (concat "\n[[" org-license-pd-url "][file:https://i.creativecommons.org/p/mark/1.0/80x15.png]]\n")) (insert (concat "\n[[" org-license-pd-url "][file:" org-license-images-directory org-license-pd-file "]]\n")))) (defun org-license-print-all () diff --git a/lisp/org/contrib/lisp/org-link-edit.el b/lisp/org-contrib/org-link-edit.el similarity index 99% rename from lisp/org/contrib/lisp/org-link-edit.el rename to lisp/org-contrib/org-link-edit.el index a27a13d0..9369dd78 100644 --- a/lisp/org/contrib/lisp/org-link-edit.el +++ b/lisp/org-contrib/org-link-edit.el @@ -1,9 +1,9 @@ ;;; org-link-edit.el --- Slurp and barf with Org links -*- lexical-binding: t; -*- -;; Copyright (C) 2015-2020 Kyle Meyer +;; Copyright (C) 2015-2021 Kyle Meyer ;; Author: Kyle Meyer -;; URL: https://git.kyleam.com/org-link-edit/about +;; Homepage: https://git.kyleam.com/org-link-edit/about ;; Keywords: convenience ;; Version: 1.2.1 ;; Package-Requires: ((cl-lib "0.5") (org "9.3")) diff --git a/lisp/org/contrib/lisp/org-mac-iCal.el b/lisp/org-contrib/org-mac-iCal.el similarity index 98% rename from lisp/org/contrib/lisp/org-mac-iCal.el rename to lisp/org-contrib/org-mac-iCal.el index 937b6dd7..e3f3d877 100644 --- a/lisp/org/contrib/lisp/org-mac-iCal.el +++ b/lisp/org-contrib/org-mac-iCal.el @@ -1,6 +1,6 @@ ;;; org-mac-iCal.el --- Imports events from iCal.app to the Emacs diary -;; Copyright (C) 2009-2014 Christopher Suckling +;; Copyright (C) 2009-2014, 2021 Christopher Suckling ;; Author: Christopher Suckling ;; Version: 0.1057.104 @@ -19,7 +19,7 @@ ;; for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;;; Commentary: ;; diff --git a/lisp/org/contrib/lisp/org-mac-link.el b/lisp/org-contrib/org-mac-link.el similarity index 92% rename from lisp/org/contrib/lisp/org-mac-link.el rename to lisp/org-contrib/org-mac-link.el index e692acb3..68be8230 100644 --- a/lisp/org/contrib/lisp/org-mac-link.el +++ b/lisp/org-contrib/org-mac-link.el @@ -1,6 +1,6 @@ ;;; org-mac-link.el --- Insert org-mode links to items selected in various Mac apps ;; -;; Copyright (c) 2010-2020 Free Software Foundation, Inc. +;; Copyright (c) 2010-2021 Free Software Foundation, Inc. ;; ;; Author: Anthony Lander ;; John Wiegley @@ -8,7 +8,23 @@ ;; Daniil Frumin ;; Alan Schmitt ;; Mike McLean +;; Maintainer: Aimé Bertrand +;; Homepage: https://gitlab.com/aimebertrand/org-mac-link ;; +;; This file is not part of GNU Emacs. +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, 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 GNU Emacs. If not, see . ;; ;; Version: 1.1 ;; Keywords: org, mac, hyperlink @@ -30,21 +46,6 @@ ;; Author: Mike McLean ;; Add Support for Evernote ;; -;; This file is not part of GNU Emacs. -;; -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 3, 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 GNU Emacs. If not, see . -;; ;;; Commentary: ;; ;; This code allows you to grab either the current selected items, or @@ -207,23 +208,24 @@ :group 'org-mac-flagged-mail :type 'string) -(defcustom org-mac-grab-Evernote-app-p - (< 0 (length (shell-command-to-string - "mdfind kMDItemCFBundleIdentifier == 'com.evernote.Evernote'"))) +(defcustom org-mac-grab-Evernote-app-p nil "Add menu option [e]vernote to grab note links from Evernote.app." :tag "Grab Evernote.app note links" :group 'org-mac-link :type 'boolean) -(defcustom org-mac-evernote-path (replace-regexp-in-string (rx (* (any " \t\n")) eos) - "" - (shell-command-to-string - "mdfind kMDItemCFBundleIdentifier == 'com.evernote.Evernote'")) +(defcustom org-mac-evernote-path nil "The path to the installed copy of Evernote.app. Do not escape spaces as the AppleScript call will quote this string." :tag "Path to Evernote" :group 'org-mac-link :type 'string) +(defcustom org-mac-grab-qutebrowser-app-p t + "Add menu option [q]utebrowser to grab links from qutebrowser.app." + :tag "Grab qutebrowser.app links" + :group 'org-mac-link + :type 'boolean) + ;; In mac.c, removed in Emacs 23. (declare-function do-applescript "org-mac-message" (script)) @@ -260,7 +262,8 @@ When done, go grab the link, and insert it at point." ("e" "evernote" org-mac-evernote-note-insert-selected ,org-mac-grab-Evernote-app-p) ("t" "ogether" org-mac-together-insert-selected ,org-mac-grab-Together-app-p) ("S" "kim" org-mac-skim-insert-page ,org-mac-grab-Skim-app-p) - ("A" "crobat" org-mac-acrobat-insert-page ,org-mac-grab-Acrobat-app-p))) + ("A" "crobat" org-mac-acrobat-insert-page ,org-mac-grab-Acrobat-app-p) + ("q" "utebrowser" org-mac-qutebrowser-insert-frontmost-url ,org-mac-grab-qutebrowser-app-p))) (menu-string (make-string 0 ?x)) input) @@ -809,11 +812,21 @@ after heading." (org-link-set-parameters "mac-evernote" :follow #'org-mac-evernote-note-open) +(defun org-mac-evernote-path () + "Get path to evernote. +First consider the value of ORG-MAC-EVERNOTE-PATH, then attempt to find it. +Finding the path can be slow." + (or org-mac-evernote-path + (replace-regexp-in-string (rx (* (any " \t\n")) eos) + "" + (shell-command-to-string + "mdfind kMDItemCFBundleIdentifier == 'com.evernote.Evernote'")))) + (defun org-mac-evernote-note-open (noteid _) "Open a note in Evernote" (do-applescript (concat - "tell application \"" org-mac-evernote-path "\"\n" + "tell application \"" (org-mac-evernote-path) "\"\n" " set theNotes to get every note of every notebook where its local id is \"" (substring-no-properties noteid) "\"\n" " repeat with _note in theNotes\n" " if length of _note is not 0 then\n" @@ -828,7 +841,7 @@ after heading." "AppleScript to create links to selected notes in Evernote.app." (do-applescript (concat - "tell application \"" org-mac-evernote-path "\"\n" + "tell application \"" (org-mac-evernote-path) "\"\n" " set noteCount to count selection\n" " if (noteCount < 1) then\n" " return\n" @@ -1009,6 +1022,52 @@ list of message:// links to flagged mail after heading." (org-insert-heading nil t) (insert org-heading "\n" (org-mac-message-get-links "f")))))) + +;; Handle links from qutebrowser.app + +(defun org-as-mac-qutebrowser-get-frontmost-url () + (let ((result + (do-applescript + (concat + "set oldClipboard to the clipboard\n" + "set frontmostApplication to path to frontmost application\n" + "tell application \"qutebrowser\"\n" + " activate\n" + " delay 0.15\n" + " tell application \"System Events\"\n" + " keystroke \"y\"\n" + " keystroke \"y\"\n" + " end tell\n" + " delay 0.15\n" + " set theUrl to the clipboard\n" + " set the clipboard to oldClipboard\n" + " delay 0.15\n" + " tell application \"System Events\"\n" + " keystroke \"y\"\n" + " keystroke \"T\"\n" + " end tell\n" + " delay 0.15\n" + " set theTitle to the clipboard\n" + " set the clipboard to oldClipboard\n" + " set theResult to (get theUrl) & \"::split::\" & (get theTitle)\n" + "end tell\n" + "activate application (frontmostApplication as text)\n" + "set links to {}\n" + "copy theResult to the end of links\n" + "return links as string\n")))) + (car (split-string result "[\r\n]+" t)))) + +;;;###autoload +(defun org-mac-qutebrowser-get-frontmost-url () + (interactive) + (message "Applescript: Getting qutebrowser url...") + (org-mac-paste-applescript-links (org-as-mac-qutebrowser-get-frontmost-url))) + +;;;###autoload +(defun org-mac-qutebrowser-insert-frontmost-url () + (interactive) + (insert (org-mac-qutebrowser-get-frontmost-url))) + (provide 'org-mac-link) diff --git a/lisp/org/contrib/lisp/org-mairix.el b/lisp/org-contrib/org-mairix.el similarity index 99% rename from lisp/org/contrib/lisp/org-mairix.el rename to lisp/org-contrib/org-mairix.el index 1037328c..56f45e4c 100644 --- a/lisp/org/contrib/lisp/org-mairix.el +++ b/lisp/org-contrib/org-mairix.el @@ -1,16 +1,16 @@ ;;; org-mairix.el - Support for hooking mairix search into Org for different MUAs ;; -;; Copyright (C) 2007-2014 Georg C. F. Greve +;; Copyright (C) 2007-2014, 2021 Georg C. F. Greve ;; mutt support by Adam Spiers ;; -;; This file is not part of GNU Emacs. -;; ;; Author: Georg C. F. Greve ;; Keywords: outlines, hypermedia, calendar, wp, email, mairix ;; Purpose: Integrate mairix email searching into Org mode ;; See https://orgmode.org and http://www.rpcurnow.force9.co.uk/mairix/ ;; Version: 0.5 ;; +;; This file is not part of GNU Emacs. +;; ;; 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 ;; the Free Software Foundation; either version 3, or (at your option) @@ -22,7 +22,7 @@ ;; License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; USAGE NOTE ;; diff --git a/lisp/org/contrib/lisp/org-notify.el b/lisp/org-contrib/org-notify.el similarity index 98% rename from lisp/org/contrib/lisp/org-notify.el rename to lisp/org-contrib/org-notify.el index 7f610a0d..cee4ea46 100644 --- a/lisp/org/contrib/lisp/org-notify.el +++ b/lisp/org-contrib/org-notify.el @@ -1,8 +1,9 @@ ;;; org-notify.el --- Notifications for Org-mode -;; Copyright (C) 2012-2020 Free Software Foundation, Inc. +;; Copyright (C) 2012-2021 Free Software Foundation, Inc. ;; Author: Peter Münster +;; Homepage: https://github.com/p-m/org-notify ;; Keywords: notification, todo-list, alarm, reminder, pop-up ;; This file is not part of GNU Emacs. @@ -18,7 +19,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: diff --git a/lisp/org/contrib/lisp/org-panel.el b/lisp/org-contrib/org-panel.el similarity index 97% rename from lisp/org/contrib/lisp/org-panel.el rename to lisp/org-contrib/org-panel.el index dec72410..ec3c5721 100644 --- a/lisp/org/contrib/lisp/org-panel.el +++ b/lisp/org-contrib/org-panel.el @@ -4,16 +4,26 @@ ;; Created: Thu Nov 15 15:35:03 2007 ;; Version: 0.21 ;; Lxast-Updated: Wed Nov 21 03:06:03 2007 (3600 +0100) -;; URL: -;; Keywords: -;; Compatibility: ;; ;; Features that might be required by this library: ;; ;; `easymenu', `font-lock', `noutline', `org', `outline', `syntax', ;; `time-date'. ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; This file is not part of GNU Emacs. +;; +;; This program is free software; you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation; either version 3, 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 GNU Emacs. If not, see . ;; ;;; Commentary: ;; @@ -32,28 +42,6 @@ ;; (eval-after-load 'org-mode ;; (define-key org-mode-map [(control ?c) ?p] 'orgpan-panel)) ;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;;; Change log: -;; -;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; -;; 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 2, 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 GNU Emacs. If not, see . -;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;;; Code: (require 'org) diff --git a/lisp/org/contrib/lisp/org-passwords.el b/lisp/org-contrib/org-passwords.el similarity index 98% rename from lisp/org/contrib/lisp/org-passwords.el rename to lisp/org-contrib/org-passwords.el index 4bdd8049..a038b995 100644 --- a/lisp/org/contrib/lisp/org-passwords.el +++ b/lisp/org-contrib/org-passwords.el @@ -2,9 +2,10 @@ ;; Author: Jorge A. Alfaro-Murillo ;; Created: December 26, 2012 +;; Homepage: https://github.com/alfaromurillo/org-passwords.el ;; Keywords: passwords, password -;; This file is NOT part of GNU Emacs. +;; This file is not part of GNU Emacs. ;; ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -17,7 +18,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;;; Commentary: diff --git a/lisp/org/contrib/lisp/org-registry.el b/lisp/org-contrib/org-registry.el similarity index 98% rename from lisp/org/contrib/lisp/org-registry.el rename to lisp/org-contrib/org-registry.el index 402ce308..7ae879a5 100644 --- a/lisp/org/contrib/lisp/org-registry.el +++ b/lisp/org-contrib/org-registry.el @@ -1,6 +1,6 @@ ;;; org-registry.el --- a registry for Org links ;; -;; Copyright 2007-2014 Bastien Guerry +;; Copyright 2007-2021 Free Software Foundation, Inc. ;; ;; Emacs Lisp Archive Entry ;; Filename: org-registry.el @@ -9,7 +9,7 @@ ;; Maintainer: Bastien Guerry ;; Keywords: org, wp, registry ;; Description: Shows Org files where the current buffer is linked -;; URL: http://www.cognition.ens.fr/~guerry/u/org-registry.el +;; Homepage: https://git.sr.ht/~bzg/org-contrib ;; ;; This file is not part of GNU Emacs. ;; @@ -24,7 +24,7 @@ ;; GNU General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;;; Commentary: ;; diff --git a/lisp/org/contrib/lisp/org-screen.el b/lisp/org-contrib/org-screen.el similarity index 92% rename from lisp/org/contrib/lisp/org-screen.el rename to lisp/org-contrib/org-screen.el index 948e93ad..a6d2192d 100644 --- a/lisp/org/contrib/lisp/org-screen.el +++ b/lisp/org-contrib/org-screen.el @@ -1,11 +1,11 @@ ;;; org-screen.el --- Integreate Org-mode with screen. -;; Copyright (c) 2008-2014 Andrew Hyatt +;; Copyright (c) 2008-2014, 2021 Andrew Hyatt ;; ;; Author: Andrew Hyatt -;; Maintainer: Carsten Dominik +;; Maintainer: Carsten Dominik ;; -;; This file is not yet part of GNU Emacs. +;; This file is not part of GNU Emacs. ;; ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -18,8 +18,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; along with GNU Emacs. If not, see . ;; ;;; Commentary: ;; diff --git a/lisp/org/contrib/lisp/org-screenshot.el b/lisp/org-contrib/org-screenshot.el similarity index 99% rename from lisp/org/contrib/lisp/org-screenshot.el rename to lisp/org-contrib/org-screenshot.el index e2e92a75..1e8e1e90 100644 --- a/lisp/org/contrib/lisp/org-screenshot.el +++ b/lisp/org-contrib/org-screenshot.el @@ -1,6 +1,6 @@ ;;; org-screenshot.el --- Take and manage screenshots in Org-mode files ;; -;; Copyright (C) 2009-2020 Free Software Foundation, Inc. +;; Copyright (C) 2009-2021 Free Software Foundation, Inc. ;; ;; Author: Max Mikhanosha ;; Keywords: outlines, hypermedia, calendar, wp @@ -8,7 +8,7 @@ ;; Version: 8.0 ;; ;; Released under the GNU General Public License version 3 -;; see: http://www.gnu.org/licenses/gpl-3.0.html +;; see: https://www.gnu.org/licenses/gpl-3.0.html ;; ;; This file is not part of GNU Emacs. ;; @@ -23,7 +23,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;;; Commentary: diff --git a/lisp/org/contrib/lisp/org-secretary.el b/lisp/org-contrib/org-secretary.el similarity index 97% rename from lisp/org/contrib/lisp/org-secretary.el rename to lisp/org-contrib/org-secretary.el index babfb753..5bb1c25c 100644 --- a/lisp/org/contrib/lisp/org-secretary.el +++ b/lisp/org-contrib/org-secretary.el @@ -1,5 +1,5 @@ ;;; org-secretary.el --- Team management with org-mode -;; Copyright (C) 2010-2014 Juan Reyero +;; Copyright (C) 2010-2014, 2021 Juan Reyero ;; ;; Author: Juan Reyero ;; Keywords: outlines, tasks, team, management @@ -19,8 +19,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; along with GNU Emacs. If not, see . ;; ;;; Commentary: ;; @@ -177,7 +176,7 @@ (global-set-key "\C-cj" 'org-sec-tag-entry) (defun join (lst sep &optional pre post) - (mapconcat (function (lambda (x) (concat pre x post))) lst sep)) + (mapconcat (lambda (x) (concat pre x post)) lst sep)) (defun org-sec-get-with () (if org-sec-with diff --git a/lisp/org/contrib/lisp/org-static-mathjax.el b/lisp/org-contrib/org-static-mathjax.el similarity index 98% rename from lisp/org/contrib/lisp/org-static-mathjax.el rename to lisp/org-contrib/org-static-mathjax.el index ac13ee2d..e1e1a303 100644 --- a/lisp/org/contrib/lisp/org-static-mathjax.el +++ b/lisp/org-contrib/org-static-mathjax.el @@ -2,7 +2,7 @@ ;; ;; Author: Jan Böker -;; This file is part of GNU Emacs. +;; This file is not part of GNU Emacs. ;; GNU Emacs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -15,9 +15,10 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;;; Commentary: +;; ;; This elisp code integrates Static MathJax into the ;; HTML export process of Org-mode. ;; diff --git a/lisp/org/contrib/lisp/org-sudoku.el b/lisp/org-contrib/org-sudoku.el similarity index 96% rename from lisp/org/contrib/lisp/org-sudoku.el rename to lisp/org-contrib/org-sudoku.el index cc54c6d6..5fe5dde6 100644 --- a/lisp/org/contrib/lisp/org-sudoku.el +++ b/lisp/org-contrib/org-sudoku.el @@ -1,13 +1,13 @@ ;;; org-sudoku.el --- Create and solve SUDOKU games in Org tables -;; Copyright (C) 2012-2020 Free Software Foundation, Inc. +;; Copyright (C) 2012-2021 Free Software Foundation, Inc. ;; -;; Author: Carsten Dominik +;; Author: Carsten Dominik ;; Keywords: outlines, hypermedia, calendar, wp, games ;; Homepage: https://orgmode.org ;; Version: 0.01 ;; -;; This file is not yet part of GNU Emacs. +;; This file is not part of GNU Emacs. ;; ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -20,8 +20,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; along with GNU Emacs. If not, see . ;; ;;; Commentary: ;; diff --git a/lisp/org/contrib/lisp/org-toc.el b/lisp/org-contrib/org-toc.el similarity index 98% rename from lisp/org/contrib/lisp/org-toc.el rename to lisp/org-contrib/org-toc.el index e05c4bdf..7a61d387 100644 --- a/lisp/org/contrib/lisp/org-toc.el +++ b/lisp/org-contrib/org-toc.el @@ -1,10 +1,10 @@ ;;; org-toc.el --- Table of contents for Org-mode buffer -;; Copyright 2007-2020 Free Software Foundation, Inc. +;; Copyright 2007-2021 Free Software Foundation, Inc. ;; ;; Author: Bastien Guerry -;; Keywords: Org table of contents -;; Homepage: http://www.cognition.ens.fr/~guerry/u/org-toc.el +;; Keywords: org, toc +;; Homepage: https://git.sr.ht/~bzg/org-contrib ;; Version: 0.8 ;; This file is not part of GNU Emacs. @@ -20,7 +20,7 @@ ;; GNU General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;;; Commentary: diff --git a/lisp/org/contrib/lisp/org-track.el b/lisp/org-contrib/org-track.el similarity index 96% rename from lisp/org/contrib/lisp/org-track.el rename to lisp/org-contrib/org-track.el index 0f5e0975..cba53e6d 100644 --- a/lisp/org/contrib/lisp/org-track.el +++ b/lisp/org-contrib/org-track.el @@ -1,17 +1,17 @@ ;;; org-track.el --- Track the most recent Org-mode version available. ;; -;; Copyright (C) 2009-2020 Free Software Foundation, Inc. +;; Copyright (C) 2009-2021 Free Software Foundation, Inc. ;; ;; Author: Bastien Guerry ;; Eric S Fraga ;; Sebastian Rose ;; The Worg people https://orgmode.org/worg/ ;; Keywords: outlines, hypermedia, calendar, wp -;; Homepage: https://orgmode.org +;; Homepage: https://git.sr.ht/~bzg/org-contrib ;; Version: 6.29a ;; ;; Released under the GNU General Public License version 3 -;; see: http://www.gnu.org/licenses/gpl-3.0.html +;; see: https://www.gnu.org/licenses/gpl-3.0.html ;; ;; This file is not part of GNU Emacs. ;; @@ -26,8 +26,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; along with GNU Emacs. If not, see . ;; ;;; Commentary: ;; diff --git a/lisp/org/contrib/lisp/org-velocity.el b/lisp/org-contrib/org-velocity.el similarity index 98% rename from lisp/org/contrib/lisp/org-velocity.el rename to lisp/org-contrib/org-velocity.el index bfc4d6c3..5e6f4b42 100644 --- a/lisp/org/contrib/lisp/org-velocity.el +++ b/lisp/org-contrib/org-velocity.el @@ -1,26 +1,30 @@ ;;; org-velocity.el --- something like Notational Velocity for Org. -*- lexical-binding: t -*- -;; Copyright (C) 2010-2014 Paul M. Rodriguez +;; Copyright (C) 2010-2014, 2021 Paul M. Rodriguez ;; Author: Paul M. Rodriguez +;; Maintainer: Paul M. Rodriguez +;; Homepage: https://github.com/ruricolist/org-velocity ;; Created: 2010-05-05 ;; Version: 4.1 ;; This file is not part of GNU Emacs. -;; This program is free software; you can redistribute it and/or -;; modify it under the terms of the GNU General Public License as -;; published by the Free Software Foundation version 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 +;; 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. +;; 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 GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;;; Commentary: +;; ;; Org-Velocity.el is an interface for Org inspired by the minimalist ;; notetaking program Notational Velocity. The idea is to let you ;; amass and access brief notes on many subjects with minimal fuss. diff --git a/lisp/org/contrib/lisp/org-wikinodes.el b/lisp/org-contrib/org-wikinodes.el similarity index 97% rename from lisp/org/contrib/lisp/org-wikinodes.el rename to lisp/org-contrib/org-wikinodes.el index e44ac987..b8a5e271 100644 --- a/lisp/org/contrib/lisp/org-wikinodes.el +++ b/lisp/org-contrib/org-wikinodes.el @@ -1,8 +1,8 @@ ;;; org-wikinodes.el --- Wiki-like CamelCase links to outline nodes -;; Copyright (C) 2010-2020 Free Software Foundation, Inc. +;; Copyright (C) 2010-2021 Free Software Foundation, Inc. -;; Author: Carsten Dominik +;; Author: Carsten Dominik ;; Keywords: outlines, hypermedia, calendar, wp ;; Homepage: https://orgmode.org ;; Version: 7.01trans @@ -20,8 +20,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; along with GNU Emacs. If not, see . (require 'org) (eval-when-compile diff --git a/lisp/org/contrib/lisp/orgtbl-sqlinsert.el b/lisp/org-contrib/orgtbl-sqlinsert.el similarity index 96% rename from lisp/org/contrib/lisp/orgtbl-sqlinsert.el rename to lisp/org-contrib/orgtbl-sqlinsert.el index 6ead169f..d8da3622 100644 --- a/lisp/org/contrib/lisp/orgtbl-sqlinsert.el +++ b/lisp/org-contrib/orgtbl-sqlinsert.el @@ -1,6 +1,6 @@ ;;; orgtbl-sqlinsert.el --- orgtbl to SQL insert statements. -;; Copyright (C) 2008-2020 Free Software Foundation +;; Copyright (C) 2008-2021 Free Software Foundation, Inc. ;; Author: Jason Riedy ;; Keywords: org, tables, sql @@ -18,7 +18,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: diff --git a/lisp/org/contrib/lisp/ox-bibtex.el b/lisp/org-contrib/ox-bibtex.el similarity index 98% rename from lisp/org/contrib/lisp/ox-bibtex.el rename to lisp/org-contrib/ox-bibtex.el index 0dcdf5de..a5eddea5 100644 --- a/lisp/org/contrib/lisp/ox-bibtex.el +++ b/lisp/org-contrib/ox-bibtex.el @@ -1,6 +1,6 @@ ;;; ox-bibtex.el --- Export bibtex fragments -;; Copyright (C) 2009-2014 Taru Karttunen +;; Copyright (C) 2009-2014, 2021 Taru Karttunen ;; Author: Taru Karttunen ;; Nicolas Goaziou @@ -8,7 +8,7 @@ ;; 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 2, or (at +;; published by the Free Software Foundation; either version 3, or (at ;; your option) any later version. ;; This program is distributed in the hope that it will be useful, but @@ -26,11 +26,11 @@ ;; This is an utility to handle BibTeX export to LaTeX, html and ascii ;; exports. For HTML and ascii it uses the bibtex2html software from: ;; -;; http://www.lri.fr/~filliatr/bibtex2html/ +;; https://www.lri.fr/~filliatr/bibtex2html/ ;; ;; For ascii it uses the pandoc software from: ;; -;; http://johnmacfarlane.net/pandoc/ +;; https://pandoc.org/ ;; ;; It also introduces "cite" syntax for Org links. ;; @@ -167,7 +167,7 @@ to `org-bibtex-citation-p' predicate." (and position (progn (goto-char position) t))))) (let ((jump-fn (car (cl-remove-if-not #'fboundp '(ebib org-bibtex-goto-citation))))) - (org-add-link-type "cite-bt" jump-fn)) + (org-add-link-type "cite" jump-fn)) diff --git a/lisp/org/contrib/lisp/ox-confluence.el b/lisp/org-contrib/ox-confluence.el similarity index 98% rename from lisp/org/contrib/lisp/ox-confluence.el rename to lisp/org-contrib/ox-confluence.el index 4f40eec1..127a6c51 100644 --- a/lisp/org/contrib/lisp/ox-confluence.el +++ b/lisp/org-contrib/ox-confluence.el @@ -1,6 +1,6 @@ ;;; ox-confluence --- Confluence Wiki Back-End for Org Export Engine -;; Copyright (C) 2012, 2014 Sébastien Delafond +;; Copyright (C) 2012-2021 Sébastien Delafond ;; Author: Sébastien Delafond ;; Keywords: outlines, confluence, wiki @@ -18,7 +18,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;;; Commentary: ;; diff --git a/lisp/org/contrib/lisp/ox-deck.el b/lisp/org-contrib/ox-deck.el similarity index 99% rename from lisp/org/contrib/lisp/ox-deck.el rename to lisp/org-contrib/ox-deck.el index 3b911e16..122b5ac6 100644 --- a/lisp/org/contrib/lisp/ox-deck.el +++ b/lisp/org-contrib/ox-deck.el @@ -1,6 +1,6 @@ ;;; ox-deck.el --- deck.js Presentation Back-End for Org Export Engine -;; Copyright (C) 2013, 2014 Rick Frankel +;; Copyright (C) 2013, 2014, 2021 Rick Frankel ;; Author: Rick Frankel ;; Keywords: outlines, hypermedia, slideshow @@ -18,7 +18,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: @@ -425,10 +425,10 @@ holding export options." (mapconcat (lambda (script) (format - "" script)) + "" script)) (plist-get pkg-info :scripts) "\n") (org-html--build-mathjax-config info) - "" (org-html--build-head info) diff --git a/lisp/org/contrib/lisp/ox-extra.el b/lisp/org-contrib/ox-extra.el similarity index 98% rename from lisp/org/contrib/lisp/ox-extra.el rename to lisp/org-contrib/ox-extra.el index 9cd6980d..4f51ed9f 100644 --- a/lisp/org/contrib/lisp/ox-extra.el +++ b/lisp/org-contrib/ox-extra.el @@ -1,6 +1,6 @@ ;;; ox-extra.el --- Convenience functions for org export -;; Copyright (C) 2014 Aaron Ecay +;; Copyright (C) 2014, 2021 Aaron Ecay ;; Author: Aaron Ecay @@ -15,7 +15,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: diff --git a/lisp/org/contrib/lisp/ox-freemind.el b/lisp/org-contrib/ox-freemind.el similarity index 99% rename from lisp/org/contrib/lisp/ox-freemind.el rename to lisp/org-contrib/ox-freemind.el index 568a6dab..21ce7316 100644 --- a/lisp/org/contrib/lisp/ox-freemind.el +++ b/lisp/org-contrib/ox-freemind.el @@ -1,6 +1,6 @@ ;;; ox-freemind.el --- Freemind Mindmap Back-End for Org Export Engine -;; Copyright (C) 2013-2020 Free Software Foundation, Inc. +;; Copyright (C) 2013-2021 Free Software Foundation, Inc. ;; Author: Jambunathan K ;; Keywords: outlines, hypermedia, calendar, wp @@ -18,7 +18,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;;; Commentary: diff --git a/lisp/org/contrib/lisp/ox-groff.el b/lisp/org-contrib/ox-groff.el similarity index 99% rename from lisp/org/contrib/lisp/ox-groff.el rename to lisp/org-contrib/ox-groff.el index 9f0a3243..5c18085f 100644 --- a/lisp/org/contrib/lisp/ox-groff.el +++ b/lisp/org-contrib/ox-groff.el @@ -1,6 +1,6 @@ ;;; ox-groff.el --- Groff Back-End for Org Export Engine -;; Copyright (C) 2011-2020 Free Software Foundation, Inc. +;; Copyright (C) 2011-2021 Free Software Foundation, Inc. ;; Author: Nicolas Goaziou ;; Author: Luis R Anaya @@ -19,7 +19,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: ;; ;; This library implements a Groff Memorandum Macro back-end for Org diff --git a/lisp/org/contrib/lisp/ox-rss.el b/lisp/org-contrib/ox-rss.el similarity index 96% rename from lisp/org/contrib/lisp/ox-rss.el rename to lisp/org-contrib/ox-rss.el index bb069dad..c98cac88 100644 --- a/lisp/org/contrib/lisp/ox-rss.el +++ b/lisp/org-contrib/ox-rss.el @@ -1,11 +1,13 @@ ;;; ox-rss.el --- RSS 2.0 Back-End for Org Export Engine -;; Copyright (C) 2013-2015 Bastien Guerry +;; Copyright (C) 2013-2021 Free Software Foundation, Inc. ;; Author: Bastien Guerry +;; Maintainer: Bastien Guerry ;; Keywords: org, wp, blog, feed, rss +;; Homepage: https://gitlab.com/nsavage/ox-rss -;; This file is not yet part of GNU Emacs. +;; This file is not part of GNU Emacs. ;; This program is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -18,7 +20,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;;; Commentary: @@ -34,8 +36,8 @@ ;; This backend understands three new option keywords: ;; ;; #+RSS_EXTENSION: xml -;; #+RSS_IMAGE_URL: http://myblog.org/mypicture.jpg -;; #+RSS_FEED_URL: http://myblog.org/feeds/blog.xml +;; #+RSS_IMAGE_URL: https://myblog.org/mypicture.jpg +;; #+RSS_FEED_URL: https://myblog.org/feeds/blog.xml ;; ;; It uses #+HTML_LINK_HOME: to set the base url of the feed. ;; @@ -245,7 +247,7 @@ communication channel." (or (org-element-property :CATEGORY headline) "") info)) (pubdate0 (org-element-property :PUBDATE headline)) (pubdate (let ((system-time-locale "C")) - (if pubdate0 + (if (and pubdate0 (not (string-empty-p pubdate0))) (format-time-string "%a, %d %b %Y %H:%M:%S %z" (org-time-string-to-time pubdate0))))) @@ -270,7 +272,7 @@ communication channel." (org-element-property :CUSTOM_ID headline) publink) info)))) - (if (not pubdate0) "" ;; Skip entries with no PUBDATE prop + (if (not pubdate) "" ;; Skip entries with no PUBDATE prop (format (concat "\n" diff --git a/lisp/org/contrib/lisp/ox-s5.el b/lisp/org-contrib/ox-s5.el similarity index 98% rename from lisp/org/contrib/lisp/ox-s5.el rename to lisp/org-contrib/ox-s5.el index 24333251..2b70c76e 100644 --- a/lisp/org/contrib/lisp/ox-s5.el +++ b/lisp/org-contrib/ox-s5.el @@ -1,6 +1,6 @@ ;;; ox-s5.el --- S5 Presentation Back-End for Org Export Engine -;; Copyright (C) 2011-2014 Rick Frankel +;; Copyright (C) 2011-2014, 2021 Rick Frankel ;; Author: Rick Frankel ;; Keywords: outlines, hypermedia, S5, wp @@ -18,7 +18,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: @@ -28,7 +28,7 @@ ;; Installation ;; ------------ ;; Get the s5 scripts from -;; http://meyerweb.com/eric/tools/s5/ +;; https://meyerweb.com/eric/tools/s5/ ;; (Note that the default s5 version is set for using the alpha, 1.2a2. ;; Copy the ui dir to somewhere reachable from your published presentation ;; The default (`org-s5-ui-url') is set to "ui" (e.g., in the @@ -255,7 +255,7 @@ INFO is a plist used as a communication channel." "" (concat "")) "\n"))) + "/default/slides.js'>")) "\n"))) (defun org-s5--build-meta-info (info) (concat diff --git a/lisp/org/contrib/lisp/ox-taskjuggler.el b/lisp/org-contrib/ox-taskjuggler.el similarity index 99% rename from lisp/org/contrib/lisp/ox-taskjuggler.el rename to lisp/org-contrib/ox-taskjuggler.el index 8c43b062..50014d89 100644 --- a/lisp/org/contrib/lisp/ox-taskjuggler.el +++ b/lisp/org-contrib/ox-taskjuggler.el @@ -1,6 +1,6 @@ ;;; ox-taskjuggler.el --- TaskJuggler Back-End for Org Export Engine ;; -;; Copyright (C) 2007-2020 Free Software Foundation, Inc. +;; Copyright (C) 2007-2021 Free Software Foundation, Inc. ;; ;; Emacs Lisp Archive Entry ;; Filename: ox-taskjuggler.el @@ -23,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: ;; @@ -64,7 +64,7 @@ ;; should end up with something similar to the example by Peter Jones ;; in: ;; -;; http://www.devalot.com/assets/articles/2008/07/project-planning/project-planning.org. +;; https://www.devalot.com/assets/articles/2008/07/project-planning/project-planning.org. ;; ;; Now mark the top node of your tasks with a tag named ;; "taskjuggler_project" (or whatever you customized @@ -720,9 +720,8 @@ Return complete project plan as a string in TaskJuggler syntax." (mapconcat 'org-element-normalize-string (mapcar - (function - (lambda (report) - (replace-regexp-in-string "%title" report-title report t t))) + (lambda (report) + (replace-regexp-in-string "%title" report-title report t t)) org-taskjuggler-default-reports) ""))))))))) (defun org-taskjuggler--build-project (project info) diff --git a/lisp/org-drill.el b/lisp/org-drill.el index 7bd53f13..707b1254 100644 --- a/lisp/org-drill.el +++ b/lisp/org-drill.el @@ -5,8 +5,8 @@ ;; Maintainer: Phillip Lord ;; Author: Paul Sexton ;; Version: 2.7.0 -;; Package-Version: 20200412.1812 -;; Package-Commit: 35c1ce349949cc213f3076799211210f49431850 +;; Package-Version: 20210427.2003 +;; Package-Commit: bf8fe812d44a3ce3e84361fb39b8ef28ca10fd0c ;; Package-Requires: ((emacs "25.3") (seq "2.14") (org "9.3") (persist "0.3")) ;; Keywords: games, outlines, multimedia @@ -2857,6 +2857,7 @@ STATUS is one of the following values: (setf (oref session warned-about-id-creation) t)) (org-id-get-create)) +;;;###autoload (defun org-drill (&optional scope drill-match resume-p cram) "Begin an interactive 'drill session'. The user is asked to review a series of topics (headers). Each topic is initially @@ -2980,6 +2981,7 @@ work correctly with older versions of org mode. Your org mode version (%s) appea (message nil) )))) +;;;###autoload (defun org-drill-cram (&optional scope drill-match) "Run an interactive drill session in 'cram mode'. In cram mode, all drill items are considered to be due for review, unless they @@ -3007,6 +3009,7 @@ files in the same directory as the current file." (interactive) (org-drill 'directory)) +;;;###autoload (defun org-drill-again (&optional scope drill-match) "Run a new drill session, but try to use leftover due items that were not reviewed during the last session, rather than scanning for diff --git a/lisp/org-fancy-priorities.el b/lisp/org-fancy-priorities.el index 6c27da81..8c39c9a7 100644 --- a/lisp/org-fancy-priorities.el +++ b/lisp/org-fancy-priorities.el @@ -5,8 +5,8 @@ ;; Author: Harry Bournis ;; Created: 5 Feb 2018 ;; Version: 1.1 -;; Package-Version: 20180328.2331 -;; Package-Commit: 819bb993b71e7253cefef7047306ab4e0f9d0a86 +;; Package-Version: 20210830.1657 +;; Package-Commit: 7f677c6c14ecf05eab8e0efbfe7f1b00ae68eb1d ;; Keywords: convenience faces outlines ;; Homepage: https://github.com/harrybournis/org-fancy-priorities ;; @@ -115,18 +115,20 @@ PRIORITY Is a string of just the priority value e.g. \"A\" \"B\" etc." (defun org-fancy-priorities-create-overlays () "Search with regex for priorities and add an overlay with their replacement string on their position." - (let (ol) - (while (re-search-forward org-fancy-priorities-regex nil t) - (setq ol (make-overlay (match-beginning 1) (- (match-end 1) 1))) - (overlay-put ol 'display (org-fancy-priorities-get-value (match-string 2))) - (push ol org-fancy-priorities-overlay-list)))) + (save-excursion + (let (ol) + (while (re-search-forward org-fancy-priorities-regex nil t) + (setq ol (make-overlay (match-beginning 1) (- (match-end 1) 1))) + (overlay-put ol 'display (org-fancy-priorities-get-value (match-string 2))) + (push ol org-fancy-priorities-overlay-list))))) ;;;###autoload (define-minor-mode org-fancy-priorities-mode "Customize the appearance of org-mode priorities. This mode does not alter your files in any way, it only changes the way that priorities are shown in your editor." - nil " FancyPriorities" nil + :lighter " FancyPriorities" + :keymap nil (let ((keyword `((,org-fancy-priorities-regex (0 (progn (let ((custom-priority (org-fancy-priorities-get-value (match-string 2)))) diff --git a/lisp/org-ref/citeproc/csl-locales/locales-en-US.xml b/lisp/org-ref/citeproc/csl-locales/locales-en-US.xml new file mode 100644 index 00000000..be78c5e8 --- /dev/null +++ b/lisp/org-ref/citeproc/csl-locales/locales-en-US.xml @@ -0,0 +1,357 @@ + + + + + Andrew Dunning + + + Sebastian Karcher + + + Rintze M. Zelle + + This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License + 2015-10-10T23:31:02+00:00 + + + + + + + + + + + + + + accessed + and + and others + anonymous + anon. + at + available at + by + circa + c. + cited + + edition + editions + + ed. + et al. + forthcoming + from + ibid. + in + in press + internet + interview + letter + no date + n.d. + online + presented at the + + reference + references + + + ref. + refs. + + retrieved + scale + version + + + AD + BC + + + + + + + + + + th + st + nd + rd + th + th + th + + + first + second + third + fourth + fifth + sixth + seventh + eighth + ninth + tenth + + + + book + books + + + chapter + chapters + + + column + columns + + + figure + figures + + + folio + folios + + + number + numbers + + + line + lines + + + note + notes + + + opus + opera + + + page + pages + + + page + pages + + + paragraph + paragraphs + + + part + parts + + + section + sections + + + sub verbo + sub verbis + + + verse + verses + + + volume + volumes + + + + + bk. + bks. + + + chap. + chaps. + + + col. + cols. + + + fig. + figs. + + + fol. + fols. + + + no. + nos. + + + l. + ll. + + + n. + nn. + + + op. + opp. + + + p. + pp. + + + p. + pp. + + + para. + paras. + + + pt. + pts. + + + sec. + secs. + + + s.v. + s.vv. + + + v. + vv. + + + vol. + vols. + + + + + + ¶¶ + + + § + §§ + + + + + director + directors + + + editor + editors + + + editor + editors + + + illustrator + illustrators + + + translator + translators + + + editor & translator + editors & translators + + + + + dir. + dirs. + + + ed. + eds. + + + ed. + eds. + + + ill. + ills. + + + tran. + trans. + + + ed. & tran. + eds. & trans. + + + + by + directed by + edited by + edited by + illustrated by + interview by + to + by + translated by + edited & translated by + + + dir. by + ed. by + ed. by + illus. by + trans. by + ed. & trans. by + + + January + February + March + April + May + June + July + August + September + October + November + December + + + Jan. + Feb. + Mar. + Apr. + May + Jun. + Jul. + Aug. + Sep. + Oct. + Nov. + Dec. + + + Spring + Summer + Autumn + Winter + + diff --git a/lisp/org-ref/citeproc/csl-styles/apa-5th-edition.csl b/lisp/org-ref/citeproc/csl-styles/apa-5th-edition.csl new file mode 100644 index 00000000..186557db --- /dev/null +++ b/lisp/org-ref/citeproc/csl-styles/apa-5th-edition.csl @@ -0,0 +1,341 @@ + + diff --git a/lisp/org-ref/citeproc/csl-styles/apa-numeric-superscript-brackets.csl b/lisp/org-ref/citeproc/csl-styles/apa-numeric-superscript-brackets.csl new file mode 100644 index 00000000..e1a2a180 --- /dev/null +++ b/lisp/org-ref/citeproc/csl-styles/apa-numeric-superscript-brackets.csl @@ -0,0 +1,1711 @@ + + diff --git a/lisp/org-ref/citeproc/csl-styles/chicago-author-date-16th-edition.csl b/lisp/org-ref/citeproc/csl-styles/chicago-author-date-16th-edition.csl new file mode 100644 index 00000000..6ff1f0ba --- /dev/null +++ b/lisp/org-ref/citeproc/csl-styles/chicago-author-date-16th-edition.csl @@ -0,0 +1,657 @@ + + diff --git a/lisp/org-ref/citeproc/csl-styles/elsevier-harvard.csl b/lisp/org-ref/citeproc/csl-styles/elsevier-harvard.csl new file mode 100644 index 00000000..cc97857b --- /dev/null +++ b/lisp/org-ref/citeproc/csl-styles/elsevier-harvard.csl @@ -0,0 +1,239 @@ + + \ No newline at end of file diff --git a/lisp/org-ref/citeproc/csl-styles/elsevier-with-titles.csl b/lisp/org-ref/citeproc/csl-styles/elsevier-with-titles.csl new file mode 100644 index 00000000..135329d2 --- /dev/null +++ b/lisp/org-ref/citeproc/csl-styles/elsevier-with-titles.csl @@ -0,0 +1,149 @@ + + diff --git a/lisp/org-ref/citeproc/csl/acs-nano.csl b/lisp/org-ref/citeproc/csl/acs-nano.csl deleted file mode 100644 index 4b65ea3f..00000000 --- a/lisp/org-ref/citeproc/csl/acs-nano.csl +++ /dev/null @@ -1,214 +0,0 @@ - - diff --git a/lisp/org-ref/citeproc/csl/author-year.el b/lisp/org-ref/citeproc/csl/author-year.el deleted file mode 100644 index a29d8ac2..00000000 --- a/lisp/org-ref/citeproc/csl/author-year.el +++ /dev/null @@ -1,92 +0,0 @@ -;;; author-year.el --- Citation Style Lisp - the other CSL - - -;;; Commentary: -;; - -;;; Code: - -(setq citation-style - '((label . orcp-citation-author-year-label) - (prefix . "(") - (suffix . ")") - (delimiter . "; ") - (citeauthor . ((vertical-align . baseline) - (label . orcp-citation-author-label) - (prefix . "") - (suffix . " "))) - (citeyear . ((vertical-align . baseline) - (label . orcp-citation-year-label) - (prefix . "") - (suffix . " ") - (chomp-leading-space . nil) - )))) - - - -(setq bibliography-style - '((sort . nil) - (hanging-indent . 3) - (justification . full) - (spacing . 1) - (label . orcp-citation-author-year-label) - (label-prefix . "(") - (label-suffix . ") ") - (header . ((text . "Bibliography") - (font-style . bold))) - ;; Formatting of fields - ;; Single author name - (author . ((initialize . t) ; use initials, not full names - ;; use firstname and lastname symbols - (name-order . (firstname lastname)) - (name-separator . " ") - (et-al . 4) ; after 4 authors use et-al - (delimiter . "; ") - (last-author-delimiter . " and ") - (suffix . "") - (field-separator . ", ") - ;; ; function to convert (first von last jr) to a string.) - (name-format . ''format-author-name) - (field-separator ", "))) - - (title . ((font-style . italics) - (suffix . "") - (field-separator . ", "))) - (booktitle . ((font-style . italics) - (suffix . "") - (field-separator . "in "))) - (journal . ((suffix . "") - (field-separator . ", "))) - ;; here we use some logic to group volume(issue) or volume - (volume . ((suffix . (when (orcp-get-entry-field "number" entry) - (orcp-issue entry))) - (field-separator . ", "))) - (issue . ((font-style . bold) - (prefix . "(") - (suffix . ")") - (field-separator . ", "))) - (pages . ((prefix . "pp. ") - (suffix . "") - (field-separator . " ") - (collapse-range . nil))) - (year . ((prefix . "(") - (suffix . ")") - (field-separator . "."))) - (doi . ((prefix . " ") - (suffix . ".") - (field-separator . "") - (formatter . orcp-doi-formatter))) - ;; Formatting of entries - (entries . ((article . (author title journal volume pages year doi)) - (inproceedings . (author title booktitle year)) - (book . (author title year)) - (manual . (author title url doi)) - (misc . (author title url doi)) - (techreport . (author title institution year)) - (mastersthesis . (author title school year)) - (phdthesis . (author title school year)) - (t . (author title year)))))) - -(provide 'author-year) - -;;; author-year.el ends here diff --git a/lisp/org-ref/citeproc/csl/unsrt-footnote.el b/lisp/org-ref/citeproc/csl/unsrt-footnote.el deleted file mode 100644 index 66f212e0..00000000 --- a/lisp/org-ref/citeproc/csl/unsrt-footnote.el +++ /dev/null @@ -1,86 +0,0 @@ -;;; unsrt-footnote.el --- Citation Style Lisp - the other CSL - - -;;; Commentary: -;; Convert citations to org-mode footnotes - -;;; Code: - -(setq citation-style - '((label . orcp-footnote-label) - (prefix . "") - (suffix . "") - ;; sort on increasing citation numbers. - (sort . (lambda (key1 key2) - (let ((i1 (-find-index - (lambda (entry) - (string= key1 (car entry))) - *orcp-unique-entries*)) - (i2 (-find-index - (lambda (entry) - (string= key2 (car entry))) - *orcp-unique-entries*))) - (> i2 i1)))) - (delimiter . ", ") - (vertical-align . baseline))) - - -(setq bibliography-style - '((sort . nil) - (hanging-indent . 3) - (justification . full) - (spacing . 1) - (label . orcp-footnote-label) - (label-prefix . "") - (label-suffix . " ") - (header . ((text . "Bibliography") - (font-style . bold))) - ;; Formatting of fields - ;; Single author name - (author . ((initialize . t) ; use initials, not full names - (name-order . (lastname firstname)) - (name-separator . ", ") - (et-al . 4) ; after 4 authors use et-al - (delimiter . "; ") - (last-author-delimiter . " and ") - (suffix . "") - (field-separator . ", ") - ;; ; function to convert (first von last jr) to a string.) - (name-format . ''format-author-name) - (field-separator ", "))) - (title . ((font-style . italics) - (suffix . "") - (field-separator . ", "))) - (journal . ((suffix . "") - (field-separator . ", "))) - ;; here we use some logic to group volume(issue) or volume - (volume . ((suffix . (when (orcp-get-entry-field "number" entry) - (orcp-issue entry))) - (field-separator . ", "))) - (issue . ((font-style . bold) - (prefix . "(") - (suffix . ")") - (field-separator . ", "))) - (pages . ((prefix . "pp. ") - (suffix . "") - (field-separator . " ") - (collapse-range . nil))) - (year . ((prefix . "(") - (suffix . ")") - (field-separator . "."))) - (doi . ((prefix . " ") - (suffix . ".") - (field-separator . "") - (formatter . orcp-doi-formatter))) - ;; Formatting of entries - (entries . ((article . (author title journal volume pages year doi)) - (book . (author title year)) - (misc . (author title url doi)) - (techreport . (author title institution year)) - (mastersthesis . (author title school year)) - (phdthesis . (author title school year)) - (t . (author title year)))))) - -(provide 'unsrt) - -;;; unsrt.el ends here diff --git a/lisp/org-ref/citeproc/csl/unsrt-paren.el b/lisp/org-ref/citeproc/csl/unsrt-paren.el deleted file mode 100644 index bfea5d13..00000000 --- a/lisp/org-ref/citeproc/csl/unsrt-paren.el +++ /dev/null @@ -1,107 +0,0 @@ -;;; unsrt-paren.el --- numbered citations in () - -;;; Commentary: -;; This does not work well for brackets because org-mode interprets them as -;; footnotes. - -;;; Code: - -(setq citation-style - '((label . orcp-citation-number-label) - (prefix . "(") - (suffix . ")") - (chomp-leading-space . nil) - (chomp-trailing-space . nil) - ;; sort on increasing citation numbers. - (sort . (lambda (key1 key2) - (let ((i1 (-find-index - (lambda (entry) - (string= key1 (car entry))) - *orcp-unique-entries*)) - (i2 (-find-index - (lambda (entry) - (string= key2 (car entry))) - *orcp-unique-entries*))) - (> i2 i1)))) - (collapse . 'orcp-collapse-numeric-range) - (delimiter . ",") - (vertical-align . baseline) - (transpose-punctuation . nil) ;put citations on right of punctuation - (citenum . ((vertical-align . baseline) - (prefix . "") - (suffix . "") - (chomp-leading-space . nil) - (chomp-trailing-space . nil))) - (citeauthor . ((vertical-align . baseline) - (label . orcp-citation-author-label) - (prefix . "") - (suffix . "") - (chomp-leading-space . nil) - (chomp-trailing-space . nil))) - (citeyear . ((vertical-align . baseline) - (label . orcp-citation-year-label) - (prefix . "") - (suffix . "") - (chomp-leading-space . nil) - (chomp-trailing-space . nil))))) - - -(setq bibliography-style - '((sort . nil) - (hanging-indent . 3) - (justification . full) - (spacing . 1) - (label . orcp-citation-number-label) - (label-prefix . "") - (label-suffix . ") ") - (header . ((text . "Bibliography") - (font-style . bold))) - ;; Formatting of fields - ;; Single author name - (author . ((initialize . t) ; use initials, not full names - (name-order . (lastname firstname)) - (name-separator . ", ") - (et-al . 4) ; after 4 authors use et-al - (delimiter . "; ") - (last-author-delimiter . " and ") - (suffix . "") - (field-separator . ", ") - ;; ; function to convert (first von last jr) to a string.) - (name-format . ''format-author-name) - (field-separator ", "))) - (title . ((font-style . italics) - (suffix . "") - (field-separator . ", "))) - (journal . ((suffix . "") - (field-separator . ", "))) - ;; here we use some logic to group volume(issue) or volume - (volume . ((suffix . (when (orcp-get-entry-field "number" entry) - (orcp-issue entry))) - (field-separator . ", "))) - (issue . ((font-style . bold) - (prefix . "(") - (suffix . ")") - (field-separator . ", "))) - (pages . ((prefix . "pp. ") - (suffix . "") - (field-separator . " ") - (collapse-range . nil))) - (year . ((prefix . "(") - (suffix . ")") - (field-separator . "."))) - (doi . ((prefix . " ") - (suffix . ".") - (field-separator . "") - (formatter . orcp-doi-formatter))) - ;; Formatting of entries - (entries . ((article . (author title journal volume pages year doi)) - (book . (author title year)) - (misc . (author title url doi)) - (techreport . (author title institution year)) - (mastersthesis . (author title school year)) - (phdthesis . (author title school year)) - (t . (author title year)))))) - -(provide 'unsrt-paren) - -;;; unsrt-paren.el ends here diff --git a/lisp/org-ref/citeproc/csl/unsrt.el b/lisp/org-ref/citeproc/csl/unsrt.el deleted file mode 100644 index 9013ed31..00000000 --- a/lisp/org-ref/citeproc/csl/unsrt.el +++ /dev/null @@ -1,111 +0,0 @@ -;;; unsrt.el --- Citation Style Lisp - the other CSL - - -;;; Commentary: -;; - -;;; Code: - -(setq citation-style - '((label . orcp-citation-number-label) - (prefix . "") - (suffix . "") - (chomp-leading-space . t) - (chomp-trailing-space . nil) - ;; sort on increasing citation numbers. - (sort . (lambda (key1 key2) - (let ((i1 (-find-index - (lambda (entry) - (string= key1 (car entry))) - *orcp-unique-entries*)) - (i2 (-find-index - (lambda (entry) - (string= key2 (car entry))) - *orcp-unique-entries*))) - (> i2 i1)))) - (collapse . 'orcp-collapse-numeric-range) - (delimiter . ",") - (vertical-align . superscript) - (transpose-punctuation . t) ;put citations on right of punctuation - (citenum . ((vertical-align . baseline) - (prefix . " ") - (suffix . " ") - (chomp-leading-space . nil) - (chomp-trailing-space . nil))) - (citeauthor . ((vertical-align . baseline) - (label . orcp-citation-author-label) - (prefix . "") - (suffix . " ") - (chomp-leading-space . nil) - (chomp-trailing-space . nil))) - (citeyear . ((vertical-align . baseline) - (label . orcp-citation-year-label) - (prefix . "") - (suffix . " ") - (chomp-leading-space . nil) - (chomp-trailing-space . nil))))) - - -(setq bibliography-style - '((sort . nil) - (hanging-indent . 3) - (justification . full) - (spacing . 1) - (label . orcp-citation-number-label) - (label-prefix . "") - (label-suffix . ". ") - (header . ((text . "Bibliography") - (font-style . bold))) - ;; Formatting of fields - ;; Single author name - (author . ((initialize . t) ; use initials, not full names - (name-order . (lastname firstname)) - (name-separator . ", ") - (et-al . 4) ; after 4 authors use et-al - (delimiter . "; ") - (last-author-delimiter . " and ") - (suffix . "") - (field-separator . ", ") - ;; ; function to convert (first von last jr) to a string.) - (name-format . ''format-author-name) - (field-separator ", "))) - (title . ((font-style . italics) - (suffix . "") - (field-separator . ", "))) - (booktitle . ((font-style . italics) - (suffix . "") - (field-separator . "in "))) - (journal . ((suffix . "") - (field-separator . ", "))) - ;; here we use some logic to group volume(issue) or volume - (volume . ((suffix . (when (orcp-get-entry-field "number" entry) - (orcp-issue entry))) - (field-separator . ", "))) - (issue . ((font-style . bold) - (prefix . "(") - (suffix . ")") - (field-separator . ", "))) - (pages . ((prefix . "pp. ") - (suffix . "") - (field-separator . " ") - (collapse-range . nil))) - (year . ((prefix . "(") - (suffix . ")") - (field-separator . "."))) - (doi . ((prefix . " ") - (suffix . ".") - (field-separator . "") - (formatter . orcp-doi-formatter))) - ;; Formatting of entries - (entries . ((article . (author title journal volume pages year doi)) - (inproceedings . (author title booktitle year)) - (book . (author title year)) - (misc . (author title url doi)) - (techreport . (author title institution year)) - (mastersthesis . (author title school year)) - (phdthesis . (author title school year)) - (t . (author title year)))))) - -(provide 'unsrt) - -;;; unsrt.el ends here diff --git a/lisp/org-ref/citeproc/readme-author-year.org b/lisp/org-ref/citeproc/readme-author-year.org deleted file mode 100644 index cb77f4e9..00000000 --- a/lisp/org-ref/citeproc/readme-author-year.org +++ /dev/null @@ -1,92 +0,0 @@ -* DONE Introduction to a citation processor in org-ref - CLOSED: [2015-12-11 Fri 18:05] - :PROPERTIES: - :categories: emacs,orgref,orgmode,citations - :date: 2015/12/11 18:05:43 - :updated: 2015/12/11 18:22:40 - :END: - -As a potential solution for citions in org-mode for non-LaTeX export, here we introduce csl (citation syntax lisp). The idea is heavily influenced by the xml-based Citation Syntax Language, but uses lisp sexps instead. - -Briefly, there is a csl file that contains two variables: citation-style and bibliography-style. The citation-style defines how the in-text citations are represented for different types of citations. The bibliography-style defines how the bibliography is constructed. - -What do we gain by this? -1. No need for external citeproc program, and hackability by org-mode experts. -2. Punctuation transposition and space chomping, i.e. put superscripts on the right side of punctuation if you want it, and remove whitespace before superscripts if you want it. -3. Total tunability of the citation format to different backends. -4. Easy to change bibliography format with the bibliographystyle link. -5. The use of Bibtex databases. These are plain text, and flexible. - -The real code for this is too long to blog about. Instead, you should check it out here: https://github.com/jkitchin/org-ref/tree/master/citeproc - -** Reference types - -- A book cite:kittel-2005-introd-solid. - -- An article cite:kitchin-2015-examp - -- A miscellaneous bibtex type cite:xu-suppor. - -There is work to do in supporting other types of entry types that are common in bibtex files. - -** Citation types - -- Regular citation: cite:kitchin-2015-examp -- citenum: See Ref. citenum:kitchin-2015-examp -- citeauthor: citeauthor:kitchin-2015-examp -- citeyear: citeyear:kitchin-2015-examp - -There is work to do in supporting other types of citations. - -** Multiple citations and sorting within citation -You can specify that the cites within a citation are consistently sorted in the export. - -- a,b: cite:kitchin-2015-examp,kitchin-2015-data-surfac-scien -- b,a: cite:kitchin-2015-data-surfac-scien,kitchin-2015-examp - -There is work to do for range collapsing, e.g. to turn 1,2,3 into 1-3. -** Space chomping and punctuation testing -I think citations should always be put in the sentence they logically belong to. LaTeX has a feature through natbib I think where for some styles, e.g. superscripts, the citations are moved to the right side of punctuation, and whitespace is chomped so the superscript is next to words, not separated by spaces. We can do that here too. - -- Citation at end of sentence cite:kitchin-2015-examp. -- Citation in clause cite:kitchin-2015-examp,kitchin-2015-data-surfac-scien, with a comma. -- Citation in middle of cite:kitchin-2015-examp,kitchin-2015-data-surfac-scien a sentence. - -** Building - :PROPERTIES: - :date: 2015/12/11 14:47:59 - :updated: 2015/12/11 14:48:26 - :END: - -At the moment, you have to add a hook function to put the replacements in the document before parsing. - -#+BEGIN_SRC emacs-lisp -(add-to-list 'load-path ".") -(require 'org-ref-citeproc) - -(let ((org-export-before-parsing-hook '(orcp-citeproc))) - (browse-url (org-html-export-to-html))) -#+End_src - -#+RESULTS: -: # - - -** Summary thoughts -This looks promising. There is probably a lot of work to do to make this as robust as say citeproc-js or the Zotero handler. I am not sure if we could write this in a way to directly use the CSL. My feeling is it would not be as flexible as this, and we would have to add to it anyway. - -Here are some remaining things that could be worked on if we continue this direction. - -1. Other bibtex entries need to be tested out. -2. Remaining bibtex fields need to be defined. -3. Standardization of styling that can be done. Not all features described in my csl are supported, e.g. et. al. and probably others. -4. The author-year style needs name disambiguation somehow. -5. Hyperlinking in html. -6. Make sure export to other backends works. -7. Can this work for notes-based styles? - -** Bibliography -You use a bibliographystyle link to specify a csl. These are similar to bibtex styles, and in some cases no change is needed for LaTeX export (although you may have to remove the citeproc hook function). - -bibliographystyle:author-year -bibliography:~/Dropbox/bibliography/references.bib diff --git a/lisp/org-ref/citeproc/readme-unsrt.org b/lisp/org-ref/citeproc/readme-unsrt.org deleted file mode 100644 index cf4d0bd7..00000000 --- a/lisp/org-ref/citeproc/readme-unsrt.org +++ /dev/null @@ -1,93 +0,0 @@ -* DONE Introduction to a citation processor in org-ref - CLOSED: [2015-12-11 Fri 18:05] - :PROPERTIES: - :categories: emacs,orgref,orgmode,citations - :date: 2015/12/11 18:05:43 - :updated: 2015/12/11 18:22:40 - :END: - -As a potential solution for citions in org-mode for non-LaTeX export, here we introduce csl (citation syntax lisp). The idea is heavily influenced by the xml-based Citation Syntax Language, but uses lisp sexps instead. - -Briefly, there is a csl file that contains two variables: citation-style and bibliography-style. The citation-style defines how the in-text citations are represented for different types of citations. The bibliography-style defines how the bibliography is constructed. - -What do we gain by this? -1. No need for external citeproc program, and hackability by org-mode experts. -2. Punctuation transposition and space chomping, i.e. put superscripts on the right side of punctuation if you want it, and remove whitespace before superscripts if you want it. -3. Total tunability of the citation format to different backends. -4. Easy to change bibliography format with the bibliographystyle link. -5. The use of Bibtex databases. These are plain text, and flexible. - -The real code for this is too long to blog about. Instead, you should check it out here: https://github.com/jkitchin/org-ref/tree/master/citeproc - -** Reference types - -- A book cite:kittel-2005-introd-solid. - -- An article cite:kitchin-2015-examp - -- A miscellaneous bibtex type cite:xu-suppor. - -There is work to do in supporting other types of entry types that are common in bibtex files. - -** Citation types - -- Regular citation: cite:kitchin-2015-examp -- citenum: See Ref. citenum:kitchin-2015-examp -- citeauthor: citeauthor:kitchin-2015-examp -- citeyear: citeyear:kitchin-2015-examp - -There is work to do in supporting other types of citations. - -** Multiple citations and sorting within citation -You can specify that the cites within a citation are consistently sorted in the export. - -- a,b: cite:kitchin-2015-examp,kitchin-2015-data-surfac-scien -- b,a: cite:kitchin-2015-data-surfac-scien,kitchin-2015-examp - -There is work to do for range collapsing, e.g. to turn 1,2,3 into 1-3. -** Space chomping and punctuation testing -I think citations should always be put in the sentence they logically belong to. LaTeX has a feature through natbib I think where for some styles, e.g. superscripts, the citations are moved to the right side of punctuation, and whitespace is chomped so the superscript is next to words, not separated by spaces. We can do that here too. - -- Citation at end of sentence cite:kitchin-2015-examp. -- Citation in clause cite:kitchin-2015-examp,kitchin-2015-data-surfac-scien, with a comma. -- Citation in middle of cite:kitchin-2015-examp,kitchin-2015-data-surfac-scien a sentence. - -** Building - :PROPERTIES: - :date: 2015/12/11 14:47:59 - :updated: 2015/12/11 14:48:26 - :END: - -At the moment, you have to add a hook function to put the replacements in the document before parsing. - -#+BEGIN_SRC emacs-lisp -(add-to-list 'load-path ".") -(require 'org-ref-citeproc) - -(when (file-exists-p "readme.html") (delete-file "readme.html")) -(let ((org-export-before-parsing-hook '(orcp-citeproc))) - (browse-url (org-html-export-to-html))) -#+End_src - -#+RESULTS: -: # - - -** Summary thoughts -This looks promising. There is probably a lot of work to do to make this as robust as say citeproc-js or the Zotero handler. I am not sure if we could write this in a way to directly use the CSL. My feeling is it would not be as flexible as this, and we would have to add to it anyway. - -Here are some remaining things that could be worked on if we continue this direction. - -1. Other bibtex entries need to be tested out. -2. Remaining bibtex fields need to be defined. -3. Standardization of styling that can be done. Not all features described in my csl are supported, e.g. et. al. and probably others. -4. The author-year style needs name disambiguation somehow. -5. Hyperlinking in html. -6. Make sure export to other backends works. -7. Can this work for notes-based styles? - -** Bibliography -You use a bibliographystyle link to specify a csl. These are similar to bibtex styles, and in some cases no change is needed for LaTeX export (although you may have to remove the citeproc hook function). - -bibliographystyle:unsrt -bibliography:~/Dropbox/bibliography/references.bib diff --git a/lisp/org-ref/citeproc/readme.bib b/lisp/org-ref/citeproc/readme.bib deleted file mode 100644 index 3685a3b4..00000000 --- a/lisp/org-ref/citeproc/readme.bib +++ /dev/null @@ -1,203 +0,0 @@ - -@techreport{2011-mater-genom, - title = {Materials Genome Initiative for Global Competitiveness}, - institution = {National Science and Technology Council}, - year = {2011}, - type = {Report} -} - -@phdthesis{Hossein-thesis, - author = {Hossein Pourmatin}, - title = {Computational Multiscale Methods for Defects: 1. Line Defects - in Liquid Crystals; 2. Electron Scattering in Defected - Crystals}, - school = {Carnegie Mellon University}, - year = 2014, - note = {Available at - \url{sites.google.com/site/kaushikdayal/publications#Theses}} -} - -@inproceedings{abolhasani-2011-model, - Author = {Abolhasani, M. and Kumacheva, E. and G{\"u}nther, - A.}, - Title = {Model-predictive Strategy for Exploration of Carbon - Dioxide Dissolution and Mass Transfer}, - Booktitle = {15th International Conference on Miniaturized - Systems for Chemistry and Life Sciences}, - Year = 2011, - Month = {October}, - Url = - {"http://www.rsc.org/images/LOC/2011/PDFs/Papers/224_1180.pdf} -} - -@article{anderson-1977-raman, - author = {George R. Anderson}, - title = {The {R}aman Spectra of Carbon Dioxide in Liquid Water and - Water-D2}, - journal = {J. Phys. Chem.}, - volume = 81, - number = 3, - pages = {273-276}, - year = 1977, - doi = {10.1021/j100518a017}, - url = {http://dx.doi.org/10.1021/j100518a017}, - month = 2, - eprint = {http://pubs.acs.org/doi/pdf/10.1021/j100518a017}, -} - -@MastersThesis{ding-2012-metal-oxide, - author = {Zhizhong Ding}, - title = {Metal Oxide Oxygen Carriers for Chemical-Looping Combustion}, - school = {Carnegie Mellon University}, - year = 2012} - -@article{kitchin-2015-data-surfac-scien, - author = "John R. Kitchin", - title = {Data Sharing in Surface Science}, - journal = "Surface Science ", - volume = "N/A", - pages = "in press", - year = 2015, - doi = {10.1016/j.susc.2015.05.007}, - url = - "http://www.sciencedirect.com/science/article/pii/S0039602815001326", - issn = "0039-6028", - keywords = {DESC0004031, early-career, orgmode, Data sharing }, -} - -@article{kitchin-2015-examp, - author = {Kitchin, John R.}, - title = {Examples of Effective Data Sharing in Scientific Publishing}, - journal = {ACS Catalysis}, - volume = {5}, - number = {6}, - pages = {3894-3899}, - year = 2015, - doi = {10.1021/acscatal.5b00538}, - url = { http://dx.doi.org/10.1021/acscatal.5b00538 }, - keywords = {DESC0004031, early-career, orgmode, Data sharing }, - eprint = { http://dx.doi.org/10.1021/acscatal.5b00538 }, -} - -@book{kittel-2005-introd-solid, - author = {Charles Kittel}, - title = {Introduction to Solid State Physics}, - publisher = {Wiley}, - year = 2005, - edition = {8th} -} - -@misc{xu-suppor, - author = {Zhongnan Xu and Jan Rossmeisl and John R. Kitchin}, - title = {Supporting data for: A linear response, {DFT+U} study of trends - in the oxygen evolution activity of transition metal rutile - dioxides. doi:10.5281/zenodo.12635}, - keywords = {DESC0004031, early-career, }, - year = {2015}, - url = {https://zenodo.org/record/12635}, - doi = {10.5281/zenodo.12635} -} - -@article{ye-2012-proces-charac, - author = {Y. E. Chunbo and Guangwen CHEN and Quan YUAN}, - title = {Process Characteristics of \ce{CO2} Absorption By Aqueous - Monoethanolamine in a Microchannel Reactor}, - journal = {Chinese Journal of Chemical Engineering}, - volume = 20, - number = 1, - pages = {111-119}, - year = 2012, - doi = {10.1016/s1004-9541(12)60370-x}, - url = {http://dx.doi.org/10.1016/S1004-9541(12)60370-X}, -} - -@article{yeo-2012-in-situ, - author = {Yeo, Boon Siang and Bell, Alexis T.}, - title = {In Situ {R}aman Study of Nickel Oxide and Gold-Supported - Nickel Oxide Catalysts for the Electrochemical Evolution of - Oxygen}, - journal = {The Journal of Physical Chemistry C}, - volume = 116, - number = 15, - pages = {8394-8400}, - year = 2012, - doi = {10.1021/jp3007415}, - url = {http://pubs.acs.org/doi/abs/10.1021/jp3007415}, - eprint = {http://pubs.acs.org/doi/pdf/10.1021/jp3007415}, -} - -@article{zhu-2013-sulfur, - author = {Zhu, Qingjun and Wegener, Staci L. and Xie, Chao and Uche, - Obioma and Neurock, Matthew and Marks, Tobin J.}, - title = {Sulfur As a Selective "soft" Oxidant for Catalytic Methane - Conversion Probed By Experiment and Theory}, - journal = {Nature chemistry}, - volume = 5, - pages = {104-109}, - year = 2013, - doi = "10.1002/ange.201311111", - url = - "http://www.nature.com/nchem/journal/v5/n2/full/nchem.1527.html", -} - -@article{lizzit-2001-surfac-ru, - author = {S. Lizzit and A. Baraldi and A. Groso and K. Reuter and M. V. - Ganduglia-Pirovano and C. Stampfl and M. Scheffler and M. - Stichler and C. Keller and W. Wurth and D. Menzel}, - title = {Surface Core-Level Shifts of Clean and Oxygen-Covered - {Ru}(0001)}, - journal = {Phys. Rev. B}, - volume = 63, - number = 20, - pages = {205419}, - year = 2001, - doi = {10.1103/physrevb.63.205419}, - url = {http://dx.doi.org/10.1103/physrevb.63.205419}, - date_added = {Mon Nov 16 16:28:01 2015}, -} - -@article{weaver-2011-high-selec, - author = {Jason F. Weaver and Can Hakanoglu and Abbin Antony and Aravind - Asthagiri}, - title = {High Selectivity for Primary {C-H} Bond Cleavage of Propane - $\sigma$-complexes on the {PdO}(101) Surface}, - keywords = {alkane}, - journal = {J. Am. Chem. Soc.}, - volume = 133, - number = 40, - pages = {16196-16200}, - year = 2011, - doi = {10.1021/ja206599k}, - url = {http://dx.doi.org/10.1021/ja206599k}, - date_added = {Sat Nov 28 09:10:59 2015}, -} - -@article{antony-2012-pathw-c, - author = {Abbin Antony and Aravind Asthagiri and Jason F. Weaver}, - title = {Pathways for {C-H} Bond Cleavage of Propane $\sigma$-complexes on - {PdO}(101)}, - keywords = {alkane}, - journal = {Phys. Chem. Chem. Phys.}, - volume = 14, - number = 35, - pages = 12202, - year = 2012, - doi = {10.1039/c2cp41900a}, - url = {http://dx.doi.org/10.1039/c2cp41900a}, - date_added = {Sat Nov 28 09:13:32 2015}, -} - -@article{wang-2013-immob-co2, - author = {Xianfeng Wang and Novruz G. Akhmedov and Yuhua Duan and David - Luebke and Bingyun Li}, - title = {Immobilization of Amino Acid Ionic Liquids Into Nanoporous - Microspheres As Robust Sorbents for CO2 Capture}, - journal = {J. Mater. Chem. A}, - volume = 1, - number = 9, - pages = 2978, - year = 2013, - doi = {10.1039/c3ta00768e}, - url = {http://dx.doi.org/10.1039/C3TA00768E}, - date_added = {Thu Dec 3 06:13:09 2015}, -} diff --git a/lisp/org-ref/citeproc/readme.org b/lisp/org-ref/citeproc/readme.org deleted file mode 100644 index dfefd263..00000000 --- a/lisp/org-ref/citeproc/readme.org +++ /dev/null @@ -1,1676 +0,0 @@ - -http://editor.citationstyles.org/styleInfo/?styleId=http%3A%2F%2Fwww.zotero.org%2Fstyles%2Facs-nano - -http://docs.citationstyles.org/en/stable/primer.html#preface - -* DONE Introduction to a citation processor in org-ref - CLOSED: [2015-12-11 Fri 18:05] - :PROPERTIES: - :categories: emacs,orgref,orgmode,citations - :date: 2015/12/11 18:05:43 - :updated: 2015/12/12 10:08:10 - :END: - -As a potential solution for citations in org-mode for non-LaTeX export, here we introduce csl (citation syntax lisp). The idea is heavily influenced by the xml-based Citation Syntax Language, but uses lisp sexps instead. - -Briefly, there is a csl file that contains two variables: citation-style and bibliography-style. The citation-style defines how the in-text citations are represented for different types of citations. The bibliography-style defines how the bibliography is constructed. - -What do we gain by this? -1. No need for external citeproc program, and hackability by org-mode experts. -2. Punctuation transposition and space chomping, i.e. put superscripts on the right side of punctuation if you want it, and remove whitespace before superscripts if you want it. -3. Total tunability of the citation format to different backends. -4. Easy to change bibliography format with the bibliographystyle link. -5. The use of Bibtex databases. These are plain text, and flexible. - -The real code for this is too long to blog about. Instead, you should check it out here: https://github.com/jkitchin/org-ref/tree/master/citeproc - -** Reference types - -- A book cite:kittel-2005-introd-solid. - -- An article cite:kitchin-2015-examp - -- A miscellaneous bibtex type cite:xu-suppor. - -- A technical report cite:2011-mater-genom - -- An MS thesis: cite:ding-2012-metal-oxide - -- A PhD thesis: cite:Hossein-thesis - -- in proceedings: cite:abolhasani-2011-model - -There is work to do in supporting other types of entry types that are common in bibtex files. - -** Citation types - -- Regular citation: cite:kitchin-2015-examp -- citenum: See Ref. citenum:kitchin-2015-examp -- citeauthor: citeauthor:kitchin-2015-examp -- citeyear: citeyear:kitchin-2015-examp - -There is work to do in supporting other types of citations. - -** Multiple citations and sorting within citation -You can specify that the cites within a citation are consistently sorted in the export. - -- a,b: cite:kitchin-2015-examp,kitchin-2015-data-surfac-scien -- b,a: cite:kitchin-2015-data-surfac-scien,kitchin-2015-examp - -There is work to do for range collapsing, e.g. to turn 1,2,3 into 1-3. -** Space chomping and punctuation testing -I think citations should always be put in the sentence they logically belong to. LaTeX has a feature through natbib I think where for some styles, e.g. superscripts, the citations are moved to the right side of punctuation, and whitespace is chomped so the superscript is next to words, not separated by spaces. We can do that here too. - -- Citation at end of sentence cite:kitchin-2015-examp. -- Citation in clause cite:kitchin-2015-examp,kitchin-2015-data-surfac-scien, with a comma. -- Citation in middle of cite:kitchin-2015-examp,kitchin-2015-data-surfac-scien a sentence. - -** Building - :PROPERTIES: - :date: 2015/12/11 14:47:59 - :updated: 2015/12/11 14:48:26 - :END: - -At the moment, you have to add a hook function to put the replacements in the document before parsing. - -#+BEGIN_SRC emacs-lisp -(add-to-list 'load-path ".") -(require 'org-ref-citeproc) - -(when (file-exists-p "readme.html") (delete-file "readme.html")) -(let ((org-export-before-parsing-hook '(orcp-citeproc))) - (browse-url (org-html-export-to-html))) -#+End_src - -#+RESULTS: -: # - -An org export for footnotes. The footnotes don't go where I expect. -#+BEGIN_SRC emacs-lisp -(add-to-list 'load-path ".") -(require 'org-ref-citeproc) - -(let ((org-export-before-parsing-hook '(orcp-citeproc))) - (org-open-file (org-org-export-to-org))) -#+End_src - -#+RESULTS: -: Position saved to mark ring, go back with C-c &. - -** Summary thoughts -This looks promising. There is probably a lot of work to do to make this as robust as say citeproc-js or the Zotero handler. I am not sure if we could write this in a way to directly use the CSL. My feeling is it would not be as flexible as this, and we would have to add to it anyway. - -Here are some remaining things that could be worked on if we continue this direction. - -1. Other bibtex entries need to be tested out. -2. Remaining bibtex fields need to be defined. -3. Standardization of styling that can be done. Not all features described in my csl are supported, e.g. et. al. and probably others. -4. The author-year style needs name disambiguation somehow. -5. Hyperlinking in org, html. -6. Make sure export to other backends works. Can this make a LaTeX output with bibitems? -7. Can this work for notes-based styles? - -** Bibliography -You use a bibliographystyle link to specify a csl. These are similar to bibtex styles, and in some cases no change is needed for LaTeX export (although you may have to remove the citeproc hook function). - -bibliographystyle:unsrt-footnote -bibliography:readme.bib - - -* Archive work -These are sections I worked on developing the working approach. -** Parsing bibtex names -Partially derived from http://nwalsh.com/tex/texhelp/bibtx-23.html - -see also http://ctan.mirrors.hoobly.com/biblio/bibtex/base/btxdoc.pdf - - -Bibtex names have 4 parts: -1. First name, which also includes middle name/initial -2. von which is part of the last name, but in lower case letters -3. Last name -4. Jr. - -Here are some acceptable formats for names in Bibtex. -#+BEGIN_EXAMPLE -"First von Last" -"von Last, First" -"von Last, Jr, First" -#+END_EXAMPLE - -Note, it is also possible to have in Bibtex, in which case the von part becomes part of the last name. -#+BEGIN_EXAMPLE -"Jan A. {van Mieghem}" -"{van Mieghem}, Jan A." -#+END_EXAMPLE - -And also - -#+BEGIN_EXAMPLE -De Gaulle, Charles -Van Buren, Martin -Scott Thomas, Kristin -Bonham Carter, Helena -Garcia Pascual, Antonio -Del Negro, Marco -Van Gogh, Vincent -Della Francesca, Piero - -Charles {De Gaulle} -Martin {Van Buren} -Kristin {Scott Thomas} -Helena {Bonham Carter} -Antonio {Garcia Pascual} -Marco {Del Negro} -Vincent {Van Gogh} -Piero {Della Francesca} -#+END_EXAMPLE - -Dealing with these brackets is somewhat tricky. We cannot simply split on spaces with these present. A hack I will use is to replace them temporarily with something that looks like a name part, parse, and then put them back. Otherwise, we need a real recursive descent parser. I will use a uuid that starts with a capital letter. We develop an elisp function to parse these into a data structure: (first von last jr). - - - -#+BEGIN_SRC emacs-lisp - - -#+END_SRC - -#+RESULTS: -: citeproc-parse-authorname - -Here are examples of case 1. -#+BEGIN_SRC emacs-lisp -(cl-loop for author in '("John R. Kitchin" - "John von Kitchin" - "John von de La von Kitchin" - "John von de Kitchin Jr." - "John {von de Kitchin}" - "John Paul Jones" - "Charles Louis Xavier Joseph de la Vallee Poussin" - "Ludwig von Beethoven" - "Jan A. {van Mieghem}" - "Vincent {Van Gogh}" - "Piero {Della Francesca}" - "{Barnes and Noble}" - "{Barnes & Noble}") - collect (citeproc-parse-authorname author)) -#+END_SRC - -#+RESULTS: -| John R. | nil | Kitchin | nil | -| John | von | Kitchin | nil | -| John | von de La von | Kitchin | nil | -| John | von de | Kitchin Jr. | nil | -| John | nil | {von de Kitchin} | nil | -| John Paul | nil | Jones | nil | -| Charles Louis Xavier Joseph | de la | Vallee Poussin | nil | -| Ludwig | von | Beethoven | nil | -| Jan A. | nil | {van Mieghem} | nil | -| Vincent | nil | {Van Gogh} | nil | -| Piero | nil | {Della Francesca} | nil | -| | nil | {Barnes and Noble} | nil | -| | nil | {Barnes & Noble} | nil | - -Case 2. -#+BEGIN_SRC emacs-lisp -(cl-loop for author in '("von Beethoven, Ludwig" - "{van {M}ieghem}, Jan A." - "De Gaulle, Charles" - "Van Buren, Martin" - "Scott Thomas, Kristin" - "Bonham Carter, Helena" - "Garcia Pascual, Antonio" - "Del Negro, Marco" - "Van Gogh, Vincent" - "Della Francesca, Piero") - collect (citeproc-parse-authorname author)) -#+END_SRC - -#+RESULTS: -| Ludwig | von | Beethoven | nil | -| Jan A. | nil | {van {M}ieghem} | nil | -| Charles | nil | De Gaulle | nil | -| Martin | nil | Van Buren | nil | -| Kristin | nil | Scott Thomas | nil | -| Helena | nil | Bonham Carter | nil | -| Antonio | nil | Garcia Pascual | nil | -| Marco | nil | Del Negro | nil | -| Vincent | nil | Van Gogh | nil | -| Piero | nil | Della Francesca | nil | - -And case 3 -#+BEGIN_SRC emacs-lisp -(cl-loop for author in '("von de la Kitchin, Sr., John Robert" - "von Kitchin, Sr., John Robert") - collect (citeproc-parse-authorname author)) -#+END_SRC - -#+RESULTS: -| John Robert | von de la | Kitchin | Sr. | -| John Robert | von | Kitchin | Sr. | - - -I am pretty satisfied with that. This is a foundation for formatting author names in a bibliography. Note the bibtex function `bibtex-autokey-demangle-name' function has some similar code for getting a last name to use as the key. - -From http://maverick.inria.fr/~Xavier.Decoret/resources/xdkbibtex/bibtex_summary.html#names -#+BEGIN_SRC emacs-lisp -(cl-loop for author in '("Aa Bb" - "Aa" - "Aa bb" - "aa" - "Aa bb Cc" - "Aa bb Cc dd Ee" - "Aa 1B cc dd" - "Aa 1b cc dd" - "Aa {b}B cc dd" - "Aa {b}b cc dd" - "Aa {B}b cc dd" - "Aa {B}B cc dd" - "Aa \\Bb{b} cc dd" - "Aa \\bb{b} cc dd" - "{Lastname with {,} in it}, Formerly Known as" - "Aa {bb} cc Dd" - "Aa bb {cc} Dd" - "Aa {bb} Cc") - collect (citeproc-parse-authorname author)) -#+END_SRC - -#+RESULTS: -| Aa | nil | Bb | nil | -| nil | nil | Aa | nil | -| Aa | nil | bb | nil | -| nil | nil | aa | nil | -| Aa | bb | Cc | nil | -| Aa | bb Cc dd | Ee | nil | -| Aa | 1B cc | dd | nil | -| Aa | 1b cc | dd | nil | -| Aa | {b}B cc | dd | nil | -| Aa {b}b | cc | dd | nil | -| Aa {B}b | cc | dd | nil | -| Aa | {B}B cc | dd | nil | -| Aa | \Bb{b} cc | dd | nil | -| Aa | \bb{b} cc | dd | nil | -| Formerly Known as | nil | {Lastname with {,} in it} | nil | -| Aa {bb} | cc | Dd | nil | -| Aa | bb | {cc} Dd | nil | -| Aa {bb} | nil | Cc | nil | - - -I think this does about what it is supposed to do. Another function would be responsible for formatting the author name as required, e.g. putting initials in, the order of the names, etc... - -Another function after that would be responsible for formatting a group of authors, e.g. specifying the delimiter between them, the trailing character after the authors, if et al should be used after some number of authors, etc... - -Finally, I don't consider any transformations of the author strings, e.g. if there are LaTeX commands or other markup in them. This gets passed verbatim to what ever is next. - -** Collapse numeric ranges -Make (1 2 3 4 7 9) be "1-4,7,9" - -#+BEGIN_SRC emacs-lisp -(defun collapse-range (cites) - "CITES is a list of at least 3 numbers." - (let (n - (groups '())) - (while cites - (setq n (pop cites)) - (if (and (caar groups) (= (- n 1) (elt (car groups) 0))) - (setf (car groups) (append `(,n) (car groups))) - (setf groups (append `((,n)) groups)))) - ;; Now for each group - (mapconcat 'identity - (mapcar - (lambda (lst) - (cond - ((>= (length lst) 3) - (format "%s-%s" (car lst) (car (last lst)))) - ((= (length lst) 2) - (format "%s,%s" (nth 0 lst) (nth 1 lst))) - (t - (number-to-string (car lst))))) - (mapcar 'reverse (reverse groups))) - ","))) - -(collapse-range '(1 2)) - -#+END_SRC - -#+RESULTS: -: 1,2 - -** CSL parsing - -*** Info nodes -This seems to be information about a CSL. -#+BEGIN_SRC emacs-lisp -(let (xml) - (setq xml (with-temp-buffer - (insert-file-contents "acs-nano.csl") - (libxml-parse-xml-region (point-min) (point-max)))) - (xml-get-children xml 'info)) -#+END_SRC - -#+RESULTS: -#+BEGIN_SRC emacs-lisp -((info nil - (title nil "ACS Nano") - (title-short nil "ACS Nano") - (id nil "http://www.zotero.org/styles/acs-nano") - (link - ((href . "http://www.zotero.org/styles/acs-nano") - (rel . "self"))) - (link - ((href . "http://www.zotero.org/styles/american-chemical-society-with-titles") - (rel . "template"))) - (link - ((href . "http://pubs.acs.org/paragonplus/submission/ancac3/ancac3_authguide.pdf") - (rel . "documentation"))) - (category - ((citation-format . "numeric"))) - (category - ((field . "chemistry"))) - (issn nil "1936-0851") - (eissn nil "1936-086X") - (summary nil "ACS style with et al in italics") - (updated nil "2014-09-21T00:39:49+00:00") - (rights - ((license . "http://creativecommons.org/licenses/by-sa/3.0/")) - "This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License"))) -#+END_SRC - -*** Macro nodes -These seem to define inputs to a function that formats each field of an entry. - -#+BEGIN_SRC emacs-lisp -(let (xml) - (setq xml (with-temp-buffer - (insert-file-contents "acs-nano.csl") - (libxml-parse-xml-region (point-min) (point-max)))) - (xml-get-children xml 'macro)) -#+END_SRC - -#+RESULTS: -#+BEGIN_SRC emacs-lisp -((macro - ((name . "editor")) - (names - ((variable . "editor")) - (name - ((sort-separator . ", ") - (initialize-with . ". ") - (name-as-sort-order . "all") - (delimiter . "; ") - (delimiter-precedes-last . "always"))) - (et-al - ((font-style . "italic"))) - (label - ((form . "short") - (prefix . ", ") - (text-case . "capitalize-first"))))) - (macro - ((name . "author")) - (names - ((variable . "author") - (suffix . ".")) - (name - ((sort-separator . ", ") - (initialize-with . ". ") - (name-as-sort-order . "all") - (delimiter . "; ") - (delimiter-precedes-last . "always"))) - (et-al - ((font-style . "italic"))) - (label - ((form . "short") - (prefix . ", ") - (text-case . "capitalize-first"))))) - (macro - ((name . "publisher")) - (group - ((delimiter . ": ")) - (text - ((variable . "publisher"))) - (text - ((variable . "publisher-place"))))) - (macro - ((name . "title")) - (choose nil - (if - ((type . "bill book graphic legal_case legislation motion_picture report song") - (match . "any")) - (text - ((variable . "title") - (text-case . "title") - (font-style . "italic")))) - (else nil - (text - ((variable . "title") - (text-case . "title")))))) - (macro - ((name . "volume")) - (group - ((delimiter . " ")) - (text - ((term . "volume") - (form . "short") - (text-case . "capitalize-first"))) - (text - ((variable . "volume"))))) - (macro - ((name . "series")) - (text - ((variable . "collection-title")))) - (macro - ((name . "pages")) - (label - ((variable . "page") - (form . "short") - (suffix . " "))) - (text - ((variable . "page")))) - (macro - ((name . "book-container")) - (group - ((delimiter . " ")) - (text - ((macro . "title") - (suffix . "."))) - (text - ((term . "in") - (text-case . "capitalize-first"))) - (text - ((variable . "container-title") - (font-style . "italic"))))) - (macro - ((name . "issued")) - (date - ((variable . "issued") - (delimiter . " ")) - (date-part - ((name . "year"))))) - (macro - ((name . "full-issued")) - (date - ((variable . "issued") - (delimiter . " ")) - (date-part - ((name . "month") - (form . "long") - (suffix . " "))) - (date-part - ((name . "day") - (suffix . ", "))) - (date-part - ((name . "year"))))) - (macro - ((name . "edition")) - (choose nil - (if - ((is-numeric . "edition")) - (group - ((delimiter . " ")) - (number - ((variable . "edition") - (form . "ordinal"))) - (text - ((term . "edition") - (form . "short"))))) - (else nil - (text - ((variable . "edition") - (suffix . "."))))))) -#+END_SRC - -*** Citation overlay -This seems to define the layout of a citation in the text, how they are sorted, collapsed, and delimited. - -#+BEGIN_SRC emacs-lisp -,#+BEGIN_SRC emacs-lisp :results code -(let (xml) - (setq xml (with-temp-buffer - (insert-file-contents "acs-nano.csl") - (libxml-parse-xml-region (point-min) (point-max)))) - (xml-get-children xml 'citation)) -#+END_SRC - -#+RESULTS: -#+BEGIN_SRC emacs-lisp -((citation - ((collapse . "citation-number")) - (sort nil - (key - ((variable . "citation-number")))) - (layout - ((delimiter . ",") - (vertical-align . "sup")) - (text - ((variable . "citation-number")))))) -#+END_SRC - -*** Bibliography - -This seems to layout how the bibliography is constructed. -#+BEGIN_SRC emacs-lisp -(let (xml) - (setq xml (with-temp-buffer - (insert-file-contents "acs-nano.csl") - (libxml-parse-xml-region (point-min) (point-max)))) - (xml-get-children xml 'bibliography)) -#+END_SRC - -#+RESULTS: -#+BEGIN_SRC emacs-lisp -((bibliography - ((second-field-align . "flush") - (entry-spacing . "0") - (et-al-min . "11") - (et-al-use-first . "10")) - (layout - ((suffix . ".")) - (text - ((variable . "citation-number") - (prefix . "(") - (suffix . ") "))) - (text - ((macro . "author") - (suffix . " "))) - (choose nil - (if - ((type . "article-magazine")) - (group - ((delimiter . " ")) - (text - ((macro . "title") - (suffix . "."))) - (text - ((variable . "container-title") - (font-style . "italic") - (suffix . "."))) - (text - ((macro . "edition"))) - (text - ((macro . "publisher"))) - (text - ((macro . "full-issued") - (suffix . ","))) - (text - ((macro . "pages"))))) - (else-if - ((type . "thesis")) - (group - ((delimiter . ", ")) - (group - ((delimiter . ". ")) - (text - ((macro . "title"))) - (text - ((variable . "genre")))) - (text - ((macro . "publisher"))) - (text - ((macro . "issued"))) - (text - ((macro . "volume"))) - (text - ((macro . "pages"))))) - (else-if - ((type . "bill book graphic legal_case legislation motion_picture report song") - (match . "any")) - (group - ((delimiter . "; ")) - (text - ((macro . "title"))) - (text - ((macro . "editor") - (prefix . " "))) - (text - ((macro . "series"))) - (text - ((macro . "edition"))) - (choose nil - (if - ((type . "report")) - (group - ((delimiter . " ")) - (text - ((variable . "genre"))) - (text - ((variable . "number")))))) - (group - ((delimiter . ", ")) - (text - ((macro . "publisher"))) - (text - ((macro . "issued")))) - (group - ((delimiter . ", ")) - (text - ((macro . "volume"))) - (text - ((macro . "pages")))))) - (else-if - ((type . "patent")) - (group - ((delimiter . ", ")) - (group - ((delimiter . ". ")) - (text - ((macro . "title"))) - (text - ((variable . "number")))) - (date - ((variable . "issued") - (form . "text"))))) - (else-if - ((type . "chapter paper-conference") - (match . "any")) - (group - ((delimiter . "; ")) - (text - ((macro . "book-container"))) - (text - ((macro . "editor"))) - (text - ((macro . "series"))) - (group - ((delimiter . ", ")) - (text - ((macro . "publisher"))) - (text - ((macro . "issued")))) - (group - ((delimiter . ", ")) - (text - ((macro . "volume"))) - (text - ((macro . "pages")))))) - (else-if - ((type . "webpage")) - (group - ((delimiter . " ")) - (text - ((variable . "title"))) - (text - ((variable . "URL"))) - (date - ((variable . "accessed") - (prefix . "(accessed ") - (suffix . ")") - (delimiter . " ")) - (date-part - ((name . "month") - (form . "short") - (strip-periods . "true"))) - (date-part - ((name . "day") - (suffix . ", "))) - (date-part - ((name . "year")))))) - (else-if - ((type . "article-journal")) - (group - ((delimiter . " ")) - (text - ((macro . "title") - (suffix . "."))) - (text - ((variable . "container-title") - (font-style . "italic") - (form . "short"))) - (group - ((delimiter . ", ")) - (text - ((macro . "issued") - (font-weight . "bold"))) - (text - ((variable . "volume") - (font-style . "italic"))) - (text - ((variable . "page")))))) - (else nil - (group - ((delimiter . ", ")) - (group - ((delimiter . ". ")) - (text - ((macro . "title"))) - (text - ((variable . "container-title") - (font-style . "italic")))) - (group - ((delimiter . ", ")) - (text - ((macro . "issued"))) - (text - ((variable . "volume") - (font-style . "italic"))) - (text - ((variable . "page")))))))))) -#+END_SRC - -**** Layout of entry -Here we get the layout of an entry. -#+BEGIN_SRC emacs-lisp -(let (xml) - (setq xml (with-temp-buffer - (insert-file-contents "acs-nano.csl") - (libxml-parse-xml-region (point-min) (point-max)))) -(car (xml-get-children (car (xml-get-children xml 'bibliography)) 'layout))) -#+END_SRC - -#+RESULTS: -#+BEGIN_SRC emacs-lisp -(layout - ((suffix . ".")) - (text - ((variable . "citation-number") - (prefix . "(") - (suffix . ") "))) - (text - ((macro . "author") - (suffix . " "))) - (choose nil - (if - ((type . "article-magazine")) - (group - ((delimiter . " ")) - (text - ((macro . "title") - (suffix . "."))) - (text - ((variable . "container-title") - (font-style . "italic") - (suffix . "."))) - (text - ((macro . "edition"))) - (text - ((macro . "publisher"))) - (text - ((macro . "full-issued") - (suffix . ","))) - (text - ((macro . "pages"))))) - (else-if - ((type . "thesis")) - (group - ((delimiter . ", ")) - (group - ((delimiter . ". ")) - (text - ((macro . "title"))) - (text - ((variable . "genre")))) - (text - ((macro . "publisher"))) - (text - ((macro . "issued"))) - (text - ((macro . "volume"))) - (text - ((macro . "pages"))))) - (else-if - ((type . "bill book graphic legal_case legislation motion_picture report song") - (match . "any")) - (group - ((delimiter . "; ")) - (text - ((macro . "title"))) - (text - ((macro . "editor") - (prefix . " "))) - (text - ((macro . "series"))) - (text - ((macro . "edition"))) - (choose nil - (if - ((type . "report")) - (group - ((delimiter . " ")) - (text - ((variable . "genre"))) - (text - ((variable . "number")))))) - (group - ((delimiter . ", ")) - (text - ((macro . "publisher"))) - (text - ((macro . "issued")))) - (group - ((delimiter . ", ")) - (text - ((macro . "volume"))) - (text - ((macro . "pages")))))) - (else-if - ((type . "patent")) - (group - ((delimiter . ", ")) - (group - ((delimiter . ". ")) - (text - ((macro . "title"))) - (text - ((variable . "number")))) - (date - ((variable . "issued") - (form . "text"))))) - (else-if - ((type . "chapter paper-conference") - (match . "any")) - (group - ((delimiter . "; ")) - (text - ((macro . "book-container"))) - (text - ((macro . "editor"))) - (text - ((macro . "series"))) - (group - ((delimiter . ", ")) - (text - ((macro . "publisher"))) - (text - ((macro . "issued")))) - (group - ((delimiter . ", ")) - (text - ((macro . "volume"))) - (text - ((macro . "pages")))))) - (else-if - ((type . "webpage")) - (group - ((delimiter . " ")) - (text - ((variable . "title"))) - (text - ((variable . "URL"))) - (date - ((variable . "accessed") - (prefix . "(accessed ") - (suffix . ")") - (delimiter . " ")) - (date-part - ((name . "month") - (form . "short") - (strip-periods . "true"))) - (date-part - ((name . "day") - (suffix . ", "))) - (date-part - ((name . "year")))))) - (else-if - ((type . "article-journal")) - (group - ((delimiter . " ")) - (text - ((macro . "title") - (suffix . "."))) - (text - ((variable . "container-title") - (font-style . "italic") - (form . "short"))) - (group - ((delimiter . ", ")) - (text - ((macro . "issued") - (font-weight . "bold"))) - (text - ((variable . "volume") - (font-style . "italic"))) - (text - ((variable . "page")))))) - (else nil - (group - ((delimiter . ", ")) - (group - ((delimiter . ". ")) - (text - ((macro . "title"))) - (text - ((variable . "container-title") - (font-style . "italic")))) - (group - ((delimiter . ", ")) - (text - ((macro . "issued"))) - (text - ((variable . "volume") - (font-style . "italic"))) - (text - ((variable . "page")))))))) -#+END_SRC - -#+END_SRC -*** An overview of a CSL for ACS Nano -#+BEGIN_SRC emacs-lisp -(with-temp-buffer - (insert-file-contents "acs-nano.csl") - (libxml-parse-xml-region (point-min) (point-max))) -#+END_SRC - -#+RESULTS: -#+BEGIN_SRC emacs-lisp -(style - ((class . "in-text") - (version . "1.0") - (demote-non-dropping-particle . "sort-only") - (page-range-format . "expanded") - (default-locale . "en-US")) - (info nil - (title nil "ACS Nano") - (title-short nil "ACS Nano") - (id nil "http://www.zotero.org/styles/acs-nano") - (link - ((href . "http://www.zotero.org/styles/acs-nano") - (rel . "self"))) - (link - ((href . "http://www.zotero.org/styles/american-chemical-society-with-titles") - (rel . "template"))) - (link - ((href . "http://pubs.acs.org/paragonplus/submission/ancac3/ancac3_authguide.pdf") - (rel . "documentation"))) - (category - ((citation-format . "numeric"))) - (category - ((field . "chemistry"))) - (issn nil "1936-0851") - (eissn nil "1936-086X") - (summary nil "ACS style with et al in italics") - (updated nil "2014-09-21T00:39:49+00:00") - (rights - ((license . "http://creativecommons.org/licenses/by-sa/3.0/")) - "This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License")) - (macro - ((name . "editor")) - (names - ((variable . "editor")) - (name - ((sort-separator . ", ") - (initialize-with . ". ") - (name-as-sort-order . "all") - (delimiter . "; ") - (delimiter-precedes-last . "always"))) - (et-al - ((font-style . "italic"))) - (label - ((form . "short") - (prefix . ", ") - (text-case . "capitalize-first"))))) - (macro - ((name . "author")) - (names - ((variable . "author") - (suffix . ".")) - (name - ((sort-separator . ", ") - (initialize-with . ". ") - (name-as-sort-order . "all") - (delimiter . "; ") - (delimiter-precedes-last . "always"))) - (et-al - ((font-style . "italic"))) - (label - ((form . "short") - (prefix . ", ") - (text-case . "capitalize-first"))))) - (macro - ((name . "publisher")) - (group - ((delimiter . ": ")) - (text - ((variable . "publisher"))) - (text - ((variable . "publisher-place"))))) - (macro - ((name . "title")) - (choose nil - (if - ((type . "bill book graphic legal_case legislation motion_picture report song") - (match . "any")) - (text - ((variable . "title") - (text-case . "title") - (font-style . "italic")))) - (else nil - (text - ((variable . "title") - (text-case . "title")))))) - (macro - ((name . "volume")) - (group - ((delimiter . " ")) - (text - ((term . "volume") - (form . "short") - (text-case . "capitalize-first"))) - (text - ((variable . "volume"))))) - (macro - ((name . "series")) - (text - ((variable . "collection-title")))) - (macro - ((name . "pages")) - (label - ((variable . "page") - (form . "short") - (suffix . " "))) - (text - ((variable . "page")))) - (macro - ((name . "book-container")) - (group - ((delimiter . " ")) - (text - ((macro . "title") - (suffix . "."))) - (text - ((term . "in") - (text-case . "capitalize-first"))) - (text - ((variable . "container-title") - (font-style . "italic"))))) - (macro - ((name . "issued")) - (date - ((variable . "issued") - (delimiter . " ")) - (date-part - ((name . "year"))))) - (macro - ((name . "full-issued")) - (date - ((variable . "issued") - (delimiter . " ")) - (date-part - ((name . "month") - (form . "long") - (suffix . " "))) - (date-part - ((name . "day") - (suffix . ", "))) - (date-part - ((name . "year"))))) - (macro - ((name . "edition")) - (choose nil - (if - ((is-numeric . "edition")) - (group - ((delimiter . " ")) - (number - ((variable . "edition") - (form . "ordinal"))) - (text - ((term . "edition") - (form . "short"))))) - (else nil - (text - ((variable . "edition") - (suffix . ".")))))) - (citation - ((collapse . "citation-number")) - (sort nil - (key - ((variable . "citation-number")))) - (layout - ((delimiter . ",") - (vertical-align . "sup")) - (text - ((variable . "citation-number"))))) - (bibliography - ((second-field-align . "flush") - (entry-spacing . "0") - (et-al-min . "11") - (et-al-use-first . "10")) - (layout - ((suffix . ".")) - (text - ((variable . "citation-number") - (prefix . "(") - (suffix . ") "))) - (text - ((macro . "author") - (suffix . " "))) - (choose nil - (if - ((type . "article-magazine")) - (group - ((delimiter . " ")) - (text - ((macro . "title") - (suffix . "."))) - (text - ((variable . "container-title") - (font-style . "italic") - (suffix . "."))) - (text - ((macro . "edition"))) - (text - ((macro . "publisher"))) - (text - ((macro . "full-issued") - (suffix . ","))) - (text - ((macro . "pages"))))) - (else-if - ((type . "thesis")) - (group - ((delimiter . ", ")) - (group - ((delimiter . ". ")) - (text - ((macro . "title"))) - (text - ((variable . "genre")))) - (text - ((macro . "publisher"))) - (text - ((macro . "issued"))) - (text - ((macro . "volume"))) - (text - ((macro . "pages"))))) - (else-if - ((type . "bill book graphic legal_case legislation motion_picture report song") - (match . "any")) - (group - ((delimiter . "; ")) - (text - ((macro . "title"))) - (text - ((macro . "editor") - (prefix . " "))) - (text - ((macro . "series"))) - (text - ((macro . "edition"))) - (choose nil - (if - ((type . "report")) - (group - ((delimiter . " ")) - (text - ((variable . "genre"))) - (text - ((variable . "number")))))) - (group - ((delimiter . ", ")) - (text - ((macro . "publisher"))) - (text - ((macro . "issued")))) - (group - ((delimiter . ", ")) - (text - ((macro . "volume"))) - (text - ((macro . "pages")))))) - (else-if - ((type . "patent")) - (group - ((delimiter . ", ")) - (group - ((delimiter . ". ")) - (text - ((macro . "title"))) - (text - ((variable . "number")))) - (date - ((variable . "issued") - (form . "text"))))) - (else-if - ((type . "chapter paper-conference") - (match . "any")) - (group - ((delimiter . "; ")) - (text - ((macro . "book-container"))) - (text - ((macro . "editor"))) - (text - ((macro . "series"))) - (group - ((delimiter . ", ")) - (text - ((macro . "publisher"))) - (text - ((macro . "issued")))) - (group - ((delimiter . ", ")) - (text - ((macro . "volume"))) - (text - ((macro . "pages")))))) - (else-if - ((type . "webpage")) - (group - ((delimiter . " ")) - (text - ((variable . "title"))) - (text - ((variable . "URL"))) - (date - ((variable . "accessed") - (prefix . "(accessed ") - (suffix . ")") - (delimiter . " ")) - (date-part - ((name . "month") - (form . "short") - (strip-periods . "true"))) - (date-part - ((name . "day") - (suffix . ", "))) - (date-part - ((name . "year")))))) - (else-if - ((type . "article-journal")) - (group - ((delimiter . " ")) - (text - ((macro . "title") - (suffix . "."))) - (text - ((variable . "container-title") - (font-style . "italic") - (form . "short"))) - (group - ((delimiter . ", ")) - (text - ((macro . "issued") - (font-weight . "bold"))) - (text - ((variable . "volume") - (font-style . "italic"))) - (text - ((variable . "page")))))) - (else nil - (group - ((delimiter . ", ")) - (group - ((delimiter . ". ")) - (text - ((macro . "title"))) - (text - ((variable . "container-title") - (font-style . "italic")))) - (group - ((delimiter . ", ")) - (text - ((macro . "issued"))) - (text - ((variable . "volume") - (font-style . "italic"))) - (text - ((variable . "page")))))))))) -#+END_SRC -** Working example - -#+BEGIN_SRC emacs-lisp -(add-to-list 'load-path ".") -(require 'org-ref-citeproc) -(require 'unsrt) -#+END_SRC - -#+RESULTS: -: unsrt - -My data cite:kitchin-2015-examp in Ref. citenum:kitchin-2015-data-surfac-scien. - -A multicite cite:kitchin-2015-examp,kitchin-2015-data-surfac-scien - -*** Getting the citations -#+BEGIN_SRC emacs-lisp -(mapcar - (lambda (link) - (org-element-property :type link)) - (orcp-collect-citations)) -#+END_SRC - -#+RESULTS: -| cite | citenum | cite | - - -I need a key to entry function -#+BEGIN_SRC emacs-lisp -(orcp-key-to-entry "kitchin-2015-examp") -#+END_SRC - -#+RESULTS: -#+BEGIN_SRC emacs-lisp -(("=type=" . "article") - ("=key=" . "kitchin-2015-examp") - ("author" . "Kitchin, John R.") - ("title" . "Examples of Effective Data Sharing in Scientific Publishing") - ("journal" . "ACS Catalysis") - ("volume" . "5") - ("number" . "6") - ("pages" . "3894-3899") - ("year" . "2015") - ("doi" . "10.1021/acscatal.5b00538") - ("url" . " http://dx.doi.org/10.1021/acscatal.5b00538 ") - ("keywords" . "DESC0004031, early-career, orgmode, Data sharing ") - ("eprint" . " http://dx.doi.org/10.1021/acscatal.5b00538 ")) -#+END_SRC - -#+BEGIN_SRC emacs-lisp -(cdr (assoc "year" (orcp-key-to-entry "kitchin-2015-examp"))) -#+END_SRC - -#+RESULTS: -: 2015 - -cite:wang-2013-immob-co2 - -cite:antony-2012-pathw-c - -cite:weaver-2011-high-selec - -*** Sorting the entries -The unique entries will make up the bibliography. They might get sorted in a variety of ways, e.g. unsorted, alphabetically, by year, etc... -#+BEGIN_SRC emacs-lisp -(orcp-sort-entries-increasing-year (orcp-collect-unique-entries)) -#+END_SRC - -#+RESULTS: -| weaver-2011-high-selec | (=type= . article) | (=key= . weaver-2011-high-selec) | (author . Jason F. Weaver and Can Hakanoglu and Abbin Antony and Aravind\n Asthagiri) | (title . High Selectivity for Primary {C-H} Bond Cleavage of Propane\n $\sigma$-complexes on the {PdO}(101) Surface) | (keywords . alkane) | (journal . J. Am. Chem. Soc.) | (volume . 133) | (number . 40) | (pages . 16196-16200) | (year . 2011) | (doi . 10.1021/ja206599k) | (url . http://dx.doi.org/10.1021/ja206599k) | (date_added . Sat Nov 28 09:10:59 2015) | -| antony-2012-pathw-c | (=type= . article) | (=key= . antony-2012-pathw-c) | (author . Abbin Antony and Aravind Asthagiri and Jason F. Weaver) | (title . Pathways for {C-H} Bond Cleavage of Propane $\sigma$-complexes on\n {PdO}(101)) | (keywords . alkane) | (journal . Phys. Chem. Chem. Phys.) | (volume . 14) | (number . 35) | (pages . 12202) | (year . 2012) | (doi . 10.1039/c2cp41900a) | (url . http://dx.doi.org/10.1039/c2cp41900a) | (date_added . Sat Nov 28 09:13:32 2015) | -| wang-2013-immob-co2 | (=type= . article) | (=key= . wang-2013-immob-co2) | (author . Xianfeng Wang and Novruz G. Akhmedov and Yuhua Duan and David\n Luebke and Bingyun Li) | (title . Immobilization of Amino Acid Ionic Liquids Into Nanoporous\n Microspheres As Robust Sorbents for Co2 Capture) | (journal . J. Mater. Chem. A) | (volume . 1) | (number . 9) | (pages . 2978) | (year . 2013) | (doi . 10.1039/c3ta00768e) | (url . http://dx.doi.org/10.1039/C3TA00768E) | (date_added . Thu Dec 3 06:13:09 2015) | | -| kitchin-2015-examp | (=type= . article) | (=key= . kitchin-2015-examp) | (author . Kitchin, John R.) | (title . Examples of Effective Data Sharing in Scientific Publishing) | (journal . ACS Catalysis) | (volume . 5) | (number . 6) | (pages . 3894-3899) | (year . 2015) | (doi . 10.1021/acscatal.5b00538) | (url . http://dx.doi.org/10.1021/acscatal.5b00538 ) | (keywords . DESC0004031, early-career, orgmode, Data sharing ) | (eprint . http://dx.doi.org/10.1021/acscatal.5b00538 ) | -| kitchin-2015-data-surfac-scien | (=type= . article) | (=key= . kitchin-2015-data-surfac-scien) | (author . John R. Kitchin) | (title . Data Sharing in Surface Science) | (journal . Surface Science ) | (number . 0) | (pages . - ) | (year . 2015) | (doi . 10.1016/j.susc.2015.05.007) | (url . http://www.sciencedirect.com/science/article/pii/S0039602815001326) | (issn . 0039-6028) | (keywords . DESC0004031, early-career, orgmode, Data sharing ) | | - -cite:anderson-1977-raman - -#+BEGIN_SRC emacs-lisp -(orcp-sort-entries-alphabetical (orcp-collect-unique-entries)) -#+END_SRC - -#+RESULTS: -| anderson-1977-raman | (=type= . article) | (=key= . anderson-1977-raman) | (author . George R. Anderson) | (title . The {R}aman Spectra of Carbon Dioxide in Liquid Water and\n Water-D2) | (journal . J. Phys. Chem.) | (volume . 81) | (number . 3) | (pages . 273-276) | (year . 1977) | (doi . 10.1021/j100518a017) | (url . http://dx.doi.org/10.1021/j100518a017) | (month . 2) | (eprint . http://pubs.acs.org/doi/pdf/10.1021/j100518a017) | -| antony-2012-pathw-c | (=type= . article) | (=key= . antony-2012-pathw-c) | (author . Abbin Antony and Aravind Asthagiri and Jason F. Weaver) | (title . Pathways for {C-H} Bond Cleavage of Propane $\sigma$-complexes on\n {PdO}(101)) | (keywords . alkane) | (journal . Phys. Chem. Chem. Phys.) | (volume . 14) | (number . 35) | (pages . 12202) | (year . 2012) | (doi . 10.1039/c2cp41900a) | (url . http://dx.doi.org/10.1039/c2cp41900a) | (date_added . Sat Nov 28 09:13:32 2015) | -| kitchin-2015-examp | (=type= . article) | (=key= . kitchin-2015-examp) | (author . Kitchin, John R.) | (title . Examples of Effective Data Sharing in Scientific Publishing) | (journal . ACS Catalysis) | (volume . 5) | (number . 6) | (pages . 3894-3899) | (year . 2015) | (doi . 10.1021/acscatal.5b00538) | (url . http://dx.doi.org/10.1021/acscatal.5b00538 ) | (keywords . DESC0004031, early-career, orgmode, Data sharing ) | (eprint . http://dx.doi.org/10.1021/acscatal.5b00538 ) | -| kitchin-2015-data-surfac-scien | (=type= . article) | (=key= . kitchin-2015-data-surfac-scien) | (author . John R. Kitchin) | (title . Data Sharing in Surface Science) | (journal . Surface Science ) | (number . 0) | (pages . - ) | (year . 2015) | (doi . 10.1016/j.susc.2015.05.007) | (url . http://www.sciencedirect.com/science/article/pii/S0039602815001326) | (issn . 0039-6028) | (keywords . DESC0004031, early-career, orgmode, Data sharing ) | | -| wang-2013-immob-co2 | (=type= . article) | (=key= . wang-2013-immob-co2) | (author . Xianfeng Wang and Novruz G. Akhmedov and Yuhua Duan and David\n Luebke and Bingyun Li) | (title . Immobilization of Amino Acid Ionic Liquids Into Nanoporous\n Microspheres As Robust Sorbents for Co2 Capture) | (journal . J. Mater. Chem. A) | (volume . 1) | (number . 9) | (pages . 2978) | (year . 2013) | (doi . 10.1039/c3ta00768e) | (url . http://dx.doi.org/10.1039/C3TA00768E) | (date_added . Thu Dec 3 06:13:09 2015) | | -| weaver-2011-high-selec | (=type= . article) | (=key= . weaver-2011-high-selec) | (author . Jason F. Weaver and Can Hakanoglu and Abbin Antony and Aravind\n Asthagiri) | (title . High Selectivity for Primary {C-H} Bond Cleavage of Propane\n $\sigma$-complexes on the {PdO}(101) Surface) | (keywords . alkane) | (journal . J. Am. Chem. Soc.) | (volume . 133) | (number . 40) | (pages . 16196-16200) | (year . 2011) | (doi . 10.1021/ja206599k) | (url . http://dx.doi.org/10.1021/ja206599k) | (date_added . Sat Nov 28 09:10:59 2015) | - -*** Getting a citation replacement -This will be taking a key, and the unique replacements, and computing a replacement for that key. - -#+BEGIN_SRC emacs-lisp -(orcp-citation-author-year-label - "anderson-1977-raman" - (orcp-sort-entries-alphabetical (orcp-collect-unique-entries))) -#+END_SRC - -#+RESULTS: -: Anderson 1977 - -citeauthor:wang-2013-immob-co2 - -citeyear:wang-2013-immob-co2 - -#+BEGIN_SRC emacs-lisp -(orcp-get-citation-style 'vertical-align 'citenum) - -(cdr (assoc 'vertical-align (cdr (assoc 'citenum citation-style)))) -#+END_SRC - -#+RESULTS: -: baseline - -#+BEGIN_SRC emacs-lisp -(setq orcp-unique-bibliography-links (orcp-collect-unique-entries)) - -(mapcar - (lambda (link) - (list - (org-element-property :type link) - (orcp-get-text-replacement link)) ) - (orcp-collect-citations)) -#+END_SRC - -#+RESULTS: -| cite | {}^{1} | -| citenum | 2 | -| cite | {}^{1,2} | -| cite | {}^{3} | -| cite | {}^{4} | -| cite | {}^{5} | -| cite | {}^{6} | -| citeauthor | Wang | -| citeyear | 2013 | - - -#+BEGIN_SRC emacs-lisp -(orcp-author (nth 3 (orcp-collect-unique-entries))) -#+END_SRC - -#+RESULTS: -: Antony, Abbin; Asthagiri, Aravind and Weaver, Jason F.. - - -#+BEGIN_SRC emacs-lisp -(let ((entry (nth 3 (orcp-collect-unique-entries)))) - (concat - (orcp-author entry) - (orcp-title entry) - (orcp-journal entry) - (orcp-volume entry) - (orcp-pages entry) - (orcp-year entry) - (orcp-doi entry))) -#+END_SRC - -#+RESULTS: -: Antony, Abbin; Asthagiri, Aravind and Weaver, Jason F., /Pathways for {C-H} Bond Cleavage of Propane $\sigma$-complexes on {PdO}(101)/, Phys. Chem. Chem. Phys., 14*(35)*, pp. 12202 (2012).doi:10.1039/c2cp41900a. - -#+BEGIN_SRC emacs-lisp -(mapconcat 'identity (cl-loop for entry in (orcp-collect-unique-entries) - collect - (concat - (orcp-author entry) - (orcp-title entry) - (orcp-journal entry) - (orcp-volume entry) - (orcp-pages entry) - (orcp-year entry) - (orcp-doi entry))) - "\n\n") -#+END_SRC - -#+RESULTS: -#+begin_example -Kitchin, John R., /Examples of Effective Data Sharing in Scientific Publishing/, ACS Catalysis, 5*(6)*, pp. 3894-3899 (2015). doi:10.1021/acscatal.5b00538. - -Kitchin, John R., /Data Sharing in Surface Science/, Surface Science , *(0)*, pp. - (2015). doi:10.1016/j.susc.2015.05.007. - -Wang, Xianfeng; Akhmedov, Novruz G.; Duan, Yuhua; Luebke, David and Li, Bingyun, /Immobilization of Amino Acid Ionic Liquids Into Nanoporous Microspheres As Robust Sorbents for Co2 Capture/, J. Mater. Chem. A, 1*(9)*, pp. 2978 (2013). doi:10.1039/c3ta00768e. - -Antony, Abbin; Asthagiri, Aravind and Weaver, Jason F., /Pathways for {C-H} Bond Cleavage of Propane $\sigma$-complexes on {PdO}(101)/, Phys. Chem. Chem. Phys., 14*(35)*, pp. 12202 (2012). doi:10.1039/c2cp41900a. - -Weaver, Jason F.; Hakanoglu, Can; Antony, Abbin and Asthagiri, Aravind, /High Selectivity for Primary {C-H} Bond Cleavage of Propane $\sigma$-complexes on the {PdO}(101) Surface/, J. Am. Chem. Soc., 133*(40)*, pp. 16196-16200 (2011). doi:10.1021/ja206599k. - -Anderson, George R., /The {R}aman Spectra of Carbon Dioxide in Liquid Water and Water-D2/, J. Phys. Chem., 81*(3)*, pp. 273-276 (1977). doi:10.1021/j100518a017. - -Zhu, Qingjun; Wegener, Staci L.; Xie, Chao; Uche, Obioma; Neurock, Matthew and Marks, Tobin J., /Sulfur As a Selective "soft" Oxidant for Catalytic Methane Conversion Probed By Experiment and Theory/, Nature chemistry, 5, pp. 104-109 (2013). doi:10.1002/ange.201311111. - -Lizzit, S.; Baraldi, A.; Groso, A.; Reuter, K.; Ganduglia-Pirovano, M. V.; Stampfl, C.; Scheffler, M.; Stichler, M.; Keller, C.; Wurth, W. and Menzel, D., /Surface Core-Level Shifts of Clean and Oxygen-Covered {Ru}(0001)/, Phys. Rev. B, 63*(20)*, pp. 205419 (2001). doi:10.1103/physrevb.63.205419. -#+end_example - - -cite:zhu-2013-sulfur,lizzit-2001-surfac-ru - -cite:yeo-2012-in-situ,ye-2012-proces-charac -#+BEGIN_SRC emacs-lisp -(orcp-formatted-bibliography) -#+END_SRC - -#+RESULTS: -#+begin_example -1. Kitchin, John R., /Examples of Effective Data Sharing in Scientific - Publishing/, ACS Catalysis, 5*(6)*, pp. 3894-3899 (2015). - doi:10.1021/acscatal.5b00538. - -2. Kitchin, John R., /Data Sharing in Surface Science/, Surface Science , *(0)*, - pp. - (2015). doi:10.1016/j.susc.2015.05.007. - -3. Wang, Xianfeng; Akhmedov, Novruz G.; Duan, Yuhua; Luebke, David and Li, - Bingyun, /Immobilization of Amino Acid Ionic Liquids Into Nanoporous - Microspheres As Robust Sorbents for Co2 Capture/, J. Mater. Chem. A, 1*(9)*, - pp. 2978 (2013). doi:10.1039/c3ta00768e. - -4. Antony, Abbin; Asthagiri, Aravind and Weaver, Jason F., /Pathways for {C-H} - Bond Cleavage of Propane $\sigma$-complexes on {PdO}(101)/, Phys. Chem. Chem. - Phys., 14*(35)*, pp. 12202 (2012). doi:10.1039/c2cp41900a. - -5. Weaver, Jason F.; Hakanoglu, Can; Antony, Abbin and Asthagiri, Aravind, /High - Selectivity for Primary {C-H} Bond Cleavage of Propane $\sigma$-complexes on - the {PdO}(101) Surface/, J. Am. Chem. Soc., 133*(40)*, pp. 16196-16200 - (2011). doi:10.1021/ja206599k. - -6. Anderson, George R., /The {R}aman Spectra of Carbon Dioxide in Liquid Water - and Water-D2/, J. Phys. Chem., 81*(3)*, pp. 273-276 (1977). - doi:10.1021/j100518a017. - -7. Zhu, Qingjun; Wegener, Staci L.; Xie, Chao; Uche, Obioma; Neurock, Matthew - and Marks, Tobin J., /Sulfur As a Selective "soft" Oxidant for Catalytic - Methane Conversion Probed By Experiment and Theory/, Nature chemistry, 5, pp. - 104-109 (2013). doi:10.1002/ange.201311111. - -8. Lizzit, S.; Baraldi, A.; Groso, A.; Reuter, K.; Ganduglia-Pirovano, M. V.; - Stampfl, C.; Scheffler, M.; Stichler, M.; Keller, C.; Wurth, W. and Menzel, - D., /Surface Core-Level Shifts of Clean and Oxygen-Covered {Ru}(0001)/, Phys. - Rev. B, 63*(20)*, pp. 205419 (2001). doi:10.1103/physrevb.63.205419. - -9. Yeo, Boon Siang and Bell, Alexis T., /In Situ {R}aman Study of Nickel Oxide - and Gold-Supported Nickel Oxide Catalysts for the Electrochemical Evolution - of Oxygen/, The Journal of Physical Chemistry C, 116*(15)*, pp. 8394-8400 - (2012). doi:10.1021/jp3007415. - -10. Chunbo, Y. E.; CHEN, Guangwen and YUAN, Quan, /Process Characteristics of - \ce{CO2} Absorption By Aqueous Monoethanolamine in a Microchannel Reactor/, - Chinese Journal of Chemical Engineering, 20*(1)*, pp. 111-119 (2012). - doi:10.1016/s1004-9541(12)60370-x. - -11. Kittel, Charles, /Introduction to Solid State Physics/, (2005). -#+end_example - - - - -cite:kittel-2005-introd-solid - - - -*** Reading my csl -#+BEGIN_SRC emacs-lisp -(require 'unsrt) -(assoc 'sort bibliography-style) -#+END_SRC - -#+RESULTS: -| sort | quote | citation-number | - - -** - -** Putting it together -You run these to get the replacements - -#+BEGIN_SRC emacs-lisp -(orcp-collect-citations) -(orcp-collect-unique-entries) -#+END_SRC - -#+BEGIN_SRC emacs-lisp -(cl-loop for link in *orcp-citation-links* - for repl in (orcp-get-citation-replacements) - collect - (list repl - (org-element-property :begin link) - (org-element-property :end link))) -#+END_SRC - -#+RESULTS: -| {}^{1} | 29467 | 29491 | -| 2 | 29499 | 29537 | -| {}^{1,2} | 29552 | 29606 | -| {}^{3} | 30578 | 30602 | -| {}^{4} | 30604 | 30628 | -| {}^{5} | 30630 | 30657 | -| {}^{6} | 34705 | 34729 | -| Wang | 39698 | 39728 | -| 2013 | 39730 | 39758 | -| {}^{7,8} | 43188 | 43230 | -| {}^{9,10} | 43232 | 43275 | -| {}^{11} | 45939 | 45968 | - -#+BEGIN_SRC emacs-lisp -(orcp-formatted-bibliography) -#+END_SRC - -#+RESULTS: -#+begin_example -1. Kitchin, John R., /Examples of Effective Data Sharing in Scientific - Publishing/, ACS Catalysis, 5*(6)*, pp. 3894-3899 (2015). - doi:10.1021/acscatal.5b00538. - -2. Kitchin, John R., /Data Sharing in Surface Science/, Surface Science , *(0)*, - pp. - (2015). doi:10.1016/j.susc.2015.05.007. - -3. Wang, Xianfeng; Akhmedov, Novruz G.; Duan, Yuhua; Luebke, David and Li, - Bingyun, /Immobilization of Amino Acid Ionic Liquids Into Nanoporous - Microspheres As Robust Sorbents for Co2 Capture/, J. Mater. Chem. A, 1*(9)*, - pp. 2978 (2013). doi:10.1039/c3ta00768e. - -4. Antony, Abbin; Asthagiri, Aravind and Weaver, Jason F., /Pathways for {C-H} - Bond Cleavage of Propane $\sigma$-complexes on {PdO}(101)/, Phys. Chem. Chem. - Phys., 14*(35)*, pp. 12202 (2012). doi:10.1039/c2cp41900a. - -5. Weaver, Jason F.; Hakanoglu, Can; Antony, Abbin and Asthagiri, Aravind, /High - Selectivity for Primary {C-H} Bond Cleavage of Propane $\sigma$-complexes on - the {PdO}(101) Surface/, J. Am. Chem. Soc., 133*(40)*, pp. 16196-16200 - (2011). doi:10.1021/ja206599k. - -6. Anderson, George R., /The {R}aman Spectra of Carbon Dioxide in Liquid Water - and Water-D2/, J. Phys. Chem., 81*(3)*, pp. 273-276 (1977). - doi:10.1021/j100518a017. - -7. Zhu, Qingjun; Wegener, Staci L.; Xie, Chao; Uche, Obioma; Neurock, Matthew - and Marks, Tobin J., /Sulfur As a Selective "soft" Oxidant for Catalytic - Methane Conversion Probed By Experiment and Theory/, Nature chemistry, 5, pp. - 104-109 (2013). doi:10.1002/ange.201311111. - -8. Lizzit, S.; Baraldi, A.; Groso, A.; Reuter, K.; Ganduglia-Pirovano, M. V.; - Stampfl, C.; Scheffler, M.; Stichler, M.; Keller, C.; Wurth, W. and Menzel, - D., /Surface Core-Level Shifts of Clean and Oxygen-Covered {Ru}(0001)/, Phys. - Rev. B, 63*(20)*, pp. 205419 (2001). doi:10.1103/physrevb.63.205419. - -9. Yeo, Boon Siang and Bell, Alexis T., /In Situ {R}aman Study of Nickel Oxide - and Gold-Supported Nickel Oxide Catalysts for the Electrochemical Evolution - of Oxygen/, The Journal of Physical Chemistry C, 116*(15)*, pp. 8394-8400 - (2012). doi:10.1021/jp3007415. - -10. Chunbo, Y. E.; CHEN, Guangwen and YUAN, Quan, /Process Characteristics of - \ce{CO2} Absorption By Aqueous Monoethanolamine in a Microchannel Reactor/, - Chinese Journal of Chemical Engineering, 20*(1)*, pp. 111-119 (2012). - doi:10.1016/s1004-9541(12)60370-x. - -11. Kittel, Charles, /Introduction to Solid State Physics/, (2005). -#+end_example - - - -#+BEGIN_SRC emacs-lisp -(cl-loop for link in (org-element-map - (org-element-parse-buffer) 'link 'identity) - if (string= "bibliographystyle" - (org-element-property :type link)) - do - ;; get path for style - (let ((style (intern (org-element-property :path link))))) - (load-library style) - ) -#+END_SRC diff --git a/lisp/org-ref/doi-utils.el b/lisp/org-ref/doi-utils.el index 33fba3e5..08cb9610 100644 --- a/lisp/org-ref/doi-utils.el +++ b/lisp/org-ref/doi-utils.el @@ -1,6 +1,6 @@ ;;; doi-utils.el --- DOI utilities for making bibtex entries -;; Copyright (C) 2015 John Kitchin +;; Copyright (C) 2015-2021 John Kitchin ;; Author: John Kitchin ;; Keywords: convenience @@ -36,17 +36,10 @@ ;;; Code: -(defvar org-ref-pdf-directory) -(defvar org-ref-bibliography-notes) -(defvar org-ref-default-bibliography) -(defvar reftex-default-bibliography) (defvar url-http-end-of-headers) -(declare-function org-ref-bib-citation "org-ref-core") (declare-function org-ref-find-bibliography "org-ref-core") (declare-function org-ref-clean-bibtex-entry "org-ref-core") -(declare-function reftex-get-bib-field "reftex-cite") (declare-function bibtex-completion-edit-notes "bibtex-completion") -(declare-function helm "helm") (declare-function org-bibtex-yank "org-bibtex") (declare-function org-ref-possible-bibfiles "org-ref-core") @@ -62,6 +55,7 @@ (require 'url-http) (require 'org-ref-utils) +(require 'hydra) ;;* Customization (defgroup doi-utils nil @@ -82,11 +76,6 @@ :type 'boolean :group 'doi-utils) -(defcustom doi-utils-make-notes - t - "Whether to create notes when adding bibtex entries." - :type 'boolean - :group 'doi-utils) (defcustom doi-utils-timestamp-field "DATE_ADDED" @@ -102,15 +91,6 @@ e.g. (lambda () nil)" :type 'function :group 'doi-utils) -(defcustom doi-utils-make-notes-function - (lambda () - (bibtex-beginning-of-entry) - (bibtex-completion-edit-notes (list (cdr (assoc "=key=" (bibtex-parse-entry)))))) - "Function to create notes for a bibtex entry. - -Set `doi-utils-make-notes' to nil if you want no notes." - :type 'function - :group 'doi-utils) (defcustom doi-utils-dx-doi-org-url "https://doi.org/" @@ -118,12 +98,22 @@ Set `doi-utils-make-notes' to nil if you want no notes." :type 'string :group 'doi-utils) + (defcustom doi-utils-metadata-function 'doi-utils-get-json-metadata "Function for retrieving json metadata from `doi-utils-dx-doi-org-url'. The default is `doi-utils-get-json-metadata', but it sometimes fails with a proxy. An alternative is `doi-utils-get-json-metadata-curl' which requires an external -program to use curl.") +program to use curl." + :type 'function + :group 'doi-utils) + + +(defcustom doi-utils-async-download t + "Use `doi-utils-async-download-pdf' to get pdfs asynchrounously. +If nil use `doi-utils-get-bibtex-entry-pdf' synchronously." + :type 'boolean + :group 'doi-utils) ;;* Getting pdf files from a DOI @@ -306,6 +296,15 @@ must return a pdf-url, or nil.") (format "http://scitation.aip.org/deliver/fulltext/%s.pdf?itemId=/%s&mimeType=pdf&containerItemId=%s" p1 p2 p3)))) +(defun aip-pdf-url-2 (*doi-utils-redirect*) + "Get url to the pdf from *DOI-UTILS-REDIRECT*." + ;; [2021-08-28 Sat] Seems like they changed the link a little? + ;; https://aip.scitation.org/doi/10.1063/1.5019667 + ;; to + ;; https://aip.scitation.org/doi/pdf/10.1063/1.5019667 + (when (string-match "^http\\(s?\\)://aip.scitation.org" *doi-utils-redirect*) + (concat "https://aip.scitation.org/doi/pdf" (cl-second (split-string *doi-utils-redirect* "doi"))))) + ;;** Taylor and Francis (defun tandfonline-pdf-url (*doi-utils-redirect*) @@ -609,6 +608,7 @@ It would be better to parse this, but here I just use a regexp. 'iop-pdf-url 'jstor-pdf-url 'aip-pdf-url + 'aip-pdf-url-2 'science-direct-pdf-url 'linkinghub-elsevier-pdf-url 'tandfonline-pdf-url @@ -647,16 +647,82 @@ until one is found." (throw 'pdf-url this-pdf-url)))))) ;;** Finally, download the pdf +(defvar bibtex-completion-library-path) +(defvar bibtex-completion-bibliography) +(declare-function async-start "async") + +;;;###autoload +(defun doi-utils-async-download-pdf () + "Download the PDF for bibtex entry at point asynchronously. +It is not fully async, only the download is. Fully async is +harder because you need to run `doi-utils-get-pdf-url' async +too. " + (interactive) + (require 'async) + (save-excursion + (bibtex-beginning-of-entry) + (let (;; get doi, removing http://dx.doi.org/ if it is there. + (doi (replace-regexp-in-string + "https?://\\(dx.\\)?.doi.org/" "" + (bibtex-autokey-get-field "doi"))) + (key (cdr (assoc "=key=" (bibtex-parse-entry)))) + (pdf-url) + (pdf-file)) + + (setq pdf-file + (concat (cond + ((stringp bibtex-completion-library-path) + bibtex-completion-library-path) + ((= 1 (length bibtex-completion-library-path)) + (car bibtex-completion-library-path)) + (t + (completing-read "Dir: " bibtex-completion-library-path))) + key ".pdf")) + + (unless doi (error "No DOI found to get a pdf for")) + + (when (file-exists-p pdf-file) + (error "%s already exists. Delete to re-download" pdf-file)) + + ;; (doi-utils-get-pdf-url "10.1063/1.5019667") + ;; If you get here, try getting the pdf file + (async-start + `(lambda () + (setq package-user-dir ,package-user-dir) + (require 'package) + (package-initialize) + (setq load-path (list ,@load-path)) + (require 'doi-utils) + + (setq pdf-url (doi-utils-get-pdf-url ,doi)) + (when pdf-url + (url-copy-file pdf-url ,pdf-file t) + + (let* ((header (with-temp-buffer + (set-buffer-multibyte nil) + (insert-file-contents-literally ,pdf-file nil 0 5) + (buffer-string))) + (valid (and (stringp header) + (string-equal (encode-coding-string header 'utf-8) "%PDF-")))) + (if valid + (format "%s downloaded" ,pdf-file) + (delete-file ,pdf-file) + (require 'browse-url) + (browse-url pdf-url) + (message "Invalid pdf (file deleted). Header = %s" header))))) + `(lambda (result) + (message "doi-utils-async-download-pdf: %s" result)))))) + ;;;###autoload (defun doi-utils-get-bibtex-entry-pdf (&optional arg) "Download pdf for entry at point if the pdf does not already exist locally. -The entry must have a doi. The pdf will be saved -to `org-ref-pdf-directory', by the name %s.pdf where %s is the -bibtex label. Files will not be overwritten. The pdf will be -checked to make sure it is a pdf, and not some html failure -page. You must have permission to access the pdf. We open the pdf -at the end if `doi-utils-open-pdf-after-download' is non-nil. +The entry must have a doi. The pdf will be saved, by the name +%s.pdf where %s is the bibtex label. Files will not be +overwritten. The pdf will be checked to make sure it is a pdf, +and not some html failure page. You must have permission to +access the pdf. We open the pdf at the end if +`doi-utils-open-pdf-after-download' is non-nil. With one prefix ARG, directly get the pdf from a file (through `read-file-name') instead of looking up a DOI. With a double @@ -667,7 +733,7 @@ checked." (interactive "P") (save-excursion (bibtex-beginning-of-entry) - (let ( ;; get doi, removing http://dx.doi.org/ if it is there. + (let (;; get doi, removing http://dx.doi.org/ if it is there. (doi (replace-regexp-in-string "https?://\\(dx.\\)?.doi.org/" "" (bibtex-autokey-get-field "doi"))) @@ -675,11 +741,15 @@ checked." (pdf-url) (pdf-file)) - (setq pdf-file (concat - (if org-ref-pdf-directory - (file-name-as-directory org-ref-pdf-directory) - (read-directory-name "PDF directory: " ".")) - key ".pdf")) + (setq pdf-file + (concat (cond + ((stringp bibtex-completion-library-path) + bibtex-completion-library-path) + ((= 1 (length bibtex-completion-library-path)) + (car bibtex-completion-library-path)) + (t + (completing-read "Dir: " bibtex-completion-library-path))) + key ".pdf")) ;; now get file if needed. (unless (file-exists-p pdf-file) (cond @@ -701,43 +771,65 @@ checked." (write-file pdf-file))) (t (message "We don't have a recipe for this journal."))) + + (when (file-exists-p pdf-file) + (bibtex-set-field "file" pdf-file)) + (when (and doi-utils-open-pdf-after-download (file-exists-p pdf-file)) (org-open-file pdf-file)))))) ;;* Getting bibtex entries from a DOI -;; I ;; [[http://homepages.see.leeds.ac.uk/~eeaol/notes/2013/02/doi-metadata/][found]] ;; you can download metadata about a DOI from http://dx.doi.org. You just have ;; to construct the right http request to get it. Here is a function that gets ;; the metadata as a plist in emacs. +;; +;; +(defvar doi-utils-cache nil + "Cache variable for storing data we can reuse. +A-list (doi . data) where doi is doi string, and data is what is +retrieved from it. This is transient, and disappears when you +restart Emacs. This mostly exists to prevent +`doi-utils-update-field' from needing to download the data for +every field.") + + +(defun doi-utils-clear-cache () + "Clear `doi-utils-cache'." + (interactive) + (setq doi-utils-cache '())) + (defun doi-utils-get-json-metadata (doi) "Try to get json metadata for DOI. Open the DOI in a browser if we do not get it." - (let ((url-request-method "GET") - (url-mime-accept-string "application/citeproc+json") - (json-object-type 'plist) - (json-data) - (url (concat doi-utils-dx-doi-org-url doi))) - (with-current-buffer - (url-retrieve-synchronously - ;; (concat "http://dx.doi.org/" doi) - url) - (setq json-data (buffer-substring url-http-end-of-headers (point-max))) - (cond - ((or (string-match "Error: DOI Not Found" json-data) - (string-match "Resource not found" json-data) - (string-match "Status *406" json-data) - (string-match "400 Bad Request" json-data)) - (browse-url (concat doi-utils-dx-doi-org-url doi)) - (error "Something went wrong. We got this response: + (if-let ((data (cdr (assoc doi doi-utils-cache)))) + ;; We have the data already, so we return it. + data + (let ((url-request-method "GET") + (url-mime-accept-string "application/citeproc+json") + (json-object-type 'plist) + (json-data) + (url (concat doi-utils-dx-doi-org-url doi))) + (with-current-buffer + (url-retrieve-synchronously + ;; (concat "http://dx.doi.org/" doi) + url) + (setq json-data (buffer-substring url-http-end-of-headers (point-max))) + + (when (or (string-match "Error: DOI Not Found" json-data) + (string-match "Resource not found" json-data) + (string-match "Status *406" json-data) + (string-match "400 Bad Request" json-data)) + (browse-url (concat doi-utils-dx-doi-org-url doi)) + (error "Something went wrong. We got this response: %s Opening %s" json-data url)) - ;; everything seems ok with the data - (t - (json-read-from-string json-data)))))) + (setq data (json-read-from-string json-data)) + (cl-pushnew (cons doi data) doi-utils-cache) + data)))) (defun doi-utils-get-json-metadata-curl (doi) @@ -806,7 +898,9 @@ Opening %s" json-data url)) (volume (plist-get results :volume)) (issue (plist-get results :issue)) (number (plist-get results :issue)) - (year (elt (elt (plist-get (plist-get results :issued) :date-parts) 0) 0)) + (year (or (elt (elt (plist-get (plist-get results :issued) :date-parts) 0) 0) + (elt (elt (plist-get (plist-get results :approved) :date-parts) 0) 0) + )) ;; Some dates don't have a month in them. (month (let ((date (elt (plist-get (plist-get results :issued) :date-parts) 0))) @@ -817,7 +911,9 @@ Opening %s" json-data url)) (plist-get results :article-number))) (doi (plist-get results :DOI)) (url (plist-get results :URL)) - (booktitle (plist-get results :container-title)))) + (booktitle (plist-get results :container-title)) + (school (or (plist-get results :school) + (plist-get (plist-get results :institution) :name))))) ;; Next, we need to define the different bibtex types. Each type has a bibtex ;; type (for output) and the type as provided in the doi record. Finally, we @@ -882,6 +978,8 @@ MATCHING-TYPES." (doi-utils-def-bibtex-type inbook ("chapter" "book-chapter" "reference-entry") author title booktitle series publisher year pages doi url) +(doi-utils-def-bibtex-type phdthesis ("phdthesis" "thesis" "dissertation") + author title school publisher year) ;; this is what preprints in chemrxiv look like for now (doi-utils-def-bibtex-type misc ("posted-content") @@ -901,12 +999,10 @@ MATCHING-TYPES." ;; That is just the string for the entry. To be useful, we need a function that ;; inserts the string into a buffer. This function will insert the string at the -;; cursor, clean the entry, try to get the pdf, and create a notes entry for -;; you. +;; cursor, clean the entry, try to get the pdf. (defun doi-utils-insert-bibtex-entry-from-doi (doi) - "Insert bibtex entry from a DOI. -Also cleans entry using ‘org-ref’, and tries to download the corresponding pdf." + "Insert and clean bibtex entry from a DOI." (insert (doi-utils-doi-to-bibtex-string doi)) (backward-char) ;; set date added for the record @@ -915,31 +1011,13 @@ Also cleans entry using ‘org-ref’, and tries to download the corresponding p (bibtex-set-field doi-utils-timestamp-field ts))) (org-ref-clean-bibtex-entry) - (save-buffer) - - ;; try to get pdf - (when doi-utils-download-pdf - (doi-utils-get-bibtex-entry-pdf)) - - (when (and doi-utils-make-notes org-ref-bibliography-notes) - (save-excursion - (when (f-file? org-ref-bibliography-notes) - (find-file-noselect org-ref-bibliography-notes) - (save-buffer)) - (let ((bibtex-completion-bibliography (list (buffer-file-name)))) - (funcall doi-utils-make-notes-function))))) - - -;; It may be you are in some other place when you want to add a bibtex entry. -;; This next function will open the first entry in org-ref-default-bibliography -;; go to the end, and add the entry. You can sort it later. + (save-buffer)) ;;;###autoload (defun doi-utils-add-bibtex-entry-from-doi (doi &optional bibfile) "Add DOI entry to end of a file in the current directory. -Pick the file ending with .bib or in -`org-ref-default-bibliography'. If you have an active region that +Pick the file ending with .bib or in . If you have an active region that starts like a DOI, that will be the initial prompt. If no region is selected and the first entry of the ‘kill-ring’ starts like a DOI, then that is the intial prompt. Otherwise, you have to type @@ -960,7 +1038,7 @@ Argument BIBFILE the bibliography to use." (find-file-noselect bibfile) ;; Check if the doi already exists (goto-char (point-min)) - (if (word-search-forward (concat doi) nil t) + (if (re-search-forward (concat doi "\\_>") nil t) (message "%s is already in this file" doi) (goto-char (point-max)) @@ -1068,14 +1146,11 @@ Optional argument NODELIM see `bibtex-make-field'." (insert value)))) -;; The updating function for a whole entry looks like this. We get all the keys -;; from the json plist metadata, and update the fields if they exist. - - (defun plist-get-keys (plist) "Return keys in a PLIST." (-slice plist 0 nil 2)) + ;;;###autoload (defun doi-utils-update-bibtex-entry-from-doi (doi) "Update fields in a bibtex entry from the DOI. @@ -1235,14 +1310,15 @@ May be empty if none are found." ;;;###autoload (defun doi-utils-open-bibtex (doi) - "Search through variable `reftex-default-bibliography' for DOI." + "Search through variable `bibtex-completion-bibliography' for DOI." (interactive "sDOI: ") - (catch 'file - (dolist (f reftex-default-bibliography) - (find-file f) - (when (search-forward doi (point-max) t) - (bibtex-beginning-of-entry) - (throw 'file t))))) + (cl-loop for f in (if (listp bibtex-completion-bibliography) + bibtex-completion-bibliography + (list bibtex-completion-bibliography)) + when (progn (find-file f) + (when (search-forward doi (point-max) t) + (bibtex-beginning-of-entry))) + return f)) ;;;###autoload @@ -1272,62 +1348,37 @@ May be empty if none are found." "http://www.ncbi.nlm.nih.gov/pubmed/?term=%s" (url-hexify-string doi)))) +(declare-function org-element-property "org-element") -(defvar doi-link-menu-funcs '() - "Functions to run in doi menu. -Each entry is a list of (key menu-name function). The function -must take one argument, the doi.") - -(setq doi-link-menu-funcs - '(("o" "pen" doi-utils-open) - ("w" "os" doi-utils-wos) - ("c" "iting articles" doi-utils-wos-citing) - ("r" "elated articles" doi-utils-wos-related) - ("a" "ds" doi-utils-ads) - ("s" "Google Scholar" doi-utils-google-scholar) - ("f" "CrossRef" doi-utils-crossref) - ("p" "ubmed" doi-utils-pubmed) - ("b" "open in bibtex" doi-utils-open-bibtex) - ("g" "et bibtex entry" doi-utils-add-bibtex-entry-from-doi))) +(defhydra doi-link-follow (:color blue :hint nil) + "DOI actions: +" + ("o" (doi-utils-open (org-element-property :path (org-element-context))) "open") + ("w" (doi-utils-wos (org-element-property :path (org-element-context))) "wos") + ("c" (doi-utils-wos-citing (org-element-property :path (org-element-context))) "wos citing articles") + ("r" (doi-utils-wos-related (org-element-property :path (org-element-context))) "wos related articles" ) + ("a" (doi-utils-ads (org-element-property :path (org-element-context))) "ads") + ("s" (doi-utils-google-scholar (org-element-property :path (org-element-context))) "Google Scholar") + ("f" (doi-utils-crossref (org-element-property :path (org-element-context))) "CrossRef") + ("p" (doi-utils-pubmed (org-element-property :path (org-element-context))) "Pubmed") + ("b" (doi-utils-open-bibtex (org-element-property :path (org-element-context))) "open in bibtex") + ("g" (doi-utils-add-bibtex-entry-from-doi (org-element-property :path (org-element-context))) "get bibtex entry")) -;;;###autoload -(defun doi-link-menu (link-string) - "Generate the link menu message, get choice and execute it. -Options are stored in `doi-link-menu-funcs'. -Argument LINK-STRING Passed in on link click." - (interactive) - (message - (concat - (mapconcat - (lambda (tup) - (concat "[" (elt tup 0) "]" - (elt tup 1) " ")) - doi-link-menu-funcs "") ": ")) - (let* ((input (read-char-exclusive)) - (choice (assoc - (char-to-string input) doi-link-menu-funcs))) - (when choice - (funcall - (elt - choice - 2) - link-string)))) - -(org-ref-link-set-parameters "doi" - :follow #'doi-link-menu - :export (lambda (doi desc format) - (cond - ((eq format 'html) - (format "%s" - doi-utils-dx-doi-org-url - doi - (or desc (concat "doi:" doi)))) - ((eq format 'latex) - (format "\\href{%s%s}{%s}" - doi-utils-dx-doi-org-url - doi - (or desc (concat "doi:" doi))))))) +(org-link-set-parameters "doi" + :follow (lambda (_) (doi-link-follow/body)) + :export (lambda (doi desc format) + (cond + ((eq format 'html) + (format "%s" + doi-utils-dx-doi-org-url + doi + (or desc (concat "doi:" doi)))) + ((eq format 'latex) + (format "\\href{%s%s}{%s}" + doi-utils-dx-doi-org-url + doi + (or desc (concat "doi:" doi))))))) ;;* Getting a doi for a bibtex entry missing one @@ -1360,25 +1411,21 @@ Argument LINK-STRING Passed in on link click." ;; According to http://search.crossref.org/help/api we can send a query with a ;; free form citation that may give us something back. We do this to get a list -;; of candidates, and run a helm command to get the doi. - +;; of candidates, which could be used to get the doi. +(declare-function org-ref-bib-citation "org-ref-bibtex") ;;;###autoload (defun doi-utils-crossref-citation-query () "Query Crossref with the title of the bibtex entry at point. -Get a list of possible matches. This opens a helm buffer to -select an entry. The default action inserts a doi and url field -in the bibtex entry at point. The second action opens the doi -url. If there is already a doi field, the function raises an -error." +Get a list of possible matches. Choose one with completion." (interactive) (bibtex-beginning-of-entry) (let* ((entry (bibtex-parse-entry)) (raw-json-string) (json-string) (json-data) - (doi)) - (unless (string= ""(reftex-get-bib-field "doi" entry)) + (doi (bibtex-autokey-get-field "doi"))) + (unless (string= "" doi) (error "Entry already has a doi field")) (with-current-buffer @@ -1398,33 +1445,26 @@ error." (replace-match "\\\"" nil t))) (setq raw-json-string (buffer-substring url-http-end-of-headers (point-max))) ;; decode json string - (setq json-string (decode-coding-string (string-make-unibyte raw-json-string) 'utf-8)) + (setq json-string (decode-coding-string (encode-coding-string raw-json-string 'utf-8) 'utf-8)) (setq json-data (json-read-from-string json-string))) (let* ((name (format "Crossref hits for %s" (org-ref-bib-citation))) - (helm-candidates (mapcar (lambda (x) - (cons - (concat - (cdr (assoc 'fullCitation x))) - (cdr (assoc 'doi x)))) - json-data)) + (candidates (mapcar (lambda (x) + (cons + (concat + (cdr (assoc 'fullCitation x))) + (cdr (assoc 'doi x)))) + json-data)) - (source `((name . ,name) - (candidates . ,helm-candidates) - ;; just return the candidate - (action . (("Insert doi and url field" . (lambda (doi) - (bibtex-make-field "doi" t) - (backward-char) - ;; crossref returns doi url, but I prefer only a doi for the doi field - (insert (replace-regexp-in-string "^https?://\\(dx.\\)?doi.org/" "" doi)) - (when (string= ""(reftex-get-bib-field "url" entry)) - (bibtex-make-field "url" t) - (backward-char) - (insert doi)))) - ("Open url" . (lambda (doi) - (browse-url doi)))))))) - (helm :sources source - :buffer "*doi utils*")))) + (doi (cdr (assoc (completing-read "DOI: " candidates) candidates)))) + (bibtex-make-field "doi" t) + (backward-char) + ;; crossref returns doi url, but I prefer only a doi for the doi field + (insert (replace-regexp-in-string "^https?://\\(dx.\\)?doi.org/" "" doi)) + (when (string= "" (bibtex-autokey-get-field "url")) + (bibtex-make-field "url" t) + (backward-char) + (insert doi))))) @@ -1471,14 +1511,14 @@ error." ;;* Adding a bibtex entry from a crossref query -;; The idea here is to perform a query on Crossref, get a helm buffer of +;; The idea here is to perform a query on Crossref, get a completion buffer of ;; candidates, and select the entry(ies) you want to add to your bibtex file. ;; You can select a region, e.g. a free form citation, or set of words, or you ;; can type the query in by hand. ;;;###autoload (defun doi-utils-add-entry-from-crossref-query (query bibtex-file) - "Search Crossref with QUERY and use helm to select an entry to add to BIBTEX-FILE." + "Search Crossref with QUERY and use completion to select an entry to add to BIBTEX-FILE." (interactive (list (read-string "Query: " @@ -1495,7 +1535,7 @@ error." (completing-read "Bibfile: " (append (f-entries "." (lambda (f) (f-ext? f "bib"))) - org-ref-default-bibliography)))) + bibtex-completion-bibliography)))) (let* ((raw-json-string) (json-string) (json-data) @@ -1519,33 +1559,24 @@ error." (replace-match "\\\"" nil t))) (setq raw-json-string (buffer-substring url-http-end-of-headers (point-max))) ;; decode json string - (setq json-string (decode-coding-string (string-make-unibyte raw-json-string) 'utf-8)) + (setq json-string (decode-coding-string (encode-coding-string raw-json-string 'utf-8) 'utf-8)) (setq json-data (json-read-from-string json-string))) (let* ((name (format "Crossref hits for %s" - ;; remove carriage returns. they cause problems in helm. + ;; remove carriage returns. They can make completion confusing. (replace-regexp-in-string "\n" " " query))) - (helm-candidates (mapcar (lambda (x) - (cons - (concat - (cdr (assoc 'fullCitation x))) - (cdr (assoc 'doi x)))) - json-data)) - (source `((name . ,name) - (candidates . ,helm-candidates) - ;; just return the candidate - (action . (("Insert bibtex entry" . (lambda (doi) - (with-current-buffer (find-file-noselect bibtex-file) - (cl-loop for doi in (helm-marked-candidates) - do - (doi-utils-add-bibtex-entry-from-doi - (replace-regexp-in-string - "^https?://\\(dx.\\)?doi.org/" "" doi) - ,bibtex-file))))) - ("Open url" . (lambda (doi) - (browse-url doi)))))))) - (helm :sources source - :buffer "*doi utils*")))) + (candidates (mapcar (lambda (x) + (cons + (concat + (cdr (assoc 'fullCitation x))) + (cdr (assoc 'doi x)))) + json-data)) + (doi (cdr (assoc (completing-read "Choice: " candidates) candidates)))) + (with-current-buffer (find-file-noselect bibtex-file) + (doi-utils-add-bibtex-entry-from-doi + (replace-regexp-in-string + "^https?://\\(dx.\\)?doi.org/" "" doi) + bibtex-file))))) (defalias 'crossref-add-bibtex-entry 'doi-utils-add-entry-from-crossref-query "Alias function for convenience.") diff --git a/lisp/org-ref/nist-webbook.el b/lisp/org-ref/nist-webbook.el index ec913672..57764dd1 100644 --- a/lisp/org-ref/nist-webbook.el +++ b/lisp/org-ref/nist-webbook.el @@ -29,13 +29,13 @@ (url-hexify-string name) "&Units=SI"))) -(org-ref-link-set-parameters "nist-wb-name" - :follow (lambda (name) - (nist-webbook-name name))) +(org-link-set-parameters "nist-wb-name" + :follow (lambda (name) + (nist-webbook-name name))) -(org-ref-link-set-parameters "nist-wb-formula" - :follow (lambda (formula) - (nist-webbook-formula formula))) +(org-link-set-parameters "nist-wb-formula" + :follow (lambda (formula) + (nist-webbook-formula formula))) (provide 'nist-webbook) diff --git a/lisp/org-ref/org-ref-arxiv.el b/lisp/org-ref/org-ref-arxiv.el index 33b30040..b1265a7c 100644 --- a/lisp/org-ref/org-ref-arxiv.el +++ b/lisp/org-ref/org-ref-arxiv.el @@ -1,6 +1,6 @@ ;;; org-ref-arxiv.el --- arxiv utilities for org-mode -*- lexical-binding: t; -*- -;; Copyright (C) 2015 John Kitchin +;; Copyright (C) 2015-2021 John Kitchin ;; Author: John Kitchin ;; Keywords: @@ -33,12 +33,12 @@ (require 'org-ref-utils) (require 'parsebib) +(require 'xml) ;; This is a local variable defined in `url-http'. We need it to avoid ;; byte-compiler errors. (defvar url-http-end-of-headers) -(defvar org-ref-default-bibliography) -(defvar org-ref-pdf-directory) + (declare-function parsebib-find-bibtex-dialect "parsebib") (declare-function org-ref-clean-bibtex-entry "org-ref-core") @@ -48,17 +48,17 @@ ;;* The org-mode link ;; this just makes a clickable link that opens the entry. ;; example: arxiv:cond-mat/0410285 -(org-ref-link-set-parameters "arxiv" - :follow (lambda (link-string) - (browse-url (format "http://arxiv.org/abs/%s" link-string))) - :export (lambda (keyword desc format) - (cond - ((eq format 'html) - (format "arxiv:%s" - keyword (or desc keyword))) - ((eq format 'latex) - ;; write out the latex command - (format "\\url{http://arxiv.org/abs/%s}{%s}" keyword (or desc keyword)))))) +(org-link-set-parameters "arxiv" + :follow (lambda (link-string) + (browse-url (format "http://arxiv.org/abs/%s" link-string))) + :export (lambda (keyword desc format) + (cond + ((eq format 'html) + (format "arxiv:%s" + keyword (or desc keyword))) + ((eq format 'latex) + ;; write out the latex command + (format "\\url{http://arxiv.org/abs/%s}{%s}" keyword (or desc keyword)))))) ;;* Getting a bibtex entry for an arXiv article using remote service: ;; For an arxiv article, there is a link to a NASA ADS page like this: @@ -76,23 +76,18 @@ (concat "http://adsabs.harvard.edu/cgi-bin/bib_query?arXiv:" arxiv-number)) - (search-forward-regexp "name=\\\"bibcode\\\" value=\\\"\\(.*\\)\\\"") + (search-forward-regexp "") (match-string 1))) (defun arxiv-get-bibtex-entry (arxiv-bibliographic-code) "Get bibtex entry for ARXIV-BIBLIOGRAPHIC-CODE." (with-current-buffer - (url-retrieve-synchronously - (format - "http://adsabs.harvard.edu/cgi-bin/nph-bib_query?bibcode=%s&data_type=BIBTEX&db_key=PRE&nocookieset=1" - arxiv-bibliographic-code)) - (goto-char url-http-end-of-headers) - (if (search-forward "Retrieved 1 abstracts" (point-max) t) - (progn - (forward-line) - (buffer-substring (point) (point-max))) - (error "Did not get one entry: %s" (buffer-substring (point) (point-max)))))) + (url-retrieve-synchronously (format "https://ui.adsabs.harvard.edu/abs/%s/exportcitation" arxiv-bibliographic-code)) + (when (re-search-forward + "\\(.*\\(?:\n.*\\)*?\\(?:\n\\s-*\n\\|\\'\\)\\)" + nil t) + (xml-substitute-special (match-string 1))))) ;;* Getting a bibtex entry for an arXiv article using arXiv API: ;; Retrieves the meta data of an article view arXiv's http API, @@ -109,9 +104,12 @@ abstract = {%s}, url = {%s}, }" - "Template for BibTeX entries of arXiv articles.") + "Template for BibTeX entries of arXiv articles.") +(declare-function doi-utils-doi-to-bibtex-string "doi-utils") +(declare-function org-ref-replace-nonascii "org-ref-bibtex") + (defun arxiv-get-bibtex-entry-via-arxiv-api (arxiv-number) "Retrieve meta data for ARXIV-NUMBER. Returns a formatted BibTeX entry." @@ -137,8 +135,12 @@ Returns a formatted BibTeX entry." (bibtex-mode) (bibtex-set-dialect (parsebib-find-bibtex-dialect) t) (org-ref-replace-nonascii) - (bibtex-generate-autokey)))) - (format arxiv-entry-format-string key title names year arxiv-number category abstract url)))) + (bibtex-generate-autokey))) + (doi (assq 'doi entry))) + (if doi + (doi-utils-doi-to-bibtex-string (nth 2 doi)) + ;; no doi, so we fall back to the simple template + (format arxiv-entry-format-string key title names year arxiv-number category abstract url))))) (defun arxiv-bibtexify-authors (authors) @@ -153,33 +155,39 @@ Returns a formatted BibTeX entry." (let* ((the-current-kill (ignore-errors (current-kill 0 t))) ;; nil if empty kill ring (arxiv-url-prefix-regexp "^https?://arxiv\\.org/\\(pdf\\|abs\\|format\\)/") (arxiv-cite-prefix-regexp "^\\(arXiv\\|arxiv\\):") - (arxiv-id-old-regexp "[a-z-]+\\(\\.[A-Z]\\{2\\}\\)?/[0-9]\\{5,7\\}$") ; Ex: math.GT/0309136 - (arxiv-id-new-regexp "[0-9]\\{4\\}[.][0-9]\\{4,5\\}\\(v[0-9]+\\)?$") ; Ex: 1304.4404v2 + (arxiv-id-old-regexp "[a-z-]+\\(\\.[A-Z]\\{2\\}\\)?/[0-9]\\{5,7\\}") ; Ex: math.GT/0309136 + (arxiv-id-new-regexp "[0-9]\\{4\\}[.][0-9]\\{4,5\\}\\(v[0-9]+\\)?") ; Ex: 1304.4404v2 (arxiv-id-regexp (concat "\\(" arxiv-id-old-regexp "\\|" arxiv-id-new-regexp "\\)"))) - (cond - (;; make sure current-kill has something in it - ;; if current-kill is not a string, return nil - (not (stringp the-current-kill)) - nil) - (;; check if current-kill looks like an arxiv ID - ;; if so, return it - ;; Ex: 1304.4404v2 - (s-match (concat "^" arxiv-id-regexp) the-current-kill) - the-current-kill) - (;; check if current-kill looks like an arxiv cite - ;; if so, remove the prefix and return - ;; Ex: arXiv:1304.4404v2 --> 1304.4404v2 - (s-match (concat arxiv-cite-prefix-regexp arxiv-id-regexp) the-current-kill) - (replace-regexp-in-string arxiv-cite-prefix-regexp "" the-current-kill)) - (;; check if current-kill looks like an arxiv url - ;; if so, remove the url prefix and return - ;; Ex: https://arxiv.org/pdf/1304.4404 --> 1304.4404 - (s-match (concat arxiv-url-prefix-regexp arxiv-id-regexp) the-current-kill) - (replace-regexp-in-string arxiv-url-prefix-regexp "" the-current-kill)) - ;; otherwise, return nil - (t - nil)))) + (cond + (;; make sure current-kill has something in it + ;; if current-kill is not a string, return nil + (not (stringp the-current-kill)) + nil) + (;; check if current-kill looks like an arxiv ID + ;; if so, return it + ;; Ex: 1304.4404v2 + (s-match (concat "^" arxiv-id-regexp) the-current-kill) + the-current-kill) + (;; check if current-kill looks like an arxiv cite + ;; if so, remove the prefix and return + ;; Ex: arXiv:1304.4404v2 --> 1304.4404v2 + (s-match (concat arxiv-cite-prefix-regexp arxiv-id-regexp "$") the-current-kill) + (replace-regexp-in-string arxiv-cite-prefix-regexp "" the-current-kill)) + (;; check if current-kill looks like an arxiv url + ;; if so, remove the url prefix and return + ;; Ex: https://arxiv.org/abs/1304.4404 --> 1304.4404 + (s-match (concat arxiv-url-prefix-regexp arxiv-id-regexp "$") the-current-kill) + (replace-regexp-in-string arxiv-url-prefix-regexp "" the-current-kill)) + (;; check if current-kill looks like an arxiv PDF url + ;; if so, remove the url prefix, the .pdf suffix, and return + ;; Ex: https://arxiv.org/pdf/1304.4404.pdf --> 1304.4404 + (s-match (concat arxiv-url-prefix-regexp arxiv-id-regexp "\\.pdf$") the-current-kill) + (replace-regexp-in-string arxiv-url-prefix-regexp "" (substring the-current-kill 0 (- (length the-current-kill) 4)))) + ;; otherwise, return nil + (t + nil)))) +(defvar bibtex-completion-bibliography) ;;;###autoload (defun arxiv-add-bibtex-entry (arxiv-number bibfile) @@ -192,7 +200,7 @@ Returns a formatted BibTeX entry." (completing-read "Bibfile: " (append (f-entries "." (lambda (f) (f-ext? f "bib"))) - org-ref-default-bibliography)))) + bibtex-completion-bibliography)))) (save-window-excursion (find-file bibfile) (goto-char (point-max)) @@ -224,11 +232,12 @@ Returns a formatted BibTeX entry." (match-string 1)))) (url-copy-file pdf-url pdf) ;; now check if we got a pdf - (if (org-ref-pdf-p pdf) - (org-open-file pdf) + (unless (org-ref-pdf-p pdf) (delete-file pdf) (message "Error downloading arxiv pdf %s" pdf-url)))) +(defvar bibtex-completion-library-path) + ;;;###autoload (defun arxiv-get-pdf-add-bibtex-entry (arxiv-number bibfile pdfdir) "Add bibtex entry for ARXIV-NUMBER to BIBFILE. @@ -243,10 +252,14 @@ key." (completing-read "Bibfile: " (append (f-entries "." (lambda (f) (f-ext? f "bib"))) - org-ref-default-bibliography)) - (read-directory-name - "PDF directory: " - org-ref-pdf-directory))) + bibtex-completion-bibliography)) + (cond + ((stringp bibtex-completion-library-path) + bibtex-completion-library-path) + ((= 1 (length bibtex-completion-library-path)) + (car bibtex-completion-library-path)) + (t + (completing-read "PDF dir: " bibtex-completion-library-path))))) (arxiv-add-bibtex-entry arxiv-number bibfile) @@ -276,7 +289,13 @@ key." (setq key (bibtex-read-key "Duplicate Key found, edit: " key)))) (setq key (bibtex-read-key "Key not found, insert: "))) (insert key) - (arxiv-get-pdf arxiv-number (concat pdfdir key ".pdf"))))) + (arxiv-get-pdf arxiv-number (concat pdfdir key ".pdf")) + ;; Check that it worked, and insert a field for it. + (when (file-exists-p (concat pdfdir key ".pdf")) + (bibtex-end-of-entry) + (backward-char) + (insert (format " file = {%s}\n " (concat pdfdir key ".pdf"))))))) + (provide 'org-ref-arxiv) ;;; org-ref-arxiv.el ends here diff --git a/lisp/org-ref/org-ref-bibliography-links.el b/lisp/org-ref/org-ref-bibliography-links.el new file mode 100644 index 00000000..b244d287 --- /dev/null +++ b/lisp/org-ref/org-ref-bibliography-links.el @@ -0,0 +1,312 @@ +;;; org-ref-bibliography-links.el --- Bibliography and bibliographystyle links +;; +;; Copyright (C) 2021 John Kitchin + +;; Author: John Kitchin +;; Keywords: convenience + +;; 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: +;; + +;;; Code: + +(defcustom org-ref-latex-bib-resolve-func #'file-relative-name + "Function to expand paths to the bibliography file on latex export. +Use this to convert a path to what you want, e.g. relative to +some directory, absolute, etc." + :type 'function + :group 'org-ref) + + +(defcustom org-ref-validate-bibliography nil + "If non-nil, validate bibliography files in fontification. +This can be slow, so we don't do it by default." + :type 'boolean + :group 'org-ref) + + +;;* bibliography* links + +(defun org-ref-get-bibfile-path (bibfile) + "Get a path to BIBFILE as local file, or using kpsewhich. +This should allow you to use a bib file that is setup with TeX +variables like BIBINPUTS." + (or (when (file-exists-p bibfile) bibfile) + (let ((f (replace-regexp-in-string + "\n$" "" + (shell-command-to-string (format "kpsewhich %s" bibfile))))) + (unless (string= "" f) + f)))) + + +(defun org-ref-bibliography*-export (cmd bibfiles _desc backend) + "Exporting function for bibliography links. +To be used as a partial function e.g. + (apply-partially \"bibliography\" 'org-ref-bibliography*-export) +Argument CMD is the command it should export to. +Argument BIBFILES is a comma-separated list of strings. +Argument BACKEND is the export backend." + (cond + ((eq backend 'latex) + (format "%s{%s}" + cmd + (if (not (string= "" bibfiles)) + (replace-regexp-in-string + "\\.bib" "" + (mapconcat + 'identity + (mapcar + (lambda (f) + (funcall org-ref-latex-bib-resolve-func (org-ref-get-bibfile-path f))) + (split-string bibfiles ",")) + ",")) + ""))))) + + +(defun org-ref-bibliography-activate (start end path _bracketp) + "Activate a bibliography link. +Adds a warning face to non-existent or invalid bib-files. +START and END are the bounds of the link. +PATH is a comma-separated list of bibfiles." + (goto-char start) + (cl-loop for p in (split-string path ",") do + (setq p (string-trim p)) + (search-forward p) + (setq p (org-ref-get-bibfile-path p)) + (put-text-property (match-beginning 0) (match-end 0) 'org-ref-bibfile p) + (put-text-property (match-beginning 0) (match-end 0) 'help-echo (format "File exists at %s" p)) + + ;; activate files that don't exist + (when (or (null p) (not (file-exists-p p))) + (put-text-property (match-beginning 0) (match-end 0) + 'face 'font-lock-warning-face) + (put-text-property (match-beginning 0) (match-end 0) + 'help-echo "This file was not found.")) + + (when (and p (file-exists-p p)) + (when org-ref-validate-bibliography + ;; Let's do a validation, but only if it has changed since the last time we checked. + (let* ((mod-time-last-check (or (get-text-property (match-beginning 0) + 'mod-time-last-check) + '(0 0 0 0))) + (last-modified (file-attribute-modification-time (file-attributes p))) + (bibtex-valid)) + (if (time-equal-p mod-time-last-check last-modified) + (setq bibtex-valid (get-text-property (match-beginning 0) 'bibtex-valid)) + + ;; the times were not equal, so we check and store the state. + (setq bibtex-valid (save-match-data + (with-current-buffer (find-file-noselect p) + (bibtex-validate)))) + (put-text-property (match-beginning 0) + (match-end 0) + 'mod-time-last-check + last-modified) + (put-text-property (match-beginning 0) + (match-end 0) + 'bibtex-valid + bibtex-valid)) + + (unless bibtex-valid + (put-text-property (match-beginning 0) (match-end 0) + 'face 'font-lock-warning-face) + (put-text-property (match-beginning 0) (match-end 0) + 'help-echo "This file did not pass `bibtex-validate'."))))))) + + +(defun org-ref-bibliography*-follow (_path) + "Function to follow bibliography links." + (interactive) + (save-excursion + (unless (get-text-property (point) 'org-ref-bibfile) + (re-search-forward ":")) + (find-file (org-ref-get-bibfile-path (get-text-property (point) 'org-ref-bibfile))))) + + +(defun org-ref-printbibliography-export (options _desc backend) + "Export function for printbibliography links. +Argument OPTIONS are the options used for the command. +Optional argument BACKEND is the export backend." + (cond + ((eq backend 'latex) + ;; write out the biblatex bibliography command + (format "\\printbibliography%s" + (if (not (string= "" options)) + (format "[%s]" options) + ""))))) + +(defvar org-ref-cite-types) +(declare-function org-element-map "org-element") +(declare-function org-element-property "org-element") +(declare-function org-element-parse-buffer "org-element") +(declare-function bibtex-completion-show-entry "bibtex-completion") +(declare-function org-ref-possible-bibfiles "org-ref-core") +(declare-function org-ref-parse-cite-path "org-ref-citation-links") + +(defun org-ref-insert-bibliography-link () + "Insert a bibliography link for the files used in this buffer." + (interactive) + (let* ((cite-links (org-element-map (org-element-parse-buffer) 'link + (lambda (lnk) + (when (assoc (org-element-property :type lnk) org-ref-cite-types) + lnk)))) + (keys (delete-dups (cl-loop for cl in cite-links append + (cl-loop for ref in (plist-get (org-ref-parse-cite-path + (org-element-property :path cl)) + :references) + collect (plist-get ref :key))))) + (files (delete-dups (cl-loop for key in keys collect + (save-window-excursion + (bibtex-completion-show-entry (list key)) + (buffer-file-name)))))) + (insert (format "bibliography:%s" (string-join files ","))))) + + +(defun org-ref-bibliography-complete (&optional arg) + "Completion function for bibliography links." + (concat "bibliography:" + (completing-read "Bibliography file: " (org-ref-possible-bibfiles)))) + +(defun org-ref-nobibliography-complete (&optional arg) + "Completion function for bibliography links." + (concat "nobibliography:" + (completing-read "Bibliography file: " (org-ref-possible-bibfiles)))) + + +(defvar org-ref-default-citation-link) + +(defun org-ref-bibtex-store-link () + "Store a link from a bibtex file. Only supports the cite link. +This essentially the same as the store link in org-bibtex, but it +creates a cite link." + (when (eq major-mode 'bibtex-mode) + (let ((link (concat org-ref-default-citation-link + ":&" + (save-excursion + (bibtex-beginning-of-entry) + (cdr (assoc "=key=" (bibtex-parse-entry))))))) + (push (list link) org-stored-links) + (car org-stored-links)))) + + +;; ** bibliography* links + +(org-link-set-parameters "bibliography" + :follow #'org-ref-bibliography*-follow + :store #'org-ref-bibtex-store-link + :complete #'org-ref-bibliography-complete + :help-echo "Bibliography link" + :export (apply-partially 'org-ref-bibliography*-export "\\bibliography") + :activate-func #'org-ref-bibliography-activate + :face 'org-link) + + +(org-link-set-parameters "nobibliography" + :complete #'org-ref-nobibliography-complete + :store #'org-ref-bibtex-store-link + :help-echo "No bibliography link" + :activate-func #'org-ref-bibliography-activate + :follow #'org-ref-bibliography*-follow + :export (apply-partially 'org-ref-bibliography*-export "\\nobibliography") + :face 'org-link) + + +(org-link-set-parameters "nobibliography*" + :complete #'org-ref-nobibliography-complete + :store #'org-ref-bibtex-store-link + :help-echo "No bibliography link" + :activate-func #'org-ref-bibliography-activate + :follow #'org-ref-bibliography*-follow + :export (apply-partially 'org-ref-bibliography*-export "\\nobibliography*") + :face 'org-link) + + +(org-link-set-parameters "printbibliography" + :export #'org-ref-printbibliography-export) + +;; Note I removed the addbibresource link, it goes in the header, not the document. + +;; *** bibliographystyle +(defvar-local org-ref-bst-styles nil + "A list of known bibliography styles. Used to cache results.") + + +(defun org-ref-clear-bst-cache () + "Clear `org-ref-bst-styles' to reload it." + (interactive) + (setq org-ref-bst-styles nil)) + + +(defun org-ref-bibliography-styles () + "Return a list of known bibliography styles. +Returns `org-ref-bst-styles' or sets it and returns it." + (or org-ref-bst-styles + (setq org-ref-bst-styles + (mapcar 'file-name-nondirectory + (mapcar 'file-name-sans-extension + (-flatten + (mapcar (lambda (path) + (setq path (replace-regexp-in-string "!" "" path)) + (when (file-directory-p path) + (f-entries path (lambda (f) (f-ext? f "bst")) t))) + (split-string + ;; https://tex.stackexchange.com/questions/431948/get-a-list-of-installed-bibliography-styles-with-kpsewhich?noredirect=1#comment1082436_431948 + (shell-command-to-string "kpsewhich -expand-path '$BSTINPUTS'") + ":")))))))) + + +(defun org-ref-bibliographystyle-complete-link (&optional arg) + "Completion function for bibliography style links. +ARG is a not used." + (when (executable-find "kpsewhich") + (concat "bibliographystyle:" + (completing-read "Style: " (org-ref-bibliography-styles))))) + + +(defun org-ref-bibliographystyle-activate (start _end path _bracketp) + "Activation function for bibliography styles. +START is the beginning position of the link. +Optional argument PATH contains the selected style." + (unless (member path (org-ref-bibliography-styles)) + (goto-char start) + (search-forward path) + (put-text-property (match-beginning 0) (match-end 0) 'face 'font-lock-warning-face) + (put-text-property (match-beginning 0) (match-end 0) 'help-echo "Unrecognized style"))) + + +(defun org-ref-bibliographystyle-export (style _desc backend) + "Export function for bibliographystyle links. +Argument STYLE is the desired style. +Optional argument BACKEND is the export backend." + (cond + ((or (eq backend 'latex) + (eq backend 'beamer)) + ;; write out the latex bibliography command + (format "\\bibliographystyle{%s}" style)) + ;; No other backend needs this I think + (t + ""))) + + +(org-link-set-parameters "bibliographystyle" + :complete #'org-ref-bibliographystyle-complete-link + :activate-func #'org-ref-bibliographystyle-activate + :export #'org-ref-bibliographystyle-export) + + +(provide 'org-ref-bibliography-links) + +;;; org-ref-bibliography-links.el ends here diff --git a/lisp/org-ref/org-ref-bibtex.el b/lisp/org-ref/org-ref-bibtex.el index f75bb45c..434810a4 100644 --- a/lisp/org-ref/org-ref-bibtex.el +++ b/lisp/org-ref/org-ref-bibtex.el @@ -1,12 +1,11 @@ ;;; org-ref-bibtex.el -- org-ref-bibtex utilities -;; Copyright(C) 2014 John Kitchin +;; Copyright(C) 2014-2021 John Kitchin ;; Author: John Kitchin ;; URL: https://github.com/jkitchin/org-ref ;; Version: 0.1 ;; Keywords: org-mode, bibtex -;; Package-Requires: ((org-ref) (s) (dash) (doi-utils) (key-chord)) ;; This file is not currently part of GNU Emacs. @@ -27,6 +26,15 @@ ;;; Commentary: + +;; Functions to act on a bibtex entry or file +;; +;; ** Modifying bibtex entries +;; - `org-ref-sort-bibtex-entry' :: sort the fields in an entry +;; - `org-ref-downcase-bibtex-entry' :: downcase the fields in an entry +;; - `org-ref-clean-bibtex-entry' :: run hooks in `org-ref-clean-bibtex-entry-hook' on an entry +;; - `org-ref-title-case-article' :: title case the title in an article or book +;; - `org-ref-sentence-case-article' :: sentence case the title in an article. ;; org-ref-bibtex-generate-longtitles ;; org-ref-bibtex-generate-shorttitles ;; org-ref-stringify-journal-name :: replace a journal name with a string in @@ -34,69 +42,36 @@ ;; org-ref-set-journal-string :: in a bibtex entry run this to replace the ;; journal with a string ;; -;; org-ref-title-case-article :: title case the title in an article or book -;; org-ref-sentence-case-article :: sentence case the title in an article. +;; * Navigating bibtex entries +;; `org-ref-bibtex-next-entry' :: bound to M-n +;; `org-ref-bibtex-previous-entry' :: bound to M-p + +;; +;; ** Operate on whole bibtex file +;; - `org-ref-build-full-bibliography' ;; org-ref-replace-nonascii :: replace nonascii characters in a bibtex ;; entry. Replacements are in `org-ref-nonascii-latex-replacements'. ;; -;; org-ref-title-case-article -;; org-ref-sentence-case-article +;; ** hydra menu for bibtex files +;; `org-ref-bibtex-hydra/body' gives a hydra menu to a lot of useful functions. +;; `org-ref-bibtex-new-entry/body' gives a hydra menu to add new bibtex entries. +;; `org-ref-bibtex-file/body' gives a hydra menu of actions for the bibtex file ;; -;; org-ref-bibtex-next-entry :: bound to M-n -;; org-ref-bibtex-previous-entry :: bound to M-p -;; -;; Functions to act on a bibtex entry or file -;; org-ref-bibtex-hydra/body gives a hydra menu to a lot of useful functions. -;; org-ref-bibtex-new-entry/body gives a hydra menu to add new bibtex entries. -;; org-ref-bibtex-file/body gives a hydra menu of actions for the bibtex file -;; -;; org-ref-bibtex :: a deprecated menu of actions +;;; Code (require 'bibtex) (require 'dash) (require 'hydra) -(require 'key-chord nil 'no-error) (require 'message) (require 's) - -(require 'org-ref-citeproc) (require 'doi-utils) +(require 'avy) -(defvar org-ref-pdf-directory) -(defvar org-ref-notes-directory) -(defvar org-ref-default-bibliography) - -(declare-function reftex-get-bib-field "reftex-cite") -(declare-function key-chord-define-global "key-chord") +(defvar bibtex-completion-bibliography) +(declare-function bibtex-completion-show-entry "bibtex-completion") (declare-function org-ref-find-bibliography "org-ref-core") -(declare-function org-ref-open-bibtex-pdf "org-ref-core") -(declare-function org-ref-open-bibtex-notes "org-ref-core") -(declare-function org-ref-clean-bibtex-entry "org-ref-core") -(declare-function org-ref-open-in-browser "org-ref-core") -(declare-function org-ref-sort-bibtex-entry "org-ref-core") -(declare-function org-ref-build-full-bibliography "org-ref-core") -(declare-function helm-tag-bibtex-entry "org-ref-helm") -(declare-function bibtex-completion-edit-notes "bibtex-completion") -(declare-function bibtex-completion-get-value "bibtex-completion") -(declare-function bibtex-completion-get-entry "bibtex-completion") -(declare-function parsebib-find-next-item "parsebib") -(declare-function parsebib-read-entry "parsebib") -(declare-function helm-bibtex "helm-bibtex") -(declare-function helm "helm") - -;;; Code: - -;; This is duplicated from org-ref-core to try to avoid a byte-compile error. -(add-to-list 'load-path - (expand-file-name - "citeproc" - (file-name-directory (or load-file-name (buffer-file-name))))) - -(add-to-list 'load-path - (expand-file-name - "citeproc/csl" - (file-name-directory (or load-file-name (buffer-file-name))))) +(declare-function org-element-property "org-element") ;;* Custom variables (defgroup org-ref-bibtex nil @@ -104,183 +79,287 @@ :group 'org-ref-bibtex) -(defcustom org-ref-bibtex-hydra-key-chord - nil - "Key-chord to run `org-ref-bibtex-hydra'. -I like \"jj\"" - :type '(choice (const nil :tag "None") - (string)) - :group 'org-ref-bibtex) - - -(defcustom org-ref-bibtex-hydra-key-binding - nil - "Key-binding to run `org-ref-bibtex-hydra'. -I like \"C-c j\"." - :type '(choice (const nil :tag "No binding") - (key-sequence)) - :group 'org-ref-bibtex) - - -(defcustom org-ref-helm-cite-shorten-authors nil - "If non-nil show only last names in the helm selection buffer." +(defcustom org-ref-shorten-authors nil + "If non-nil show only last names in the completion selection buffer." :type 'boolean :group 'org-ref-bibtex) -(defcustom org-ref-formatted-citation-formats - '(("text" . (("article" . "${author}, ${title}, ${journal}, ${volume}(${number}), ${pages} (${year}). ${doi}") - ("inproceedings" . "${author}, ${title}, In ${editor}, ${booktitle} (pp. ${pages}) (${year}). ${address}: ${publisher}.") - ("book" . "${author}, ${title} (${year}), ${address}: ${publisher}.") - ("phdthesis" . "${author}, ${title} (Doctoral dissertation) (${year}). ${school}, ${address}.") - ("inbook" . "${author}, ${title}, In ${editor} (Eds.), ${booktitle} (pp. ${pages}) (${year}). ${address}: ${publisher}.") - ("incollection" . "${author}, ${title}, In ${editor} (Eds.), ${booktitle} (pp. ${pages}) (${year}). ${address}: ${publisher}.") - ("proceedings" . "${editor} (Eds.), ${booktitle} (${year}). ${address}: ${publisher}.") - ("unpublished" . "${author}, ${title} (${year}). Unpublished manuscript.") - (nil . "${author}, ${title} (${year})."))) - ("org" . (("article" . "${author}, /${title}/, ${journal}, *${volume}(${number})*, ${pages} (${year}). ${doi}") - ("inproceedings" . "${author}, /${title}/, In ${editor}, ${booktitle} (pp. ${pages}) (${year}). ${address}: ${publisher}.") - ("book" . "${author}, /${title}/ (${year}), ${address}: ${publisher}.") - ("phdthesis" . "${author}, /${title}/ (Doctoral dissertation) (${year}). ${school}, ${address}.") - ("inbook" . "${author}, /${title}/, In ${editor} (Eds.), ${booktitle} (pp. ${pages}) (${year}). ${address}: ${publisher}.") - ("incollection" . "${author}, /${title}/, In ${editor} (Eds.), ${booktitle} (pp. ${pages}) (${year}). ${address}: ${publisher}.") - ("proceedings" . "${editor} (Eds.), _${booktitle}_ (${year}). ${address}: ${publisher}.") - ("unpublished" . "${author}, /${title}/ (${year}). Unpublished manuscript.") - (nil . "${author}, /${title}/ (${year}).")))) - "Format strings for formatted bibtex entries for different citation backends. -Used in `org-ref-format-entry'." - :type '(alist) - :group 'org-ref-bibtex) +(defcustom org-ref-bibtex-sort-order + '(("article" . ("author" "title" "journal" "volume" "number" "pages" "year" "doi" "url")) + ("inproceedings" . ("author" "title" "booktitle" "year" "volume" "number" "pages" "doi" "url")) + ("book" . ("author" "title" "year" "publisher" "url"))) + "A-list of bibtex entry fields and the order to sort an entry with. +\(entry-type . (list of fields). This is used in +`org-ref-sort-bibtex-entry'. Entry types not listed here will +have fields sorted alphabetically." + :type '(alist :key-type (string) :value-type (repeat string)) + :group 'org-ref) -(defcustom org-ref-formatted-citation-backend "text" - "The backend format for formatted citations. -Should be one of the cars of `org-ref-formatted-citation-formats'." - :type 'string - :group 'org-ref-bibtex) -;;* Journal abbreviations -(defvar org-ref-bibtex-journal-abbreviations - '() - "List of (string journal-full-name journal-abbreviation). Find - new abbreviations at http://cassi.cas.org/search.jsp.") +(defcustom orcb-%-replacement-string " \\\\%" + "Replacement for a naked % sign in cleaning a BibTeX entry. +The replacement string should be escaped for use with +`replace-match'. Compare to the default value. Common choices +would be to omit the space or to replace the space with a ~ for a +non-breaking space." + :type 'regexp + :group 'org-ref) + + +(defcustom org-ref-clean-bibtex-key-function + (lambda (key) + (replace-regexp-in-string ":" "" key)) + "Function to modify a bibtex key. +The default behavior is to remove : from the key." + :type 'function + :group 'org-ref) + + +(defcustom org-ref-clean-bibtex-entry-hook + '(org-ref-bibtex-format-url-if-doi + orcb-key-comma + org-ref-replace-nonascii + orcb-& + orcb-% + org-ref-title-case-article + orcb-clean-year + orcb-key + orcb-clean-doi + orcb-clean-pages + orcb-check-journal + org-ref-sort-bibtex-entry + orcb-fix-spacing + orcb-download-pdf) + "Hook that is run in `org-ref-clean-bibtex-entry'. +The functions should have no arguments, and +operate on the bibtex entry at point. You can assume point starts +at the beginning of the entry. These functions are wrapped in +`save-restriction' and `save-excursion' so you do not need to +save the point position. + +Org ref contains some functions that are not included by default +such as `orcb-clean-nil' or `orcb-clean-nil-opinionated' that +users may be interested in adding themselves." + :group 'org-ref + :type 'hook) + +;; see https://github.com/fxcoudert/tools/blob/master/doi2bib for more replacements +(defcustom org-ref-nonascii-latex-replacements + '(("í" . "{\\\\'i}") + ("æ" . "{\\\\ae}") + ("ć" . "{\\\\'c}") + ("é" . "{\\\\'e}") + ("ä" . "{\\\\\"a}") + ("è" . "{\\\\`e}") + ("à" . "{\\\\`a}") + ("á" . "{\\\\'a}") + ("ø" . "{\\\\o}") + ("ë" . "{\\\\\"e}") + ("ü" . "{\\\\\"u}") + ("ñ" . "{\\\\~n}") + ("ņ" . "{\\\\c{n}}") + ("ñ" . "{\\\\~n}") + ("å" . "{\\\\aa}") + ("ö" . "{\\\\\"o}") + ("Á" . "{\\\\'A}") + ("í" . "{\\\\'i}") + ("ó" . "{\\\\'o}") + ("ó" . "{\\\\'o}") + ("ú" . "{\\\\'u}") + ("ú" . "{\\\\'u}") + ("ý" . "{\\\\'y}") + ("š" . "{\\\\v{s}}") + ("č" . "{\\\\v{c}}") + ("ř" . "{\\\\v{r}}") + ("š" . "{\\\\v{s}}") + ("İ" . "{\\\\.I}") + ("ğ" . "{\\\\u{g}}") + ("δ" . "$\\\\delta$") + ("ç" . "{\\\\c{c}}") + ("ß" . "{\\\\ss}") + ("≤" . "$\\\\le$") + ("≥" . "$\\\\ge$") + ("θ" . "$\\\\theta$") + ("μ" . "$\\\\mu$") + ("→" . "$\\\\rightarrow$") + ("⇌" . "$\\\\leftrightharpoons$") + ("×" . "$\\\\times$") + ("°" . "$\\\\deg$") + ("ş" . "{\\\\c{s}}") + ("γ" . "$\\\\gamma$") + ("ɣ" . "$\\\\gamma$") + ("º" . "degC") + ("η" . "$\\\\eta$") + ("µ" . "$\\\\mu$") + ("α" . "$\\\\alpha$") + ("β" . "$\\\\beta$") + ("ɛ" . "$\\\\epsilon$") + ("Ⅵ" . "\\textrm{VI}") + ("Ⅲ" . "\\textrm{III}") + ("Ⅴ" . "\\textrm{V}") + ("λ" . "$\\\\lambda$") + ("π" . "$\\\\pi$") + ("∞" . "$\\\\infty$") + ("χ" . "$\\\\chi$") + ("∼" . "\\\\textasciitilde{}") + ("‑" . "\\\\textemdash{}") + (" " . " ") + ("…" . "...") + ("•" . "\\\\textbullet ") + ;; I think these are non-ascii spaces. there seems to be more than one. + (" " . " ") + (" " . " ") + (" " . " ") + ("–" . "-") + ("−" . "-") + ("–" . "-") + ("—" . "-") + ("‒" . "\\\\textemdash{}") + ("‘" . "'") + ("’" . "'") + ("’" . "'") + ("“" . "\"") + ("’" . "'") + ("”" . "\"")) + "Cons list of non-ascii characters and their LaTeX representations. +This may be deprecated. When `org-ref' started, non-ascii +characters were often problematic with bibtex, but in 2021, it is +not obvious that is still try." + :type '(alist :key-type (string) :value-type (string)) + :group 'org-ref-bibtex) (defcustom org-ref-bibtex-assoc-pdf-with-entry-move-function 'rename-file "Function to use when associating pdf files with bibtex entries. The value should be either `rename-file' or `copy-file'. The former will move and rename the original file. The latter will leave the -original file in place while creating a renamed copy in -`org-ref-pdf-directory'." +original file in place while creating a renamed copy in some directory." :type 'function :group 'org-ref-bibtex) -(setq org-ref-bibtex-journal-abbreviations - '(("ACR" "Accounts of Chemical Research" "Acc. Chem. Res.") - ("ACAT" "ACS Catalysis" "ACS Catal.") - ("AM" "Acta Materialia" "Acta Mater.") - ("AMM" "Acta Metallurgica et Materialia" "Acta Metall. Mater.") - ("AEM" "Advanced Energy Materials" "Adv. Energy Mater.") - ("AAMI" "ACS Applied Materials \\& Interfaces" - "ACS Appl. Mater. Interfaces") - ("AMiner" "American Mineralogist" "Am. Mineral.") - ("AngC" "Angewandte Chemie-International Edition" - "Angew. Chem. Int. Edit.") - ("APLM" "APL Materials" "APL Mat.") - ("ACBE" "Applied Catalysis B: Environmental" "Appl. Catal. B-Environ.") - ("APL" "Applied Physics Letters" "Appl. Phys. Lett.") - ("ASS" "Applied Surface Science" "Appl. Surf. Sci.") - ("CL" "Catalysis Letters" "Catal. Lett.") - ("CC" "Catalysis Communications" "Catal. Commun.") - ("CST" "Catalysis Science & Technology" "Catal. Sci. Technol.") - ("CT" "Catalysis Today" "Catal. Today") - ("ChC" "Chemical Communications" "Chem. Commun.") - ("CPL" "Chemical Physics Letters" "Chem. Phys. Lett") - ("CR" "Chemical Reviews" "Chem. Rev.") - ("CSR" "Chemical Society Reviews" "Chem. Soc. Rev.") - ("CSR" "Chemical Society Reviews" "Chem. Soc. Rev.") - ("CM" "Chemistry of Materials" "Chem. Mater.") - ("CSA" "Colloids and Surfaces, A: Physicochemical and Engineering Aspects" - "Colloids Surf., A") - ("CF" "Combustion and Flame" "Combust. Flame") - ("CPMS" "Computational Materials Science" "Comp. Mater. Sci.") - ("CPC" "Computer Physics Communications" "Comput. Phys. Commun.") - ("CSE" "Computing in Science \\& Engineering" "Comput. Sci. Eng.") - ("CGD" "Crystal Growth \\& Design" "Cryst. Growth Des.") - ("CEC" "CrystEngComm" "CrystEngComm") - ("EA" "Electrochimica Acta" "Electrochim. Acta") - ("ECST" "ECS Transactions" "ECS Trans.") - ("EES" "Energy \\& Environmental Science" "Energy Environ. Sci.") - ("HPR" "High Pressure Research" "High Pressure Res.") - ("IC" "Inorganic Chemistry" "Inorg. Chem.") - ("IECR" "Industrial \\& Engineering Chemistry Research" - "Ind. Eng. Chem. Res.") - ("JJAP" "Japanese Journal of Applied Physics" "Jpn. J. Appl. Phys.") - ("JMatR" "Journal of Materials Research" "J. Mater. Res.") - ("JALC" "Journal of Alloys and Compounds" "J. Alloy Compd.") - ("JAC" "Journal of Applied Crystallography" "J. Appl. Crystallogr.") - ("JAE" "Journal of Applied Electrochemistry" "J. Appl. Electrochem.") - ("JAP" "Journal of Applied Physics" "J. Appl. Phys.") - ("JC" "Journal of Catalysis" "J. Catal.") - ("JCP" "Journal of Chemical Physics" "J. Chem. Phys.") - ("JCC" "Journal of Computational Chemistry" "J. Comput. Chem.") - ("JCG" "Journal of Crystal Growth" "J. Crys. Growth") - ("JMC" "Journal of Materials Chemistry" "J. Mater. Chem.") - ("JMC" "Journal of Materials Chemistry" "J. Mater. Chem.") - ("JMSL" "Journal of Materials Science Letters" "J. Mater. Sci. Lett.") - ("JMS" "Journal of Membrane Science" "J. Memb. Sci.") - ("JPE" "Journal of Phase Equilibria" "J. Phase Equilib.") - ("JPCS" "Journal of Physics and Chemistry of Solids" - "J. Phys. Chem. Solids") - ("JPCM" "Journal of Physics: Condensed Matter" - "J. Phys.: Condens. Matter") - ("JPS" "Journal of Power Sources" "J. Power Sources") - ("JSSC" "Journal of Solid State Chemistry" "J. Solid State Chem.") - ("JACerS" "Journal of the American Ceramic Society" "J. Am. Ceram. Soc.") - ("JACS" "Journal of the American Chemical Society" "J. Am. Chem. Soc.") - ("JASIST" "Journal of the American Society for Information Science and Technology" - "J. Am. Soc. Inf. Sci. Technol.") - ("JES" "Journal of The Electrochemical Society" "J. Electrochem. Soc.") - ("JEaC" "Journal of Electroanalytical Chemistry" "J. Electroanal. Chem.") - ("JMS" "Journal of Membrane Science" "J. Memb. Sci.") - ("JRS" "Journal of Raman Spectroscopy" "J. Raman Spectrosc.") - ("JVST" "Journal of Vacuum Science \\& Technology A" - "J. Vac. Sci. Technol. A") - ("ML" "Materials Letters" "Mater. Lett.") - ("MSE-BS" "Materials Science and Engineering B" "Mat. Sci. Eng. B-Solid") - ("MOLSIM" "Molecular Simulation" "Mol. Sim.") - ("Nature" "Nature" "Nature") - ("NM" "Nature Materials" "Nat. Mater.") - ("NC" "Nature Chemistry" "Nat. Chem.") - ("PML" "Philosophical Magazine Letters" "Phil. Mag. Lett.") - ("PMA" "Philosophical Magazine A" "Phil. Mag. A") - ("PA" "Physica A: Statistical Mechanics and its Applications" "Physica A") - ("PB" "Physica B-Condensed Matter" "Physica B") - ("PCCP" "Physical Chemistry Chemical Physics" "Phys. Chem. Chem. Phys.") - ("PSSB" "physica status solidi (b)" "Phys. Status Solidi B") - ("PRA" "Physical Review A" "Phys. Rev. A") - ("PRB" "Physical Review B" "Phys. Rev. B") - ("PRL" "Physical Review Letters" "Phys. Rev. Lett.") - ("PCM" "Physics and Chemistry of Minerals" "Phys. Chem. Miner.") - ("PNAS" "Proceedings of the National Academy of Sciences of the United States of America" - "Proc. Natl. Acad. Sci. U. S. A.") - ("PSurfSci" "Progress in Surface Science" "Prog. Surf. Sci.") - ("Science" "Science" "Science") - ("SM" "Scripta Materialia" "Scr. Mater.") - ("SABC" "Sensors and Actuators B: Chemical" "Sensor. Actuat. B-Chem.") - ("SS" "Surface Science" "Surf. Sci.") - ("EPJB" "The European Physical Journal B" "Eur. Phys. J. B") - ("JPC" "The Journal of Physical Chemistry" "J. Phys. Chem.") - ("JPCB" "The Journal of Physical Chemistry B" "J. Phys. Chem. B") - ("JPCC" "The Journal of Physical Chemistry C" "J. Phys. Chem. C") - ("JPCL" "The Journal of Physical Chemistry Letters" - "J. Phys. Chem. Lett.") - ("JCP" "The Journal of Chemical Physics" "J. Chem. Phys.") - ("MSMSE" "Modelling and Simulation in Materials Science and Engineering" - "Modell. Simul. Mater. Sci. Eng.") - ("TSF" "Thin Solid Films" "Thin Solid Films") - ("TC" "Topics in Catalysis" "Top. Catal.") - ("WR" "Water Research" "Water Res."))) +;;* Journal abbreviations +(defcustom org-ref-bibtex-journal-abbreviations + '(("ACR" "Accounts of Chemical Research" "Acc. Chem. Res.") + ("ACAT" "ACS Catalysis" "ACS Catal.") + ("AM" "Acta Materialia" "Acta Mater.") + ("AMM" "Acta Metallurgica et Materialia" "Acta Metall. Mater.") + ("AEM" "Advanced Energy Materials" "Adv. Energy Mater.") + ("AAMI" "ACS Applied Materials \\& Interfaces" + "ACS Appl. Mater. Interfaces") + ("AMiner" "American Mineralogist" "Am. Mineral.") + ("AngC" "Angewandte Chemie-International Edition" + "Angew. Chem. Int. Edit.") + ("APLM" "APL Materials" "APL Mat.") + ("ACBE" "Applied Catalysis B: Environmental" "Appl. Catal. B-Environ.") + ("APL" "Applied Physics Letters" "Appl. Phys. Lett.") + ("ASS" "Applied Surface Science" "Appl. Surf. Sci.") + ("CL" "Catalysis Letters" "Catal. Lett.") + ("CC" "Catalysis Communications" "Catal. Commun.") + ("CST" "Catalysis Science & Technology" "Catal. Sci. Technol.") + ("CT" "Catalysis Today" "Catal. Today") + ("ChC" "Chemical Communications" "Chem. Commun.") + ("CPL" "Chemical Physics Letters" "Chem. Phys. Lett") + ("CR" "Chemical Reviews" "Chem. Rev.") + ("CSR" "Chemical Society Reviews" "Chem. Soc. Rev.") + ("CSR" "Chemical Society Reviews" "Chem. Soc. Rev.") + ("CM" "Chemistry of Materials" "Chem. Mater.") + ("CSA" "Colloids and Surfaces, A: Physicochemical and Engineering Aspects" + "Colloids Surf., A") + ("CF" "Combustion and Flame" "Combust. Flame") + ("CPMS" "Computational Materials Science" "Comp. Mater. Sci.") + ("CPC" "Computer Physics Communications" "Comput. Phys. Commun.") + ("CSE" "Computing in Science \\& Engineering" "Comput. Sci. Eng.") + ("CGD" "Crystal Growth \\& Design" "Cryst. Growth Des.") + ("CEC" "CrystEngComm" "CrystEngComm") + ("EA" "Electrochimica Acta" "Electrochim. Acta") + ("ECST" "ECS Transactions" "ECS Trans.") + ("EES" "Energy \\& Environmental Science" "Energy Environ. Sci.") + ("HPR" "High Pressure Research" "High Pressure Res.") + ("IC" "Inorganic Chemistry" "Inorg. Chem.") + ("IECR" "Industrial \\& Engineering Chemistry Research" + "Ind. Eng. Chem. Res.") + ("JJAP" "Japanese Journal of Applied Physics" "Jpn. J. Appl. Phys.") + ("JMatR" "Journal of Materials Research" "J. Mater. Res.") + ("JALC" "Journal of Alloys and Compounds" "J. Alloy Compd.") + ("JAC" "Journal of Applied Crystallography" "J. Appl. Crystallogr.") + ("JAE" "Journal of Applied Electrochemistry" "J. Appl. Electrochem.") + ("JAP" "Journal of Applied Physics" "J. Appl. Phys.") + ("JC" "Journal of Catalysis" "J. Catal.") + ("JCP" "Journal of Chemical Physics" "J. Chem. Phys.") + ("JCC" "Journal of Computational Chemistry" "J. Comput. Chem.") + ("JCG" "Journal of Crystal Growth" "J. Crys. Growth") + ("JMC" "Journal of Materials Chemistry" "J. Mater. Chem.") + ("JMC" "Journal of Materials Chemistry" "J. Mater. Chem.") + ("JMSL" "Journal of Materials Science Letters" "J. Mater. Sci. Lett.") + ("JMS" "Journal of Membrane Science" "J. Memb. Sci.") + ("JPE" "Journal of Phase Equilibria" "J. Phase Equilib.") + ("JPCS" "Journal of Physics and Chemistry of Solids" + "J. Phys. Chem. Solids") + ("JPCM" "Journal of Physics: Condensed Matter" + "J. Phys.: Condens. Matter") + ("JPS" "Journal of Power Sources" "J. Power Sources") + ("JSSC" "Journal of Solid State Chemistry" "J. Solid State Chem.") + ("JACerS" "Journal of the American Ceramic Society" "J. Am. Ceram. Soc.") + ("JACS" "Journal of the American Chemical Society" "J. Am. Chem. Soc.") + ("JASIST" "Journal of the American Society for Information Science and Technology" + "J. Am. Soc. Inf. Sci. Technol.") + ("JES" "Journal of The Electrochemical Society" "J. Electrochem. Soc.") + ("JEaC" "Journal of Electroanalytical Chemistry" "J. Electroanal. Chem.") + ("JMS" "Journal of Membrane Science" "J. Memb. Sci.") + ("JRS" "Journal of Raman Spectroscopy" "J. Raman Spectrosc.") + ("JVST" "Journal of Vacuum Science \\& Technology A" + "J. Vac. Sci. Technol. A") + ("ML" "Materials Letters" "Mater. Lett.") + ("MSE-BS" "Materials Science and Engineering B" "Mat. Sci. Eng. B-Solid") + ("MOLSIM" "Molecular Simulation" "Mol. Sim.") + ("Nature" "Nature" "Nature") + ("NM" "Nature Materials" "Nat. Mater.") + ("NC" "Nature Chemistry" "Nat. Chem.") + ("PML" "Philosophical Magazine Letters" "Phil. Mag. Lett.") + ("PMA" "Philosophical Magazine A" "Phil. Mag. A") + ("PA" "Physica A: Statistical Mechanics and its Applications" "Physica A") + ("PB" "Physica B-Condensed Matter" "Physica B") + ("PCCP" "Physical Chemistry Chemical Physics" "Phys. Chem. Chem. Phys.") + ("PSSB" "physica status solidi (b)" "Phys. Status Solidi B") + ("PRA" "Physical Review A" "Phys. Rev. A") + ("PRB" "Physical Review B" "Phys. Rev. B") + ("PRL" "Physical Review Letters" "Phys. Rev. Lett.") + ("PCM" "Physics and Chemistry of Minerals" "Phys. Chem. Miner.") + ("PNAS" "Proceedings of the National Academy of Sciences of the United States of America" + "Proc. Natl. Acad. Sci. U. S. A.") + ("PSurfSci" "Progress in Surface Science" "Prog. Surf. Sci.") + ("Science" "Science" "Science") + ("SM" "Scripta Materialia" "Scr. Mater.") + ("SABC" "Sensors and Actuators B: Chemical" "Sensor. Actuat. B-Chem.") + ("SS" "Surface Science" "Surf. Sci.") + ("EPJB" "The European Physical Journal B" "Eur. Phys. J. B") + ("JPC" "The Journal of Physical Chemistry" "J. Phys. Chem.") + ("JPCB" "The Journal of Physical Chemistry B" "J. Phys. Chem. B") + ("JPCC" "The Journal of Physical Chemistry C" "J. Phys. Chem. C") + ("JPCL" "The Journal of Physical Chemistry Letters" + "J. Phys. Chem. Lett.") + ("JCP" "The Journal of Chemical Physics" "J. Chem. Phys.") + ("MSMSE" "Modelling and Simulation in Materials Science and Engineering" + "Modell. Simul. Mater. Sci. Eng.") + ("TSF" "Thin Solid Films" "Thin Solid Films") + ("TC" "Topics in Catalysis" "Top. Catal.") + ("WR" "Water Research" "Water Res.")) + "List of (string journal-full-name journal-abbreviation). Find + new abbreviations at http://cassi.cas.org/search.jsp." + :type '(list (repeat (list string string))) + :group 'org-ref-bibtex) +(defcustom org-ref-title-case-types '(("article" . ("title")) + ("book" . ("booktitle"))) + + "An a-list of bibtex entry types and fields that will be converted to +title-case by org-ref-title-case." + :type '(repeat string) + :group 'org-ref-bibtex) + + +;; * Modifying journal titles ;;;###autoload (defun org-ref-bibtex-generate-longtitles () "Generate longtitles.bib which are @string definitions. @@ -334,27 +413,6 @@ START and END allow you to use this with `bibtex-map-entries'" (bibtex-fill-entry))))) -;;;###autoload -(defun org-ref-helm-set-journal-string () - "Helm interface to set a journal string in a bibtex entry. -Entries come from `org-ref-bibtex-journal-abbreviations'." - (interactive) - (bibtex-set-field - "journal" - (helm :sources - `((name . "journal") - (candidates . ,(mapcar - (lambda (x) - (cons (format "%s | %s" (nth 1 x) (nth 2 x)) - (car x))) - org-ref-bibtex-journal-abbreviations)) - (action . (lambda (x) (identity x)))) - :input (s-trim (bibtex-autokey-get-field "journal"))) - t) - (bibtex-fill-entry) - (bibtex-clean-entry)) - - ;;;###autoload (defun org-ref-set-journal-string (full-journal-name) "Set a bibtex journal name to the string that represents FULL-JOURNAL-NAME. @@ -376,94 +434,11 @@ This is defined in `org-ref-bibtex-journal-abbreviations'." (bibtex-clean-entry))) ;;* Non-ascii character replacement -;; see https://github.com/fxcoudert/tools/blob/master/doi2bib for more replacements -(defvar org-ref-nonascii-latex-replacements - '() - "Cons list of non-ascii characters and their LaTeX representations.") - - -(setq org-ref-nonascii-latex-replacements - '(("í" . "{\\\\'i}") - ("æ" . "{\\\\ae}") - ("ć" . "{\\\\'c}") - ("é" . "{\\\\'e}") - ("ä" . "{\\\\\"a}") - ("è" . "{\\\\`e}") - ("à" . "{\\\\`a}") - ("á" . "{\\\\'a}") - ("ø" . "{\\\\o}") - ("ë" . "{\\\\\"e}") - ("ü" . "{\\\\\"u}") - ("ñ" . "{\\\\~n}") - ("ņ" . "{\\\\c{n}}") - ("ñ" . "{\\\\~n}") - ("å" . "{\\\\aa}") - ("ö" . "{\\\\\"o}") - ("Á" . "{\\\\'A}") - ("í" . "{\\\\'i}") - ("ó" . "{\\\\'o}") - ("ó" . "{\\\\'o}") - ("ú" . "{\\\\'u}") - ("ú" . "{\\\\'u}") - ("ý" . "{\\\\'y}") - ("š" . "{\\\\v{s}}") - ("č" . "{\\\\v{c}}") - ("ř" . "{\\\\v{r}}") - ("š" . "{\\\\v{s}}") - ("İ" . "{\\\\.I}") - ("ğ" . "{\\\\u{g}}") - ("δ" . "$\\\\delta$") - ("ç" . "{\\\\c{c}}") - ("ß" . "{\\\\ss}") - ("≤" . "$\\\\le$") - ("≥" . "$\\\\ge$") - ("θ" . "$\\\\theta$") - ("μ" . "$\\\\mu$") - ("→" . "$\\\\rightarrow$") - ("⇌" . "$\\\\leftrightharpoons$") - ("×" . "$\\\\times$") - ("°" . "$\\\\deg$") - ("ş" . "{\\\\c{s}}") - ("γ" . "$\\\\gamma$") - ("ɣ" . "$\\\\gamma$") - ("º" . "degC") - ("η" . "$\\\\eta$") - ("µ" . "$\\\\mu$") - ("α" . "$\\\\alpha$") - ("β" . "$\\\\beta$") - ("ɛ" . "$\\\\epsilon$") - ("Ⅵ" . "\\textrm{VI}") - ("Ⅲ" . "\\textrm{III}") - ("Ⅴ" . "\\textrm{V}") - ("λ" . "$\\\\lambda$") - ("π" . "$\\\\pi$") - ("∞" . "$\\\\infty$") - ("χ" . "$\\\\chi$") - ("∼" . "\\\\textasciitilde{}") - ("‑" . "\\\\textemdash{}") - (" " . " ") - ("…" . "...") - ("•" . "\\\\textbullet ") - ;; I think these are non-ascii spaces. there seems to be more than one. - (" " . " ") - (" " . " ") - (" " . " ") - ("–" . "-") - ("−" . "-") - ("–" . "-") - ("—" . "-") - ("‒" . "\\\\textemdash{}") - ("‘" . "'") - ("’" . "'") - ("’" . "'") - ("“" . "\"") - ("’" . "'") - ("”" . "\""))) - ;;;###autoload (defun org-ref-replace-nonascii () - "Hook function to replace non-ascii characters in a bibtex entry." + "Replace non-ascii characters with LaTeX representations in a +bibtex entry." (interactive) (save-restriction (bibtex-narrow-to-entry) @@ -475,19 +450,13 @@ This is defined in `org-ref-bibtex-journal-abbreviations'." (replace-match (cdr (assoc char org-ref-nonascii-latex-replacements)))) (goto-char (point-min))))) + ;;* Title case transformations (defvar org-ref-lower-case-words '("a" "an" "on" "and" "for" "the" "of" "in") "List of words to keep lowercase when changing case in a title.") -(defcustom org-ref-title-case-types '(("article" . ("title")) - ("book" . ("booktitle"))) - - "An a-list of bibtex entry types and fields that will be converted to -title-case by org-ref-title-case." - :type '(repeat string) - :group 'org-ref-bibtex) ;;;###autoload (defun org-ref-title-case (&optional key start end) @@ -502,7 +471,9 @@ books." (bibtex-narrow-to-entry) (bibtex-beginning-of-entry) (let* ((entry-type (downcase (cdr (assoc "=type=" (bibtex-parse-entry))))) - (fields (cdr (assoc entry-type org-ref-title-case-types)))) + (fields (cdr (assoc entry-type org-ref-title-case-types))) + ;; temporary variables + title words) (when fields (cl-loop for field in fields when (bibtex-autokey-get-field field) @@ -556,6 +527,7 @@ books." title) (bibtex-fill-entry)))))) + ;;;###autoload (defun org-ref-title-case-article (&optional key start end) "Convert a bibtex entry article or book title to title-case. @@ -609,13 +581,13 @@ all the title entries in articles." (setq start (match-end 1)))) ;; this is defined in doi-utils - (bibtex-set-field - "title" title) + (bibtex-set-field "title" title) ;; clean and refill entry so it looks nice (bibtex-clean-entry) (bibtex-fill-entry)))) + ;;* Navigation in bibtex file ;;;###autoload (defun org-ref-bibtex-next-entry (&optional n) @@ -648,6 +620,36 @@ N is a prefix argument. If it is numeric, jump that many entries back." (bibtex-beginning-of-entry))) +;;;###autoload +(defun org-ref-bibtex-visible-entry () + "Jump to visible entry." + (interactive) + (avy-with avy-ve + (avy-process + (save-excursion + (goto-char (window-start)) + (let ((positions ())) + (while (re-search-forward "^@.*{" (window-end) t) + (push (match-beginning 0) positions)) + (reverse positions)))) + (avy--style-fn avy-style))) + + +;;;###autoload +(defun org-ref-bibtex-visible-field () + "Jump to visible field." + (interactive) + (avy-with avy-vf + (avy-process + (save-excursion + (goto-char (window-start)) + (let ((positions ())) + (while (re-search-forward ".*=\\s-*." (window-end) t) + (push (match-end 0) positions)) + (reverse positions)))) + (avy--style-fn avy-style))) + + (defun org-ref-bibtex-mode-keys () "Modify keymaps used by `bibtex-mode'." (local-set-key (kbd "M-n") 'org-ref-bibtex-next-entry) @@ -657,10 +659,9 @@ N is a prefix argument. If it is numeric, jump that many entries back." (add-hook 'bibtex-mode-hook 'org-ref-bibtex-mode-keys) ;;* Functions to act on an entry with a doi -;;;###autoload + (defun org-ref-bibtex-entry-doi () "Get doi from entry at point." - (interactive) (save-excursion (bibtex-beginning-of-entry) (when (not (looking-at bibtex-any-valid-entry-type)) @@ -668,7 +669,7 @@ N is a prefix argument. If it is numeric, jump that many entries back." (let ((entry (bibtex-parse-entry t))) (when (null entry) (error "Unable to parse this bibtex entry.")) - (reftex-get-bib-field "doi" entry)))) + (cdr (assoc "doi" entry))))) ;; function that ensures that the url field of a bibtex entry is the ;; properly-formatted hyperlink of the DOI. See @@ -678,11 +679,13 @@ N is a prefix argument. If it is numeric, jump that many entries back." (defun org-ref-bibtex-format-url-if-doi () "Hook function to format url to follow the current DOI conventions." (interactive) - (if (eq (org-ref-bibtex-entry-doi) "") nil - (let ((front-url "https://doi.org/") - (doi (org-ref-bibtex-entry-doi))) - (bibtex-set-field "url" - (concat front-url doi))))) + ;; Don't overwrite an existing url field though. + (unless (bibtex-autokey-get-field "url") + (if (eq (org-ref-bibtex-entry-doi) "") nil + (let ((front-url "https://doi.org/") + (doi (org-ref-bibtex-entry-doi))) + (bibtex-set-field "url" + (concat front-url doi)))))) ;;;###autoload @@ -724,7 +727,7 @@ there is a DOI." (if (string= "" doi) (save-excursion (bibtex-beginning-of-entry) - (reftex-get-bib-field "title" (bibtex-parse-entry t))) + (cdr (assoc "title" (bibtex-parse-entry t)))) doi)))) @@ -743,6 +746,7 @@ calls functions with a DOI argument." (interactive) (org-ref-open-bibtex-pdf)) + (defun org-ref-bibtex-get-file-move-func (prefix) "Determine whether to use `rename-file' or `copy-file' for `org-ref-bibtex-assoc-pdf-with-entry'. When called with a PREFIX argument, @@ -756,14 +760,19 @@ opposite function from that which is defined in 'copy-file 'rename-file))) + +(defvar bibtex-completion-library-path) +(declare-function bibtex-completion-find-pdf-in-library "bibtex-completion") + + ;;;###autoload (defun org-ref-bibtex-assoc-pdf-with-entry (&optional prefix) "Prompt for pdf associated with entry at point and rename it. -Check whether a pdf already exists in `org-ref-pdf-directory' with the +Check whether a pdf already exists in `bibtex-completion-library' with the name '[bibtexkey].pdf'. If the file does not exist, rename it to '[bibtexkey].pdf' using `org-ref-bibtex-assoc-pdf-with-entry-move-function' and place it in -`org-ref-pdf-directory'. Optional PREFIX argument toggles between +a directory. Optional PREFIX argument toggles between `rename-file' and `copy-file'." (interactive "P") (save-excursion @@ -771,114 +780,140 @@ name '[bibtexkey].pdf'. If the file does not exist, rename it to (let* ((file (read-file-name "Select file associated with entry: ")) (bibtex-expand-strings t) (entry (bibtex-parse-entry t)) - (key (reftex-get-bib-field "=key=" entry)) - (pdf (concat org-ref-pdf-directory (concat key ".pdf"))) - (file-move-func (org-ref-bibtex-get-file-move-func prefix))) - (if (file-exists-p pdf) - (message (format "A file named %s already exists" pdf)) - (progn - (funcall file-move-func file pdf) - (message (format "Created file %s" pdf))))))) + (key (cdr (assoc "=key=" entry))) + (file-move-func (org-ref-bibtex-get-file-move-func prefix)) + pdf) + (if (bibtex-completion-find-pdf-in-library key) + (message (format "A file named %s already exists" (bibtex-completion-find-pdf-in-library key))) + (setq pdf (expand-file-name (concat key ".pdf") (cond + ((stringp bibtex-completion-library-path) + bibtex-completion-library-path) + ((and (listp bibtex-completion-library-path) + (= 1 (length bibtex-completion-library-path))) + (car bibtex-completion-library-path)) + (t + (completing-read "Dir: " bibtex-completion-library-path))))) + (funcall file-move-func file pdf) + (message (format "Created file %s" pdf)))))) ;;* Hydra menus ;;** Hydra menu for bibtex entries ;; hydra menu for actions on bibtex entries -(defhydra org-ref-bibtex-hydra (:color blue) - " -_p_: Open pdf _y_: Copy key _N_: New entry _w_: WOS -_b_: Open url _f_: Copy formatted entry _o_: Copy entry _c_: WOS citing -_r_: Refile entry _k_: Add keywords _d_: delete entry _a_: WOS related -_e_: Email entry _K_: Edit keywords _L_: clean entry _P_: Pubmed -_U_: Update entry _N_: New entry _R_: Crossref _g_: Google Scholar -_s_: Sort entry _a_: Remove nonascii _h_: helm-bibtex _q_: quit -_u_: Update field _F_: file funcs _A_: Assoc pdf with entry -_n_: Open notes _T_: Title case - _S_: Sentence case +(defhydra org-ref-bibtex-hydra (:color blue :hint nil) + "Bibtex actions: " - ("p" org-ref-open-bibtex-pdf) - ("P" org-ref-bibtex-pubmed) - ("w" org-ref-bibtex-wos) - ("c" org-ref-bibtex-wos-citing) - ("a" org-ref-bibtex-wos-related) - ("R" org-ref-bibtex-crossref) - ("g" org-ref-bibtex-google-scholar) - ("N" org-ref-bibtex-new-entry/body) - ("n" org-ref-open-bibtex-notes) - ("o" (lambda () - (interactive) - (bibtex-copy-entry-as-kill) - (message "Use %s to paste the entry" - (substitute-command-keys (format "\\[bibtex-yank]"))))) - ("d" bibtex-kill-entry) - ("L" org-ref-clean-bibtex-entry) - ("y" (save-excursion - (bibtex-beginning-of-entry) - (when (looking-at bibtex-entry-maybe-empty-head) - (kill-new (bibtex-key-in-head))))) - ("f" (progn - (bibtex-beginning-of-entry) - (kill-new - (org-ref-format-entry - (cdr (assoc "=key=" (bibtex-parse-entry t))))))) - ("k" helm-tag-bibtex-entry) + ;; Open-like actions + ("p" org-ref-open-bibtex-pdf "PDF" :column "Open") + ("n" org-ref-open-bibtex-notes "Notes" :column "Open") + ("b" org-ref-open-in-browser "URL" :column "Open") + + ;; edit/modify ("K" (lambda () (interactive) (org-ref-set-bibtex-keywords (read-string "Keywords: " (bibtex-autokey-get-field "keywords")) - t))) - ("b" org-ref-open-in-browser) + t)) + "Keywords" :column "Edit") + ("a" org-ref-replace-nonascii "Replace nonascii" :column "Edit") + ("s" org-ref-sort-bibtex-entry "Sort fields" :column "Edit") + ("T" org-ref-title-case-article "Title case" :column "Edit") + ("S" org-ref-sentence-case-article "Sentence case" :column "Edit") + ("U" (doi-utils-update-bibtex-entry-from-doi (org-ref-bibtex-entry-doi)) "Update entry" :column "Edit") + ("u" doi-utils-update-field "Update field" :column "Edit" :color red) + ("" (cl--set-buffer-substring (line-beginning-position) (+ 1 (line-end-position)) "") + "Delete line" :column "Edit" :color red) + ("d" bibtex-kill-entry "Kill entry" :column "Edit") + ("L" org-ref-clean-bibtex-entry "Clean entry" :column "Edit") + ("A" org-ref-bibtex-assoc-pdf-with-entry "Add pdf" :column "Edit") ("r" (lambda () (interactive) (bibtex-beginning-of-entry) (bibtex-kill-entry) (find-file (completing-read "Bibtex file: " - (f-entries "." (lambda (f) (f-ext? f "bib"))))) + (append bibtex-completion-bibliography + (f-entries "." (lambda (f) (f-ext? f "bib")))))) (goto-char (point-max)) (bibtex-yank) (save-buffer) - (kill-buffer))) - ("e" org-ref-email-bibtex-entry) - ("U" (doi-utils-update-bibtex-entry-from-doi (org-ref-bibtex-entry-doi))) - ("u" doi-utils-update-field) - ("F" org-ref-bibtex-file/body) - ("h" helm-bibtex) - ("A" org-ref-bibtex-assoc-pdf-with-entry) - ("a" org-ref-replace-nonascii) - ("s" org-ref-sort-bibtex-entry) - ("T" org-ref-title-case-article) - ("S" org-ref-sentence-case-article) + (kill-buffer)) + "Refile entry" :column "Edit") + + ;; www + ("P" org-ref-bibtex-pubmed "Pubmed" :column "WWW") + ("w" org-ref-bibtex-wos "WOS" :column "WWW") + ("c" org-ref-bibtex-wos-citing "WOS citing" :column "WWW") + ("a" org-ref-bibtex-wos-related "WOS related" :column "WWW") + ("R" org-ref-bibtex-crossref "Crossref" :column "WWW") + ("g" org-ref-bibtex-google-scholar "Google Scholar" :column "WWW") + ("e" org-ref-email-bibtex-entry "Email" :column "WWW") + + + ;; Copy + ("o" (lambda () + (interactive) + (bibtex-copy-entry-as-kill) + (message "Use %s to paste the entry" + (substitute-command-keys (format "\\[bibtex-yank]")))) + "Copy entry" :column "Copy") + + ("y" (save-excursion + (bibtex-beginning-of-entry) + (when (looking-at bibtex-entry-maybe-empty-head) + (kill-new (bibtex-key-in-head)))) + "Copy key" :column "Copy") + + ("f" (save-excursion + (bibtex-beginning-of-entry) + (kill-new (bibtex-completion-apa-format-reference + (cdr (assoc "=key=" (bibtex-parse-entry t)))))) + "Formatted entry" :column "Copy") + + ;; Navigation + ("[" org-ref-bibtex-next-entry "Next entry" :column "Navigation" :color red) + ("]" org-ref-bibtex-previous-entry "Previous entry" :column "Navigation" :color red) + ("" next-line "Next line" :column "Navigation" :color red) + ("" previous-line "Previous line" :column "Navigation" :color red) + ("" scroll-up-command "Scroll up" :column "Navigation" :color red) + ("" scroll-down-command "Scroll down" :column "Navigation" :color red) + ("v" org-ref-bibtex-visible-entry "Visible entry" :column "Navigation" :color red) + ("V" org-ref-bibtex-visible-field "Visible field" :column "Navigation" :color red) + + + ;; Miscellaneous + ("F" org-ref-bibtex-file/body "File hydra" :column "Misc") + ("N" org-ref-bibtex-new-entry/body "New entry" :column "Misc") ("q" nil)) -;; create key-chord and key binding for hydra -(when (and (featurep 'key-chord) org-ref-bibtex-hydra-key-chord) - (key-chord-define-global - org-ref-bibtex-hydra-key-chord - 'org-ref-bibtex-hydra/body)) - -(when org-ref-bibtex-hydra-key-binding - (define-key bibtex-mode-map org-ref-bibtex-hydra-key-binding 'org-ref-bibtex-hydra/body)) +(declare-function biblio-lookup "biblio") +(declare-function arxiv-add-bibtex-entry "org-ref-arxiv") +(declare-function doi-insert-bibtex "doi-utils") ;;** Hydra menu for new bibtex entries ;; A hydra for adding new bibtex entries. (defhydra org-ref-bibtex-new-entry (:color blue) "New Bibtex entry:" - ("a" bibtex-Article "Article") - ("b" bibtex-Book "Book") - ("i" bibtex-InBook "In book") - ("l" bibtex-Booklet "Booklet") - ("P" bibtex-Proceedings "Proceedings") - ("p" bibtex-InProceedings "In proceedings") - ("m" bibtex-Misc "Misc.") - ("M" bibtex-Manual "Manual") - ("T" bibtex-PhdThesis "PhD Thesis") - ("t" bibtex-MastersThesis "MS Thesis") - ("R" bibtex-TechReport "Report") - ("u" bibtex-Unpublished "unpublished") - ("c" bibtex-InCollection "Article in collection") + ("d" doi-insert-bibtex "from DOI" :column "Automatic") + ("c" crossref-add-bibtex-entry "from Crossref" :column "Automatic") + ("a" arxiv-add-bibtex-entry "From Arxiv" :column "Automatic") + ("b" biblio-lookup "From biblio" :column "Automatic") + ;; Bibtex types + ("ma" bibtex-Article "Article" :column "Manual") + ("mb" bibtex-Book "Book" :column "Manual") + ("mi" bibtex-InBook "In book" :column "Manual") + ("ml" bibtex-Booklet "Booklet" :column "Manual") + ("mP" bibtex-Proceedings "Proceedings" :column "Manual") + ("mp" bibtex-InProceedings "In proceedings" :column "Manual") + ("mm" bibtex-Misc "Misc." :column "Manual") + ("mM" bibtex-Manual "Manual" :column "Manual") + ("mT" bibtex-PhdThesis "PhD Thesis" :column "Manual") + ("mt" bibtex-MastersThesis "MS Thesis" :column "Manual") + ("mR" bibtex-TechReport "Report" :column "Manual") + ("mu" bibtex-Unpublished "unpublished" :column "Manual") + ("mc" bibtex-InCollection "Article in collection" :column "Manual") ("q" nil "quit")) @@ -892,74 +927,28 @@ _n_: Open notes _T_: Title case ("p" org-ref-build-full-bibliography "PDF bibliography")) -;;* DEPRECATED bibtex menu -(defvar org-ref-bibtex-menu-funcs '() - "Functions to run in doi menu. -Each entry is a list of (key menu-name function). The function -must take one argument, the doi. This is somewhat deprecated, as -I prefer the hydra interfaces above.") - -(setq org-ref-bibtex-menu-funcs - '(("p" "df" org-ref-bibtex-pdf) - ("C" "opy" (lambda (doi) - (kill-new (org-ref-bib-citation)) - (bury-buffer))) - ("w" "os" doi-utils-wos) - ("c" "iting articles" doi-utils-wos-citing) - ("r" "elated articles" doi-utils-wos-related) - ("s" "Google Scholar" doi-utils-google-scholar) - ("P" "Pubmed" doi-utils-pubmed) - ("f" "CrossRef" doi-utils-crossref))) - -;;;###autoload -(defun org-ref-bibtex () - "Menu command to run in a bibtex entry. -Functions from `org-ref-bibtex-menu-funcs'. They all rely on the -entry having a doi." - (interactive) - ;; construct menu string as a message - (message - (concat - (mapconcat - (lambda (tup) - (concat "[" (elt tup 0) "]" - (elt tup 1) " ")) - org-ref-bibtex-menu-funcs "") ": ")) - (let* ((input (read-char-exclusive)) - (choice (assoc - (char-to-string input) org-ref-bibtex-menu-funcs))) - (when choice - (funcall - (elt - choice - 2) - (org-ref-bibtex-entry-doi))))) - -(defalias 'jb 'org-ref-bibtex) - +;;* Email a bibtex entry +(declare-function bibtex-completion-find-pdf "bibtex-completion") ;;;###autoload (defun org-ref-email-bibtex-entry () "Email current bibtex entry at point and pdf if it exists." (interactive) + (bibtex-beginning-of-entry) + (let* ((key (cdr (assoc "=key=" (bibtex-parse-entry t)))) + (pdfs (bibtex-completion-find-pdf key))) - (save-excursion - (bibtex-beginning-of-entry) - (let* ((key (reftex-get-bib-field "=key=" (bibtex-parse-entry t))) - pdf) - ;; when we have org-ref defined we may have pdf to find. - (when (boundp 'org-ref-pdf-directory) - (setq pdf (funcall org-ref-get-pdf-filename-function key))) - (bibtex-copy-entry-as-kill) - (compose-mail) - (message-goto-body) - (insert (pop bibtex-entry-kill-ring)) - (message-goto-subject) - (insert key) - (message "%s exists %s" pdf (file-exists-p pdf)) - (when (file-exists-p pdf) - (mml-attach-file pdf)) - (message-goto-to)))) + (bibtex-copy-entry-as-kill) + (compose-mail) + (message-goto-body) + (insert (pop bibtex-entry-kill-ring)) + (message-goto-subject) + (insert key) + (cl-loop for pdf in pdfs do (mml-attach-file pdf)) + (message-goto-to) + ;; I am not sure why I have to put an empty string here, but it prevents a + ;; bell error. + "")) ;;* org-ref bibtex keywords ;; adapted from bibtex-utils.el @@ -1020,319 +1009,8 @@ keywords. Optional argument ARG prefix arg to replace keywords." (save-buffer))))) -;;* org-ref bibtex cache -(defvar orhc-bibtex-cache-data - '((hashes . ()) - (candidates . ())) - "Cache data as an alist. -'hashes is a list of cons cells (bibfile . hash) -'candidates is a list of cons cells (bibfile . candidates). -Stored persistently in `orhc-bibtex-cache-file'.") - - -(defvar orhc-bibtex-cache-file - "~/.orhc-bibtex-cache" - "File to store cached data in.") - - -(defvar org-ref-bibtex-files nil - "List of bibtex files to get entries from. -This is set internally.") - - -(defvar orhc-candidate-formats - '(("article" . "${pdf}${notes}|${=key=}| ${author}, ${title}, ${journal} (${year}). ${keywords}") - ("book" . " |${=key=}| ${author}, ${title} (${year}) ${keywords}.") - ("inbook" . " |${=key=}| ${author}, ${chapter} in ${title} (${year}) ${keywords}") - ("techreport" . " |${=key=}| ${title}, ${institution} (${year}). ${keywords}") - ("inproceedings" . " |${=key=}| ${author}, ${title} in ${booktitle} (${year}). ${keywords}") - ("incollection" . " |${=key=}| ${author}, ${title} in ${booktitle} (${year}). ${keywords}") - ("phdthesis" . " |${=key=}| ${author}, ${title}, ${school} (${year}). Phd thesis. ${keywords}") - ("mastersthesis" . " |${=key=}| ${author}, ${title}, ${school} (${year}). MS thesis. ${keywords}") - ("misc" . " |${=key=}| ${author}, ${title}") - ("unpublished" . " |${=key=}| ${author}, ${title}")) - "Formats for candidates. -It is an alist of (=type= . s-format-string).") - - -;; when you load, we should check the hashes and files -(defun orhc-load-cache-file () - "Load the cache file to set `orhc-bibtex-cache-data'." - (when (file-exists-p orhc-bibtex-cache-file) - (with-current-buffer (find-file-noselect orhc-bibtex-cache-file) - (goto-char (point-min)) - (setq orhc-bibtex-cache-data (read (current-buffer)))) - (when (find-buffer-visiting orhc-bibtex-cache-file) - (kill-buffer (find-buffer-visiting orhc-bibtex-cache-file))))) - - -(defun orhc-clear-cache () - "Clear the cache and delete `orhc-bibtex-cache-file'." - (interactive) - (setq orhc-bibtex-cache-data '((hashes . nil) - (candidates . nil))) - (when (find-buffer-visiting orhc-bibtex-cache-file) - (kill-buffer (find-buffer-visiting orhc-bibtex-cache-file))) - (when (file-exists-p orhc-bibtex-cache-file) - (delete-file orhc-bibtex-cache-file)) - (message "org-ref-helm-cite cache cleared.")) - - -(defun orhc-bibtex-cache-up-to-date () - "Return if bibtex caches are up to date. -This means the hash of each bibfile is equal to the one for it in -the cache." - (-all? 'identity - (cl-loop - for bibfile in org-ref-bibtex-files - collect - (string= (with-temp-buffer - (insert-file-contents bibfile) - (secure-hash 'sha256 (current-buffer))) - (or (cdr (assoc - bibfile - (cdr (assoc 'hashes orhc-bibtex-cache-data)))) ""))))) - -(defun orhc-bibtex-field-formatter (field entry) - "Format FIELD in a bibtex parsed ENTRY. -A few fields are treated specially, e.g. authors are replaced by -comma-separated list, and I put :: around keywords to make it -easier to search specifically for them." - (let ((s (replace-regexp-in-string - "^{\\|}$" "" - (replace-regexp-in-string - "[\n\t\s]+" " " - (or (cdr (assoc field entry)) - (and (string= field "author") - (cdr (assoc "editor" entry))) - ""))))) - (cond - ((string= field "author") - (if org-ref-helm-cite-shorten-authors - ;; copied from `helm-bibtex-shorten-authors' - (cl-loop for a in (s-split " and " s) - for p = (s-split "," a t) - for sep = "" then ", " - concat sep - if (eq 1 (length p)) - concat (-last-item (s-split " +" (car p) t)) - else - concat (car p)) - (mapconcat 'identity (s-split " and " s) ", "))) - ((string= field "keywords") - (if (> (length s) 0) - (mapconcat (lambda (keyword) - (concat ":" (s-trim keyword) ":")) - (s-split "," s) - " ") - "")) - ((string= field "pdf") - (if (file-exists-p (expand-file-name - (concat (cdr (assoc "=key=" entry)) ".pdf") - org-ref-pdf-directory)) - "⌘" - " ")) - ((string= field "notes") - (if (file-exists-p (expand-file-name - (concat (cdr (assoc "=key=" entry)) ".org") - org-ref-notes-directory)) - "✎" - " ")) - ;; catch all the other fields and just return them. - (t - s)))) - -(defun orhc-update-bibfile-cache (bibfile) - "Update cache for BIBFILE. -This generates the candidates for the file. Some of this code is -adapted from `helm-bibtex-parse-bibliography'. This function runs -when called, it resets the cache for the BIBFILE." - ;; check if the bibfile is already open, and preserve this state. i.e. if it - ;; is not open close it, and if it is leave it open. - (let ((bibfile-open (find-buffer-visiting bibfile))) - (with-current-buffer (find-file-noselect bibfile) - (bibtex-beginning-of-first-entry) - (message "Updating cache for %s" bibfile) - (let ((hash (secure-hash 'sha256 (current-buffer))) - (entries - (cl-loop - for entry-type = (parsebib-find-next-item) - while entry-type - unless (member-ignore-case entry-type - '("preamble" "string" "comment")) - collect - (let* ((entry (cl-loop for cons-cell in (parsebib-read-entry entry-type) - ;; we remove all properties too. they - ;; cause errors in reading/writing. - collect - (cons (substring-no-properties - (downcase (car cons-cell))) - (substring-no-properties - ;; clumsy way to remove surrounding - ;; brackets - (let ((s (cdr cons-cell))) - (if (or (and (s-starts-with? "{" s) - (s-ends-with? "}" s)) - (and (s-starts-with? "\"" s) - (s-ends-with? "\"" s))) - (substring s 1 -1) - s)))))) - ;; (key (cdr (assoc "=key=" entry))) - ) - (cons - ;; this is the display string for helm. We try to use the formats - ;; in `orhc-candidate-formats', but if there isn't one we just put - ;; all the fields in. - (s-format - (or (cdr (assoc (downcase entry-type) orhc-candidate-formats)) - (format "%s: %s" (cdr (assoc "=key=" entry)) entry)) - 'orhc-bibtex-field-formatter - entry) - ;; this is the candidate that is returned, the entry a-list + - ;; file and position. - (append entry (list (cons "bibfile" (buffer-file-name)) - (cons "position" (point))))))))) - - ;; Now update the cache variables for hash and entries - (if (assoc bibfile (cdr (assoc 'candidates orhc-bibtex-cache-data))) - (setf (cdr (assoc bibfile - (cdr (assoc 'candidates orhc-bibtex-cache-data)))) - entries) - (cl-pushnew (cons bibfile entries) - (cdr (assoc 'candidates orhc-bibtex-cache-data)))) - (if (assoc bibfile (cdr (assoc 'hashes orhc-bibtex-cache-data))) - (setf (cdr (assoc - bibfile - (cdr (assoc 'hashes orhc-bibtex-cache-data)))) - hash) - (cl-pushnew (cons bibfile hash) - (cdr (assoc 'hashes orhc-bibtex-cache-data)))) - - ;; And save it to disk for persistent use - (with-temp-file orhc-bibtex-cache-file - (print orhc-bibtex-cache-data (current-buffer))))) - (unless bibfile-open (kill-buffer (find-buffer-visiting bibfile))))) - -(defun orhc-update-bibtex-cache () - "Conditionally update cache for all files in `org-ref-bibtex-files'. -Files that have the same hash as in the cache are not updated." - (cl-loop for bibfile in org-ref-bibtex-files - unless (string= (with-temp-buffer - (insert-file-contents bibfile) - (secure-hash 'sha256 (current-buffer))) - (or (cdr - (assoc bibfile - (cdr - (assoc 'hashes orhc-bibtex-cache-data)))) - "")) - do - (orhc-update-bibfile-cache bibfile))) - - -(defun orhc-helm-cite-describe-cache () - "Show what is in the cache." - (interactive) - (let ((hash-cache (cdr (assoc 'hashes orhc-bibtex-cache-data))) - (candidates-cache (cdr (assoc 'candidates orhc-bibtex-cache-data)))) - (message "%s\n\n%s" - (mapconcat (lambda (h) - (format "%s - %s" (car h) (cdr h))) - hash-cache "\n") - (mapconcat (lambda (c) - (format "%s - %s entries" (car c) (length (cdr c)))) - candidates-cache "\n")))) - - -(defun orhc-bibtex-candidates () - "Return the candidates from cache for files listed in `org-ref-bibtex-files'. -Update the cache if necessary." - ;; this only does something when the cache is out of date - (org-ref-save-all-bibtex-buffers) - (orhc-update-bibtex-cache) - (let ((candidates (cdr (assoc 'candidates orhc-bibtex-cache-data)))) - (apply 'append - (cl-loop for bibfile in org-ref-bibtex-files - collect (cdr (assoc bibfile candidates)))))) - - -;; Now load files and update them if needed. We do this when you load the -;; library so they are available later. -(orhc-load-cache-file) -(orhc-update-bibtex-cache) - - -;;* org-ref bibtex formatted citation - -(defun org-ref-format-bibtex-entry (entry) - "Return a formatted citation for the bibtex entry at point. -Formats are from `org-ref-formatted-citation-formats'. The -variable `org-ref-formatted-citation-backend' determines the set -of format strings used." - (save-excursion - (bibtex-beginning-of-entry) - (let* ((formats (cdr (assoc org-ref-formatted-citation-backend org-ref-formatted-citation-formats))) - (format-string) - (ref)) - (if (null entry) - "!!! No entry found !!!" - (setq format-string (cdr (or (assoc (downcase (bibtex-completion-get-value "=type=" entry)) formats) - (assoc nil formats)))) - (setq ref (s-format format-string 'bibtex-completion-apa-get-value entry)) - (replace-regexp-in-string "\\([.?!]\\)\\." "\\1" ref))))) - - -(defun org-ref-format-entry (key) - "Returns a formatted bibtex entry for KEY." - (let* ((bibtex-completion-bibliography (org-ref-find-bibliography))) - (if (string= "*" key) - "*" - (org-ref-format-bibtex-entry (ignore-errors (bibtex-completion-get-entry key)))))) - - -(defun org-ref-format-bibtex-entry-at-point () - "Return a formatted citation for the bibtex entry at point." - (save-excursion - (bibtex-beginning-of-entry) - (org-ref-format-bibtex-entry (bibtex-parse-entry t)))) - - -;; ** using citeproc -(defun orhc-formatted-citation (entry) - "Get a formatted string for ENTRY." - (require 'unsrt) - (let* ((adaptive-fill-function '(lambda () " ")) - (indent-tabs-mode nil) - (entry-type (downcase - (cdr (assoc "=type=" entry)))) - (entry-styles (cdr (assoc 'entries bibliography-style))) - (entry-fields - (progn - (if (cdr (assoc (intern entry-type) entry-styles)) - (cdr (assoc (intern entry-type) entry-styles)) - (warn "%s not found. Using default." entry-type) - (cdr (assoc 't entry-styles))))) - (funcs (mapcar - (lambda (field) - (if (fboundp (intern - (format "orcp-%s" field))) - (intern - (format "orcp-%s" field)) - ;; No formatter found. just get the data - `(lambda (entry) - (orcp-get-entry-field - ,(symbol-name field) entry)))) - entry-fields))) - - ;; this is the entry. We do this in a buffer to make it - ;; easy to indent, fill, etc... - (with-temp-buffer - (insert (mapconcat (lambda (field-func) - (funcall field-func entry)) - funcs - "")) - (buffer-string)))) - ;; * Extract bibtex blocks from an org-file + ;;;###autoload (defun org-ref-extract-bibtex-blocks (bibfile) "Extract all bibtex blocks in buffer to BIBFILE. @@ -1363,16 +1041,394 @@ will clobber the file." (with-temp-file bibfile (insert contents)))) -(defun org-ref-bibtex-key-from-doi (doi &optional bib) - "Return a bibtex entry's key from a DOI. -BIB is an optional filename to get the entry from. Defaults to -the first entry of `org-ref-default-bibliography'." - (let ((bibfile (if bib bib (car org-ref-default-bibliography)))) - (with-temp-buffer - (insert-file-contents (expand-file-name bibfile)) - (search-forward doi) + +;;** create text citations from a bibtex entry +(declare-function bibtex-completion-apa-format-reference "bibtex-completion") +(declare-function bibtex-completion-get-key-bibtex "bibtex-completion") + +(defun org-ref-bib-citation () + "From a bibtex entry, create and return a lightly formatted citation string." + (bibtex-completion-apa-format-reference (list (bibtex-completion-get-key-bibtex)))) + + +;;** Open pdf in bibtex entry +(declare-function bibtex-completion-open-pdf "bibtex-completion") +;;;###autoload +(defun org-ref-open-bibtex-pdf () + "Open pdf for a bibtex entry, if it exists." + (interactive) + (bibtex-completion-open-pdf (list (bibtex-completion-get-key-bibtex)))) + + +;;** Open notes from bibtex entry +(declare-function bibtex-completion-edit-notes "bibtex-completion") + +;;;###autoload +(defun org-ref-open-bibtex-notes () + "From a bibtex entry, open the notes if they exist." + (interactive) + (bibtex-completion-edit-notes (list (bibtex-completion-get-key-bibtex)))) + + +;;** Open bibtex entry in browser +(declare-function bibtex-completion-open-url-or-doi "bibtex-completion") + +;;;###autoload +(defun org-ref-open-in-browser () + "Open the bibtex entry at point in a browser using the url field or doi field." + (interactive) + (bibtex-completion-open-url-or-doi (list (bibtex-completion-get-key-bibtex)))) + + +;;** Build a pdf of the bibtex file +;;;###autoload +(defun org-ref-build-full-bibliography () + "Build pdf of all bibtex entries, and open it." + (interactive) + (let* ((bibfile (file-name-nondirectory (buffer-file-name))) + (bib-base (file-name-sans-extension bibfile)) + (texfile (concat bib-base ".tex")) + (pdffile (concat bib-base ".pdf"))) + (find-file texfile) + (erase-buffer) + (insert (format "\\documentclass[12pt]{article} +\\usepackage[version=3]{mhchem} +\\usepackage{url} +\\usepackage[numbers]{natbib} +\\usepackage[colorlinks=true, linkcolor=blue, urlcolor=blue, pdfstartview=FitH]{hyperref} +\\usepackage{doi} +\\begin{document} +\\nocite{*} +\\bibliographystyle{unsrtnat} +\\bibliography{%s} +\\end{document}" bib-base)) + (save-buffer) + (shell-command (concat "pdflatex " bib-base)) + (shell-command (concat "bibtex " bib-base)) + (shell-command (concat "pdflatex " bib-base)) + (shell-command (concat "pdflatex " bib-base)) + (kill-buffer texfile) + (org-open-file pdffile))) + + +;;** Sort fields in a bibtex entry +;;;###autoload +(defun org-ref-sort-bibtex-entry () + "Sort fields of entry in standard order." + (interactive) + (bibtex-beginning-of-entry) + (let* ((entry (bibtex-parse-entry)) + (entry-fields) + (other-fields) + (type (cdr (assoc "=type=" entry))) + (key (cdr (assoc "=key=" entry))) + (field-order (cdr (assoc (if type (downcase type)) + org-ref-bibtex-sort-order)))) + + ;; these are the fields we want to order that are in this entry + (setq entry-fields (mapcar (lambda (x) (car x)) entry)) + ;; we do not want to reenter these fields + (setq entry-fields (remove "=key=" entry-fields)) + (setq entry-fields (remove "=type=" entry-fields)) + + ;;these are the other fields in the entry, and we sort them alphabetically. + (setq other-fields + (sort (-remove (lambda(x) (member x field-order)) entry-fields) + 'string<)) + + (save-restriction + (bibtex-kill-entry) + (insert + (concat "@" type "{" key ",\n" + (mapconcat + (lambda (field) + (when (member field entry-fields) + (format "%s = %s," + field + (cdr (assoc field entry))))) + field-order "\n") + ;; now add the other fields + (mapconcat + (lambda (field) + (cl-loop for (f . v) in entry concat + (when (string= f field) + (format "%s = %s,\n" f v)))) + (-uniq other-fields) "\n") + "\n}")) + (bibtex-find-entry key) + (bibtex-fill-entry) + (bibtex-clean-entry)))) + +;; downcase entries +;;;###autoload +(defun org-ref-downcase-bibtex-entry () + "Downcase the entry type and fields." + (interactive) + (bibtex-beginning-of-entry) + (let* ((entry (bibtex-parse-entry)) + (entry-fields) + (type (downcase (cdr (assoc "=type=" entry)))) + (key (cdr (assoc "=key=" entry)))) + + (setq entry-fields (mapcar (lambda (x) (car x)) entry)) + ;; we do not want to reenter these fields + (setq entry-fields (remove "=key=" entry-fields)) + (setq entry-fields (remove "=type=" entry-fields)) + + (bibtex-kill-entry) + (insert + (concat "@" (downcase type) "{" key ",\n" + (mapconcat + (lambda (field) + (format "%s = %s," + (downcase field) + (cdr (assoc field entry)))) + entry-fields "\n") + "\n}\n\n")) + (bibtex-find-entry key) + (bibtex-fill-entry) + (bibtex-clean-entry))) + + +;;** Clean a bibtex entry +;; These functions operate on a bibtex entry and "clean" it in some way. + +(defun orcb-clean-nil (arg) + "Remove nil from some article fields. +The removal is conditional. Sometimes it is useful to have nil +around, e.g. for ASAP articles where the fields are not defined +yet but will be in the future. + +With \\[univeral-argument], run `bibtex-clean-entry' after." + (interactive "P") + (bibtex-beginning-of-entry) + (let* ((entry (bibtex-parse-entry)) + (type (downcase (cdr (assoc "=type=" entry))))) + (when (string= type "article") + (cond + ;; we have volume and pages but number is nil. + ;; remove the number field. + ((and (string= type "article") + (not (string= (cdr (assoc "volume" entry)) "{nil}")) + (not (string= (cdr (assoc "pages" entry)) "{nil}")) + (string= (cdr (assoc "number" entry)) "{nil}")) + (bibtex-set-field "number" "") + (if arg + (bibtex-clean-entry))))))) + + +(defun orcb-clean-nil-opinionated () + "Remove nil from all article fields. + +Note that by default, this will leave the entry empty, which may +then get deleted by `bibtex-clean-entry.' To disable this +behavior, remove opts-or-alts from `bibtex-entry-format'. This +will leave the empty entries so that you may fill them in later." + (interactive) + (bibtex-beginning-of-entry) + (let* ((entry (bibtex-parse-entry)) + (type (downcase (cdr (assoc "=type=" entry))))) + (when (string= type "article") + (cl-loop for (field . text) in entry do + (if (string= text "{nil}") + (bibtex-set-field field "")))))) + + +(defun orcb-clean-doi () + "Remove http://dx.doi.org/ or https://doi.org in the doi field." + (let ((doi (bibtex-autokey-get-field "doi"))) + (when (or (string-match "^http://dx.doi.org/" doi) + (string-match "^https://doi.org/" doi)) + (setq doi (replace-match "" nil nil doi)) (bibtex-beginning-of-entry) - (cdr (assoc "=key=" (bibtex-parse-entry)))))) + (goto-char (car (cdr (bibtex-search-forward-field "doi" t)))) + (bibtex-kill-field) + (bibtex-make-field "doi") + (backward-char) + (insert doi)))) + + +(defun orcb-clean-year (&optional new-year) + "Fix years set to 0. +If optional NEW-YEAR set it to that, otherwise prompt for it." + ;; asap articles often set year to 0, which messes up key + ;; generation. fix that. + (let ((year (bibtex-autokey-get-field "year"))) + (when (string= "0" year) + (bibtex-beginning-of-entry) + (goto-char (car (cdr (bibtex-search-forward-field "year" t)))) + (bibtex-kill-field) + (bibtex-make-field "year") + (backward-char) + (insert (or new-year (read-string "Enter year: ")))))) + + +(defun orcb-clean-pages () + "Check for empty pages, and put eid in its place if it exists." + (let ((pages (bibtex-autokey-get-field "pages")) + (eid (bibtex-autokey-get-field "eid"))) + (when (and (not (string= "" eid)) + (or (string= "" pages))) + (bibtex-set-field "pages" eid)))) + + +(defun orcb-& () + "Replace naked & with \& in a bibtex entry." + (save-restriction + (bibtex-narrow-to-entry) + (bibtex-beginning-of-entry) + (while (re-search-forward " & " nil t) + (replace-match " \\\\& ")))) + + +(defun orcb-% () + "Replace naked % with % in a bibtex entry. +Except when it is already escaped or in a URL. The replacement +for the % is defined by `orcb-%-replacement-string'." + (save-restriction + (bibtex-narrow-to-entry) + (bibtex-beginning-of-entry) + (while (re-search-forward "\\([^\\]\\)%\\([^[:xdigit:]]\\)" nil t) + (replace-match (concat "\\1" + orcb-%-replacement-string + "\\2"))))) + + +(defun orcb-key-comma () + "Make sure there is a comma at the end of the first line." + (bibtex-beginning-of-entry) + (end-of-line) + ;; some entries do not have a key or comma in first line. We check and add it, + ;; if needed. + (unless (string-match ", *$" (thing-at-point 'line)) + (end-of-line) + (insert ","))) + + +(defun orcb-key (&optional allow-duplicate-keys) + "Replace the key in the entry. +Prompts for replacement if the new key duplicates one already in +the file, unless ALLOW-DUPLICATE-KEYS is non-nil." + (let ((key (funcall org-ref-clean-bibtex-key-function + (bibtex-generate-autokey)))) + ;; remove any \\ in the key + (setq key (replace-regexp-in-string "\\\\" "" key)) + ;; first we delete the existing key + (bibtex-beginning-of-entry) + (re-search-forward bibtex-entry-maybe-empty-head) + (if (match-beginning bibtex-key-in-head) + (delete-region (match-beginning bibtex-key-in-head) + (match-end bibtex-key-in-head))) + ;; check if the key is in the buffer + (when (and (not allow-duplicate-keys) + (save-excursion + (bibtex-search-entry key))) + (save-excursion + (bibtex-search-entry key) + (bibtex-copy-entry-as-kill) + (switch-to-buffer-other-window "*duplicate entry*") + (bibtex-yank)) + (setq key (bibtex-read-key "Duplicate Key found, edit: " key))) + + (insert key) + (kill-new key))) + + +(defun orcb-check-journal () + "Check entry at point to see if journal exists in `org-ref-bibtex-journal-abbreviations'. +If not, issue a warning." + (interactive) + (when + (string= "article" + (downcase + (cdr (assoc "=type=" (bibtex-parse-entry))))) + (save-excursion + (bibtex-beginning-of-entry) + (let* ((entry (bibtex-parse-entry t)) + (journal (cdr (assoc "journal" entry)))) + (when (null journal) + (warn "Unable to get journal for this entry.")) + (unless (member journal (-flatten org-ref-bibtex-journal-abbreviations)) + (message "Journal \"%s\" not found in org-ref-bibtex-journal-abbreviations." journal)))))) + + +(defun orcb-fix-spacing () + "Delete whitespace and fix spacing between entries." + (let (beg end) + (save-excursion + (save-restriction + (widen) + (bibtex-beginning-of-entry) + (setq beg (point)) + (bibtex-end-of-entry) + (setq end (if (re-search-forward bibtex-any-entry-maybe-empty-head nil t) + (progn (beginning-of-line) + (point)) + (point-max))) + ;; 1. delete whitespace + (narrow-to-region beg end) + (delete-trailing-whitespace) + ;; 2. delete consecutive empty lines + (goto-char end) + (while (re-search-backward "\n\n\n+" nil 'move) + (replace-match "\n\n")) + ;; 3. add one line between entries + (goto-char end) + (forward-line -1) + (when (looking-at "[}][ \t]*\\|@Comment.+\\|%.+") + (end-of-line) + (newline)))))) + + +(defun orcb-download-pdf () + "Try to get the pdf in an entry." + ;; try to get pdf + (when doi-utils-download-pdf + (if doi-utils-async-download + (doi-utils-async-download-pdf) + (doi-utils-get-bibtex-entry-pdf)))) + + +;;;###autoload +(defun org-ref-clean-bibtex-entry () + "Clean and replace the key in a bibtex entry. +See functions in `org-ref-clean-bibtex-entry-hook'." + (interactive) + (save-excursion + (save-restriction + (bibtex-narrow-to-entry) + (bibtex-beginning-of-entry) + ;; run hooks. each of these operates on the entry with no arguments. + ;; this did not work like i thought, it gives a symbolp error. + ;; (run-hooks org-ref-clean-bibtex-entry-hook) + (mapc (lambda (x) + (save-restriction + (save-excursion + (funcall x)))) + org-ref-clean-bibtex-entry-hook)))) + + +;; * Missing functions in bibtex-completion +;; I couldn't find these, and they seem useful. + +(defun org-ref-bibtex-get-entry (key) + "Return a parsed bibtex entry." + (save-window-excursion + (let ((bibtex-completion-bibliography (org-ref-find-bibliography))) + (bibtex-completion-show-entry (list key)) + (bibtex-beginning-of-entry) + (bibtex-parse-entry)))) + + +(defun org-ref-bibtex-get-entry-value (key field) + "For the entry associated with KEY get the FIELD value." + (cdr (assoc field (org-ref-bibtex-get-entry key)))) + + +(defun org-ref-get-citation-year (key) + "Get the year of an entry with KEY. Return year as a string." + (org-ref-bibtex-get-entry-value key "year")) + ;;* The end (provide 'org-ref-bibtex) diff --git a/lisp/org-ref/org-ref-citation-links.el b/lisp/org-ref/org-ref-citation-links.el new file mode 100644 index 00000000..74c22ea6 --- /dev/null +++ b/lisp/org-ref/org-ref-citation-links.el @@ -0,0 +1,1339 @@ +;;; org-ref-citation-links.el --- citation links for org-ref -*- lexical-binding: t; -*- +;; +;; Copyright (C) 2021 John Kitchin + +;; Author: John Kitchin +;; Keywords: convenience + +;; 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: +;; +;; This library provides hyper-functional citation links. These links can +;; contain common pre/post notes, and multiple citation keys that each have +;; their own pre/postnotes. +;; +;; These links are fontified to indicate if the citation keys are valid, and to +;; indicate the pre/post-note structure. They also have tooltips that show +;; information from the bibtex entry. +;; +;; Each link is functional, and clicking on one will open a hydra menu +;; `org-ref-citation-hydra/body' of actions that range from opening the bibtex +;; entry, notes, pdf or associated URL, to searching the internet for related +;; articles. +;; +;; Each citation link also has a local keymap on it, which provides keyboard +;; shortcuts for some actions like sorting, rearranging and navigating citation +;; links. See `org-ref-cite-keymap' for the key bindings. +;; +;; Each link exports to a corresponding LaTeX citation command, or can be +;; rendered with CSL for other kinds of exports like HTML, markdown, or ODT. +;; +;; This library also provides a minimal set of insertion functions that use +;; completion. You can also use the org link completion mechanism to insert a +;; citation. +;; +;; natmove like preprocessing is provided with `org-ref-cite-natmove'. +;; +;;; Code: + +(require 'hydra) +(require 'xref) +(eval-when-compile (require 'subr-x)) + +(defgroup org-ref-faces nil + "A group for faces in `org-ref'." + :group 'org-ref-faces) + + +(defface org-ref-cite-face + `((t (:inherit org-link + :foreground "forest green"))) + "Color for cite-like links in org-ref." + :group 'org-ref-faces) + + +(defface org-ref-bad-cite-key-face + `((t (:inherit org-ref-cite-face + :foreground "red"))) + "Color for bad cite keys in org-ref." + :group 'org-ref-faces) + + +(defface org-ref-cite-global-prefix/suffix-face + `((t (:inherit org-ref-cite-face :weight bold))) + "Face for global prefix/suffix in a cite link." + :group 'org-ref-faces) + + +(defface org-ref-cite-&-face + `((t (:inherit org-ref-cite-face :weight bold))) + "Face for the starting & in a cite key." + :group 'org-ref-faces) + + +(defface org-ref-cite-local-prefix/suffix-face + `((t (:inherit org-ref-cite-face :slant italic))) + "Face for local prefix/suffix in a cite link." + :group 'org-ref-faces) + + +(defface org-ref-cite-invalid-local-prefix/suffix-face + `((t (:inherit org-ref-cite-face :foreground "red"))) + "Face for invalid local prefix/suffix in a cite link. +This is mostly for multicites and natbib." + :group 'org-ref-faces) + + +(defcustom org-ref-default-citation-link + "cite" + "The default type of citation link to use." + :type 'string + :group 'org-ref) + + +(defcustom org-ref-natbib-types + '(("cite" "basic citation") + ("nocite" "add key to bibliography, but do not cite it in the text") + ("citet" "textual, Jones et al. (1990") + ("citet*" "textual, full author list Jones, Baker, and Williams (1990)") + ("citep" "parenthetical citation (Jones et al. (1990)") + ("citep*" "parenthetical, full author list, (Jones, Baker, and Williams, 1990)") + ("citealt" "same as citet, but without parentheses") + ("citealt*" "same as citet, with full author list but without parentheses") + ("citealp" "same as citep, but without parentheses") + ("citealp*" "same as citep, with full author list, but without parentheses") + ("citenum" "The number of the citation in the bibliography, e.g. 11") + ("citetext" "text inserted in citation in the document") + ("citeauthor" "Only the author, Jones et al.") + ("citeauthor*" "The full author list, Jones, Baker, and Williams") + ("citeyear" "The year of the citation, 2021") + ("citeyearpar" "The year in parentheses (2021)") + ("Citet" "like citet, but with forced capitalization for starting sentences") + ("Citep" "like citep, but with forced capitalization for starting sentences") + ("Citealt" "like citet, but with forced capitalization and no parentheses") + ("Citealp" "like citep, but with forced capitalization and no parentheses") + ("Citeauthor" "like citeauthor with forced capitalization") + ("Citet*" "like citet, with full author list and forced capitalization") + ("Citep*" "like citep, with full author list and forced capitalization") + ("Citealt*" "like citet, with full author list, forced capitalization and no parentheses") + ("Citealp*" "like citep, with full author list, forced capitalization and no parentheses") + ("Citeauthor*" "like citeauthor with forced capitalization")) + "Natbib commands can have many references, and global prefix/suffix text. + For natbib cite commands see + http://tug.ctan.org/macros/latex/contrib/natbib/natnotes.pdf" + :type '(repeat :tag "List of citation types" (list string string)) + :group 'org-ref) + + +(defcustom org-ref-biblatex-types + '(("Cite" "basic citation with capitalization") + ("parencite" "similar to cite with parentheses") + ("Parencite" "similar to cite with parentheses and capitalization") + ("footcite" "Put the citation in a footnote") + ("footcitetext" "Put the citation in a footnote using \footnotetext") + + ("textcite" "print the authors or editors as a subject of the sentence") + ("Textcite" "print the authors or editors as a subject of the sentence with capitalization") + ("smartcite" "like parencite in a footnote, and footcite in the body") + ("Smartcite" "like parencite in a footnote, and footcite in the body with capitalization") + ("cite*" "similar to cite, but prints the year or title") + ("parencite*" "similar to parencite, but prints the year or title") + ("supercite" "superscripted numeric citation (only in numberic styles)") + + ("autocite" "handles some punctuation nuances") + ("Autocite" "handles some punctuation nuances with punctuation") + ("autocite*" "same as autocite but * is passed to the backend") + ("Autocite*" "same as Autocite but * is passed to the backend") + + ("citetitle" "the shorttitle or title field") + ("citetitle*" "the full title") + + ("citeyear" "the year field") + ("citeyear*" "the year field and extradate information if available") + + ("citedate" "the full date or year") + ("citedate*" "the full date or year, including extradate information if available") + + ("citeurl" "the url field") + + ("fullcite" "create a full citation similar to what is in the bibliography") + ("footfullcite" "create a full citation as a footnote") + ;; "volcite" "Volcite" cannot support the syntax + ("notecite" "print prenote and postnote, but no citation") + ("Notecite" "print prenote and postnote, but no citation with capitalization") + + ("pnotecite" "similar to notecite with parentheses") + ("Pnotecite" "similar to Notecite with parentheses") + ("fnotecite" "similar to notecite in a footnote")) + "biblatex commands. + Biblatex commands + https://mirrors.ibiblio.org/CTAN/macros/latex/contrib/biblatex/doc/biblatex.pdf" + :type '(repeat :tag "List of citation types" string) + :group 'org-ref) + + +(defcustom org-ref-biblatex-multitypes + '(("cites" "multicite version of cite") + ("Cites" "multicite version of Cite") + ("parencites" "multicite version of parencite") + ("Parencites" "multicite version of Parencite") + ("footcites" "multicite version of footcite") + ("footcitetexts" "multicite version of footcitetext") + ("smartcites" "multicite version of smartcite") + ("Smartcites" "multicite version of Smartcite") + ("textcites" "multicite version of textcite") + ("Textcites" "multicite version of Textcite") + ("supercites" "multicite version of supercite") + ("autocites" "multicite version of autocite") + ("Autocites" "multicite version of Autocite")) + "Multicite link types" + :type '(repeat :tag "List of citation types" string) + :group 'org-ref) + + +(defcustom org-ref-cite-types + (append + org-ref-natbib-types + org-ref-biblatex-types + org-ref-biblatex-multitypes + ;; for the bibentry package + '(("bibentry" "Insert the bibtex entry"))) + "List of citation types known in `org-ref'." + :type '(repeat :tag "List of citation types (type description)" (list string string)) + :group 'org-ref) + + +(defvar org-ref-insert-cite-function) + +(defcustom org-ref-cite-keymap + (let ((map (copy-keymap org-mouse-map))) + ;; Navigation keys + (define-key map (kbd "C-") 'org-ref-previous-key) + (define-key map (kbd "C-") 'org-ref-next-key) + + ;; rearrangement keys + (define-key map (kbd "S-") (lambda () (interactive) (org-ref-swap-citation-link -1))) + (define-key map (kbd "S-") (lambda () (interactive) (org-ref-swap-citation-link 1))) + (define-key map (kbd "S-") 'org-ref-sort-citation-link) + (define-key map (kbd "") (lambda () + (interactive) + (funcall org-ref-insert-cite-function))) + + ;; xref navigation + (define-key map (kbd "M-.") (lambda () + (interactive) + (xref-push-marker-stack) + (org-ref-open-citation-at-point))) + map) + "Keymap for cite links." + :type 'symbol + :group 'org-ref) + + +(defcustom org-ref-cite-insert-version 3 + "Default version to insert citations with. + The default is 3. In legacy documents you might prefer 2 though, + so this variable can be buffer- or directory local if you want. + + version 2 means the links are not bracketed, and comma-separated keys. + + version 3 means the links are bracketed, with semicolon-separated + &keys." + :type 'number + :group 'org-ref) + + +(defvar org-ref-citation-key-re + (rx "&" (group-n 1 (one-or-more (any word "-.:?!`'/*@+|(){}<>&_^$#%~")))) + "Numbered regular expression for a version 3 cite key. + Key is in group 1. + Adapted from the expression in org-cite.") + + +(defun org-ref-cite-version (path) + "Return the version for PATH. + PATH is from a cite link. + Version 2 is separated by commas and uses plain keys. + Version 3 is separated by semicolons and uses &keys. + I think that if there is a & in path, it must be version 3." + (if (string-match "&" path) + 3 + 2)) + + +;; * Parsing/interpreting a citation path + +(defun org-ref-parse-cite-path (path) + "Return a data structure representing the PATH. + the data structure is a plist with (:version :prefix :suffix :references). + Each reference is a plist with (:key :prefix :suffix)." + (pcase (org-ref-cite-version path) + (2 + ;; This will not have any prefix or suffix, since that was previously done in the desc. + (list :version 2 :references (cl-loop for key in (split-string path ",") collect + (list :key (string-trim key))))) + (3 (let ((citation-references (split-string path ";")) + (these-results '(:version 3))) + ;; if the first ref doesn't match a key, it must be a global prefix + ;; this pops the referenc off. + (when (null (string-match org-ref-citation-key-re (cl-first citation-references))) + (setq these-results (append these-results (list :prefix (cl-first citation-references))) + citation-references (cdr citation-references))) + + ;; if the last ref doesn't match a key, then it is a global suffix + ;; we remove the last one if this is true after getting the suffix. + (when (null (string-match org-ref-citation-key-re (car (last citation-references)))) + (setq these-results (append these-results (list :suffix (car (last citation-references)))) + citation-references (butlast citation-references))) + + (setq these-results + (append these-results + (list + :references + (cl-loop for s in citation-references collect + (if (null (string-match org-ref-citation-key-re s)) + (error "No matching key found in %s" s) + (let* ((key (match-string-no-properties 1 s)) + (key-start (match-beginning 0)) + (key-end (match-end 0)) + (prefix (let ((p (substring s 0 key-start))) + (if (string= "" (string-trim p)) + nil + p))) + (suffix (let ((s (substring s key-end))) + (if (string= "" (string-trim s)) + nil + s)))) + (list :key key :prefix prefix :suffix suffix))))))))))) + + +(defun org-ref-interpret-cite-data (data) + "Interpret the DATA structure from `org-ref-parse-cite-path' back +to a path string." + (pcase (plist-get data :version) + (2 + (string-join (cl-loop for ref in (plist-get data :references) collect (plist-get ref :key)) ",")) + (3 + (concat + (when-let (prefix (plist-get data :prefix)) (concat prefix ";")) + (string-join (cl-loop for ref in (plist-get data :references) collect + (concat + (plist-get ref :prefix) + "&" (plist-get ref :key) + (plist-get ref :suffix))) + ";") + (when-let (suffix (plist-get data :suffix)) (concat ";" suffix)))))) + + +;; * Activating citation links +;; +;; We use the activate-func for fontification of pieces of each link. + + +(declare-function bibtex-completion-candidates "bibtex-completion") +(declare-function bibtex-completion-init "bibtex-completion") +(defvar bibtex-completion-bibliography) +(defvar bibtex-completion-display-formats-internal) + +;; (defun org-ref-valid-keys () +;; "Return a list of valid bibtex keys for this buffer. +;; This is used a lot in `org-ref-cite-activate' so it needs to be +;; fast, but also up to date." +;; ;; this seems to be needed, but we don't want to do this every time +;; (unless bibtex-completion-display-formats-internal +;; (bibtex-completion-init)) + +;; (let ((bibtex-completion-bibliography (org-ref-find-bibliography))) +;; (cl-loop for entry in (bibtex-completion-candidates) +;; collect +;; (cdr (assoc "=key=" (cdr entry)))))) + + +(defun org-ref-valid-keys () + "Return a list of valid bibtex keys for this buffer. +This is used a lot in `org-ref-cite-activate' so it needs to be +fast, but also up to date." + + ;; this seems to be needed, but we don't want to do this every time + (unless bibtex-completion-display-formats-internal + (bibtex-completion-init)) + + (let* ((files (org-ref-find-bibliography))) + (if (seq-every-p 'identity + (cl-loop for file in files + collect (assoc file bibtex-completion-cache))) + ;; We have a cache for each file + ;; bibtex-completion-cache contains (filename md5hash entries) + (cl-loop for entry in + (cl-loop + for file in files + append (cddr (assoc file bibtex-completion-cache))) + collect (cdr (assoc "=key=" (cdr entry)))) + ;; you need to get a cache because one or more of the files was not in the cache. + (let ((bibtex-completion-bibliography files)) + (cl-loop for entry in (bibtex-completion-candidates) + collect + (cdr (assoc "=key=" (cdr entry)))))))) + + +(defvar-local org-ref-valid-keys-hashes nil) +(defvar-local org-ref-valid-keys-cache nil) + +(defun org-ref-valid-keys-cached () + "Update `org-ref-valid-keys-cache` only when files changed." + + (let ((local-hashes (cons bibtex-completion-bibliography + (mapcar 'cadr bibtex-completion-cache)))) + (when (not (equal local-hashes org-ref-valid-keys-hashes)) + (setq-local org-ref-valid-keys-hashes local-hashes) + (setq-local org-ref-valid-keys-cache (make-hash-table :test 'equal)) + (cl-loop for entry in (org-ref-valid-keys) + do + (puthash entry t org-ref-valid-keys-cache)))) + org-ref-valid-keys-cache) + +(defun org-ref-cite-activate (start end path _bracketp) + "Activation function for a cite link. +START and END are the bounds of the link. +PATH has the citations in it." + (let* ((valid-keys (org-ref-valid-keys-cached)) + valid-key + substrings) + (goto-char start) + (pcase (org-ref-cite-version path) + (2 + ;; This makes the brackets visible, but we only need it when there is a + ;; description. + (when (looking-at "\\[\\[\\(.*\\)\\]\\[\\(.*\\)\\]\\]") + (remove-text-properties start end '(invisible nil))) + (setq substrings (split-string path ",")) + (cl-loop for key in substrings + do + ;; get to the substring + (search-forward key end) + (put-text-property (match-beginning 0) + (match-end 0) + 'keymap + org-ref-cite-keymap) + (put-text-property (match-beginning 0) + (match-end 0) + 'cite-key + key) + (unless (gethash (string-trim key) valid-keys nil) + (put-text-property (match-beginning 0) + (match-end 0) + 'face 'org-ref-bad-cite-key-face) + (put-text-property (match-beginning 0) + (match-end 0) + 'help-echo "Key not found")) + )) + (3 + (setq substrings (split-string path ";")) + (cl-loop for i from 0 for s in substrings + do + ;; get to the substring + (search-forward s end) + (put-text-property (match-beginning 0) + (match-end 0) + 'keymap + org-ref-cite-keymap) + (let* (key-begin + key-end + key) + + ;; Look for a key. common pre/post notes do not have keys in them. + (save-match-data + (when (string-match org-ref-citation-key-re s) + (setq key (match-string-no-properties 1 s) + valid-key (gethash key valid-keys nil) + ))) + + ;; these are global prefix/suffixes + (when (and (or (= i 0) + (= i (- (length substrings) 1))) + (null key)) + (put-text-property (match-beginning 0) (match-end 0) + 'face 'org-ref-cite-global-prefix/suffix-face) + (put-text-property (match-beginning 0) (match-end 0) + 'help-echo "Global prefix/suffix")) + + ;; we have a key. we have to re-search to get its position + (when key + (save-excursion + (save-match-data + (search-backward (concat "&" key)) + (setq key-begin (match-beginning 0) + key-end (match-end 0)))) + ;; mark the & + (put-text-property key-begin (+ 1 key-begin) + 'face 'org-ref-cite-&-face) + ;; store key on the whole thing + (put-text-property (match-beginning 0) + (match-end 0) + 'cite-key + key) + + ;; fontify any prefix /suffix text + (put-text-property (match-beginning 0) key-begin + 'face 'org-ref-cite-local-prefix/suffix-face) + + (put-text-property key-end (match-end 0) + 'face 'org-ref-cite-local-prefix/suffix-face) + + ;; bad key activation + (unless valid-key + (put-text-property key-begin key-end + 'face 'font-lock-warning-face) + (put-text-property key-begin key-end + 'help-echo "Key not found"))))))))) + + +;; * Following citation links + +(declare-function org-ref-get-bibtex-key-and-file "org-ref-core") + +(defhydra org-ref-citation-hydra (:color blue :hint nil) + "Citation actions +" + ("o" org-ref-open-citation-at-point "Bibtex" :column "Open") + ("p" org-ref-open-pdf-at-point "PDF" :column "Open") + ("n" org-ref-open-notes-at-point "Notes" :column "Open") + ("u" org-ref-open-url-at-point "URL" :column "Open") + + ;; WWW actions + ("ww" org-ref-wos-at-point "WOS" :column "WWW") + ("wr" org-ref-wos-related-at-point "WOS related" :column "WWW") + ("wc" org-ref-wos-citing-at-point "WOS citing" :column "WWW") + ("wg" org-ref-google-scholar-at-point "Google Scholar" :column "WWW") + ("wp" org-ref-pubmed-at-point "Pubmed" :column "WWW") + ("wf" org-ref-crossref-at-point "Crossref" :column "WWW") + ("wb" org-ref-biblio-at-point "Biblio" :column "WWW") + ("e" org-ref-email-at-point "Email" :column "WWW") + + ;; Copyish actions + ("K" (save-window-excursion + (let ((bibtex-completion-bibliography (org-ref-find-bibliography))) + (bibtex-completion-show-entry (list (org-ref-get-bibtex-key-under-cursor))) + (bibtex-copy-entry-as-kill) + (kill-new (pop bibtex-entry-kill-ring)))) + "Copy bibtex" :column "Copy") + ("k" (kill-new (car (org-ref-get-bibtex-key-and-file))) "Copy key" :column "Copy") + ("f" (kill-new (bibtex-completion-apa-format-reference + (org-ref-get-bibtex-key-under-cursor))) + "Copy formatted" :column "Copy") + ("h" (kill-new + (format "* %s\n\n cite:&%s" + (bibtex-completion-apa-format-reference + (org-ref-get-bibtex-key-under-cursor)) + (car (org-ref-get-bibtex-key-and-file)))) + "Copy org heading" + :column "Copy") + + ;; Editing actions + ("" org-ref-cite-shift-left "Shift left" :color red :column "Edit") + ("" org-ref-cite-shift-right "Shift right" :color red :column "Edit") + ("" org-ref-sort-citation-link "Sort by year" :column "Edit") + ("i" (funcall org-ref-insert-cite-function) "Insert cite" :column "Edit") + ("t" org-ref-change-cite-type "Change cite type" :column "Edit") + ("d" org-ref-delete-citation-at-point "Delete at point" :column "Edit") + ("r" org-ref-replace-citation-at-point "Replace cite" :column "Edit") + ("P" org-ref-edit-pre-post-notes "Edit pre/suffix" :column "Edit") + + ;; Navigation + ("[" org-ref-previous-key "Previous key" :column "Navigation" :color red) + ("]" org-ref-next-key "Next key" :column "Navigation" :color red) + ("v" org-ref-jump-to-visible-key "Visible key" :column "Navigation" :color red) + ("q" nil "Quit")) + + +(defun org-ref-cite-follow (_path) + "Follow a cite link." + (org-ref-citation-hydra/body)) + + +;; * Citation links tooltips +(defvar bibtex-completion-bibliography) +(defvar bibtex-completion-pdf-symbol) +(defvar bibtex-completion-notes-symbol) +(defvar bibtex-completion-find-note-functions) + +(declare-function org-ref-find-bibliography "org-ref-core") +(declare-function bibtex-completion-find-pdf "bibtex-completion") +(declare-function bibtex-completion-apa-format-reference "bibtex-completion") + +(defun org-ref-cite-tooltip (_win _obj position) + "Get a tooltip for the cite at POSITION." + (let ((key (get-text-property position 'cite-key))) + (when key + (let ((bibtex-completion-bibliography (org-ref-find-bibliography)) + (has-pdf (when (bibtex-completion-find-pdf key) bibtex-completion-pdf-symbol)) + (has-notes (when (cl-some #'identity + (mapcar (lambda (fn) + (funcall fn key)) + bibtex-completion-find-note-functions)) + bibtex-completion-notes-symbol))) + (format "%s%s %s" (or has-pdf "") (or has-notes "") + (bibtex-completion-apa-format-reference key)))))) + + +;; * Exporting citation links + +(defun org-ref-cite-export (cmd path desc backend) + "Export a cite link. +This supports the syntax: \\cmd[optional prefix][optional suffix]{keys} +The prefix and suffix must be the global version. Local prefix/suffixes are ignored. +PATH contains the link path. +BACKEND is the export backend. +Use with apply-partially." + (pcase backend + ('latex + (let* ((cite (org-ref-parse-cite-path path)) + (references (plist-get cite :references)) + (keys (cl-loop for ref in references collect + (plist-get ref :key)))) + (pcase (org-ref-cite-version path) + (2 + (let* ((prefix-suffix (split-string (or desc "") "::")) + (prefix (cond + ((and (cl-first prefix-suffix) (not (string= "" (cl-first prefix-suffix)))) + (format "[%s]" (cl-first prefix-suffix))) + ((cl-second prefix-suffix) + "[]") + (t + ""))) + (suffix (cond + ((cl-second prefix-suffix) + (format "[%s]" (cl-second prefix-suffix))) + (t + "")))) + (s-format "\\${cmd}${prefix}${suffix}{${keys}}" 'aget + `(("cmd" . ,cmd) + ("prefix" . ,(string-trim prefix)) + ("suffix" . ,(string-trim suffix)) + ("keys" . ,(string-join keys ",")))))) + (3 + (s-format "\\${cmd}${prefix}${suffix}{${keys}}" 'aget + `(("cmd" . ,cmd) + ;; if there is more than one key, we only do global + ;; prefix/suffix But for one key, we should allow local + ;; prefix and suffix or the global one. + ("prefix" . ,(if (= 1 (length references)) + ;; single reference + (cond + ;; local prefix is not empty, we use it. + ((plist-get (car references) :prefix) + (concat "[" + (string-trim (plist-get (car references) :prefix)) + "]")) + ;; local prefix is empty, but global one + ;; is not, so we use it + ((plist-get cite :prefix) + (concat "[" + (string-trim (plist-get cite :prefix)) + "]")) + ;; if you have a suffix, you need an empty prefix + ((plist-get cite :suffix) + "[]") + (t + "")) + ;; Multiple references + (cond + ;; Check the common prefix + ((plist-get cite :prefix) + (concat "[" + (string-trim (plist-get cite :prefix)) + "]")) + ;; Check the prefix in the first cite + ((plist-get (car references) :prefix) + (concat "[" + (string-trim (plist-get (car references) :prefix)) + "]")) + ;; if you have a suffix, you need an empty prefix + ((plist-get cite :suffix) + "[]") + (t + "")))) + ("suffix" . ,(if (= 1 (length references)) + ;; Single reference + (cond + ;; local prefix is not empty, so use it + ((plist-get (car references) :suffix) + (format "[%s]" + (string-trim (plist-get (car references) :suffix)))) + ;; global prefix is not empty + ((plist-get cite :suffix) + (format "[%s]" (string-trim (plist-get cite :suffix)))) + (t + "")) + ;; Multiple references + (cond + ;; this is a common suffix + ((plist-get cite :suffix) + (format "[%s]" (string-trim (plist-get cite :suffix)))) + ;; last reference has a suffix + ((plist-get (car (last references)) :suffix) + (format "[%s]" (string-trim (plist-get (car (last references)) :suffix)))) + (t + ;; If there is a prefix, then this should + ;; be an empty bracket, and if not it + ;; should am empty string. You need an + ;; empty bracket, at least for biblatex + ;; commands. With just one set of + ;; brackets it is interpreted as a + ;; suffix. + (if (or (plist-get cite :prefix) + (plist-get (car references) :prefix)) + "[]" + ""))))) + ("keys" . ,(string-join keys ",")))))))))) + + +(defun org-ref-multicite-export (cmd path _desc backend) + "Export a multicite link. +This supports the syntax: \\cmd(multiprenote)(multipostnote)[prenote][postnote]{key1}...[prenote][postnote]{key} +PATH contains the link path. +BACKEND is the export backend. +Use with apply-partially." + (pcase backend + ('latex + (let ((cite (org-ref-parse-cite-path path))) + (s-format "\\${cmd}${global-prefix}${global-suffix}${keys}" 'aget + `(("cmd" . ,cmd) + ("global-prefix" . ,(cond + ((plist-get cite :prefix) + (concat "(" (plist-get cite :prefix) ")")) + ;; if you have a suffix, you need an empty prefix + ((plist-get cite :suffix) + "()") + (t + ""))) + ("global-suffix" . ,(if (not (string= "" (or (plist-get cite :suffix) ""))) + (format "(%s)" (plist-get cite :suffix)) + "")) + ("keys" . ,(string-join + (cl-loop for ref in (plist-get cite :references) + collect + (format "%s%s{%s}" + (cond + ;; we have a prefix, stick it in + ((not (string= "" + (or (plist-get ref :prefix) ""))) + (concat "[" (plist-get ref :prefix) "]")) + ;; no prefix, but a suffix, so + ;; empty prefix for placeholder + ((not (string= "" + (or (plist-get ref :suffix) ""))) + "[]") + (t + "")) + (cond + ((not (string= "" + (or (plist-get ref :suffix) ""))) + (concat "[" (plist-get ref :suffix) "]")) + (t + "")) + (plist-get ref :key))))))))))) + +;; * Completion for citation links +;; +;; This allows you to type C-c l, choose a cite link type, and then insert a key. + +(defun org-ref-cite-link-complete (cmd &optional _arg) + "Cite link completion for CMD." + (concat + cmd ":" + "&" (org-ref-read-key))) + +;; * Generate all the links +;; +;; We loop on the three categories because there are some differences between +;; them, mostly in the multitypes. + +(cl-loop for (cmd _desc) in (append org-ref-natbib-types + org-ref-biblatex-types) + do + (org-link-set-parameters + cmd + :complete (apply-partially #'org-ref-cite-link-complete cmd) + :follow #'org-ref-cite-follow + :face 'org-ref-cite-face + :help-echo #'org-ref-cite-tooltip + :export (apply-partially 'org-ref-cite-export cmd) + :activate-func #'org-ref-cite-activate)) + + +(cl-loop for (cmd _desc) in org-ref-biblatex-multitypes do + (org-link-set-parameters + cmd + :complete (apply-partially #'org-ref-cite-link-complete cmd) + :follow #'org-ref-cite-follow + :face 'org-ref-cite-face + :help-echo #'org-ref-cite-tooltip + :export (apply-partially 'org-ref-multicite-export cmd) + :activate-func #'org-ref-cite-activate)) + + +(org-link-set-parameters + "bibentry" + :complete (apply-partially #'org-ref-cite-link-complete "bibentry") + :follow #'org-ref-cite-follow + :face 'org-ref-cite-face + :help-echo #'org-ref-cite-tooltip + :export (apply-partially 'org-ref-cite-export "bibentry") + :activate-func #'org-ref-cite-activate) + + +;; * Cite link utilities + +;;;###autoload +(defun org-ref-delete-citation-at-point () + "Delete the citation or reference at point." + (interactive) + (let* ((object (org-element-context)) + (type (org-element-property :type object)) + (begin (org-element-property :begin object)) + (end (org-element-property :end object)) + (link-string (org-element-property :path object)) + (data (org-ref-parse-cite-path link-string)) + (references (plist-get data :references)) + (cp (point)) + key i) + ;; We only want this to work on citation links + (when (assoc type org-ref-cite-types) + (setq key (org-ref-get-bibtex-key-under-cursor)) + (if (null key) + ;; delete the whole cite + (cl--set-buffer-substring begin end "") + (setq i (seq-position references key (lambda (el key) + (string= key (plist-get el :key))))) + ;; delete i'th reference + (setq references (-remove-at i references)) + (setq data (plist-put data :references references)) + (save-excursion + (goto-char begin) + (re-search-forward link-string) + (replace-match (org-ref-interpret-cite-data data))) + (goto-char cp))))) + + +;;;###autoload +(defun org-ref-replace-citation-at-point () + "Replace the citation at point." + (interactive) + (let* ((object (org-element-context)) + (type (org-element-property :type object)) + (begin (org-element-property :begin object)) + (end (org-element-property :end object)) + (link-string (org-element-property :path object)) + (data (org-ref-parse-cite-path link-string)) + (references (plist-get data :references)) + (cp (point)) + key i) + ;; We only want this to work on citation links + (when (assoc type org-ref-cite-types) + (setq key (org-ref-get-bibtex-key-under-cursor)) + + (if (null key) + ;; delete the whole cite + (cl--set-buffer-substring begin end "") + (setq i (seq-position references key (lambda (el key) (string= key (plist-get el :key))))) ;; defined in org-ref + (setf (plist-get (nth i references) :key) (org-ref-read-key)) + + (setq data (plist-put data :references references)) + (save-excursion + (goto-char begin) + (re-search-forward link-string) + (replace-match (org-ref-interpret-cite-data data))) + (goto-char cp))))) + + +;;;###autoload +(defun org-ref-edit-pre-post-notes (&optional common) + "Edit the pre/post notes at point. + +if you are not on a key, or with optional prefix +arg COMMON, edit the common prefixes instead." + (interactive "P") + ;; find out what the point is on. + (let* ((key (get-text-property (point) 'cite-key)) + (cp (point)) + (cite (org-element-context)) + (type (org-element-property :type cite)) + (data (org-ref-parse-cite-path (org-element-property :path cite))) + prefix suffix + (delta 0)) + + (if (or (null key) common) + (progn + (setq prefix (read-string "prenote: " (plist-get data :prefix)) + suffix (read-string "postnote: " (plist-get data :suffix)) + delta (- (length (plist-get data :prefix)) (length prefix))) + + (plist-put data :prefix (if (string= "" prefix) + nil prefix)) + + (plist-put data :suffix (if (string= "" suffix) + nil suffix))) + + ;; On a key + (let ((index (seq-position (plist-get data :references) + key + (lambda (el1 key-at-point) + (string= key-at-point (plist-get el1 :key)))))) + ;; Pad with spaces after prefix and before suffix + (setq prefix (concat + (read-string "prenote: " + (string-trim + (plist-get + (nth index (plist-get data :references)) + :prefix))) + " ") + suffix (concat " " + (read-string "postnote: " + (string-trim + (plist-get + (nth index (plist-get data :references)) + :suffix)))) + delta (- (length (plist-get + (nth index (plist-get data :references)) + :prefix)) + (length prefix))) + (plist-put + (nth index (plist-get data :references)) + :prefix (if (string= "" prefix) + nil prefix)) + + (plist-put + (nth index (plist-get data :references)) + :suffix (if (string= "" suffix) + nil suffix)))) + + + (setf (buffer-substring (org-element-property :begin cite) (org-element-property :end cite)) + (format "[[%s:%s]]" type (org-ref-interpret-cite-data data))) + + ;; This doesn't exactly save the point. I need a fancier calculation for + ;; that I think that accounts for the change due to the prefix change. e.g. + ;; you might add or subtract from the prefix. + (goto-char (- cp delta)))) + + +(declare-function org-element-create "org-element") + +;;;###autoload +(defun org-ref-change-cite-type () + "Change the cite type of citation link at point." + (interactive) + (let* ((type-annotation (lambda (s) + (let ((item (assoc s minibuffer-completion-table))) + (when item (concat + (make-string (- 12 (length s)) ? ) + "-- " + (cl-second item)))))) + (completion-extra-properties `(:annotation-function ,type-annotation)) + (new-type (completing-read "Type: " org-ref-cite-types)) + (cite-link (org-element-context)) + (cp (point))) + (cl--set-buffer-substring + (org-element-property :begin cite-link) + (org-element-property :end cite-link) + (org-element-interpret-data + (org-element-create 'link + `(:type ,new-type + :path ,(org-element-property :path cite-link) + :contents-begin ,(org-element-property :contents-begin cite-link) + :contents-end ,(org-element-property :contents-end cite-link))))) + (goto-char cp))) + + +(defun org-ref-get-bibtex-key-under-cursor () + "Return key under the cursor in org-mode. +If not on a key, but on a cite, prompt for key." + (if-let ((key (get-text-property (point) 'cite-key))) + ;; Point is on a key, so we get it directly + key + ;; point is not on a key, but may still be on a cite link + (let ((el (org-element-context)) + data + keys) + (cond + ;; on a cite-link type + ((and + (eq (org-element-type el) 'link) + (assoc (org-element-property :type el) org-ref-cite-types)) + + (goto-char (org-element-property :begin el)) + (setq data (org-ref-parse-cite-path (org-element-property :path el)) + keys (cl-loop for ref in (plist-get data :references) + collect (plist-get ref :key))) + (cond + ((= 1 (length keys)) + (search-forward (car keys)) + (goto-char (match-beginning 0))) + ;; multiple keys + (t + (setq key (completing-read "Key: " keys)) + (search-forward key) + (goto-char (match-beginning 0)))) + (get-text-property (point) 'cite-key)) + + ;; somewhere else, but looking at a cite-type see issue #908. links in + ;; places like keywords are not parsed as links, but they seem to get + ;; activated, so we can just get onto the key, and then open it. + ((assoc (thing-at-point 'word) org-ref-cite-types) + (save-excursion + (when (re-search-forward ":" (line-end-position) t) + (get-text-property (point) 'cite-key)))))))) + + +;; ** Shift-arrow sorting of keys in a cite link + +(defun org-ref-swap-list-elements (i j lst) + "Swap index I and J in the list LST." + (let ((tempi (nth i lst))) + (setf (nth i lst) (nth j lst)) + (setf (nth j lst) tempi)) + lst) + + +(defun org-ref-swap-citation-link (direction) + "Move citation at point in DIRECTION +1 is to the right, -1 to the left." + (let* ((object (org-element-context)) + (type (org-element-property :type object)) + (begin (org-element-property :begin object)) + ;; (end (org-element-property :end object)) + (link-string (org-element-property :path object)) + (data (org-ref-parse-cite-path link-string)) + (references (plist-get data :references)) + key i) + ;; We only want this to work on citation links + (when (assoc type org-ref-cite-types) + (setq key (org-ref-get-bibtex-key-under-cursor)) + (setq i (seq-position references key (lambda (el key) (string= key (plist-get el :key))))) ;; defined in org-ref + (if (> direction 0) ;; shift right + (org-ref-swap-list-elements i (min (+ i 1) (- (length references) 1)) references) + (org-ref-swap-list-elements i (max (- i 1) 0) references)) + (setq data (plist-put data :references references)) + + ;; and replace the link with the sorted keys + (save-excursion + (goto-char begin) + (re-search-forward link-string) + (replace-match (org-ref-interpret-cite-data data))) + ;; now go forward to key so we can move with the key + (goto-char begin) + (re-search-forward key) + (goto-char (match-beginning 0))))) + + +(defun org-ref-cite-shift-left () + "Shift reference at point to the left." + (interactive) + (org-ref-swap-citation-link -1)) + + +(defun org-ref-cite-shift-right () + "Shift citation at point to the right." + (interactive) + (org-ref-swap-citation-link +1)) + + +;;** Sort cite in cite link + +;;;###autoload +(defun org-ref-sort-citation-link () + "Replace link at point with sorted link by year." + (interactive) + (let* ((object (org-element-context)) + ;; (type (org-element-property :type object)) + (begin (org-element-property :begin object)) + ;; (end (org-element-property :end object)) + (link-string (org-element-property :path object)) + (data (org-ref-parse-cite-path link-string)) + (references (plist-get data :references)) + (bibtex-completion-bibliography (org-ref-find-bibliography))) + + (setq references (cl-sort (cl-loop for ref in references collect + (append ref (list :year (bibtex-completion-get-value + "year" + (bibtex-completion-get-entry + (plist-get ref :key)))))) + (lambda (x y) + (< (string-to-number (plist-get x :year)) + (string-to-number (plist-get y :year)))))) + (setq data (plist-put data :references references)) + (save-excursion + (goto-char begin) + (re-search-forward link-string) + (replace-match (org-ref-interpret-cite-data data))))) + + +;;** C-arrow navigation of cite keys +;; +;; These are a little tricky to understand to me. There are two calls because +;; when you are on a cite, and move, the first change is the boundary of the +;; current cite, and the second is the boundary of next cite. + +;;;###autoload +(defun org-ref-next-key () + "Move cursor to the next cite key when on a cite link. +Otherwise run `right-word'. If the cursor moves off the link, +move to the beginning of the next cite link after this one." + (interactive) + (when-let (next (next-single-property-change (point) 'cite-key)) + (goto-char next)) + (unless (get-text-property (point) 'cite-key) + (when-let (next (next-single-property-change (point) 'cite-key)) + (goto-char next)))) + + +;;;###autoload +(defun org-ref-previous-key () + "Move cursor to the previous cite key when on a cite link. +Otherwise run `left-word'. If the cursor moves off the link, +move to the beginning of the previous cite link after this one." + (interactive) + (when-let (prev (previous-single-property-change (point) 'cite-key)) + (goto-char prev)) + (unless (get-text-property (point) 'cite-key) + (when-let (prev (previous-single-property-change (point) 'cite-key)) + (goto-char prev)))) + +(defvar avy-goto-key) +(defvar avy-style) +(declare-function avy--style-fn "avy") +(declare-function avy-process "avy") +(declare-function avy-with "avy") +(declare-function org-element-parse-buffer "org-element") +(declare-function org-element-property "org-element") +(declare-function org-element-type "org-element") +(declare-function org-element-map "org-element") +(declare-function bibtex-completion-get-value "bibtex-completion") +(declare-function bibtex-completion-get-entry "bibtex-completion") + +;;;###autoload +(defun org-ref-jump-to-visible-key () + "Jump to a visible key with avy." + (interactive) + (avy-with avy-goto-key + (avy-process + (apply #'append + (save-excursion + (org-element-map (org-element-parse-buffer) 'link + (lambda (c) + (when (assoc (org-element-property :type c) org-ref-cite-types) + (goto-char (org-element-property :begin c)) + (let* ((path (org-element-property :path c)) + (data (org-ref-parse-cite-path path)) + (references (plist-get data :references))) + (append (list (org-element-property :begin c)) + (cl-loop for ref in references collect + (progn + (search-forward (plist-get ref :key)) + (match-beginning 0))))))))))) + (avy--style-fn avy-style))) + + +;; * Insert links +(declare-function bibtex-completion-format-entry "bibtex-completion") + +;; The formatting is adapted from ivy-bibtex-transformer. I feel like it is +;; slower than ivy-bibtex though. It is completion agnostic though... +(defun org-ref-read-key () + "Read a key with completion." + (unless bibtex-completion-display-formats-internal + (bibtex-completion-init)) + (let* ((bibtex-completion-bibliography (org-ref-find-bibliography)) + (candidates (mapcar (lambda (entry) + (cons (bibtex-completion-format-entry entry (1- (frame-width))) + (cdr entry))) + (bibtex-completion-candidates))) + (choice (completing-read "org-ref BibTeX entries: " candidates))) + (cdr (assoc "=key=" (assoc choice candidates))))) + + +(defun org-ref-insert-cite-key (key &optional set-type) + "Insert KEY at point as a cite link. +With optional prefix SET-TYPE choose the link type (only on initial insert). +Rules: +1. at beginning of key, insert before it. +2. at middle or end of key, insert after it." + (let* ((object (org-element-context)) + (type (org-element-property :type object)) + ;; (cp (point)) + link-string version data references key-at-point index + (type-annotation (lambda (s) + (let ((item (assoc s minibuffer-completion-table))) + (when item (concat + (make-string (- 12 (length s)) ? ) + "-- " + (cl-second item)))))) + (completion-extra-properties `(:annotation-function ,type-annotation))) + + + (cond + ;; Not on a link, so we just insert a cite + ((null (assoc type org-ref-cite-types)) + (insert (format "[[%s:%s%s]]" + (if set-type + (completing-read "cite type: " org-ref-cite-types) + org-ref-default-citation-link) + (pcase org-ref-cite-insert-version + (2 "") + (3 "&")) + key))) + ;; On a link with no path + ;; See https://github.com/jkitchin/org-ref/issues/951#issuecomment-985998821 + ;; This is an unusual corner case most often triggered by a snippet, although + ;; perhaps there is some scenario like [[cite:]] + ((string= "" (org-element-property :path object)) + (unless (looking-back ":" 1) + (goto-char (org-element-property :end object)) + (skip-chars-backward "]")) + (insert (concat + (pcase org-ref-cite-insert-version + (2 "") + (3 "&")) + key))) + + ;; On a link somewhere, and we need to figure out what to do. + (t + (setq link-string (org-element-property :path object) + version (org-ref-cite-version link-string) + data (org-ref-parse-cite-path link-string) + references (plist-get data :references) + key-at-point (get-text-property (point) 'cite-key)) + + ;; There are two scenarios where key-at-point is null + ;; 1. on the link-type before the : + ;; 2. at the end of the link + ;; Either way we just go to the end. + (when (null key-at-point) + ;; that failed, so move to the last one This seems weird, but when you + ;; insert several marked candidates the point does weird things. + (goto-char (org-element-property :end object)) + (skip-chars-backward " ") + (setq key-at-point (plist-get (car (last references)) :key))) + + + ;; this is index of selected key + (setq index (seq-position references key-at-point + (lambda (el1 key-at-point) + (string= key-at-point (plist-get el1 :key))))) + + (setq data (plist-put data :references + (-insert-at + (+ index (if (and (= 3 version) (looking-at "&")) + 0 + 1)) + (list :key key) references))) + + (pcase org-ref-cite-insert-version + (2 + (cl--set-buffer-substring + (org-element-property :begin object) + (org-element-property :end object) + (concat type ":" (string-join (cl-loop for ref in (plist-get data :references) + collect (plist-get ref :key)) + ",")))) + (3 (cl--set-buffer-substring + (org-element-property :begin object) + (org-element-property :end object) + (concat "[[" type ":" (org-ref-interpret-cite-data data) "]]")))))) + + ;; Now get to the end of the key you just put in. + (setq object (org-element-context)) + (goto-char (org-element-property :end object)) + (skip-chars-backward " "))) + + +(defun org-ref-insert-cite-keys (keys &optional set-type) + "Insert KEYS as citation links. +Optional SET-TYPE to choose the cite type." + (cl-loop for key in keys + do + (org-ref-insert-cite-key key set-type))) + + +;;;###autoload +(defun org-ref-insert-cite-link (&optional set-type) + "Insert a cite link with completion. +Optional prefix arg SET-TYPE to choose the cite type." + (interactive "P") + (org-ref-insert-cite-key (org-ref-read-key) set-type)) + + +;; * natmove like pre-processing +;; +;; I think that citations belong in the sentence where they are used, which +;; means on the left side of punctuation. However, for some citation styles, +;; especially superscripts, it is nicer if they appear on the right hand side of +;; punctuation. achemso in LaTeX provides natmove +;; (https://ctan.org/pkg/natmove?lang=en) for this. It doesn't seem to work for +;; all LaTeX styles though, and in particular only works on the cite command +;; itself. So, Here is a preprocessor function you can use to move all the +;; cites. + +(declare-function org-ref-get-cite-links "org-ref-export") + +(defun org-ref-cite-natmove (_backend) + "Move citations to the right side of punctuation. +Intended for use in `org-export-before-parsing-hook'. + +Here is an example use: + + (let ((org-export-before-parsing-hook '(org-ref-cite-natmove))) + (org-open-file (org-latex-export-to-pdf)))" + (let ((cites (org-ref-get-cite-links)) + punct) + (cl-loop for cite in (reverse cites) do + (goto-char (org-element-property :end cite)) + (skip-chars-backward " ") + (when (string-match-p "[[:punct:]]" (buffer-substring (point) (+ (point) 1))) + (setq punct (buffer-substring (point) (+ (point) 1))) + ;; delete the punctuation + (cl--set-buffer-substring (point) (+ (point) 1) "") + ;; and insert it at the beginning of the link. + (goto-char (org-element-property :begin cite)) + ;; delete spaces backward + (skip-chars-backward " ") + (cl--set-buffer-substring (point) (org-element-property :begin cite) "") + (insert punct))))) + +;; * Convert version 2 to version 3 + +(defun org-ref-v2-cites-to-v3 () + "Replace version 2 citation syntax with version 3 citation syntax" + (interactive) + (cl-loop for cite in (reverse (org-ref-get-cite-links)) + collect + (let ((data (org-ref-parse-cite-path (org-element-property :path cite))) + prefix-suffix) + (when (org-element-property :contents-begin cite) + (setq prefix-suffix (split-string (buffer-substring (org-element-property :contents-begin cite) + (org-element-property :contents-end cite)) + "::")) + (plist-put data :prefix (cl-first prefix-suffix)) + (plist-put data :suffix (cl-second prefix-suffix))) + (plist-put data :version 3) + (setf (buffer-substring (org-element-property :begin cite) + (org-element-property :end cite)) + (format "[[%s:%s]]" (org-element-property :type cite) + (org-ref-interpret-cite-data data)))))) + + +(provide 'org-ref-citation-links) + +;;; org-ref-citation-links.el ends here diff --git a/lisp/org-ref/org-ref-citeproc.el b/lisp/org-ref/org-ref-citeproc.el deleted file mode 100644 index 8dd4b270..00000000 --- a/lisp/org-ref/org-ref-citeproc.el +++ /dev/null @@ -1,919 +0,0 @@ -;;; readme.org --- org-ref-citeproc - Citation processor for org-mode -;;; Commentary: This code is style agnostic. It will get information from the -;;; information in `citation-style' and `bibliography-style'. These are defined -;;; in a csl.el file. -;; -;; Conventions: -;; an "entry" is the result of `bibtex-parse-entry'. -;; - -;;; Commentary: -;; - -(declare-function org-ref-get-bibtex-key-and-file "org-ref-core") -(declare-function org-ref-get-bibtex-keys "org-ref-core") -(declare-function parsebib-find-bibtex-dialect "parsebib") -(defvar org-export-current-backend) -(defvar org-ref-cite-types) - -(require 'org-element) - - - -;;; Code: -(defvar *orcp-citation-links* '() - "List of citation links in the text. -A link may have more than one citation in it. These links get -replaced by the new citation text.") - - -(defvar *orcp-unique-entries* '() - "List of unique (key . entry) parsed bibtex entries in the document. -The list is sorted according to the style. This list eventually -makes up the bibliography.") - - -(defvar citation-style '() - "Style data for an in-text citation. -For unsrt, a regular cite is superscripted, sorted, -range-collapsed numbers. - -LABEL is a function that is run to get the label. -PREFIX goes before a citation. -SUFFIX goes after a citation. -citations are separated by DELIMITER. -SORT specifies that 3, 1, 2 be converted to 1,2,3 -COLLAPSE is a function to collapse multiple citations, e.g. 1,2,3 becomes 1-3. -VERTICAL-ALIGN is a function that places the citation, e.g. -superscript, nil for baseline, etc... - -Additional entries provide overrides for special citation types.") - - -(defvar bibliography-style '() - "Bibliography style data. -SORT is a function that sorts the entries, e.g. by author, or -year, or nil. It should take one argument, the list of unique -entries (key . entry). - -LABEL is a function that returns how the entry is numbered, or -referenced in the text. - -HANGING-INDENT is for the indentation of the entry on the left. - -JUSTIFICATION is the overall justification on the right. - -SPACING is the number of lines between entries. - -HEADER is a string that is inserted above the bibliography. - -ENTRIES is a alist of entry type and fields to make the entry from.") - - -;;* Collect citations - -(defun orcp-collect-citations () - "Return a list of citation links in the document." - (setq *orcp-citation-links* - (cl-loop for link in (org-element-map - (org-element-parse-buffer) 'link 'identity) - if (-contains? - org-ref-cite-types - (org-element-property :type link)) - collect link))) - - -(defun orcp-key-to-entry (key) - "Return a parsed bibtex entry for KEY. -The KEY is found for the bibliography in the file." - (let* ((results (org-ref-get-bibtex-key-and-file key)) - (bibfile (cdr results))) - - (save-excursion - (with-temp-buffer - (insert-file-contents bibfile) - (bibtex-set-dialect (parsebib-find-bibtex-dialect) t) - (bibtex-search-entry key) - (let ((entry (bibtex-parse-entry t))) - (dolist (cons-cell entry) - (setf (car cons-cell) (downcase (car cons-cell)))) - (setf (cdr (assoc "=type=" entry)) - (downcase (cdr (assoc "=type=" entry)))) - entry))))) - - -(defun orcp-collect-unique-entries () - "Return a list of unique entries, sorted as required by the style. -Each entry is (key . entry)." - (let ((keys (org-ref-get-bibtex-keys)) - sort-func - entries) - (setq entries - (cl-loop for key in keys - collect (cons key (orcp-key-to-entry key)))) - ;; Now we should sort them if the style requires it - (setq sort-func (cdr (assoc 'sort bibliography-style))) - - (when sort-func - (setq entries (funcall sort-func entries))) - (setq *orcp-unique-entries* entries))) - - -;;** Unique entry sorting functions - -(defun orcp-sort-entries-increasing-year (unique-entries) - "Sort UNIQUE-ENTRIES in increasing year of publication. -i.e. oldest stuff first." - (sort unique-entries - (lambda (a b) - (let* ((e1 (cdr a)) - (e2 (cdr b)) - (year1 (string-to-number (cdr (assoc "year" e1)))) - (year2 (string-to-number (cdr (assoc "year" e2))))) - (> year2 year1))))) - -(defun orcp-sort-entries-decreasing-year (unique-entries) - "Sort UNIQUE-ENTRIES in decreasing year. -i.e. most current first." - (reverse (orcp-sort-entries-increasing-year unique-entries))) - -(defun orcp-get-entry-field (field entry) - "RETURN FIELD from ENTRY. -Strip extra spaces and carriage returns." - (let ((result (cdr (assoc field entry)))) - (when result - (while (string-match "[\n\t\r]\\|[ \t][ \t]+" result) - (setq result (replace-match " " nil t result)))) - result)) - - -(defun orcp-sort-entries-alphabetical (unique-entries) - "Sort UNIQUE-ENTRIES alphabetically by first author last name." - (sort unique-entries - (lambda (a b) - (let* ((e1 (cdr a)) - (e2 (cdr b)) - (authors1 (s-split - " and " - (orcp-get-entry-field "author" e1))) - (author1 (orcp-parse-authorname (car authors1))) - ;; lastname is "von last" - (last1 (concat (nth 1 author1) " " (nth 2 author1))) - (authors2 (s-split - " and " - (orcp-get-entry-field "author" e2))) - (author2 (orcp-parse-authorname (car authors2))) - (last2 (concat (nth 1 author2) " " (nth 2 author2)))) - (string-lessp last1 last2))))) - - -;;* Citation labels for one citation key -;; No styling is done here. - -(defun orcp-citation-number-label (key unique-entries) - "Find the numeric index of KEY in UNIQUE-ENTRIES and return as a string. -Indexing starts at 0 so we add one." - (number-to-string - (+ 1 - (-find-index - (lambda (entry) - (string= key (car entry))) - unique-entries)))) - - -(defun orcp-footnote-label (key unique-entries) - "Return an org footnote label for KEY in UNIQUE-ENTRIES." - (format "[fn:%s]" (orcp-citation-number-label key unique-entries))) - - -(defun orcp-citation-author-label (key unique-entries) - "Return an author last name label for KEY. -KEY is found in UNIQUE-ENTRIES." - (let* ((i (-find-index - (lambda (entry) - (string= key (car entry))) - unique-entries)) - (entry (cdr (nth i unique-entries))) - (authors (s-split - " and " - (orcp-get-entry-field "author" entry))) - (first-author (orcp-parse-authorname (car authors)))) - (format "%s" (concat (nth 1 first-author) - (nth 2 first-author))))) - -(defun orcp-citation-year-label (key unique-entries) - "Return a year label for KEY. -KEY is found in UNIQUE-ENTRIES." - (let* ((i (-find-index - (lambda (entry) - (string= key (car entry))) - unique-entries)) - (entry (cdr (nth i unique-entries))) - (year (orcp-get-entry-field "year" entry))) - (format "%s" year))) - - -(defun orcp-citation-author-year-label (key unique-entries) - "Return an author last name year label for KEY. -KEY is found in UNIQUE-ENTRIES. -We do not have a disambiguation strategy yet." - (let* ((i (-find-index - (lambda (entry) - (string= key (car entry))) - unique-entries)) - (entry (cdr (nth i unique-entries))) - (authors (s-split - " and " - (orcp-get-entry-field "author" entry))) - (first-author (orcp-parse-authorname (car authors))) - (year (orcp-get-entry-field "year" entry))) - (format "%s %s" (concat (nth 1 first-author) - (nth 2 first-author)) - year))) - -;;* Replacements for citation links - -;; Here we have to map over the keys in a citation, sort them according to the -;; style, get replacement labels, concat them together with the style delimiter, -;; add the prefix and suffix, and finally format for the type and output -;; backend. - -(defun orcp-get-citation-style (symbol type) - "Get the style info for SYMBOL for a citation TYPE from `citation-style'. -Styles have a default, but allow TYPE overrides. This function -returns the style with the override." - (let (style) - ;; first get default style - (setq style (cdr (assoc symbol citation-style))) - - ;; now check for an override - ;; we need to find the type, and the symbol in the type - (when (and (assoc type citation-style) - (assoc symbol (assoc type citation-style))) - (setq style (cdr (assoc symbol (assoc type citation-style))))) - style)) - - -(defun orcp-get-text-replacement (citation-link) - "Return replacement string for CITATION-LINK." - (let* ((type (intern (org-element-property :type citation-link))) - (path (org-element-property :path citation-link)) - (keys (s-split "," path)) - (entries (mapcar 'orcp-key-to-entry keys)) - (label-func (orcp-get-citation-style 'label type)) - (delimiter (orcp-get-citation-style 'delimiter type)) - (sort-func (orcp-get-citation-style 'sort type)) - labels - replacement-text) - - ;; sort is not coded yet. I am not sure the best data to sort here. the keys? - (when sort-func - (setq keys (sort keys sort-func))) - - ;; get labels. This function is where you would, for example, create - ;; hyperlinks to the bibliography. This function should return a list of - ;; strings - (setq labels - (mapcar - (lambda (key) - (funcall label-func key *orcp-unique-entries*)) - keys)) - - ;; collapse range - not used yet. - - ;; now get a string collecting everything - (setq labels (mapconcat 'identity labels delimiter)) - - (setq replacement-text (concat - (orcp-get-citation-style 'prefix type) - labels - (orcp-get-citation-style 'suffix type))) - - ;; finally, call formatter - (funcall (or (orcp-get-citation-style 'vertical-align type) - 'baseline) - replacement-text))) - - -(defun orcp-get-citation-replacements () - "Get a list of replacements for all links in `*orcp-citation-links*'." - (mapcar 'orcp-get-text-replacement *orcp-citation-links*)) - -;;* Formatted bibliography - -(defun orcp-formatted-bibliography () - "Return the formatted bibliography." - (let* ((spacing (or (cdr (assoc 'spacing bibliography-style)) 1)) - (label-func (cdr (assoc 'label bibliography-style))) - (label-prefix (cdr (assoc 'label-prefix bibliography-style))) - (label-suffix (cdr (assoc 'label-suffix bibliography-style))) - (justification (cdr (assoc 'justification bibliography-style))) - (hanging-indent (cdr (assoc 'hanging-indent bibliography-style))) - (header (cdr (assoc 'header bibliography-style))) - (unique-entries (orcp-collect-unique-entries)) - (adaptive-fill-function '(lambda () " ")) - (indent-tabs-mode nil) - bibliography-string) - - (setq bibliography-string - (mapconcat - 'identity - ;; loop over the entries in the bibliography - (cl-loop for entry in unique-entries - collect - (progn - (let* ((entry-type (downcase - (cdr (assoc "=type=" (cdr entry))))) - (key (cdr (assoc "=key=" (cdr entry)))) - (entry-styles (cdr (assoc 'entries bibliography-style))) - (entry-fields - (progn - (if (cdr (assoc (intern entry-type) entry-styles)) - (cdr (assoc (intern entry-type) entry-styles)) - (warn "%s not found. Using default." entry-type) - (cdr (assoc 't entry-styles)) - ))) - (funcs (mapcar - (lambda (field) - (if (fboundp (intern - (format "orcp-%s" field))) - (intern - (format "orcp-%s" field)) - ;; No formatter found. just get the data - `(lambda (entry) - (orcp-get-entry-field - ,(symbol-name field) entry)))) - entry-fields)) - (label (concat label-prefix - (funcall label-func key unique-entries) - label-suffix))) - - ;; this is the entry. We do this in a buffer to make it - ;; easy to indent, fill, etc... - (with-temp-buffer - (insert label) - (insert (mapconcat (lambda (field-func) - (funcall field-func entry)) - funcs - "")) - (goto-char (point-min)) - (forward-word) - ;; It doesn't make sense to do this for all formats, e.g.HTML. - ;; commenting out for now. - ;; (increase-left-margin - ;; (point-min) (point-max) hanging-indent) - ;; (fill-region (point-min) (point-max) justification) - (buffer-string))))) - ;; Here we put in the separator between entries - (cond - ;; placeholder for other formats - ((eq org-export-current-backend 'html) - " @@html:
@@\n") - (t - ;; put in a \n for each spacing - (mapconcat 'identity - (cl-loop for i to spacing - collect "\n") - ""))))) - ;; TODO: figure out header. how do we insert it properly formatted? - bibliography-string)) - -;;* Text formatting functions. - -;; These take text, and format them according to a backend. We derive the -;; backend from `org-export-current-backend' because I anticipate using this -;; during export. - -(defun baseline (text) - "Return TEXT." - text) - - -(defun superscript (text) - "Format TEXT as superscripted." - (cond - ((eq org-export-current-backend 'html) - (format "@@html:%s@@" text)) - ;; the catch-all case is org-syntax - (t - (format "^{%s}" text)))) - - -(defun italics (text) - "Format TEXT as italics." - (cond - ((eq org-export-current-backend 'html) - (format "@@html:%s@@" text)) - ;; the catch-all case is org-syntax - (t - (format "/%s/" text)))) - - -(defun bold (text) - "Format TEXT in bold." - (cond - ((eq org-export-current-backend 'html) - (format "@@html:%s@@" text)) - ;; the catch-all case is org-syntax - (t - (format "*%s*" text)))) - -;;* Field formatting functions - -;;These should be style agnostic functions. They take an entry and return a -;; formatted field for the entry, using information from the csl file. - -(defun firstname (author-cell) - "Return firstname from AUTHOR-CELL." - (car author-cell)) - - -(defun lastname (author-cell) - "Return lastname from AUTHOR-CELL." - (cdr author-cell)) - - -(defun orcp-author (entry) - "Return formatted author string from the ENTRY. -ENTRY is from `bibtex-parse-entry'. -Style information comes from `bibliography'" - (let* ((style (cdr (assoc 'author bibliography-style))) - (delimiter (cdr (assoc 'delimiter style))) - (name1 (nth 0 (cdr (assoc 'name-order style)))) - (name2 (nth 1 (cdr (assoc 'name-order style)))) - (name-separator (cdr (assoc 'name-separator style))) - (suffix (cdr (assoc 'suffix style))) - (field-separator (cdr (assoc 'field-separator style))) - (et-al (cdr (assoc 'et-al style))) - (authors (s-split - " and " - (or - (orcp-get-entry-field "author" entry) - ""))) - ;; parse to list of (first von last jr) - (author-data (mapcar - (lambda (x) - (let ((aud (orcp-parse-authorname x))) - (cons (nth 0 aud) - (concat - (or (nth 1 aud) "") - (or (nth 2 aud) "") - (or (nth 3 aud) ""))))) - authors)) - ;; map first and last names, in order specified in style with separator - (author-names - (mapcar - (lambda (x) - (concat - (funcall name1 x) - name-separator - (funcall name2 x))) - author-data))) - ;; check on et-al - not implemented yet - - ;; work on initialize - not implemented yet - - ;; mapconcat on delimiter then last author. - (if (= 1 (length author-names)) - (concat (car author-names) suffix field-separator) - (concat - (mapconcat - 'identity - (butlast author-names) - delimiter) - (cdr (assoc 'last-author-delimiter style)) - (car (last author-names)) - suffix - field-separator)))) - - -(defun orcp-title (entry) - "Return formatted title for the bibtex ENTRY." - (let* ((style (cdr (assoc 'title bibliography-style))) - (font-style (cdr (assoc 'font-style style))) - (suffix (cdr (assoc 'suffix style))) - (field-separator (cdr (assoc 'field-separator style))) - (title (orcp-get-entry-field "title" entry))) - - (concat - (if font-style - (funcall font-style title) - title) - suffix - field-separator))) - - -(defun orcp-journal (entry) - "Return formatted journal for the bibtex ENTRY." - (let* ((style (cdr (assoc 'journal bibliography-style))) - (font-style (cdr (assoc 'font-style style))) - (suffix (cdr (assoc 'suffix style))) - (field-separator (cdr (assoc 'field-separator style))) - (journal (orcp-get-entry-field "journal" entry))) - - (concat - (if font-style - (funcall font-style journal) - journal) - suffix - field-separator))) - - -(defun orcp-volume (entry) - "Return formatted volume for the bibtex ENTRY." - (let* ((style (cdr (assoc 'volume bibliography-style))) - (font-style (cdr (assoc 'font-style style))) - (prefix (cdr (assoc 'prefix style))) - (suffix (eval (cdr (assoc 'suffix style)))) - (field-separator (cdr (assoc 'field-separator style))) - (volume (orcp-get-entry-field "volume" entry))) - - (setq volume (concat prefix volume suffix)) - (concat - (if font-style - (funcall font-style volume) - volume) - field-separator))) - - -(defun orcp-issue (entry) - "Return formatted issue for the bibtex ENTRY." - (let* ((style (cdr (assoc 'issue bibliography-style))) - (font-style (cdr (assoc 'font-style style))) - (prefix (cdr (assoc 'prefix style))) - (suffix (cdr (assoc 'suffix style))) - (field-separator (cdr (assoc 'field-separator style))) - (issue (orcp-get-entry-field "number" entry))) - - ;; issue is optional and isn't always present. - (if (not issue) - field-separator - (setq issue (concat prefix issue suffix)) - (if font-style - (funcall font-style - issue) - issue)))) - - -(defun orcp-pages (entry) - "Return formatted pages for the bibtex ENTRY." - (let* ((style (cdr (assoc 'pages bibliography-style))) - (font-style (cdr (assoc 'font-style style))) - (prefix (cdr (assoc 'prefix style))) - (suffix (cdr (assoc 'suffix style))) - (field-separator (cdr (assoc 'field-separator style))) - (pages (orcp-get-entry-field "pages" entry))) - - (setq pages (concat prefix pages suffix)) - - ;; collapse-range not supported yet - (concat (if font-style - (funcall font-style - pages) - pages) - field-separator))) - - -(defun orcp-year (entry) - "Return formatted year for the bibtex ENTRY." - (let* ((style (cdr (assoc 'year bibliography-style))) - (font-style (cdr (assoc 'font-style style))) - (prefix (cdr (assoc 'prefix style))) - (suffix (cdr (assoc 'suffix style))) - (field-separator (cdr (assoc 'field-separator style))) - (year (orcp-get-entry-field "year" entry))) - - (setq year (concat prefix year suffix)) - - ;; collapse-range not supported yet - (concat - (if font-style - (funcall font-style - year) - year) - field-separator))) - - -(defun orcp-doi-formatter (doi) - "Return formatted DOI for different backends." - (cond - ((eq org-export-current-backend 'html) - (format "http://dx.doi.org/%s" doi)) - (t - (format "doi:%s" doi)))) - - -(defun orcp-doi (entry) - "Return formatted doi for the bibtex ENTRY." - (let* ((style (cdr (assoc 'doi bibliography-style))) - (font-style (cdr (assoc 'font-style style))) - (prefix (cdr (assoc 'prefix style))) - (suffix (cdr (assoc 'suffix style))) - (formatter (cdr (assoc 'formatter style))) - (doi (orcp-get-entry-field "doi" entry))) - - (when formatter - (setq doi (funcall formatter doi))) - (setq doi (concat prefix doi suffix)) - - (if font-style - (funcall font-style - (concat prefix doi suffix)) - doi))) - - -(defun orcp-url (entry) - "Return formatted url for the bibtex ENTRY." - (let* ((style (cdr (assoc 'doi bibliography-style))) - (font-style (cdr (assoc 'font-style style))) - (prefix (cdr (assoc 'prefix style))) - (suffix (cdr (assoc 'suffix style))) - (formatter (cdr (assoc 'formatter style))) - (url (orcp-get-entry-field "url" entry))) - - (when formatter - (setq url (funcall formatter url))) - (setq url (concat prefix url suffix)) - - (if font-style - (funcall font-style - (concat prefix url suffix)) - url))) - -;;* Data structures for Author names - -(defun orcp-unprotect-brackets (piece protected-strings) - "Unprotect PIECE with the information in PROTECTED-STRINGS. -PROTECTED-STRINGS is a list of cons-cells (\"protection\" . -original text)." - (when piece - (mapc - (lambda (cons-cell) - (when (string-match (car cons-cell) piece) - (setq piece (replace-match (cdr cons-cell) t t piece)))) - protected-strings)) - piece) - - -;; See http://maverick.inria.fr/~Xavier.Decoret/resources/xdkbibtex/bibtex_summary.html#names for the parsing rules. -(defun orcp-parse-authorname (name) - "Convert an author NAME to (first von last jr) data structure. -Valid name forms are: -First1 First2 Last -First1 First 2 {Last1 Last2} - -First1 First2 von1 von2 Last1 Last2 -von1 von2 Last1 Last2, Jr., First1 First2 - -Last1, First1 First2 -{Von Last1}, First1 First2 - -We try to protect strings in curly brackets." - (let* (protected-strings - uuid - ncommas - fields - first von last jr) - - ;; protect bracketed strings - (while (string-match "{\\(.*\\)}" name) - ;; We want our substitute to look like a name, not a von part so we add a - ;; capital letter to the front. - (setq uuid (concat "A" (md5 (format "%s%s%s%s%s%s%s" - (random) - (current-time) - (user-uid) - (emacs-pid) - (user-full-name) - user-mail-address - (recent-keys))))) - (add-to-list 'protected-strings (cons uuid (match-string 0 name))) - (setq name (replace-match uuid nil nil name))) - - (setq ncommas (s-count-matches "," name)) - - (cond - ;; "First von Last" - ((= 0 ncommas) - (setq fields (s-split " " name)) - (while (and (s-capitalized? (car fields)) (> (length fields) 1)) - (setq first (append first (list (pop fields))))) - (when first - (setq first (mapconcat 'identity first " "))) - - ;; Next, we get the von part. this is the longest white space delimited - ;; string that ends with a lowercase word, and is not the rest of the - ;; string. - (let ((last-lower-index nil)) - (cl-loop for i to (length fields) - for word in (butlast fields) - if (s-lowercase? word) - do (setq last-lower-index i)) - (when last-lower-index - (setq von (mapconcat - 'identity - (-slice fields 0 (+ 1 last-lower-index)) " ")) - (setq fields (-slice fields (+ 1 last-lower-index))))) - - ;; all that should be left is the last name but it might be more than one - ;; word, e.g. with a Jr. or a two work last name. - (setq last (mapconcat 'identity fields " ")) - (mapcar - (lambda (x) - (orcp-unprotect-brackets x protected-strings)) - (list first von last jr))) - - ;; "von Last, First" - ((= 1 ncommas) - (setq fields (s-split "," name)) - (setq first (nth 1 fields)) - ;; split first field which could be von Lastname. - (setq fields (s-split " " (car fields))) - (let ((last-lower-index nil)) - (cl-loop for i to (length fields) - for word in fields - if (s-lowercase? word) - do (setq last-lower-index i)) - (when last-lower-index - (setq von (mapconcat - 'identity - (-slice fields 0 (+ 1 last-lower-index)) " ")) - (setq fields (-slice fields (+ 1 last-lower-index))))) - ;; all that should be left is the last name - (setq last (mapconcat 'identity fields " ")) - (mapcar - (lambda (x) - (orcp-unprotect-brackets x protected-strings)) - (list first von last jr))) - - ;; "von Last, Jr, First" - ((= 2 ncommas) - (setq fields (s-split "," name)) - (setq first (nth 2 fields)) - (setq jr (nth 1 fields)) - ;; split first field which could be von Lastname. - (setq fields (s-split " " (car fields))) - (let ((last-lower-index nil)) - (cl-loop for i to (length fields) - for word in fields - if (s-lowercase? word) - do (setq last-lower-index i)) - (when last-lower-index - (setq von (mapconcat 'identity (-slice fields 0 (+ 1 last-lower-index)) " ")) - (setq fields (-slice fields (+ 1 last-lower-index))))) - ;; all that should be left is the last name - (setq last (mapconcat 'identity fields " ")) - (mapcar - (lambda (x) - (orcp-unprotect-brackets x protected-strings)) - (list first von last jr)))))) - - -;;* Collapse numeric range - -(defun orcp-collapse-numeric-range (cites delimiter) - "TODO use style info. -Collapse a numeric list of CITES into a range. -Collapsed ranges are separated by DELIMITER." - (let (n - (groups '())) - (while cites - (setq n (pop cites)) - (if (and (caar groups) (= (- n 1) (elt (car groups) 0))) - (setf (car groups) (append `(,n) (car groups))) - (setf groups (append `((,n)) groups)))) - ;; Now for each group - (mapconcat 'identity - (mapcar - (lambda (lst) - (cond - ((>= (length lst) 3) - (format "%s-%s" (car lst) (car (last lst)))) - ((= (length lst) 2) - (format "%s,%s" (nth 0 lst) (nth 1 lst))) - (t - (number-to-string (car lst))))) - (mapcar 'reverse (reverse groups))) - delimiter))) - - -;;* Putting it all together - -(defun sentence-beginning-p () - "Determine if point is at the beginning of a sentence. -The idea is to move forward a sentence, then back. If the point -doesn't move, it means you were at the beginning of a sentence." - (let ((cp (point))) - (save-excursion - (forward-sentence) - (backward-sentence) - (= cp (point))))) - - -(defun orcp-citeproc (&optional backend) - "Format citations and bibliography for BACKEND. -Warning. Destructive to your document! Will replace links. -Meant to be used in export on a temporary version of the -documents." - - ;; Get the style from bibliographystyle link - ;; and eliminate bibliography style links - ;; This will load all style modules - (cl-loop for link in (org-element-map - (org-element-parse-buffer) 'link 'identity) - if (string= "bibliographystyle" - (org-element-property :type link)) - do - ;; get path for style and load it - (load-library (org-element-property :path link)) - ;; get rid of the link in the buffer - (setf (buffer-substring (org-element-property :begin link) - (org-element-property :end link)) - "")) - - (orcp-collect-citations) - (orcp-collect-unique-entries) - - (let ((link-replacements (cl-loop for link in *orcp-citation-links* - for repl in (orcp-get-citation-replacements) - collect - (list repl - (org-element-property :begin link) - (org-element-property :end link)))) - (bibliography-string (orcp-formatted-bibliography)) - punctuation - trailing-space - bibliography-link) - - ;; replace citation links - (cl-loop for (repl start end) in (reverse link-replacements) - for link in (reverse *orcp-citation-links*) - do - ;; chomp leading spaces if needed - (when (orcp-get-citation-style - 'chomp-leading-space - (intern (org-element-property :type link))) - (goto-char start) - (while (and (not (sentence-beginning-p)) - (looking-back " " (- (point) 2))) - (delete-char -1) - (setq start (- start 1)) - (setq end (- end 1)))) - - ;; chomp trailing spaces if needed - (when (orcp-get-citation-style - 'chomp-trailing-space - (intern (org-element-property :type link))) - (goto-char end) - (while (looking-back " " (- (point) 2)) - (delete-char 1))) - - ;; Check for transposing punctuation - (setq punctuation nil) - (when (orcp-get-citation-style - 'transpose-punctuation - (intern (org-element-property :type link))) - ;; goto end of link - (goto-char end) - (when (looking-at "\\.\\|,\\|;") - (setq punctuation (buffer-substring end (+ 1 end))) - (delete-char 1))) - - ;; preserve trailing space - (goto-char end) - (setq trailing-space (if (looking-back " " (line-beginning-position)) " " "")) - - (setf (buffer-substring start end) (concat repl trailing-space)) - - (when punctuation - (goto-char start) - ;; I can't figure out why this is necessary. I would have thought - ;; the chomp leading spaces would get it. - (when (thing-at-point 'whitespace) - (delete-char -1)) - (insert punctuation))) - - ;; Insert bibliography section at the bibliography link - (setq bibliography-link (cl-loop for link - in (org-element-map - (org-element-parse-buffer) - 'link 'identity) - if (string= "bibliography" - (org-element-property :type link)) - collect link)) - (pcase (length bibliography-link) - ((pred (< 1)) (error "Only one bibliography link allowed")) - ((pred (= 1)) - ;; replace bibliography link - (setq bibliography-link (car bibliography-link)) - (setf (buffer-substring (org-element-property :begin bibliography-link) - (org-element-property :end bibliography-link)) - bibliography-string)) - ((pred (= 0)) - ;; no bibliography link in document - (when link-replacements - (message "Warning: No bibliography link found although there are citations to process")))))) - -;; * the end -(provide 'org-ref-citeproc) -;;; org-ref-citeproc.el ends here diff --git a/lisp/org-ref/org-ref-core.el b/lisp/org-ref/org-ref-core.el index 05cb7779..ebf15283 100644 --- a/lisp/org-ref/org-ref-core.el +++ b/lisp/org-ref/org-ref-core.el @@ -1,6 +1,6 @@ -;;; org-ref-core.el --- citations, cross-references and bibliographies in org-mode +;;; org-ref-core.el --- citations, cross-references and bibliographies in org-mode -*- lexical-binding: t; -*- -;; Copyright(C) 2014-2017 John Kitchin +;; Copyright(C) 2014-2021 John Kitchin ;; This file is not currently part of GNU Emacs. @@ -21,125 +21,48 @@ ;;; Commentary: ;; -;; Lisp code to setup bibliography, cite, ref and label org-mode links. -;; Also sets up reftex and helm for org-mode citations. The links are -;; clickable and do things that are useful. You should really read -;; org-ref.org in this package for details. +;; This is the core library. ;; ;;; Code: + (eval-when-compile (require 'cl-lib)) + +(require 'org) +;; the eval and compile seems especially necessary for native compilation on the newest Emacs. +(eval-and-compile (require 'org-macs)) + +(require 'org-element) + (require 'dash) (require 'f) -(require 'htmlize) (require 's) -(require 'doi-utils) -(require 'seq) -(add-to-list 'load-path - (expand-file-name - "citeproc" - (file-name-directory (or load-file-name (buffer-file-name))))) - -(add-to-list 'load-path - (expand-file-name - "citeproc/csl" - (file-name-directory (or load-file-name (buffer-file-name))))) - -(require 'org-ref-bibtex) -(require 'org-ref-utils) -(require 'org-ref-glossary) -(require 'org) -(require 'org-element) -(require 'ox) (require 'parsebib) -(require 'reftex-cite) +(require 'bibtex-completion) +(require 'hydra) -(defvar org-export-exclude-tags) -(defvar warning-suppress-types) -(declare-function bibtex-completion-get-entry "bibtex-completion") -(declare-function bibtex-completion-edit-notes "bibtex-completion") +(require 'org-ref-bibliography-links) +(require 'org-ref-citation-links) +(require 'org-ref-ref-links) +(require 'org-ref-label-link) +(require 'org-ref-misc-links) +(require 'org-ref-export) + +(require 'org-ref-utils) +(require 'org-ref-bibtex) +(require 'org-ref-glossary) ;;* Custom variables + (defgroup org-ref nil "Customization group for org-ref." :tag "Org Ref" :group 'org) -(defcustom org-ref-bibliography-notes - nil - "Filename where you will put all your notes about an entry in the default bibliography. -Used by backends that append all notes as entries in a single file. - -See also `org-ref-notes-function'" - :type '(choice (const nil) - (file)) - :group 'org-ref) - - -(defcustom org-ref-notes-directory - nil - "Directory where you will put all your notes about an entry in the default bibliography. -Used for backends that create a single file of notes per entry. - -See also `org-ref-notes-function'." - :type 'directory - :group 'org-ref) - - -(defcustom org-ref-default-bibliography - nil - "List of bibtex files to search for. -You should use full-paths for each file. Note that you must -include a bibliography link in your document if you will be -exporting it to pdf; org-ref-default-bibliography is not -used by the LaTeX exporter." - :type '(repeat :tag "List of bibtex files" file) - :group 'org-ref) - - -(defcustom org-ref-pdf-directory - nil - "Directory where pdfs are stored by key. -Put a trailing / in the name." - :type '(choice directory (repeat directory)) - :group 'org-ref) - - -(defcustom org-ref-default-citation-link - "cite" - "The default type of citation link to use." - :type 'string - :group 'org-ref) - - -(defcustom org-ref-insert-cite-key - "C-c ]" - "Keyboard shortcut to insert a citation." - :type 'string - :group 'org-ref) - - -(defcustom org-ref-completion-library - 'org-ref-helm-bibtex - "Symbol for library to define completion functions. -The completion library should provide functions for -`org-ref-insert-link-function', `org-ref-insert-cite-function', -`org-ref-insert-label-function', `org-ref-insert-ref-function', -and `org-ref-cite-onclick-function', and set those variables to -the values of those functions." - :type 'symbol - :options '(org-ref-helm-bibtex ; completion with helm + helm-bibtex - org-ref-helm-cite ; completion with helm in org-ref - org-ref-ivy-cite ; completion with ivy - org-ref-reftex ; org-completion - ) - :group 'org-ref) - - (defcustom org-ref-insert-link-function nil "Generic function for inserting org-ref links. @@ -160,12 +83,6 @@ the citation link into the buffer." :group 'org-ref) -(defcustom org-ref-prefer-bracket-links nil - "If non-nil use bracketed links when inserting them." - :type 'boolean - :group 'org-ref) - - (defcustom org-ref-cite-completion-function nil "Function to prompt for keys with completion." @@ -196,2181 +113,67 @@ insert the ref link." nil "Function that runs when you click on a cite link. The function must take one argument which is the path of the link -that was clicked on. This function is normally set by the -function in `org-ref-completion-library'." +that was clicked on." :type 'function :group 'org-ref) -;; define key for inserting citations -(define-key org-mode-map - (kbd org-ref-insert-cite-key) - org-ref-insert-link-function) +(defvar org-ref-prefix-arg nil + "Variable to store a prefix arg during completion.") -(defcustom org-ref-cite-keymap - (let ((map (copy-keymap org-mouse-map))) - (define-key map (kbd "H-o") 'org-ref-cite-hydra/body) - (define-key map (kbd "H-b") 'org-ref-open-citation-at-point) - (define-key map (kbd "H-u") 'org-ref-open-url-at-point) - (define-key map (kbd "H-p") 'org-ref-open-pdf-at-point) - (define-key map (kbd "H-n") 'org-ref-open-notes-at-point) - (define-key map (kbd "H-r") 'org-ref-wos-related-at-point) - (define-key map (kbd "H-c") 'org-ref-wos-citing-at-point) - (define-key map (kbd "H-e") (lambda () - "Email entry at point" - (interactive) - (org-ref-open-citation-at-point) - (org-ref-email-bibtex-entry))) - (define-key map (kbd "H-g") 'org-ref-google-scholar-at-point) - (define-key map (kbd "H-f") (lambda () - (interactive) - (save-excursion - (org-ref-open-citation-at-point) - (kill-new - (org-ref-format-bibtex-entry-at-point))))) - (define-key map (kbd "H-w") (lambda () - (interactive) - (kill-new (car (org-ref-get-bibtex-key-and-file))))) - (define-key map (kbd "H-W") (lambda () - "Copy all the keys at point." - (interactive) - (kill-new (org-element-property :path (org-element-context))))) - (define-key map (kbd "H-y") (lambda () - "Paste key at point. Assumes the first thing in the killring is a key." - (interactive) - (org-ref-insert-key-at-point (car kill-ring)))) +(defun org-ref-minibuffer-prefix () + "Hook function for `minibuffer-setup-hook'. +The idea is to locally bind C-u to a function that captures +prefix args in `org-ref-prefix-arg' so you can use them later." + (setq org-ref-prefix-arg nil) + (local-set-key (kbd "C-u") (lambda () + (interactive) + (setq org-ref-prefix-arg + (if (null org-ref-prefix-arg) + '(4) + (list (* 4 (car org-ref-prefix-arg)))))))) - ;; Navigation keys - (define-key map (kbd "C-") 'org-ref-previous-key) - (define-key map (kbd "C-") 'org-ref-next-key) - - ;; rearrangement keys - (define-key map (kbd "S-") (lambda () (interactive) (org-ref-swap-citation-link -1))) - (define-key map (kbd "S-") (lambda () (interactive) (org-ref-swap-citation-link 1))) - (define-key map (kbd "S-") 'org-ref-sort-citation-link) - (define-key map (kbd "") (lambda () (interactive) - (funcall org-ref-insert-cite-function))) - map) - "Keymap for cite links." - :type 'symbol - :group 'org-ref) - - -(defcustom org-ref-bibliography-entry-format - '(("article" . "%a, %t, %j, %v(%n), %p (%y). link. doi.") - - ("book" . "%a, %t, %u (%y).") - ("techreport" . "%a, %t, %i, %u (%y).") - ("proceedings" . "%e, %t in %S, %u (%y).") - ("inproceedings" . "%a, %t, %p, in %b, edited by %e, %u (%y)")) - "String to format an entry. -Just the reference, no numbering at the beginning, etc... see the -`org-ref-reftex-format-citation' docstring for the escape codes." - :type '(alist :key-type (string) :value-type (string)) - :group 'org-ref) - - -(defcustom org-ref-note-title-format - "** TODO %y - %t - :PROPERTIES: - :CUSTOM_ID: %k - :AUTHOR: %9a - :JOURNAL: %j - :YEAR: %y - :VOLUME: %v - :PAGES: %p - :DOI: %D - :URL: %U - :END: - -" - "String to format the title and properties drawer of a note. -See the `org-ref-reftex-format-citation' docstring for the escape -codes." - :type 'string - :group 'org-ref) - - -(defcustom org-ref-ref-html "%s" - "HTML code to represent a reference." - :type 'string - :group 'org-ref) - - -(defcustom org-ref-notes-function #'org-ref-notes-function-one-file - "Function to open the notes for the bibtex key in a cite link at point. - -The default behavior adds entries to a long file with headlines -for each entry. It also tries to be compatible with `org-bibtex'. - -An alternative is `org-ref-notes-function-many-files'. Use that -if you prefer the `bibtex-completion' approach, which also -supports an additional method for storing notes. See -`bibtex-completion-notes-path' for more information. You may also -want to set `org-ref-notes-directory'." - :type 'function - :group 'org-ref) - - -(defcustom org-ref-open-notes-function - (lambda () - (org-show-entry) - (outline-show-branches) - (outline-show-children) - (org-cycle '(64)) - (recenter-top-bottom 0)) - "User-defined way to open a notes entry. -This is executed after the entry is found in -`org-ref-open-bibtex-notes', with the cursor at the beginning of -the headline. The default setting fully expands the notes, and -moves the headline to the top of the buffer." - :type 'function - :group 'org-ref) - - -(defcustom org-ref-create-notes-hook - '((lambda () - (org-narrow-to-subtree) - (insert (format "cite:%s\n" (org-entry-get (point) "CUSTOM_ID"))))) - "List of hook functions to run in the note entry after it is created. -The function takes no arguments. It could be used to insert links -to the citation, or pdf, etc..." - :type 'hook - :group 'org-ref) - - -(defcustom org-ref-open-pdf-function - 'org-ref-open-pdf-at-point - "User-defined function to open a pdf from a link. -The function must get the key at point, and derive a path to the pdf -file, then open it. The default function is -`org-ref-open-pdf-at-point'." - :type 'function - :group 'org-ref) - - -(defcustom org-ref-get-pdf-filename-function - 'org-ref-get-pdf-filename - "User-defined function to get a filename from a bibtex key. -The function must take a key as an argument, and return the path -to the corresponding filename. The default is -`org-ref-get-pdf-filename'. Alternative values are -`org-ref-get-mendeley-filename' or -`org-ref-get-pdf-filename-helm-bibtex'." - :type 'function - :group 'org-ref) - - -(defcustom org-ref-clean-bibtex-key-function - (lambda (key) - (replace-regexp-in-string ":" "" key)) - "Function to modify a bibtex key. -The default behavior is to remove : from the key." - :type 'function - :group 'org-ref) - - -(defcustom org-ref-show-citation-on-enter t - "If non-nil show the citation summary. -Uses a hook function to display the message in the minibuffer." - :type 'boolean - :group 'org-ref) - - -(defcustom org-ref-natbib-types - '("citet" "citet*" "citep" "citep*" - "citealt" "citealt*" "citealp" "citealp*" - "citenum" "citetext" - "citeauthor" "citeauthor*" - "citeyear" "citeyear*" "citeyearpar" - "Citet" "Citep" "Citealt" "Citealp" "Citeauthor") - "natbib cite commands, http://tug.ctan.org/macros/latex/contrib/natbib/natnotes.pdf" - :type '(repeat :tag "List of citation types" string) - :group 'org-ref) - - -(defcustom org-ref-biblatex-types - '("Cite" - "parencite" "Parencite" - "footcite" "footcitetext" - "textcite" "Textcite" - "smartcite" "Smartcite" - "cite*" "parencite*" "supercite" - "autocite" "Autocite" "autocite*" "Autocite*" - "Citeauthor*" - "citetitle" "citetitle*" - "citedate" "citedate*" - "citeurl" - "fullcite" "footfullcite" - ;; "volcite" "Volcite" cannot support the syntax - "notecite" "Notecite" - "pnotecite" "Pnotecite" - "fnotecite" - ;; multicites. Very limited support for these. - "cites" "Cites" "parencites" "Parencites" - "footcites" "footcitetexts" - "smartcites" "Smartcites" "textcites" "Textcites" - "supercites" "autocites" "Autocites") - "biblatex commands -http://ctan.mirrorcatalogs.com/macros/latex/contrib/biblatex/doc/biblatex.pdf" - :type '(repeat :tag "List of citation types" string) - :group 'org-ref) - - -(defcustom org-ref-cite-types - (append - '("cite" "nocite") ;; the default latex cite commands - org-ref-natbib-types - org-ref-biblatex-types - ;; for the bibentry package - '("bibentry")) - "List of citation types known in `org-ref'." - :type '(repeat :tag "List of citation types" string) - :group 'org-ref) - - -(defcustom org-ref-ref-types - '("ref" "eqref" "pageref" "nameref" "autoref" "cref" "Cref") - "List of ref link types." - :type '(repeat :tag "List of ref types" string) - :group 'org-ref) - - -(defcustom org-ref-default-ref-type "ref" - "Default ref link type to use when inserting ref links" - :type 'string - :group 'org-ref) - - -(defcustom org-ref-clean-bibtex-entry-hook - '(org-ref-bibtex-format-url-if-doi - orcb-key-comma - org-ref-replace-nonascii - orcb-& - orcb-% - org-ref-title-case-article - orcb-clean-year - orcb-key - orcb-clean-doi - orcb-clean-pages - orcb-check-journal - org-ref-sort-bibtex-entry - orcb-fix-spacing) - "Hook that is run in `org-ref-clean-bibtex-entry'. -The functions should have no arguments, and -operate on the bibtex entry at point. You can assume point starts -at the beginning of the entry. These functions are wrapped in -`save-restriction' and `save-excursion' so you do not need to -save the point position. - -Org ref contains some functions that are not included by default -such as `orcb-clean-nil' or `orcb-clean-nil-opinionated' that -users may be interested in adding themselves." - :group 'org-ref - :type 'hook) - - -(defcustom org-ref-bibtex-sort-order - '(("article" . ("author" "title" "journal" "volume" "number" "pages" "year" "doi" "url")) - ("inproceedings" . ("author" "title" "booktitle" "year" "volume" "number" "pages" "doi" "url")) - ("book" . ("author" "title" "year" "publisher" "url"))) - "A-list of bibtex entry fields and the order to sort an entry with. -\(entry-type . (list of fields). This is used in -`org-ref-sort-bibtex-entry'. Entry types not listed here will -have fields sorted alphabetically." - :type '(alist :key-type (string) :value-type (repeat string)) - :group 'org-ref) - - -(defcustom org-ref-printbibliography-cmd "\\printbibliography" - "LaTeX command to print bibliography. Customize this to add options." - :type 'string - :group 'org-ref) - - -(defvar org-ref-bibliography-files - nil - "Variable to hold bibliography files to be searched.") - - -(defcustom org-ref-show-broken-links t - "If non-nil show bad org-ref links in a warning face." - :type 'boolean - :group 'org-ref) - - -(defcustom org-ref-enable-colon-insert nil - "If non-nil enable colon to insert cites, labels, and ref links." - :type 'booleanp - :group 'org-ref) - - -(defcustom org-ref-label-use-font-lock t - "If non-nil use font-lock to find labels in the buffer. -If nil, each time you ask for labels the whole buffer will be -searched, which may be slower.") - - -(defun org-ref-colon-insert-link (arg) - "Function to run when : has a special meaning. -See `org-ref-enable-colon-insert'." - (interactive "P") - (insert ":") - (cond - ;; cite links - ((save-excursion - (backward-word 1) - (looking-at (regexp-opt org-ref-cite-types))) - (funcall org-ref-insert-cite-function)) - ((save-excursion - (backward-word 1) - (looking-at "label:")) - (funcall org-ref-insert-label-function)) - ((save-excursion - (backward-word 1) - (looking-at (regexp-opt org-ref-ref-types))) - (funcall org-ref-insert-ref-function)))) - - -(when org-ref-enable-colon-insert - (define-key org-mode-map ":" - '(menu-item "maybe-cite" nil - :filter (lambda (&optional _) - (unless (org-in-src-block-p) - #'org-ref-colon-insert-link))))) - - -(defun org-ref-change-cite-type (new-type) - "Change the cite type to NEW-TYPE." - (interactive (list (completing-read "Type: " org-ref-cite-types))) - (let* ((cite-link (org-element-context)) - (old-type (org-element-property :type cite-link)) - (begin (org-element-property :begin cite-link)) - (end (org-element-property :end cite-link)) - (bracketp (eq 'bracket (org-element-property :format cite-link))) - (path (org-element-property :path cite-link)) - (deltap (- (point) begin))) - ;; note this does not respect brackets - (setf (buffer-substring begin end) - (concat - (if bracketp "[[" "") - new-type ":" path - (if bracketp "]]" ""))) - ;; try to preserve the character the point is on. - (goto-char (+ begin deltap (- (length new-type) (length old-type)))))) - - - -(defun org-ref-change-ref-type (new-type) - "Change the ref type to NEW-TYPE." - (interactive (list (completing-read "Type: " org-ref-ref-types))) - (let* ((cite-link (org-element-context)) - (old-type (org-element-property :type cite-link)) - (begin (org-element-property :begin cite-link)) - (end (org-element-property :end cite-link)) - (bracketp (eq 'bracket (org-element-property :format cite-link))) - (path (org-element-property :path cite-link)) - (deltap (- (point) begin))) - ;; note this does not respect brackets - (setf (buffer-substring begin end) - (concat - (if bracketp "[[" "") - new-type ":" path - (if bracketp "]]" ""))) - ;; try to preserve the character the point is on. - (goto-char (+ begin deltap (- (length new-type) (length old-type)))))) - - -;;* Messages for link at cursor - -(defvar org-ref-message-timer nil - "Variable to store the link message timer in.") - - -;;;###autoload -(defun org-ref-show-link-messages () - "Turn on link messages. -You will see a message in the minibuffer when on a cite, ref or -label link." - (interactive) - (or org-ref-message-timer - (setq org-ref-message-timer - (run-with-idle-timer 0.5 t 'org-ref-link-message) - org-ref-show-citation-on-enter t))) - - -;;;###autoload -(defun org-ref-cancel-link-messages () - "Stop showing messages in minibuffer when on a link." - (interactive) - (cancel-timer org-ref-message-timer) - (setq org-ref-message-timer nil - org-ref-show-citation-on-enter nil)) - - -(when org-ref-show-citation-on-enter - (org-ref-show-link-messages)) - - -;;;###autoload -(defun org-ref-change-completion () - "Change the completion backend. -Options are \"org-ref-helm-bibtex\", \"org-ref-helm-cite\", -\"org-ref-ivy-cite\" and \"org-ref-reftex\"." - (interactive) - (require - (intern - (completing-read "Backend: " '("org-ref-helm-bibtex" - "org-ref-helm-cite" - "org-ref-ivy-cite" - "org-ref-reftex") - nil - t - "org-ref-helm-cite")))) - -;;** Messages for context under mouse pointer - -(defvar org-ref-last-mouse-pos nil - "Stores last mouse position for use in `org-ref-mouse-message'.") - - -(defun org-ref-can-move-p () - "See if a character is under the mouse. -If so return the position for `goto-char'." - (let* ((line (cddr org-ref-last-mouse-pos)) - (col (cadr org-ref-last-mouse-pos))) - (save-excursion - (goto-char (window-start)) - (forward-line line) - (if - (> (- (line-end-position) (line-beginning-position)) col) - (progn (forward-char col) (point)) - nil)))) - - -;;;###autoload -(defun org-ref-mouse-message () - "Display message for link under mouse cursor." - (interactive) - (when (not (equal (mouse-position) org-ref-last-mouse-pos)) - (setq org-ref-last-mouse-pos (mouse-position)) - (let ((p (org-ref-can-move-p))) - (when p - (save-excursion - (goto-char p) - (org-ref-link-message)))))) - - -(defvar org-ref-message-timer-mouse nil - "Store mouse timer.") - - -(defvar org-ref-mouse-message-interval 0.5 - "How often to run the mouse message timer in seconds.") - - -;;;###autoload -(defun org-ref-mouse-messages-on () - "Turn on mouse messages." - (interactive) - (or org-ref-message-timer-mouse - (setq org-ref-message-timer-mouse - (run-at-time "0.5 sec" - org-ref-mouse-message-interval - 'org-ref-mouse-message)))) - - -;;;###autoload -(defun org-ref-mouse-messages-off () - "Turn off mouse messages." - (interactive) - (cancel-timer org-ref-message-timer-mouse) - (setq org-ref-message-timer-mouse nil) - (message "Mouse messages are off")) - - - -;;* font lock for org-ref - -(defcustom org-ref-colorize-links - t - "When non-nil, change colors of links." - :type 'boolean - :group 'org-ref) - - -(defcustom org-ref-cite-color - "forest green" - "Color of cite like links." - :type 'string - :group 'org-ref) - - -(defcustom org-ref-ref-color - "dark red" - "Color of ref like links." - :type 'string - :group 'org-ref) - - -(defcustom org-ref-label-color - "dark magenta" - "Color of label links." - :type 'string - :group 'org-ref) - -(defcustom org-ref-latex-bib-resolve-func #'file-relative-name - "used to expand paths to the bibliography file on latex export." - :type 'function - :group 'org-ref) - -(defvar org-ref-cite-re - (concat "\\(" (mapconcat - (lambda (x) - (replace-regexp-in-string "\\*" "\\\\*" x)) - org-ref-cite-types "\\|") "\\):" - "\\([a-zA-Z0-9_:\\./-]+,?\\)+") - "Regexp for cite links. -Group 1 contains the cite type. -Group 2 contains the keys.") - - -(defvar org-ref-label-re - "label:\\([a-zA-Z0-9_:-]+,?\\)+" - "Regexp for label links.") - - -(defvar org-ref-ref-re - "\\(eq\\)?ref:\\([a-zA-Z0-9_:-]+,?\\)+" - "Regexp for ref links.") - - -(defface org-ref-cite-face - `((t (:inherit org-link - :foreground ,org-ref-cite-color))) - "Color for cite-like links in org-ref.") - - -(defface org-ref-label-face - `((t (:inherit org-link :foreground ,org-ref-label-color))) - "Color for ref links in org-ref.") - - -(defface org-ref-ref-face - `((t (:inherit org-link :foreground ,org-ref-ref-color))) - "Face for ref links in org-ref.") - - -;;** Font-lock org-ref links - -;; We use functions to search for the next link, and then use org-mode to find -;; the boundaries. I wasn't able to figure out robust regexps for these links -;; that includes all possible link syntaxes eg. bare, [[cite:key]] and -;; [[cite:key] [text]]. Using regexps might be a bit more efficient, so if they -;; ever get figured out, we could eliminate the org-element code in these -;; functions. - -;; These functions are not used with org-9. I define them here to make -;; byte-compiling quiet. -(defun org-ref-match-next-cite-link (_) nil) -(defun org-ref-match-next-label-link (_) nil) -(defun org-ref-match-next-ref-link (_) nil) -(defun org-ref-make-org-link-cite-key-visible (_) nil) - -(when (not (fboundp 'org-link-set-parameters)) - - (defun org-ref-match-next-cite-link (&optional limit) - "Search forward to next cite link up to LIMIT -Add a tooltip to the match." - (when (and (re-search-forward org-ref-cite-re limit t) - (not (org-in-src-block-p)) - (not (org-at-comment-p))) - ;; we think we are on a cite link lets get on it and make sure - (forward-char -2) - (let ((this-link (org-element-context))) - (if (-contains? org-ref-cite-types (org-element-property :type this-link)) - ;; we are on a cite link - (progn - (when org-ref-show-citation-on-enter - (add-text-properties - (org-element-property :begin this-link) - (- (org-element-property :end this-link) - (org-element-property :post-blank this-link)) - (list - 'help-echo (lambda (window object position) - (save-excursion - (goto-char position) - ;; Here we wrap the citation string to a reasonable size. - (let ((s (org-ref-format-entry - (org-ref-get-bibtex-key-under-cursor)))) - (with-temp-buffer - (insert s) - (fill-paragraph) - (buffer-string)))))))) - (set-match-data - (list (org-element-property :begin this-link) - (- (org-element-property :end this-link) - (org-element-property :post-blank this-link)))) - (goto-char (org-element-property :end this-link))) - ;; Must be a false match. - ;; somehow were not on a - ;; cite link, so we try - ;; again. - (org-ref-match-next-cite-link limit))))) - - - (defun org-ref-match-next-label-link (limit) - "Find next label link up to LIMIT. -Add tooltip." - (if (and (re-search-forward "label:\\([[:alnum:]]\\)\\{2,\\}" limit t) - (not (org-in-src-block-p)) - (not (org-at-comment-p))) - (progn - (forward-char -2) - (let ((this-link (org-element-context))) - (if (string= "label" (org-element-property :type this-link)) - ;; on a label - (progn - (add-text-properties - (org-element-property :begin this-link) - (- (org-element-property :end this-link) - (org-element-property :post-blank this-link)) - (list - 'help-echo (lambda (window object position) - (save-excursion - (goto-char position) - (let ((s (org-ref-link-message))) - (with-temp-buffer - (insert s) - (fill-paragraph) - (buffer-string))))))) - (set-match-data - (list (org-element-property :begin this-link) - (- (org-element-property :end this-link) - (org-element-property :post-blank this-link)))) - (goto-char (org-element-property :end this-link))) - ;; false match - (org-ref-match-next-label-link limit)))))) - - - (defun org-ref-match-next-ref-link (limit) - "Find next ref link up to LIMIT. -Add tooltip to the link. We avoid tags by not finding :ref: in -tags." - (when (and (re-search-forward "[^:]\\(eq\\)?ref:\\([[:alnum:]]\\)\\{2,\\}" limit t) - (not (org-in-src-block-p)) - (not (org-at-comment-p))) - ;; we think we are on a ref link, lets make sure. - (forward-char -2) - (let ((this-link (org-element-context))) - (if (-contains? org-ref-ref-types - (org-element-property :type this-link)) - ;; we are, so we do our business - (progn - (add-text-properties - (org-element-property :begin this-link) - (- (org-element-property :end this-link) - (org-element-property :post-blank this-link)) - (list - 'help-echo (lambda (window object position) - (save-excursion - (goto-char position) - (let ((s (org-ref-link-message))) - (with-temp-buffer - (insert s) - (fill-paragraph) - (buffer-string))))))) - (set-match-data - (list (org-element-property :begin this-link) - (- (org-element-property :end this-link) - (org-element-property :post-blank this-link)))) - (goto-char (org-element-property :end this-link))) - ;; False match, let's try again - (org-ref-match-next-ref-link limit))))) - - - (defun org-ref-match-next-bibliography-link (limit) - "Find next bibliography link up to LIMIT. -Add tooltip to the link." - (when (and (re-search-forward "bibliography:\\([[:alnum:]]\\)\\{2,\\}" limit t) - (not (org-in-src-block-p)) - (not (org-at-comment-p))) - (forward-char -2) - (let ((this-link (org-element-context))) - (add-text-properties - (org-element-property :begin this-link) - (- (org-element-property :end this-link) - (org-element-property :post-blank this-link)) - (list - 'help-echo (lambda (window object position) - (save-excursion - (goto-char position) - (let ((s (org-ref-link-message))) - (with-temp-buffer - (insert s) - (fill-paragraph) - (buffer-string))))))) - (set-match-data - (list (org-element-property :begin this-link) - (- (org-element-property :end this-link) - (org-element-property :post-blank this-link)))) - (goto-char (org-element-property :end this-link))))) - - - (defun org-ref-match-next-bibliographystyle-link (limit) - "Find next bibliographystyle link up to LIMIT. -Add tooltip to the link." - (when (and (re-search-forward "bibliographystyle:\\([[:alnum:]]\\)\\{2,\\}" limit t) - (not (org-in-src-block-p)) - (not (org-at-comment-p))) - (forward-char -2) - (let* ((this-link (org-element-context)) - (path (org-element-property :path this-link)) - (msg (shell-command-to-string (format "kpsewhich %s.bst" path)))) - (add-text-properties - (org-element-property :begin this-link) - (- (org-element-property :end this-link) - (org-element-property :post-blank this-link)) - (list - 'help-echo msg)) - (set-match-data - (list (org-element-property :begin this-link) - (- (org-element-property :end this-link) - (org-element-property :post-blank this-link)))) - (goto-char (org-element-property :end this-link))))) - - - (defun org-ref-make-org-link-cite-key-visible (&rest _) - "Make the org-ref cite link visible in descriptive links." - (when (string-match-p "\\.org$\\|\\.txt$" (buffer-name)) - (save-match-data - (let ((s (match-string 1)) - (s-begin (match-beginning 1)) - (s-end (match-end 1)) - (beg (match-beginning 0)) - (end (match-end 0)) - (cite-re (format "^\\(%s:\\)" - (regexp-opt (-sort - (lambda (a b) - (> (length a) (length b))) - org-ref-cite-types)))) - cite-type) - - (when (and s (string-match cite-re s)) - (setq cite-type (match-string 1 s)) - (remove-text-properties beg end - '(invisible)) - (add-text-properties - beg end - `(face (:foreground ,org-ref-cite-color)))))))) - - (when org-ref-colorize-links - (add-hook - 'org-mode-hook - (lambda () - (advice-add 'org-activate-bracket-links :after #'org-ref-make-org-link-cite-key-visible) - (font-lock-add-keywords - nil - '((org-ref-match-next-cite-link (0 'org-ref-cite-face t)) - (org-ref-match-next-label-link (0 'org-ref-label-face t)) - (org-ref-match-next-ref-link (0 'org-ref-ref-face t)) - (org-ref-match-next-bibliography-link (0 'org-link t)) - (org-ref-match-next-bibliographystyle-link (0 'org-link t))) - t))))) - - -;;* Links -;;** bibliography and bibliographystyle -(defun org-ref-open-bibliography-no-org (link-string) - "Open a bibliography link when you are not in org-mode. -This means you cannot use the usual org-machinery to figure it -out. We don't try to be clever here. If there is only one file, -we open it, otherwise prompt for which one to open." - (let ((bibfiles (split-string link-string ","))) - (find-file (if (= 1 (length bibfiles)) - (car bibfiles) - (completing-read - "Bib file: " bibfiles nil t))))) - - -(defun org-ref-bibinputs () - "Feed BIBINPUTS environment variable to `parse-colon-path'." - (parse-colon-path (getenv "BIBINPUTS"))) - - -(defun org-ref-bibfile-kpsewhich (bibfile) - "Try to find BIBFILE using kpsewhich." - (let ((f (replace-regexp-in-string - "\n$" "" - (shell-command-to-string (format "kpsewhich %s" bibfile))))) - (unless (string= "" f) - f))) - - -(defun org-ref-find-bibfile (bibfile) - "Find BIBFILE as local file, or using kpsewhich or bibinputs." - (or (if (file-exists-p bibfile) bibfile) - (org-ref-bibfile-kpsewhich bibfile) - ;; this should never be reached if bibfile exists, because kpsewhich is - ;; stronger - (org-ref-locate-file bibfile (org-ref-bibinputs)))) - - -(defun org-ref-locate-file (filename path) - "Search for FILENAME through PATH. -Like `locate-file-internal', but with `file-exists-p' as -PREDICATE." - (locate-file-internal filename path () #'file-exists-p)) - - -(defun org-ref-open-bibliography (link-string) - "The click function for a bibliography link." - ;; get link-string boundaries we have to go to the - ;; beginning of the line, and then search forward - (if (not (eq major-mode 'org-mode)) - (org-ref-open-bibliography-no-org link-string) - (let* ((bibfile) - ;; object is the link you clicked on - (object (org-element-context)) - (link-string-beginning) - (link-string-end) - (cp (point))) - (save-excursion - (goto-char (org-element-property :begin object)) - (search-forward link-string nil nil 1) - (setq link-string-beginning (match-beginning 0)) - (setq link-string-end (match-end 0))) - - ;; Make sure point is in the link-path. - (if (< cp link-string-beginning) - (goto-char link-string-beginning)) - ;; We set the reftex-default-bibliography - ;; here. it should be a local variable only in - ;; the current buffer. We need this for using - ;; reftex to do citations. - (set (make-local-variable 'reftex-default-bibliography) - (split-string - (org-element-property :path object) ",")) - - (let (key-beginning key-end) - ;; now if we have comma separated bibliographies - ;; we find the one clicked on. we want to - ;; search forward to next comma from point - (save-excursion - (if (search-forward "," link-string-end 1 1) - ;; we found a match - (setq key-end (- (match-end 0) 1)) - ;; no comma found so take the point - (setq key-end (point)))) - ;; and backward to previous comma from point - (save-excursion - (if (search-backward "," link-string-beginning 1 1) - ;; we found a match - (setq key-beginning (+ (match-beginning 0) 1)) - (setq key-beginning (point)))) ; no match found - ;; save the key we clicked on. - (setq bibfile (org-ref-strip-string - (buffer-substring key-beginning key-end))) - ;; open file on click. I use or because org-ref-find-bibfile returns nil - ;; if the file doesn't exist, and clicking should open the file in that - ;; case. - (find-file (or (org-ref-find-bibfile bibfile) bibfile)))))) - - -(defun org-ref-bibliography-format (keyword desc format) - "Formatting function for bibliography links." - (cond - ((eq format 'org) (org-ref-get-org-bibliography)) - ((eq format 'ascii) (org-ref-get-ascii-bibliography)) - ((eq format 'md) (org-ref-get-md-bibliography)) - ((eq format 'odt) (org-ref-get-odt-bibliography)) - ((eq format 'html) (org-ref-get-html-bibliography)) - ((eq format 'latex) - ;; write out the latex bibliography command - (format "\\bibliography{%s}" - (replace-regexp-in-string - "\\.bib" "" - (mapconcat - 'identity - (mapcar org-ref-latex-bib-resolve-func - (split-string keyword ",")) - ",")))))) - - -(defun org-bibliography-complete-link (&optional arg) - "Completion function for bibliography link. -This will scan the org-file for citations, and if it finds the -citation keys in `org-ref-default-bibliography' or bib files in -the current directory it will insert them. Otherwise you will be -prompted for a file. - -ARG does nothing. I think it is a required signature." - (let* ((keys (reverse (org-ref-get-bibtex-keys))) - (possible-files (org-ref-possible-bibfiles)) - (found '())) - - ;; remove bib links, we will be replacing them. It is debatable if this is a - ;; good idea. I could easily be persuaded not to do this, but it is also not - ;; a great idea to have multiple bibliography links. - (org-element-map (org-ref-parse-buffer) - 'link (lambda (link) - (when (string= "bibliography" - (org-element-property :type link)) - (setf (buffer-substring (org-element-property :begin link) - (org-element-property :end link)) - "")))) - - ;; Get bibfiles containing keys - (setq found - (mapconcat #'identity - (-uniq (cl-loop for key in keys - collect - (catch 'result - (cl-loop for file in possible-files do - (if (org-ref-key-in-file-p - key - (file-truename file)) - (throw 'result - (file-relative-name file))))))) - ",")) - (concat "bibliography:" - (if (string= found "") - (completing-read "Bibfile: " possible-files) - found)))) - - -(defun org-ref-bibliography-face-fn (path) - "Return face for a bibliography link. -org-link if the files exist. -font-lock-warning-face if any file does not exist." - (save-match-data - (cond - ((or (not org-ref-show-broken-links) - (-every? - 'identity - (mapcar - (lambda (bibfile) - (file-exists-p bibfile)) - (split-string path ",")))) - 'org-link) - (t - 'font-lock-warning-face)))) - - -(org-ref-link-set-parameters "bibliography" - :follow #'org-ref-open-bibliography - :export #'org-ref-bibliography-format - :complete #'org-bibliography-complete-link - :help-echo (lambda (window object position) - (save-excursion - (goto-char position) - (let ((s (org-ref-link-message))) - (with-temp-buffer - (insert s) - (fill-paragraph) - (buffer-string))))) - :face #'org-ref-bibliography-face-fn) - - -(defun org-ref-nobibliography-format (keyword desc format) - "Format function for nobibliography link export" - (cond - ((eq format 'org) (org-ref-get-org-bibliography)) - ((eq format 'ascii) (org-ref-get-ascii-bibliography)) - ((eq format 'odt) (org-ref-get-ascii-bibliography)) - ((eq format 'html) (org-ref-get-html-bibliography)) - ((eq format 'latex) - ;; write out the latex bibliography command - (format "\\nobibliography{%s}" - (replace-regexp-in-string - "\\.bib" "" - (mapconcat 'identity - (mapcar org-ref-latex-bib-resolve-func - (split-string keyword ",")) - ",")))))) - - -(org-ref-link-set-parameters "nobibliography" - :follow #'org-ref-open-bibliography - :export #'org-ref-nobibliography-format) - - -(org-ref-link-set-parameters "printbibliography" - :follow #'org-ref-open-bibliography - :export (lambda (keyword desc format) - (cond - ((eq format 'org) (org-ref-get-org-bibliography)) - ((eq format 'html) (org-ref-get-html-bibliography)) - ((eq format 'latex) - ;; write out the biblatex bibliography command - org-ref-printbibliography-cmd)))) - - -(org-ref-link-set-parameters "bibliographystyle" - :export (lambda (keyword desc format) - (cond - ((or (eq format 'latex) - (eq format 'beamer)) - ;; write out the latex bibliography command - (format "\\bibliographystyle{%s}" keyword)) - ;; Other styles should not have an output for this - (t - "")))) - -(defun org-bibliographystyle-complete-link (&optional arg) - "Completion function for bibliography style links." - (when (executable-find "kpsewhich") - (concat "bibliographystyle:" - (completing-read "Style: " (mapcar 'file-name-nondirectory - (mapcar 'file-name-sans-extension - (-flatten - (mapcar (lambda (path) - (setq path (replace-regexp-in-string "!" "" path)) - (when (file-directory-p path) - (f-entries path (lambda (f) (f-ext? f "bst")) t))) - (split-string - ;; https://tex.stackexchange.com/questions/431948/get-a-list-of-installed-bibliography-styles-with-kpsewhich?noredirect=1#comment1082436_431948 - (shell-command-to-string "kpsewhich -expand-path '$BSTINPUTS'") - ":"))))))))) - - -(defun org-ref-insert-bibliographystyle-link () - "Insert a bibliographystyle link with completion." - (interactive) - (insert (org-bibliographystyle-complete-link))) - - -;;;###autoload -(defun org-ref-insert-bibliography-link () - "Insert a bibliography with completion." - (interactive) - (insert (org-bibliography-complete-link))) - - -;;** addbibresource - -(defun org-ref-follow-addbibresource (link-string) - ;; get link-string boundaries. we have to go to the - ;; beginning of the line, and then search forward - (let* ((bibfile) - ;; object is the link you clicked on - (object (org-element-context)) - - (link-string-beginning) - (link-string-end)) - - (save-excursion - (goto-char (org-element-property :begin object)) - (search-forward link-string nil nil 1) - (setq link-string-beginning (match-beginning 0)) - (setq link-string-end (match-end 0))) - - ;; We set the reftex-default-bibliography - ;; here. it should be a local variable only in - ;; the current buffer. We need this for using - ;; reftex to do citations. - (set (make-local-variable 'reftex-default-bibliography) - (split-string (org-element-property :path object) ",")) - - (let (key-beginning key-end) - ;; now if we have comma separated bibliographies - ;; we find the one clicked on. we want to - ;; search forward to next comma from point - (save-excursion - (if (search-forward "," link-string-end 1 1) - (setq key-end (- (match-end 0) 1)) ; we found a match - (setq key-end (point)))) ; no comma found so take the point - ;; and backward to previous comma from point - (save-excursion - (if (search-backward "," link-string-beginning 1 1) - (setq key-beginning (+ (match-beginning 0) 1)) ; we found a match - (setq key-beginning (point)))) ; no match found - ;; save the key we clicked on. - (setq bibfile (org-ref-strip-string - (buffer-substring key-beginning key-end))) - (find-file bibfile)))) - - -(org-ref-link-set-parameters "addbibresource" - :follow #'org-ref-follow-addbibresource - :export (lambda (keyword desc format) - (cond - ((eq format 'html) (format "")) ; no output for html - ((eq format 'latex) - ;; write out the latex addbibresource command - (format "\\addbibresource{%s}" keyword))))) - -;;** List of figures - -;; org-in-commented-heading-p was introduced in org commit 6d1d61f6. Org version -;; 8.3 was the first version to contain this function. This is provided for -;; backward compatibility for the org-mode included with Emacs. -(unless (fboundp 'org-in-commented-heading-p) - (defun org-in-commented-heading-p (&optional no-inheritance) - "Non-nil if point is under a commented heading. -This function also checks ancestors of the current headline, -unless optional argument NO-INHERITANCE is non-nil." - (cond - ((org-before-first-heading-p) nil) - ((let ((headline (nth 4 (org-heading-components)))) - (and headline - (let ((case-fold-search nil)) - (org-string-match-p - (concat - "^" - org-comment-string "\\(?: \\|$\\)") - headline))))) - (no-inheritance nil) - (t - (save-excursion (and (org-up-heading-safe) (org-in-commented-heading-p))))))) - - -;;;###autoload -(defun org-ref-list-of-figures (&optional arg) - "Generate buffer with list of figures in them. -ARG does nothing. -Ignore figures in COMMENTED sections." - (interactive) - (save-excursion - (widen) - (let* ((c-b (buffer-name)) - (counter 0) - (list-of-figures - (org-element-map (org-ref-parse-buffer) 'link - (lambda (link) - "create a link for to the figure" - (when - (and (string= (org-element-property :type link) "file") - (string-match-p - "[^.]*\\.\\(png\\|jpg\\|eps\\|pdf\\|svg\\)$" - (org-element-property :path link)) - ;; ignore commented sections - (save-excursion - (goto-char (org-element-property :begin link)) - (not (or (org-in-commented-heading-p) - (org-at-comment-p) - (-intersection (org-get-tags) org-export-exclude-tags))))) - (cl-incf counter) - - (let* ((start (org-element-property :begin link)) - (linenum (progn (goto-char start) (line-number-at-pos))) - (fname (org-element-property :path link)) - (parent (car (cdr - (org-element-property :parent link)))) - (caption (cl-caaar (plist-get parent :caption))) - (name (plist-get parent :name))) - - (if caption - (format "[[file:%s::%s][Figure %s:]] %s\n" c-b linenum counter caption) - ;; if it has no caption, try the name - ;; if it has no name, use the file name - (cond (name - (format "[[file:%s::%s][Figure %s:]] %s\n" c-b linenum counter name)) - (fname - (format "[[file:%s::%s][Figure %s:]] %s\n" - c-b linenum counter fname)))))))))) - (switch-to-buffer "*List of Figures*") - (setq buffer-read-only nil) - (org-mode) - (erase-buffer) - (insert (mapconcat 'identity list-of-figures "")) - (goto-char (point-min)) - ;; open links in the same window - (setq-local org-link-frame-setup - '((file . find-file))) - (setq buffer-read-only t) - (use-local-map (copy-keymap org-mode-map)) - (local-set-key "q" #'(lambda () (interactive) (kill-buffer)))))) - - -(org-ref-link-set-parameters "list-of-figures" - :follow #'org-ref-list-of-figures - :export (lambda (keyword desc format) - (cond - ((eq format 'latex) - (format "\\listoffigures"))))) - -;;** List of tables -;;;###autoload -(defun org-ref-list-of-tables (&optional arg) - "Generate a buffer with a list of tables. -ARG does nothing." - (interactive) - (save-excursion - (widen) - (let* ((c-b (buffer-name)) - (counter 0) - (list-of-tables - (org-element-map (org-ref-parse-buffer 'element) 'table - (lambda (table) - "create a link for to the table" - (save-excursion - (when - ;; ignore commented sections - (goto-char (org-element-property :begin table)) - (not (or (org-in-commented-heading-p) - (-intersection (org-get-tags) org-export-exclude-tags))) - (cl-incf counter) - (let* ((start (org-element-property :begin table)) - (linenum (progn (goto-char start) (line-number-at-pos))) - (caption (cl-caaar (org-element-property :caption table))) - (name (org-element-property :name table))) - (if caption - (format "[[file:%s::%s][Table %s:]] %s\n" c-b linenum counter caption) - ;; if it has no caption, try the name - ;; if it has no name, use generic name - (cond (name - (format "[[file:%s::%s][Table %s:]] %s\n" - c-b linenum counter name)) - (t - (format "[[file:%s::%s][Table %s:]] No caption\n" - c-b linenum counter))))))))))) - (switch-to-buffer "*List of Tables*") - (setq buffer-read-only nil) - (org-mode) - (erase-buffer) - (insert (mapconcat 'identity list-of-tables "")) - (goto-char (point-min)) - ;; open links in the same window - (setq-local org-link-frame-setup - '((file . find-file))) - (setq buffer-read-only t) - (use-local-map (copy-keymap org-mode-map)) - (local-set-key "q" #'(lambda () (interactive) (kill-buffer)))))) - - -(org-ref-link-set-parameters "list-of-tables" - :follow #'org-ref-list-of-tables - :export (lambda (keyword desc format) - (cond - ((eq format 'latex) - (format "\\listoftables"))))) - -;;** label link - -(defun org-ref-count-labels (label) - "Count number of LABELs in the document." - (+ (count-matches - (format "label:%s\\( \\|]\\|$\\)" (regexp-quote label)) - (point-min) (point-max)) - (count-matches - (format "<<%s>>" label) - (point-min) (point-max)) - ;; for tblname, it is not enough to get word boundary - ;; tab-little and tab-little-2 match then. - (count-matches - (format "^\\( \\)*#\\+tblname:\\s-*%s\\b[^-:]" label) - (point-min) (point-max)) - (count-matches (format "\\label{%s}" label) - (point-min) (point-max)) - ;; this is the org-format #+label: - (count-matches (format "^\\( \\)*#\\+label:\\s-*%s\\b[^-:]" label) - (point-min) (point-max)) - ;; #+name: - (count-matches (format "^\\( \\)*#\\+name:\\s-*%s\\b[^-:]" label) - (point-min) (point-max)) - (let ((custom-id-count 0)) - (org-map-entries - (lambda () - (when (string= label (org-entry-get (point) "CUSTOM_ID")) - (setq custom-id-count (+ 1 custom-id-count))))) - custom-id-count))) - - -(defun org-ref-label-store-link () - "Store a link to a label. The output will be a ref to that label. -This has several conditional ways to store a link to figures and -tables also. Note it does not currently work with latex labels, -only org labels and names." - ;; First we have to make sure we are on a label link. - (let* ((object (and (eq major-mode 'org-mode) (org-element-context))) - (stored nil) - label) - (cond - ;; here literally on a label link. - ((and - (equal (org-element-type object) 'link) - (equal (org-element-property :type object) "label")) - (setq label (org-element-property :path object)) - (org-store-link-props - :type "ref" - :link (concat "ref:" label))) - - ;; here on a file link that probably contains an image, although I don't check that - ((and - (equal (org-element-type object) 'link) - (equal (org-element-property :type object) "file") - (org-file-image-p (org-element-property :path object))) - - (if (org-element-property :name object) - (progn - (setq label (org-element-property :name object)) - (org-store-link-props - :type "ref" - :link (concat "ref:"label))) - ;; maybe we have a caption to get it from. - (let* ((parent (org-element-property :parent object)) - (caption)) - (when (and parent - (equal (org-element-type parent) 'paragraph)) - (if (org-element-property :name parent) - ;; caption paragraph may have a name which we use if it is there - (setq label (org-element-property :name parent)) - ;; else search caption - (setq caption (s-join - "" - (mapcar 'org-no-properties - (org-export-get-caption parent)))) - (when (string-match org-ref-label-re caption) - (setq label (match-string 1 caption)))) - - (org-store-link-props - :type "ref" - :link (concat "ref:" label)))))) - - ;; here on a paragraph (eg in a caption of an image). it is a paragraph with a caption - ;; in a caption, with no name, but maybe a label - ((equal (org-element-type object) 'paragraph) - (if (org-element-property :name object) - (org-store-link-props - :type "ref" - :link (concat "ref:" (org-element-property :name object))) - ;; See if it is in the caption name - (let ((caption (s-join "" (mapcar 'org-no-properties - (org-export-get-caption object))))) - (when (string-match org-ref-label-re caption) - (setq label (match-string 1 caption)) - (org-store-link-props - :type "ref" - :link (concat "ref:" label)))))) - - ;; If you are in a table, we need to be at the beginning to make sure we get the name. - ;; Note when in a caption it appears you are in a table but org-at-table-p is nil there. - ((or (equal (org-element-type object) 'table) (org-at-table-p)) - (save-excursion - (goto-char (org-table-begin)) - (let* ((table (org-element-context)) - (label (org-element-property :name table)) - (caption (s-join "" (mapcar 'org-no-properties (org-export-get-caption table))))) - (when (null label) - ;; maybe there is a label in the caption? - (when (string-match org-ref-label-re caption) - (setq label (match-string 1 caption)))) - - (org-store-link-props - :type "ref" - :link (concat "ref:" label))))) - - ;; and to #+label: lines - ((and (equal (org-element-type object) 'paragraph) - (org-element-property :name object)) - (setq label (org-element-property :name object)) - (org-store-link-props - :type "ref" - :link (concat "ref:" label))) - - ;; in a latex environment - ((equal (org-element-type object) 'latex-environment) - (let ((value (org-element-property :value object)) - label) - (when (string-match "\\\\label{\\(?1:[+a-zA-Z0-9:\\._-]*\\)}" value) - (setq label (match-string-no-properties 1 value)) - (org-store-link-props - :type "ref" - :link (concat "ref:" label))))) - - (t - nil)))) - - -(defun org-ref-label-face-fn (label) - "Return a face for the label link." - (save-match-data - (cond - ((or (not org-ref-show-broken-links) - (= 1 (org-ref-count-labels label))) - 'org-ref-label-face) - (t - 'font-lock-warning-face)))) - - -(org-ref-link-set-parameters "label" - :follow (lambda (label) - "On clicking count the number of label tags used in the buffer. -A number greater than one means multiple labels!" - (let ((count (org-ref-count-labels label))) - (message (format "%s occurence%s" - count - (if (or (= count 0) - (> count 1)) - "s" - "")) - (org-ref-count-labels label)))) - :export (lambda (keyword desc format) - (cond - ((eq format 'html) (format "
" keyword)) - ((eq format 'md) (format "" keyword)) - ((eq format 'latex) - (format "\\label{%s}" keyword)))) - :store #'org-ref-label-store-link - :face 'org-ref-label-face-fn - :help-echo (lambda (window object position) - (save-excursion - (goto-char position) - (let ((s (org-ref-link-message))) - (with-temp-buffer - (insert s) - (fill-paragraph) - (buffer-string)))))) - -;;** ref link - -(defun org-ref-ref-follow (label) - "On clicking goto the LABEL. -Navigate back with \`\\[org-mark-ring-goto]'." - ;; Suppress minibuffer message in helm. See `org-ref-browser'. - (if (and (boundp 'helm-alive-p) helm-alive-p) - (lambda (&optional pos buffer) - (setq pos (or pos (point))) - (setq org-mark-ring (nthcdr (1- org-mark-ring-length) org-mark-ring)) - (move-marker (car org-mark-ring) - (or pos (point)) - (or buffer (current-buffer)))) - (org-mark-ring-push)) - ;; next search from beginning of the buffer it is possible you would not find - ;; the label if narrowing is in effect - (widen) - (unless - (or - ;; our label links - (progn - (goto-char (point-min)) - (re-search-forward (format "label:%s\\b" (regexp-quote label)) nil t)) - - ;; a latex label - (progn - (goto-char (point-min)) - (re-search-forward (format "\\label{%s}" (regexp-quote label)) nil t)) - - ;; #+label: name org-definition - (progn - (goto-char (point-min)) - (re-search-forward - (format "^\\( \\)*#\\+label:\\s-*\\(%s\\)\\b" (regexp-quote label)) nil t)) - - ;; org tblname - (progn - (goto-char (point-min)) - (re-search-forward - (format "^\\( \\)*#\\+tblname:\\s-*\\(%s\\)\\b" (regexp-quote label)) nil t)) - - ;; a #+name - (progn - (goto-char (point-min)) - (re-search-forward - (format "^\\( \\)*#\\+name:\\s-*\\(%s\\)\\b" (regexp-quote label)) nil t)) - - ;; CUSTOM_ID - (progn - (goto-char (point-min)) - (let ((p (org-map-entries - (lambda () - (point)) - (format "CUSTOM_ID=\"%s\"" label)))) - (if (not (= 1 (length p))) - nil - (goto-char (car p))))) - (progn - (goto-char (point-min)) - (re-search-forward - (format "<<%s>>" (regexp-quote label)) nil t))) - - ;; we did not find anything, so go back to where we came - (org-mark-ring-goto) - (error "%s not found" label)) - (org-show-entry) - (unless (and (boundp 'helm-alive-p) helm-alive-p) - (substitute-command-keys - "Go back with (org-mark-ring-goto) \`\\[org-mark-ring-goto]'."))) - - -(defun org-ref-complete-link (&optional arg) - "Completion function for ref links. -Optional argument ARG Does nothing." - (let ((label)) - (setq label (completing-read "label: " (org-ref-get-labels))) - (format "%s:%s" (org-ref-infer-ref-type label) label))) - -(defun org-ref-ref-help-echo (window object position) - "A help-echo function for ref links." - (save-excursion - (goto-char position) - (let ((s (org-ref-link-message))) - (with-temp-buffer - (insert s) - (fill-paragraph) - (buffer-string))))) - - -(defun org-ref-ref-export (keyword desc format) - "An export function for ref links." - (cond - ((eq format 'html) - (format "%s" keyword (or desc keyword))) - ((eq format 'latex) - (format "\\ref{%s}" keyword)) - ((eq format 'md) - (format "[%s](#%s)" keyword keyword)))) - - -(defun org-ref-ref-face-fn (label) - "Return a face for a ref link." - (save-match-data - (cond - ((or (not org-ref-show-broken-links) - (member label (org-ref-get-labels))) - 'org-ref-ref-face) - (t - 'font-lock-warning-face)))) - - -(org-ref-link-set-parameters "ref" - :follow #'org-ref-ref-follow - :export #'org-ref-ref-export - :complete #'org-ref-complete-link - :face 'org-ref-ref-face-fn - :help-echo #'org-ref-ref-help-echo) - - -(defun org-ref-get-org-labels () - "Return a list of #+LABEL: labels." - (save-excursion - (goto-char (point-min)) - (let ((matches '())) - (while (re-search-forward "^#\\+label:\\s-+\\(.*\\)\\b" (point-max) t) - ;; do not do this for tables. We get those in `org-ref-get-tblnames'. - ;; who would have thought you have save match data here? Trust me. When - ;; I wrote this, you did. - (unless (save-match-data (equal (car (org-element-at-point)) 'table)) - (add-to-list 'matches (match-string-no-properties 1) t))) - matches))) - - -(defun org-ref-get-custom-ids () - "Return a list of custom_id properties in the buffer." - (let ((results '()) custom_id) - (org-map-entries - (lambda () - (let ((custom_id (org-entry-get (point) "CUSTOM_ID"))) - (when (not (null custom_id)) - (setq results (append results (list custom_id))))))) - results)) - - -(defun org-ref-get-latex-labels () - "Return list of matchin LaTeX defined labels in buffer." - (save-excursion - (goto-char (point-min)) - (let ((matches '())) - (while (re-search-forward "\\\\label{\\([-a-zA-Z0-9:_\\.]*\\)}" - (point-max) t) - (add-to-list 'matches (match-string-no-properties 1) t)) - matches))) - - -(defun org-ref-get-tblnames () - "Return list of table names in the buffer." - (org-element-map (org-ref-parse-buffer) 'table - (lambda (table) - (org-element-property :name table)))) - - -(defun org-ref-get-names () - "Return list of names in the buffer." - (save-excursion - (save-restriction - (widen) - (goto-char (point-min)) - (let ((case-fold-search t) - (matches '())) - (while (re-search-forward "^\\( \\)*#\\+name:\\s-+\\(.*\\)" nil t) - (cl-pushnew (match-string 2) matches)) - matches)))) - - -(defvar-local org-ref-labels '() - "Known labels in org-ref -Stores a list of strings.") - - -(defvar org-ref-label-regexps - '(;; #+label: - "^#\\+label:\\s-+\\(?1:[+a-zA-Z0-9:\\._-]*\\)\\_>" - ;; CUSTOM_ID in a heading - ":CUSTOM_ID:\\s-+\\(?1:[+a-zA-Z0-9:\\._-]*\\)\\_>" - ;; #+name - "^\\s-*#\\+name:\\s-+\\(?1:[+a-zA-Z0-9:\\._-]*\\)\\_>" - ;; radio targets - "<<\\(?1:[+a-zA-Z0-9:\\._-]*\\)>>" - ;; #+tblname: - "^\\s-*#\\+tblname:\\s-+\\(?1:[+a-zA-Z0-9:\\._-]*\\)\\_>" - ;; label links - "label:\\(?1:[+a-zA-Z0-9:\\._-]*\\)" - ;; labels in latex - "\\\\label{\\(?1:[+a-zA-Z0-9:\\._-]*\\)}") - "List of regexps that are labels in org-ref.") - - -(defvar org-ref-label-debug nil "If non-nil print debug messages.") - - -(defun org-ref-add-labels (start end) - "Add labels in the region from START to END. -This is run by font-lock. START tends to be the beginning of the -line, and END tends to be where the point is, so this function -seems to work fine at recognizing labels by the regexps in -`org-ref-label-regexps'." - (interactive "r") - (save-excursion - (save-match-data - (cl-loop for rx in org-ref-label-regexps - do - (goto-char start) - (while (re-search-forward rx end t) - (let ((label (match-string-no-properties 1))) - ;; I don't know why this gets found, but some labels are - ;; empty strings. we don't store these. - (unless (string= "" label) - (with-silent-modifications - (put-text-property (match-beginning 1) - (match-end 1) - 'org-ref-label t) - (put-text-property (match-beginning 1) - (match-end 1) - 'rear-nonsticky '(org-ref-label))) - - (when org-ref-label-debug - (message "oral: adding %s" label) - (message "%S\n" org-ref-labels)) - (cl-pushnew label - org-ref-labels :test 'string=) - (when org-ref-label-debug - (message " oral: added %s" label) - (message " %S\n" org-ref-labels)) - ;; now store the last end so we can tell for the next run - ;; if we are adding to a label. - (setq org-ref-last-label-end end)))))))) - - -(defun org-ref-delete-labels-deletion (start end) - "Function to run before text from START to END is deleted. -If you have deleted or inserted more than one char, we just -recheck the whole buffer. It is tricky to manage labels on the -region." - (cond - ;; If you are deleting a region, we just rescan the whole buffer. - ((> 1 (abs (- end start))) - (org-ref-reset-labels)) - - ;; start is at beginning of a label - ((and - (null (if (bobp) nil (get-text-property (- start 1) 'org-ref-label))) - (get-text-property start 'org-ref-label)) - (let ((label (buffer-substring-no-properties - start - (next-single-property-change start 'org-ref-label)))) - (when org-ref-label-debug - (message "ordl-0: at beginning - removing %s" label) - (message "%S\n" org-ref-labels)) - (setq org-ref-labels - (cl-remove label org-ref-labels - :test 'string=)) - (when org-ref-label-debug - (message " ordl-0: removed %s" label) - (message " %S\n" org-ref-labels)))) - - ;; in a label - ((and - (if (bobp) nil (get-text-property (- start 1) 'org-ref-label)) - (get-text-property start 'org-ref-label) - (if (eobp) nil (get-text-property (+ start 1) 'org-ref-label))) - (let ((label (buffer-substring-no-properties - (previous-single-property-change start 'org-ref-label) - (next-single-property-change start 'org-ref-label)))) - (when org-ref-label-debug - (message "ordl-1: removing %s" label) - (message "%S\n" org-ref-labels)) - (setq org-ref-labels - (cl-remove label org-ref-labels - :test 'string=)) - (when org-ref-label-debug - (message " ordl-1: removed %s" label) - (message " %S\n" org-ref-labels)))) - - ;; at end of label - ((and - (get-text-property start 'org-ref-label) - (null (if (eobp) nil (get-text-property (+ start 1) 'org-ref-label)))) - (let* ((start (previous-single-property-change end 'org-ref-label)) - (label (buffer-substring-no-properties start end))) - (when org-ref-label-debug - (message "ordl-2: removing %s" label) - (message "%s" org-ref-labels)) - (setq org-ref-labels - (cl-remove label org-ref-labels - :test 'string=)) - (when org-ref-label-debug - (message " ordl-2: removed %s" label) - (message " %S\n" org-ref-labels)))))) - - -(defun org-ref-delete-labels-insertion (start end) - "Function to run before inserting text. -START=END for an insertion." - ;; this is an insertion. start=end - (cl-assert (= start end)) - ;; if the previous position is a label, we need to find it - (when org-ref-label-debug - (message "ordl: inserting %s %s" start end) - (message "%S\n" org-ref-labels)) - - (cond - ;; at the beginning of a label - ((and - (get-text-property start 'org-ref-label) - (not (if (bobp) nil (get-text-property (- start 1) 'org-ref-label)))) - (let ((label (buffer-substring-no-properties - start - (next-single-property-change start 'org-ref-label)))) - (when org-ref-label-debug - (message "ordl-5: removing %s" label) - (message "%S\n" org-ref-labels)) - (setq org-ref-labels - (cl-remove - label - org-ref-labels - :test 'string=)) - (when org-ref-label-debug - (message " ordl-5: removing %s" label) - (message " %S\n" org-ref-labels)))) - - ;; in a label - ((and - ;; this means in a label - (if (bobp) nil (get-text-property (- start 1) 'org-ref-label)) - (get-text-property start 'org-ref-label)) - (let ((label (buffer-substring-no-properties - (previous-single-property-change start 'org-ref-label) - (next-single-property-change start 'org-ref-label)))) - (when org-ref-label-debug - (message "ordl-4: removing %s" label) - (message "%S\n" org-ref-labels)) - (setq org-ref-labels - (cl-remove label - org-ref-labels - :test 'string=)) - (when org-ref-label-debug - (message " ordl-4: removed %s" label) - (message " %S\n" org-ref-labels)))) - - ;; at the end of a label but not on it. - ((and - (not (get-text-property start 'org-ref-label)) - (if (bobp) nil (get-text-property (- start 1) 'org-ref-label))) - (let ((label (buffer-substring-no-properties - start - (previous-single-property-change start 'org-ref-label)))) - (when org-ref-label-debug - (message "ordl-6: removing %s" label) - (message "%S\n" org-ref-labels)) - (setq org-ref-labels - (cl-remove - label - org-ref-labels - :test 'string=)) - (when org-ref-label-debug - (message " ordl-6: removing %s" label) - (message " %S\n" org-ref-labels)))) - (t - (when org-ref-label-debug - (message "*********** ordl fell through:%s\n%s\n%s" - (if (bobp) nil (get-text-property (- start 1) 'org-ref-label)) - (get-text-property start 'org-ref-label) - (if (eobp) nil (get-text-property (+ start 1) 'org-ref-label))))))) - - -(defun org-ref-delete-labels (start end) - "Check for labels between START and END and remove them from the known list. -This is called as a `before-change-functions' and it means text -from START to END has been deleted. - -This idea was suggested by @vspinu. - -This is harder than it seems. The main issue is that START and -END here may be the same if the change is an insertion, different -by one for a simple character delete, or bigger if a selection is -deleted. - -Note: this will not necessarily trigger fontification on ref -links so they might not look broken right away if their label is -missing." - (when org-ref-label-debug - (message "ordl start-----------------------------------------------------------------") - (message "start: %S" org-ref-labels)) - ;; This conditional is here because I get errors like Args out of range: - ;; 176, 176 which seem to be triggered by get-text-property. I also find that - ;; this can happen during export. The check on `org-export-current-backend' is - ;; not perfect, this can be nil for anonyomous derived backends. - (when (and org-ref-labels - (not org-export-current-backend)) - (if (eq start end) - (org-ref-delete-labels-insertion start end) - (org-ref-delete-labels-deletion start end))) - (when org-ref-label-debug - (message "end: %S" org-ref-labels) - (message "ordl end-----------------------------------------------------------------"))) - - -(defun org-ref-reset-labels () - "Reset `org-ref-labels'." - (interactive) - (setq org-ref-labels nil) - (org-ref-setup-label-finders) - (org-ref-add-labels (point-min) (point-max)) - org-ref-labels) - - -(defun org-ref-setup-label-finders () - "Set up the functions for maintaining labels in a buffer." - (setq-local org-ref-labels '()) - (org-ref-add-labels (point-min) (point-max)) - (add-to-list 'jit-lock-functions 'org-ref-add-labels) - (add-to-list 'before-change-functions 'org-ref-delete-labels)) - - -(add-hook 'org-mode-hook 'org-ref-setup-label-finders t) - - -(defun org-ref-get-labels () - "Return a list of labels in the buffer that you can make a ref link to. -This is used to complete ref links and in `org-ref-ref-face-fn'. -Note the list is returned in reverse order as it was created by -font-lock. Initially, the labels start in order, but if you edit -the buffer in nonlinear ways, the labels may get out of order. I -don't know a good way to keep these in order. I tried a version -where I kept the pos of each one, but they change so it is hard -to keep them sorted. - -If the `org-ref-labels' variable is empty, we try scanning the -whole buffer for them." - (when (or (null org-ref-labels) (null org-ref-label-use-font-lock)) - (save-excursion - (org-ref-add-labels (point-min) (point-max)))) - (reverse org-ref-labels)) - - -;;;###autoload -(defun org-ref-insert-ref-link () - "Completion function for a ref link." - (interactive) - (insert (org-ref-complete-link))) - - -;;** pageref link - -(org-ref-link-set-parameters "pageref" - :follow #'org-ref-ref-follow - :export (lambda (path desc format) - (cond - ((eq format 'html) (format "(%s)" path)) - ((eq format 'latex) - (format "\\pageref{%s}" path)))) - :face 'org-ref-ref-face-fn - :complete #'org-pageref-complete-link - :help-echo #'org-ref-ref-help-echo) - - -(defun org-pageref-complete-link (&optional arg) - "Completion function for ref links. -Optional argument ARG Does nothing." - (let ((label)) - (setq label (completing-read "label: " (org-ref-get-labels))) - (format "ref:%s" label))) - - -;;;###autoload -(defun org-pageref-insert-ref-link () - "Insert a pageref link with completion." - (interactive) - (insert (org-pageref-complete-link))) - -;;** nameref link - -(defun org-ref-export-nameref (path desc format) - "Export function for nameref links." - (cond - ((eq format 'html) (format "(%s)" path)) - ((eq format 'latex) - (format "\\nameref{%s}" path)))) - - -(org-ref-link-set-parameters "nameref" - :follow #'org-ref-ref-follow - :export #'org-ref-export-nameref - :complete #'org-ref-complete-link - :face 'org-ref-ref-face-fn - :help-echo #'org-ref-ref-help-echo) - -;;** eqref link - -(defun org-ref-eqref-export (keyword desc format) - (cond - ((eq format 'latex) (format "\\eqref{%s}" keyword)) - ;;considering the fact that latex's the standard of math formulas, just use mathjax to render the html - ;;customize the variable 'org-html-mathjax-template' and 'org-html-mathjax-options' refering to 'autonumber' - ((eq format 'html) (format "\\eqref{%s}" keyword)) - ((eq format 'md) - (format "[%s](#%s)" keyword keyword)))) - - -(org-ref-link-set-parameters "eqref" - :follow #'org-ref-ref-follow - :export #'org-ref-eqref-export - ;; This isn't equation specific, one day we might try to make it that way. - :complete #'org-ref-complete-link - :face 'org-ref-ref-face-fn - :help-echo #'org-ref-ref-help-echo) - -;;** autoref link - -(defun org-ref-autoref-export (keyword desc format) - "Autoref export function." - (cond - ((eq format 'latex) (format "\\autoref{%s}" keyword)) - ;; considering the fact that latex's the standard of math formulas, just use - ;;mathjax to render the html customize the variable - ;;'org-html-mathjax-template' and 'org-html-mathjax-options' refering to - ;;'autonumber' - ((eq format 'html) (format "\\autoref{%s}" keyword)))) - - -(org-ref-link-set-parameters "autoref" - :follow #'org-ref-ref-follow - :export #'org-ref-autoref-export - :complete #'org-ref-complete-link - :face 'org-ref-ref-face-fn - :help-echo #'org-ref-ref-help-echo) - -;;** cref link -;; for LaTeX cleveref package: -;; https://www.ctan.org/tex-archive/macros/latex/contrib/cleveref - -(defun org-ref-cref-export (keyword desc format) - "cref link export function. -See https://www.ctan.org/tex-archive/macros/latex/contrib/cleveref" - (cond - ((eq format 'latex) (format "\\cref{%s}" keyword)) - ;; considering the fact that latex's the standard of math formulas, just use - ;;mathjax to render the html customize the variable - ;;'org-html-mathjax-template' and 'org-html-mathjax-options' refering to - ;;'autonumber' - ((eq format 'html) (format "\\cref{%s}" keyword)))) - - -(defun org-ref-Cref-export (keyword desc format) - "Cref link export function. -The capitalized version. See -https://www.ctan.org/tex-archive/macros/latex/contrib/cleveref" - (cond - ((eq format 'latex) (format "\\Cref{%s}" keyword)) - ;; considering the fact that latex's the standard of math formulas, just use - ;;mathjax to render the html customize the variable - ;;'org-html-mathjax-template' and 'org-html-mathjax-options' refering to - ;;'autonumber' - ((eq format 'html) (format "\\Cref{%s}" keyword)))) - - -(org-ref-link-set-parameters "cref" - :follow #'org-ref-ref-follow - :export #'org-ref-cref-export - :complete #'org-ref-complete-link - :face 'org-ref-ref-face-fn - :help-echo #'org-ref-ref-help-echo) - - -(org-ref-link-set-parameters "Cref" - :follow #'org-ref-ref-follow - :export #'org-ref-Cref-export - :complete #'org-ref-complete-link - :face 'org-ref-ref-face-fn - :help-echo #'org-ref-ref-help-echo) - - -;;** cite link - -(defun org-ref-get-bibtex-key-under-cursor () - "Return key under the cursor in org-mode. -We search forward from point to get a comma, or the end of the link, -and then backwards to get a comma, or the beginning of the link. that -delimits the keyword we clicked on. We also strip the text -properties." - (let* ((object (org-element-context)) - (link-string (if (eq (org-element-type object) 'link) - (org-element-property :path object) - (org-in-regexp org-link-any-re) - ;; this is clunkier than I prefer, but some keys have - ;; colons in them, and this gets rid of the link type, - ;; then rejoins the rest of the keys - (s-join ":" (cdr (split-string - (match-string-no-properties 0) ":")))))) - ;; you may click on the part before the citations. here we make - ;; sure to move to the beginning so you get the first citation. - (let ((cp (point))) - (goto-char (org-element-property :begin object)) - (search-forward link-string (org-element-property :end object)) - (goto-char (match-beginning 0)) - ;; check if we clicked before the path and move as needed. - (unless (< cp (point)) - (goto-char cp))) - - (if (not (org-element-property :contents-begin object)) - ;; this means no description in the link - (progn - ;; we need the link path start and end - (let (link-string-beginning link-string-end) - (save-excursion - (goto-char (org-element-property :begin object)) - (search-forward link-string nil nil 1) - (setq link-string-beginning (match-beginning 0)) - (setq link-string-end (match-end 0))) - - (let (key-beginning key-end) - ;; The key is the text between commas, or the link boundaries - (save-excursion - (if (search-forward "," link-string-end t 1) - (setq key-end (- (match-end 0) 1)) ; we found a match - (setq key-end link-string-end))) ; no comma found so take the end - ;; and backward to previous comma from point which defines the start character - (save-excursion - (if (search-backward "," link-string-beginning 1 1) - (setq key-beginning (+ (match-beginning 0) 1)) ; we found a match - (setq key-beginning link-string-beginning))) ; no match found - ;; save the key we clicked on. - (let ((bibtex-key - (org-ref-strip-string - (buffer-substring key-beginning key-end)))) - (set-text-properties 0 (length bibtex-key) nil bibtex-key) - bibtex-key)))) - - ;; link with description and multiple keys - (if (and (org-element-property :contents-begin object) - (string-match "," link-string) - (equal (org-element-type object) 'link)) - ;; point is not on the link description - (if (not (>= (point) (org-element-property :contents-begin object))) - (let (link-string-beginning link-string-end) - (save-excursion - (goto-char (org-element-property :begin object)) - (search-forward link-string nil t 1) - (setq link-string-beginning (match-beginning 0)) - (setq link-string-end (match-end 0))) - - (let (key-beginning key-end) - ;; The key is the text between commas, or the link boundaries - (save-excursion - (if (search-forward "," link-string-end t 1) - (setq key-end (- (match-end 0) 1)) ; we found a match - (setq key-end link-string-end))) ; no comma found so take the end - ;; and backward to previous comma from point which defines the start character - - (save-excursion - (if (search-backward "," link-string-beginning 1 1) - (setq key-beginning (+ (match-beginning 0) 1)) ; we found a match - (setq key-beginning link-string-beginning))) ; no match found - ;; save the key we clicked on. - (let ((bibtex-key - (org-ref-strip-string - (buffer-substring key-beginning key-end)))) - (set-text-properties 0 (length bibtex-key) nil bibtex-key) - bibtex-key))) - ;; point is on the link description, assume we want the - ;; last key - (let ((last-key (replace-regexp-in-string "[a-zA-Z0-9_-]*," "" link-string))) - last-key)) - ;; link with description. assume only one key - link-string)))) +;; * Bibliography related functions (defun org-ref-find-bibliography () "Find the bibliography in the buffer. -This function sets and returns cite-bibliography-files, which is -a list of files either from }, internal bibliographies, from files in the +This function sets and returns a list of files either from internal bibliographies, from files in the BIBINPUTS env var, and finally falling back to what the user has -set in `org-ref-default-bibliography'" - (catch 'result - ;; If you call this in a bibtex file, assume we want this file - (when (and buffer-file-name (f-ext? buffer-file-name "bib")) - (throw 'result (setq org-ref-bibliography-files (list buffer-file-name)))) +set in `bibtex-completion-bibliography'" + (let ((org-ref-bibliography-files ())) + (catch 'result + (save-excursion + (when (eq major-mode 'org-mode) + (org-with-wide-buffer + (goto-char (point-min)) + ;; This just searches for these strings, and then checks if it + ;; is on a link. This is faster than parsing the org-file when + ;; it gets large. + ;; look for org-ref bibliography + (while (re-search-forward "\\(no\\)?bibliography:" nil t) + (let ((link (org-element-context))) + (when (and (eq (car link) 'link) + (member (org-element-property :type link) '("bibliography" "nobibliography"))) + (setq org-ref-bibliography-files + (mapcar 'org-ref-get-bibfile-path + (mapcar 'string-trim (split-string + (org-element-property :path link) + ",")))) + (throw 'result (nreverse (delete-dups org-ref-bibliography-files)))))) - ;; otherwise, check current file for a bibliography source - (save-excursion - (save-restriction - (widen) - (goto-char (point-min)) - (setq org-ref-bibliography-files ()) + (goto-char (point-min)) + (while (re-search-forward "\\\\addbibresource{\\(.*\\)}" nil t) + (push (match-string 1) org-ref-bibliography-files)) - ;; look for org-ref bibliography or addbibresource links - (while (re-search-forward - ;; This just searches for these strings, and then checks if it - ;; is on a link. This is faster than parsing the org-file when - ;; it gets large. - "\\(bibliography\\|addbibresource\\):" - nil t) - (let ((link (org-element-context))) - (when (and (eq (car link) 'link) - (or - (string= (org-element-property :type link) "bibliography") - (string= (org-element-property :type link) "addbibresource"))) - (dolist (bibfile (org-ref-split-and-strip-string - (org-element-property :path link))) - (let ((bibf (org-ref-find-bibfile bibfile))) - (when bibf - (push bibf org-ref-bibliography-files))))))) - - (when org-ref-bibliography-files - (throw 'result - (setq org-ref-bibliography-files - (nreverse (delete-dups org-ref-bibliography-files))))) - - ;; Try addbibresource as a latex command. It appears that reftex does - ;; not do this correctly, it only finds the first one but there could be - ;; many. - (goto-char (point-min)) - (while (re-search-forward - "\\\\addbibresource{\\(.*\\)}" - nil t) - (push (match-string 1) org-ref-bibliography-files)) - - (when org-ref-bibliography-files - (throw 'result (setq org-ref-bibliography-files - (nreverse org-ref-bibliography-files)))) - - ;; we did not find org-ref links. now look for latex links - (goto-char (point-min)) - (setq org-ref-bibliography-files - (reftex-locate-bibliography-files default-directory)) - (when org-ref-bibliography-files - (throw 'result org-ref-bibliography-files))) - - - ;; we did not find anything. use defaults - (setq org-ref-bibliography-files org-ref-default-bibliography))) - - - ;; set reftex-default-bibliography so we can search - (set (make-local-variable 'reftex-default-bibliography) org-ref-bibliography-files) - org-ref-bibliography-files) + (when org-ref-bibliography-files + (throw 'result (nreverse (delete-dups (mapcar 'org-ref-get-bibfile-path org-ref-bibliography-files))))))) + ;; we did not find anything. use defaults. Make sure we have a list in + ;; case it is a single string. + (throw 'result (if (listp bibtex-completion-bibliography) + bibtex-completion-bibliography + (list bibtex-completion-bibliography))))))) (defun org-ref-key-in-file-p (key filename) @@ -2393,1848 +196,33 @@ set in `org-ref-default-bibliography'" (and (not (string-match "#" f)) (f-ext? f "bib")))) ;; and last in the default bibliography - org-ref-default-bibliography))) + (if (stringp bibtex-completion-bibliography) + (list bibtex-completion-bibliography) + bibtex-completion-bibliography)))) (defun org-ref-get-bibtex-key-and-file (&optional key) "Return a a cons cell of (KEY . file) that KEY is in. If no key is provided, get one under point." - (let ((org-ref-bibliography-files (org-ref-find-bibliography)) - (file)) - (unless key - (setq key (org-ref-get-bibtex-key-under-cursor))) - (setq file (catch 'result - (cl-loop for file in org-ref-bibliography-files do - (if (org-ref-key-in-file-p - key - (file-truename file)) - (throw 'result file))))) - (cons key (when (stringp file) (substring-no-properties file))))) + (unless key + (setq key (org-ref-get-bibtex-key-under-cursor))) + + (cons key (save-window-excursion + (let ((bibtex-completion-bibliography (org-ref-find-bibliography))) + (bibtex-completion-show-entry (list key)) + (buffer-file-name))))) -;;*** Generation of the cite links -(defmacro org-ref-make-completion-function (type) - "Macro to make a link completion function for a link of TYPE." - `(defun ,(intern (format "org-%s-complete-link" type)) (&optional arg) - (format - "%s:%s" - ,type - (completing-read - "bibtex key: " - (let ((bibtex-files (org-ref-find-bibliography))) - (bibtex-global-key-alist)))))) - - -(defmacro org-ref-make-format-function (type) - "Macro to make a format function for a link of TYPE." - `(defun ,(intern (format "org-ref-format-%s" type)) (keyword desc format) - ,(format "Formatting function for %s links.\n[[%s:KEYWORD][DESC]] -FORMAT is a symbol for the export backend. -Supported backends: 'html, 'latex, 'ascii, 'org, 'md, 'pandoc" type type) - (cond - ((eq format 'org) - (mapconcat - (lambda (key) - (format "[[#%s][%s]]" key key)) - (org-ref-split-and-strip-string keyword) ",")) - - ((eq format 'ascii) - (concat "[" - (mapconcat - (lambda (key) - (format "%s" key)) - (org-ref-split-and-strip-string keyword) ",") "]")) - - ((eq format 'html) - (mapconcat - (lambda (key) - (format org-ref-ref-html key key)) - (org-ref-split-and-strip-string keyword) ",")) - - ((eq format 'latex) - (if (string= (substring ,type -1) "s") - ;; biblatex format for multicite commands, which all end in s. These - ;; are formated as \cites{key1}{key2}... - (concat "\\" ,type - (mapconcat (lambda (key) (format "{%s}" key)) - (org-ref-split-and-strip-string keyword) "")) - ;; bibtex format - (concat "\\" ,type - (when desc (org-ref-format-citation-description desc)) "{" - (mapconcat - (lambda (key) key) - (org-ref-split-and-strip-string keyword) ",") - "}"))) - ;; simple format for odt. - ((eq format 'odt) - (format "[%s]" keyword)) - - ((eq format 'md) - (mapconcat (lambda (key) - ;; this is an html link that has an anchor to jump back to, - ;; and links to the entry in the bibliography. Also contains - ;; a tooltip. - (format "%s" - ;; this makes an anchor to return to - (md5 key) - key - ;; awful way to get a simple tooltip... I just need - ;; a simple formatted string, but the default has - ;; too much html stuff in it, and this needs to be - ;; cleaned of quotes and stuff, - (let ((org-ref-bibliography-files (org-ref-find-bibliography)) - (file) (entry) (bibtex-entry) (entry-type) (format) - (org-ref-bibliography-entry-format - '(("article" . "%a, %t, %j, v(%n), %p (%y).") - ("book" . "%a, %t, %u (%y).") - ("techreport" . "%a, %t, %i, %u (%y).") - ("proceedings" . "%e, %t in %S, %u (%y).") - ("inproceedings" . "%a, %t, %p, in %b, edited by %e, %u (%y)")))) - (setq file (catch 'result - (cl-loop for file in org-ref-bibliography-files do - (if (org-ref-key-in-file-p key (file-truename file)) - (throw 'result file) - (message "%s not found in %s" - key (file-truename file)))))) - (if file - (with-temp-buffer - (insert-file-contents file) - (bibtex-set-dialect (parsebib-find-bibtex-dialect) t) - (bibtex-search-entry key nil 0) - (setq bibtex-entry (bibtex-parse-entry)) - ;; downcase field names so they work in the format-citation code - (dolist (cons-cell bibtex-entry) - (setf (car cons-cell) (downcase (car cons-cell)))) - (setq entry-type (downcase (cdr (assoc "=type=" bibtex-entry)))) - - (setq format (cdr (assoc entry-type org-ref-bibliography-entry-format))) - (if format - (setq entry (org-ref-reftex-format-citation bibtex-entry format)) - ;; if no format, we use the bibtex entry itself as a fallback - (save-restriction - (bibtex-narrow-to-entry) - (setq entry (buffer-string))))) - "Key not found") - (replace-regexp-in-string "\"" "" (htmlize-escape-or-link entry))) - key)) - (s-split "," keyword) ",")) - ;; for pandoc we generate pandoc citations - ((eq format 'pandoc) - (cond - (desc ;; pre and or post text - (let* ((text (split-string desc "::")) - (pre (car text)) - (post (cadr text))) - (concat - (format "[@%s," keyword) - (when pre (format " %s" pre)) - (when post (format ", %s" post)) - "]"))) - (t - (format "[%s]" - (mapconcat - (lambda (key) (concat "@" key)) - (org-ref-split-and-strip-string keyword) - "; ")))))))) - - -(defun org-ref-format-citation-description (desc) - "Return formatted citation description. -If the cite link has a DESC (description), it is optional text -for the citation command. You can specify pre and post text by -separating these with ::, for example [[cite:key][pre text::post -text]]." - (cond - ((string-match "::" desc) - (let ((results (split-string desc "::"))) - (format "[%s][%s]" (nth 0 results) (nth 1 results)))) - (t (format "[%s]" desc)))) - - -(defun org-ref-bibtex-store-link () - "Store a link from a bibtex file. Only supports the cite link. -This essentially the same as the store link in org-bibtex, but it -creates a cite link." - (when (eq major-mode 'bibtex-mode) - (let* ((entry (mapcar - ;; repair strings enclosed in "..." or {...} - (lambda(c) - (if (string-match - "^\\(?:{\\|\"\\)\\(.*\\)\\(?:}\\|\"\\)$" (cdr c)) - (cons (car c) (match-string 1 (cdr c))) c)) - (save-excursion - (bibtex-beginning-of-entry) - (bibtex-parse-entry)))) - (link (concat "cite:" (cdr (assoc "=key=" entry))))) - (org-store-link-props - :key (cdr (assoc "=key=" entry)) - :author (or (cdr (assoc "author" entry)) "[no author]") - :editor (or (cdr (assoc "editor" entry)) "[no editor]") - :title (or (cdr (assoc "title" entry)) "[no title]") - :booktitle (or (cdr (assoc "booktitle" entry)) "[no booktitle]") - :journal (or (cdr (assoc "journal" entry)) "[no journal]") - :publisher (or (cdr (assoc "publisher" entry)) "[no publisher]") - :pages (or (cdr (assoc "pages" entry)) "[no pages]") - :url (or (cdr (assoc "url" entry)) "[no url]") - :year (or (cdr (assoc "year" entry)) "[no year]") - :month (or (cdr (assoc "month" entry)) "[no month]") - :address (or (cdr (assoc "address" entry)) "[no address]") - :volume (or (cdr (assoc "volume" entry)) "[no volume]") - :number (or (cdr (assoc "number" entry)) "[no number]") - :annote (or (cdr (assoc "annote" entry)) "[no annotation]") - :series (or (cdr (assoc "series" entry)) "[no series]") - :abstract (or (cdr (assoc "abstract" entry)) "[no abstract]") - :btype (or (cdr (assoc "=type=" entry)) "[no type]") - :type "bibtex" - :link link - :description (let ((bibtex-autokey-names 1) - (bibtex-autokey-names-stretch 1) - (bibtex-autokey-name-case-convert-function 'identity) - (bibtex-autokey-name-separator " & ") - (bibtex-autokey-additional-names " et al.") - (bibtex-autokey-year-length 4) - (bibtex-autokey-name-year-separator " ") - (bibtex-autokey-titlewords 3) - (bibtex-autokey-titleword-separator " ") - (bibtex-autokey-titleword-case-convert-function 'identity) - (bibtex-autokey-titleword-length 'infty) - (bibtex-autokey-year-title-separator ": ")) - (setq org-bibtex-description (bibtex-generate-autokey))))))) - - -;; This suppresses showing the warning buffer. helm-bibtex seems to make this -;; pop up in an irritating way. -(unless (boundp 'warning-suppress-types) - (require 'warnings)) - - -(add-to-list 'warning-suppress-types '(:warning)) - - -(defvar org-ref-buffer-hacked nil - "If non-nil this buffer has already been hacked and we don't need to do it again. -I use this so we only hack the variables once. This was added -because when you have local file/directory variables, it seems -like they don't get defined when font-lock is occurring, and it -results in warnings from `bibtex-completion' because it cannot -find the keys in the bibliographies. Doing this hack and the one -in `org-ref-cite-link-face-fn' makes the warnings go away. It -seems hacky, but the functions that fix it start with hack -so...") - -(make-variable-buffer-local 'org-ref-buffer-hacked) - -(defun org-ref-cite-link-face-fn (keys) - "Return a face for a cite link. -KEYS may be a comma-separated list of keys. -This is not smart enough yet to only highlight the bad key. If any key is bad, the whole cite will be red." - (unless org-ref-buffer-hacked - (hack-dir-local-variables) - (hack-local-variables-apply) - (setq org-ref-buffer-hacked t)) - - (save-match-data - (cond - ((or (not org-ref-show-broken-links) - (let ((bibtex-completion-bibliography (org-ref-find-bibliography))) - (-every? - 'identity - (mapcar - (lambda (key) - (if (string= key "*") - t - (assoc "=key=" - (bibtex-completion-get-entry key)))) - (split-string keys ","))))) - 'org-ref-cite-face) - (t - 'font-lock-warning-face)))) - +;; * Insert link functions ;;;###autoload -(defun org-ref-define-citation-link (type &optional key) - "Add a citation link of TYPE for `org-ref'. -With optional KEY, set the reftex binding. For example: -\(org-ref-define-citation-link \"citez\" ?z) will create a new -citez link, with reftex key of z, and the completion function." - (interactive "sCitation Type: \ncKey: ") - - ;; create the formatting function - (eval `(org-ref-make-format-function ,type)) - - (eval - `(if (fboundp 'org-link-set-parameters) - (org-link-set-parameters - ,type - :follow (lambda (_) (funcall org-ref-cite-onclick-function nil)) - :export (quote ,(intern (format "org-ref-format-%s" type))) - :complete (quote ,(intern (format "org-%s-complete-link" type))) - :help-echo (lambda (window object position) - (when org-ref-show-citation-on-enter - (save-excursion - (goto-char position) - ;; Here we wrap the citation string to a reasonable size. - (let ((s (org-ref-format-entry - (org-ref-get-bibtex-key-under-cursor)))) - (with-temp-buffer - (insert s) - (fill-paragraph) - (buffer-string)))))) - :face 'org-ref-cite-link-face-fn - :display 'full - :keymap org-ref-cite-keymap) - (org-add-link-type - ,type - (lambda (_path) (funcall org-ref-cite-onclick-function nil)) - (quote ,(intern (format "org-ref-format-%s" type)))))) - - ;; create the completion function - (eval `(org-ref-make-completion-function ,type)) - - ;; store new type so it works with adding citations, which checks - ;; for existence in this list - (add-to-list 'org-ref-cite-types type) - - (unless (assoc 'org reftex-cite-format-builtin) - (add-to-list 'reftex-cite-format-builtin '(org "org-ref citations" ()))) - - ;; and finally if a key is specified, we modify the reftex menu - (when key - (setf (nth 2 (assoc 'org reftex-cite-format-builtin)) - (append (nth 2 (assoc 'org reftex-cite-format-builtin)) - `((,key . ,(concat type ":%l"))))))) - - -(defun org-ref-generate-cite-links () - "Create all the link types and their completion functions." - (interactive) - (dolist (type org-ref-cite-types) - (when (fboundp 'org-link-set-parameters) - (when (assoc type org-link-parameters) - (display-warning 'org-ref - (format - "%s type is already defined, and will get redefined." - type) - :warning))) - (org-ref-define-citation-link type)) - (when (fboundp 'org-link-set-parameters) - (org-link-set-parameters "cite" :store #'org-ref-bibtex-store-link))) - - -;; This is what actually generated the cite links -(org-ref-generate-cite-links) - - -;;;###autoload -(defun org-ref-insert-cite-with-completion (type) - "Insert a cite link of TYPE with completion." - (interactive (list (completing-read "Type: " org-ref-cite-types))) - (insert (funcall (intern (format "org-%s-complete-link" type))))) - - -;;;###autoload -(defun org-ref-store-bibtex-entry-link () - "Save a citation link to the current bibtex entry. -Save in the default link type." - (interactive) - (let ((link (concat org-ref-default-citation-link - ":" - (save-excursion - (bibtex-beginning-of-entry) - (reftex-get-bib-field - "=key=" (bibtex-parse-entry)))))) - (message "saved %s" link) - (push (list link) org-stored-links) - (car org-stored-links))) - -;;* Index link -(org-ref-link-set-parameters "index" - :follow (lambda (path) - (occur path)) - :export (lambda (path desc format) - (cond - ((eq format 'latex) - (format "\\index{%s}" path))))) - - -;; this will generate a temporary index of entries in the file when clicked on. -;;;###autoload -(defun org-ref-index (&optional path) - "Open an *index* buffer with links to index entries. -PATH is required for the org-link, but it does nothing here." - (interactive) - (let ((*index-links* '()) - (*initial-letters* '())) - - ;; get links - (org-element-map (org-ref-parse-buffer) 'link - (lambda (link) - (let ((type (nth 0 link)) - (plist (nth 1 link))) - - (when (equal (plist-get plist ':type) "index") - (add-to-list - '*index-links* - (cons (plist-get plist :path) - (format - "[[elisp:(progn (switch-to-buffer \"%s\") (goto-char %s) (org-cycle '(64)))][%s]] " - (current-buffer) - (plist-get plist :begin) ;; position of link - ;; grab a description - (save-excursion - (goto-char (plist-get plist :begin)) - (if (thing-at-point 'sentence) - ;; get a sentence - (let ((s (thing-at-point 'sentence))) - (cl-loop for char in '("[" "]" "\n") - do - (setq s (replace-regexp-in-string - (regexp-quote char) " " s))) - (concat s " ")) - ;; or call it a link - "link"))))))))) - - ;; sort the links - (setq *index-links* (cl-sort *index-links* 'string-lessp :key 'car)) - - ;; now separate out into chunks first letters - (dolist (link *index-links*) - (add-to-list '*initial-letters* (substring (car link) 0 1) t)) - - ;; now create the index - (switch-to-buffer (get-buffer-create "*index*")) - (org-mode) - (erase-buffer) - (insert "#+TITLE: Index\n\n") - (dolist (letter *initial-letters*) - (insert (format "* %s\n" (upcase letter))) - ;; now process the links - (while (and - *index-links* - (string= letter (substring (car (car *index-links*)) 0 1))) - (let ((link (pop *index-links*))) - (insert (format "%s %s\n\n" (car link) (cdr link)))))) - (switch-to-buffer "*index*"))) - - -(org-ref-link-set-parameters "printindex" - :follow #'org-ref-index - :export (lambda (path desc format) - (cond - ((eq format 'latex) - (format "\\printindex"))))) - - -;;* Utilities -;;** create text citations from a bibtex entry - -(defun org-ref-bib-citation () - "From a bibtex entry, create and return a citation string. -If `bibtex-completion' library is loaded, return reference in APA -format. Otherwise return a citation string from `org-ref-get-bibtex-entry-citation'." - (save-excursion - (bibtex-beginning-of-entry) - (let* ((bibtex-expand-strings t) - (entry (bibtex-parse-entry t)) - (key (reftex-get-bib-field "=key=" entry))) - (org-ref-format-entry key)))) - - -;;** Open pdf in bibtex entry -;;;###autoload -(defun org-ref-open-bibtex-pdf () - "Open pdf for a bibtex entry, if it exists. -assumes point is in -the entry of interest in the bibfile. but does not check that." - (interactive) - (save-excursion - (bibtex-beginning-of-entry) - (let* ((bibtex-expand-strings t) - (entry (bibtex-parse-entry t)) - (key (reftex-get-bib-field "=key=" entry)) - (pdf (funcall org-ref-get-pdf-filename-function key))) - (if (file-exists-p pdf) - (org-open-link-from-string (format "[[file:%s]]" pdf)) - (ding))))) - - -(defun org-ref-notes-function-one-file (key) - "Function to open note belonging to KEY. - Set `org-ref-notes-function' to this function if you use one -long file with headlines for each entry." - ;; save key to clipboard to make saving pdf later easier by pasting. - (with-temp-buffer - (insert key) - (kill-ring-save (point-min) (point-max))) - (let ((entry (with-temp-buffer - (insert (org-ref-get-bibtex-entry key)) - (reftex-parse-bibtex-entry nil (point-min) (point-max))))) - - ;; add =key= and =type= for code which expects `bibtex-parse-entry` style - (add-to-list 'entry - (cons "=key=" (reftex-get-bib-field "&key" entry)) - (cons "=type=" (reftex-get-bib-field "&type" entry))) - - (save-restriction - (if org-ref-bibliography-notes - (find-file-other-window org-ref-bibliography-notes) - (error "org-ref-bibliography-notes is not set to anything")) - - (widen) - (goto-char (point-min)) - (let* ((headlines (org-element-map - (org-ref-parse-buffer) - 'headline 'identity)) - (keys (mapcar - (lambda (hl) (org-element-property :CUSTOM_ID hl)) - headlines))) - (if (-contains? keys key) - ;; we have it so we go to it. - (progn - (org-open-link-from-string (format "[[#%s]]" key)) - (funcall org-ref-open-notes-function)) - ;; no entry found, so add one - (goto-char (point-max)) - (insert (org-ref-reftex-format-citation - entry (concat "\n" org-ref-note-title-format))) - (mapc (lambda (x) - (save-restriction - (save-excursion - (funcall x)))) - org-ref-create-notes-hook) - (save-buffer)))))) - - -(defun org-ref-notes-function-many-files (thekey) - "Function to open note belonging to THEKEY. -Set `org-ref-notes-function' to this function if you use one file -for each bib entry." - (let ((bibtex-completion-bibliography (org-ref-find-bibliography))) - (bibtex-completion-edit-notes - (list (car (org-ref-get-bibtex-key-and-file thekey)))))) - -;;** Open notes from bibtex entry -;;;###autoload -(defun org-ref-open-bibtex-notes () - "From a bibtex entry, open the notes if they exist." - (interactive) - (bibtex-beginning-of-entry) - (let* ((cb (current-buffer)) - (bibtex-expand-strings t) - (entry (cl-loop for (key . value) in (bibtex-parse-entry t) - collect (cons (downcase key) (s-collapse-whitespace value)))) - (key (reftex-get-bib-field "=key=" entry))) - - ;; Issue 746. If the bibtex file is not in `org-ref-default-bibliography' - ;; you get an error. I think it is ok to just add this in a let-binding. I - ;; don't think duplicates matter, and this will eliminate issue 746 in part. - ;; You still need to have a bibliography file listed in the notes buffer, - ;; and this does not automatically do that. - (let* ((this-bib (buffer-file-name (current-buffer))) - (org-ref-default-bibliography (append - (list - this-bib) - org-ref-default-bibliography))) - (funcall org-ref-notes-function key)))) - - -;;** Open bibtex entry in browser -;;;###autoload -(defun org-ref-open-in-browser () - "Open the bibtex entry at point in a browser using the url field or doi field." - (interactive) - (save-excursion - (bibtex-beginning-of-entry) - (catch 'done - (let ((url (bibtex-autokey-get-field "url"))) - (when url - (browse-url url) - (throw 'done nil))) - - (let ((doi (bibtex-autokey-get-field "doi"))) - (when doi - (if (string-match "^http" doi) - (browse-url doi) - (browse-url (format "http://dx.doi.org/%s" doi))) - (throw 'done nil))) - (message "No url or doi found")))) - - -;;** Build a pdf of the bibtex file -;;;###autoload -(defun org-ref-build-full-bibliography () - "Build pdf of all bibtex entries, and open it." - (interactive) - (let* ((bibfile (file-name-nondirectory (buffer-file-name))) - (bib-base (file-name-sans-extension bibfile)) - (texfile (concat bib-base ".tex")) - (pdffile (concat bib-base ".pdf"))) - (find-file texfile) - (erase-buffer) - (insert (format "\\documentclass[12pt]{article} -\\usepackage[version=3]{mhchem} -\\usepackage{url} -\\usepackage[numbers]{natbib} -\\usepackage[colorlinks=true, linkcolor=blue, urlcolor=blue, pdfstartview=FitH]{hyperref} -\\usepackage{doi} -\\begin{document} -\\nocite{*} -\\bibliographystyle{unsrtnat} -\\bibliography{%s} -\\end{document}" bib-base)) - (save-buffer) - (shell-command (concat "pdflatex " bib-base)) - (shell-command (concat "bibtex " bib-base)) - (shell-command (concat "pdflatex " bib-base)) - (shell-command (concat "pdflatex " bib-base)) - (kill-buffer texfile) - (org-open-file pdffile))) - - -;;** Extract bibtex entries in org-file - -;;;###autoload -(defun org-ref-extract-bibtex-entries () - "Extract the bibtex entries in the current buffer into a bibtex src block." - (interactive) - (let* ((bibtex-files (org-ref-find-bibliography)) - (keys (reverse (org-ref-get-bibtex-keys))) - (bibtex-entry-kill-ring-max (length keys)) - (bibtex-entry-kill-ring '())) - - (save-window-excursion - (cl-loop for key in keys - do - (bibtex-search-entry key t) - (bibtex-kill-entry t))) - - (goto-char (point-max)) - (insert "\n\n") - (org-insert-heading) - (insert (format " Bibtex entries - -#+BEGIN_SRC bibtex :tangle %s -%s -#+END_SRC" - (let ((bibfile (concat (file-name-base - (or (buffer-file-name) "references")) - ".bib"))) - (if (file-exists-p bibfile) - (file-name-nondirectory - (read-file-name "Bibfile: " nil nil nil bibfile)) - bibfile)) - (mapconcat - 'identity - bibtex-entry-kill-ring - "\n\n"))))) - -;;;###autoload -(defun org-ref-extract-bibtex-to-file (bibfile &optional clobber) - "Extract all bibtex entries for citations buffer to BIBFILE. -If BIBFILE exists, append, unless you use a prefix arg (C-u), -which will CLOBBER the file." - (interactive - (list (read-file-name "Bibfile: " nil nil nil - (file-name-nondirectory - (concat (file-name-sans-extension - (buffer-file-name)) - ".bib"))) - current-prefix-arg)) - - (let* ((bibtex-files (org-ref-find-bibliography)) - (keys (reverse (org-ref-get-bibtex-keys))) - (bibtex-entry-kill-ring-max (length keys)) - (bibtex-entry-kill-ring '()) - (kill-cb (not (find-buffer-visiting bibfile))) - (cb (find-file-noselect bibfile)) - (current-bib-entries (with-current-buffer cb - (prog1 - (buffer-string) - (when kill-cb (kill-buffer cb)))))) - - (save-window-excursion - (cl-loop for key in keys - do - (bibtex-search-entry key t) - (bibtex-kill-entry t))) - - (with-temp-file bibfile - (unless clobber (insert current-bib-entries)) - (insert (mapconcat - 'identity - bibtex-entry-kill-ring - "\n\n"))))) - - -;;** Find bad citations -(defun org-ref-list-index (substring list) - "Return the index of SUBSTRING in a LIST of strings." - (seq-position list substring) - ;; (let ((i 0) - ;; (found nil)) - ;; (dolist (arg list i) - ;; (if (string-match (concat "^" substring "$") arg) - ;; (progn - ;; (setq found t) - ;; (cl-return i))) - ;; (setq i (+ i 1))) - ;; ;; return counter if found, otherwise return nil - ;; (if found i nil)) - ) - - -;;;###autoload -(defun org-ref-find-bad-citations () - "Create a list of citation keys that do not have a matching bibtex entry. -List is displayed in an `org-mode' buffer using the known bibtex -file. Makes a new buffer with clickable links." - (interactive) - ;; generate the list of bibtex-keys and cited keys - (let* ((bibtex-files (mapcar - 'file-name-nondirectory - (org-ref-find-bibliography))) - (bibtex-file-path (mapconcat - (lambda (x) - (file-name-directory (file-truename x))) - (org-ref-find-bibliography) - ":")) - (bibtex-keys (mapcar (lambda (x) - (car x)) - (bibtex-global-key-alist))) - (bad-citations '())) - - (org-element-map (org-ref-parse-buffer) 'link - (lambda (link) - (let ((plist (nth 1 link))) - (when (-contains? org-ref-cite-types - (plist-get plist :type)) - (cl-dolist (key (org-ref-split-and-strip-string - (plist-get plist :path))) - (when (not (org-ref-list-index key bibtex-keys)) - (setq - bad-citations - (append - bad-citations - `(,(format "%s [[elisp:(progn (switch-to-buffer-other-frame \"%s\")(goto-char %s))][not found here]]\n" - key - (buffer-name) - (plist-get plist :begin)))))))))) - ;; set with-affilates to t to get citations in a caption - nil nil nil t) - - (if bad-citations - (progn - (switch-to-buffer-other-window "*Missing citations*") - (org-mode) - (erase-buffer) - (insert "* List of bad cite links\n") - (insert (mapconcat 'identity bad-citations "")) - (use-local-map (copy-keymap org-mode-map)) - (local-set-key "q" #'(lambda () (interactive) (kill-buffer)))) - - (when (get-buffer "*Missing citations*") - (kill-buffer "*Missing citations*")) - (message "No bad cite links found")))) - - -;;** bad citations, labels, refs and files in orgfile -(defun org-ref-bad-cite-candidates () - "Return a list of conses (key . marker) where key does not exist in the known bibliography files, and marker points to the key." - (let* ((cp (point)) ; save to return to later - (bibtex-files (cl-loop for f in (org-ref-find-bibliography) - if (file-exists-p f) - collect (file-truename f))) - (bibtex-file-path (mapconcat - (lambda (x) - (file-name-directory (file-truename x))) - bibtex-files ":")) - (bibtex-keys (mapcar (lambda (x) (car x)) - (bibtex-global-key-alist))) - (bad-citations '())) - - (org-element-map (org-ref-parse-buffer) 'link - (lambda (link) - (let ((plist (nth 1 link))) - (when (-contains? org-ref-cite-types (plist-get plist :type)) - (when (not (string= "*" (plist-get plist :path))) - (dolist (key (org-ref-split-and-strip-string - (plist-get plist :path))) - (when (not (org-ref-list-index key bibtex-keys)) - (goto-char (plist-get plist :begin)) - (re-search-forward key) - (push (cons key (point-marker)) bad-citations))))))) - ;; add with-affiliates to get cites in caption - nil nil nil t) - (goto-char cp) - bad-citations)) - - -(defun org-ref-bad-ref-candidates () - "Return a list of conses (ref . marker) where ref is a ref link that does not point to anything (i.e. a label)." - ;; first get a list of legitimate labels - (let ((cp (point)) - (labels (org-ref-get-labels)) - (bad-refs '())) - ;; now loop over ref links - (goto-char (point-min)) - (org-element-map (org-ref-parse-buffer) 'link - (lambda (link) - (let ((plist (nth 1 link))) - (when (or (equal (plist-get plist ':type) "ref") - (equal (plist-get plist ':type) "eqref") - (equal (plist-get plist ':type) "pageref") - (equal (plist-get plist ':type) "nameref") - (equal (plist-get plist ':type) "autoref") - (equal (plist-get plist ':type) "cref") - (equal (plist-get plist ':type) "Cref")) - (unless (-contains? labels (plist-get plist :path)) - (goto-char (plist-get plist :begin)) - (add-to-list - 'bad-refs - (cons (plist-get plist :path) - (point-marker)))))))) - (goto-char cp) - bad-refs)) - - -(defun org-ref-bad-label-candidates () - "Return a list of labels where label is multiply defined." - (let ((labels (org-ref-get-labels)) - (multiple-labels '())) - ;; labels should be a unique list. - (dolist (label labels) - (when (> (org-ref-count-labels label) 1) - (let ((cp (point))) - (goto-char (point-min)) - ;; regular org label:tag links - (while (re-search-forward - (format "[^#+]label:%s\\s-" label) nil t) - (cl-pushnew (cons label (point-marker)) multiple-labels - :test (lambda (a b) - (and (string= (car a) (car b)) - (= (marker-position (cdr a)) - (marker-position (cdr b))))))) - - (goto-char (point-min)) - ;; latex style - (while (re-search-forward - (format "\\label{%s}\\s-?" label) nil t) - (cl-pushnew (cons label (point-marker)) multiple-labels - :test (lambda (a b) - (and (string= (car a) (car b)) - (= (marker-position (cdr a)) - (marker-position (cdr b))))))) - - ;; keyword style - (goto-char (point-min)) - (while (re-search-forward - (format "^\\( \\)*#\\+label:\\s-*%s" label) nil t) - (cl-pushnew (cons label (point-marker)) multiple-labels - :test (lambda (a b) - (and (string= (car a) (car b)) - (= (marker-position (cdr a)) - (marker-position (cdr b))))))) - - (goto-char (point-min)) - (while (re-search-forward - (format "^\\( \\)*#\\+tblname:\\s-*%s" label) nil t) - (cl-pushnew (cons label (point-marker)) multiple-labels - :test (lambda (a b) - (and (string= (car a) (car b)) - (= (marker-position (cdr a)) - (marker-position (cdr b))))))) - (goto-char cp)))) - multiple-labels)) - - -(defun org-ref-bad-file-link-candidates () - "Return list of conses (link . marker) where the file in the link does not exist." - (let* ((bad-files '())) - (org-element-map (org-ref-parse-buffer) 'link - (lambda (link) - (let ((type (org-element-property :type link))) - (when (or (string= "file" type) - (string= "attachfile" type)) - (unless (file-exists-p (org-element-property :path link)) - (add-to-list 'bad-files - (cons (org-element-property :path link) - (save-excursion - (goto-char - (org-element-property :begin link)) - (point-marker))))))))) - ;; Let us also check \attachfile{fname} - (save-excursion - (goto-char (point-min)) - (while (re-search-forward "\\\\attachfile{\\([^}]*\\)}" nil t) - (unless (file-exists-p (match-string 1)) - (add-to-list 'bad-files (cons (match-string 1) (point-marker)))))) - bad-files)) - - - -;;** Find non-ascii charaters -;;;###autoload -(defun org-ref-find-non-ascii-characters () - "Find non-ascii characters in the buffer. Useful for cleaning up bibtex files." - (interactive) - (occur "[^[:ascii:]]")) - - -;;** Sort fields in a bibtex entry -;;;###autoload -(defun org-ref-sort-bibtex-entry () - "Sort fields of entry in standard order." - (interactive) - (bibtex-beginning-of-entry) - (let* ((entry (bibtex-parse-entry)) - (entry-fields) - (other-fields) - (type (cdr (assoc "=type=" entry))) - (key (cdr (assoc "=key=" entry))) - (field-order (cdr (assoc (if type (downcase type)) - org-ref-bibtex-sort-order)))) - - ;; these are the fields we want to order that are in this entry - (setq entry-fields (mapcar (lambda (x) (car x)) entry)) - ;; we do not want to reenter these fields - (setq entry-fields (remove "=key=" entry-fields)) - (setq entry-fields (remove "=type=" entry-fields)) - - ;;these are the other fields in the entry, and we sort them alphabetically. - (setq other-fields - (sort (-remove (lambda(x) (member x field-order)) entry-fields) - 'string<)) - - (save-restriction - (bibtex-kill-entry) - (insert - (concat "@" type "{" key ",\n" - (mapconcat - (lambda (field) - (when (member field entry-fields) - (format "%s = %s," - field - (cdr (assoc field entry))))) - field-order "\n") - ;; now add the other fields - (mapconcat - (lambda (field) - (cl-loop for (f . v) in entry concat - (when (string= f field) - (format "%s = %s,\n" f v)))) - (-uniq other-fields) "\n") - "\n}")) - (bibtex-find-entry key) - (bibtex-fill-entry) - (bibtex-clean-entry)))) - -;; downcase entries -;;;###autoload -(defun org-ref-downcase-bibtex-entry () - "Downcase the entry type and fields." - (interactive) - (bibtex-beginning-of-entry) - (let* ((entry (bibtex-parse-entry)) - (entry-fields) - (type (downcase (cdr (assoc "=type=" entry)))) - (key (cdr (assoc "=key=" entry)))) - - (setq entry-fields (mapcar (lambda (x) (car x)) entry)) - ;; we do not want to reenter these fields - (setq entry-fields (remove "=key=" entry-fields)) - (setq entry-fields (remove "=type=" entry-fields)) - - (bibtex-kill-entry) - (insert - (concat "@" (downcase type) "{" key ",\n" - (mapconcat - (lambda (field) - (format "%s = %s," - (downcase field) - (cdr (assoc field entry)))) - entry-fields "\n") - "\n}\n\n")) - (bibtex-find-entry key) - (bibtex-fill-entry) - (bibtex-clean-entry))) - - -;;** Clean a bibtex entry -;; These functions operate on a bibtex entry and "clean" it in some way. - -(defun orcb-clean-nil (arg) - "Remove nil from some article fields. -The removal is conditional. Sometimes it is useful to have nil -around, e.g. for ASAP articles where the fields are not defined -yet but will be in the future. - -With \\[univeral-argument], run `bibtex-clean-entry' after. -" - (interactive "P") - (bibtex-beginning-of-entry) - (let* ((entry (bibtex-parse-entry)) - (type (downcase (cdr (assoc "=type=" entry))))) - (when (string= type "article") - (cond - ;; we have volume and pages but number is nil. - ;; remove the number field. - ((and (string= type "article") - (not (string= (cdr (assoc "volume" entry)) "{nil}")) - (not (string= (cdr (assoc "pages" entry)) "{nil}")) - (string= (cdr (assoc "number" entry)) "{nil}")) - (bibtex-set-field "number" "") - (if arg - (bibtex-clean-entry))))))) - - -(defun orcb-clean-nil-opinionated () - "Remove nil from all article fields. - -Note that by default, this will leave the entry empty, which may -then get deleted by `bibtex-clean-entry.' To disable this -behavior, remove opts-or-alts from `bibtex-entry-format'. This -will leave the empty entries so that you may fill them in later." - (interactive) - (bibtex-beginning-of-entry) - (let* ((entry (bibtex-parse-entry)) - (type (downcase (cdr (assoc "=type=" entry))))) - (when (string= type "article") - (cl-loop for (field . text) in entry do - (if (string= text "{nil}") - (bibtex-set-field field "")))))) - - -(defun orcb-clean-doi () - "Remove http://dx.doi.org/ in the doi field." - (let ((doi (bibtex-autokey-get-field "doi"))) - (when (string-match "^http://dx.doi.org/" doi) - (bibtex-beginning-of-entry) - (goto-char (car (cdr (bibtex-search-forward-field "doi" t)))) - (bibtex-kill-field) - (bibtex-make-field "doi") - (backward-char) - (insert (replace-regexp-in-string "^http://dx.doi.org/" "" doi))))) - - -(defun orcb-clean-year (&optional new-year) - "Fix years set to 0. -If optional NEW-YEAR set it to that, otherwise prompt for it." - ;; asap articles often set year to 0, which messes up key - ;; generation. fix that. - (let ((year (bibtex-autokey-get-field "year"))) - (when (string= "0" year) - (bibtex-beginning-of-entry) - (goto-char (car (cdr (bibtex-search-forward-field "year" t)))) - (bibtex-kill-field) - (bibtex-make-field "year") - (backward-char) - (insert (or new-year (read-string "Enter year: ")))))) - - -(defun orcb-clean-pages () - "Check for empty pages, and put eid in its place if it exists." - (let ((pages (bibtex-autokey-get-field "pages")) - (eid (bibtex-autokey-get-field "eid"))) - (when (and (not (string= "" eid)) - (or (string= "" pages))) - (bibtex-set-field "pages" eid)))) - - -(defun orcb-& () - "Replace naked & with \& in a bibtex entry." - (save-restriction - (bibtex-narrow-to-entry) - (bibtex-beginning-of-entry) - (while (re-search-forward " & " nil t) - (replace-match " \\\\& ")))) - - -(defvar orcb-%-replacement-string " \\\\%" - "Replacement for a naked % sign in cleaning a BibTeX entry. -The replacement string should be escaped for use with -`replace-match'. Compare to the default value. Common choices -would be to omit the space or to replace the space with a ~ for a -non-breaking space.") - -(defun orcb-% () - "Replace naked % with % in a bibtex entry. -Except when it is already escaped or in a URL. The replacement -for the % is defined by `orcb-%-replacement-string'." - (save-restriction - (bibtex-narrow-to-entry) - (bibtex-beginning-of-entry) - (while (re-search-forward "\\([^\\]\\)%\\([^[:xdigit:]]\\)" nil t) - (replace-match (concat "\\1" - orcb-%-replacement-string - "\\2"))))) - - -(defun orcb-key-comma () - "Make sure there is a comma at the end of the first line." - (bibtex-beginning-of-entry) - (end-of-line) - ;; some entries do not have a key or comma in first line. We check and add it, - ;; if needed. - (unless (string-match ", *$" (thing-at-point 'line)) - (end-of-line) - (insert ","))) - - -(defun orcb-key (&optional allow-duplicate-keys) - "Replace the key in the entry. -Prompts for replacement if the new key duplicates one already in -the file, unless ALLOW-DUPLICATE-KEYS is non-nil." - (let ((key (funcall org-ref-clean-bibtex-key-function - (bibtex-generate-autokey)))) - ;; remove any \\ in the key - (setq key (replace-regexp-in-string "\\\\" "" key)) - ;; first we delete the existing key - (bibtex-beginning-of-entry) - (re-search-forward bibtex-entry-maybe-empty-head) - (if (match-beginning bibtex-key-in-head) - (delete-region (match-beginning bibtex-key-in-head) - (match-end bibtex-key-in-head))) - ;; check if the key is in the buffer - (when (and (not allow-duplicate-keys) - (save-excursion - (bibtex-search-entry key))) - (save-excursion - (bibtex-search-entry key) - (bibtex-copy-entry-as-kill) - (switch-to-buffer-other-window "*duplicate entry*") - (bibtex-yank)) - (setq key (bibtex-read-key "Duplicate Key found, edit: " key))) - - (insert key) - (kill-new key))) - - -(defun orcb-check-journal () - "Check entry at point to see if journal exists in `org-ref-bibtex-journal-abbreviations'. -If not, issue a warning." - (interactive) - (when - (string= "article" - (downcase - (cdr (assoc "=type=" (bibtex-parse-entry))))) - (save-excursion - (bibtex-beginning-of-entry) - (let* ((entry (bibtex-parse-entry t)) - (journal (reftex-get-bib-field "journal" entry))) - (when (null journal) - (error "Unable to get journal for this entry.")) - (unless (member journal (-flatten org-ref-bibtex-journal-abbreviations)) - (message "Journal \"%s\" not found in org-ref-bibtex-journal-abbreviations." journal)))))) - - -(defun orcb-fix-spacing () - "Delete whitespace and fix spacing between entries." - (let (beg end) - (save-excursion - (save-restriction - (widen) - (bibtex-beginning-of-entry) - (setq beg (point)) - (bibtex-end-of-entry) - (setq end (if (re-search-forward bibtex-any-entry-maybe-empty-head nil t) - (progn (beginning-of-line) - (point)) - (point-max))) - ;; 1. delete whitespace - (narrow-to-region beg end) - (delete-trailing-whitespace) - ;; 2. delete consecutive empty lines - (goto-char end) - (while (re-search-backward "\n\n\n+" nil 'move) - (replace-match "\n\n")) - ;; 3. add one line between entries - (goto-char end) - (forward-line -1) - (when (looking-at "[}][ \t]*\\|@Comment.+\\|%.+") - (end-of-line) - (newline)))))) - - -;;;###autoload -(defun org-ref-clean-bibtex-entry () - "Clean and replace the key in a bibtex entry. -See functions in `org-ref-clean-bibtex-entry-hook'." - (interactive) - (save-excursion - (save-restriction - (bibtex-narrow-to-entry) - (bibtex-beginning-of-entry) - ;; run hooks. each of these operates on the entry with no arguments. - ;; this did not work like i thought, it gives a symbolp error. - ;; (run-hooks org-ref-clean-bibtex-entry-hook) - (mapc (lambda (x) - (save-restriction - (save-excursion - (funcall x)))) - org-ref-clean-bibtex-entry-hook)))) - -(defun org-ref-get-citation-year (key) - "Get the year of an entry with KEY. Return year as a string." - (let* ((results (org-ref-get-bibtex-key-and-file key)) - (bibfile (cdr results))) - (with-temp-buffer - (insert-file-contents bibfile) - (bibtex-set-dialect (parsebib-find-bibtex-dialect) t) - (bibtex-search-entry key nil 0) - (prog1 (reftex-get-bib-field "year" (bibtex-parse-entry t)))))) - -;;** Sort cite in cite link -;;;###autoload -(defun org-ref-sort-citation-link () - "Replace link at point with sorted link by year." - (interactive) - (let* ((object (org-element-context)) - (type (org-element-property :type object)) - (begin (org-element-property :begin object)) - (end (org-element-property :end object)) - (link-string (org-element-property :path object)) - keys years data) - (setq keys (org-ref-split-and-strip-string link-string)) - (setq years (mapcar 'org-ref-get-citation-year keys)) - (setq data (-zip-with 'cons years keys)) - (setq data (cl-sort data (lambda (x y) - (< (string-to-number (car x)) - (string-to-number (car y)))))) - ;; now get the keys separated by commas - (setq keys (mapconcat (lambda (x) (cdr x)) data ",")) - (save-excursion - (goto-char begin) - (re-search-forward link-string) - (replace-match keys)))) - - -;;** Shift-arrow sorting of keys in a cite link -(defun org-ref-swap-keys (i j keys) - "Swap index I and J in the list KEYS." - (let ((tempi (nth i keys))) - (setf (nth i keys) (nth j keys)) - (setf (nth j keys) tempi)) - keys) - - -;;;###autoload -(defun org-ref-swap-citation-link (direction) - "Move citation at point in DIRECTION +1 is to the right, -1 to the left." - (interactive) - (let* ((object (org-element-context)) - (type (org-element-property :type object)) - (begin (org-element-property :begin object)) - (end (org-element-property :end object)) - (link-string (org-element-property :path object)) - key keys i) - ;; We only want this to work on citation links - (when (-contains? org-ref-cite-types type) - (setq key (org-ref-get-bibtex-key-under-cursor)) - (setq keys (org-ref-split-and-strip-string link-string)) - (setq i (org-ref-list-index key keys)) ;; defined in org-ref - (if (> direction 0) ;; shift right - (org-ref-swap-keys i (+ i 1) keys) - (org-ref-swap-keys i (- i 1) keys)) - (setq keys (mapconcat 'identity keys ",")) - ;; and replace the link with the sorted keys - (save-excursion - (goto-char begin) - (re-search-forward link-string) - (replace-match keys)) - ;; now go forward to key so we can move with the key - (re-search-forward key) - (goto-char (match-beginning 0))))) - - -;;** C-arrow navigation of cite keys -(defun org-ref-parse-cite () - "Parse link to get cite keys, and start and end of the keys." - (interactive) - (let ((link (org-element-context)) - path begin end - keys) - - (unless (-contains? org-ref-cite-types - (org-element-property :type link)) - (error "Not on a cite link")) - (setq path (org-element-property :path link) - begin (org-element-property :begin link) - end (org-element-property :end link)) - - (setq keys (org-ref-split-and-strip-string path)) - (save-excursion - (cl-loop for key in keys - do - (goto-char begin) - (re-search-forward key end) - collect - (list key (match-beginning 0) (match-end 0)))))) - - -;;;###autoload -(defun org-ref-next-key () - "Move cursor to the next cite key when on a cite link. -Otherwise run `right-word'. If the cursor moves off the link, -move to the beginning of the next cite link after this one." - (interactive) - (let ((cps (org-ref-parse-cite)) - (p (point))) - (cond - ;; point is before first key - ((< (point) (nth 1 (car cps))) - (goto-char (nth 1 (car cps)))) - ;; point is on a single key, or on the last key - ((or (= 1 (length cps)) - (> p (nth 1 (car (last cps))))) - (re-search-forward org-ref-cite-re nil t) - (goto-char (match-end 1)) - (forward-char 1)) - ;; in a link with multiple keys. We need to figure out if there is a - ;; next key and go to beginning - (t - (goto-char (min - (point-max) - (+ 1 - (cl-loop for (k s e) in cps - if (and (>= p s) - (<= p e)) - return e)))))) - ;; if we get off a link,jump to the next one. - (when - (not (-contains? org-ref-cite-types - (org-element-property - :type - (org-element-context)))) - (when (re-search-forward org-ref-cite-re nil t) - (goto-char (match-beginning 0)) - (re-search-forward ":"))))) - - -;;;###autoload -(defun org-ref-previous-key () - "Move cursor to the previous cite key when on a cite link. -Otherwise run `left-word'. If the cursor moves off the link, -move to the beginning of the previous cite link after this one." - (interactive) - (let ((cps (org-ref-parse-cite)) - (p (point)) - index) - (cond - ;; point is on or before first key, go to previous link. - ((<= (point) (nth 1 (car cps))) - (unless (re-search-backward org-ref-cite-re nil t) - (left-word)) - (when (re-search-backward org-ref-cite-re nil t) - (goto-char (match-end 0)) - (re-search-backward ",\\|:") - (forward-char))) - ;; point is less than end of first key, goto beginning - ((< p (nth 2 (car cps))) - ;; we do this twice. the first one just goes to the beginning of the - ;; current link - (goto-char (nth 1 (car cps)))) - ;; in a link with multiple keys. We need to figure out if there is a - ;; previous key and go to beginning - (t - (setq index (cl-loop - for i from 0 - for (k s e) in cps - if (and (>= p s) - (<= p e)) - return i)) - (goto-char (nth 1 (nth (- index 1) cps))))))) - -(defvar org-ref-equation-environments - '("equation" - "equation*" - "align" - "align*" - "multline" - "multline*") - "LaTeX environments that should be treated as equations when referencing.") - -(defvar org-ref-ref-type-inference-alist - '((org-ref-equation-label-p . "eqref")) - "Alist of predicate functions taking a label name and the - desired reference type if the predicate returns true.") - -(defun org-ref-enclosing-environment (label) - "Returns the name of the innermost LaTeX environment containing -the first instance of the label, or nil of there is none." - (save-excursion - (save-restriction - (widen) - (goto-char (point-min)) - (let ((label-point (search-forward (format "\\label{%s}" label) nil t))) - (when label-point - (catch 'return - (let (last-begin-point last-env) - (while (setq - last-begin-point (re-search-backward "\\\\begin{\\([^}]+\\)}" nil t) - last-env (match-string-no-properties 1)) - (let ((env-end-point - (search-forward (format "\\end{%s}" last-env) nil t))) - (if (and env-end-point - (> env-end-point label-point)) - (throw 'return last-env) - (goto-char last-begin-point))))))))))) - -(defun org-ref-equation-label-p (label) - "Return non-nil if LABEL is an equation label." - (let ((maybe-env (org-ref-enclosing-environment label))) - (when maybe-env - (member maybe-env org-ref-equation-environments)))) - -(defun org-ref-infer-ref-type (label) - "Return inferred type for LABEL." - (or (cl-dolist (pred-pair org-ref-ref-type-inference-alist) - (when (funcall (car pred-pair) label) - (cl-return (eval (cdr pred-pair))))) - org-ref-default-ref-type)) - -;;** context around org-ref links -(defun org-ref-get-label-context (label) - "Return a string of context around a LABEL." - (save-excursion - (save-restriction - (widen) - (catch 'result - (goto-char (point-min)) - (when (re-search-forward - (format "label:%s\\b" label) nil t) - (throw 'result (buffer-substring - (progn - (forward-line -1) - (beginning-of-line) - (point)) - (progn - (forward-line 4) - (point))))) - - (goto-char (point-min)) - (when (re-search-forward - (format "\\label{%s}" label) nil t) - (throw 'result (buffer-substring - (progn - (forward-line -1) - (beginning-of-line) - (point)) - (progn - (forward-line 4) - (point))))) - - (goto-char (point-min)) - (when (re-search-forward - (format "^\\( \\)*#\\+label:\\s-*\\(%s\\)\\b" label) nil t) - (throw 'result (buffer-substring - (progn - (forward-line -1) - (beginning-of-line) - (point)) - (progn - (forward-line 4) - (point))))) - - (goto-char (point-min)) - (when (re-search-forward - (format "^\\( \\)*#\\+tblname:\\s-*\\(%s\\)\\b" label) nil t) - (throw 'result (buffer-substring - (progn - (forward-line -1) - (beginning-of-line) - (point)) - (progn - (forward-line 4) - (point))))) - - (goto-char (point-min)) - (when (re-search-forward - (format "^\\( \\)*#\\+name:\\s-*\\(%s\\)\\b" label) nil t) - (throw 'result (buffer-substring - (progn - (forward-line -1) - (beginning-of-line) - (point)) - (progn - (forward-line 4) - (point))))) - ;; ;; CUSTOM_ID - (goto-char (point-min)) - ;; do we have a CUSTOM-ID? - (let ((heading (org-map-entries - (lambda () - (buffer-substring - (progn - (forward-line -1) - (beginning-of-line) - (point)) - (progn - (forward-line 4) - (point)))) - (format "CUSTOM_ID=\"%s\"" label)))) - ;; (message-box heading) - (when heading - (throw 'result (car heading)))) - ;; radio target - (goto-char (point-min)) - (when (re-search-forward (format "<<%s>>" (regexp-quote label)) nil t) - (throw 'result (match-string 0))) - - - (throw 'result "!!! NO CONTEXT FOUND !!!"))))) - - -;;;###autoload -(defun org-ref-link-message () - "Print a minibuffer message about the link that point is on." - (interactive) - ;; the way links are recognized in org-element-context counts blank spaces - ;; after a link and the closing brackets in literal links. We don't try to get - ;; a message if the cursor is on those, or if it is on a blank line. - (when (not (or (looking-at " ") ;looking at a space - (looking-at "^$") ;looking at a blank line - (looking-at "]") ;looking at a bracket at the end - ;looking at the end of the line. - (looking-at "$"))) - - (save-restriction - (widen) - (when (eq major-mode 'org-mode) - (let* ((object (org-element-context)) - (type (org-element-property :type object))) - (save-excursion - (cond - ;; cite links - ((-contains? org-ref-cite-types type) - (let ((key (org-ref-get-bibtex-key-under-cursor))) - (if (string= "*" key) - "*" - (message (org-ref-format-entry key))))) - - ;; message some context about the label we are referring to - ((or (string= type "ref") - (string= type "cref") - (string= type "eqref") - (string= type "pageref") - (string= type "nameref") - (string= type "autoref")) - (if - (= (org-ref-count-labels - (org-element-property :path object)) - 0) - (message "!!! NO CONTEXT FOUND !!!count: 0") - (message "%scount: %s" - (org-ref-get-label-context - (org-element-property :path object)) - (org-ref-count-labels - (org-element-property :path object))))) - - ;; message the count - ((string= type "label") - (let ((count (org-ref-count-labels - (org-element-property :path object)))) - ;; get plurality on occurrence correct - (message (concat - (number-to-string count) - " occurrence" - (when (or (= count 0) - (> count 1)) - "s"))))) - - ((string= type "custom-id") - (save-excursion - (org-open-link-from-string - (format "[[#%s]]" (org-element-property :path object))) - (message "%s" (org-get-heading)))) - - ;; check if the bibliography files exist. - ((string= type "bibliography") - (let* ((bibfile) - ;; object is the link you clicked on - (object (org-element-context)) - (link-string (org-element-property :path object)) - (link-string-beginning) - (link-string-end)) - (save-excursion - (goto-char (org-element-property :begin object)) - (search-forward link-string nil nil 1) - (setq link-string-beginning (match-beginning 0)) - (setq link-string-end (match-end 0))) - - ;; make sure we are in link and not before the : - (when (> link-string-beginning (point)) - (goto-char link-string-beginning)) - - (let (key-beginning key-end) - ;; now if we have comma separated bibliographies - ;; we find the one clicked on. we want to - ;; search forward to next comma from point - (save-excursion - (if (search-forward "," link-string-end 1 1) - (setq key-end (- (match-end 0) 1)) ; we found a match - (setq key-end (point)))) ; no comma found so take the point - - ;; and backward to previous comma from point - (save-excursion - (if (search-backward "," link-string-beginning 1 1) - (setq key-beginning (+ (match-beginning 0) 1)) ; we found a match - (setq key-beginning (point)))) ; no match found - ;; save the key we clicked on. - (setq bibfile - (org-ref-strip-string - (buffer-substring key-beginning key-end))) - (let ((file (org-ref-find-bibfile bibfile))) - (message (if file "%s exists." "!!! %s NOT FOUND !!!") - (or file bibfile))))))))))))) - -;;** aliases -(defalias 'oro 'org-ref-open-citation-at-point) -(defalias 'orc 'org-ref-citation-at-point) -(defalias 'orp 'org-ref-open-pdf-at-point) -(defalias 'oru 'org-ref-open-url-at-point) -(defalias 'orn 'org-ref-open-notes-at-point) - - -(defalias 'orib 'org-ref-insert-bibliography-link) -(defalias 'oric 'org-ref-insert-cite-link) -(defalias 'orir 'org-ref-insert-ref-link) -(defalias 'orsl 'org-ref-store-bibtex-entry-link) - -(defalias 'orcb 'org-ref-clean-bibtex-entry) - -(defun org-ref-delete-cite-at-point () - "Delete the citation link at point." - (let* ((cite (org-element-context)) - (type (org-element-property :type cite))) - (when (-contains? org-ref-cite-types type) - (cl--set-buffer-substring - (org-element-property :begin cite) - (org-element-property :end cite) - "")))) - - -(defun org-ref-update-pre-post-text () - "Prompt for pre/post text and update link accordingly. -A blank string deletes pre/post text." - (save-excursion - (let* ((cite (org-element-context)) - (type (org-element-property :type cite)) - (key (org-element-property :path cite)) - (text (read-from-minibuffer "Pre/post text: "))) - ;; First we delete the citation - (when (-contains? org-ref-cite-types type) - (cl--set-buffer-substring - (org-element-property :begin cite) - (org-element-property :end cite) - "")) - ;; Then we reformat the citation - (if (string= text "") - (progn - (insert (format "%s:%s " type key)) - ;; Avoid space before punctuation - (when (looking-at "[[:punct:]]") - (delete-char 1))) - (insert (format "[[%s:%s][%s]] " type key text)) - (when (looking-at "[[:punct:]]") - (delete-char 1)))))) - - -(defun org-ref-delete-key-at-point () - "Delete the key at point." - (save-excursion - (let* ((cite (org-element-context)) - (path (org-element-property :path cite)) - (keys (org-ref-split-and-strip-string path)) - (key (org-ref-get-bibtex-key-under-cursor)) - (begin (org-element-property :begin cite)) - (end (org-element-property :end cite)) - (type (org-element-property :type cite)) - (bracketp (string= "[[" (buffer-substring begin (+ 2 begin)))) - (trailing-space (if (save-excursion - (goto-char end) - (string= (string (preceding-char)) " ")) - " " ""))) - - (setq keys (-remove-item key keys)) - (setf (buffer-substring begin end) - (concat - (when bracketp "[[") - type ":" (mapconcat 'identity keys ",") - (when bracketp "]]") - trailing-space)) - (kill-new key)))) - - -(defun org-ref-insert-key-at-point (keys) - "Insert KEYS at point. -KEYS is a list of bibtex keys. If point is at : or earlier, -insert at the beginning. Otherwise, insert after the key at -point. Leaves point at end of added keys." - (interactive - (list - (funcall org-ref-cite-completion-function))) - (let* ((cite (org-element-context)) - (type (org-element-property :type cite)) - (p (point)) - begin end - opath - okey okeys - ikey - bracket-p - trailing-space - newkeys - new-cite) - - (cond - ;; on a link, and before the keys. Insert keys at the beginning. - ((and (-contains? org-ref-cite-types type) - (< (point) (+ (org-element-property :begin cite) - (length type) 1))) - (setq - begin (org-element-property :begin cite) - end (org-element-property :end cite) - opath (org-element-property :path cite) - okeys (org-ref-split-and-strip-string opath) - newkeys (append keys okeys) - bracket-p (string= "[" (buffer-substring begin (+ 1 begin))) - new-cite (concat - (when bracket-p "[[") - type - ":" - (mapconcat 'identity newkeys ",") - (when bracket-p "]]") - trailing-space))) - - ;; on a link, stick new keys after current key - ((or (-contains? org-ref-cite-types type) - (and (not (bobp)) - (save-excursion - (forward-char -1) - (-contains? - org-ref-cite-types - (org-element-property :type (org-element-context)))))) - - ;; we are after a cite. get back on it - (when (save-excursion - (forward-char -1) - (-contains? - org-ref-cite-types - (org-element-property :type (org-element-context)))) - (forward-char -1)) - - (setq - cite (org-element-context) - type (org-element-property :type cite) - begin (org-element-property :begin cite) - end (org-element-property :end cite) - opath (org-element-property :path cite) - okeys (org-ref-split-and-strip-string opath) - okey (org-ref-get-bibtex-key-under-cursor) - ikey (org-ref-list-index okey okeys) - bracket-p (string= "[" (buffer-substring begin (+ 1 begin))) - trailing-space (if (save-excursion - (goto-char end) - (string= (string (preceding-char)) " ")) - " " "") - newkeys (-flatten (-insert-at (+ 1 ikey) keys okeys)) - new-cite (concat - (when bracket-p "[[") - type - ":" - (mapconcat 'identity newkeys ",") - (when bracket-p "]]") - trailing-space))) - ;; Looking back at a link beginning that a user has typed in - ((save-excursion - (backward-word 1) - (looking-at (regexp-opt org-ref-cite-types))) - (setq begin (point) - end (point) - newkeys keys - new-cite (mapconcat 'identity keys ","))) - ;; a new cite - (t - (setq - begin (point) - end (point) - type org-ref-default-citation-link - newkeys keys - bracket-p org-ref-prefer-bracket-links - new-cite (concat - (when bracket-p "[[") - type - ":" - (mapconcat 'identity newkeys ",") - (when bracket-p "]]") - trailing-space)))) - ;; post link processing after all the variables habe been defined for each - ;; case - (delete-region begin end) - (goto-char begin) - (insert new-cite) - (goto-char begin) - (re-search-forward (mapconcat 'identity keys ",")) - (when (looking-at "]") - (forward-char 2)))) - - -(defun org-ref-replace-key-at-point (&optional replacement-keys) - "Replace the key at point. -Optional REPLACEMENT-KEYS should be a string of comma-separated -keys. if it is not specified, find keys interactively." - (save-excursion - (let* ((cite (org-element-context)) - (opath (org-element-property :path cite)) - (okeys (org-ref-split-and-strip-string opath)) - (okey (org-ref-get-bibtex-key-under-cursor)) - (end (org-element-property :end cite))) - ;; First, insert new keys at end - (save-excursion - (goto-char end) - (skip-chars-backward " ") - (if replacement-keys - (insert (format ",%s" replacement-keys)) - (funcall org-ref-insert-cite-function))) - - ;; Now get the new keys, delete the old one and put the new ones in - (let* ((cite (org-element-context)) - (type (org-element-property :type cite)) - (path (org-element-property :path cite)) - (keys (org-ref-split-and-strip-string path)) - (new-keys (-difference keys okeys)) - (key (org-ref-get-bibtex-key-under-cursor)) - (begin (org-element-property :begin cite)) - (end (org-element-property :end cite)) - (bracketp (string= "[[" (buffer-substring begin (+ 2 begin)))) - (trailing-space (if (save-excursion - (goto-char end) - (string= (string (preceding-char)) " ")) - " " "")) - (index (org-ref-list-index key keys))) - ;; keys here has the old key at index, and the new keys at the end. - ;; delete old key - (setq keys (-remove-at index keys)) - (dolist (nkey (reverse new-keys)) - (setq keys (-insert-at index nkey keys))) - - ;; now remove off the end keys which are now duplicated. - (setq keys (nbutlast keys (length new-keys))) - - (setf (buffer-substring begin end) - (concat - (when bracketp "[[") - type ":" (mapconcat 'identity keys ",") - (when bracketp "]]") - trailing-space)))))) - - (defun org-ref-insert-link (arg) "Insert an org-ref link. If no prefix ARG insert a cite. If one prefix ARG insert a ref. If two prefix ARGs insert a label. -This is a generic function. Specific completion engines might +This is a generic function. Specific backends might provide their own version." (interactive "P") (cond @@ -4245,6 +233,64 @@ provide their own version." ((equal arg '(16)) (funcall org-ref-insert-label-function)))) + +;; This is an alternative that doesn't rely on prefix args. +(defhydra org-ref-insert-link-hydra (:color red :hint nil) + "Insert an org-ref link +" + ("[" (funcall org-ref-insert-cite-function) "Citation" :column "org-ref") + ("]" (funcall org-ref-insert-ref-function) "Cross-reference" :column "org-ref") + ("\\" (funcall org-ref-insert-label-function) "Label" :column "org-ref") + + ("bs" (insert (org-ref-bibliographystyle-complete-link)) "Bibliographystyle" :column "Bibliography" :color blue) + ("bf" (insert (org-ref-bibliography-complete)) "Bibliography" :column "Bibliography" :color blue) + ("nb" (insert (org-ref-nobibliography-complete)) "Bibliography" :column "Bibliography" :color blue) + + ("g" org-ref-insert-glossary-link "Glossary link" :column "Glossary" :color blue) + ("a" org-ref-insert-acronym-link "Acronym link" :column "Glossary" :color blue) + ("ng" (progn + (org-mark-ring-push) + (goto-char (point-min)) + (if (re-search-forward "#\\+name: glossary" nil t) + (progn + (goto-char (org-element-property :contents-end (org-element-context))) + (backward-char) + (org-table-insert-row '(4))) + ;; no table found + (goto-char (point-max)) + (insert "\n\n#+name: glossary +| label | term | definition | +|-------+---------+-------------------------------| +| | | |") + (beginning-of-line) + (forward-char))) + "New glossary term" :column "Glossary") + + ("na" (progn + (org-mark-ring-push) + (goto-char (point-min)) + (if (re-search-forward "#\\+name: acronym" nil t) + (progn + (goto-char (org-element-property :contents-end (org-element-context))) + (backward-char) + (org-table-insert-row '(4))) + ;; no table found + (goto-char (point-max)) + (insert "\n\n#+name: acronyms +| label | abbreviation | full form | +|-------+--------------+----------------------------| +| | | |") + (beginning-of-line) + (forward-char))) + "New acronym term" :column "Glossary") + + ("t" (insert "[[list-of-tables:]]\n") "List of tables" :column "Misc") + ("f" (insert "[[list-of-figures:]]\n") "List of figures" :column "Misc") + ("i" (insert (format "[[index:%s]]" (string-trim (read-string "Index entry: ")))) "Index entry" :column "Misc") + ("pi" (insert "[[printindex:]]") "Print index" :column "Misc") + ("pg" (insert "[[printglossaries:]]") "Print glossary" :column "Misc")) + + ;;* org-ref-help ;;;###autoload (defun org-ref-help () @@ -4272,8 +318,6 @@ provide their own version." ["Extract bibtex entries" org-ref-extract-bibtex-entries] ["Check org-file" org-ref] "--" - ["Change completion backend" org-ref-change-completion] - "--" ["Help" org-ref-help] ["Customize org-ref" (customize-group 'org-ref)]) "Show/Hide") diff --git a/lisp/org-ref/org-ref-export.el b/lisp/org-ref/org-ref-export.el new file mode 100644 index 00000000..cfbb5063 --- /dev/null +++ b/lisp/org-ref/org-ref-export.el @@ -0,0 +1,594 @@ +;;; org-ref-export.el --- org-ref-export library -*- lexical-binding: t; -*- +;; +;; Copyright (C) 2021 John Kitchin + +;; Author: John Kitchin +;; Keywords: convenience + +;; 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: +;; This is an export library that uses CSL to process the citations and bibliography. +;; +;; It is intended for non-LaTeX exports, but you can also use it with LaTeX if +;; you want to avoid using bibtex/biblatex for some reason. +;; +;; The default style is set by a CSL-STYLE keyword or +;; `org-ref-csl-default-style'. If this is an absolute or relative path that +;; exists, it is used. Otherwise, it looks in `org-cite-csl-styles-dir' from +;; `org-cite' if it is defined, and in the citeproc/csl-styles directory in +;; `org-ref' otherwise. +;; +;; The default locale is set by a CSL-LOCALE keyword or +;; `org-ref-csl-default-locale'. This is looked for in +;; `org-cite-csl-locales-dir' if it is defined, and otherwise in the csl-locales +;; directory of `org-ref'. +;; +;; Note that citeproc does not do anything for cross-references, so if non-LaTeX +;; export is your goal, you may want to use org-ref-refproc.el to handle +;; cross-references. +;; + +;;; Code: +(eval-when-compile + (require 'hydra)) + +(defvar hfy-user-sheet-assoc) ; to quiet compiler + +(require 'ox-org) + +(require 'citeproc) + +(defcustom org-ref-backend-csl-formats + '((html . html) + (latex . latex) + (md . plain) + (org . org) + (ascii . plain) + (odt . org-odt)) + "Mapping of export backend to csl-backends." + :type '(alist :key-type (symbol) :value-type (symbol)) + :group 'org-ref) + + +(defcustom org-ref-cite-internal-links 'auto + "Should be on of +- 'bib-links :: link cites to bibliography entries +- 'no-links :: do not link cites to bibliography entries +- nil or 'auto :: add links based on the style." + :type '(choice bib-links no-links auto nil) + :group 'org-ref) + + +(defcustom org-ref-csl-default-style "chicago-author-date-16th-edition.csl" + "Default csl style to use. +Should be a csl filename, or an absolute path to a csl filename." + :type 'string + :group 'org-ref) + + +(defcustom org-ref-csl-default-locale "en-US" + "Default csl locale to use." + :type 'string + :group 'org-ref) + + +(defcustom org-ref-csl-label-aliases + '((("app" "apps") . "appendix") + (("art" "arts") . "article-locator") + (("bk" "bks") . "book") + (("can") . "canon") + (("ch" "chap" "chaps" "chapt") . "chapter") + (("col" "cols") . "column") + (("el") . "elocation") + (("eq" "eqs") . "equation") + (("fig" "figs") . "figure") + (("fol" "fols") . "folio") + (("iss") . "issue") + (("l" "ll") . "line") + (("n" "nn") . "note") + ;; number is not listed in the url in the docstring + (("no" "nos" "#") . "number") + (("op" "opp") . "opus") + (("p" "pp" "pg" "pgs") . "page") + (("para" "paras" "¶" "¶¶" "§" "§§") . "paragraph") + (("pt" "pts") . "part") + (("sec" "secs") . "section") + (("s.v" "s.vv") . "sub verbo") + (("sup" "supp") . "supplement") + (("tab" "tabs") . "table") + (("ts") . "timestamp") + (("ti" "tit") . "title") + (("v" "vv") . "verse") + (("vol" "vols") . "volume")) + "A-list of aliases for a csl label. +The car is a list of possible aliases (including if they end in a . +This list was adapted from `org-cite-csl--label-alist'. +See https://github.com/citation-style-language/documentation/blob/master/specification.rst#locators" + :type '(alist :key-type (list (repeat string)) :value-type string) + :group 'org-ref) + + +(defun org-ref-dealias-label (alias) + "Return the full, de-aliased label for ALIAS. +Looked up from `org-ref-csl-label-aliases'. + +I added this because I think it is reasonable to expect if you +write pg. 2 that it will show that way when rendered. At the +moment that is not the case, and only page is accepted. This is +actually done in oc-csl too, although it uses a flat a-list." + (or (cdr (assoc "page" org-ref-csl-label-aliases + (lambda (x1 _x2) + (or (member alias x1) + (member (concat (downcase alias) ".") x1))))) + alias)) + + +(defun org-ref-get-cite-links () + "Return list of cite links in the order they appear in the buffer." + (org-element-map (org-element-parse-buffer) 'link + (lambda (lnk) + (when (assoc (org-element-property :type lnk) org-ref-cite-types) + lnk)))) + + +(defun org-ref-ref-csl-data (ref type) + "Return the CSL alist for a REF of TYPE. +REF is a plist data structure returned from `org-ref-parse-cite-path'." + ;; I believe the suffix contains "label locator suffix" + ;; where locator is a number, or maybe a range of numbers like 5-6. + ;; label is something like page or chapter + ;; and the rest is the suffix text. + ;; For example: ch. 5, for example + ;; would be label = ch., locator=5, ",for example" as suffix. + (let* ((full-suffix (string-trim (or (plist-get ref :suffix) ""))) + locator + label locator suffix) + + ;; org-cite is more sophisticated than this and would allow things like 5, 6 + ;; and 12. I am not sure about what all should be supported yet. I guess the + ;; idea there is you use everything from the first to last number as the + ;; locator, but that seems tricky, what about something like: 5, 6 and 12, + ;; because he had 3 books. One solution might be some kind of delimiter, + ;; e.g. {5, 6 and 12}, because he had 3 books. + + (if (and (string-match + (rx + ;; optional label + (group-n 1 (optional + (regexp (regexp-opt (cl-loop for (abbrvs . full) + in org-ref-csl-label-aliases + append (append abbrvs (list full))))))) + (optional (one-or-more space)) + ;; number or numeric ranges + (group-n 2 (one-or-more digit) (optional "-" (one-or-more digit))) + ;; everything else + (group-n 3 (* "."))) + full-suffix) + (match-string 2 full-suffix) + (not (string= "" (match-string 2 full-suffix)))) + ;; We found a locator + (setq label (match-string 1 full-suffix) + locator (match-string 2 full-suffix) + suffix (match-string 3 full-suffix)) + (setq label nil + locator nil + suffix full-suffix)) + + ;; Let's assume if you have a locator but not a label that you mean page. + (when (and locator (string= "" (string-trim label))) + (setq label "page")) + + `((id . ,(plist-get ref :key)) + (prefix . ,(plist-get ref :prefix)) + (suffix . ,suffix) + (locator . ,locator) + (label . ,(when label (org-ref-dealias-label (string-trim label)))) + ;; TODO: proof of concept and not complete. I did not go through all the + ;; types to see what else should be in here. + (suppress-author . ,(not (null (member type + '("citenum" + "citeyear" + "citeyear*" + "citedate" + "citedate*" + "citetitle" + "citetitle*" + "citeurl")))))))) + +(declare-function org-ref-find-bibliography "org-ref-core") + +(defun org-ref-process-buffer (backend &optional subtreep) + "Process the citations and bibliography in the org-buffer. +Usually run on a copy of the buffer during export. +BACKEND is the org export backend." + (save-restriction + (when subtreep + (org-narrow-to-subtree)) + (let* ((csl-backend (or (cdr (assoc backend org-ref-backend-csl-formats)) 'plain)) + + (style (or (cadr (assoc "CSL-STYLE" + (org-collect-keywords + '("CSL-STYLE")))) + org-ref-csl-default-style)) + (locale (or (cadr (assoc "CSL-LOCALE" + (org-collect-keywords + '("CSL-LOCALE")))) + org-ref-csl-default-locale)) + + (proc (citeproc-create + ;; The style + (cond + ((file-exists-p style) + style) + ;; In a user-dir + ((and (boundp 'org-cite-csl-styles-dir) + (file-exists-p (f-join org-cite-csl-styles-dir style))) + (f-join org-cite-csl-styles-dir style)) + ;; provided by org-ref + ((file-exists-p (expand-file-name style + (f-join (file-name-directory + (locate-library "org-ref")) + "citeproc/csl-styles"))) + (expand-file-name style (f-join + (file-name-directory + (locate-library "org-ref")) + "citeproc/csl-styles"))) + (t + (error "%s not found" style))) + ;; item-getter + ;; (citeproc-itemgetter-from-bibtex (org-ref-find-bibliography)) + (citeproc-hash-itemgetter-from-any (org-ref-find-bibliography)) + ;; locale getter + (citeproc-locale-getter-from-dir (cond + ((boundp 'org-cite-csl-locales-dir) + org-cite-csl-locales-dir) + (t + (f-join (file-name-directory + (locate-library "org-ref")) + "citeproc/csl-locales")))) + ;; the actual locale + locale)) + + ;; list of links in the buffer + (cite-links (org-element-map (org-element-parse-buffer) 'link + (lambda (lnk) + (when (assoc (org-element-property :type lnk) org-ref-cite-types) + lnk)))) + + (cites (cl-loop for cl in cite-links collect + (let* ((cite-data (org-ref-parse-cite-path (org-element-property :path cl))) + (common-prefix (or (plist-get cite-data :prefix) "")) + (common-suffix (or (plist-get cite-data :suffix) "")) + (refs (plist-get cite-data :references)) + (type (org-element-property :type cl)) + + (cites (cl-loop for ref in refs collect + (org-ref-ref-csl-data ref type)))) + ;; TODO: update eventually + ;; https://github.com/andras-simonyi/citeproc-el/issues/46 + ;; To handle common prefixes, suffixes, I just concat + ;; them with the first/last entries. That is all that + ;; is supported for now. Combine common/local prefix + (setf (cdr (assoc 'prefix (cl-first cites))) + (concat common-prefix + (cdr (assoc 'prefix (cl-first cites))))) + ;; Combine local/common suffix + (setf (cdr (assoc 'suffix (car (last cites)))) + (concat (cdr (assoc 'suffix (car (last cites)))) + common-suffix)) + + ;; https://github.com/andras-simonyi/citeproc-el#creating-citation-structures + (citeproc-citation-create + :cites cites + ;; TODO: proof of concept, incomplete if this is + ;; true, the citation is not parenthetical + :suppress-affixes (let ((type (org-element-property :type cl))) + (when (member type '("citet" + "citet*" + "citenum")) + t)) + + ;; TODO: this is proof of concept, and not complete. + ;; mode is one of suppress-author, textual, + ;; author-only, year-only, or nil for default. These + ;; are not all clear to me. + :mode (let ((type (org-element-property :type cl))) + (cond + ((member type '("citet" "citet*")) + 'textual) + ((member type '("citeauthor" "citeauthor*")) + 'author-only) + ((member type '("citeyear" "citeyear*")) + 'year-only) + ((member type '("citedate" "citedate*")) + 'suppress-author) + (t + nil))) + + ;; I think the capitalized styles are what this is for + :capitalize-first (string-match + "[A-Z]" + (substring + (org-element-property :type cl) 0 1)) + ;; I don't know where this information would come from. + :note-index nil + :ignore-et-al nil)))) + + (rendered-citations (progn (citeproc-append-citations cites proc) + (citeproc-render-citations proc csl-backend org-ref-cite-internal-links))) + ;; I only use the returned bibliography string. citeproc returns a + ;; bunch of other things related to offsets and linespacing, but I + ;; don't know what you do with these, so just ignore them here. + (rendered-bib (car (citeproc-render-bib proc csl-backend))) + ;; The idea is we will wrap each citation and the bibliography in + ;; org-code so it exports appropriately. + (cite-formatters '((html . "@@html:%s@@") + (latex . "@@latex:%s@@") + (odt . "@@odt:%s@@"))) + (bib-formatters '((html . "\n#+BEGIN_EXPORT html\n%s\n#+END_EXPORT\n") + (latex . "\n#+BEGIN_EXPORT latex\n%s\n#+END_EXPORT\n") + (odt . "\n#+BEGIN_EXPORT ODT\n%s\n#+END_EXPORT\n")))) + + ;; replace the cite links + (cl-loop for cl in (reverse cite-links) for rc in (reverse rendered-citations) do + (cl--set-buffer-substring (org-element-property :begin cl) + (org-element-property :end cl) + (format (or + (cdr (assoc backend cite-formatters)) + "%s") + (concat + rc + ;; Add on extra spaces that were + ;; following it. + (make-string + (or + (org-element-property :post-blank cl) 0) + ? ))))) + + ;; replace the bibliography + (org-element-map (org-element-parse-buffer) 'link + (lambda (lnk) + (cond + ((string= (org-element-property :type lnk) "bibliography") + (cl--set-buffer-substring (org-element-property :begin lnk) + (org-element-property :end lnk) + (format (or + (cdr (assoc backend bib-formatters)) + "%s") + rendered-bib))) + ;; We just get rid of nobibliography links. + ((string= (org-element-property :type lnk) "nobibliography") + (cl--set-buffer-substring (org-element-property :begin lnk) + (org-element-property :end lnk) + ""))))) + ;; For LaTeX we need to define the citeprocitem commands + ;; see https://www.mail-archive.com/emacs-orgmode@gnu.org/msg138546.html + (when (eq backend 'latex) + (goto-char (point-min)) + (insert "#+latex_header: \\makeatletter +#+latex_header: \\newcommand{\\citeprocitem}[2]{\\hyper@linkstart{cite}{citeproc_bib_item_#1}#2\\hyper@linkend} +#+latex_header: \\makeatother\n"))))) + + +(defun org-ref-export-to (backend &optional async subtreep visible-only + body-only info) + "Export buffer to BACKEND. +See `org-export-as' for the meaning of ASYNC SUBTREEP +VISIBLE-ONLY BODY-ONLY and INFO." + (let* ((fname (buffer-file-name)) + (extensions '((html . ".html") + (latex . ".tex") + (ascii . ".txt") + (odt . ".odf"))) + (cp (point)) + (mm) ;marker to save place + (export-name (concat (file-name-sans-extension fname) + (or (cdr (assoc backend extensions)) "")))) + + (org-export-with-buffer-copy + ;; Note I use a marker here to make sure we stay in the same place we were. + ;; This is more robust than save-excursion I think, since processing moves + ;; points around. In theory the marker should move too. + (setq mm (make-marker)) + (move-marker mm cp) + ;; make sure we expand includes + (org-export-expand-include-keyword) + (goto-char (marker-position mm)) + (org-ref-process-buffer backend subtreep) + (message-box (buffer-substring (line-beginning-position) (line-end-position))) + (set-marker mm nil) + + (pcase backend + ;; odt is a little bit special, and is missing one argument + ('odt (org-open-file (org-odt-export-to-odt async subtreep visible-only + info) + 'system)) + (_ + (org-open-file (org-export-to-file backend export-name + async subtreep visible-only + body-only info) + 'system)))))) + + +;; I guess I tried to use apply-partially here, and it did not work, so these +;; are each defined manually + +(defun org-ref-export-to-html (&optional async subtreep visible-only + body-only info) + "Export the buffer to HTML and open. +See `org-export-as' for the meaning of ASYNC SUBTREEP +VISIBLE-ONLY BODY-ONLY and INFO." + (org-ref-export-to 'html async subtreep visible-only + body-only info)) + + +(defun org-ref-export-to-ascii (&optional async subtreep visible-only + body-only info) + "Export the buffer to ascii and open. +See `org-export-as' for the meaning of ASYNC SUBTREEP +VISIBLE-ONLY BODY-ONLY and INFO." + (org-ref-export-to 'ascii async subtreep visible-only + body-only info)) + + +(defun org-ref-export-to-pdf (&optional async subtreep visible-only + body-only info) + "Export the buffer to PDF via LaTeX and open. +See `org-export-as' for the meaning of ASYNC SUBTREEP +VISIBLE-ONLY BODY-ONLY and INFO." + (let ((org-export-before-parsing-hook '(org-ref-csl-preprocess-buffer))) + (org-open-file (org-latex-export-to-pdf async subtreep visible-only + body-only info)))) + + +(defun org-ref-export-to-latex (&optional async subtreep visible-only + body-only info) + "Export the buffer to LaTeX and open. +See `org-export-as' for the meaning of ASYNC SUBTREEP +VISIBLE-ONLY BODY-ONLY and INFO." + (org-ref-export-to 'latex async subtreep visible-only + body-only info)) + + +(defun org-ref-export-to-odt (&optional async subtreep visible-only + body-only info) + "Export the buffer to ODT and open. +See `org-export-as' for the meaning of ASYNC SUBTREEP +VISIBLE-ONLY BODY-ONLY and INFO." + (require 'htmlfontify) + (unless (boundp 'hfy-user-sheet-assoc) (setq hfy-user-sheet-assoc nil)) + (org-ref-export-to 'odt async subtreep visible-only + body-only info)) + + +(defun org-ref-export-as-org (&optional _async subtreep visible-only + body-only info) + "Export the buffer to an ORG buffer and open. +We only make a buffer here to avoid overwriting the original file. +See `org-export-as' for the meaning of ASYNC SUBTREEP +VISIBLE-ONLY BODY-ONLY and INFO." + (let* ((export-buf "*org-ref ORG Export*") + export) + + (org-export-with-buffer-copy + (org-ref-process-buffer 'org subtreep) + (setq export (org-export-as 'org subtreep visible-only body-only info)) + (with-current-buffer (get-buffer-create export-buf) + (erase-buffer) + (org-mode) + (insert export))) + (pop-to-buffer export-buf))) + + +(defun org-ref-export-to-message (&optional _async subtreep visible-only + body-only info) + "Export to ascii and insert in an email message." + (let* ((backend 'ascii) + (content (org-export-with-buffer-copy + (org-ref-process-buffer backend subtreep) + (org-export-as backend subtreep visible-only + body-only info)))) + (compose-mail) + (message-goto-body) + (insert content) + (message-goto-to))) + + +(org-export-define-derived-backend 'org-ref 'org + :menu-entry + '(?r "Org-ref export" + ((?a "to Ascii" org-ref-export-to-ascii) + (?h "to html" org-ref-export-to-html) + (?l "to LaTeX" org-ref-export-to-latex) + (?p "to PDF" org-ref-export-to-pdf) + (?o "to ODT" org-ref-export-to-odt) + (?O "to Org buffer" org-ref-export-as-org) + (?e "to email" org-ref-export-to-message)))) + +;; An alternative to this exporter is to use an `org-export-before-parsing-hook' +;; (add-hook 'org-export-before-parsing-hook 'org-ref-csl-preprocess-buffer) + +(defun org-ref-csl-preprocess-buffer (backend) + "Preprocess the buffer in BACKEND export. +Note this may not work as expected, what about subtreep? The hook +function just takes one argument. For now we rely on +`buffer-narrowed-p' and an org-heading at the beginning. +I am not positive on this though." + (org-ref-process-buffer backend (and (buffer-narrowed-p) + (save-excursion + (goto-char (point-min)) + (org-at-heading-p))))) + + +;; A hydra exporter with preprocessors +(defhydradio org-ref () + (natmove "natmove") + (citeproc "CSL citations") + (refproc "cross-references") + (acrossproc "Acronyms, glossary") + (idxproc "Index") + (bblproc "BBL citations")) + + +(defun org-ref-export-from-hydra (&optional arg) + "Run the export dispatcher with the desired hooks selected in `org-ref-export/body'." + (interactive "P") + + (when (and org-ref/citeproc org-ref/bblproc) + (error "You cannot use CSL and BBL at the same time.")) + + (let ((org-export-before-parsing-hook org-export-before-parsing-hook)) + (when org-ref/citeproc + (cl-pushnew 'org-ref-csl-preprocess-buffer org-export-before-parsing-hook)) + + (when org-ref/refproc + (cl-pushnew 'org-ref-refproc org-export-before-parsing-hook)) + + (when org-ref/acrossproc + (cl-pushnew 'org-ref-acrossproc org-export-before-parsing-hook)) + + (when org-ref/idxproc + (cl-pushnew 'org-ref-idxproc org-export-before-parsing-hook)) + + (when org-ref/bblproc + (unless (featurep 'org-ref-natbib-bbl-citeproc) + (require 'org-ref-natbib-bbl-citeproc)) + (cl-pushnew 'org-ref-bbl-preprocess org-export-before-parsing-hook)) + + ;; this goes last since it moves cites before they might get replaced. + (when org-ref/natmove + (cl-pushnew 'org-ref-cite-natmove org-export-before-parsing-hook)) + + (org-export-dispatch arg))) + + +(defhydra org-ref-export (:color red) + " +_C-n_: natmove % -15`org-ref/natmove _C-c_: citeproc % -15`org-ref/citeproc^^^ _C-r_: refproc % -15`org-ref/refproc^^^ +_C-a_: acrossproc % -15`org-ref/acrossproc _C-i_: idxproc % -15`org-ref/idxproc^^^ _C-b_: bblproc % -15`org-ref/bblproc^^^ +" + ("C-n" (org-ref/natmove) nil) + ("C-c" (org-ref/citeproc) nil) + ("C-r" (org-ref/refproc) nil) + ("C-a" (org-ref/acrossproc) nil) + ("C-i" (org-ref/idxproc) nil) + ("C-b" (org-ref/bblproc) nil) + + ("e" org-ref-export-from-hydra "Export" :color blue) + ("q" nil "quit")) + +(provide 'org-ref-export) + +;;; org-ref-export.el ends here diff --git a/lisp/org-ref/org-ref-glossary.el b/lisp/org-ref/org-ref-glossary.el index f7364e82..3e90e771 100644 --- a/lisp/org-ref/org-ref-glossary.el +++ b/lisp/org-ref/org-ref-glossary.el @@ -1,6 +1,6 @@ ;;; org-ref-glossary.el --- glossary support in org-ref -*- lexical-binding: t; -*- -;; Copyright (C) 2016 John Kitchin +;; Copyright (C) 2016-2021 John Kitchin ;; Author: John Kitchin ;; Keywords: @@ -20,9 +20,9 @@ ;;; Commentary: -;; Provides Some glossary support for org-mode. Only export to LaTeX is -;; supported. The functionality is based on the LaTeX glossaries package. See -;; https://en.wikibooks.org/wiki/LaTeX/Glossary and +;; Provides Some acronym and glossary support for org-mode. Only export to LaTeX +;; is currently supported. The functionality is based on the LaTeX glossaries +;; package. See https://en.wikibooks.org/wiki/LaTeX/Glossary and ;; http://ctan.math.washington.edu/tex-archive/macros/latex/contrib/glossaries/glossaries-user.pdf ;; Put something like this in your org-file. @@ -30,8 +30,42 @@ ;; #+latex_header: \makeglossaries ;; Put this where you want the glossaries to appear in your org-file. -;; \printglossaries +;; [[printglossaries:]] +;; This is the preferred way to add glossary entries to an org-file. The table +;; must be named glossary. +;; +;; #+name: glossary +;; | label | name | description | +;; |-------+-------+---------------| +;; | tree | Tree | A woody plant | +;; | shrub | Shrub | A woody bush | +;; +;; This is the preferred way to add acronyms +;; #+name: acronyms +;; | key | abbreviation | full form | +;; |------+--------------+--------------------------------| +;; | mimo | | multiple-input multiple output | +;; | qos | QoS | quality-of-service | +;; | bb | BB | branch and bound | +;; +;; Then add `org-ref-glossary-before-parsing' and +;; `org-ref-acronyms-before-parsing' to the `org-export-before-parsing-hook'. + +;; See `org-ref-acronym-types' and `org-ref-glossary-gls-commands' for the types defined. + +;; Use `org-ref-insert-glossary-link' and `org-ref-insert-acronym-link' to +;; insert a link with completion. + +;; * Known limitations +;; +;; This only works well in a single file (i.e. you cannot include the tables +;; from another file). I tried implementing that once, and it was too slow. + + + +;; * DEPRECATED way of adding entries +;; This is still supported but using the tables is preferred. ;; Add new glossary entries to your org-file like this. Enclose strings ;; containing a comma in {}. Multiline entries are supported. @@ -49,34 +83,10 @@ ;; Here is an example acronym definition ;; #+latex_header_extra: \newacronym{lvm}{LVM}{Logical Volume Manager} -;; New links defined: -;; gls:name A reference to the glossary entry NAME. -;; glspl:name The plural version of the entry -;; Gls:name Capitalized glossary entry -;; Glspl: Capitalized, plural glossary entry -;; [[gslink:name][alternate text]] -;; glssymbol:name Outputs the symbol value of the glossary entry settings. -;; glsdesc:name The description of name - -;; The links export to LaTeX. You can click on the link and jump to the -;; definition. The links have tooltips for the definitions. - -;; Acronym links -;; acrshort:label -;; acrfull:label -;; acrlong:label -;; ac:label (exports to \gls{label}) -;; Ac:label (exports to \Gls{label}) -;; acp:label (exports to \glspl{label}) -;; Acp:label (exports to \Glspl{label}) - (require 'org-element) (require 'org-ref-utils) (require 'ox) -(declare-function helm "helm") -(declare-function helm-build-sync-source "helm-source") - ;;; Code: (defgroup org-ref-glossary nil "Customization group for org-ref-glossary." @@ -84,16 +94,8 @@ :group 'org) -(defcustom org-ref-glossary-color "Mediumpurple3" - "Color for glossary links." - :type 'string - :group 'org-ref) - - -(defcustom org-ref-acronym-color "Darkorange2" - "Color for acronym links." - :type 'string - :group 'org-ref) +(defvar org-ref-glsentries '() + "Variable to hold locations of glsentries load files.") (defun or-find-closing-curly-bracket (&optional limit) @@ -119,17 +121,24 @@ there is an escaped \" for example. This seems pretty robust." ;;* Glossary (defun or-parse-glossary-entry (entry) - "Parse glossary ENTRY definition to a p-list of key=value. + "Parse a LaTeX glossary ENTRY definition to a p-list of key=value. Typically: (:name name :description description) but there could be other :key value pairs." (save-excursion (goto-char (point-min)) - (let (end-of-entry - data - (external (when (re-search-forward "\\loadglsentries\\(\\[.*\\]\\){\\(?1:.*\\)}" nil t) - (match-string 1))) - key value p1 p2) + (let* (end-of-entry + data + (external (when (re-search-forward "\\loadglsentries\\(\\[.*\\]\\){\\(?1:.*\\)}" nil t) + (match-string 1))) + (glsentries (and external + (or (cdr (assoc external org-ref-glsentries)) + (progn + (cl-pushnew (cons external (s-trim (shell-command-to-string + (format "kpsewhich tex %s" external)))) + org-ref-glsentries) + (cdr (assoc external org-ref-glsentries)))))) + key value p1 p2) (catch 'data ;; look inside first for latex-headers (goto-char (point-min)) @@ -161,6 +170,7 @@ but there could be other :key value pairs." (setq value (replace-regexp-in-string "\n +" " " value)) (setq data (append data + (list :label entry) (list (intern (format ":%s" key))) (list value)))) (throw 'data data)) @@ -178,12 +188,13 @@ but there could be other :key value pairs." (nthcdr 2 (org-babel-read-table))))))))) (result (assoc entry entries))) (when result - (throw 'data (list :name (cl-second result) :description (cl-third result))))) + (throw 'data (list :label entry :name (cl-second result) :description (cl-third result))))) ;; then external - (when (and external - (file-exists-p (concat external ".tex"))) - (with-current-buffer (find-file-noselect (concat external ".tex")) + (when (and glsentries + (file-exists-p glsentries)) + + (with-current-buffer (find-file-noselect glsentries) (goto-char (point-min)) (when (re-search-forward (format "\\newglossaryentry{%s}" entry) nil t) @@ -208,41 +219,7 @@ but there could be other :key value pairs." (re-search-forward "," end-of-entry 'mv) (setq value (buffer-substring p1 (- (point) 1)))) (setq data (append data - (list (intern (format ":%s" key))) - (list value)))) - (throw 'data data)))) - - ;; and finally with an export in case there are includes - (let ((org-export-show-temporary-export-buffer nil)) - (with-current-buffer (org-org-export-as-org) - (when (re-search-forward - (format "\\newglossaryentry{%s}" entry) nil t) - (re-search-forward "{") - (save-excursion - (backward-char) - (or-find-closing-curly-bracket) - (setq end-of-entry (point))) - - (while (re-search-forward "\\(\\w+?\\)=" end-of-entry t) - (setq key (match-string 1)) - ;; get value - (goto-char (+ 1 (match-end 1))) - (setq p1 (point)) - (if (looking-at "{") - ;; value is wrapped in {} - (progn - (or-find-closing-curly-bracket) - (setq p2 (point) - value (buffer-substring (+ 1 p1) p2))) - ;; value is up to the next comma - (re-search-forward "," end-of-entry 'mv) - (setq value (buffer-substring p1 (- (point) 1)))) - ;; remove #+latex_header_extra: - (setq value (replace-regexp-in-string - "#\\+latex_header_extra: " "" value)) - (setq value (replace-regexp-in-string - "\n +" " " value)) - (setq data (append data + (list :label entry) (list (intern (format ":%s" key))) (list value)))) (throw 'data data)))))))) @@ -254,9 +231,14 @@ but there could be other :key value pairs." LABEL is how you refer to it with links. NAME is the name of the entry to be defined. DESCRIPTION is the definition of the entry. -Entry gets added after the last #+latex_header line." - (interactive "sLabel: \nsName: \nsDescription: ") +Entry gets added after the last #+latex_header line. + +This is not a preferred way to add entries. It is preferred to +manually add them to the glossary table." + (interactive "sLabel: \nsName: \nsDescription: ") (save-excursion + (goto-char (point-max)) + ;; get to the last latex_header line (re-search-backward "#\\+latex_header" nil t) (forward-line) (when (not (looking-at "^$")) @@ -271,8 +253,7 @@ Entry gets added after the last #+latex_header line." "Return a face for a glossary link." (save-match-data (cond - ((or (not org-ref-show-broken-links) - (or-parse-glossary-entry label)) + ((or-parse-glossary-entry label) 'org-ref-glossary-face) (t 'font-lock-warning-face)))) @@ -282,43 +263,59 @@ Entry gets added after the last #+latex_header line." (defun or-follow-glossary (entry) "Goto beginning of the glossary ENTRY." (org-mark-ring-push) - (goto-char (point-min)) - (re-search-forward (format "\\newglossaryentry{%s}" entry)) - (goto-char (match-beginning 0))) + + (cond + ;; Try finding in the table + ((progn (goto-char (point-min)) + (and (re-search-forward "#\\+name: glossary" nil t) + (re-search-forward entry nil t))) + nil) + + ((progn (goto-char (point-min)) (re-search-forward (format "\\newglossaryentry{%s}" entry) nil t)) + (goto-char (match-beginning 0))) + + (t + (message "no entry found for %s" entry)))) (defvar org-ref-glossary-gls-commands - '("gls" "glspl" "Gls" "Glspl" "glssymbol" "glsdesc")) - + '(("gls" "The term associated with the label") + ("glspl" "The plural term") + ("Gls" "The capitalized term") + ("Glspl" "The plural capitalized term") + ("glssymbol" "The symbol defined (only with latex definition)") + ("Glssymbol" "The capitalized symbol defined (only with latex definition)") + ("glsdesc" "The description associated with the label") + ("Glsdesc" "The capitalized description associated with the label")) + "An alist of (cmd description).") (dolist (command org-ref-glossary-gls-commands) - (org-ref-link-set-parameters command - :follow #'or-follow-glossary - :face 'org-ref-glossary-face-fn - :help-echo 'or-glossary-tooltip - :export (lambda (path _ format) - (cond - ((memq format '(latex beamer)) - (format "\\%s{%s}" command path)) - (t - (format "%s" path)))))) + (org-link-set-parameters (cl-first command) + :follow #'or-follow-glossary + :face 'org-ref-glossary-face-fn + :help-echo 'or-glossary-tooltip + :export (lambda (path _ format) + (cond + ((memq format '(latex beamer)) + (format "\\%s{%s}" (cl-first command) path)) + (t + (format "%s" path)))))) -(org-ref-link-set-parameters "glslink" - :follow #'or-follow-glossary - :face 'org-ref-glossary-face-fn - :help-echo 'or-glossary-tooltip - :export (lambda (path desc format) - (cond - ((memq format '(latex beamer)) - (format "\\glslink{%s}{%s}" path desc)) - (t - (format "%s" path))))) - +(org-link-set-parameters "glslink" + :follow #'or-follow-glossary + :face 'org-ref-glossary-face-fn + :help-echo 'or-glossary-tooltip + :export (lambda (path desc format) + (cond + ((memq format '(latex beamer)) + (format "\\glslink{%s}{%s}" path desc)) + (t + (format "%s" path))))) ;;** Tooltips on glossary entries (defface org-ref-glossary-face - `((t (:inherit org-link :foreground ,org-ref-glossary-color))) + `((t (:inherit org-link :foreground "Mediumpurple3"))) "Face for glossary links.") @@ -344,41 +341,20 @@ Used in fontification." (buffer-string)))))) -(unless (fboundp 'org-link-set-parameters) - (defun or-next-glossary-link (limit) - "Search to next glossary link up to LIMIT. -Adds a tooltip to the link that is found." - (when (and (re-search-forward - (concat - (regexp-opt '("gls" "glspl" - "Gls" "Glspl" - "glslink" - "glssymbol" - "glsdesc")) - ":[a-zA-Z]\\{2,\\}") - limit t) - (not (org-in-src-block-p)) - (not (org-at-comment-p))) - (forward-char -2) - (let ((next-link (org-element-context))) - (if next-link - (progn - (set-match-data (list (org-element-property :begin next-link) - (- (org-element-property :end next-link) - (org-element-property :post-blank next-link)))) - (add-text-properties - (org-element-property :begin next-link) - (- (org-element-property :end next-link) - (org-element-property :post-blank next-link)) - (list - 'help-echo 'or-glossary-tooltip)) - (goto-char (org-element-property :end next-link))) - (goto-char limit) - nil))))) +;; ** printglossaries links +;; There is a printglossary command in LaTeX, but I am not supporting it for now. +(org-link-set-parameters "printglossaries" + :export (lambda (path _desc format) + (cond + ((memq format '(latex beamer)) + "\\printglossaries") + (t + (format "%s" path))))) + ;; ** exporting with a glossary table -(defun org-ref-glossary-before-parsing (backend) +(defun org-ref-glossary-before-parsing (_backend) "Function to preprocess a glossary table on export. This assumes a table like @@ -388,9 +364,13 @@ This assumes a table like | tree | Tree | A woody plant | | shrub | Shrub | A woody bush | -is in the org-buffer, and will add the relevant latex_header items if there is. The table is deleted in a copy of the buffer before the export. +is in the org-buffer, and will add the relevant latex_header +items if there is. The table is deleted in a copy of the buffer +before the export, so you can put it where you want. The column +names are arbitrary, but three columns are expected, and the +hline is expected. -This will run in `org-export-before-parsing-hook'." +This is intended to be run in `org-export-before-parsing-hook'." (let* (begin end (entries (save-excursion @@ -417,14 +397,17 @@ This will run in `org-export-before-parsing-hook'." (insert (format "#+latex_header_extra: \\newglossaryentry{%s}{name=%s,description={{%s}}}\n" label name description)))))) -(add-to-list 'org-export-before-parsing-hook 'org-ref-glossary-before-parsing) ;;* Acronyms + ;;;###autoload (defun org-ref-add-acronym-entry (label abbrv full) "Add an acronym entry with LABEL. ABBRV is the abbreviated form. - FULL is the expanded acronym." + FULL is the expanded acronym. + +This is not the preferred way to add acronyms, you should add +them manually to the acroynms table." (interactive "sLabel: \nsAcronym: \nsFull name: ") (save-excursion (re-search-backward "#\\+latex_header" nil t) @@ -433,21 +416,28 @@ This will run in `org-export-before-parsing-hook'." (beginning-of-line) (insert "\n") (forward-line -1)) - (insert (format "#+latex_header_extra: \\newacronym{%s}{%s}{%s}\n" label abbrv full)))) (defun or-parse-acronym-entry (label) "Parse an acronym entry LABEL to a plist. - \(:abbrv abbrv :full full) -\newacronym{