From f5649dceab87529e120961bf7fba085fcce2ceab Mon Sep 17 00:00:00 2001 From: Daniel Weschke Date: Fri, 8 Jan 2021 19:32:30 +0100 Subject: [PATCH] update packages --- lisp/all-the-icons/all-the-icons-pkg.el | 8 +- lisp/all-the-icons/all-the-icons.el | 51 +- lisp/all-the-icons/data/data-fileicons.el | 2 +- lisp/amx.el | 22 +- lisp/anaconda-mode.el | 87 +- lisp/async/async-bytecomp.el | 10 +- lisp/async/async-pkg.el | 8 +- lisp/avy.el | 20 +- lisp/bibtex-completion.el | 104 +- lisp/bind-key.el | 17 +- lisp/company-quickhelp.el | 77 +- lisp/company/company-abbrev.el | 2 +- lisp/company/company-bbdb.el | 2 +- lisp/company/company-capf.el | 2 +- lisp/company/company-clang.el | 23 +- lisp/company/company-cmake.el | 3 +- lisp/company/company-css.el | 2 +- lisp/company/company-dabbrev-code.el | 2 +- lisp/company/company-dabbrev.el | 2 +- lisp/company/company-eclim.el | 186 - lisp/company/company-elisp.el | 4 +- lisp/company/company-etags.el | 2 +- lisp/company/company-files.el | 2 +- lisp/company/company-gtags.el | 31 +- lisp/company/company-ispell.el | 2 +- lisp/company/company-keywords.el | 2 +- lisp/company/company-nxml.el | 2 +- lisp/company/company-oddmuse.el | 2 +- lisp/company/company-pkg.el | 8 +- lisp/company/company-semantic.el | 2 +- lisp/company/company-template.el | 2 +- lisp/company/company-tempo.el | 2 +- lisp/company/company-tng.el | 132 +- lisp/company/company-xcode.el | 123 - lisp/company/company-yasnippet.el | 13 +- lisp/company/company.el | 495 +- lisp/counsel.el | 364 +- lisp/crdt.el | 315 +- lisp/dash/dash-pkg.el | 11 +- lisp/dash/dash.el | 895 ++- lisp/dash/dash.info | 2322 ++++++-- lisp/dash/dir | 2 +- lisp/dashboard/dashboard-pkg.el | 8 +- lisp/dashboard/dashboard-widgets.el | 666 ++- lisp/dashboard/dashboard.el | 55 +- lisp/deft.el | 21 +- lisp/diff-hl/diff-hl-amend.el | 9 +- lisp/diff-hl/diff-hl-dired.el | 2 +- lisp/diff-hl/diff-hl-flydiff.el | 2 +- lisp/diff-hl/diff-hl-margin.el | 2 +- lisp/diff-hl/diff-hl-pkg.el | 8 +- lisp/diff-hl/diff-hl.el | 103 +- lisp/emojify/data/emoji-sets.json | 14 +- lisp/emojify/emojify-pkg.el | 8 +- lisp/emojify/emojify.el | 27 +- lisp/ess/.dir-locals.el | 2 +- lisp/ess/allnews.info | 49 + lisp/ess/announc.info | 768 --- lisp/ess/dir | 4 +- lisp/ess/ess-help.el | 24 +- lisp/ess/ess-inf.el | 372 +- lisp/ess/ess-julia.el | 8 +- lisp/ess/ess-mode.el | 4 +- lisp/ess/ess-pkg.el | 4 +- lisp/ess/ess-r-completion.el | 41 +- lisp/ess/ess-r-flymake.el | 6 +- lisp/ess/ess-r-mode.el | 105 +- lisp/ess/ess-r-package.el | 18 +- lisp/ess/ess-r-xref.el | 2 +- lisp/ess/ess-rd.el | 7 +- lisp/ess/ess-roxy.el | 15 +- lisp/ess/ess-s-lang.el | 4 + lisp/ess/ess-tracebug.el | 40 +- lisp/ess/ess-utils.el | 34 +- lisp/ess/ess.info | 5032 ----------------- lisp/ess/etc/ESSR.rds | Bin 13441 -> 14288 bytes lisp/ess/etc/ESSR/BUILDESSR | 2 +- lisp/ess/etc/ESSR/R/.basic.R | 83 +- lisp/ess/news.info | 49 + lisp/ess/readme.info | 775 --- lisp/flycheck/flycheck-pkg.el | 8 +- lisp/flycheck/flycheck.el | 150 +- lisp/git-commit.el | 20 +- lisp/git-messenger.el | 11 +- lisp/gnuplot/gnuplot-context.el | 71 +- lisp/gnuplot/gnuplot-gui.el | 107 +- lisp/gnuplot/gnuplot-pkg.el | 10 +- lisp/gnuplot/gnuplot.el | 1252 +--- lisp/ht.el | 80 +- lisp/htmlize.el | 94 +- lisp/hydra/hydra-pkg.el | 8 +- lisp/hydra/hydra.el | 16 +- lisp/ivy-bibtex.el | 8 +- lisp/ivy/ivy-pkg.el | 8 +- lisp/ivy/ivy.el | 211 +- lisp/js2-mode/js2-imenu-extras.el | 2 +- lisp/js2-mode/js2-mode-pkg.el | 8 +- lisp/js2-mode/js2-mode.el | 309 +- lisp/js2-mode/js2-old-indent.el | 2 +- lisp/key-chord.el | 218 + lisp/ledger-mode/ledger-mode-pkg.el | 4 +- lisp/ledger-mode/ledger-mode.info | 119 +- lisp/ledger-mode/ledger-report.el | 27 +- lisp/ledger-mode/ledger-xact.el | 6 +- lisp/magit/AUTHORS.md | 20 +- lisp/magit/git-rebase.el | 98 +- lisp/magit/magit-apply.el | 35 +- lisp/magit/magit-autorevert.el | 2 +- lisp/magit/magit-bisect.el | 92 +- lisp/magit/magit-blame.el | 15 +- lisp/magit/magit-bookmark.el | 2 +- lisp/magit/magit-branch.el | 2 +- lisp/magit/magit-clone.el | 73 +- lisp/magit/magit-commit.el | 57 +- lisp/magit/magit-core.el | 2 +- lisp/magit/magit-diff.el | 53 +- lisp/magit/magit-ediff.el | 2 +- lisp/magit/magit-extras.el | 83 +- lisp/magit/magit-fetch.el | 5 +- lisp/magit/magit-files.el | 76 +- lisp/magit/magit-git.el | 137 +- lisp/magit/magit-gitignore.el | 2 +- lisp/magit/magit-imenu.el | 2 +- lisp/magit/magit-log.el | 78 +- lisp/magit/magit-margin.el | 2 +- lisp/magit/magit-merge.el | 12 +- lisp/magit/magit-mode.el | 73 +- lisp/magit/magit-notes.el | 2 +- lisp/magit/magit-obsolete.el | 2 +- lisp/magit/magit-patch.el | 16 +- lisp/magit/magit-pkg.el | 11 +- lisp/magit/magit-process.el | 57 +- lisp/magit/magit-pull.el | 2 +- lisp/magit/magit-push.el | 35 +- lisp/magit/magit-reflog.el | 2 +- lisp/magit/magit-refs.el | 8 +- lisp/magit/magit-remote.el | 8 +- lisp/magit/magit-repos.el | 8 +- lisp/magit/magit-reset.el | 2 +- lisp/magit/magit-section.el | 131 +- lisp/magit/magit-sequence.el | 14 +- lisp/magit/magit-stash.el | 19 +- lisp/magit/magit-status.el | 4 +- lisp/magit/magit-submodule.el | 2 +- lisp/magit/magit-subtree.el | 2 +- lisp/magit/magit-tag.el | 8 +- lisp/magit/magit-transient.el | 2 +- lisp/magit/magit-utils.el | 115 +- lisp/magit/magit-version.el | 2 +- lisp/magit/magit-wip.el | 3 +- lisp/magit/magit-worktree.el | 9 +- lisp/magit/magit.el | 69 +- lisp/magit/magit.info | 324 +- lisp/magit/magit.info-1 | 124 +- lisp/magit/magit.info-2 | 434 +- lisp/markdown-mode.el | 499 +- lisp/mu4e-maildirs-extension.el | 29 +- .../mc-hide-unmatched-lines-mode.el | 5 +- lisp/multiple-cursors/mc-mark-more.el | 4 +- .../multiple-cursors/multiple-cursors-core.el | 18 +- lisp/multiple-cursors/multiple-cursors-pkg.el | 9 +- lisp/multiple-cursors/multiple-cursors.el | 2 - lisp/org-brain.el | 69 +- lisp/org-cliplink/org-cliplink-pkg.el | 4 +- lisp/org-cliplink/org-cliplink-string.el | 4 +- lisp/org-cliplink/org-cliplink.el | 5 + lisp/org-ref/doi-utils.el | 209 +- lisp/org-ref/org-ref-arxiv.el | 48 +- lisp/org-ref/org-ref-bibtex.el | 123 +- lisp/org-ref/org-ref-core.el | 617 +- lisp/org-ref/org-ref-glossary.el | 343 +- lisp/org-ref/org-ref-helm-bibtex.el | 22 +- lisp/org-ref/org-ref-helm-cite.el | 1 + lisp/org-ref/org-ref-helm.el | 8 +- lisp/org-ref/org-ref-ivy-cite.el | 5 +- lisp/org-ref/org-ref-pdf.el | 10 +- lisp/org-ref/org-ref-pkg.el | 8 +- lisp/org-ref/org-ref-url-utils.el | 17 +- lisp/org-ref/org-ref-utils.el | 480 +- lisp/org-ref/org-ref.org | 61 +- lisp/org-sticky-header.el | 114 +- lisp/org-superstar.el | 288 +- lisp/org/README | 57 +- lisp/org/contrib/lisp/ob-php.el | 17 +- lisp/org/contrib/lisp/ob-redis.el | 2 +- lisp/org/contrib/lisp/ob-sclang.el | 2 +- lisp/org/contrib/lisp/ol-bookmark.el | 2 +- lisp/org/contrib/lisp/ol-elisp-symbol.el | 8 +- lisp/org/contrib/lisp/ol-git-link.el | 4 +- lisp/org/contrib/lisp/ol-man.el | 16 +- lisp/org/contrib/lisp/ol-mew.el | 2 +- lisp/org/contrib/lisp/ol-notmuch.el | 6 +- lisp/org/contrib/lisp/ol-vm.el | 4 +- lisp/org/contrib/lisp/ol-wl.el | 9 +- lisp/org/contrib/lisp/org-choose.el | 2 +- lisp/org/contrib/lisp/org-depend.el | 4 +- lisp/org/contrib/lisp/org-eldoc.el | 56 +- lisp/org/contrib/lisp/org-link-edit.el | 56 +- lisp/org/contrib/lisp/org-mac-link.el | 18 +- lisp/org/contrib/lisp/org-mairix.el | 4 +- lisp/org/contrib/lisp/org-notify.el | 67 +- lisp/org/contrib/lisp/ox-bibtex.el | 11 +- lisp/org/contrib/lisp/ox-confluence.el | 25 +- lisp/org/contrib/lisp/ox-groff.el | 2 +- lisp/org/contrib/lisp/ox-koma-letter.el | 7 +- lisp/org/contrib/lisp/ox-taskjuggler.el | 6 +- lisp/org/doc/org | 2820 ++++----- lisp/org/doc/org-guide.org | 4 +- lisp/org/doc/org-manual.org | 1278 +++-- lisp/org/doc/org-version.inc | 4 +- lisp/org/doc/org-version.tex | 2 +- lisp/org/doc/org.pdf | Bin 1248207 -> 1259816 bytes lisp/org/doc/org.texi | 931 +-- lisp/org/doc/orgcard.pdf | Bin 118688 -> 118610 bytes lisp/org/doc/orgcard.tex | 4 +- lisp/org/doc/orgcard_letter.pdf | Bin 119120 -> 119042 bytes lisp/org/doc/orgguide | 187 +- lisp/org/doc/orgguide.pdf | Bin 293794 -> 293802 bytes lisp/org/doc/orgguide.texi | 8 +- lisp/org/etc/ORG-NEWS | 582 +- lisp/org/lisp/ob-C.el | 10 +- lisp/org/lisp/ob-J.el | 9 +- lisp/org/lisp/ob-R.el | 9 +- lisp/org/lisp/ob-abc.el | 4 +- lisp/org/lisp/ob-asymptote.el | 2 - lisp/org/lisp/ob-awk.el | 2 - lisp/org/lisp/ob-calc.el | 2 - lisp/org/lisp/ob-clojure.el | 332 +- lisp/org/lisp/ob-comint.el | 2 - lisp/org/lisp/ob-coq.el | 4 +- lisp/org/lisp/ob-core.el | 534 +- lisp/org/lisp/ob-css.el | 2 - lisp/org/lisp/ob-ditaa.el | 2 - lisp/org/lisp/ob-dot.el | 2 - lisp/org/lisp/ob-ebnf.el | 26 +- lisp/org/lisp/ob-emacs-lisp.el | 51 +- lisp/org/lisp/ob-eval.el | 2 - lisp/org/lisp/ob-exp.el | 8 +- lisp/org/lisp/ob-forth.el | 3 +- lisp/org/lisp/ob-fortran.el | 5 +- lisp/org/lisp/ob-gnuplot.el | 2 - lisp/org/lisp/ob-groovy.el | 4 - lisp/org/lisp/ob-haskell.el | 86 +- lisp/org/lisp/ob-hledger.el | 5 +- lisp/org/lisp/ob-io.el | 3 - lisp/org/lisp/ob-java.el | 7 +- lisp/org/lisp/ob-js.el | 10 +- lisp/org/lisp/ob-latex.el | 12 +- lisp/org/lisp/ob-ledger.el | 2 - lisp/org/lisp/ob-lilypond.el | 7 +- lisp/org/lisp/ob-lisp.el | 2 - lisp/org/lisp/ob-lua.el | 5 +- lisp/org/lisp/ob-makefile.el | 2 - lisp/org/lisp/ob-matlab.el | 2 - lisp/org/lisp/ob-maxima.el | 5 - lisp/org/lisp/ob-mscgen.el | 5 +- lisp/org/lisp/ob-ocaml.el | 2 - lisp/org/lisp/ob-octave.el | 8 +- lisp/org/lisp/ob-org.el | 2 - lisp/org/lisp/ob-perl.el | 2 - lisp/org/lisp/ob-picolisp.el | 8 +- lisp/org/lisp/ob-plantuml.el | 98 +- lisp/org/lisp/ob-python.el | 219 +- lisp/org/lisp/ob-ref.el | 4 +- lisp/org/lisp/ob-ruby.el | 35 +- lisp/org/lisp/ob-sass.el | 4 +- lisp/org/lisp/ob-scheme.el | 11 +- lisp/org/lisp/ob-screen.el | 15 +- lisp/org/lisp/ob-sed.el | 5 +- lisp/org/lisp/ob-shell.el | 59 +- lisp/org/lisp/ob-shen.el | 1 + lisp/org/lisp/ob-sql.el | 118 +- lisp/org/lisp/ob-sqlite.el | 7 +- lisp/org/lisp/ob-stan.el | 3 +- lisp/org/lisp/ob-table.el | 5 +- lisp/org/lisp/ob-tangle.el | 60 +- lisp/org/lisp/ob-vala.el | 2 +- lisp/org/lisp/ol-bbdb.el | 29 +- lisp/org/lisp/ol-bibtex.el | 27 +- lisp/org/lisp/ol-docview.el | 3 +- lisp/org/lisp/ol-eshell.el | 2 +- lisp/org/lisp/ol-eww.el | 15 +- lisp/org/lisp/ol-gnus.el | 15 +- lisp/org/lisp/ol-info.el | 2 +- lisp/org/lisp/ol-irc.el | 2 +- lisp/org/lisp/ol-mhe.el | 2 +- lisp/org/lisp/ol-rmail.el | 6 +- lisp/org/lisp/ol.el | 454 +- lisp/org/lisp/org-agenda.el | 1348 +++-- lisp/org/lisp/org-archive.el | 54 +- lisp/org/lisp/org-attach.el | 149 +- lisp/org/lisp/org-capture.el | 97 +- lisp/org/lisp/org-clock.el | 140 +- lisp/org/lisp/org-colview.el | 53 +- lisp/org/lisp/org-compat.el | 139 +- lisp/org/lisp/org-crypt.el | 229 +- lisp/org/lisp/org-datetree.el | 29 +- lisp/org/lisp/org-duration.el | 52 +- lisp/org/lisp/org-element.el | 182 +- lisp/org/lisp/org-entities.el | 5 +- lisp/org/lisp/org-faces.el | 29 +- lisp/org/lisp/org-goto.el | 38 +- lisp/org/lisp/org-habit.el | 5 +- lisp/org/lisp/org-id.el | 131 +- lisp/org/lisp/org-indent.el | 29 +- lisp/org/lisp/org-keys.el | 20 +- lisp/org/lisp/org-lint.el | 77 +- lisp/org/lisp/org-list.el | 646 ++- lisp/org/lisp/org-loaddefs.el | 380 +- lisp/org/lisp/org-macro.el | 58 +- lisp/org/lisp/org-macs.el | 104 +- lisp/org/lisp/org-mobile.el | 11 + lisp/org/lisp/org-mouse.el | 10 +- lisp/org/lisp/org-num.el | 9 +- lisp/org/lisp/org-pcomplete.el | 36 +- lisp/org/lisp/org-plot.el | 46 +- lisp/org/lisp/org-protocol.el | 30 +- lisp/org/lisp/org-refile.el | 740 +++ lisp/org/lisp/org-src.el | 89 +- lisp/org/lisp/org-table.el | 375 +- lisp/org/lisp/org-tempo.el | 2 +- lisp/org/lisp/org-timer.el | 19 +- lisp/org/lisp/org-version.el | 4 +- lisp/org/lisp/org.el | 4390 +++++++------- lisp/org/lisp/ox-ascii.el | 17 +- lisp/org/lisp/ox-beamer.el | 2 +- lisp/org/lisp/ox-html.el | 336 +- lisp/org/lisp/ox-icalendar.el | 11 +- lisp/org/lisp/ox-latex.el | 84 +- lisp/org/lisp/ox-man.el | 22 +- lisp/org/lisp/ox-md.el | 345 +- lisp/org/lisp/ox-odt.el | 34 +- lisp/org/lisp/ox-org.el | 4 +- lisp/org/lisp/ox-publish.el | 11 +- lisp/org/lisp/ox-texinfo.el | 23 +- lisp/org/lisp/ox.el | 307 +- lisp/org/mk/org-fixup.el | 2 +- lisp/org/mk/version.mk | 4 +- lisp/org/testing/examples/babel.el | 5 + lisp/org/testing/examples/babel.org | 13 + lisp/org/testing/examples/ob-C-test.org | 6 + lisp/org/testing/examples/ob-shell-test.org | 12 +- .../testing/examples/property-inheritance.org | 6 +- lisp/org/testing/lisp/test-ob-C.el | 23 +- lisp/org/testing/lisp/test-ob-lob.el | 28 + lisp/org/testing/lisp/test-ob-python.el | 75 +- lisp/org/testing/lisp/test-ob-shell.el | 44 +- lisp/org/testing/lisp/test-ob-tangle.el | 208 +- lisp/org/testing/lisp/test-ob.el | 215 +- lisp/org/testing/lisp/test-ol.el | 118 +- lisp/org/testing/lisp/test-org-agenda.el | 15 +- lisp/org/testing/lisp/test-org-archive.el | 38 + lisp/org/testing/lisp/test-org-attach.el | 147 +- lisp/org/testing/lisp/test-org-capture.el | 10 + lisp/org/testing/lisp/test-org-clock.el | 53 +- lisp/org/testing/lisp/test-org-colview.el | 19 +- lisp/org/testing/lisp/test-org-datetree.el | 65 +- lisp/org/testing/lisp/test-org-duration.el | 14 +- lisp/org/testing/lisp/test-org-element.el | 67 +- lisp/org/testing/lisp/test-org-inlinetask.el | 1 - lisp/org/testing/lisp/test-org-lint.el | 35 + lisp/org/testing/lisp/test-org-list.el | 213 +- lisp/org/testing/lisp/test-org-macro.el | 66 + lisp/org/testing/lisp/test-org-num.el | 19 + lisp/org/testing/lisp/test-org-pcomplete.el | 15 + lisp/org/testing/lisp/test-org-src.el | 11 + lisp/org/testing/lisp/test-org-table.el | 143 +- lisp/org/testing/lisp/test-org.el | 1172 +++- lisp/org/testing/lisp/test-ox.el | 29 +- lisp/org/testing/org-test.el | 1 + lisp/orgit.el | 19 +- lisp/page-break-lines.el | 7 +- lisp/php-mode/php-align.el | 1 - lisp/php-mode/php-face.el | 1 - lisp/php-mode/php-local-manual.el | 39 + lisp/php-mode/php-mode-debug.el | 1 - lisp/php-mode/php-mode-pkg.el | 8 +- lisp/php-mode/php-mode.el | 38 +- lisp/php-mode/php-project.el | 1 - lisp/php-mode/php.el | 1 - lisp/popwin.el | 212 +- lisp/powershell.el | 14 +- lisp/pythonic.el | 6 +- lisp/rainbow-mode.el | 14 +- lisp/restart-emacs.el | 39 +- lisp/spacemacs-theme/spacemacs-common.el | 18 + lisp/spacemacs-theme/spacemacs-theme-pkg.el | 4 +- lisp/swiper.el | 52 +- lisp/transient/transient-pkg.el | 8 +- lisp/transient/transient.el | 402 +- lisp/transient/transient.info | 206 +- lisp/treemacs-magit.el | 15 +- lisp/treemacs/Changelog.org | 14 + lisp/treemacs/icons/default/svgrepo/cal.png | Bin 14260 -> 1350 bytes lisp/treemacs/icons/default/svgrepo/house.png | Bin 24590 -> 1636 bytes lisp/treemacs/icons/default/svgrepo/list.png | Bin 15994 -> 846 bytes .../treemacs/icons/default/svgrepo/repeat.png | Bin 19617 -> 1213 bytes .../treemacs/icons/default/svgrepo/screen.png | Bin 18207 -> 1153 bytes .../icons/default/svgrepo/suitcase.png | Bin 17182 -> 1215 bytes lisp/treemacs/icons/default/vsc/binary.png | Bin 1965 -> 816 bytes lisp/treemacs/icons/default/vsc/deps.png | Bin 2039 -> 676 bytes lisp/treemacs/icons/default/vsc/elm.png | Bin 2356 -> 890 bytes lisp/treemacs/icons/default/vsc/license.png | Bin 2377 -> 830 bytes lisp/treemacs/icons/default/vsc/lisp.png | Bin 2112 -> 684 bytes lisp/treemacs/icons/default/vsc/log.png | Bin 1548 -> 642 bytes lisp/treemacs/icons/default/vsc/lua.png | Bin 2981 -> 1149 bytes lisp/treemacs/icons/default/vsc/make.png | Bin 1775 -> 1337 bytes lisp/treemacs/icons/default/vsc/nim.png | Bin 1773 -> 652 bytes lisp/treemacs/icons/default/vsc/org.png | Bin 2732 -> 957 bytes lisp/treemacs/icons/default/vsc/perl.png | Bin 3043 -> 1103 bytes lisp/treemacs/icons/default/vsc/perl6.png | Bin 1637 -> 1444 bytes lisp/treemacs/icons/default/vsc/r.png | Bin 2832 -> 937 bytes lisp/treemacs/icons/default/vsc/ruby.png | Bin 3525 -> 1241 bytes lisp/treemacs/icons/default/vsc/scss.png | Bin 2877 -> 981 bytes lisp/treemacs/icons/default/vsc/sql.png | Bin 2080 -> 843 bytes lisp/treemacs/icons/default/vsc/toml.png | Bin 1836 -> 641 bytes lisp/treemacs/icons/default/vsc/vim.png | Bin 3410 -> 1224 bytes lisp/treemacs/icons/default/vsc/xml.png | Bin 1994 -> 576 bytes lisp/treemacs/icons/default/vsc/zip.png | Bin 3328 -> 1259 bytes lisp/treemacs/treemacs-async.el | 32 +- lisp/treemacs/treemacs-bookmarks.el | 15 +- lisp/treemacs/treemacs-compatibility.el | 41 +- lisp/treemacs/treemacs-core-utils.el | 66 +- lisp/treemacs/treemacs-customization.el | 195 +- lisp/treemacs/treemacs-diagnostics.el | 2 +- lisp/treemacs/treemacs-dirs-to-collapse.py | 2 +- lisp/treemacs/treemacs-dom.el | 18 +- lisp/treemacs/treemacs-extensions.el | 55 +- lisp/treemacs/treemacs-faces.el | 6 +- lisp/treemacs/treemacs-filewatch-mode.el | 19 +- lisp/treemacs/treemacs-follow-mode.el | 5 +- lisp/treemacs/treemacs-fringe-indicator.el | 79 +- lisp/treemacs/treemacs-header-line.el | 18 +- lisp/treemacs/treemacs-hydras.el | 291 + lisp/treemacs/treemacs-icons.el | 103 +- lisp/treemacs/treemacs-interface.el | 148 +- lisp/treemacs/treemacs-logging.el | 27 +- lisp/treemacs/treemacs-macros.el | 68 +- lisp/treemacs/treemacs-mode.el | 210 +- lisp/treemacs/treemacs-mouse-interface.el | 69 +- lisp/treemacs/treemacs-persistence.el | 70 +- lisp/treemacs/treemacs-pkg.el | 9 +- lisp/treemacs/treemacs-rendering.el | 203 +- lisp/treemacs/treemacs-scope.el | 17 +- .../treemacs-single-file-git-status.py | 3 + lisp/treemacs/treemacs-tag-follow-mode.el | 115 +- lisp/treemacs/treemacs-tags.el | 187 +- lisp/treemacs/treemacs-themes.el | 14 +- lisp/treemacs/treemacs-visuals.el | 10 +- lisp/treemacs/treemacs-workspaces.el | 295 +- lisp/treemacs/treemacs.el | 30 +- lisp/use-package/use-package-core.el | 15 +- lisp/use-package/use-package-pkg.el | 8 +- lisp/use-package/use-package.el | 2 +- lisp/use-package/use-package.info | 64 +- lisp/versions | 133 +- lisp/virtual-auto-fill.el | 6 +- lisp/visual-fill-column.el | 220 +- lisp/web-mode.el | 589 +- lisp/which-key.el | 162 +- lisp/with-editor/with-editor-pkg.el | 8 +- lisp/with-editor/with-editor.el | 45 +- lisp/with-editor/with-editor.info | 42 +- lisp/yasnippet.el | 6 +- settings/deft-settings.el | 1 + settings/gui-settings.el | 4 +- settings/version-control-settings.el | 12 +- 467 files changed, 26642 insertions(+), 22487 deletions(-) delete mode 100644 lisp/company/company-eclim.el delete mode 100644 lisp/company/company-xcode.el delete mode 100644 lisp/ess/announc.info delete mode 100644 lisp/ess/ess.info delete mode 100644 lisp/ess/readme.info create mode 100644 lisp/key-chord.el create mode 100644 lisp/org/lisp/org-refile.el create mode 100644 lisp/org/testing/examples/babel.el create mode 100644 lisp/php-mode/php-local-manual.el create mode 100644 lisp/treemacs/treemacs-hydras.el diff --git a/lisp/all-the-icons/all-the-icons-pkg.el b/lisp/all-the-icons/all-the-icons-pkg.el index 85c16d3b..6dee3c79 100644 --- a/lisp/all-the-icons/all-the-icons-pkg.el +++ b/lisp/all-the-icons/all-the-icons-pkg.el @@ -1,12 +1,12 @@ -(define-package "all-the-icons" "20200730.1545" "A library for inserting Developer icons" +(define-package "all-the-icons" "20210106.1227" "A library for inserting Developer icons" '((emacs "24.3") (memoize "1.0.1")) - :commit "8c0228053dd6693d926970d89270094be52b0f75" :keywords - '("convenient" "lisp") - :authors + :commit "9aa16ae198073fe839a0abfa9a7d3a9dc85ef5f9" :authors '(("Dominic Charlesworth" . "dgc336@gmail.com")) :maintainer '("Dominic Charlesworth" . "dgc336@gmail.com") + :keywords + '("convenient" "lisp") :url "https://github.com/domtronn/all-the-icons.el") ;; Local Variables: ;; no-byte-compile: t diff --git a/lisp/all-the-icons/all-the-icons.el b/lisp/all-the-icons/all-the-icons.el index e99b658a..4a21b441 100644 --- a/lisp/all-the-icons/all-the-icons.el +++ b/lisp/all-the-icons/all-the-icons.el @@ -98,6 +98,7 @@ (require 'all-the-icons-faces) +(defvar web-mode-content-type) ;silence byte-compiler warning ;;; Custom Variables (defgroup all-the-icons nil "Manage how All The Icons formats icons." @@ -213,7 +214,7 @@ ("\\.java$" all-the-icons-alltheicon "java" :height 1.0 :face all-the-icons-purple) - ("\\.go$" all-the-icons-alltheicon "go" :height 1.0 :face all-the-icons-blue) + ("\\.go$" all-the-icons-fileicon "go" :height 1.0 :face all-the-icons-blue) ("\\.mp3$" all-the-icons-faicon "volume-up" :face all-the-icons-dred) ("\\.wav$" all-the-icons-faicon "volume-up" :face all-the-icons-dred) @@ -239,6 +240,7 @@ ("\\.ps1$" all-the-icons-fileicon "powershell" :face all-the-icons-blue) ("\\.prol?o?g?$" all-the-icons-alltheicon "prolog" :height 1.1 :face all-the-icons-lmaroon) ("\\.py$" all-the-icons-alltheicon "python" :height 1.0 :face all-the-icons-dblue) + ("\\.ipynb$" all-the-icons-fileicon "jupyter" :height 1.0 :face all-the-icons-dorange) ("\\.rkt$" all-the-icons-fileicon "racket" :height 1.2 :face all-the-icons-red) ("^Gemfile\\(\\.lock\\)?$" all-the-icons-alltheicon "ruby-alt" :face all-the-icons-red) @@ -332,7 +334,7 @@ ("\\.csx?$" all-the-icons-alltheicon "csharp-line" :face all-the-icons-dblue) - ("\\.cljc?$" all-the-icons-alltheicon "clojure-line" :height 1.0 :face all-the-icons-blue :v-adjust 0.0) + ("\\.cljc?$" all-the-icons-alltheicon "clojure" :height 1.0 :face all-the-icons-blue :v-adjust 0.0) ("\\.cljs$" all-the-icons-fileicon "cljs" :height 1.0 :face all-the-icons-dblue :v-adjust 0.0) ("\\.coffee$" all-the-icons-alltheicon "coffeescript" :height 1.0 :face all-the-icons-maroon) @@ -347,7 +349,7 @@ ;; Lisps ("\\.cl$" all-the-icons-fileicon "clisp" :face all-the-icons-lorange) ("\\.l\\(isp\\)?$" all-the-icons-fileicon "lisp" :face all-the-icons-orange) - ("\\.el$" all-the-icons-fileicon "elisp" :height 1.0 :v-adjust -0.2 :face all-the-icons-purple) + ("\\.el$" all-the-icons-fileicon "elisp" :height 1.0 :v-adjust -0.1 :face all-the-icons-purple) ;; Stylesheeting ("\\.css$" all-the-icons-alltheicon "css3" :face all-the-icons-yellow) @@ -498,9 +500,9 @@ (defvar all-the-icons-mode-icon-alist '( - (emacs-lisp-mode all-the-icons-fileicon "elisp" :height 1.0 :v-adjust -0.2 :face all-the-icons-purple) + (emacs-lisp-mode all-the-icons-fileicon "elisp" :height 1.0 :v-adjust -0.1 :face all-the-icons-purple) (erc-mode all-the-icons-faicon "commenting-o" :height 1.0 :v-adjust 0.0) - (inferior-emacs-lisp-mode all-the-icons-fileicon "elisp" :height 1.0 :v-adjust -0.2 :face all-the-icons-lblue) + (inferior-emacs-lisp-mode all-the-icons-fileicon "elisp" :height 1.0 :v-adjust -0.1 :face all-the-icons-lblue) (dired-mode all-the-icons-octicon "file-directory" :v-adjust 0.0) (lisp-interaction-mode all-the-icons-fileicon "lisp" :v-adjust -0.1 :face all-the-icons-orange) (sly-mrepl-mode all-the-icons-fileicon "clisp" :v-adjust -0.1 :face all-the-icons-orange) @@ -541,8 +543,8 @@ ;; Special matcher for Web Mode based on the `web-mode-content-type' of the current buffer (web-mode all-the-icons--web-mode-icon) - (fundamental-mode all-the-icons-fileicon "elisp" :height 1.0 :v-adjust -0.2 :face all-the-icons-dsilver) - (special-mode all-the-icons-fileicon "elisp" :height 1.0 :v-adjust -0.2 :face all-the-icons-yellow) + (fundamental-mode all-the-icons-fileicon "elisp" :height 1.0 :v-adjust -0.1 :face all-the-icons-dsilver) + (special-mode all-the-icons-fileicon "elisp" :height 1.0 :v-adjust -0.1 :face all-the-icons-yellow) (text-mode all-the-icons-octicon "file-text" :v-adjust 0.0 :face all-the-icons-cyan) (enh-ruby-mode all-the-icons-alltheicon "ruby-alt" :face all-the-icons-lred) (ruby-mode all-the-icons-alltheicon "ruby-alt" :face all-the-icons-lred) @@ -567,7 +569,7 @@ (erlang-mode all-the-icons-alltheicon "erlang" :face all-the-icons-red :v-adjust -0.1 :height 0.9) (elixir-mode all-the-icons-alltheicon "elixir" :face all-the-icons-lorange :v-adjust -0.1 :height 0.9) (java-mode all-the-icons-alltheicon "java" :height 1.0 :face all-the-icons-purple) - (go-mode all-the-icons-alltheicon "go" :height 1.0 :face all-the-icons-blue) + (go-mode all-the-icons-fileicon "go" :height 1.0 :face all-the-icons-blue) (matlab-mode all-the-icons-fileicon "matlab" :face all-the-icons-orange) (perl-mode all-the-icons-alltheicon "perl" :face all-the-icons-lorange) (cperl-mode all-the-icons-alltheicon "perl" :face all-the-icons-lorange) @@ -583,8 +585,8 @@ (c-mode all-the-icons-alltheicon "c-line" :face all-the-icons-blue) (c++-mode all-the-icons-alltheicon "cplusplus-line" :v-adjust -0.2 :face all-the-icons-blue) (csharp-mode all-the-icons-alltheicon "csharp-line" :face all-the-icons-dblue) - (clojure-mode all-the-icons-alltheicon "clojure-line" :height 1.0 :face all-the-icons-blue) - (cider-repl-mode all-the-icons-alltheicon "clojure-line" :height 1.0 :face all-the-icons-dblue) + (clojure-mode all-the-icons-alltheicon "clojure" :height 1.0 :face all-the-icons-blue) + (cider-repl-mode all-the-icons-alltheicon "clojure" :height 1.0 :face all-the-icons-green) (clojurescript-mode all-the-icons-fileicon "cljs" :height 1.0 :face all-the-icons-dblue) (coffee-mode all-the-icons-alltheicon "coffeescript" :height 1.0 :face all-the-icons-maroon) (lisp-mode all-the-icons-fileicon "lisp" :face all-the-icons-orange) @@ -926,7 +928,13 @@ When F is provided, the info function is calculated with the format (defun all-the-icons--insert-function-name (name) "Get the symbol for an icon insert function for icon set NAME." - (intern (concat "all-the-icons-insert-" (downcase (symbol-name name)))))) + (intern (concat "all-the-icons-insert-" (downcase (symbol-name name))))) + + (defun all-the-icons--family-scale-factor (family) + (intern (concat "all-the-icons-" (symbol-name family) "-scale-factor"))) + + (defun all-the-icons--family-adjust (family) + (intern (concat "all-the-icons-default-" (symbol-name family) "-adjust")))) ;; Icon insertion functions @@ -1036,14 +1044,27 @@ FONT-NAME is the name of the .ttf file providing the font, defaults to FAMILY." `(progn (add-to-list 'all-the-icons-font-families (quote ,name)) (add-to-list 'all-the-icons-font-names (quote ,(downcase (format "%s.ttf" (or font-name family))))) - + (defcustom ,(all-the-icons--family-scale-factor name) 1.0 + ,(format "The additional Scale Factor for the `height' face property of all %s icons." + (symbol-name name)) + :group 'all-the-icons + :type 'number) + (defcustom ,(all-the-icons--family-adjust name) 0.0 + ,(format "The additional adjustment to be made to the `raise' display property of all %s icons." + (symbol-name name)) + :group 'all-the-icons + :type 'number) (defun ,(all-the-icons--family-name name) () ,family) (defun ,(all-the-icons--data-name name) () ,alist) (defun ,(all-the-icons--function-name name) (icon-name &rest args) (let ((icon (cdr (assoc icon-name ,alist))) (other-face (when all-the-icons-color-icons (plist-get args :face))) - (height (* all-the-icons-scale-factor (or (plist-get args :height) 1.0))) - (v-adjust (* all-the-icons-scale-factor (or (plist-get args :v-adjust) all-the-icons-default-adjust))) + (height (* all-the-icons-scale-factor + ,(all-the-icons--family-scale-factor name) + (or (plist-get args :height) 1.0))) + (v-adjust (* all-the-icons-scale-factor ,(all-the-icons--family-scale-factor name) + (+ (or (plist-get args :v-adjust) all-the-icons-default-adjust) + ,(all-the-icons--family-adjust name)))) (family ,family)) (unless icon (error (format "Unable to find icon with name `%s' in icon set `%s'" icon-name (quote ,name)))) @@ -1060,7 +1081,7 @@ FONT-NAME is the name of the .ttf file providing the font, defaults to FAMILY." (interactive "P") (all-the-icons-insert arg (quote ,name))))) -(define-obsolete-function-alias 'define-icon 'all-the-icons-define-icon) +(define-obsolete-function-alias 'define-icon 'all-the-icons-define-icon "4.0.0") (all-the-icons-define-icon alltheicon all-the-icons-data/alltheicons-alist "all-the-icons") (all-the-icons-define-icon fileicon all-the-icons-data/file-icon-alist "file-icons") diff --git a/lisp/all-the-icons/data/data-fileicons.el b/lisp/all-the-icons/data/data-fileicons.el index 35108af3..200cf853 100644 --- a/lisp/all-the-icons/data/data-fileicons.el +++ b/lisp/all-the-icons/data/data-fileicons.el @@ -171,7 +171,7 @@ ( "glyphs" . "\x47" ) ( "gn" . "\xea25" ) ( "gnu" . "\xe679" ) - ( "go" . "\xe624" ) + ( "go" . "\xeaae" ) ( "godot" . "\xe974" ) ( "golo" . "\xe979" ) ( "gosu" . "\xe97a" ) diff --git a/lisp/amx.el b/lisp/amx.el index 5fb087be..1d795d24 100644 --- a/lisp/amx.el +++ b/lisp/amx.el @@ -8,8 +8,8 @@ ;; Cornelius Mika ;; Maintainer: Ryan C. Thompson ;; URL: http://github.com/DarwinAwardWinner/amx/ -;; Package-Version: 20200701.2108 -;; Package-Commit: ccfc92c600df681df5e8b5fecec328c462ceb71e +;; Package-Version: 20210101.1921 +;; Package-Commit: b99149715266b5c2c48f5a0fc43716d36575da5f ;; Package-Requires: ((emacs "24.4") (s "0")) ;; Version: 3.3 ;; Keywords: convenience, usability @@ -187,10 +187,7 @@ periodic updates will be performed." (defun amx-set-save-file (symbol value) "Custom setter for `amx-save-file'. -Arguments are the same as in `set-default'. - -This function will refuse to set the backend unless it can load -the associated feature, if any." +Arguments are the same as in `set-default'." (cl-assert (eq symbol 'amx-save-file)) (let ((old-value (when (boundp symbol) (symbol-value symbol)))) (set-default symbol value) @@ -200,14 +197,21 @@ the associated feature, if any." (when (bound-and-true-p amx-initialized) (amx-initialize t)) ;; If the new save file doesn't exist but the old one does, copy - ;; the old file to the new location. + ;; the old file to the new location. In this case we don't need + ;; to re-initialize, because the contents of the file have not + ;; changed. (when (and old-value (file-exists-p old-value)) (copy-file old-value value))))) (defcustom amx-save-file (locate-user-emacs-file "amx-items" ".amx-items") "File in which the amx state is saved between Emacs sessions. -Variables stored are: `amx-data', `amx-history'." +Variables stored are: `amx-data', `amx-history'. + +When changing this variable through Custom, amx will check for an +already-existing file at the new path. If it exists, amx will +re-initialize using this file. Otherwise, it will copy the +current save file from the old location to the new one." :type '(choice (string :tag "File name") (const :tag "Don't save" nil)) :set #'amx-set-save-file) @@ -629,6 +633,8 @@ May not work for things like ido and ivy." :history extended-command-history :reverse-history t :must-match t + :fuzzy (or (bound-and-true-p helm-mode-fuzzy-match) + (bound-and-true-p helm-M-x-fuzzy-match)) :keymap (make-composed-keymap amx-map helm-comp-read-map))) (amx-define-backend diff --git a/lisp/anaconda-mode.el b/lisp/anaconda-mode.el index 5534b34c..b7638fa8 100644 --- a/lisp/anaconda-mode.el +++ b/lisp/anaconda-mode.el @@ -4,8 +4,8 @@ ;; Author: Artem Malyshev ;; URL: https://github.com/proofit404/anaconda-mode -;; Package-Version: 20200129.1718 -;; Package-Commit: 10299bd9ff38c4f0da1d892905d02ef828e7fdce +;; Package-Version: 20200912.239 +;; Package-Commit: 39b1cf88c8c459901630d248d6135d8644075648 ;; Version: 0.1.13 ;; Package-Requires: ((emacs "25.1") (pythonic "0.1.0") (dash "2.6.0") (s "1.9") (f "0.16.2")) @@ -73,7 +73,10 @@ (defcustom anaconda-mode-tunnel-setup-sleep 2 "Time in seconds `anaconda-mode' waits after tunnel creation before first RPC call." - :group 'anaconda-mode + :type 'integer) + +(defcustom anaconda-mode-sync-request-timeout 2 + "Time in seconds `anaconda-mode' waits for a synchronous response." :type 'integer) ;;; Compatibility @@ -379,12 +382,27 @@ be bound." (equal (process-get anaconda-mode-process 'remote-port) (pythonic-remote-port))))))) +(defun anaconda-mode-get-server-process-cwd () + "Get the working directory for starting the anaconda server process. + +The current working directory ends up being on sys.path, which may +result in conflicts with stdlib modules. + +When running python from the local machine, we start the server +process from `anaconda-mode-installation-directory'. +This function creates that directory if it doesn't exist yet." + (when (pythonic-local-p) + (unless (file-directory-p anaconda-mode-installation-directory) + (make-directory anaconda-mode-installation-directory t)) + anaconda-mode-installation-directory)) + (defun anaconda-mode-bootstrap (&optional callback) "Run `anaconda-mode' server. CALLBACK function will be called when `anaconda-mode-port' will be bound." (setq anaconda-mode-process (pythonic-start-process :process anaconda-mode-process-name + :cwd (anaconda-mode-get-server-process-cwd) :buffer (get-buffer-create anaconda-mode-process-buffer) :query-on-exit nil :filter (lambda (process output) @@ -473,7 +491,10 @@ called when `anaconda-mode-port' will be bound." anaconda-mode-ssh-process-buffer "ssh" "-nNT" "-L" (format "%s:localhost:%s" (anaconda-mode-port) (anaconda-mode-port)) - (format "%s@%s" (pythonic-remote-user) (pythonic-remote-host)) + (if (pythonic-remote-user) + (format "%s@%s" (pythonic-remote-user) (pythonic-remote-host)) + ;; Asssume remote host is an ssh alias + (pythonic-remote-host)) "-p" (number-to-string (or (pythonic-remote-port) 22))))) ;; prevent race condition between tunnel setup and first use (sleep-for anaconda-mode-tunnel-setup-sleep) @@ -486,10 +507,25 @@ called when `anaconda-mode-port' will be bound." (defun anaconda-mode-call (command callback) "Make remote procedure call for COMMAND. -Apply CALLBACK to it result." +Apply CALLBACK to the result asynchronously." (anaconda-mode-start (lambda () (anaconda-mode-jsonrpc command callback)))) +(defun anaconda-mode-call-sync (command callback) + "Make remote procedure call for COMMAND. +Apply CALLBACK to the result synchronously." + (let ((start-time (current-time)) + (result 'pending)) + (anaconda-mode-call + command + (lambda (r) (setq result r))) + (while (eq result 'pending) + (accept-process-output nil 0.01) + (when (> (cadr (time-subtract (current-time) start-time)) + anaconda-mode-sync-request-timeout) + (error "%s request timed out" command))) + (funcall callback result))) + (defun anaconda-mode-jsonrpc (command callback) "Perform JSONRPC call for COMMAND. Apply CALLBACK to the call result when retrieve it. Remote @@ -740,6 +776,42 @@ number position, column number position and file path." ;;; Xref. +(defun anaconda-mode-xref-backend () + "Integrate `anaconda-mode' with xref." + 'anaconda) + +(cl-defmethod xref-backend-definitions ((_backend (eql anaconda)) _identifier) + "Find definitions for thing at point." + (anaconda-mode-call-sync + "goto_definitions" + (lambda (result) + (if result + (if (stringp result) + (progn + (message result) + nil) + (anaconda-mode-make-xrefs result)))))) + +(cl-defmethod xref-backend-references ((_backend (eql anaconda)) _identifier) + "Find references for thing at point." + (anaconda-mode-call-sync + "usages" + (lambda (result) + (if result + (if (stringp result) + (progn + (message result) + nil) + (anaconda-mode-make-xrefs result)))))) + +(cl-defmethod xref-backend-apropos ((_backend (eql anaconda)) _pattern) + "Not implemented." + nil) + +(cl-defmethod xref-backend-identifier-completion-table ((_backend (eql anaconda))) + "Not implemented." + nil) + (defun anaconda-mode-show-xrefs (result display-action error-message) "Show xref from RESULT using DISPLAY-ACTION. Show ERROR-MESSAGE if result is empty." @@ -826,7 +898,10 @@ Show ERROR-MESSAGE if result is empty." \\{anaconda-mode-map}" :lighter anaconda-mode-lighter :keymap anaconda-mode-map - (setq-local url-http-attempt-keepalives nil)) + (setq-local url-http-attempt-keepalives nil) + (if anaconda-mode + (add-hook 'xref-backend-functions #'anaconda-mode-xref-backend nil t) + (remove-hook 'xref-backend-functions #'anaconda-mode-xref-backend t))) ;;;###autoload (define-minor-mode anaconda-eldoc-mode diff --git a/lisp/async/async-bytecomp.el b/lisp/async/async-bytecomp.el index 1198497f..430d196b 100644 --- a/lisp/async/async-bytecomp.el +++ b/lisp/async/async-bytecomp.el @@ -41,17 +41,11 @@ (require 'cl-lib) (require 'async) -(defcustom async-bytecomp-allowed-packages - ;; FIXME: Arguably the default should be `all', but currently - ;; this minor mode is silently/forcefully enabled by Helm and Magit to ensure - ;; they get compiled asynchronously, so this conservative default value is - ;; here to make sure that the mode can be enabled without the user's - ;; explicit consent. - '(async forge helm helm-core helm-ls-git helm-ls-hg magit) +(defcustom async-bytecomp-allowed-packages 'all "Packages in this list will be compiled asynchronously by `package--compile'. All the dependencies of these packages will be compiled async too, so no need to add dependencies to this list. -The value of this variable can also be the symbol `all', in this case +The value of this variable can also be the symbol `all' (default), in this case all packages are always compiled asynchronously." :group 'async :type '(choice diff --git a/lisp/async/async-pkg.el b/lisp/async/async-pkg.el index dbce789b..19b84371 100644 --- a/lisp/async/async-pkg.el +++ b/lisp/async/async-pkg.el @@ -1,7 +1,11 @@ -(define-package "async" "20200113.1745" "Asynchronous processing in Emacs" +(define-package "async" "20200809.501" "Asynchronous processing in Emacs" '((emacs "24.3")) + :commit "14f48de586b0977e3470f053b810d77b07ea427a" :authors + '(("John Wiegley" . "jwiegley@gmail.com")) + :maintainer + '("John Wiegley" . "jwiegley@gmail.com") :keywords - '("async") + '("convenience" "async") :url "https://github.com/jwiegley/emacs-async") ;; Local Variables: ;; no-byte-compile: t diff --git a/lisp/avy.el b/lisp/avy.el index 02d026ff..c4ee91f6 100644 --- a/lisp/avy.el +++ b/lisp/avy.el @@ -4,8 +4,8 @@ ;; Author: Oleh Krehel ;; URL: https://github.com/abo-abo/avy -;; Package-Version: 20200624.1148 -;; Package-Commit: bbf1e7339eba06784dfe86643bb0fbddf5bb0342 +;; Package-Version: 20201226.1734 +;; Package-Commit: e92cb37457b43336b765630dbfbea8ba4be601fa ;; Version: 0.5.0 ;; Package-Requires: ((emacs "24.1") (cl-lib "0.5")) ;; Keywords: point, location @@ -2178,6 +2178,22 @@ The window scope is determined by `avy-all-windows' (ARG negates it)." (error (set-mark-command 4))))) +;;;###autoload +(defun avy-transpose-lines-in-region () + "Transpose lines in the active region." + (interactive) + (when (and (use-region-p) (> (count-lines (region-beginning) (region-end)) 1)) + (let ((avy-all-windows nil) + (fst-line-point (avy--line nil (region-beginning) (region-end)))) + (when fst-line-point + (let ((snd-line-point (avy--line nil (region-beginning) (region-end)))) + (when snd-line-point + (save-mark-and-excursion + (push-mark fst-line-point) + (goto-char snd-line-point) + (transpose-lines 0)) + (avy-transpose-lines-in-region))))))) + ;; ** Org-mode (defvar org-reverse-note-order) (declare-function org-refile "org") diff --git a/lisp/bibtex-completion.el b/lisp/bibtex-completion.el index 44b028a8..ac0d4f6f 100644 --- a/lisp/bibtex-completion.el +++ b/lisp/bibtex-completion.el @@ -4,8 +4,8 @@ ;; Justin Burkett ;; Maintainer: Titus von der Malsburg ;; URL: https://github.com/tmalsburg/helm-bibtex -;; Package-Version: 20200513.852 -;; Package-Commit: 8a0dd9841316793aacddea744d6b8ca4a7857a35 +;; Package-Version: 20200908.1017 +;; Package-Commit: 1bb81d77e08296a50de7ebfe5cf5b0c715b7f3d6 ;; Version: 1.0.0 ;; Package-Requires: ((parsebib "1.0") (s "1.9.0") (dash "2.6.0") (f "0.16.2") (cl-lib "0.5") (biblio "0.2") (emacs "26.1")) @@ -115,6 +115,8 @@ This should be a single character." '((org-mode . bibtex-completion-format-citation-ebib) (latex-mode . bibtex-completion-format-citation-cite) (markdown-mode . bibtex-completion-format-citation-pandoc-citeproc) + (python-mode . bibtex-completion-format-citation-sphinxcontrib-bibtex) + (rst-mode . bibtex-completion-format-citation-sphinxcontrib-bibtex) (default . bibtex-completion-format-citation-default)) "The functions used for formatting citations. The publication can be cited, for example, as \cite{key} or @@ -419,7 +421,7 @@ Also sets `bibtex-completion-display-formats-internal'." (let* ((format-string (cdr format)) (fields-width 0) (string-width - (length + (string-width (s-format format-string (lambda (field) (setq fields-width @@ -481,7 +483,7 @@ for string replacement." (defun bibtex-completion-candidates () "Read the BibTeX files and return a list of conses, one for each entry. The first element of these conses is a string containing authors, -editors, title, year, type, and key of the entry. This is string +editors, title, year, type, and key of the entry. This string is used for matching. The second element is the entry (only the fields listed above) as an alist." (let ((files (nreverse (bibtex-completion-normalize-bibliography 'bibtex))) @@ -1032,6 +1034,10 @@ only adds KEYS to it." (s-join ", " (--map (format "ebib:%s" it) keys))) +(defun bibtex-completion-format-citation-sphinxcontrib-bibtex (keys) + "Format sphinxcontrib-bibtex references for keys in KEYS." + (format ":cite:`%s`" (s-join "," keys))) + (defun bibtex-completion-format-citation-org-link-to-PDF (keys) "Format org-links to PDFs associated with entries in KEYS. Uses first matching PDF if several are available. Entries for @@ -1539,41 +1545,65 @@ BibTeX files. If this fails, return nil." (require 'reftex-cite nil t) (ignore-errors (reftex-get-bibfile-list))))) +(defun bibtex-completion-get-key-bibtex () + "Return the key of the BibTeX entry at point, nil otherwise. +This function can be used by `bibtex-completion-key-at-point' to +find the key of the BibTeX entry at point in a BibTeX-mode +buffer." + (when (eq major-mode 'bibtex-mode) + (save-excursion + (bibtex-beginning-of-entry) + (and (looking-at bibtex-entry-maybe-empty-head) + (bibtex-key-in-head))))) + +(defun bibtex-completion-get-key-latex () + "Return the key of the BibTeX entry at point, nil otherwise. +This function can be used by `bibtex-completion-key-at-point' to +find the key of the BibTeX entry at point in a LaTeX buffer." + (when (and (derived-mode-p 'latex-mode) + (require 'reftex-parse nil t)) + (save-excursion + (skip-chars-backward "[:space:],;}") + (let ((macro (reftex-what-macro 1))) + (and (stringp (car macro)) + (string-match "\\`\\\\cite\\|cite\\'" (car macro)) + ;; allow '_' in citekeys + (let ((temp-syn-table (make-syntax-table))) + (modify-syntax-entry ?_ "_" temp-syn-table) + (with-syntax-table temp-syn-table + (thing-at-point 'symbol)))))))) + +(defun bibtex-completion-get-key-org-bibtex () + "Return the key of the BibTeX entry at point, nil otherwise. +This function can be used by `bibtex-completion-key-at-point' to +find the key of the BibTeX entry at point in an Org-mode buffer." + (when (eq major-mode 'org-mode) + (let (key) + (and (setq key (org-entry-get nil + (if (boundp 'org-bibtex-key-property) + org-bibtex-key-property + "CUSTOM_ID") + t)) + ;; KEY may be the empty string the the property is + ;; present but has no value + (> (length key) 0) + key)))) + +(defvar bibtex-completion-key-at-point-functions + (list #'bibtex-completion-get-key-bibtex + #'bibtex-completion-get-key-latex + #'bibtex-completion-get-key-org-bibtex) + "List of functions to use to find the BibTeX key. +The functions should take no argument and return the BibTeX +key. Stops as soon as a function returns something. +See `bibtex-completion-key-at-point' for details.") + (defun bibtex-completion-key-at-point () "Return the key of the BibTeX entry at point. -If the current file is a BibTeX file, return the key of the entry -at point. Otherwise, try to use `reftex' to check whether point -is at a citation macro, and if so return the key at -point. Otherwise, if the current file is an org mode file, return -the value of `org-bibtex-key-property' (or default to -\"CUSTOM_ID\"). Otherwise, return nil." - (or (and (eq major-mode 'bibtex-mode) - (save-excursion - (bibtex-beginning-of-entry) - (and (looking-at bibtex-entry-maybe-empty-head) - (bibtex-key-in-head)))) - (and (require 'reftex-parse nil t) - (save-excursion - (skip-chars-backward "[:space:],;}") - (let ((macro (reftex-what-macro 1))) - (and (stringp (car macro)) - (string-match "\\`\\\\cite\\|cite\\'" (car macro)) - ;; allow '_' in citekeys - (let ((temp-syn-table (make-syntax-table))) - (modify-syntax-entry ?_ "_" temp-syn-table) - (with-syntax-table temp-syn-table - (thing-at-point 'symbol))))))) - (and (eq major-mode 'org-mode) - (let (key) - (and (setq key (org-entry-get nil - (if (boundp 'org-bibtex-key-property) - org-bibtex-key-property - "CUSTOM_ID") - t)) - ;; KEY may be the empty string the the property is - ;; present but has no value - (> (length key) 0) - key))))) +The functions used to match the keys are defined in +`bibtex-completion-key-at-point-functions'." + (cl-some #'identity + (mapcar #'funcall bibtex-completion-key-at-point-functions))) (provide 'bibtex-completion) diff --git a/lisp/bind-key.el b/lisp/bind-key.el index 803d78ef..bb232efe 100644 --- a/lisp/bind-key.el +++ b/lisp/bind-key.el @@ -7,8 +7,8 @@ ;; Created: 16 Jun 2012 ;; Modified: 29 Nov 2017 ;; Version: 2.4 -;; Package-Version: 20191110.416 -;; Package-Commit: 7d925367ef0857d513d62eab4cb57b7436b9ffe9 +;; Package-Version: 20200805.1727 +;; Package-Commit: 365c73d2618dd0040a32c2601c5456ab5495b812 ;; Keywords: keys keybinding config dotemacs ;; URL: https://github.com/jwiegley/use-package @@ -156,11 +156,13 @@ spelled-out keystrokes, e.g., \"C-c C-z\". See documentation of COMMAND must be an interactive function or lambda form. -KEYMAP, if present, should be a keymap and not a quoted symbol. +KEYMAP, if present, should be a keymap variable or symbol. For example: (bind-key \"M-h\" #'some-interactive-function my-mode-map) + (bind-key \"M-h\" #'some-interactive-function 'my-mode-map) + If PREDICATE is non-nil, it is a form evaluated to determine when a key should be bound. It must return non-nil in such cases. Emacs can evaluate this form at any time that it does redisplay @@ -173,10 +175,11 @@ can safely be called at any time." `(let* ((,namevar ,key-name) (,keyvar (if (vectorp ,namevar) ,namevar (read-kbd-macro ,namevar))) + (kmap (if (and ,keymap (symbolp ,keymap)) (symbol-value ,keymap) ,keymap)) (,kdescvar (cons (if (stringp ,namevar) ,namevar (key-description ,namevar)) - (quote ,keymap))) - (,bindingvar (lookup-key (or ,keymap global-map) ,keyvar))) + (if (symbolp ,keymap) ,keymap (quote ,keymap)))) + (,bindingvar (lookup-key (or kmap global-map) ,keyvar))) (let ((entry (assoc ,kdescvar personal-keybindings)) (details (list ,command (unless (numberp ,bindingvar) @@ -185,11 +188,11 @@ can safely be called at any time." (setcdr entry details) (add-to-list 'personal-keybindings (cons ,kdescvar details)))) ,(if predicate - `(define-key (or ,keymap global-map) ,keyvar + `(define-key (or kmap global-map) ,keyvar '(menu-item "" nil :filter (lambda (&optional _) (when ,predicate ,command)))) - `(define-key (or ,keymap global-map) ,keyvar ,command))))) + `(define-key (or kmap global-map) ,keyvar ,command))))) ;;;###autoload (defmacro unbind-key (key-name &optional keymap) diff --git a/lisp/company-quickhelp.el b/lisp/company-quickhelp.el index ba78c978..f94e436c 100644 --- a/lisp/company-quickhelp.el +++ b/lisp/company-quickhelp.el @@ -4,8 +4,8 @@ ;; Author: Lars Andersen ;; URL: https://www.github.com/expez/company-quickhelp -;; Package-Version: 20200626.1245 -;; Package-Commit: c401603685edafa82454fbf045c835e055e8bc56 +;; Package-Version: 20201208.2308 +;; Package-Commit: b13ff1ba0d6176825f165920b17625948f1256c5 ;; Keywords: company popup documentation quickhelp ;; Version: 2.2.0 ;; Package-Requires: ((emacs "24.3") (company "0.8.9") (pos-tip "0.4.6")) @@ -174,49 +174,50 @@ currently active `company' completion candidate." (pos-tip-hide))) (defun company-quickhelp--show () - (when (company-quickhelp-pos-tip-available-p) + (when (and (company-quickhelp-pos-tip-available-p) + company-selection) (company-quickhelp--cancel-timer) (while-no-input (let* ((selected (nth company-selection company-candidates)) (doc (let ((inhibit-message t)) (company-quickhelp--doc selected))) - (width 80) - (timeout 300) - (ovl company-pseudo-tooltip-overlay) - (overlay-width (* (frame-char-width) - (if ovl (overlay-get ovl 'company-width) 0))) - (overlay-position (* (frame-char-width) - (- (if ovl (overlay-get ovl 'company-column) 1) 1))) - (x-gtk-use-system-tooltips nil) - (fg-bg `(,company-quickhelp-color-foreground - . ,company-quickhelp-color-background)) - (pos (save-excursion - (goto-char (min (overlay-start ovl) (point))) - (line-beginning-position))) - (dy (if (and ovl (< (overlay-get ovl 'company-height) 0)) - 0 - (frame-char-height)))) + (ovl company-pseudo-tooltip-overlay)) (when (and ovl doc) (with-no-warnings - (if company-quickhelp-use-propertized-text - (let* ((frame (window-frame (selected-window))) - (max-width (pos-tip-x-display-width frame)) - (max-height (pos-tip-x-display-height frame)) - (w-h (pos-tip-string-width-height doc))) - (cond - ((> (car w-h) width) - (setq doc (pos-tip-fill-string doc width nil 'none nil max-height) - w-h (pos-tip-string-width-height doc))) - ((or (> (car w-h) max-width) - (> (cdr w-h) max-height)) - (setq doc (pos-tip-truncate-string doc max-width max-height) - w-h (pos-tip-string-width-height doc)))) - (pos-tip-show-no-propertize doc fg-bg pos nil timeout - (pos-tip-tooltip-width (car w-h) (frame-char-width frame)) - (pos-tip-tooltip-height (cdr w-h) (frame-char-height frame) frame) - nil (+ overlay-width overlay-position) dy)) - (pos-tip-show doc fg-bg pos nil timeout width nil - (+ overlay-width overlay-position) dy)))))))) + (let ((width 80) + (timeout 300) + (overlay-width (* (frame-char-width) + (overlay-get ovl 'company-width))) + (overlay-position (* (frame-char-width) + (- (overlay-get ovl 'company-column) 1))) + (x-gtk-use-system-tooltips nil) + (fg-bg `(,company-quickhelp-color-foreground + . ,company-quickhelp-color-background)) + (pos (save-excursion + (goto-char (min (overlay-start ovl) (point))) + (line-beginning-position))) + (dy (if (< (overlay-get ovl 'company-height) 0) + 0 + (frame-char-height)))) + (if company-quickhelp-use-propertized-text + (let* ((frame (window-frame (selected-window))) + (max-width (pos-tip-x-display-width frame)) + (max-height (pos-tip-x-display-height frame)) + (w-h (pos-tip-string-width-height doc))) + (cond + ((> (car w-h) width) + (setq doc (pos-tip-fill-string doc width nil 'none nil max-height) + w-h (pos-tip-string-width-height doc))) + ((or (> (car w-h) max-width) + (> (cdr w-h) max-height)) + (setq doc (pos-tip-truncate-string doc max-width max-height) + w-h (pos-tip-string-width-height doc)))) + (pos-tip-show-no-propertize doc fg-bg pos nil timeout + (pos-tip-tooltip-width (car w-h) (frame-char-width frame)) + (pos-tip-tooltip-height (cdr w-h) (frame-char-height frame) frame) + nil (+ overlay-width overlay-position) dy)) + (pos-tip-show doc fg-bg pos nil timeout width nil + (+ overlay-width overlay-position) dy))))))))) (defun company-quickhelp--set-timer () (when (or (null company-quickhelp--timer) diff --git a/lisp/company/company-abbrev.el b/lisp/company/company-abbrev.el index 24ec3b77..386feb64 100644 --- a/lisp/company/company-abbrev.el +++ b/lisp/company/company-abbrev.el @@ -17,7 +17,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/company/company-bbdb.el b/lisp/company/company-bbdb.el index a68c34ec..7160231e 100644 --- a/lisp/company/company-bbdb.el +++ b/lisp/company/company-bbdb.el @@ -17,7 +17,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 'company) (require 'cl-lib) diff --git a/lisp/company/company-capf.el b/lisp/company/company-capf.el index cb30a801..7d34f9c5 100644 --- a/lisp/company/company-capf.el +++ b/lisp/company/company-capf.el @@ -17,7 +17,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/company/company-clang.el b/lisp/company/company-clang.el index 1460e092..24e59770 100644 --- a/lisp/company/company-clang.el +++ b/lisp/company/company-clang.el @@ -17,7 +17,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: @@ -136,6 +136,7 @@ or automatically through a custom `company-clang-prefix-guesser'." (let ((pattern (format company-clang--completion-pattern (regexp-quote prefix))) (case-fold-search nil) + (results (make-hash-table :test 'equal :size (/ (point-max) 100))) lines match) (while (re-search-forward pattern nil t) (setq match (match-string-no-properties 1)) @@ -144,11 +145,21 @@ or automatically through a custom `company-clang-prefix-guesser'." (when (string-match ":" match) (setq match (substring match 0 (match-beginning 0))))) (let ((meta (match-string-no-properties 2))) - (when (and meta (not (string= match meta))) - (put-text-property 0 1 'meta - (company-clang--strip-formatting meta) - match))) - (push match lines))) + ;; Avoiding duplicates: + ;; https://github.com/company-mode/company-mode/issues/841 + (cond + ;; Either meta != completion (not a macro) + ((not (equal match meta)) + (puthash match meta results)) + ;; Or it's the first time we see this completion + ((eq (gethash match results 'none) 'none) + (puthash match nil results)))))) + (maphash + (lambda (match meta) + (when meta + (put-text-property 0 1 'meta (company-clang--strip-formatting meta) match)) + (push match lines)) + results) lines)) (defun company-clang--meta (candidate) diff --git a/lisp/company/company-cmake.el b/lisp/company/company-cmake.el index 1bfb20ba..136c3e52 100644 --- a/lisp/company/company-cmake.el +++ b/lisp/company/company-cmake.el @@ -16,7 +16,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: ;; @@ -40,6 +40,7 @@ (defvar company-cmake-executable-arguments '("--help-command-list" "--help-module-list" + "--help-property-list" "--help-variable-list") "The arguments we pass to cmake, separately. They affect which types of symbols we get completion candidates for.") diff --git a/lisp/company/company-css.el b/lisp/company/company-css.el index d3ece74d..c98040b4 100644 --- a/lisp/company/company-css.el +++ b/lisp/company/company-css.el @@ -17,7 +17,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/company/company-dabbrev-code.el b/lisp/company/company-dabbrev-code.el index 37f287c5..6d250ce5 100644 --- a/lisp/company/company-dabbrev-code.el +++ b/lisp/company/company-dabbrev-code.el @@ -17,7 +17,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/company/company-dabbrev.el b/lisp/company/company-dabbrev.el index 5d2f3186..88b74198 100644 --- a/lisp/company/company-dabbrev.el +++ b/lisp/company/company-dabbrev.el @@ -17,7 +17,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/company/company-eclim.el b/lisp/company/company-eclim.el deleted file mode 100644 index b37f7560..00000000 --- a/lisp/company/company-eclim.el +++ /dev/null @@ -1,186 +0,0 @@ -;;; company-eclim.el --- company-mode completion backend for Eclim - -;; Copyright (C) 2009, 2011, 2013, 2015 Free Software Foundation, Inc. - -;; Author: Nikolaj Schumacher - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: -;; -;; Using `emacs-eclim' together with (or instead of) this backend is -;; recommended, as it allows you to use other Eclim features. -;; -;; The alternative backend provided by `emacs-eclim' uses `yasnippet' -;; instead of `company-template' to expand function calls, and it supports -;; some languages other than Java. - -;;; Code: - -(require 'company) -(require 'company-template) -(require 'cl-lib) - -(defgroup company-eclim nil - "Completion backend for Eclim." - :group 'company) - -(defun company-eclim-executable-find () - (let (file) - (cl-dolist (eclipse-root '("/Applications/eclipse" "/usr/lib/eclipse" - "/usr/local/lib/eclipse")) - (and (file-exists-p (setq file (expand-file-name "plugins" eclipse-root))) - (setq file (car (last (directory-files file t "^org.eclim_")))) - (file-exists-p (setq file (expand-file-name "bin/eclim" file))) - (cl-return file))))) - -(defcustom company-eclim-executable - (or (bound-and-true-p eclim-executable) - (executable-find "eclim") - (company-eclim-executable-find)) - "Location of eclim executable." - :type 'file) - -(defcustom company-eclim-auto-save t - "Determines whether to save the buffer when retrieving completions. -eclim can only complete correctly when the buffer has been saved." - :type '(choice (const :tag "Off" nil) - (const :tag "On" t))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defvar-local company-eclim--project-dir 'unknown) - -(defvar-local company-eclim--project-name nil) - -(declare-function json-read "json") -(defvar json-array-type) - -(defun company-eclim--call-process (&rest args) - (let ((coding-system-for-read 'utf-8) - res) - (require 'json) - (with-temp-buffer - (if (= 0 (setq res (apply 'call-process company-eclim-executable nil t nil - "-command" args))) - (let ((json-array-type 'list)) - (goto-char (point-min)) - (unless (eobp) - (json-read))) - (message "Company-eclim command failed with error %d:\n%s" res - (buffer-substring (point-min) (point-max))) - nil)))) - -(defun company-eclim--project-list () - (company-eclim--call-process "project_list")) - -(defun company-eclim--project-dir () - (if (eq company-eclim--project-dir 'unknown) - (let ((dir (locate-dominating-file buffer-file-name ".project"))) - (when dir - (setq company-eclim--project-dir - (directory-file-name - (expand-file-name dir))))) - company-eclim--project-dir)) - -(defun company-eclim--project-name () - (or company-eclim--project-name - (let ((dir (company-eclim--project-dir))) - (when dir - (setq company-eclim--project-name - (cl-loop for project in (company-eclim--project-list) - when (equal (cdr (assoc 'path project)) dir) - return (cdr (assoc 'name project)))))))) - -(defun company-eclim--candidates (prefix) - (interactive "d") - (let ((project-file (file-relative-name buffer-file-name - (company-eclim--project-dir))) - completions) - (when company-eclim-auto-save - (when (buffer-modified-p) - (basic-save-buffer)) - ;; FIXME: Sometimes this isn't finished when we complete. - (company-eclim--call-process "java_src_update" - "-p" (company-eclim--project-name) - "-f" project-file)) - (dolist (item (cdr (assoc 'completions - (company-eclim--call-process - "java_complete" "-p" (company-eclim--project-name) - "-f" project-file - "-o" (number-to-string - (company-eclim--search-point prefix)) - "-e" "utf-8" - "-l" "standard")))) - (let* ((meta (cdr (assoc 'info item))) - (completion meta)) - (when (string-match " ?[(:-]" completion) - (setq completion (substring completion 0 (match-beginning 0)))) - (put-text-property 0 1 'meta meta completion) - (push completion completions))) - (let ((completion-ignore-case nil)) - (all-completions prefix completions)))) - -(defun company-eclim--search-point (prefix) - (if (or (cl-plusp (length prefix)) (eq (char-before) ?.)) - (1- (point)) - (point))) - -(defun company-eclim--meta (candidate) - (get-text-property 0 'meta candidate)) - -(defun company-eclim--annotation (candidate) - (let ((meta (company-eclim--meta candidate))) - (when (string-match "\\(([^-]*\\) -" meta) - (substring meta (match-beginning 1) (match-end 1))))) - -(defun company-eclim--prefix () - (let ((prefix (company-grab-symbol))) - (when prefix - ;; Completion candidates for annotations don't include '@'. - (when (eq ?@ (string-to-char prefix)) - (setq prefix (substring prefix 1))) - prefix))) - -(defun company-eclim (command &optional arg &rest ignored) - "`company-mode' completion backend for Eclim. -Eclim provides access to Eclipse Java IDE features for other editors. - -Eclim version 1.7.13 or newer (?) is required. - -Completions only work correctly when the buffer has been saved. -`company-eclim-auto-save' determines whether to do this automatically." - (interactive (list 'interactive)) - (cl-case command - (interactive (company-begin-backend 'company-eclim)) - (prefix (and (derived-mode-p 'java-mode 'jde-mode) - buffer-file-name - company-eclim-executable - (company-eclim--project-name) - (not (company-in-string-or-comment)) - (or (company-eclim--prefix) 'stop))) - (candidates (company-eclim--candidates arg)) - (meta (company-eclim--meta arg)) - ;; because "" doesn't return everything - (no-cache (equal arg "")) - (annotation (company-eclim--annotation arg)) - (post-completion (let ((anno (company-eclim--annotation arg))) - (when anno - (insert anno) - (company-template-c-like-templatify anno)))))) - -(provide 'company-eclim) -;;; company-eclim.el ends here diff --git a/lisp/company/company-elisp.el b/lisp/company/company-elisp.el index db1653da..c024d66f 100644 --- a/lisp/company/company-elisp.el +++ b/lisp/company/company-elisp.el @@ -17,7 +17,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: @@ -37,7 +37,7 @@ (defcustom company-elisp-detect-function-context t "If enabled, offer Lisp functions only in appropriate contexts. -Functions are offered for completion only after ' and \(." +Functions are offered for completion only after \\=' and \(." :type '(choice (const :tag "Off" nil) (const :tag "On" t))) diff --git a/lisp/company/company-etags.el b/lisp/company/company-etags.el index d0c27c9c..55a1279d 100644 --- a/lisp/company/company-etags.el +++ b/lisp/company/company-etags.el @@ -17,7 +17,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/company/company-files.el b/lisp/company/company-files.el index 8859266f..3d74c4de 100644 --- a/lisp/company/company-files.el +++ b/lisp/company/company-files.el @@ -17,7 +17,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/company/company-gtags.el b/lisp/company/company-gtags.el index 598ba60f..30b6f209 100644 --- a/lisp/company/company-gtags.el +++ b/lisp/company/company-gtags.el @@ -17,7 +17,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: @@ -48,6 +48,7 @@ :package-version '(company . "0.8.1")) (defvar-local company-gtags--tags-available-p 'unknown) +(defvar-local company-gtags--executable 'unknown) (defcustom company-gtags-modes '(prog-mode jde-mode) "Modes that use `company-gtags'. @@ -62,6 +63,32 @@ completion." (locate-dominating-file buffer-file-name "GTAGS")) company-gtags--tags-available-p)) +(defun company-gtags--executable () + (cond + ((not (eq company-gtags--executable 'unknown)) ;; the value is already cached + company-gtags--executable) + ((and (version<= "27" emacs-version) ;; can search remotely to set + (file-remote-p default-directory)) + + (with-connection-local-variables + (if (boundp 'company-gtags--executable-connection) + (setq-local company-gtags--executable ;; use if defined as connection-local + company-gtags--executable-connection) + + ;; Else search and set as connection local for next uses. + (setq-local company-gtags--executable (executable-find "global" t)) + (let* ((host (file-remote-p default-directory 'host)) + (symvars (intern (concat host "-vars")))) ;; profile name + + (connection-local-set-profile-variables + symvars + `((company-gtags--executable-connection . ,company-gtags--executable))) + + (connection-local-set-profiles `(:machine ,host) symvars)) + company-gtags--executable))) + (t ;; use default value (searched locally) + company-gtags-executable))) + (defun company-gtags--fetch-tags (prefix) (with-temp-buffer (let (tags) @@ -98,7 +125,7 @@ completion." (interactive (list 'interactive)) (cl-case command (interactive (company-begin-backend 'company-gtags)) - (prefix (and company-gtags-executable + (prefix (and (company-gtags--executable) buffer-file-name (apply #'derived-mode-p company-gtags-modes) (not (company-in-string-or-comment)) diff --git a/lisp/company/company-ispell.el b/lisp/company/company-ispell.el index ed658f2f..4d0bc229 100644 --- a/lisp/company/company-ispell.el +++ b/lisp/company/company-ispell.el @@ -17,7 +17,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/company/company-keywords.el b/lisp/company/company-keywords.el index 7cafb4cd..80a0103e 100644 --- a/lisp/company/company-keywords.el +++ b/lisp/company/company-keywords.el @@ -17,7 +17,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/company/company-nxml.el b/lisp/company/company-nxml.el index 36ff1ceb..d05f57c1 100644 --- a/lisp/company/company-nxml.el +++ b/lisp/company/company-nxml.el @@ -17,7 +17,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/company/company-oddmuse.el b/lisp/company/company-oddmuse.el index 1b689509..787ca91e 100644 --- a/lisp/company/company-oddmuse.el +++ b/lisp/company/company-oddmuse.el @@ -17,7 +17,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/company/company-pkg.el b/lisp/company/company-pkg.el index 315a54d0..1d72ca31 100644 --- a/lisp/company/company-pkg.el +++ b/lisp/company/company-pkg.el @@ -1,11 +1,11 @@ -(define-package "company" "20200616.2354" "Modular text completion framework" +(define-package "company" "20210103.1124" "Modular text completion framework" '((emacs "24.3")) - :commit "1f56bec0ba7ce336eb8661b4d34e4b024d7dd04c" :keywords - '("abbrev" "convenience" "matching") - :authors + :commit "6116c4617a7934acfe84cb82a058e9b198f0f480" :authors '(("Nikolaj Schumacher")) :maintainer '("Dmitry Gutov" . "dgutov@yandex.ru") + :keywords + '("abbrev" "convenience" "matching") :url "http://company-mode.github.io/") ;; Local Variables: ;; no-byte-compile: t diff --git a/lisp/company/company-semantic.el b/lisp/company/company-semantic.el index 2f6fe2af..86cc8c69 100644 --- a/lisp/company/company-semantic.el +++ b/lisp/company/company-semantic.el @@ -17,7 +17,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/company/company-template.el b/lisp/company/company-template.el index be4c41f1..4cd9292d 100644 --- a/lisp/company/company-template.el +++ b/lisp/company/company-template.el @@ -17,7 +17,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 . ;;; Code: diff --git a/lisp/company/company-tempo.el b/lisp/company/company-tempo.el index cba42c3e..fc8f227c 100644 --- a/lisp/company/company-tempo.el +++ b/lisp/company/company-tempo.el @@ -17,7 +17,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/company/company-tng.el b/lisp/company/company-tng.el index 404d436e..3bfa2985 100644 --- a/lisp/company/company-tng.el +++ b/lisp/company/company-tng.el @@ -17,7 +17,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: @@ -38,14 +38,15 @@ ;; ;; Usage: ;; -;; To apply the default configuration for company-tng call -;; `company-tng-configure-default' from your init script. +;; Enable `company-tng-mode' with: ;; -;; You can also configure company-tng manually: +;; (add-hook 'after-init-hook 'company-tng-mode) ;; -;; Add `company-tng-frontend' to `company-frontends': +;; in your init script. It will set up the required frontend, as well as make a +;; number of recommended configuration changes described below. ;; -;; (add-to-list 'company-frontends 'company-tng-frontend) +;; To avoid these changes, if you want to tweak everything yourself, customize +;;`company-tng-auto-configure' to nil. ;; ;; We recommend to bind TAB to `company-select-next', S-TAB to ;; `company-select-previous', and unbind RET and other now-unnecessary @@ -74,8 +75,8 @@ ;; continues typing would be surprising and undesirable, since the candidate was ;; already inserted into the buffer. ;; -;; For this reason `company-tng-configure-default' disables arguments insertion -;; for a number of popular backends. If the backend you are using is not among +;; For this reason `company-tng-mode' by default disables arguments insertion +;; for a number of popular backends. If the backend you are using is not among ;; them, you might have to configure it not to do that yourself. ;; ;; YASnippet and company-tng both use TAB, which causes conflicts. The @@ -105,25 +106,22 @@ confirm the selection and finish the completion." (show (let ((ov (make-overlay (point) (point)))) (setq company-tng--overlay ov) - (overlay-put ov 'priority 2)) - (advice-add 'company-select-next :before-until 'company-tng--allow-unselected) - (advice-add 'company-fill-propertize :filter-args 'company-tng--adjust-tooltip-highlight)) + (overlay-put ov 'priority 2))) (update - (let ((ov company-tng--overlay) - (selected (nth company-selection company-candidates)) - (prefix (length company-prefix))) + (let* ((ov company-tng--overlay) + (selected (and company-selection + (nth company-selection company-candidates))) + (prefix (length company-prefix))) (move-overlay ov (- (point) prefix) (point)) (overlay-put ov (if (= prefix 0) 'after-string 'display) - (and company-selection-changed selected)))) + selected))) (hide (when company-tng--overlay (delete-overlay company-tng--overlay) - (kill-local-variable 'company-tng--overlay)) - (advice-remove 'company-select-next 'company-tng--allow-unselected) - (advice-remove 'company-fill-propertize 'company-tng--adjust-tooltip-highlight)) + (kill-local-variable 'company-tng--overlay))) (pre-command - (when (and company-selection-changed + (when (and company-selection (not (company--company-command-p (this-command-keys)))) (company--unread-this-command-keys) (setq this-command 'company-complete-selection))))) @@ -133,65 +131,51 @@ confirm the selection and finish the completion." (defvar company-rtags-insert-arguments) (defvar lsp-enable-snippet) +(defgroup company-tng nil + "Company Tab and Go." + :group 'company) + +(defcustom company-tng-auto-configure t + "Automatically apply default configure when enable `company-tng-mode'." + :type 'boolean) + ;;;###autoload -(defun company-tng-configure-default () - "Applies the default configuration to enable company-tng." - (setq company-require-match nil) - (setq company-frontends '(company-tng-frontend - company-pseudo-tooltip-frontend - company-echo-metadata-frontend)) - (setq company-clang-insert-arguments nil - company-semantic-insert-arguments nil - company-rtags-insert-arguments nil - lsp-enable-snippet nil) - (advice-add #'eglot--snippet-expansion-fn :override #'ignore) - (let ((keymap company-active-map)) - (define-key keymap [return] nil) - (define-key keymap (kbd "RET") nil) - (define-key keymap [tab] 'company-select-next) - (define-key keymap (kbd "TAB") 'company-select-next) - (define-key keymap [backtab] 'company-select-previous) - (define-key keymap (kbd "S-TAB") 'company-select-previous))) +(define-obsolete-function-alias 'company-tng-configure-default 'company-tng-mode "0.9.14" + "Applies the default configuration to enable company-tng.") -(defun company-tng--allow-unselected (&optional arg) - "Advice `company-select-next' to allow for an 'unselected' -state. Unselected means that no user interaction took place on the -completion candidates and it's marked by setting -`company-selection-changed' to nil. This advice will call the underlying -`company-select-next' unless we need to transition to or from an unselected -state. +(declare-function eglot--snippet-expansion-fn "eglot") -Possible state transitions: -- (arg > 0) unselected -> first candidate selected -- (arg < 0) first candidate selected -> unselected -- (arg < 0 wrap-round) unselected -> last candidate selected -- (arg < 0 no wrap-round) unselected -> unselected - -There is no need to advice `company-select-previous' because it calls -`company-select-next' internally." +;;;###autoload +(define-minor-mode company-tng-mode + "This minor mode enables `company-tng-frontend'." + :init-value nil + :global t (cond - ;; Selecting next - ((or (not arg) (> arg 0)) - (unless company-selection-changed - (company-set-selection (1- (or arg 1)) 'force-update) - t)) - ;; Selecting previous - ((< arg 0) - (when (and company-selection-changed - (< (+ company-selection arg) 0)) - (company-set-selection 0) - (setq company-selection-changed nil) - (company-call-frontends 'update) - t) - ))) - -(defun company-tng--adjust-tooltip-highlight (args) - "Prevent the tooltip from highlighting the current selection if it wasn't -made explicitly (i.e. `company-selection-changed' is true)" - (unless company-selection-changed - ;; The 4th arg of `company-fill-propertize' is selected - (setf (nth 3 args) nil)) - args) + (company-tng-mode + (setq company-frontends + (add-to-list 'company-frontends 'company-tng-frontend)) + (when company-tng-auto-configure + (setq company-require-match nil) + (setq company-frontends '(company-tng-frontend + company-pseudo-tooltip-frontend + company-echo-metadata-frontend)) + (setq company-clang-insert-arguments nil + company-semantic-insert-arguments nil + company-rtags-insert-arguments nil + lsp-enable-snippet nil) + (advice-add #'eglot--snippet-expansion-fn :override #'ignore) + (let ((keymap company-active-map)) + (define-key keymap [return] nil) + (define-key keymap (kbd "RET") nil) + (define-key keymap [tab] 'company-select-next) + (define-key keymap (kbd "TAB") 'company-select-next) + (define-key keymap [backtab] 'company-select-previous) + (define-key keymap (kbd "S-TAB") 'company-select-previous))) + (setq company-selection-default nil)) + (t + (setq company-frontends + (delete 'company-tng-frontend company-frontends)) + (setq company-selection-default 0)))) (provide 'company-tng) ;;; company-tng.el ends here diff --git a/lisp/company/company-xcode.el b/lisp/company/company-xcode.el deleted file mode 100644 index 56da1989..00000000 --- a/lisp/company/company-xcode.el +++ /dev/null @@ -1,123 +0,0 @@ -;;; company-xcode.el --- company-mode completion backend for Xcode projects - -;; Copyright (C) 2009-2011, 2014 Free Software Foundation, Inc. - -;; Author: Nikolaj Schumacher - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - - -;;; Commentary: -;; - -;;; Code: - -(require 'company) -(require 'cl-lib) - -(defgroup company-xcode nil - "Completion backend for Xcode projects." - :group 'company) - -(defcustom company-xcode-xcodeindex-executable (executable-find "xcodeindex") - "Location of xcodeindex executable." - :type 'file) - -(defvar company-xcode-tags nil) - -(defun company-xcode-reset () - "Reset the cached tags." - (interactive) - (setq company-xcode-tags nil)) - -(defcustom company-xcode-types - '("Class" "Constant" "Enum" "Macro" "Modeled Class" "Structure" - "Type" "Union" "Function") - "The types of symbols offered by `company-xcode'. -No context-enabled completion is available. Types like methods will be -offered regardless of whether the class supports them. The defaults should be -valid in most contexts." - :set (lambda (variable value) - (set variable value) - (company-xcode-reset)) - :type '(set (const "Category") (const "Class") (const "Class Method") - (const "Class Variable") (const "Constant") (const "Enum") - (const "Field") (const "Instance Method") - (const "Instance Variable") (const "Macro") - (const "Modeled Class") (const "Modeled Method") - (const "Modeled Property") (const "Property") (const "Protocol") - (const "Structure") (const "Type") (const "Union") - (const "Variable") (const "Function"))) - -(defvar-local company-xcode-project 'unknown) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defun company-xcode-fetch (project-bundle) - (setq project-bundle (directory-file-name project-bundle)) - (message "Retrieving dump from %s..." project-bundle) - (with-temp-buffer - (let ((default-directory (file-name-directory project-bundle))) - (call-process company-xcode-xcodeindex-executable nil (current-buffer) - nil "dump" "-project" - (file-name-nondirectory project-bundle) "-quiet") - (goto-char (point-min)) - (let ((regexp (concat "^\\([^\t\n]*\\)\t[^\t\n]*\t" - (regexp-opt company-xcode-types) - "\t[^\t\n]*\t[^\t\n]*")) - candidates) - (while (re-search-forward regexp nil t) - (cl-pushnew (match-string 1) candidates :test #'equal)) - (message "Retrieving dump from %s...done" project-bundle) - candidates)))) - -(defun company-xcode-find-project () - (let ((dir (if buffer-file-name - (file-name-directory buffer-file-name) - (expand-file-name default-directory))) - (prev-dir nil) - file) - (while (not (or file (equal dir prev-dir))) - (setq file (car (directory-files dir t ".xcodeproj\\'" t)) - prev-dir dir - dir (file-name-directory (directory-file-name dir)))) - file)) - -(defun company-xcode-tags () - (when (eq company-xcode-project 'unknown) - (setq company-xcode-project (company-xcode-find-project))) - (when company-xcode-project - (cdr (or (assoc company-xcode-project company-xcode-tags) - (car (push (cons company-xcode-project - (company-xcode-fetch company-xcode-project)) - company-xcode-tags)))))) -;;;###autoload -(defun company-xcode (command &optional arg &rest ignored) - "`company-mode' completion backend for Xcode projects." - (interactive (list 'interactive)) - (cl-case command - (interactive (company-begin-backend 'company-xcode)) - (prefix (and company-xcode-xcodeindex-executable - (company-xcode-tags) - (not (company-in-string-or-comment)) - (or (company-grab-symbol) 'stop))) - (candidates (let ((completion-ignore-case nil)) - (company-xcode-tags) - (all-completions arg (company-xcode-tags)))))) - - -(provide 'company-xcode) -;;; company-xcode.el ends here diff --git a/lisp/company/company-yasnippet.el b/lisp/company/company-yasnippet.el index c2c26886..dfc959c6 100644 --- a/lisp/company/company-yasnippet.el +++ b/lisp/company/company-yasnippet.el @@ -17,7 +17,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,6 +34,7 @@ (declare-function yas--template-content "yasnippet") (declare-function yas--template-expand-env "yasnippet") (declare-function yas--warning "yasnippet") +(declare-function yas-minor-mode "yasnippet") (defvar company-yasnippet-annotation-fn (lambda (name) @@ -137,18 +138,18 @@ shadow backends that come after it. Recommended usages: * In a buffer-local value of `company-backends', grouped with a backend or several that provide actual text completions. - (add-hook 'js-mode-hook + (add-hook \\='js-mode-hook (lambda () - (set (make-local-variable 'company-backends) - '((company-dabbrev-code company-yasnippet))))) + (set (make-local-variable \\='company-backends) + \\='((company-dabbrev-code company-yasnippet))))) * After keyword `:with', grouped with other backends. - (push '(company-semantic :with company-yasnippet) company-backends) + (push \\='(company-semantic :with company-yasnippet) company-backends) * Not in `company-backends', just bound to a key. - (global-set-key (kbd \"C-c y\") 'company-yasnippet) + (global-set-key (kbd \"C-c y\") \\='company-yasnippet) " (interactive (list 'interactive)) (cl-case command diff --git a/lisp/company/company.el b/lisp/company/company.el index d1f17fe1..c20475e5 100644 --- a/lisp/company/company.el +++ b/lisp/company/company.el @@ -5,7 +5,7 @@ ;; Author: Nikolaj Schumacher ;; Maintainer: Dmitry Gutov ;; URL: http://company-mode.github.io/ -;; Version: 0.9.12 +;; Version: 0.9.13 ;; Keywords: abbrev, convenience, matching ;; Package-Requires: ((emacs "24.3")) @@ -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: ;; @@ -280,6 +280,11 @@ This doesn't include the margins and the scroll bar." :type 'integer :package-version '(company . "0.9.5")) +(defcustom company-tooltip-width-grow-only nil + "When non-nil, the tooltip width is not allowed to decrease." + :type 'boolean + :package-version '(company . "0.9.14")) + (defcustom company-tooltip-margin 1 "Width of margin columns to show around the toolip." :type 'integer) @@ -307,21 +312,19 @@ This doesn't include the margins and the scroll bar." (company-capf . "completion-at-point-functions") (company-clang . "Clang") (company-cmake . "CMake") - (company-css . "CSS") + (company-css . "CSS (obsolete backend)") (company-dabbrev . "dabbrev for plain text") (company-dabbrev-code . "dabbrev for code") - (company-eclim . "Eclim (an Eclipse interface)") - (company-elisp . "Emacs Lisp") + (company-elisp . "Emacs Lisp (obsolete backend)") (company-etags . "etags") (company-files . "Files") (company-gtags . "GNU Global") (company-ispell . "Ispell") (company-keywords . "Programming language keywords") - (company-nxml . "nxml") + (company-nxml . "nxml (obsolete backend)") (company-oddmuse . "Oddmuse") (company-semantic . "Semantic") - (company-tempo . "Tempo templates") - (company-xcode . "Xcode"))) + (company-tempo . "Tempo templates"))) (put 'company-safe-backends 'risky-local-variable t) (defun company-safe-backends-p (backends) @@ -339,9 +342,10 @@ This doesn't include the margins and the scroll bar." (list 'company-nxml)) ,@(unless (version<= "26" emacs-version) (list 'company-css)) - company-eclim company-semantic company-clang - company-xcode company-cmake + company-semantic + company-cmake company-capf + company-clang company-files (company-dabbrev-code company-gtags company-etags company-keywords) @@ -539,39 +543,60 @@ prefix it was started from." :type 'boolean :package-version '(company . "0.8.0")) +(defcustom company-abort-on-unique-match t + "If non-nil, typing a full unique match aborts completion. + +You can still invoke `company-complete' manually to run the +`post-completion' handler, though. + +If it's nil, completion will remain active until you type a prefix that +doesn't match anything or finish it manually, e.g. with RET." + :type 'boolean) + (defcustom company-require-match 'company-explicit-action-p "If enabled, disallow non-matching input. This can be a function do determine if a match is required. This can be overridden by the backend, if it returns t or `never' to -`require-match'. `company-auto-complete' also takes precedence over this." +`require-match'. `company-auto-commit' also takes precedence over this." :type '(choice (const :tag "Off" nil) (function :tag "Predicate function") (const :tag "On, if user interaction took place" 'company-explicit-action-p) (const :tag "On" t))) -(defcustom company-auto-complete nil - "Determines when to auto-complete. -If this is enabled, all characters from `company-auto-complete-chars' +(define-obsolete-variable-alias + 'company-auto-complete + 'company-auto-commit + "0.9.14") + +(defcustom company-auto-commit nil + "Determines whether to auto-commit. +If this is enabled, all characters from `company-auto-commit-chars' trigger insertion of the selected completion candidate. This can also be a function." :type '(choice (const :tag "Off" nil) (function :tag "Predicate function") (const :tag "On, if user interaction took place" 'company-explicit-action-p) - (const :tag "On" t))) + (const :tag "On" t)) + :package-version '(company . "0.9.14")) -(defcustom company-auto-complete-chars '(?\ ?\) ?.) - "Determines which characters trigger auto-completion. -See `company-auto-complete'. If this is a string, each string character -triggers auto-completion. If it is a list of syntax description characters (see -`modify-syntax-entry'), all characters with that syntax auto-complete. +(define-obsolete-variable-alias + 'company-auto-complete-chars + 'company-auto-commit-chars + "0.9.14") + +(defcustom company-auto-commit-chars '(?\ ?\) ?.) + "Determines which characters trigger auto-commit. +See `company-auto-commit'. If this is a string, each character in it +triggers auto-commit. If it is a list of syntax description characters (see +`modify-syntax-entry'), characters with any of those syntaxes do that. This can also be a function, which is called with the new input and should -return non-nil if company should auto-complete. +return non-nil if company should auto-commit. -A character that is part of a valid candidate never triggers auto-completion." +A character that is part of a valid completion never triggers auto-commit." :type '(choice (string :tag "Characters") (set :tag "Syntax" (const :tag "Whitespace" ?\ ) @@ -588,7 +613,8 @@ A character that is part of a valid candidate never triggers auto-completion." (const :tag "Character-quote." ?/) (const :tag "Generic string fence." ?|) (const :tag "Generic comment fence." ?!)) - (function :tag "Predicate function"))) + (function :tag "Predicate function")) + :package-version '(company . "0.9.14")) (defcustom company-idle-delay .5 "The idle delay in seconds until completion starts automatically. @@ -741,9 +767,10 @@ asynchronous call into synchronous.") (company-candidates (:eval (if (consp company-backend) - (company--group-lighter (nth company-selection - company-candidates) - company-lighter-base) + (when company-selection + (company--group-lighter (nth company-selection + company-candidates) + company-lighter-base)) (symbol-name company-backend))) company-lighter-base)) "Mode line lighter for Company. @@ -1092,7 +1119,9 @@ matches IDLE-BEGIN-AFTER-RE, return it wrapped in a cons." (defvar-local company-common nil) -(defvar-local company-selection 0) +(defvar company-selection-default 0 + "The default value for `company-selection'.") +(defvar-local company-selection company-selection-default) (defvar-local company-selection-changed nil) @@ -1101,10 +1130,6 @@ matches IDLE-BEGIN-AFTER-RE, return it wrapped in a cons." (defvar-local company--manual-prefix nil) -(defvar company--auto-completion nil - "Non-nil when current candidate is being inserted automatically. -Controlled by `company-auto-complete'.") - (defvar-local company--point-max nil) (defvar-local company-point nil) @@ -1173,17 +1198,28 @@ can retrieve meta-data for them." (string-match-p "\\`company-" (symbol-name this-command))))))) (defun company-call-frontends (command) - (dolist (frontend company-frontends) - (condition-case-unless-debug err - (funcall frontend command) - (error (error "Company: frontend %s error \"%s\" on command %s" - frontend (error-message-string err) command))))) + (cl-loop for frontend in company-frontends collect + (condition-case-unless-debug err + (funcall frontend command) + (error (error "Company: frontend %s error \"%s\" on command %s" + frontend (error-message-string err) command))))) (defun company-set-selection (selection &optional force-update) - (setq selection - (if company-selection-wrap-around - (mod selection company-candidates-length) - (max 0 (min (1- company-candidates-length) selection)))) + "Set SELECTION for company candidates. +This will update `company-selection' and related variable. +Only update when the current selection is changed, but optionally always +update if FORCE-UPDATE." + (when selection + (let* ((offset (if company-selection-default 0 1)) + (company-candidates-length + (+ company-candidates-length offset))) + (setq selection (+ selection offset)) + (setq selection + (if company-selection-wrap-around + (mod selection company-candidates-length) + (max 0 (min (1- company-candidates-length) selection)))) + (setq selection (unless (< selection offset) + (- selection offset))))) (when (or force-update (not (equal selection company-selection))) (setq company-selection selection company-selection-changed t) @@ -1202,10 +1238,11 @@ can retrieve meta-data for them." (setq company-candidates-length (length candidates)) (if company-selection-changed ;; Try to restore the selection - (let ((selected (nth company-selection company-candidates))) - (setq company-selection 0 - company-candidates candidates) + (let ((selected (and company-selection + (nth company-selection company-candidates)))) + (setq company-candidates candidates) (when selected + (setq company-selection 0) (catch 'found (while candidates (let ((candidate (pop candidates))) @@ -1214,9 +1251,9 @@ can retrieve meta-data for them." (company-call-backend 'annotation selected))) (throw 'found t))) (cl-incf company-selection)) - (setq company-selection 0 + (setq company-selection company-selection-default company-selection-changed nil)))) - (setq company-selection 0 + (setq company-selection company-selection-default company-candidates candidates)) ;; Calculate common. (let ((completion-ignore-case (company-call-backend 'ignore-case))) @@ -1505,18 +1542,18 @@ prefix match (same case) will be prioritized." (funcall company-require-match) (eq company-require-match t)))))) -(defun company-auto-complete-p (input) - "Return non-nil if INPUT should trigger auto-completion." - (and (if (functionp company-auto-complete) - (funcall company-auto-complete) - company-auto-complete) - (if (functionp company-auto-complete-chars) - (funcall company-auto-complete-chars input) - (if (consp company-auto-complete-chars) +(defun company-auto-commit-p (input) + "Return non-nil if INPUT should trigger auto-commit." + (and (if (functionp company-auto-commit) + (funcall company-auto-commit) + company-auto-commit) + (if (functionp company-auto-commit-chars) + (funcall company-auto-commit-chars input) + (if (consp company-auto-commit-chars) (memq (char-syntax (string-to-char input)) - company-auto-complete-chars) + company-auto-commit-chars) (string-match (regexp-quote (substring input 0 1)) - company-auto-complete-chars))))) + company-auto-commit-chars))))) (defun company--incremental-p () (and (> (point) company-point) @@ -1569,7 +1606,8 @@ prefix match (same case) will be prioritized." (- company-point (length company-prefix)))) (company-calculate-candidates new-prefix ignore-case)))) (cond - ((company--unique-match-p c new-prefix ignore-case) + ((and company-abort-on-unique-match + (company--unique-match-p c new-prefix ignore-case)) ;; Handle it like completion was aborted, to differentiate from user ;; calling one of Company's commands to insert the candidate, ;; not to trigger template expansion, etc. @@ -1580,12 +1618,11 @@ prefix match (same case) will be prioritized." (company-update-candidates c) c) ((and (characterp last-command-event) - (company-auto-complete-p (string last-command-event))) - ;; auto-complete + (company-auto-commit-p (string last-command-event))) + ;; auto-commit (save-excursion (goto-char company-point) - (let ((company--auto-completion t)) - (company-complete-selection)) + (company-complete-selection) nil)) ((not (company--incremental-p)) (company-cancel)) @@ -1611,7 +1648,8 @@ prefix match (same case) will be prioritized." company-backend backend c (company-calculate-candidates company-prefix ignore-case)) (cond - ((and (company--unique-match-p c company-prefix ignore-case) + ((and company-abort-on-unique-match + (company--unique-match-p c company-prefix ignore-case) (if company--manual-action ;; If `company-manual-begin' was called, the user ;; really wants something to happen. Otherwise... @@ -1655,7 +1693,7 @@ prefix match (same case) will be prioritized." company-candidates-cache nil company-candidates-predicate nil company-common nil - company-selection 0 + company-selection company-selection-default company-selection-changed nil company--manual-action nil company--manual-prefix nil @@ -1819,6 +1857,7 @@ each one wraps a part of the input string." (defun company--permutations (lst) (if (not lst) '(nil) + ;; FIXME: Replace with `mapcan' in Emacs 26. (cl-mapcan (lambda (e) (mapcar (lambda (perm) (cons e perm)) @@ -1859,11 +1898,12 @@ each one wraps a part of the input string." (company-update-candidates cc))) (defun company--search-update-string (new) - (let* ((pos (company--search new (nthcdr company-selection company-candidates)))) + (let* ((selection (or company-selection 0)) + (pos (company--search new (nthcdr selection company-candidates)))) (if (null pos) (ding) (setq company-search-string new) - (company-set-selection (+ company-selection pos) t)))) + (company-set-selection (+ selection pos) t)))) (defun company--search-assert-input () (company--search-assert-enabled) @@ -1874,24 +1914,25 @@ each one wraps a part of the input string." "Repeat the incremental search in completion candidates forward." (interactive) (company--search-assert-input) - (let ((pos (company--search company-search-string - (cdr (nthcdr company-selection - company-candidates))))) + (let* ((selection (or company-selection 0)) + (pos (company--search company-search-string + (cdr (nthcdr selection company-candidates))))) (if (null pos) (ding) - (company-set-selection (+ company-selection pos 1) t)))) + (company-set-selection (+ selection pos 1) t)))) (defun company-search-repeat-backward () "Repeat the incremental search in completion candidates backwards." (interactive) (company--search-assert-input) - (let ((pos (company--search company-search-string + (let* ((selection (or company-selection 0)) + (pos (company--search company-search-string (nthcdr (- company-candidates-length - company-selection) + selection) (reverse company-candidates))))) (if (null pos) (ding) - (company-set-selection (- company-selection pos 1) t)))) + (company-set-selection (- selection pos 1) t)))) (defun company-search-toggle-filtering () "Toggle `company-search-filtering'." @@ -2016,14 +2057,6 @@ uses the search string to filter the completion candidates." (interactive) (company-search-mode 1)) -(defvar company-filter-map - (let ((keymap (make-keymap))) - (define-key keymap [remap company-search-printing-char] - 'company-filter-printing-char) - (set-keymap-parent keymap company-search-map) - keymap) - "Keymap used for incrementally searching the completion candidates.") - (defun company-filter-candidates () "Start filtering the completion candidates incrementally. This works the same way as `company-search-candidates' immediately @@ -2037,10 +2070,16 @@ followed by `company-search-toggle-filtering'." (defun company-select-next (&optional arg) "Select the next candidate in the list. -With ARG, move by that many elements." +With ARG, move by that many elements. +When `company-selection-default' is nil, add a special pseudo candidates +meant for no selection." (interactive "p") (when (company-manual-begin) - (company-set-selection (+ (or arg 1) company-selection)))) + (let ((selection (+ (or arg 1) + (or company-selection + company-selection-default + -1)))) + (company-set-selection selection)))) (defun company-select-previous (&optional arg) "Select the previous candidate in the list. @@ -2071,6 +2110,16 @@ With ARG, move by that many elements." (company-abort) (company--unread-this-command-keys))) +(defun company-select-first () + "Select the first completion candidate." + (interactive) + (company-set-selection 0)) + +(defun company-select-last () + "Select the last completion candidate." + (interactive) + (company-set-selection (1- company-candidates-length))) + (defun company-next-page () "Select the candidate one page further." (interactive) @@ -2114,31 +2163,19 @@ With ARG, move by that many elements." (defun company--event-col-row (event) (company--posn-col-row (event-start event))) +(defvar company-mouse-event nil + "Holds the mouse event from `company-select-mouse'. +For use in the `select-mouse' frontend action. `let'-bound.") + (defun company-select-mouse (event) "Select the candidate picked by the mouse." (interactive "e") - (let ((event-col-row (company--event-col-row event)) - (ovl-row (company--row)) - (ovl-height (and company-pseudo-tooltip-overlay - (min (overlay-get company-pseudo-tooltip-overlay - 'company-height) - company-candidates-length)))) - (if (and ovl-height - (company--inside-tooltip-p event-col-row ovl-row ovl-height)) - (progn - (company-set-selection (+ (cdr event-col-row) - (1- company-tooltip-offset) - (if (and (eq company-tooltip-offset-display 'lines) - (not (zerop company-tooltip-offset))) - -1 0) - (- ovl-row) - (if (< ovl-height 0) - (- 1 ovl-height) - 0))) - t) - (company-abort) - (company--unread-this-command-keys) - nil))) + (or (let ((company-mouse-event event)) + (cl-some #'identity (company-call-frontends 'select-mouse))) + (progn + (company-abort) + (company--unread-this-command-keys) + nil))) (defun company-complete-mouse (event) "Insert the candidate picked by the mouse." @@ -2149,7 +2186,7 @@ With ARG, move by that many elements." (defun company-complete-selection () "Insert the selected candidate." (interactive) - (when (company-manual-begin) + (when (and (company-manual-begin) company-selection) (let ((result (nth company-selection company-candidates))) (company-finish result)))) @@ -2277,7 +2314,7 @@ character, stripping the modifiers. That character must be a digit." (defvar-local company-last-metadata nil) (defun company-fetch-metadata () - (let ((selected (nth company-selection company-candidates))) + (let ((selected (nth (or company-selection 0) company-candidates))) (unless (eq selected (car company-last-metadata)) (setq company-last-metadata (cons selected (company-call-backend 'meta selected)))) @@ -2328,9 +2365,10 @@ character, stripping the modifiers. That character must be a digit." (defun company-show-doc-buffer () "Temporarily show the documentation buffer for the selection." (interactive) - (let (other-window-scroll-buffer) + (let ((other-window-scroll-buffer) + (selection (or company-selection 0))) (company--electric-do - (let* ((selected (nth company-selection company-candidates)) + (let* ((selected (nth selection company-candidates)) (doc-buffer (or (company-call-backend 'doc-buffer selected) (user-error "No documentation available"))) start) @@ -2398,7 +2436,7 @@ It defaults to 0. CALLBACK is a function called with the selected result if the user successfully completes the input. -Example: \(company-begin-with '\(\"foo\" \"foobar\" \"foobarbaz\"\)\)" +Example: \(company-begin-with \\='\(\"foo\" \"foobar\" \"foobarbaz\"\)\)" (let ((begin-marker (copy-marker (point) t))) (company-begin-backend (lambda (command &optional arg &rest ignored) @@ -2438,6 +2476,7 @@ If SHOW-VERSION is non-nil, show the version in the echo area." thereis (let ((company-backend b)) (setq backend b) (company-call-backend 'prefix)))) + (c-a-p-f completion-at-point-functions) cc annotations) (when (or (stringp prefix) (consp prefix)) (let ((company-backend backend)) @@ -2464,7 +2503,7 @@ If SHOW-VERSION is non-nil, show the version in the echo area." (memq 'company-capf backend) (eq backend 'company-capf)) (insert "Value of c-a-p-f: " - (pp-to-string completion-at-point-functions))) + (pp-to-string c-a-p-f))) (insert "Major mode: " mode) (insert "\n") (insert "Prefix: " (pp-to-string prefix)) @@ -2486,6 +2525,8 @@ If SHOW-VERSION is non-nil, show the version in the echo area." (defvar-local company-tooltip-offset 0) +(defvar-local company--tooltip-current-width 0) + (defun company-tooltip--lines-update-offset (selection num-lines limit) (cl-decf limit 2) (setq company-tooltip-offset @@ -2637,7 +2678,10 @@ If SHOW-VERSION is non-nil, show the version in the echo area." ((match-beginning 1) ;; FIXME: Better char for 'non-printable'? ;; We shouldn't get any of these, but sometimes we might. - "\u2017") + ;; The official "replacement character" is not supported by some fonts. + ;;"\ufffd" + "?" + ) ((match-beginning 2) ;; Zero-width non-breakable space. "") @@ -2712,6 +2756,27 @@ If SHOW-VERSION is non-nil, show the version in the echo area." (cl-decf ww (1- (length (aref buffer-display-table ?\n))))) ww)) +(defun company--face-attribute (face attr) + ;; Like `face-attribute', but accounts for faces that have been remapped to + ;; another face, a list of faces, or a face spec. + (cond ((null face) nil) + ((symbolp face) + (let ((remap (cdr (assq face face-remapping-alist)))) + (if remap + (company--face-attribute + ;; Faces can be remapped to their unremapped selves, but that + ;; would cause us infinite recursion. + (if (listp remap) (remq face remap) remap) + attr) + (face-attribute face attr nil t)))) + ((keywordp (car-safe face)) + (or (plist-get face attr) + (company--face-attribute (plist-get face :inherit) attr))) + ((listp face) + (cl-find-if #'stringp + (mapcar (lambda (f) (company--face-attribute f attr)) + face))))) + (defun company--replacement-string (lines old column nl &optional align-top) (cl-decf column company-tooltip-margin) @@ -2744,9 +2809,21 @@ If SHOW-VERSION is non-nil, show the version in the echo area." (company--offset-line (pop lines) offset)) new)) - (let ((str (concat (when nl " \n") - (mapconcat 'identity (nreverse new) "\n") - "\n"))) + ;; XXX: Also see branch 'more-precise-extend'. + (let* ((nl-face (list + :extend t + :inverse-video nil + :background (or (company--face-attribute 'default :background) + (face-attribute 'default :background nil t)))) + (str (apply #'concat + (when nl " \n") + (cl-mapcan + ;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=42552#23 + (lambda (line) (list line (propertize "\n" 'face nl-face))) + (nreverse new))))) + ;; Use add-face-text-property in Emacs 24.4 + ;; https://debbugs.gnu.org/38563 + (font-lock-append-text-property 0 (length str) 'face 'default str) (when nl (put-text-property 0 1 'cursor t str)) str))) @@ -2770,23 +2847,26 @@ If SHOW-VERSION is non-nil, show the version in the echo area." (when (< len (+ company-tooltip-offset limit)) (setq company-tooltip-offset 0)) - ;; Scroll to offset. - (if (eq company-tooltip-offset-display 'lines) - (setq limit (company-tooltip--lines-update-offset selection len limit)) - (company-tooltip--simple-update-offset selection len limit)) + (let ((selection (or selection 0))) + ;; Scroll to offset. + (if (eq company-tooltip-offset-display 'lines) + (setq limit (company-tooltip--lines-update-offset selection len limit)) + (company-tooltip--simple-update-offset selection len limit)) - (cond - ((eq company-tooltip-offset-display 'scrollbar) - (setq scrollbar-bounds (company--scrollbar-bounds company-tooltip-offset - limit len))) - ((eq company-tooltip-offset-display 'lines) - (when (> company-tooltip-offset 0) - (setq previous (format "...(%d)" company-tooltip-offset))) - (setq remainder (- len limit company-tooltip-offset) - remainder (when (> remainder 0) - (setq remainder (format "...(%d)" remainder)))))) + (cond + ((eq company-tooltip-offset-display 'scrollbar) + (setq scrollbar-bounds (company--scrollbar-bounds company-tooltip-offset + limit len))) + ((eq company-tooltip-offset-display 'lines) + (when (> company-tooltip-offset 0) + (setq previous (format "...(%d)" company-tooltip-offset))) + (setq remainder (- len limit company-tooltip-offset) + remainder (when (> remainder 0) + (setq remainder (format "...(%d)" remainder))))))) + + (when selection + (cl-decf selection company-tooltip-offset)) - (cl-decf selection company-tooltip-offset) (setq width (max (length previous) (length remainder)) lines (nthcdr company-tooltip-offset company-candidates) len (min limit len) @@ -2803,6 +2883,7 @@ If SHOW-VERSION is non-nil, show the version in the echo area." (setq annotation (company--clean-string annotation)) (when company-tooltip-align-annotations ;; `lisp-completion-at-point' adds a space. + ;; FIXME: Use `string-trim' in Emacs 24.4 (setq annotation (comment-string-strip annotation t nil)))) (push (cons value annotation) items) (setq width (max (+ (length value) @@ -2818,6 +2899,10 @@ If SHOW-VERSION is non-nil, show the version in the echo area." (+ 2 width) width)))) + (when company-tooltip-width-grow-only + (setq width (max company--tooltip-current-width width)) + (setq company--tooltip-current-width width)) + (let ((items (nreverse items)) (numbered (if company-show-numbers 0 99999)) new) @@ -2955,14 +3040,12 @@ Returns a negative number if the tooltip should be displayed above point." (overlay-put ov 'priority 111) ;; No (extra) prefix for the first line. (overlay-put ov 'line-prefix "") - ;; `display' is better - ;; (http://debbugs.gnu.org/18285, http://debbugs.gnu.org/20847), - ;; but it doesn't work on 0-length overlays. - (if (< (overlay-start ov) (overlay-end ov)) - (overlay-put ov 'display disp) - (overlay-put ov 'after-string disp) - (overlay-put ov 'invisible t)) - (overlay-put ov 'face 'default) + (overlay-put ov 'after-string disp) + ;; `display' is better than `invisible': + ;; https://debbugs.gnu.org/18285 + ;; https://debbugs.gnu.org/20847 + ;; https://debbugs.gnu.org/42521 + (overlay-put ov 'display "") (overlay-put ov 'window (selected-window))))) (defun company-pseudo-tooltip-guard () @@ -2983,23 +3066,43 @@ Returns a negative number if the tooltip should be displayed above point." (pre-command (company-pseudo-tooltip-hide-temporarily)) (post-command (unless (when (overlayp company-pseudo-tooltip-overlay) - (let* ((ov company-pseudo-tooltip-overlay) - (old-height (overlay-get ov 'company-height)) - (new-height (company--pseudo-tooltip-height))) - (and - (>= (* old-height new-height) 0) - (>= (abs old-height) (abs new-height)) - (equal (company-pseudo-tooltip-guard) - (overlay-get ov 'company-guard))))) + (let* ((ov company-pseudo-tooltip-overlay) + (old-height (overlay-get ov 'company-height)) + (new-height (company--pseudo-tooltip-height))) + (and + (>= (* old-height new-height) 0) + (>= (abs old-height) (abs new-height)) + (equal (company-pseudo-tooltip-guard) + (overlay-get ov 'company-guard))))) ;; Redraw needed. (company-pseudo-tooltip-show-at-point (point) (length company-prefix)) (overlay-put company-pseudo-tooltip-overlay 'company-guard (company-pseudo-tooltip-guard))) (company-pseudo-tooltip-unhide)) + (show (setq company--tooltip-current-width 0)) (hide (company-pseudo-tooltip-hide) (setq company-tooltip-offset 0)) (update (when (overlayp company-pseudo-tooltip-overlay) - (company-pseudo-tooltip-edit company-selection))))) + (company-pseudo-tooltip-edit company-selection))) + (select-mouse + (let ((event-col-row (company--event-col-row company-mouse-event)) + (ovl-row (company--row)) + (ovl-height (and company-pseudo-tooltip-overlay + (min (overlay-get company-pseudo-tooltip-overlay + 'company-height) + company-candidates-length)))) + (cond ((and ovl-height + (company--inside-tooltip-p event-col-row ovl-row ovl-height)) + (company-set-selection (+ (cdr event-col-row) + (1- company-tooltip-offset) + (if (and (eq company-tooltip-offset-display 'lines) + (not (zerop company-tooltip-offset))) + -1 0) + (- ovl-row) + (if (< ovl-height 0) + (- 1 ovl-height) + 0))) + t)))))) (defun company-pseudo-tooltip-unless-just-one-frontend (command) "`company-pseudo-tooltip-frontend', but not shown for single candidates." @@ -3089,8 +3192,10 @@ Delay is determined by `company-tooltip-idle-delay'." "`company-mode' frontend showing the selection as if it had been inserted." (pcase command (`pre-command (company-preview-hide)) - (`post-command (company-preview-show-at-point (point) - (nth company-selection company-candidates))) + (`post-command + (when company-selection + (company-preview-show-at-point (point) + (nth company-selection company-candidates)))) (`hide (company-preview-hide)))) (defun company-preview-if-just-one-frontend (command) @@ -3166,59 +3271,61 @@ Delay is determined by `company-tooltip-idle-delay'." (run-with-idle-timer company-echo-delay nil 'company-echo-show getter))) (defun company-echo-format () + (let ((selection (or company-selection 0))) + (let ((limit (window-body-width (minibuffer-window))) + (len -1) + ;; Roll to selection. + (candidates (nthcdr selection company-candidates)) + (i (if company-show-numbers selection 99999)) + comp msg) - (let ((limit (window-body-width (minibuffer-window))) - (len -1) - ;; Roll to selection. - (candidates (nthcdr company-selection company-candidates)) - (i (if company-show-numbers company-selection 99999)) - comp msg) + (while candidates + (setq comp (company-reformat (company--clean-string (pop candidates))) + len (+ len 1 (length comp))) + (if (< i 10) + ;; Add number. + (progn + (setq comp (propertize (format "%d: %s" i comp) + 'face 'company-echo)) + (cl-incf len 3) + (cl-incf i) + ;; FIXME: Add support for the `match' backend action, and thus, + ;; non-prefix matches. + (add-text-properties 3 (+ 3 (string-width (or company-common ""))) + '(face company-echo-common) comp)) + (setq comp (propertize comp 'face 'company-echo)) + (add-text-properties 0 (string-width (or company-common "")) + '(face company-echo-common) comp)) + (if (>= len limit) + (setq candidates nil) + (push comp msg))) - (while candidates - (setq comp (company-reformat (company--clean-string (pop candidates))) - len (+ len 1 (length comp))) - (if (< i 10) - ;; Add number. - (progn - (setq comp (propertize (format "%d: %s" i comp) - 'face 'company-echo)) - (cl-incf len 3) - (cl-incf i) - (add-text-properties 3 (+ 3 (string-width company-common)) - '(face company-echo-common) comp)) - (setq comp (propertize comp 'face 'company-echo)) - (add-text-properties 0 (string-width company-common) - '(face company-echo-common) comp)) - (if (>= len limit) - (setq candidates nil) - (push comp msg))) - - (mapconcat 'identity (nreverse msg) " "))) + (mapconcat 'identity (nreverse msg) " ")))) (defun company-echo-strip-common-format () + (let ((selection (or company-selection 0))) + (let ((limit (window-body-width (minibuffer-window))) + (len (+ (length company-prefix) 2)) + ;; Roll to selection. + (candidates (nthcdr selection company-candidates)) + (i (if company-show-numbers selection 99999)) + msg comp) - (let ((limit (window-body-width (minibuffer-window))) - (len (+ (length company-prefix) 2)) - ;; Roll to selection. - (candidates (nthcdr company-selection company-candidates)) - (i (if company-show-numbers company-selection 99999)) - msg comp) + (while candidates + (setq comp (company-strip-prefix (pop candidates)) + len (+ len 2 (length comp))) + (when (< i 10) + ;; Add number. + (setq comp (format "%s (%d)" comp i)) + (cl-incf len 4) + (cl-incf i)) + (if (>= len limit) + (setq candidates nil) + (push (propertize comp 'face 'company-echo) msg))) - (while candidates - (setq comp (company-strip-prefix (pop candidates)) - len (+ len 2 (length comp))) - (when (< i 10) - ;; Add number. - (setq comp (format "%s (%d)" comp i)) - (cl-incf len 4) - (cl-incf i)) - (if (>= len limit) - (setq candidates nil) - (push (propertize comp 'face 'company-echo) msg))) - - (concat (propertize company-prefix 'face 'company-echo-common) "{" - (mapconcat 'identity (nreverse msg) ", ") - "}"))) + (concat (propertize company-prefix 'face 'company-echo-common) "{" + (mapconcat 'identity (nreverse msg) ", ") + "}")))) (defun company-echo-hide () (unless (equal company-echo-last-msg "") diff --git a/lisp/counsel.el b/lisp/counsel.el index 2f09ac54..27652348 100644 --- a/lisp/counsel.el +++ b/lisp/counsel.el @@ -4,8 +4,8 @@ ;; Author: Oleh Krehel ;; URL: https://github.com/abo-abo/swiper -;; Package-Version: 20200619.1030 -;; Package-Commit: d951004c7f3ebf98d55fc5a80a3471ec95b6db05 +;; Package-Version: 20201227.1327 +;; Package-Commit: 71c59aecf669142ebe264fac8ff7b440c0c71712 ;; Version: 0.13.0 ;; Package-Requires: ((emacs "24.5") (swiper "0.13.0")) ;; Keywords: convenience, matching, tools @@ -116,17 +116,25 @@ complex regexes." str) str)) +(defalias 'counsel--executable-find + ;; Gained optional argument in 27.1. + (if (>= emacs-major-version 27) + #'executable-find + (lambda (command &optional _remote) + (executable-find command))) + "Compatibility shim for `executable-find'.") + (defun counsel-require-program (cmd) "Check system for program used in CMD, printing error if not found. CMD is either a string or a list of strings. To skip the `executable-find' check, start the string with a space." - (unless (and (stringp cmd) (string-match-p "^ " cmd)) + (unless (and (stringp cmd) (string-prefix-p " " cmd)) (let ((program (if (listp cmd) (car cmd) (car (split-string cmd))))) (or (and (stringp program) (not (string= program "")) - (executable-find program)) + (counsel--executable-find program t)) (user-error "Required program \"%s\" not found in your path" program))))) (declare-function eshell-split-path "esh-util") @@ -1094,17 +1102,17 @@ See `describe-buffer-bindings' for further information." (describe-buffer-bindings buffer prefix)) (goto-char (point-min)) ;; Skip the "Key translations" section - (re-search-forward " ") - (forward-char 1) + (skip-chars-forward "^\C-l") + (forward-char 2) (while (not (eobp)) (when (looking-at "^\\([^\t\n]+\\)[\t ]*\\(.*\\)$") (let ((key (match-string 1)) (fun (match-string 2)) cmd) (unless (or (member fun '("??" "self-insert-command")) - (string-match re-exclude key) + (string-match-p re-exclude key) (not (or (commandp (setq cmd (intern-soft fun))) - (member fun '("Prefix Command"))))) + (equal fun "Prefix Command")))) (push (cons (format "%-15s %s" @@ -1112,7 +1120,7 @@ See `describe-buffer-bindings' for further information." fun) (cons key cmd)) res)))) - (forward-line 1))) + (forward-line))) (nreverse res))) (defcustom counsel-descbinds-function #'describe-function @@ -1188,6 +1196,15 @@ back to the face of the character after point, and finally the "Customize face with NAME in another window." (customize-face-other-window (intern name))) +(declare-function hi-lock-set-pattern "hi-lock") +(defun counsel-highlight-with-face (face) + "Highlight thing-at-point with FACE." + (hi-lock-mode 1) + (let ((thing (ivy-thing-at-point))) + (when (use-region-p) + (deactivate-mark)) + (hi-lock-set-pattern (regexp-quote thing) (intern face)))) + (ivy-set-actions 'counsel-describe-face '(("c" counsel-customize-face "customize") @@ -1232,7 +1249,8 @@ selected face." (ivy-set-actions 'counsel-faces '(("c" counsel-customize-face "customize") - ("C" counsel-customize-face-other-window "customize other window"))) + ("C" counsel-customize-face-other-window "customize other window") + ("h" counsel-highlight-with-face "highlight"))) ;;* Git ;;** `counsel-git' @@ -1791,10 +1809,17 @@ currently checked out." (let ((map (make-sparse-keymap))) (define-key map (kbd "C-DEL") 'counsel-up-directory) (define-key map (kbd "C-") 'counsel-up-directory) - (define-key map (kbd "`") (ivy-make-magic-action 'counsel-find-file "b")) + (define-key map (kbd "`") #'counsel-file-jump-from-find) + (define-key map (kbd "C-`") (ivy-make-magic-action 'counsel-find-file "b")) (define-key map [remap undo] 'counsel-find-file-undo) map)) +(defun counsel-file-jump-from-find () + "Switch to `counsel-file-jump' from `counsel-find-file'." + (interactive) + (ivy-quit-and-run + (counsel-file-jump ivy-text))) + (when (executable-find "git") (add-to-list 'ivy-ffap-url-functions 'counsel-github-url-p) (add-to-list 'ivy-ffap-url-functions 'counsel-emacs-url-p)) @@ -1963,15 +1988,14 @@ Skip some dotfiles unless `ivy-text' requires them." (defun counsel-find-file-action (x) "Find file X." - (with-ivy-window - (cond ((and counsel-find-file-speedup-remote - (file-remote-p ivy--directory)) - (let ((find-file-hook nil)) - (find-file (expand-file-name x ivy--directory)))) - ((member (file-name-extension x) counsel-find-file-extern-extensions) - (counsel-find-file-extern x)) - (t - (find-file (expand-file-name x ivy--directory)))))) + (cond ((and counsel-find-file-speedup-remote + (file-remote-p ivy--directory)) + (let ((find-file-hook nil)) + (find-file (expand-file-name x ivy--directory)))) + ((member (file-name-extension x) counsel-find-file-extern-extensions) + (counsel-find-file-extern x)) + (t + (find-file (expand-file-name x ivy--directory))))) (defun counsel--preselect-file () "Return candidate to preselect during filename completion. @@ -2520,13 +2544,13 @@ can use `C-x r j i' to open that file." ;;** `counsel-locate' (defcustom counsel-locate-cmd (cond ((memq system-type '(darwin berkeley-unix)) - 'counsel-locate-cmd-noregex) + #'counsel-locate-cmd-noregex) ((and (eq system-type 'windows-nt) (executable-find "es.exe")) - 'counsel-locate-cmd-es) + #'counsel-locate-cmd-es) (t - 'counsel-locate-cmd-default)) - "The function for producing a locate command string from the input. + #'counsel-locate-cmd-default)) + "The function for producing a `locate' command string from the input. The function takes a string - the current input, and returns a string - the full shell command to run." @@ -2534,7 +2558,8 @@ string - the full shell command to run." (const :tag "Default" counsel-locate-cmd-default) (const :tag "No regex" counsel-locate-cmd-noregex) (const :tag "mdfind" counsel-locate-cmd-mdfind) - (const :tag "everything" counsel-locate-cmd-es))) + (const :tag "everything" counsel-locate-cmd-es) + (function :tag "Custom"))) (ivy-set-actions 'counsel-locate @@ -2569,33 +2594,33 @@ string - the full shell command to run." (dired-jump nil x)) (defun counsel-locate-cmd-default (input) - "Return a shell command based on INPUT." + "Return a `locate' shell command based on regexp INPUT." (counsel-require-program "locate") - (format "locate -i --regex '%s'" - (counsel--elisp-to-pcre - (ivy--regex input)))) + (format "locate -i --regex %s" + (shell-quote-argument + (counsel--elisp-to-pcre + (ivy--regex input))))) (defun counsel-locate-cmd-noregex (input) - "Return a shell command based on INPUT." + "Return a `locate' shell command based on INPUT." (counsel-require-program "locate") - (format "locate -i '%s'" input)) + (format "locate -i %s" (shell-quote-argument input))) (defun counsel-locate-cmd-mdfind (input) - "Return a shell command based on INPUT." + "Return a `mdfind' shell command based on INPUT." (counsel-require-program "mdfind") - (format "mdfind -name '%s'" input)) - -(defvar w32-ansi-code-page) + (format "mdfind -name %s" (shell-quote-argument input))) (defun counsel-locate-cmd-es (input) - "Return a shell command based on INPUT." + "Return a `es' shell command based on INPUT." + (defvar w32-ansi-code-page) (counsel-require-program "es.exe") (let ((raw-string (format "es.exe -i -p -r %s" (counsel--elisp-to-pcre (ivy--regex input t))))) - ;; W32 don't use Unicode by default, so we encode search command - ;; to local codepage to support searching filename contains non-ASCII - ;; characters. + ;; W32 doesn't use Unicode by default, so we encode search command + ;; to local codepage to support searching file names containing + ;; non-ASCII characters. (if (and (eq system-type 'windows-nt) (boundp 'w32-ansi-code-page)) (encode-coding-string raw-string @@ -2603,7 +2628,7 @@ string - the full shell command to run." raw-string))) (defun counsel-locate-function (input) - "Call the \"locate\" shell command with INPUT." + "Call a \"locate\" style shell command with INPUT." (or (ivy-more-chars) (progn @@ -2617,10 +2642,7 @@ string - the full shell command to run." (defun counsel-file-stale-p (fname seconds) "Return non-nil if FNAME was modified more than SECONDS ago." - (> (time-to-seconds - (time-subtract - (current-time) - (nth 5 (file-attributes fname)))) + (> (float-time (time-subtract nil (nth 5 (file-attributes fname)))) seconds)) (defun counsel--locate-updatedb () @@ -2635,7 +2657,7 @@ string - the full shell command to run." ;;;###autoload (defun counsel-locate (&optional initial-input) - "Call the \"locate\" shell command. + "Call a \"locate\" style shell command. INITIAL-INPUT can be given as the initial minibuffer input." (interactive) (counsel--locate-updatedb) @@ -2966,24 +2988,33 @@ NEEDLE is the search string." ;;;###autoload (cl-defun counsel-ag (&optional initial-input initial-directory extra-ag-args ag-prompt &key caller) - "Grep for a string in the current directory using ag. + "Grep for a string in a root directory using ag. + +By default, the root directory is the first directory containing a .git subdirectory. + INITIAL-INPUT can be given as the initial minibuffer input. INITIAL-DIRECTORY, if non-nil, is used as the root directory for search. -EXTRA-AG-ARGS string, if non-nil, is appended to `counsel-ag-base-command'. +EXTRA-AG-ARGS, if non-nil, is appended to `counsel-ag-base-command'. AG-PROMPT, if non-nil, is passed as `ivy-read' prompt argument. -CALLER is passed to `ivy-read'." +CALLER is passed to `ivy-read'. + +With a `\\[universal-argument]' prefix argument, prompt for INITIAL-DIRECTORY. +With a `\\[universal-argument] \\[universal-argument]' prefix argument, \ +prompt additionally for EXTRA-AG-ARGS." (interactive) (setq counsel-ag-command counsel-ag-base-command) (setq counsel--regex-look-around counsel--grep-tool-look-around) (counsel-require-program counsel-ag-command) (let ((prog-name (car (if (listp counsel-ag-command) counsel-ag-command - (split-string counsel-ag-command))))) - (when current-prefix-arg + (split-string counsel-ag-command)))) + (arg (prefix-numeric-value current-prefix-arg))) + (when (>= arg 4) (setq initial-directory (or initial-directory (counsel-read-directory-name (concat prog-name - " in directory: ")))) + " in directory: "))))) + (when (>= arg 16) (setq extra-ag-args (or extra-ag-args (read-from-minibuffer (format "%s args: " prog-name))))) @@ -3056,10 +3087,12 @@ Works for `counsel-git-grep', `counsel-ag', etc." (funcall cmd-template ivy-text) (let* ((command-args (counsel--split-command-args ivy-text)) (regex (counsel--grep-regex (cdr command-args))) + (extra-switches (counsel--ag-extra-switches regex)) (all-args (append (when (car command-args) (split-string (car command-args))) - (counsel--ag-extra-switches regex) + (when extra-switches + (split-string extra-switches)) (list (counsel--grep-smart-case-flag) regex)))) @@ -3762,7 +3795,7 @@ include attachments of other Org buffers." (let (dirs) (save-excursion (goto-char (point-min)) - (while (re-search-forward "^:\\(ATTACH_DIR\\|ID\\):[\t ]+\\(.*\\)$" nil t) + (while (re-search-forward ":\\(?:ATTACH_DIR\\|ID\\):[\t ]+.*$" nil t) (let ((dir (org-attach-dir))) (when dir (push dir dirs))))) @@ -3828,18 +3861,28 @@ include attachments of other Org buffers." (interactive) (require 'org-capture) (ivy-read "Capture template: " - (delq nil - (mapcar - (lambda (x) - (when (> (length x) 2) - (format "%-5s %s" (nth 0 x) (nth 1 x)))) - ;; We build the list of capture templates as in - ;; `org-capture-select-template': - (or (org-contextualize-keys - (org-capture-upgrade-templates org-capture-templates) - org-capture-templates-contexts) - '(("t" "Task" entry (file+headline "" "Tasks") - "* TODO %?\n %u\n %a"))))) + ;; We build the list of capture templates as in `org-capture-select-template': + (let (prefixes) + (cl-mapcan + (lambda (x) + (let ((x-keys (car x))) + ;; Remove prefixed keys until we get one that matches the current item. + (while (and prefixes + (let ((p1-keys (caar prefixes))) + (or + (<= (length x-keys) (length p1-keys)) + (not (string-prefix-p p1-keys x-keys))))) + (pop prefixes)) + (if (> (length x) 2) + (let ((desc (mapconcat #'cadr (reverse (cons x prefixes)) " | "))) + (list (format "%-5s %s" x-keys desc))) + (push x prefixes) + nil))) + (or (org-contextualize-keys + (org-capture-upgrade-templates org-capture-templates) + org-capture-templates-contexts) + '(("t" "Task" entry (file+headline "" "Tasks") + "* TODO %?\n %u\n %a"))))) :require-match t :action (lambda (x) (org-capture nil (car (split-string x)))) @@ -3987,7 +4030,7 @@ This variable has no effect unless ;; Misc. Emacs ;;** `counsel-mark-ring' (defface counsel--mark-ring-highlight - '((t (:inherit highlight))) + '((t :inherit highlight)) "Face for current `counsel-mark-ring' line." :group 'ivy-faces) @@ -4037,7 +4080,7 @@ Obeys `widen-automatically', which see." (cons (copy-marker (mark-marker)) marks))) (candidates (counsel-mark--get-candidates marks))) (if candidates - (counsel-mark--ivy-read candidates 'counsel-mark-ring) + (counsel-mark--ivy-read "Mark: " candidates 'counsel-mark-ring) (message "Mark ring is empty")))) (defun counsel-mark--get-candidates (marks) @@ -4061,7 +4104,7 @@ point to indicarte where the candidate mark is." (propertize (format fmt linum line) 'point (point)))) marks)))))) -(defun counsel-mark--ivy-read (candidates caller) +(defun counsel-mark--ivy-read (prompt candidates caller) "call `ivy-read' with sane defaults for traversing marks. CANDIDATES should be an alist with the `car' of the list being the string displayed by ivy and the `cdr' being the point that @@ -4069,7 +4112,7 @@ mark should take you to. NOTE This has been abstracted out into it's own method so it can be used by both `counsel-mark-ring' and `counsel-evil-marks'" - (ivy-read "Mark: " candidates + (ivy-read prompt candidates :require-match t :update-fn #'counsel--mark-ring-update-fn :action (lambda (cand) @@ -4150,8 +4193,8 @@ When ARG is non-nil, display all active evil registers." (let* ((counsel--mark-ring-calling-point (point)) (candidates (counsel-mark--get-evil-candidates arg))) (if candidates - (counsel-mark--ivy-read candidates 'counsel-evil-marks) - (message "no evil marks are active"))) + (counsel-mark--ivy-read "Evil mark: " candidates 'counsel-evil-marks) + (message "No evil marks are active"))) (user-error "Required feature `evil' not installed or loaded"))) ;;** `counsel-package' @@ -4211,7 +4254,8 @@ Additional actions:\\ :history 'counsel-package-history :caller 'counsel-package)) -(cl-pushnew '(counsel-package . "^+") ivy-initial-inputs-alist :key #'car) +(ivy-configure 'counsel-package + :initial-input "^+") (defun counsel-package-action (package) "Delete or install PACKAGE." @@ -4387,13 +4431,18 @@ Signal a `buffer-read-only' error if called from a read-only buffer position." (with-ivy-window (barf-if-buffer-read-only) - (setq last-command 'yank) (setq yank-window-start (window-start)) + (unless (eq last-command 'yank) + ;; Avoid unexpected deletions with `yank-handler' properties. + (setq yank-undo-function nil)) (condition-case nil - ;; Avoid unexpected additions to `kill-ring' - (let (interprogram-paste-function) + (let (;; Deceive `yank-pop'. + (last-command 'yank) + ;; Avoid unexpected additions to `kill-ring'. + interprogram-paste-function) (yank-pop (counsel--yank-pop-position s))) (error + ;; Support strings not present in the kill ring. (insert s))) (when (funcall (if counsel-yank-pop-after-point #'> #'<) (point) (mark t)) @@ -4538,7 +4587,7 @@ matching the register's value description against a regexp in ;;** `counsel-evil-registers' (defface counsel-evil-register-face - '((t (:inherit counsel-outline-1))) + '((t :inherit counsel-outline-1)) "Face for highlighting `evil' registers in ivy." :group 'ivy-faces) @@ -4723,9 +4772,11 @@ An extra action allows to switch to the process buffer." (defvar eshell-history-index) (defvar slime-repl-input-history-position) -(defvar counsel-esh--index-last) -(defvar counsel-shell-history--index-last) -(defvar counsel-slime-repl-history--index-last) +(defvar counsel-esh--index-last nil + "Index corresponding to last selection with `counsel-esh-history'.") + +(defvar counsel-shell-history--index-last nil + "Index corresponding to last selection with `counsel-shell-history'.") (defun counsel--browse-history-action (pair) (let ((snd (cdr pair))) @@ -4736,9 +4787,12 @@ An extra action allows to switch to the process buffer." (counsel-shell-history (setq comint-input-ring-index snd counsel-shell-history--index-last snd)) + ;; Leave this as a no-op. If someone decides to patch + ;; `slime-repl-previous-input' or one of its utility functions, + ;; or to add history-replay to Slime, then this section can be + ;; updated to add the relevant support for those commands. (counsel-slime-repl-history - (setq slime-repl-input-history-position snd - counsel-slime-repl-history--index-last snd))) + nil)) (ivy-completion-in-region-action (car pair)))) (cl-defun counsel--browse-history (ring &key caller) @@ -4761,9 +4815,6 @@ An extra action allows to switch to the process buffer." (defvar eshell-history-ring) (defvar eshell-matching-input-from-input-string) -(defvar counsel-esh--index-last nil - "Index corresponding to last selection with `counsel-esh-history'.") - ;;;###autoload (defun counsel-esh-history () "Browse Eshell history." @@ -4783,9 +4834,6 @@ An extra action allows to switch to the process buffer." (defvar comint-input-ring) (defvar comint-matching-input-from-input-string) -(defvar counsel-shell-history--index-last nil - "Index corresponding to last selection with `counsel-shell-history'.") - ;;;###autoload (defun counsel-shell-history () "Browse shell history." @@ -4804,9 +4852,6 @@ An extra action allows to switch to the process buffer." (defvar slime-repl-input-history) -(defvar counsel-slime-repl-history--index-last nil - "Index corresponding to last selection with `counsel-slime-repl-history'.") - ;;;###autoload (defun counsel-slime-repl-history () "Browse Slime REPL history." @@ -4816,7 +4861,9 @@ An extra action allows to switch to the process buffer." :caller #'counsel-slime-repl-history)) ;; TODO: add advice for slime-repl-input-previous/next to properly -;; reassign the ring index and match string +;; reassign the ring index and match string. This requires a case for +;; `counsel-slime-repl-history' within +;; `counsel--browse-history-action'. ;;** `counsel-hydra-heads' (defvar hydra-curr-body-fn) @@ -5854,6 +5901,7 @@ as arguments." (const :tag "Command : Name - Comment" counsel-linux-app-format-function-default) (const :tag "Name - Comment (Command)" counsel-linux-app-format-function-name-first) (const :tag "Name - Comment" counsel-linux-app-format-function-name-only) + (const :tag "Name - Comment (Pretty)" counsel-linux-app-format-function-name-pretty) (const :tag "Command" counsel-linux-app-format-function-command-only) (function :tag "Custom"))) @@ -5928,7 +5976,9 @@ NAME is the name of the application, COMMENT its comment and EXEC the command to launch it." (format "% -45s: %s%s" (propertize - (ivy--truncate-string exec 45) + (ivy--truncate-string + (replace-regexp-in-string "env +[^ ]+ +" "" exec) + 45) 'face 'counsel-application-name) name (if comment @@ -5957,6 +6007,16 @@ EXEC is the command to launch the application." "Display only the command EXEC when formatting Linux application names." exec) +(defun counsel-linux-app-format-function-name-pretty (name comment _exec) + "Format Linux application names with the NAME (and COMMENT) only, but pretty." + (format "% -45s%s" + (propertize + (ivy--truncate-string name 45) + 'face 'counsel-application-name) + (if comment + (concat ": " comment) + ""))) + (defun counsel-linux-apps-list-desktop-files () "Return an alist of all Linux applications. Each list entry is a pair of (desktop-name . desktop-file). @@ -6087,7 +6147,7 @@ Any desktop entries that fail to parse are recorded in "Launch a Linux desktop application, similar to Alt-. When ARG is non-nil, ignore NoDisplay property in *.desktop files." (interactive "P") - (ivy-read "Run a command: " (counsel-linux-apps-list) + (ivy-read "Run application: " (counsel-linux-apps-list) :predicate (unless arg (lambda (x) (get-text-property 0 'visible (car x)))) :action #'counsel-linux-app-action-default :caller 'counsel-linux-app)) @@ -6279,7 +6339,8 @@ Use the presence of a `dir-locals-file' to determine the root." (defvar counsel-compile-local-builds '(counsel-compile-get-filtered-history counsel-compile-get-build-directories - counsel-compile-get-make-invocation) + counsel-compile-get-make-invocation + counsel-compile-get-make-help-invocations) "Additional compile invocations to feed into `counsel-compile'. This can either be a list of compile invocation strings or @@ -6319,26 +6380,30 @@ list is passed to `compilation-environment'." (defvar counsel-compile-phony-pattern "^\\.PHONY:[\t ]+\\(.+\\)$" "Regexp for extracting phony targets from Makefiles.") -;; This is loosely based on the Bash Make completion code +(defvar counsel-compile-help-pattern + "\\(?:^\\(\\*\\)?[[:space:]]+\\([^[:space:]]+\\)[[:space:]]+-\\)" + "Regexp for extracting help targets from a make help call.") + +;; This is loosely based on the Bash Make completion code which +;; relies on GNUMake having the following return codes: +;; 0 = no-rebuild, -q & 1 needs rebuild, 2 error (defun counsel-compile--probe-make-targets (dir) "Return a list of Make targets for DIR. -Return an empty list is Make exits with an error. This might -happen because some sort of configuration needs to be done first -or the source tree is pristine and being used for multiple build -trees." - (let ((default-directory dir) - (targets nil)) - (with-temp-buffer - ;; 0 = no-rebuild, -q & 1 needs rebuild, 2 error (for GNUMake at - ;; least) - (when (< (call-process "make" nil t nil "-nqp") 2) +Return a single blank target (so we invoke the default target) +if Make exits with an error. This might happen because some sort +of configuration needs to be done first or the source tree is +pristine and being used for multiple build trees." + (with-temp-buffer + (let* ((default-directory dir) + (res (call-process "make" nil t nil "-nqp")) + targets) + (if (or (not (numberp res)) (> res 1)) + (list "") (goto-char (point-min)) (while (re-search-forward counsel-compile-phony-pattern nil t) - (setq targets - (nconc targets (split-string - (match-string-no-properties 1))))))) - (sort targets #'string-lessp))) + (push (split-string (match-string-no-properties 1)) targets)) + (sort (apply #'nconc targets) #'string-lessp))))) (defun counsel-compile--pretty-propertize (leader text face) "Return a pretty string of the form \" LEADER TEXT\". @@ -6349,12 +6414,13 @@ text with FACE." 'font-lock-warning-face) (propertize text 'face face))) -(defun counsel--compile-get-make-targets (srcdir &optional blddir) - "Return a list of Make targets for a given SRCDIR/BLDDIR combination. +(defun counsel--compile-get-make-targets (probe-fn srcdir &optional blddir) + "Return propertized make targets returned by PROBE-FN in SRCDIR. -We search the Makefile for a list of phony targets which are -generally the top level targets a Make system provides. -The resulting strings are tagged with properties that +The optional BLDDIR allows for handling build directories. We +search the Makefile for a list of phony targets which are +generally the top level targets a Make system provides. The +resulting strings are tagged with properties that `counsel-compile-history' can use for filtering results." (let ((fmt (format (propertize "make %s %%s" 'cmd t) counsel-compile-make-args)) @@ -6371,7 +6437,7 @@ The resulting strings are tagged with properties that (setq target (concat (format fmt target) suffix build-env)) (add-text-properties 0 (length target) props target) target) - (counsel-compile--probe-make-targets (or blddir srcdir))))) + (funcall probe-fn (or blddir srcdir))))) (defun counsel-compile-get-make-invocation (&optional blddir) "Have a look in the root directory for any build control files. @@ -6381,7 +6447,41 @@ sub-directories that builds may be invoked in." (let ((srcdir (counsel--compile-root))) (when (directory-files (or blddir srcdir) nil counsel-compile-make-pattern t) - (counsel--compile-get-make-targets srcdir blddir)))) + (counsel--compile-get-make-targets + #'counsel-compile--probe-make-targets srcdir blddir)))) + +(defun counsel-compile--probe-make-help (dir) + "Return a list of Make targets based on help for DIR. + +It is quite common for a 'make help' invocation to return a human +readable list of targets. Often common targets are marked with a +leading asterisk. The exact search pattern is controlled by +`counsel-compile-help-pattern'." + (let ((default-directory dir) + primary-targets targets) + ;; Only proceed if the help target exists. + (when (eql 1 (apply #'call-process "make" nil nil nil "-q" "help" + counsel-compile-env)) + (with-temp-buffer + (when (eql 0 (apply #'call-process "make" nil t nil "help" + counsel-compile-env)) + (goto-char (point-min)) + (while (re-search-forward counsel-compile-help-pattern nil t) + (push (match-string 2) + (if (match-beginning 1) primary-targets targets))) + (nconc (sort primary-targets #'string-lessp) + (sort targets #'string-lessp))))))) + +(defun counsel-compile-get-make-help-invocations (&optional blddir) + "Query the root directory for makefiles with help output. + +The optional BLDDIR is useful for other helpers that have found +sub-directories that builds may be invoked in." + (let ((srcdir (counsel--compile-root))) + (when (directory-files (or blddir srcdir) nil + counsel-compile-make-pattern t) + (counsel--compile-get-make-targets + #'counsel-compile--probe-make-help srcdir blddir)))) (defun counsel--find-build-subdir (srcdir) "Return builds subdirectory of SRCDIR, if one exists." @@ -6495,9 +6595,36 @@ specified by the `blddir' property." (compile cmd) (remove-hook 'compilation-start-hook #'counsel-compile--update-history)))))) +(defun counsel-compile-edit-command () + "Insert current compile command into the minibuffer for editing. + +This mirrors the behavior of `ivy-insert-current' but with specific +handling for the `counsel-compile' metadata." + (interactive) + (delete-minibuffer-contents) + (let* ((cmd (ivy-state-current ivy-last)) + (blddir (get-text-property 0 'blddir cmd))) + (when blddir + (setq counsel-compile--current-build-dir blddir)) + (insert (substring-no-properties + cmd 0 (and (get-text-property 0 'cmd cmd) + (next-single-property-change 0 'cmd cmd)))))) + +;; Currently the only thing we do is override ivy's default insert +;; operation which doesn't include the metadata we want. +(defvar counsel-compile-map + (let ((map (make-sparse-keymap))) + (define-key map [remap ivy-insert-current] #'counsel-compile-edit-command) + map) + "Additional ivy keybindings during command selection.") + ;;;###autoload (defun counsel-compile (&optional dir) - "Call `compile' completing with smart suggestions, optionally for DIR." + "Call `compile' completing with smart suggestions, optionally for DIR. + +Additional actions: + +\\{counsel-compile-map}" (interactive) (setq counsel-compile--current-build-dir (or dir (counsel--compile-root) @@ -6505,6 +6632,7 @@ specified by the `blddir' property." (ivy-read "Compile command: " (delete-dups (counsel--get-compile-candidates dir)) :action #'counsel-compile--action + :keymap counsel-compile-map :caller 'counsel-compile)) (ivy-add-actions @@ -6679,7 +6807,7 @@ We update it in the callback with `ivy-update-candidates'." (browse-url (concat (nth 2 (assoc counsel-search-engine counsel-search-engines-alist)) - x))) + (url-hexify-string x)))) (defun counsel-search () "Ivy interface for dynamically querying a search engine." diff --git a/lisp/crdt.el b/lisp/crdt.el index 50fde7fe..c2d5fd50 100644 --- a/lisp/crdt.el +++ b/lisp/crdt.el @@ -44,8 +44,8 @@ "Ask for server password everytime a CRDT server is to be started." :type 'boolean) -(defcustom crdt-confirm-stop-session t - "Ask for confirmation when a CRDT server with some client connected is to be stopped." +(defcustom crdt-confirm-disconnect t + "Ask for confirmation when a CRDT server is to stop the connection from some client." :type 'boolean) (defvar crdt--log-network-traffic nil @@ -191,7 +191,7 @@ and HIGH-OFFSET. (to save two copying from using CRDT--ID-REPLACE-OFFSET)" (get-text-property pos 'crdt-id obj)) (defsubst crdt--get-starting-id (pos &optional obj) - "Get the CRDT-ID at POS in OBJ." + "Get the CRDT-ID object at POS in OBJ." (car (crdt--get-crdt-id-pair pos obj))) (defsubst crdt--end-of-block-p (pos &optional obj) @@ -295,12 +295,19 @@ Must be used inside CRDT--WITH-INSERTION-INFORMATION." This is useful for functions that apply remote change to local buffer, to avoid recusive calling of CRDT synchronization functions.") -(crdt--defvar-permanent-local crdt--changed-string nil) +(crdt--defvar-permanent-local crdt--changed-string nil + "Save changed substring in CRDT--BEFORE-CHANGE.") + +(crdt--defvar-permanent-local crdt--changed-start nil + "Save start character address of changes in CRDT--BEFORE-CHANGE, +to recover the portion being overwritten in CRDT--AFTER-CHANGE.") (crdt--defvar-permanent-local crdt--last-point nil) (crdt--defvar-permanent-local crdt--last-mark nil) +(crdt--defvar-permanent-local crdt--last-process-mark-id nil) + (crdt--defvar-permanent-local crdt--pseudo-cursor-table nil "A hash table that maps SITE-ID to CONSes of the form (CURSOR-OVERLAY . REGION-OVERLAY).") @@ -326,6 +333,8 @@ to avoid recusive calling of CRDT synchronization functions.") (crdt--defvar-permanent-local crdt--buffer-sync-callback) +(crdt--defvar-permanent-local crdt--buffer-pseudo-process) + ;;; Global variables (defvar crdt--session-list nil) @@ -364,8 +373,10 @@ Also set CRDT--PSEUDO-CURSOR-TABLE to NIL." "CRDT mode" nil " CRDT" nil (if crdt-mode (progn - (setq crdt--pseudo-cursor-table (make-hash-table)) - (setq crdt--overlay-table (make-hash-table :test 'equal)) + (unless crdt--pseudo-cursor-table + (setq crdt--pseudo-cursor-table (make-hash-table))) + (unless crdt--overlay-table + (setq crdt--overlay-table (make-hash-table :test 'equal))) (crdt--install-hooks)) (crdt--uninstall-hooks) (crdt--clear-pseudo-cursor-table) @@ -383,13 +394,18 @@ If SESSION is nil, use current CRDT--SESSION." (defmacro crdt--with-buffer-name (name &rest body) "Find CRDT shared buffer associated with NAME and evaluate BODY in it. +Also, try to recover from synchronization error if any error happens in BODY. Must be called when CURRENT-BUFFER is a CRDT status buffer. If such buffer doesn't exist yet, do nothing." `(let (crdt-buffer) (setq crdt-buffer (gethash ,name (crdt--session-buffer-table crdt--session))) (when (and crdt-buffer (buffer-live-p crdt-buffer)) (with-current-buffer crdt-buffer - ,@body)))) + (condition-case err + ,(cons 'progn body) + (error (if (crdt--server-p) + (signal (car err) (cdr err)) ; didn't implement server side recovery yet + (crdt--client-recover)))))))) (defmacro crdt--with-buffer-name-pull (name &rest body) "Find CRDT shared buffer associated with NAME and evaluate BODY in it. @@ -412,7 +428,8 @@ after synchronization is completed." (crdt-mode) (crdt--broadcast-maybe (crdt--format-message `(get ,,name))) (let ((crdt--inhibit-update t)) - (insert "Synchronizing with server...")) + (insert "Synchronizing with server...") + (read-only-mode)) (setq crdt--buffer-sync-callback (lambda () ,@body)))))))) @@ -587,9 +604,26 @@ Otherwise use a dedicated buffer for displaying active users on CRDT-BUFFER." t))) (message "Doesn't have position information for this user yet."))))) +(defun crdt--user-menu-kill () + "Disconnect the user under point in CRDT user menu. +Only server can perform this action." + (interactive) + (if (crdt--server-p) + (let ((site-id (tabulated-list-get-id))) + (if site-id + (if (eq site-id (crdt--session-local-id crdt--session)) + (message "Suicide is not allowed.") + (dolist (p (process-list)) + (when (eq (process-get p 'client-id) site-id) + (delete-process p)))) + (message "We somehow don't have the SITE-ID for this user. + Please submit a bug report to crdt.el maintainer."))) + (message "Only server can disconnect a user."))) + (defvar crdt-user-menu-mode-map (let ((map (make-sparse-keymap))) (define-key map (kbd "RET") #'crdt--user-menu-goto) + (define-key map (kbd "k") #'crdt--user-menu-kill) map)) (define-derived-mode crdt-user-menu-mode tabulated-list-mode @@ -599,9 +633,10 @@ Otherwise use a dedicated buffer for displaying active users on CRDT-BUFFER." ("Address" 15 t)])) (defun crdt-list-users (&optional crdt-buffer display-buffer) - "Display a list of active users working on a CRDT-shared buffer CRDT-BUFFER. + "Display a list of active users working on a CRDT-shared session. +Find the session in CRDT-BUFFER if non NIL, or current buffer. If DISPLAY-BUFFER is provided, display the output there. -Otherwise use a dedicated buffer for displaying active users on CRDT-BUFFER." +Otherwise create a dedicated buffer." (interactive) (with-current-buffer (or crdt-buffer (current-buffer)) (unless crdt--session @@ -787,10 +822,11 @@ Start the search around POSITION-HINT." ;; (crdt--verify-buffer) ) -(defun crdt--local-delete (beg end) +(defun crdt--local-delete (beg end length) "Handle local deletion event and return a message to be sent to other peers. -The deletion happens between BEG and END." - (let ((outer-end end)) +The deletion happens between BEG and END, and have LENGTH." + (let ((outer-end end) + (crdt--changed-string (crdt--changed-string beg length))) (crdt--with-insertion-information (beg 0 nil crdt--changed-string nil (length crdt--changed-string)) (when (crdt--split-maybe) @@ -801,10 +837,10 @@ The deletion happens between BEG and END." (crdt--id-replace-offset ending-id (+ 1 left-offset (length crdt--changed-string)))))))) (crdt--with-insertion-information ((length crdt--changed-string) outer-end crdt--changed-string nil 0 nil) - (crdt--split-maybe))) - ;; (crdt--verify-buffer) - `(delete ,crdt--buffer-network-name - ,beg ,@ (crdt--dump-ids 0 (length crdt--changed-string) crdt--changed-string t))) + (crdt--split-maybe)) + ;; (crdt--verify-buffer) + `(delete ,crdt--buffer-network-name + ,beg ,@ (crdt--dump-ids 0 (length crdt--changed-string) crdt--changed-string t)))) (defun crdt--remote-delete (position-hint id-items) "Handle remote deletion message of ID-ITEMS. @@ -837,7 +873,13 @@ Start the search for those ID-ITEMs around POSITION-HINT." "Before change hook used by CRDT-MODE. It saves the content to be changed (between BEG and END) into CRDT--CHANGED-STRING." (unless crdt--inhibit-update - (setq crdt--changed-string (buffer-substring beg end)))) + (setq crdt--changed-string (buffer-substring beg end)) + (setq crdt--changed-start beg))) + +(defsubst crdt--changed-string (beg length) + "Retrieve part of CRDT--CHANGED-STRING starting at BEG with LENGTH before change." + (let ((from (- beg crdt--changed-start))) + (substring crdt--changed-string from (+ from length)))) (defsubst crdt--crdt-id-assimilate (template beg &optional object) "Make the CRDT-ID property after BEG in OBJECT the same as TEMPLATE. @@ -854,11 +896,9 @@ TEMPLATE should be a string. If OBJECT is NIL, use current buffer." (defun crdt--after-change (beg end length) "After change hook used by CRDT-MODE. -It examine CRDT--CHANGED-STRING (should be saved by -CRDT--BEFORE-STRING and whose length shall equal to LENGTH) -and current content between BEG and END, -update the CRDT-ID for any newly inserted text, -and send message to other peers if needed." +It examine (CRDT--CHANGED-STRING) (should be saved by CRDT--BEFORE-STRING) +and current content between BEG and END with LENGTH, +update the CRDT-ID for any newly inserted text, and send message to other peers if needed." (when (markerp beg) (setq beg (marker-position beg))) (when (markerp end) @@ -875,18 +915,25 @@ and send message to other peers if needed." (save-excursion (goto-char beg) (if (and (= length (- end beg)) - (string-equal crdt--changed-string + (string-equal (crdt--changed-string beg length) (buffer-substring-no-properties beg end))) - (crdt--crdt-id-assimilate crdt--changed-string beg) + (crdt--crdt-id-assimilate (crdt--changed-string beg length) beg) (widen) (with-silent-modifications (unless (= length 0) (crdt--broadcast-maybe - (crdt--format-message (crdt--local-delete beg end)))) + (crdt--format-message (crdt--local-delete beg end length)))) (unless (= beg end) (dolist (message (crdt--local-insert beg end)) (crdt--broadcast-maybe - (crdt--format-message message))))))))))) + (crdt--format-message message))))))) + ;; process-mark synchronization is dependent on correct CRDT-ID + ;; therefore we must do it after the insert/change stuff is done + (crdt--send-process-mark-maybe) + ;; see if region stuff changed + (let ((cursor-message (crdt--local-cursor))) + (when cursor-message + (crdt--broadcast-maybe (crdt--format-message cursor-message)))))))) ;;; CRDT point/mark synchronization @@ -957,7 +1004,8 @@ Send message to other peers about any changes." (unless (eq crdt--buffer-network-name (crdt--session-focused-buffer-name crdt--session)) (crdt--broadcast-maybe (crdt--format-message `(focus ,(crdt--session-local-id crdt--session) ,crdt--buffer-network-name))) - (setf (crdt--session-focused-buffer-name crdt--session) crdt--buffer-network-name)) + (setf (crdt--session-focused-buffer-name crdt--session) crdt--buffer-network-name) + (crdt--refresh-users-maybe)) (let ((cursor-message (crdt--local-cursor))) (when cursor-message (crdt--broadcast-maybe (crdt--format-message cursor-message))))) @@ -1016,6 +1064,17 @@ Verify that CRDT IDs in a document follows ascending order." (setq pos next-pos) (setq id next-id)))))) +;;; Recovery + +(defun crdt--client-recover () + "Try to recover from a synchronization failure from a client. +Current buffer is assmuned to be the one with synchronization error." + (ding) + (read-only-mode) + (message "Synchronization error detected, try recovering...") + (crdt--broadcast-maybe + (crdt--format-message `(get ,crdt--buffer-network-name)))) + ;;; Network protocol (defun crdt--format-message (args) @@ -1031,7 +1090,7 @@ If (CRDT--SESSION-NETWORK-PROCESS CRDT--SESSION) is a server process, broadcast MESSAGE-STRING to clients except the one of which CLIENT-ID property is EQ to WITHOUT. If (CRDT--SESSION-NETWORK-PROCESS CRDT--SESSION) is a client process, -send MESSAGE-STRING to server when WITHOUT is T." +send MESSAGE-STRING to server when WITHOUT is non-nil." (when crdt--log-network-traffic (message "Send %s" message-string)) (if (process-contact (crdt--session-network-process crdt--session) :server) @@ -1061,7 +1120,7 @@ The overlay is FRONT-ADVANCE and REAR-ADVANCE, and lies between BEG and END." (base64-encode-string (crdt--get-id end)) (crdt--base64-encode-maybe (crdt--get-id (1- end)))))) -(defun crdt--generate-challenge () +(defsubst crdt--generate-challenge () "Generate a challenge string for authentication." (apply #'unibyte-string (cl-loop for i below 32 collect (random 256)))) @@ -1069,9 +1128,11 @@ The overlay is FRONT-ADVANCE and REAR-ADVANCE, and lies between BEG and END." "Send messages to a client about the full state of BUFFER. The network process for the client connection is PROCESS." (with-current-buffer buffer - (process-send-string process (crdt--format-message `(sync - ,crdt--buffer-network-name - ,@ (crdt--dump-ids (point-min) (point-max) nil nil t)))) + (process-send-string process + (crdt--format-message + `(sync + ,crdt--buffer-network-name + ,@ (crdt--dump-ids (point-min) (point-max) nil nil t)))) ;; synchronize cursor (maphash (lambda (site-id ov-pair) (cl-destructuring-bind (cursor-ov . region-ov) ov-pair @@ -1109,6 +1170,15 @@ The network process for the client connection is PROCESS." ,(car k) ,(cdr k) ,prop ,value)))))) crdt--overlay-table) + ;; synchronize process marker if there's any + (let ((buffer-process (get-buffer-process buffer))) + (when buffer-process + (let ((mark-pos (marker-position (process-mark buffer-process)))) + (process-send-string process + (crdt--format-message + `(process-mark ,crdt--buffer-network-name + ,(crdt--get-id mark-pos) ,mark-pos)))))) + (process-send-string process (crdt--format-message `(ready ,crdt--buffer-network-name ,major-mode))))) (defun crdt--greet-client (process) @@ -1132,19 +1202,23 @@ The network process for the client connection is PROCESS." (cons 'add (hash-table-keys (crdt--session-buffer-table crdt--session))))) ;; synchronize contact (maphash (lambda (k v) - (process-send-string - process (crdt--format-message `(contact ,k ,(crdt--contact-metadata-display-name v) - ,(crdt--contact-metadata-host v) - ,(crdt--contact-metadata-service v)))) - (process-send-string - process (crdt--format-message `(focus ,k ,(crdt--contact-metadata-focused-buffer-name v))))) + (process-send-string process + (crdt--format-message + `(contact ,k ,(crdt--contact-metadata-display-name v) + ,(crdt--contact-metadata-host v) + ,(crdt--contact-metadata-service v)))) + (process-send-string process + (crdt--format-message + `(focus ,k ,(crdt--contact-metadata-focused-buffer-name v))))) (crdt--session-contact-table crdt--session)) (process-send-string process - (crdt--format-message `(contact ,(crdt--session-local-id crdt--session) - ,(crdt--session-local-name crdt--session)))) + (crdt--format-message + `(contact ,(crdt--session-local-id crdt--session) + ,(crdt--session-local-name crdt--session)))) (process-send-string process - (crdt--format-message `(focus ,(crdt--session-local-id crdt--session) - ,(crdt--session-focused-buffer-name crdt--session)))) + (crdt--format-message + `(focus ,(crdt--session-local-id crdt--session) + ,(crdt--session-focused-buffer-name crdt--session)))) (let ((contact-message `(contact ,client-id ,(process-get process 'client-name) ,(process-contact process :host) ,(process-contact process :service)))) @@ -1195,6 +1269,7 @@ The network process for the client connection is PROCESS." (cl-destructuring-bind (buffer-name . ids) (cdr message) (crdt--with-buffer-name buffer-name + (read-only-mode -1) (let ((crdt--inhibit-update t)) (unless crdt--buffer-sync-callback ;; try to get to the same position after sync, @@ -1301,7 +1376,8 @@ Handle received STRING from PROCESS." (unless (and (process-buffer process) (buffer-live-p (process-buffer process))) (set-process-buffer process (generate-new-buffer "*crdt-server*")) - (set-marker (process-mark process) 1)) + (with-current-buffer (process-buffer process) + (set-marker (process-mark process) 1))) (with-current-buffer (process-buffer process) (unless crdt--session (setq crdt--session (process-get process 'crdt-session))) @@ -1336,7 +1412,8 @@ Handle received STRING from PROCESS." (error (message "%s error when processing message from %s:%s, disconnecting." err (process-contact process :host) (process-contact process :service)) (if (crdt--server-p) - (delete-process process) + (progn + (delete-process process)) (crdt--stop-session crdt--session)))))) (delete-region (point-min) (point)) (goto-char (point-min))))))) @@ -1365,6 +1442,7 @@ Handle received STRING from PROCESS." (unless (eq (process-status process) 'open) (when (process-get process 'tuntox-process) (process-send-string process (crdt--format-message '(leave)))) + (ding) (crdt--stop-session (process-get process 'crdt-session)))) ;;; UI commands @@ -1417,10 +1495,12 @@ Otherwise, return the list of names for client sessions." (cl-find name crdt--session-list :test 'equal :key #'crdt--session-name)) -(defun crdt-share-buffer (session-name) +(defun crdt-share-buffer (session-name &optional port) "Share the current buffer in the CRDT session with name SESSION-NAME. -Create a new one if such a CRDT session doesn't exist. -If SESSION-NAME is empty, use the buffer name of the current buffer." +Create a new one if such a CRDT session doesn't exist. When PORT +is non-NIL use when creating a new session, otherwise prompt +from minibuffer. If SESSION-NAME is empty, use the buffer name +of the current buffer." (interactive (progn (when (and crdt-mode crdt--session) @@ -1438,7 +1518,7 @@ If SESSION-NAME is empty, use the buffer name of the current buffer." (let ((session (crdt--get-session session-name))) (if session (crdt--share-buffer (current-buffer) session) - (let ((port (read-from-minibuffer "Create new session on port (default 6530): " nil nil t nil "6530"))) + (let ((port (or port (read-from-minibuffer "Create new session on port (default 6530): " nil nil t nil "6530")))) (when (not (numberp port)) (error "Port must be a number")) (crdt--share-buffer (current-buffer) (crdt-new-session port session-name)))))) @@ -1504,7 +1584,7 @@ Setup up the server with PASSWORD and assign this Emacs DISPLAY-NAME." (defun crdt--stop-session (session) "Kill the CRDT SESSION. Disconnect if it's a client session, or stop serving if it's a server session." - (when (if (and crdt-confirm-stop-session + (when (if (and crdt-confirm-disconnect (crdt--server-p session) (crdt--session-network-clients session)) (yes-or-no-p "There are yet connected clients. Stop session? ") @@ -1528,10 +1608,14 @@ Disconnect if it's a client session, or stop serving if it's a server session." (setq crdt--session-list (delq session crdt--session-list)) (crdt--refresh-sessions-maybe) - (let ((proxy-process (process-get (crdt--session-network-process session) 'tuntox-process))) + (let* ((process (crdt--session-network-process session)) + (proxy-process (process-get process 'tuntox-process)) + (process-buffer (process-buffer process))) + (delete-process (crdt--session-network-process session)) + (when (and process-buffer (buffer-live-p process-buffer)) + (kill-buffer process-buffer)) (when (and proxy-process (process-live-p proxy-process)) (interrupt-process proxy-process))) - (delete-process (crdt--session-network-process session)) (message "Disconnected."))) (defun crdt-stop-session (&optional session-name) @@ -1761,7 +1845,7 @@ Join with DISPLAY-NAME." (crdt--base64-encode-maybe (crdt--get-id (1- end)))))))))))) (apply orig-fun ov beg end args)) -(cl-defmethod crdt-process-message ((message (head overlay-move)) process) +(cl-defmethod crdt-process-message ((message (head overlay-move)) _process) (cl-destructuring-bind (buffer-name site-id logical-clock start-hint start-id-base64 end-hint end-id-base64) (cdr message) @@ -1777,7 +1861,7 @@ Join with DISPLAY-NAME." (end (crdt--find-id (base64-decode-string end-id-base64) end-hint rear-advance))) (let ((crdt--inhibit-overlay-advices t)) (move-overlay ov start end))))))) - (crdt--broadcast-maybe (crdt--format-message message) (process-get process 'client-id))) + (crdt--broadcast-maybe (crdt--format-message message) nil)) (defun crdt--delete-overlay-advice (orig-fun ov) (unless crdt--inhibit-overlay-advices @@ -1832,7 +1916,7 @@ Join with DISPLAY-NAME." (when (memq (crdt--overlay-metadata-species meta) crdt--enabled-overlay-species) (let ((crdt--inhibit-overlay-advices t)) (overlay-put ov prop value)))))))) - (crdt--broadcast-maybe (crdt--format-message message) (process-get process 'client-id))) + (crdt--broadcast-maybe (crdt--format-message message) nil)) (advice-add 'make-overlay :around #'crdt--make-overlay-advice) @@ -1867,5 +1951,126 @@ Join with DISPLAY-NAME." (cl-loop for command in '(org-cycle org-shifttab) do (advice-add command :around #'crdt--org-overlay-advice)) +;;; pseudo process +(cl-defstruct (crdt--pseudo-process (:constructor crdt--make-pseudo-process)) + buffer + mark) + +(defun crdt--pseudo-process-send-string (pseudo-process string) + (with-current-buffer (crdt--pseudo-process-buffer pseudo-process) + (crdt--broadcast-maybe (crdt--format-message + `(process ,crdt--buffer-network-name ,string))))) + +(defun crdt--process-send-string-advice (orig-func process string) + (if (crdt--pseudo-process-p process) + (crdt--pseudo-process-send-string process string) + (funcall orig-func process string))) + +(defun crdt--process-send-region-advice (orig-func process start end) + (if (crdt--pseudo-process-p process) + (crdt--pseudo-process-send-string process (buffer-substring-no-properties start end)) + (funcall orig-func process start end))) + +(defun crdt--get-buffer-process-advice (orig-func buffer) + (and buffer + (setq buffer (get-buffer buffer)) + (with-current-buffer buffer + (if (and crdt--session (not (crdt--server-p))) + crdt--buffer-pseudo-process + (funcall orig-func buffer))))) + +(defun crdt--get-process-advice (orig-func name) + (if (crdt--pseudo-process-p name) + name + (funcall orig-func name))) + +(defun crdt--process-mark-advice (orig-func process) + (if (crdt--pseudo-process-p process) + (crdt--pseudo-process-mark process) + (funcall orig-func process))) + +(defun crdt--process-name-advice (orig-func process) + (if (crdt--pseudo-process-p process) + process + (funcall orig-func process))) + +(cl-defmethod crdt-process-message ((message (head process-mark)) process) + (cl-destructuring-bind (buffer-name crdt-id position-hint) (cdr message) + (crdt--with-buffer-name + buffer-name + (save-excursion + (goto-char (crdt--id-to-pos crdt-id position-hint)) + (let ((buffer-process (get-buffer-process (current-buffer)))) + (if buffer-process + (progn (set-marker (process-mark buffer-process) (point)) + (setq crdt--last-process-mark-id crdt-id) + (crdt--broadcast-maybe (crdt--format-message message) nil)) + (unless (crdt--server-p) + (setq crdt--buffer-pseudo-process + (crdt--make-pseudo-process :buffer (current-buffer) :mark (point-marker))) + (setq crdt--last-process-mark-id crdt-id)))))))) + +(defun crdt--send-process-mark-maybe () + (let ((buffer-process (get-buffer-process (current-buffer)))) + (when buffer-process + (let* ((mark-pos (marker-position (process-mark buffer-process))) + (current-id (crdt--get-id mark-pos))) + (unless (string-equal crdt--last-process-mark-id current-id) + (setq crdt--last-process-mark-id current-id) + (crdt--broadcast-maybe + (crdt--format-message + `(process-mark ,crdt--buffer-network-name + ,current-id ,mark-pos)))))))) + +(defun crdt--process-status-advice (orig-func process) + (if (crdt--pseudo-process-p process) + 'run + (funcall orig-func process))) + +(defun crdt--delete-process-advice (orig-func process) + (unless (crdt--pseudo-process-p process) + (funcall orig-func process))) + +(defun crdt--process-buffer-advice (orig-func process) + (if (crdt--pseudo-process-p process) + (crdt--pseudo-process-buffer process) + (funcall orig-func process))) + +(defun crdt--processp-advice (orig-func object) + (or (crdt--pseudo-process-p object) (funcall orig-func object))) + +(defun crdt--dummy () nil) + +(defun crdt--process-sentinel/filter-advice (orig-func process) + (if (crdt--pseudo-process-p process) + #'crdt--dummy + (funcall orig-func process))) + +(defun crdt--set-process-sentinel/filter-advice (orig-func process func) + (if (crdt--pseudo-process-p process) + nil + (funcall orig-func process func))) + +(advice-add 'process-send-string :around #'crdt--process-send-string-advice) +(advice-add 'process-send-region :around #'crdt--process-send-region-advice) +(advice-add 'processp :around #'crdt--processp-advice) +(advice-add 'get-buffer-process :around #'crdt--get-buffer-process-advice) +(advice-add 'get-process :around #'crdt--get-process-advice) +(advice-add 'process-status :around #'crdt--process-status-advice) +(advice-add 'process-buffer :around #'crdt--process-buffer-advice) +(advice-add 'process-mark :around #'crdt--process-mark-advice) +(advice-add 'delete-process :around #'crdt--delete-process-advice) +(advice-add 'process-name :around #'crdt--process-name-advice) +(advice-add 'process-sentinel :around #'crdt--process-sentinel/filter-advice) +(advice-add 'process-filter :around #'crdt--process-sentinel/filter-advice) +(advice-add 'set-process-sentinel :around #'crdt--set-process-sentinel/filter-advice) +(advice-add 'set-process-filter :around #'crdt--set-process-sentinel/filter-advice) + +(cl-defmethod crdt-process-message ((message (head process)) process) + (cl-destructuring-bind (buffer-name string) (cdr message) + (crdt--with-buffer-name + buffer-name + (process-send-string (get-buffer-process (current-buffer)) string)))) + (provide 'crdt) ;;; crdt.el ends here diff --git a/lisp/dash/dash-pkg.el b/lisp/dash/dash-pkg.el index 08d89823..cbeb204e 100644 --- a/lisp/dash/dash-pkg.el +++ b/lisp/dash/dash-pkg.el @@ -1,9 +1,12 @@ -(define-package "dash" "20200524.1947" "A modern list library for Emacs" 'nil :commit "732d92eac56023a4fb4a5dc3d9d4e274ebf44bf9" :keywords - '("lists") - :authors +(define-package "dash" "20210106.2158" "A modern list library for Emacs" + '((emacs "24")) + :commit "b3c58ffdb1739d601bc388cc7c7a9e7bd8e753f5" :authors '(("Magnar Sveen" . "magnars@gmail.com")) :maintainer - '("Magnar Sveen" . "magnars@gmail.com")) + '("Magnar Sveen" . "magnars@gmail.com") + :keywords + '("extensions" "lisp") + :url "https://github.com/magnars/dash.el") ;; Local Variables: ;; no-byte-compile: t ;; End: diff --git a/lisp/dash/dash.el b/lisp/dash/dash.el index 1fc2ec83..2303681f 100644 --- a/lisp/dash/dash.el +++ b/lisp/dash/dash.el @@ -1,12 +1,14 @@ ;;; dash.el --- A modern list library for Emacs -*- lexical-binding: t -*- -;; Copyright (C) 2012-2016 Free Software Foundation, Inc. +;; Copyright (C) 2012-2021 Free Software Foundation, Inc. ;; Author: Magnar Sveen ;; Version: 2.17.0 -;; Keywords: lists +;; Package-Requires: ((emacs "24")) +;; Keywords: extensions, lisp +;; Homepage: https://github.com/magnars/dash.el -;; This program is free software; you can redistribute it and/or modify +;; 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. @@ -17,19 +19,13 @@ ;; 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: -;; A modern list api for Emacs. -;; -;; See documentation on https://github.com/magnars/dash.el#functions -;; -;; **Please note** The lexical binding in this file is not utilised at the -;; moment. We will take full advantage of lexical binding in an upcoming 3.0 -;; release of Dash. In the meantime, we've added the pragma to avoid a bug that -;; you can read more about in https://github.com/magnars/dash.el/issues/130. +;; A modern list API for Emacs. ;; +;; See its overview at https://github.com/magnars/dash.el#functions. ;;; Code: @@ -40,22 +36,11 @@ (require 'cl))) (defgroup dash () - "Customize group for dash.el" + "Customize group for Dash, a modern list library." + :group 'extensions :group 'lisp :prefix "dash-") -(defun dash--enable-fontlock (symbol value) - (when value - (dash-enable-font-lock)) - (set-default symbol value)) - -(defcustom dash-enable-fontlock nil - "If non-nil, enable fontification of dash functions, macros and -special values." - :type 'boolean - :set 'dash--enable-fontlock - :group 'dash) - (defmacro !cons (car cdr) "Destructive: Set CDR to the cons of CAR and CDR." `(setq ,cdr (cons ,car ,cdr))) @@ -65,148 +50,171 @@ special values." `(setq ,list (cdr ,list))) (defmacro --each (list &rest body) - "Anaphoric form of `-each'." - (declare (debug (form body)) - (indent 1)) - (let ((l (make-symbol "list"))) + "Evaluate BODY for each element of LIST and return nil. +Each element of LIST in turn is bound to `it' and its index +within LIST to `it-index' before evaluating BODY. +This is the anaphoric counterpart to `-each'." + (declare (debug (form body)) (indent 1)) + (let ((l (make-symbol "list")) + (i (make-symbol "i"))) `(let ((,l ,list) - (it-index 0)) + (,i 0) + it it-index) + (ignore it it-index) (while ,l - (let ((it (car ,l))) - ,@body) - (setq it-index (1+ it-index)) - (!cdr ,l))))) - -(defmacro -doto (eval-initial-value &rest forms) - "Eval a form, then insert that form as the 2nd argument to other forms. -The EVAL-INITIAL-VALUE form is evaluated once. Its result is -passed to FORMS, which are then evaluated sequentially. Returns -the target form." - (declare (indent 1)) - (let ((retval (make-symbol "value"))) - `(let ((,retval ,eval-initial-value)) - ,@(mapcar (lambda (form) - (if (sequencep form) - `(,(-first-item form) ,retval ,@(cdr form)) - `(funcall form ,retval))) - forms) - ,retval))) - -(defmacro --doto (eval-initial-value &rest forms) - "Anaphoric form of `-doto'. -Note: `it' is not required in each form." - (declare (indent 1)) - `(let ((it ,eval-initial-value)) - ,@forms - it)) + (setq it (pop ,l) it-index ,i ,i (1+ ,i)) + ,@body)))) (defun -each (list fn) - "Call FN with every item in LIST. Return nil, used for side-effects only." - (--each list (funcall fn it))) - -(put '-each 'lisp-indent-function 1) + "Call FN on each element of LIST. +Return nil; this function is intended for side effects. +Its anaphoric counterpart is `--each'. For access to the current +element's index in LIST, see `-each-indexed'." + (declare (indent 1)) + (ignore (mapc fn list))) (defalias '--each-indexed '--each) (defun -each-indexed (list fn) - "Call (FN index item) for each item in LIST. - -In the anaphoric form `--each-indexed', the index is exposed as symbol `it-index'. - + "Call FN on each index and element of LIST. +For each ITEM at INDEX in LIST, call (funcall FN INDEX ITEM). +Return nil; this function is intended for side effects. See also: `-map-indexed'." + (declare (indent 1)) (--each list (funcall fn it-index it))) -(put '-each-indexed 'lisp-indent-function 1) (defmacro --each-while (list pred &rest body) - "Anaphoric form of `-each-while'." - (declare (debug (form form body)) - (indent 2)) + "Evaluate BODY for each item in LIST, while PRED evaluates to non-nil. +Each element of LIST in turn is bound to `it' and its index +within LIST to `it-index' before evaluating PRED or BODY. Once +an element is reached for which PRED evaluates to nil, no further +BODY is evaluated. The return value is always nil. +This is the anaphoric counterpart to `-each-while'." + (declare (debug (form form body)) (indent 2)) (let ((l (make-symbol "list")) - (c (make-symbol "continue"))) + (i (make-symbol "i")) + (elt (make-symbol "elt"))) `(let ((,l ,list) - (,c t) - (it-index 0)) - (while (and ,l ,c) - (let ((it (car ,l))) - (if (not ,pred) (setq ,c nil) ,@body)) - (setq it-index (1+ it-index)) - (!cdr ,l))))) + (,i 0) + ,elt it it-index) + (ignore it it-index) + (while (and ,l (setq ,elt (pop ,l) it ,elt it-index ,i) ,pred) + (setq it ,elt it-index ,i ,i (1+ ,i)) + ,@body)))) (defun -each-while (list pred fn) - "Call FN with every item in LIST while (PRED item) is non-nil. -Return nil, used for side-effects only." + "Call FN on each ITEM in LIST, while (PRED ITEM) is non-nil. +Once an ITEM is reached for which PRED returns nil, FN is no +longer called. Return nil; this function is intended for side +effects. +Its anaphoric counterpart is `--each-while'." + (declare (indent 2)) (--each-while list (funcall pred it) (funcall fn it))) -(put '-each-while 'lisp-indent-function 2) - (defmacro --each-r (list &rest body) - "Anaphoric form of `-each-r'." - (declare (debug (form body)) - (indent 1)) - (let ((v (make-symbol "vector"))) - ;; Implementation note: building vector is considerably faster + "Evaluate BODY for each element of LIST in reversed order. +Each element of LIST in turn, starting at its end, is bound to +`it' and its index within LIST to `it-index' before evaluating +BODY. The return value is always nil. +This is the anaphoric counterpart to `-each-r'." + (declare (debug (form body)) (indent 1)) + (let ((v (make-symbol "vector")) + (i (make-symbol "i"))) + ;; Implementation note: building a vector is considerably faster ;; than building a reversed list (vector takes less memory, so - ;; there is less GC), plus length comes naturally. In-place - ;; 'nreverse' would be faster still, but BODY would be able to see - ;; that, even if modification was reversed before we return. + ;; there is less GC), plus `length' comes naturally. In-place + ;; `nreverse' would be faster still, but BODY would be able to see + ;; that, even if the modification was undone before we return. `(let* ((,v (vconcat ,list)) - (it-index (length ,v)) - it) - (while (> it-index 0) - (setq it-index (1- it-index)) - (setq it (aref ,v it-index)) + (,i (length ,v)) + it it-index) + (ignore it it-index) + (while (> ,i 0) + (setq ,i (1- ,i) it-index ,i it (aref ,v ,i)) ,@body)))) (defun -each-r (list fn) - "Call FN with every item in LIST in reversed order. - Return nil, used for side-effects only." + "Call FN on each element of LIST in reversed order. +Return nil; this function is intended for side effects. +Its anaphoric counterpart is `--each-r'." (--each-r list (funcall fn it))) (defmacro --each-r-while (list pred &rest body) - "Anaphoric form of `-each-r-while'." - (declare (debug (form form body)) - (indent 2)) - (let ((v (make-symbol "vector"))) + "Eval BODY for each item in reversed LIST, while PRED evals to non-nil. +Each element of LIST in turn, starting at its end, is bound to +`it' and its index within LIST to `it-index' before evaluating +PRED or BODY. Once an element is reached for which PRED +evaluates to nil, no further BODY is evaluated. The return value +is always nil. +This is the anaphoric counterpart to `-each-r-while'." + (declare (debug (form form body)) (indent 2)) + (let ((v (make-symbol "vector")) + (i (make-symbol "i")) + (elt (make-symbol "elt"))) `(let* ((,v (vconcat ,list)) - (it-index (length ,v)) - it) - (while (> it-index 0) - (setq it-index (1- it-index)) - (setq it (aref ,v it-index)) - (if (not ,pred) - (setq it-index -1) - ,@body))))) + (,i (length ,v)) + ,elt it it-index) + (ignore it it-index) + (while (when (> ,i 0) + (setq ,i (1- ,i) it-index ,i) + (setq ,elt (aref ,v ,i) it ,elt) + ,pred) + (setq it-index ,i it ,elt) + ,@body)))) (defun -each-r-while (list pred fn) - "Call FN with every item in reversed LIST while (PRED item) is non-nil. -Return nil, used for side-effects only." + "Call FN on each ITEM in reversed LIST, while (PRED ITEM) is non-nil. +Once an ITEM is reached for which PRED returns nil, FN is no +longer called. Return nil; this function is intended for side +effects. +Its anaphoric counterpart is `--each-r-while'." (--each-r-while list (funcall pred it) (funcall fn it))) (defmacro --dotimes (num &rest body) - "Repeatedly executes BODY (presumably for side-effects) with symbol `it' bound to integers from 0 through NUM-1." - (declare (debug (form body)) - (indent 1)) - (let ((n (make-symbol "num"))) + "Evaluate BODY NUM times, presumably for side effects. +BODY is evaluated with the local variable `it' temporarily bound +to successive integers running from 0, inclusive, to NUM, +exclusive. BODY is not evaluated if NUM is less than 1. +This is the anaphoric counterpart to `-dotimes'." + (declare (debug (form body)) (indent 1)) + (let ((n (make-symbol "num")) + (i (make-symbol "i"))) `(let ((,n ,num) - (it 0)) - (while (< it ,n) - ,@body - (setq it (1+ it)))))) + (,i 0) + it) + (ignore it) + (while (< ,i ,n) + (setq it ,i ,i (1+ ,i)) + ,@body)))) (defun -dotimes (num fn) - "Repeatedly calls FN (presumably for side-effects) passing in integers from 0 through NUM-1." + "Call FN NUM times, presumably for side effects. +FN is called with a single argument on successive integers +running from 0, inclusive, to NUM, exclusive. FN is not called +if NUM is less than 1. +This function's anaphoric counterpart is `--dotimes'." + (declare (indent 1)) (--dotimes num (funcall fn it))) -(put '-dotimes 'lisp-indent-function 1) - (defun -map (fn list) - "Return a new list consisting of the result of applying FN to the items in LIST." + "Apply FN to each item in LIST and return the list of results. +This function's anaphoric counterpart is `--map'." (mapcar fn list)) (defmacro --map (form list) - "Anaphoric form of `-map'." + "Eval FORM for each item in LIST and return the list of results. +Each element of LIST in turn is bound to `it' before evaluating +BODY. +This is the anaphoric counterpart to `-map'." (declare (debug (form form))) - `(mapcar (lambda (it) ,form) ,list)) + (let ((l (make-symbol "list")) + (r (make-symbol "res"))) + `(let ((,l ,list) ,r it) + (ignore it) + (while ,l + (setq it (pop ,l)) + (push ,form ,r)) + (nreverse ,r)))) (defmacro --reduce-from (form initial-value list) "Anaphoric form of `-reduce-from'." @@ -530,6 +538,26 @@ See also: `-map-last'" Thus function FN should return a list." (--mapcat (funcall fn it) list)) +(defmacro --iterate (form init n) + "Anaphoric version of `-iterate'." + (declare (debug (form form form))) + (let ((res (make-symbol "result"))) + `(let ((it ,init) ,res) + (dotimes (_ ,n) + (push it ,res) + (setq it ,form)) + (nreverse ,res)))) + +(defun -iterate (fun init n) + "Return a list of iterated applications of FUN to INIT. + +This means a list of the form: + + (INIT (FUN INIT) (FUN (FUN INIT)) ...) + +N is the length of the returned list." + (--iterate (funcall fun it) init n)) + (defun -flatten (l) "Take a nested list L and return its contents as a single, flat list. @@ -547,11 +575,6 @@ See also: `-flatten-n'" (-mapcat '-flatten l) (list l))) -(defmacro --iterate (form init n) - "Anaphoric version of `-iterate'." - (declare (debug (form form form))) - `(-iterate (lambda (it) ,form) ,init ,n)) - (defun -flatten-n (num list) "Flatten NUM levels of a nested LIST. @@ -847,50 +870,21 @@ section is returned. Defaults to 1." (push it new-list))) (nreverse new-list))) -(defun -take (n list) - "Return a new list of the first N items in LIST, or all items if there are fewer than N. - -See also: `-take-last'" - (declare (pure t) (side-effect-free t)) - (let (result) - (--dotimes n - (when list - (!cons (car list) result) - (!cdr list))) - (nreverse result))) - -(defun -take-last (n list) - "Return the last N items of LIST in order. - -See also: `-take'" - (declare (pure t) (side-effect-free t)) - (copy-sequence (last list n))) - -(defalias '-drop 'nthcdr - "Return the tail of LIST without the first N items. - -See also: `-drop-last' - -\(fn N LIST)") - -(defun -drop-last (n list) - "Remove the last N items of LIST and return a copy. - -See also: `-drop'" - ;; No alias because we don't want magic optional argument - (declare (pure t) (side-effect-free t)) - (butlast list n)) - (defmacro --take-while (form list) "Anaphoric form of `-take-while'." (declare (debug (form form))) (let ((r (make-symbol "result"))) `(let (,r) - (--each-while ,list ,form (!cons it ,r)) + (--each-while ,list ,form (push it ,r)) (nreverse ,r)))) (defun -take-while (pred list) - "Return a new list of successive items from LIST while (PRED item) returns a non-nil value." + "Take successive items from LIST for which PRED returns non-nil. +PRED is a function of one argument. Return a new list of the +successive elements from the start of LIST for which PRED returns +non-nil. + +See also: `-drop-while'" (--take-while (funcall pred it) list)) (defmacro --drop-while (form list) @@ -898,14 +892,52 @@ See also: `-drop'" (declare (debug (form form))) (let ((l (make-symbol "list"))) `(let ((,l ,list)) - (while (and ,l (let ((it (car ,l))) ,form)) - (!cdr ,l)) - ,l))) + (--each-while ,l ,form (pop ,l)) + (copy-sequence ,l)))) (defun -drop-while (pred list) - "Return the tail of LIST starting from the first item for which (PRED item) returns nil." + "Drop successive items from LIST for which PRED returns non-nil. +PRED is a function of one argument. Return a copy of the tail of +LIST starting from its first element for which PRED returns nil. + +See also: `-take-while'" (--drop-while (funcall pred it) list)) +(defun -take (n list) + "Return a copy of the first N items in LIST. +Return a copy of LIST if it contains N items or fewer. +Return nil if N is zero or less. + +See also: `-take-last'" + (declare (pure t) (side-effect-free t)) + (--take-while (< it-index n) list)) + +(defun -take-last (n list) + "Return a copy of the last N items of LIST in order. +Return a copy of LIST if it contains N items or fewer. +Return nil if N is zero or less. + +See also: `-take'" + (declare (pure t) (side-effect-free t)) + (copy-sequence (last list n))) + +(defun -drop (n list) + "Return a copy of the tail of LIST without the first N items. +Return a copy of LIST if N is zero or less. +Return nil if LIST contains N items or fewer. + +See also: `-drop-last'" + (copy-sequence (nthcdr n list))) + +(defun -drop-last (n list) + "Return a copy of LIST without its last N items. +Return a copy of LIST if N is zero or less. +Return nil if LIST contains N items or fewer. + +See also: `-drop'" + (declare (pure t) (side-effect-free t)) + (nbutlast (copy-sequence list) n)) + (defun -split-at (n list) "Return a list of ((-take N LIST) (-drop N LIST)), in no more than one pass through the list." (declare (pure t) (side-effect-free t)) @@ -1334,10 +1366,12 @@ See also: `-zip'" (apply '-zip lists)) (defun -cycle (list) - "Return an infinite copy of LIST that will cycle through the -elements and repeat from the beginning." + "Return an infinite circular copy of LIST. +The returned list cycles through the elements of LIST and repeats +from the beginning." (declare (pure t) (side-effect-free t)) - (let ((newlist (-map 'identity list))) + ;; Also works with sequences that aren't lists. + (let ((newlist (append list ()))) (nconc newlist newlist))) (defun -pad (fill-value &rest lists) @@ -1581,7 +1615,7 @@ and when that result is non-nil, through the next form, etc." ,@more)))) (defmacro -some--> (x &optional form &rest more) - "When expr in non-nil, thread it through the first form (via `-->'), + "When expr is non-nil, thread it through the first form (via `-->'), and when that result is non-nil, through the next form, etc." (declare (debug ->) (indent 1)) @@ -1591,6 +1625,27 @@ and when that result is non-nil, through the next form, etc." (--> ,result ,form)) ,@more)))) +(defmacro -doto (init &rest forms) + "Evaluate INIT and pass it as argument to FORMS with `->'. +The RESULT of evaluating INIT is threaded through each of FORMS +individually using `->', which see. The return value is RESULT, +which FORMS may have modified by side effect." + (declare (debug (form body)) (indent 1)) + (let ((retval (make-symbol "result"))) + `(let ((,retval ,init)) + ,@(mapcar (lambda (form) `(-> ,retval ,form)) forms) + ,retval))) + +(defmacro --doto (init &rest forms) + "Anaphoric form of `-doto'. +This just evaluates INIT, binds the result to `it', evaluates +FORMS, and returns the final value of `it'. +Note: `it' need not be used in each form." + (declare (debug (form body)) (indent 1)) + `(let ((it ,init)) + ,@forms + it)) + (defun -grade-up (comparator list) "Grade elements of LIST using COMPARATOR relation, yielding a permutation vector such that applying this permutation to LIST @@ -1717,17 +1772,6 @@ SOURCE is a proper or improper list." (t ;; Handle improper lists. Last matching place, no need for shift (dash--match match-form (dash--match-cons-get-cdr skip-cdr source)))))) -(defun dash--vector-tail (seq start) - "Return the tail of SEQ starting at START." - (cond - ((vectorp seq) - (let* ((re-length (- (length seq) start)) - (re (make-vector re-length 0))) - (--dotimes re-length (aset re it (aref seq (+ it start)))) - re)) - ((stringp seq) - (substring seq start)))) - (defun dash--match-vector (match-form source) "Setup a vector matching environment and call the real matcher." (let ((s (dash--match-make-source-symbol))) @@ -1775,7 +1819,7 @@ is discarded." (eq m '&rest)) (prog1 (dash--match (aref match-form (1+ i)) - `(dash--vector-tail ,source ,i)) + `(substring ,source ,i)) (setq i l))) ((and (symbolp m) ;; do not match symbols starting with _ @@ -1926,7 +1970,7 @@ Key-value stores are disambiguated by placing a token &plist, (eq '&as (aref match-form 1))) (let ((s (aref match-form 0))) (cons (list s source) - (dash--match (dash--vector-tail match-form 2) s)))) + (dash--match (substring match-form 2) s)))) (t (dash--match-vector match-form source)))))) (defun dash--normalize-let-varlist (varlist) @@ -1978,11 +2022,11 @@ If VARLIST only contains one (PATTERN SOURCE) element, you can optionally specify it using a vector and discarding the outer-most parens. Thus - (-let ((PATTERN SOURCE)) ..) + (-let ((PATTERN SOURCE)) ...) becomes - (-let [PATTERN SOURCE] ..). + (-let [PATTERN SOURCE] ...). `-let' uses a convention of not binding places (symbols) starting with _ whenever it's possible. You can use this to skip over @@ -2007,7 +2051,7 @@ Conses and lists: (a b) - bind car of list to A and `cadr' to B - (a1 a2 a3 ...) - bind 0th car of list to A1, 1st to A2, 2nd to A3 ... + (a1 a2 a3 ...) - bind 0th car of list to A1, 1st to A2, 2nd to A3... (a1 a2 a3 ... aN . rest) - as above, but bind the Nth cdr to REST. @@ -2471,21 +2515,17 @@ if the first element should sort before the second." `(-sort (lambda (it other) ,form) ,list)) (defun -list (&rest args) - "Return a list with ARGS. - -If first item of ARGS is already a list, simply return ARGS. If -not, return a list with ARGS as elements." + "Return a list based on ARGS. +If the first item of ARGS is already a list, simply return it. +Otherwise, return a list with ARGS as elements." (declare (pure t) (side-effect-free t)) - (let ((arg (car args))) - (if (listp arg) arg args))) + (if (listp (car args)) (car args) args)) (defun -repeat (n x) - "Return a list with X repeated N times. + "Return a new list of length N with each element being X. Return nil if N is less than 1." (declare (pure t) (side-effect-free t)) - (let (ret) - (--dotimes n (!cons x ret)) - ret)) + (and (natnump n) (make-list n x))) (defun -sum (list) "Return the sum of LIST." @@ -2555,20 +2595,6 @@ The items for the comparator form are exposed as \"it\" and \"other\"." (declare (debug (form form))) `(-min-by (lambda (it other) ,form) ,list)) -(defun -iterate (fun init n) - "Return a list of iterated applications of FUN to INIT. - -This means a list of form: - - (init (fun init) (fun (fun init)) ...) - -N is the length of the returned list." - (if (= n 0) nil - (let ((r (list init))) - (--dotimes (1- n) - (push (funcall fun (car r)) r)) - (nreverse r)))) - (defun -fix (fn list) "Compute the (least) fixpoint of FN with initial input LIST. @@ -2775,298 +2801,157 @@ structure such as plist or alist." (declare (pure t) (side-effect-free t)) (-tree-map 'identity list)) -(defun dash-enable-font-lock () - "Add syntax highlighting to dash functions, macros and magic values." - (eval-after-load 'lisp-mode - '(progn - (let ((new-keywords '( - "!cons" - "!cdr" - "-each" - "--each" - "-each-indexed" - "--each-indexed" - "-each-while" - "--each-while" - "-doto" - "-dotimes" - "--dotimes" - "-map" - "--map" - "-reduce-from" - "--reduce-from" - "-reduce" - "--reduce" - "-reduce-r-from" - "--reduce-r-from" - "-reduce-r" - "--reduce-r" - "-reductions-from" - "-reductions-r-from" - "-reductions" - "-reductions-r" - "-filter" - "--filter" - "-select" - "--select" - "-remove" - "--remove" - "-reject" - "--reject" - "-remove-first" - "--remove-first" - "-reject-first" - "--reject-first" - "-remove-last" - "--remove-last" - "-reject-last" - "--reject-last" - "-remove-item" - "-non-nil" - "-keep" - "--keep" - "-map-indexed" - "--map-indexed" - "-splice" - "--splice" - "-splice-list" - "--splice-list" - "-map-when" - "--map-when" - "-replace-where" - "--replace-where" - "-map-first" - "--map-first" - "-map-last" - "--map-last" - "-replace" - "-replace-first" - "-replace-last" - "-flatten" - "-flatten-n" - "-concat" - "-mapcat" - "--mapcat" - "-copy" - "-cons*" - "-snoc" - "-first" - "--first" - "-find" - "--find" - "-some" - "--some" - "-any" - "--any" - "-last" - "--last" - "-first-item" - "-second-item" - "-third-item" - "-fourth-item" - "-fifth-item" - "-last-item" - "-butlast" - "-count" - "--count" - "-any?" - "--any?" - "-some?" - "--some?" - "-any-p" - "--any-p" - "-some-p" - "--some-p" - "-some->" - "-some->>" - "-some-->" - "-all?" - "-all-p" - "--all?" - "--all-p" - "-every?" - "--every?" - "-all-p" - "--all-p" - "-every-p" - "--every-p" - "-none?" - "--none?" - "-none-p" - "--none-p" - "-only-some?" - "--only-some?" - "-only-some-p" - "--only-some-p" - "-slice" - "-take" - "-drop" - "-drop-last" - "-take-last" - "-take-while" - "--take-while" - "-drop-while" - "--drop-while" - "-split-at" - "-rotate" - "-insert-at" - "-replace-at" - "-update-at" - "--update-at" - "-remove-at" - "-remove-at-indices" - "-split-with" - "--split-with" - "-split-on" - "-split-when" - "--split-when" - "-separate" - "--separate" - "-partition-all-in-steps" - "-partition-in-steps" - "-partition-all" - "-partition" - "-partition-after-item" - "-partition-after-pred" - "-partition-before-item" - "-partition-before-pred" - "-partition-by" - "--partition-by" - "-partition-by-header" - "--partition-by-header" - "-group-by" - "--group-by" - "-interpose" - "-interleave" - "-unzip" - "-zip-with" - "--zip-with" - "-zip" - "-zip-fill" - "-zip-lists" - "-zip-pair" - "-cycle" - "-pad" - "-annotate" - "--annotate" - "-table" - "-table-flat" - "-partial" - "-elem-index" - "-elem-indices" - "-find-indices" - "--find-indices" - "-find-index" - "--find-index" - "-find-last-index" - "--find-last-index" - "-select-by-indices" - "-select-columns" - "-select-column" - "-grade-up" - "-grade-down" - "->" - "->>" - "-->" - "-as->" - "-when-let" - "-when-let*" - "--when-let" - "-if-let" - "-if-let*" - "--if-let" - "-let*" - "-let" - "-lambda" - "-distinct" - "-uniq" - "-union" - "-intersection" - "-difference" - "-powerset" - "-permutations" - "-inits" - "-tails" - "-common-prefix" - "-common-suffix" - "-contains?" - "-contains-p" - "-same-items?" - "-same-items-p" - "-is-prefix-p" - "-is-prefix?" - "-is-suffix-p" - "-is-suffix?" - "-is-infix-p" - "-is-infix?" - "-sort" - "--sort" - "-list" - "-repeat" - "-sum" - "-running-sum" - "-product" - "-running-product" - "-max" - "-min" - "-max-by" - "--max-by" - "-min-by" - "--min-by" - "-iterate" - "--iterate" - "-fix" - "--fix" - "-unfold" - "--unfold" - "-cons-pair?" - "-cons-pair-p" - "-cons-to-list" - "-value-to-list" - "-tree-mapreduce-from" - "--tree-mapreduce-from" - "-tree-mapreduce" - "--tree-mapreduce" - "-tree-map" - "--tree-map" - "-tree-reduce-from" - "--tree-reduce-from" - "-tree-reduce" - "--tree-reduce" - "-tree-seq" - "--tree-seq" - "-tree-map-nodes" - "--tree-map-nodes" - "-clone" - "-rpartial" - "-juxt" - "-applify" - "-on" - "-flip" - "-const" - "-cut" - "-orfn" - "-andfn" - "-iteratefn" - "-fixfn" - "-prodfn" - )) - (special-variables '( - "it" - "it-index" - "acc" - "other" - ))) - (font-lock-add-keywords 'emacs-lisp-mode `((,(concat "\\_<" (regexp-opt special-variables 'paren) "\\_>") - 1 font-lock-variable-name-face)) 'append) - (font-lock-add-keywords 'emacs-lisp-mode `((,(concat "(\\s-*" (regexp-opt new-keywords 'paren) "\\_>") - 1 font-lock-keyword-face)) 'append)) - (--each (buffer-list) - (with-current-buffer it - (when (and (eq major-mode 'emacs-lisp-mode) - (boundp 'font-lock-mode) - font-lock-mode) - (font-lock-refresh-defaults))))))) +;;; Font lock + +(defvar dash--keywords + `(;; TODO: Do not fontify the following automatic variables + ;; globally; detect and limit to their local anaphoric scope. + (,(concat "\\_<" (regexp-opt '("acc" "it" "it-index" "other")) "\\_>") + 0 font-lock-variable-name-face) + ;; Elisp macro fontification was static prior to Emacs 25. + ,@(when (< emacs-major-version 25) + (let ((macs '("!cdr" + "!cons" + "-->" + "--all?" + "--annotate" + "--any?" + "--count" + "--dotimes" + "--doto" + "--drop-while" + "--each" + "--each-r" + "--each-r-while" + "--each-while" + "--filter" + "--find-index" + "--find-indices" + "--find-last-index" + "--first" + "--fix" + "--group-by" + "--if-let" + "--iterate" + "--keep" + "--last" + "--map" + "--map-first" + "--map-indexed" + "--map-last" + "--map-when" + "--mapcat" + "--max-by" + "--min-by" + "--none?" + "--only-some?" + "--partition-by" + "--partition-by-header" + "--reduce" + "--reduce-from" + "--reduce-r" + "--reduce-r-from" + "--remove" + "--remove-first" + "--remove-last" + "--separate" + "--some" + "--sort" + "--splice" + "--splice-list" + "--split-when" + "--split-with" + "--take-while" + "--tree-map" + "--tree-map-nodes" + "--tree-mapreduce" + "--tree-mapreduce-from" + "--tree-reduce" + "--tree-reduce-from" + "--tree-seq" + "--unfold" + "--update-at" + "--when-let" + "--zip-with" + "->" + "->>" + "-as->" + "-doto" + "-if-let" + "-if-let*" + "-lambda" + "-let" + "-let*" + "-setq" + "-some-->" + "-some->" + "-some->>" + "-split-on" + "-when-let" + "-when-let*"))) + `((,(concat "(" (regexp-opt macs 'symbols)) . 1))))) + "Font lock keywords for `dash-fontify-mode'.") + +(defcustom dash-fontify-mode-lighter nil + "Mode line lighter for `dash-fontify-mode'. +Either a string to display in the mode line when +`dash-fontify-mode' is on, or nil to display +nothing (the default)." + :package-version '(dash . "2.18.0") + :group 'dash + :type '(choice (string :tag "Lighter" :value " Dash") + (const :tag "Nothing" nil))) + +;;;###autoload +(define-minor-mode dash-fontify-mode + "Toggle fontification of Dash special variables. + +Dash-Fontify mode is a buffer-local minor mode intended for Emacs +Lisp buffers. Enabling it causes the special variables bound in +anaphoric Dash macros to be fontified. These anaphoras include +`it', `it-index', `acc', and `other'. In older Emacs versions +which do not dynamically detect macros, Dash-Fontify mode +additionally fontifies Dash macro calls. + +See also `dash-fontify-mode-lighter' and +`global-dash-fontify-mode'." + :group 'dash :lighter dash-fontify-mode-lighter + (if dash-fontify-mode + (font-lock-add-keywords nil dash--keywords t) + (font-lock-remove-keywords nil dash--keywords)) + (cond ((fboundp 'font-lock-flush) ;; Added in Emacs 25. + (font-lock-flush)) + ;; `font-lock-fontify-buffer' unconditionally enables + ;; `font-lock-mode' and is marked `interactive-only' in later + ;; Emacs versions which have `font-lock-flush', so we guard + ;; and pacify as needed, respectively. + (font-lock-mode + (with-no-warnings + (font-lock-fontify-buffer))))) + +(defun dash--turn-on-fontify-mode () + "Enable `dash-fontify-mode' if in an Emacs Lisp buffer." + (when (derived-mode-p #'emacs-lisp-mode) + (dash-fontify-mode))) + +;;;###autoload +(define-globalized-minor-mode global-dash-fontify-mode + dash-fontify-mode dash--turn-on-fontify-mode + :group 'dash) + +(defcustom dash-enable-fontlock nil + "If non-nil, fontify Dash macro calls and special variables." + :group 'dash + :set (lambda (sym val) + (set-default sym val) + (global-dash-fontify-mode (if val 1 0))) + :type 'boolean) + +(make-obsolete-variable + 'dash-enable-fontlock #'global-dash-fontify-mode "2.18.0") + +(define-obsolete-function-alias + 'dash-enable-font-lock #'global-dash-fontify-mode "2.18.0") (provide 'dash) ;;; dash.el ends here diff --git a/lisp/dash/dash.info b/lisp/dash/dash.info index a88cea7b..e67c2e11 100644 --- a/lisp/dash/dash.info +++ b/lisp/dash/dash.info @@ -1,64 +1,57 @@ This is dash.info, produced by makeinfo version 6.5 from dash.texi. -This manual is for ‘dash.el’ version 2.12.1. +This manual is for Dash version 2.17.0. - Copyright © 2012-2015 Magnar Sveen + Copyright © 2012–2021 Free Software Foundation, Inc. - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - . + Permission is granted to copy, distribute and/or modify this + document under the terms of the GNU Free Documentation License, + Version 1.3 or any later version published by the Free Software + Foundation; with the Invariant Sections being “GNU General Public + License,” and no Front-Cover Texts or Back-Cover Texts. A copy of + the license is included in the section entitled “GNU Free + Documentation License”. INFO-DIR-SECTION Emacs START-INFO-DIR-ENTRY -* Dash: (dash.info). A modern list library for GNU Emacs +* Dash: (dash.info). A modern list library for GNU Emacs. END-INFO-DIR-ENTRY  File: dash.info, Node: Top, Next: Installation, Up: (dir) -dash +Dash **** -This manual is for ‘dash.el’ version 2.12.1. +This manual is for Dash version 2.17.0. - Copyright © 2012-2015 Magnar Sveen + Copyright © 2012–2021 Free Software Foundation, Inc. - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see - . + Permission is granted to copy, distribute and/or modify this + document under the terms of the GNU Free Documentation License, + Version 1.3 or any later version published by the Free Software + Foundation; with the Invariant Sections being “GNU General Public + License,” and no Front-Cover Texts or Back-Cover Texts. A copy of + the license is included in the section entitled “GNU Free + Documentation License”. * Menu: -* Installation:: -* Functions:: -* Development:: -* Index:: +* Installation:: Installing and configuring Dash. +* Functions:: Dash API reference. +* Development:: Contributing to Dash development. -— The Detailed Node Listing — +Appendices + +* FDL:: The license for this documentation. +* GPL:: Conditions for copying and changing Dash. +* Index:: Index including functions and macros. + + — The Detailed Node Listing — Installation -* Using in a package:: -* Syntax highlighting of dash functions:: +* Using in a package:: Listing Dash as a package dependency. +* Fontification of special variables:: Font Lock of anaphoric macro variables. Functions @@ -75,15 +68,15 @@ Functions * Tree operations:: * Threading macros:: * Binding:: -* Side-effects:: +* Side effects:: * Destructive operations:: * Function combinators:: Development -* Contribute:: How to contribute -* Changes:: List of significant changes by version -* Contributors:: List of contributors +* Contribute:: How to contribute. +* Change log:: List of significant changes by version. +* Contributors:: List of contributors.  File: dash.info, Node: Installation, Next: Functions, Prev: Top, Up: Top @@ -91,46 +84,57 @@ File: dash.info, Node: Installation, Next: Functions, Prev: Top, Up: Top 1 Installation ************** -It’s available on Melpa (https://melpa.org/); use ‘M-x package-install’: +Dash is available on GNU ELPA (https://elpa.gnu.org/) and MELPA +(https://melpa.org/), and can be installed with the standard command +‘package-install’ (*note (emacs)Package Installation::). -‘M-x package-install dash’ - Install the dash library. +‘M-x package-install dash ’ + Install the Dash library. -‘M-x package-install dash-functional’ - Optional, if you want the function combinators. +‘M-x package-install dash-functional ’ + Install an optional library of additional function combinators. - Alternatively, you can just dump dash.el or dash-functional.el in + Alternatively, you can just dump ‘dash.el’ or ‘dash-functional.el’ in your load path somewhere. * Menu: -* Using in a package:: -* Syntax highlighting of dash functions:: +* Using in a package:: Listing Dash as a package dependency. +* Fontification of special variables:: Font Lock of anaphoric macro variables.  -File: dash.info, Node: Using in a package, Next: Syntax highlighting of dash functions, Up: Installation +File: dash.info, Node: Using in a package, Next: Fontification of special variables, Up: Installation 1.1 Using in a package ====================== -Add this to the big comment block at the top: +If you use Dash in your own package, be sure to list it as a dependency +in the library’s headers as follows (*note (elisp)Library Headers::). - ;; Package-Requires: ((dash "2.12.1")) + ;; Package-Requires: ((dash "2.17.0")) -To get function combinators: + The same goes for the ‘dash-functional.el’ library of function +combinators: - ;; Package-Requires: ((dash "2.12.1") (dash-functional "1.2.0") (emacs "24")) + ;; Package-Requires: ((dash "2.17.0") (dash-functional "1.2.0"))  -File: dash.info, Node: Syntax highlighting of dash functions, Prev: Using in a package, Up: Installation +File: dash.info, Node: Fontification of special variables, Prev: Using in a package, Up: Installation -1.2 Syntax highlighting of dash functions -========================================= +1.2 Fontification of special variables +====================================== -Font lock of dash functions in emacs lisp buffers is now optional. -Include this in your emacs settings to get syntax highlighting: +The autoloaded minor mode ‘dash-fontify-mode’ is provided for optional +fontification of anaphoric Dash variables (‘it’, ‘acc’, etc.) in Emacs +Lisp buffers using search-based Font Lock (*note (emacs)Font Lock::). +In older Emacs versions which do not dynamically detect macros, the +minor mode also fontifies calls to Dash macros. - (eval-after-load 'dash '(dash-enable-font-lock)) + To automatically enable the minor mode in all Emacs Lisp buffers, +just call its autoloaded global counterpart ‘global-dash-fontify-mode’, +either interactively or from your ‘user-init-file’: + + (global-dash-fontify-mode)  File: dash.info, Node: Functions, Next: Development, Prev: Installation, Up: Top @@ -138,28 +142,36 @@ File: dash.info, Node: Functions, Next: Development, Prev: Installation, Up: 2 Functions *********** -This chapter contains reference documentation for the dash application -programming interface (API). All functions and constructs in the library -are prefixed with a dash (-). +This chapter contains reference documentation for the Dash API +(Application Programming Interface). The names of all public functions +defined in the library are prefixed with a dash character (‘-’). - There are also anaphoric versions of functions where that makes -sense, prefixed with two dashes instead of one. + The library also provides anaphoric macro versions of functions where +that makes sense. The names of these macros are prefixed with two +dashes (‘--’) instead of one. - For instance, while ‘-map’ takes a function to map over the list, one -can also use the anaphoric form with double dashes - which will then be -executed with ‘it’ exposed as the list item. Here’s an example: + For instance, while the function ‘-map’ applies a function to each +element of a list, its anaphoric counterpart ‘--map’ evaluates a form +with the local variable ‘it’ temporarily bound to the current list +element instead. - (-map (lambda (n) (* n n)) '(1 2 3 4)) ;; normal version + ;; Normal version. + (-map (lambda (n) (* n n)) '(1 2 3 4)) + ⇒ (1 4 9 16) - (--map (* it it) '(1 2 3 4)) ;; anaphoric version + ;; Anaphoric version. + (--map (* it it) '(1 2 3 4)) + ⇒ (1 4 9 16) -Of course, the original can also be written like + The normal version can, of course, also be written as in the +following example, which demonstrates the utility of both versions. - (defun square (n) (* n n)) + (defun my-square (n) + "Return N multiplied by itself." + (* n n)) - (-map 'square '(1 2 3 4)) - -which demonstrates the usefulness of both versions. + (-map #'my-square '(1 2 3 4)) + ⇒ (1 4 9 16) * Menu: @@ -176,7 +188,7 @@ which demonstrates the usefulness of both versions. * Tree operations:: * Threading macros:: * Binding:: -* Side-effects:: +* Side effects:: * Destructive operations:: * Function combinators:: @@ -188,16 +200,16 @@ File: dash.info, Node: Maps, Next: Sublist selection, Up: Functions Functions in this category take a transforming function, which is then applied sequentially to each or selected elements of the input list. -The results are collected in order and returned as new list. +The results are collected in order and returned as a new list. -- Function: -map (fn list) - Return a new list consisting of the result of applying FN to the - items in LIST. + Apply FN to each item in LIST and return the list of results. This + function’s anaphoric counterpart is ‘--map’. (-map (lambda (num) (* num num)) '(1 2 3 4)) ⇒ '(1 4 9 16) - (-map 'square '(1 2 3 4)) - ⇒ '(1 4 9 16) + (-map #'1+ '(1 2 3 4)) + ⇒ '(2 3 4 5) (--map (* it it) '(1 2 3 4)) ⇒ '(1 4 9 16) @@ -426,8 +438,8 @@ Functions returning a sublist of the original list. ⇒ '(2 4 6 8) -- Function: -take (n list) - Return a new list of the first N items in LIST, or all items if - there are fewer than N. + Return a copy of the first N items in LIST. Return a copy of LIST + if it contains N items or fewer. Return nil if N is zero or less. See also: ‘-take-last’ (*note -take-last::) @@ -435,9 +447,13 @@ Functions returning a sublist of the original list. ⇒ '(1 2 3) (-take 17 '(1 2 3 4 5)) ⇒ '(1 2 3 4 5) + (-take 0 '(1 2 3 4 5)) + ⇒ nil -- Function: -take-last (n list) - Return the last N items of LIST in order. + Return a copy of the last N items of LIST in order. Return a copy + of LIST if it contains N items or fewer. Return nil if N is zero + or less. See also: ‘-take’ (*note -take::) @@ -449,41 +465,54 @@ Functions returning a sublist of the original list. ⇒ '(5) -- Function: -drop (n list) - Return the tail of LIST without the first N items. + Return a copy of the tail of LIST without the first N items. + Return a copy of LIST if N is zero or less. Return nil if LIST + contains N items or fewer. See also: ‘-drop-last’ (*note -drop-last::) - (fn N LIST) - (-drop 3 '(1 2 3 4 5)) ⇒ '(4 5) (-drop 17 '(1 2 3 4 5)) - ⇒ '() + ⇒ nil + (-drop 0 '(1 2 3 4 5)) + ⇒ '(1 2 3 4 5) -- Function: -drop-last (n list) - Remove the last N items of LIST and return a copy. + Return a copy of LIST without its last N items. Return a copy of + LIST if N is zero or less. Return nil if LIST contains N items or + fewer. See also: ‘-drop’ (*note -drop::) (-drop-last 3 '(1 2 3 4 5)) ⇒ '(1 2) (-drop-last 17 '(1 2 3 4 5)) - ⇒ '() + ⇒ nil + (-drop-last 0 '(1 2 3 4 5)) + ⇒ '(1 2 3 4 5) -- Function: -take-while (pred list) - Return a new list of successive items from LIST while (PRED item) - returns a non-nil value. + Take successive items from LIST for which PRED returns non-nil. + PRED is a function of one argument. Return a new list of the + successive elements from the start of LIST for which PRED returns + non-nil. + + See also: ‘-drop-while’ (*note -drop-while::) (-take-while 'even? '(1 2 3 4)) - ⇒ '() + ⇒ nil (-take-while 'even? '(2 4 5 6)) ⇒ '(2 4) (--take-while (< it 4) '(1 2 3 4 3 2 1)) ⇒ '(1 2 3) -- Function: -drop-while (pred list) - Return the tail of LIST starting from the first item for which - (PRED item) returns nil. + Drop successive items from LIST for which PRED returns non-nil. + PRED is a function of one argument. Return a copy of the tail of + LIST starting from its first element for which PRED returns nil. + + See also: ‘-take-while’ (*note -take-while::) (-drop-while 'even? '(1 2 3 4)) ⇒ '(1 2 3 4) @@ -1005,19 +1034,19 @@ File: dash.info, Node: Unfolding, Next: Predicates, Prev: Reductions, Up: Fu 2.5 Unfolding ============= -Operations dual to reductions, building lists from seed value rather +Operations dual to reductions, building lists from a seed value rather than consuming a list to produce a single value. -- Function: -iterate (fun init n) Return a list of iterated applications of FUN to INIT. - This means a list of form: + This means a list of the form: - (init (fun init) (fun (fun init)) ...) + (INIT (FUN INIT) (FUN (FUN INIT)) ...) N is the length of the returned list. - (-iterate '1+ 1 10) + (-iterate #'1+ 1 10) ⇒ '(1 2 3 4 5 6 7 8 9 10) (-iterate (lambda (x) (+ x x)) 2 5) ⇒ '(2 4 8 16 32) @@ -1552,8 +1581,8 @@ Other list functions not fit to be classified elsewhere. ⇒ '(6 7 1 2 3 4 5) -- Function: -repeat (n x) - Return a list with X repeated N times. Return nil if N is less - than 1. + Return a new list of length N with each element being X. Return + nil if N is less than 1. (-repeat 3 :a) ⇒ '(:a :a :a) @@ -1701,8 +1730,8 @@ Other list functions not fit to be classified elsewhere. ⇒ '((1 . 3) (2 . 4)) -- Function: -cycle (list) - Return an infinite copy of LIST that will cycle through the - elements and repeat from the beginning. + Return an infinite circular copy of LIST. The returned list cycles + through the elements of LIST and repeats from the beginning. (-take 5 (-cycle '(1 2 3))) ⇒ '(1 2 3 1 2) @@ -1896,10 +1925,9 @@ Other list functions not fit to be classified elsewhere. ⇒ '(1 2 3) -- Function: -list (&rest args) - Return a list with ARGS. - - If first item of ARGS is already a list, simply return ARGS. If - not, return a list with ARGS as elements. + Return a list based on ARGS. If the first item of ARGS is already + a list, simply return it. Otherwise, return a list with ARGS as + elements. (-list 1) ⇒ '(1) @@ -2132,7 +2160,7 @@ File: dash.info, Node: Threading macros, Next: Binding, Prev: Tree operations ⇒ 106 -- Macro: -some--> (x &optional form &rest more) - When expr in non-nil, thread it through the first form (via ‘-->’ + When expr is non-nil, thread it through the first form (via ‘-->’ (*note -->::)), and when that result is non-nil, through the next form, etc. @@ -2143,8 +2171,21 @@ File: dash.info, Node: Threading macros, Next: Binding, Prev: Tree operations (-some--> '(1 3 5) (-filter 'even? it) (append it it) (-map 'square it)) ⇒ nil + -- Macro: -doto (init &rest forms) + Evaluate INIT and pass it as argument to FORMS with ‘->’ (*note + ->::). The RESULT of evaluating INIT is threaded through each of + FORMS individually using ‘->’ (*note ->::), which see. The return + value is RESULT, which FORMS may have modified by side effect. + + (-doto (list 1 2 3) pop pop) + ⇒ '(3) + (-doto (cons 1 2) (setcar 3) (setcdr 4)) + ⇒ '(3 . 4) + (gethash 'k (--doto (make-hash-table) (puthash 'k 'v it))) + ⇒ 'v +  -File: dash.info, Node: Binding, Next: Side-effects, Prev: Threading macros, Up: Functions +File: dash.info, Node: Binding, Next: Side effects, Prev: Threading macros, Up: Functions 2.13 Binding ============ @@ -2224,11 +2265,11 @@ control. optionally specify it using a vector and discarding the outer-most parens. Thus - (-let ((PATTERN SOURCE)) ..) + (-let ((PATTERN SOURCE)) ...) becomes - (-let [PATTERN SOURCE] ..). + (-let [PATTERN SOURCE] ...). ‘-let’ (*note -let::) uses a convention of not binding places (symbols) starting with _ whenever it’s possible. You can use this @@ -2253,37 +2294,36 @@ control. (a b) - bind car of list to A and ‘cadr’ to B - (a1 a2 a3 ...) - bind 0th car of list to A1, 1st to A2, 2nd to A3 - ... + (a1 a2 a3 ...) - bind 0th car of list to A1, 1st to A2, 2nd to + A3... - (a1 a2 a3 ... aN . rest) - as above, but bind the Nth cdr to - REST. + (a1 a2 a3 ... aN . rest) - as above, but bind the Nth cdr to REST. Vectors: [a] - bind 0th element of a non-list sequence to A (works with vectors, strings, bit arrays...) - [a1 a2 a3 ...] - bind 0th element of non-list sequence to A0, 1st + [a1 a2 a3 ...] - bind 0th element of non-list sequence to A0, 1st to A1, 2nd to A2, ... If the PATTERN is shorter than SOURCE, the values at places not in PATTERN are ignored. If the PATTERN is longer than SOURCE, an ‘error’ is thrown. - [a1 a2 a3 ... &rest rest] - as above, but bind the rest of the + [a1 a2 a3 ... &rest rest] - as above, but bind the rest of the sequence to REST. This is conceptually the same as improper list - matching (a1 a2 ... aN . rest) + matching (a1 a2 ... aN . rest) Key/value stores: - (&plist key0 a0 ... keyN aN) - bind value mapped by keyK in the + (&plist key0 a0 ... keyN aN) - bind value mapped by keyK in the SOURCE plist to aK. If the value is not found, aK is nil. Uses ‘plist-get’ to fetch values. - (&alist key0 a0 ... keyN aN) - bind value mapped by keyK in the + (&alist key0 a0 ... keyN aN) - bind value mapped by keyK in the SOURCE alist to aK. If the value is not found, aK is nil. Uses ‘assoc’ to fetch values. - (&hash key0 a0 ... keyN aN) - bind value mapped by keyK in the + (&hash key0 a0 ... keyN aN) - bind value mapped by keyK in the SOURCE hash table to aK. If the value is not found, aK is nil. Uses ‘gethash’ to fetch values. @@ -2291,10 +2331,10 @@ control. plist-like key-value pairs, similarly to &keys keyword of ‘cl-defun’. - (a1 a2 ... aN &keys key1 b1 ... keyN bK) + (a1 a2 ... aN &keys key1 b1 ... keyN bK) - This binds N values from the list to a1 ... aN, then interprets - the cdr as a plist (see key/value matching above). + This binds N values from the list to a1 ... aN, then interprets the + cdr as a plist (see key/value matching above). A shorthand notation for kv-destructuring exists which allows the patterns be optionally left out and derived from the key name in @@ -2402,7 +2442,7 @@ control. Note that you have to enclose the MATCH-FORM in a pair of parens, such that: - (-lambda (x) body) (-lambda (x y ...) body) + (-lambda (x) body) (-lambda (x y ...) body) has the usual semantics of ‘lambda’. Furthermore, these get translated into normal lambda, so there is no performance penalty. @@ -2445,95 +2485,92 @@ control. ⇒ "c"  -File: dash.info, Node: Side-effects, Next: Destructive operations, Prev: Binding, Up: Functions +File: dash.info, Node: Side effects, Next: Destructive operations, Prev: Binding, Up: Functions -2.14 Side-effects +2.14 Side effects ================= -Functions iterating over lists for side-effect only. +Functions iterating over lists for side effect only. -- Function: -each (list fn) - Call FN with every item in LIST. Return nil, used for side-effects - only. + Call FN on each element of LIST. Return nil; this function is + intended for side effects. Its anaphoric counterpart is ‘--each’. + For access to the current element’s index in LIST, see + ‘-each-indexed’ (*note -each-indexed::). - (let (s) (-each '(1 2 3) (lambda (item) (setq s (cons item s))))) + (let (l) (-each '(1 2 3) (lambda (x) (push x l))) l) + ⇒ '(3 2 1) + (let (l) (--each '(1 2 3) (push it l)) l) + ⇒ '(3 2 1) + (-each '(1 2 3) #'identity) ⇒ nil - (let (s) (-each '(1 2 3) (lambda (item) (setq s (cons item s)))) s) - ⇒ '(3 2 1) - (let (s) (--each '(1 2 3) (setq s (cons it s))) s) - ⇒ '(3 2 1) -- Function: -each-while (list pred fn) - Call FN with every item in LIST while (PRED item) is non-nil. - Return nil, used for side-effects only. + Call FN on each ITEM in LIST, while (PRED ITEM) is non-nil. Once + an ITEM is reached for which PRED returns nil, FN is no longer + called. Return nil; this function is intended for side effects. + Its anaphoric counterpart is ‘--each-while’. - (let (s) (-each-while '(2 4 5 6) 'even? (lambda (item) (!cons item s))) s) + (let (l) (-each-while '(2 4 5 6) #'even? (lambda (x) (push x l))) l) ⇒ '(4 2) - (let (s) (--each-while '(1 2 3 4) (< it 3) (!cons it s)) s) + (let (l) (--each-while '(1 2 3 4) (< it 3) (push it l)) l) ⇒ '(2 1) + (let ((s 0)) (--each-while '(1 3 4 5) (odd? it) (setq s (+ s it))) s) + ⇒ 4 -- Function: -each-indexed (list fn) - Call (FN index item) for each item in LIST. + Call FN on each index and element of LIST. For each ITEM at INDEX + in LIST, call (funcall FN INDEX ITEM). Return nil; this function + is intended for side effects. See also: ‘-map-indexed’ (*note + -map-indexed::). - In the anaphoric form ‘--each-indexed’, the index is exposed as - symbol ‘it-index’. - - See also: ‘-map-indexed’ (*note -map-indexed::). - - (let (s) (-each-indexed '(a b c) (lambda (index item) (setq s (cons (list item index) s)))) s) + (let (l) (-each-indexed '(a b c) (lambda (i x) (push (list x i) l))) l) ⇒ '((c 2) (b 1) (a 0)) - (let (s) (--each-indexed '(a b c) (setq s (cons (list it it-index) s))) s) + (let (l) (--each-indexed '(a b c) (push (list it it-index) l)) l) ⇒ '((c 2) (b 1) (a 0)) + (let (l) (--each-indexed nil (push it l)) l) + ⇒ nil -- Function: -each-r (list fn) - Call FN with every item in LIST in reversed order. Return nil, - used for side-effects only. + Call FN on each element of LIST in reversed order. Return nil; + this function is intended for side effects. Its anaphoric + counterpart is ‘--each-r’. - (let (s) (-each-r '(1 2 3) (lambda (item) (setq s (cons item s))))) + (let (l) (-each-r '(1 2 3) (lambda (x) (push x l))) l) + ⇒ '(1 2 3) + (let (l) (--each-r '(1 2 3) (push it l)) l) + ⇒ '(1 2 3) + (-each-r '(1 2 3) #'identity) ⇒ nil - (let (s) (-each-r '(1 2 3) (lambda (item) (setq s (cons item s)))) s) - ⇒ '(1 2 3) - (let (s) (--each-r '(1 2 3) (setq s (cons it s))) s) - ⇒ '(1 2 3) -- Function: -each-r-while (list pred fn) - Call FN with every item in reversed LIST while (PRED item) is - non-nil. Return nil, used for side-effects only. + Call FN on each ITEM in reversed LIST, while (PRED ITEM) is + non-nil. Once an ITEM is reached for which PRED returns nil, FN is + no longer called. Return nil; this function is intended for side + effects. Its anaphoric counterpart is ‘--each-r-while’. - (let (s) (-each-r-while '(2 4 5 6) 'even? (lambda (item) (!cons item s))) s) + (let (l) (-each-r-while '(2 4 5 6) #'even? (lambda (x) (push x l))) l) ⇒ '(6) - (let (s) (--each-r-while '(1 2 3 4) (>= it 3) (!cons it s)) s) + (let (l) (--each-r-while '(1 2 3 4) (>= it 3) (push it l)) l) ⇒ '(3 4) + (let ((s 0)) (--each-r-while '(1 2 3 5) (odd? it) (setq s (+ s it))) s) + ⇒ 8 -- Function: -dotimes (num fn) - Repeatedly calls FN (presumably for side-effects) passing in - integers from 0 through NUM-1. + Call FN NUM times, presumably for side effects. FN is called with + a single argument on successive integers running from 0, inclusive, + to NUM, exclusive. FN is not called if NUM is less than 1. This + function’s anaphoric counterpart is ‘--dotimes’. - (let (s) (-dotimes 3 (lambda (n) (!cons n s))) s) + (let (s) (-dotimes 3 (lambda (n) (push n s))) s) ⇒ '(2 1 0) - (let (s) (--dotimes 5 (!cons it s)) s) + (let (s) (-dotimes 0 (lambda (n) (push n s))) s) + ⇒ nil + (let (s) (--dotimes 5 (push it s)) s) ⇒ '(4 3 2 1 0) - -- Macro: -doto (eval-initial-value &rest forms) - Eval a form, then insert that form as the 2nd argument to other - forms. The EVAL-INITIAL-VALUE form is evaluated once. Its result - is passed to FORMS, which are then evaluated sequentially. Returns - the target form. - - (-doto '(1 2 3) (!cdr) (!cdr)) - ⇒ '(3) - (-doto '(1 . 2) (setcar 3) (setcdr 4)) - ⇒ '(3 . 4) - - -- Macro: --doto (eval-initial-value &rest forms) - Anaphoric form of ‘-doto’ (*note -doto::). Note: ‘it’ is not - required in each form. - - (gethash "key" (--doto (make-hash-table :test 'equal) (puthash "key" "value" it))) - ⇒ "value" -  -File: dash.info, Node: Destructive operations, Next: Function combinators, Prev: Side-effects, Up: Functions +File: dash.info, Node: Destructive operations, Next: Function combinators, Prev: Side effects, Up: Functions 2.15 Destructive operations =========================== @@ -2564,8 +2601,8 @@ These combinators require Emacs 24 for its lexical scope. So they are offered in a separate package: ‘dash-functional‘. -- Function: -partial (fn &rest args) - Takes a function FN and fewer than the normal arguments to FN, and - returns a fn that takes a variable number of additional ARGS. When + Take a function FN and fewer than the normal arguments to FN, and + return a fn that takes a variable number of additional ARGS. When called, the returned function calls FN with ARGS first and then additional args. @@ -2772,12 +2809,12 @@ offered in a separate package: ‘dash-functional‘. This function satisfies the following laws: - (-compose (-prodfn f g ...) (-prodfn f’ g’ ...)) = (-prodfn - (-compose f f’) (-compose g g’) ...) (-prodfn f g ...) = (-juxt + (-compose (-prodfn f g ...) (-prodfn f’ g’ ...)) = (-prodfn + (-compose f f’) (-compose g g’) ...) (-prodfn f g ...) = (-juxt (-compose f (-partial ’nth 0)) (-compose g (-partial ’nth 1)) ...) - (-compose (-prodfn f g ...) (-juxt f’ g’ ...)) = (-juxt (-compose - f f’) (-compose g g’) ...) (-compose (-partial ’nth n) (-prod f1 - f2 ...)) = (-compose fn (-partial ’nth n)) + (-compose (-prodfn f g ...) (-juxt f’ g’ ...)) = (-juxt (-compose f + f’) (-compose g g’) ...) (-compose (-partial ’nth n) (-prod f1 f2 + ...)) = (-compose fn (-partial ’nth n)) (funcall (-prodfn '1+ '1- 'number-to-string) '(1 2 3)) ⇒ '(2 1 "3") @@ -2787,153 +2824,250 @@ offered in a separate package: ‘dash-functional‘. ⇒ 18  -File: dash.info, Node: Development, Next: Index, Prev: Functions, Up: Top +File: dash.info, Node: Development, Next: FDL, Prev: Functions, Up: Top 3 Development ************* -The dash repository is hosted on GitHub: - +The Dash repository is hosted on GitHub at +. * Menu: -* Contribute:: How to contribute -* Changes:: List of significant changes by version -* Contributors:: List of contributors +* Contribute:: How to contribute. +* Change log:: List of significant changes by version. +* Contributors:: List of contributors.  -File: dash.info, Node: Contribute, Next: Changes, Up: Development +File: dash.info, Node: Contribute, Next: Change log, Up: Development 3.1 Contribute ============== Yes, please do. Pure functions in the list manipulation realm only, -please. There’s a suite of tests in dev/examples.el, so remember to add -tests for your function, or it might get broken later. +please. There’s a suite of examples/tests in ‘dev/examples.el’, so +remember to add tests for your additions, or they may get broken later. - Run the tests with ‘./run-tests.sh’. Create the docs with -‘./create-docs.sh’. I highly recommend that you install these as a + Run the tests with ‘make check’. Regenerate the docs with ‘make +docs’. Contributors are encouraged to install these commands as a Git pre-commit hook, so that the tests are always running and the docs are always in sync: -cp pre-commit.sh .git/hooks/pre-commit + $ cp pre-commit.sh .git/hooks/pre-commit - Oh, and don’t edit ‘README.md’ directly, it is auto-generated. -Change ‘readme-template.md’ or ‘examples-to-docs.el’ instead. The same -goes for the info manual. + Oh, and don’t edit ‘README.md’ or ‘dash.texi’ directly, as they are +auto-generated. Instead, change their respective templates +‘readme-template.md’ or ‘dash-template.texi’. + + To ensure that Dash can be distributed with GNU ELPA or Emacs, we +require that all contributors assign copyright to the Free Software +Foundation. For more on this, *note (emacs)Copyright Assignment::.  -File: dash.info, Node: Changes, Next: Contributors, Prev: Contribute, Up: Development +File: dash.info, Node: Change log, Next: Contributors, Prev: Contribute, Up: Development -3.2 Changes -=========== +3.2 Change log +============== + +Changes in 2.17: + + • Sped up ‘-uniq’ by using hash-tables when possible (Zhu + Zihao). + • Fixed ‘-inits’ to be non-destructive (Zach Shaftel). + • Fixed indent rules for ‘-some->’ and family (Wouter + Bolsterlee). + • Added ‘-zip-lists’ which always returns a list of proper + lists, even for two input lists (see issue #135). + +Changes in 2.16: + + • Added ‘--doto’, anaphoric version of ‘-doto’. + • Aliased ‘-cons-pair-p’ to ‘-cons-pair?’. + • Generalized ‘-rotate’ for |N| greater than the length of the + list (Brian Leung). + • Added a mechanism to extend destructuring with custom matchers + (Ivan Yonchovski). + +Changes in 2.15: + + This release brought new destructuring features, some new control + flow functions, and performance optimizations. + + • Added ‘-setq’ with destructuring binding support similar to + the ‘-let’ family. + • Added smarter key destructuring in ‘-let’ and friends where + variables are auto-derived from keys. + • Allowed ‘-let’ bindings without a source value form. + • Added ‘-each-r’ and ‘-each-r-while’ (Paul Pogonyshev). + • Added ‘-common-suffix’ (Basil L. Contovounesios). + • Improved performance of folds (‘-reduce’ and friends) (Basil + L. Contovounesios). + +Changes in 2.14: + + This release retired support for Emacs 23. + + • Added Edebug support for threading macros (Wilfred Hughes). + • Added ‘-unzip’. + • Added support for ‘-first-item’ and ‘-last-item’ as place + forms (*note (elisp)Generalized Variables::). + • Added ‘-powerset’ and ‘-permutations’ (Mark Oteiza). + • Added ‘-as->’ for threading a named variable (Zachary Kanfer). + • Added ‘-partition-after-pred’, ‘-partition-before-pred’, + ‘-partition-after-item’, and ‘-partition-before-item’ (Zachary + Kanfer). + • Fixed a bug in ‘-any-p’ and friends testing for ‘null’ on + lists containing ‘nil’. + • Fixed infinite loop bug in ‘-zip’ and ‘-interleave’ when + called with empty input. + • Added ‘-second-item’ through ‘-fifth-item’ as alternatives to + ‘nth’ (Wilfred Hughes). + • Added ‘-tails’ and ‘-inits’. + • Added ‘-running-sum’ and ‘-running-product’. + • Added the ‘-reductions[-r][-from]’ family of functions (like + ‘-reduce’ but collecting intermediate results). + • Added ‘-common-prefix’ (Basil L. Contovounesios). + +Changes in 2.13: + + • ‘-let’ now supports ‘&alist’ destructuring. + • Various performance improvements. + • ‘-zip’ might change in a future release to always return a + list of proper lists. Added ‘-zip-pair’ for users who + explicitly want the old behavior. + • Enabled lexical binding in ‘dash.el’ for Emacs versions 24 or + newer. + • Added ‘-select-column’ and ‘-select-columns’. + • Fixed ‘-map-last’ and ‘--remove-last’ to be non-destructive. + • Added ‘-each-indexed’ and ‘--each-indexed’. + • Added ‘-take-last’ and ‘-drop-last’. + • Added the ‘-doto’ macro. + • ‘-cut <>’ is now treated as a function, consistent with SRFI + 26 (https://srfi.schemers.org/srfi-26/srfi-26.html). + +Changes in 2.12: + + • Added GNU ELPA support (Phillip Lord). + • Added ‘-some->’, ‘-some->>’, and ‘-some-->’ macros (Cam Saul). + • ‘-is-suffix?’ is now non-destructive. + • Faster hash table implementation for ‘-union’. + • Improvements to docstrings and examples. + +Changes in 2.11: + + • Lots of clean up w.r.t. byte compilation, debug macros, and + tests. Changes in 2.10: - • Add ‘-let’ destructuring to ‘-if-let’ and ‘-when-let’ (Fredrik - Bergroth) + • Added ‘-let’ destructuring to ‘-if-let’ and ‘-when-let’ + (Fredrik Bergroth). Changes in 2.9: - • Add ‘-let’, ‘-let*’ and ‘-lambda’ with destructuring - • Add ‘-tree-seq’ and ‘-tree-map-nodes’ - • Add ‘-non-nil’ - • Add ‘-fix’ - • Add ‘-fixfn’ (dash-functional 1.2) - • Add ‘-copy’ (Wilfred Hughes) + • Added ‘-let’, ‘-let*’, and ‘-lambda’ with destructuring. + • Added ‘-tree-seq’ and ‘-tree-map-nodes’. + • Added ‘-non-nil’. + • Added ‘-fix’. + • Added ‘-fixfn’ (‘dash-functional’ version 1.2). + • Added ‘-copy’ (Wilfred Hughes). Changes in 2.8: - • Add ‘-butlast’ + • Added ‘-butlast’. Changes in 2.7: - • ‘-zip’ now supports more than two lists (Steve Lamb) - • Add ‘-cycle’, ‘-pad’, ‘-annotate’, ‘-zip-fill’ (Steve Lamb) - • Add ‘-table’, ‘-table-flat’ (finite cartesian product) - • Add ‘-flatten-n’ - • ‘-slice’ now supports "step" argument - • Add functional combinators ‘-iteratefn’, ‘-prodfn’ - • Add ‘-replace’, ‘-splice’, ‘-splice-list’ which generalize - ‘-replace-at’ and ‘-insert-at’ - • Add ‘-compose’, ‘-iteratefn’ and ‘-prodfn’ (dash-functional 1.1) + • ‘-zip’ now supports more than two lists (Steve Lamb). + • Added ‘-cycle’, ‘-pad’, ‘-annotate’, and ‘-zip-fill’ (Steve + Lamb). + • Added ‘-table’, ‘-table-flat’ (finite Cartesian product). + • Added ‘-flatten-n’. + • ‘-slice’ now supports a “step” argument. + • Added functional combinators ‘-iteratefn’ and ‘-prodfn’. + • Added ‘-replace’, ‘-splice’, and ‘-splice-list’ which + generalize ‘-replace-at’ and ‘-insert-at’. + • Added ‘-compose’, ‘-iteratefn’, and ‘-prodfn’ + (‘dash-functional’ version 1.1). Changes in 2.6: - • Add ‘-is-prefix-p’, ‘-is-suffix-p’, ‘-is-infix-p’ (Matus Goljer) - • Add ‘-iterate’, ‘-unfold’ (Matus Goljer) - • Add ‘-split-on’, ‘-split-when’ (Matus Goljer) - • Add ‘-find-last-index’ (Matus Goljer) - • Add ‘-list’ (Johan Andersson) + • Added ‘-is-prefix-p’, ‘-is-suffix-p’, and ‘-is-infix-p’ (Matus + Goljer). + • Added ‘-iterate’ and ‘-unfold’ (Matus Goljer). + • Added ‘-split-on’ and ‘-split-when’ (Matus Goljer). + • Added ‘-find-last-index’ (Matus Goljer). + • Added ‘-list’ (Johan Andersson). Changes in 2.5: - • Add ‘-same-items?’ (Johan Andersson) - • A few bugfixes + • Added ‘-same-items?’ (Johan Andersson). + • Various bugfixes. Changes in 2.4: - • Add ‘-snoc’ (Matus Goljer) - • Add ‘-replace-at’, ‘-update-at’, ‘-remove-at’, and - ‘-remove-at-indices’ (Matus Goljer) + • Added ‘-snoc’ (Matus Goljer). + • Added ‘-replace-at’, ‘-update-at’, ‘-remove-at’, and + ‘-remove-at-indices’ (Matus Goljer). Changes in 2.3: - • Add tree operations (Matus Goljer) - • Make font-lock optional + • Added tree operations (Matus Goljer). + • Made Font Lock optional. Changes in 2.2: - • Add ‘-compose’ (Christina Whyte) + • Added ‘-compose’ (Christina Whyte). Changes in 2.1: - • Add indexing operations (Matus Goljer) + • Added indexing operations (Matus Goljer). Changes in 2.0: - • Split out ‘dash-functional.el’ (Matus Goljer) - • Add ‘-andfn’, ‘-orfn’, ‘-not’, ‘-cut’, ‘-const’, ‘-flip’ and ‘-on’. - (Matus Goljer) - • Fix ‘-min’, ‘-max’, ‘-min-by’ and ‘-max-by’ (Matus Goljer) + • Split out ‘dash-functional.el’ (Matus Goljer). + • Added ‘-andfn’, ‘-orfn’, ‘-not’, ‘-cut’, ‘-const’, ‘-flip’, + and ‘-on’ (Matus Goljer). + • Fixed ‘-min’, ‘-max’, ‘-min-by’, and ‘-max-by’ (Matus Goljer). Changes in 1.8: - • Add ‘-first-item’ and ‘-last-item’ (Wilfred Hughes) + • Added ‘-first-item’ and ‘-last-item’ (Wilfred Hughes). Changes in 1.7: - • Add ‘-rotate’ (Matus Goljer) + • Added ‘-rotate’ (Matus Goljer). Changes in 1.6: - • Add ‘-min’, ‘-max’, ‘-min-by’ and ‘-max-by’ (Johan Andersson) + • Added ‘-min’, ‘-max’, ‘-min-by’, and ‘-max-by’ (Johan + Andersson). Changes in 1.5: - • Add ‘-sum’ and ‘-product’ (Johan Andersson) + • Added ‘-sum’ and ‘-product’ (Johan Andersson). Changes in 1.4: - • Add ‘-sort’ - • Add ‘-reduce-r’ (Matus Goljer) - • Add ‘-reduce-r-from’ (Matus Goljer) + • Added ‘-sort’. + • Added ‘-reduce-r’ (Matus Goljer). + • Added ‘-reduce-r-from’ (Matus Goljer). Changes in 1.3: - • Add ‘-partition-in-steps’ - • Add ‘-partition-all-in-steps’ + • Added ‘-partition-in-steps’. + • Added ‘-partition-all-in-steps’. Changes in 1.2: - • Add ‘-last’ (Matus Goljer) - • Add ‘-insert-at’ (Emanuel Evans) - • Add ‘-when-let’ and ‘-if-let’ (Emanuel Evans) - • Add ‘-when-let*’ and ‘-if-let*’ (Emanuel Evans) - • Some bugfixes + • Added ‘-last’ (Matus Goljer). + • Added ‘-insert-at’ (Emanuel Evans). + • Added ‘-when-let’ and ‘-if-let’ (Emanuel Evans). + • Added ‘-when-let*’ and ‘-if-let*’ (Emanuel Evans). + • Various bugfixes.  -File: dash.info, Node: Contributors, Prev: Changes, Up: Development +File: dash.info, Node: Contributors, Prev: Change log, Up: Development 3.3 Contributors ================ @@ -2946,29 +3080,1235 @@ File: dash.info, Node: Contributors, Prev: Changes, Up: Development ‘-repeat’. • Nic Ferrier (https://github.com/nicferrier) contributed ‘-cons*’. • Wilfred Hughes (https://github.com/Wilfred) contributed ‘-slice’, - ‘-first-item’ and ‘-last-item’. + ‘-first-item’, and ‘-last-item’. • Emanuel Evans (https://github.com/shosti) contributed ‘-if-let’, - ‘-when-let’ and ‘-insert-at’. + ‘-when-let’, and ‘-insert-at’. • Johan Andersson (https://github.com/rejeep) contributed ‘-sum’, - ‘-product’ and ‘-same-items?’ + ‘-product’, and ‘-same-items?’. • Christina Whyte (https://github.com/kurisuwhyte) contributed - ‘-compose’ + ‘-compose’. • Steve Lamb (https://github.com/steventlamb) contributed ‘-cycle’, - ‘-pad’, ‘-annotate’, ‘-zip-fill’ and an n-ary version of ‘-zip’. + ‘-pad’, ‘-annotate’, ‘-zip-fill’, and a variadic version of ‘-zip’. • Fredrik Bergroth (https://github.com/fbergroth) made the ‘-if-let’ - family use ‘-let’ destructuring and improved script for generating - documentation. + family use ‘-let’ destructuring and improved the script for + generating documentation. • Mark Oteiza (https://github.com/holomorph) contributed the script - to create an info manual. + to create an Info manual. • Vasilij Schneidermann (https://github.com/wasamasa) contributed ‘-some’. • William West (https://github.com/occidens) made ‘-fixfn’ more robust at handling floats. + • Cam Saul (https://github.com/camsaul) contributed ‘-some->’, + ‘-some->>’, and ‘-some-->’. + • Basil L. Contovounesios (https://github.com/basil-conto) + contributed ‘-common-prefix’. + • Paul Pogonyshev (https://github.com/doublep) contributed ‘-each-r’ + and ‘-each-r-while’. Thanks! + New contributors are very welcome. *Note Contribute::. +  -File: dash.info, Node: Index, Prev: Development, Up: Top +File: dash.info, Node: FDL, Next: GPL, Prev: Development, Up: Top + +Appendix A GNU Free Documentation License +***************************************** + + Version 1.3, 3 November 2008 + + Copyright © 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. + + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + 0. PREAMBLE + + The purpose of this License is to make a manual, textbook, or other + functional and useful document “free” in the sense of freedom: to + assure everyone the effective freedom to copy and redistribute it, + with or without modifying it, either commercially or + noncommercially. Secondarily, this License preserves for the + author and publisher a way to get credit for their work, while not + being considered responsible for modifications made by others. + + This License is a kind of “copyleft”, which means that derivative + works of the document must themselves be free in the same sense. + It complements the GNU General Public License, which is a copyleft + license designed for free software. + + We have designed this License in order to use it for manuals for + free software, because free software needs free documentation: a + free program should come with manuals providing the same freedoms + that the software does. But this License is not limited to + software manuals; it can be used for any textual work, regardless + of subject matter or whether it is published as a printed book. We + recommend this License principally for works whose purpose is + instruction or reference. + + 1. APPLICABILITY AND DEFINITIONS + + This License applies to any manual or other work, in any medium, + that contains a notice placed by the copyright holder saying it can + be distributed under the terms of this License. Such a notice + grants a world-wide, royalty-free license, unlimited in duration, + to use that work under the conditions stated herein. The + “Document”, below, refers to any such manual or work. Any member + of the public is a licensee, and is addressed as “you”. You accept + the license if you copy, modify or distribute the work in a way + requiring permission under copyright law. + + A “Modified Version” of the Document means any work containing the + Document or a portion of it, either copied verbatim, or with + modifications and/or translated into another language. + + A “Secondary Section” is a named appendix or a front-matter section + of the Document that deals exclusively with the relationship of the + publishers or authors of the Document to the Document’s overall + subject (or to related matters) and contains nothing that could + fall directly within that overall subject. (Thus, if the Document + is in part a textbook of mathematics, a Secondary Section may not + explain any mathematics.) The relationship could be a matter of + historical connection with the subject or with related matters, or + of legal, commercial, philosophical, ethical or political position + regarding them. + + The “Invariant Sections” are certain Secondary Sections whose + titles are designated, as being those of Invariant Sections, in the + notice that says that the Document is released under this License. + If a section does not fit the above definition of Secondary then it + is not allowed to be designated as Invariant. The Document may + contain zero Invariant Sections. If the Document does not identify + any Invariant Sections then there are none. + + The “Cover Texts” are certain short passages of text that are + listed, as Front-Cover Texts or Back-Cover Texts, in the notice + that says that the Document is released under this License. A + Front-Cover Text may be at most 5 words, and a Back-Cover Text may + be at most 25 words. + + A “Transparent” copy of the Document means a machine-readable copy, + represented in a format whose specification is available to the + general public, that is suitable for revising the document + straightforwardly with generic text editors or (for images composed + of pixels) generic paint programs or (for drawings) some widely + available drawing editor, and that is suitable for input to text + formatters or for automatic translation to a variety of formats + suitable for input to text formatters. A copy made in an otherwise + Transparent file format whose markup, or absence of markup, has + been arranged to thwart or discourage subsequent modification by + readers is not Transparent. An image format is not Transparent if + used for any substantial amount of text. A copy that is not + “Transparent” is called “Opaque”. + + Examples of suitable formats for Transparent copies include plain + ASCII without markup, Texinfo input format, LaTeX input format, + SGML or XML using a publicly available DTD, and standard-conforming + simple HTML, PostScript or PDF designed for human modification. + Examples of transparent image formats include PNG, XCF and JPG. + Opaque formats include proprietary formats that can be read and + edited only by proprietary word processors, SGML or XML for which + the DTD and/or processing tools are not generally available, and + the machine-generated HTML, PostScript or PDF produced by some word + processors for output purposes only. + + The “Title Page” means, for a printed book, the title page itself, + plus such following pages as are needed to hold, legibly, the + material this License requires to appear in the title page. For + works in formats which do not have any title page as such, “Title + Page” means the text near the most prominent appearance of the + work’s title, preceding the beginning of the body of the text. + + The “publisher” means any person or entity that distributes copies + of the Document to the public. + + A section “Entitled XYZ” means a named subunit of the Document + whose title either is precisely XYZ or contains XYZ in parentheses + following text that translates XYZ in another language. (Here XYZ + stands for a specific section name mentioned below, such as + “Acknowledgements”, “Dedications”, “Endorsements”, or “History”.) + To “Preserve the Title” of such a section when you modify the + Document means that it remains a section “Entitled XYZ” according + to this definition. + + The Document may include Warranty Disclaimers next to the notice + which states that this License applies to the Document. These + Warranty Disclaimers are considered to be included by reference in + this License, but only as regards disclaiming warranties: any other + implication that these Warranty Disclaimers may have is void and + has no effect on the meaning of this License. + + 2. VERBATIM COPYING + + You may copy and distribute the Document in any medium, either + commercially or noncommercially, provided that this License, the + copyright notices, and the license notice saying this License + applies to the Document are reproduced in all copies, and that you + add no other conditions whatsoever to those of this License. You + may not use technical measures to obstruct or control the reading + or further copying of the copies you make or distribute. However, + you may accept compensation in exchange for copies. If you + distribute a large enough number of copies you must also follow the + conditions in section 3. + + You may also lend copies, under the same conditions stated above, + and you may publicly display copies. + + 3. COPYING IN QUANTITY + + If you publish printed copies (or copies in media that commonly + have printed covers) of the Document, numbering more than 100, and + the Document’s license notice requires Cover Texts, you must + enclose the copies in covers that carry, clearly and legibly, all + these Cover Texts: Front-Cover Texts on the front cover, and + Back-Cover Texts on the back cover. Both covers must also clearly + and legibly identify you as the publisher of these copies. The + front cover must present the full title with all words of the title + equally prominent and visible. You may add other material on the + covers in addition. Copying with changes limited to the covers, as + long as they preserve the title of the Document and satisfy these + conditions, can be treated as verbatim copying in other respects. + + If the required texts for either cover are too voluminous to fit + legibly, you should put the first ones listed (as many as fit + reasonably) on the actual cover, and continue the rest onto + adjacent pages. + + If you publish or distribute Opaque copies of the Document + numbering more than 100, you must either include a machine-readable + Transparent copy along with each Opaque copy, or state in or with + each Opaque copy a computer-network location from which the general + network-using public has access to download using public-standard + network protocols a complete Transparent copy of the Document, free + of added material. If you use the latter option, you must take + reasonably prudent steps, when you begin distribution of Opaque + copies in quantity, to ensure that this Transparent copy will + remain thus accessible at the stated location until at least one + year after the last time you distribute an Opaque copy (directly or + through your agents or retailers) of that edition to the public. + + It is requested, but not required, that you contact the authors of + the Document well before redistributing any large number of copies, + to give them a chance to provide you with an updated version of the + Document. + + 4. MODIFICATIONS + + You may copy and distribute a Modified Version of the Document + under the conditions of sections 2 and 3 above, provided that you + release the Modified Version under precisely this License, with the + Modified Version filling the role of the Document, thus licensing + distribution and modification of the Modified Version to whoever + possesses a copy of it. In addition, you must do these things in + the Modified Version: + + A. Use in the Title Page (and on the covers, if any) a title + distinct from that of the Document, and from those of previous + versions (which should, if there were any, be listed in the + History section of the Document). You may use the same title + as a previous version if the original publisher of that + version gives permission. + + B. List on the Title Page, as authors, one or more persons or + entities responsible for authorship of the modifications in + the Modified Version, together with at least five of the + principal authors of the Document (all of its principal + authors, if it has fewer than five), unless they release you + from this requirement. + + C. State on the Title page the name of the publisher of the + Modified Version, as the publisher. + + D. Preserve all the copyright notices of the Document. + + E. Add an appropriate copyright notice for your modifications + adjacent to the other copyright notices. + + F. Include, immediately after the copyright notices, a license + notice giving the public permission to use the Modified + Version under the terms of this License, in the form shown in + the Addendum below. + + G. Preserve in that license notice the full lists of Invariant + Sections and required Cover Texts given in the Document’s + license notice. + + H. Include an unaltered copy of this License. + + I. Preserve the section Entitled “History”, Preserve its Title, + and add to it an item stating at least the title, year, new + authors, and publisher of the Modified Version as given on the + Title Page. If there is no section Entitled “History” in the + Document, create one stating the title, year, authors, and + publisher of the Document as given on its Title Page, then add + an item describing the Modified Version as stated in the + previous sentence. + + J. Preserve the network location, if any, given in the Document + for public access to a Transparent copy of the Document, and + likewise the network locations given in the Document for + previous versions it was based on. These may be placed in the + “History” section. You may omit a network location for a work + that was published at least four years before the Document + itself, or if the original publisher of the version it refers + to gives permission. + + K. For any section Entitled “Acknowledgements” or “Dedications”, + Preserve the Title of the section, and preserve in the section + all the substance and tone of each of the contributor + acknowledgements and/or dedications given therein. + + L. Preserve all the Invariant Sections of the Document, unaltered + in their text and in their titles. Section numbers or the + equivalent are not considered part of the section titles. + + M. Delete any section Entitled “Endorsements”. Such a section + may not be included in the Modified Version. + + N. Do not retitle any existing section to be Entitled + “Endorsements” or to conflict in title with any Invariant + Section. + + O. Preserve any Warranty Disclaimers. + + If the Modified Version includes new front-matter sections or + appendices that qualify as Secondary Sections and contain no + material copied from the Document, you may at your option designate + some or all of these sections as invariant. To do this, add their + titles to the list of Invariant Sections in the Modified Version’s + license notice. These titles must be distinct from any other + section titles. + + You may add a section Entitled “Endorsements”, provided it contains + nothing but endorsements of your Modified Version by various + parties—for example, statements of peer review or that the text has + been approved by an organization as the authoritative definition of + a standard. + + You may add a passage of up to five words as a Front-Cover Text, + and a passage of up to 25 words as a Back-Cover Text, to the end of + the list of Cover Texts in the Modified Version. Only one passage + of Front-Cover Text and one of Back-Cover Text may be added by (or + through arrangements made by) any one entity. If the Document + already includes a cover text for the same cover, previously added + by you or by arrangement made by the same entity you are acting on + behalf of, you may not add another; but you may replace the old + one, on explicit permission from the previous publisher that added + the old one. + + The author(s) and publisher(s) of the Document do not by this + License give permission to use their names for publicity for or to + assert or imply endorsement of any Modified Version. + + 5. COMBINING DOCUMENTS + + You may combine the Document with other documents released under + this License, under the terms defined in section 4 above for + modified versions, provided that you include in the combination all + of the Invariant Sections of all of the original documents, + unmodified, and list them all as Invariant Sections of your + combined work in its license notice, and that you preserve all + their Warranty Disclaimers. + + The combined work need only contain one copy of this License, and + multiple identical Invariant Sections may be replaced with a single + copy. If there are multiple Invariant Sections with the same name + but different contents, make the title of each such section unique + by adding at the end of it, in parentheses, the name of the + original author or publisher of that section if known, or else a + unique number. Make the same adjustment to the section titles in + the list of Invariant Sections in the license notice of the + combined work. + + In the combination, you must combine any sections Entitled + “History” in the various original documents, forming one section + Entitled “History”; likewise combine any sections Entitled + “Acknowledgements”, and any sections Entitled “Dedications”. You + must delete all sections Entitled “Endorsements.” + + 6. COLLECTIONS OF DOCUMENTS + + You may make a collection consisting of the Document and other + documents released under this License, and replace the individual + copies of this License in the various documents with a single copy + that is included in the collection, provided that you follow the + rules of this License for verbatim copying of each of the documents + in all other respects. + + You may extract a single document from such a collection, and + distribute it individually under this License, provided you insert + a copy of this License into the extracted document, and follow this + License in all other respects regarding verbatim copying of that + document. + + 7. AGGREGATION WITH INDEPENDENT WORKS + + A compilation of the Document or its derivatives with other + separate and independent documents or works, in or on a volume of a + storage or distribution medium, is called an “aggregate” if the + copyright resulting from the compilation is not used to limit the + legal rights of the compilation’s users beyond what the individual + works permit. When the Document is included in an aggregate, this + License does not apply to the other works in the aggregate which + are not themselves derivative works of the Document. + + If the Cover Text requirement of section 3 is applicable to these + copies of the Document, then if the Document is less than one half + of the entire aggregate, the Document’s Cover Texts may be placed + on covers that bracket the Document within the aggregate, or the + electronic equivalent of covers if the Document is in electronic + form. Otherwise they must appear on printed covers that bracket + the whole aggregate. + + 8. TRANSLATION + + Translation is considered a kind of modification, so you may + distribute translations of the Document under the terms of section + 4. Replacing Invariant Sections with translations requires special + permission from their copyright holders, but you may include + translations of some or all Invariant Sections in addition to the + original versions of these Invariant Sections. You may include a + translation of this License, and all the license notices in the + Document, and any Warranty Disclaimers, provided that you also + include the original English version of this License and the + original versions of those notices and disclaimers. In case of a + disagreement between the translation and the original version of + this License or a notice or disclaimer, the original version will + prevail. + + If a section in the Document is Entitled “Acknowledgements”, + “Dedications”, or “History”, the requirement (section 4) to + Preserve its Title (section 1) will typically require changing the + actual title. + + 9. TERMINATION + + You may not copy, modify, sublicense, or distribute the Document + except as expressly provided under this License. Any attempt + otherwise to copy, modify, sublicense, or distribute it is void, + and will automatically terminate your rights under this License. + + 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, receipt of a copy of some or all of the + same material does not give you any rights to use it. + + 10. FUTURE REVISIONS OF THIS LICENSE + + The Free Software Foundation may publish new, revised versions of + the GNU Free Documentation 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. See + . + + Each version of the License is given a distinguishing version + number. If the Document specifies that a particular numbered + version of this License “or any later version” applies to it, you + have the option of following the terms and conditions either of + that specified version or of any later version that has been + published (not as a draft) by the Free Software Foundation. If the + Document does not specify a version number of this License, you may + choose any version ever published (not as a draft) by the Free + Software Foundation. If the Document specifies that a proxy can + decide which future versions of this License can be used, that + proxy’s public statement of acceptance of a version permanently + authorizes you to choose that version for the Document. + + 11. RELICENSING + + “Massive Multiauthor Collaboration Site” (or “MMC Site”) means any + World Wide Web server that publishes copyrightable works and also + provides prominent facilities for anybody to edit those works. A + public wiki that anybody can edit is an example of such a server. + A “Massive Multiauthor Collaboration” (or “MMC”) contained in the + site means any set of copyrightable works thus published on the MMC + site. + + “CC-BY-SA” means the Creative Commons Attribution-Share Alike 3.0 + license published by Creative Commons Corporation, a not-for-profit + corporation with a principal place of business in San Francisco, + California, as well as future copyleft versions of that license + published by that same organization. + + “Incorporate” means to publish or republish a Document, in whole or + in part, as part of another Document. + + An MMC is “eligible for relicensing” if it is licensed under this + License, and if all works that were first published under this + License somewhere other than this MMC, and subsequently + incorporated in whole or in part into the MMC, (1) had no cover + texts or invariant sections, and (2) were thus incorporated prior + to November 1, 2008. + + The operator of an MMC Site may republish an MMC contained in the + site under CC-BY-SA on the same site at any time before August 1, + 2009, provided the MMC is eligible for relicensing. + +ADDENDUM: How to use this License for your documents +==================================================== + +To use this License in a document you have written, include a copy of +the License in the document and put the following copyright and license +notices just after the title page: + + Copyright (C) YEAR YOUR NAME. + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.3 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover + Texts. A copy of the license is included in the section entitled ``GNU + Free Documentation License''. + + If you have Invariant Sections, Front-Cover Texts and Back-Cover +Texts, replace the “with...Texts.” line with this: + + with the Invariant Sections being LIST THEIR TITLES, with + the Front-Cover Texts being LIST, and with the Back-Cover Texts + being LIST. + + If you have Invariant Sections without Cover Texts, or some other +combination of the three, merge those two alternatives to suit the +situation. + + If your document contains nontrivial examples of program code, we +recommend releasing these examples in parallel under your choice of free +software license, such as the GNU General Public License, to permit +their use in free software. + + +File: dash.info, Node: GPL, Next: Index, Prev: FDL, Up: Top + +Appendix B GNU General Public License +************************************* + + Version 3, 29 June 2007 + + Copyright © 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. + + ONE LINE TO GIVE THE PROGRAM'S NAME AND A BRIEF IDEA OF WHAT IT DOES. + Copyright (C) YEAR NAME OF AUTHOR + + 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: + + PROGRAM Copyright (C) YEAR NAME OF AUTHOR + 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 . + + +File: dash.info, Node: Index, Prev: GPL, Up: Top Index ***** @@ -2981,7 +4321,6 @@ Index * !cons: Destructive operations. (line 6) * -->: Threading macros. (line 32) -* --doto: Side-effects. (line 81) * ->: Threading macros. (line 6) * ->>: Threading macros. (line 19) * -all?: Predicates. (line 18) @@ -3013,16 +4352,16 @@ Index (line 168) * -difference: Set operations. (line 20) * -distinct: Set operations. (line 62) -* -dotimes: Side-effects. (line 61) -* -doto: Side-effects. (line 70) -* -drop: Sublist selection. (line 124) -* -drop-last: Sublist selection. (line 136) -* -drop-while: Sublist selection. (line 157) -* -each: Side-effects. (line 8) -* -each-indexed: Side-effects. (line 28) -* -each-r: Side-effects. (line 41) -* -each-r-while: Side-effects. (line 52) -* -each-while: Side-effects. (line 19) +* -dotimes: Side effects. (line 72) +* -doto: Threading macros. (line 95) +* -drop: Sublist selection. (line 128) +* -drop-last: Sublist selection. (line 142) +* -drop-while: Sublist selection. (line 171) +* -each: Side effects. (line 8) +* -each-indexed: Side effects. (line 34) +* -each-r: Side effects. (line 47) +* -each-r-while: Side effects. (line 59) +* -each-while: Side effects. (line 21) * -elem-index: Indexing. (line 9) * -elem-indices: Indexing. (line 21) * -fifth-item: Other list operations. @@ -3036,7 +4375,7 @@ Index * -first-item: Other list operations. (line 271) * -fix: Other list operations. - (line 376) + (line 375) * -fixfn: Function combinators. (line 175) * -flatten: List to list. (line 33) @@ -3066,13 +4405,13 @@ Index * -juxt: Function combinators. (line 31) * -keep: List to list. (line 8) -* -lambda: Binding. (line 252) +* -lambda: Binding. (line 251) * -last: Other list operations. (line 261) * -last-item: Other list operations. (line 330) * -let: Binding. (line 65) -* -let*: Binding. (line 232) +* -let*: Binding. (line 231) * -list: Other list operations. (line 363) * -map: Maps. (line 10) @@ -3142,11 +4481,11 @@ Index * -same-items?: Predicates. (line 72) * -second-item: Other list operations. (line 286) -* -select-by-indices: Sublist selection. (line 168) -* -select-column: Sublist selection. (line 198) -* -select-columns: Sublist selection. (line 179) +* -select-by-indices: Sublist selection. (line 185) +* -select-column: Sublist selection. (line 215) +* -select-columns: Sublist selection. (line 196) * -separate: Partitioning. (line 63) -* -setq: Binding. (line 274) +* -setq: Binding. (line 273) * -slice: Sublist selection. (line 85) * -snoc: Other list operations. (line 44) @@ -3170,8 +4509,8 @@ Index (line 209) * -tails: Reductions. (line 213) * -take: Sublist selection. (line 101) -* -take-last: Sublist selection. (line 112) -* -take-while: Sublist selection. (line 146) +* -take-last: Sublist selection. (line 114) +* -take-while: Sublist selection. (line 156) * -third-item: Other list operations. (line 298) * -tree-map: Tree operations. (line 28) @@ -3196,211 +4535,216 @@ Index (line 119) * -zip-with: Other list operations. (line 79) +* dash-fontify-mode: Fontification of special variables. + (line 6) +* global-dash-fontify-mode: Fontification of special variables. + (line 12)  Tag Table: -Node: Top946 -Node: Installation2425 -Node: Using in a package2958 -Node: Syntax highlighting of dash functions3322 -Node: Functions3705 -Node: Maps4916 -Ref: -map5211 -Ref: -map-when5552 -Ref: -map-first6130 -Ref: -map-last6608 -Ref: -map-indexed7081 -Ref: -annotate7561 -Ref: -splice8051 -Ref: -splice-list8832 -Ref: -mapcat9294 -Ref: -copy9670 -Node: Sublist selection9874 -Ref: -filter10067 -Ref: -remove10519 -Ref: -remove-first10925 -Ref: -remove-last11452 -Ref: -remove-item11973 -Ref: -non-nil12368 -Ref: -slice12527 -Ref: -take13059 -Ref: -take-last13367 -Ref: -drop13690 -Ref: -drop-last13963 -Ref: -take-while14223 -Ref: -drop-while14573 -Ref: -select-by-indices14929 -Ref: -select-columns15443 -Ref: -select-column16149 -Node: List to list16613 -Ref: -keep16805 -Ref: -concat17308 -Ref: -flatten17605 -Ref: -flatten-n18364 -Ref: -replace18751 -Ref: -replace-first19214 -Ref: -replace-last19711 -Ref: -insert-at20201 -Ref: -replace-at20528 -Ref: -update-at20918 -Ref: -remove-at21409 -Ref: -remove-at-indices21897 -Node: Reductions22479 -Ref: -reduce-from22648 -Ref: -reduce-r-from23414 -Ref: -reduce24181 -Ref: -reduce-r24910 -Ref: -reductions-from25781 -Ref: -reductions-r-from26496 -Ref: -reductions27221 -Ref: -reductions-r27846 -Ref: -count28481 -Ref: -sum28705 -Ref: -running-sum28894 -Ref: -product29187 -Ref: -running-product29396 -Ref: -inits29709 -Ref: -tails29957 -Ref: -common-prefix30204 -Ref: -common-suffix30501 -Ref: -min30798 -Ref: -min-by31024 -Ref: -max31547 -Ref: -max-by31772 -Node: Unfolding32300 -Ref: -iterate32539 -Ref: -unfold32984 -Node: Predicates33792 -Ref: -any?33916 -Ref: -all?34236 -Ref: -none?34566 -Ref: -only-some?34868 -Ref: -contains?35353 -Ref: -same-items?35742 -Ref: -is-prefix?36127 -Ref: -is-suffix?36450 -Ref: -is-infix?36773 -Node: Partitioning37127 -Ref: -split-at37315 -Ref: -split-with37600 -Ref: -split-on38003 -Ref: -split-when38679 -Ref: -separate39319 -Ref: -partition39761 -Ref: -partition-all40213 -Ref: -partition-in-steps40641 -Ref: -partition-all-in-steps41138 -Ref: -partition-by41623 -Ref: -partition-by-header42005 -Ref: -partition-after-pred42609 -Ref: -partition-before-pred42953 -Ref: -partition-before-item43304 -Ref: -partition-after-item43615 -Ref: -group-by43921 -Node: Indexing44358 -Ref: -elem-index44560 -Ref: -elem-indices44955 -Ref: -find-index45338 -Ref: -find-last-index45827 -Ref: -find-indices46331 -Ref: -grade-up46739 -Ref: -grade-down47142 -Node: Set operations47552 -Ref: -union47735 -Ref: -difference48177 -Ref: -intersection48594 -Ref: -powerset49031 -Ref: -permutations49244 -Ref: -distinct49544 -Node: Other list operations49922 -Ref: -rotate50147 -Ref: -repeat50517 -Ref: -cons*50780 -Ref: -snoc51167 -Ref: -interpose51580 -Ref: -interleave51878 -Ref: -zip-with52247 -Ref: -zip52964 -Ref: -zip-lists53796 -Ref: -zip-fill54497 -Ref: -unzip54820 -Ref: -cycle55565 -Ref: -pad55938 -Ref: -table56261 -Ref: -table-flat57050 -Ref: -first58058 -Ref: -some58430 -Ref: -last58739 -Ref: -first-item59073 -Ref: -second-item59489 -Ref: -third-item59769 -Ref: -fourth-item60047 -Ref: -fifth-item60313 -Ref: -last-item60575 -Ref: -butlast60867 -Ref: -sort61114 -Ref: -list61603 -Ref: -fix61934 -Node: Tree operations62474 -Ref: -tree-seq62670 -Ref: -tree-map63528 -Ref: -tree-map-nodes63971 -Ref: -tree-reduce64821 -Ref: -tree-reduce-from65703 -Ref: -tree-mapreduce66304 -Ref: -tree-mapreduce-from67164 -Ref: -clone68450 -Node: Threading macros68778 -Ref: ->68923 -Ref: ->>69414 -Ref: -->69919 -Ref: -as->70475 -Ref: -some->70930 -Ref: -some->>71304 -Ref: -some-->71740 -Node: Binding72211 -Ref: -when-let72423 -Ref: -when-let*72908 -Ref: -if-let73431 -Ref: -if-let*73826 -Ref: -let74443 -Ref: -let*80533 -Ref: -lambda81473 -Ref: -setq82270 -Node: Side-effects83086 -Ref: -each83280 -Ref: -each-while83687 -Ref: -each-indexed84047 -Ref: -each-r84565 -Ref: -each-r-while84998 -Ref: -dotimes85373 -Ref: -doto85676 -Ref: --doto86104 -Node: Destructive operations86379 -Ref: !cons86552 -Ref: !cdr86758 -Node: Function combinators86953 -Ref: -partial87227 -Ref: -rpartial87623 -Ref: -juxt88026 -Ref: -compose88458 -Ref: -applify89011 -Ref: -on89442 -Ref: -flip89968 -Ref: -const90280 -Ref: -cut90619 -Ref: -not91105 -Ref: -orfn91415 -Ref: -andfn91849 -Ref: -iteratefn92344 -Ref: -fixfn93047 -Ref: -prodfn94610 -Node: Development95678 -Node: Contribute96027 -Node: Changes96775 -Node: Contributors99773 -Node: Index101392 +Node: Top742 +Node: Installation2397 +Node: Using in a package3162 +Node: Fontification of special variables3662 +Node: Functions4425 +Node: Maps5909 +Ref: -map6206 +Ref: -map-when6582 +Ref: -map-first7160 +Ref: -map-last7638 +Ref: -map-indexed8111 +Ref: -annotate8591 +Ref: -splice9081 +Ref: -splice-list9862 +Ref: -mapcat10324 +Ref: -copy10700 +Node: Sublist selection10904 +Ref: -filter11097 +Ref: -remove11549 +Ref: -remove-first11955 +Ref: -remove-last12482 +Ref: -remove-item13003 +Ref: -non-nil13398 +Ref: -slice13557 +Ref: -take14089 +Ref: -take-last14498 +Ref: -drop14931 +Ref: -drop-last15361 +Ref: -take-while15789 +Ref: -drop-while16315 +Ref: -select-by-indices16839 +Ref: -select-columns17353 +Ref: -select-column18059 +Node: List to list18523 +Ref: -keep18715 +Ref: -concat19218 +Ref: -flatten19515 +Ref: -flatten-n20274 +Ref: -replace20661 +Ref: -replace-first21124 +Ref: -replace-last21621 +Ref: -insert-at22111 +Ref: -replace-at22438 +Ref: -update-at22828 +Ref: -remove-at23319 +Ref: -remove-at-indices23807 +Node: Reductions24389 +Ref: -reduce-from24558 +Ref: -reduce-r-from25324 +Ref: -reduce26091 +Ref: -reduce-r26820 +Ref: -reductions-from27691 +Ref: -reductions-r-from28406 +Ref: -reductions29131 +Ref: -reductions-r29756 +Ref: -count30391 +Ref: -sum30615 +Ref: -running-sum30804 +Ref: -product31097 +Ref: -running-product31306 +Ref: -inits31619 +Ref: -tails31867 +Ref: -common-prefix32114 +Ref: -common-suffix32411 +Ref: -min32708 +Ref: -min-by32934 +Ref: -max33457 +Ref: -max-by33682 +Node: Unfolding34210 +Ref: -iterate34451 +Ref: -unfold34901 +Node: Predicates35709 +Ref: -any?35833 +Ref: -all?36153 +Ref: -none?36483 +Ref: -only-some?36785 +Ref: -contains?37270 +Ref: -same-items?37659 +Ref: -is-prefix?38044 +Ref: -is-suffix?38367 +Ref: -is-infix?38690 +Node: Partitioning39044 +Ref: -split-at39232 +Ref: -split-with39517 +Ref: -split-on39920 +Ref: -split-when40596 +Ref: -separate41236 +Ref: -partition41678 +Ref: -partition-all42130 +Ref: -partition-in-steps42558 +Ref: -partition-all-in-steps43055 +Ref: -partition-by43540 +Ref: -partition-by-header43922 +Ref: -partition-after-pred44526 +Ref: -partition-before-pred44870 +Ref: -partition-before-item45221 +Ref: -partition-after-item45532 +Ref: -group-by45838 +Node: Indexing46275 +Ref: -elem-index46477 +Ref: -elem-indices46872 +Ref: -find-index47255 +Ref: -find-last-index47744 +Ref: -find-indices48248 +Ref: -grade-up48656 +Ref: -grade-down49059 +Node: Set operations49469 +Ref: -union49652 +Ref: -difference50094 +Ref: -intersection50511 +Ref: -powerset50948 +Ref: -permutations51161 +Ref: -distinct51461 +Node: Other list operations51839 +Ref: -rotate52064 +Ref: -repeat52434 +Ref: -cons*52715 +Ref: -snoc53102 +Ref: -interpose53515 +Ref: -interleave53813 +Ref: -zip-with54182 +Ref: -zip54899 +Ref: -zip-lists55731 +Ref: -zip-fill56432 +Ref: -unzip56755 +Ref: -cycle57500 +Ref: -pad57902 +Ref: -table58225 +Ref: -table-flat59014 +Ref: -first60022 +Ref: -some60394 +Ref: -last60703 +Ref: -first-item61037 +Ref: -second-item61453 +Ref: -third-item61733 +Ref: -fourth-item62011 +Ref: -fifth-item62277 +Ref: -last-item62539 +Ref: -butlast62831 +Ref: -sort63078 +Ref: -list63567 +Ref: -fix63907 +Node: Tree operations64447 +Ref: -tree-seq64643 +Ref: -tree-map65501 +Ref: -tree-map-nodes65944 +Ref: -tree-reduce66794 +Ref: -tree-reduce-from67676 +Ref: -tree-mapreduce68277 +Ref: -tree-mapreduce-from69137 +Ref: -clone70423 +Node: Threading macros70751 +Ref: ->70896 +Ref: ->>71387 +Ref: -->71892 +Ref: -as->72448 +Ref: -some->72903 +Ref: -some->>73277 +Ref: -some-->73713 +Ref: -doto74184 +Node: Binding74740 +Ref: -when-let74952 +Ref: -when-let*75437 +Ref: -if-let75960 +Ref: -if-let*76355 +Ref: -let76972 +Ref: -let*83047 +Ref: -lambda83987 +Ref: -setq84783 +Node: Side effects85599 +Ref: -each85793 +Ref: -each-while86310 +Ref: -each-indexed86914 +Ref: -each-r87504 +Ref: -each-r-while87942 +Ref: -dotimes88565 +Node: Destructive operations89121 +Ref: !cons89294 +Ref: !cdr89500 +Node: Function combinators89695 +Ref: -partial89969 +Ref: -rpartial90363 +Ref: -juxt90766 +Ref: -compose91198 +Ref: -applify91751 +Ref: -on92182 +Ref: -flip92708 +Ref: -const93020 +Ref: -cut93359 +Ref: -not93845 +Ref: -orfn94155 +Ref: -andfn94589 +Ref: -iteratefn95084 +Ref: -fixfn95787 +Ref: -prodfn97350 +Node: Development98410 +Node: Contribute98763 +Node: Change log99769 +Node: Contributors107307 +Node: FDL109325 +Node: GPL134645 +Node: Index172394  End Tag Table diff --git a/lisp/dash/dir b/lisp/dash/dir index 49b1700d..7d473f49 100644 --- a/lisp/dash/dir +++ b/lisp/dash/dir @@ -15,4 +15,4 @@ File: dir, Node: Top This is the top of the INFO tree * Menu: Emacs -* Dash: (dash.info). A modern list library for GNU Emacs +* Dash: (dash.info). A modern list library for GNU Emacs. diff --git a/lisp/dashboard/dashboard-pkg.el b/lisp/dashboard/dashboard-pkg.el index 44d332ae..9a21024c 100644 --- a/lisp/dashboard/dashboard-pkg.el +++ b/lisp/dashboard/dashboard-pkg.el @@ -1,12 +1,12 @@ -(define-package "dashboard" "20200306.1344" "A startup screen extracted from Spacemacs" +(define-package "dashboard" "20210104.1605" "A startup screen extracted from Spacemacs" '((emacs "25.3") (page-break-lines "0.11")) - :commit "bf38867ae80902d58207974b4a2bba4249324599" :keywords - '("startup" "screen" "tools" "dashboard") - :authors + :commit "2b1ef13392be2f07d2a52636edf578b89512d501" :authors '(("Rakan Al-Hneiti")) :maintainer '("Rakan Al-Hneiti") + :keywords + '("startup" "screen" "tools" "dashboard") :url "https://github.com/emacs-dashboard/emacs-dashboard") ;; Local Variables: ;; no-byte-compile: t diff --git a/lisp/dashboard/dashboard-widgets.el b/lisp/dashboard/dashboard-widgets.el index a045ce78..6bdbc437 100644 --- a/lisp/dashboard/dashboard-widgets.el +++ b/lisp/dashboard/dashboard-widgets.el @@ -1,6 +1,8 @@ ;;; dashboard-widgets.el --- A startup screen extracted from Spacemacs -*- lexical-binding: t -*- -;; Copyright (c) 2016-2020 Rakan Al-Hneiti & Contributors +;; Copyright (c) 2016-2020 Rakan Al-Hneiti +;; Copyright (c) 2019-2020 Jesús Martínez +;; Copyright (c) 2020 Shen, Jen-Chieh ;; ;; Author: Rakan Al-Hneiti ;; URL: https://github.com/emacs-dashboard/emacs-dashboard @@ -16,7 +18,7 @@ ;;; Commentary: ;; An extensible Emacs dashboard, with sections for -;; bookmarks, projectile projects, org-agenda and more. +;; bookmarks, projects (projectile or project.el), org-agenda and more. ;;; Code: @@ -25,6 +27,8 @@ ;; Compiler pacifier (declare-function all-the-icons-icon-for-dir "ext:all-the-icons.el") (declare-function all-the-icons-icon-for-file "ext:all-the-icons.el") +(declare-function all-the-icons-fileicon "ext:data-fileicons.el") +(declare-function all-the-icons-octicon "ext:data-octicons.el") (declare-function bookmark-get-filename "ext:bookmark.el") (declare-function bookmark-all-names "ext:bookmark.el") (declare-function calendar-date-compare "ext:calendar.el") @@ -32,6 +36,8 @@ (declare-function projectile-load-known-projects "ext:projectile.el") (declare-function projectile-mode "ext:projectile.el") (declare-function projectile-relevant-known-projects "ext:projectile.el") +;;; project.el in Emacs 26 does not contain this function +(declare-function project-known-project-roots "ext:project.el" nil t) (declare-function org-agenda-format-item "ext:org-agenda.el") (declare-function org-compile-prefix-format "ext:org-agenda.el") (declare-function org-entry-is-done-p "ext:org.el") @@ -42,6 +48,12 @@ (declare-function org-get-tags "ext:org.el") (declare-function org-map-entries "ext:org.el") (declare-function org-outline-level "ext:org.el") +(declare-function org-today "ext:org.el") +(declare-function org-get-todo-face "ext:org.el") +(declare-function org-get-todo-state "ext:org.el") +(declare-function org-entry-is-todo-p "ext:org.el") +(defalias 'org-time-less-p 'time-less-p) +(defvar org-level-faces "ext:org-faces.el") (defvar all-the-icons-dir-icon-alist) (defvar package-activated-list) @@ -53,18 +65,20 @@ (defcustom dashboard-image-banner-max-height 0 "Maximum height of banner image. -This setting applies only if Emacs is compiled with Imagemagick -support. When value is non-zero the image banner will be resized -to the specified height, with aspect ratio preserved." +This setting applies only if Emacs supports image transforms or +compiled with Imagemagick support. When value is non-zero the image +banner will be resized to the specified height in pixels, with aspect +ratio preserved." :type 'integer :group 'dashboard) (defcustom dashboard-image-banner-max-width 0 "Maximum width of banner image. -This setting applies if Emacs is compiled with Imagemagick -support. When value is non-zero the image banner will be resized -to the specified width, with aspect ratio preserved." +This setting applies if Emacs supports image transforms or compiled +with Imagemagick support. When value is non-zero the image banner +will be resized to the specified width in pixels, with aspect ratio +preserved." :type 'integer :group 'dashboard) @@ -101,8 +115,7 @@ to the specified width, with aspect ratio preserved." "Happy coding!" "Vi Vi Vi, the editor of the beast" "Welcome to the church of Emacs" - "While any text editor can save your files,\ - only Emacs can save your soul" + "While any text editor can save your files, only Emacs can save your soul" "I showed you my source code, pls respond") "A list of messages, one of which dashboard chooses to display." :type 'list @@ -121,9 +134,8 @@ Example: :group 'dashboard) (defconst dashboard-banners-directory - (concat (file-name-directory - (locate-library "dashboard")) - "/banners/")) + (concat (file-name-directory (locate-library "dashboard")) "/banners/") + "Default banner directory.") (defconst dashboard-banner-official-png (expand-file-name (concat dashboard-banners-directory "emacs.png")) @@ -151,31 +163,20 @@ Example: :group 'dashboard) (defcustom dashboard-init-info - ;; Check if package.el was loaded and if package loading was enabled - (if (bound-and-true-p package-alist) - (format "%d packages loaded in %s" - (length package-activated-list) (emacs-init-time)) - (if (and (boundp 'straight--profile-cache) (hash-table-p straight--profile-cache)) - (format "%d packages loaded in %s" - (hash-table-size straight--profile-cache) (emacs-init-time)) - (format "Emacs started in %s" (emacs-init-time)))) + (let ((package-count 0) (time (emacs-init-time))) + (when (bound-and-true-p package-alist) + (setq package-count (length package-activated-list))) + (when (boundp 'straight--profile-cache) + (setq package-count (+ (hash-table-size straight--profile-cache) package-count))) + (if (zerop package-count) + (format "Emacs started in %s" time) + (format "%d packages loaded in %s" package-count time))) "Init info with packages loaded and init time." :type 'boolean :group 'dashboard) (defcustom dashboard-footer - (let ((list '("The one true editor, Emacs!" - "Who the hell uses VIM anyway? Go Evil!" - "Free as free speech, free as free Beer" - "Richard Stallman is proud of you" - "Happy coding!" - "Vi Vi Vi, the editor of the beast" - "Welcome to the church of Emacs" - "While any text editor can save your files,\ - only Emacs can save your soul" - "I showed you my source code, pls respond" - ))) - (nth (random (1- (1+ (length list)))) list)) + (nth (random (1- (1+ (length dashboard-footer-messages)))) dashboard-footer-messages) "A footer with some short message." :type 'string :group 'dashboard) @@ -198,11 +199,11 @@ Example: Default value is `official', it displays the Emacs logo. `logo' displays Emacs alternative logo. An integer value is the index of text -banner. A string value must be a path to a .PNG file. +banner. A string value must be a path to a .PNG or .TXT file. If the value is nil then no banner is displayed." :type '(choice (const :tag "offical" official) (const :tag "logo" logo) - (string :tag "a png path")) + (string :tag "a png or txt path")) :group 'dashboard) (defcustom dashboard-buffer-last-width nil @@ -210,11 +211,12 @@ If the value is nil then no banner is displayed." :type 'integer :group 'dashboard) -(defcustom dashboard-item-generators '((recents . dashboard-insert-recents) - (bookmarks . dashboard-insert-bookmarks) - (projects . dashboard-insert-projects) - (agenda . dashboard-insert-agenda) - (registers . dashboard-insert-registers)) +(defcustom dashboard-item-generators + '((recents . dashboard-insert-recents) + (bookmarks . dashboard-insert-bookmarks) + (projects . dashboard-insert-projects) + (agenda . dashboard-insert-agenda) + (registers . dashboard-insert-registers)) "Association list of items to how to generate in the startup buffer. Will be of the form `(list-type . list-function)'. Possible values for list-type are: `recents', `bookmarks', `projects', @@ -222,6 +224,19 @@ Possible values for list-type are: `recents', `bookmarks', `projects', :type '(repeat (alist :key-type symbol :value-type function)) :group 'dashboard) +(defcustom dashboard-projects-backend 'projectile + "The package that supplies the list of recent projects. +With the value `projectile', the projects widget uses the package +projectile (available in MELPA). With the value `project-el', +the widget uses the package project (available in GNU ELPA). + +To activate the projects widget, add e.g. `(projects . 10)' to +`dashboard-items' after making sure the necessary package is +installed." + :type '(choice (const :tag "Use projectile" projectile) + (const :tag "Use project.el" project-el)) + :group 'dashboard) + (defcustom dashboard-items '((recents . 5) (bookmarks . 5) (agenda . 5)) @@ -232,6 +247,19 @@ If nil it is disabled. Possible values for list-type are: :type '(repeat (alist :key-type symbol :value-type integer)) :group 'dashboard) +(defcustom dashboard-item-shortcuts '((recents . "r") + (bookmarks . "m") + (projects . "p") + (agenda . "a") + (registers . "e")) + "Association list of items and their corresponding shortcuts. +Will be of the form `(list-type . keys)' as understood by +`(kbd keys)'. If nil, shortcuts are disabled. If an entry's +value is nil, that item's shortcut is disbaled. See +`dashboard-items' for possible values of list-type.'" + :type '(repeat (alist :key-type symbol :value-type string)) + :group 'dashboard) + (defcustom dashboard-items-default-length 20 "Length used for startup lists with otherwise unspecified bounds. Set to nil for unbounded." @@ -250,8 +278,29 @@ If nil it is disabled. Possible values for list-type are: :type '(repeat (alist :key-type symbol :value-type string)) :group 'dashboard) +(defcustom dashboard-path-style nil + "Style to display path." + :type '(choice + (const :tag "No specify" nil) + (const :tag "Truncate the beginning part of the path" truncate-beginning) + (const :tag "Truncate the middle part of the path" truncate-middle) + (const :tag "Truncate the end part of the path" truncate-end)) + :group 'dashboard) + +(defcustom dashboard-path-max-length 70 + "Maximum length for path to display." + :type 'integer + :group 'dashboard) + +(defcustom dashboard-path-shorten-string "..." + "String the that displays in the center of the path." + :type 'string + :group 'dashboard) + (defvar recentf-list nil) +(defvar dashboard-buffer-name) + ;; ;; Faces ;; @@ -275,6 +324,16 @@ If nil it is disabled. Possible values for list-type are: "Face used for widget headings." :group 'dashboard) +(defface dashboard-items-face + '((t (:inherit widget-button))) + "Face used for items." + :group 'dashboard) + +(defface dashboard-no-items-face + '((t (:inherit widget-button))) + "Face used for no items." + :group 'dashboard) + (defface dashboard-footer '((t (:inherit font-lock-doc-face))) "Face used for widget headings." @@ -299,31 +358,45 @@ Return entire list if `END' is omitted." (cl-subseq seq start (and (number-or-marker-p end) (min len end))))) +(defun dashboard-get-shortcut (item) + "Get the shortcut to be used for ITEM." + (let ((elem (assq item dashboard-item-shortcuts))) + (and elem (cdr elem)))) + (defmacro dashboard-insert-shortcut (shortcut-char search-label &optional no-next-line) "Insert a shortcut SHORTCUT-CHAR for a given SEARCH-LABEL. Optionally, provide NO-NEXT-LINE to move the cursor forward a line." - `(progn - (eval-when-compile (defvar dashboard-mode-map)) - (let ((sym (make-symbol (format "Jump to \"%s\"" ,search-label)))) - (fset sym (lambda () - (interactive) - (unless (search-forward ,search-label (point-max) t) - (search-backward ,search-label (point-min) t)) - ,@(unless no-next-line - '((forward-line 1))) - (back-to-indentation))) + (let* (;; Ensure punctuation and upper case in search string is not + ;; used to construct the `defun' + (name (downcase (replace-regexp-in-string + "[[:punct:]]+" "" (format "%s" search-label) nil nil nil))) + ;; Ensure whitespace in e.g. "recent files" is replaced with dashes. + (sym (intern (format "dashboard-jump-to-%s" (replace-regexp-in-string + "[[:blank:]]+" "-" name nil nil nil))))) + `(progn + (eval-when-compile (defvar dashboard-mode-map)) + (defun ,sym nil + ,(concat + "Jump to " + name + ". This code is dynamically generated in `dashboard-insert-shortcut'.") + (interactive) + (unless (search-forward ,search-label (point-max) t) + (search-backward ,search-label (point-min) t)) + ,@(unless no-next-line + '((forward-line 1))) + (back-to-indentation)) (eval-after-load 'dashboard - (define-key dashboard-mode-map ,shortcut-char sym))))) + (define-key dashboard-mode-map ,shortcut-char ',sym))))) (defun dashboard-append (msg &optional _messagebuf) "Append MSG to dashboard buffer. If MESSAGEBUF is not nil then MSG is also written in message buffer." - (with-current-buffer (get-buffer-create "*dashboard*") + (with-current-buffer (get-buffer-create dashboard-buffer-name) (goto-char (point-max)) - (let ((buffer-read-only nil)) - (insert msg)))) + (let ((buffer-read-only nil)) (insert msg)))) (defun dashboard-modify-heading-icons (alist) "Append ALIST items to `dashboard-heading-icons' to modify icons." @@ -364,7 +437,7 @@ If MESSAGEBUF is not nil then MSG is also written in message buffer." (insert " ")) (insert (propertize heading 'face 'dashboard-heading)) - (if shortcut (insert (format " (%s)" shortcut)))) + (when shortcut (insert (format " (%s)" shortcut)))) (defun dashboard-center-line (string) "Center a STRING accoring to it's size." @@ -399,14 +472,18 @@ If MESSAGEBUF is not nil then MSG is also written in message buffer." "Display an image BANNER." (when (file-exists-p banner) (let* ((title dashboard-banner-logo-title) + (size-props + (append (when (> dashboard-image-banner-max-width 0) + (list :max-width dashboard-image-banner-max-width)) + (when (> dashboard-image-banner-max-height 0) + (list :max-height dashboard-image-banner-max-height)))) (spec (if (image-type-available-p 'imagemagick) - (apply 'create-image banner 'imagemagick nil - (append (when (> dashboard-image-banner-max-width 0) - (list :max-width dashboard-image-banner-max-width)) - (when (> dashboard-image-banner-max-height 0) - (list :max-height dashboard-image-banner-max-height)))) - (create-image banner))) + (apply 'create-image banner 'imagemagick nil size-props) + (apply 'create-image banner nil nil + (when (and (fboundp 'image-transforms-p) + (memq 'scale (funcall 'image-transforms-p))) + size-props)))) (size (image-size spec)) (width (car size)) (left-margin (max 0 (floor (- dashboard-banner-length width) 2)))) @@ -426,8 +503,7 @@ If MESSAGEBUF is not nil then MSG is also written in message buffer." "Insert init info when `dashboard-set-init-info' is t." (when dashboard-set-init-info (dashboard-center-line dashboard-init-info) - (insert - (propertize dashboard-init-info 'face 'font-lock-comment-face)))) + (insert (propertize dashboard-init-info 'face 'font-lock-comment-face)))) (defun dashboard-get-banner-path (index) "Return the full path to banner with index INDEX." @@ -446,14 +522,14 @@ If MESSAGEBUF is not nil then MSG is also written in message buffer." (dashboard-get-banner-path 1))) ((integerp dashboard-startup-banner) (dashboard-get-banner-path dashboard-startup-banner)) - ((and dashboard-startup-banner - (image-type-available-p (intern (file-name-extension - dashboard-startup-banner))) - (display-graphic-p)) - (if (file-exists-p dashboard-startup-banner) + ((stringp dashboard-startup-banner) + (if (and (file-exists-p dashboard-startup-banner) + (or (string-suffix-p ".txt" dashboard-startup-banner) + (and (display-graphic-p) + (image-type-available-p (intern (file-name-extension + dashboard-startup-banner)))))) dashboard-startup-banner - (message (format "could not find banner %s" - dashboard-startup-banner)) + (message "could not find banner %s, use default instead" dashboard-startup-banner) (dashboard-get-banner-path 1))) (t (dashboard-get-banner-path 1))))) @@ -462,13 +538,12 @@ If MESSAGEBUF is not nil then MSG is also written in message buffer." (goto-char (point-max)) (let ((banner (dashboard-choose-banner)) (buffer-read-only nil)) - (progn - (when banner - (if (image-type-available-p (intern (file-name-extension banner))) - (dashboard-insert-image-banner banner) - (dashboard-insert-ascii-banner-centered banner)) - (dashboard-insert-navigator) - (dashboard-insert-init-info))))) + (when banner + (if (image-type-available-p (intern (file-name-extension banner))) + (dashboard-insert-image-banner banner) + (dashboard-insert-ascii-banner-centered banner)) + (dashboard-insert-navigator) + (dashboard-insert-init-info)))) (defun dashboard-insert-navigator () "Insert Navigator of the dashboard." @@ -485,10 +560,11 @@ If MESSAGEBUF is not nil then MSG is also written in message buffer." (widget-create 'item :tag (concat (when icon - (propertize icon 'face `(:inherit - ,(get-text-property 0 'face icon) - :inherit - ,face))) + (propertize icon 'face + (let ((prop-face (get-text-property 0 'face icon))) + (if prop-face + `(:inherit ,prop-face :inherit ,face) + `(:inherit ,face))))) (when (and icon title (not (string-equal icon "")) (not (string-equal title ""))) @@ -496,7 +572,7 @@ If MESSAGEBUF is not nil then MSG is also written in message buffer." (when title (propertize title 'face face))) :help-echo help :action action - :button-face `(:underline nil) + :button-face 'dashboard-items-face :mouse-face 'highlight :button-prefix prefix :button-suffix suffix @@ -516,15 +592,16 @@ ACTION is theaction taken when the user activates the widget button. WIDGET-PARAMS are passed to the \"widget-create\" function." `(progn (dashboard-insert-heading ,section-name - (if (and ,list dashboard-show-shortcuts) ,shortcut)) + (if (and ,list ,shortcut dashboard-show-shortcuts) ,shortcut)) (if ,list - (when (dashboard-insert-section-list - ,section-name - (dashboard-subseq ,list 0 ,list-size) - ,action - ,@widget-params) + (when (and (dashboard-insert-section-list + ,section-name + (dashboard-subseq ,list 0 ,list-size) + ,action + ,@widget-params) + ,shortcut) (dashboard-insert-shortcut ,shortcut ,section-name)) - (insert "\n --- No items ---")))) + (insert (propertize "\n --- No items ---" 'face 'dashboard-no-items-face))))) ;; ;; Section list @@ -557,7 +634,7 @@ WIDGET-PARAMS are passed to the \"widget-create\" function." (widget-create 'item :tag tag :action ,action - :button-face `(:underline nil) + :button-face 'dashboard-items-face :mouse-face 'highlight :button-prefix "" :button-suffix "" @@ -580,135 +657,390 @@ WIDGET-PARAMS are passed to the \"widget-create\" function." (insert (propertize footer 'face 'dashboard-footer)) (insert "\n")))) +;; +;; Truncate +;; +(defun dashboard-f-filename (path) + "Return file name from PATH." + (file-name-nondirectory path)) + +(defun dashboard-f-base (path) + "Return directory name from PATH." + (file-name-nondirectory (directory-file-name (file-name-directory path)))) + +(defun dashboard-shorten-path-beginning (path) + "Shorten PATH from beginning if exceeding maximum length." + (let* ((len-path (length path)) (len-rep (length dashboard-path-shorten-string)) + (len-total (- dashboard-path-max-length len-rep)) + front) + (if (<= len-path dashboard-path-max-length) path + (setq front (ignore-errors (substring path (- len-path len-total) len-path))) + (if front (concat dashboard-path-shorten-string front) "")))) + +(defun dashboard-shorten-path-middle (path) + "Shorten PATH from middle if exceeding maximum length." + (let* ((len-path (length path)) (len-rep (length dashboard-path-shorten-string)) + (len-total (- dashboard-path-max-length len-rep)) + (center (/ len-total 2)) + (end-back center) + (start-front (- len-path center)) + back front) + (if (<= len-path dashboard-path-max-length) path + (setq back (substring path 0 end-back) + front (ignore-errors (substring path start-front len-path))) + (if front (concat back dashboard-path-shorten-string front) "")))) + +(defun dashboard-shorten-path-end (path) + "Shorten PATH from end if exceeding maximum length." + (let* ((len-path (length path)) (len-rep (length dashboard-path-shorten-string)) + (len-total (- dashboard-path-max-length len-rep)) + back) + (if (<= len-path dashboard-path-max-length) path + (setq back (ignore-errors (substring path 0 len-total))) + (if (and back (< 0 dashboard-path-max-length)) + (concat back dashboard-path-shorten-string) "")))) + +(defun dashboard-shorten-path (path) + "Shorten the PATH." + (setq path (abbreviate-file-name path)) + (cl-case dashboard-path-style + (truncate-beginning (dashboard-shorten-path-beginning path)) + (truncate-middle (dashboard-shorten-path-middle path)) + (truncate-end (dashboard-shorten-path-end path)) + (t path))) + +(defun dashboard-shorten-paths (paths alist) + "Shorten all path from PATHS and store it to ALIST." + (let (lst-display abbrev (index 0)) + (setf (symbol-value alist) nil) ; reset + (dolist (item paths) + (setq abbrev (dashboard-shorten-path item) + ;; Add salt here, and use for extraction. + ;; See function `dashboard-extract-key-path-alist'. + abbrev (format "%s|%s" index abbrev)) + ;; store `abbrev' as id; and `item' with value + (push (cons abbrev item) (symbol-value alist)) + (push abbrev lst-display) + (cl-incf index)) + (reverse lst-display))) + +(defun dashboard-extract-key-path-alist (key alist) + "Remove salt from KEY, and return true shorten path from ALIST." + (let* ((key (car (assoc key alist))) (split (split-string key "|"))) + (nth 1 split))) + +(defun dashboard-expand-path-alist (key alist) + "Get the full path (un-shorten) using KEY from ALIST." + (cdr (assoc key alist))) + +(defun dashboard--generate-align-format (fmt len) + "Return FMT after inserting align LEN." + (let ((pos (1+ (string-match-p "%s" fmt)))) + (concat (substring fmt 0 pos) + (concat "-" (number-to-string len)) + (substring fmt pos (length fmt))))) + +(defun dashboard--get-align-length (alist &optional dir) + "Return maximum align length from ALIST. + +If optional argument DIR is non-nil; align with directory name instead." + (let ((align-length -1) path len-path) + (dolist (item alist) + (setq path (cdr item) + path (if dir (dashboard-f-base path) (dashboard-f-filename path)) + len-path (length path) + align-length (max len-path align-length))) + align-length)) + ;; ;; Recentf ;; +(defcustom dashboard-recentf-show-base nil + "Show the base file name infront of it's path." + :type '(choice + (const :tag "Don't show the base infront" nil) + (const :tag "Respect format" t) + (const :tag "Align the from base" align)) + :group 'dashboard) + +(defcustom dashboard-recentf-item-format "%s %s" + "Format to use when showing the base of the file name." + :type 'string + :group 'dashboard) + +(defvar dashboard-recentf-alist nil + "Alist records shorten's recent files and it's full paths.") + +(defvar dashboard--recentf-cache-item-format nil + "Cache to record the new generated align format.") + (defun dashboard-insert-recents (list-size) "Add the list of LIST-SIZE items from recently edited files." + (setq dashboard--recentf-cache-item-format nil) (recentf-mode) (dashboard-insert-section "Recent Files:" - recentf-list + (dashboard-shorten-paths recentf-list 'dashboard-recentf-alist) list-size - "r" - `(lambda (&rest ignore) (find-file-existing ,el)) - (abbreviate-file-name el))) + (dashboard-get-shortcut 'recents) + `(lambda (&rest ignore) + (find-file-existing (dashboard-expand-path-alist ,el dashboard-recentf-alist))) + (let* ((file (dashboard-expand-path-alist el dashboard-recentf-alist)) + (filename (dashboard-f-filename file)) + (path (dashboard-extract-key-path-alist el dashboard-recentf-alist))) + (cl-case dashboard-recentf-show-base + (align + (unless dashboard--recentf-cache-item-format + (let* ((len-align (dashboard--get-align-length dashboard-recentf-alist)) + (new-fmt (dashboard--generate-align-format + dashboard-recentf-item-format len-align))) + (setq dashboard--recentf-cache-item-format new-fmt))) + (format dashboard--recentf-cache-item-format filename path)) + (nil (format dashboard-recentf-item-format filename path)) + (t path))))) ;; ;; Bookmarks ;; +(defvar dashboard-bookmark-alist nil + "Alist records shorten's recent files and it's full paths.") + (defun dashboard-insert-bookmarks (list-size) "Add the list of LIST-SIZE items of bookmarks." (require 'bookmark) (dashboard-insert-section "Bookmarks:" - (dashboard-subseq (bookmark-all-names) - 0 list-size) + (dashboard-subseq (bookmark-all-names) 0 list-size) list-size - "m" + (dashboard-get-shortcut 'bookmarks) `(lambda (&rest ignore) (bookmark-jump ,el)) (let ((file (bookmark-get-filename el))) (if file - (format "%s - %s" el (abbreviate-file-name file)) + (format "%s - %s" el (dashboard-shorten-path file)) el)))) ;; -;; Projectile +;; Projects ;; +(defcustom dashboard-projects-switch-function + nil + "Custom function to switch to projects from dashboard. +If non-NIL, should be bound to a function with one argument. The +function will be called with the root directory of the project to +switch to." + :type '(choice (const :tag "Default" nil) function) + :group 'dashboard) + +(defcustom dashboard-projects-show-base nil + "Show the project name infront of it's path." + :type '(choice + (const :tag "Don't show the base infront" nil) + (const :tag "Respect format" t) + (const :tag "Align the from base" align)) + :group 'dashboard) + +(defcustom dashboard-projects-item-format "%s %s" + "Format to use when showing the base of the project name." + :type 'string + :group 'dashboard) + +(defvar dashboard-projects-alist nil + "Alist records the shorten's project paths and it's full paths.") + +(defvar dashboard--projects-cache-item-format nil + "Cache to record the new generated align format.") + (defun dashboard-insert-projects (list-size) "Add the list of LIST-SIZE items of projects." - (require 'projectile) - (let ((inhibit-message t) (message-log-max nil)) - (projectile-cleanup-known-projects)) - (projectile-load-known-projects) + (setq dashboard--projects-cache-item-format nil) (dashboard-insert-section "Projects:" - (dashboard-subseq (projectile-relevant-known-projects) - 0 list-size) + (dashboard-shorten-paths + (dashboard-subseq (dashboard-projects-backend-load-projects) 0 list-size) + 'dashboard-projects-alist) list-size - "p" - `(lambda (&rest ignore) (projectile-switch-project-by-name ,el)) - (abbreviate-file-name el))) + (dashboard-get-shortcut 'projects) + `(lambda (&rest ignore) + (funcall (dashboard-projects-backend-switch-function) + (dashboard-expand-path-alist ,el dashboard-projects-alist))) + (let* ((file (dashboard-expand-path-alist el dashboard-projects-alist)) + (filename (dashboard-f-base file)) + (path (dashboard-extract-key-path-alist el dashboard-projects-alist))) + (cl-case dashboard-projects-show-base + (align + (unless dashboard--projects-cache-item-format + (let* ((len-align (dashboard--get-align-length dashboard-projects-alist t)) + (new-fmt (dashboard--generate-align-format + dashboard-projects-item-format len-align))) + (setq dashboard--projects-cache-item-format new-fmt))) + (format dashboard--projects-cache-item-format filename path)) + (nil (format dashboard-projects-item-format filename path)) + (t path))))) +(defun dashboard-projects-backend-load-projects () + "Depending on `dashboard-projects-backend' load corresponding backend. +Return function that returns a list of projects." + (cond + ((eq dashboard-projects-backend 'projectile) + (require 'projectile) + (let ((inhibit-message t) (message-log-max nil)) + (projectile-cleanup-known-projects)) + (projectile-load-known-projects)) + ((eq dashboard-projects-backend 'project-el) + (require 'project) + (project-known-project-roots)) + (t + (display-warning '(dashboard) + "Invalid value for `dashboard-projects-backend'" + :error)))) + +(defun dashboard-projects-backend-switch-function () + "Return the function to switch to a project. +Custom variable `dashboard-projects-switch-function' variable takes preference +over custom backends." + (or dashboard-projects-switch-function + (cond + ((eq dashboard-projects-backend 'projectile) + 'projectile-switch-project-by-name) + ((eq dashboard-projects-backend 'project-el) + (lambda (project) + "This function is used to switch to `PROJECT'." + (let ((default-directory project)) + (project-find-file)))) + (t + (display-warning '(dashboard) + "Invalid value for `dashboard-projects-backend'" + :error))))) ;; ;; Org Agenda ;; -(defun dashboard-timestamp-to-gregorian-date (timestamp) - "Convert TIMESTAMP to a gregorian date. +(defcustom dashboard-week-agenda t + "Show agenda weekly if its not nil." + :type 'boolean + :group 'dashboard) -The result can be used with functions like -`calendar-date-compare'." - (let ((decoded-timestamp (decode-time timestamp))) - (list (nth 4 decoded-timestamp) - (nth 3 decoded-timestamp) - (nth 5 decoded-timestamp)))) +(defcustom dashboard-agenda-time-string-format "%Y-%m-%d" + "Format time of agenda entries." + :type 'string + :group 'dashboard) -(defun dashboard-date-due-p (timestamp &optional due-date) - "Check if TIMESTAMP is today or in the past. +(defcustom dashboard-match-agenda-entry nil + "Match agenda to extra filter. +It is the MATCH attribute for `org-map-entries'" + :type 'string + :group 'dashboard) -If DUE-DATE is nil, compare TIMESTAMP to today; otherwise, -compare to the date in DUE-DATE. +(defun dashboard-agenda-entry-time (schedule-time) + "Format SCHEDULE-TIME with custom format. +If SCHEDULE-TIME is nil returns a blank string which length +is todays date format." + (let* ((time (or schedule-time (org-today))) + (formated-time (format-time-string + dashboard-agenda-time-string-format time))) + (if schedule-time + formated-time + (replace-regexp-in-string "." " " formated-time)))) -The time part of both TIMESTAMP and DUE-DATE is ignored, only the -date part is considered." - (unless due-date - (setq due-date (current-time))) - (setq due-date (time-add due-date 86400)) - (let* ((gregorian-date (dashboard-timestamp-to-gregorian-date timestamp)) - (gregorian-due-date (dashboard-timestamp-to-gregorian-date due-date))) - (calendar-date-compare (list gregorian-date) - (list gregorian-due-date)))) +(defun dashboard-agenda-entry-format () + "Format agenda entry to show it on dashboard." + (let* ((schedule-time (org-get-scheduled-time (point))) + (deadline-time (org-get-deadline-time (point))) + (item (org-agenda-format-item + (dashboard-agenda-entry-time (or schedule-time deadline-time)) + (org-get-heading) + (org-outline-level) + (org-get-category) + (org-get-tags) + t)) + (loc (point)) + (file (buffer-file-name))) + (dashboard-agenda--set-agenda-headline-face item) + (list item loc file))) + +(defun dashboard-agenda--set-agenda-headline-face (headline) + "Set agenda faces to `HEADLINE' when face text property is nil." + (let ((todo (org-get-todo-state)) + (org-level-face (nth (- (org-outline-level) 1) org-level-faces))) + (dashboard-agenda--set-face-when-match org-level-face + (org-get-heading t t t t) + headline) + (dashboard-agenda--set-face-when-match (org-get-todo-face todo) + todo + headline))) + +(defun dashboard-agenda--set-face-when-match (face text entry) + "Set `FACE' to match text between `TEXT' and `ENTRY'. +Do nothing if `TEXT' has already a face property or is nil." + (let ((match-part (and text (string-match text entry)))) + (when (and match-part (null (get-text-property 0 'face text))) + (add-face-text-property (match-beginning 0) (match-end 0) + face t entry)))) + +(defun dashboard-due-date-for-agenda () + "Return due-date for agenda period." + (if dashboard-week-agenda + (time-add (current-time) (* 86400 8)) + (time-add (current-time) 86400))) + +(defun dashboard-filter-agenda-by-time () + "Include entry if it has a schedule-time or deadline-time in the future. +An entry is included if this function returns nil and excluded +if returns a point." + (let ((schedule-time (org-get-scheduled-time (point))) + (deadline-time (org-get-deadline-time (point))) + (due-date (dashboard-due-date-for-agenda))) + (unless (and (not (org-entry-is-done-p)) + (or (and schedule-time + (org-time-less-p schedule-time due-date)) + (and deadline-time + (org-time-less-p deadline-time due-date)))) + (point)))) + +(defun dashboard-filter-agenda-by-todo () + "Include entry if it is todo and not done. +An entry is included if this function returns nil and excluded +if returns a point." + (unless (and (org-entry-is-todo-p) + (not (org-entry-is-done-p))) + (point))) + +(defun dashboard-no-filter-agenda () + "No filter agenda entries." + (when (org-entry-is-done-p) (point))) + +(defcustom dashboard-filter-agenda-entry 'dashboard-filter-agenda-by-time + "Function to filter `org-agenda' entries." + :type '(choice + (const :tag "No filter" dashboard-no-filter-agenda) + (const :tag "Filter by time" dashboard-filter-agenda-by-time) + (const :tag "Filter by todo" dashboard-filter-agenda-by-todo) + (function :tag "Custom function")) + :group 'dashboard) (defun dashboard-get-agenda () "Get agenda items for today or for a week from now." (org-compile-prefix-format 'agenda) - (let ((due-date nil)) - (if (and (boundp 'show-week-agenda-p) show-week-agenda-p) - (setq due-date (time-add (current-time) (* 86400 7))) - (setq due-date nil) - ) - (let* ((filtered-entries nil)) - (org-map-entries - (lambda () - (let* ((schedule-time (org-get-scheduled-time (point))) - (deadline-time (org-get-deadline-time (point))) - (item (org-agenda-format-item - (format-time-string "%Y-%m-%d" schedule-time) - (org-get-heading t t) - (org-outline-level) - (org-get-category) - (org-get-tags) - t)) - (loc (point)) - (file (buffer-file-name))) - (if (or (equal dashboard-org-agenda-categories nil) - (member (org-get-category) dashboard-org-agenda-categories)) - (when (and (not (org-entry-is-done-p)) - (or (and schedule-time (dashboard-date-due-p schedule-time due-date)) - (and deadline-time (dashboard-date-due-p deadline-time due-date)))) - (setq filtered-entries - (append filtered-entries - (list (list item schedule-time deadline-time loc file)))))))) - nil - 'agenda) - filtered-entries))) + (org-map-entries 'dashboard-agenda-entry-format + dashboard-match-agenda-entry + 'agenda + dashboard-filter-agenda-entry)) (defun dashboard-insert-agenda (list-size) "Add the list of LIST-SIZE items of agenda." (require 'org-agenda) - (require 'calendar) (let ((agenda (dashboard-get-agenda))) (dashboard-insert-section - (or (and (boundp 'show-week-agenda-p) show-week-agenda-p "Agenda for the coming week:") - "Agenda for today:") + (if dashboard-week-agenda + "Agenda for the coming week:" + "Agenda for today:") agenda list-size - "a" + (dashboard-get-shortcut 'agenda) `(lambda (&rest ignore) - (let ((buffer (find-file-other-window (nth 4 ',el)))) + (let ((buffer (find-file-other-window (nth 2 ',el)))) (with-current-buffer buffer - (goto-char (nth 3 ',el))) - (switch-to-buffer buffer))) + (goto-char (nth 1 ',el)) + (switch-to-buffer buffer)))) (format "%s" (nth 0 el))))) ;; @@ -721,7 +1053,7 @@ date part is considered." "Registers:" register-alist list-size - "e" + (dashboard-get-shortcut 'registers) (lambda (&rest _ignore) (jump-to-register (car el))) (format "%c - %s" (car el) (register-describe-oneline (car el))))) diff --git a/lisp/dashboard/dashboard.el b/lisp/dashboard/dashboard.el index 56b64180..091daafb 100644 --- a/lisp/dashboard/dashboard.el +++ b/lisp/dashboard/dashboard.el @@ -1,6 +1,8 @@ ;;; dashboard.el --- A startup screen extracted from Spacemacs -*- lexical-binding: t -*- -;; Copyright (c) 2016-2020 Rakan Al-Hneiti & Contributors +;; Copyright (c) 2016-2020 Rakan Al-Hneiti +;; Copyright (c) 2019-2020 Jesús Martínez +;; Copyright (c) 2020 Shen, Jen-Chieh ;; ;; Author: Rakan Al-Hneiti ;; URL: https://github.com/emacs-dashboard/emacs-dashboard @@ -16,12 +18,11 @@ ;;; Commentary: ;; An extensible Emacs dashboard, with sections for -;; bookmarks, projectile projects, org-agenda and more. +;; bookmarks, projects (projectile or project.el), org-agenda and more. ;;; Code: (require 'seq) -(require 'page-break-lines) (require 'recentf) (require 'dashboard-widgets) @@ -39,13 +40,18 @@ (define-key map (kbd "C-i") 'widget-forward) (define-key map [backtab] 'widget-backward) (define-key map (kbd "RET") 'dashboard-return) - (define-key map [down-mouse-1] 'widget-button-click) + (define-key map [mouse-1] 'dashboard-mouse-1) (define-key map (kbd "g") #'dashboard-refresh-buffer) (define-key map (kbd "}") #'dashboard-next-section) (define-key map (kbd "{") #'dashboard-previous-section) map) "Keymap for dashboard mode.") +(defcustom dashboard-after-initialize-hook nil + "Hook that is run after dashboard buffer is initialized." + :group 'dashboard + :type 'hook) + (define-derived-mode dashboard-mode special-mode "Dashboard" "Dashboard major mode for startup screen. \\ @@ -59,8 +65,8 @@ (when (>= emacs-major-version 26) (display-line-numbers-mode -1)) (page-break-lines-mode 1) - (setq inhibit-startup-screen t) - (setq buffer-read-only t + (setq inhibit-startup-screen t + buffer-read-only t truncate-lines t)) (defgroup dashboard nil @@ -153,6 +159,13 @@ Optional prefix ARG says how many lines to move; default is one line." (widget-button-press entry-pt) (call-interactively #'widget-button-press)))) +(defun dashboard-mouse-1 () + "Key for keymap `mouse-1'." + (interactive) + (let ((old-track-mouse track-mouse)) + (when (call-interactively #'widget-button-click) + (setq track-mouse old-track-mouse)))) + (defun dashboard-maximum-section-length () "For the just-inserted section, calculate the length of the longest line." (let ((max-line-length 0)) @@ -162,7 +175,7 @@ Optional prefix ARG says how many lines to move; default is one line." (setq max-line-length (max max-line-length (- (line-end-position) (line-beginning-position)))) - (forward-line))) + (forward-line 1))) max-line-length)) (defun dashboard-insert-startupify-lists () @@ -180,8 +193,8 @@ Optional prefix ARG says how many lines to move; default is one line." ;; then restore the orginal list afterwards ;; (this avoids many saves/loads that would result from ;; disabling/enabling recentf-mode) - (if recentf-is-on - (setq recentf-list (seq-take recentf-list dashboard-num-recents))) + (when recentf-is-on + (setq recentf-list (seq-take recentf-list dashboard-num-recents))) (when (or (not (eq dashboard-buffer-last-width (window-width))) (not buffer-exists)) (setq dashboard-banner-length (window-width) @@ -208,16 +221,16 @@ Optional prefix ARG says how many lines to move; default is one line." (when dashboard-center-content (when dashboard--section-starts (goto-char (car (last dashboard--section-starts)))) - (let ((margin (floor (/ (max (- (window-width) max-line-length) 0) 2)))) + (let ((margin (floor (/ (max (- (window-width) max-line-length) 0) 2)))) (while (not (eobp)) - (and (not (eq ? (char-after))) - (insert (make-string margin ?\ ))) + (unless (string-suffix-p (thing-at-point 'line) dashboard-page-separator) + (insert (make-string margin ?\ ))) (forward-line 1)))) (dashboard-insert-footer)) - (dashboard-mode) - (goto-char (point-min)))) - (if recentf-is-on - (setq recentf-list origial-recentf-list)))) + (goto-char (point-min)) + (dashboard-mode))) + (when recentf-is-on + (setq recentf-list origial-recentf-list)))) (add-hook 'window-setup-hook (lambda () @@ -227,7 +240,8 @@ Optional prefix ARG says how many lines to move; default is one line." (defun dashboard-refresh-buffer () "Refresh buffer." (interactive) - (kill-buffer dashboard-buffer-name) + (when (get-buffer dashboard-buffer-name) + (kill-buffer dashboard-buffer-name)) (dashboard-insert-startupify-lists) (switch-to-buffer dashboard-buffer-name)) @@ -245,14 +259,15 @@ Optional prefix ARG says how many lines to move; default is one line." "Setup post initialization hooks. If a command line argument is provided, assume a filename and skip displaying Dashboard." - (when (< (length command-line-args) 2 ) + (when (< (length command-line-args) 2) (add-hook 'after-init-hook (lambda () ;; Display useful lists of items (dashboard-insert-startupify-lists))) (add-hook 'emacs-startup-hook '(lambda () - (switch-to-buffer "*dashboard*") + (switch-to-buffer dashboard-buffer-name) (goto-char (point-min)) - (redisplay))))) + (redisplay) + (run-hooks 'dashboard-after-initialize-hook))))) (provide 'dashboard) ;;; dashboard.el ends here diff --git a/lisp/deft.el b/lisp/deft.el index e07435e5..570b550f 100644 --- a/lisp/deft.el +++ b/lisp/deft.el @@ -27,8 +27,8 @@ ;; POSSIBILITY OF SUCH DAMAGE. ;;; Version: 0.8 -;; Package-Version: 20200515.1513 -;; Package-Commit: fca9ea05ef4fdac825e2ad3921baa7042f6b82c8 +;; Package-Version: 20210101.1519 +;; Package-Commit: c4af44827f4257e7619e63abfd22094a29a9ab52 ;;; Author: Jason R. Blevins ;;; Keywords: plain text, notes, Simplenote, Notational Velocity ;;; URL: https://jblevins.org/projects/deft/ @@ -548,7 +548,7 @@ ;;; Code: -(require 'cl) +(require 'cl-lib) (require 'widget) (require 'wid-edit) @@ -1367,7 +1367,7 @@ name." (fmt (concat slug "_%d")) (counter 1) (file (deft-absolute-filename slug))) - (while (or (file-exists-p file) (get-file-buffer file)) + (while (or (file-exists-p file) (get-file-buffer (file-truename file))) (setq counter (1+ counter)) (setq slug (format fmt counter)) (setq file (deft-absolute-filename slug))) @@ -1375,9 +1375,9 @@ name." (defun deft-update-visiting-buffers (old new) "Rename visited file of buffers visiting file OLD to NEW." - (let ((buffer (get-file-buffer old))) + (let ((buffer (get-file-buffer (file-truename old)))) (when buffer - (with-current-buffer (get-file-buffer old) + (with-current-buffer (get-file-buffer (file-truename old)) (set-visited-file-name new nil t) (hack-local-variables))))) @@ -1386,7 +1386,7 @@ name." When OTHER is non-nil, open the file in another window. When OTHER and SWITCH are both non-nil, switch to the other window. FILE must be a relative or absolute path, with extension." - (let ((buffer (find-file-noselect file))) + (let ((buffer (find-file-noselect (file-truename file)))) (with-current-buffer buffer (hack-local-variables) (when deft-filter-regexp @@ -1456,7 +1456,7 @@ SLUG is the short file name, without a path or a file extension." (deft-cache-update-file file) (deft-refresh-filter) (deft-open-file file) - (with-current-buffer (get-file-buffer file) + (with-current-buffer (get-file-buffer (file-truename file)) (goto-char (point-max)))))) ;;;###autoload @@ -1498,7 +1498,7 @@ proceeding." (when filename (when (y-or-n-p (concat "Delete file " (file-name-nondirectory filename) "? ")) - (let ((buffer (get-file-buffer filename))) + (let ((buffer (get-file-buffer (file-truename filename)))) (when buffer (kill-buffer buffer))) (delete-file filename) (delq filename deft-current-files) @@ -1576,7 +1576,7 @@ all elements." (when title (insert title)) (when contents (insert contents))) (if batch - (if (every (lambda (filter) + (if (cl-every (lambda (filter) (goto-char (point-min)) (deft-search-forward filter)) deft-filter-regexp) @@ -1859,7 +1859,6 @@ Turning on `deft-mode' runs the hook `deft-mode-hook'. (provide 'deft) ;; Local Variables: -;; byte-compile-warnings: (not cl-functions) ;; indent-tabs-mode: nil ;; End: diff --git a/lisp/diff-hl/diff-hl-amend.el b/lisp/diff-hl/diff-hl-amend.el index defb3f45..c58a2bd6 100644 --- a/lisp/diff-hl/diff-hl-amend.el +++ b/lisp/diff-hl/diff-hl-amend.el @@ -16,7 +16,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: @@ -31,7 +31,7 @@ (define-minor-mode diff-hl-amend-mode "Show changes against the second-last revision in `diff-hl-mode'. Most useful with backends that support rewriting local commits, -and most importantly, 'amending' the most recent one. +and most importantly, \"amending\" the most recent one. Currently only supports Git, Mercurial and Bazaar." :lighter " Amend" (if diff-hl-amend-mode @@ -39,7 +39,7 @@ Currently only supports Git, Mercurial and Bazaar." (diff-hl-amend-setup) (add-hook 'after-revert-hook 'diff-hl-amend-setup nil t)) (remove-hook 'after-revert-hook 'diff-hl-amend-setup t) - (setq-local diff-hl-reference-revision nil)) + (kill-local-variable 'diff-hl-reference-revision)) (when diff-hl-mode (diff-hl-update))) @@ -57,7 +57,8 @@ Currently only supports Git, Mercurial and Bazaar." ;;;###autoload (define-globalized-minor-mode global-diff-hl-amend-mode diff-hl-amend-mode - turn-on-diff-hl-amend-mode) + turn-on-diff-hl-amend-mode + :group 'diff-hl) (defun turn-on-diff-hl-amend-mode () "Turn on `diff-hl-amend-mode' in a buffer if appropriate." diff --git a/lisp/diff-hl/diff-hl-dired.el b/lisp/diff-hl/diff-hl-dired.el index 947c2b6a..af2df466 100644 --- a/lisp/diff-hl/diff-hl-dired.el +++ b/lisp/diff-hl/diff-hl-dired.el @@ -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 GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;;; Commentary: diff --git a/lisp/diff-hl/diff-hl-flydiff.el b/lisp/diff-hl/diff-hl-flydiff.el index c09293a0..3f8c9260 100644 --- a/lisp/diff-hl/diff-hl-flydiff.el +++ b/lisp/diff-hl/diff-hl-flydiff.el @@ -16,7 +16,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/diff-hl/diff-hl-margin.el b/lisp/diff-hl/diff-hl-margin.el index e3fd9c81..a3b8b9e5 100644 --- a/lisp/diff-hl/diff-hl-margin.el +++ b/lisp/diff-hl/diff-hl-margin.el @@ -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 GNU Emacs. If not, see . +;; along with GNU Emacs. If not, see . ;;; Commentary: diff --git a/lisp/diff-hl/diff-hl-pkg.el b/lisp/diff-hl/diff-hl-pkg.el index 009298fd..ea2f2369 100644 --- a/lisp/diff-hl/diff-hl-pkg.el +++ b/lisp/diff-hl/diff-hl-pkg.el @@ -1,12 +1,12 @@ -(define-package "diff-hl" "20200604.1223" "Highlight uncommitted changes using VC" +(define-package "diff-hl" "20210107.220" "Highlight uncommitted changes using VC" '((cl-lib "0.2") (emacs "24.3")) - :commit "176f931a9bfc6bc6fc5360c6ed7128ff96b21289" :keywords - '("vc" "diff") - :authors + :commit "89aeb2fc8b24b6c4de4394f85041c5dd5fa60dad" :authors '(("Dmitry Gutov" . "dgutov@yandex.ru")) :maintainer '("Dmitry Gutov" . "dgutov@yandex.ru") + :keywords + '("vc" "diff") :url "https://github.com/dgutov/diff-hl") ;; Local Variables: ;; no-byte-compile: t diff --git a/lisp/diff-hl/diff-hl.el b/lisp/diff-hl/diff-hl.el index 94b9f734..bf82254c 100644 --- a/lisp/diff-hl/diff-hl.el +++ b/lisp/diff-hl/diff-hl.el @@ -5,7 +5,7 @@ ;; Author: Dmitry Gutov ;; URL: https://github.com/dgutov/diff-hl ;; Keywords: vc, diff -;; Version: 1.8.7 +;; Version: 1.8.8 ;; Package-Requires: ((cl-lib "0.2") (emacs "24.3")) ;; This file is part of GNU Emacs. @@ -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: @@ -35,6 +35,8 @@ ;; `diff-hl-revert-hunk' C-x v n ;; `diff-hl-previous-hunk' C-x v [ ;; `diff-hl-next-hunk' C-x v ] +;; `diff-hl-set-reference-rev' +;; `diff-hl-reset-reference-rev' ;; ;; The mode takes advantage of `smartrep' if it is installed. @@ -55,6 +57,8 @@ (require 'diff-mode) (require 'vc) (require 'vc-dir) +(require 'log-view) + (eval-when-compile (require 'cl-lib) (require 'vc-git) @@ -141,6 +145,26 @@ the end position as its only argument." (const :tag "Highlight the first column" diff-hl-revert-highlight-first-column))) +(defcustom diff-hl-global-modes '(not image-mode) + "Modes for which `diff-hl-mode' is automagically turned on. +This affects the behavior of `global-diff-hl-mode'. +If nil, no modes have `diff-hl-mode' automatically turned on. +If t, all modes have `diff-hl-mode' enabled. +If a list, it should be a list of `major-mode' symbol names for +which it should be automatically turned on. The sense of the list +is negated if it begins with `not'. As such, the default value + (not image-mode) +means that `diff-hl-mode' is turned on in all modes except for +`image-mode' buffers. Previously, `diff-hl-mode' caused worse +performance when viewing such files in certain conditions." + :type '(choice (const :tag "none" nil) + (const :tag "all" t) + (set :menu-tag "mode specific" :tag "modes" + :value (not) + (const :tag "Except" not) + (repeat :inline t (symbol :tag "mode")))) + :group 'diff-hl) + (defvar diff-hl-reference-revision nil "Revision to diff against. nil means the most recent one.") @@ -338,6 +362,15 @@ the end position as its only argument." (overlay-put h 'insert-in-front-hooks hook) (overlay-put h 'insert-behind-hooks hook))))))))) +(defvar-local diff-hl--modified-tick nil) + +(put 'diff-hl--modified-tick 'permanent-local t) + +(defun diff-hl-update-once () + (unless (equal diff-hl--modified-tick (buffer-chars-modified-tick)) + (diff-hl-update) + (setq diff-hl--modified-tick (buffer-chars-modified-tick)))) + (defun diff-hl-add-highlighting (type shape) (let ((o (make-overlay (point) (point)))) (overlay-put o 'diff-hl t) @@ -376,6 +409,11 @@ the end position as its only argument." (unless (buffer-modified-p) (diff-hl-update)))) +(defun diff-hl-after-revert () + (defvar revert-buffer-preserve-modes) + (when revert-buffer-preserve-modes + (diff-hl-update))) + (defun diff-hl-diff-goto-hunk-1 () (vc-buffer-sync) (let* ((line (line-number-at-pos)) @@ -551,9 +589,9 @@ The value of this variable is a mode line template as in ;; let's wait until the state information is ;; saved, in order not to fetch it twice. 'find-file-hook) - 'diff-hl-update t t) + 'diff-hl-update-once t t) (add-hook 'vc-checkin-hook 'diff-hl-update nil t) - (add-hook 'after-revert-hook 'diff-hl-update nil t) + (add-hook 'after-revert-hook 'diff-hl-after-revert nil t) ;; Magit does call `auto-revert-handler', but it usually ;; doesn't do much, because `buffer-stale--default-function' ;; doesn't care about changed VC state. @@ -653,9 +691,64 @@ The value of this variable is a mode line template as in ((eq major-mode 'vc-dir-mode) (diff-hl-dir-mode 1)))) +;;;###autoload +(defun diff-hl--global-turn-on () + "Call `turn-on-diff-hl-mode' if the current major mode is applicable." + (when (cond ((eq diff-hl-global-modes t) + t) + ((eq (car-safe diff-hl-global-modes) 'not) + (not (memq major-mode (cdr diff-hl-global-modes)))) + (t (memq major-mode diff-hl-global-modes))) + (turn-on-diff-hl-mode))) + +;;;###autoload +(defun diff-hl-set-reference-rev (&optional rev) + "Set the reference revision globally to REV. +When called interactively, REV is get from contexts: + +- In a log view buffer, it uses the revision of current entry. +Call `vc-print-log' or `vc-print-root-log' first to open a log +view buffer. +- In a VC annotate buffer, it uses the revision of current line. +- In other situations, get the revision name at point. + +Notice that this sets the reference revision globally, so in +files from other repositories, `diff-hl-mode' will not highlight +changes correctly, until you run `diff-hl-reset-reference-rev'. + +Also notice that this will disable `diff-hl-amend-mode' in +buffers that enables it, since `diff-hl-amend-mode' overrides its +effect." + (interactive) + (let* ((rev (or rev + (and (equal major-mode 'vc-annotate-mode) + (car (vc-annotate-extract-revision-at-line))) + (log-view-current-tag) + (thing-at-point 'symbol t)))) + (if rev + (message "Set reference rev to %s" rev) + (user-error "Can't find a revision around point")) + (setq diff-hl-reference-revision rev)) + (dolist (buf (buffer-list)) + (with-current-buffer buf + (when diff-hl-mode + (when diff-hl-amend-mode + (diff-hl-amend-mode -1)) + (diff-hl-update))))) + +;;;###autoload +(defun diff-hl-reset-reference-rev () + "Reset the reference revision globally to the most recent one." + (interactive) + (setq diff-hl-reference-revision nil) + (dolist (buf (buffer-list)) + (with-current-buffer buf + (when diff-hl-mode + (diff-hl-update))))) + ;;;###autoload (define-globalized-minor-mode global-diff-hl-mode diff-hl-mode - turn-on-diff-hl-mode :after-hook (diff-hl-global-mode-change)) + diff-hl--global-turn-on :after-hook (diff-hl-global-mode-change)) (defun diff-hl-global-mode-change () (unless global-diff-hl-mode diff --git a/lisp/emojify/data/emoji-sets.json b/lisp/emojify/data/emoji-sets.json index 3eab4859..1e7dcfc6 100644 --- a/lisp/emojify/data/emoji-sets.json +++ b/lisp/emojify/data/emoji-sets.json @@ -24,15 +24,21 @@ "sha256" : "eb0ff5637924a2a04d3ab649b66d816a69c5d71eab2bf5274d292115e8178244" }, "twemoji-v2": { - "description": "Emojis provided by Twitter (version 2)", + "description" : "Emojis provided by Twitter (version 2)", "website" : "https://twemoji.twitter.com/", "url": "https://raw.githubusercontent.com/iqbalansari/emacs-emojify/9e36d0e8c2a9c373a39728f837a507adfbb7b931/twemoji-fixed-v2.tar", - "sha256": "0991b1032a04d948835fba4249f43993b4ac88a66d2ae7f278f03be31884851d" + "sha256" : "0991b1032a04d948835fba4249f43993b4ac88a66d2ae7f278f03be31884851d" }, "twemoji-v2-22": { - "description": "Emojis provided by Twitter (version 2), resized to 22px", + "description" : "Emojis provided by Twitter (version 2), resized to 22px", "website" : "https://twemoji.twitter.com/", "url": "https://raw.githubusercontent.com/iqbalansari/emacs-emojify/9e36d0e8c2a9c373a39728f837a507adfbb7b931/twemoji-fixed-v2-22.tar", - "sha256": "e3ae26d7ac111fe0be7b90f29afdab89676610a865353dfb672673efb5af044a" + "sha256" : "e3ae26d7ac111fe0be7b90f29afdab89676610a865353dfb672673efb5af044a" + }, + "openmoji-v13-0": { + "description" : "Emojis provided by HfG Schwäbisch Gmünd (version 13.0) at 72px", + "website" : "https://openmoji.org", + "url": "https://raw.githubusercontent.com/iqbalansari/emacs-emojify/9161fd27f399944516e86d36c90c3b55f31427dd/openmoji-v13.0.tar", + "sha256" : "ccb0bce387e216a0c5f4ff54d53607dbfa1c62e7de9be95ee56af0cd39e42807" } } diff --git a/lisp/emojify/emojify-pkg.el b/lisp/emojify/emojify-pkg.el index a94dcfc6..2d274843 100644 --- a/lisp/emojify/emojify-pkg.el +++ b/lisp/emojify/emojify-pkg.el @@ -1,13 +1,13 @@ -(define-package "emojify" "20200513.1627" "Display emojis in Emacs" +(define-package "emojify" "20201130.1116" "Display emojis in Emacs" '((seq "1.11") (ht "2.0") (emacs "24.3")) - :commit "dfa3c6d060914c6082d6837da32df0c337330ee4" :keywords - '("multimedia" "convenience") - :authors + :commit "4b96f37f315182f95d4ea9ff33a9b5af9f1b1620" :authors '(("Iqbal Ansari" . "iqbalansari02@yahoo.com")) :maintainer '("Iqbal Ansari" . "iqbalansari02@yahoo.com") + :keywords + '("multimedia" "convenience") :url "https://github.com/iqbalansari/emacs-emojify") ;; Local Variables: ;; no-byte-compile: t diff --git a/lisp/emojify/emojify.el b/lisp/emojify/emojify.el index 10421ff1..176384b7 100644 --- a/lisp/emojify/emojify.el +++ b/lisp/emojify/emojify.el @@ -429,6 +429,13 @@ can customize `emojify-inhibit-major-modes' and +;; Obsolete vars + +(define-obsolete-variable-alias 'emojify-emoji-style 'emojify-emoji-styles "0.2") +(define-obsolete-function-alias 'emojify-set-emoji-style 'emojify-set-emoji-styles "0.2") + + + ;; Customizations to control display of emojis (defvar emojify-emoji-style-change-hook nil @@ -638,13 +645,6 @@ the visible area." -;; Obsolete vars - -(define-obsolete-variable-alias 'emojify-emoji-style 'emojify-emoji-styles "0.2") -(define-obsolete-function-alias 'emojify-set-emoji-style 'emojify-set-emoji-styles "0.2") - - - ;; Customizations to control the behaviour when point enters emojified text (defcustom emojify-point-entered-behaviour 'echo @@ -1824,16 +1824,16 @@ HIST, DEF, INHERIT-INPUT-METHOD correspond to the arguments for `emojify-completing-read-function' and are passed to ‘emojify-completing-read-function’ without any interpretation. -For each possible emoji PREDICATE is called with emoji text and data about the -emoji as a hash-table, the predate should return nil if it the emoji should -not be displayed for selection. +For each possible emoji PREDICATE is called with a string of the form +' - (