diff --git a/code/elpa/archives/melpa/archive-contents b/code/elpa/archives/melpa/archive-contents index 5f588c9..b42afe9 100644 --- a/code/elpa/archives/melpa/archive-contents +++ b/code/elpa/archives/melpa/archive-contents @@ -14,7 +14,7 @@ (abgaben . [(20171119 646) ((pdf-tools (0 80)) (f (0 19 0)) (s (1 11 0))) "review and correct assignments received by mail" single ((:commit . "966bfcfdd3b2e288576ffe363d676ad282902090") (:authors ("Arne Köhn" . "arne@chark.eu")) (:maintainer "Arne Köhn" . "arne@chark.eu") (:keywords "mail" "outlines" "convenience") (:url . "http://arne.chark.eu/"))]) (abl-mode . [(20210923 950) nil "Python TDD minor mode" single ((:commit . "7f692cf9bb263b26fda51bb56a58f6ac61febe3b") (:authors ("Ulas Tuerkmen ")) (:maintainer "Ulas Tuerkmen ") (:url . "http://github.com/afroisalreadyinu/abl-mode"))]) (abridge-diff . [(20230307 2159) ((emacs (26 1))) "Abridge long line-based diff hunks, including in magit" single ((:commit . "31e0ccaa9d0bd4ad257f5de25cc3c0b3395fafa1") (:authors ("J.D. Smith ")) (:maintainer "J.D. Smith ") (:keywords "magit" "diffs" "tools") (:url . "https://github.com/jdtsmith/abridge-diff"))]) - (abs-mode . [(20220316 921) ((emacs (26 1)) (erlang (2 8)) (maude-mode (0 3)) (flymake (1 0))) "Major mode for the modeling language Abs" single ((:commit . "d860ddbbd7cb93c7a77980c78c1a2a7634ef01e1") (:authors ("Rudi Schlatte" . "rudi@constantly.at")) (:maintainer "Rudi Schlatte" . "rudi@constantly.at") (:keywords "languages") (:url . "https://github.com/abstools/abs-mode"))]) + (abs-mode . [(20230402 1422) ((emacs (26 1)) (erlang (2 8)) (maude-mode (0 3)) (flymake (1 0)) (yasnippet (0 14 0))) "Major mode for the modeling language Abs" tar ((:commit . "bfeeb70964ee03f7d29ff44959951c713318dee5") (:authors ("Rudi Schlatte" . "rudi@constantly.at")) (:maintainer "Rudi Schlatte" . "rudi@constantly.at") (:keywords "languages") (:url . "https://github.com/abstools/abs-mode"))]) (abyss-theme . [(20170808 1345) ((emacs (24))) "A dark theme with contrasting colours." single ((:commit . "18791c6e8d9cc2b4815c9f08627a2e94fc0eeb14") (:authors ("Matt Russell" . "matt@mgrbyte.co.uk")) (:maintainer "Matt Russell" . "matt@mgrbyte.co.uk") (:keywords "theme" "dark" "contrasting colours") (:url . "https://github.com/mgrbyte/emacs-abyss-theme"))]) (ac-alchemist . [(20150908 656) ((auto-complete (1 5 0)) (alchemist (1 5 0)) (cl-lib (0 5))) "auto-complete source for alchemist" single ((:commit . "b1891c3d41aed83f61d78a609ea97be5cc2758d9") (:authors ("Syohei YOSHIDA" . "syohex@gmail.com")) (:maintainer "Syohei YOSHIDA" . "syohex@gmail.com") (:url . "https://github.com/syohex/emacs-ac-alchemist"))]) (ac-c-headers . [(20200816 1007) ((auto-complete (1 3 1))) "auto-complete source for C headers" single ((:commit . "67e1e86a48c9bed57bc7ce5ce2553ad203f5752e") (:authors ("zk_phi")) (:maintainer "zk_phi") (:url . "http://zk-phi.gitub.io/"))]) @@ -88,9 +88,9 @@ (airline-themes . [(20211214 1749) ((powerline (2 3))) "vim-airline themes for emacs powerline" tar ((:commit . "6bd102e49a7d87af1a72eb86e953991ff7bc954e") (:authors ("Anthony DiGirolamo" . "anthony.digirolamo@gmail.com")) (:maintainer "Anthony DiGirolamo" . "anthony.digirolamo@gmail.com") (:keywords "evil" "mode-line" "powerline" "airline" "themes") (:url . "http://github.com/AnthonyDiGirolamo/airline-themes"))]) (airplay . [(20130212 1226) ((request (20130110 2144)) (simple-httpd (1 4 1)) (deferred (0 3 1))) "Airplay bindings to Emacs" tar ((:commit . "46fad71d293a3e18551cf464fe6c6208a7a32d9d") (:authors ("Wataru MIYAGUNI" . "gonngo@gmail.com")) (:maintainer "Wataru MIYAGUNI" . "gonngo@gmail.com") (:keywords "appletv" "airplay") (:url . "https://github.com/gongo/airplay-el"))]) (alan-mode . [(20230216 857) ((flycheck (32)) (emacs (25 1)) (s (1 12))) "Major mode for editing Alan files" single ((:commit . "723cf8e8d7e00c1498935553c46f459aa1d26135") (:authors ("Paul van Dam" . "pvandam@kjerner.com")) (:maintainer "Paul van Dam" . "pvandam@kjerner.com") (:keywords "alan" "languages") (:url . "https://github.com/Kjerner/AlanForEmacs"))]) - (alarm-clock . [(20230216 1337) ((emacs (24 4))) "Alarm Clock" tar ((:commit . "3e43ca49804afb06477dbf7ff3d6e9824522be4b") (:authors ("Steve Lemuel" . "wlemuel@hotmail.com")) (:maintainer "Steve Lemuel" . "wlemuel@hotmail.com") (:keywords "calendar" "tools" "convenience") (:url . "https://github.com/wlemuel/alarm-clock"))]) + (alarm-clock . [(20230326 718) ((emacs (24 4))) "Alarm Clock" tar ((:commit . "bcd9158f18ead2aa25f10a48e4a38e2c3ed64217") (:authors ("Steve Lemuel" . "wlemuel@hotmail.com")) (:maintainer "Steve Lemuel" . "wlemuel@hotmail.com") (:keywords "calendar" "tools" "convenience") (:url . "https://github.com/wlemuel/alarm-clock"))]) (alchemist . [(20180312 1304) ((elixir-mode (2 2 5)) (dash (2 11 0)) (emacs (24 4)) (company (0 8 0)) (pkg-info (0 4)) (s (1 11 0))) "Elixir tooling integration into Emacs" tar ((:commit . "6f99367511ae209f8fe2c990779764bbb4ccb6ed") (:authors ("Samuel Tonini" . "tonini.samuel@gmail.com")) (:maintainer "Samuel Tonini" . "tonini.samuel@gmail.com") (:keywords "languages" "elixir" "elixirc" "mix" "hex" "alchemist") (:url . "http://www.github.com/tonini/alchemist.el"))]) - (alda-mode . [(20210705 654) ((emacs (24 0))) "An Alda major mode" single ((:commit . "ae08444d16bd1859a06c8ed6a3e7ae2e9ad397ed") (:authors ("Jay Kamat" . "jaygkamat@gmail.com")) (:maintainer "Jay Kamat" . "jaygkamat@gmail.com") (:keywords "alda" "highlight") (:url . "http://gitlab.com/jgkamat/alda-mode"))]) + (alda-mode . [(20230406 1927) ((emacs (24 0))) "An Alda major mode" single ((:commit . "580f6e94c93aead91406d00a42ccf9040a898cb8") (:authors ("Jay Kamat" . "jaygkamat@gmail.com")) (:maintainer "Jay Kamat" . "jaygkamat@gmail.com") (:keywords "alda" "highlight") (:url . "http://gitlab.com/jgkamat/alda-mode"))]) (alect-themes . [(20211022 1651) ((emacs (24 0))) "Configurable light, dark and black themes for Emacs 24 or later" tar ((:commit . "89560047934c236d05ea6b911c0c63702a8e06f3") (:authors ("Alex Kost" . "alezost@gmail.com")) (:maintainer "Alex Kost" . "alezost@gmail.com") (:keywords "color" "theme") (:url . "https://github.com/alezost/alect-themes"))]) (alectryon . [(20220925 2236) ((flycheck (31)) (emacs (25 1))) "Toggle between Coq and reStructuredText" tar ((:commit . "8a1f3054c97fc86d628413800cfef75577c43485") (:authors ("Clément Pit-Claudel" . "clement.pitclaudel@live.com")) (:maintainer "Clément Pit-Claudel" . "clement.pitclaudel@live.com") (:keywords "convenience" "languages" "tools") (:url . "https://github.com/cpitclaudel/alectryon"))]) (alert . [(20221213 1619) ((gntp (0 1)) (log4e (0 3 0)) (cl-lib (0 5))) "Growl-style notification system for Emacs" single ((:commit . "c762380ff71c429faf47552a83605b2578656380") (:authors ("John Wiegley" . "jwiegley@gmail.com")) (:maintainer "John Wiegley" . "jwiegley@gmail.com") (:keywords "notification" "emacs" "message") (:url . "https://github.com/jwiegley/alert"))]) @@ -102,9 +102,9 @@ (all-the-icons-completion . [(20230224 1610) ((emacs (26 1)) (all-the-icons (5 0))) "Add icons to completion candidates" single ((:commit . "b08f053cee444546ab44a05fd541f59e8bc8983b") (:authors ("Itai Y. Efrat ")) (:maintainer "Itai Y. Efrat" . "itai3397@gmail.com") (:keywords "convenient" "lisp") (:url . "https://github.com/iyefrat/all-the-icons-completion"))]) (all-the-icons-dired . [(20220929 1135) ((emacs (26 1)) (all-the-icons (2 2 0))) "Shows icons for each file in dired mode" single ((:commit . "bcaed35bb3ad7fc46007f16e0d670beb82bb613e") (:authors ("jtbm37")) (:maintainer "Jimmy Yuen Ho Wong" . "wyuenho@gmail.com") (:keywords "files" "icons" "dired") (:url . "https://github.com/wyuenho/all-the-icons-dired"))]) (all-the-icons-gnus . [(20180511 654) ((emacs (24 4)) (dash (2 12 0)) (all-the-icons (3 1 0))) "Shows icons for in Gnus" single ((:commit . "27f78996da0725943bcfb2d18038e6f7bddfa9c7") (:authors ("Nicolas Lamirault" . "nicolas.lamirault@gmail.com")) (:maintainer "Nicolas Lamirault" . "nicolas.lamirault@gmail.com") (:keywords "mail" "tools"))]) - (all-the-icons-ibuffer . [(20220424 1027) ((emacs (24 4)) (all-the-icons (2 2 0))) "Display icons for all buffers in ibuffer" single ((:commit . "0c7221366ceddbf122073ecd07dd86e1baf032ff") (:authors ("Vincent Zhang" . "seagle0128@gmail.com")) (:maintainer "Vincent Zhang" . "seagle0128@gmail.com") (:keywords "convenience" "icons" "ibuffer") (:url . "https://github.com/seagle0128/all-the-icons-ibuffer"))]) + (all-the-icons-ibuffer . [(20230402 1554) ((emacs (24 4)) (all-the-icons (2 2 0))) "Display icons for all buffers in ibuffer" single ((:commit . "22cfc4324cd7ef6473c892f1721a0a144c5aba36") (:authors ("Vincent Zhang" . "seagle0128@gmail.com")) (:maintainer "Vincent Zhang" . "seagle0128@gmail.com") (:keywords "convenience" "icons" "ibuffer") (:url . "https://github.com/seagle0128/all-the-icons-ibuffer"))]) (all-the-icons-ivy . [(20190508 1803) ((emacs (24 4)) (all-the-icons (2 4 0)) (ivy (0 8 0))) "Shows icons while using ivy and counsel" single ((:commit . "babea626db20773de4c408acb2788e2b9c8277e3") (:authors ("asok")) (:maintainer "asok") (:keywords "faces"))]) - (all-the-icons-ivy-rich . [(20230314 1559) ((emacs (25 1)) (ivy-rich (0 1 0)) (all-the-icons (2 2 0))) "Better experience with icons for ivy" single ((:commit . "1bae2c95e5bf865af55d219d50baf4ee9ce5e7c6") (:authors ("Vincent Zhang" . "seagle0128@gmail.com")) (:maintainer "Vincent Zhang" . "seagle0128@gmail.com") (:keywords "convenience" "icons" "ivy") (:url . "https://github.com/seagle0128/all-the-icons-ivy-rich"))]) + (all-the-icons-ivy-rich . [(20230404 1331) ((emacs (25 1)) (ivy-rich (0 1 0)) (all-the-icons (2 2 0))) "Better experience with icons for ivy" single ((:commit . "cf833e988a953743d5f5bbc799a91a47862d7008") (:authors ("Vincent Zhang" . "seagle0128@gmail.com")) (:maintainer "Vincent Zhang" . "seagle0128@gmail.com") (:keywords "convenience" "icons" "ivy") (:url . "https://github.com/seagle0128/all-the-icons-ivy-rich"))]) (almost-mono-themes . [(20220422 1714) ((emacs (24))) "Almost monochromatic color themes" tar ((:commit . "0641bf565c113caef8d5c2a93f38cff32ebb62b7") (:authors ("John Olsson" . "john@cryon.se")) (:maintainer "John Olsson" . "john@cryon.se") (:keywords "faces") (:url . "https://github.com/cryon/almost-mono-themes"))]) (alsamixer . [(20191002 1133) nil "Functions to call out to amixer." single ((:commit . "1bdb99e433acd38685f05408562746cfbf2bc820") (:authors ("R.W. van 't Veer")) (:maintainer "R.W. van 't Veer") (:keywords "convenience") (:url . "https://github.com/remvee/alsamixer-el"))]) (alt-codes . [(20220704 644) ((emacs (26 1))) "Insert alt codes using meta key" single ((:commit . "36dbcbeb69525cd21caeb4c267421b69fa2fffcb") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "alt" "codes" "insertion" "meta") (:url . "https://github.com/jcs-elpa/alt-codes"))]) @@ -113,7 +113,7 @@ (ample-regexps . [(20200508 1021) nil "ample regular expressions for Emacs" tar ((:commit . "153969ce547afe410b8986f01c9ed4087c9cd20b") (:authors ("immerrr" . "immerrr@gmail.com")) (:maintainer "immerrr" . "immerrr@gmail.com") (:keywords "regexps" "extensions" "tools"))]) (ample-theme . [(20180207 1745) nil "Calm Dark Theme for Emacs" tar ((:commit . "366698400c555211c2082962a5d74f3dd79a78c8") (:authors ("Jordon Biondo" . "jordonbiondo@gmail.com")) (:maintainer "Jordon Biondo" . "jordonbiondo@gmail.com") (:keywords "theme" "dark") (:url . "https://github.com/jordonbiondo/ample-theme"))]) (ample-zen-theme . [(20150119 2154) nil "AmpleZen Theme for Emacs 24" single ((:commit . "b277bb7abd4b6624e8d59f02474b79af50a007bd") (:authors ("Michael Wall")) (:maintainer "Michael Wall") (:keywords "theme" "dark" "emacs 24") (:url . "https://github.com/mjwall/ample-zen"))]) - (amread-mode . [(20230107 1433) ((emacs (24 3)) (cl-lib (0 6 1)) (pyim (5 2 8))) "A minor mode helper user speed-reading" single ((:commit . "4746c6adf81bedf8933faf912c4c65dafea9bb62") (:keywords "wp") (:url . "https://repo.or.cz/amread-mode.git"))]) + (amread-mode . [(20230406 1202) ((emacs (24 3)) (cl-lib (0 6 1)) (pyim (5 2 8))) "A minor mode helper user speed-reading" single ((:commit . "f5b46f83ce205b1f6c1cf54e99da3e46ad17dfad") (:keywords "wp") (:url . "https://repo.or.cz/amread-mode.git"))]) (amsreftex . [(20220115 1838) ((emacs (25 1))) "Add amsrefs bibliography support for reftex" single ((:commit . "facf47b82572e3f62bd8d9b8d4f4d5258f6c8a38") (:authors ("Fran Burstall" . "fran.burstall@gmail.com")) (:maintainer "Fran Burstall" . "fran.burstall@gmail.com") (:keywords "tex") (:url . "https://github.com/franburstall/amsreftex"))]) (amx . [(20210305 118) ((emacs (24 4)) (s (0))) "Alternative M-x with extra features." single ((:commit . "37f9c7ae55eb0331b27200fb745206fc58ceffc0") (:authors ("Ryan C. Thompson" . "rct@thompsonclan.org") ("Cornelius Mika" . "cornelius.mika@gmail.com")) (:maintainer "Ryan C. Thompson" . "rct@thompsonclan.org") (:keywords "convenience" "usability" "completion") (:url . "http://github.com/DarwinAwardWinner/amx/"))]) (anaconda-mode . [(20230306 2112) ((emacs (25 1)) (pythonic (0 1 0)) (dash (2 6 0)) (s (1 9)) (f (0 16 2))) "Code navigation, documentation lookup and completion for Python" tar ((:commit . "e250596f5587129f55f446ef127d0dac5e9730a3") (:authors ("Artem Malyshev" . "proofit404@gmail.com")) (:maintainer "Artem Malyshev" . "proofit404@gmail.com") (:url . "https://github.com/proofit404/anaconda-mode"))]) @@ -130,7 +130,7 @@ (anki-mode . [(20201223 719) ((emacs (24 4)) (dash (2 12 0)) (markdown-mode (2 2)) (s (1 11 0)) (request (0 3 0))) "A major mode for creating anki cards" single ((:commit . "7cde5a68c9d0ef3811b0bd480274ea79909d2ddc") (:authors ("David Shepherd" . "davidshepherd7@gmail.com")) (:maintainer "David Shepherd" . "davidshepherd7@gmail.com") (:keywords "tools") (:url . "https://github.com/davidshepherd7/anki-mode"))]) (anki-vocabulary . [(20200103 325) ((emacs (24 4)) (s (1 0)) (youdao-dictionary (0 4)) (anki-connect (1 0)) (s (1 10))) "Help you to create vocabulary cards in Anki" single ((:commit . "863fe0219577f996ab126f1b7902db3c2cc59b2b") (:authors ("DarkSun" . "lujun9972@gmail.com")) (:maintainer "DarkSun" . "lujun9972@gmail.com") (:keywords "lisp" "anki" "translator" "chinese") (:url . "https://github.com/lujun9972/anki-vocabulary.el"))]) (annalist . [(20190929 207) ((emacs (24 4)) (cl-lib (0 5))) "Record and display information such as keybindings" tar ((:commit . "08df07e4530953a2c0b1aa553adcab37b7b614b0") (:authors ("Fox Kiester" . "noct@posteo.net")) (:maintainer "Fox Kiester" . "noct@posteo.net") (:keywords "convenience" "tools" "keybindings" "org") (:url . "https://github.com/noctuid/annalist.el"))]) - (annotate . [(20230310 1452) nil "annotate files without changing them" single ((:commit . "265ac1a9053795be34028c62f43adb09cf585864") (:authors ("Bastian Bechtold")) (:maintainer "Bastian Bechtold , cage" . "cage-dev@twistfold.it") (:url . "https://github.com/bastibe/annotate.el"))]) + (annotate . [(20230401 1613) nil "annotate files without changing them" single ((:commit . "69d7e2138c35f8c8adb33cf27b440eee2591810d") (:authors ("Bastian Bechtold")) (:maintainer "Bastian Bechtold , cage" . "cage-dev@twistfold.it") (:url . "https://github.com/bastibe/annotate.el"))]) (annotate-depth . [(20160520 2040) nil "Annotate buffer if indentation depth is beyond threshold." single ((:commit . "fcb24fa36287250e40d195590c4ca4a8a696277b") (:authors ("Morten Slot Kristensen ")) (:maintainer "Morten Slot Kristensen ") (:keywords "convenience") (:url . "https://github.com/netromdk/annotate-depth"))]) (annotation . [(20200914 644) nil "Functions for annotating text with faces and help bubbles" single ((:commit . "aa5e3a127bf17a8c80d947f3c286758a36dadc36") (:url . "https://github.com/agda/agda"))]) (annoying-arrows-mode . [(20161024 646) ((cl-lib (0 5))) "Ring the bell if using arrows too much" single ((:commit . "3c42e9807d7696da2da2a21b63beebf9cdb3f5dc") (:authors ("Magnar Sveen" . "magnars@gmail.com")) (:maintainer "Magnar Sveen" . "magnars@gmail.com"))]) @@ -149,7 +149,7 @@ (apache-mode . [(20210519 1931) nil "Major mode for editing Apache httpd configuration files" single ((:commit . "f2c11aac2f5fc598123e04f4604bea248689a117") (:authors ("Karl Chen" . "quarl@nospam.quarl.org")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "languages" "faces") (:url . "https://github.com/emacs-php/apache-mode"))]) (apdl-mode . [(20211023 1831) ((emacs (25 1))) "Major mode for the APDL programming language." tar ((:commit . "ba756eaa1d229c9bf6936fb8d2d4126ad073d488") (:authors ("H. Dieter Wilhelm" . "dieter@duenenhof-wilhelm.de")) (:maintainer "H. Dieter Wilhelm") (:keywords "languages" "convenience" "tools" "ansys" "apdl") (:url . "https://github.com/dieter-wilhelm/apdl-mode"))]) (apel . [(20220720 1308) ((emacs (24 5))) "A Portable Emacs Library provides support for portable Emacs Lisp programs" tar ((:commit . "82eb2325bd149dc57b43a9ce9402c6c6183e4052"))]) - (apheleia . [(20230312 1050) ((emacs (26))) "Reformat buffer stably" tar ((:commit . "26e436dfd03f79c4c1bf45695ac05d00ab7440c4") (:authors ("Radian LLC" . "contact+apheleia@radian.codes")) (:maintainer "Radian LLC" . "contact+apheleia@radian.codes") (:keywords "tools") (:url . "https://github.com/raxod502/apheleia"))]) + (apheleia . [(20230329 2135) ((emacs (26))) "Reformat buffer stably" tar ((:commit . "23c8b7d1ca3d855b38b8fe8bee760fa1234b6143") (:authors ("Radian LLC" . "contact+apheleia@radian.codes")) (:maintainer "Radian LLC" . "contact+apheleia@radian.codes") (:keywords "tools") (:url . "https://github.com/raxod502/apheleia"))]) (apib-mode . [(20200101 1017) ((markdown-mode (2 1))) "Major mode for API Blueprint files" single ((:commit . "c6dd05201f6eb9295736d8668a79a7510d11159e") (:authors ("Vilibald Wanča" . "vilibald@wvi.cz")) (:maintainer "Vilibald Wanča" . "vilibald@wvi.cz") (:keywords "tools" "api-blueprint") (:url . "http://github.com/w-vi/apib-mode"))]) (apiwrap . [(20180602 2231) ((emacs (25))) "api-wrapping macros" single ((:commit . "e4c9c57d6620a788ec8a715ff1bb50542edea3a6") (:authors ("Sean Allred" . "code@seanallred.com")) (:maintainer "Sean Allred" . "code@seanallred.com") (:keywords "tools" "maint" "convenience") (:url . "https://github.com/vermiculus/apiwrap.el"))]) (apparmor-mode . [(20230209 2325) ((emacs (26 1))) "Major mode for editing AppArmor policy files" single ((:commit . "3b641de4e34fb4a0594a461254f1454973b6b7aa") (:authors ("Alex Murray" . "murray.alex@gmail.com")) (:maintainer "Alex Murray" . "murray.alex@gmail.com") (:url . "https://github.com/alexmurray/apparmor-mode"))]) @@ -179,7 +179,7 @@ (assess . [(20220719 1904) ((emacs (24 4)) (m-buffer (0 15))) "Test support functions" tar ((:commit . "44083d94feb45d3636f7ee6c55e0ef6bbb32b938") (:authors ("Phillip Lord" . "phillip.lord@russet.org.uk")) (:maintainer "Phillip Lord" . "phillip.lord@russet.org.uk"))]) (astyle . [(20200328 616) ((emacs (24 4)) (reformatter (0 3))) "Astyle formatter functions" single ((:commit . "04ff2941f08c4b731fe6a18ee1697436d1ca1cc0") (:authors ("Petter Storvik")) (:maintainer "Petter Storvik") (:keywords "astyle" "c" "c++" "cpp" "reformatter") (:url . "https://github.com/storvik/emacs-astyle"))]) (asx . [(20191024 1100) ((emacs (26 1))) "Ask StackExchange/StackOverflow" single ((:commit . "5ca12cc51bb02b5926adf9a7976ba9ca08a1ea21") (:authors ("Alex Ragone" . "ragonedk@gmail.com")) (:maintainer "Alex Ragone" . "ragonedk@gmail.com") (:keywords "convenience") (:url . "https://github.com/ragone/asx"))]) - (async . [(20230322 521) ((emacs (24 4))) "Asynchronous processing in Emacs" tar ((:commit . "3f91ce8b963cd6909c6578f87b5545fd761f1547") (:authors ("John Wiegley" . "jwiegley@gmail.com")) (:maintainer "Thierry Volpiatto" . "thievol@posteo.net") (:keywords "async") (:url . "https://github.com/jwiegley/emacs-async"))]) + (async . [(20230323 643) ((emacs (24 4))) "Asynchronous processing in Emacs" tar ((:commit . "34feabe1142863a2c96f75afda1a2ae4aa0813f6") (:authors ("John Wiegley" . "jwiegley@gmail.com")) (:maintainer "Thierry Volpiatto" . "thievol@posteo.net") (:keywords "async") (:url . "https://github.com/jwiegley/emacs-async"))]) (async-await . [(20220827 437) ((emacs (25 1)) (promise (1 1)) (iter2 (0 9 10))) "Async/Await" single ((:commit . "e0d15e8057ed7520100bc50c5552278292ebcb07") (:authors ("chuntaro" . "chuntaro@sakura-games.jp")) (:maintainer "chuntaro" . "chuntaro@sakura-games.jp") (:keywords "async" "await" "convenience") (:url . "https://github.com/chuntaro/emacs-async-await"))]) (async-backup . [(20220131 1438) ((emacs (24 4))) "Backup on each save without freezing Emacs" single ((:commit . "6ddb39fe77d66cdef48b87cb0d0554ad7d132308") (:authors ("contrapunctus" . "xmpp:contrapunctus@jabjab.de")) (:maintainer "contrapunctus" . "xmpp:contrapunctus@jabjab.de") (:keywords "files") (:url . "https://tildegit.org/contrapunctus/async-backup"))]) (atcoder-tools . [(20200109 1236) ((emacs (26)) (f (0 20)) (s (1 12))) "An atcoder-tools client" single ((:commit . "cfe61ed18ea9b3b1bfb6f9e7d80a47599680cd1f") (:authors ("Seong Yong-ju" . "sei40kr@gmail.com")) (:maintainer "Seong Yong-ju" . "sei40kr@gmail.com") (:keywords "extensions" "tools") (:url . "https://github.com/sei40kr/atcoder-tools"))]) @@ -228,13 +228,12 @@ (auto-rename-tag . [(20220704 639) ((emacs (24 4))) "Automatically rename paired HTML/XML tag" single ((:commit . "58ef595757350f4d8c1cea30d6902b26afaf8743") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "auto-complete" "html" "rename" "tag" "xml") (:url . "https://github.com/jcs-elpa/auto-rename-tag"))]) (auto-save-buffers-enhanced . [(20161109 710) nil "Automatically save buffers in a decent way" single ((:commit . "461e8c816c1b7c650be5f209078b381fe55da8c6") (:authors ("Kentaro Kuribayashi" . "kentarok@gmail.com")) (:maintainer "Kentaro Kuribayashi" . "kentarok@gmail.com"))]) (auto-shell-command . [(20180817 1502) ((deferred (20130312)) (popwin (20130329))) "Run the shell command asynchronously that you specified when you save the file." single ((:commit . "a8f9213e3c773b5687b81881240e6e648f2f56ba") (:authors ("ongaeshi")) (:maintainer "ongaeshi") (:keywords "shell" "save" "async" "deferred" "auto"))]) - (auto-sudoedit . [(20220421 1147) ((emacs (26 1)) (f (0 19 0))) "Auto sudo edit by tramp" single ((:commit . "39cb574a4b5ec74ad62857320bf5fec58abe876f") (:authors ("ncaq" . "ncaq@ncaq.net")) (:maintainer "ncaq" . "ncaq@ncaq.net") (:url . "https://github.com/ncaq/auto-sudoedit"))]) + (auto-sudoedit . [(20230323 650) ((emacs (26 1)) (f (0 19 0))) "Auto sudo edit by tramp" single ((:commit . "7ee72f31e762e225595e330c6108f3a69dbb0187") (:authors ("ncaq" . "ncaq@ncaq.net")) (:maintainer "ncaq" . "ncaq@ncaq.net") (:url . "https://github.com/ncaq/auto-sudoedit"))]) (auto-virtualenv . [(20220712 1612) ((cl-lib (0 5)) (pyvenv (1 9)) (s (1 10 0))) "Auto activate python virtualenvs" single ((:commit . "1e58a878984dbd2c91b4f128ded03fd954336907") (:authors ("Marcwebbie" . "marcwebbie@gmail.com")) (:maintainer "Marcwebbie" . "marcwebbie@gmail.com") (:keywords "python" "virtualenv" "tools") (:url . "http://github.com/marcwebbie/auto-virtualenv"))]) (auto-virtualenvwrapper . [(20230317 1313) ((cl-lib (1 0)) (s (1 13 0)) (virtualenvwrapper (0))) "Lightweight auto activate python virtualenvs" single ((:commit . "8cc2616af46d7e26c1d9ecea5fffd8974e5b1acb") (:authors ("Marcwebbie" . "marcwebbie@gmail.com") ("Robert Zaremba" . "robert-zaremba@scale-it.pl")) (:maintainer "Marcwebbie" . "marcwebbie@gmail.com") (:keywords "python" "virtualenv" "tools"))]) (auto-yasnippet . [(20230208 331) ((yasnippet (0 14 0)) (emacs (25 1))) "Quickly create disposable yasnippets" single ((:commit . "6a9e406d0d7f9dfd6dff7647f358cb05a0b1637e") (:authors ("Oleh Krehel" . "ohwoeowho@gmail.com") ("Jason Milkins" . "jasonm23@gmail.com")) (:maintainer "Jason Milkins" . "jasonm23@gmail.com") (:url . "https://github.com/abo-abo/auto-yasnippet"))]) (autobookmarks . [(20220509 1712) ((dash (2 10 0)) (cl-lib (0 5))) "Save recently visited files and buffers" single ((:commit . "8acd6f182181e23257e01c1b5cf90b872507a74d") (:authors ("Matúš Goljer" . "matus.goljer@gmail.com")) (:maintainer "Matúš Goljer" . "matus.goljer@gmail.com") (:keywords "files"))]) (autobuild . [(20200713 227) ((cl-lib (0 3)) (emacs (26 1))) "Define and execute build rules and compilation pipelines" single ((:commit . "6c10b13c285cc4180dc64c1f89ead264e6786f53") (:authors ("Ernesto Alfonso")) (:maintainer nil . "(concat \"erjoalgo\" \"@\" \"gmail\" \".com\")") (:keywords "compile" "build" "pipeline" "autobuild" "extensions" "processes" "tools") (:url . "https://github.com/erjoalgo/autobuild"))]) - (autocrypt . [(20221220 2359) ((emacs (24 3))) "Autocrypt implementation" tar ((:commit . "1444f1861fd13367bdf75ec60a83a94dd1802a49") (:authors ("Philip Kaludercic" . "philipk@posteo.net")) (:maintainer "Philip Kaludercic" . "~pkal/public-inbox@lists.sr.ht") (:keywords "comm") (:url . "https://git.sr.ht/~pkal/autocrypt"))]) (autodisass-java-bytecode . [(20211005 1920) nil "Automatically disassemble Java bytecode" tar ((:commit . "9eaddd63645e64825b2d07805999c5a645248c53") (:authors ("George Balatsouras ")) (:maintainer "George Balatsouras ") (:keywords "convenience" "data" "files"))]) (autodisass-llvm-bitcode . [(20150411 125) nil "Automatically disassemble LLVM bitcode" tar ((:commit . "14bb1bfe2be3b04d6e0c87a7a9d1e88ce15506d0") (:authors ("George Balatsouras ")) (:maintainer "George Balatsouras ") (:keywords "convenience" "data" "files"))]) (autotetris-mode . [(20141114 1646) ((cl-lib (0 5))) "automatically play tetris" single ((:commit . "7d348d33829bc89ddbd2b4d5cfe5073c3b0cbaaa") (:authors ("Christopher Wellons" . "wellons@nullprogram.com")) (:maintainer "Christopher Wellons" . "wellons@nullprogram.com") (:url . "https://github.com/skeeto/autotetris-mode"))]) @@ -271,13 +270,13 @@ (bap-mode . [(20200128 1354) nil "Major-mode for BAP's IR" single ((:commit . "8969679f60db0aa918d35f40d959c0a9c723b111") (:authors ("Thomas Barabosch ")) (:maintainer "Thomas Barabosch" . "thomas.barabosch@fkie.fraunhofer.de") (:keywords "languages") (:url . "https://github.com/fkie-cad/bap-mode"))]) (bar-cursor . [(20201204 2244) nil "package used to switch block cursor to a bar" single ((:commit . "78f195b6db63459033c4f1c7e7add5d82f3ce424") (:authors ("Joe Casadonte" . "emacs@northbound-train.com")) (:maintainer "Andrew Johnson" . "andrew@andrewjamesjohnson.com") (:keywords "files") (:url . "https://github.com/ajsquared/bar-cursor"))]) (bart-mode . [(20190601 1004) ((emacs (24 3))) "Real time BART departures info." single ((:commit . "f70b6c42452e47c0c6b3ebd4c90e555a9bedeec7") (:authors ("Michael Schuldt" . "mbschuldt@gmail.com")) (:maintainer "Michael Schuldt" . "mbschuldt@gmail.com") (:keywords "convenience" "transit") (:url . "https://github.com/mschuldt/bart-mode"))]) - (base16-theme . [(20230319 114) nil "Collection of themes built on combinations of 16 base colors" tar ((:commit . "dcdfa86e42cba11ae1c80be6170e52236728b234") (:authors ("Kaleb Elwert" . "belak@coded.io") ("Neil Bhakta")) (:maintainer "Kaleb Elwert" . "belak@coded.io") (:url . "https://github.com/tinted-theming/base16-emacs"))]) + (base16-theme . [(20230326 110) nil "Collection of themes built on combinations of 16 base colors" tar ((:commit . "4843c8bb359746ed3a5dd269b1ab86410f9fffc1") (:authors ("Kaleb Elwert" . "belak@coded.io") ("Neil Bhakta")) (:maintainer "Kaleb Elwert" . "belak@coded.io") (:url . "https://github.com/tinted-theming/base16-emacs"))]) (bash-completion . [(20230315 1918) ((emacs (25 3))) "Bash completion for the shell buffer" single ((:commit . "ae6560fe897ab6fcc0b1c4aac1ac084be5bc632e") (:authors ("Stephane Zermatten" . "szermatt@gmx.net")) (:maintainer "Stephane Zermatten" . "szermatt@gmail.com") (:keywords "convenience" "unix") (:url . "http://github.com/szermatt/emacs-bash-completion"))]) (basic-c-compile . [(20170302 1112) ((cl-lib (0 5)) (f (0 19 0))) "Quickly create a Makefile, compile and run C." single ((:commit . "335e96e19647ad7245fb68cf7e68cf86c5023d23") (:authors ("Nick Spain" . "nicholas.spain96@gmail.com")) (:maintainer "Nick Spain" . "nicholas.spain96@gmail.com") (:keywords "c" "makefile" "compilation" "convenience") (:url . "https://github.com/nick96/basic-c-compile"))]) (basic-ide . [(20230118 1040) ((emacs (25)) (basic-mode (0 4 2)) (company (0 9 12)) (flycheck (0 22)) (dash (2 12 0)) (f (0 17 0))) "BASIC IDE c64" single ((:commit . "e33036f838e61b647927165e81be5d5b855e0518") (:authors ("Fermin MF" . "fmfs@posteo.net")) (:maintainer "Fermin MF" . "fmfs@posteo.net") (:keywords "languages" "basic") (:url . "https://gitlab.com/sasanidas/emacs-c64-basic-ide"))]) - (basic-mode . [(20230311 1518) ((seq (2 20)) (emacs (25 1))) "Major mode for editing BASIC code" single ((:commit . "5773a2639471db7ce0ecea7bb2b6f797c7fcad9a") (:authors ("Johan Dykstrom")) (:maintainer "Johan Dykstrom") (:keywords "basic" "languages") (:url . "https://github.com/dykstrom/basic-mode"))]) + (basic-mode . [(20230401 845) ((seq (2 20)) (emacs (25 1))) "Major mode for editing BASIC code" single ((:commit . "2971591510f08ab1645ed8a238b6ad086750f994") (:authors ("Johan Dykstrom")) (:maintainer "Johan Dykstrom") (:keywords "basic" "languages") (:url . "https://github.com/dykstrom/basic-mode"))]) (basic-theme . [(20160817 827) ((emacs (24))) "Minimalistic light color theme" single ((:commit . "9d0fd5f56898a5237c1de3363ad416aeab7f880e") (:authors ("Felix Geller" . "fgeller@gmail.com")) (:maintainer "Felix Geller" . "fgeller@gmail.com") (:keywords "theme" "basic" "minimal" "colors") (:url . "http://github.com/fgeller/basic-theme.el"))]) - (bats-mode . [(20160514 615) nil "Emacs mode for editing and running Bats tests" single ((:commit . "d519f7c89f5ae17dfc33400596df4564b478315f") (:authors ("Doug MacEachern")) (:maintainer "Doug MacEachern") (:keywords "bats" "tests") (:url . "https://github.com/dougm/bats-mode"))]) + (bats-mode . [(20230325 7) nil "Emacs mode for editing and running Bats tests" single ((:commit . "fa88930b1baba101ae6474f289a239a236a7d19f") (:authors ("Doug MacEachern")) (:maintainer "Doug MacEachern") (:keywords "bats" "tests") (:url . "https://github.com/dougm/bats-mode"))]) (battery-notifier . [(20220705 2030) ((alert (1 3))) "Notify when battery capacity is low" single ((:commit . "b7301d3633afff78609afd45dcf78268f98d52d3") (:authors ("Jason Johnson" . "jason@fullsteamlabs.com")) (:maintainer "Jason Johnson" . "jason@fullsteamlabs.com") (:keywords "hardware" "battery") (:url . "https://github.com/jasonmj/battery-notifier"))]) (battle-haxe . [(20210219 354) ((emacs (25)) (company (0 9 9)) (helm (3 0)) (async (1 9 3)) (cl-lib (0 5)) (dash (2 18 0)) (s (1 10 0)) (f (0 19 0))) "A Haxe development system, with code completion and more" single ((:commit . "2f32c81dcecfc68fd410cb9d2aca303d6e3028c7") (:authors ("Alon Tzarafi " . "alontzarafi@gmail.com")) (:maintainer "Alon Tzarafi " . "alontzarafi@gmail.com") (:keywords "programming" "languages" "completion") (:url . "https://github.com/AlonTzarafi/battle-haxe"))]) (bazel . [(20221105 2049) ((emacs (27 1))) "Bazel support for Emacs" single ((:commit . "68d58547dd1df92adc91715f97c3dcd125b00810") (:keywords "build tools" "languages") (:url . "https://github.com/bazelbuild/emacs-bazel-mode"))]) @@ -346,7 +345,7 @@ (blog-admin . [(20170923 1409) ((ctable (0 1 1)) (s (1 10 0)) (f (0 17 3)) (names (20151201 0)) (cl-lib (0 5))) "Blog admin for emacs with hexo/org-page supported" tar ((:commit . "b5f2e1dad7d68ec903619f7280bb0bcb7e398a1e") (:authors (nil . "code.falling@gmail.com")) (:maintainer nil . "code.falling@gmail.com") (:keywords "tools" "blog" "org" "hexo" "org-page"))]) (blog-minimal . [(20181021 849) ((ht (1 5)) (simple-httpd (1 4 6)) (mustache (0 22)) (s (1 11 0)) (org (9 0 3))) "a simple static site generator based on org mode" tar ((:commit . "a634a2db0b80cb445ef0b072d1a1482ced91f9ad") (:authors ("Thank Fly" . "thiefuniverses@gmail.com")) (:maintainer "Thank Fly" . "thiefuniverses@gmail.com") (:keywords "tools") (:url . "https://github.com/thiefuniverse/blog-minimal"))]) (blox . [(20220521 807) ((emacs (25 1))) "Interaction with Roblox tooling" single ((:commit . "9ebebb65fb38b5570ba8dfbb5ec835633c06b67d") (:authors ("Kenneth Loeffler" . "kenloef@gmail.com")) (:maintainer "Kenneth Loeffler" . "kenloef@gmail.com") (:keywords "roblox" "rojo" "tools") (:url . "https://github.com/kennethloeffler/blox"))]) - (bluesound . [(20221104 656) ((emacs (26 1))) "Play, pause, resume music on a Bluesound player" single ((:commit . "416b9825db5feea326388ca1bec2614046522006") (:authors ("R.W. van 't Veer")) (:maintainer "R.W. van 't Veer") (:keywords "convenience" "multimedia") (:url . "https://git.sr.ht/~rwv/bluesound-el/"))]) + (bluesound . [(20230328 1430) ((emacs (26 1))) "Play, pause, resume music on a Bluesound player" single ((:commit . "f6a43dbe8b5a3d4541170717571c793ae3313c98") (:authors ("R.W. van 't Veer")) (:maintainer "R.W. van 't Veer") (:keywords "convenience" "multimedia") (:url . "https://git.sr.ht/~rwv/bluesound-el/"))]) (bm . [(20210421 1351) nil "Visible bookmarks in buffer." tar ((:commit . "da9735f8b3f833a21b39a7bbfa7f563ba96429f3") (:authors ("Jo Odland ")) (:maintainer "Jo Odland ") (:keywords "bookmark" "highlight" "faces" "persistent") (:url . "https://github.com/joodland/bm"))]) (bmx-mode . [(20210319 620) ((emacs (25 1)) (cl-lib (0 5)) (company (0 9 4)) (dash (2 13 0)) (s (1 12 0))) "Batch Mode eXtras" single ((:commit . "6f008707efe0bb5646f0c1b0d6f57f0a8800e200") (:authors ("Jostein Kjønigsen" . "jostein@gmail.com")) (:maintainer "Jostein Kjønigsen" . "jostein@gmail.com") (:keywords "c" "convenience" "tools") (:url . "http://github.com/josteink/bmx-mode"))]) (bnf-mode . [(20221205 1451) ((cl-lib (0 5)) (emacs (25 1))) "Major mode for editing BNF grammars." tar ((:commit . "dcdb422e219b29d53a9385e19083441c57f0beb3") (:authors ("Serghei Iakovlev" . "egrep@protonmail.ch")) (:maintainer "Serghei Iakovlev" . "egrep@protonmail.ch") (:keywords "languages") (:url . "https://github.com/sergeyklay/bnf-mode"))]) @@ -363,16 +362,16 @@ (borg . [(20230319 1956) ((emacs (27 1)) (epkg (3 3 3)) (magit (3 3 0))) "Assimilate Emacs packages as Git submodules" tar ((:commit . "723ffe760d535618794d9e90ff17c18f66120131") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "tools") (:url . "https://github.com/emacscollective/borg"))]) (borland-blue-theme . [(20160117 1321) ((emacs (24 1))) "Blue/yellow theme based on old DOS Borland/Turbo C IDE" single ((:commit . "db74eefebbc89d3c62575f8f50b319e87b4a3470") (:authors ("Alexey Veretennikov ")) (:maintainer "Alexey Veretennikov ") (:keywords "themes") (:url . "http://github.com/fourier/borland-blue-theme"))]) (boron-theme . [(20170808 1308) ((emacs (24 0))) "an Emacs 24 theme based on Boron (tmTheme)" single ((:commit . "87ae1a765e07429fec25d2f29b004f84b52d2e0a") (:authors ("Jason Milkins")) (:maintainer "Jason Milkins") (:url . "https://github.com/emacsfodder/tmtheme-to-deftheme"))]) - (boxes . [(20221213 2047) ((emacs (24 3))) "ASCII boxes unlimited!" single ((:commit . "380e7814acb7de490a3b5729c3b943f875bc6a73") (:authors ("Jason L. Shiffer" . "jshiffer@zerotao.com")) (:maintainer "Jason L. Shiffer" . "jshiffer@zerotao.com") (:keywords "extensions") (:url . "https://boxes.thomasjensen.com"))]) + (boxes . [(20230326 1932) ((emacs (24 3))) "ASCII boxes unlimited!" single ((:commit . "77d02890a749a30bc228c848ec1d4bc9b09ac6c0") (:authors ("Jason L. Shiffer" . "jshiffer@zerotao.com")) (:maintainer "Jason L. Shiffer" . "jshiffer@zerotao.com") (:keywords "extensions") (:url . "https://boxes.thomasjensen.com"))]) (boxquote . [(20220919 714) ((cl-lib (0 5))) "Quote text with a semi-box." single ((:commit . "fe676396fa7e4372e01bf2c3d9a62e8d53615d46") (:authors ("Dave Pearson" . "davep@davep.org")) (:maintainer "Dave Pearson" . "davep@davep.org") (:keywords "quoting") (:url . "https://github.com/davep/boxquote.el"))]) (bpe . [(20141228 2205) ((emacs (24 1))) "Blog from Org mode to Blogger" single ((:commit . "7b5b25f83506e6c9f4075d3803fa32404943a189") (:authors ("Yuta Yamada ")) (:maintainer "Yuta Yamada ") (:keywords "blogger" "blog") (:url . "https://github.com/yuutayamada/bpe"))]) (bpftrace-mode . [(20190608 2201) ((emacs (24 0))) "Major mode for editing bpftrace script files" single ((:commit . "587b39ea7a1d786df5c04796d51bf2a5a4eda0d7") (:authors ("Jay Kamat" . "jaygkamat@gmail.com")) (:maintainer "Jay Kamat" . "jaygkamat@gmail.com") (:keywords "highlight" "c") (:url . "http://gitlab.com/jgkamat/bpftrace-mode"))]) (bpr . [(20180220 1844) ((emacs (24))) "Background Process Runner" tar ((:commit . "af84a83dea09d86e77d87ac30604f2c5b4bf4117") (:authors ("Ilya Babanov" . "ilya-babanov@ya.ru")) (:maintainer "Ilya Babanov" . "ilya-babanov@ya.ru") (:keywords "background" "async" "process" "management") (:url . "https://github.com/ilya-babanov/emacs-bpr"))]) - (bqn-mode . [(20230311 1245) ((emacs (26 1))) "Emacs mode for BQN" tar ((:commit . "8dd46215c4534a057758bd4ef15173d2820cefa7") (:authors ("Marshall Lochbaum" . "mwlochbaum@gmail.com")) (:maintainer "Marshall Lochbaum" . "mwlochbaum@gmail.com") (:url . "https://github.com/museoa/bqn-mode"))]) + (bqn-mode . [(20230407 210) ((emacs (26 1))) "Emacs mode for BQN" tar ((:commit . "87677284ae6d01b716f00cb858c22587da2becd3") (:authors ("Marshall Lochbaum" . "mwlochbaum@gmail.com")) (:maintainer "Marshall Lochbaum" . "mwlochbaum@gmail.com") (:url . "https://github.com/museoa/bqn-mode"))]) (bracketed-paste . [(20160407 2348) ((emacs (24 3))) "bracketed paste mode support within emacs -nw" single ((:commit . "843ce3bbb63d560face889e13a57a2f7543957d5") (:authors ("Takeshi Banse" . "takebi@laafc.net")) (:maintainer "Takeshi Banse" . "takebi@laafc.net") (:keywords "terminals"))]) (brainfuck-mode . [(20150113 842) ((langdoc (20130601 1450))) "Brainfuck mode for Emacs" single ((:commit . "36e69552bb3b97a4f888d362c59845651bd0d492") (:authors ("Tomoya Tanjo" . "ttanjo@gmail.com")) (:maintainer "Tomoya Tanjo" . "ttanjo@gmail.com") (:keywords "brainfuck" "langdoc") (:url . "https://github.com/tom-tan/brainfuck-mode/"))]) (brazilian-holidays . [(20220828 2348) ((emacs (26))) "Brazilian holidays" single ((:commit . "03206ea673df49c91a8f924db799620713d86240") (:authors ("Jaguaraquem A. Reinaldo" . "jaguar.adler@gmail.com")) (:maintainer "Jaguaraquem A. Reinaldo" . "jaguar.adler@gmail.com") (:keywords "calendar" "holidays" "brazilian") (:url . "https://github.com/jadler/brazilian-holidays"))]) - (brec-mode . [(20230227 1146) ((emacs (24 3))) "A major mode for editing Breccian text" single ((:commit . "8672af3d473985b4ccd1d06a41ab74bf0d745655") (:authors ("Michael Allan" . "mike@reluk.ca")) (:maintainer "Michael Allan" . "mike@reluk.ca") (:keywords "outlines" "wp") (:url . "http://reluk.ca/project/Breccia/Emacs/"))]) + (brec-mode . [(20230322 1406) ((emacs (24 3))) "A major mode for editing Breccian text" single ((:commit . "41a83edda400c34857aca5e91b651f2dfb0b8009") (:authors ("Michael Allan" . "mike@reluk.ca")) (:maintainer "Michael Allan" . "mike@reluk.ca") (:keywords "outlines" "wp") (:url . "http://reluk.ca/project/Breccia/Emacs/"))]) (brf . [(20230321 1843) ((fringe-helper (0 1 1)) (emacs (24 3))) "Brf-mode provides features from the legendary editor Brief" tar ((:commit . "3113bfff9c73d5901e7a684a066bfa7a13ce8f6a") (:authors ("Mike Woolley" . "mike@bulsara.com")) (:maintainer "Mike Woolley" . "mike@bulsara.com") (:keywords "brief" "crisp" "emulations") (:url . "https://bitbucket.org/MikeWoolley/brf-mode"))]) (brightscript-mode . [(20220906 827) ((emacs (26 3))) "Major mode for editing Brightscript files" single ((:commit . "025d6f5a70752c62a28d4f86c053a283b3898a49") (:authors ("Daniel Mircea" . "daniel@viseztrance.com")) (:maintainer nil . "daniel@viseztrance.com") (:keywords "languages") (:url . "https://github.com/viseztrance/brightscript-mode"))]) (broadcast . [(20151205 212) ((emacs (24 4))) "Links buffers together for simultaneous editing." single ((:commit . "f6f9cd2e0e3f8c31d6b8e7446c27eb0e50b25f16") (:authors ("Russell Black" . "killdash9@github")) (:maintainer "Russell Black" . "killdash9@github") (:keywords "convenience" "frames" "link" "cursors") (:url . "https://github.com/killdash9/broadcast.el"))]) @@ -442,7 +441,7 @@ (camcorder . [(20190317 2138) ((emacs (24)) (names (20150000)) (cl-lib (0 5))) "Record screencasts in gif or other formats." single ((:commit . "b11ca61491a27681bb3131b72b51c105fd996bed") (:authors ("Artur Malabarba" . "bruce.connor.am@gmail.com")) (:maintainer "Artur Malabarba" . "bruce.connor.am@gmail.com") (:keywords "multimedia" "screencast") (:url . "http://github.com/Bruce-Connor/camcorder.el"))]) (caml . [(20230129 1145) ((emacs (24 3))) "Caml mode for GNU Emacs" tar ((:commit . "959a5a27bfdbaa43a9ff99be136d62e0798f5e01") (:authors ("Jacques Garrigue" . "garrigue@kurims.kyoto-u.ac.jp") ("Ian T Zimmerman" . "itz@rahul.net") ("Damien Doligez" . "damien.doligez@inria.fr")) (:maintainer "Christophe Troestler" . "Christophe.Troestler@umons.ac.be") (:keywords "ocaml") (:url . "https://github.com/ocaml/caml-mode"))]) (cangjie . [(20230219 1150) ((emacs (24 4)) (s (1 12 0)) (dash (2 14 1)) (f (0 2 0))) "Retrieve cangjie code for han characters" tar ((:commit . "d6882e15f47fdde37e9f739dde604d77d25f11db") (:keywords "convenience" "writing") (:url . "https://github.com/kisaragi-hiu/cangjie.el"))]) - (cape . [(20230305 1641) ((emacs (27 1)) (compat (29 1 4 0))) "Completion At Point Extensions" tar ((:commit . "23ca151dd41c95ce41956a0483aefee4a92b07ea") (:authors ("Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainer "Daniel Mendler" . "mail@daniel-mendler.de") (:url . "https://github.com/minad/cape"))]) + (cape . [(20230406 1657) ((emacs (27 1)) (compat (29 1 4 0))) "Completion At Point Extensions" tar ((:commit . "a49e50af8914f5101b3dce07e752516a8136f518") (:authors ("Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainer "Daniel Mendler" . "mail@daniel-mendler.de") (:url . "https://github.com/minad/cape"))]) (capnp-mode . [(20210707 2310) nil "Major mode for editing Capn' Proto Files" single ((:commit . "f7fccad7d737f77896211bec1173117497634143") (:authors ("Brian Taylor" . "el.wubo@gmail.com")) (:maintainer "Brian Taylor" . "el.wubo@gmail.com") (:url . "https://github.com/capnproto/capnproto"))]) (capture . [(20130828 1644) nil "screencasting with \"avconv\" or \"ffmpeg\"" tar ((:commit . "9140c207b48b3520a2f06674b3e1bee2fc92b80c") (:authors ("Sergey Pashinin ")) (:maintainer "Sergey Pashinin "))]) (carbon-now-sh . [(20220701 332) ((emacs (24 4))) "https://carbon.now.sh integration." single ((:commit . "e66f2e43e288f35ad9075f5fc84d59ad348efc88") (:authors ("Vitalii Elenhaupt")) (:maintainer "Vitalii Elenhaupt") (:keywords "convenience") (:url . "https://github.com/veelenga/carbon-now-sh.el"))]) @@ -458,7 +457,7 @@ (cask-package-toolset . [(20170921 2256) ((emacs (24)) (cl-lib (0 3)) (s (1 6 1)) (dash (1 8 0)) (f (0 10 0)) (commander (0 2 0)) (ansi (0 1 0)) (shut-up (0 1 0))) "Toolsettize your package" tar ((:commit . "2c74cd827e88c7f8360581a841e45f0b794510e7") (:authors ("Adrien Becchis" . "adriean.khisbe@live.fr")) (:maintainer "Adrien Becchis" . "adriean.khisbe@live.fr") (:keywords "convenience" "tools") (:url . "http://github.com/AdrieanKhisbe/cask-package-toolset.el"))]) (caskxy . [(20140513 1539) ((log4e (0 2 0)) (yaxception (0 1))) "Control Cask in Emacs" single ((:commit . "279f3ab79bd77fe69cb3148a79896b9bf118a9b3") (:authors ("Hiroaki Otsu" . "ootsuhiroaki@gmail.com")) (:maintainer "Hiroaki Otsu" . "ootsuhiroaki@gmail.com") (:keywords "convenience") (:url . "https://github.com/aki2o/caskxy"))]) (catmacs . [(20170826 1157) ((emacs (24))) "Simple CAT interface for Yaesu Transceivers." single ((:commit . "6ea9ee195661fe95355413856476c45dcc8e24e8") (:authors ("Frank Singleton" . "b17flyboy@gmail.com")) (:maintainer "Frank Singleton" . "b17flyboy@gmail.com") (:keywords "comm" "hardware") (:url . "https://bitbucket.org/pymaximus/catmacs"))]) - (catppuccin-theme . [(20230223 808) ((emacs (25 1))) "Catppuccin for Emacs - 🍄 Soothing pastel theme for Emacs" tar ((:commit . "cc450390d0b3a8fdbb032ee96deb0aeaa1984ce0") (:authors ("nyxkrage")) (:maintainer "Carsten Kragelund" . "carsten@kragelund.me") (:url . "https://github.com/catppuccin/emacs"))]) + (catppuccin-theme . [(20230401 622) ((emacs (25 1))) "Catppuccin for Emacs - 🍄 Soothing pastel theme for Emacs" tar ((:commit . "fa9e421b5e041217d4841bea27384faa194deff6") (:authors ("nyxkrage")) (:maintainer "Carsten Kragelund" . "carsten@kragelund.me") (:url . "https://github.com/catppuccin/emacs"))]) (cbm . [(20171116 1240) ((cl-lib (0 5))) "Switch to similar buffers." single ((:commit . "5b41c936ba9f6d170309a85ffebc9939c1050b31") (:authors ("Lukas Fürmetz" . "fuermetz@mailbox.org")) (:maintainer "Lukas Fürmetz" . "fuermetz@mailbox.org") (:keywords "buffers") (:url . "http://github.com/akermu/cbm.el"))]) (cbor . [(20221225 1909) ((emacs (25 1))) "CBOR utilities" single ((:commit . "b369e8ac68c4cbabeb3a57f7db6bd44341523d72") (:authors ("Oscar Najera ")) (:maintainer "Oscar Najera" . "hi@oscarnajera.com") (:url . "https://github.com/Titan-C/cardano.el"))]) (cc-cedict . [(20210814 819) ((emacs (26 1))) "Interface to CC-CEDICT (a Chinese-English dictionary)" single ((:commit . "03fbe7d1589d36f627ef9fe7b86f9fe6f623cbb3") (:authors ("Xu Chunyang")) (:maintainer "Xu Chunyang") (:url . "https://github.com/xuchunyang/cc-cedict.el"))]) @@ -470,13 +469,13 @@ (cdnjs . [(20161031 1522) ((dash (2 13 0)) (deferred (0 4)) (f (0 17 2)) (pkg-info (0 5))) "A front end for http://cdnjs.com" single ((:commit . "ce19880d3ec3d81e6c665d0b1dfea99cc7a3f908") (:authors ("Yasuyuki Oka" . "yasuyk@gmail.com")) (:maintainer "Yasuyuki Oka" . "yasuyk@gmail.com") (:keywords "tools") (:url . "https://github.com/yasuyk/cdnjs.el"))]) (cedit . [(20200816 526) nil "paredit-like commands for c-like languages" single ((:commit . "cb38316903e6cfa8b8c978defa7e1dafcd4e0c12") (:authors ("zk_phi")) (:maintainer "zk_phi") (:url . "http://zk-phi.gitub.io/"))]) (celery . [(20170225 924) ((emacs (24)) (dash-functional (2 11 0)) (s (1 9 0)) (deferred (0 3 2))) "a minor mode to draw stats from celery and more?" single ((:commit . "b3378dd81e5a717432123fb13d70201da5dc841a") (:authors ("ardumont" . "eniotna.t@gmail.com")) (:maintainer "ardumont" . "eniotna.t@gmail.com") (:keywords "celery" "convenience") (:url . "https://github.com/ardumont/emacs-celery"))]) - (celestial-mode-line . [(20180518 822) ((emacs (24))) "Show lunar phase and sunrise/-set time in modeline" single ((:commit . "3f5794aca99b977f1592cf1ab4516ae7922196a1") (:authors ("Peter" . "craven@gmx.net")) (:maintainer "Peter" . "craven@gmx.net") (:keywords "extensions") (:url . "https://github.com/ecraven/celestial-mode-line"))]) + (celestial-mode-line . [(20230323 737) ((emacs (24))) "Show lunar phase and sunrise/-set time in modeline" single ((:commit . "90056322d6664e2e2b593912e4d5e68f1468cafc") (:authors ("Peter" . "craven@gmx.net")) (:maintainer "Peter" . "craven@gmx.net") (:keywords "extensions") (:url . "https://github.com/ecraven/celestial-mode-line"))]) (centaur-tabs . [(20230109 457) ((emacs (24 4)) (powerline (2 4)) (cl-lib (0 5))) "Aesthetic, modern looking customizable tabs plugin" tar ((:commit . "a2890d968d877b269a814a691356fc5877833c39") (:authors ("Emmanuel Bustos" . "ema2159@gmail.com")) (:maintainer "Emmanuel Bustos" . "ema2159@gmail.com") (:url . "https://github.com/ema2159/centaur-tabs"))]) (centered-cursor-mode . [(20200507 1529) nil "cursor stays vertically centered" single ((:commit . "e9ee518d314ef7fb105a1e0cdc33dbb4dfe9d9e4") (:authors ("André Riemann" . "andre.riemann@web.de")) (:maintainer "André Riemann" . "andre.riemann@web.de") (:keywords "convenience") (:url . "https://github.com/andre-r/centered-cursor-mode.el"))]) (centered-window . [(20220125 804) ((emacs (24 4))) "Center the text when there's only one window" single ((:commit . "80965f6c6afe8d918481433984b493de72af5399") (:authors ("Anler Hernández Peral" . "inbox+emacs@anler.me")) (:maintainer "Anler Hernández Peral" . "inbox+emacs@anler.me") (:keywords "faces" "windows") (:url . "https://github.com/anler/centered-window-mode"))]) (centimacro . [(20201225 1132) nil "Assign multiple macros as global key bindings" single ((:commit . "0149877584b333c4f1953f0767f0cae23881b0df") (:authors ("Oleh Krehel" . "ohwoeowho@gmail.com")) (:maintainer "Oleh Krehel" . "ohwoeowho@gmail.com") (:keywords "macros") (:url . "https://github.com/abo-abo/centimacro"))]) (cerbere . [(20181113 1641) ((pkg-info (0 5))) "Unit testing in Emacs for several programming languages" tar ((:commit . "bb18d932b16541105d41a668dbf6fc4e833a6dc2") (:authors ("Nicolas Lamirault" . "nicolas.lamirault@gmail.com")) (:maintainer "Nicolas Lamirault" . "nicolas.lamirault@gmail.com") (:keywords "python" "go" "php" "phpunit" "elisp" "ert" "tests" "tdd") (:url . "https://github.com/nlamirault/cerbere"))]) - (cern-ldap . [(20230321 1439) ((emacs (27 1))) "Library to interact with CERN's LDAP servers" single ((:commit . "01e2798948245316178c392811324c09981a98ee") (:authors ("Nacho Barrientos" . "nacho.barrientos@cern.ch")) (:maintainer "Nacho Barrientos" . "nacho.barrientos@cern.ch") (:keywords "tools" "convenience") (:url . "https://git.sr.ht/~nbarrientos/cern-ldap.el"))]) + (cern-ldap . [(20230325 843) ((emacs (27 1))) "Library to interact with CERN's LDAP servers" single ((:commit . "ebb546221eed36616669ea4e42d35aa8b167202c") (:authors ("Nacho Barrientos" . "nacho.barrientos@cern.ch")) (:maintainer "Nacho Barrientos" . "nacho.barrientos@cern.ch") (:keywords "tools" "convenience") (:url . "https://git.sr.ht/~nbarrientos/cern-ldap.el"))]) (cern-root-mode . [(20220905 2016) ((emacs (26 1))) "Major-mode for running C++ code with ROOT" single ((:commit . "a54241681012b00b514fd20ff894e3c4c83b45c7") (:authors ("Jay Morgan" . "jay@morganwastaken.com")) (:maintainer "Jay Morgan" . "jay@morganwastaken.com") (:keywords "languages" "tools") (:url . "https://github.com/jaypmorgan/cern-root-mode"))]) (ceylon-mode . [(20180606 1324) ((emacs (25))) "Major mode for editing Ceylon source code" single ((:commit . "948515672bc596dc118e8e3ede3ede5ec6a3c95a") (:authors ("Lucas Werkmeister" . "mail@lucaswerkmeister.de")) (:maintainer "Lucas Werkmeister" . "mail@lucaswerkmeister.de") (:keywords "languages" "ceylon") (:url . "https://github.com/lucaswerkmeister/ceylon-mode"))]) (cfengine-code-style . [(20171111 1027) nil "C code style for CFEngine project." single ((:commit . "92a25872a6d1de00c5bfc2b9455ccb0082bf6569") (:authors ("Mikhail Gusarov" . "mikhail.gusarov@cfengine.com")) (:maintainer "Mikhail Gusarov" . "mikhail.gusarov@cfengine.com") (:url . "https://github.com/cfengine/core"))]) @@ -485,7 +484,7 @@ (cfn-mode . [(20220221 1029) ((emacs (26 0)) (f (0 20 0)) (s (1 12 0)) (yaml-mode (0 0 13))) "AWS cloudformation mode" tar ((:commit . "4cf56affe3035fda364109836e26499431095185") (:authors ("William Orr" . "will@worrbase.com")) (:maintainer "William Orr" . "will@worrbase.com") (:keywords "convenience" "languages" "tools") (:url . "https://gitlab.com/worr/cfn-mode"))]) (cframe . [(20201222 1930) ((emacs (26)) (buffer-manage (0 11)) (dash (2 17 0))) "Customize a frame and fast switch size and positions" single ((:commit . "38544521e82befc06e397123a118dd96dda2c6b6") (:authors ("Paul Landes")) (:maintainer "Paul Landes") (:keywords "frames") (:url . "https://github.com/plandes/cframe"))]) (cfrs . [(20220129 1149) ((emacs (26 1)) (dash (2 11 0)) (s (1 10 0)) (posframe (0 6 0))) "Child-frame based read-string" single ((:commit . "f3a21f237b2a54e6b9f8a420a9da42b4f0a63121") (:authors ("Alexander Miller" . "alexanderm@web.de")) (:maintainer "Alexander Miller" . "alexanderm@web.de") (:url . "https://github.com/Alexander-Miller/cfrs"))]) - (cg . [(20230316 856) ((emacs (26 1))) "Major mode for editing Constraint Grammar files" single ((:commit . "59c26d965b689fdc4bd3c11eb5783d11efe370be") (:authors ("Kevin Brubeck Unhammer" . "unhammer@fsfe.org")) (:maintainer "Kevin Brubeck Unhammer" . "unhammer@fsfe.org") (:keywords "languages") (:url . "https://visl.sdu.dk/constraint_grammar.html"))]) + (cg . [(20230329 1235) ((emacs (26 1))) "Major mode for editing Constraint Grammar files" single ((:commit . "1a727582f4e929b9850e36adb8a52d6b4fb45075") (:authors ("Kevin Brubeck Unhammer" . "unhammer@fsfe.org")) (:maintainer "Kevin Brubeck Unhammer" . "unhammer@fsfe.org") (:keywords "languages") (:url . "https://visl.sdu.dk/constraint_grammar.html"))]) (challenger-deep-theme . [(20210120 941) ((emacs (24))) "challenger-deep Theme" single ((:commit . "2a799259406a8b96a688873093ffab6630a3ad3b") (:authors ("MaxSt")) (:maintainer "MaxSt") (:url . "https://github.com/challenger-deep-theme/emacs"))]) (change-inner . [(20210126 1456) ((expand-region (0 7))) "Change contents based on semantic units" single ((:commit . "42cad58aed2caec260f8e8ff61f78a7d3db72d1b") (:authors ("Magnar Sveen" . "magnars@gmail.com")) (:maintainer "Magnar Sveen" . "magnars@gmail.com") (:keywords "convenience" "extensions"))]) (chaos-mode . [(20221227 223) ((emacs (24 3))) "A major mode for the Chaos programming language" single ((:commit . "801d869c461166eb2face2554b9b7883a26374c6") (:authors ("XXIV")) (:maintainer "XXIV") (:keywords "files" "chaos") (:url . "https://github.com/thechampagne/chaos-mode"))]) @@ -510,6 +509,7 @@ (chinese-yasdcv . [(20171015 144) ((cl-lib (0 5)) (pyim (1 6 0))) "Yet another StarDict frontend" tar ((:commit . "5ab830daf1273d5a5cddcb94b56a9737f12d996f") (:authors ("Feng Shu" . "tumashu@gmail.com")) (:maintainer "Feng Shu" . "tumashu@gmail.com") (:keywords "convenience" "chinese" "dictionary") (:url . "https://github.com/tumashu/chinese-yasdcv"))]) (chocolate-theme . [(20210128 1647) ((emacs (24 1)) (autothemer (0 2))) "A dark chocolaty theme" single ((:commit . "ccc05f7ad96d3d1332727689bf6250443adc7ec0") (:url . "http://github.com/SavchenkoValeriy/emacs-chocolate-theme"))]) (choice-program . [(20201217 1751) ((emacs (26)) (dash (2 17 0))) "Parameter based program" tar ((:commit . "b8b1b6c5568f8778783454d5747912487c8e69b8") (:authors ("Paul Landes")) (:maintainer "Paul Landes") (:keywords "execution" "processes" "unix" "lisp") (:url . "https://github.com/plandes/choice-program"))]) + (chroma . [(20230327 1634) ((emacs (24 1))) "Color manipulation library" single ((:commit . "ace854e577a126f830443de89f617e5ff4b4cfce") (:authors ("Nicolas Martyanoff" . "nicolas@n16f.net")) (:maintainer "Nicolas Martyanoff" . "nicolas@n16f.net") (:url . "https://github.com/galdor/chroma"))]) (chronometer . [(20190304 1528) ((emacs (24))) "a [not so] simple chronometer" single ((:commit . "8457b296ef87be339cbe47730b922757d60bdcd5") (:authors ("Marcelo Toledo" . "marcelo@marcelotoledo.com")) (:maintainer "Marcelo Toledo" . "marcelo@marcelotoledo.com") (:keywords "tools" "convenience") (:url . "https://github.com/marcelotoledo/chronometer"))]) (chronometrist . [(20230302 700) ((emacs (27 1)) (dash (2 16 0)) (seq (2 20)) (ts (0 2))) "Friendly and powerful personal time tracker and analyzer" tar ((:commit . "015524bbeb4a112db7bb2af813408cc3c5c93240") (:authors ("contrapunctus" . "xmpp:contrapunctus@jabjab.de")) (:maintainer "contrapunctus" . "xmpp:contrapunctus@jabjab.de") (:keywords "calendar") (:url . "https://tildegit.org/contrapunctus/chronometrist"))]) (chronometrist-goal . [(20210510 1831) ((emacs (25 1)) (alert (1 2)) (chronometrist (0 7 0))) "Adds support for time goals to Chronometrist" single ((:commit . "6cb939d160f5d5966d7853aa23f3ed7c7ef9df44") (:authors ("contrapunctus" . "xmpp:contrapunctus@jabber.fr")) (:maintainer "contrapunctus" . "xmpp:contrapunctus@jabber.fr") (:keywords "calendar") (:url . "https://tildegit.org/contrapunctus/chronometrist-goal"))]) @@ -518,7 +518,7 @@ (chronos . [(20150602 1529) nil "multiple simultaneous countdown / countup timers" tar ((:commit . "b360d9dae57aa553cf2a14ffa0756a51ad71de09") (:authors ("David Knight" . "dxknight@opmbx.org")) (:maintainer "David Knight" . "dxknight@opmbx.org") (:keywords "calendar") (:url . "http://github.com/dxknight/chronos"))]) (chruby . [(20180114 1652) ((cl-lib (0 5))) "Emacs integration for chruby" single ((:commit . "42bc6d521f832eca8e2ba210f30d03ad5529788f") (:authors ("Arne Brasseur" . "arne@arnebrasseur.net")) (:maintainer "Arne Brasseur" . "arne@arnebrasseur.net") (:keywords "languages") (:url . "https://github.com/plexus/chruby.el"))]) (chyla-theme . [(20221213 1012) nil "chyla.org - green color theme." single ((:commit . "b24d0379516857ccf75caff9ae1d00b820c9a6f6") (:authors ("Adam Chyła" . "adam@chyla.org")) (:maintainer "Adam Chyła" . "adam@chyla.org") (:url . "https://github.com/chyla/ChylaThemeForEmacs"))]) - (cider . [(20230320 641) ((emacs (26)) (clojure-mode (5 16 0)) (parseedn (1 0 6)) (queue (0 2)) (spinner (1 7)) (seq (2 22)) (sesman (0 3 2))) "Clojure Interactive Development Environment that Rocks" tar ((:commit . "10cc78675e0f3b7746050e218fe897c4c3173960") (:authors ("Tim King" . "kingtim@gmail.com") ("Phil Hagelberg" . "technomancy@gmail.com") ("Bozhidar Batsov" . "bozhidar@batsov.dev") ("Artur Malabarba" . "bruce.connor.am@gmail.com") ("Hugo Duncan" . "hugo@hugoduncan.org") ("Steve Purcell" . "steve@sanityinc.com")) (:maintainer "Bozhidar Batsov" . "bozhidar@batsov.dev") (:keywords "languages" "clojure" "cider") (:url . "http://www.github.com/clojure-emacs/cider"))]) + (cider . [(20230405 731) ((emacs (26)) (clojure-mode (5 16 0)) (parseedn (1 0 6)) (queue (0 2)) (spinner (1 7)) (seq (2 22)) (sesman (0 3 2))) "Clojure Interactive Development Environment that Rocks" tar ((:commit . "b2d4769db33c000b7b49b94f31935faf4a229ce9") (:authors ("Tim King" . "kingtim@gmail.com") ("Phil Hagelberg" . "technomancy@gmail.com") ("Bozhidar Batsov" . "bozhidar@batsov.dev") ("Artur Malabarba" . "bruce.connor.am@gmail.com") ("Hugo Duncan" . "hugo@hugoduncan.org") ("Steve Purcell" . "steve@sanityinc.com")) (:maintainer "Bozhidar Batsov" . "bozhidar@batsov.dev") (:keywords "languages" "clojure" "cider") (:url . "http://www.github.com/clojure-emacs/cider"))]) (cider-decompile . [(20151122 537) ((cider (0 3 0)) (javap-mode (9))) "decompilation extension for cider" single ((:commit . "5d87035f3c3c14025e8f01c0c53d0ce2c8f56651") (:authors ("Dmitry Bushenko")) (:maintainer "Dmitry Bushenko") (:keywords "languages" "clojure" "cider") (:url . "http://www.github.com/clojure-emacs/cider-decompile"))]) (cider-eval-sexp-fu . [(20190311 2152) ((emacs (24)) (eval-sexp-fu (0 5 0))) "Briefly highlights an evaluated sexp." single ((:commit . "7fd229f1441356866aedba611fd0cf4e89b50921") (:authors ("Sylvain Benner" . "sylvain.benner@gmail.com")) (:maintainer "Sylvain Benner" . "sylvain.benner@gmail.com") (:keywords "languages" "clojure" "cider"))]) (cider-hydra . [(20190816 1121) ((cider (0 22 0)) (hydra (0 13 0))) "Hydras for CIDER." single ((:commit . "c3b8a15d72dddfbc390ab6a454bd7e4c765a2c95") (:authors ("Tianxiang Xiong" . "tianxiang.xiong@gmail.com")) (:maintainer "Tianxiang Xiong" . "tianxiang.xiong@gmail.com") (:keywords "convenience" "tools") (:url . "https://github.com/clojure-emacs/cider-hydra"))]) @@ -530,10 +530,10 @@ (circe . [(20221126 1508) ((emacs (25 1)) (cl-lib (0 5))) "Client for IRC in Emacs" tar ((:commit . "57fe189d7c0b98b9b1b5a59767cea1c7e2c22b13") (:authors ("Jorgen Schaefer" . "forcer@forcix.cx")) (:maintainer "Jorgen Schaefer" . "forcer@forcix.cx") (:keywords "irc" "chat" "comm") (:url . "https://github.com/emacs-circe/circe"))]) (circe-notifications . [(20180102 2318) ((emacs (24 4)) (circe (2 3)) (alert (1 2))) "Add desktop notifications to Circe." single ((:commit . "291149ac12877bbd062da993479d3533a26862b0") (:authors ("Ruben Maher" . "r@rkm.id.au")) (:maintainer "Ruben Maher" . "r@rkm.id.au") (:url . "https://github.com/eqyiel/circe-notifications"))]) (circleci-api . [(20210227 1607) ((emacs (27)) (request (0 3 2))) "Bindings for the CircleCI API" single ((:commit . "1432b0ad0f32b03fec564c0815951d5e096c2f6a") (:authors ("Robin Schroer")) (:maintainer "Robin Schroer") (:url . "https://github.com/sulami/circleci-api"))]) - (citar . [(20230321 1501) ((emacs (27 1)) (parsebib (4 2)) (org (9 5)) (citeproc (0 9))) "Citation-related commands for org, latex, markdown" tar ((:commit . "f8e4dcacffd8f73d47378a832068ded2e6eb4b79") (:authors ("Bruce D'Arcus ")) (:maintainer "Bruce D'Arcus ") (:url . "https://github.com/emacs-citar/citar"))]) - (citar-denote . [(20230322 738) ((emacs (28 1)) (citar (1 1)) (denote (1 2 0)) (dash (2 19 1))) "Minor mode to integrate Citar and Denote" single ((:commit . "756682bcaeeb28bfcdfddbcfe91de8bc28147f73") (:authors ("Peter Prevos" . "peter@prevos.net")) (:maintainer "Peter Prevos" . "peter@prevos.net") (:url . "https://github.com/pprevos/citar-denote"))]) - (citar-embark . [(20230321 1501) ((emacs (27 1)) (embark (0 17)) (citar (0 9 7))) "Citar/Embark integration" single ((:commit . "f8e4dcacffd8f73d47378a832068ded2e6eb4b79") (:authors ("Bruce D'Arcus" . "bdarcus@gmail.com")) (:maintainer "Bruce D'Arcus" . "bdarcus@gmail.com") (:keywords "bib" "extensions") (:url . "https://github.com/emacs-citar/citar-embark"))]) - (citar-org-roam . [(20230319 1845) ((emacs (27 1)) (org-roam (2 2)) (citar (1 2 0))) "Citar/org-roam integration" single ((:commit . "5dc976c113225254a2b4118d20b8a7d0e1ed9f48") (:authors ("Bruce D'Arcus" . "bdarcus@gmail.com")) (:maintainer "Bruce D'Arcus" . "bdarcus@gmail.com") (:url . "https://github.com/emacs-citar/citar-org-roam"))]) + (citar . [(20230325 136) ((emacs (27 1)) (parsebib (4 2)) (org (9 5)) (citeproc (0 9))) "Citation-related commands for org, latex, markdown" tar ((:commit . "02034795f4c3bb46e782f8bd34dd486ce1fb9244") (:authors ("Bruce D'Arcus ")) (:maintainer "Bruce D'Arcus ") (:url . "https://github.com/emacs-citar/citar"))]) + (citar-denote . [(20230403 1038) ((emacs (28 1)) (citar (1 1)) (denote (1 2 0)) (dash (2 19 1))) "Minor mode to integrate Citar and Denote" single ((:commit . "327c7f386e8660c63b48568d23315cbebf95d151") (:authors ("Peter Prevos" . "peter@prevos.net")) (:maintainer "Peter Prevos" . "peter@prevos.net") (:url . "https://github.com/pprevos/citar-denote"))]) + (citar-embark . [(20230323 1926) ((emacs (27 1)) (embark (0 17)) (citar (0 9 7))) "Citar/Embark integration" single ((:commit . "0c6a8038e9b7f72c2e6837bd3342eab942c08d0d") (:authors ("Bruce D'Arcus" . "bdarcus@gmail.com")) (:maintainer "Bruce D'Arcus" . "bdarcus@gmail.com") (:keywords "bib" "extensions") (:url . "https://github.com/emacs-citar/citar-embark"))]) + (citar-org-roam . [(20230404 1225) ((emacs (27 1)) (org-roam (2 2)) (citar (1 2 0))) "Citar/org-roam integration" single ((:commit . "761eed66782fdbb6d65749098caa42ba43e8441d") (:authors ("Bruce D'Arcus" . "bdarcus@gmail.com")) (:maintainer "Bruce D'Arcus" . "bdarcus@gmail.com") (:url . "https://github.com/emacs-citar/citar-org-roam"))]) (citeproc . [(20230228 1414) ((emacs (26)) (dash (2 13 0)) (s (1 12 0)) (f (0 18 0)) (queue (0 2)) (string-inflection (1 0)) (org (9)) (parsebib (2 4))) "A CSL 1.0.2 Citation Processor" tar ((:commit . "290320fc579f886255f00d7268600df7fa5cc7e8") (:authors ("András Simonyi" . "andras.simonyi@gmail.com")) (:maintainer "András Simonyi" . "andras.simonyi@gmail.com") (:keywords "bib") (:url . "https://github.com/andras-simonyi/citeproc-el"))]) (citeproc-org . [(20200915 2009) ((emacs (25 1)) (dash (2 12 0)) (org (9)) (f (0 18 0)) (citeproc (0 1)) (org-ref (1 1 1))) "Render org-mode references in CSL styles" tar ((:commit . "22a759c4f0ec80075014dcc594baa4d1b470d995") (:authors ("András Simonyi" . "andras.simonyi@gmail.com")) (:maintainer "András Simonyi" . "andras.simonyi@gmail.com") (:keywords "org-ref" "org-mode" "cite" "bib") (:url . "https://github.com/andras-simonyi/citeproc-org"))]) (citre . [(20230217 1202) ((emacs (26 1))) "Ctags IDE on the True Editor" tar ((:commit . "4626ada80fabea6b62935567acc1cb8dad607016") (:authors ("Hao Wang" . "amaikinono@gmail.com")) (:maintainer "Hao Wang" . "amaikinono@gmail.com") (:keywords "convenience" "tools") (:url . "https://github.com/universal-ctags/citre"))]) @@ -542,6 +542,7 @@ (clang-capf . [(20221030 1830) ((emacs (24 4))) "Completion-at-point backend for c/c++ using clang" single ((:commit . "5e4dfba90ce86bbc7ee61805edfca04fff93c291") (:authors ("Philip K. ")) (:maintainer "Philip K. ") (:keywords "c" "abbrev" "convenience") (:url . "https://git.sr.ht/~pkal/clang-capf"))]) (clang-format . [(20191106 950) ((cl-lib (0 3))) "Format code using clang-format" single ((:commit . "e48ff8ae18dc7ab6118c1f6752deb48cb1fc83ac") (:keywords "tools" "c"))]) (clang-format+ . [(20190824 2216) ((emacs (25 1)) (clang-format (20180406 1514))) "Minor mode for automatic clang-format application" single ((:commit . "ddd4bfe1a13c2fd494ce339a320a51124c1d2f68") (:keywords "c" "c++" "clang-format") (:url . "https://github.com/SavchenkoValeriy/emacs-clang-format-plus"))]) + (clause . [(20230405 1235) ((emacs (27 1)) (mark-thing-at (0 3))) "Functions to move, mark, kill by clause" single ((:commit . "0ea166fa218618c1b80b60c995f927310c25b02a") (:authors ("Marty Hiatt ")) (:maintainer "Marty Hiatt ") (:keywords "wp" "convenience" "sentences" "text") (:url . "https://codeberg.org/martianh/clause.el"))]) (clean-aindent-mode . [(20171017 2043) nil "Simple indent and unindent, trims indent white-space" single ((:commit . "a97bcae8f43a9ff64e95473e4ef0d8bafe829211") (:authors ("peter marinov" . "efravia@gmail.com")) (:maintainer "peter marinov" . "efravia@gmail.com") (:keywords "indentation" "whitespace" "backspace") (:url . "https://github.com/pmarinov/clean-aindent-mode"))]) (clean-buffers . [(20160529 2259) ((cl-lib (0 5))) "clean useless buffers" single ((:commit . "1be6c54e3095761b6b64bf749faae3dfce94e72a") (:authors ("DarkSun" . "lujun9972@gmail.com")) (:maintainer "DarkSun" . "lujun9972@gmail.com") (:keywords "convenience" "usability" "buffers"))]) (clean-kill-ring . [(20230115 2153) ((emacs (24 4))) "Keep the kill ring clean" single ((:commit . "d05fa7ee97e760d21d533261c7b63eecf223f612") (:authors ("Nicholas Hubbard" . "nicholashubbard@posteo.net")) (:maintainer "Nicholas Hubbard" . "nicholashubbard@posteo.net") (:keywords "kill-ring" "convenience") (:url . "http://github.com/NicholasBHubbard/clean-kill-ring.el"))]) @@ -583,7 +584,7 @@ (cm-mode . [(20170203 2107) ((cl-lib (0 5))) "Minor mode for CriticMarkup" single ((:commit . "276d49c859822265070ae5dfbb403fd7d8d06436") (:authors ("Joost Kremers" . "joostkremers@fastmail.fm")) (:maintainer "Joost Kremers" . "joostkremers@fastmail.fm") (:keywords "text" "markdown"))]) (cmake-font-lock . [(20230304 2223) ((cmake-mode (0 0))) "Advanced, type aware, highlight support for CMake" single ((:commit . "a6038e916bcca807ae695f7d7e5c300c3f38f415") (:authors ("Anders Lindgren")) (:maintainer "Anders Lindgren") (:keywords "faces" "languages") (:url . "https://github.com/Lindydancer/cmake-font-lock"))]) (cmake-ide . [(20210610 1525) ((emacs (24 4)) (cl-lib (0 5)) (seq (1 11)) (levenshtein (0)) (s (1 11 0))) "Calls CMake to find out include paths and other compiler flags" single ((:commit . "28dc4ab5bd01d99553901b4efeb7234280928b18") (:authors ("Atila Neves" . "atila.neves@gmail.com")) (:maintainer "Atila Neves" . "atila.neves@gmail.com") (:keywords "languages") (:url . "http://github.com/atilaneves/cmake-ide"))]) - (cmake-mode . [(20230314 1404) ((emacs (24 1))) "major-mode for editing CMake sources" single ((:commit . "6c71fa6d56d3e2de30de3e0eb1d72375530598c4"))]) + (cmake-mode . [(20230404 1329) ((emacs (24 1))) "major-mode for editing CMake sources" single ((:commit . "9831bb160ac94a92ce3f3a4ebea0948971f62f98"))]) (cmake-project . [(20171121 1115) nil "Integrates CMake build process with Emacs" single ((:commit . "d3f408f226eff3f77f7e00dd519f4efc78fd292d") (:authors ("Alexander Lamaison" . "alexander.lamaison@gmail")) (:maintainer "Alexander Lamaison" . "alexander.lamaison@gmail") (:keywords "c" "cmake" "languages" "tools") (:url . "http://github.com/alamaison/emacs-cmake-project"))]) (cmd-to-echo . [(20161203 2133) ((emacs (24 4)) (s (1 11 0)) (shell-split-string (20151224 208))) "Show the output of long-running commands in the echo area" single ((:commit . "e0e874fc0e1ad6d291e39ed76023445297ad438a") (:authors ("Tijs Mallaerts" . "tijs.mallaerts@gmail.com")) (:maintainer "Tijs Mallaerts" . "tijs.mallaerts@gmail.com"))]) (cmm-mode . [(20150225 746) nil "Major mode for C-- source code" single ((:commit . "c3ad514dff3eb30434f6b20d953276d4c00de1ee"))]) @@ -604,7 +605,7 @@ (coffee-mode . [(20200315 1133) ((emacs (24 3))) "Major mode for CoffeeScript code" single ((:commit . "35a41c7d8233eac0b267d9593e67fb8b6235e134") (:authors ("Chris Wanstrath" . "chris@ozmm.org")) (:maintainer "Chris Wanstrath" . "chris@ozmm.org") (:keywords "coffeescript" "major" "mode") (:url . "http://github.com/defunkt/coffee-mode"))]) (coin-ticker . [(20170611 727) ((request (0 3 0)) (emacs (25))) "Show a cryptocurrency price ticker" single ((:commit . "45108e239e1d129c0cc1ff37f2870cf73087780b") (:authors ("Evan Klitzke" . "evan@eklitzke.org")) (:maintainer "Evan Klitzke" . "evan@eklitzke.org") (:keywords "news") (:url . "https://github.com/eklitzke/coin-ticker-mode"))]) (colonoscopy-theme . [(20170808 1309) ((emacs (24 0))) "an Emacs 24 theme based on Colonoscopy (tmTheme)" single ((:commit . "64bbb322b13dae91ce9f1e3581f836f94f800ead") (:authors ("Jason Milkins")) (:maintainer "Jason Milkins") (:url . "https://github.com/emacsfodder/tmtheme-to-deftheme"))]) - (color-identifiers-mode . [(20230302 226) ((dash (2 5 0)) (emacs (24))) "Color identifiers based on their names" single ((:commit . "1bc474bdbb1086a73638effde51f37a9da748173") (:authors ("Ankur Dave" . "ankurdave@gmail.com")) (:maintainer "Ankur Dave" . "ankurdave@gmail.com") (:keywords "faces" "languages") (:url . "https://github.com/ankurdave/color-identifiers-mode"))]) + (color-identifiers-mode . [(20230405 527) ((dash (2 5 0)) (emacs (24))) "Color identifiers based on their names" single ((:commit . "c4060d1bca6fa2acfe449e086171d4efee62863f") (:authors ("Ankur Dave" . "ankurdave@gmail.com")) (:maintainer "Ankur Dave" . "ankurdave@gmail.com") (:keywords "faces" "languages") (:url . "https://github.com/ankurdave/color-identifiers-mode"))]) (color-moccur . [(20141223 35) nil "multi-buffer occur (grep) mode" single ((:commit . "4f1c59ffd1ccc2ab1a171cd6b721e8cb9e002fb7") (:keywords "convenience") (:url . "http://www.bookshelf.jp/elc/color-moccur.el"))]) (color-theme . [(20190220 1115) nil "An OBSOLETE color-theme implementation" tar ((:commit . "3a2f6b615f5e2401e30d93a3e0adc210bbb4b7aa") (:authors ("Jonadab the Unsightly One" . "jonadab@bright.net")) (:maintainer "Xavier Maillard" . "zedek@gnu.org") (:keywords "faces") (:url . "http://www.emacswiki.org/cgi-bin/wiki.pl?ColorTheme"))]) (color-theme-approximate . [(20140228 436) nil "Makes Emacs theme works on terminal transparently" single ((:commit . "f54301ca39bc5d2ffb000f233f8114184a3e7d71") (:authors ("Tung Dao" . "me@tungdao.com")) (:maintainer "Tung Dao" . "me@tungdao.com"))]) @@ -631,7 +632,7 @@ (commenter . [(20160219 1627) ((emacs (24 4)) (let-alist (1 0 4))) "multiline-comment support package" single ((:commit . "6d1885419434ba779270c6fda0e30d390bb074bd") (:authors ("Yuta Yamada ")) (:maintainer "Yuta Yamada ") (:keywords "comment") (:url . "https://github.com/yuutayamada/commenter"))]) (commify . [(20220531 1301) ((s (1 9 0))) "Toggle grouping commas in numbers" single ((:commit . "c4aeccae5b4a073fc3f4e8bd780a2ebbb7d5e533") (:authors ("Daniel E. Doherty" . "ded-commify@ddoherty.net")) (:maintainer "Daniel E. Doherty" . "ded-commify@ddoherty.net") (:keywords "convenience" "editing" "numbers" "grouping" "commas") (:url . "https://github.com/ddoherty03/commify"))]) (common-lisp-snippets . [(20180226 1523) ((yasnippet (0 8 0))) "Yasnippets for Common Lisp" tar ((:commit . "1ddf808311ba4d9e8444a1cb50bd5ee75e4111f6") (:authors ("Mark Karpov" . "markkarpov92@gmail.com")) (:maintainer "Mark Karpov" . "markkarpov92@gmail.com") (:keywords "snippets") (:url . "https://github.com/mrkkrp/common-lisp-snippets"))]) - (company . [(20230303 2331) ((emacs (25 1))) "Modular text completion framework" tar ((:commit . "83c408b187b957f5939ee814de68d46993247d4f") (:authors ("Nikolaj Schumacher")) (:maintainer "Dmitry Gutov" . "dgutov@yandex.ru") (:keywords "abbrev" "convenience" "matching") (:url . "http://company-mode.github.io/"))]) + (company . [(20230404 140) ((emacs (25 1))) "Modular text completion framework" tar ((:commit . "246837b12cbedaac0c9e2b654d97426639e0c778") (:authors ("Nikolaj Schumacher")) (:maintainer "Dmitry Gutov" . "dgutov@yandex.ru") (:keywords "abbrev" "convenience" "matching") (:url . "http://company-mode.github.io/"))]) (company-anaconda . [(20200404 1859) ((company (0 8 0)) (anaconda-mode (0 1 1)) (cl-lib (0 5 0)) (dash (2 6 0)) (s (1 9))) "Anaconda backend for company-mode" single ((:commit . "da1566db41a68809ef7f91ebf2de28118067c89b") (:authors ("Artem Malyshev" . "proofit404@gmail.com")) (:maintainer "Artem Malyshev" . "proofit404@gmail.com") (:url . "https://github.com/proofit404/anaconda-mode"))]) (company-ansible . [(20200306 1441) ((emacs (24 4)) (company (0 8 12))) "A company back-end for ansible" tar ((:commit . "79dd421b161efa49fbdffad57fa40edb41f484a3") (:authors ("Krzysztof Magosa" . "krzysztof@magosa.pl")) (:maintainer "Krzysztof Magosa" . "krzysztof@magosa.pl") (:keywords "ansible") (:url . "https://github.com/krzysztof-magosa/company-ansible"))]) (company-arduino . [(20160306 1739) ((emacs (24 1)) (company (0 8 0)) (irony (0 1 0)) (cl-lib (0 5)) (company-irony (0 1 0)) (company-c-headers (20140930)) (arduino-mode (1 0))) "company-mode for Arduino" single ((:commit . "5958b917cc5cc729dc64d74d947da5ee91c48980") (:authors ("Yuta Yamada" . "sleepboy.zzz@gmail.com")) (:maintainer "Yuta Yamada" . "sleepboy.zzz@gmail.com") (:keywords "convenience" "development" "company") (:url . "https://github.com/yuutayamada/company-arduino"))]) @@ -715,10 +716,10 @@ (conllu-mode . [(20200501 2328) ((emacs (25)) (cl-lib (0 5)) (flycheck (30)) (hydra (0 13 0)) (s (1 0))) "editing mode for CoNLL-U files" tar ((:commit . "0db3063572b0de08874822e20570bb153747e6ed") (:authors ("bruno cuconato" . "bcclaro+emacs@gmail.com")) (:maintainer "bruno cuconato" . "bcclaro+emacs@gmail.com") (:keywords "extensions") (:url . "https://github.com/odanoburu/conllu-mode"))]) (connection . [(20191111 446) nil "TCP-based client connection" single ((:commit . "c9cad101100975e88873636bfd426b7a19304ebd") (:authors ("Torsten Hilbrich" . "torsten.hilbrich@gmx.net")) (:maintainer "Torsten Hilbrich" . "torsten.hilbrich@gmx.net") (:keywords "network"))]) (constant-theme . [(20180921 1012) ((emacs (24 1))) "A calm, dark, almost monochrome color theme." tar ((:commit . "0feb9f99d708633d62fa548c953ebbe68fd70de0") (:authors ("Jannis Pohlmann" . "contact@jannispohlmann.de")) (:maintainer "Jannis Pohlmann" . "contact@jannispohlmann.de") (:keywords "themes") (:url . "https://github.com/jannis/emacs-constant-theme"))]) - (consult . [(20230322 747) ((emacs (27 1)) (compat (29 1 4 0))) "Consulting completing-read" tar ((:commit . "28b74703113765137cc4639285e511bd73fd99e6") (:authors ("Daniel Mendler and Consult contributors")) (:maintainer "Daniel Mendler" . "mail@daniel-mendler.de") (:url . "https://github.com/minad/consult"))]) + (consult . [(20230406 1519) ((emacs (27 1)) (compat (29 1 4 1))) "Consulting completing-read" tar ((:commit . "f93949999d3681dbede5cd88c849199d7adf3d8d") (:authors ("Daniel Mendler and Consult contributors")) (:maintainer "Daniel Mendler" . "mail@daniel-mendler.de") (:url . "https://github.com/minad/consult"))]) (consult-ag . [(20230227 406) ((emacs (27 1)) (consult (0 32))) "The silver searcher integration using Consult" single ((:commit . "9eb4df265aedf2628a714610c2ade6d2f21de053") (:authors ("Kanon Kakuno" . "yadex205@outlook.jp")) (:maintainer "Kanon Kakuno" . "yadex205@outlook.jp") (:url . "https://github.com/yadex205/consult-ag"))]) (consult-codesearch . [(20230315 1424) ((emacs (27 1)) (consult (0 20))) "Consult interface for codesearch" single ((:commit . "51df545bb57b468058245950322ae15f6c3a0ce2") (:authors ("Youngjoo Lee" . "youngker@gmail.com")) (:maintainer "Youngjoo Lee" . "youngker@gmail.com") (:keywords "tools") (:url . "https://github.com/youngker/consult-codesearch"))]) - (consult-company . [(20220830 1834) ((emacs (27 1)) (company (0 9)) (consult (0 9))) "Consult frontend for company" single ((:commit . "5d8275bff131ce2aaa678dd46aac345eb4fc8b27") (:authors ("mohsin kaleem" . "mohkale@kisara.moe")) (:maintainer "mohsin kaleem" . "mohkale@kisara.moe") (:url . "https://github.com/mohkale/consult-company"))]) + (consult-company . [(20230403 1911) ((emacs (27 1)) (company (0 9)) (consult (0 9))) "Consult frontend for company" single ((:commit . "24559103a77210c0178b95a842ad13b555be3d43") (:authors ("mohsin kaleem" . "mohkale@kisara.moe")) (:maintainer "mohsin kaleem" . "mohkale@kisara.moe") (:url . "https://github.com/mohkale/consult-company"))]) (consult-dash . [(20220621 226) ((emacs (27 2)) (dash-docs (1 4 0)) (consult (0 16))) "Consult front-end for dash-docs" single ((:commit . "0eb8e133a12570f482efcf367dcc7887c15def32") (:authors ("Ravi R Kiran" . "lists.ravi@gmail.com")) (:maintainer "Ravi R Kiran" . "lists.ravi@gmail.com") (:keywords "consult" "dash" "docs") (:url . "https://codeberg.org/ravi/consult-dash"))]) (consult-dir . [(20221001 1748) ((emacs (26 1)) (consult (0 9)) (project (0 6 0))) "Insert paths into the minibuffer prompt" single ((:commit . "ed8f0874d26f10f5c5b181ab9f2cf4107df8a0eb") (:authors ("Karthik Chikmagalur")) (:maintainer "Karthik Chikmagalur" . "karthik.chikmagalur@gmail.com") (:keywords "convenience") (:url . "https://github.com/karthink/consult-dir"))]) (consult-eglot . [(20230213 1359) ((emacs (27 1)) (eglot (1 7)) (consult (0 31)) (project (0 3 0))) "A consulting-read interface for eglot" single ((:commit . "6504ccd2b7555452c61cc24a45965f7e2a37c44d") (:authors ("mohsin kaleem" . "mohkale@kisara.moe")) (:maintainer "Mohsin Kaleem") (:keywords "tools" "completion" "lsp") (:url . "https://github.com/mohkale/consult-eglot"))]) @@ -729,7 +730,7 @@ (consult-hatena-bookmark . [(20221125 109) ((emacs (27 1)) (consult (0 9)) (async-await (1 1))) "Consult commands for the Hatena Bookmark" single ((:commit . "b85484b11705ebd896878d3ac7fdb12bc8c9637a") (:authors ("Yukinori Kitadai")) (:maintainer "Yukinori Kitadai") (:url . "https://github.com/Nyoho/consult-hatena-bookmark"))]) (consult-ls-git . [(20230120 1500) ((emacs (27 1)) (consult (0 16))) "Consult integration for git" single ((:commit . "7ba583abc16f70c497d038bfcbddbadd6894bd3d") (:authors ("Robin Joy")) (:maintainer "Robin Joy") (:keywords "convenience") (:url . "https://github.com/rcj/consult-ls-git"))]) (consult-lsp . [(20230209 714) ((emacs (27 1)) (lsp-mode (5 0)) (consult (0 16)) (f (0 20 0))) "LSP-mode Consult integration" single ((:commit . "f8db3252c0daa41225ba4ed1c0d178b281cd3e90") (:authors ("Gerry Agbobada")) (:maintainer "Gerry Agbobada") (:keywords "tools" "completion" "lsp") (:url . "https://github.com/gagbo/consult-lsp"))]) - (consult-notes . [(20230316 1720) ((emacs (27 1)) (consult (0 17)) (s (1 12 0)) (dash (2 19))) "Manage notes with consult" tar ((:commit . "43cf9a2f3adbed934b0907fe1fd3664b99ca5afe") (:authors ("Colin McLear" . "mclear@fastmail.com")) (:maintainer "Colin McLear") (:keywords "convenience") (:url . "https://github.com/mclear-tools/consult-notes"))]) + (consult-notes . [(20230401 1922) ((emacs (27 1)) (consult (0 17)) (s (1 12 0)) (dash (2 19))) "Manage notes with consult" tar ((:commit . "941325a3484782017c27e3ffe5ddb3b9151b8740") (:authors ("Colin McLear" . "mclear@fastmail.com")) (:maintainer "Colin McLear") (:keywords "convenience") (:url . "https://github.com/mclear-tools/consult-notes"))]) (consult-notmuch . [(20221216 1701) ((emacs (26 1)) (consult (0 9)) (notmuch (0 31))) "Notmuch search using consult" single ((:commit . "d0d4129d45ccceddaeeaa3631eb42d5dd09a758b") (:authors ("Jose A Ortega Ruiz" . "jao@gnu.org")) (:maintainer "Jose A Ortega Ruiz") (:keywords "mail") (:url . "https://codeberg.org/jao/consult-notmuch"))]) (consult-org-roam . [(20230301 1555) ((emacs (27 1)) (org-roam (2 2 0)) (consult (0 16))) "Consult integration for org-roam" tar ((:commit . "ede01c2710836f055351d2ef0d9fac70b885ac65") (:authors ("jgru ")) (:maintainer "jgru ") (:url . "https://github.com/jgru/consult-org-roam"))]) (consult-project-extra . [(20221013 1014) ((emacs (27 1)) (consult (0 17)) (project (0 8 1))) "Consult integration for project.el" single ((:commit . "9fdf45fa40471900b0b158d73c4b1521a13d47ef") (:authors ("Enrique Kessler Martínez")) (:maintainer "Enrique Kessler Martínez") (:keywords "convenience" "project" "management") (:url . "https://github.com/Qkessler/consult-project-extra"))]) @@ -744,7 +745,7 @@ (conventional-changelog . [(20230101 1656) ((emacs (26 3)) (transient (0 3 7))) "Conventional Changelog Generator" single ((:commit . "56f0e134f0edc1964965575dea259b186d34155a") (:authors ("liuyinz" . "liuyinz95@gmail.com")) (:maintainer "liuyinz" . "liuyinz95@gmail.com") (:keywords "tools") (:url . "https://github.com/liuyinz/emacs-conventional-changelog"))]) (cool-mode . [(20220612 1904) ((emacs (25))) "Major mode for cool compiler language" tar ((:commit . "961e66956412a1dd63f79473a8273da8853f7179") (:authors ("Noah Peart" . "noah.v.peart@gmail.com")) (:maintainer "Noah Peart" . "noah.v.peart@gmail.com") (:url . "https://github.com/nverno/cool-mode"))]) (copy-as-format . [(20190523 258) ((cl-lib (0 5))) "Copy buffer locations as GitHub/Slack/JIRA etc... formatted code" single ((:commit . "a0962b670e26b723ce304b14e3397da453aef84e") (:authors ("Skye Shaw" . "skye.shaw@gmail.com")) (:maintainer "Skye Shaw" . "skye.shaw@gmail.com") (:keywords "github" "slack" "jira" "hipchat" "gitlab" "bitbucket" "org-mode" "pod" "rst" "asciidoc" "tools" "convenience") (:url . "https://github.com/sshaw/copy-as-format"))]) - (copy-file-on-save . [(20200616 518) ((emacs (24 3)) (cl-lib (0 5)) (f (0 17)) (s (1 7 0))) "Copy file on save, automatic deployment it." single ((:commit . "811c8fe638c5616b6471525421e61a4470be3b52") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "files" "comm" "deploy") (:url . "https://github.com/emacs-php/emacs-auto-deployment"))]) + (copy-file-on-save . [(20230402 1829) ((emacs (24 3)) (compat (29))) "Copy file on save, automatic deployment it" single ((:commit . "370b1586feb2690d3c72185bd4f17c31ce03673a") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "files" "comm" "deploy") (:url . "https://github.com/emacs-php/emacs-auto-deployment"))]) (copyit . [(20190919 1258) ((emacs (24 3)) (s (1 9 0))) "Copy it, yank anything!" single ((:commit . "c4f2c28e5b6270e8e3364341619f1154bb4e682e") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "convenience" "yank" "clipboard") (:url . "https://github.com/zonuexe/emacs-copyit"))]) (copyit-pandoc . [(20190919 1258) ((emacs (24 3)) (copyit (0 1 0)) (pandoc (0 0 1))) "Copy it, yank anything!" single ((:commit . "c4f2c28e5b6270e8e3364341619f1154bb4e682e") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "convenience" "yank" "clipboard") (:url . "https://github.com/zonuexe/emacs-copyit"))]) (coq-commenter . [(20170822 2309) ((dash (2 13 0)) (s (1 11 0)) (cl-lib (0 5))) "Coq commenting minor mode for proof" single ((:commit . "7fe9a2cc0ebdb0b1e54a24eb7971d757fb588ac3") (:authors ("Junyoung Clare Jang" . "jjc9310@gmail.com")) (:maintainer "Junyoung Clare Jang" . "jjc9310@gmail.com") (:keywords "comment" "coq" "proof") (:url . "http://github.com/ailrun/coq-commenter"))]) @@ -752,7 +753,7 @@ (corral . [(20160502 948) nil "Quickly surround text with delimiters" single ((:commit . "e7ab6aa118e46b93d4933d1364bc273f57cd6911") (:authors ("Kevin Liu" . "mail@nivekuil.com")) (:maintainer "Kevin Liu" . "mail@nivekuil.com") (:url . "http://github.com/nivekuil/corral"))]) (cort . [(20211020 18) ((emacs (24 1)) (ansi (0 4)) (cl-lib (0 6))) "Simplify extended unit test framework" single ((:commit . "3f64a7b03a4c5b768ec21fd5987acd0d62d16c7b") (:authors ("Naoya Yamashita" . "conao3@gmail.com")) (:maintainer "Naoya Yamashita" . "conao3@gmail.com") (:keywords "test" "lisp") (:url . "https://github.com/conao3/cort.el"))]) (cosmo . [(20170922 744) ((emacs (24 4))) "Cosmological Calculator" single ((:commit . "dd83b09a49a2843606b28279b674b2207040b36b") (:authors ("Francesco Montanari" . "fmnt@fmnt.info")) (:maintainer "Francesco Montanari" . "fmnt@fmnt.info") (:keywords "tools") (:url . "https://gitlab.com/montanari/cosmo-el"))]) - (counsel . [(20221015 936) ((emacs (24 5)) (ivy (0 13 4)) (swiper (0 13 4))) "Various completion functions using Ivy" single ((:commit . "b8be4913a661b557e0d3275726e36871556569d3") (:authors ("Oleh Krehel" . "ohwoeowho@gmail.com")) (:maintainer "Oleh Krehel" . "ohwoeowho@gmail.com") (:keywords "convenience" "matching" "tools") (:url . "https://github.com/abo-abo/swiper"))]) + (counsel . [(20230327 1216) ((emacs (24 5)) (ivy (0 13 4)) (swiper (0 13 4))) "Various completion functions using Ivy" single ((:commit . "8df9516ae6d2e86ec6104b6783ad380fa3945dec") (:authors ("Oleh Krehel" . "ohwoeowho@gmail.com")) (:maintainer "Oleh Krehel" . "ohwoeowho@gmail.com") (:keywords "convenience" "matching" "tools") (:url . "https://github.com/abo-abo/swiper"))]) (counsel-ag-popup . [(20210121 805) ((emacs (26 1)) (counsel (0 13 0)) (transient (0 3 0))) "Interactive search with counsel-ag" single ((:commit . "41d85fe36edd72da68f5009ad9cf9013cd19960d") (:authors ("Eder Elorriaga" . "gexplorer8@gmail.com")) (:maintainer "Eder Elorriaga" . "gexplorer8@gmail.com") (:keywords "convenience" "matching" "tools") (:url . "https://github.com/gexplorer/counsel-ag-popup"))]) (counsel-at-point . [(20230116 951) ((emacs (26 2)) (counsel (0 13 0))) "Context sensitive project search" single ((:commit . "a84cc0e409325d051208c43dfcabcebaa0d98ba3") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:keywords "convenience") (:url . "https://codeberg.org/ideasman42/emacs-counsel-at-point"))]) (counsel-bbdb . [(20220909 727) ((emacs (24 3)) (bbdb (3 2 2 2))) "Quick search&input email from BBDB based on Emacs API `completing-read'" single ((:commit . "ccae56b0551abb305cad087d85f1b6a97adb7c0f") (:authors ("Chen Bin" . "chenbin.sh@gmail.com")) (:maintainer "Chen Bin" . "chenbin.sh@gmail.com") (:keywords "mail" "abbrev" "convenience" "matching") (:url . "https://github.com/redguard/counsel-bbdb"))]) @@ -853,13 +854,13 @@ (dakrone-theme . [(20170801 1933) nil "dakrone's custom dark theme" single ((:commit . "232ad1be5f3572dcbdf528f1655109aa355a6937") (:authors ("Lee Hinman ")) (:maintainer "Lee Hinman ") (:keywords "color" "themes") (:url . "https://github.com/dakrone/dakrone-theme"))]) (danneskjold-theme . [(20221121 634) nil "Beautiful high-contrast Emacs theme." tar ((:commit . "39ff00f8a40bcab96afd9450195124b57becd625") (:authors ("Dmitry Akatov" . "akatovda@yandex.com")) (:maintainer "Dmitry Akatov" . "akatovda@yandex.com") (:url . "https://github.com/rails-to-cosmos/"))]) (dante . [(20221116 840) ((dash (2 12 0)) (emacs (27 1)) (f (0 19 0)) (flycheck (0 30)) (company (0 9)) (flymake (1 0)) (s (1 11 0)) (lcr (1 5))) "Development mode for Haskell" single ((:commit . "914d4f21252a66fe526abedebe24703bc73397d9") (:authors ("Jean-Philippe Bernardy" . "jeanphilippe.bernardy@gmail.com")) (:maintainer "Jean-Philippe Bernardy" . "jeanphilippe.bernardy@gmail.com") (:keywords "haskell" "tools") (:url . "https://github.com/jyp/dante"))]) - (dap-mode . [(20230226 1910) ((emacs (26 1)) (dash (2 18 0)) (lsp-mode (6 0)) (bui (1 1 0)) (f (0 20 0)) (s (1 12 0)) (lsp-treemacs (0 1)) (posframe (0 7 0)) (ht (2 3)) (lsp-docker (1 0 0))) "Debug Adapter Protocol mode" tar ((:commit . "2cff309019de6b49e8508b2b07e1a6c043d3df5f") (:authors ("Ivan Yonchovski" . "yyoncho@gmail.com")) (:maintainer "Ivan Yonchovski" . "yyoncho@gmail.com") (:keywords "languages" "debug") (:url . "https://github.com/emacs-lsp/dap-mode"))]) + (dap-mode . [(20230322 1728) ((emacs (26 1)) (dash (2 18 0)) (lsp-mode (6 0)) (bui (1 1 0)) (f (0 20 0)) (s (1 12 0)) (lsp-treemacs (0 1)) (posframe (0 7 0)) (ht (2 3)) (lsp-docker (1 0 0))) "Debug Adapter Protocol mode" tar ((:commit . "18254e16bae53fb4a8c2434764d3cf674644bf2a") (:authors ("Ivan Yonchovski" . "yyoncho@gmail.com")) (:maintainer "Ivan Yonchovski" . "yyoncho@gmail.com") (:keywords "languages" "debug") (:url . "https://github.com/emacs-lsp/dap-mode"))]) (darcsum . [(20190316 2215) nil "a pcl-cvs like interface for managing darcs patches" single ((:commit . "6a8b690539d133c5e3d17cb23fe4365fbb6fb493") (:authors ("John Wiegley" . "johnw@gnu.org")) (:maintainer "John Wiegley" . "johnw@gnu.org") (:keywords "completion" "convenience" "tools" "vc"))]) (darcula-theme . [(20171227 1845) nil "Inspired by IntelliJ's Darcula theme" single ((:commit . "d9b82b58ded9014985be6658f4ab17e26ed9e93e") (:authors ("Sam Halliday" . "Sam.Halliday@gmail.com")) (:maintainer "Sam Halliday" . "Sam.Halliday@gmail.com") (:keywords "faces") (:url . "https://gitlab.com/fommil/emacs-darcula-theme"))]) (dark-krystal-theme . [(20170808 1300) ((emacs (24 0))) "an Emacs 24 theme based on Dark Krystal (tmTheme)" single ((:commit . "79084b99665dc9ffb0ec62cc092349a5ecebebbc") (:authors ("Jason Milkins")) (:maintainer "Jason Milkins") (:url . "https://github.com/emacsfodder/tmtheme-to-deftheme"))]) (dark-mint-theme . [(20160302 642) nil "dark & minty fresh theme" single ((:commit . "c8ad39b7115baf889b54c3e9bffe32daeab93c29"))]) (dark-souls . [(20140314 1128) nil "Prepare to die" single ((:commit . "2c9437265b52f966b2fb13a410a12f3b1e167cb7") (:authors ("Tom Jakubowski" . "tom@crystae.net")) (:maintainer "Tom Jakubowski" . "tom@crystae.net") (:keywords "games") (:url . "http://github.com/tomjakubowski/dark-souls.el"))]) - (darkman . [(20230318 1035) ((emacs (28 1))) "Seamless integration with Darkman" tar ((:commit . "9f1f713b210ab7317191ab5c73e8e4216d0ef8ab") (:authors ("Aziz Ben Ali" . "tahaaziz.benali@esprit.tn")) (:maintainer "Aziz Ben Ali" . "tahaaziz.benali@esprit.tn") (:keywords "convenience") (:url . "https://grtcdr.tn/darkman.el/"))]) + (darkman . [(20230327 113) ((emacs (28 1))) "Seamless integration with Darkman" tar ((:commit . "3960a534781368c82737ee5d2c4c9e0cef22bf8f") (:authors ("Aziz Ben Ali" . "tahaaziz.benali@esprit.tn")) (:maintainer "Aziz Ben Ali" . "tahaaziz.benali@esprit.tn") (:keywords "convenience") (:url . "https://grtcdr.tn/darkman.el/"))]) (darkmine-theme . [(20160406 624) nil "Yet another emacs dark color theme." single ((:commit . "7f7e82ca03bcad52911fa41fb3e204e32d6ee63e") (:authors ("Pierre Lecocq" . "pierre.lecocq@gmail.com")) (:maintainer "Pierre Lecocq" . "pierre.lecocq@gmail.com") (:url . "https://github.com/pierre-lecocq/darkmine-theme"))]) (darkokai-theme . [(20200614 1452) nil "A darker variant on Monokai." single ((:commit . "5820aeddfc8c869ba840cc534eba776936656a66") (:url . "http://github.com/sjrmanning/darkokai"))]) (darktooth-theme . [(20221014 1418) ((emacs (27 1)) (autothemer (0 2))) "From the darkness... it watches" tar ((:commit . "fd3df73a4d937fa9e12f0b18acb009a9d40f245e") (:url . "http://github.com/emacsfodder/emacs-theme-darktooth"))]) @@ -870,7 +871,7 @@ (dash-at-point . [(20211023 104) nil "Search the word at point with Dash" single ((:commit . "fba1a6f42ea51d05110e12c62bdced664059eb55") (:authors ("Shinji Tanaka" . "shinji.tanaka@gmail.com")) (:maintainer "Shinji Tanaka" . "shinji.tanaka@gmail.com") (:url . "https://github.com/stanaka/dash-at-point"))]) (dash-docs . [(20210830 926) ((emacs (24 4)) (cl-lib (0 5)) (async (1 9 3))) "Offline documentation browser using Dash docsets." tar ((:commit . "29848b6b347ac520f7646c200ed2ec36cea3feda") (:authors ("Raimon Grau" . "raimonster@gmail.com") ("Toni Reina " . "areina0@gmail.com") ("Bryan Gilbert" . "bryan@bryan.sh")) (:maintainer "Raimon Grau" . "raimonster@gmail.com") (:keywords "docs") (:url . "http://github.com/areina/helm-dash"))]) (dash-functional . [(20210826 1149) ((dash (2 18 0))) "Collection of useful combinators for Emacs Lisp" single ((:commit . "39d067b9fbb2db65fc7a6938bfb21489ad990cb4") (:authors ("Matus Goljer" . "matus.goljer@gmail.com") ("Magnar Sveen" . "magnars@gmail.com")) (:maintainer "Matus Goljer" . "matus.goljer@gmail.com") (:keywords "extensions" "lisp") (:url . "https://github.com/magnars/dash.el"))]) - (dashboard . [(20230317 413) ((emacs (26 1))) "A startup screen extracted from Spacemacs" tar ((:commit . "b648a45684677aa29cdb00e4d14d02dd9fa9cb68") (:authors ("Rakan Al-Hneiti" . "rakan.alhneiti@gmail.com")) (:maintainer "Jesús Martínez" . "jesusmartinez93@gmail.com") (:keywords "startup" "screen" "tools" "dashboard") (:url . "https://github.com/emacs-dashboard/emacs-dashboard"))]) + (dashboard . [(20230331 2304) ((emacs (26 1))) "A startup screen extracted from Spacemacs" tar ((:commit . "0f970d298931f9de7b511086728af140bf44a642") (:authors ("Rakan Al-Hneiti" . "rakan.alhneiti@gmail.com")) (:maintainer "Jesús Martínez" . "jesusmartinez93@gmail.com") (:keywords "startup" "screen" "tools" "dashboard") (:url . "https://github.com/emacs-dashboard/emacs-dashboard"))]) (dashboard-hackernews . [(20220516 1809) ((emacs (24)) (dashboard (1 2 5)) (request (0 3 0))) "Display Hacker News on dashboard" single ((:commit . "34d86bffcde7e6d10ffa7c5080a71a144f01f3aa") (:authors ("Hayato KAJIYAMA" . "kaji1216@gmail.com")) (:maintainer "Hayato KAJIYAMA" . "kaji1216@gmail.com") (:url . "https://github.com/hyakt/emacs-dashboard-hackernews"))]) (dashboard-ls . [(20221231 1629) ((emacs (26 1)) (dashboard (1 2 5))) "Display files/directories in current directory on Dashboard" single ((:commit . "b24e0bcb87e20ffcc71efb83a97f9516255fa8e4") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "directory" "file" "show") (:url . "https://github.com/emacs-dashboard/dashboard-ls"))]) (dashboard-project-status . [(20190202 1354) ((emacs (24)) (git (0 1 1)) (dashboard (1 2 5))) "Display a git project status in a dashboard widget." single ((:commit . "7675c138e9df8fe2c626e7ba9bbb8b6717671a41") (:authors ("Jason Duncan" . "jasond496@msn.com")) (:maintainer "Jason Duncan" . "jasond496@msn.com") (:url . "https://github.com/functionreturnfunction/dashboard-project-status"))]) @@ -885,7 +886,7 @@ (db-pg . [(20130131 1902) ((pg (0 12)) (db (0 0 6))) "A PostgreSQL adapter for emacs-db" single ((:commit . "7d5ab86b74b05fe003b3b434d4835f37f3f3eded") (:authors ("Nic Ferrier" . "nic@ferrier.me.uk")) (:maintainer "Nic Ferrier" . "nic@ferrier.me.uk") (:keywords "data" "comm" "database" "postgresql"))]) (dbc . [(20201001 1452) ((emacs (24 4)) (cl-lib (0 5)) (ht (2 3))) "Control how to open buffers" single ((:commit . "6728e72f72347d098b7d75ac4c29a7d687cc9ed3") (:authors ("Matsievskiy S.V.")) (:maintainer "Matsievskiy S.V.") (:keywords "convenience") (:url . "https://gitlab.com/matsievskiysv/display-buffer-control"))]) (ddate . [(20221031 1611) ((emacs (24 4))) "Manage Discordian dates with ddate" single ((:commit . "31576a62792743c614e362688b3752b7a959814e") (:authors ("Erik L. Arneson" . "earneson@arnesonium.com")) (:maintainer "Erik L. Arneson" . "earneson@arnesonium.com") (:keywords "lisp" "dates" "tools" "dashboard") (:url . "https://git.sr.ht/~earneson/emacs-ddate"))]) - (ddskk . [(20230319 758) ((ccc (1 43)) (cdb (20141201 754))) "Simple Kana to Kanji conversion program." tar ((:commit . "fb29a01e3f1e759ad6a7e35af388f6bbdff79309") (:authors ("Masahiko Sato" . "masahiko@kuis.kyoto-u.ac.jp")) (:maintainer "SKK Development Team") (:keywords "japanese" "mule" "input method") (:url . "https://github.com/skk-dev/ddskk"))]) + (ddskk . [(20230328 1058) ((ccc (1 43)) (cdb (20141201 754))) "Simple Kana to Kanji conversion program." tar ((:commit . "98c103ed697e461439401f731c13b3bda02e5128") (:authors ("Masahiko Sato" . "masahiko@kuis.kyoto-u.ac.jp")) (:maintainer "SKK Development Team") (:keywords "japanese" "mule" "input method") (:url . "https://github.com/skk-dev/ddskk"))]) (ddskk-posframe . [(20200812 917) ((emacs (26 1)) (posframe (0 4 3)) (ddskk (16 2 50))) "Show Henkan tooltip for ddskk via posframe" single ((:commit . "299493dd951e5a0b43b8213321e3dc0bac10f762") (:authors ("Naoya Yamashita" . "conao3@gmail.com")) (:maintainer "Naoya Yamashita" . "conao3@gmail.com") (:keywords "tooltip" "convenience" "posframe") (:url . "https://github.com/conao3/ddskk-posframe.el"))]) (deadgrep . [(20230310 1634) ((emacs (25 1)) (dash (2 12 0)) (s (1 11 0)) (spinner (1 7 3))) "fast, friendly searching with ripgrep" single ((:commit . "aed448bf4c8bdf94564b775aac2429be6ed028b9") (:authors ("Wilfred Hughes" . "me@wilfred.me.uk")) (:maintainer "Wilfred Hughes" . "me@wilfred.me.uk") (:keywords "tools") (:url . "https://github.com/Wilfred/deadgrep"))]) (debian-el . [(20211006 1939) nil "Emacs helpers specific to Debian users" tar ((:commit . "a3ef20c269b9192710567571b20718f572942bc4"))]) @@ -913,7 +914,7 @@ (describe-hash . [(20200718 1556) nil "Help function for examining a hash map" single ((:commit . "20dbbbea630055b2401f13a55fbb21216960dc46") (:url . "https://github.com/Junker/describe-hash"))]) (describe-number . [(20151101 55) ((yabin (1 1))) "Describe arbitrarily large number at point." single ((:commit . "40618345a37831804b29589849a785ef5aa5ac24") (:authors ("Morten Slot Kristensen ")) (:maintainer "Morten Slot Kristensen ") (:keywords "describe" "value" "help") (:url . "https://github.com/netromdk/describe-number"))]) (desktop+ . [(20170107 2132) ((emacs (24 4)) (dash (2 11 0)) (f (0 17 2))) "Handle special buffers when saving & restoring sessions" single ((:commit . "d26f369bda96860eef18365cdb5c79f39a2c765c") (:authors ("François Févotte" . "fevotte@gmail.com")) (:maintainer "François Févotte" . "fevotte@gmail.com") (:url . "https://github.com/ffevotte/desktop-plus"))]) - (desktop-environment . [(20230118 820) ((emacs (25 1))) "Helps you control your GNU/Linux computer" single ((:commit . "3b1fe3816ffaef16d210939dc74bd19e0024ff64") (:authors ("Damien Cassou , Nicolas Petton" . "nicolas@petton.fr")) (:maintainer "Damien Cassou , Nicolas Petton" . "nicolas@petton.fr") (:url . "https://gitlab.petton.fr/DamienCassou/desktop-environment"))]) + (desktop-environment . [(20230403 1823) ((emacs (25 1))) "Helps you control your GNU/Linux computer" single ((:commit . "530035e567a95830f1a8b265e026b76d163c7367") (:authors ("Damien Cassou , Nicolas Petton" . "nicolas@petton.fr")) (:maintainer "Damien Cassou , Nicolas Petton" . "nicolas@petton.fr") (:url . "https://gitlab.petton.fr/DamienCassou/desktop-environment"))]) (desktop-mail-user-agent . [(20210519 1008) ((emacs (24 3))) "Call OS default mail program to compose mail" single ((:commit . "caac672ef7e4ddced960fa31cef3a6ba5d7ab451") (:authors ("Lassi Kortela" . "lassi@lassi.io")) (:maintainer "Lassi Kortela" . "lassi@lassi.io") (:keywords "mail") (:url . "https://github.com/lassik/emacs-desktop-mail-user-agent"))]) (desktop-registry . [(20140119 2143) nil "Keep a central registry of desktop files" single ((:commit . "244c2e7f9f0a1050aa8a47ad0b38f4e4584682dd") (:authors ("Tom Willemse" . "tom@ryuslash.org")) (:maintainer "Tom Willemse" . "tom@ryuslash.org") (:keywords "convenience") (:url . "http://projects.ryuslash.org/desktop-registry/"))]) (detached . [(20221129 1430) ((emacs (27 1))) "A package to launch, and manage, detached processes" tar ((:commit . "6b64d4d8064cee781e071e825857b442ea96c3d9") (:authors ("Niklas Eklund" . "niklas.eklund@posteo.net")) (:maintainer "detached.el Development" . "~niklaseklund/detached.el@lists.sr.ht") (:keywords "convenience" "processes") (:url . "https://sr.ht/~niklaseklund/detached.el/"))]) @@ -1047,7 +1048,7 @@ (dokuwiki-mode . [(20170223 1301) nil "Major mode for DokuWiki document" single ((:commit . "e4e116f6fcc373e3f5937c1a7daa5c2c9c6d3fa1") (:authors ("Tsunenobu Kai" . "kai2nenobu@gmail.com")) (:maintainer "Tsunenobu Kai" . "kai2nenobu@gmail.com") (:keywords "hypermedia" "text" "dokuwiki") (:url . "https://github.com/kai2nenobu/emacs-dokuwiki-mode"))]) (dollaro . [(20151123 1302) ((s (1 6 0))) "simple text templates" single ((:commit . "500127f0172ac7a1eec627e026b59136580a74ac") (:authors ("Alessandro Piras" . "laynor@gmail.com")) (:maintainer "Alessandro Piras" . "laynor@gmail.com") (:keywords "tools" "convenience"))]) (doom . [(20180301 2308) ((cl-lib (0 5))) "DOM implementation and manipulation library" single ((:commit . "e59040aefc92dd9b3134eb623624307fb9e4327b") (:authors ("Alex Schroeder" . "alex@gnu.org") ("Henrik.Motakef" . "elisp@henrik-motakef.de") ("Katherine Whitlock" . "toroidal-code@gmail.com") ("Syohei YOSHIDA" . "syohex@gmail.com")) (:maintainer "Alex Schroeder") (:keywords "xml" "dom") (:url . "http://www.github.com/kensanata/doom.el/"))]) - (doom-modeline . [(20230306 250) ((emacs (25 1)) (compat (28 1 1 1)) (shrink-path (0 2 0))) "A minimal and modern mode-line" tar ((:commit . "236fa330c631228e9a513dea2f4598a29b7e8444") (:authors ("Vincent Zhang" . "seagle0128@gmail.com")) (:maintainer "Vincent Zhang" . "seagle0128@gmail.com") (:keywords "faces" "mode-line") (:url . "https://github.com/seagle0128/doom-modeline"))]) + (doom-modeline . [(20230406 623) ((emacs (25 1)) (compat (28 1 1 1)) (shrink-path (0 2 0))) "A minimal and modern mode-line" tar ((:commit . "a86ec8effe242cab8aba09ec0a2c7fed555c1fce") (:authors ("Vincent Zhang" . "seagle0128@gmail.com")) (:maintainer "Vincent Zhang" . "seagle0128@gmail.com") (:keywords "faces" "mode-line") (:url . "https://github.com/seagle0128/doom-modeline"))]) (doom-modeline-now-playing . [(20210831 1442) ((emacs (24 4)) (doom-modeline (3 0 0)) (async (1 9 3))) "Segment for Doom Modeline to show playerctl information" single ((:commit . "ef9158dfdf32e8eb789b69e7394d0bddaa68f42c") (:authors ("Ellis Kenyő" . "me@elken.dev")) (:maintainer "Ellis Kenyő" . "me@elken.dev") (:url . "https://github.com/elken/doom-modeline-now-playing"))]) (doom-themes . [(20230221 610) ((emacs (25 1)) (cl-lib (0 5))) "an opinionated pack of modern color-themes" tar ((:commit . "4c239dbe42232e81c28901000f435746de2a55ab") (:authors ("Henrik Lissner" . "contact@henrik.io")) (:maintainer "Henrik Lissner" . "contact@henrik.io") (:keywords "themes" "faces") (:url . "https://github.com/doomemacs/themes"))]) (dot-mode . [(20180312 2300) ((emacs (24 3))) "minor mode to repeat typing or commands" single ((:commit . "6ca22b73bcdae2363ee9641b822a60685df16a3e") (:authors ("Robert Wyrick" . "rob@wyrick.org")) (:maintainer "Robert Wyrick" . "rob@wyrick.org") (:keywords "convenience") (:url . "https://github.com/wyrickre/dot-mode"))]) @@ -1061,7 +1062,7 @@ (dpaste_de . [(20131015 1225) ((web (0 3 7))) "Emacs mode to paste to dpaste.de" single ((:commit . "ab041443884a7a4bfdc81b055688821e8efc9b02") (:authors ("Thejaswi Puthraya" . "thejaswi.puthraya@gmail.com")) (:maintainer "Thejaswi Puthraya" . "thejaswi.puthraya@gmail.com") (:keywords "pastebin"))]) (dpkg-dev-el . [(20230220 1635) ((debian-el (37))) "Emacs modes for debian packaging" tar ((:commit . "af9aad721cb263e495e2f77df458e9496549c04b") (:authors ("Peter S Galbraith" . "psg@debian.org")) (:maintainer "Peter S Galbraith" . "psg@debian.org"))]) (dr-racket-like-unicode . [(20220810 2000) ((emacs (24 3))) "DrRacket-style unicode input" single ((:commit . "d09b9be289e91e25c941107be5e8f52e7c8f0065") (:authors ("David Christiansen" . "david@davidchristiansen.dk")) (:maintainer "David Christiansen" . "david@davidchristiansen.dk") (:keywords "i18n" "tools") (:url . "https://github.com/david-christiansen/dr-racket-like-unicode"))]) - (dracula-theme . [(20230118 1201) ((emacs (24 3))) "Dracula Theme" single ((:commit . "be1dd97ef3968bef25b9de89e7dc1251f5aaee10") (:authors ("film42")) (:maintainer "Étienne Deparis" . "etienne@depar.is") (:url . "https://github.com/dracula/emacs"))]) + (dracula-theme . [(20230405 1844) ((emacs (24 3))) "Dracula Theme" single ((:commit . "54c26402555ab5b8b7cfd8ee2488c57b2fa5d32a") (:authors ("film42")) (:maintainer "Étienne Deparis" . "etienne@depar.is") (:url . "https://github.com/dracula/emacs"))]) (draft-mode . [(20160106 859) nil "Rough drafting for Emacs." single ((:commit . "4779fb32daf53746459da2def7e08004492d4f18") (:authors ("Eeli Reilin" . "gaudecker@fea.st")) (:maintainer "Eeli Reilin" . "gaudecker@fea.st") (:keywords "draft" "drafting") (:url . "https://github.com/gaudecker/draft-mode"))]) (drag-stuff . [(20161108 749) nil "Drag stuff (lines, words, region, etc...) around" tar ((:commit . "d49fe376d24f0f8ac5ade67b6d7fccc2487c81db") (:authors ("Johan Andersson" . "johan.rejeep@gmail.com")) (:maintainer "Johan Andersson" . "johan.rejeep@gmail.com") (:keywords "speed" "convenience") (:url . "http://github.com/rejeep/drag-stuff"))]) (drawille . [(20160418 1838) ((cl-lib (0 5))) "Drawille implementation in elisp" tar ((:commit . "d582b455c01432bc80933650c52a1f586bd1b5ad") (:authors ("Josuah Demangeon" . "josuah.demangeon@gmail.com")) (:maintainer "Josuah Demangeon" . "josuah.demangeon@gmail.com") (:keywords "graphics") (:url . "https://github.com/sshbio/elisp-drawille"))]) @@ -1073,7 +1074,7 @@ (drupal-spell . [(20130520 1655) nil "Aspell extra dictionary for Drupal" tar ((:commit . "a69f5e3b62c4c0da74ce26c1d00d5b8f7395e4ae") (:authors ("Arne Jørgensen" . "arne@arnested.dk")) (:maintainer "Arne Jørgensen" . "arne@arnested.dk") (:keywords "wp") (:url . "https://github.com/arnested/drupal-spell"))]) (dsvn . [(20221102 1416) nil "Subversion interface" single ((:commit . "36ecd5219584e46dcf6bd252e2ea1ec517d2fc05") (:authors ("David Kågedal" . "davidk@lysator.liu.se") (" Mattias Engdegård" . "mattiase@acm.org")) (:maintainer "Mattias Engdegård" . "mattiase@acm.org") (:keywords "docs"))]) (dtb-mode . [(20210105 1132) ((emacs (25))) "Show device tree souce in dtbs" single ((:commit . "d5bca7d1afaac5615c586b60c7314a1d0e2514dc") (:authors ("Schspa Shi" . "schspa@gmail.com")) (:maintainer "Schspa Shi" . "schspa@gmail.com") (:keywords "dtb" "dts" "convenience") (:url . "https://github.com/schspa/dtb-mode"))]) - (dtk . [(20230304 2348) ((emacs (24 4)) (cl-lib (0 6 1)) (dash (2 12 0)) (seq (1 9)) (s (1 9))) "access SWORD content via diatheke" single ((:commit . "8dffb1e53ac850b3e3698d57b150ed0282a44a7c") (:authors ("David Thompson")) (:maintainer "David Thompson") (:keywords "hypermedia") (:url . "https://github.com/dtk01/dtk.el"))]) + (dtk . [(20230406 1321) ((emacs (24 4)) (cl-lib (0 6 1)) (dash (2 12 0)) (seq (1 9)) (s (1 9))) "access SWORD content via diatheke" single ((:commit . "3fc8f3bb8f39840cc5030aca3e3f5c74346d77f2") (:authors ("David Thompson")) (:maintainer "David Thompson") (:keywords "hypermedia") (:url . "https://github.com/dtk01/dtk.el"))]) (dtrace-script-mode . [(20150214 623) nil "DTrace code editing commands for Emacs" single ((:commit . "a92f76c65b9fb64d448e503b4ea7ff06085be8ee"))]) (dtrt-indent . [(20230302 2151) nil "Adapt to foreign indentation offsets" tar ((:commit . "07364ae07301f6f0a1713a8dff520c813849ffb3") (:authors ("Julian Scheid" . "julians37@googlemail.com")) (:maintainer "Reuben Thomas" . "rrt@sc3d.org") (:keywords "convenience" "files" "languages" "c"))]) (dts-mode . [(20211202 18) nil "Major mode for Devicetree source code" single ((:commit . "32517e7eeeccc785b7c669fd5e93c5df45597ef1") (:authors ("Ben Gamari" . "ben@smart-cactus.org")) (:maintainer "Ben Gamari" . "ben@smart-cactus.org") (:keywords "languages"))]) @@ -1081,12 +1082,12 @@ (dumb-diff . [(20171211 2122) ((emacs (24 3))) "fast arbitrary diffs" single ((:commit . "1a2331d283049b71a07c1b06b1e0627a950d55f4") (:authors ("jack angers")) (:maintainer "jack angers") (:keywords "programming" "diff"))]) (dumb-jump . [(20220620 2325) ((emacs (24 3)) (s (1 11 0)) (dash (2 9 0)) (popup (0 5 3))) "Jump to definition for 50+ languages without configuration" single ((:commit . "ba4127336d897f5656032694bbe22c490ecbb000") (:authors ("jack angers and contributors")) (:maintainer "jack angers and contributors") (:keywords "programming") (:url . "https://github.com/jacktasia/dumb-jump"))]) (dummyparens . [(20141009 1024) nil "parenthesis auto-pairing and wrapping" single ((:commit . "9798ef1d0eaa24e4fe66f8aa6022a8c62714cc89") (:authors ("Sergei Nosov ")) (:maintainer "Sergei Nosov ") (:keywords "dummyparens" "auto-pair" "wrapping") (:url . "https://github.com/snosov1/dummyparens"))]) - (dune . [(20230217 1444) nil "Integration with the dune build system" tar ((:commit . "d3d628f2eda2278bd2df6e37452d8693f367fcfd") (:url . "https://github.com/ocaml/dune"))]) + (dune . [(20230402 1815) nil "Integration with the dune build system" tar ((:commit . "e53368337be3c353fd654bdbead322605fc875c5") (:url . "https://github.com/ocaml/dune"))]) (dune-format . [(20210505 108) ((reformatter (0 6)) (emacs (24 1))) "Reformat OCaml's dune files automatically" single ((:commit . "eda7a16ae378e7c482c11228c43ef32b893a1520") (:authors ("Steve Purcell" . "steve@sanityinc.com")) (:maintainer "Steve Purcell" . "steve@sanityinc.com") (:keywords "languages") (:url . "https://github.com/purcell/emacs-dune-format"))]) (duplicate-thing . [(20181031 1500) nil "Duplicate current line & selection" single ((:commit . "9d8fd05e3e5caa35d3f2a0c0032c92f0c0908e21") (:authors ("ongaeshi")) (:maintainer "ongaeshi") (:keywords "convenience" "command" "duplicate" "line" "selection") (:url . "https://github.com/ongaeshi/duplicate-thing"))]) (dut-mode . [(20170729 2111) ((emacs (24))) "Major mode for the Dut programming language" single ((:commit . "9235c7acaa6690942e9de8b7acd1e4be0c859dc1") (:authors ("The dut-mode Authors")) (:maintainer "The dut-mode Authors") (:keywords "languages" "gut") (:url . "https://github.com/dut-lang/dut-mode"))]) (dw . [(20210331 2311) ((emacs (25 1))) "Diceware passphrase generation commands" single ((:commit . "61c5718ba64ace4c9e29de18aa2690ecc3f0f258") (:authors ("D. Williams" . "d.williams@posteo.net")) (:maintainer "D. Williams" . "d.williams@posteo.net") (:keywords "convenience" "games") (:url . "https://github.com/integral-dw/dw-passphrase-generator"))]) - (dwim-shell-command . [(20230209 2234) ((emacs (28 1))) "Shell commands with DWIM behaviour" tar ((:commit . "078fb50b15cd024a9ce252ef69b58794df392be0") (:authors ("Alvaro Ramirez")) (:maintainer "Alvaro Ramirez") (:url . "https://github.com/xenodium/dwim-shell-command"))]) + (dwim-shell-command . [(20230407 1000) ((emacs (28 1))) "Shell commands with DWIM behaviour" tar ((:commit . "a4386911668eaccf726a3024d989863be49b62c4") (:authors ("Alvaro Ramirez")) (:maintainer "Alvaro Ramirez") (:url . "https://github.com/xenodium/dwim-shell-command"))]) (dyalog-mode . [(20230214 1027) ((cl-lib (0 2)) (emacs (24 3))) "Major mode for editing Dyalog APL source code" tar ((:commit . "13c0d391aa878a1609259a89fe3e6db8d21935e8") (:authors ("Joakim Hårsman" . "joakim.harsman@gmail.com")) (:maintainer "Joakim Hårsman" . "joakim.harsman@gmail.com") (:keywords "languages") (:url . "https://github.com/harsman/dyalog-mode.git"))]) (dylan . [(20220115 1804) ((emacs (25 1))) "Dylan editing modes" tar ((:commit . "9d2891e3e06405b75072d296f385fa795aeb9835") (:url . "https://opendylan.org/"))]) (dynamic-fonts . [(20140731 1226) ((font-utils (0 7 0)) (persistent-soft (0 8 8)) (pcache (0 2 3))) "Set faces based on available fonts" single ((:commit . "004ee6014dc7dbff8f14d26015c91d9229f6eac0") (:authors ("Roland Walker" . "walker@pobox.com")) (:maintainer "Roland Walker" . "walker@pobox.com") (:keywords "faces" "frames") (:url . "http://github.com/rolandwalker/dynamic-fonts"))]) @@ -1138,7 +1139,7 @@ (edit-list . [(20100930 1443) nil "edit a single list" single ((:commit . "f460d3f9e208a4e606fe6ded307f1b011916ca71") (:authors ("Michael Olson" . "mwolson@gnu.org")) (:maintainer "Michael Olson" . "mwolson@gnu.org") (:url . "http://mwolson.org/static/dist/elisp/edit-list.el"))]) (edit-server . [(20220908 1014) nil "server that responds to edit requests from Chrome" single ((:commit . "3ce09c6eb2919d56ef052b1584bba6abb12f7e99") (:authors ("Alex Bennée" . "alex@bennee.com")) (:maintainer "Alex Bennée" . "alex@bennee.com") (:url . "https://github.com/stsquad/emacs_chrome"))]) (edit-server-htmlize . [(20130329 2248) ((edit-server (1 9))) "(de)HTMLization hooks for edit-server.el" single ((:commit . "e7f8dadfabe869c77ca241cd6fbd4c52bd908392") (:authors ("Roland McGrath" . "roland@hack.frob.com")) (:maintainer "Roland McGrath" . "roland@hack.frob.com") (:url . "https://github.com/frobtech/edit-server-htmlize"))]) - (editorconfig . [(20230302 831) ((emacs (26 1)) (nadvice (0 3))) "EditorConfig Emacs Plugin" tar ((:commit . "e1a391a618ec33d157822dbcc51d010559289f1a") (:authors ("EditorConfig Team" . "editorconfig@googlegroups.com")) (:maintainer "EditorConfig Team" . "editorconfig@googlegroups.com") (:keywords "convenience" "editorconfig") (:url . "https://github.com/editorconfig/editorconfig-emacs#readme"))]) + (editorconfig . [(20230329 118) ((emacs (26 1)) (nadvice (0 3))) "EditorConfig Emacs Plugin" tar ((:commit . "cd5799a6b728cfb9995605cdceffb5bf7c97622d") (:authors ("EditorConfig Team" . "editorconfig@googlegroups.com")) (:maintainer "EditorConfig Team" . "editorconfig@googlegroups.com") (:keywords "convenience" "editorconfig") (:url . "https://github.com/editorconfig/editorconfig-emacs#readme"))]) (editorconfig-charset-extras . [(20180223 457) ((editorconfig (0 6 0))) "Extra EditorConfig Charset Support" single ((:commit . "ddf60923c6f4841cb593b2ea04c9c710a01d262f") (:authors ("10sr" . "8.slashes@gmail.com")) (:maintainer "10sr" . "8.slashes@gmail.com") (:keywords "tools") (:url . "https://github.com/10sr/editorconfig-charset-extras-el"))]) (editorconfig-custom-majormode . [(20180816 244) ((editorconfig (0 6 0))) "Decide major-mode and mmm-mode from EditorConfig" single ((:commit . "13ad1c83f847bedd4b3a19f9df7fd925853b19de") (:authors ("10sr <8slashes+el [at] gmail [dot] com>")) (:maintainer "10sr <8slashes+el [at] gmail [dot] com>") (:keywords "editorconfig" "util") (:url . "https://github.com/10sr/editorconfig-custom-majormode-el"))]) (editorconfig-domain-specific . [(20180505 924) ((cl-lib (0 5)) (editorconfig (0 6 0))) "Apply brace style and other \"domain-specific\" EditorConfig properties" single ((:commit . "e9824160fb2e466afa755240ee3ab7cc5657fb04") (:authors ("Lassi Kortela" . "lassi@lassi.io")) (:maintainer "Lassi Kortela" . "lassi@lassi.io") (:keywords "editorconfig" "util") (:url . "https://github.com/lassik/editorconfig-emacs-domain-specific"))]) @@ -1154,7 +1155,7 @@ (egg . [(20181126 500) nil "Emacs Got Git - Emacs interface to Git" tar ((:commit . "00e768a78ac3d25f457eed667d02cac568480bf9") (:authors ("Bogolisk" . "bogolisk@gmail.com")) (:maintainer "Bogolisk" . "bogolisk@gmail.com") (:keywords "git" "version control" "release management"))]) (egg-timer . [(20200217 1650) ((emacs (25 1))) "Commonly used intervals for setting timers while working" single ((:commit . "53a9e9d20453ea4b0198ca413b8b5069a0b30b38") (:authors ("William Carroll" . "wpcarro@gmail.com")) (:maintainer "William Carroll" . "wpcarro@gmail.com") (:url . "https://github.com/wpcarro/egg-timer.el"))]) (egison-mode . [(20211218 1115) nil "Egison editing mode" tar ((:commit . "dbb395b41a4e4eb69f3f045cbfbe95a1575ac45b") (:authors ("Satoshi Egi" . "egisatoshi@gmail.com")) (:maintainer "Satoshi Egi" . "egisatoshi@gmail.com") (:url . "https://github.com/egisatoshi/egison3/blob/master/elisp/egison-mode.el"))]) - (eglot-fsharp . [(20230319 1916) ((emacs (27 1)) (eglot (1 4)) (fsharp-mode (1 10)) (jsonrpc (1 0 14))) "fsharp-mode eglot integration" single ((:commit . "cbe4d3c7bec5431113df11f84b93876ea75ff8f1") (:authors ("Jürgen Hötzel" . "juergen@hoetzel.info")) (:maintainer "Jürgen Hötzel" . "juergen@hoetzel.info") (:keywords "languages") (:url . "https://github.com/fsharp/emacs-fsharp-mode"))]) + (eglot-fsharp . [(20230324 1942) ((emacs (27 1)) (eglot (1 4)) (fsharp-mode (1 10)) (jsonrpc (1 0 14))) "fsharp-mode eglot integration" single ((:commit . "0ce19f272949f9ed335ab7a9fd9454c01f07eb8f") (:authors ("Jürgen Hötzel" . "juergen@hoetzel.info")) (:maintainer "Jürgen Hötzel" . "juergen@hoetzel.info") (:keywords "languages") (:url . "https://github.com/fsharp/emacs-fsharp-mode"))]) (eglot-java . [(20230213 218) ((emacs (26 1)) (eglot (1 0)) (jsonrpc (1 0 0))) "Java extension for the eglot LSP client" single ((:commit . "ff0f9515d78f94b8dfe158bf9a2c4f52216504c0") (:authors ("Yves Zoundi" . "yves_zoundi@hotmail.com")) (:maintainer "Yves Zoundi" . "yves_zoundi@hotmail.com") (:keywords "convenience" "languages") (:url . "https://github.com/yveszoundi/eglot-java"))]) (eglot-jl . [(20230117 1243) ((emacs (25 1)) (eglot (1 4)) (project (0 8 1)) (cl-generic (1 0))) "Julia support for eglot" tar ((:commit . "2e04597223553a369dd5b6520b6365b41e6ea508") (:authors ("Adam Beckmeyer" . "adam_git@thebeckmeyers.xyz")) (:maintainer "Adam Beckmeyer" . "adam_git@thebeckmeyers.xyz") (:keywords "convenience" "languages") (:url . "https://github.com/non-Jedi/eglot-jl"))]) (ego . [(20200803 1101) ((emacs (24 5)) (ht (1 5)) (mustache (0 22)) (htmlize (1 47)) (org (8 0)) (dash (2 0 0))) "a static site generator based on org mode, forked from org-page." tar ((:commit . "211c4cb2af2582849d9df984fb2346deecaf79be") (:authors ("Feng Shu ") ("Kelvin Hu ") ("Kuangdash ")) (:maintainer "Feng Shu ") (:keywords "org-mode" "convenience" "beautify") (:url . "https://github.com/emacs-china/EGO"))]) @@ -1188,17 +1189,17 @@ (elcontext . [(20210109 1238) ((ht (2 3)) (hydra (0 14 0)) (emacs (24 3)) (f (0 20 0)) (osx-location (0 4)) (uuidgen (0 3))) "Create context specific actions" tar ((:commit . "2efd3dd8c5176c4f071bb048be6cb069b05d6e9e") (:authors ("Thomas Sojka")) (:maintainer "Thomas Sojka") (:keywords "calendar" "convenience") (:url . "https://github.com/rollacaster/elcontext"))]) (elcord . [(20230303 457) ((emacs (25 1))) "Allows you to integrate Rich Presence from Discord" tar ((:commit . "e97283f8cdc3ca16a0179a14c78f1ba6e93cef80") (:authors ("heatingdevice") ("Wilfredo Velázquez-Rodríguez" . "zulu.inuoe@gmail.com")) (:maintainer "heatingdevice") (:keywords "games") (:url . "https://github.com/Mstrodl/elcord"))]) (elcouch . [(20201108 955) ((emacs (25 1)) (json-mode (1 0 0)) (libelcouch (0 11 0)) (navigel (0 3 0))) "View and manipulate CouchDB databases" single ((:commit . "3d162dda14411349e12509029d2b621c5d1edea2") (:authors ("Damien Cassou" . "damien@cassou.me")) (:maintainer "Damien Cassou" . "damien@cassou.me") (:keywords "data" "tools") (:url . "https://gitlab.petton.fr/DamienCassou/elcouch"))]) - (eldev . [(20230121 1404) ((emacs (24 4))) "Elisp development tool" tar ((:commit . "a1ea1a3df7602ffab30c15348365d2e6a75063b7") (:authors ("Paul Pogonyshev" . "pogonyshev@gmail.com")) (:maintainer "Paul Pogonyshev" . "pogonyshev@gmail.com") (:keywords "maint" "tools") (:url . "https://github.com/doublep/eldev"))]) - (eldoc-box . [(20230310 2245) ((emacs (27 1))) "Display documentation in childframe" single ((:commit . "c805bfcd61a060891ccb04f85798225b1bf14418") (:authors ("Yuan Fu" . "casouri@gmail.com")) (:maintainer "Yuan Fu" . "casouri@gmail.com") (:url . "https://github.com/casouri/eldoc-box"))]) + (eldev . [(20230326 1127) ((emacs (24 4))) "Elisp development tool" tar ((:commit . "3162ae8015ec37ae8560bedc7e0b28f0695dd4d3") (:authors ("Paul Pogonyshev" . "pogonyshev@gmail.com")) (:maintainer "Paul Pogonyshev" . "pogonyshev@gmail.com") (:keywords "maint" "tools") (:url . "https://github.com/doublep/eldev"))]) + (eldoc-box . [(20230404 2324) ((emacs (27 1))) "Display documentation in childframe" single ((:commit . "143d7c5eff5ded45d1e1b9462c93f2a4e603089e") (:authors ("Yuan Fu" . "casouri@gmail.com")) (:maintainer "Yuan Fu" . "casouri@gmail.com") (:url . "https://github.com/casouri/eldoc-box"))]) (eldoc-cmake . [(20190419 2244) ((emacs (25 1))) "Eldoc support for CMake" single ((:commit . "4453c03b5c95ff32842f13db2fc317fb0fe2f79e") (:authors ("Kirill Ignatiev")) (:maintainer "Kirill Ignatiev") (:url . "https://github.com/ikirill/eldoc-cmake"))]) (eldoc-eval . [(20220106 1951) nil "Enable eldoc support when minibuffer is in use." single ((:commit . "e91800503c90cb75dc70abe42f1d6ae499346cc1") (:authors ("Thierry Volpiatto" . "thievol@posteo.net")) (:maintainer "Thierry Volpiatto" . "thievol@posteo.net"))]) - (eldoc-overlay . [(20221007 212) ((emacs (24 4)) (inline-docs (1 0 1)) (quick-peek (1 0))) "Display eldoc with contextual documentation overlay" single ((:commit . "5ae9e062295ea2a2855569826b770f3469f73e2f") (:authors ("stardiviner" . "numbchild@gmail.com")) (:maintainer "stardiviner" . "numbchild@gmail.com") (:keywords "docs" "eldoc" "overlay") (:url . "https://repo.or.cz/eldoc-overlay.git"))]) + (eldoc-overlay . [(20230406 959) ((emacs (24 4)) (inline-docs (1 0 1)) (quick-peek (1 0))) "Display eldoc with contextual documentation overlay" single ((:commit . "14a9e141918c2e18a107920e8631e622c580b3ef") (:authors ("stardiviner" . "numbchild@gmail.com")) (:maintainer "stardiviner" . "numbchild@gmail.com") (:keywords "docs" "eldoc" "overlay") (:url . "https://repo.or.cz/eldoc-overlay.git"))]) (eldoc-stan . [(20211129 2051) ((emacs (25)) (stan-mode (10 3 0))) "Eldoc support for stan functions" tar ((:commit . "150bbbe5fd3ad2b5a3dbfba9d291e66eeea1a581") (:authors ("Kazuki Yoshida" . "kazukiyoshida@mail.harvard.edu")) (:maintainer "Kazuki Yoshida" . "kazukiyoshida@mail.harvard.edu") (:keywords "help" "tools") (:url . "https://github.com/stan-dev/stan-mode/tree/master/eldoc-stan"))]) (eldoc-toml . [(20211026 1122) ((emacs (24 4))) "TOML table name at point for ElDoc" single ((:commit . "61106be3c3f3a5b293c3f285eec8c6f400142b6d") (:authors ("Maor Kadosh" . "git@avocadosh.xyz")) (:maintainer "Maor Kadosh" . "git@avocadosh.xyz") (:keywords "data") (:url . "https://github.com/it-is-wednesday/eldoc-toml"))]) (electric-case . [(20150417 1112) nil "insert camelCase, snake_case words without \"Shift\"ing" single ((:commit . "984b6a4c6c4cdcefeecb59e941f5f184cc1dedff") (:authors ("zk_phi")) (:maintainer "zk_phi") (:url . "http://hins11.yu-yake.com/"))]) (electric-cursor . [(20221221 438) ((emacs (25 1))) "Change cursor automatically depending on mode" single ((:commit . "bc09aa8c5d3cc32e3e6452cbf8018fc1ea772b73") (:authors ("Case Duckworth" . "acdw@acdw.net")) (:maintainer "Case Duckworth" . "acdw@acdw.net") (:keywords "terminals" "frames") (:url . "https://github.com/duckwork/electric-cursor"))]) (electric-operator . [(20220814 1439) ((dash (2 10 0)) (emacs (24 4))) "Automatically add spaces around operators" tar ((:commit . "281abdae033559fa9a8878ed1dd05a7ade118cfd") (:authors ("David Shepherd" . "davidshepherd7@gmail.com")) (:maintainer "David Shepherd" . "davidshepherd7@gmail.com") (:keywords "electric") (:url . "https://github.com/davidshepherd7/electric-operator"))]) - (electric-ospl . [(20230320 2127) ((emacs (26 1))) "Electric OSPL Mode" single ((:commit . "61de9d25bea9eda67c693d8c2e098904075c3fd6") (:authors ("Samuel W. Flint" . "swflint@flintfam.org")) (:maintainer "Samuel W. Flint" . "swflint@flintfam.org") (:keywords "convenience" "text") (:url . "https://git.sr.ht/~swflint/electric-ospl-mode"))]) + (electric-ospl . [(20230325 1518) ((emacs (26 1))) "Electric OSPL Mode" single ((:commit . "55fa59592d0d3e929bd8646ea691a592965a167a") (:authors ("Samuel W. Flint" . "swflint@flintfam.org")) (:maintainer "Samuel W. Flint" . "swflint@flintfam.org") (:keywords "convenience" "text") (:url . "https://git.sr.ht/~swflint/electric-ospl-mode"))]) (electric-spacing . [(20220220 1540) nil "Insert operators with surrounding spaces smartly" tar ((:commit . "c37b2502512dd49a8311d7c34e9bfd1af3d4dbcd") (:authors ("William Xu" . "william.xwl@gmail.com")) (:maintainer "William Xu" . "william.xwl@gmail.com"))]) (elegant-agenda-mode . [(20210115 353) ((emacs (26 1))) "An elegant theme for your org-agenda" single ((:commit . "5cbc688584ba103ea3be7d7b30e5d94e52f59eb6") (:authors ("Justin Barclay" . "justinbarclay@gmail.com")) (:maintainer "Justin Barclay" . "justinbarclay@gmail.com") (:keywords "faces") (:url . "https://github.com/justinbarclay/elegant-agenda-mode"))]) (elein . [(20120120 1116) nil "running leiningen commands from emacs" single ((:commit . "d4c0c0491dbb7c90e953d7a16172107c37103605") (:authors ("R.W. van 't Veer")) (:maintainer "R.W. van 't Veer") (:keywords "tools" "processes") (:url . "https://github.com/remvee/elein"))]) @@ -1230,7 +1231,7 @@ (elisp-sandbox . [(20131116 1842) nil "Evaluate EmacsLisp expressions in a sandbox" single ((:commit . "ddd669266ca36d7e4ebba73eb1ab42523787e042") (:authors ("Joel McCracken , D. Goel" . "deego@gnufans.org")) (:maintainer "Joel McCracken , D. Goel" . "deego@gnufans.org") (:keywords "lisp") (:url . "https://github.com/joelmccracken/elisp-sandbox"))]) (elisp-slime-nav . [(20210510 528) ((emacs (24 1)) (cl-lib (0 2))) "Make M-. and M-, work in elisp like they do in slime" single ((:commit . "8588d80d414aee1fafce5b9da0e913612ee0bcdd") (:authors ("Steve Purcell" . "steve@sanityinc.com")) (:maintainer "Steve Purcell" . "steve@sanityinc.com") (:keywords "languages" "navigation" "slime" "elisp" "emacs-lisp") (:url . "https://github.com/purcell/elisp-slime-nav"))]) (elixir-mode . [(20221017 2044) ((emacs (25))) "Major mode for editing Elixir files" tar ((:commit . "4974ff9a83daf50f2f03dc0d6d00871296e088b0") (:keywords "languages" "elixir") (:url . "https://github.com/elixir-editors/emacs-elixir"))]) - (elixir-ts-mode . [(20230321 1458) ((emacs (29)) (heex-ts-mode (1 2))) "Major mode for Elixir with tree-sitter support" single ((:commit . "0d4ef4794655a2a3c5324e07eef46dc4766ad65d") (:authors ("Wilhelm H Kirschbaum")) (:maintainer "Wilhelm H Kirschbaum") (:keywords "elixir" "languages" "tree-sitter") (:url . "https://github.com/wkirschbaum/elixir-ts-mode"))]) + (elixir-ts-mode . [(20230403 823) ((emacs (29)) (heex-ts-mode (1 2))) "Major mode for Elixir with tree-sitter support" single ((:commit . "6671c0ffe0e59d82b99948b08d200bd744cc9d26") (:authors ("Wilhelm H Kirschbaum")) (:maintainer "Wilhelm H Kirschbaum") (:keywords "elixir" "languages" "tree-sitter") (:url . "https://github.com/wkirschbaum/elixir-ts-mode"))]) (elixir-yasnippets . [(20150417 1239) ((yasnippet (0 8 0))) "Yasnippets for Elixir" tar ((:commit . "980ca7626c14ef0573bec0035ec7942796062783") (:authors ("Yinghai Zhao" . "zyinghai@gmail.com")) (:maintainer "Yinghai Zhao" . "zyinghai@gmail.com") (:keywords "snippets"))]) (ellocate . [(20200112 1931) ((emacs (25 1)) (s (1 12 0)) (f (0 20 0))) "The locate command reimplemented in Emacs Lisp" single ((:commit . "81405082f68f0577c9f176d3d4f034a7142aba59") (:authors ("Sebastian Wålinder" . "s.walinder@gmail.com")) (:maintainer "Sebastian Wålinder" . "s.walinder@gmail.com") (:keywords "matching") (:url . "https://github.com/walseb/ellocate"))]) (elm-mode . [(20230315 1122) ((f (0 17)) (s (1 7 0)) (emacs (25 1)) (seq (2 23)) (reformatter (0 3))) "Major mode for Elm" tar ((:commit . "699841865e1bd5b7f2077baa7121510b6bcad3c7") (:authors ("Joseph Collard")) (:maintainer "Joseph Collard") (:url . "https://github.com/jcollard/elm-mode"))]) @@ -1247,9 +1248,9 @@ (elpa-clone . [(20221201 1227) ((emacs (24 4))) "Clone ELPA archive" single ((:commit . "1d130c251690f24c23b77a4e4570157fca881d8f") (:authors ("ZHANG Weiyi" . "dochang@gmail.com")) (:maintainer "ZHANG Weiyi" . "dochang@gmail.com") (:keywords "comm" "elpa" "clone" "mirror") (:url . "https://github.com/dochang/elpa-clone"))]) (elpa-deploy . [(20191022 718) ((emacs (24 4)) (f (0 0))) "ELPA deployment library" single ((:commit . "f5126a2da1e0e52981fad9c12028814be80328c2") (:authors ("Bruno Félix Rezende Ribeiro" . "oitofelix@gnu.org")) (:maintainer "Bruno Félix Rezende Ribeiro" . "oitofelix@gnu.org") (:keywords "tools") (:url . "https://github.com/oitofelix/elpa-deploy"))]) (elpa-mirror . [(20230208 1148) ((emacs (25 1))) "Create local package repository from installed packages" single ((:commit . "9d7cfbf72ef8c7cd014c91e5bb3d8fbebda56140") (:authors ("Chen Bin" . "chenbin.sh@gmail.com")) (:maintainer "Chen Bin" . "chenbin.sh@gmail.com") (:keywords "tools") (:url . "http://github.com/redguardtoo/elpa-mirror"))]) - (elpher . [(20220809 253) ((emacs (27 1))) "A friendly gopher and gemini client" tar ((:commit . "b5269970249871a8889950a3e47bdff51eb0420c") (:authors ("Tim Vaughan" . "plugd@thelambdalab.xyz")) (:maintainer "Tim Vaughan" . "plugd@thelambdalab.xyz") (:keywords "comm" "gopher") (:url . "https://thelambdalab.xyz/elpher"))]) + (elpher . [(20230331 749) ((emacs (27 1))) "A friendly gopher and gemini client" tar ((:commit . "593310c145f1836781b16abed4503969e642212e") (:authors ("Tim Vaughan" . "plugd@thelambdalab.xyz")) (:maintainer "Tim Vaughan" . "plugd@thelambdalab.xyz") (:keywords "comm" "gopher") (:url . "https://thelambdalab.xyz/elpher"))]) (elpl . [(20220328 316) ((emacs (24 4))) "Emacs Lisp REPL" single ((:commit . "501871ab543b9967bfe87a8a82f83ab96b7f909e") (:authors ("Gong Qijian" . "gongqijian@gmail.com")) (:maintainer "Gong Qijian" . "gongqijian@gmail.com") (:keywords "lisp" "tool") (:url . "https://github.com/twlz0ne/elpl"))]) - (elpy . [(20220922 2253) ((company (0 9 2)) (emacs (24 4)) (highlight-indentation (0 5 0)) (pyvenv (1 3)) (yasnippet (0 8 0)) (s (1 11 0))) "Emacs Python Development Environment" tar ((:commit . "ae7919d94659eb26d4146d4c3422c5f4c3610837") (:authors ("Jorgen Schaefer , Gaby Launay" . "gaby.launay@protonmail.com")) (:maintainer "Jorgen Schaefer , Gaby Launay" . "gaby.launay@protonmail.com") (:keywords "python" "ide" "languages" "tools") (:url . "https://github.com/jorgenschaefer/elpy"))]) + (elpy . [(20230402 1946) ((company (0 9 2)) (emacs (24 4)) (highlight-indentation (0 5 0)) (pyvenv (1 3)) (yasnippet (0 8 0)) (s (1 11 0))) "Emacs Python Development Environment" tar ((:commit . "840713f23af99b83d04034c3703f7e73c3baa7dc") (:authors ("Jorgen Schaefer , Gaby Launay" . "gaby.launay@protonmail.com")) (:maintainer "Jorgen Schaefer , Gaby Launay" . "gaby.launay@protonmail.com") (:keywords "python" "ide" "languages" "tools") (:url . "https://github.com/jorgenschaefer/elpy"))]) (elpygen . [(20171225 1736) ((emacs (25)) (yasnippet (0 8 0))) "Generate a Python function/method using a symbol under point" single ((:commit . "21929c997a05968f9eefe52b85a76ceaab3b0d81") (:authors ("Vladimir Kazanov" . "vkazanov@inbox.ru")) (:maintainer "Vladimir Kazanov" . "vkazanov@inbox.ru") (:keywords "python" "languages" "tools") (:url . "https://github.com/vkazanov/elpygen"))]) (elquery . [(20220331 143) ((emacs (25 1)) (dash (2 13 0))) "The HTML library for elisp" tar ((:commit . "38f3bd41096cb270919b06095da0b9ac1add4598") (:authors ("Adam Niederer")) (:maintainer "Adam Niederer") (:keywords "html" "hypermedia" "tools" "webscale") (:url . "https://github.com/AdamNiederer/elquery"))]) (elsa . [(20230318 2024) ((emacs (25 1)) (trinary (0)) (f (0)) (dash (2 14)) (cl-lib (0 3)) (lsp-mode (0))) "Emacs Lisp Static Analyser" tar ((:commit . "2aa912dcc7d3732ba04eb96ab1cd186565a48f98") (:authors ("Matúš Goljer" . "matus.goljer@gmail.com")) (:maintainer "Matúš Goljer" . "matus.goljer@gmail.com") (:keywords "languages" "lisp") (:url . "https://github.com/emacs-elsa/Elsa"))]) @@ -1264,7 +1265,7 @@ (elwm . [(20150817 1007) ((dash (1 1 0))) "Minimalistic window manager for emacs" single ((:commit . "c33b183f006ad476c3a44dab316f580f8b369930") (:authors ("Matus Goljer" . "matus.goljer@gmail.com")) (:maintainer "Matus Goljer" . "matus.goljer@gmail.com") (:keywords "docs") (:url . "https://github.com/Fuco1/elwm"))]) (elx . [(20230212 2019) ((emacs (25 1)) (compat (29 1 3 4)) (llama (0 2 0))) "Extract information from Emacs Lisp libraries" single ((:commit . "9daf56b1b11ca267f263f70823ade6f1a92d307c") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "docs" "libraries" "packages") (:url . "https://github.com/emacscollective/elx"))]) (emacs-everywhere . [(20220831 1636) ((emacs (26 3))) "System-wide popup windows for quick edits" single ((:commit . "e1b701894196b0e0aaf18ab88c778877ec87d0c9") (:authors ("TEC ")) (:maintainer "TEC" . "contact@tecosaur.net") (:keywords "conenience" "frames") (:url . "https://github.com/tecosaur/emacs-everywhere"))]) - (emacsc . [(20221105 1715) nil "helper for emacsc(1)" tar ((:commit . "f7634a86c3643a6432dda3897bd524957cf9ff1f") (:authors ("Akinori MUSHA" . "knu@iDaemons.org")) (:maintainer "Akinori MUSHA" . "knu@iDaemons.org") (:keywords "tools") (:url . "https://github.com/knu/emacsc"))]) + (emacsc . [(20230326 1852) nil "helper for emacsc(1)" tar ((:commit . "b4afd616c4ef160c58fc9a9682d3431b30a9d434") (:authors ("Akinori MUSHA" . "knu@iDaemons.org")) (:maintainer "Akinori MUSHA" . "knu@iDaemons.org") (:keywords "tools") (:url . "https://github.com/knu/emacsc"))]) (emacsist-view . [(20160426 1223) nil "Mode for viewing emacsist.com" single ((:commit . "f67761259ed779a9bc95c9a4e0474522990c5c6b") (:authors ("DarkSun" . "lujun9972@gmail.com")) (:maintainer "DarkSun" . "lujun9972@gmail.com") (:keywords "convenience" "usability") (:url . "https://github.com/lujun9972/emacsist-view"))]) (emacsql . [(20230228 1040) ((emacs (25 1))) "High-level SQL database front-end" tar ((:commit . "415dbfd846f46d921a70a351695f0d0e8f75da35") (:authors ("Christopher Wellons" . "wellons@nullprogram.com")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:url . "https://github.com/magit/emacsql"))]) (emacsql-mysql . [(20230225 2205) ((emacs (25 1)) (emacsql (20230220))) "EmacSQL back-end for MySQL" single ((:commit . "b436adf09ebe058c28e0f473bed90ccd7084f6aa") (:authors ("Christopher Wellons" . "wellons@nullprogram.com")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:url . "https://github.com/magit/emacsql"))]) @@ -1277,15 +1278,15 @@ (emamux . [(20200315 1220) ((emacs (24 3))) "Interact with tmux" single ((:commit . "6172131d78038f0b1490e24bac60534bf4ad3b30") (:authors ("Syohei YOSHIDA" . "syohex@gmail.com")) (:maintainer "Syohei YOSHIDA" . "syohex@gmail.com") (:url . "https://github.com/syohex/emacs-emamux"))]) (emamux-ruby-test . [(20130812 1639) ((emamux (0 1)) (projectile (0 9 1))) "Ruby test with emamux" single ((:commit . "785bfd44d097a46bb2ebe1e62ac7595fd4dc9ab5") (:url . "https://github.com/syohex/emamux-ruby-test"))]) (emaps . [(20200508 1759) ((dash (2 17 0)) (emacs (24))) "Utilities for working with keymaps" single ((:commit . "7c561f3ded2015ed3774e5784059d6601082743e") (:authors ("Ben Moon" . "software@guiltydolphin.com")) (:maintainer "Ben Moon" . "software@guiltydolphin.com") (:keywords "convenience" "keyboard" "keymap" "utility") (:url . "https://github.com/GuiltyDolphin/emaps"))]) - (embark . [(20230321 1407) ((emacs (27 1)) (compat (29 1 4 0))) "Conveniently act on minibuffer completions" tar ((:commit . "3ffb27a833d326ccf7e375bb9d94ebf4dc37fa77") (:authors ("Omar Antolín Camarena" . "omar@matem.unam.mx")) (:maintainer "Omar Antolín Camarena" . "omar@matem.unam.mx") (:keywords "convenience") (:url . "https://github.com/oantolin/embark"))]) - (embark-consult . [(20230320 1442) ((emacs (27 1)) (embark (0 20)) (consult (0 17))) "Consult integration for Embark" single ((:commit . "16c3d337f0ef67d680ed4d929e75e823a05332f3") (:authors ("Omar Antolín Camarena" . "omar@matem.unam.mx")) (:maintainer "Omar Antolín Camarena" . "omar@matem.unam.mx") (:keywords "convenience") (:url . "https://github.com/oantolin/embark"))]) + (embark . [(20230328 1813) ((emacs (27 1)) (compat (29 1 4 0))) "Conveniently act on minibuffer completions" tar ((:commit . "846b3fd311d06dd0f9aa20f133907ae10855c9ae") (:authors ("Omar Antolín Camarena" . "omar@matem.unam.mx")) (:maintainer "Omar Antolín Camarena" . "omar@matem.unam.mx") (:keywords "convenience") (:url . "https://github.com/oantolin/embark"))]) + (embark-consult . [(20230327 1843) ((emacs (27 1)) (embark (0 20)) (consult (0 17))) "Consult integration for Embark" single ((:commit . "51b5a693b5fe3d573acac97cfd3ce75e0d41c187") (:authors ("Omar Antolín Camarena" . "omar@matem.unam.mx")) (:maintainer "Omar Antolín Camarena" . "omar@matem.unam.mx") (:keywords "convenience") (:url . "https://github.com/oantolin/embark"))]) (embark-vc . [(20230212 1920) ((emacs (27 1)) (embark (0 21 1)) (forge (0 3)) (compat (29 1 3 0))) "Embark actions for various version control integrations" single ((:commit . "070666b0de8fc2832aa2510b9ba492565cb5e35e") (:authors ("Ellis Kenyő ")) (:maintainer "Ellis Kenyő" . "me@elken.dev") (:keywords "convenience" "matching" "terminals" "tools" "unix" "vc") (:url . "https://github.com/elken/embark-vc"))]) (ember-mode . [(20200208 1423) ((cl-lib (0 5))) "Ember navigation mode for emacs" single ((:commit . "a587c423041b2fcb065fd5b6a03b2899b764e462") (:authors ("Aad Versteden" . "madnificent@gmail.com")) (:maintainer "Aad Versteden" . "madnificent@gmail.com") (:keywords "ember" "ember.js" "emberjs"))]) (ember-yasnippets . [(20160526 1658) ((yasnippet (0 8 0))) "Snippets for Ember.js development" tar ((:commit . "3b5bd01569646237bf1b540d097e12f9118b67f4") (:authors ("Ron White" . "ronco@costite.com")) (:maintainer "Ron White" . "ronco@costite.com") (:keywords "tools" "abbrev" "languages"))]) (embrace . [(20171031 1833) ((cl-lib (0 5)) (expand-region (0 10 0))) "Add/Change/Delete pairs based on `expand-region'" single ((:commit . "dd5da196e5bcc5e6d87e1937eca0c21da4334ef2") (:authors ("Junpeng Qiu" . "qjpchmail@gmail.com")) (:maintainer "Junpeng Qiu" . "qjpchmail@gmail.com") (:keywords "extensions"))]) (emidje . [(20190209 1726) ((emacs (25)) (cider (0 17 0)) (seq (2 16)) (magit-popup (2 4 0))) "Test runner and report viewer for Midje" single ((:commit . "7e92f053964d925c97dc8cca8d4d70a3030021db") (:authors ("Alan Ghelardi" . "alan.ghelardi@nubank.com.br")) (:maintainer "Alan Ghelardi" . "alan.ghelardi@nubank.com.br") (:keywords "tools") (:url . "https://github.com/nubank/emidje"))]) (emmet-mode . [(20221111 329) nil "Unofficial Emmet's support for emacs" single ((:commit . "63b6932603184956b5ea8919036d2b307b48d7fd") (:authors ("Shin Aoyama" . "smihica@gmail.com")) (:maintainer "Shin Aoyama" . "smihica@gmail.com") (:keywords "convenience") (:url . "https://github.com/smihica/emmet-mode"))]) - (emms . [(20230306 1833) ((cl-lib (0 5)) (nadvice (0 3)) (seq (0))) "The Emacs Multimedia System" tar ((:commit . "c8b64ecc934a0832c91ca59813aceaf868540707") (:authors ("Jorgen Schäfer" . "forcer@forcix.cx")) (:maintainer "Yoni Rabkin" . "yrk@gnu.org") (:keywords "emms" "mp3" "ogg" "flac" "music" "mpeg" "video" "multimedia") (:url . "https://www.gnu.org/software/emms/"))]) + (emms . [(20230329 2020) ((cl-lib (0 5)) (nadvice (0 3)) (seq (0))) "The Emacs Multimedia System" tar ((:commit . "0f4bd0c551b6ec1debfa834464f28030ce9c287b") (:authors ("Jorgen Schäfer" . "forcer@forcix.cx")) (:maintainer "Yoni Rabkin" . "yrk@gnu.org") (:keywords "emms" "mp3" "ogg" "flac" "music" "mpeg" "video" "multimedia") (:url . "https://www.gnu.org/software/emms/"))]) (emms-bilibili . [(20180103 418) ((emacs (25)) (cl-lib (0 5))) "Play Bilibili in EMMS." single ((:commit . "294bca3dfc42fe3a55fb326ab39bc0fcfc8c5090") (:keywords "emms" "bilibili") (:url . "https://github.com/stardiviner/emms-bilibili"))]) (emms-info-mediainfo . [(20131223 1300) ((emms (0))) "Info-method for EMMS using medianfo" single ((:commit . "bce16eae9eacd38719fea62a9755225a888da59d") (:authors ("Fabián Ezequiel Gallina" . "fgallina@gnu.org")) (:maintainer "Fabián Ezequiel Gallina" . "fgallina@gnu.org") (:keywords "multimedia" "processes"))]) (emms-mark-ext . [(20130529 327) ((emms (3 0))) "Extra functions for emms-mark-mode and emms-tag-edit-mode" single ((:commit . "ec68129e3e9e469e5bf160c6a1b7030e322f3541") (:authors ("Joe Bloggs" . "vapniks@yahoo.com")) (:maintainer "Joe Bloggs" . "vapniks@yahoo.com") (:keywords "convenience" "multimedia") (:url . "https://github.com/vapniks/emms-mark-ext"))]) @@ -1302,7 +1303,7 @@ (emojify . [(20210108 1111) ((seq (1 11)) (ht (2 0)) (emacs (24 3))) "Display emojis in Emacs" tar ((:commit . "cfa00865388809363df3f884b4dd554a5d44f835") (:authors ("Iqbal Ansari" . "iqbalansari02@yahoo.com")) (:maintainer "Iqbal Ansari" . "iqbalansari02@yahoo.com") (:keywords "multimedia" "convenience") (:url . "https://github.com/iqbalansari/emacs-emojify"))]) (emojify-logos . [(20180814 917) ((emojify (0 4))) "Add logos to emojify" tar ((:commit . "a3e78bcbdf863092d4c9b026ac08bf7d1c7c0e8b") (:authors ("mxgoldstein" . "m_goldstein@gmx.net")) (:maintainer "mxgoldstein" . "m_goldstein@gmx.net") (:url . "https://github.com/mxgoldstein/emojify-logos"))]) (empos . [(20151011 1916) nil "Locate bibtex citations from within emacs" single ((:commit . "7b99ad30e56937adb7e6349777e5a2045597d564") (:authors ("Dimitris Alikaniotis ")) (:maintainer "Dimitris Alikaniotis ") (:keywords "citations" "reference" "bibtex" "reftex") (:url . "http://github.com/dimalik/empos/"))]) - (empv . [(20230314 1759) ((emacs (28 1))) "A multimedia player/manager, YouTube interface" single ((:commit . "5e9054b58d2896e005a953e0213bf7eb0d10b7f1") (:authors ("Isa Mert Gurbuz" . "isamertgurbuz@gmail.com")) (:maintainer "Isa Mert Gurbuz" . "isamertgurbuz@gmail.com") (:url . "https://github.com/isamert/empv.el"))]) + (empv . [(20230402 1852) ((emacs (28 1)) (s (1 13 0))) "A multimedia player/manager, YouTube interface" single ((:commit . "643bb7d1f42c627ae28b86d9554198e5b68665b1") (:authors ("Isa Mert Gurbuz" . "isamertgurbuz@gmail.com")) (:maintainer "Isa Mert Gurbuz" . "isamertgurbuz@gmail.com") (:url . "https://github.com/isamert/empv.el"))]) (emr . [(20220108 548) ((s (1 3 1)) (dash (1 2 0)) (cl-lib (0 2)) (popup (0 5 0)) (emacs (24 1)) (list-utils (0 3 0)) (paredit (24 0 0)) (projectile (0 9 1)) (clang-format (0 0 1)) (iedit (0 97))) "Emacs refactoring system." tar ((:commit . "cac1b52932926f56d7f6d2923732d20bbd20670d") (:authors ("Chris Barrett" . "chris.d.barrett@me.com")) (:maintainer "Chris Barrett" . "chris.d.barrett@me.com") (:keywords "tools" "convenience" "refactoring") (:url . "https://github.com/Wilfred/emacs-refactor"))]) (enclose . [(20121008 1614) nil "Enclose cursor within punctuation pairs." tar ((:commit . "2fff3d4fcc1089f87647042d7164ba04282766ae") (:authors ("Johan Andersson" . "johan.rejeep@gmail.com")) (:maintainer "Johan Andersson" . "johan.rejeep@gmail.com") (:keywords "speed" "convenience") (:url . "http://github.com/rejeep/enclose"))]) (encourage-mode . [(20151128 905) ((emacs (24 4))) "Encourages you in your work. :D" single ((:commit . "ca411e6bfd3d0edffe95852127bd995730b942e3") (:authors ("Patrick Mosby" . "patrick@schreiblogade.de")) (:maintainer "Patrick Mosby" . "patrick@schreiblogade.de") (:keywords "fun") (:url . "https://github.com/halbtuerke/encourage-mode.el"))]) @@ -1350,7 +1351,7 @@ (ergoemacs-status . [(20160318 538) ((powerline (2 3)) (mode-icons (0 1 0))) "Adaptive Status Bar / Mode Line" single ((:commit . "d952cc2361adf6eb4d6af60950ad4ab699c81320") (:authors ("Matthew Fidler")) (:maintainer "Matthew Fidler"))]) (eri . [(20200914 644) nil "Enhanced relative indentation (eri)" single ((:commit . "aa5e3a127bf17a8c80d947f3c286758a36dadc36") (:url . "https://github.com/agda/agda"))]) (erk . [(20230120 622) ((emacs (28 1)) (auto-compile (1 2 0)) (dash (2 18 0))) "Elisp (GitHub) Repository Kit" single ((:commit . "6ca1aabc6c60c8722bc5dca4aedbc033b1d9fff5") (:authors ("")) (:maintainer "") (:keywords "convenience") (:url . "http://github.com/positron-solutions/elisp-repo-kit"))]) - (erlang . [(20230215 909) ((emacs (24 1))) "Erlang major mode" tar ((:commit . "127026003180a834e9fa5d5919c824a184faeb92") (:authors ("Anders Lindgren")) (:maintainer "Anders Lindgren") (:keywords "erlang" "languages" "processes"))]) + (erlang . [(20230322 848) ((emacs (24 1))) "Erlang major mode" tar ((:commit . "dac89a6acc1a93a615930ca18f1dbf4e9323b038") (:authors ("Anders Lindgren")) (:maintainer "Anders Lindgren") (:keywords "erlang" "languages" "processes"))]) (erlstack-mode . [(20230202 1955) ((emacs (25 1)) (dash (2 12 0))) "Minor mode for analysing Erlang stacktraces" single ((:commit . "b0fa450da826b7b9fcfe9b0b209955735830eb38") (:authors ("k32")) (:maintainer "k32") (:keywords "tools" "erlang") (:url . "https://github.com/k32/erlstack-mode"))]) (eros . [(20230309 615) ((emacs (24 4))) "Evaluation Result OverlayS for Emacs Lisp" single ((:commit . "a9a92bdc6be0521a6a06eb464be55ed61946639c") (:authors ("Tianxiang Xiong" . "tianxiang.xiong@gmail.com")) (:maintainer "Tianxiang Xiong" . "tianxiang.xiong@gmail.com") (:keywords "convenience" "lisp") (:url . "https://github.com/xiongtx/eros"))]) (ert-async . [(20200105 1031) ((emacs (24 1))) "Async support for ERT" single ((:commit . "948cf2faa10e085bda3739034ca5ea1912893433") (:authors ("Johan Andersson" . "johan.rejeep@gmail.com")) (:maintainer "Johan Andersson" . "johan.rejeep@gmail.com") (:keywords "lisp" "test") (:url . "http://github.com/rejeep/ert-async.el"))]) @@ -1374,7 +1375,7 @@ (eshell-info-banner . [(20220728 1006) ((emacs (25 1)) (s (1))) "System information as your Eshell banner" single ((:commit . "987e69a66276ca057798896c606e5c5d5fb9ee5c") (:authors ("Lucien Cartier-Tilet" . "lucien@phundrak.com")) (:maintainer "Lucien Cartier-Tilet" . "lucien@phundrak.com") (:url . "https://github.com/Phundrak/eshell-info-banner.el"))]) (eshell-outline . [(20201121 620) ((emacs (25 1))) "Enhanced outline-mode for Eshell" single ((:commit . "6f917afa5b3d36764d76d7864589094647d8c3b4") (:authors ("Jamie Beardslee" . "jdb@jamzattack.xyz")) (:maintainer "Jamie Beardslee" . "jdb@jamzattack.xyz") (:keywords "unix" "eshell" "outline" "convenience") (:url . "https://git.jamzattack.xyz/eshell-outline"))]) (eshell-prompt-extras . [(20210925 110) ((emacs (25))) "Display extra information for your eshell prompt." single ((:commit . "c2078093323206b91a1b1f5786d79faa00b76be7") (:authors ("zwild" . "judezhao@outlook.com")) (:maintainer "Chunyang Xu" . "mail@xuchunyang.me") (:keywords "eshell" "prompt") (:url . "https://github.com/zwild/eshell-prompt-extras"))]) - (eshell-syntax-highlighting . [(20220816 2017) ((emacs (25 1))) "Highlight eshell commands" single ((:commit . "1ba39a9ffb2298cd716a4314cf3f369028c7bafe") (:authors ("Alex Kreisher" . "akreisher18@gmail.com")) (:maintainer "Alex Kreisher" . "akreisher18@gmail.com") (:keywords "convenience") (:url . "https://github.com/akreisher/eshell-syntax-highlighting"))]) + (eshell-syntax-highlighting . [(20230402 2034) ((emacs (25 1))) "Highlight eshell commands" single ((:commit . "0ac5259d497a9794e147d2b9dc23edf5bc844e3c") (:authors ("Alex Kreisher" . "akreisher18@gmail.com")) (:maintainer "Alex Kreisher" . "akreisher18@gmail.com") (:keywords "convenience") (:url . "https://github.com/akreisher/eshell-syntax-highlighting"))]) (eshell-toggle . [(20220718 729) ((emacs (25 1)) (dash (2 11 0))) "Show/hide eshell under active window." single ((:commit . "d4e884624f02e68b267b0044322ad17baa6780f8") (:authors ("Dmitry Cherkassov" . "dcherkassov@gmail.com")) (:maintainer "Dmitry Cherkassov" . "dcherkassov@gmail.com") (:keywords "processes") (:url . "https://github.com/4da/eshell-toggle"))]) (eshell-up . [(20170425 1737) ((emacs (24))) "Quickly go to a specific parent directory in eshell" single ((:commit . "b00e447ad7941ab31bcbb6bc0205fd492e887e7d") (:authors ("Peter W. V. Tran-Jørgensen" . "peter.w.v.jorgensen@gmail.com")) (:maintainer "Peter W. V. Tran-Jørgensen" . "peter.w.v.jorgensen@gmail.com") (:keywords "eshell") (:url . "https://github.com/peterwvj/eshell-up"))]) (eshell-vterm . [(20221229 1328) ((emacs (27 1)) (vterm (0 0 1))) "Vterm for visual commands in eshell" single ((:commit . "e96c30ad5e7d63b778fc3232e81b090b63b13277") (:authors ("Illia Ostapyshyn" . "ilya.ostapyshyn@gmail.com")) (:maintainer "Illia Ostapyshyn" . "ilya.ostapyshyn@gmail.com") (:keywords "eshell" "vterm" "terminals" "shell" "visual" "tools" "processes") (:url . "https://github.com/iostapyshyn/eshell-vterm"))]) @@ -1390,7 +1391,7 @@ (espy . [(20200317 2333) ((emacs (24))) "Emacs Simple Password Yielder" single ((:commit . "2c01be937a5e5bde62921684a0b27300705fb4e0") (:authors ("Sebastian Wålinder" . "s.walinder@gmail.com")) (:maintainer "Sebastian Wålinder" . "s.walinder@gmail.com") (:keywords "convenience") (:url . "https://github.com/walseb/espy"))]) (esqlite . [(20151206 1206) ((pcsv (1 3 3))) "Manipulate sqlite file from Emacs" single ((:commit . "fae9826cbc255b0f0686a801288f1441bda5f631") (:authors ("Masahiro Hayashi" . "mhayashi1120@gmail.com")) (:maintainer "Masahiro Hayashi" . "mhayashi1120@gmail.com") (:keywords "data") (:url . "https://github.com/mhayashi1120/Emacs-esqlite"))]) (esqlite-helm . [(20151116 850) ((esqlite (0 2 0)) (helm (20131207 845))) "Define helm source for sqlite database" single ((:commit . "84d5b16198f30949c544affba751ee0d58a000d9") (:authors ("Masahiro Hayashi" . "mhayashi1120@gmail.com")) (:maintainer "Masahiro Hayashi" . "mhayashi1120@gmail.com") (:keywords "data") (:url . "https://github.com/mhayashi1120/Emacs-esqlite"))]) - (ess . [(20230302 2111) ((emacs (25 1))) "Emacs Speaks Statistics" tar ((:commit . "86d1bce8b53522a5939924960025799e66d9414e") (:authors ("David Smith" . "dsmith@stats.adelaide.edu.au") ("A.J. Rossini" . "blindglobe@gmail.com") ("Richard M. Heiberger" . "rmh@temple.edu") ("Kurt Hornik" . "Kurt.Hornik@R-project.org") ("Martin Maechler" . "maechler@stat.math.ethz.ch") ("Rodney A. Sparapani" . "rsparapa@mcw.edu") ("Stephen Eglen" . "stephen@gnu.org") ("Sebastian P. Luque" . "spluque@gmail.com") ("Henning Redestig" . "henning.red@googlemail.com") ("Vitalie Spinu" . "spinuvit@gmail.com") ("Lionel Henry" . "lionel.hry@gmail.com") ("J. Alexander Branham" . "alex.branham@gmail.com")) (:maintainer "ESS Core Team" . "ESS-core@r-project.org") (:url . "https://ess.r-project.org/"))]) + (ess . [(20230404 912) ((emacs (25 1))) "Emacs Speaks Statistics" tar ((:commit . "2d6d543946ec959f1c860b28218dcdac8e35168d") (:authors ("David Smith" . "dsmith@stats.adelaide.edu.au") ("A.J. Rossini" . "blindglobe@gmail.com") ("Richard M. Heiberger" . "rmh@temple.edu") ("Kurt Hornik" . "Kurt.Hornik@R-project.org") ("Martin Maechler" . "maechler@stat.math.ethz.ch") ("Rodney A. Sparapani" . "rsparapa@mcw.edu") ("Stephen Eglen" . "stephen@gnu.org") ("Sebastian P. Luque" . "spluque@gmail.com") ("Henning Redestig" . "henning.red@googlemail.com") ("Vitalie Spinu" . "spinuvit@gmail.com") ("Lionel Henry" . "lionel.hry@gmail.com") ("J. Alexander Branham" . "alex.branham@gmail.com")) (:maintainer "ESS Core Team" . "ESS-core@r-project.org") (:url . "https://ess.r-project.org/"))]) (ess-R-data-view . [(20130509 1158) ((ctable (20130313 1743)) (popup (20130324 1305)) (ess (20130225 1754))) "Data viewer for GNU R" single ((:commit . "d6e98d3ae1e2a2ea39a56eebcdb73e99d29562e9") (:authors ("myuhe ")) (:maintainer "myuhe") (:keywords "convenience") (:url . "https://github.com/myuhe/ess-R-data-view.el"))]) (ess-r-insert-obj . [(20220610 1406) ((emacs (26 1)) (ess (18 10 1))) "Insert objects in ESS-R" single ((:commit . "2ded9c23d0af2a7f6c0e02f9ea4af0e5b3cb7fb4") (:authors ("Shuguang Sun" . "shuguang79@qq.com")) (:maintainer "Shuguang Sun" . "shuguang79@qq.com") (:keywords "tools") (:url . "https://github.com/ShuguangSun/ess-r-insert-obj"))]) (ess-smart-equals . [(20210411 1333) ((emacs (25 1)) (ess (18 10))) "flexible, context-sensitive assignment key for R/S" single ((:commit . "fea9eea4b59c3e9559b379508e3500076ca99ef1") (:authors ("Christopher R. Genovese" . "genovese@cmu.edu")) (:maintainer "Christopher R. Genovese" . "genovese@cmu.edu") (:keywords "r" "s" "ess" "convenience") (:url . "https://github.com/genovese/ess-smart-equals"))]) @@ -1415,7 +1416,7 @@ (evalator-clojure . [(20160208 2148) ((cider (0 10 0)) (evalator (1 0 0))) "Clojure evaluation context for evalator via CIDER." tar ((:commit . "caa4e0a137bdfada86593128a654e16aa617ad50") (:authors ("Sean Irby")) (:maintainer "Sean Irby" . "sean.t.irby@gmail.com") (:keywords "languages" "clojure" "cider" "helm") (:url . "http://www.github.com/seanirby/evalator-clojure"))]) (eve-mode . [(20170822 2231) ((emacs (25)) (polymode (1 0)) (markdown-mode (2 0))) "Major mode for editing Eve documents." single ((:commit . "a4661114d9c18725691b76321d72167ca5a9070a") (:authors ("Joshua Cole" . "joshuafcole@gmail.com")) (:maintainer "Joshua Cole" . "joshuafcole@gmail.com") (:keywords "languages" "wp" "tools") (:url . "https://github.com/witheve/emacs-eve-mode"))]) (everlasting-scratch . [(20230105 507) ((emacs (25 1))) "The *scratch* that lasts forever" single ((:commit . "1b7dac779501dcd988552aa6455a5be89e8b0562") (:authors ("Huming Chen" . "chenhuming@gmail.com")) (:maintainer "Huming Chen" . "chenhuming@gmail.com") (:keywords "convenience" "tool") (:url . "https://github.com/beacoder/everlasting-scratch"))]) - (evil . [(20230317 1043) ((emacs (24 1)) (goto-chg (1 6)) (cl-lib (0 5))) "Extensible Vi layer for Emacs." tar ((:commit . "53fb7af0204d297661949aa208a867d74362a256") (:maintainer "Tom Dalziel" . "tom.dalziel@gmail.com") (:keywords "emulations") (:url . "https://github.com/emacs-evil/evil"))]) + (evil . [(20230322 1818) ((emacs (24 1)) (goto-chg (1 6)) (cl-lib (0 5))) "Extensible Vi layer for Emacs." tar ((:commit . "c61bc34b40f1f0605a999e874e837d1e8bda85af") (:maintainer "Tom Dalziel" . "tom.dalziel@gmail.com") (:keywords "emulations") (:url . "https://github.com/emacs-evil/evil"))]) (evil-anzu . [(20220911 1939) ((evil (1 0 0)) (anzu (0 46))) "anzu for evil-mode" single ((:commit . "d1e98ee6976437164627542909a25c6946497899") (:authors ("Syohei YOSHIDA" . "syohex@gmail.com") ("Fredrik Bergroth" . "fbergroth@gmail.com")) (:maintainer "Syohei YOSHIDA" . "syohex@gmail.com") (:url . "https://github.com/syohex/emacs-evil-anzu"))]) (evil-args . [(20220125 1626) ((evil (1 0 8))) "Motions and text objects for delimited arguments in Evil." single ((:commit . "2671071a4a57eaee7cc8c27b9e4b6fc60fd2ccd3") (:authors ("Connor Smith" . "wconnorsmith@gmail.com")) (:maintainer "Connor Smith" . "wconnorsmith@gmail.com") (:keywords "evil" "vim-emulation") (:url . "http://github.com/wcsmith/evil-args"))]) (evil-avy . [(20150908 748) ((emacs (24 1)) (cl-lib (0 5)) (avy (0 3 0)) (evil (1 2 3))) "set-based completion" single ((:commit . "2dd955cc3ecaa7ddeb67b295298abdc6d16dd3a5") (:authors ("Yufan Lou" . "loganlyf@gmail.com")) (:maintainer "Yufan Lou" . "loganlyf@gmail.com") (:keywords "point" "location" "evil" "vim") (:url . "https://github.com/louy2/evil-avy"))]) @@ -1447,7 +1448,7 @@ (evil-lisp-state . [(20160404 248) ((evil (1 0 9)) (bind-map (0)) (smartparens (1 6 1))) "An evil state to edit Lisp code" single ((:commit . "3c65fecd9917a41eaf6460f22187e2323821f3ce") (:authors ("Sylvain Benner" . "sylvain.benner@gmail.com")) (:maintainer "Sylvain Benner" . "sylvain.benner@gmail.com") (:keywords "convenience" "editing" "evil" "smartparens" "lisp" "mnemonic") (:url . "https://github.com/syl20bnr/evil-lisp-state"))]) (evil-lispy . [(20190502 739) ((lispy (0 26 0)) (evil (1 2 12)) (hydra (0 13 5))) "precision Lisp editing with Evil and Lispy" tar ((:commit . "ed317f7fccbdbeea8aa04a91b1b1f48a0e2ddc4e") (:authors ("Brandon Carrell , Mika Vilpas" . "mika.vilpas@gmail.com")) (:maintainer "Brandon Carrell , Mika Vilpas" . "mika.vilpas@gmail.com") (:keywords "lisp") (:url . "https://github.com/sp3ctum/evil-lispy"))]) (evil-mark-replace . [(20200630 940) ((evil (1 14 0))) "replace the thing in marked area" single ((:commit . "d4fec7b10e93cca149163324cd2b2b2dcc211047") (:authors ("Chen Bin ")) (:maintainer "Chen Bin ") (:keywords "convenience") (:url . "http://github.com/redguardtoo/evil-mark-replace"))]) - (evil-matchit . [(20230205 420) ((emacs (25 1))) "Vim matchit ported to Evil" tar ((:commit . "2218356f05ad19efc9476d0bd10051843d2306da") (:authors ("Chen Bin" . "chenbin.sh@gmail.com")) (:maintainer "Chen Bin" . "chenbin.sh@gmail.com") (:keywords "matchit" "vim" "evil") (:url . "http://github.com/redguardtoo/evil-matchit"))]) + (evil-matchit . [(20230325 618) ((emacs (25 1))) "Vim matchit ported to Evil" tar ((:commit . "3b12ed55d67bb70e8957c0c7fdad4ab4ad79eb2f") (:authors ("Chen Bin" . "chenbin.sh@gmail.com")) (:maintainer "Chen Bin" . "chenbin.sh@gmail.com") (:keywords "matchit" "vim" "evil") (:url . "http://github.com/redguardtoo/evil-matchit"))]) (evil-mc . [(20220118 122) ((emacs (24 3)) (evil (1 2 14)) (cl-lib (0 5))) "Multiple cursors for evil-mode" tar ((:commit . "63fd2fe0c213a4cc31c464d246f92931c4cb720f") (:authors ("Gabriel Adomnicai" . "gabesoft@gmail.com")) (:maintainer "Gabriel Adomnicai" . "gabesoft@gmail.com") (:keywords "evil" "editing" "multiple-cursors" "vim" "evil-multiple-cursors" "evil-mc" "evil-mc") (:url . "https://github.com/gabesoft/evil-mc"))]) (evil-mc-extras . [(20170202 1649) ((emacs (24 3)) (evil (1 2 12)) (cl-lib (0 5)) (evil-mc (0 0 2)) (evil-numbers (0 4))) "Extra functionality for evil-mc" tar ((:commit . "ba3252ae129c3b79aeb70ec3d276cbda32b00421") (:authors ("Gabriel Adomnicai" . "gabesoft@gmail.com")) (:maintainer "Gabriel Adomnicai" . "gabesoft@gmail.com") (:keywords "evil" "editing" "multiple-cursors" "vim" "evil-multiple-cursors" "evil-mc" "evil-mc-extras") (:url . "https://github.com/gabesoft/evil-mc-extras"))]) (evil-mu4e . [(20180613 1039) ((emacs (24 4)) (evil (1 2 10))) "evil-based key bindings for mu4e" single ((:commit . "f4b387ccbd2c49f3bbb5401e93bfcc050ca128ef") (:authors ("Joris Engbers" . "info@jorisengbers.nl")) (:maintainer "Joris Engbers" . "info@jorisengbers.nl") (:url . "https://github.com/JorisE/evil-mu4e"))]) @@ -1522,7 +1523,7 @@ (exwm-firefox-evil . [(20220318 1958) ((emacs (24 4)) (exwm (0 16)) (evil (1 0 0)) (exwm-firefox-core (1 0))) "evil-mode implementation of exwm-firefox-core" single ((:commit . "a377326e2e4ac386a0abb3fc9b1b356a0d955b61") (:authors ("Sebastian Wålinder" . "s.walinder@gmail.com")) (:maintainer "Sebastian Wålinder" . "s.walinder@gmail.com") (:keywords "extensions") (:url . "https://github.com/walseb/exwm-firefox-evil"))]) (exwm-float . [(20210207 2035) ((emacs (25 1)) (xelb (0 18)) (exwm (0 24)) (popwin (1 0 2))) "Convenient modes and bindings for floating EXWM frames" single ((:commit . "047c83aa6b54bfb6ca8cac4d3ea18542611cef77") (:authors ("Mehmet Tekman")) (:maintainer "Mehmet Tekman") (:keywords "outlines") (:url . "https://gitlab.com/mtekman/exwm-float.el"))]) (exwm-mff . [(20210603 1723) ((emacs (25 1))) "Mouse Follows Focus" single ((:commit . "89206f2e3189f589c27c56bd2b6203e906ee7100") (:authors ("Ian Eure" . "public@lowbar.fyi")) (:maintainer "Ian Eure" . "public@lowbar.fyi") (:keywords "unix") (:url . "https://github.com/ieure/exwm-mff"))]) - (exwm-modeline . [(20220131 1520) ((emacs (27 1)) (exwm (0 26))) "A modeline segment for EXWM workspaces" single ((:commit . "86bce1d91089b9a1517e1abfca86bac47be91be3") (:authors ("Korytov Pavel" . "thexcloud@gmail.com")) (:maintainer "Korytov Pavel" . "thexcloud@gmail.com") (:url . "https://github.com/SqrtMinusOne/exwm-modeline"))]) + (exwm-modeline . [(20230331 1747) ((emacs (27 1)) (exwm (0 26))) "A modeline segment for EXWM workspaces" single ((:commit . "852a88a58714e3e59675b79b185f036f7b0300e8") (:authors ("Korytov Pavel" . "thexcloud@gmail.com")) (:maintainer "Korytov Pavel" . "thexcloud@gmail.com") (:url . "https://github.com/SqrtMinusOne/exwm-modeline"))]) (exwm-surf . [(20171204 1140) ((emacs (24 4)) (exwm (0 16))) "Interface for Surf (surf.suckless.org) under exwm" single ((:commit . "6c17e2c1597fe4b7b454a1dac23b9127ac951e94") (:authors ("Peter" . "craven@gmx.net")) (:maintainer "Peter" . "craven@gmx.net") (:keywords "extensions") (:url . "https://github.com/ecraven/exwm-surf"))]) (exwm-x . [(20230119 624) ((cl-lib (0 5)) (async (1 6)) (exwm (0 22))) "A derivative wm based on EXWM (emacs x window manager)" tar ((:commit . "1e2bbfca872ad76eaa8f1c00d17762bed256881a") (:authors ("Feng Shu" . "tumashu@163.com")) (:maintainer "Feng Shu" . "tumashu@163.com") (:keywords "window-manager" "exwm") (:url . "https://github.com/tumashu/exwm-x"))]) (eyebrowse . [(20201107 955) ((dash (2 7 0)) (emacs (24 3 1))) "Easy window config switching" single ((:commit . "bdc626f88ab8e3d88bf5bf2e929707606675ef92") (:authors ("Vasilij Schneidermann" . "mail@vasilij.de")) (:maintainer "Vasilij Schneidermann" . "mail@vasilij.de") (:keywords "convenience") (:url . "https://depp.brause.cc/eyebrowse"))]) @@ -1534,7 +1535,6 @@ (f3 . [(20180130 1158) ((emacs (24 3)) (helm (2 8 8)) (cl-lib (0 5))) "a helm interface to find" tar ((:commit . "000009ce4adf7a57eae80512f29c4ec2a1391ce5") (:authors ("Danny McClanahan")) (:maintainer "Danny McClanahan") (:keywords "find" "file" "files" "helm" "fast" "finder") (:url . "https://github.com/cosmicexplorer/f3"))]) (fabric . [(20171116 656) nil "Launch Fabric using Emacs" tar ((:commit . "df79be341d0b34ed23850f9894136092fa5fea8c") (:authors ("Nicolas Lamirault" . "nicolas.lamirault@chmouel.com")) (:maintainer "Nicolas Lamirault" . "nicolas.lamirault@chmouel.com") (:keywords "python" "fabric") (:url . "https://github.com/nlamirault/fabric.el"))]) (face-explorer . [(20190517 1857) nil "Library and tools for faces and text properties" single ((:commit . "ad1300e13e5643e4c246cabfd91f833d39113052") (:authors ("Anders Lindgren")) (:maintainer "Anders Lindgren") (:keywords "faces") (:url . "https://github.com/Lindydancer/face-explorer"))]) - (face-shift . [(20210725 2146) ((emacs (24 1))) "Shift the colour of certain faces" single ((:commit . "c214be3398a7671c6ea975f97740abdd38e910ea") (:authors ("Philip Kaludercic" . "philipk@posteo.net")) (:maintainer "Philip Kaludercic" . "philipk@posteo.net") (:keywords "faces") (:url . "https://git.sr.ht/~pkal/face-shift"))]) (faceup . [(20170925 1946) nil "Markup language for faces and font-lock regression testing" single ((:commit . "6c92dad56a133e14e7b27831e1bcf9b3a71ff154") (:authors ("Anders Lindgren")) (:maintainer "Anders Lindgren") (:keywords "faces" "languages") (:url . "https://github.com/Lindydancer/faceup"))]) (factlog . [(20130210 140) ((deferred (0 3 1))) "File activity logger" single ((:commit . "38f78132ae311faffba98ed5dd18d661af68678e") (:authors ("Takafumi Arakaki ")) (:maintainer "Takafumi Arakaki ") (:url . "https://github.com/tkf/factlog"))]) (faff-theme . [(20220629 1216) nil "Light Emacs color theme on cornsilk3 background" single ((:commit . "5d3c7e2f32f4dcdb22865c385ec48ababe5f293a") (:authors ("James Ferguson <(concat \"wjcferguson\" at-sign \"gmail.com\")>")) (:maintainer "James Ferguson <(concat \"wjcferguson\" at-sign \"gmail.com\")>") (:keywords "color" "theme") (:url . "https://github.com/WJCFerguson/emacs-faff-theme"))]) @@ -1569,7 +1569,7 @@ (fic-mode . [(20180603 2035) nil "Show FIXME/TODO/BUG(...) in special face only in comments and strings" single ((:commit . "a05fc36ed54ba0c6dc22ac216a6a72cf191ca13d") (:url . "https://github.com/lewang/fic-mode"))]) (fifo-class . [(20160425 558) nil "First in first out abstract class" single ((:commit . "8fe4cf690727f4ac7b67f29c55f845df023c3f21") (:authors ("Mola-T" . "Mola@molamola.xyz")) (:maintainer "Mola-T" . "Mola@molamola.xyz") (:keywords "lisp") (:url . "https://github.com/mola-T/fifo-class"))]) (figlet . [(20160218 2237) nil "Annoy people with big, ascii art text" single ((:commit . "19a38783a90e151faf047ff233a21a729db0cea9") (:authors ("Philip Jackson" . "phil@shellarchive.co.uk")) (:maintainer "Philip Jackson" . "phil@shellarchive.co.uk"))]) - (file-info . [(20230214 1955) ((emacs (28 1)) (hydra (0 15 0)) (browse-at-remote (0 15 0))) "Show pretty information about current file" single ((:commit . "0c7717796ed84629145387b4b9ef60b600c3efc0") (:authors ("Artur Yaroshenko" . "artawower@protonmail.com")) (:maintainer "Artur Yaroshenko" . "artawower@protonmail.com") (:url . "https://github.com/artawower/file-info.el"))]) + (file-info . [(20230330 1709) ((emacs (28 1)) (hydra (0 15 0)) (browse-at-remote (0 15 0))) "Show pretty information about current file" single ((:commit . "0c9eb805f5600045cd0870747abc801e8a6e3ffa") (:authors ("Artur Yaroshenko" . "artawower@protonmail.com")) (:maintainer "Artur Yaroshenko" . "artawower@protonmail.com") (:url . "https://github.com/artawower/file-info.el"))]) (filelock . [(20180524 2215) ((emacs (24)) (cl-lib (0)) (f (0))) "Functions for manipulating file locks" single ((:commit . "17a5ca6e0dee14d2e7d92c84be91143bca9d9663") (:authors ("Ryan C. Thompson")) (:maintainer "Ryan C. Thompson") (:keywords "extensions" "files" "tools") (:url . "https://github.com/DarwinAwardWinner/emacs-filelock"))]) (filetags . [(20190706 804) ((emacs (24 4))) "Package to manage filetags in filename" single ((:commit . "71667a819e46eb1f6e30e2fa61321acb7c6ccb3d") (:authors ("Max Beutelspacher")) (:maintainer "Max Beutelspacher") (:keywords "convenience" "files") (:url . "https://github.com/DerBeutlin/filetags.el"))]) (filetree . [(20221108 236) ((dash (2 12 0)) (helm (3 7 0)) (seq (2 23)) (transient (0 3 6))) "File tree view/manipulatation package" single ((:commit . "1c48ef63a639bfe1ae4d5095725ef88a3f2c590d") (:authors ("Ketan Patel" . "knpatel401@gmail.com")) (:maintainer "Ketan Patel" . "knpatel401@gmail.com") (:url . "https://github.com/knpatel401/filetree"))]) @@ -1596,7 +1596,7 @@ (firestarter . [(20210508 1626) ((emacs (24 1))) "Execute (shell) commands on save" single ((:commit . "76070c9074aa363350abe6ad06143e90b3e12ab1") (:authors ("Vasilij Schneidermann" . "mail@vasilij.de")) (:maintainer "Vasilij Schneidermann" . "mail@vasilij.de") (:keywords "convenience") (:url . "https://depp.brause.cc/firestarter"))]) (firrtl-mode . [(20200329 2002) ((emacs (24 3))) "mode for working with FIRRTL files" single ((:commit . "fa40141411a876ce7a1a9d6d3fe47134bc1fa954") (:authors ("Schuyler Eldridge" . "schuyler.eldridge@ibm.com")) (:maintainer "Schuyler Eldridge" . "schuyler.eldridge@ibm.com") (:keywords "languages" "firrtl") (:url . "https://github.com/ibm/firrtl-mode"))]) (fish-completion . [(20191103 1210) ((emacs (25 1))) "Fish completion for pcomplete (shell and Eshell)" single ((:commit . "10384881817b5ae38cf6197a077a663420090d2c") (:authors ("Pierre Neidhardt" . "mail@ambrevar.xyz")) (:maintainer "Pierre Neidhardt" . "mail@ambrevar.xyz") (:url . "https://gitlab.com/Ambrevar/emacs-fish-completion"))]) - (fish-mode . [(20220505 1111) ((emacs (24))) "Major mode for fish shell scripts" single ((:commit . "d04478c0aba018cb789d77d591bfe315cb25132a") (:authors ("Tony Wang" . "wwwjfy@gmail.com")) (:maintainer "Tony Wang" . "wwwjfy@gmail.com") (:keywords "fish" "shell"))]) + (fish-mode . [(20230326 1604) ((emacs (24))) "Major mode for fish shell scripts" single ((:commit . "6869efbc05cdb628209338bf57fe52742e53d956") (:authors ("Tony Wang" . "wwwjfy@gmail.com")) (:maintainer "Tony Wang" . "wwwjfy@gmail.com") (:keywords "fish" "shell"))]) (fit-text-scale . [(20211230 2002) ((emacs (25 1))) "Fit text by scaling" single ((:commit . "c53c8ce606380088643463848a9ee3502b0c64f4") (:authors ("Marco Wahl" . "marcowahlsoft@gmail.com")) (:maintainer "Marco Wahl" . "marcowahlsoft@gmail.com") (:keywords "convenience") (:url . "https://gitlab.com/marcowahl/fit-text-scale"))]) (fix-input . [(20210320 1244) ((emacs (24 4))) "Make input methods play nicely with alternative keyboard layout on OS level" single ((:commit . "10b3aebc3d4411e6889f3428e8f097c0fbf8585c") (:authors ("Mark Karpov" . "markkarpov92@gmail.com")) (:maintainer "Mark Karpov" . "markkarpov92@gmail.com") (:keywords "input" "method") (:url . "https://github.com/mrkkrp/fix-input"))]) (fix-muscle-memory . [(20210702 1755) nil "Simple hacks to fix muscle memory problems" single ((:commit . "b8d4b8025d758762f4459c70c3a7a209ead865ed") (:authors ("Jonathan Arkell" . "jonnay@jonnay.net")) (:maintainer "Jonathan Arkell" . "jonnay@jonnay.net") (:keywords "spelling" "typing"))]) @@ -1612,6 +1612,7 @@ (flatland-theme . [(20171113 1521) nil "A simple theme for Emacs based on the Flatland theme for Sublime Text" single ((:commit . "a98a6f19ad4dff0fa3fad1ea487b7d0ef634a19a") (:authors ("Greg Chapple" . "info@gregchapple.com")) (:maintainer "Greg Chapple" . "info@gregchapple.com") (:url . "http://github.com/gregchapple/flatland-emacs"))]) (flatui-dark-theme . [(20170513 1422) ((emacs (24))) "Dark color theme with colors from https://flatuicolors.com/" single ((:commit . "5b959a9f743f891e4660b1b432086417947872ea") (:authors ("Andrew Phillips" . "theasp@gmail.com")) (:maintainer "Andrew Phillips" . "theasp@gmail.com") (:keywords "color" "theme" "dark" "flatui" "faces") (:url . "https://github.com/theasp/flatui-dark-theme"))]) (flatui-theme . [(20160619 127) nil "A color theme for Emacs based on flatuicolors.com" single ((:commit . "9c15db5526c15c8dba55023f5698372b19c2a780") (:authors ("John Louis Del Rosario" . "john2x@gmail.com")) (:maintainer "John Louis Del Rosario" . "john2x@gmail.com") (:url . "https://github.com/john2x/flatui-theme.el"))]) + (fleetish-theme . [(20230407 1438) ((emacs (24))) "A take on the JetBrains Fleet theme" single ((:commit . "482513562b6691c7f3440b62a31033d22378ed96") (:authors ("Scott Raine" . "scott@raine.sh")) (:maintainer "Scott Raine" . "scott@raine.sh") (:url . "https://github.com/nylar/fleetish-emacs-theme"))]) (flex-autopair . [(20120809 1218) nil "Automatically insert pair braces and quotes, insertion conditions & actions are highly customizable." single ((:commit . "55d128749cc070551a1624a4508d1c4f6d76f7cf") (:authors ("Yuuki Arisawa" . "yuuki.ari@gmail.com")) (:maintainer "Yuuki Arisawa" . "yuuki.ari@gmail.com") (:keywords "keyboard" "input") (:url . "https://github.com/uk-ar/flex-autopair.el"))]) (flex-compile . [(20230116 1638) ((emacs (26 1)) (dash (2 17 0)) (buffer-manage (1 1))) "Run, evaluate and compile across many languages" tar ((:commit . "791e297048e02ef1649ad17a5a2bd9d78e766c03") (:authors ("Paul Landes")) (:maintainer "Paul Landes") (:keywords "compilation" "integration" "processes") (:url . "https://github.com/plandes/flex-compile"))]) (flex-isearch . [(20170308 2010) nil "Flex matching (like ido) in isearch." single ((:commit . "b1f7e04de762282c276343cc2709af9ff4abc9d2") (:authors ("Jonathan Kotta" . "jpkotta@gmail.com")) (:maintainer "Jonathan Kotta" . "jpkotta@gmail.com") (:keywords "convenience" "search") (:url . "https://bitbucket.org/jpkotta/flex-isearch"))]) @@ -1676,7 +1677,7 @@ (flycheck-gradle . [(20190315 234) ((emacs (25 1)) (flycheck (0 25))) "Flycheck extension for Gradle." single ((:commit . "1ca08bbc343362a923cbdc2010f66e41655e92ab") (:maintainer "James Nguyen" . "james@jojojames.com") (:keywords "languages" "gradle") (:url . "https://github.com/jojojames/flycheck-gradle"))]) (flycheck-grammalecte . [(20221216 1904) ((emacs (26 1)) (flycheck (26))) "Integrate Grammalecte with Flycheck" tar ((:commit . "68c5087c8b31cf10fb9df77478edd24200fb4108") (:authors ("Guilhem Doulcier" . "guilhem.doulcier@espci.fr") ("Étienne Deparis" . "etienne@depar.is")) (:maintainer "Étienne Deparis" . "etienne@depar.is") (:keywords "i18n" "text") (:url . "https://git.umaneti.net/flycheck-grammalecte/"))]) (flycheck-grammarly . [(20221231 1654) ((emacs (25 1)) (flycheck (0 14)) (grammarly (0 3 0)) (s (1 12 0))) "Grammarly support for Flycheck" single ((:commit . "d4a788acc3875a1ffdd7460ab3377a887413c582") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "grammar" "check") (:url . "https://github.com/emacs-grammarly/flycheck-grammarly"))]) - (flycheck-guile . [(20220831 453) ((emacs (25 1)) (flycheck (0 22)) (geiser (0 20))) "A Flycheck checker for GNU Guile" single ((:commit . "e58ceb8b511cd395b9be69f4a1ff85305fbb51c3") (:authors ("Ricardo Wurmus" . "rekado@elephly.net")) (:maintainer "Andrew Whatson" . "whatson@gmail.com") (:url . "https://github.com/flatwhatson/flycheck-guile"))]) + (flycheck-guile . [(20230405 1154) ((emacs (25 1)) (flycheck (0 22)) (geiser (0 20))) "A Flycheck checker for GNU Guile" single ((:commit . "dd7bbdc48fd21cf8d270c913c56cd580f8ec3d03") (:authors ("Ricardo Wurmus" . "rekado@elephly.net")) (:maintainer "Andrew Whatson" . "whatson@tailcall.au") (:url . "https://notabug.org/flatwhatson/flycheck-guile"))]) (flycheck-haskell . [(20221111 59) ((emacs (24 3)) (flycheck (0 25)) (haskell-mode (13 7)) (dash (2 4 0)) (seq (1 11)) (let-alist (1 0 1))) "Flycheck: Automatic Haskell configuration" tar ((:commit . "50425a8b96fea84ea15940a4a07b184e43bb8e7a") (:authors ("Sebastian Wiesner" . "swiesner@lunaryorn.com")) (:maintainer "Sebastian Wiesner" . "swiesner@lunaryorn.com") (:keywords "tools" "convenience") (:url . "https://github.com/flycheck/flycheck-haskell"))]) (flycheck-hdevtools . [(20160926 702) ((flycheck (0 21 -4 1)) (dash (2 0))) "A flycheck checker for Haskell using hdevtools" single ((:commit . "53829f0c57800615718cfce27ffa16d8ba286cee") (:authors ("Steve Purcell" . "steve@sanityinc.com")) (:maintainer "Steve Purcell" . "steve@sanityinc.com") (:keywords "convenience" "languages" "tools") (:url . "https://github.com/flycheck/flycheck-hdevtools"))]) (flycheck-hledger . [(20220715 1115) ((emacs (27 1)) (flycheck (31))) "Flycheck module to check hledger journals" single ((:commit . "c360025b8433abc4da89b0bfcc7ed1ff27004c64") (:authors ("Damien Cassou" . "damien@cassou.me")) (:maintainer "Damien Cassou" . "damien@cassou.me") (:url . "https://github.com/DamienCassou/flycheck-hledger/"))]) @@ -1690,7 +1691,7 @@ (flycheck-julia . [(20170729 2141) ((emacs (24)) (flycheck (0 22))) "Julia support for Flycheck" single ((:commit . "213b60a5a9a1cb7887260e1d159b5bb27167cbb6") (:authors ("Guido Kraemer" . "guido.kraemer@gmx.de")) (:maintainer "Guido Kraemer" . "guido.kraemer@gmx.de") (:keywords "convenience" "tools" "languages") (:url . "https://github.com/gdkrmr/flycheck-julia"))]) (flycheck-keg . [(20200726 218) ((emacs (24 3)) (keg (0 1)) (flycheck (0 1))) "Flycheck for Keg projects" single ((:commit . "926de8f43842380e7150d99971eb73ff84cb59cb") (:authors ("Naoya Yamashita" . "conao3@gmail.com")) (:maintainer "Naoya Yamashita" . "conao3@gmail.com") (:keywords "convenience") (:url . "https://github.com/conao3/keg.el"))]) (flycheck-kotlin . [(20230111 1907) ((flycheck (0 20))) "Support kotlin in flycheck" single ((:commit . "a2a6abb9a7f85c6fb15ce327459ec3c8ff780188") (:authors ("Elric Milon" . "whirm_REMOVETHIS__@gmx.com")) (:maintainer "Elric Milon" . "whirm_REMOVETHIS__@gmx.com"))]) - (flycheck-languagetool . [(20221231 1658) ((emacs (25 1)) (flycheck (0 14))) "Flycheck support for LanguageTool" single ((:commit . "1fe838c8678a9a101935ce4a4f3183a731e38f01") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com") ("Peter Oliver" . "git@mavit.org.uk")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "grammar" "check") (:url . "https://github.com/emacs-languagetool/flycheck-languagetool"))]) + (flycheck-languagetool . [(20230329 1246) ((emacs (25 1)) (flycheck (0 14))) "Flycheck support for LanguageTool" single ((:commit . "04195838e21da84ec46d2940c2b3ee82d8beda70") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com") ("Peter Oliver" . "git@mavit.org.uk")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "grammar" "check") (:url . "https://github.com/emacs-languagetool/flycheck-languagetool"))]) (flycheck-ledger . [(20200304 2204) ((emacs (24 1)) (flycheck (0 15))) "Flycheck integration for ledger files" single ((:commit . "628e25ba66604946085571652a94a54f4d1ad96f") (:authors ("Steve Purcell" . "steve@sanityinc.com")) (:maintainer "Steve Purcell" . "steve@sanityinc.com") (:keywords "convenience" "languages" "tools") (:url . "https://github.com/purcell/flycheck-ledger"))]) (flycheck-lilypond . [(20211006 2102) ((emacs (24 3)) (flycheck (0 22))) "LilyPond support in Flycheck" single ((:commit . "78f8c16cd67f9f6d3f1806e1fd403222723ba400") (:authors ("Hinrik Örn Sigurðsson" . "hinrik.sig@gmail.com")) (:maintainer "Hinrik Örn Sigurðsson" . "hinrik.sig@gmail.com") (:keywords "tools" "convenience") (:url . "https://github.com/hinrik/flycheck-lilypond"))]) (flycheck-liquidhs . [(20170412 2326) ((flycheck (0 15))) "A flycheck checker for Haskell using liquid (i.e. liquidhaskell)" single ((:commit . "c27252ac24d77f4b6eec76a4ba9cd61761a3fba9") (:authors ("Ranjit Jhala" . "jhala@cs.ucsd.edu")) (:maintainer "Ranjit Jhala" . "jhala@cs.ucsd.edu") (:keywords "convenience" "languages" "tools") (:url . "https://github.com/ucsd-progsys/liquidhaskell/flycheck-liquid.el"))]) @@ -1705,7 +1706,7 @@ (flycheck-pact . [(20180920 2052) ((emacs (24 3)) (flycheck (0 25)) (pact-mode (0 0 4))) "Flycheck support for pact-mode" single ((:commit . "0e10045064ef89ec8b6f5a473073d47b976a2ca3") (:authors ("Stuart Popejoy")) (:maintainer "Stuart Popejoy" . "stuart@kadena.io") (:keywords "pact" "lisp" "languages" "blockchain" "smartcontracts" "tools" "linting") (:url . "http://github.com/kadena-io/flycheck-pact"))]) (flycheck-pest . [(20200710 2327) ((emacs (26 3)) (flycheck (31)) (pest-mode (0 1))) "Flycheck integration for Pest -" single ((:commit . "43447a2c70f98edd1139005e32f437d3f142442b") (:authors ("Naoya Yamashita" . "conao3@gmail.com")) (:maintainer "Naoya Yamashita" . "conao3@gmail.com") (:keywords "convenience" "flycheck") (:url . "https://github.com/ksqsf/pest-mode"))]) (flycheck-php-noverify . [(20211005 401) ((flycheck (0 22))) "Flycheck checker for PHP Noverify linter" single ((:commit . "3aa3035c637eb0476f05bd0fbc66c058aa67ffb7") (:url . "https://github.com/Junker/flycheck-php-noverify"))]) - (flycheck-phpstan . [(20220723 1451) ((emacs (24 3)) (flycheck (26)) (phpstan (0 5 0))) "Flycheck integration for PHPStan" single ((:commit . "8928206e16d7408f80d6987390fcebe26e3d30dd") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "tools" "php") (:url . "https://github.com/emacs-php/phpstan.el"))]) + (flycheck-phpstan . [(20230404 1351) ((emacs (24 3)) (flycheck (26)) (phpstan (0 5 0))) "Flycheck integration for PHPStan" single ((:commit . "6dc8f1df29f22f0b0ef839c66822d48e2c7b1848") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "tools" "php") (:url . "https://github.com/emacs-php/phpstan.el"))]) (flycheck-pkg-config . [(20230119 1721) ((dash (2 8 0)) (s (1 9 0)) (flycheck (29))) "configure flycheck using pkg-config" single ((:commit . "c4e4028f6621187365b7362566ac2786206765a1") (:authors ("Wilfred Hughes" . "me@wilfred.me.uk")) (:maintainer "Wilfred Hughes" . "me@wilfred.me.uk") (:keywords "flycheck"))]) (flycheck-plantuml . [(20171018 111) ((flycheck (0 24)) (emacs (24 4)) (plantuml-mode (1 2 2))) "Integrate plantuml with flycheck" single ((:commit . "183be89e1dbba0b38237dd198dff600e0790309d") (:authors ("Alex Murray" . "murray.alex@gmail.com")) (:maintainer "Alex Murray" . "murray.alex@gmail.com") (:url . "https://github.com/alexmurray/flycheck-plantuml"))]) (flycheck-pony . [(20210118 1327) ((flycheck (0 25 1))) "Pony support in Flycheck" single ((:commit . "22787cf8223ca9ec309e30a42c20a8e706d8bfbe") (:keywords "tools" "convenience") (:url . "https://github.com/seantallen/flycheck-pony"))]) @@ -1774,7 +1775,7 @@ (flymake-pest . [(20200710 2327) ((emacs (26 3)) (pest-mode (0 1))) "A flymake handler for Pest files" single ((:commit . "43447a2c70f98edd1139005e32f437d3f142442b") (:authors ("ksqsf" . "i@ksqsf.moe") ("Naoya Yamashita" . "conao3@gmail.com")) (:maintainer "ksqsf" . "i@ksqsf.moe") (:keywords "languages" "flymake") (:url . "https://github.com/ksqsf/pest-mode"))]) (flymake-php . [(20170723 146) ((flymake-easy (0 1))) "A flymake handler for php-mode files" single ((:commit . "c045d01e002ba5e09b05f40e25bf5068d02126bc") (:authors ("Steve Purcell" . "steve@sanityinc.com")) (:maintainer "Steve Purcell" . "steve@sanityinc.com") (:url . "https://github.com/purcell/flymake-php"))]) (flymake-phpcs . [(20210213 732) ((flymake-easy (0 9))) "making flymake work with PHP CodeSniffer" single ((:commit . "f947ba3066c1fa903d2ec69d67bf84413f51eb3f") (:authors ("Akiha Senda")) (:maintainer "Akiha Senda") (:keywords "flymake" "phpcs" "php") (:url . "https://github.com/senda-akiha/flymake-phpcs/"))]) - (flymake-phpstan . [(20210714 1805) ((emacs (26 1)) (phpstan (0 5 0))) "Flymake backend for PHP using PHPStan" single ((:commit . "0869b152f82a76138daa53e953285936b9d558bd") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "tools" "php") (:url . "https://github.com/emacs-php/phpstan.el"))]) + (flymake-phpstan . [(20230404 1351) ((emacs (26 1)) (phpstan (0 5 0))) "Flymake backend for PHP using PHPStan" single ((:commit . "6dc8f1df29f22f0b0ef839c66822d48e2c7b1848") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "tools" "php") (:url . "https://github.com/emacs-php/phpstan.el"))]) (flymake-puppet . [(20170801 554) ((flymake-easy (0 9))) "Flymake handler using puppet-lint" single ((:commit . "9579e5c736cb890195464fabf51df113313de88d") (:authors ("Ben Prew")) (:maintainer "Ben Prew") (:url . "https://github.com/benprew/flymake-puppet"))]) (flymake-python-pyflakes . [(20170723 146) ((flymake-easy (0 8))) "A flymake handler for python-mode files using pyflakes (or flake8)" single ((:commit . "1d65c26bf65a5dcbd29fcd967e2feb90e1e7a33d") (:authors ("Steve Purcell" . "steve@sanityinc.com")) (:maintainer "Steve Purcell" . "steve@sanityinc.com") (:url . "https://github.com/purcell/flymake-python-pyflakes"))]) (flymake-quickdef . [(20200308 2342) ((emacs (26 1))) "Quickly define a new Flymake backend" single ((:commit . "150c5839768a3d32f988f9dc08052978a68f2ad7") (:authors ("Karl Otness")) (:maintainer "Karl Otness") (:keywords "languages" "tools" "convenience" "lisp") (:url . "https://github.com/karlotness/flymake-quickdef"))]) @@ -1816,12 +1817,12 @@ (fontawesome . [(20170305 1356) ((emacs (24 4))) "fontawesome utility" tar ((:commit . "a743f80bfd53767ca9ee32da34c5ca032172a480") (:authors ("Syohei YOSHIDA" . "syohex@gmail.com")) (:maintainer "Syohei YOSHIDA" . "syohex@gmail.com") (:url . "https://github.com/syohex/emacs-fontawesome"))]) (fontify-face . [(20210503 1956) ((emacs (24))) "Fontify symbols representing faces with that face." single ((:commit . "d1386c88ccc77ccfb40b888ff90d6181325d14f8") (:authors ("Matúš Goljer" . "matus.goljer@gmail.com")) (:maintainer "Matúš Goljer" . "matus.goljer@gmail.com") (:keywords "faces") (:url . "https://github.com/Fuco1/fontify-face"))]) (fontsloth . [(20211118 2018) ((f (0 20 0)) (logito (0 1)) (pcache (0 5)) (stream (2 2 5)) (emacs (28 0))) "Elisp otf/ttf font loader/renderer" tar ((:commit . "615dd846cb80701cda4b34bc1dfb43bf695318b6") (:authors ("Jo Gay" . "jo.gay@mailfence.com")) (:maintainer "Jo Gay" . "jo.gay@mailfence.com") (:keywords "data" "font" "rasterization" "ttf" "otf") (:url . "https://github.com/jollm/fontsloth"))]) - (for . [(20221218 1023) ((emacs (28 1))) "Iteration and sequence" tar ((:commit . "3556d3693288a552a0962ee01ad7ec71caeb0dc8") (:authors ("Wing Hei Chan" . "whmunkchan@outlook.com")) (:maintainer "Wing Hei Chan" . "whmunkchan@outlook.com") (:keywords "extensions") (:url . "https://github.com/usaoc/elisp-for"))]) + (for . [(20230330 2007) ((emacs (28 1))) "Iteration and sequence" tar ((:commit . "db14b5da78feecd5eb139eaadb2accb94eabc347") (:authors ("Wing Hei Chan" . "whmunkchan@outlook.com")) (:maintainer "Wing Hei Chan" . "whmunkchan@outlook.com") (:keywords "extensions") (:url . "https://github.com/usaoc/elisp-for"))]) (forecast . [(20191004 1850) ((emacs (24 4))) "Weather forecasts" single ((:commit . "5f3e67448cc98fe2875115163849acae4d9e8526") (:authors ("Göktuğ Kayaalp" . "self@gkayaalp.com")) (:maintainer "Göktuğ Kayaalp" . "self@gkayaalp.com") (:keywords "weather" "forecast") (:url . "https://dev.gkayaalp.com/elisp/index.html#forecast-el"))]) (foreign-regexp . [(20200325 50) nil "search and replace by foreign regexp." tar ((:commit . "e2dd47f2160cadc194eb156e7c76c3c869e6706e") (:authors ("K-talo Miyazaki ")) (:maintainer "K-talo Miyazaki ") (:keywords "convenience" "emulations" "matching" "tools" "unix" "wp"))]) (foreman-mode . [(20170725 1422) ((s (1 9 0)) (dash (2 10 0)) (dash-functional (1 2 0)) (f (0 17 2)) (emacs (24))) "View and manage Procfile-based applications" single ((:commit . "22b3bb13134b617870ed1e888af739f4818be929") (:authors ("ZHOU Feng" . "zf.pascal@gmail.com")) (:maintainer "ZHOU Feng" . "zf.pascal@gmail.com") (:keywords "foreman") (:url . "http://github.com/zweifisch/foreman-mode"))]) (forest-blue-theme . [(20160627 842) ((emacs (24))) "Emacs theme with a dark background." single ((:commit . "58096ce1a25615d2bae806c3775bae3e2775019d") (:authors ("olkinn")) (:maintainer "olkinn"))]) - (forge . [(20230319 2100) ((emacs (25 1)) (compat (29 1 3 4)) (closql (20230220)) (dash (2 19 1)) (emacsql (20230220)) (ghub (20220621)) (let-alist (1 0 6)) (magit (20230319)) (markdown-mode (2 4)) (transient (0 3 6)) (yaml (0 3 5))) "Access Git forges from Magit." tar ((:commit . "e82b45fc426ac2542932c63e926f868e535a813f") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "git" "tools" "vc") (:url . "https://github.com/magit/forge"))]) + (forge . [(20230326 2058) ((emacs (25 1)) (compat (29 1 3 4)) (closql (20230220)) (dash (2 19 1)) (emacsql (20230220)) (ghub (20220621)) (let-alist (1 0 6)) (magit (20230319)) (markdown-mode (2 4)) (transient (0 3 6)) (yaml (0 3 5))) "Access Git forges from Magit." tar ((:commit . "422881e552afd9df15e591dbf52aa36e2d481758") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "git" "tools" "vc") (:url . "https://github.com/magit/forge"))]) (form-feed . [(20210508 1627) ((emacs (24 1))) "Display ^L glyphs as horizontal lines" single ((:commit . "ac1f0ef30a11979f5dfe12d8c05a666739e486ff") (:authors ("Vasilij Schneidermann" . "mail@vasilij.de")) (:maintainer "Vasilij Schneidermann" . "mail@vasilij.de") (:keywords "faces") (:url . "https://depp.brause.cc/form-feed"))]) (format-all . [(20230306 534) ((emacs (24 4)) (inheritenv (0 1)) (language-id (0 19))) "Auto-format C, C++, JS, Python, Ruby and 50 other languages" single ((:commit . "91ea3c16f594294b8064e61c4b14c5264d88e24d") (:authors ("Lassi Kortela" . "lassi@lassi.io")) (:maintainer "Lassi Kortela" . "lassi@lassi.io") (:keywords "languages" "util") (:url . "https://github.com/lassik/emacs-format-all-the-code"))]) (format-sql . [(20150422 1333) nil "Use format-sql to make your SQL readable in directly Emacs." single ((:commit . "97f475c245cd6c81a72a265678e2087cee66ac7b") (:authors ("Friedrich Paetzke" . "paetzke@fastmail.fm")) (:maintainer "Friedrich Paetzke" . "paetzke@fastmail.fm") (:url . "https://github.com/paetzke/format-sql.el"))]) @@ -1871,7 +1872,7 @@ (fwb-cmds . [(20230213 1143) ((emacs (25 1)) (compat (29 1 3 4))) "misc frame, window and buffer commands" single ((:commit . "1b375c6890de61eaccc97c92f2b46de6f9205417") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "convenience") (:url . "https://github.com/tarsius/fwb-cmds"))]) (fxrd-mode . [(20170728 1801) ((s (1 2))) "Major mode for editing fixed field width files" tar ((:commit . "795b969346982b75e24b5c8619b46197982fbb4d") (:authors ("Marc Sherry" . "msherry@gmail.com")) (:maintainer "Marc Sherry" . "msherry@gmail.com") (:keywords "convenience") (:url . "https://github.com/msherry/fxrd-mode"))]) (fyure . [(20130216 1314) nil "An interface to fix Japanese hyoki-yure" tar ((:commit . "b6977f1eb148e8b63259f7233b55bb050e44d9b8") (:authors ("Masafumi Oyamada" . "stillpedant@gmail.com")) (:maintainer "Masafumi Oyamada" . "stillpedant@gmail.com") (:keywords "languages"))]) - (fzf . [(20230224 1236) ((emacs (24 4))) "A front-end for fzf." single ((:commit . "f90ee73f9427ddce396fdca93a5be1ea04e56a1b") (:authors ("Bailey Ling")) (:maintainer "Bailey Ling") (:keywords "fzf" "fuzzy" "search") (:url . "https://github.com/bling/fzf.el"))]) + (fzf . [(20230403 1304) ((emacs (24 4))) "A front-end for fzf." single ((:commit . "3a55b983921c620fb5a2cc811f42aa4daaad8266") (:authors ("Bailey Ling")) (:maintainer "Bailey Ling") (:keywords "fzf" "fuzzy" "search") (:url . "https://github.com/bling/fzf.el"))]) (gameoflife . [(20200614 1814) nil "Screensaver running Conway's Game of Life" single ((:commit . "2483f3d98dbcf7f1633f551cc3691f5659b4b942") (:authors ("Anders Lindgren")) (:maintainer "Anders Lindgren") (:keywords "games") (:url . "https://github.com/Lindydancer/gameoflife"))]) (gams-ac . [(20180423 926) ((emacs (24)) (auto-complete (1 0)) (gams-mode (4 0))) "auto-complete source file for GAMS mode" single ((:commit . "66d04ff36033f54205c19bc1d893e926d4dbf02e") (:authors ("Shiro Takeda")) (:maintainer "Shiro Takeda") (:keywords "languages" "tools" "gams-mode" "auto-complete") (:url . "https://github.com/ShiroTakeda/gams-ac"))]) (gams-mode . [(20230214 1359) ((emacs (24 3))) "Major mode for General Algebraic Modeling System (GAMS)" tar ((:commit . "a50a290e5559e9f099e2bbbcecacac9e484ef4d9") (:authors ("Shiro Takeda")) (:maintainer "Shiro Takeda") (:keywords "languages" "tools" "gams") (:url . "http://shirotakeda.org/en/gams/gams-mode/"))]) @@ -1940,7 +1941,7 @@ (git-gutter-fringe . [(20211003 2228) ((git-gutter (0 88)) (fringe-helper (0 1 1)) (cl-lib (0 5)) (emacs (24))) "Fringe version of git-gutter.el" single ((:commit . "648cb5b57faec55711803cdc9434e55a733c3eba") (:authors ("Syohei YOSHIDA" . "syohex@gmail.com")) (:maintainer "Neil Okamoto" . "neil.okamoto+melpa@gmail.com") (:url . "https://github.com/emacsorphanage/git-gutter-fringe"))]) (git-gutter-fringe+ . [(20140729 1103) ((git-gutter+ (0 1)) (fringe-helper (1 0 1))) "Fringe version of git-gutter+.el" single ((:commit . "3857d486e5b3eca9281fba1c76756cb39a9f9866") (:authors ("Syohei YOSHIDA" . "syohex@gmail.com")) (:maintainer "Syohei YOSHIDA" . "syohex@gmail.com") (:url . "https://github.com/nonsequitur/git-gutter-fringe-plus"))]) (git-identity . [(20220721 912) ((emacs (25 1)) (dash (2 10)) (hydra (0 14)) (f (0 20))) "Identity management for (ma)git" single ((:commit . "f920916a92fad0c551cd0739e48fc09d8709bd8d") (:authors ("Akira Komamura" . "akira.komamura@gmail.com")) (:maintainer "Akira Komamura" . "akira.komamura@gmail.com") (:keywords "git" "vc" "convenience") (:url . "https://github.com/akirak/git-identity.el"))]) - (git-io . [(20180317 1752) ((emacs (24 4))) "git.io integration" single ((:commit . "48753acba73b48b997bb678fb5e2a938ae63b5d6") (:authors ("Tejas Bubane" . "tejasbubane@gmail.com")) (:maintainer "Tejas Bubane" . "tejasbubane@gmail.com") (:keywords "convenience" "files") (:url . "https://github.com/tejasbubane/emacs-git-io"))]) + (git-io . [(20230322 1038) ((emacs (24 4))) "Integration for git.io URL shortening in buffer" single ((:commit . "fb25f9432e6454edd621a7512ee7abc6220151a5") (:authors ("Tejas Bubane" . "tejasbubane@gmail.com")) (:maintainer "Tejas Bubane" . "tejasbubane@gmail.com") (:keywords "convenience" "files") (:url . "https://github.com/tejasbubane/emacs-git-io"))]) (git-lens . [(20220922 710) ((emacs (24 4))) "Show new, deleted or modified files in branch" single ((:commit . "347832fbdb75a0930aa3eef628ec0069a335f3b7") (:authors ("Peter Stiernström" . "peter@stiernstrom.se")) (:maintainer "Peter Stiernström" . "peter@stiernstrom.se") (:keywords "vc" "convenience") (:url . "https://github.com/pidu/git-lens"))]) (git-link . [(20230216 300) ((emacs (24 3))) "Get the GitHub/Bitbucket/GitLab URL for a buffer location" single ((:commit . "d3ba912079e0ca5fd727b1f617791c6ae1e0da82") (:authors ("Skye Shaw" . "skye.shaw@gmail.com")) (:maintainer "Skye Shaw" . "skye.shaw@gmail.com") (:keywords "git" "vc" "github" "bitbucket" "gitlab" "sourcehut" "aws" "azure" "convenience") (:url . "http://github.com/sshaw/git-link"))]) (git-messenger . [(20201202 1637) ((emacs (24 3)) (popup (0 5 3))) "Popup last commit of current line" single ((:commit . "fb9a049ac3b5fba7369ef1f027b97881f1e377ec") (:authors ("Syohei YOSHIDA" . "syohex@gmail.com")) (:maintainer "Neil Okamoto") (:url . "https://github.com/emacsorphanage/git-messenger"))]) @@ -1992,7 +1993,7 @@ (gntp . [(20141025 250) nil "Growl Notification Protocol for Emacs" single ((:commit . "767571135e2c0985944017dc59b0be79af222ef5") (:authors ("Engelke Eschner" . "tekai@gmx.li")) (:maintainer "Engelke Eschner" . "tekai@gmx.li"))]) (gnu-apl-mode . [(20220404 341) ((emacs (27))) "Integrate GNU APL with Emacs" tar ((:commit . "c8695b0d55b5167263a843252ffd21a589018427") (:authors ("Elias Mårtenson" . "lokedhs@gmail.com")) (:maintainer "Elias Mårtenson" . "lokedhs@gmail.com") (:keywords "languages") (:url . "http://www.gnu.org/software/apl/"))]) (gnu-indent . [(20221127 2112) ((emacs (25 1))) "Indent your code with GNU Indent" single ((:commit . "f31dbe60478b6270bb57b6b05998df8eec56f801") (:authors ("Akib Azmain Turja" . "akib@disroot.org")) (:maintainer "Akib Azmain Turja" . "akib@disroot.org") (:keywords "tools" "c") (:url . "https://codeberg.org/akib/emacs-gnu-indent"))]) - (gnuplot . [(20230224 926) ((emacs (25 1))) "Major-mode and interactive frontend for gnuplot" tar ((:commit . "9a31a12903cd3d9eb413948ef206023917c0d469") (:authors ("Jon Oddie, Bruce Ravel, Phil Type")) (:maintainer "Maxime Tréca , Daniel Mendler" . "mail@daniel-mendler.de") (:keywords "data" "gnuplot" "plotting") (:url . "https://github.com/emacs-gnuplot/gnuplot"))]) + (gnuplot . [(20230323 1400) ((emacs (25 1))) "Major-mode and interactive frontend for gnuplot" tar ((:commit . "f99effa21f85a4c0963fec6a38e9112a8157d27e") (:authors ("Jon Oddie, Bruce Ravel, Phil Type")) (:maintainer "Maxime Tréca , Daniel Mendler" . "mail@daniel-mendler.de") (:keywords "data" "gnuplot" "plotting") (:url . "https://github.com/emacs-gnuplot/gnuplot"))]) (gnuplot-mode . [(20171013 1616) nil "Major mode for editing gnuplot scripts" single ((:commit . "601f6392986f0cba332c87678d31ae0d0a496ce7") (:keywords "gnuplot" "plotting") (:url . "https://github.com/mkmcc/gnuplot-mode"))]) (gnus-alias . [(20150316 42) nil "an alternative to gnus-posting-styles" single ((:commit . "9447d3ccb4c0e75d0468899cccff7aa249657bac") (:authors ("Joe Casadonte" . "emacs@northbound-train.com")) (:maintainer "Mark A. Hershberger" . "mah@everybody.org") (:keywords "personality" "identity" "news" "mail" "gnus"))]) (gnus-desktop-notify . [(20180623 1538) ((gnus (1 0))) "Gnus Desktop Notification global minor mode" single ((:commit . "44ebe0241a19f4052cd427dff408206542aa3c8f") (:authors ("Yuri D'Elia ")) (:maintainer "Yuri D'Elia ") (:url . "http://www.thregr.org/~wavexx/software/gnus-desktop-notify.el/"))]) @@ -2054,14 +2055,14 @@ (goto-char-preview . [(20230111 1525) ((emacs (24 3))) "Preview character when executing `goto-char` command" single ((:commit . "feee79f83194155e67f5b16ca57b51b2d941b2ee") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "character" "navigation") (:url . "https://github.com/emacs-vs/goto-char-preview"))]) (goto-chg . [(20220107 1733) ((emacs (24 1))) "Go to last change" single ((:commit . "278cd3e6d5107693aa2bb33189ca503f22f227d0") (:authors ("David Andersson ")) (:maintainer "Vasilij Schneidermann" . "mail@vasilij.de") (:keywords "convenience" "matching") (:url . "https://github.com/emacs-evil/goto-chg"))]) (goto-last-change . [(20150109 1823) nil "Move point through buffer-undo-list positions" single ((:commit . "58b0928bc255b47aad318cd183a5dce8f62199cc") (:authors ("Kevin Rodgers" . "ihs_4664@yahoo.com")) (:maintainer "Kevin Rodgers" . "ihs_4664@yahoo.com") (:keywords "convenience") (:url . "https://github.com/camdez/goto-last-change.el"))]) - (goto-last-point . [(20230316 220) ((emacs (24 3))) "Record and jump to the last point in the buffer" single ((:commit . "5663311fee7f2c7aa07c46675a78960afe157b9a") (:authors ("Manuel Uberti" . "manuel.uberti@inventati.org")) (:maintainer "Manuel Uberti" . "manuel.uberti@inventati.org") (:keywords "convenience") (:url . "https://github.com/manuel-uberti/goto-last-point"))]) + (goto-last-point . [(20230406 1822) ((emacs (24 3))) "Record and jump to the last point in the buffer" single ((:commit . "2ad8ff095bc34b433803c824ec4f500ff51cd1b2") (:authors ("Manuel Uberti" . "manuel.uberti@inventati.org")) (:maintainer "Manuel Uberti" . "manuel.uberti@inventati.org") (:keywords "convenience") (:url . "https://github.com/manuel-uberti/goto-last-point"))]) (goto-line-preview . [(20230111 1531) ((emacs (25))) "Preview line when executing `goto-line` command" single ((:commit . "c6db484cf401351f7f2f57496b0466b774435947") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "line" "navigation") (:url . "https://github.com/emacs-vs/goto-line-preview"))]) (govc . [(20221216 1712) ((emacs (24 3)) (dash (1 5 0)) (s (1 9 0)) (magit-popup (2 0 50)) (json-mode (1 6 0))) "Interface to govc for managing VMware ESXi and vCenter" single ((:commit . "c82a709c50c0cd1ae560dd4c8da2d5b266114c50") (:authors ("The govc developers")) (:maintainer "The govc developers") (:keywords "convenience") (:url . "https://github.com/vmware/govmomi/tree/main/govc/emacs"))]) (govet . [(20170808 1724) nil "linter/problem finder for the Go source code" single ((:commit . "1b8c044aa856f4b62a682bc57494af19d22a6053") (:url . "https://godoc.org/golang.org/x/tools/cmd/vet"))]) (gpastel . [(20181229 1404) ((emacs (25 1))) "Integrates GPaste with the kill-ring" single ((:commit . "8a5522b274f79d55d7c9a0b2aaf062526f9253c7") (:authors ("Damien Cassou" . "damien@cassou.me")) (:maintainer "Damien Cassou" . "damien@cassou.me") (:keywords "tools") (:url . "https://gitlab.petton.fr/DamienCassou/desktop-environment"))]) (gpt . [(20230204 433) ((emacs (24 4))) "Run instruction-following language models" tar ((:commit . "a5eb9ce9cced47c26ecac5fa6bee044054ef948e") (:authors ("Andreas Stuhlmueller" . "andreas@ought.org")) (:maintainer "Andreas Stuhlmueller" . "andreas@ought.org") (:keywords "gpt3" "language" "copilot" "convenience" "tools") (:url . "https://github.com/stuhlmueller/gpt.el"))]) (gptai . [(20230318 1547) ((emacs (24 1))) "Integrate with the OpenAI API" tar ((:commit . "5cdea5c85b102e1e57904ea6bb826cccd506067f") (:authors ("Anton Hibl" . "antonhibl11@gmail.com")) (:maintainer "Anton Hibl" . "antonhibl11@gmail.com") (:keywords "comm" "convenience") (:url . "https://github.com/antonhibl/gptai"))]) - (gptel . [(20230320 258) ((emacs (27 1)) (transient (0 3 7))) "A simple ChatGPT client" tar ((:commit . "4f3ca234545a3643eb3bed2baf55645463b6f728") (:authors ("Karthik Chikmagalur")) (:maintainer "Karthik Chikmagalur") (:keywords "convenience") (:url . "https://github.com/karthink/gptel"))]) + (gptel . [(20230407 32) ((emacs (27 1)) (transient (0 3 7))) "A simple ChatGPT client" tar ((:commit . "6c47c0a48306e127557caf54c5a03e162e2d2ed3") (:authors ("Karthik Chikmagalur")) (:maintainer "Karthik Chikmagalur") (:keywords "convenience") (:url . "https://github.com/karthink/gptel"))]) (grab-mac-link . [(20210511 1303) ((emacs (24))) "Grab link from Mac Apps and insert it into Emacs" single ((:commit . "5fdb03bf57bc4a530374b896e0f8b5139dc794e3") (:authors ("Xu Chunyang")) (:maintainer "Xu Chunyang") (:keywords "mac" "hyperlink") (:url . "https://github.com/xuchunyang/grab-mac-link.el"))]) (grab-x-link . [(20191113 848) ((emacs (24)) (cl-lib (0 5))) "Grab links from X11 apps and insert into Emacs" single ((:commit . "d898db46e4864118359fdedfe915e180de3fe290") (:authors ("Xu Chunyang" . "mail@xuchunyang.me")) (:maintainer "Xu Chunyang" . "mail@xuchunyang.me") (:keywords "hyperlink") (:url . "https://github.com/xuchunyang/grab-x-link"))]) (gradle-mode . [(20150313 1905) ((s (1 8 0))) "Gradle integration with Emacs' compile" single ((:commit . "579de06674551919cddac9cfe42129f4fb0155c9") (:authors ("Daniel Mijares" . "daniel.j.mijares@gmail.com")) (:maintainer "Daniel Mijares" . "daniel.j.mijares@gmail.com") (:keywords "gradle") (:url . "http://github.com/jacobono/emacs-gradle-mode"))]) @@ -2074,7 +2075,7 @@ (graphql . [(20221128 1106) ((emacs (25))) "GraphQL utilities" tar ((:commit . "b57b5ca5d2d0837e1fb4a4f30c051d5f3e643f0f") (:authors ("Sean Allred" . "code@seanallred.com")) (:maintainer "Sean Allred" . "code@seanallred.com") (:keywords "hypermedia" "tools" "lisp") (:url . "https://github.com/vermiculus/graphql.el"))]) (graphql-doc . [(20220527 1721) ((emacs (26 1)) (request (0 3 2)) (promise (1 1))) "GraphQL Documentation Explorer" single ((:commit . "d37140267e0c426c7c18aff31900aa1650257394") (:authors ("Ian Fitzpatrick")) (:maintainer "Ian Fitzpatrick") (:url . "https://github.com/ifitzpatrick/graphql-doc.el"))]) (graphql-mode . [(20220716 827) ((emacs (24 3))) "Major mode for editing GraphQL schemas" single ((:commit . "92136cf9b5a4dcd8c202c8dba9064b497776d2f7") (:authors ("David Vazquez Pua" . "davazp@gmail.com")) (:maintainer "David Vazquez Pua" . "davazp@gmail.com") (:keywords "languages") (:url . "https://github.com/davazp/graphql-mode"))]) - (graphviz-dot-mode . [(20230227 2008) ((emacs (25 0))) "Mode for the dot-language used by graphviz (att)." single ((:commit . "3199817b54ffd6644b9c1c3fdd2d9317bf95a152") (:maintainer "Pieter Pareit" . "pieter.pareit@gmail.com") (:keywords "mode" "dot" "dot-language" "dotlanguage" "graphviz" "graphs" "att") (:url . "https://ppareit.github.io/graphviz-dot-mode/"))]) + (graphviz-dot-mode . [(20230325 1050) ((emacs (25 0))) "Mode for the dot-language used by graphviz (att)." single ((:commit . "8ff793b13707cb511875f56e167ff7f980a31136") (:maintainer "Pieter Pareit" . "pieter.pareit@gmail.com") (:keywords "mode" "dot" "dot-language" "dotlanguage" "graphviz" "graphs" "att") (:url . "https://ppareit.github.io/graphviz-dot-mode/"))]) (grapnel . [(20131001 1534) nil "HTTP request lib with flexible callback dispatch" single ((:commit . "7387234eb3f0285a490fddb1e06a4bf029719fb7") (:authors ("David Leatherman" . "leathekd@gmail.com")) (:maintainer "David Leatherman" . "leathekd@gmail.com") (:url . "http://www.github.com/leathekd/grapnel"))]) (grass-mode . [(20170503 1500) ((cl-lib (0 2)) (dash (2 8 0))) "Provides Emacs modes for interacting with the GRASS GIS program" single ((:commit . "f17e330dfde6a1b81a9b33d019fc0dff890f482d") (:authors ("Tyler Smith" . "tyler@plantarum.ca")) (:maintainer "Tyler Smith" . "tyler@plantarum.ca") (:keywords "grass" "gis"))]) (grayscale-theme . [(20171005 802) nil "A simple grayscale theme" single ((:commit . "917d63c0effc8459502a41e0cad5822d2b200499") (:authors ("Kaleb Elwert" . "belak@coded.io")) (:maintainer "Kaleb Elwert" . "belak@coded.io") (:keywords "lisp") (:url . "https://github.com/belak/emacs-grayscale-theme"))]) @@ -2121,7 +2122,7 @@ (ham-mode . [(20150811 1306) ((html-to-markdown (1 2)) (markdown-mode (2 0))) "Html As Markdown. Transparently edit an html file using markdown" single ((:commit . "3a141986a21c2aa6eefb428983352abb8b7907d2") (:authors ("Artur Malabarba" . "bruce.connor.am@gmail.com")) (:maintainer "Artur Malabarba" . "bruce.connor.am@gmail.com") (:keywords "convenience" "emulation" "wp") (:url . "http://github.com/Bruce-Connor/ham-mode"))]) (hamburg-theme . [(20160123 740) ((emacs (24))) "Color Theme with a dark blue background." single ((:commit . "a05bf090e0c57c34cc59e301f95d9961280db244") (:authors ("Martin Haesler")) (:maintainer "Martin Haesler"))]) (hamburger-menu . [(20220509 1341) ((emacs (28 1))) "Mode line hamburger menu" single ((:commit . "06bc9d6872007a31226d7410d497a0acd98b272b") (:authors ("Iain Nicol")) (:maintainer "Iain Nicol") (:keywords "hamburger" "menu") (:url . "https://gitlab.com/iain/hamburger-menu-mode"))]) - (haml-mode . [(20190219 2102) ((emacs (24)) (cl-lib (0 5))) "Major mode for editing Haml files" single ((:commit . "bf5b6c11b1206759d2b28af48765e04882dd1fc4") (:authors ("Natalie Weizenbaum")) (:maintainer "Natalie Weizenbaum") (:keywords "markup" "languages" "html") (:url . "https://github.com/nex3/haml-mode"))]) + (haml-mode . [(20230322 1744) ((emacs (24)) (cl-lib (0 5))) "Major mode for editing Haml files" single ((:commit . "45a0b23db0b8f827c78f7749457f3427263e6ffd") (:authors ("Natalie Weizenbaum")) (:maintainer "Natalie Weizenbaum") (:keywords "markup" "languages" "html") (:url . "https://github.com/nex3/haml-mode"))]) (hamlet-mode . [(20131208 724) ((cl-lib (0 3)) (dash (2 3 0)) (s (1 7 0))) "Hamlet editing mode" single ((:commit . "7362b955e556a3d007fa06945a27e5b99349527d") (:authors (nil . "Kata ")) (:maintainer "myuhe") (:keywords "convenience") (:url . "https://github.com/myuhe/helm-R.el"))]) (helm-ack . [(20141030 1226) ((helm (1 0)) (cl-lib (0 5))) "Ack command with helm interface" single ((:commit . "5982f3cb6ec9f460ebbe06ec0ce7b3590bca3118") (:authors ("Syohei YOSHIDA" . "syohex@gmail.com")) (:maintainer "Syohei YOSHIDA" . "syohex@gmail.com") (:url . "https://github.com/syohex/emacs-helm-ack"))]) (helm-ad . [(20151209 1015) ((dash (2 8 0)) (helm (1 6 2))) "helm source for Active Directory" single ((:commit . "8ac044705d8620ee354a9cfa8cc1b865e83c0d55") (:authors ("Takahiro Noda" . "takahiro.noda+github@gmail.com")) (:maintainer "Takahiro Noda" . "takahiro.noda+github@gmail.com") (:keywords "comm"))]) @@ -2253,7 +2254,7 @@ (helm-lib-babel . [(20180510 1324) ((cl-lib (0 5)) (helm (1 9 2)) (emacs (24 4))) "helm insertion of babel function references" single ((:commit . "41bc0cdea8a604c6c8dc83ed5066644d33688fad") (:authors ("Derek Feichtinger" . "dfeich@gmail.com")) (:maintainer "Derek Feichtinger" . "dfeich@gmail.com") (:keywords "convenience") (:url . "https://github.com/dfeich/helm-lib-babel.el"))]) (helm-lines . [(20220103 1909) ((emacs (24 4)) (helm (1 9 8))) "A helm interface for completing by lines" single ((:commit . "f5ad178818d223f32a0bf60d370b50c01df5f3da") (:authors ("@torgeir")) (:maintainer "@torgeir") (:keywords "files" "helm" "rg" "ag" "pt" "vc" "git" "lines" "complete" "tools" "languages") (:url . "https://github.com/torgeir/helm-lines.el/"))]) (helm-lobsters . [(20150213 1546) ((helm (1 0)) (cl-lib (0 5))) "helm front-end for lobste.rs" single ((:commit . "4121b232aeded2f82ad2c8a85c7dda17ef9d97bb") (:authors ("Julien BLANCHARD" . "julien@sideburns.eu")) (:maintainer "Julien BLANCHARD" . "julien@sideburns.eu") (:url . "https://github.com/julienXX/helm-lobste.rs"))]) - (helm-ls-git . [(20221118 503) ((helm (1 7 8))) "list git files." single ((:commit . "c5893f0cd92b20dcdcd5dc89d9ba6200a95c3f80"))]) + (helm-ls-git . [(20230405 957) ((helm (1 7 8))) "list git files." single ((:commit . "356e7f0c2725fc4ab6d2eb5bb4752ac1a8133039"))]) (helm-ls-hg . [(20150909 543) ((helm (1 7 8))) "List hg files in hg project." single ((:commit . "61b91a22fcfb62d0fc56e361ec01ce96973c7165"))]) (helm-ls-svn . [(20190316 2203) ((emacs (24 1)) (helm (1 7 0)) (cl-lib (0 5))) "helm extension to list svn files" single ((:commit . "a6043e1187282f649e2cb9f0e722a42daf41294b") (:authors ("Chunyang Xu" . "chunyang@macports.org")) (:maintainer "Chunyang Xu" . "chunyang@macports.org") (:keywords "helm" "svn") (:url . "https://svn.macports.org/repository/macports/users/chunyang/helm-ls-svn.el/helm-ls-svn.el"))]) (helm-lsp . [(20210419 2014) ((emacs (25 1)) (dash (2 14 1)) (lsp-mode (5 0)) (helm (2 0))) "LSP helm integration" single ((:commit . "c2c6974dadfac459b1a69a1217441283874cea92") (:authors ("Ivan Yonchovski" . "yyoncho@gmail.com")) (:maintainer "Ivan Yonchovski" . "yyoncho@gmail.com") (:keywords "languages" "debug") (:url . "https://github.com/yyoncho/helm-lsp"))]) @@ -2337,7 +2338,7 @@ (helm-zhihu-daily . [(20160625 1145) ((helm (1 0)) (cl-lib (0 5)) (emacs (24 4))) "Helm interface for 知乎日报 (http://daily.zhihu.com)" single ((:commit . "be27dcc6be1eb97663b65581a9a5c0fc81cfaba7") (:authors ("Chunyang Xu" . "xuchunyang56@gmail.com")) (:maintainer "Chunyang Xu" . "xuchunyang56@gmail.com") (:url . "https://github.com/xuchunyang/helm-zhihu-daily"))]) (help-find . [(20220929 822) ((emacs (25 2)) (dash (2 12))) "Additional help functions for working with keymaps" single ((:commit . "ef7266fc480367c12bff64817c875af940d0c9c0") (:authors ("Duncan Burke" . "duncankburke@gmail.com")) (:maintainer "Duncan Burke" . "duncankburke@gmail.com") (:keywords "help") (:url . "https://github.com/duncanburke/help-find"))]) (help-find-org-mode . [(20181204 234) ((emacs (24 4))) "Advise help to find org source over tangled code" single ((:commit . "c6fa2c8a8e9381572190010a9fa01f2be78f2790") (:authors ("Eric Crosson" . "eric.s.crosson@utexas.com")) (:maintainer "Eric Crosson" . "eric.s.crosson@utexas.com") (:keywords "convenience") (:url . "https://github.com/EricCrosson/help-find-org-mode"))]) - (helpful . [(20221209 1743) ((emacs (25)) (dash (2 18 0)) (s (1 11 0)) (f (0 20 0)) (elisp-refs (1 2))) "A better *help* buffer" single ((:commit . "94c25337b2de2f9da60914a7c0c6cca9584c0231") (:authors ("Wilfred Hughes" . "me@wilfred.me.uk")) (:maintainer "Wilfred Hughes" . "me@wilfred.me.uk") (:keywords "help" "lisp") (:url . "https://github.com/Wilfred/helpful"))]) + (helpful . [(20230323 414) ((emacs (25)) (dash (2 18 0)) (s (1 11 0)) (f (0 20 0)) (elisp-refs (1 2))) "A better *help* buffer" single ((:commit . "e9ec6fc2ae10db2b9b59ed656021845d11881a0a") (:authors ("Wilfred Hughes" . "me@wilfred.me.uk")) (:maintainer "Wilfred Hughes" . "me@wilfred.me.uk") (:keywords "help" "lisp") (:url . "https://github.com/Wilfred/helpful"))]) (hemera-theme . [(20180916 924) ((emacs (24))) "Light theme" single ((:commit . "b67c902b210b37b00cac68726822404543147ba8") (:authors ("Guido Schmidt")) (:maintainer "Guido Schmidt" . "guido.schmidt.2912@gmail.com") (:keywords "themes" "light-theme") (:url . "https://github.com/GuidoSchmidt/emacs-hemera-theme"))]) (hemisu-theme . [(20130508 1844) nil "Hemisu for Emacs." tar ((:commit . "ae593ac58e6bffef97467259c1d1472840385e84") (:authors ("Andrzej Sliwa")) (:maintainer "Andrzej Sliwa") (:url . "http://github/anrzejsliwa/django-theme"))]) (hercules . [(20200420 747) ((emacs (24 4)) (which-key (3 3 2))) "An auto-magical, which-key-based hydra banisher." single ((:commit . "557da39878d0637395fdded91243b340c37eff7b") (:authors ("Uros Perisic")) (:maintainer "Uros Perisic") (:keywords "convenience") (:url . "https://gitlab.com/jjzmajic/hercules"))]) @@ -2405,7 +2406,7 @@ (hookify . [(20141216 2209) ((s (1 9 0)) (dash (1 5 0))) "Interactive commands to create temporary hooks" single ((:commit . "e76127230716f7fab6662410c03c3872d17a172b") (:authors ("Philippe Vaucher" . "philippe.vaucher@gmail.com")) (:maintainer "Philippe Vaucher" . "philippe.vaucher@gmail.com") (:keywords "hook" "convenience") (:url . "https://github.com/Silex/hookify"))]) (horizon-theme . [(20200720 1832) ((emacs (24 3))) "A beautifully warm dual theme" single ((:commit . "9595549c514a9376c61d5d303405f6a6982e9e46") (:url . "https://github.com/aodhneine/horizon-theme.el"))]) (horoscope . [(20180409 641) ((emacs (24))) "generate horoscopes." single ((:commit . "f4c683e991adce0a8f9023f15050f306f9b9a9ed") (:authors ("Bob Manson" . "manson@cygnus.com")) (:maintainer "Noah Friedman" . "friedman@prep.ai.mit.edu") (:keywords "extensions" "games") (:url . "https://github.com/mschuldt/horoscope.el"))]) - (hotfuzz . [(20230221 844) ((emacs (27 1))) "Fuzzy completion style" single ((:commit . "90d95663f9ff667786b71071a039502d873ef4aa") (:authors ("Axel Forsman" . "axelsfor@gmail.com")) (:maintainer "Axel Forsman" . "axelsfor@gmail.com") (:keywords "matching") (:url . "https://github.com/axelf4/hotfuzz"))]) + (hotfuzz . [(20230322 1318) ((emacs (27 1))) "Fuzzy completion style" single ((:commit . "f02edb699c5b9bb60a1372dde3f187dac7797c48") (:authors ("Axel Forsman" . "axelsfor@gmail.com")) (:maintainer "Axel Forsman" . "axelsfor@gmail.com") (:keywords "matching") (:url . "https://github.com/axelf4/hotfuzz"))]) (hound . [(20200122 1700) ((request (0 2 0)) (cl-lib (0 5))) "Display hound search results in a compilation window" single ((:commit . "35e2cdc81fcc904b450a7ef3ec00fd25df6a4431") (:authors ("Ryan Young")) (:maintainer "Ryan Young"))]) (hover . [(20220129 1935) ((emacs (25 2)) (dash (2 14 1))) "Package to use hover with flutter" single ((:commit . "2b826735bb8d3bcfced489a1e0fa21b10fbc967e") (:authors ("Eric Dallo")) (:maintainer "Eric Dallo") (:keywords "hover" "flutter" "mobile" "tools") (:url . "https://github.com/ericdallo/hover.el"))]) (howdoi . [(20150204 43) nil "Instant coding answers via Emacs." tar ((:commit . "5fbf7069ee160c597a328e5ce5fb32920e1ca88f") (:authors ("Andrey Tykhonov ")) (:maintainer "Andrey Tykhonov" . "atykhonov@gmail.com") (:keywords "howdoi" "convenience") (:url . "https://github.com/atykhonov/emacs-howdoi/"))]) @@ -2436,7 +2437,7 @@ (hydandata-light-theme . [(20190809 1925) nil "A light color theme that is easy on your eyes" single ((:commit . "812ffa4bee3163098ef66ee4506feed45018be4e") (:authors ("David Chkhikvadze" . "david@chkhd.net")) (:maintainer "David Chkhikvadze" . "david@chkhd.net") (:keywords "color-theme" "theme") (:url . "https://github.com/chkhd/hydandata-light-theme"))]) (hyde . [(20160508 308) nil "Major mode to help create and manage Jekyll blogs" tar ((:commit . "a8cd6ed00ecd8d7de0ded2f4867015b412b15b76"))]) (hydra . [(20220910 1206) ((cl-lib (0 5)) (lv (0))) "Make bindings that stick around." tar ((:commit . "317e1de33086637579a7aeb60f77ed0405bf359b") (:authors ("Oleh Krehel" . "ohwoeowho@gmail.com")) (:maintainer "Oleh Krehel" . "ohwoeowho@gmail.com") (:keywords "bindings") (:url . "https://github.com/abo-abo/hydra"))]) - (hyperdrive . [(20230322 151) ((emacs (27 1)) (map (3 0)) (compat (29 1 3 2)) (plz (0 4)) (persist (0 5))) "Emacs gateway to the Hypercore network" tar ((:commit . "dfbf830eb51a23f3655a444a857b21897a35397b") (:authors ("Joseph Turner")) (:maintainer "Joseph Turner" . "joseph@ushin.org") (:url . "https://git.sr.ht/~ushin/hyperdrive.el"))]) + (hyperdrive . [(20230404 2049) ((emacs (27 1)) (map (3 0)) (compat (29 1 3 2)) (plz (0 4)) (persist (0 5))) "P2P filesystem in Emacs" tar ((:commit . "349be636e7dc4ba61262c9cf8d669b9b0637cd54") (:authors ("Joseph Turner")) (:maintainer "Joseph Turner" . "joseph@ushin.org") (:url . "https://git.sr.ht/~ushin/hyperdrive.el"))]) (hyperkitty . [(20220226 1951) ((request (0 3 2)) (emacs (25 1))) "Emacs interface for Hyperkitty archives" single ((:commit . "2c1d22ff017d096c359aa151e6a29f7214a58118") (:authors ("Abhilash Raj" . "maxking@asynchronous.in")) (:maintainer "Abhilash Raj" . "maxking@asynchronous.in") (:keywords "mail" "hyperkitty" "mailman") (:url . "https://github.com/maxking/hyperkitty.el"))]) (hyperlist-mode . [(20230119 28) ((emacs (24))) "A major-mode for viewing Hyperlists" single ((:commit . "480dbf33ca72e7b5fade952aaf0d5a5eb43acb1d") (:authors ("Wojciech Siewierski")) (:maintainer "Wojciech Siewierski") (:keywords "outlines") (:url . "https://github.com/vifon/hyperlist-mode"))]) (hyperspace . [(20210603 1825) ((emacs (25)) (s (1 12 0))) "Get there from here" single ((:commit . "c4c363c140250ba6b775516082063878975a6154") (:authors ("Ian Eure" . "ian@retrospec.tv")) (:maintainer "Ian Eure" . "ian@retrospec.tv") (:keywords "tools" "convenience") (:url . "https://github.com/ieure/hyperspace-el"))]) @@ -2521,7 +2522,7 @@ (indicators . [(20161211 1126) ((dash (2 13 0)) (cl-lib (0 5 0))) "Display the buffer relative location of line in the fringe." single ((:commit . "f62a1201f21453e3aca93f48483e65ae8251432e") (:authors ("Matus Goljer" . "matus.goljer@gmail.com")) (:maintainer "Matus Goljer" . "matus.goljer@gmail.com") (:keywords "fringe" "frames") (:url . "https://github.com/Fuco1/indicators.el"))]) (indium . [(20210309 1210) ((emacs (25)) (seq (2 16)) (js2-mode (20140114)) (js2-refactor (0 9 0)) (company (0 9 0)) (json-process-client (0 2 0))) "JavaScript Awesome Development Environment" tar ((:commit . "8499e156bf7286846c3a2bf8c9e0c4d4f24b224c") (:authors ("Nicolas Petton" . "nicolas@petton.fr")) (:maintainer "Nicolas Petton" . "nicolas@petton.fr") (:keywords "tools" "javascript") (:url . "https://github.com/NicolasPetton/indium"))]) (indy . [(20190807 625) nil "A minor mode and EDSL to manage your mode's indentation rules." single ((:commit . "abc5bee424780ad2de5520f8fefbf8e120c0d9ed") (:authors ("Kevin W. van Rooijen" . "kevin.van.rooijen@attichacker.com")) (:maintainer "Kevin W. van Rooijen" . "kevin.van.rooijen@attichacker.com") (:keywords "convenience" "matching" "tools"))]) - (inf-clojure . [(20230226 653) ((emacs (25 1)) (clojure-mode (5 11))) "Run an external Clojure process in an Emacs buffer" single ((:commit . "fb9b5ea55f9ef02be32660cc29df15023968fb78") (:maintainer "Bozhidar Batsov" . "bozhidar@batsov.dev") (:keywords "processes" "comint" "clojure") (:url . "http://github.com/clojure-emacs/inf-clojure"))]) + (inf-clojure . [(20230326 1946) ((emacs (26 2)) (clojure-mode (5 11))) "Run an external Clojure process in an Emacs buffer" single ((:commit . "8ad2242b75ea1a06fad391deb8f858a392408a94") (:maintainer "Bozhidar Batsov" . "bozhidar@batsov.dev") (:keywords "processes" "comint" "clojure") (:url . "http://github.com/clojure-emacs/inf-clojure"))]) (inf-crystal . [(20180119 211) ((emacs (24 3)) (crystal-mode (0 1 0))) "Run a Inferior-Crystal process in a buffer" single ((:commit . "dd5c85e621976ea09b602182a15396e3b510ec63") (:authors ("Brantou" . "brantou89@gmail.com")) (:maintainer "Brantou" . "brantou89@gmail.com") (:keywords "languages" "crystal") (:url . "https://github.com/brantou/inf-crystal.el"))]) (inf-elixir . [(20221120 2028) ((emacs (25 1))) "Run an interactive Elixir shell" single ((:commit . "6fbb0867b586ad1bf8adc09cc55f33dfa72db833") (:authors ("Jonathan Arnett" . "jonathan.arnett@protonmail.com")) (:maintainer "Jonathan Arnett" . "jonathan.arnett@protonmail.com") (:keywords "languages" "processes" "tools") (:url . "https://github.com/J3RN/inf-elixir"))]) (inf-mongo . [(20180408 1338) nil "Run a MongoDB shell process in a buffer" single ((:commit . "2e498d1c88bd1904eeec18ed06b1a0cf8bdc2a92") (:authors ("Tobias Svensson")) (:maintainer "Tobias Svensson") (:keywords "databases" "mongodb") (:url . "http://github.com/endofunky/inf-mongo"))]) @@ -2542,9 +2543,9 @@ (init-open-recentf . [(20220220 2004) ((emacs (24 4))) "Invoke a command immediately after startup" single ((:commit . "51463effe54ca9390ec339b9678968f35a40dbfd") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "files" "recentf" "after-init-hook") (:url . "https://github.com/zonuexe/init-open-recentf.el"))]) (initsplit . [(20160919 1818) nil "code to split customizations into different files" single ((:commit . "c941d436eb2b10b01c76a582c5a2b23fb30751aa") (:authors ("John Wiegley , Dave Abrahams" . "dave@boostpro.com")) (:maintainer "John Wiegley , Dave Abrahams" . "dave@boostpro.com") (:keywords "lisp") (:url . "http://www.gci-net.com/users/j/johnw/emacs.html"))]) (ink-mode . [(20201105 2242) ((emacs (26 1))) "Major mode for writing interactive fiction in Ink" tar ((:commit . "71d215712067729eb92e766a3b2067e7f3254183") (:authors ("Erik Sjöstrand") ("Damien Picard")) (:maintainer "Damien Picard") (:keywords "languages" "wp" "hypermedia") (:url . "https://github.com/Kungsgeten/ink-mode"))]) - (inkpot-theme . [(20230306 3) ((emacs (24 1))) "A port of vim's inkpot theme" single ((:commit . "f30a84f3d98e5682ef123136394e5859752c5168") (:authors ("Sarah Iovan" . "sarah@hwaetageek.com") ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Sarah Iovan" . "sarah@hwaetageek.com") (:url . "https://codeberg.org/ideasman42/emacs-inkpot-theme"))]) + (inkpot-theme . [(20230404 1301) ((emacs (24 1))) "A port of vim's inkpot theme" single ((:commit . "df3db22bf12246cb96a75aae1e8324555a1212f6") (:authors ("Sarah Iovan" . "sarah@hwaetageek.com") ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Sarah Iovan" . "sarah@hwaetageek.com") (:url . "https://codeberg.org/ideasman42/emacs-inkpot-theme"))]) (inline-crypt . [(20170824 900) nil "Simple inline encryption via openssl" tar ((:commit . "af4981c613bfd355d5ef34da1995a8384f167fd9") (:authors ("Daniel Ralston" . "Wubbulous@gmail.com")) (:maintainer "Daniel Ralston" . "Wubbulous@gmail.com") (:keywords "crypt") (:url . "https://github.com/Sodel-the-Vociferous/inline-crypt-el"))]) - (inline-docs . [(20220210 1402) ((emacs (24 3))) "Show inline contextual docs." single ((:commit . "cda596d9ff4c2aa5035692a97c430f6589eafbb1") (:authors ("stardiviner" . "numbchild@gmail.com")) (:maintainer "stardiviner" . "numbchild@gmail.com") (:keywords "inline" "docs" "overlay") (:url . "https://repo.or.cz/inline-docs.git"))]) + (inline-docs . [(20230406 1002) ((emacs (24 3))) "Show inline contextual docs." single ((:commit . "8eb1c43b53a7f51cf74cb85529d108b5ce5efff5") (:authors ("stardiviner" . "numbchild@gmail.com")) (:maintainer "stardiviner" . "numbchild@gmail.com") (:keywords "inline" "docs" "overlay") (:url . "https://repo.or.cz/inline-docs.git"))]) (inlineR . [(20191017 1920) nil "insert Tag for inline image of R graphics" single ((:commit . "bf6450a3540aa3538546d312324c41befd0a4e54") (:authors ("myuhe ")) (:maintainer "myuhe") (:keywords "convenience" "iimage.el" "cacoo.el") (:url . "https://github.com/myuhe/inlineR.el"))]) (insecure-lock . [(20221111 2002) ((emacs (28 1))) "Extensible screen lock framework" single ((:commit . "2750190c70ebf564fe142ab5ee7e44675609b06a") (:authors ("Qiantan Hong" . "qhong@alum.mit.edu")) (:maintainer "Qiantan Hong" . "qhong@alum.mit.edu") (:keywords "unix" "screensaver" "security") (:url . "https://github.com/BlueFlo0d/insecure-lock"))]) (insert-char-preview . [(20201023 2108) ((emacs (24 1))) "Insert Unicode char" single ((:commit . "8f13262ebcb3f271f1d188584d04ca6d87214111") (:authors ("Matsievskiy S.V.")) (:maintainer "Matsievskiy S.V.") (:keywords "convenience") (:url . "https://gitlab.com/matsievskiysv/insert-char-preview"))]) @@ -2590,7 +2591,7 @@ (iterator . [(20210109 1859) ((emacs (24)) (cl-lib (0 5))) "A library to create and use elisp iterators objects." single ((:commit . "b514d4d1d0167e5973afbc93a34070d1aa967d82") (:authors ("Thierry Volpiatto ")) (:maintainer "Thierry Volpiatto ") (:url . "https://github.com/thierryvolpiatto/iterator"))]) (ivariants . [(20170823 224) ((emacs (24 3)) (ivs-edit (1 0))) "Ideographic variants editor and browser" tar ((:commit . "ca0b74d32b5d2d77a45cc6ad6edc00be0ee85284") (:authors ("KAWABATA, Taichi ")) (:maintainer "KAWABATA, Taichi ") (:keywords "i18n" "languages") (:url . "http://github.com/kawabata/ivariants"))]) (ivs-edit . [(20170818 1441) ((emacs (24 3)) (dash (2 6 0)) (cl-lib (1 0))) "IVS (Ideographic Variation Sequence) editing tool" tar ((:commit . "5db39c234aa7393b591168a4fd0a9a4cbbca347d") (:authors ("KAWABATA, Taichi ")) (:maintainer "KAWABATA, Taichi ") (:keywords "text") (:url . "http://github.com/kawabata/ivs-edit"))]) - (ivy . [(20220926 1250) ((emacs (24 5))) "Incremental Vertical completYon" tar ((:commit . "29b61fe1f4d5268d750b666a7ffc1269e22c6477") (:authors ("Oleh Krehel" . "ohwoeowho@gmail.com")) (:maintainer "Oleh Krehel" . "ohwoeowho@gmail.com") (:keywords "matching") (:url . "https://github.com/abo-abo/swiper"))]) + (ivy . [(20230326 1253) ((emacs (24 5))) "Incremental Vertical completYon" tar ((:commit . "24a8262767b7917a91ed7ffc11298f28569e3087") (:authors ("Oleh Krehel" . "ohwoeowho@gmail.com")) (:maintainer "Oleh Krehel" . "ohwoeowho@gmail.com") (:keywords "matching") (:url . "https://github.com/abo-abo/swiper"))]) (ivy-avy . [(20211021 1602) ((emacs (24 5)) (ivy (0 13 4)) (avy (0 5 0))) "Avy integration for Ivy" single ((:commit . "bb77cf058d9fbc0a64e73491179e88c32e0b0b47") (:authors ("Oleh Krehel" . "ohwoeowho@gmail.com")) (:maintainer "Oleh Krehel" . "ohwoeowho@gmail.com") (:keywords "convenience") (:url . "https://github.com/abo-abo/swiper"))]) (ivy-bibtex . [(20210927 1205) ((bibtex-completion (1 0 0)) (ivy (0 13 0)) (cl-lib (0 5))) "A bibliography manager based on Ivy" single ((:commit . "bb47f355b0da8518aa3fb516019120c14c8747c9") (:authors ("Justin Burkett" . "justin@burkett.cc")) (:maintainer "Titus von der Malsburg" . "malsburg@posteo.de") (:url . "https://github.com/tmalsburg/helm-bibtex"))]) (ivy-clipmenu . [(20220202 2122) ((emacs (26 1)) (f (0 20 0)) (s (1 12 0)) (dash (2 16 0)) (ivy (0 13 0))) "Ivy client for clipmenu" single ((:commit . "7c200cd4732821187084fad23547ee3f58365062") (:authors ("William Carroll" . "wpcarro@gmail.com")) (:maintainer "William Carroll" . "wpcarro@gmail.com") (:url . "https://github.com/wpcarro/ivy-clipmenu.el"))]) @@ -2662,6 +2663,7 @@ (jetbrains-darcula-theme . [(20230223 1901) nil "A complete port of the default JetBrains Darcula theme" single ((:commit . "46f153385e50998826ca13e18056c6a972768cfd") (:authors ("Ian Y.E. Pan")) (:maintainer "Ian Y.E. Pan") (:url . "https://github.com/ianpan870102/jetbrains-darcula-emacs-theme"))]) (jg-quicknav . [(20170809 130) ((s (1 9 0)) (cl-lib (0 5))) "Quickly navigate the file system to find a file." single ((:commit . "c8d53e774d63e68a944092c08a026b57da741038") (:authors ("Jeff Gran" . "jeff@jeffgran.com")) (:maintainer "Jeff Gran" . "jeff@jeffgran.com") (:keywords "navigation") (:url . "https://github.com/jeffgran/jg-quicknav"))]) (jinja2-mode . [(20220117 807) nil "A major mode for jinja2" single ((:commit . "03e5430a7efe1d163a16beaf3c82c5fd2c2caee1") (:authors ("Florian Mounier aka paradoxxxzero")) (:maintainer "Florian Mounier aka paradoxxxzero"))]) + (jinx . [(20230406 2124) ((emacs (27 1)) (compat (29 1 4 0))) "Enchanted Spell Checker" tar ((:commit . "8578f7fa7c94dba34dc5067e2940069df58c4fe4") (:authors ("Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainer "Daniel Mendler" . "mail@daniel-mendler.de") (:url . "https://github.com/minad/jinx"))]) (jira-markup-mode . [(20150601 2109) nil "Emacs Major mode for JIRA-markup-formatted text files" single ((:commit . "53bf083fdbece483f1351f32085b424b38c4c1f2") (:authors ("Matthias Nuessler" . "m.nuessler@web.de>")) (:maintainer "Matthias Nuessler" . "m.nuessler@web.de>") (:keywords "jira" "markup") (:url . "https://github.com/mnuessler/jira-markup-mode"))]) (jiralib2 . [(20200520 2031) ((emacs (25)) (request (0 3)) (dash (2 14 1))) "JIRA REST API bindings to Elisp" single ((:commit . "c21c4e759eff549dbda11099f2f680b78d7f5a01") (:authors ("Henrik Nyman" . "h@nyymanni.com")) (:maintainer "Henrik Nyman" . "h@nyymanni.com") (:keywords "comm" "jira" "rest" "api") (:url . "https://github.com/nyyManni/jiralib2"))]) (jist . [(20161229 1721) ((emacs (24 4)) (dash (2 12 0)) (seq (1 11)) (let-alist (1 0 4)) (magit (2 1 0)) (request (0 2 0))) "Gist integration" single ((:commit . "ec4b27eb4051f0084cb3b1e4f19fab9e2db77665") (:authors ("Mario Rodas" . "marsam@users.noreply.github.com")) (:maintainer "Mario Rodas" . "marsam@users.noreply.github.com") (:keywords "convenience") (:url . "https://github.com/emacs-pe/jist.el"))]) @@ -2689,10 +2691,11 @@ (js2hl . [(20201119 816) ((emacs (25 1)) (js2-mode (20190219))) "Highlight/rename things using js2-mode parser" single ((:commit . "8a9a53a861d20ce51a382d6caef48ccd978d8212") (:authors ("Chen Bin ")) (:maintainer "Chen Bin ") (:keywords "convenience") (:url . "https://github.com/redguardtoo/js2hl"))]) (js3-mode . [(20160515 1550) nil "An improved JavaScript editing mode" tar ((:commit . "7fceb21ec56aac7af4b189bb0c0d0cf620327f5a") (:authors ("Thom Blake" . "webmaster@thomblake.com")) (:maintainer "Thom Blake" . "webmaster@thomblake.com") (:keywords "javascript" "languages"))]) (jscs . [(20151015 1749) ((emacs (24 1)) (cl-lib (0 5))) "Consistent JavaScript editing using JSCS" single ((:commit . "9d39d0f2355e69a020bf76242504f3a33e013ccf") (:authors ("papaeye" . "papaeye@gmail.com")) (:maintainer "papaeye" . "papaeye@gmail.com") (:keywords "languages" "convenience") (:url . "https://github.com/papaeye/emacs-jscs"))]) + (jsdoc . [(20230331 647) ((emacs (29 1)) (dash (2 11 0)) (s (1 12 0))) "Insert JSDoc comments" single ((:commit . "10606a37f70cbf419590bbbc292fe1e800435ed5") (:authors ("Isa Mert Gurbuz" . "isamertgurbuz@gmail.com")) (:maintainer "Isa Mert Gurbuz" . "isamertgurbuz@gmail.com") (:url . "https://github.com/isamert/jsdoc.el"))]) (jsfmt . [(20180920 1008) nil "Interface to jsfmt command for javascript files" single ((:commit . "ca141a135c7700eaedef92561d334e1fb7dc28a1") (:authors ("Brett Langdon" . "brett@blangdon.com")) (:maintainer "Brett Langdon" . "brett@blangdon.com") (:url . "https://github.com/brettlangdon/jsfmt.el"))]) (json-mode . [(20211011 630) ((json-snatcher (1 0 0)) (emacs (24 4))) "Major mode for editing JSON files." single ((:commit . "eedb4560034f795a7950fa07016bd4347c368873") (:authors ("Josh Johnston")) (:maintainer "Josh Johnston") (:url . "https://github.com/joshwnj/json-mode"))]) (json-navigator . [(20191213 755) ((emacs (25 1)) (hierarchy (0 6 0))) "View and navigate JSON structures" single ((:commit . "afd902e0b5cde37fad4786515a695d17f1625286") (:authors ("Damien Cassou" . "damien@cassou.me")) (:maintainer "Damien Cassou" . "damien@cassou.me") (:url . "https://github.com/DamienCassou/json-navigator"))]) - (json-par . [(20220919 652) ((emacs (24 4)) (json-mode (1 7 0))) "Minor mode for structural editing of JSON" tar ((:commit . "2dd58826eef67a656efd9897f65d306b5c3eb8b0") (:authors ("taku0" . "mxxouy6x3m_github@tatapa.org")) (:maintainer "taku0" . "mxxouy6x3m_github@tatapa.org") (:keywords "abbrev" "convenience" "files") (:url . "https://github.com/taku0/json-par"))]) + (json-par . [(20230401 901) ((emacs (24 4)) (json-mode (1 7 0))) "Minor mode for structural editing of JSON" tar ((:commit . "9d4503d595c41c5e501f6ce9067b487f8933cd4b") (:authors ("taku0" . "mxxouy6x3m_github@tatapa.org")) (:maintainer "taku0" . "mxxouy6x3m_github@tatapa.org") (:keywords "abbrev" "convenience" "files") (:url . "https://github.com/taku0/json-par"))]) (json-process-client . [(20210525 733) ((emacs (25 1))) "Interact with a TCP process using JSON" single ((:commit . "373b2cc7e3d26dc00594e0b2c1bb66815aad2826") (:authors ("Nicolas Petton" . "nicolas@petton.fr") ("Damien Cassou" . "damien@cassou.me")) (:maintainer "Nicolas Petton" . "nicolas@petton.fr") (:url . "https://gitlab.petton.fr/nico/json-process-client"))]) (json-reformat . [(20220905 2342) ((emacs (24 3))) "Reformatting tool for JSON" single ((:commit . "e9999b1f1fc933c02ff44f4136602b6a45ed59c6") (:authors ("Wataru MIYAGUNI" . "gonngo@gmail.com")) (:maintainer "Wataru MIYAGUNI" . "gonngo@gmail.com") (:keywords "json") (:url . "https://github.com/gongo/json-reformat"))]) (json-rpc . [(20200417 1629) ((emacs (24 1)) (cl-lib (0 5))) "JSON-RPC library" single ((:commit . "81a5a520072e20d18aeab2aac4d66c046b031e56") (:authors ("Christopher Wellons" . "wellons@nullprogram.com")) (:maintainer "Christopher Wellons" . "wellons@nullprogram.com") (:url . "https://github.com/skeeto/elisp-json-rpc"))]) @@ -2708,7 +2711,7 @@ (julia-mode . [(20230119 1840) ((emacs (24 3))) "Major mode for editing Julia source code" tar ((:commit . "7aafa8e77df64a47fa4729a0c1ea572b5bc8e30e") (:keywords "languages") (:url . "https://github.com/JuliaEditorSupport/julia-emacs"))]) (julia-repl . [(20230112 1929) ((emacs (25 1)) (s (1 12))) "A minor mode for a Julia REPL" single ((:commit . "57a15dfafed680ad7d81f779d414e8cb6717417c") (:authors ("Tamas Papp" . "tkpapp@gmail.com")) (:maintainer "Tamas Papp" . "tkpapp@gmail.com") (:keywords "languages") (:url . "https://github.com/tpapp/julia-repl"))]) (julia-shell . [(20161125 1910) ((julia-mode (0 3))) "Major mode for an inferior Julia shell" tar ((:commit . "583a0b2ca20461ab4356929fd0f2212c22341b69") (:authors ("Dennis Ogbe" . "dogbe@purdue.edu")) (:maintainer "Dennis Ogbe" . "dogbe@purdue.edu"))]) - (julia-snail . [(20220927 704) ((emacs (26 2)) (dash (2 16 0)) (julia-mode (0 3)) (s (1 12 0)) (spinner (1 7 3)) (vterm (0 0 1)) (popup (0 5 9))) "Julia Snail" tar ((:commit . "0e6fa5180447024c794cb8186c782c5cf28ae68e") (:url . "https://github.com/gcv/julia-snail"))]) + (julia-snail . [(20230331 2240) ((emacs (26 2)) (dash (2 16 0)) (julia-mode (0 3)) (s (1 12 0)) (spinner (1 7 3)) (vterm (0 0 1)) (popup (0 5 9))) "Julia Snail" tar ((:commit . "35e54bdf7d3d585772af6d7b0789bc4ca2d12be3") (:url . "https://github.com/gcv/julia-snail"))]) (julia-ts-mode . [(20230318 2210) ((emacs (29)) (julia-mode (0 4))) "Major mode for Julia source code using tree-sitter" single ((:commit . "33ea957ef696155ad45a952d653a9ff18d45c866") (:authors ("Ronan Arraes Jardim Chagas")) (:maintainer "Ronan Arraes Jardim Chagas") (:keywords "julia" "languages" "tree-sitter") (:url . "https://github.com/ronisbr/julia-ts-mode"))]) (julia-vterm . [(20220912 246) ((emacs (25 1)) (vterm (0 0 1))) "A mode for Julia REPL using vterm" single ((:commit . "e4d1c28935c47429442ddfcd735cb8d8c2d8db66") (:authors ("Shigeaki Nishina")) (:maintainer "Shigeaki Nishina") (:keywords "languages" "julia") (:url . "https://github.com/shg/julia-vterm.el"))]) (jumblr . [(20170727 2043) ((s (1 8 0)) (dash (2 2 0))) "an anagram game for emacs" tar ((:commit . "34533dfb9db8538c005f4eaffafeff7ed193729f") (:keywords "anagram" "word game" "games") (:url . "https://github.com/mkmcc/jumblr"))]) @@ -2722,18 +2725,18 @@ (justl . [(20221222 1650) ((transient (0 1 0)) (emacs (25 3)) (s (1 2 0)) (f (0 20 0))) "Major mode for driving just files" single ((:commit . "141daaa4b0dc07fe25423609dcd14441a9f2613e") (:authors ("Sibi Prabakaran")) (:maintainer "Sibi Prabakaran") (:keywords "just" "justfile" "tools" "processes") (:url . "https://github.com/psibi/justl.el"))]) (jvm-mode . [(20150422 708) ((dash (2 6 0)) (emacs (24))) "Monitor and manage your JVMs" single ((:commit . "3355dbaf5b0185aadfbad24160399abb32c5bea0") (:authors ("Martin Trojer" . "martin.trojer@gmail.com")) (:maintainer "Martin Trojer" . "martin.trojer@gmail.com") (:keywords "convenience") (:url . "https://github.com/martintrojer/jvm-mode.el"))]) (k8s-mode . [(20230305 1039) ((emacs (24 3)) (yaml-mode (0 0 10))) "Major mode for Kubernetes configuration file" tar ((:commit . "83266cecd6a39cdf57d124270646047860bfb7ab") (:authors ("Giap Tran" . "txgvnn@gmail.com")) (:maintainer "Giap Tran" . "txgvnn@gmail.com") (:url . "https://github.com/TxGVNN/emacs-k8s-mode"))]) - (kaesar . [(20230212 743) ((emacs (24 3))) "AES algorithm encrypt/decrypt" single ((:commit . "d62b18e888d69d27b0b74cf47224a1ac204dfb0b") (:authors ("Masahiro Hayashi" . "mhayashi1120@gmail.com")) (:maintainer "Masahiro Hayashi" . "mhayashi1120@gmail.com") (:keywords "data") (:url . "https://github.com/mhayashi1120/Emacs-kaesar"))]) - (kaesar-file . [(20230212 743) ((emacs (24 3)) (kaesar (0 1 1))) "AES encrypt/decrypt file" single ((:commit . "d62b18e888d69d27b0b74cf47224a1ac204dfb0b") (:authors ("Masahiro Hayashi" . "mhayashi1120@gmail.com")) (:maintainer "Masahiro Hayashi" . "mhayashi1120@gmail.com") (:keywords "data" "files") (:url . "https://github.com/mhayashi1120/Emacs-kaesar"))]) - (kaesar-mode . [(20230212 755) ((emacs (24 3)) (kaesar (0 1 4))) "AES encrypt/decrypt buffer" single ((:commit . "48b7160a817cb1e430726e1d2243d921c3f0508f") (:authors ("Masahiro Hayashi" . "mhayashi1120@gmail.com")) (:maintainer "Masahiro Hayashi" . "mhayashi1120@gmail.com") (:keywords "data" "convenience") (:url . "https://github.com/mhayashi1120/Emacs-kaesar"))]) + (kaesar . [(20230221 108) ((emacs (24 3)) (kaesar-pbkdf2 (0 9 0))) "AES algorithm encrypt/decrypt" single ((:commit . "75655238e0dcdb77a74d685cc4f3368fcd284020") (:authors ("Masahiro Hayashi" . "mhayashi1120@gmail.com")) (:maintainer "Masahiro Hayashi" . "mhayashi1120@gmail.com") (:keywords "data") (:url . "https://github.com/mhayashi1120/Emacs-kaesar"))]) + (kaesar-file . [(20230221 108) ((emacs (24 3)) (kaesar (0 1 1))) "AES encrypt/decrypt file" single ((:commit . "75655238e0dcdb77a74d685cc4f3368fcd284020") (:authors ("Masahiro Hayashi" . "mhayashi1120@gmail.com")) (:maintainer "Masahiro Hayashi" . "mhayashi1120@gmail.com") (:keywords "data" "files") (:url . "https://github.com/mhayashi1120/Emacs-kaesar"))]) + (kaesar-mode . [(20230221 108) ((emacs (24 3)) (kaesar (0 1 4))) "AES encrypt/decrypt buffer" single ((:commit . "75655238e0dcdb77a74d685cc4f3368fcd284020") (:authors ("Masahiro Hayashi" . "mhayashi1120@gmail.com")) (:maintainer "Masahiro Hayashi" . "mhayashi1120@gmail.com") (:keywords "data" "convenience") (:url . "https://github.com/mhayashi1120/Emacs-kaesar"))]) (kakapo-mode . [(20171004 451) ((cl-lib (0 5))) "TABS (hard or soft) for indentation (leading whitespace), and SPACES for alignment." single ((:commit . "67d516138172fd60782df94454b3d0bd247e84f3") (:keywords "indentation") (:url . "https://github.com/listx/kakapo-mode"))]) (kakoune . [(20230206 2037) ((ryo-modal (0 45)) (multiple-cursors (1 4)) (expand-region (0 11 0)) (emacs (25 1))) "A simulation, but not emulation, of kakoune" tar ((:commit . "b39c5605e896c55ea246f755c46171bd6d0768a8") (:authors ("Joseph Morag" . "jm4157@columbia.edu")) (:maintainer "Joseph Morag" . "jm4157@columbia.edu") (:url . "https://github.com/jmorag/kakoune.el"))]) (kaleidoscope . [(20170808 817) ((s (1 11 0))) "Controlling Kaleidoscope-powered devices." single ((:commit . "b89a243f6024099192f1bc38d8a54e3e7a654090") (:authors ("Gergely Nagy")) (:maintainer "Gergely Nagy") (:url . "https://github.com/algernon/kaleidoscope.el"))]) (kaleidoscope-evil-state-flash . [(20170728 1020) ((evil (1 2 12)) (kaleidoscope (0 1 0)) (s (1 11 0))) "Flash keyboard LEDs when changing Evil state" single ((:commit . "5b88327350c3d6375ef1d43fb31342eaabd88fdc") (:authors ("Gergely Nagy")) (:maintainer "Gergely Nagy") (:url . "https://github.com/algernon/kaleidoscope.el"))]) (kana . [(20210531 1427) ((emacs (24 4)) (dash (2 17 0))) "Learn Japanese hiragana and katakana" single ((:commit . "d3d550aad67ef8625b3860598bf3622f5b2a7d32") (:authors ("Damon Chan" . "elecming@gmail.com")) (:maintainer "Damon Chan" . "elecming@gmail.com") (:keywords "tools") (:url . "https://github.com/chenyanming/kana"))]) - (kanban . [(20230206 2131) nil "Parse org-todo headlines to use org-tables as Kanban tables" single ((:commit . "9b588f94efb5a784c9bc10ad66f424b253c5fe5e") (:authors ("Arne Babenhauserheide" . "arne_bab@web.de")) (:maintainer "Arne Babenhauserheide" . "arne_bab@web.de") (:keywords "outlines" "convenience"))]) + (kanban . [(20230210 1505) nil "Parse org-todo headlines to use org-tables as Kanban tables" single ((:commit . "d70fa7acab2bfcbb7d3da43c1343073f7eff4998") (:authors ("Arne Babenhauserheide" . "arne_bab@web.de")) (:maintainer "Arne Babenhauserheide" . "arne_bab@web.de") (:keywords "outlines" "convenience"))]) (kanji-mode . [(20160826 1139) nil "View stroke order for kanji characters at cursor" tar ((:commit . "5e9d5b72468ece11cfb81b729be6babf63ede425") (:authors ("Wojciech Gac" . "wojciech.s.gac@gmail.com")) (:maintainer "Wojciech Gac" . "wojciech.s.gac@gmail.com") (:url . "http://github.com/wsgac/kanji-mode "))]) (kaocha-runner . [(20190904 1950) ((emacs (26)) (s (1 4 0)) (cider (0 21 0)) (parseedn (0 1 0))) "A package for running Kaocha tests via CIDER." single ((:commit . "c4ec9cdc817e5f4c3f8d6013e44ea2df8f3eb07f") (:authors ("Magnar Sveen" . "magnars@gmail.com")) (:maintainer "Magnar Sveen" . "magnars@gmail.com") (:url . "https://github.com/magnars/kaocha-runner.el"))]) - (kaolin-themes . [(20230313 1916) ((emacs (25 1)) (autothemer (0 2 2)) (cl-lib (0 6))) "A set of eye pleasing themes" tar ((:commit . "674435c66a6540f01618c34db7ea18cc087021fb") (:authors ("Ogden Webb" . "ogdenwebb@gmail.com")) (:maintainer "Ogden Webb" . "ogdenwebb@gmail.com") (:keywords "dark" "light" "teal" "blue" "violet" "purple" "brown" "theme" "faces") (:url . "https://github.com/ogdenwebb/emacs-kaolin-themes"))]) + (kaolin-themes . [(20230402 1851) ((emacs (25 1)) (autothemer (0 2 2)) (cl-lib (0 6))) "A set of eye pleasing themes" tar ((:commit . "facb2a08d3179103d4c3a9905b37c87831fe1665") (:authors ("Ogden Webb" . "ogdenwebb@gmail.com")) (:maintainer "Ogden Webb" . "ogdenwebb@gmail.com") (:keywords "dark" "light" "teal" "blue" "violet" "purple" "brown" "theme" "faces") (:url . "https://github.com/ogdenwebb/emacs-kaolin-themes"))]) (kaomoji . [(20220721 441) ((emacs (24 3)) (helm-core (3 6 0))) "Input kaomoji superb easily" tar ((:commit . "fba0018a13eba70c2bffc6153dcfee99937fa3d6") (:authors ("Ono Hiroko" . "azazabc123@gmail.com")) (:maintainer "Ono Hiroko" . "azazabc123@gmail.com") (:keywords "tools" "fun") (:url . "https://github.com/kuanyui/kaomoji.el"))]) (kapacitor . [(20190414 1908) ((emacs (25 1)) (magit (2 13 0)) (magit-popup (2 12 4))) "Main file for kapacitor-mode" single ((:commit . "e3300d8b4017a2f66b0d929cb85bcc7ee2612072") (:authors ("Manoj Kumar Manikchand" . "manojm.321@gmail.com")) (:maintainer "Manoj Kumar Manikchand" . "manojm.321@gmail.com") (:keywords "kapacitor" "emacs" "magit" "tools") (:url . "http://github.com/Manoj321/kapacitor-el"))]) (karma . [(20160220 1245) ((pkg-info (0 4)) (emacs (24))) "Karma Test Runner Emacs Integration" single ((:commit . "31d3e7708246183d7ed0686be92bf23140af348c") (:authors ("Samuel Tonini")) (:maintainer "Samuel Tonini") (:keywords "language" "javascript" "js" "karma" "testing") (:url . "http://github.com/tonini/karma.el"))]) @@ -2743,11 +2746,11 @@ (keepass-mode . [(20211030 958) ((emacs (27))) "Mode for KeePass DB." tar ((:commit . "f432bb60f9f3bd027025140d723906dcabeefaef") (:authors ("Ignasi Fosch" . "natx@y10k.ws")) (:maintainer "Ignasi Fosch" . "natx@y10k.ws") (:keywords "data" "files" "tools") (:url . "https://github.com/ifosch/keepass-mode"))]) (keg . [(20220923 958) ((emacs (24 1))) "Modern Elisp package development system" tar ((:commit . "7fbfd987d35e29eaab2ebad4f0ed6ee2e2adfe28") (:authors ("Naoya Yamashita" . "conao3@gmail.com")) (:maintainer "Naoya Yamashita" . "conao3@gmail.com") (:keywords "convenience") (:url . "https://github.com/conao3/keg.el"))]) (keg-mode . [(20220307 829) ((emacs (24 4))) "Major mode for editing Keg files" single ((:commit . "d2ef9cfaee1256849291cfade3d730667f55aaf2") (:authors ("Naoya Yamashita" . "conao3@gmail.com")) (:maintainer "Naoya Yamashita" . "conao3@gmail.com") (:keywords "convenience") (:url . "https://github.com/conao3/keg.el"))]) - (kele . [(20230319 1613) ((emacs (28 1)) (async (1 9 7)) (dash (2 19 1)) (f (0 20 0)) (ht (2 3)) (plz (0 3)) (s (1 13 0)) (yaml (0 5 1))) "Spritzy Kubernetes cluster management" single ((:commit . "cb2c1a8279815358d96d3757b6fa4917b76b0735") (:authors ("Jonathan Jin" . "me@jonathanj.in")) (:maintainer "Jonathan Jin" . "me@jonathanj.in") (:keywords "kubernetes" "tools") (:url . "https://github.com/jinnovation/kele.el"))]) + (kele . [(20230326 33) ((emacs (28 1)) (async (1 9 7)) (dash (2 19 1)) (f (0 20 0)) (ht (2 3)) (plz (0 4)) (s (1 13 0)) (yaml (0 5 1))) "Spritzy Kubernetes cluster management" single ((:commit . "15e841fb7bbc08545534e466ce831d6e80fd8901") (:authors ("Jonathan Jin" . "me@jonathanj.in")) (:maintainer "Jonathan Jin" . "me@jonathanj.in") (:keywords "kubernetes" "tools") (:url . "https://github.com/jinnovation/kele.el"))]) (kerl . [(20150424 2005) nil "Emacs integration for kerl" single ((:commit . "1732ee26213f021bf040919c45ad276aafcaae14") (:authors ("Correl Roush" . "correl@gmail.com")) (:maintainer "Correl Roush" . "correl@gmail.com") (:keywords "tools") (:url . "http://github.com/correl/kerl.el/"))]) (key-assist . [(20230122 718) ((emacs (24 3))) "Minibuffer keybinding cheatsheet and launcher" single ((:commit . "41a958ca6b038586bfdcf01045bb8b9d379248fe") (:authors ("Boruch Baum" . "boruch_baum@gmx.com")) (:maintainer "Boruch Baum" . "boruch_baum@gmx.com") (:keywords "abbrev" "convenience" "docs" "help") (:url . "https://github.com/Boruch-Baum/emacs-key-assist"))]) (key-chord . [(20201222 2030) ((emacs (24))) "map pairs of simultaneously pressed keys to commands" single ((:commit . "7f7fd7c5bd2b996fa054779357e1566f7989e07d") (:authors ("David Andersson ")) (:maintainer "David Andersson ") (:keywords "keyboard" "chord" "input"))]) - (key-combo . [(20150324 1439) nil "map key sequence to commands" single ((:commit . "09a917bdfd3b309b4b3cbe3b11212e1ae6fab38d") (:authors ("Yuuki Arisawa" . "yuuki.ari@gmail.com")) (:maintainer "Vitalie Spinu" . "spinuvit@gmail.com") (:keywords "keyboard" "input") (:url . "https://github.com/uk-ar/key-combo"))]) + (key-combo . [(20230323 829) nil "map key sequence to commands" single ((:commit . "16fb73522d53547ef38f3710aff7c0b01005d576") (:authors ("Yuuki Arisawa" . "yuuki.ari@gmail.com")) (:maintainer "Vitalie Spinu" . "spinuvit@gmail.com") (:keywords "keyboard" "input") (:url . "https://github.com/uk-ar/key-combo"))]) (key-intercept . [(20140211 749) nil "Intercept prefix keys" single ((:commit . "d9a60edb4ce893f2d3d94f242164fdcc62d43cf2") (:authors ("INA Lintaro ")) (:maintainer "INA Lintaro ") (:keywords "keyboard") (:url . "http://github.com/tarao/key-intercept-el"))]) (key-leap . [(20160831 1447) ((emacs (24 3))) "Leap between lines by typing keywords" single ((:commit . "b3f6ef15c8a13870475d5af159fa24b30f97dea0") (:authors ("Martin Rykfors" . "martinrykfors@gmail.com")) (:maintainer "Martin Rykfors" . "martinrykfors@gmail.com") (:keywords "point" "convenience") (:url . "https://github.com/MartinRykfors/key-leap"))]) (key-quiz . [(20200226 2129) ((emacs (26))) "Emacs Keys Quiz" single ((:commit . "1ee67f3f8977d95785e021f7896685de1979137e") (:authors ("Federico Tedin" . "federicotedin@gmail.com")) (:maintainer "Federico Tedin" . "federicotedin@gmail.com") (:keywords "games") (:url . "https://github.com/federicotdn/key-quiz"))]) @@ -2767,7 +2770,7 @@ (kfg . [(20140909 538) ((f (0 17 1))) "an emacs configuration system" single ((:commit . "ffc35b77f227d4c64a1271ec30d31333ffeb0013") (:authors ("Austin Bingham" . "austin.bingham@gmail.com")) (:maintainer "Austin Bingham" . "austin.bingham@gmail.com") (:url . "https://github.com/abingham/kfg"))]) (khalel . [(20230122 1139) ((emacs (27 1))) "Import, edit and create calendar events through khal" tar ((:commit . "fbd4b4d6ae8f152140674e843ed7d82d223d52fe") (:authors ("Hanno Perrey ")) (:maintainer "Hanno Perrey" . "hanno@hoowl.se") (:keywords "event" "calendar" "ics" "khal") (:url . "https://gitlab.com/hperrey/khalel"))]) (khardel . [(20220223 934) ((emacs (27 1)) (yaml-mode (0 0 13))) "Integrate with khard" tar ((:commit . "1436ec5ef1b5b26104a4735ee64c0afe148700de") (:authors ("Damien Cassou" . "damien@cassou.me")) (:maintainer "Damien Cassou" . "damien@cassou.me") (:url . "https://github.com/DamienCassou/khardel"))]) - (khoj . [(20230310 2123) ((emacs (27 1)) (transient (0 3 0))) "Natural, Incremental Search for your Second Brain" single ((:commit . "8bb8824d0c4cb4de3c9dc936db7ca512726cdd6b") (:authors ("Debanjum Singh Solanky" . "debanjum@gmail.com")) (:maintainer "Debanjum Singh Solanky" . "debanjum@gmail.com") (:keywords "search" "org-mode" "outlines" "markdown" "beancount" "ledger" "image") (:url . "https://github.com/debanjum/khoj/tree/master/src/interface/emacs"))]) + (khoj . [(20230331 1113) ((emacs (27 1)) (transient (0 3 0)) (dash (2 19 1))) "A search assistant for your second brain" single ((:commit . "35aa06067fb2b35ac79344f1af407fcc6b34083d") (:authors ("Debanjum Singh Solanky" . "debanjum@gmail.com")) (:maintainer "Debanjum Singh Solanky" . "debanjum@gmail.com") (:keywords "search" "chat" "org-mode" "outlines" "markdown" "beancount" "image") (:url . "https://github.com/debanjum/khoj/tree/master/src/interface/emacs"))]) (kibit-helper . [(20150508 1533) ((s (0 8)) (emacs (24))) "Conveniently use the Kibit Leiningen plugin from Emacs" single ((:commit . "ec5f154db3bb0c838e86f527353f08644cede926") (:authors ("Jonas Enlund") ("James Elliott" . "james@brunchboy.com")) (:maintainer "Jonas Enlund") (:keywords "languages" "clojure" "kibit") (:url . "http://www.github.com/brunchboy/kibit-helper"))]) (kill-file-path . [(20230306 1041) ((emacs (26))) "Copy file name into kill ring" single ((:commit . "5dcbce69cbae17665216a32dd20f27de54c62972") (:authors ("Adam Chyła" . "adam@chyla.org")) (:maintainer "Adam Chyła" . "adam@chyla.org") (:keywords "files") (:url . "https://github.com/chyla/kill-file-path/kill-file-path.el"))]) (kill-or-bury-alive . [(20210320 1231) ((emacs (24 4)) (cl-lib (0 5))) "Precise control over buffer killing in Emacs" single ((:commit . "388067e764bf3922234196e2e9dd9e8f664c634d") (:authors ("Mark Karpov" . "markkarpov92@gmail.com")) (:maintainer "Mark Karpov" . "markkarpov92@gmail.com") (:keywords "buffer" "killing" "convenience") (:url . "https://github.com/mrkkrp/kill-or-bury-alive"))]) @@ -2778,7 +2781,7 @@ (kivy-mode . [(20220306 810) nil "Emacs major mode for editing Kivy files" single ((:commit . "023bd79b90f9831b45bb8eb449346648aa5fe5f8") (:authors ("Dean Serenevy" . "dean@serenevy.net")) (:maintainer "Dean Serenevy" . "dean@serenevy.net"))]) (kiwix . [(20220316 847) ((emacs (25 1)) (request (0 3 0))) "Searching offline Wikipedia through Kiwix." tar ((:commit . "444f686a7f75db788d54f544b923a3532732eb8b") (:authors ("stardiviner" . "numbchild@gmail.com")) (:maintainer "stardiviner" . "numbchild@gmail.com") (:keywords "kiwix" "wikipedia") (:url . "https://repo.or.cz/kiwix.el.git"))]) (kixtart-mode . [(20150611 1604) ((emacs (24))) "major mode for Kixtart scripting files" single ((:commit . "1c2356797e7b766bbaaa2b341176a8b10499cd79") (:authors ("Ryrun ")) (:maintainer "Ryrun ") (:keywords "languages") (:url . "https://github.com/ryrun/kixtart-mode"))]) - (kkp . [(20230309 1602) ((emacs (27 1)) (compat (29 1 3 4))) "Enable support for the Kitty Keyboard Protocol" single ((:commit . "0d35568de8b21c4d3525a50ff3d5d36cac28c185") (:authors ("Benjamin Orthen" . "contact@orthen.net")) (:maintainer "Benjamin Orthen" . "contact@orthen.net") (:keywords "terminals") (:url . "https://github.com/benjaminor/kkp"))]) + (kkp . [(20230403 2156) ((emacs (27 1)) (compat (29 1 3 4))) "Enable support for the Kitty Keyboard Protocol" single ((:commit . "5652ba0bfa7a4c03daffc301c9ca4a9899c4f440") (:authors ("Benjamin Orthen" . "contact@orthen.net")) (:maintainer "Benjamin Orthen" . "contact@orthen.net") (:keywords "terminals") (:url . "https://github.com/benjaminor/kkp"))]) (klere-theme . [(20230214 213) ((emacs (24))) "A dark theme with lambent color highlights and incremental grays" single ((:commit . "61d2cd649a1cf57ce61063f76b395f21f358372e") (:authors ("Wamm K. D." . "jaft.r@outlook.com")) (:maintainer "Wamm K. D." . "jaft.r@outlook.com") (:url . "https://codeberg.org/WammKD/emacs-klere-theme"))]) (kmacro-x . [(20230313 1051) ((emacs (27 2))) "Keyboard macro helpers and extensions" tar ((:commit . "da76f841776c26f59e31ab17bc942a0b34a18292") (:authors ("Wojciech Siewierski")) (:maintainer "Wojciech Siewierski") (:keywords "convenience") (:url . "https://github.com/vifon/kmacro-x.el"))]) (know-your-http-well . [(20160208 2305) nil "Look up the meaning of HTTP headers, methods, relations, status codes" tar ((:commit . "c381a9735f3ea86ebc9667e35cdfeab0b67fefb7"))]) @@ -2805,7 +2808,7 @@ (kuronami-theme . [(20220602 339) ((emacs (24 1))) "A deep blue theme with cool autumnal colors" single ((:commit . "a51d5ff3883bd94d0a181bb5d60f747190eda4f6") (:authors ("Eric Chung <>")) (:maintainer "Eric Chung <>") (:url . "https://github.com/inj0h/kuronami"))]) (kv . [(20140108 1534) nil "key/value data structure functions" single ((:commit . "721148475bce38a70e0b678ba8aa923652e8900e") (:authors ("Nic Ferrier" . "nferrier@ferrier.me.uk")) (:maintainer "Nic Ferrier" . "nferrier@ferrier.me.uk") (:keywords "lisp"))]) (kwin . [(20220120 2125) nil "communicatewith the KWin window manager" single ((:commit . "20fac6508e5535a26df783ba05f04d1800b7382c") (:authors ("Simon Hafner")) (:maintainer "Simon Hafner") (:url . "http://github.com/reactormonk/kwin-minor-mode"))]) - (laas . [(20230302 1345) ((emacs (26 3)) (auctex (11 88)) (aas (1 1))) "A bundle of as-you-type LaTeX snippets" tar ((:commit . "7f4044918c4e0a9b71128f36f65f1d86842203f9") (:maintainer "Yoav Marco" . "yoavm448@gmail.com") (:keywords "tools" "tex") (:url . "https://github.com/tecosaur/LaTeX-auto-activating-snippets"))]) + (laas . [(20230331 1806) ((emacs (26 3)) (auctex (11 88)) (aas (1 1))) "A bundle of as-you-type LaTeX snippets" tar ((:commit . "a00f0aba237b85b3e5fd60cf84de5759d1bf5d48") (:maintainer "Yoav Marco" . "yoavm448@gmail.com") (:keywords "tools" "tex") (:url . "https://github.com/tecosaur/LaTeX-auto-activating-snippets"))]) (lab-themes . [(20200815 2104) ((emacs (24))) "A custom theme carefully constructed in the LAB space" tar ((:commit . "9d7deb9635959d3a50ccb1082eb1207275f4b3e8") (:authors ("MetroWind" . "chris.corsair@gmail.com")) (:maintainer "MetroWind" . "chris.corsair@gmail.com") (:keywords "lisp") (:url . "https://github.com/MetroWind/lab-theme"))]) (labburn-theme . [(20221208 1611) nil "A lab color space zenburn theme." single ((:commit . "bd0de2fdcf285d981f32e3e5ebc56fe3c9b589a5") (:authors ("Johannes Goslar")) (:maintainer "Johannes Goslar") (:keywords "theme" "zenburn") (:url . "https://github.com/ksjogo/labburn-theme"))]) (lacquer . [(20230206 756) ((emacs (25 2))) "Switch theme/font by selecting from a cache" tar ((:commit . "8a4e7dc1827862ad025f2af5354ca377cc660939") (:authors ("zakudriver" . "zy.hua1122@gmail.com")) (:maintainer "zakudriver" . "zy.hua1122@gmail.com") (:keywords "tools") (:url . "https://github.com/zakudriver/lacquer"))]) @@ -2819,8 +2822,8 @@ (langtool-popup . [(20230222 401) ((emacs (25 1)) (popup (0 5 9))) "Popup message extension for langtool.el" single ((:commit . "d86101eafe9a994eb0425e08e7c1795e9cb0cd42") (:authors ("Masahiro Hayashi" . "mhayashi1120@gmail.com")) (:maintainer "Masahiro Hayashi" . "mhayashi1120@gmail.com") (:keywords "docs") (:url . "https://github.com/mhayashi1120/Emacs-langtool"))]) (language-detection . [(20161123 1813) ((emacs (24)) (cl-lib (0 5))) "Automatic language detection from code snippets" single ((:commit . "38f5d294870678efc6ccf94ce6e8175a58f93025") (:authors ("Andreas Jansson" . "andreas@jansson.me.uk")) (:maintainer "Andreas Jansson" . "andreas@jansson.me.uk") (:url . "https://github.com/andreasjansson/language-detection.el"))]) (language-id . [(20230214 710) ((emacs (24 3))) "Library to work with programming language identifiers" single ((:commit . "302533245972d9bc7722328742247d2b2b225e01") (:authors ("Lassi Kortela" . "lassi@lassi.io")) (:maintainer "Lassi Kortela" . "lassi@lassi.io") (:keywords "languages" "util") (:url . "https://github.com/lassik/emacs-language-id"))]) - (languagetool . [(20230122 121) ((emacs (27 0))) "LanguageTool integration for grammar and spell check" tar ((:commit . "57af28a0c370866945988461a259b6551a1c4074") (:authors ("Joar Buitrago" . "jebuitragoc@unal.edu.co")) (:maintainer "Joar Buitrago" . "jebuitragoc@unal.edu.co") (:keywords "grammar" "text" "docs" "tools" "convenience" "checker") (:url . "https://github.com/PillFall/Emacs-LanguageTool.el"))]) - (lark-mode . [(20230313 1851) ((emacs (24 3))) "Major mode for editing Lark parser code" single ((:commit . "8f5dcb26c38b5c6417001327189f0c71f8163afd") (:authors ("Ta Quang Trung")) (:maintainer "Ta Quang Trung") (:keywords "languages") (:url . "https://github.com/taquangtrung/lark-mode"))]) + (languagetool . [(20230325 507) ((emacs (27 1))) "LanguageTool integration for grammar and spell check" tar ((:commit . "b136d531129eb488dc4134784e34c4afedcb0c2f") (:authors ("Joar Buitrago" . "jebuitragoc@unal.edu.co")) (:maintainer "Joar Buitrago" . "jebuitragoc@unal.edu.co") (:keywords "grammar" "text" "docs" "tools" "convenience" "checker") (:url . "https://github.com/PillFall/Emacs-LanguageTool.el"))]) + (lark-mode . [(20230327 1003) ((emacs (24 3))) "Major mode for editing Lark parser code" single ((:commit . "9e19b40df29d273cf3aec9ddd0e739d3b3d9b3a8") (:authors ("Ta Quang Trung")) (:maintainer "Ta Quang Trung") (:keywords "languages") (:url . "https://github.com/taquangtrung/lark-mode"))]) (lastfm . [(20211018 838) ((emacs (26 1)) (request (0 3 0)) (anaphora (1 0 4)) (memoize (1 1)) (elquery (0 1 0)) (s (1 12 0))) "Last.fm API for Emacs Lisp" single ((:commit . "b4b19f0aadc5087febeeb3f59944a89c4cdcf325") (:authors ("Mihai Olteanu" . "mihai_olteanu@fastmail.fm")) (:maintainer "Mihai Olteanu" . "mihai_olteanu@fastmail.fm") (:keywords "multimedia" "api") (:url . "https://github.com/mihaiolteanu/lastfm.el/"))]) (lastpass . [(20201229 2109) ((emacs (24 4)) (seq (1 9)) (cl-lib (0 5))) "LastPass command wrapper" single ((:commit . "2366de7824b6c5f8e9ec6811d219dc06794e8630") (:authors ("Petter Storvik")) (:maintainer "Petter Storvik") (:keywords "extensions" "processes" "lpass" "lastpass") (:url . "https://github.com/storvik/emacs-lastpass"))]) (latex-change-env . [(20230220 637) ((emacs (27 1)) (auctex (13 1))) "Change in and out of LaTeX environments" single ((:commit . "748cdbb4bbf29a2e5053cf3d965e95cc7db67fac") (:authors ("Tony Zorman" . "soliditsallgood@mailbox.org")) (:maintainer "Tony Zorman" . "soliditsallgood@mailbox.org") (:keywords "convenience" "tex") (:url . "https://gitlab.com/slotThe/change-env"))]) @@ -2831,6 +2834,7 @@ (latex-table-wizard . [(20230103 2241) ((emacs (27 1)) (auctex (12 1)) (transient (0 3 7))) "Magic editing of LaTeX tables" tar ((:commit . "61fb455a1e6a28b93512e63c609ca7ad7dd5bec5") (:authors ("Enrico Flor" . "enrico@eflor.net")) (:maintainer "Enrico Flor" . "enrico@eflor.net") (:keywords "convenience") (:url . "https://github.com/enricoflor/latex-table-wizard"))]) (latex-unicode-math-mode . [(20170123 1816) nil "Input method for Unicode math symbols" tar ((:commit . "e8931e68214ca94e6a04080ebc629693d5881884") (:authors ("Christoph Dittmann" . "github@christoph-d.de")) (:maintainer "Christoph Dittmann" . "github@christoph-d.de") (:url . "https://github.com/Christoph-D/latex-unicode-math-mode"))]) (latexdiff . [(20190827 1651) ((emacs (24 4))) "Latexdiff integration in Emacs" single ((:commit . "56d0b240867527d1b43d3ddec14059361929b971") (:authors ("Launay Gaby" . "gaby.launay@tutanota.com")) (:maintainer "Launay Gaby" . "gaby.launay@tutanota.com") (:keywords "tex" "vc" "tools" "git" "helm") (:url . "http://github.com/galaunay/latexdiff.el"))]) + (latvian-holidays . [(20230326 2030) nil "Latvian holidays for the calendar" single ((:commit . "6b82f3bd9682c97f19a65b7d359ce7a02ec9cfec") (:authors ("Alexander Shumilov" . "alexander.shumilov@me.com")) (:maintainer "Alexander Shumilov" . "alexander.shumilov@me.com") (:keywords "calendar") (:url . "https://github.com/ashumilov/latvian-holidays"))]) (launch . [(20130619 2204) nil "launch files with OS-standard associated applications." single ((:commit . "e7c3b573fc05fe4d3d322389079909311542e799") (:authors ("Simon Law" . "sfllaw@sfllaw.ca")) (:maintainer "Simon Law" . "sfllaw@sfllaw.ca") (:keywords "convenience" "processes") (:url . "https://github.com/sfllaw/emacs-launch"))]) (launch-mode . [(20170106 512) ((emacs (24 4))) "Major mode for launch-formatted text" tar ((:commit . "25ebd4ba77afcbe729901eb74923dbe9ae81c313") (:authors ("iory" . "ab.ioryz@gmail.com")) (:maintainer "iory" . "ab.ioryz@gmail.com") (:url . "https://github.com/iory/launch-mode"))]) (launchctl . [(20210611 2243) ((emacs (24 1))) "Interface to launchctl on Mac OS X." single ((:commit . "c9b7e93f5ec6fa504dfb03d60571cf3e5dc38e12") (:authors ("Peking Duck ")) (:maintainer "Peking Duck ") (:keywords "tools" "convenience") (:url . "http://github.com/pekingduck/launchctl-el"))]) @@ -2849,7 +2853,7 @@ (leanote . [(20161223 139) ((emacs (24 4)) (cl-lib (0 5)) (request (0 2)) (let-alist (1 0 3)) (pcache (0 4 0)) (s (1 10 0)) (async (1 9))) "A minor mode writing markdown leanote" single ((:commit . "d499e7b59bb1f1a2fabc0e4c26fb101ed62ebc7b") (:authors ("Aborn Jiang" . "aborn.jiang@gmail.com")) (:maintainer "Aborn Jiang" . "aborn.jiang@gmail.com") (:keywords "leanote" "note" "markdown") (:url . "https://github.com/aborn/leanote-emacs"))]) (learn-ocaml . [(20211003 1412) ((emacs (25 1))) "Emacs frontend for learn-ocaml" single ((:commit . "abdc263537a6a534152a4eaaa17b2c3e4e10418b") (:url . "https://github.com/pfitaxel/learn-ocaml.el"))]) (ledger-import . [(20210419 818) ((emacs (25 1)) (ledger-mode (3 1 1))) "Fetch OFX files from bank and push them to Ledger" single ((:commit . "f77adf79ce67524c3e08546448ac88ea1a665b64") (:authors ("Damien Cassou" . "damien@cassou.me")) (:maintainer "Damien Cassou" . "damien@cassou.me") (:url . "https://gitlab.petton.fr/mpdel/libmpdel"))]) - (ledger-mode . [(20230321 1334) ((emacs (25 1))) "Helper code for use with the \"ledger\" command-line tool" tar ((:commit . "4028ed7458e1c8c01be769c0153aa3b01189c851"))]) + (ledger-mode . [(20230404 855) ((emacs (25 1))) "Helper code for use with the \"ledger\" command-line tool" tar ((:commit . "e74fe9e84f278cedc3b9fc661c243ab5e1bbf434"))]) (leerzeichen . [(20220626 835) nil "Minor mode to display whitespace characters." single ((:commit . "9d4126d5f6563569080845a69b0867119a9fd6ea") (:authors ("Felix Geller" . "fgeller@gmail.com")) (:maintainer "Felix Geller" . "fgeller@gmail.com") (:keywords "whitespace" "characters") (:url . "http://github.com/fgeller/leerzeichen.el"))]) (leetcode . [(20220503 534) ((emacs (26 1)) (dash (2 16 0)) (graphql (0 1 1)) (spinner (1 7 3)) (aio (1 0)) (log4e (0 3 3))) "An leetcode client" single ((:commit . "682f7a44d0bea0daf6f9a2888fa7f905d3a0cd70") (:authors ("Wang Kai" . "kaiwkx@gmail.com")) (:maintainer "Wang Kai" . "kaiwkx@gmail.com") (:keywords "extensions" "tools") (:url . "https://github.com/kaiwk/leetcode.el"))]) (legalese . [(20200119 2248) nil "Add legalese to your program files" single ((:commit . "e465471d2d5a62d35073d93e0f8d40387a82e302") (:authors ("Jorgen Schaefer" . "forcer@forcix.cx")) (:maintainer "Jorgen Schaefer" . "forcer@forcix.cx") (:keywords "convenience") (:url . "https://github.com/jorgenschaefer/legalese"))]) @@ -2888,7 +2892,7 @@ (linguistic . [(20181129 2116) nil "A package for basic linguistic analysis." tar ((:commit . "23e47e98cdb09ee61883669b6d8a11bf6449862c") (:authors ("Andrew Favia ")) (:maintainer "Andrew Favia ") (:keywords "linguistics" "text analysis" "matching") (:url . "https://github.com/andcarnivorous/linguistic"))]) (lingva . [(20220910 1435) ((emacs (25 1))) "Access Google Translate without tracking via lingva.ml" single ((:commit . "6c33594068fa33de622172503deeec6778d9c744") (:authors ("marty hiatt ")) (:maintainer "marty hiatt ") (:keywords "convenience" "translation" "wp" "text") (:url . "https://codeberg.org/martianh/lingva.el"))]) (link . [(20191111 446) nil "Hypertext links in text buffers" single ((:commit . "c9cad101100975e88873636bfd426b7a19304ebd") (:authors ("Torsten Hilbrich" . "torsten.hilbrich@gmx.net")) (:maintainer "Torsten Hilbrich" . "torsten.hilbrich@gmx.net") (:keywords "interface" "hypermedia"))]) - (link-hint . [(20221008 1445) ((avy (0 4 0)) (emacs (24 4))) "Use avy to open, copy, etc. visible links" single ((:commit . "1f9bb60289d87f31f92b86ed22d1f2c0a7af0222") (:authors ("Fox Kiester" . "noct@posteo.net")) (:maintainer "Fox Kiester" . "noct@posteo.net") (:keywords "convenience" "url" "avy" "link" "links" "hyperlink") (:url . "https://github.com/noctuid/link-hint.el"))]) + (link-hint . [(20230405 1801) ((avy (0 4 0)) (emacs (24 4))) "Use avy to open, copy, etc. visible links" single ((:commit . "36ce929331f2838213bcaa1145ece4b73ce84afe") (:authors ("Fox Kiester" . "noct@posteo.net")) (:maintainer "Fox Kiester" . "noct@posteo.net") (:keywords "convenience" "url" "avy" "link" "links" "hyperlink") (:url . "https://github.com/noctuid/link-hint.el"))]) (linkode . [(20200607 2152) nil "Generate a linkode snippet with region/buffer content" single ((:commit . "e31bdae11ff38b736b1869fbe94920e862f29794") (:authors ("Erick Navarro" . "erick@navarro.io")) (:maintainer "Erick Navarro" . "erick@navarro.io") (:url . "https://github.com/erickgnavar/linkode.el"))]) (linphone . [(20130524 1109) nil "Emacs interface to Linphone" tar ((:commit . "99af3db941b7f4e5272bb48bff96c1ce4ceac302") (:authors ("Yoni Rabkin" . "yonirabkin@member.fsf.org")) (:maintainer "Yoni Rabkin" . "yonirabkin@member.fsf.org") (:keywords "comm") (:url . "https://github.com/zabbal/emacs-linphone"))]) (linum-off . [(20160217 2137) nil "Provides an interface for turning line-numbering off" single ((:commit . "3e37baaad27d27e405f8dfe01d4ab9cd5b591353") (:authors ("Matthew L. Fidler, Florian Adamsky (see wiki)")) (:maintainer "Matthew L. Fidler") (:keywords "line" "numbering") (:url . "http://www.emacswiki.org/emacs/auto-indent-mode.el "))]) @@ -2918,7 +2922,7 @@ (litex-mode . [(20221107 147) ((emacs (24 4)) (units-mode (0 1 1))) "Minor mode for converting lisp to LaTeX" tar ((:commit . "45004b3a865771799b739d17ebb7849190fffa63") (:authors ("Gaurav Atreya" . "allmanpride@gmail.com")) (:maintainer "Gaurav Atreya" . "allmanpride@gmail.com") (:keywords "calculator" "lisp" "latex") (:url . "https://github.com/Atreyagaurav/litex-mode"))]) (live-code-talks . [(20180907 1647) ((emacs (24)) (cl-lib (0 5)) (narrowed-page-navigation (0 1))) "Support for slides with live code in them" single ((:commit . "97f16a9ee4e6ff3e0f9291eaead772c66e3e12ae") (:authors ("David Raymond Christiansen" . "david@davidchristiansen.dk")) (:maintainer "David Raymond Christiansen" . "david@davidchristiansen.dk") (:keywords "docs" "multimedia"))]) (live-preview . [(20201010 1948) ((emacs (24 4))) "Live preview by any shell command while editing" single ((:commit . "603a4a1759fbec92e7a1cabc249517c78e59ce7e") (:authors ("Lassi Kortela" . "lassi@lassi.io")) (:maintainer "Lassi Kortela" . "lassi@lassi.io") (:keywords "languages" "util") (:url . "https://github.com/lassik/emacs-live-preview"))]) - (live-py-mode . [(20230320 2347) ((emacs (24 3))) "Live Coding in Python" tar ((:commit . "f56343b3dc68aaeb4f9d2bdb48509750cdaa2fcf") (:authors ("Don Kirkby http://donkirkby.github.io")) (:maintainer "Don Kirkby http://donkirkby.github.io") (:keywords "live" "coding") (:url . "http://donkirkby.github.io/live-py-plugin/"))]) + (live-py-mode . [(20230330 58) ((emacs (24 3))) "Live Coding in Python" tar ((:commit . "4ea88695df456108adf37a547884cb37ea55438c") (:authors ("Don Kirkby http://donkirkby.github.io")) (:maintainer "Don Kirkby http://donkirkby.github.io") (:keywords "live" "coding") (:url . "http://donkirkby.github.io/live-py-plugin/"))]) (lively . [(20171005 754) nil "interactively updating text" single ((:commit . "348675828c6a81bfa1ac311ca465aad813542c1b") (:authors ("Luke Gorrie" . "luke@bup.co.nz")) (:maintainer "Steve Purcell" . "steve@sanityinc.com"))]) (livereload . [(20170629 650) ((emacs (25)) (websocket (1 8))) "Livereload server" tar ((:commit . "1e501d7e46dbd476c2c7cc9d20b5ac9d41fb1955") (:authors ("João Távora" . "joaotavora@gmail.com")) (:maintainer "João Távora" . "joaotavora@gmail.com") (:keywords "convenience"))]) (livescript-mode . [(20221015 1316) ((emacs (24 3))) "Major mode for editing LiveScript files" single ((:commit . "e71a82a400e9d451c966c397bb8fa7887d35637b") (:authors ("Hisamatsu Yasuyuki" . "yas@null.net")) (:maintainer "Hisamatsu Yasuyuki" . "yas@null.net") (:keywords "languages" "livescript") (:url . "https://github.com/yhisamatsu/livescript-mode"))]) @@ -2969,8 +2973,8 @@ (lsp-julia . [(20211229 1534) ((emacs (25 1)) (lsp-mode (6 3)) (julia-mode (0 3))) "Julia support for lsp-mode" tar ((:commit . "e6ff5c09eb73c9b376bfbbd94f47c0366a01cf44") (:authors ("Martin Wolke" . "vibhavp@gmail.com") ("Adam Beckmeyer" . "adam_git@thebeckmeyers.xyz") ("Guido Kraemer" . "gdkrmr@users.noreply.github.com")) (:maintainer "Guido Kraemer" . "gdkrmr@users.noreply.github.com") (:keywords "languages" "tools") (:url . "https://github.com/gdkrmr/lsp-julia"))]) (lsp-latex . [(20230316 1906) ((emacs (26 3)) (lsp-mode (6 0))) "LSP-mode client for LaTeX, on texlab" single ((:commit . "4f3d7166aeda16099d226066928d89bb44849624") (:authors ("ROCKTAKEY" . "rocktakey@gmail.com")) (:maintainer "ROCKTAKEY" . "rocktakey@gmail.com") (:keywords "languages" "tex") (:url . "https://github.com/ROCKTAKEY/lsp-latex"))]) (lsp-ltex . [(20221231 1658) ((emacs (27 1)) (lsp-mode (6 1))) "LSP Clients for LTEX" single ((:commit . "d1a599c8ec3748c2b81899d5831b6e7158255479") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "lsp" "languagetool" "checker") (:url . "https://github.com/emacs-languagetool/lsp-ltex"))]) - (lsp-metals . [(20221102 1628) ((emacs (26 1)) (scala-mode (1 1)) (lsp-mode (7 0)) (lsp-treemacs (0 2)) (dap-mode (0 3)) (dash (2 18 0)) (f (0 20 0)) (ht (2 0)) (treemacs (2 5))) "Scala Client settings" tar ((:commit . "9a5c8b0e636e6796e5ce8ccea040a583856fb1f5") (:authors ("Ross A. Baker" . "ross@rossabaker.com") ("Evgeny Kurnevsky" . "kurnevsky@gmail.com")) (:maintainer "Ross A. Baker" . "ross@rossabaker.com") (:keywords "languages" "extensions") (:url . "https://github.com/emacs-lsp/lsp-metals"))]) - (lsp-mode . [(20230321 1042) ((emacs (26 3)) (dash (2 18 0)) (f (0 20 0)) (ht (2 3)) (spinner (1 7 3)) (markdown-mode (2 3)) (lv (0)) (eldoc (1 11))) "LSP mode" tar ((:commit . "586ec020d43351e14f3b1d63bf2a39db316fe98b") (:authors ("Vibhav Pant, Fangrui Song, Ivan Yonchovski")) (:maintainer "Vibhav Pant, Fangrui Song, Ivan Yonchovski") (:keywords "languages") (:url . "https://github.com/emacs-lsp/lsp-mode"))]) + (lsp-metals . [(20230406 755) ((emacs (26 1)) (scala-mode (1 1)) (lsp-mode (7 0)) (lsp-treemacs (0 2)) (dap-mode (0 3)) (dash (2 18 0)) (f (0 20 0)) (ht (2 0)) (treemacs (2 5)) (posframe (1 4 1))) "Scala Client settings" tar ((:commit . "a11099b79f032aa2fc92a727d2c1e40987727d65") (:authors ("Ross A. Baker" . "ross@rossabaker.com") ("Evgeny Kurnevsky" . "kurnevsky@gmail.com")) (:maintainer "Ross A. Baker" . "ross@rossabaker.com") (:keywords "languages" "extensions") (:url . "https://github.com/emacs-lsp/lsp-metals"))]) + (lsp-mode . [(20230401 434) ((emacs (26 3)) (dash (2 18 0)) (f (0 20 0)) (ht (2 3)) (spinner (1 7 3)) (markdown-mode (2 3)) (lv (0)) (eldoc (1 11))) "LSP mode" tar ((:commit . "955b2805b4e3488189da9230382de27f74d20290") (:authors ("Vibhav Pant, Fangrui Song, Ivan Yonchovski")) (:maintainer "Vibhav Pant, Fangrui Song, Ivan Yonchovski") (:keywords "languages") (:url . "https://github.com/emacs-lsp/lsp-mode"))]) (lsp-mssql . [(20230316 1612) ((emacs (25 1)) (lsp-mode (6 2)) (dash (2 14 1)) (f (0 20 0)) (ht (2 0)) (lsp-treemacs (0 1))) "MSSQL LSP bindings" tar ((:commit . "9d9a14a2b40c5fd13b8e33fccd397283a2437526") (:authors ("Ivan Yonchovski" . "yyoncho@gmail.com")) (:maintainer "Ivan Yonchovski" . "yyoncho@gmail.com") (:keywords "data" "languages") (:url . "https://github.com/emacs-lsp/lsp-mssql"))]) (lsp-origami . [(20211016 1045) ((origami (1 0)) (lsp-mode (6 1))) "origami.el support for lsp-mode" single ((:commit . "5b88ab77dc2696c93fa5dd9debe183821c533b71") (:authors ("Vibhav Pant")) (:maintainer "Vibhav Pant") (:keywords "languages" "lsp-mode") (:url . "https://github.com/emacs-lsp/lsp-origami"))]) (lsp-p4 . [(20190127 1049) ((lsp-mode (3 0))) "P4 support for lsp-mode" tar ((:commit . "084e33a5782f9153502d9b03e63d9cbbe81cdaeb") (:authors ("Dmitri Makarov")) (:maintainer "Dmitri Makarov") (:keywords "lsp" "p4") (:url . "https://github.com/dmakarov/p4ls"))]) @@ -2982,7 +2986,7 @@ (lsp-scheme . [(20221029 816) ((emacs (26 1)) (f (0 20 0)) (lsp-mode (8 0 0))) "Scheme support for lsp-mode" tar ((:commit . "447df67e0347a2f26101432066a8724b1f39446e") (:authors ("Ricardo G. Herdt" . "r.herdt@posteo.de")) (:maintainer "Ricardo G. Herdt" . "r.herdt@posteo.de") (:keywords "languages" "lisp" "tools") (:url . "https://codeberg.org/rgherdt/emacs-lsp-scheme"))]) (lsp-sonarlint . [(20220510 1802) ((emacs (25)) (dash (2 12 0)) (lsp-mode (6 3)) (ht (2 3))) "Emacs Sonarlint lsp client" tar ((:commit . "a429be2aea7797369a3c751ef54e3554733117be") (:authors ("Fermin MF" . "fmfs@posteo.net")) (:maintainer "Fermin MF" . "fmfs@posteo.net") (:keywords "languages" "tools" "php" "javascript" "xml" "ruby" "html" "scala" "java" "python") (:url . "https://github.com/emacs-lsp/lsp-sonarlint"))]) (lsp-sourcekit . [(20210905 2017) ((emacs (25 1)) (lsp-mode (5))) "sourcekit-lsp client for lsp-mode" single ((:commit . "97ff36b228a61e69734c7180f33cc6951b1a600f") (:authors ("Daniel Martín")) (:maintainer "Daniel Martín") (:keywords "languages" "lsp" "swift" "objective-c" "c++") (:url . "https://github.com/emacs-lsp/lsp-sourcekit"))]) - (lsp-tailwindcss . [(20230309 1037) ((lsp-mode (7 1)) (f (0 20 0)) (emacs (26 1))) "A lsp-mode client for tailwindcss" single ((:commit . "f03b8f6030be14d7876006ff67a01263c22ef082") (:authors ("A.I." . "merrick@luois.me")) (:maintainer "A.I." . "merrick@luois.me") (:keywords "language" "tools") (:url . "https://github.com/merrickluo/lsp-tailwindcss"))]) + (lsp-tailwindcss . [(20230407 951) ((lsp-mode (7 1)) (f (0 20 0)) (emacs (26 1))) "A lsp-mode client for tailwindcss" single ((:commit . "6ade9cacd1db89da0e9c0941a86408a42091d479") (:authors ("A.I." . "merrick@luois.me")) (:maintainer "A.I." . "merrick@luois.me") (:keywords "language" "tools") (:url . "https://github.com/merrickluo/lsp-tailwindcss"))]) (lsp-treemacs . [(20221001 1958) ((emacs (26 1)) (dash (2 18 0)) (f (0 20 0)) (ht (2 0)) (treemacs (2 5)) (lsp-mode (6 0))) "LSP treemacs" tar ((:commit . "2894e6dec583eaa77037627e9d8c3bc89cf7273d") (:authors ("Ivan Yonchovski")) (:maintainer "Ivan Yonchovski") (:keywords "languages") (:url . "https://github.com/emacs-lsp/lsp-treemacs"))]) (lsp-ui . [(20230116 2024) ((emacs (26 1)) (dash (2 18 0)) (lsp-mode (6 0)) (markdown-mode (2 3))) "UI modules for lsp-mode" tar ((:commit . "295d8984da06a745b0a36c56e28ce915bc389adb") (:authors ("Sebastien Chapuis , Fangrui Song" . "i@maskray.me")) (:maintainer "Sebastien Chapuis , Fangrui Song" . "i@maskray.me") (:keywords "languages" "tools") (:url . "https://github.com/emacs-lsp/lsp-ui"))]) (lua-mode . [(20221218 605) ((emacs (24 3))) "a major-mode for editing Lua scripts" single ((:commit . "ad639c62e38a110d8d822c4f914af3e20b40ccc4") (:authors ("2011-2013 immerrr" . "immerrr+lua@gmail.com") ("2010-2011 Reuben Thomas" . "rrt@sc3d.org") ("2006 Juergen Hoetzel" . "juergen@hoetzel.info") ("2004 various (support for Lua 5 and byte compilation)") ("2001 Christian Vogler" . "cvogler@gradient.cis.upenn.edu") ("1997 Bret Mogilefsky" . "mogul-lua@gelatinous.com") ("tcl-mode by Gregor Schmid" . "schmid@fb3-s7.math.tu-berlin.de") ("with tons of assistance from") ("Paul Du Bois" . "pld-lua@gelatinous.com") ("Aaron Smith" . "aaron-lua@gelatinous.com")) (:maintainer "2011-2013 immerrr" . "immerrr+lua@gmail.com") (:keywords "languages" "processes" "tools") (:url . "https://immerrr.github.io/lua-mode"))]) @@ -3009,8 +3013,8 @@ (magic-filetype . [(20180219 1552) ((emacs (24)) (s (1 9 0))) "Enhance filetype major mode" single ((:commit . "019494add5ff02dd36cb3f500142fc51125522cc") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "emulations" "vim" "ft" "file" "magic-mode") (:url . "https://github.com/zonuexe/magic-filetype.el"))]) (magic-latex-buffer . [(20210306 422) ((cl-lib (0 5)) (emacs (25 1))) "Magically enhance LaTeX-mode font-locking for semi-WYSIWYG editing" single ((:commit . "903ec91872760e47c0e5715795f8465173615098") (:authors ("zk_phi")) (:maintainer "zk_phi") (:url . "http://zk-phi.github.io/"))]) (magik-mode . [(20230103 1503) nil "mode for editing Magik + some utils." tar ((:commit . "a2ddc7cad487e6165c2e2ac26acec62b1f7bbeca") (:keywords "languages") (:url . "http://github.com/roadrunner1776/magik"))]) - (magit . [(20230319 2325) ((emacs (25 1)) (compat (29 1 3 4)) (dash (20221013)) (git-commit (20230101)) (magit-section (20230101)) (transient (20230201)) (with-editor (20230118))) "A Git porcelain inside Emacs." tar ((:commit . "a760dd107843a8fb632e647f6ba9ed34d7c2dd45") (:authors ("Marius Vollmer" . "marius.vollmer@gmail.com") ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "git" "tools" "vc") (:url . "https://github.com/magit/magit"))]) - (magit-annex . [(20230319 2103) ((cl-lib (0 3)) (magit (3 0 0))) "Control git-annex from Magit" single ((:commit . "f1bf48d79e51805a017e9c1501f4fb3698c3f310") (:authors ("Kyle Meyer" . "kyle@kyleam.com") ("Rémi Vanicat" . "vanicat@debian.org")) (:maintainer "Kyle Meyer" . "kyle@kyleam.com") (:keywords "vc" "tools") (:url . "https://github.com/magit/magit-annex"))]) + (magit . [(20230402 1342) ((emacs (25 1)) (compat (29 1 3 4)) (dash (20221013)) (git-commit (20230101)) (magit-section (20230101)) (transient (20230201)) (with-editor (20230118))) "A Git porcelain inside Emacs." tar ((:commit . "1abfb52886536f90f3561b18a49182ad21b6d8e8") (:authors ("Marius Vollmer" . "marius.vollmer@gmail.com") ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "git" "tools" "vc") (:url . "https://github.com/magit/magit"))]) + (magit-annex . [(20230407 1200) ((cl-lib (0 3)) (magit (3 0 0))) "Control git-annex from Magit" single ((:commit . "255e443e19a32e716ff414e09ad5e00f6f8bc8fb") (:authors ("Kyle Meyer" . "kyle@kyleam.com") ("Rémi Vanicat" . "vanicat@debian.org")) (:maintainer "Kyle Meyer" . "kyle@kyleam.com") (:keywords "vc" "tools") (:url . "https://github.com/magit/magit-annex"))]) (magit-commit-mark . [(20230214 1821) ((emacs (28 1)) (magit (3 3 0))) "Support marking commits as read" single ((:commit . "6ed61986ae28c01d0f8c4f2bcff8ab70707488df") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:url . "https://codeberg.org/ideasman42/emacs-magit-commit-mark"))]) (magit-delta . [(20220125 50) ((emacs (25 1)) (magit (20200426)) (xterm-color (2 0))) "Use Delta when displaying diffs in Magit" single ((:commit . "5fc7dbddcfacfe46d3fd876172ad02a9ab6ac616") (:authors ("Dan Davison" . "dandavison7@gmail.com")) (:maintainer "Dan Davison" . "dandavison7@gmail.com") (:url . "https://github.com/dandavison/magit-delta"))]) (magit-diff-flycheck . [(20190524 551) ((magit (2)) (flycheck (31)) (seq (2)) (emacs (25 1))) "Report errors in diffs" single ((:commit . "ad58efa312d708f25661dfcc2a7f83a833cca328") (:authors ("Alex Ragone" . "ragonedk@gmail.com")) (:maintainer "Alex Ragone" . "ragonedk@gmail.com") (:keywords "convenience" "matching") (:url . "https://github.com/ragone/magit-diff-flycheck"))]) @@ -3034,7 +3038,7 @@ (magit-tbdiff . [(20220527 2213) ((emacs (25 1)) (magit (3 0 0))) "Magit extension for range diffs" single ((:commit . "55e6443710def357f3f78eea27d5bbe023d868f5") (:authors ("Kyle Meyer" . "kyle@kyleam.com")) (:maintainer "Kyle Meyer" . "kyle@kyleam.com") (:keywords "vc" "tools") (:url . "https://github.com/magit/magit-tbdiff"))]) (magit-todos . [(20230307 549) ((emacs (26 1)) (async (1 9 2)) (dash (2 13 0)) (f (0 17 2)) (hl-todo (1 9 0)) (magit (2 13 0)) (pcre2el (1 8)) (s (1 12 0)) (transient (0 2 0))) "Show source file TODOs in Magit" single ((:commit . "7724259a008144b8cfc6cacdae3e764f207a03e7") (:authors ("Adam Porter" . "adam@alphapapa.net")) (:maintainer "Adam Porter" . "adam@alphapapa.net") (:keywords "magit" "vc") (:url . "http://github.com/alphapapa/magit-todos"))]) (magit-topgit . [(20161105 1623) ((emacs (24 4)) (magit (2 1 0))) "TopGit extension for Magit" single ((:commit . "11489ea798bc88d0ea5244bbf725285eedfefbef") (:authors ("Yann Hodique" . "yann.hodique@gmail.com")) (:maintainer "Robin Green" . "greenrd@greenrd.org") (:keywords "vc" "tools"))]) - (magit-vcsh . [(20190817 2014) ((magit (2 90 1)) (vcsh (0 4)) (emacs (24 4))) "Magit vcsh integration" single ((:commit . "fcff128cdbe3ef547dc64f2496cb6405b8ee21ca") (:authors ("Štěpán Němec" . "stepnem@gmail.com")) (:maintainer "Štěpán Němec" . "stepnem@gmail.com") (:keywords "vc" "files" "magit") (:url . "https://gitlab.com/stepnem/magit-vcsh-el"))]) + (magit-vcsh . [(20230402 1219) ((magit (2 90 1)) (vcsh (0 4)) (emacs (24 4))) "Magit vcsh integration" single ((:commit . "fd6c86c066b14bbf78644d38eca9711d6d9544a1") (:authors ("Štěpán Němec" . "stepnem@smrk.net")) (:maintainer "Štěpán Němec" . "stepnem@smrk.net") (:keywords "vc" "files" "magit") (:url . "http://git.smrk.net/magit-vcsh.el"))]) (magithub . [(20220315 117) ((emacs (25)) (magit (2 12)) (s (1 12 0)) (ghub+ (0 3)) (git-commit (2 12)) (markdown-mode (2 3))) "Magit interfaces for GitHub" tar ((:commit . "dd62c7057155c0a334e6d9087779a2923d2300b8") (:authors ("Sean Allred" . "code@seanallred.com")) (:maintainer "Sean Allred" . "code@seanallred.com") (:keywords "git" "tools" "vc") (:url . "https://github.com/vermiculus/magithub"))]) (magma-mode . [(20211018 917) ((emacs (24 3)) (cl-lib (0 3)) (dash (2 6 0)) (f (0 17 1))) "Mode for editing Magma source code" tar ((:commit . "11428d18ce3742334923d14ff2a8f493e7bd5ef0") (:url . "https://github.com/ThibautVerron/magma-mode"))]) (magnatune . [(20151030 1935) ((dash (2 9 0)) (s (1 9 0))) "browse magnatune's music catalog" tar ((:commit . "605b01505ba30589c77ebb4c96834b5072ccbdd4"))]) @@ -3059,12 +3063,12 @@ (map-progress . [(20190128 16) ((cl-lib (0 6 1))) "mapping macros that report progress" single ((:commit . "1fb916159cd054c233ce3c80d9d01adfae640297") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "convenience") (:url . "https://github.com/tarsius/map-progress"))]) (map-regexp . [(20190128 18) ((cl-lib (0 6 1))) "map over matches of a regular expression" single ((:commit . "ae2d1c22f786ad987aef3e319925e80160a887a0") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "convenience") (:url . "https://github.com/tarsius/map-regexp"))]) (marcopolo . [(20160421 1004) ((s (1 9 0)) (dash (2 9 0)) (pkg-info (0 5 0)) (request (0 1 0))) "Emacs client to the Docker HUB/Registry API" tar ((:commit . "85db828f2bb4346a811b3326349b1c6d0aae4601") (:authors ("Nicolas Lamirault" . "nicolas.lamirault@gmail.com")) (:maintainer "Nicolas Lamirault" . "nicolas.lamirault@gmail.com") (:keywords "docker") (:url . "https://github.com/nlamirault/marcopolo"))]) - (marginalia . [(20230317 926) ((emacs (27 1)) (compat (29 1 4 0))) "Enrich existing commands with completion annotations" single ((:commit . "2633b2dee22261531f960e49106771e679102a98") (:authors ("Omar Antolín Camarena , Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainer "Omar Antolín Camarena , Daniel Mendler" . "mail@daniel-mendler.de") (:url . "https://github.com/minad/marginalia"))]) + (marginalia . [(20230403 2057) ((emacs (27 1)) (compat (29 1 4 0))) "Enrich existing commands with completion annotations" single ((:commit . "c1ae5807731fea4837d20489436232731ae8fb9f") (:authors ("Omar Antolín Camarena , Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainer "Omar Antolín Camarena , Daniel Mendler" . "mail@daniel-mendler.de") (:url . "https://github.com/minad/marginalia"))]) (mark-multiple . [(20121118 1554) nil "Sorta lets you mark several regions at once." tar ((:commit . "f6a53c7c5283d640ae718f4548b0fda78877a375") (:authors ("Magnar Sveen" . "magnars@gmail.com")) (:maintainer "Magnar Sveen" . "magnars@gmail.com") (:keywords "marking" "library"))]) (mark-thing-at . [(20201219 232) ((emacs (26)) (choice-program (0 13))) "Mark a pattern at the current point" single ((:commit . "a622d128afc8d2d67de897666a1e2eccba8d7818") (:authors ("Paul Landes")) (:maintainer "Paul Landes") (:keywords "mark" "point" "lisp") (:url . "https://github.com/plandes/mark-thing-at"))]) (mark-tools . [(20130614 1025) nil "Some simple tools to access the mark-ring in Emacs" single ((:commit . "a11b61effa90bd0abc876d12573674d36fc17f0c") (:authors ("Alex Bennée" . "alex@bennee.com")) (:maintainer "Alex Bennée" . "alex@bennee.com") (:url . "https://github.com/stsquad/emacs-mark-tools"))]) (markdown-changelog . [(20200120 2253) ((emacs (26)) (dash (2 13 0))) "Maintain changelog entries" single ((:commit . "1a2c3a4c3e4196f2b5dbb145b01b4bc435a93a96") (:authors ("Paul Landes")) (:maintainer "Paul Landes") (:keywords "markdown" "changelog" "files") (:url . "https://github.com/plandes/markdown-changelog"))]) - (markdown-mode . [(20230306 2344) ((emacs (26 1))) "Major mode for Markdown-formatted text" single ((:commit . "ece1dd845904b08ab78598dc7e1a2eaf7875d1c4") (:authors ("Jason R. Blevins" . "jblevins@xbeta.org")) (:maintainer "Jason R. Blevins" . "jblevins@xbeta.org") (:keywords "markdown" "github flavored markdown" "itex") (:url . "https://jblevins.org/projects/markdown-mode/"))]) + (markdown-mode . [(20230331 913) ((emacs (26 1))) "Major mode for Markdown-formatted text" single ((:commit . "ad3a816f7be97deb83fc0a7fa41305c79009bac5") (:authors ("Jason R. Blevins" . "jblevins@xbeta.org")) (:maintainer "Jason R. Blevins" . "jblevins@xbeta.org") (:keywords "markdown" "github flavored markdown" "itex") (:url . "https://jblevins.org/projects/markdown-mode/"))]) (markdown-preview-eww . [(20160111 1502) ((emacs (24 4))) "Realtime preview by eww" single ((:commit . "5853f836425c877c8a956501f0adda137ef1d3b7") (:authors ("niku" . "niku@niku.name")) (:maintainer "niku" . "niku@niku.name") (:url . "https://github.com/niku/markdown-preview-eww"))]) (markdown-preview-mode . [(20221006 1601) ((emacs (24 4)) (websocket (1 6)) (markdown-mode (2 0)) (cl-lib (0 5)) (web-server (0 1 1))) "markdown realtime preview minor mode." tar ((:commit . "85fbfec507a222326695a3b91ff7306d0c4f94c6") (:authors ("Igor Shymko" . "igor.shimko@gmail.com")) (:maintainer "Igor Shymko" . "igor.shimko@gmail.com") (:keywords "markdown" "gfm" "convenience") (:url . "https://github.com/ancane/markdown-preview-mode"))]) (markdown-soma . [(20220802 956) ((emacs (25)) (s (1 11 0)) (dash (2 19 1)) (f (0 20 0))) "Live preview for Markdown" single ((:commit . "e604b9e4a65bbd2057befbfaebfa73d00bd9826a") (:authors ("Jason Milkins" . "jasonm23@gmail.com")) (:maintainer "Jason Milkins" . "jasonm23@gmail.com") (:keywords "wp" "docs" "text" "markdown") (:url . "https://github.com/jasonm23/markdown-soma"))]) @@ -3078,7 +3082,7 @@ (marshal . [(20201223 1853) ((emacs (25 1)) (ht (2 0))) "eieio extension for automatic (un)marshalling" single ((:commit . "490496d974d03906f784707ecc2e0ac36ed84b96") (:authors ("Yann Hodique" . "yann.hodique@gmail.com")) (:maintainer "Yann Hodique" . "yann.hodique@gmail.com") (:keywords "extensions") (:url . "https://github.com/sigma/marshal.el"))]) (maruo-macro-mode . [(20160616 1349) ((emacs (24 3))) "Major mode for editing Hidemaru/Maruo macro script" single ((:commit . "8fc9a38ad051eafa8eb94038711acc52c5d1d8d5") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "programming" "editor" "macro"))]) (masm-mode . [(20200308 1450) ((emacs (25 1))) "MASM x86 and x64 assembly major mode" single ((:commit . "ab63524d195332ec9f703783704231606e69c292") (:authors ("YiGeeker" . "zyfchinese@yeah.net")) (:maintainer "YiGeeker" . "zyfchinese@yeah.net") (:keywords "languages") (:url . "https://github.com/YiGeeker/masm-mode"))]) - (mastodon . [(20230321 1608) ((emacs (27 1)) (request (0 3 0)) (persist (0 4)) (ts (0 3))) "Client for Mastodon, a federated social network" tar ((:commit . "cf6b1c9f32bdabf2005585bde5369b322a9f0f5f") (:authors ("Johnson Denen" . "johnson.denen@gmail.com") ("Marty Hiatt" . "martianhiatus@riseup.net")) (:maintainer "Marty Hiatt" . "martianhiatus@riseup.net") (:url . "https://codeberg.org/martianh/mastodon.el"))]) + (mastodon . [(20230407 848) ((emacs (27 1)) (request (0 3 0)) (persist (0 4)) (ts (0 3))) "Client for Mastodon and compatible fediverse services" tar ((:commit . "319560d2ba769ae43e8a5a19cd3cdfb2d3daf5f0") (:authors ("Johnson Denen" . "johnson.denen@gmail.com") ("Marty Hiatt" . "martianhiatus@riseup.net")) (:maintainer "Marty Hiatt" . "martianhiatus@riseup.net") (:url . "https://codeberg.org/martianh/mastodon.el"))]) (material-theme . [(20210904 1226) ((emacs (24 1))) "A Theme based on the colors of the Google Material Design" tar ((:commit . "6823009bc92f82aa3a90e27e1009f7da8e87b648") (:authors ("Christoph Paulik" . "cpaulik@gmail.com")) (:maintainer "Christoph Paulik" . "cpaulik@gmail.com") (:keywords "themes") (:url . "http://github.com/cpaulik/emacs-material-theme"))]) (math-preview . [(20220830 1740) ((emacs (26 1)) (json (1 4)) (dash (2 18 0)) (s (1 12 0))) "Preview TeX math equations inline" single ((:commit . "dd41b03c64eca324558e6139699cacccfdd0efd2") (:authors ("Matsievskiy S.V.")) (:maintainer "Matsievskiy S.V.") (:keywords "convenience") (:url . "https://gitlab.com/matsievskiysv/math-preview"))]) (math-symbol-lists . [(20220828 2047) nil "Lists of Unicode math symbols and latex commands" tar ((:commit . "ac3eb053d3b576fcdd192b0ac6ad5090ea3a7079") (:authors ("Vitalie Spinu" . "spinuvit@gmail.com")) (:maintainer "Vitalie Spinu" . "spinuvit@gmail.com") (:keywords "unicode" "symbols" "mathematics") (:url . "https://github.com/vspinu/math-symbol-lists"))]) @@ -3100,14 +3104,14 @@ (media-thumbnail . [(20220827 2325) ((emacs (28 1))) "Utility package to provide media icons" single ((:commit . "14e626fe7ee714ab45c9e636d00a26e89aa2832a") (:authors ("James Nguyen" . "james@jojojames.com")) (:maintainer "James Nguyen" . "james@jojojames.com") (:keywords "files" "tools") (:url . "https://github.com/jojojames/media-thumbnail"))]) (mediawiki . [(20220923 1336) nil "mediawiki frontend" single ((:commit . "c28cf78d4fe4969df3af8dcc2adaf71c4212e5ad") (:authors ("Mark A. Hershberger" . "mah@everybody.org")) (:maintainer "Mark A. Hershberger" . "mah@everybody.org") (:keywords "mediawiki" "wikipedia" "network" "wiki") (:url . "https://github.com/hexmode/mediawiki-el"))]) (meghanada . [(20220101 505) ((emacs (24 3)) (yasnippet (0 6 1)) (company (0 9 0)) (flycheck (0 23))) "A better java development mode" tar ((:commit . "59c46cabb7eee715fe810ce59424934a1286df84") (:authors ("Yutaka Matsubara" . "yutaka.matsubara@gmail.com")) (:maintainer "Yutaka Matsubara" . "yutaka.matsubara@gmail.com") (:keywords "languages" "java") (:url . "https://github.com/mopemope/meghanada-emacs"))]) - (melancholy-theme . [(20230322 320) ((emacs (27 1))) "A dark theme that's pretty sad -*- lexical-binding: t; -" single ((:commit . "380f7fb5a62781412b5808f3a15aeb3c88295b5f") (:authors ("@baaash" . "bleat@baaa.sh")) (:maintainer "@baaash" . "bleat@baaa.sh") (:keywords "faces" "frames") (:url . "https://gitlab.com/baaash/melancholy-theme"))]) + (melancholy-theme . [(20230330 835) ((emacs (27 1))) "A dark theme that's pretty sad -*- lexical-binding: t; -" single ((:commit . "a5c4360f57793401b63b0df382e845b4845c8f97") (:authors ("@baaash" . "bleat@baaa.sh")) (:maintainer "@baaash" . "bleat@baaa.sh") (:keywords "faces" "frames") (:url . "https://gitlab.com/baaash/melancholy-theme"))]) (mellow-theme . [(20170808 1317) ((emacs (24 0))) "an Emacs 24 theme based on Mellow (tmTheme)" single ((:commit . "2bdf18f05f5212b6f269d9a94afe2cf201766891") (:authors ("Jason Milkins")) (:maintainer "Jason Milkins") (:url . "https://github.com/emacsfodder/tmtheme-to-deftheme"))]) (melpa-upstream-visit . [(20130720 1033) ((s (1 6 0))) "A set of kludges to visit a melpa-hosted package's homepage" single ((:commit . "7310c74fdead3c0f86ad6eff76cf989e63f70f66") (:authors ("Alessandro Piras" . "laynor@gmail.com")) (:maintainer "Alessandro Piras" . "laynor@gmail.com") (:keywords "convenience"))]) (memento-mori . [(20190628 2147) ((emacs (24)) (cl-lib (0 5))) "Reminder of mortality" single ((:commit . "52f95bd4cf6617b60dc204c9bccb8d8fa17d4f9e") (:authors ("Lassi Kortela" . "lassi@lassi.io")) (:maintainer "Lassi Kortela" . "lassi@lassi.io") (:keywords "help") (:url . "https://github.com/lassik/emacs-memento-mori"))]) (memoize . [(20200103 2036) nil "Memoization functions" single ((:commit . "51b075935ca7070f62fae1d69fe0ff7d8fa56fdd") (:authors ("Christopher Wellons" . "mosquitopsu@gmail.com")) (:maintainer "Christopher Wellons" . "mosquitopsu@gmail.com") (:url . "https://github.com/skeeto/emacs-memoize"))]) (memolist . [(20150804 1721) ((markdown-mode (22 0)) (ag (0 45))) "memolist.el is Emacs port of memolist.vim." single ((:commit . "60c296e202a71e9dcf1c3936d47b5c4b95c5839f") (:authors ("mikanfactory ")) (:maintainer "mikanfactory") (:keywords "markdown" "memo") (:url . "http://github.com/mikanfactory/emacs-memolist"))]) (mentor . [(20230103 1146) ((emacs (25 1)) (xml-rpc (1 6 15)) (seq (1 11)) (async (1 9 3)) (url-scgi (0 8))) "Frontend for the rTorrent bittorrent client" tar ((:commit . "f51dd4f3f87c54b7cc92189924b9d873a53f5a75") (:authors ("Stefan Kangas" . "stefankangas@gmail.com")) (:maintainer "Stefan Kangas" . "stefankangas@gmail.com") (:keywords "comm" "processes" "bittorrent") (:url . "https://github.com/skangas/mentor"))]) - (meow . [(20230319 311) ((emacs (27 1))) "Yet Another modal editing" tar ((:commit . "fb61ce5943d7ad11f4a7350e4b561947bbbaea71") (:authors ("Shi Tianshu")) (:maintainer "Shi Tianshu") (:keywords "convenience" "modal-editing") (:url . "https://www.github.com/DogLooksGood/meow"))]) + (meow . [(20230327 524) ((emacs (27 1))) "Yet Another modal editing" tar ((:commit . "d80c2ff2f94333492dd7714c4210440162985b20") (:authors ("Shi Tianshu")) (:maintainer "Shi Tianshu") (:keywords "convenience" "modal-editing") (:url . "https://www.github.com/DogLooksGood/meow"))]) (merlin . [(20221222 1239) ((emacs (25 1))) "Mode for Merlin, an assistant for OCaml" tar ((:commit . "41cd949106fbf0769c97e3a56808e4d99fc42c6f") (:authors ("Frédéric Bour ")) (:maintainer "Frédéric Bour ") (:keywords "ocaml" "languages") (:url . "https://github.com/ocaml/merlin"))]) (merlin-ac . [(20221123 1408) ((emacs (25 1)) (merlin (3)) (auto-complete (1 5))) "Merlin and auto-complete integration" single ((:commit . "8bcab034a680f57ddf58092fda6288dc4caddd2a") (:authors ("Simon Castellan ") ("Frédéric Bour ") ("Thomas Refis ")) (:maintainer "Simon Castellan ") (:keywords "ocaml" "languages") (:url . "http://github.com/ocaml/merlin"))]) (merlin-company . [(20221123 1408) ((emacs (25 1)) (merlin (3)) (company (0 9))) "Merlin and company mode integration" single ((:commit . "8bcab034a680f57ddf58092fda6288dc4caddd2a") (:authors ("Simon Castellan ") ("Frédéric Bour ") ("Thomas Refis ")) (:maintainer "Simon Castellan ") (:keywords "ocaml" "languages") (:url . "http://github.com/ocaml/merlin"))]) @@ -3183,7 +3187,7 @@ (modern-sh . [(20211101 1001) ((emacs (25 1)) (hydra (0 15 0)) (eval-in-repl (0 9 7))) "Minor mode for editing shell script" single ((:commit . "8ebebe77304aa8170f7af809e7564c79d3bd45da") (:keywords "languages" "programming") (:url . "https://github.com/damon-kwok/modern-sh"))]) (modtime-skip-mode . [(20140128 2201) nil "Minor mode for disabling modtime and supersession checks on files." single ((:commit . "c0e49523aa26b2263a8693691ac775988015f592") (:authors ("Jordon Biondo" . "biondoj@mail.gvsu.edu")) (:maintainer "Jordon Biondo" . "biondoj@mail.gvsu.edu") (:url . "http://www.github.com/jordonbiondo/modtime-skip-mode"))]) (modular-config . [(20210726 1614) ((emacs (25 1))) "Organize your config into small and loadable modules" single ((:commit . "043907d96efff70dfaea1e721de90bd35970e8bd") (:authors ("Sidharth Arya" . "sidhartharya10@gmail.com")) (:maintainer "Sidharth Arya" . "sidhartharya10@gmail.com") (:keywords "startup" "lisp" "tools") (:url . "https://github.com/SidharthArya/modular-config.el"))]) - (modus-themes . [(20230320 449) ((emacs (27 1))) "Elegant, highly legible and customizable themes" tar ((:commit . "2c34f81b831e646fa31840be8102ecaf4df6b6bf") (:authors ("Protesilaos Stavrou" . "info@protesilaos.com")) (:maintainer "Modus-Themes Development" . "~protesilaos/modus-themes@lists.sr.ht") (:keywords "faces" "theme" "accessibility") (:url . "https://git.sr.ht/~protesilaos/modus-themes"))]) + (modus-themes . [(20230405 456) ((emacs (27 1))) "Elegant, highly legible and customizable themes" tar ((:commit . "ede2ab0e0ff43b25fdac24a9946a95be705eff95") (:authors ("Protesilaos Stavrou" . "info@protesilaos.com")) (:maintainer "Modus-Themes Development" . "~protesilaos/modus-themes@lists.sr.ht") (:keywords "faces" "theme" "accessibility") (:url . "https://git.sr.ht/~protesilaos/modus-themes"))]) (moe-theme . [(20230110 422) nil "A colorful eye-candy theme. Moe, moe, kyun!" tar ((:commit . "171d76b0c69e42a9d7b62c5c472944951cb2be6c") (:authors ("kuanyui" . "azazabc123@gmail.com")) (:maintainer "kuanyui" . "azazabc123@gmail.com") (:keywords "themes") (:url . "https://github.com/kuanyui/moe-theme.el"))]) (molar-mass . [(20220922 1752) ((emacs (24 3))) "Calculates molar mass of a molecule" single ((:commit . "c3b686c4b621b45fa4b17857b4934eb4487d74f5") (:authors ("Sergi Ruiz Trepat")) (:maintainer "Sergi Ruiz Trepat") (:keywords "convenience" "chemistry") (:url . "https://github.com/sergiruiztrepat/molar-mass.el"))]) (molecule . [(20180527 743) ((emacs (25 1))) "Simple wrapper for molecule" single ((:commit . "2ef72b81d9aa24ea782b71a061a3abdad6cae162") (:authors (": drymer ")) (:maintainer ": drymer ") (:keywords ":" "languages" "terminals") (:url . "https://git.daemons.it/drymer/molecule.el"))]) @@ -3192,7 +3196,7 @@ (monitor . [(20161018 1144) ((dash (2 13 0))) "Utilities for monitoring expressions." tar ((:commit . "63f4643a0ee81616dbb692b8b03bae21df2283e2") (:authors ("Ben Moon" . "software@guiltydolphin.com")) (:maintainer "Ben Moon" . "software@guiltydolphin.com") (:keywords "lisp" "monitor" "utility") (:url . "https://github.com/guiltydolphin/monitor"))]) (monkeytype . [(20210110 513) ((emacs (25 1)) (scrollable-quick-peek (0 1 0))) "Mode for speed typing" single ((:commit . "0e949d08198c0bd003f1d5c8cdceb7e36bef22f7") (:authors ("Pablo Barrantes" . "xjpablobrx@gmail.com")) (:maintainer "Pablo Barrantes" . "xjpablobrx@gmail.com") (:keywords "games") (:url . "https://github.com/jpablobr/emacs-monkeytype"))]) (monky . [(20230222 2153) nil "Control Hg from Emacs." tar ((:commit . "7046eee5fc9ac625924382cb4a82b0d8efcd9ff0") (:authors ("Anantha kumaran" . "ananthakumaran@gmail.com")) (:maintainer "Anantha kumaran" . "ananthakumaran@gmail.com") (:keywords "tools") (:url . "http://github.com/ananthakumaran/monky"))]) - (mono-complete . [(20230319 556) ((emacs (28 1))) "Completion suggestions with multiple back-ends" tar ((:commit . "9a408bc19fdd878d1ca9b8881a2bb30e84e4f517") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:url . "https://codeberg.org/ideasman42/emacs-mono-complete"))]) + (mono-complete . [(20230405 529) ((emacs (28 1))) "Completion suggestions with multiple back-ends" tar ((:commit . "29436788b9ebe8a147b1deece6e86151528880f5") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:url . "https://codeberg.org/ideasman42/emacs-mono-complete"))]) (monochrome-theme . [(20140326 1050) nil "A dark Emacs 24 theme for your focused hacking sessions" tar ((:commit . "9cf993670c9e8d198f41d840216e13280585b3e1") (:authors ("Xavier Noria" . "fxn@hashref.com")) (:maintainer "Xavier Noria" . "fxn@hashref.com"))]) (monokai-alt-theme . [(20170630 2048) ((emacs (24))) "Theme with a dark background. Based on sublime monokai theme." single ((:commit . "f342b6afc31f929be0626eca2d696ee9fab78011") (:authors ("Dmytro Koval")) (:maintainer "Dmytro Koval") (:url . "https://github.com/dawidof/emacs-monokai-theme"))]) (monokai-pro-theme . [(20210206 1820) nil "A simple theme based on the Monokai Pro Sublime color schemes" tar ((:commit . "d0489741a80d818713c290a1a4bdd985877228bb") (:authors ("Kaleb Elwert" . "belak@coded.io")) (:maintainer "Kaleb Elwert" . "belak@coded.io") (:url . "https://github.com/belak/emacs-monokai-pro-theme"))]) @@ -3202,7 +3206,7 @@ (mood-line . [(20230126 917) ((emacs (25 1))) "A minimal mode line inspired by doom-modeline" tar ((:commit . "58e85c815092ac93d02dab584fe537fd1be3828a") (:authors ("Jessie Hildebrandt ")) (:maintainer "Jessie Hildebrandt ") (:keywords "mode-line" "faces") (:url . "https://gitlab.com/jessieh/mood-line"))]) (mood-one-theme . [(20221222 1214) ((emacs (27 1))) "A dark color scheme inspired by the Doom One theme" single ((:commit . "dfbc81900737d3382a340feeed24d2bcd9bdedb0") (:authors ("Jessie Hildebrandt ")) (:maintainer "Jessie Hildebrandt ") (:keywords "mode-line" "faces") (:url . "https://gitlab.com/jessieh/mood-one-theme"))]) (moody . [(20230212 2015) ((emacs (25 3)) (compat (29 1 3 4))) "Tabs and ribbons for the mode line" single ((:commit . "4c7171cbe39adcf2ab1ae5290bdb0ecfd7d669d1") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "faces") (:url . "https://github.com/tarsius/moody"))]) - (moom . [(20230224 1234) ((emacs (25 1))) "Commands to control frame position and size" tar ((:commit . "864bee4e121771a055fab2b9f3e53cb3b8a8e02a") (:authors ("Takaaki ISHIKAWA ")) (:maintainer "Takaaki ISHIKAWA ") (:keywords "frames" "faces" "convenience") (:url . "https://github.com/takaxp/Moom"))]) + (moom . [(20230401 1025) ((emacs (25 1))) "Commands to control frame position and size" tar ((:commit . "c7f319c29e5740b03910e75e89bfb2379d4ed680") (:authors ("Takaaki ISHIKAWA ")) (:maintainer "Takaaki ISHIKAWA ") (:keywords "frames" "faces" "convenience") (:url . "https://github.com/takaxp/Moom"))]) (moonscript . [(20170831 2226) ((cl-lib (0 5)) (emacs (24))) "Major mode for editing MoonScript code" tar ((:commit . "56f90471e2ced2b0a177aed4d8c2f854797e9cc7") (:authors ("@GriffinSchneider, @k2052, @EmacsFodder")) (:maintainer "@GriffinSchneider, @k2052, @EmacsFodder"))]) (moonshot . [(20210627 2244) ((emacs (25 1)) (cl-lib (0 5)) (f (0 18)) (s (1 11 0)) (projectile (2 0 0)) (counsel (0 11 0)) (realgud (1 5 1)) (seq (2 20)) (levenshtein (1 0))) "Run executable file, debug and build commands on project" single ((:commit . "ec37a12825888047a90d9ee8131aa4bea348edf7") (:authors ("Jong-Hyouk Yun" . "ageldama@gmail.com")) (:maintainer "Jong-Hyouk Yun" . "ageldama@gmail.com") (:keywords "convenience" "files" "processes" "tools" "unix") (:url . "https://github.com/ageldama/moonshot"))]) (morganey-mode . [(20170118 934) ((emacs (24 4))) "Major mode for editing Morganey files" single ((:commit . "7e33f1be486f58dfcf02adcbf82ccac47f69bd9b") (:authors ("Alexey Kutepov" . "reximkut@gmail.com")) (:maintainer "Alexey Kutepov" . "reximkut@gmail.com") (:url . "https://github.com/morganey-lang/morganey-mode"))]) @@ -3311,7 +3315,7 @@ (ncl-mode . [(20180129 703) ((emacs (24))) "Major Mode for editing NCL scripts and other goodies" tar ((:commit . "602292712a9e6b7e7c25155978999e77d06b7338") (:authors ("Yagnesh Raghava Yakkala" . "hi@yagnesh.org")) (:maintainer "Yagnesh Raghava Yakkala" . "hi@yagnesh.org") (:keywords "ncl" "major mode" "ncl-mode" "atmospheric science.") (:url . "https://github.com/yyr/ncl-mode"))]) (nclip . [(20130617 2015) nil "Network (HTTP) Clipboard" tar ((:commit . "af88e38b1f04be02bf2e57affc662dbd0f828e67") (:authors ("Marian Schubert" . "marian.schubert@gmail.com")) (:maintainer "Marian Schubert" . "marian.schubert@gmail.com") (:keywords "nclip" "clipboard" "network") (:url . "http://www.github.com/maio/nclip.el"))]) (neato-graph-bar . [(20181130 1649) ((emacs (24 3))) "Neat-o graph bars CPU/memory etc." single ((:commit . "a7ae35afd67911e8924f36e646bce0d3e3c1bbe6") (:authors ("Robert Cochran" . "robert-git@cochranmail.com")) (:maintainer "Robert Cochran" . "robert-git@cochranmail.com") (:url . "https://gitlab.com/RobertCochran/neato-graph-bar"))]) - (neil . [(20230309 954) ((emacs (27 1))) "companion for Babashka Neil" single ((:commit . "112173b84d1e69e633a63403e5f8d2bc5465ad0c") (:authors ("Ag Ibragimov" . "agzam.ibragimov@gmail.com")) (:maintainer "Ag Ibragimov" . "agzam.ibragimov@gmail.com") (:keywords "convenience" "tools") (:url . "https://github.com/babashka/neil"))]) + (neil . [(20230322 2035) ((emacs (27 1))) "companion for Babashka Neil" single ((:commit . "19bc12d1c868eb5c1f200963c240a2a107982556") (:authors ("Ag Ibragimov" . "agzam.ibragimov@gmail.com")) (:maintainer "Ag Ibragimov" . "agzam.ibragimov@gmail.com") (:keywords "convenience" "tools") (:url . "https://github.com/babashka/neil"))]) (nemerle . [(20161029 2023) nil "major mode for editing nemerle programs" single ((:commit . "8818c5af5598e16ea59189e1e3245f0a3d7c78f0") (:authors ("Jacek Sliwerski (rzyjontko)" . "rzyj@o2.pl")) (:maintainer "Jacek Sliwerski (rzyjontko)" . "rzyj@o2.pl") (:keywords "nemerle" "mode" "languages"))]) (neon-mode . [(20180406 1156) nil "Simple major mode for editing neon files" single ((:commit . "99d15e46beaf1e7d71e39a00cce810df1f33229d") (:authors ("Matúš Goljer" . "matus.goljer@gmail.com")) (:maintainer "Matúš Goljer" . "matus.goljer@gmail.com") (:keywords "conf"))]) (neotree . [(20200324 1946) ((cl-lib (0 5))) "A tree plugin like NerdTree for Vim" tar ((:commit . "98fe21334affaffe2334bf7c987edaf1980d2d0b") (:authors ("jaypei" . "jaypei97159@gmail.com")) (:maintainer "jaypei" . "jaypei97159@gmail.com") (:url . "https://github.com/jaypei/emacs-neotree"))]) @@ -3329,17 +3333,18 @@ (ng2-mode . [(20201203 1925) ((typescript-mode (0 1))) "Major modes for editing Angular 2" tar ((:commit . "d341f177c6e4fb9d99b8639943ab5fc9184e2715") (:authors ("Adam Niederer" . "adam.niederer@gmail.com")) (:maintainer "Adam Niederer" . "adam.niederer@gmail.com") (:keywords "typescript" "angular" "angular2" "template") (:url . "http://github.com/AdamNiederer/ng2-mode"))]) (nginx-mode . [(20170612 437) nil "major mode for editing nginx config files" single ((:commit . "a2bab83c2eb233d57d76b236e7c141c2ccc97005") (:authors ("Andrew J Cosgriff" . "andrew@cosgriff.name")) (:maintainer "Andrew J Cosgriff" . "andrew@cosgriff.name") (:keywords "languages" "nginx"))]) (niceify-info . [(20160416 1244) nil "improve usability of Info pages" single ((:commit . "66b45916f1994e16ee023d29fa7cf8fec48078f1"))]) + (nickel-mode . [(20230406 910) ((emacs (24 3))) "A major mode for editing Nickel source code" single ((:commit . "fea2152d591e46e19e4be6a7aca7fb0b1de15dd0") (:authors ("The Nickel Team" . "nickel-lang@tweag.io")) (:maintainer "The Nickel Team" . "nickel-lang@tweag.io") (:keywords "languages" "configuration-language" "configuration" "nickel" "infrastructure") (:url . "https://github.com/nickel-lang/nickel-mode"))]) (niconama . [(20170910 1501) ((emacs (24)) (request (20170131 1747)) (cl-lib (0 5))) "Tools for Niconico Live Broadcast" single ((:commit . "96e7553e50e6bf7b58aac50f52c9b0b8edb41c56") (:keywords "comm") (:url . "https://github.com/NOBUTOKA/niconama.el"))]) (night-owl-theme . [(20200622 1943) ((emacs (24))) "A color theme for the night owls out there" single ((:commit . "50315d6a4e170dccc83bf2d59a8a761f5ea32bb6") (:authors ("Aaron Jensen" . "aaronjensen@gmail.com")) (:maintainer "Aaron Jensen" . "aaronjensen@gmail.com") (:url . "http://github.com/aaronjensen/night-owl-theme"))]) (nikki . [(20210228 428) ((emacs (24 3))) "A simple diary mode" single ((:commit . "b2ea20d04a061df88d72bd8dd0412a6e7876458d") (:authors ("Taiki Harada" . "thdev994@gmail.com")) (:maintainer "Taiki Harada" . "thdev994@gmail.com") (:keywords "convenience") (:url . "https://github.com/th994/nikki"))]) (nikola . [(20170703 2021) ((async (1 5)) (emacs (24 3))) "Simple wrapper for nikola" single ((:commit . "964715ac30943c9d6976999cad208dc60d09def0") (:authors (": drymer ")) (:maintainer ": drymer ") (:keywords ":" "nikola") (:url . ": https://git.daemons.it/drymer/nikola.el"))]) (nim-mode . [(20211102 917) ((emacs (24 4)) (epc (0 1 1)) (let-alist (1 0 1)) (commenter (0 5 1)) (flycheck-nimsuggest (0 8 1))) "A major mode for the Nim programming language" tar ((:commit . "744e076f0bea1c5ddc49f92397d9aa98ffa7eff8") (:authors ("Simon Hafner")) (:maintainer "Simon Hafner" . "hafnersimon@gmail.com") (:keywords "nim" "languages"))]) - (nimbus-theme . [(20230219 1337) ((emacs (24 1))) "Nimbus dark theme" single ((:commit . "b28256c3a3d3d316d09e63a1fdd0817db110c3ce") (:authors ("Marcin Swieczkowski" . "marcin.swieczkowski@gmail.com") ("See README.md for full list of contributors.")) (:maintainer "Marcin Swieczkowski" . "marcin.swieczkowski@gmail.com") (:keywords "faces") (:url . "https://github.com/mrcnski/nimbus-theme"))]) + (nimbus-theme . [(20230403 819) ((emacs (24 1))) "Nimbus dark theme" single ((:commit . "80d5b622dd0c51547235d1e206e7d98cedb5c291") (:authors ("Marcin Swieczkowski" . "marcin.swieczkowski@gmail.com") ("See README.md for full list of contributors.")) (:maintainer "Marcin Swieczkowski" . "marcin.swieczkowski@gmail.com") (:keywords "faces") (:url . "https://github.com/mrcnski/nimbus-theme"))]) (ninja-mode . [(20181024 1439) ((emacs (24))) "Major mode for editing .ninja files" single ((:commit . "d2045dedc39885e702176b2b5e05bc77024ae3aa"))]) (nix-buffer . [(20180212 1518) ((f (0 17 3)) (emacs (24 4))) "Set up buffer environments with nix" single ((:commit . "db57cda36e7477bdc7ef5a136357b971b1d4d099") (:authors ("Shea Levy")) (:maintainer "Shea Levy") (:url . "https://github.com/shlevy/nix-buffer/tree/master/"))]) (nix-env-install . [(20200812 1305) ((emacs (25 1))) "Install packages using nix-env" single ((:commit . "79c34bc117ba1cebeb67fab32c364951d2ec37a0") (:authors ("Akira Komamura" . "akira.komamura@gmail.com")) (:maintainer "Akira Komamura" . "akira.komamura@gmail.com") (:keywords "processes" "tools") (:url . "https://github.com/akirak/nix-env-install"))]) (nix-haskell-mode . [(20190615 135) ((emacs (25)) (haskell-mode (16 0)) (nix-mode (1 3 0))) "haskell-mode integrations for Nix" single ((:commit . "68efbcbf949a706ecca6409506968ed2ef928a20") (:authors ("Matthew Bauer" . "mjbauer95@gmail.com")) (:maintainer "Matthew Bauer" . "mjbauer95@gmail.com") (:keywords "nix" "haskell" "languages" "processes") (:url . "https://github.com/matthewbauer/nix-haskell"))]) - (nix-mode . [(20230318 156) ((emacs (25 1)) (magit-section (0)) (transient (0 3))) "Major mode for editing .nix files" tar ((:commit . "e06fbfd62b60da4b76918d9bddb47752cf59fc03") (:maintainer "Matthew Bauer" . "mjbauer95@gmail.com") (:keywords "nix" "languages" "tools" "unix") (:url . "https://github.com/NixOS/nix-mode"))]) + (nix-mode . [(20230329 1948) ((emacs (25 1)) (magit-section (0)) (transient (0 3))) "Major mode for editing .nix files" tar ((:commit . "8a5c9d3437a7b21e3a10df635c8ec283eda1ad08") (:maintainer "Matthew Bauer" . "mjbauer95@gmail.com") (:keywords "nix" "languages" "tools" "unix") (:url . "https://github.com/NixOS/nix-mode"))]) (nix-modeline . [(20210405 742) ((emacs (25 1))) "Info about in-progress Nix evaluations on your modeline" single ((:commit . "9a6116a11bdacf649f2c50ae1f2f4b12c03bed70") (:authors ("Jordan Mulcahey" . "snhjordy@gmail.com")) (:maintainer "Jordan Mulcahey" . "snhjordy@gmail.com") (:keywords "processes" "unix" "tools") (:url . "https://github.com/ocelot-project/nix-modeline"))]) (nix-sandbox . [(20210325 1622) ((dash (2 12 1)) (s (1 10 0))) "Utility functions to work with nix-shell sandboxes" single ((:commit . "d3ec98405f1f9dac833abf9e146249b1b943870d") (:authors ("Sven Keidel" . "svenkeidel@gmail.com")) (:maintainer "Sven Keidel" . "svenkeidel@gmail.com") (:url . "https://github.com/travisbhartwell/nix-emacs"))]) (nix-update . [(20220816 2212) ((emacs (25))) "Update \"fetch\" blocks in .nix expressions" single ((:commit . "aab70a38165575a9cb41726f1cc67df60fbf2832") (:authors ("John Wiegley" . "johnw@newartisans.com")) (:maintainer "John Wiegley" . "johnw@newartisans.com") (:keywords "nix") (:url . "https://github.com/jwiegley/nix-update-el"))]) @@ -3351,7 +3356,7 @@ (nnhackernews . [(20230222 1441) ((emacs (25 2)) (request (0 3 3)) (dash (2 18 1)) (anaphora (1 0 4))) "Gnus backend for Hacker News" single ((:commit . "bf0ff5d4a079004f937e7440ba282c156f24dced") (:keywords "news") (:url . "https://github.com/dickmao/nnhackernews"))]) (nnir-est . [(20180710 2103) nil "Gnus nnir interface for HyperEstraier" single ((:commit . "6d0d5c8e33f4e4ccbc22350324c0990d2676fb5a") (:authors ("KAWABATA, Taichi ")) (:maintainer "KAWABATA, Taichi ") (:keywords "mail") (:url . "https://github.com/kawabata/nnir-est"))]) (nnreddit . [(20220423 2302) ((emacs (25 1)) (request (0 3 3)) (anaphora (1 0 4)) (dash (2 18 1)) (json-rpc (0 0 1)) (virtualenvwrapper (20151123)) (s (1 6 1))) "Gnus Backend For Reddit" tar ((:commit . "8f247dce12bd10de37f0903f3027a1ddbc318eff") (:keywords "news") (:url . "https://github.com/dickmao/nnreddit"))]) - (nntwitter . [(20220213 1654) ((emacs (25 1)) (dash (20190401)) (anaphora (20180618)) (request (20190819))) "Gnus Backend For Twitter" tar ((:commit . "f0eb3f6e8040f9064a18d3761b41f41dfd21a6ee") (:keywords "news") (:url . "https://github.com/dickmao/nntwitter"))]) + (nntwitter . [(20230323 1458) ((emacs (25 1)) (dash (20190401)) (anaphora (20180618)) (request (20190819))) "Gnus Backend For Twitter" tar ((:commit . "8189100aa071386665b8616c6b57067383abd47b") (:keywords "news") (:url . "https://github.com/dickmao/nntwitter"))]) (no-clown-fiesta-theme . [(20230220 1019) ((emacs (26 1)) (autothemer (0 2))) "Not-so-colorful-theme" single ((:commit . "e143cdfa7cecac6383328eca88586105f308bca9") (:authors ("ranmaru22")) (:maintainer "ranmaru22") (:url . "https://github.com/ranmaru22/no-clown-fiesta-theme.el"))]) (no-emoji . [(20180515 1837) ((emacs (24))) "Show :emoji-name: instead of emoji characters" single ((:commit . "ebceeab50dbfe4d60235180a57633745dbc18c77") (:authors ("Peter" . "craven@gmx.net")) (:maintainer "Peter" . "craven@gmx.net") (:keywords "extensions") (:url . "https://github.com/ecraven/no-emoji"))]) (no-littering . [(20230220 1519) ((emacs (25 1)) (compat (29 1 3 4))) "Help keeping ~/.emacs.d clean" single ((:commit . "b1ba75ab9296ada356219ff8ae26333a79871c61") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "convenience") (:url . "https://github.com/emacscollective/no-littering"))]) @@ -3377,7 +3382,7 @@ (notmuch-labeler . [(20131230 1719) ((notmuch (0))) "Improve notmuch way of displaying labels" tar ((:commit . "d65d1129555d368243df4770ecc1e7ccb88efc58") (:authors ("Damien Cassou" . "damien.cassou@gmail.com")) (:maintainer "Damien Cassou" . "damien.cassou@gmail.com") (:keywords "emacs" "package" "elisp" "notmuch" "emails") (:url . "https://github.com/DamienCassou/notmuch-labeler"))]) (notmuch-maildir . [(20230212 2014) ((emacs (26 1)) (compat (29 1 3 4)) (notmuch (0 30))) "Visualize maildirs as a tree" single ((:commit . "0d8f1534691e834f26e1899dd54df2db7f810669") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "mail") (:url . "https://git.sr.ht/~tarsius/notmuch-maildir"))]) (notmuch-transient . [(20230212 2014) ((emacs (27 1)) (compat (29 1 3 4)) (notmuch (0 31 4))) "Command dispatchers for Notmuch" single ((:commit . "9d1fa80be0656e712a3f86079ea0abba0542dd88") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "mail") (:url . "https://git.sr.ht/~tarsius/notmuch-transient"))]) - (nov . [(20220805 2031) ((esxml (0 3 6)) (emacs (25 1))) "Featureful EPUB reader mode" single ((:commit . "cb5f45cbcfbcf263cdeb2d263eb15edefc8b07cb") (:authors ("Vasilij Schneidermann" . "mail@vasilij.de")) (:maintainer "Vasilij Schneidermann" . "mail@vasilij.de") (:keywords "hypermedia" "multimedia" "epub") (:url . "https://depp.brause.cc/nov.el"))]) + (nov . [(20230327 1739) ((esxml (0 3 6)) (emacs (25 1))) "Featureful EPUB reader mode" single ((:commit . "6c992c2c5c4ad03a0f432a74fe4d0cde3b6da4bd") (:authors ("Vasilij Schneidermann" . "mail@vasilij.de")) (:maintainer "Vasilij Schneidermann" . "mail@vasilij.de") (:keywords "hypermedia" "multimedia" "epub") (:url . "https://depp.brause.cc/nov.el"))]) (nova-theme . [(20210512 1802) ((emacs (24 3))) "A dark, pastel color theme" single ((:commit . "1498f756a4c1c9ea9740cd3208f74d071283b930") (:authors ("Muir Manders" . "muir+emacs@mnd.rs")) (:maintainer "Muir Manders" . "muir+emacs@mnd.rs") (:keywords "theme" "dark" "nova" "pastel" "faces") (:url . "https://github.com/muirmanders/emacs-nova-theme"))]) (noxml-fold . [(20170823 1357) nil "Fold away XML things." single ((:commit . "46c7f6a008672213238a9f8d7a416ce80916aa62") (:authors ("Patrick McAllister" . "pma@rdorte.org")) (:maintainer "Patrick McAllister" . "pma@rdorte.org") (:keywords "xml" "folding") (:url . "https://github.com/paddymcall/noxml-fold"))]) (npm . [(20220428 927) ((emacs (25 1)) (transient (0 1 0)) (jest (20200625))) "Run your npm workflows" tar ((:commit . "6eb0a58274870dd75bf848cf5a916a9f2c6ddae5") (:authors ("Shane Kennedy")) (:maintainer "Shane Kennedy") (:keywords "tools") (:url . "https://github.com/shaneikennedy/npm.el"))]) @@ -3400,7 +3405,6 @@ (nxml-uxml . [(20220606 1213) ((emacs (25))) "MicroXML support for nXML" single ((:commit . "95bbd0018ab218b9f39f5bf1f1e809f60fbc3edc") (:authors ("Daphne Preston-Kendal")) (:maintainer "Daphne Preston-Kendal") (:keywords "languages" "xml" "microxml") (:url . "https://gitlab.com/dpk/nxml-uxml"))]) (nyan-mode . [(20220408 2334) ((emacs (24 1))) "Nyan Cat shows position in current buffer in mode-line" tar ((:commit . "09904af23adb839c6a9c1175349a1fb67f5b4370") (:authors ("Jacek \"TeMPOraL\" Zlydach" . "temporal.pl@gmail.com")) (:maintainer "Jacek \"TeMPOraL\" Zlydach" . "temporal.pl@gmail.com") (:keywords "convenience" "games" "mouse" "multimedia") (:url . "https://github.com/TeMPOraL/nyan-mode/"))]) (nyx-theme . [(20170910 1307) ((emacs (24))) "Dark theme" single ((:commit . "afe2b8c3b5421b4c292d182dcf77079b278e93d8") (:authors ("Guido Schmidt")) (:maintainer "Guido Schmidt" . "guido.schmidt.2912@gmail.com") (:keywords "themes" "dark-theme") (:url . "https://github.com/GuidoSchmidt/emacs-nyx-theme"))]) - (nz-holidays . [(20190415 703) nil "New Zealand public holidays for calendar." single ((:commit . "afc875cf40789fa45a4a811685b0a7c4f239392f") (:authors ("Sod Oscarfono" . "sod@oscarfono.com")) (:maintainer "Sod Oscarfono" . "sod@oscarfono.com") (:keywords "calendar") (:url . "https://github.com/techquila/nz-holidays"))]) (oauth . [(20130128 151) nil "Oauth library." tar ((:commit . "ee4744ad76a1560281b0c4944575a3bd598c6458") (:authors ("Peter Sanford ")) (:maintainer "Peter Sanford ") (:keywords "comm"))]) (oauth2-request . [(20210215 657) ((emacs (26 1)) (oauth2 (0 14)) (request (0 3))) "OAuth2 request package interface" single ((:commit . "86ff048635e002b00e23d6bed2ec6f36c17bca8e") (:authors ("Naoya Yamashita" . "conao3@gmail.com")) (:maintainer "Naoya Yamashita" . "conao3@gmail.com") (:keywords "convenience") (:url . "https://github.com/conao3/oauth2-request.el"))]) (ob-ada-spark . [(20221114 2007) ((emacs (26 1)) (f (0 20 0))) "Babel functions for Ada & SPARK" single ((:commit . "92978410ca14aa4e84c229a0920ad40be91c35e1") (:authors ("Francesc Rocher")) (:maintainer "Francesc Rocher") (:keywords "languages" "tools" "outlines") (:url . "https://github.com/rocher/ob-ada-spark"))]) @@ -3422,6 +3426,7 @@ (ob-dart . [(20221201 633) ((emacs (24 4))) "Evaluate Dart source blocks in org-mode" single ((:commit . "f6d5664d5cc8b15e002f6899f8adedcb10ced5f1") (:authors ("Milan Zimmermann")) (:maintainer "Milan Zimmermann") (:keywords "languages") (:url . "http://github.org/mzimmerm/ob-dart"))]) (ob-deno . [(20201019 101) ((emacs (26 1))) "Babel Functions for Javascript/TypeScript with Deno" single ((:commit . "e3b06d7662687e402905b9de4ad1d5816e89b842") (:authors ("HIGASHI Taiju")) (:maintainer "HIGASHI Taiju") (:keywords "literate programming" "reproducible research" "javascript" "typescript" "tools") (:url . "https://github.com/taiju/ob-deno"))]) (ob-diagrams . [(20160407 1237) nil "org-babel functions for diagrams evaluation" single ((:commit . "be45815f5596d181592fae709096b7b5f4a71992") (:authors ("Daniel Bergey")) (:maintainer "Daniel Bergey") (:keywords "literate programming" "reproducible research") (:url . "http://orgmode.org"))]) + (ob-drawtiming . [(20230312 1740) ((emacs (24 1)) (org (8 0))) "Functions for drawtiming evaluation in org-babel" single ((:commit . "813736e20ce1c223700c87a6e70e3f126a11e933") (:authors ("Fabien Perez")) (:maintainer "Fabien Perez") (:keywords "tools" "multimedia") (:url . "https://github.com/perfab71/ob-drawtiming"))]) (ob-dsq . [(20220915 1610) ((emacs (27 1))) "Babel functions for the `dsq` CLI tool by Multiprocess Labs" single ((:commit . "e001b263af87993755319caefaf5d19e196e4e1b") (:authors ("Fritz Grabo" . "hello@fritzgrabo.com")) (:maintainer "Fritz Grabo" . "hello@fritzgrabo.com") (:keywords "data" "tools") (:url . "https://github.com/fritzgrabo/ob-dsq"))]) (ob-elixir . [(20170725 1419) ((org (8))) "org-babel functions for elixir evaluation" single ((:commit . "8990a8178b2f7bd93504a9ab136622aab6e82e32") (:authors ("ZHOU Feng" . "zf.pascal@gmail.com")) (:maintainer "ZHOU Feng" . "zf.pascal@gmail.com") (:keywords "org" "babel" "elixir") (:url . "http://github.com/zweifisch/ob-elixir"))]) (ob-elm . [(20200528 1857) ((emacs (26 1)) (org (9 3))) "Org-babel functions for elm evaluation" single ((:commit . "d3a9fbc2f56416894c9aed65ea9a20cc1d98f15d") (:authors ("Bonface M. K.")) (:maintainer "Bonface M. K.") (:keywords "languages" "tools") (:url . "https://www.bonfacemunyoki.com"))]) @@ -3487,7 +3492,7 @@ (octicons . [(20151101 340) ((cl-lib (0 5))) "octicons utility" tar ((:commit . "229286a6166dba8ddabc8c4d338798c6cd3cf67d") (:authors ("Syohei YOSHIDA" . "syohex@gmail.com")) (:maintainer "Syohei YOSHIDA" . "syohex@gmail.com") (:url . "https://github.com/syohex/emacs-octicons"))]) (octo-mode . [(20161008 1229) ((emacs (24))) "Major mode for Octo assembly language" single ((:commit . "4b2ed4a61674f73a6ccd390b5ae123474bd0c977") (:authors ("John Olsson" . "john@cryon.se")) (:maintainer "John Olsson" . "john@cryon.se") (:keywords "languages") (:url . "https://github.com/cryon/octo-mode"))]) (octopress . [(20190123 107) nil "A lightweight wrapper for Jekyll and Octopress." tar ((:commit . "f2c92d5420f14fc9167c7de1873836510e652de2") (:authors ("Aaron Bieber" . "aaron@aaronbieber.com")) (:maintainer "Aaron Bieber" . "aaron@aaronbieber.com") (:keywords "octopress" "blog") (:url . "https://github.com/aaronbieber/octopress.el"))]) - (oer-reveal . [(20230313 911) ((emacs (24 4)) (org-re-reveal (3 1 0))) "OER with reveal.js, plugins, and org-re-reveal" tar ((:commit . "d281566d476229fabaab6bc127b6b5f6c26834b6") (:authors ("Jens Lechtenbörger")) (:maintainer "Jens Lechtenbörger") (:keywords "hypermedia" "tools" "slideshow" "presentation" "oer") (:url . "https://gitlab.com/oer/oer-reveal"))]) + (oer-reveal . [(20230403 1322) ((emacs (24 4)) (org-re-reveal (3 1 0))) "OER with reveal.js, plugins, and org-re-reveal" tar ((:commit . "f7b0d952c9ab0969dbb9c003df4f298ec9d3ee79") (:authors ("Jens Lechtenbörger")) (:maintainer "Jens Lechtenbörger") (:keywords "hypermedia" "tools" "slideshow" "presentation" "oer") (:url . "https://gitlab.com/oer/oer-reveal"))]) (offlineimap . [(20150916 1158) nil "Run OfflineIMAP from Emacs" single ((:commit . "cc3e067e6237a1eb7b21c575a41683b1febb47f1") (:authors ("Julien Danjou" . "julien@danjou.info")) (:maintainer "Julien Danjou" . "julien@danjou.info") (:url . "http://julien.danjou.info/offlineimap-el.html"))]) (oj . [(20230212 148) ((emacs (26 1)) (quickrun (2 2))) "Competitive programming tools client for AtCoder, Codeforces" single ((:commit . "6d586cb108c642bc166c64df113e03193f4d1495") (:authors ("Naoya Yamashita" . "conao3@gmail.com")) (:maintainer "Naoya Yamashita" . "conao3@gmail.com") (:keywords "convenience") (:url . "https://github.com/conao3/oj.el"))]) (ol-notmuch . [(20230212 2013) ((emacs (25 1)) (compat (29 1 3 4)) (notmuch (0 32)) (org (9 4 5))) "Links to notmuch messages" single ((:commit . "ee3646627e47312a0c6ab0a5f6eba3baf8b20cb6") (:authors ("Matthieu Lemerre" . "racin@free.fr")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "hypermedia" "mail") (:url . "https://git.sr.ht/~tarsius/ol-notmuch"))]) @@ -3527,7 +3532,7 @@ (ordinal . [(20210519 1442) ((emacs (24 3))) "Convert number to ordinal number notation" single ((:commit . "a7f378306290b6807fb6b87cee3ef79b31cec711") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "lisp") (:url . "https://github.com/zonuexe/ordinal.el"))]) (org-ac . [(20170401 1307) ((auto-complete-pcmp (0 0 1)) (log4e (0 2 0)) (yaxception (0 1))) "Some auto-complete sources for org-mode" single ((:commit . "41e3ef8e4039619d0370c23c66730b3b2e9e32ed") (:authors ("Hiroaki Otsu" . "ootsuhiroaki@gmail.com")) (:maintainer "Hiroaki Otsu" . "ootsuhiroaki@gmail.com") (:keywords "org" "completion") (:url . "https://github.com/aki2o/org-ac"))]) (org-agenda-property . [(20140626 2116) ((emacs (24 2))) "Display org properties in the agenda buffer." single ((:commit . "01afb36072eb27846eb09310dfca7991dbae831e") (:authors ("Artur Malabarba" . "bruce.connor.am@gmail.com")) (:maintainer "Artur Malabarba" . "bruce.connor.am@gmail.com") (:keywords "calendar") (:url . "http://github.com/Bruce-Connor/org-agenda-property"))]) - (org-ai . [(20230317 2217) ((emacs (28 2))) "Emacs org-mode integration for the OpenAI API" single ((:commit . "8748ac5687b22b7e637505871125554ec727189e") (:authors ("Robert Krahn" . "robert@kra.hn")) (:maintainer "Robert Krahn" . "robert@kra.hn") (:url . "https://github.com/rksm/org-ai"))]) + (org-ai . [(20230407 950) ((emacs (28 2))) "Your AI assistant with ChatGPT, DALL-E, Whisper" tar ((:commit . "17fee8f50328692076e66570ffe5f749c0dc52e7") (:authors ("Robert Krahn" . "robert@kra.hn")) (:maintainer "Robert Krahn" . "robert@kra.hn") (:url . "https://github.com/rksm/org-ai"))]) (org-alert . [(20220721 1721) ((org (9 0)) (alert (1 2))) "Notify org deadlines via notify-send" single ((:commit . "f1801e061722843329b95409957c7dbd5cc223e9") (:authors ("Stephen Pegoraro" . "spegoraro@tutive.com")) (:maintainer "Stephen Pegoraro" . "spegoraro@tutive.com") (:keywords "org" "org-mode" "notify" "notifications" "calendar") (:url . "https://github.com/spegoraro/org-alert"))]) (org-analyzer . [(20191001 1717) nil "org-analyzer is a tool that extracts time tracking data from org files." tar ((:commit . "19da62aa4dcf1090be8f574f6f2d4c7e116163a8") (:authors ("Robert Krahn" . "robert@kra.hn")) (:maintainer "Robert Krahn" . "robert@kra.hn") (:keywords "calendar") (:url . "https://github.com/rksm/clj-org-analyzer"))]) (org-anki . [(20230117 727) ((emacs (27 1)) (request (0 3 2)) (dash (2 17)) (promise (1 1))) "Synchronize org-mode entries to Anki" single ((:commit . "f10feec7bd70916808a3cd8b4c3e3c7f65764acf") (:authors ("Markus Läll" . "markus.l2ll@gmail.com")) (:maintainer "Markus Läll" . "markus.l2ll@gmail.com") (:keywords "outlines" "flashcards" "memory") (:url . "https://github.com/eyeinsky/org-anki"))]) @@ -3545,7 +3550,7 @@ (org-books . [(20210408 1913) ((enlive (0 0 1)) (s (1 11 0)) (helm (2 9 2)) (helm-org (1 0)) (dash (2 14 1)) (org (9 3)) (emacs (25))) "Reading list management with Org mode and helm" single ((:commit . "9f4ec4a981bfc5eebff993c3ad49a4bed26aebd1") (:authors ("Abhinav Tushar" . "abhinav@lepisma.xyz")) (:maintainer "Abhinav Tushar" . "abhinav@lepisma.xyz") (:keywords "outlines") (:url . "https://github.com/lepisma/org-books"))]) (org-brain . [(20230217 1908) ((emacs (25 1)) (org (9 2))) "Org-mode concept mapping" single ((:commit . "2bad7732aae1a3051e2a14de2e30f970bbe43c25") (:authors ("Erik Sjöstrand" . "sjostrand.erik@gmail.com")) (:maintainer "Erik Sjöstrand" . "sjostrand.erik@gmail.com") (:keywords "outlines" "hypermedia") (:url . "http://github.com/Kungsgeten/org-brain"))]) (org-bullets . [(20200317 1740) nil "Show bullets in org-mode as UTF-8 characters" single ((:commit . "9ec0dbd30be7c6310804141ee952ac8c5f753557") (:authors ("sabof")) (:maintainer "D. Williams" . "d.williams@posteo.net") (:url . "https://github.com/integral-dw/org-bullets"))]) - (org-caldav . [(20230205 2235) ((emacs (26 3)) (org (9 1))) "Sync org files with external calendar through CalDAV" single ((:commit . "cc1b820773ccab9e3d8f584e96c14cdbb22cdb16") (:authors ("David Engster" . "deng@randomsample.de")) (:maintainer "Jack Kamm" . "jackkamm@tatersworld.org") (:keywords "calendar" "caldav") (:url . "https://github.com/dengste/org-caldav/"))]) + (org-caldav . [(20230331 11) ((emacs (26 3)) (org (9 1))) "Sync org files with external calendar through CalDAV" single ((:commit . "618bf4cdc9be140ca1993901d017b7f18297f1b8") (:authors ("David Engster" . "deng@randomsample.de")) (:maintainer "Jack Kamm" . "jackkamm@tatersworld.org") (:keywords "calendar" "caldav") (:url . "https://github.com/dengste/org-caldav/"))]) (org-calibre-notes . [(20221202 1657) ((emacs (27 1))) "Extract highlights and notes from Calibre EPUB reader" single ((:commit . "3120797ecbcb58827b91e3610e65579593d9a402") (:authors ("Bibek Panthi" . "bpanthi977@gmail.com")) (:maintainer "Bibek Panthi" . "bpanthi977@gmail.com") (:url . "https://github.com/bpanthi977/org-calibre-notes"))]) (org-capture-pop-frame . [(20160518 1008) ((emacs (24 4))) "Run org-capture in a new pop frame" single ((:commit . "b16fd712de62cf0d1f9befd03be6ab5983cb3301") (:authors ("Feng Shu" . "tumashu@163.com")) (:maintainer "Feng Shu" . "tumashu@163.com") (:url . "https://github.com/tumashu/org-capture-pop-frame.git"))]) (org-category-capture . [(20220114 730) ((org (9 0 0)) (emacs (24))) "Contextualy capture of org-mode TODOs." single ((:commit . "bc5a2401b456c42c4346d59fa77d633770b6efea") (:authors ("Ivan Malison" . "IvanMalison@gmail.com")) (:maintainer "Ivan Malison" . "IvanMalison@gmail.com") (:keywords "org-mode" "todo" "tools" "outlines") (:url . "https://github.com/IvanMalison/org-projectile"))]) @@ -3592,18 +3597,18 @@ (org-if . [(20150920 1513) nil "Interactive Fiction Authoring System for Org-Mode." tar ((:commit . "fab602cc1bbee7a4e99c0083e129219d3f9ed2e8") (:authors ("Philip Woods" . "elzairthesorcerer@gmail.com")) (:maintainer "Philip Woods" . "elzairthesorcerer@gmail.com") (:keywords "if" "org-if" "org org-mode"))]) (org-incoming . [(20230209 1509) ((emacs (24 4)) (dash (2 19 1)) (datetime (0 7 2)) (s (1 13 1))) "Sort incoming PDFs into your org files" single ((:commit . "5c5a5cc034a0b9ed808e5cbbf4876d489a6c7d28") (:authors ("Lukas Barth" . "mail@tinloaf.de")) (:maintainer "Lukas Barth" . "mail@tinloaf.de") (:keywords "files") (:url . "https://github.com/tinloaf/org-incoming"))]) (org-index . [(20230103 1720) ((org (9 3)) (dash (2 12)) (s (1 12)) (emacs (26 3))) "No description available." single ((:commit . "d919b9e2ef8c0f814455b82ffea080e872b89c72") (:authors ("Marc Ihm" . "1@2484.de")) (:maintainer "Marc Ihm" . "1@2484.de") (:url . "https://github.com/marcIhm/org-index"))]) - (org-inline-anim . [(20211101 413) ((emacs (25 3)) (org (9 4))) "Inline playback of animated GIF/PNG for Org" single ((:commit . "1808574ff04ed66b7382247f3f13815fae2a4929") (:authors ("Shigeaki Nishina")) (:maintainer "Shigeaki Nishina") (:keywords "org" "outlines" "hypermedia" "multimedia") (:url . "https://github.com/shg/org-inline-anim.el"))]) + (org-inline-anim . [(20230331 1048) ((emacs (25 3)) (org (9 4))) "Inline playback of animated GIF/PNG for Org" single ((:commit . "9316fe78319fa18c7282993bd547cd33fda1b8ee") (:authors ("Shigeaki Nishina")) (:maintainer "Shigeaki Nishina") (:keywords "org" "outlines" "hypermedia" "multimedia") (:url . "https://github.com/shg/org-inline-anim.el"))]) (org-inline-pdf . [(20221029 751) ((emacs (25 1)) (org (9 4))) "Inline PDF previewing for Org" single ((:commit . "513c0badffcc65d618d43543abd72077e144fd22") (:authors ("Shigeaki Nishina")) (:maintainer "Shigeaki Nishina") (:keywords "org" "outlines" "hypermedia") (:url . "https://github.com/shg/org-inline-pdf.el"))]) (org-iv . [(20171001 1022) ((impatient-mode (1 0 0)) (org (8 0)) (cl-lib (0 5))) "a tool used to view html (in browser) generated by org-file once the org-file changes" tar ((:commit . "7f2bb1b32647655fd9d6684f6f09dcc66b61b0cd") (:authors ("kuangdash" . "kuangdash@163.com")) (:maintainer "kuangdash" . "kuangdash@163.com") (:url . "https://github.com/kuangdash/org-iv"))]) (org-ivy-search . [(20230222 514) ((emacs (25 1)) (ivy (0 10 0)) (org (0 10 0)) (beacon (1 3 4))) "Full text search for org files powered by ivy" single ((:commit . "7f2afd8c196e3723ae6ac4dd229367ece9acd3bf") (:authors ("Huming Chen" . "chenhuming@gmail.com")) (:maintainer "Huming Chen" . "chenhuming@gmail.com") (:keywords "convenience" "tool" "org") (:url . "https://github.com/beacoder/org-ivy-search"))]) - (org-jira . [(20230228 1619) ((emacs (24 5)) (cl-lib (0 5)) (request (0 2 0)) (dash (2 14 1))) "Syncing between Jira and Org-mode." tar ((:commit . "13457755932565306f42074c69076759a428568a") (:maintainer "Matthew Carter" . "m@ahungry.com") (:keywords "ahungry" "jira" "org" "bug" "tracker") (:url . "https://github.com/ahungry/org-jira"))]) + (org-jira . [(20230329 1527) ((emacs (24 5)) (cl-lib (0 5)) (request (0 2 0)) (dash (2 14 1))) "Syncing between Jira and Org-mode." tar ((:commit . "2ca5df517ca6f47703408b056fde14ac0340cc9e") (:maintainer "Matthew Carter" . "m@ahungry.com") (:keywords "ahungry" "jira" "org" "bug" "tracker") (:url . "https://github.com/ahungry/org-jira"))]) (org-journal . [(20230309 1240) ((emacs (25 1)) (org (9 1))) "a simple org-mode based journaling mode" single ((:commit . "18df4d5ae5e15580df42562c143d007c6d28d75f") (:authors ("Bastian Bechtold") ("Christian Schwarzgruber")) (:maintainer "Bastian Bechtold") (:url . "http://github.com/bastibe/org-journal"))]) (org-journal-list . [(20190221 2052) ((emacs (25))) "Org mode Journal List" single ((:commit . "2b26d00181bb49bff64b31ad020490acd1b6ae02") (:authors ("Huy Tran" . "huytd189@gmail.com")) (:maintainer "Huy Tran" . "huytd189@gmail.com") (:url . "https://github.com/huytd/org-journal-list"))]) (org-journal-tags . [(20230105 1937) ((emacs (27 1)) (org-journal (2 1 2)) (magit-section (3 3 0)) (transient (0 3 7))) "Tagging and querying system for org-journal" single ((:commit . "dfb3b2d583ceb7ad9fbc8ac23ab6316ae172e9fb") (:authors ("Korytov Pavel" . "thexcloud@gmail.com")) (:maintainer "Korytov Pavel" . "thexcloud@gmail.com") (:url . "https://github.com/SqrtMinusOne/org-journal-tags"))]) (org-kanban . [(20220723 1216) ((s (0)) (dash (2 17 0)) (emacs (24 4)) (org (9 1))) "kanban dynamic block for org-mode." single ((:commit . "e78deb03880ae89d6bceae6563ef1383526233a1") (:authors ("Christian Köstlin" . "christian.koestlin@gmail.com")) (:maintainer "Christian Köstlin" . "christian.koestlin@gmail.com") (:keywords "org-mode" "org" "kanban" "tools") (:url . "http://github.com/gizmomogwai/org-kanban"))]) (org-kindle . [(20220210 1408) ((emacs (25)) (cl-lib (0 5)) (seq (2 20))) "Send org link file to ebook reader." single ((:commit . "fadcfd62e254d0c45e87d63128a82a08ae21869a") (:keywords "org" "link" "ebook" "kindle" "epub" "azw3" "mobi") (:url . "https://repo.or.cz/org-kindle.git"))]) (org-latex-impatient . [(20221111 623) ((emacs (26)) (s (1 8 0)) (posframe (0 8 0)) (org (9 3)) (dash (2 17 0))) "Preview org-latex Fragments Instantly via MathJax" single ((:commit . "031025a8be9bf7255aa047388d027642cd2d6183") (:authors ("Sheng Yang" . "styang@fastmail.com")) (:maintainer "Sheng Yang" . "styang@fastmail.com") (:keywords "tex" "tools") (:url . "https://github.com/yangsheng6810/org-latex-instant-preview"))]) - (org-link-beautify . [(20230311 1220) ((emacs (28 1)) (all-the-icons (5 0 0))) "Beautify Org Links" tar ((:commit . "5e596819a82198212dfb461a8a3b61ebbee97835") (:keywords "hypermedia") (:url . "https://repo.or.cz/org-link-beautify.git"))]) + (org-link-beautify . [(20230407 916) ((emacs (28 1)) (all-the-icons (5 0 0))) "Beautify Org Links" tar ((:commit . "3d36a4ae5ade049d03b88f635e4b7d1097dafc91") (:keywords "hypermedia") (:url . "https://repo.or.cz/org-link-beautify.git"))]) (org-link-travis . [(20140405 2327) ((org (7))) "Insert/Export the link of Travis CI on org-mode" single ((:commit . "596615ad8373d9090bd4138da683524f0ad0bda5") (:authors ("Hiroaki Otsu" . "ootsuhiroaki@gmail.com")) (:maintainer "Hiroaki Otsu" . "ootsuhiroaki@gmail.com") (:keywords "org") (:url . "https://github.com/aki2o/org-link-travis"))]) (org-linkotron . [(20200112 2235) ((emacs (26 1)) (org (9 3))) "Org-mode link selector" tar ((:commit . "d0adc5247b205bc73d2f1a83d4a512d2be541eb5") (:authors ("Per Weijnitz" . "per.weijnitz@gmail.com")) (:maintainer "Per Weijnitz" . "per.weijnitz@gmail.com") (:keywords "hypermedia" "org") (:url . "https://gitlab.com/perweij/org-linkotron"))]) (org-listcruncher . [(20210706 1741) ((seq (2 3)) (emacs (26 1))) "Planning tool - Parse Org mode lists into table" single ((:commit . "075e0e6d36eb50406a608bc8a2f0dd359ec63938") (:authors ("Derek Feichtinger" . "dfeich@gmail.com")) (:maintainer "Derek Feichtinger" . "dfeich@gmail.com") (:keywords "convenience") (:url . "https://github.com/dfeich/org-listcruncher"))]) @@ -3611,17 +3616,17 @@ (org-make-toc . [(20200409 1436) ((emacs (26 1)) (dash (2 12)) (s (1 10 0)) (org (9 0))) "Automatic tables of contents for Org files" single ((:commit . "43d4a2490a048b01ca5a6f44c5b4f24a458dfc95") (:authors ("Adam Porter" . "adam@alphapapa.net")) (:maintainer "Adam Porter" . "adam@alphapapa.net") (:keywords "org" "convenience") (:url . "http://github.com/alphapapa/org-make-toc"))]) (org-mime . [(20230321 2341) ((emacs (25 1))) "org html export for text/html MIME emails" single ((:commit . "d368bd4119bfcf2997a6a23bbf5f41e043164d29") (:authors ("Eric Schulte")) (:maintainer "Chen Bin" . "chenbin.sh@gmail.com") (:keywords "mime" "mail" "email" "html") (:url . "http://github.com/org-mime/org-mime"))]) (org-mind-map . [(20180826 2340) ((emacs (24)) (dash (1 8 0)) (org (8 2 10))) "Creates a directed graph from org-mode files" single ((:commit . "41df4b2e30455494f1848b4e06cc9208aa9e902b") (:authors ("Ted Wiles" . "theodore.wiles@gmail.com")) (:maintainer "Ted Wiles" . "theodore.wiles@gmail.com") (:keywords "orgmode" "extensions" "graphviz" "dot") (:url . "https://github.com/theodorewiles/org-mind-map"))]) - (org-ml . [(20230309 2) ((emacs (27 1)) (org (9 3)) (dash (2 17)) (s (1 12))) "Functional Org Mode API" tar ((:commit . "90ce9ba627422b768449d397986e4d2c7944de15") (:authors ("Nathan Dwarshuis" . "ndwar@yavin4.ch")) (:maintainer "Nathan Dwarshuis" . "ndwar@yavin4.ch") (:keywords "org-mode" "outlines") (:url . "https://github.com/ndwarshuis/org-ml"))]) + (org-ml . [(20230401 230) ((emacs (27 1)) (org (9 3)) (dash (2 17)) (s (1 12))) "Functional Org Mode API" tar ((:commit . "d1a942df35c0b37413ac335f89651cf46688df79") (:authors ("Nathan Dwarshuis" . "ndwar@yavin4.ch")) (:maintainer "Nathan Dwarshuis" . "ndwar@yavin4.ch") (:keywords "org-mode" "outlines") (:url . "https://github.com/ndwarshuis/org-ml"))]) (org-mobile-sync . [(20180606 524) ((emacs (24 3 50)) (org (8 0))) "automatically sync org-mobile on changes" single ((:commit . "06764b943a528827df1e2acc6bc7806cc2c1351f") (:authors ("steckerhalter")) (:maintainer "steckerhalter") (:keywords "org-mode" "org" "mobile" "sync" "todo") (:url . "https://framagit.org/steckerhalter/org-mobile-sync"))]) (org-modern . [(20230312 852) ((emacs (27 1)) (compat (29 1 4 0))) "Modern looks for Org" single ((:commit . "b614ad31d72c49f9eb29d3836995fd7fb0d1fd4a") (:authors ("Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainer "Daniel Mendler" . "mail@daniel-mendler.de") (:url . "https://github.com/minad/org-modern"))]) (org-movies . [(20210920 101) ((emacs (26 1)) (org (9 0)) (request (0 3 0))) "Manage watchlist with Org mode" single ((:commit . "e96fecaffa2924de64a507aa31d2934e667ee1ea") (:authors ("Anh T Nguyen")) (:maintainer "Anh T Nguyen") (:keywords "hypermedia" "outlines" "org") (:url . "https://github.com/teeann/org-movies"))]) - (org-mpv-notes . [(20221202 1657) ((emacs (27 1)) (mpv (0 2 0))) "Take notes in org mode while watching videos in mpv" single ((:commit . "8c123996044cfb87101da6c5f16634188f019cca") (:authors ("Bibek Panthi" . "bpanthi977@gmail.com")) (:maintainer "Bibek Panthi" . "bpanthi977@gmail.com") (:url . "https://github.com/bpanthi977/org-mpv-notes"))]) + (org-mpv-notes . [(20230406 359) ((emacs (27 1)) (mpv (0 2 0))) "Take notes in org mode while watching videos in mpv" single ((:commit . "c437a51aef646839437d6eb699ba86bc530b52b7") (:authors ("Bibek Panthi" . "bpanthi977@gmail.com")) (:maintainer "Bibek Panthi" . "bpanthi977@gmail.com") (:url . "https://github.com/bpanthi977/org-mpv-notes"))]) (org-mru-clock . [(20230104 1922) ((emacs (26 1))) "Clock in/out of tasks with completion and persistent history" single ((:commit . "be90bc9084b384d8a728d68f69da09171ca26d3c") (:authors ("Kevin Brubeck Unhammer" . "unhammer@fsfe.org")) (:maintainer "Kevin Brubeck Unhammer" . "unhammer@fsfe.org") (:keywords "convenience" "calendar") (:url . "https://github.com/unhammer/org-mru-clock"))]) (org-msg . [(20230127 520) ((emacs (24 4)) (htmlize (1 54))) "Org mode to send and reply to email in HTML." single ((:commit . "7b1dfb96d558f6e5626e96d4f4a5150d55cb7eb2") (:authors ("Jérémy Compostella" . "jeremy.compostella@gmail.com")) (:maintainer "Jérémy Compostella" . "jeremy.compostella@gmail.com") (:keywords "extensions" "mail") (:url . "https://github.com/jeremy-compostella/org-msg"))]) (org-multi-wiki . [(20210324 1820) ((emacs (26 1)) (dash (2 12)) (s (1 12)) (org-ql (0 5)) (org (9 3))) "Multiple wikis based on Org mode" single ((:commit . "bf8039aadddaf02569fab473f766071ef7e63563") (:authors ("Akira Komamura" . "akira.komamura@gmail.com")) (:maintainer "Akira Komamura" . "akira.komamura@gmail.com") (:keywords "org" "outlines" "files") (:url . "https://github.com/akirak/org-multi-wiki"))]) (org-multiple-keymap . [(20191017 1920) ((org (8 2 4)) (emacs (24)) (cl-lib (0 5))) "Set keymap to elements, such as timestamp and priority." single ((:commit . "4eb8aa0aada012b2346cc7f0c55e07783141a2c3") (:authors ("myuhe ")) (:maintainer "myuhe") (:keywords "convenience" "org-mode") (:url . "https://github.com/myuhe/org-multiple-keymap.el"))]) (org-notebook . [(20170322 452) ((emacs (24)) (org (8)) (cl-lib (0 5))) "Ease the use of org-mode as a notebook" single ((:commit . "d90c4aeca2442161e6dd89de175561af85aace03") (:authors ("Paul Elder" . "paul.elder@amanokami.net")) (:maintainer "Paul Elder" . "paul.elder@amanokami.net") (:keywords "convenience" "tools"))]) - (org-noter . [(20230315 111) ((emacs (24 4)) (cl-lib (0 6)) (org (9 0))) "A synchronized, Org-mode, document annotator" tar ((:commit . "228a3c8f62d7c020770dfa5dbc4d7e4bfa84ea9d") (:authors ("Gonçalo Santos (github.com/weirdNox)" . "in@bsentia") (" Maintainer Dmitry M" . "dmitrym@gmail.com")) (:maintainer "Peter Mao" . "peter.mao@gmail.com") (:keywords "lisp" "pdf" "interleave" "annotate" "external" "sync" "notes" "documents" "org-mode") (:url . "https://github.com/org-noter/org-noter"))]) + (org-noter . [(20230404 307) ((emacs (24 4)) (cl-lib (0 6)) (org (9 0))) "A synchronized, Org-mode, document annotator" tar ((:commit . "a24ba82f5c9ad2f2a93bd71ab60b78547a94463d") (:authors ("Gonçalo Santos (github.com/weirdNox)" . "in@bsentia") (" Maintainer Dmitry M" . "dmitrym@gmail.com")) (:maintainer "Peter Mao" . "peter.mao@gmail.com") (:keywords "lisp" "pdf" "interleave" "annotate" "external" "sync" "notes" "documents" "org-mode") (:url . "https://github.com/org-noter/org-noter"))]) (org-noter-pdftools . [(20220320 300) ((emacs (26 1)) (org (9 4)) (pdf-tools (0 8)) (org-pdftools (1 0)) (org-noter (1 4 1))) "Integration between org-pdftools and org-noter" single ((:commit . "c88130c90aac5a4759849df86fb1829db183bed4") (:authors ("Alexander Fu Xi" . "fuxialexander@gmail.com")) (:maintainer "Alexander Fu Xi" . "fuxialexnader@gmail.com") (:keywords "convenience") (:url . "https://github.com/fuxialexander/org-pdftools"))]) (org-notifications . [(20210918 1827) ((emacs (25 1)) (org (9 0)) (sound-wav (0 2)) (alert (1 2)) (seq (2 21))) "Creates notifications for org-mode entries" tar ((:commit . "b8032f8adfbeb328962a5657c6dd173e64cc76e5") (:authors ("doppelc")) (:maintainer "doppelc") (:keywords "outlines") (:url . "https://github.com/doppelc/org-notifications"))]) (org-octopress . [(20170821 415) ((org (9 0)) (orglue (0 1)) (ctable (0 1 1))) "Compose octopress articles using org-mode." tar ((:commit . "38598ef98d04076a8eb78d549907ddfde8d3a652") (:authors ("Yoshinari Nomura" . "nom@quickhack.net")) (:maintainer "Yoshinari Nomura" . "nom@quickhack.net") (:keywords "org" "jekyll" "octopress" "blog"))]) @@ -3664,7 +3669,7 @@ (org-roam-ui . [(20221105 1040) ((emacs (27 1)) (org-roam (2 0 0)) (simple-httpd (20191103 1446)) (websocket (1 13))) "User Interface for Org-roam" tar ((:commit . "5ac74960231db0bf7783c2ba7a19a60f582e91ab") (:authors ("Kirill Rogovoy, Thomas Jorna")) (:maintainer "Kirill Rogovoy, Thomas Jorna") (:keywords "files" "outlines") (:url . "https://github.com/org-roam/org-roam-ui"))]) (org-ros . [(20220320 1705) ((emacs (24 1))) "Rahul's Org-Mode Screenshot" single ((:commit . "70e0f33ee027ca1dce68351ad14a9e47a452fc17") (:authors ("Rahul Martim Juliato" . "rahul.juliato@gmail.com")) (:maintainer "Rahul Martim Juliato" . "rahul.juliato@gmail.com") (:url . "https://github.com/LionyxML/ros"))]) (org-rtm . [(20160214 1236) ((rtm (0 1))) "Simple import/export from rememberthemilk to org-mode" single ((:commit . "adc42ad1fbe92ab447ccc9553780f4456f2508d2") (:authors ("Philipp Middendorf" . "pmidden@secure.mailbox.org")) (:maintainer "Philipp Middendorf" . "pmidden@secure.mailbox.org") (:keywords "outlines" "data") (:url . "https://github.com/pmiddend/org-rtm"))]) - (org-runbook . [(20230120 140) nil "Org mode for runbooks" tar ((:commit . "be8218d66493c122a60049ff5e6bd41abfaabbd8") (:authors ("Tyler Dodge")) (:maintainer "Tyler Dodge") (:keywords "convenience" "processes" "terminals" "files") (:url . "https://github.com/tyler-dodge/org-runbook"))]) + (org-runbook . [(20230330 325) ((emacs (26 1)) (seq (2 3)) (f (0 20 0)) (s (1 12 0)) (dash (2 17 0)) (mustache (0 24)) (ht (0 9)) (ivy (0 8 0))) "Org mode for runbooks" tar ((:commit . "3de6e4e31cd240a2ba128287a3d1bc550c253144") (:authors ("Tyler Dodge")) (:maintainer "Tyler Dodge") (:keywords "convenience" "processes" "terminals" "files") (:url . "https://github.com/tyler-dodge/org-runbook"))]) (org-scrum . [(20200131 1129) ((emacs (24 5)) (org (8 2)) (seq (2 3)) (cl-lib (1 0))) "org mode extensions for scrum planning and reporting" single ((:commit . "a383348ea80c2459bfb96fa0652b98f0059bd311") (:authors ("Ian Martins" . "ianxm@jhu.edu")) (:maintainer "Ian Martins" . "ianxm@jhu.edu") (:url . "https://github.com/ianxm/emacs-scrum"))]) (org-seek . [(20161217 502) ((emacs (24 3)) (ag (0 48))) "Searching Org-mode files with search tools." single ((:commit . "1f51e6634e3b9a6a29d335d0d14370a6ffef2265") (:authors ("stardiviner" . "numbchild@gmail.com")) (:maintainer "stardiviner" . "numbchild@gmail.com") (:keywords "org" "search" "ag" "pt") (:url . "https://github.com/stardiviner/org-seek.el"))]) (org-shoplist . [(20210629 2157) ((emacs (25))) "Eat the world" single ((:commit . "71ea7643e66c97d21df49fb8b600578ca0464f83") (:authors ("lordnik22")) (:maintainer "lordnik22") (:keywords "extensions" "matching") (:url . "https://github.com/lordnik22"))]) @@ -3683,7 +3688,7 @@ (org-table-color . [(20220311 1927) ((emacs (26 1))) "Add color to your org-mode table cells" single ((:commit . "2022f301ef323953c3a0e087a1b601da85e06da1") (:authors ("Colin Woodbury" . "colin@fosskers.ca")) (:maintainer "Colin Woodbury" . "colin@fosskers.ca") (:keywords "data" "faces" "lisp") (:url . "https://github.com/fosskers/org-table-color"))]) (org-table-comment . [(20120209 1851) nil "Org table comment modes." single ((:commit . "33b9966c33ecbc3e27cca67c2f2cdea04364d74e") (:authors ("Matthew L. Fidler ")) (:maintainer "Matthew L. Fidler") (:keywords "org-mode" "orgtbl") (:url . "http://github.com/mlf176f2/org-table-comment.el"))]) (org-table-sticky-header . [(20190924 506) ((org (8 2 10)) (emacs (24 4))) "Sticky header for org-mode tables" single ((:commit . "b65442857128ab04724aaa301e60aa874a31a798") (:authors ("Junpeng Qiu" . "qjpchmail@gmail.com")) (:maintainer "Junpeng Qiu" . "qjpchmail@gmail.com") (:keywords "extensions"))]) - (org-tag-beautify . [(20230316 419) ((emacs (26 1)) (org-pretty-tags (0 2 2)) (all-the-icons (5 0 0))) "Beautify Org mode tags" single ((:commit . "caa38e550e3c1e9f9a472cfcc94ea4db3775d9b4") (:keywords "hypermedia") (:url . "https://repo.or.cz/org-tag-beautify.git"))]) + (org-tag-beautify . [(20230402 554) ((emacs (26 1)) (org-pretty-tags (0 2 2)) (all-the-icons (5 0 0))) "Beautify Org mode tags" single ((:commit . "a9ec18a5b8132178b1c9f5a9e00680f4af295ba3") (:keywords "hypermedia") (:url . "https://repo.or.cz/org-tag-beautify.git"))]) (org-tagged . [(20220926 2048) ((s (1 13 0)) (dash (2 19 1)) (emacs (28 1)) (org (9 5 2))) "Dynamic block for tagged org-mode todos" single ((:commit . "4b0174473772fca976426e982bb3f4a3037c1e37") (:authors ("Christian Köstlin" . "christian.koestlin@gmail.com")) (:maintainer "Christian Köstlin" . "christian.koestlin@gmail.com") (:keywords "org-mode" "org" "gtd" "tools") (:url . "http://github.com/gizmomogwai/org-tagged"))]) (org-tanglesync . [(20200127 1616) ((emacs (24 4))) "Syncing org src blocks with tangled external files" single ((:commit . "31aa5502d1d4f8b032807949908c016b00556684") (:authors ("Mehmet Tekman")) (:maintainer "Mehmet Tekman") (:keywords "outlines") (:url . "https://github.com/mtekman/org-tanglesync.el"))]) (org-tfl . [(20170923 1218) ((org (0 16 2)) (cl-lib (0 5)) (emacs (24 1))) "Transport for London meets Orgmode" tar ((:commit . "f0d7d39106a1de5457f5160cddd98ab892b61066") (:authors ("storax (David Zuber), ")) (:maintainer "storax (David Zuber), ") (:keywords "org" "tfl") (:url . "https://github.com/storax/org-tfl"))]) @@ -3705,7 +3710,7 @@ (org-visibility . [(20220929 1415) ((emacs (27 1))) "Persistent org tree visibility" single ((:commit . "afa4b6f8ff274df87eb11f1afd0321084a45a2ab") (:authors ("Kyle W T Sherman" . "kylewsherman@gmail.com")) (:maintainer "Kyle W T Sherman" . "kylewsherman@gmail.com") (:keywords "outlines" "convenience") (:url . "https://github.com/nullman/emacs-org-visibility"))]) (org-wc . [(20200731 2244) nil "Count words in org mode trees." single ((:commit . "dbbf794e4ec6c4080d945f43338185e34a4a582d") (:authors ("Simon Guest")) (:maintainer "Simon Guest"))]) (org-web-tools . [(20201212 1058) ((emacs (25 1)) (org (9 0)) (dash (2 12)) (esxml (0 3 4)) (s (1 10 0)) (request (0 3 0))) "Display and capture web content with Org-mode" tar ((:commit . "b94a07add8558ef7b0666173dbb8a2554f1d41a6") (:authors ("Adam Porter" . "adam@alphapapa.net")) (:maintainer "Adam Porter" . "adam@alphapapa.net") (:keywords "hypermedia" "outlines" "org" "web") (:url . "http://github.com/alphapapa/org-web-tools"))]) - (org-wild-notifier . [(20230211 2354) ((alert (1 2)) (async (1 9 3)) (dash (2 18 0)) (emacs (24 4))) "Customizable org-agenda notifications" single ((:commit . "4bbf7e90886122b1320ee793a00ef6a27a797c25") (:authors ("Artem Khramov" . "akhramov+emacs@pm.me")) (:maintainer "Artem Khramov" . "akhramov+emacs@pm.me") (:keywords "notification" "alert" "org" "org-agenda" "agenda") (:url . "https://github.com/akhramov/org-wild-notifier.el"))]) + (org-wild-notifier . [(20230323 920) ((alert (1 2)) (async (1 9 3)) (dash (2 18 0)) (emacs (24 4))) "Customizable org-agenda notifications" single ((:commit . "cdca8be45b80ab52077a915e77c625bc0ad07dd7") (:authors ("Artem Khramov" . "akhramov+emacs@pm.me")) (:maintainer "Artem Khramov" . "akhramov+emacs@pm.me") (:keywords "notification" "alert" "org" "org-agenda" "agenda") (:url . "https://github.com/akhramov/org-wild-notifier.el"))]) (org-working-set . [(20220414 1402) ((org (9 3)) (dash (2 12)) (s (1 12)) (emacs (26 3))) "Manage and visit a small set of org-nodes." single ((:commit . "6af54ed3a5d9bf90629223157803c42f5d3b152c") (:authors ("Marc Ihm" . "1@2484.de")) (:maintainer "Marc Ihm" . "1@2484.de") (:url . "https://github.com/marcIhm/org-working-set"))]) (org-wunderlist . [(20191017 1917) ((request-deferred (0 2 0)) (alert (1 1)) (emacs (24)) (cl-lib (0 5)) (org (8 2 4)) (s (1 9 0))) "Org sync with Wunderlist" single ((:commit . "1a084bb49be4b5a1066db9cd9b7da2f8efab293f") (:authors ("myuhe ")) (:maintainer "myuhe") (:keywords "convenience") (:url . "https://github.com/myuhe/org-wunderlist.el"))]) (org-zettelkasten . [(20230108 1326) ((emacs (25 1)) (org (9 3))) "A Zettelkasten mode leveraging Org" tar ((:commit . "8002c96d94cb89a0f5af03974f6d1eaea45e1e41") (:authors ("Yann Herklotz" . "yann@ymhg.org")) (:maintainer "Yann Herklotz" . "yann@ymhg.org") (:keywords "files" "hypermedia" "org" "notes") (:url . "https://sr.ht/~ymherklotz/org-zettelkasten"))]) @@ -3722,8 +3727,9 @@ (orgit-forge . [(20230212 2013) ((emacs (25 1)) (compat (29 1 3 4)) (forge (0 3)) (magit (3 3)) (org (9 5)) (orgit (1 8))) "Org links to Forge issue buffers" single ((:commit . "6f424ff3a2df7d9c00c217011949c1367cc15227") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "hypermedia" "vc") (:url . "https://github.com/magit/orgit-forge"))]) (orglink . [(20230212 2213) ((emacs (25 1)) (compat (29 1 3 4)) (org (9 5)) (seq (2 23))) "Use Org Mode links in other modes" single ((:commit . "168d46a33476c4c8ce56818faa6183421b16d211") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "hypermedia") (:url . "https://github.com/tarsius/orglink"))]) (orglue . [(20200411 311) ((org (9 3)) (epic (0 2))) "more functionality to org-mode." tar ((:commit . "9d5a8e24be9acb8c55bb4d6aa8b98e30e2677401") (:authors ("Yoshinari Nomura" . "nom@quickhack.net")) (:maintainer "Yoshinari Nomura" . "nom@quickhack.net") (:keywords "org"))]) + (orgmdb . [(20230312 2231) ((emacs (27 1)) (dash (2 11 0)) (s (1 12 0)) (org (8 0 0))) "An OMDb API client with some convenience functions" single ((:commit . "385a747f41130b714207432045161915eb65b206") (:authors ("Isa Mert Gurbuz" . "isamert@protonmail.com")) (:maintainer "Isa Mert Gurbuz" . "isamert@protonmail.com") (:url . "https://github.com/isamert/orgmdb"))]) (orgnav . [(20170608 1713) ((helm (2 7 0)) (s (1 11 0)) (dash (1 11 0)) (emacs (24))) "Org tree navigation using helm" tar ((:commit . "9e2cac9c1a67af5f0080e60022e821bf7b70312d") (:authors ("Facet Framer" . "facet@facetframer.com")) (:maintainer "Facet Framer" . "facet@facetframer.com") (:keywords "convenience" "outlines") (:url . "http://github.com/facetframer/orgnav"))]) - (orgstrap . [(20230202 235) ((emacs (24 4))) "Bootstrap an Org file using file local variables" single ((:commit . "3cf0fec936fc0dc72bd7bd970fa91d445e763af4") (:authors ("Tom Gillespie")) (:maintainer "Tom Gillespie") (:keywords "lisp" "org" "org-mode" "bootstrap") (:url . "https://github.com/tgbugs/orgstrap"))]) + (orgstrap . [(20230327 650) ((emacs (24 4))) "Bootstrap an Org file using file local variables" single ((:commit . "045600b52dc5277b4fe4ec11fe140b1e7240f1f9") (:authors ("Tom Gillespie")) (:maintainer "Tom Gillespie") (:keywords "lisp" "org" "org-mode" "bootstrap") (:url . "https://github.com/tgbugs/orgstrap"))]) (orgtbl-aggregate . [(20230205 836) ((emacs (26 1))) "Create an aggregated Org table from another one" single ((:commit . "4f9fcb4f7380b247d628b899135df23c8fc8b6f1") (:keywords "data" "extensions") (:url . "https://github.com/tbanel/orgaggregate/blob/master/README.org"))]) (orgtbl-ascii-plot . [(20230122 816) nil "ascii-art bar plots in org-mode tables" single ((:commit . "4160128045b271bc1aef3d14dbf0c5b53ae58bd2") (:authors ("Thierry Banel tbanelwebmin at free dot fr") ("Michael Brand")) (:maintainer "Thierry Banel tbanelwebmin at free dot fr") (:keywords "org" "table" "ascii" "plot"))]) (orgtbl-fit . [(20230110 1544) ((emacs (24 4))) "Regression-fit a column in an Org Mode table" single ((:commit . "5bde4902187b2578dc39ee3a02cd7c84c4470b8a") (:authors ("Thierry Banel tbanelwebmin at free dot fr")) (:maintainer "Thierry Banel tbanelwebmin at free dot fr") (:keywords "data" "extensions") (:url . "https://github.com/tbanel/orgtblfit/blob/master/README.org"))]) @@ -3735,7 +3741,7 @@ (orthodox-christian-new-calendar-holidays . [(20210830 1657) nil "Feasts (NS)" single ((:commit . "6869024ecd45eefd0ec648979c6a59d7c79770e0") (:authors ("Carson Chittom" . "carson@wistly.net")) (:maintainer "Carson Chittom" . "carson@wistly.net") (:keywords "calendar") (:url . "https://github.com/cmchittom/orthodox-christian-new-calendar-holidays"))]) (osa . [(20200522 2103) ((emacs (25 1))) "OSA (JavaScript / AppleScript) bridge" tar ((:commit . "615ca9eef4131a23d9971691fa0d0f20fe59d01b") (:authors ("xristos" . "xristos@sdf.org")) (:maintainer "xristos" . "xristos@sdf.org") (:keywords "extensions") (:url . "https://github.com/atomontage/osa"))]) (osa-chrome . [(20201122 1639) ((emacs (25 1)) (osa (1 0))) "Google Chrome remote tab control" tar ((:commit . "9148e21cf2e91b357f5ea3a349975e8b89c8d5e4") (:authors ("xristos" . "xristos@sdf.org")) (:maintainer "xristos" . "xristos@sdf.org") (:keywords "comm") (:url . "https://github.com/atomontage/osa-chrome"))]) - (osm . [(20230314 155) ((emacs (27 1)) (compat (29 1 4 0))) "OpenStreetMap viewer" tar ((:commit . "8246774ad883c097dd63e95f114bbc825ac04cff") (:authors ("Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainer "Daniel Mendler" . "mail@daniel-mendler.de") (:url . "https://github.com/minad/osm"))]) + (osm . [(20230405 1939) ((emacs (27 1)) (compat (29 1 4 0))) "OpenStreetMap viewer" tar ((:commit . "b3d90704b4e3caa5bf94216124ecdb9f9ae15207") (:authors ("Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainer "Daniel Mendler" . "mail@daniel-mendler.de") (:url . "https://github.com/minad/osm"))]) (osx-browse . [(20140508 2041) ((string-utils (0 3 2)) (browse-url-dwim (0 6 6))) "Web browsing helpers for OS X" single ((:commit . "838b81625853e04919fbb56fd21f387762b2e3f5") (:authors ("Roland Walker" . "walker@pobox.com")) (:maintainer "Roland Walker" . "walker@pobox.com") (:keywords "hypermedia" "external") (:url . "http://github.com/rolandwalker/osx-browse"))]) (osx-clipboard . [(20141012 717) nil "Use the OS X clipboard from terminal Emacs" single ((:commit . "e46dd31327a3f92f77b013b4c9b1e5fdd0e5c73d") (:authors ("Jon Oddie ")) (:maintainer "Jon Oddie ") (:url . "https://github.com/joddie/osx-clipboard-mode"))]) (osx-dictionary . [(20220801 1542) ((cl-lib (0 5))) "Interface for OSX Dictionary.app" tar ((:commit . "0715e5a3ac659df32a0f0fabfbbeef0228fbd9a9") (:authors ("Chunyang Xu" . "mail@xuchunyang.me")) (:maintainer "Chunyang Xu" . "mail@xuchunyang.me") (:keywords "mac" "dictionary") (:url . "https://github.com/xuchunyang/osx-dictionary.el"))]) @@ -3749,7 +3755,7 @@ (other-emacs-eval . [(20180408 1348) ((emacs (25 1)) (async (1 9 2))) "Evaluate the Emacs Lisp expression in other Emacs" single ((:commit . "8ace5acafef65daabf0c6619eff60733d7f5d792") (:authors ("Xu Chunyang" . "mail@xuchunyang.me")) (:maintainer "Xu Chunyang" . "mail@xuchunyang.me") (:keywords "tools") (:url . "https://github.com/xuchunyang/other-emacs-eval"))]) (ouroboros . [(20221229 1731) ((emacs (27 1)) (dash (2 19 0)) (cbor (0 2 3)) (bech32 (0 2 1))) "Ouroboros network mini-protocol" single ((:commit . "fb7d4deee41816bf6d79004b2301a1275fa87402") (:authors ("Oscar Najera ")) (:maintainer "Oscar Najera" . "hi@oscarnajera.com") (:url . "https://github.com/Titan-C/cardano.el"))]) (outline-magic . [(20180619 1819) nil "outline mode extensions for Emacs" single ((:commit . "2a5f07417b696cf7541d435c43bafcc64817636b") (:authors ("Carsten Dominik" . "dominik@science.uva.nl")) (:maintainer "Thorsten Jolitz ") (:keywords "outlines"))]) - (outline-minor-faces . [(20230312 1635) ((emacs (25 1)) (compat (29 1 3 4))) "Headings faces for outline-minor-mode" single ((:commit . "02170814fe6feb14b31cf00af7c8c2df5918fd12") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "faces" "outlines") (:url . "https://github.com/tarsius/outline-minor-faces"))]) + (outline-minor-faces . [(20230407 1051) ((emacs (25 1)) (compat (29 1 3 4))) "Headings faces for outline-minor-mode" single ((:commit . "0e7cd26d4ebe9a1c842645bd3535fc835d16fdf4") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "faces" "outlines") (:url . "https://github.com/tarsius/outline-minor-faces"))]) (outline-toc . [(20200401 1208) nil "Sidebar showing a \"table of contents\"." single ((:commit . "81d373633b40628cc3a6b6fb534fd7730076bcdb") (:authors ("Austin Bingham" . "austin.bingham@gmail.com")) (:maintainer "Austin Bingham" . "austin.bingham@gmail.com") (:keywords "convenience" "outlines") (:url . "https://github.com/abingham/outline-toc.el"))]) (outlook . [(20180428 1430) ((emacs (24 4))) "send emails in MS Outlook style" tar ((:commit . "b6a7a06b996d84647e8024412876e9e76ca884e4") (:authors ("Andrew Savonichev")) (:maintainer "Andrew Savonichev") (:keywords "mail") (:url . "https://github.com/asavonic/outlook.el"))]) (outorg . [(20190720 2002) ((emacs (24 4))) "Org-style comment editing" single ((:commit . "ef0f86f4b893b30be8bcf8b43a5ec357a6c70f07") (:maintainer "Adam Porter" . "adam@alphapapa.net") (:url . "https://github.com/alphapapa/outorg"))]) @@ -3787,12 +3793,12 @@ (ox-nikola . [(20151114 1116) ((emacs (24 4)) (org (8 2 4)) (ox-rst (0 2))) "Export Nikola articles using org-mode." single ((:commit . "5bcbc1a38f6619f62294194f13ca0cd4ca14dd48") (:authors ("IGARASHI Masanao" . "syoux2@gmail.com")) (:maintainer "IGARASHI Masanao" . "syoux2@gmail.com") (:keywords "org" "nikola") (:url . "https://github.com/masayuko/ox-nikola"))]) (ox-pandoc . [(20230128 1219) ((org (8 2)) (emacs (24 4)) (dash (2 8)) (ht (2 0))) "An Org-mode exporter using pandoc" single ((:commit . "66c32cca4f6047dd7e0f77f10bd565a2d83d4729") (:authors ("KAWABATA, Taichi" . "kawabata.taichi@gmail.com") ("FENTON, Alex" . "a-fent@github")) (:maintainer "FENTON, Alex" . "a-fent@github") (:keywords "tools") (:url . "https://github.com/a-fent/ox-pandoc"))]) (ox-pukiwiki . [(20150124 1716) ((org (8 1))) "Pukiwiki Back-End for Org Export Engine" single ((:commit . "b53920abf698fa6682623d671108393e92c68bd7") (:authors ("Yasushi SHOJI" . "yasushi.shoji@gmail.com")) (:maintainer "Yasushi SHOJI" . "yasushi.shoji@gmail.com") (:keywords "org" "pukiwiki") (:url . "https://github.com/yashi/org-pukiwiki"))]) - (ox-qmd . [(20221127 702) ((emacs (24 4))) "Qiita Markdown Back-End for Org Export Engine" single ((:commit . "026e4bd227589b3500294a56c2eca43b3405f992") (:authors ("0x60DF" . "0x60DF@gmail.com")) (:maintainer "0x60DF" . "0x60DF@gmail.com") (:keywords "wp") (:url . "https://github.com/0x60df/ox-qmd"))]) + (ox-qmd . [(20230325 1315) ((emacs (27 2)) (request (0 3 3)) (mimetypes (1 0))) "Qiita Markdown Back-End for Org Export Engine" tar ((:commit . "0b5fa1e20aaa48d93600e1b8d09c3b6f55af3373") (:authors ("0x60DF" . "0x60DF@gmail.com")) (:maintainer "0x60DF" . "0x60DF@gmail.com") (:keywords "wp") (:url . "https://github.com/0x60df/ox-qmd"))]) (ox-report . [(20220910 951) ((emacs (24 4)) (org-msg (3 9))) "Export your org file to minutes report PDF file" single ((:commit . "029fac8d4c83cc8841ade0dfebc8b7d7508efbb2") (:authors ("Matthias David" . "matthias@gnu.re")) (:maintainer "Matthias David" . "matthias@gnu.re") (:keywords "org" "outlines" "report" "exporter" "meeting" "minutes") (:url . "https://github.com/DarkBuffalo/ox-report"))]) (ox-reveal . [(20221127 814) ((org (8 3))) "reveal.js Presentation Back-End for Org Export Engine" single ((:commit . "f55c851bf6aeb1bb2a7f6cf0f2b7bd0e79c4a5a0") (:authors ("Yujie Wen ")) (:maintainer "Yujie Wen ") (:keywords "outlines" "hypermedia" "slideshow" "presentation"))]) (ox-review . [(20220619 724) ((emacs (26 1)) (org (9))) "Re:VIEW Back-End for Org Export Engine" single ((:commit . "f7dc418f9812088afc0ee0d08f778a5654686ef3") (:authors ("Masashi Fujimoto")) (:maintainer "Masashi Fujimoto") (:keywords "outlines" "hypermedia") (:url . "https://github.com/masfj/ox-review"))]) (ox-rfc . [(20220604 1114) ((emacs (24 3)) (org (8 3))) "RFC Back-End for Org Export Engine" single ((:commit . "f0fe3503f8732ea5e95a4016c6b7ce5b47cf6295") (:authors ("Christian Hopps" . "chopps@devhopps.com")) (:maintainer "Christian Hopps" . "chopps@devhopps.com") (:keywords "org" "rfc" "wp" "xml") (:url . "https://github.com/choppsv1/org-rfc-export"))]) - (ox-rss . [(20230129 1538) ((emacs (26 1)) (org (9 3))) "RSS 2.0 Back-End for Org Export Engine" single ((:commit . "81e2eea65e0654e9022f3f732b6cf9dc942423d1") (:authors ("Bastien Guerry" . "bzg@gnu.org")) (:maintainer "Benedict Wang" . "foss@bhw.name") (:keywords "org" "wp" "blog" "feed" "rss") (:url . "https://github.com/benedicthw/ox-rss.git"))]) + (ox-rss . [(20230324 157) ((emacs (26 1)) (org (9 3))) "RSS 2.0 Back-End for Org Export Engine" single ((:commit . "aceff7c50e9d8ace97cefc09ca265a11e75e4d68") (:authors ("Bastien Guerry" . "bzg@gnu.org")) (:maintainer "Benedict Wang" . "foss@bhw.name") (:keywords "org" "wp" "blog" "feed" "rss") (:url . "https://github.com/benedicthw/ox-rss.git"))]) (ox-rst . [(20200815 1511) ((emacs (25 1)) (org (8 3))) "Export reStructuredText using org-mode." single ((:commit . "99fa790da55b57a3f2e9aa187493ba434a64250e") (:authors ("Masanao Igarashi" . "syoux2@gmail.com")) (:maintainer "Masanao Igarashi" . "syoux2@gmail.com") (:keywords "org" "rst" "rest" "restructuredtext") (:url . "https://github.com/msnoigrs/ox-rst"))]) (ox-slack . [(20200108 1546) ((emacs (24)) (org (9 1 4)) (ox-gfm (1 0))) "Slack Exporter for org-mode" single ((:commit . "c55b003f4ac343d6c6d8ef7cbe01d0d100abac34") (:authors ("Matt Price")) (:maintainer "Matt Price") (:keywords "org" "slack" "outlines") (:url . "https://github.com/titaniumbones/ox-slack"))]) (ox-spectacle . [(20230307 316) ((emacs (28 1)) (org (8 3))) "Spectacle.js Presentation Back-End for Org Export Engine" single ((:commit . "85c617200587eb3f7954c278b6cde44f8d43fd87") (:authors ("lorniu" . "lorniu@gmail.com")) (:maintainer "lorniu" . "lorniu@gmail.com") (:keywords "convenience") (:url . "https://github.com/lorniu/ox-spectacle"))]) @@ -3812,7 +3818,7 @@ (pacfiles-mode . [(20200915 1815) ((emacs (26)) (cl-lib (0 5))) "pacnew and pacsave merging tool" tar ((:commit . "8d06f64abc98c3f3338560c8d6eb47719e034069") (:authors ("Carlos G. Cordero ")) (:maintainer "Carlos G. Cordero" . "pacfiles@binarycharly.com") (:keywords "files" "pacman" "arch" "pacnew" "pacsave" "update" "linux") (:url . "https://github.com/UndeadKernel/pacfiles-mode"))]) (pack . [(20191017 456) ((emacs (24)) (cl-lib (0 5))) "Pack and unpack archive files" single ((:commit . "85cd856fdc00a2365e88b50373b99f1b3d2227be") (:authors ("10sr" . "8.slashes@gmail.com")) (:maintainer "10sr" . "8.slashes@gmail.com") (:keywords "files" "dired") (:url . "https://github.com/10sr/pack-el"))]) (package+ . [(20210124 640) ((emacs (24 3))) "Extensions for the package library." tar ((:commit . "06fbc904e09d3349b669c2624a587fee5accf5ef") (:authors ("Ryan Davis" . "ryand-ruby@zenspider.com")) (:maintainer "Ryan Davis" . "ryand-ruby@zenspider.com") (:keywords "extensions" "tools") (:url . "https://github.com/zenspider/package"))]) - (package-build . [(20230319 1115) ((emacs (26 1))) "Tools for assembling a package archive" tar ((:commit . "974406211f9c9d6549f80ca33f6ba8797cb2b11f") (:authors ("Donald Ephraim Curtis" . "dcurtis@milkbox.net") ("Steve Purcell" . "steve@sanityinc.com") ("Jonas Bernoulli" . "jonas@bernoul.li") ("Phil Hagelberg" . "technomancy@gmail.com")) (:maintainer "Donald Ephraim Curtis" . "dcurtis@milkbox.net") (:keywords "maint" "tools") (:url . "https://github.com/melpa/package-build"))]) + (package-build . [(20230329 1735) ((emacs (26 1))) "Tools for assembling a package archive" tar ((:commit . "70ad610a996f6289cc24586af6ca885f784688fc") (:authors ("Donald Ephraim Curtis" . "dcurtis@milkbox.net") ("Steve Purcell" . "steve@sanityinc.com") ("Jonas Bernoulli" . "jonas@bernoul.li") ("Phil Hagelberg" . "technomancy@gmail.com")) (:maintainer "Donald Ephraim Curtis" . "dcurtis@milkbox.net") (:keywords "maint" "tools") (:url . "https://github.com/melpa/package-build"))]) (package-filter . [(20161122 719) nil "package archive whitelist and blacklist" single ((:commit . "c8e2531227c02c4c5e9d593f2cdb6a4ab4a6849b") (:authors ("Donald Ephraim Curtis" . "dcurtis@milkbox.net")) (:maintainer "Donald Ephraim Curtis" . "dcurtis@milkbox.net") (:url . "https://github.com/milkypostman/package-filter"))]) (package-lint . [(20230315 1052) ((cl-lib (0 5)) (emacs (24 1)) (let-alist (1 0 6))) "A linting library for elisp package authors" tar ((:commit . "78ae823bd89d83299a0d7a52797d2593d03e9795") (:authors ("Steve Purcell" . "steve@sanityinc.com") ("Fanael Linithien" . "fanael4@gmail.com")) (:maintainer "Steve Purcell" . "steve@sanityinc.com") (:keywords "lisp") (:url . "https://github.com/purcell/package-lint"))]) (package-lint-flymake . [(20230315 1052) ((emacs (26 1)) (package-lint (0 5))) "A package-lint Flymake backend" single ((:commit . "78ae823bd89d83299a0d7a52797d2593d03e9795") (:url . "https://github.com/purcell/package-lint"))]) @@ -3884,7 +3890,7 @@ (pd-remote . [(20230314 428) ((emacs (24 3)) (faust-mode (0 6)) (lua-mode (20210802))) "Pd remote control helper" single ((:commit . "dcd68097d2b7468303517d91cb76682bfb47db63") (:authors ("Albert Graef" . "aggraef@gmail.com")) (:maintainer "Albert Graef" . "aggraef@gmail.com") (:keywords "multimedia" "pure-data") (:url . "https://github.com/agraef/pd-remote"))]) (pdb-capf . [(20200419 1237) ((emacs (25 1))) "Completion-at-point function for python debugger" single ((:commit . "2f4099aa1330f87df4e9cd526de057ee9b71de6c") (:authors ("Andrii Kolomoiets" . "andreyk.mad@gmail.com")) (:maintainer "Andrii Kolomoiets" . "andreyk.mad@gmail.com") (:keywords "languages" "abbrev" "convenience") (:url . "https://github.com/muffinmad/emacs-pdb-capf"))]) (pdb-mode . [(20150128 1751) nil "Major mode for editing Protein Data Bank files" single ((:commit . "855fb18ebb73b5df30c8d7677c2bcd0f361b138a") (:authors (nil . "charles.bond@uwa.edu.au")) (:maintainer nil . "aix.bing@gmail.com") (:keywords "data" "pdb") (:url . "http://bondxray.org/software/pdb-mode/"))]) - (pdf-tools . [(20230117 632) ((emacs (26 3)) (tablist (1 0)) (let-alist (1 0 4))) "Support library for PDF documents" tar ((:commit . "bc2ba117e8c3196ff9adf0da4fa1e63a8da3d7c8") (:authors ("Andreas Politz" . "mail@andreas-politz.de")) (:maintainer "Vedang Manerikar" . "vedang.manerikar@gmail.com") (:keywords "files" "multimedia") (:url . "http://github.com/vedang/pdf-tools/"))]) + (pdf-tools . [(20230404 327) ((emacs (26 3)) (tablist (1 0)) (let-alist (1 0 4))) "Support library for PDF documents" tar ((:commit . "7ff6293a25baaae65651b3e1c54b61208279a7ef") (:authors ("Andreas Politz" . "mail@andreas-politz.de")) (:maintainer "Vedang Manerikar" . "vedang.manerikar@gmail.com") (:keywords "files" "multimedia") (:url . "http://github.com/vedang/pdf-tools/"))]) (pdf-view-restore . [(20190904 1708) ((pdf-tools (0 90)) (emacs (26 0))) "Support for opening last known pdf position in pdfview mode" single ((:commit . "5a1947c01a3edecc9e0fe7629041a2f53e0610c9") (:authors ("Kevin Kim" . "kevinkim1991@gmail.com")) (:maintainer "Kevin Kim" . "kevinkim1991@gmail.com") (:keywords "files" "convenience") (:url . "https://github.com/007kevin/pdf-view-restore"))]) (pdfgrep . [(20210203 1730) ((emacs (24 4))) "run `pdfgrep' and display the results." single ((:commit . "a4ca0a1e6521de93f28bb6736a5344b4974d144c") (:authors ("Jérémy Compostella" . "jeremy.compostella@gmail.com")) (:maintainer "Jérémy Compostella" . "jeremy.compostella@gmail.com") (:keywords "extensions" "mail" "pdf" "grep") (:url . "https://github.com/jeremy-compostella/pdfgrep"))]) (peacock-theme . [(20170808 1320) ((emacs (24 0))) "an Emacs 24 theme based on Peacock (tmTheme)" single ((:commit . "9e46fbfb562b6e26c6e3d6d618b044b3694da4c8") (:authors ("Jason Milkins")) (:maintainer "Jason Milkins") (:url . "https://github.com/emacsfodder/tmtheme-to-deftheme"))]) @@ -3933,10 +3939,10 @@ (php-mode . [(20230318 2134) ((emacs (26 1))) "Major mode for editing PHP code" tar ((:commit . "47e0813079cea6243139da2b6efedd36940367c8") (:authors ("Eric James Michael Ritz")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "languages" "php") (:url . "https://github.com/emacs-php/php-mode"))]) (php-quickhelp . [(20210819 2025) ((emacs (25 1))) "Quickhelp at point for php" single ((:commit . "d5e11b7a6bad64550521e8822139a33218b8c9bb") (:authors ("Vincenzo Pupillo")) (:maintainer "Vincenzo Pupillo") (:url . "https://github.com/vpxyz/php-quickhelp"))]) (php-refactor-mode . [(20171124 635) nil "Minor mode to quickly and safely perform common refactorings" single ((:commit . "d06dabd9ca743a04067e02282b69d7b7467fb4b7") (:authors ("Matthew M. Keeler" . "keelerm84@gmail.com")) (:maintainer "Matthew M. Keeler" . "keelerm84@gmail.com") (:keywords "php" "refactor") (:url . "https://github.com/keelerm84/php-refactor-mode.el"))]) - (php-runtime . [(20221009 1955) ((emacs (25 1)) (s (1 7))) "Language binding bridge to PHP" single ((:commit . "36e6ae862cb02104b5782a563f0a5846c00e0082") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "processes" "php") (:url . "https://github.com/emacs-php/php-runtime.el"))]) + (php-runtime . [(20230404 1713) ((emacs (25 1)) (compat (29))) "Language binding bridge to PHP" tar ((:commit . "ba64f30e716f89f9cf2c3bd44c5d00da69736868") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "processes" "php" "lisp") (:url . "https://github.com/emacs-php/php-runtime.el"))]) (php-scratch . [(20210706 459) ((emacs (24 3)) (s (1 11 0)) (php-mode (1 17 0))) "A scratch buffer to interactively evaluate php code" single ((:commit . "b6bfd279da8a8ac7fc30459485956f3fd5d02573") (:authors ("Tijs Mallaerts" . "tijs.mallaerts@gmail.com")) (:maintainer "Tijs Mallaerts" . "tijs.mallaerts@gmail.com") (:url . "https://github.com/mallt/php-scratch"))]) (phpactor . [(20221023 608) ((emacs (25 1)) (f (0 17)) (php-runtime (0 2)) (composer (0 2 0)) (async (1 9 3))) "Interface to Phpactor" tar ((:commit . "dde09addf36017527441a855054406f8ffc4e534") (:authors ("USAMI Kenta" . "tadsan@zonu.me") ("Mikael Kermorgant" . "mikael@kgtech.fi")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "tools" "php") (:url . "https://github.com/emacs-php/phpactor.el"))]) - (phpstan . [(20221105 2112) ((emacs (24 3)) (php-mode (1 22 3))) "Interface to PHPStan" single ((:commit . "8b4be09defe5856a1855c976474ada67557780cd") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "tools" "php") (:url . "https://github.com/emacs-php/phpstan.el"))]) + (phpstan . [(20230404 1351) ((emacs (24 3)) (compat (29)) (php-mode (1 22 3)) (php-runtime (0 2))) "Interface to PHPStan" single ((:commit . "6dc8f1df29f22f0b0ef839c66822d48e2c7b1848") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "tools" "php") (:url . "https://github.com/emacs-php/phpstan.el"))]) (phpt-mode . [(20190512 1809) ((emacs (25)) (polymode (0 1 5)) (php-mode (1 21 2))) "Major mode for editing PHPT test code" single ((:commit . "deb386f1a81003074c476f15e1975d445ff6df01") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "languages" "php") (:url . "https://github.com/emacs-php/phpt-mode"))]) (phpunit . [(20230124 743) ((s (1 12 0)) (f (0 19 0)) (pkg-info (0 6)) (cl-lib (0 5)) (emacs (24 3))) "Launch PHP unit tests using phpunit" tar ((:commit . "4a36906344c0abc11f48cc08cd8d50a9f46963f8") (:authors ("Nicolas Lamirault" . "nicolas.lamirault@gmail.com") ("Eric Hansen" . "hansen.c.eric@gmail.com")) (:maintainer "Nicolas Lamirault" . "nicolas.lamirault@gmail.com") (:keywords "tools" "php" "tests" "phpunit") (:url . "https://github.com/nlamirault/phpunit.el"))]) (pianobar . [(20201002 1756) nil "thin wrapper for Pianobar, a Pandora Radio client" single ((:commit . "d708417608df4f09ee565fddaad03dfe181829a8") (:authors ("Aaron Griffith" . "aargri@gmail.com")) (:maintainer "Aaron Griffith" . "aargri@gmail.com") (:url . "http://github.com/agrif/pianobar.el"))]) @@ -4039,7 +4045,7 @@ (powerline . [(20221110 1956) ((cl-lib (0 2))) "Rewrite of Powerline" tar ((:commit . "c35c35bdf5ce2d992882c1f06f0f078058870d4a") (:authors ("Donald Ephraim Curtis" . "dcurtis@milkbox.net")) (:maintainer "Donald Ephraim Curtis" . "dcurtis@milkbox.net") (:keywords "mode-line") (:url . "http://github.com/milkypostman/powerline/"))]) (powerline-evil . [(20190603 340) ((evil (1 0 8)) (powerline (2 3))) "Utilities for better Evil support for Powerline" tar ((:commit . "b77e2cf571e9990734f2b30d826f3a362b559fd1") (:authors ("Chris Johnson" . "chris@christophermjohnson.net")) (:maintainer "Chris Johnson" . "chris@christophermjohnson.net") (:keywords "evil" "mode-line" "powerline") (:url . "http://github.com/johnson-christopher/powerline-evil/"))]) (powershell . [(20220805 1712) ((emacs (24))) "Mode for editing PowerShell scripts" single ((:commit . "f2da15857e430206e215a3c65289b4058ae3c976") (:authors ("Frédéric Perrin ")) (:maintainer "Frédéric Perrin ") (:keywords "powershell" "languages") (:url . "http://github.com/jschaf/powershell.el"))]) - (powerthesaurus . [(20230321 1459) ((emacs (26 1)) (jeison (1 0 0))) "Powerthesaurus integration" single ((:commit . "8bcc2a7f7d1751e34291a1983885da3ebb8c3023") (:keywords "convenience" "writing") (:url . "http://github.com/SavchenkoValeriy/emacs-powerthesaurus"))]) + (powerthesaurus . [(20230402 1904) ((emacs (26 1)) (jeison (1 0 0)) (s (1 13 0))) "Powerthesaurus integration" single ((:commit . "782df1d92f95acc100bc33d4b5f17fe6bad88682") (:keywords "convenience" "writing") (:url . "http://github.com/SavchenkoValeriy/emacs-powerthesaurus"))]) (ppcompile . [(20220619 1535) ((emacs (25 1))) "Ping-pong compile projects on remote machines" single ((:commit . "4c287c9ebc0e78dbbe75195bb5eb3fe82e0bfaff") (:authors ("Guangwang Huang" . "whatacold@gmail.com")) (:maintainer "Guangwang Huang") (:keywords "tools") (:url . "https://github.com/whatacold/ppcompile"))]) (ppd-sr-speedbar . [(20151108 1224) ((sr-speedbar (20140914 2339)) (project-persist-drawer (0 0 4))) "Sr Speedbar adaptor for project-persist-drawer." tar ((:commit . "19d3e924407f40a6bb38c8fe427a159af755adce") (:authors ("Robert Dallas Gray")) (:maintainer "Robert Dallas Gray") (:keywords "projects" "drawer") (:url . "https://github.com/rdallasgrayppd-sr-speedbar"))]) (ppp . [(20220211 1529) ((emacs (25 1))) "Extended pretty printer for Emacs Lisp" single ((:commit . "d5d854c3006dfd268e62c7f91c2aad6f86a505b5") (:authors ("Naoya Yamashita" . "conao3@gmail.com")) (:maintainer "Naoya Yamashita" . "conao3@gmail.com") (:keywords "tools") (:url . "https://github.com/conao3/ppp.el"))]) @@ -4098,7 +4104,7 @@ (prompt-text . [(20190408 310) nil "Configure your minibuffer prompt" single ((:commit . "b842bf13c53d0a2bd2bc7a00d37cc713d69fa9e9") (:authors ("10sr <8slashes+el [at] gmail [dot] com>")) (:maintainer "10sr <8slashes+el [at] gmail [dot] com>") (:keywords "utility" "minibuffer") (:url . "https://github.com/10sr/prompt-text-el"))]) (prompts . [(20160916 1041) ((dash (2 13 0))) "utilities for working with text prompts." single ((:commit . "1cd5e732ff2a86b47836eb7252e5b59cd4b6ab26") (:authors ("Ben Moon" . "guiltydolphin@gmail.com")) (:maintainer "Ben Moon" . "guiltydolphin@gmail.com") (:keywords "input" "minibuffer") (:url . "https://github.com/guiltydolphin/prompts.el"))]) (pronto . [(20200218 1633) ((emacs (24))) "Compilation mode for pronto stylechecks" single ((:commit . "c0cd13d8219879610b7fe284b182a9db4d3d40b3") (:authors ("Julian Rubisch" . "julian@julianrubisch.at")) (:maintainer "Julian Rubisch" . "julian@julianrubisch.at") (:keywords "processes" "tools") (:url . "https://github.com/julianrubisch/pronto.el"))]) - (proof-general . [(20230317 2001) ((emacs (25 2))) "A generic Emacs interface for proof assistants" tar ((:commit . "4a4a5cc8f4be16c1748ac81f0213ee981ffc42f9") (:maintainer nil . "proof-general-maintainers@groupes.renater.fr") (:url . "https://proofgeneral.github.io/"))]) + (proof-general . [(20230407 909) ((emacs (25 2))) "A generic Emacs interface for proof assistants" tar ((:commit . "911cf014b899212815c2ec8d3e8c8b88be0df57b") (:maintainer nil . "proof-general-maintainers@groupes.renater.fr") (:url . "https://proofgeneral.github.io/"))]) (prop-menu . [(20150728 1118) ((emacs (24 3)) (cl-lib (0 5))) "Create and display a context menu based on text and overlay properties" single ((:commit . "50b102c1c0935fd3e0c465feed7f27d66b21cdf3") (:authors ("David Christiansen" . "david@davidchristiansen.dk")) (:maintainer "David Christiansen" . "david@davidchristiansen.dk") (:keywords "convenience") (:url . "https://github.com/david-christiansen/prop-menu-el"))]) (propfont-mixed . [(20150113 2211) ((emacs (24)) (cl-lib (0 5))) "Use proportional fonts with space-based indentation." single ((:commit . "0b461ef4754a469610dba71874a34b6da42176bf") (:authors ("Kirill Ignatiev ")) (:maintainer "Kirill Ignatiev ") (:keywords "faces") (:url . "https://github.com/ikirill/propfont-mixed"))]) (proportional . [(20221205 1417) ((emacs (25 1))) "use a proportional font everywhere" single ((:commit . "6b675694292a5dbebb52b6196e8ccee6e3a73042") (:authors ("Johannes Goslar")) (:maintainer "Johannes Goslar") (:keywords "faces") (:url . "https://github.com/ksjogo/proportional"))]) @@ -4146,8 +4152,8 @@ (pydoc . [(20221222 1426) nil "functional, syntax highlighted pydoc navigation" single ((:commit . "c9d8b5249c1b3814da062ed9976e4137d6e8d869") (:authors ("John Kitchin" . "jkitchin@andrew.cmu.edu")) (:maintainer "Brian J. Lopes" . "statmobile@gmail.com") (:keywords "pydoc" "python") (:url . "https://github.com/statmobile/pydoc"))]) (pyenv-mode . [(20200518 1521) ((pythonic (0 1 0))) "Integrate pyenv with python-mode" single ((:commit . "d191037fe62ed8d4fee5888845da3e2c386d8e89") (:authors ("Artem Malyshev" . "proofit404@gmail.com")) (:maintainer "Artem Malyshev" . "proofit404@gmail.com") (:url . "https://github.com/proofit404/pyenv-mode"))]) (pygen . [(20161121 506) ((elpy (1 12 0)) (python-mode (6 2 2)) (dash (2 13 0))) "Python code generation using Elpy and Python-mode." single ((:commit . "3a5d1d1a0640865b15be05cd1eeb33bb4793b622") (:authors ("Jack Crawley ")) (:maintainer "Jack Crawley ") (:keywords "python" "code generation") (:url . "https://github.com/JackCrawley/pygen/"))]) - (pygn-mode . [(20220531 1422) ((emacs (26 1)) (tree-sitter (0 15 2)) (tree-sitter-langs (0 10 7)) (uci-mode (0 5 4)) (nav-flash (1 0 0)) (ivy (0 10 0))) "Major-mode for chess PGN files, powered by Python" tar ((:commit . "9a56e701cfcdf9024dda15175e0d0fc645446019") (:authors ("Dodge Coates and Roland Walker")) (:maintainer "Dodge Coates and Roland Walker") (:keywords "data" "games" "chess") (:url . "https://github.com/dwcoates/pygn-mode"))]) - (pyim . [(20230316 716) ((emacs (27 1)) (async (1 6)) (xr (1 13))) "A Chinese input method support quanpin, shuangpin, wubi, cangjie and rime." tar ((:commit . "6cc5b76a947938b3b9e842423497a1875b7ca1a0") (:authors ("Ye Wenbin" . "wenbinye@163.com") ("Feng Shu" . "tumashu@163.com")) (:maintainer "Feng Shu" . "tumashu@163.com") (:keywords "convenience" "chinese" "pinyin" "input-method") (:url . "https://github.com/tumashu/pyim"))]) + (pygn-mode . [(20230401 1858) ((emacs (26 1)) (tree-sitter (0 15 2)) (tree-sitter-langs (0 10 7)) (uci-mode (0 5 4)) (nav-flash (1 0 0)) (ivy (0 10 0))) "Major-mode for chess PGN files, powered by Python" tar ((:commit . "8d290f69ce64a5e6f310ffa42c44fd781c20bcfd") (:authors ("Dodge Coates and Roland Walker")) (:maintainer "Dodge Coates and Roland Walker") (:keywords "data" "games" "chess") (:url . "https://github.com/dwcoates/pygn-mode"))]) + (pyim . [(20230404 244) ((emacs (27 1)) (async (1 6)) (xr (1 13))) "A Chinese input method support quanpin, shuangpin, wubi, cangjie and rime." tar ((:commit . "2a66ab1a02c946e4be0c340639ee897bf0d9e1e5") (:authors ("Ye Wenbin" . "wenbinye@163.com") ("Feng Shu" . "tumashu@163.com")) (:maintainer "Feng Shu" . "tumashu@163.com") (:keywords "convenience" "chinese" "pinyin" "input-method") (:url . "https://github.com/tumashu/pyim"))]) (pyim-basedict . [(20220614 1108) nil "The default pinyin dict of pyim" tar ((:commit . "d61af27686f7a39e6c138b7261a686e7ea7a0ef7") (:authors ("Feng Shu" . "tumashu@163.com")) (:maintainer "Feng Shu" . "tumashu@163.com") (:keywords "convenience" "chinese" "pinyin" "input-method" "complete") (:url . "https://github.com/tumashu/pyim-basedict"))]) (pyim-cangjiedict . [(20210617 934) ((pyim (3 7))) "Some cangjie dicts for pyim" tar ((:commit . "d17e3d32a6480939b350a91a915ebe8e6efad819") (:authors ("Yuanchen Xie" . "yuanchen.gm@gmail.com")) (:maintainer "Yuanchen Xie" . "yuanchen.gm@gmail.com") (:keywords "convenience" "chinese" "pinyin" "input-method" "complete") (:url . "https://github.com/p1uxtar/pyim-cangjiedict"))]) (pyim-smzmdict . [(20210505 1445) ((pyim (3 7))) "Sanma(triple) Zhengma dict for pyim" tar ((:commit . "fcddbde17a04d174c7353548056524687f7be8d2") (:authors ("Yue Shi (Zhizhi)")) (:maintainer "Yuanchen Xie") (:keywords "convenience" "i18n" "pyim" "chinese" "zhengma") (:url . "https://github.com/p1uxtar/pyim-smzmdict"))]) @@ -4164,7 +4170,7 @@ (python-cell . [(20230224 1925) ((emacs (25 1))) "Support for MATLAB-like cells in python mode" single ((:commit . "cb8e6381b1fab16bcf475d115bb22fef503bea32") (:authors ("Thomas Hisch" . "t.hisch@gmail.com")) (:maintainer "Thomas Hisch" . "t.hisch@gmail.com") (:keywords "extensions" "python" "matlab" "cell") (:url . "https://github.com/thisch/python-cell.el"))]) (python-coverage . [(20211224 1420) ((emacs (25 1)) (dash (2 18 0)) (s (1 12 0)) (xml+ (1))) "Show Python coverage via overlays or Flycheck" single ((:commit . "a341615af03dbe3ce0ac9b63cf43dc01c1ae5ebe") (:authors ("wouter bolsterlee" . "wouter@bolsterl.ee")) (:maintainer "wouter bolsterlee" . "wouter@bolsterl.ee") (:keywords "languages" "processes" "tools") (:url . "https://github.com/wbolster/emacs-python-coverage"))]) (python-django . [(20150822 404) nil "A Jazzy package for managing Django projects" single ((:commit . "fc54ad74f0309670359b939f64d0f1fff68aeac4") (:authors ("Fabián E. Gallina" . "fabian@anue.biz")) (:maintainer "FSF") (:keywords "languages") (:url . "https://github.com/fgallina/python-django.el"))]) - (python-docstring . [(20230317 1742) nil "Smart Python docstring formatting" tar ((:commit . "3fe87a28acdc83e63191a29fed8649f57d075e3b"))]) + (python-docstring . [(20230326 1929) nil "Smart Python docstring formatting" tar ((:commit . "40f0ca57831a71a9e6437088149784f37704ef6c"))]) (python-environment . [(20150310 853) ((deferred (0 3 1))) "virtualenv API for Emacs Lisp" tar ((:commit . "401006584e32864a10c69d29f14414828909362e") (:authors ("Takafumi Arakaki ")) (:maintainer "Takafumi Arakaki ") (:keywords "applications" "tools"))]) (python-info . [(20151228 1852) nil "Python info manual for Emacs" tar ((:commit . "306f15441b54b25757cdfd3b327b84024ea21ed7"))]) (python-insert-docstring . [(20211127 1232) ((emacs (25 1))) "Python Google docstring inserter" single ((:commit . "cd6419b74c99c06d5c48c1b289572acce1fd193b") (:authors ("Marco Vocialta" . "macurovc@tutanota.com")) (:maintainer "Marco Vocialta" . "macurovc@tutanota.com") (:url . "https://github.com/macurovc/insert-docstring"))]) @@ -4180,7 +4186,7 @@ (pyvenv-auto . [(20230106 415) ((emacs (26 3)) (pyvenv (1 21))) "Automatically switch Python venvs" single ((:commit . "b4365e60e3ba747a5fec8ca909f64fe8c73d8db2") (:url . "https://github.com/nryotaro/pyvenv-auto"))]) (q-mode . [(20221224 2024) ((emacs (24))) "A q editing mode" single ((:commit . "e18a7b40e876a5502d9d2d6d16a356295c555fab") (:keywords "faces" "files" "q") (:url . "https://github.com/psaris/q-mode"))]) (qml-mode . [(20161016 31) nil "Major mode for editing QT Declarative (QML) code." single ((:commit . "6c5f33ba88ae010bf201a80ee8095e20a724558c") (:authors ("Yen-Chin Lee" . "coldnew.tw@gmail.com")) (:maintainer "Yen-Chin Lee" . "coldnew.tw@gmail.com") (:keywords "qml" "qt" "qt declarative") (:url . "https://github.com/coldnew/qml-mode"))]) - (qrencode . [(20230318 1430) ((emacs (25 1))) "QRCode encoder" single ((:commit . "8aaf7cc378dd60436ce07aa744f434d9ba6039a3") (:authors ("Rüdiger Sonderfeld" . "ruediger@c-plusplus.net")) (:maintainer "Rüdiger Sonderfeld" . "ruediger@c-plusplus.net") (:keywords "qrcode" "comm") (:url . "https://github.com/ruediger/qrencode-el"))]) + (qrencode . [(20230324 2335) ((emacs (25 1))) "QRCode encoder" single ((:commit . "d7896e9594d45d7b2622d4617ff9cb7037378167") (:authors ("Rüdiger Sonderfeld" . "ruediger@c-plusplus.net")) (:maintainer "Rüdiger Sonderfeld" . "ruediger@c-plusplus.net") (:keywords "qrcode" "comm") (:url . "https://github.com/ruediger/qrencode-el"))]) (qt-pro-mode . [(20170604 1841) ((emacs (24))) "Qt Pro/Pri major mode" single ((:commit . "1e0052fcfb89c15cb47714c1546d4e8ec6e01ae6") (:authors ("Todd Neal" . "tolchz@gmail.com")) (:maintainer "Todd Neal" . "tolchz@gmail.com") (:keywords "extensions"))]) (qtcreator-theme . [(20201215 1523) ((emacs (24 3))) "A color theme that mimics Qt Creator IDE" single ((:commit . "515532b05063898459157d2ba5c10ec0d5a4b1bd") (:authors ("Lesley Lai" . "lesley@lesleylai.info")) (:maintainer "Lesley Lai" . "lesley@lesleylai.info") (:keywords "theme" "light" "faces") (:url . "https://github.com/LesleyLai/emacs-qtcreator-theme"))]) (quack . [(20181106 1301) nil "enhanced support for editing and running Scheme code" single ((:commit . "2146805ce2b5a9b155d73929986f11e713787e26"))]) @@ -4248,7 +4254,7 @@ (realgud-rdb2 . [(20190520 1146) ((realgud (1 4 5)) (load-relative (1 2)) (cl-lib (0 5)) (emacs (24))) "Realgud front-end for interacting with Ruby debugger2" tar ((:commit . "3594aa74f7afda3c3251bb2af7fe0e8ec6d621ae") (:authors ("Rocky Bernstein")) (:maintainer "Rocky Bernstein") (:url . "http://github.com/rocky/realgud-ruby-debugger2"))]) (realgud-trepan-ni . [(20210513 2237) ((load-relative (1 2)) (realgud (1 5 0)) (emacs (25))) "Realgud front-end to trepan-ni" tar ((:commit . "0ec088ea343835e24ae73da09bea96bfb02a3130") (:authors ("Rocky Bernstein" . "rocky@gnu.org")) (:maintainer "Rocky Bernstein" . "rocky@gnu.org") (:url . "https://github.com/realgud/realgud-trepan-ni"))]) (reaper . [(20220527 2122) ((emacs (26 2))) "Interact with Harvest time tracking app" single ((:commit . "a8ec93656698c5c02a02279ee7d7976325cc74cd") (:authors ("Thomas Fini Hansen" . "xen@xen.dk")) (:maintainer "Thomas Fini Hansen" . "xen@xen.dk") (:keywords "tools") (:url . "https://github.com/xendk/reaper"))]) - (reason-mode . [(20200929 1606) ((emacs (24 3))) "A major mode for editing ReasonML" tar ((:commit . "5690544a7091630e0ea0023bbbd57a733cea8bde") (:authors ("Mozilla")) (:maintainer "Mozilla") (:keywords "languages" "ocaml") (:url . "https://github.com/reasonml-editor/reason-mode"))]) + (reason-mode . [(20230405 517) ((emacs (24 3))) "A major mode for editing ReasonML" tar ((:commit . "d657ff75572a8ea7eda6fe22ada3a2ebf5bc6119") (:authors ("Mozilla")) (:maintainer "Mozilla") (:keywords "languages" "ocaml") (:url . "https://github.com/reasonml-editor/reason-mode"))]) (reazon . [(20211229 1733) ((emacs (26))) "miniKanren for Emacs" tar ((:commit . "da3c4a8acf236eddb73348056e08bea330e868c0") (:authors ("Nick Drozd" . "nicholasdrozd@gmail.com")) (:maintainer "Nick Drozd" . "nicholasdrozd@gmail.com") (:keywords "languages" "extensions" "lisp") (:url . "https://github.com/nickdrozd/reazon"))]) (rebecca-theme . [(20180324 821) ((emacs (24))) "Rebecca Purple Theme" single ((:commit . "1fe3662d1b02caea96e9a780252b2c45f7a49b1d") (:authors ("vic" . "vborja@apache.org")) (:maintainer "vic" . "vborja@apache.org") (:keywords "theme" "dark") (:url . "https://github.com/vic/rebecca-theme"))]) (rebox2 . [(20121113 1300) nil "Handling of comment boxes in various styles." single ((:commit . "00634eca420cc48657b81e40e599ff8548083985") (:authors ("François Pinard") ("Le Wang")) (:maintainer "Le Wang (lewang.emacs!!!gmayo.com remove exclamations, correct host, hint: google mail)") (:url . "https://github.com/lewang/rebox2"))]) @@ -4283,7 +4289,7 @@ (register-quicknav . [(20200524 2006) ((emacs (25 3))) "Quickly jump to next/previous register" single ((:commit . "c15ea92b0946c28b3f14986d42b15b0b534aa6a2") (:authors ("tastytea" . "tastytea@tastytea.de")) (:maintainer "tastytea" . "tastytea@tastytea.de") (:keywords "convenience") (:url . "https://schlomp.space/tastytea/register-quicknav"))]) (rego-mode . [(20201102 1420) ((emacs (24 4)) (reformatter (0 3))) "A major mode for rego language" single ((:commit . "be110e6cef5d34eef0529a8739c68e619cf15310") (:authors ("Sibi Prabakaran" . "sibi@psibi.in")) (:maintainer "Sibi Prabakaran" . "sibi@psibi.in") (:keywords "languages") (:url . "https://github.com/psibi/rego-mode"))]) (related . [(20190327 1024) ((cl-lib (0 5))) "Switch back and forth between similarly named buffers." single ((:commit . "546c7e811b290470288b617f2c27106bd83ccd33") (:authors ("Julien Montmartin")) (:maintainer "Julien Montmartin") (:keywords "file" "buffer" "switch" "selection" "matching" "convenience") (:url . "https://github.com/julien-montmartin/related"))]) - (related-files . [(20230319 705) ((emacs (28 2))) "Easily find files related to the current one" tar ((:commit . "3ae9de03998d4d1f48a847ebe5e8964eb0d02dbc") (:authors ("Damien Cassou" . "damien@cassou.me")) (:maintainer "Damien Cassou" . "damien@cassou.me") (:keywords "tools") (:url . "https://www.gnu.org/software/emacs/"))]) + (related-files . [(20230324 934) ((emacs (28 2))) "Easily find files related to the current one" tar ((:commit . "f3f841f625a51b964b88cfe08378311124cc5240") (:authors ("Damien Cassou" . "damien@cassou.me")) (:maintainer "Damien Cassou" . "damien@cassou.me") (:keywords "tools") (:url . "https://www.gnu.org/software/emacs/"))]) (remark-mode . [(20221123 2127) ((emacs (25 1)) (markdown-mode (2 0))) "Major mode for the remark slideshow tool" tar ((:commit . "5a2a702d2af8fd007ae02237d5824356d0c1acc6") (:authors ("@torgeir")) (:maintainer "@torgeir") (:keywords "remark" "slideshow" "markdown" "hot reload"))]) (remember-last-theme . [(20170619 2133) ((emacs (24 4))) "Remember the last used theme between sessions." single ((:commit . "57e8e2a475ea89316dbb5c4d2ea047f56a2cbcdf") (:authors ("Anler Hernández Peral" . "inbox+emacs@anler.me")) (:maintainer "Anler Hernández Peral" . "inbox+emacs@anler.me") (:keywords "convenience" "faces") (:url . "https://github.com/anler/remember-last-theme"))]) (remind-bindings . [(20200820 1723) ((emacs (25 1)) (omni-quotes (0 5)) (popwin (1 0)) (map (2 0))) "Reminders for your init bindings" single ((:commit . "c9a327bfd3c68a0c41b5b64df491bdee4c73ca39") (:authors ("Mehmet Tekman")) (:maintainer "Mehmet Tekman") (:keywords "outlines") (:url . "https://github.com/mtekman/remind-bindings.el"))]) @@ -4319,7 +4325,7 @@ (review-mode . [(20220817 1010) nil "major mode for ReVIEW" single ((:commit . "2b24db8d85a1c40dbd67be195caa79c9df1e0f4b") (:authors ("Kenshi Muto" . "kmuto@kmuto.jp")) (:maintainer "Kenshi Muto" . "kmuto@kmuto.jp") (:url . "https://github.com/kmuto/review-el"))]) (reykjavik-theme . [(20201219 947) ((emacs (24))) "Theme with a dark background." single ((:commit . "f6d8e83946633603234cd1dac725e17447f40bce") (:authors ("martin haesler")) (:maintainer "martin haesler"))]) (rfc-mode . [(20230307 937) ((emacs (25 1))) "RFC document browser and viewer" single ((:commit . "c938c8134e7434b623ebfd92ad22586205cb1c92") (:authors ("Nicolas Martyanoff" . "nicolas@n16f.net")) (:maintainer "Nicolas Martyanoff" . "nicolas@n16f.net") (:url . "https://github.com/galdor/rfc-mode"))]) - (rg . [(20230318 1152) ((emacs (25 1)) (transient (0 3 0)) (wgrep (2 1 10))) "A search tool based on ripgrep" tar ((:commit . "766e2991fc589bdaa9b610b9a0b76e3c78ada37f") (:authors ("David Landell" . "david.landell@sunnyhill.email") ("Roland McGrath" . "roland@gnu.org")) (:maintainer "David Landell" . "david.landell@sunnyhill.email") (:keywords "matching" "tools") (:url . "https://github.com/dajva/rg.el"))]) + (rg . [(20230401 1434) ((emacs (26 1)) (transient (0 3 0)) (wgrep (2 1 10))) "A search tool based on ripgrep" tar ((:commit . "e8397ea2f9cadda20bf87e3fae71540511b52d9c") (:authors ("David Landell" . "david.landell@sunnyhill.email") ("Roland McGrath" . "roland@gnu.org")) (:maintainer "David Landell" . "david.landell@sunnyhill.email") (:keywords "matching" "tools") (:url . "https://github.com/dajva/rg.el"))]) (rgb . [(20220717 1940) ((emacs (24 3))) "RGB control via OpenRGB" single ((:commit . "4aab5a5be16b69b47ef5e67d02782df5e41dbd7b") (:url . "https://gitlab.com/cwpitts/rgb.el"))]) (rhq . [(20220916 1632) ((emacs (24 4))) "Client for rhq" single ((:commit . "7d9c5dee2e493eb0c5d41afca1b6049de8c2a26d") (:authors ("ROCKTAKEY" . "rocktakey@gmail.com")) (:maintainer "ROCKTAKEY" . "rocktakey@gmail.com") (:keywords "tools" "extensions") (:url . "https://github.com/ROCKTAKEY/rhq"))]) (rhtml-mode . [(20130422 1311) nil "major mode for editing RHTML files" tar ((:commit . "a6d71b38a3db867ccf82999c99805db1a3a33c33"))]) @@ -4338,7 +4344,7 @@ (rivet-mode . [(20201013 1905) ((emacs (24)) (web-mode (16))) "A minor mode for editing Apache Rivet files" single ((:commit . "6cf58cf04fee933113857af07414b3f27c24b505") (:authors ("Jade Michael Thornton")) (:maintainer "Jade Michael Thornton") (:url . "https://gitlab.com/thornjad/rivet-mode"))]) (rjsx-mode . [(20200224 2149) ((emacs (24 4)) (js2-mode (20170504))) "Real support for JSX" single ((:commit . "0061587a06cdc2579a8d0e90863498d96bf982d8") (:authors ("Felipe Ochoa" . "felipe@fov.space")) (:maintainer "Felipe Ochoa" . "felipe@fov.space") (:keywords "languages") (:url . "https://github.com/felipeochoa/rjsx-mode/"))]) (rmsbolt . [(20230309 1751) ((emacs (25 1))) "A compiler output viewer" tar ((:commit . "197fb7b7eeccfa2d3755d723841c7eb1c2a2768c") (:authors ("Jay Kamat" . "jaygkamat@gmail.com")) (:maintainer "Jay Kamat" . "jaygkamat@gmail.com") (:keywords "compilation" "tools") (:url . "http://gitlab.com/jgkamat/rmsbolt"))]) - (robe . [(20221207 225) ((inf-ruby (2 5 1)) (emacs (25 1))) "Code navigation, documentation lookup and completion for Ruby" tar ((:commit . "4ddcc847542ffbba41339e83e462c7d9aaaac860") (:authors ("Dmitry Gutov")) (:maintainer "Dmitry Gutov") (:keywords "ruby" "convenience" "rails") (:url . "https://github.com/dgutov/robe"))]) + (robe . [(20230327 113) ((inf-ruby (2 5 1)) (emacs (25 1))) "Code navigation, documentation lookup and completion for Ruby" tar ((:commit . "a8d2c3293f0760194fd138f346bcc8876cbd8640") (:authors ("Dmitry Gutov")) (:maintainer "Dmitry Gutov") (:keywords "ruby" "convenience" "rails") (:url . "https://github.com/dgutov/robe"))]) (robot-log . [(20220719 1301) ((emacs (28 1))) "Major mode for viewing RobotFramework debug log files" single ((:commit . "26da47597aa97be9649cb60f4da6d94d47d0c0ac") (:keywords "convenience" "files") (:url . "https://git.sr.ht/~apteryx/emacs-robot-log"))]) (robot-mode . [(20221109 1630) ((emacs (26 1))) "Major-mode for Robot Framework files" single ((:commit . "fb9be47a1d4e57a80ae2c0d4dff3eba2fe29ebdc") (:authors ("Kalle Kankare" . "kalle.kankare@iki.fi")) (:maintainer "Kalle Kankare" . "kalle.kankare@iki.fi") (:keywords "languages" "files") (:url . "https://github.com/kopoli/robot-mode"))]) (robots-txt-mode . [(20190812 1858) nil "Major mode for editing robots.txt" single ((:commit . "8bf67285a25a6756607354d184e36583f2847e7d") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "languages" "comm" "web") (:url . "https://github.com/emacs-php/robots-txt-mode"))]) @@ -4374,7 +4380,7 @@ (ruled-switch-buffer . [(20211205 636) ((emacs (24 3))) "Rule based buffer switching" single ((:commit . "99b53f7679e3eb868e4b4585085bbed102e5fce7") (:authors ("Kazuki Nishikawa" . "kzkn@hey.com")) (:maintainer "Kazuki Nishikawa" . "kzkn@hey.com") (:keywords "convenience") (:url . "https://github.com/kzkn/ruled-switch-buffer"))]) (rum-mode . [(20180127 22) ((emacs (24))) "Major mode for Rum programming language" single ((:commit . "161471e6476d232d479f9767535918920811d7bf") (:keywords "rum" "languages" "lisp") (:url . "https://github.com/rumlang/rum-mode"))]) (run-command . [(20230317 2004) ((emacs (27 1))) "Run an external command from a context-dependent list" tar ((:commit . "477c42acce9e36ec59d18deaa73992f94faf7b99") (:authors ("Massimiliano Mirra" . "hyperstruct@gmail.com")) (:maintainer "Massimiliano Mirra" . "hyperstruct@gmail.com") (:keywords "processes") (:url . "https://github.com/bard/emacs-run-command"))]) - (run-command-recipes . [(20230202 1326) ((emacs (25 1)) (dash (2 18 0)) (f (0 20 0)) (run-command (0 1 0))) "This is collection of recipes to `run-command'" tar ((:commit . "60e6fdbe6e8bea3871674a0e5779324ed5dbd318") (:authors ("semenInRussia" . "hrams205@gmail.com")) (:maintainer "semenInRussia" . "hrams205@gmail.com") (:keywords "extensions" "run-command") (:url . "https://github.com/semenInRussia/emacs-run-command-recipes"))]) + (run-command-recipes . [(20230406 1757) ((emacs (25 1)) (dash (2 18 0)) (f (0 20 0)) (run-command (0 1 0))) "This is collection of recipes to `run-command'" tar ((:commit . "adbde3fddd67f1f40b3374c1696af03ac9b72e5e") (:authors ("semenInRussia" . "hrams205@gmail.com")) (:maintainer "semenInRussia" . "hrams205@gmail.com") (:keywords "extensions" "run-command") (:url . "https://github.com/semenInRussia/emacs-run-command-recipes"))]) (run-stuff . [(20230319 459) ((emacs (25 1))) "Context based command execution" single ((:commit . "cd4d250603f0df835dbaf91c45ea603ffd52c416") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:keywords "files" "lisp" "files" "convenience" "hypermedia") (:url . "https://codeberg.org/ideasman42/emacs-run-stuff"))]) (runner . [(20160524 1048) nil "Improved \"open with\" suggestions for dired" single ((:commit . "a211d57ddc600410d07a8b534920ba905b093d87") (:authors ("Thamer Mahmoud" . "thamer.mahmoud@gmail.com")) (:maintainer "Thamer Mahmoud" . "thamer.mahmoud@gmail.com") (:keywords "shell command" "dired" "file extension" "open with") (:url . "https://github.com/thamer/runner"))]) (runtests . [(20150807 831) nil "Run unit tests from Emacs" single ((:commit . "ed90249f24cc48290018df48b9b9b7172440be3e") (:authors ("Sune Simonsen" . "sune@we-knowhow.dk")) (:maintainer "Sune Simonsen" . "sune@we-knowhow.dk") (:keywords "test") (:url . "https://github.com/sunesimonsen/emacs-runtests"))]) @@ -4418,7 +4424,7 @@ (scihub . [(20220913 618) ((emacs (27 1))) "Sci-Hub integration" single ((:commit . "56aa7205b5f2a6c9821557f9f1b9ff76dc1bb882") (:authors ("Mario Rodas" . "marsam@users.noreply.github.com")) (:maintainer "Mario Rodas" . "marsam@users.noreply.github.com") (:keywords "convenience") (:url . "https://github.com/emacs-pe/scihub.el"))]) (sclang-extensions . [(20160509 338) ((auto-complete (1 4 0)) (s (1 3 1)) (dash (1 2 0)) (emacs (24 1))) "Extensions for the SuperCollider Emacs mode." tar ((:commit . "e9cc79732f16fdb582129303110c163dcc0d6da0") (:authors ("Chris Barrett" . "chris.d.barrett@me.com")) (:maintainer "Chris Barrett" . "chris.d.barrett@me.com") (:keywords "sclang" "supercollider" "languages" "tools"))]) (sclang-snippets . [(20130513 751) ((yasnippet (0 8 0))) "Snippets for the SuperCollider Emacs mode" tar ((:commit . "c840a416b96f83bdd70491e3d1fbe2f1ae8b3f58") (:authors ("ptrv" . "mail@petervasil.net")) (:maintainer "ptrv" . "mail@petervasil.net") (:keywords "snippets"))]) - (scopeline . [(20230319 1156) ((emacs (26 1))) "Show scope info of blocks in buffer at end of scope" single ((:commit . "83438c7f08a9142e7998b92d8fef74719353fcaa") (:keywords "scope" "context" "tree-sitter" "convenience") (:url . "https://github.com/meain/scopeline.el"))]) + (scopeline . [(20230327 331) ((emacs (26 1))) "Show scope info of blocks in buffer at end of scope" single ((:commit . "204d2c635e93e0702c15f6d4faf9bffb39ecff7e") (:keywords "scope" "context" "tree-sitter" "convenience") (:url . "https://github.com/meain/scopeline.el"))]) (scpaste . [(20221125 1731) ((htmlize (1 39))) "Paste to the web via scp." single ((:commit . "56c67ef63be86ef1f03e15a62ad17c3983e1e5dc") (:authors ("Phil Hagelberg")) (:maintainer "Phil Hagelberg") (:keywords "convenience" "hypermedia") (:url . "https://git.sr.ht/~technomancy/scpaste"))]) (scratch . [(20220319 1705) ((emacs (25 1))) "Mode-specific scratch buffers" single ((:commit . "f000648c9663833a76a8de9b1e78c99a9d698e48") (:authors ("Ian Eure" . "ian.eure@gmail.com")) (:maintainer "Ian Eure" . "ian.eure@gmail.com") (:keywords "convenience" "tools" "files") (:url . "https://github.com/ieure/scratch-el"))]) (scratch-comment . [(20200812 1025) ((emacs (26 1))) "Insert Elisp result as comment in scratch buffer" single ((:commit . "cf3e967b4def1308b6ef1cfeedd2cf15ee6e226c") (:authors ("Naoya Yamashita" . "conao3@gmail.com")) (:maintainer "Naoya Yamashita" . "conao3@gmail.com") (:keywords "convenience") (:url . "https://github.com/conao3/scratch-comment.el"))]) @@ -4461,7 +4467,7 @@ (sensitive . [(20170818 1251) ((emacs (24)) (sequences (0 1 0))) "A dead simple way to load sensitive information" single ((:commit . "69dd6125a41d8b55f4b6ba61daa4d1aa1f716fa8") (:authors ("Tim Visher" . "tim.visher@gmail.com")) (:maintainer "Tim Visher" . "tim.visher@gmail.com") (:keywords "convenience"))]) (sentence-navigation . [(20220522 1137) ((ample-regexps (0 1)) (cl-lib (0 5)) (emacs (24 4))) "Commands to navigate one-spaced sentences." single ((:commit . "ea6e94a5518643acda5b6e98e4e7f47dfc107d29") (:authors ("Fox Kiester" . "noct@openmailbox.org")) (:maintainer "Fox Kiester" . "noct@openmailbox.org") (:keywords "sentence" "evil") (:url . "https://github.com/noctuid/emacs-sentence-navigation"))]) (seoul256-theme . [(20180505 757) ((emacs (24 3))) "Low-contrast color scheme based on Seoul Colors." single ((:commit . "8e76d0207489964ef780420723d49e409f68f7d1") (:authors ("Anand Iyer" . "anand.ucb@gmail.com")) (:maintainer "Anand Iyer" . "anand.ucb@gmail.com") (:keywords "theme") (:url . "http://github.com/anandpiyer/seoul256-emacs"))]) - (separedit . [(20230201 752) ((emacs (25 1)) (dash (2 18)) (edit-indirect (0 1 5))) "Edit comment/string/docstring/code block in separate buffer" single ((:commit . "03e356f1a645a884921975890899fb47acf7d00d") (:authors ("Gong Qijian" . "gongqijian@gmail.com")) (:maintainer "Gong Qijian" . "gongqijian@gmail.com") (:keywords "tools" "languages" "docs") (:url . "https://github.com/twlz0ne/separedit.el"))]) + (separedit . [(20230403 1242) ((emacs (25 1)) (dash (2 18)) (edit-indirect (0 1 5))) "Edit comment/string/docstring/code block in separate buffer" single ((:commit . "8344e7338a0ab7968cab807e0073934a8444559d") (:authors ("Gong Qijian" . "gongqijian@gmail.com")) (:maintainer "Gong Qijian" . "gongqijian@gmail.com") (:keywords "tools" "languages" "docs") (:url . "https://github.com/twlz0ne/separedit.el"))]) (sequed . [(20220115 743) ((emacs (25 2))) "Major mode for FASTA format DNA alignments" single ((:commit . "c886981c46d199e1522f18c3fc15198ab8c9a02f") (:authors ("Bruce Rannala" . "brannala@ucdavis.edu")) (:maintainer "Bruce Rannala" . "brannala@ucdavis.edu") (:url . "https://github.com/brannala/sequed"))]) (sequences . [(20170818 1252) ((emacs (24))) "Ports of some Clojure sequence functions." single ((:commit . "564ebbd93b0beea4e75acfbf824350e90b5d5738") (:authors ("Tim Visher" . "tim.visher@gmail.com")) (:maintainer "Tim Visher" . "tim.visher@gmail.com") (:keywords "convenience"))]) (sequential-command . [(20170926 40) nil "Many commands into one command" tar ((:commit . "a48cbcbe273b33edd3ae56e68f44b4100fa3a48a") (:authors ("rubikitch" . "rubikitch@ruby-lang.org")) (:maintainer "rubikitch" . "rubikitch@ruby-lang.org") (:keywords "convenience" "lisp") (:url . "http://www.emacswiki.org/cgi-bin/wiki/download/sequential-command.el"))]) @@ -4503,7 +4509,7 @@ (shfmt . [(20220602 1535) ((emacs (24)) (reformatter (0 3))) "Reformat shell scripts using shfmt" single ((:commit . "279a51defa3e0d97dc40b8a26e078699d4e22e90") (:authors ("Steve Purcell" . "steve@sanityinc.com")) (:maintainer "Steve Purcell" . "steve@sanityinc.com") (:keywords "languages") (:url . "https://github.com/purcell/emacs-shfmt"))]) (shift-number . [(20170301 1459) nil "Increase/decrease the number at point" single ((:commit . "94c3713cc11283a831f66d5205d112762edc186b") (:authors ("Alex Kost" . "alezost@gmail.com")) (:maintainer "Alex Kost" . "alezost@gmail.com") (:keywords "convenience") (:url . "https://github.com/alezost/shift-number.el"))]) (shift-text . [(20130831 1655) ((cl-lib (1 0)) (es-lib (0 3))) "Move the region in 4 directions, in a way similar to Eclipse's" single ((:commit . "1be9cbf994000022172ceb746fe1d597f57ea8ba") (:authors ("sabof")) (:maintainer "sabof") (:url . "https://github.com/sabof/shift-text"))]) - (shimbun . [(20230127 612) nil "interfacing with web newspapers" tar ((:commit . "e556f82247918bdc33acf01b29917314b8b9e22b") (:authors ("TSUCHIYA Masatoshi" . "tsuchiya@namazu.org") ("Akihiro Arisawa " . "ari@mbf.sphere.ne.jp") ("Yuuichi Teranishi " . "teranisi@gohome.org") ("Katsumi Yamaoka " . "yamaoka@jpl.org")) (:maintainer "TSUCHIYA Masatoshi" . "tsuchiya@namazu.org") (:keywords "news"))]) + (shimbun . [(20230324 125) nil "interfacing with web newspapers" tar ((:commit . "f8819bca0c97970662cd4214f8f3104ab4a376c1") (:authors ("TSUCHIYA Masatoshi" . "tsuchiya@namazu.org") ("Akihiro Arisawa " . "ari@mbf.sphere.ne.jp") ("Yuuichi Teranishi " . "teranisi@gohome.org") ("Katsumi Yamaoka " . "yamaoka@jpl.org")) (:maintainer "TSUCHIYA Masatoshi" . "tsuchiya@namazu.org") (:keywords "news"))]) (shm . [(20180327 57) nil "Structured Haskell Mode" tar ((:commit . "7f9df73f45d107017c18ce4835bbc190dfe6782e") (:authors ("Chris Done" . "chrisdone@gmail.com")) (:maintainer "Chris Done" . "chrisdone@gmail.com") (:keywords "development" "haskell" "structured"))]) (shoulda . [(20140616 1833) ((cl-lib (0 5))) "Shoulda test support for ruby" single ((:commit . "24dc6b6138a06edde9c8d13a6aaa1654d1d7de54") (:authors ("Marcwebbie" . "marcwebbie@gmail.com")) (:maintainer "Marcwebbie" . "marcwebbie@gmail.com") (:keywords "ruby" "tests" "shoulda"))]) (show-css . [(20160210 1408) ((doom (1 3)) (s (1 10 0))) "Show the css of the html attribute the cursor is on" tar ((:commit . "771daeddd4df7a7c10f66419a837145649bab63b") (:authors ("Sheldon McGrandle" . "developer@rednemesis.com")) (:maintainer "Sheldon McGrandle" . "developer@rednemesis.com") (:keywords "hypermedia") (:url . "https://github.com/smmcg/showcss-mode"))]) @@ -4524,9 +4530,9 @@ (side-notes . [(20210709 1403) ((emacs (24 4))) "Easy access to a directory notes file" single ((:commit . "41fe8544661a772f764a0924e04080f258053955") (:authors ("Paul W. Rankin" . "pwr@bydasein.com")) (:maintainer "Paul W. Rankin" . "pwr@bydasein.com") (:keywords "convenience") (:url . "https://github.com/rnkn/side-notes"))]) (sidecar-locals . [(20230109 536) ((emacs (27 1))) "A flexible alternative to built-in dir-locals" single ((:commit . "882923811e9de84c8ebc2f9fe65e9673d7d1f469") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:keywords "convenience") (:url . "https://codeberg.org/ideasman42/emacs-sidecar-locals"))]) (sideline . [(20230216 843) ((emacs (27 1))) "Show information on the side" single ((:commit . "0441f2c308eb9316f01d721a949ba73b6df8c4c7") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience") (:url . "https://github.com/emacs-sideline/sideline"))]) - (sideline-blame . [(20221231 1636) ((emacs (27 1)) (sideline (0 1 0)) (vc-msg (1 1 1))) "Show blame messages with sideline" single ((:commit . "1a1d80a71bdabe77fe2a33cd681b7188f193acfc") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "blame") (:url . "https://github.com/emacs-sideline/sideline-blame"))]) - (sideline-flycheck . [(20230216 859) ((emacs (27 1)) (sideline (0 1 1)) (flycheck (0 14)) (ht (2 4))) "Show flycheck errors with sideline" single ((:commit . "1f2f82d4383718a8dd2aff40cffafce4a8d0aca1") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "flycheck") (:url . "https://github.com/emacs-sideline/sideline-flycheck"))]) - (sideline-flymake . [(20230216 914) ((emacs (27 1)) (sideline (0 1 0))) "Show flymake errors with sideline" single ((:commit . "e92fa5ca861ff5a54273aecde319974fe4aa9dda") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "flymake") (:url . "https://github.com/emacs-sideline/sideline-flymake"))]) + (sideline-blame . [(20230406 2312) ((emacs (27 1)) (sideline (0 1 0)) (vc-msg (1 1 1))) "Show blame messages with sideline" single ((:commit . "4d3343795bc95662adb65c85bcbb41947862699f") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "blame") (:url . "https://github.com/emacs-sideline/sideline-blame"))]) + (sideline-flycheck . [(20230402 1816) ((emacs (27 1)) (sideline (0 1 1)) (flycheck (0 14)) (ht (2 4))) "Show flycheck errors with sideline" single ((:commit . "3d74a008835eff71899b9455cd00f989378fe70e") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "flycheck") (:url . "https://github.com/emacs-sideline/sideline-flycheck"))]) + (sideline-flymake . [(20230402 1816) ((emacs (27 1)) (sideline (0 1 0))) "Show flymake errors with sideline" single ((:commit . "316325cb050d13f33e83e7d7823e3730a70ecf4e") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "flymake") (:url . "https://github.com/emacs-sideline/sideline-flymake"))]) (sideline-lsp . [(20221231 1636) ((emacs (27 1)) (sideline (0 1 0)) (lsp-mode (6 0)) (dash (2 18 0)) (ht (2 4)) (s (1 12 0))) "Show lsp information with sideline" single ((:commit . "38ba700db1769de216989fb9217795934147d160") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "lsp") (:url . "https://github.com/emacs-sideline/sideline-lsp"))]) (sift . [(20200421 1423) nil "Front-end for sift, a fast and powerful grep alternative" single ((:commit . "cdddba2d183146c340915003f1b5d09d13712c22") (:authors ("Nicolas Lamirault" . "nicolas.lamirault@gmail.com")) (:maintainer "Nicolas Lamirault" . "nicolas.lamirault@gmail.com") (:keywords "sift" "ack" "pt" "ag" "grep" "search") (:url . "https://github.com/nlamirault/sift.el"))]) (signal . [(20160816 1438) ((emacs (24)) (cl-lib (0 5))) "Advanced hook" single ((:commit . "aa58327e2297df921d72a0370468b48663efd438") (:authors ("Mola-T" . "Mola@molamola.xyz")) (:maintainer "Mola-T" . "Mola@molamola.xyz") (:keywords "internal" "lisp" "processes" "tools") (:url . "https://github.com/mola-T/signal"))]) @@ -4550,7 +4556,7 @@ (siri-shortcuts . [(20211229 1833) ((emacs (25 2))) "Interact with Siri Shortcuts" single ((:commit . "190f242f71e071adfd89fa1f2f6ea22b62afd133") (:authors ("Daniils Petrovs" . "thedanpetrov@gmail.com")) (:maintainer "Daniils Petrovs" . "thedanpetrov@gmail.com") (:keywords "convenience" "multimedia") (:url . "https://github.com/DaniruKun/siri-shortcuts.el"))]) (sis . [(20230305 1006) ((emacs (25 1)) (terminal-focus-reporting (0 0))) "Less manual switch for native or OS input source (input method)." single ((:commit . "e4142baa470e5f33dd508bce0264359dc5204b6f") (:keywords "convenience") (:url . "https://github.com/laishulu/emacs-smart-input-source"))]) (sisyphus . [(20230213 1152) ((emacs (27)) (compat (29 1 3 4)) (elx (1 6 0)) (llama (0 3 0)) (magit (3 4 0))) "Create releases of Emacs packages" single ((:commit . "1e6fd5ae0fb5384063e8b59d053bc5df7630cf5c") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "git" "tools" "vc") (:url . "https://github.com/magit/sisyphus"))]) - (sixcolors-mode . [(20221127 1208) ((emacs (27 1))) "A customizable horizontal scrollbar" single ((:commit . "fbcf57749ebc74d7b77d148da6c021b1a8e0f650") (:authors ("Davide Mastromatteo" . "mastro35@gmail.com")) (:maintainer "Davide Mastromatteo" . "mastro35@gmail.com") (:keywords "convenience" "colors") (:url . "https://github.com/mastro35/sixcolors-mode"))]) + (sixcolors-mode . [(20230406 1031) ((emacs (27 1))) "A customizable horizontal scrollbar" single ((:commit . "4124a8cf664b04a4bf4c39f7c3b7da3e480b99c8") (:authors ("Davide Mastromatteo" . "mastro35@gmail.com")) (:maintainer "Davide Mastromatteo" . "mastro35@gmail.com") (:keywords "convenience" "colors") (:url . "https://github.com/mastro35/sixcolors-mode"))]) (skeletor . [(20210129 239) ((s (1 7 0)) (f (0 14 0)) (dash (2 2 0)) (cl-lib (0 3)) (let-alist (1 0 3)) (emacs (24 1))) "Provides project skeletons for Emacs" tar ((:commit . "f6e560a0bfe459e0b8a268047920ce1148f2ebf6") (:authors ("Chris Barrett" . "chris.d.barrett@me.com")) (:maintainer "Chris Barrett" . "chris.d.barrett@me.com"))]) (skerrick . [(20220306 2139) ((emacs (27 1)) (request (0 3 2))) "REPL-driven development for NodeJS" single ((:commit . "015de8369b8b6be0d4d1e21c24239a037350e87e") (:authors ("Rafael Nicdao ")) (:maintainer "Rafael Nicdao" . "nicdaoraf@gmail.com") (:keywords "languages" "javascript" "js" "repl" "repl-driven") (:url . "https://github.com/anonimitoraf/skerrick"))]) (sketch-themes . [(20230210 1507) ((emacs (26 1))) "Sketch color themes" tar ((:commit . "5534254232f1a556ec20952c75b5506625573049") (:authors ("Daw-Ran Liou" . "hi@dawranliou.com")) (:maintainer "Daw-Ran Liou" . "hi@dawranliou.com") (:keywords "faces") (:url . "https://github.com/dawranliou/sketch-themes/"))]) @@ -4573,7 +4579,7 @@ (slow-keys . [(20220807 1425) ((emacs (24 1))) "Slow keys mode to avoid RSI" single ((:commit . "b951ae4bdcea56ced03f227b82b28c3d91d15e61") (:authors ("Manuel Uberti" . "manuel.uberti@inventati.org")) (:maintainer "Manuel Uberti" . "manuel.uberti@inventati.org") (:keywords "convenience") (:url . "https://github.com/manuel-uberti/slow-keys"))]) (slstats . [(20170823 849) ((cl-lib (0 5)) (emacs (24))) "Acquire and display stats about Second Life" single ((:commit . "e9696066abf3f2b7b818a57c062530dfd9377033") (:authors ("Dave Pearson" . "davep@davep.org")) (:maintainer "Dave Pearson" . "davep@davep.org") (:keywords "games") (:url . "https://github.com/davep/slstats.el"))]) (slurm-mode . [(20210519 1109) nil "Interaction with the SLURM job scheduling system" tar ((:commit . "4e6ac09245313cf4018b8e5784b2fca8604269d7") (:url . "https://github.com/ffevotte/slurm.el"))]) - (sly . [(20230224 911) ((emacs (24 3))) "Sylvester the Cat's Common Lisp IDE" tar ((:commit . "f34c22289a2b3ab10e607f9f8822d62bb5c98cf5") (:keywords "languages" "lisp" "sly") (:url . "https://github.com/joaotavora/sly"))]) + (sly . [(20230327 1434) ((emacs (24 3))) "Sylvester the Cat's Common Lisp IDE" tar ((:commit . "82b20a9a83209b4dbfbfb62a1536896aed5f85f7") (:keywords "languages" "lisp" "sly") (:url . "https://github.com/joaotavora/sly"))]) (sly-asdf . [(20221119 2235) ((emacs (24 3)) (sly (1 0 0 -2 2)) (popup (0 5 3))) "ASDF system support for SLY" tar ((:commit . "6f9d751469bb82530db1673c22e7437ca6c95f45") (:maintainer "Matt George" . "mmge93@gmail.com") (:keywords "languages" "lisp" "sly" "asdf") (:url . "https://github.com/mmgeorge/sly-asdf"))]) (sly-hello-world . [(20200225 1755) ((sly (1 0 0 -2 2))) "A template SLY contrib" tar ((:commit . "be257e9ad354db690c7378e89899335597348a0d") (:authors ("João Távora" . "joaotavora@gmail.com")) (:maintainer "João Távora" . "joaotavora@gmail.com") (:keywords "languages" "lisp" "sly") (:url . "https://github.com/capitaomorte/sly-hello-world"))]) (sly-macrostep . [(20191211 1630) ((sly (1 0 0 -2 2)) (macrostep (0 9))) "fancy macro-expansion via macrostep.el" tar ((:commit . "5113e4e926cd752b1d0bcc1508b3ebad5def5fad") (:keywords "languages" "lisp" "sly") (:url . "https://github.com/capitaomorte/sly-macrostep"))]) @@ -4632,7 +4638,7 @@ (snoopy . [(20171008 2004) ((emacs (24)) (cl-lib (0 6))) "minor mode for number row unshifted character insertion" single ((:commit . "ec4123bdebfe0bb7bf4feaac2dc02b59caffe386") (:authors ("António Nuno Monteiro" . "anmonteiro@gmail.com")) (:maintainer "António Nuno Monteiro" . "anmonteiro@gmail.com") (:keywords "lisp"))]) (snow . [(20221226 2238) ((emacs (26 3))) "Let it snow in Emacs!" single ((:commit . "be17977677fa29709a726715a1a1cba1bd299f68") (:authors ("Adam Porter" . "adam@alphapapa.net")) (:maintainer "Adam Porter" . "adam@alphapapa.net") (:keywords "games") (:url . "https://github.com/alphapapa/snow.el"))]) (soar-mode . [(20190503 1843) nil "A major mode for the Soar language" single ((:commit . "ebb79789cd35530aea2c6d0eb4f4b280e97107d4") (:keywords "languages" "soar") (:url . "https://github.com/adeschamps/soar-mode"))]) - (soccer . [(20221127 1534) ((emacs (26 1)) (dash (2 19 1))) "Fixtures, results, table etc for soccer" tar ((:commit . "49d0db4f6274f1bd39c58255be069f79e310f465") (:authors ("Md Arif Shaikh" . "arifshaikh.astro@gmail.com")) (:maintainer "Md Arif Shaikh" . "arifshaikh.astro@gmail.com") (:keywords "games" "soccer" "football") (:url . "https://github.com/md-arif-shaikh/soccer"))]) + (soccer . [(20230403 1518) ((emacs (26 1)) (dash (2 19 1))) "Fixtures, results, table etc for soccer" tar ((:commit . "4515eaa5e12613185f4569c79772db886dcfa2f7") (:authors ("Md Arif Shaikh" . "arifshaikh.astro@gmail.com")) (:maintainer "Md Arif Shaikh" . "arifshaikh.astro@gmail.com") (:keywords "games" "soccer" "football") (:url . "https://github.com/md-arif-shaikh/soccer"))]) (socyl . [(20170212 642) ((s (1 11 0)) (dash (2 12 0)) (pkg-info (0 5 0)) (cl-lib (0 5))) "Frontend for several search tools" tar ((:commit . "1ef2da42f66f3ab31a34131e51648f352416f0ba") (:authors ("Nicolas Lamirault" . "nicolas.lamirault@gmail.com")) (:maintainer "Nicolas Lamirault" . "nicolas.lamirault@gmail.com") (:keywords "ripgrep" "sift" "ack" "pt" "ag" "grep" "search") (:url . "https://github.com/nlamirault/socyl"))]) (soft-charcoal-theme . [(20140420 1643) nil "Dark charcoal theme with soft colors" single ((:commit . "5607ab977fae6638e78b1495e02da8955c9ba19f") (:authors ("Martin Haesler")) (:maintainer "Martin Haesler") (:url . "http://github.com/mswift42/soft-charcoal-theme"))]) (soft-morning-theme . [(20150918 2041) nil "Emacs24 theme with a light background." single ((:commit . "c0f9c70c97ef2be2a093cf839c4bfe27740a111c") (:authors ("Martin Haesler")) (:maintainer "Martin Haesler") (:url . "http://github.com/mswift42/soft-morning-theme"))]) @@ -4664,17 +4670,17 @@ (spaceline-all-the-icons . [(20190325 1602) ((emacs (24 4)) (all-the-icons (2 6 0)) (spaceline (2 0 0)) (memoize (1 0 1))) "A Spaceline theme using All The Icons" tar ((:commit . "5afd48c10f1bd42d9b9648c5e64596b72f3e9042") (:authors ("Dominic Charlesworth" . "dgc336@gmail.com")) (:maintainer "Dominic Charlesworth" . "dgc336@gmail.com") (:keywords "convenience" "lisp" "tools") (:url . "https://github.com/domtronn/spaceline-all-the-icons.el"))]) (spacemacs-theme . [(20230321 2210) nil "Color theme with a dark and light versions" tar ((:commit . "05fe9bc750203960179d456ae4079d582561659c"))]) (spaces . [(20170809 2208) nil "Create and switch between named window configurations." single ((:commit . "6bdb51e9a346907d60a9625f6180bddd06be6674") (:authors ("Steven Thomas")) (:maintainer "Steven Thomas") (:keywords "frames" "convenience") (:url . "https://github.com/chumpage/chumpy-windows"))]) - (spark . [(20211021 1832) ((emacs (24 3))) "sparkline generation" single ((:commit . "c9af24a169b1f1aeba175f1f8d51abda113639af") (:authors ("Alvin Francis Dumalus")) (:maintainer "Alvin Francis Dumalus") (:keywords "lisp" "data") (:url . "https://github.com/alvinfrancis/spark"))]) + (spark . [(20230406 2307) ((emacs (24 3))) "sparkline generation" single ((:commit . "0e58e5122cbb46fb6d850e3b72487431a3696861") (:authors ("Alvin Francis Dumalus")) (:maintainer "Alvin Francis Dumalus") (:keywords "lisp" "data") (:url . "https://github.com/alvinfrancis/spark"))]) (sparkline . [(20150101 1319) ((cl-lib (0 3))) "Make sparkline images from a list of numbers" single ((:commit . "a2b5d817d272d6363b67ed8f8cc75499a19fa8d2") (:authors ("Willem Rein Oudshoorn" . "woudshoo@xs4all.nl")) (:maintainer "Willem Rein Oudshoorn" . "woudshoo@xs4all.nl") (:keywords "extensions"))]) (sparql-mode . [(20230104 1113) ((cl-lib (0 5)) (emacs (24 3))) "Edit and interactively evaluate SPARQL queries." tar ((:commit . "1f6196094ec6626722c6e03a13f6844c68f62703") (:authors ("Craig Andera ")) (:maintainer "Bjarte Johansen ") (:url . "https://github.com/ljos/sparql-mode"))]) (spatial-navigate . [(20230115 633) ((emacs (26 2))) "Directional navigation between white-space blocks" single ((:commit . "11f281ae16b541ede9b4fadf96200e1728eb6ed0") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:url . "https://codeberg.org/ideasman42/emacs-spatial-navigate"))]) - (spdx . [(20230322 110) ((emacs (24 4))) "Insert SPDX license and copyright headers" tar ((:commit . "7692d30983bd3299d42265266edb181d8bbc8d12") (:authors ("Zhiwei Chen" . "condy0919@gmail.com")) (:maintainer "Zhiwei Chen" . "condy0919@gmail.com") (:keywords "license" "tools") (:url . "https://github.com/condy0919/spdx.el"))]) + (spdx . [(20230405 58) ((emacs (24 4))) "Insert SPDX license and copyright headers" tar ((:commit . "b0640e03cc237d2c378a809a6e5acb1ffb2fa97a") (:authors ("Zhiwei Chen" . "condy0919@gmail.com")) (:maintainer "Zhiwei Chen" . "condy0919@gmail.com") (:keywords "license" "tools") (:url . "https://github.com/condy0919/spdx.el"))]) (speech-tagger . [(20170728 1829) ((cl-lib (0 5))) "tag parts of speech using coreNLP" tar ((:commit . "61955b40d4e8b09e66a3e8033e82893f81657c06") (:authors ("Danny McClanahan" . "danieldmcclanahan@gmail.com")) (:maintainer "Danny McClanahan" . "danieldmcclanahan@gmail.com") (:keywords "speech" "tag" "nlp" "language" "corenlp" "parsing" "natural") (:url . "https://github.com/cosmicexplorer/speech-tagger"))]) (speechd-el . [(20220608 1422) nil "Client to speech synthesizers and Braille displays." tar ((:commit . "7e30c439729d5635ddd341ad5ab16f832a4619ea") (:authors ("Milan Zamazal" . "pdm@zamazal.org")) (:maintainer "Milan Zamazal" . "pdm@zamazal.org"))]) (speed-type . [(20230206 1330) ((emacs (26 1)) (compat (29 1 3))) "Practice touch and speed typing" tar ((:commit . "4f8553632d71e827b4da6e091143779d2ad970a8") (:authors ("Gunther Hagleitner")) (:maintainer "Daniel Kraus" . "daniel@kraus.my") (:keywords "games") (:url . "https://github.com/dakra/speed-type"))]) (speedbar-git-respect . [(20200901 246) ((f (0 8 0)) (emacs (25 1))) "Particular respect git repo in speedbar" single ((:commit . "dd8f0849fc1dd21b42380e1a8c28a9a29acd9511") (:authors ("Muromi Ukari" . "chendianbuji@gmail.com")) (:maintainer "Muromi Ukari" . "chendianbuji@gmail.com") (:url . "https://github.com/ukari/speedbar-git-respect"))]) (speeddating . [(20180319 723) ((emacs (25))) "Increase date and time at point" single ((:commit . "eeaf90cd10e376bff5a295590a3d5f7fd1402523") (:authors ("Xu Chunyang" . "mail@xuchunyang.me")) (:maintainer "Xu Chunyang" . "mail@xuchunyang.me") (:keywords "date" "time") (:url . "https://github.com/xuchunyang/emacs-speeddating"))]) - (spell-fu . [(20230319 854) ((emacs (26 2))) "Fast & light spelling highlighter" single ((:commit . "aed6e87aa31013534b7a6cbedb26e4f29ccea735") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:keywords "convenience") (:url . "https://codeberg.org/ideasman42/emacs-spell-fu"))]) + (spell-fu . [(20230326 736) ((emacs (26 2))) "Fast & light spelling highlighter" single ((:commit . "67a26b7a00449ee8ef3a80ab662c93a32adef679") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:keywords "convenience") (:url . "https://codeberg.org/ideasman42/emacs-spell-fu"))]) (sphinx-doc . [(20210213 1250) ((s (1 9 0)) (cl-lib (0 5)) (dash (2 10 0))) "Sphinx friendly docstrings for Python functions" single ((:commit . "1eda612a44ef027e5229895daa77db99a21b8801") (:authors ("Vineet Naik" . "naikvin@gmail.com")) (:maintainer "Vineet Naik" . "naikvin@gmail.com") (:keywords "sphinx" "python") (:url . "https://github.com/naiquevin/sphinx-doc.el"))]) (sphinx-frontend . [(20161025 758) nil "Launch build process for rst documents via sphinx." single ((:commit . "0cbb03361c245382d3e679dded30c4fc1713c252") (:authors ("Kostafey" . "kostafey@gmail.com")) (:maintainer "Kostafey" . "kostafey@gmail.com") (:keywords "compile" "sphinx" "restructuredtext") (:url . "https://github.com/kostafey/sphinx-frontend"))]) (sphinx-mode . [(20220417 1552) ((f (0 20 0)) (dash (2 14 1))) "Minor mode providing sphinx support." tar ((:commit . "77ca51adf9ee877f3a8f43e744f59e650772f121") (:authors ("Matúš Goljer" . "matus.goljer@gmail.com")) (:maintainer "Matúš Goljer" . "matus.goljer@gmail.com") (:keywords "languages"))]) @@ -4703,7 +4709,7 @@ (sr-speedbar . [(20161025 831) nil "Same frame speedbar" single ((:commit . "77a83fb50f763a465c021eca7343243f465b4a47") (:authors ("Sebastian Rose" . "sebastian_rose@gmx.de")) (:maintainer "Sebastian Rose" . "sebastian_rose@gmx.de") (:keywords "speedbar" "sr-speedbar.el") (:url . "http://www.emacswiki.org/emacs/download/sr-speedbar.el"))]) (srcery-theme . [(20210601 1247) ((emacs (24))) "Dark color theme" single ((:commit . "58dd21cd63e4a2eed15e0082c2547069363f107b") (:authors ("Daniel Berg")) (:maintainer "Daniel Berg") (:keywords "faces") (:url . "https://github.com/srcery-colors/srcery-emacs"))]) (srefactor . [(20180703 1810) ((emacs (24 4))) "A refactoring tool based on Semantic parser framework" tar ((:commit . "6f2c97d17fb70f4ca2112f5a2b99a8ec162004f5") (:authors ("Tu, Do Hoang" . "tuhdo1710@gmail.com")) (:maintainer "Tu, Do Hoang") (:keywords "c" "languages" "tools") (:url . "https://github.com/tuhdo/semantic-refactor"))]) - (srfi . [(20230228 2212) ((emacs (25 1))) "Scheme Requests for Implementation browser" tar ((:commit . "5599488e07c538d893e296da1f55fa24ac9f194a") (:authors ("Lassi Kortela" . "lassi@lassi.io")) (:maintainer "Lassi Kortela" . "lassi@lassi.io") (:keywords "languages" "util") (:url . "https://github.com/srfi-explorations/emacs-srfi"))]) + (srfi . [(20230324 2) ((emacs (25 1))) "Scheme Requests for Implementation browser" tar ((:commit . "67de3f09d1e51ba8449ebc00748ad2e285d0ae0e") (:authors ("Lassi Kortela" . "lassi@lassi.io")) (:maintainer "Lassi Kortela" . "lassi@lassi.io") (:keywords "languages" "util") (:url . "https://github.com/srfi-explorations/emacs-srfi"))]) (srv . [(20180715 1959) ((emacs (24 3))) "perform SRV DNS requests" single ((:commit . "714387d5a5cf34d8d8cd96bdb1f9cb8ded823ff7") (:authors ("Magnus Henoch" . "magnus.henoch@gmail.com")) (:maintainer "Magnus Henoch" . "magnus.henoch@gmail.com") (:keywords "comm") (:url . "https://github.com/legoscia/srv.el"))]) (ssass-mode . [(20200211 132) ((emacs (24 3))) "Edit Sass without a Turing Machine" single ((:commit . "96f557887ad97a0066a60c54f92b7234b8407016") (:authors ("Adam Niederer" . "adam.niederer@gmail.com")) (:maintainer "Adam Niederer" . "adam.niederer@gmail.com") (:keywords "languages" "sass") (:url . "http://github.com/AdamNiederer/ssass-mode"))]) (ssh . [(20120904 2042) nil "Support for remote logins using ssh." single ((:commit . "c17cf5b43df8ac4662a0580f85898e1f078df0d1") (:authors ("Noah Friedman" . "friedman@splode.com")) (:maintainer "Ian Eure" . "ian.eure@gmail.com") (:keywords "unix" "comm"))]) @@ -4715,7 +4721,7 @@ (stan-snippets . [(20211129 2051) ((emacs (24 3)) (stan-mode (10 3 0)) (yasnippet (0 8 0))) "Yasnippets for Stan" tar ((:commit . "150bbbe5fd3ad2b5a3dbfba9d291e66eeea1a581") (:authors ("Jeffrey Arnold" . "jeffrey.arnold@gmail.com") ("Kazuki Yoshida" . "kazukiyoshida@mail.harvard.edu")) (:maintainer "Kazuki Yoshida" . "kazukiyoshida@mail.harvard.edu") (:keywords "languages" "tools") (:url . "https://github.com/stan-dev/stan-mode/tree/master/stan-snippets"))]) (standard-dirs . [(20200621 1603) ((emacs (26 1)) (f (0 20 0)) (s (1 7 0))) "Platform-specific paths for config, cache, and other data" single ((:commit . "e37b7e1c714c7798cd8e3a6569e4d71b96718a60") (:authors ("Joseph M LaFreniere" . "joseph@lafreniere.xyz")) (:maintainer "Joseph M LaFreniere" . "joseph@lafreniere.xyz") (:keywords "files") (:url . "https://github.com/lafrenierejm/standard-dirs.el"))]) (standoff-mode . [(20210810 1814) nil "Create stand-off markup, also called external markup." tar ((:commit . "5e603092410d9c393d19050bcbed3014a379f0e6") (:authors ("Christian Lück" . "christian.lueck@ruhr-uni-bochum.de")) (:maintainer "Christian Lück" . "christian.lueck@ruhr-uni-bochum.de") (:keywords "text" "annotations" "ner" "humanities") (:url . "https://github.com/lueck/standoff-mode"))]) - (starlit-theme . [(20230221 1620) ((emacs (25 1))) "Deep blue dark theme with bright colors from the starlit sky" single ((:commit . "5ef623020e6a2d43ac82a2a9b71c434d4e8a0585") (:authors ("Jonas Jelten" . "jj@sft.lol")) (:maintainer "Jonas Jelten" . "jj@sft.lol") (:keywords "faces") (:url . "https://github.com/SFTtech/starlit-emacs"))]) + (starlit-theme . [(20230324 1636) ((emacs (25 1))) "Deep blue dark theme with bright colors from the starlit sky" single ((:commit . "d6f327fb09497be7bee64d5d204d27f655cc5b04") (:authors ("Jonas Jelten" . "jj@sft.lol")) (:maintainer "Jonas Jelten" . "jj@sft.lol") (:keywords "faces") (:url . "https://github.com/SFTtech/starlit-emacs"))]) (start-menu . [(20160426 1225) ((cl-lib (0 5)) (config-parser (0 1))) "start-menu for executing external program like in windows" single ((:commit . "f7d33fed7ad2dc61156f1c1cff9e1805366fbd69") (:authors ("DarkSun" . "lujun9972@gmail.com")) (:maintainer "DarkSun" . "lujun9972@gmail.com") (:keywords "convenience" "menu") (:url . "https://github.com/lujun9972/el-start-menu"))]) (stash . [(20151117 1427) nil "lightweight persistent caching" single ((:commit . "c2e494d20c752b80ebbdffbf66687b3cdfc425ad") (:authors ("Sean Allred" . "code@seanallred.com")) (:maintainer "Sean Allred" . "code@seanallred.com") (:keywords "extensions" "data" "internal" "lisp") (:url . "https://www.github.com/vermiculus/stash.el/"))]) (state . [(20200727 1227) ((emacs (24))) "Quick navigation between workspaces" single ((:commit . "8cd9210f17c1b134274a7352b996839aed9a7d8c") (:authors ("Sylvain Rousseau ")) (:maintainer "Sylvain Rousseau ") (:keywords "convenience" "workspaces") (:url . "https://github.com/thisirs/state.git"))]) @@ -4724,11 +4730,11 @@ (stem . [(20131102 1109) nil "Routines for stemming" single ((:commit . "dd704c3447bd5d3f5ac0a4840f8987d4f855d87e") (:authors ("Tsuchiya Masatoshi" . "tsuchiya@pine.kuee.kyoto-u.ac.jp")) (:maintainer "Tsuchiya Masatoshi" . "tsuchiya@pine.kuee.kyoto-u.ac.jp") (:keywords "stemming") (:url . "https://github.com/yuutayamada/stem"))]) (stem-english . [(20180109 358) ((emacs (24 3))) "- routines for stemming English word" single ((:commit . "c9fc4c6ed6bf82382e479dae80912f4ae17d31f4") (:authors ("Tsuchiya Masatoshi" . "tsuchiya@pine.kuee.kyoto-u.ac.jp")) (:maintainer "KAWABATA, Taichi ") (:keywords "text") (:url . "http://github.com/kawabata/stem-english"))]) (stem-reading-mode . [(20220522 1053) ((emacs (25 1))) "Highlight word stems for speed-reading" single ((:commit . "6efc9962e3a19a452c7ab9636cf1e2566a51bd38") (:authors ("Yuri D'Elia" . "wavexx@thregr.org")) (:maintainer "Yuri D'Elia" . "wavexx@thregr.org") (:keywords "convenience" "wp") (:url . "https://gitlab.com/wavexx/stem-reading-mode.el"))]) - (stgit . [(20230224 2315) nil "major mode for StGit interaction" single ((:commit . "327d1dbed318a21b96d8234b6ee11e58efe442cc") (:authors ("David Kågedal" . "davidk@lysator.liu.se")) (:maintainer "David Kågedal" . "davidk@lysator.liu.se") (:url . "http://stacked-git.github.io"))]) + (stgit . [(20230401 1354) nil "major mode for StGit interaction" single ((:commit . "bd68bebcb0c3ff0127a18b496a1de38e9bcd8fcc") (:authors ("David Kågedal" . "davidk@lysator.liu.se")) (:maintainer "David Kågedal" . "davidk@lysator.liu.se") (:url . "http://stacked-git.github.io"))]) (sticky . [(20170926 36) nil "Sticky key for capital letters" single ((:commit . "fec4e1af38f17f5cd80eca361d8e8ef8772db366") (:authors ("rubikitch" . "rubikitch@ruby-lang.org")) (:maintainer "rubikitch" . "rubikitch@ruby-lang.org") (:keywords "convenience") (:url . "http://www.emacswiki.org/cgi-bin/wiki/download/sticky.el"))]) (sticky-shell . [(20230207 1454) ((emacs (25 1))) "Minor mode to keep track of previous prompt in your shell" single ((:commit . "030535451b7c12eea3a94dfc1a439b8baa96944b") (:authors ("Andrew De Angelis" . "bobodeangelis@gmail.com")) (:maintainer "Andrew De Angelis" . "bobodeangelis@gmail.com") (:keywords "processes" "terminals" "tools") (:url . "https://github.com/andyjda/sticky-shell"))]) (stickyfunc-enhance . [(20150429 1814) ((emacs (24 3))) "An enhancement to stock `semantic-stickyfunc-mode'" single ((:commit . "13bdba51fcd83ccbc3267959d23afc94d458dcb0") (:authors ("Tu, Do Hoang" . "tuhdo1710@gmail.com")) (:maintainer "Tu, Do Hoang") (:keywords "c" "languages" "tools") (:url . "https://github.com/tuhdo/semantic-stickyfunc-enhance"))]) - (stimmung-themes . [(20230227 852) ((emacs (25))) "Themes tuned to inner harmonies" tar ((:commit . "85bee715164c186114d986332b7d694a0c9c068c") (:authors ("Love Lagerkvist")) (:maintainer "Love Lagerkvist") (:keywords "faces") (:url . "https://github.com/motform/stimmung-themes"))]) + (stimmung-themes . [(20230328 1245) ((emacs (25))) "Themes tuned to inner harmonies" tar ((:commit . "edd330a418e39ca06c35993fa6ee6f6f4efea9ee") (:authors ("Love Lagerkvist")) (:maintainer "Love Lagerkvist") (:keywords "faces") (:url . "https://github.com/motform/stimmung-themes"))]) (stock-ticker . [(20150204 1052) ((s (1 9 0)) (request (0 2 0))) "Show stock prices in mode line" single ((:commit . "74251cc810604af75f48333d51133326c053dd16") (:authors ("Gunther Hagleitner")) (:maintainer "Gunther Hagleitner") (:keywords "comms") (:url . "https://github.com/hagleitn/stock-ticker"))]) (stock-tracker . [(20230105 503) ((emacs (27 1)) (dash (2 16 0)) (async (1 9 5))) "Track stock price" single ((:commit . "327488e0f1232616bf33ab1a69da1a53aca25371") (:authors ("Huming Chen" . "chenhuming@gmail.com")) (:maintainer "Huming Chen" . "chenhuming@gmail.com") (:keywords "convenience" "stock" "finance") (:url . "https://github.com/beacoder/stock-tracker"))]) (strace-mode . [(20171116 2039) nil "strace output syntax highlighting" single ((:commit . "2901baa968d5180ab985ac40ca22cc20914d01f5") (:authors ("Preston Moore" . "prestonkmoore@gmail.com")) (:maintainer "Preston Moore" . "prestonkmoore@gmail.com") (:keywords "languages"))]) @@ -4739,7 +4745,7 @@ (string-inflection . [(20220910 1306) nil "underscore -> UPCASE -> CamelCase -> lowerCamelCase conversion of names" single ((:commit . "50ad54970b3cc79b6b83979bde9889ad9a9e1a9c") (:authors ("akicho8" . "akicho8@gmail.com")) (:maintainer "akicho8" . "akicho8@gmail.com") (:keywords "elisp"))]) (string-utils . [(20140508 2041) ((list-utils (0 4 2))) "String-manipulation utilities" single ((:commit . "8b56e1f79d2de46d1e9b5e24d889e9f4c3cc85d4") (:authors ("Roland Walker" . "walker@pobox.com")) (:maintainer "Roland Walker" . "walker@pobox.com") (:keywords "extensions") (:url . "http://github.com/rolandwalker/string-utils"))]) (stripe-buffer . [(20141208 1508) ((cl-lib (1 0))) "Use a different background for even and odd lines" single ((:commit . "c252080f55cb78c951b19ebab9687f6d00237baf") (:authors ("Andy Stewart" . "lazycat.manatee@gmail.com")) (:maintainer "sabof" . "esabof@gmail.com") (:url . "https://github.com/sabof/stripe-buffer"))]) - (stripes . [(20220310 2237) ((emacs (24 3))) "highlight alternating lines differently" single ((:commit . "618e40e0a9cf80decea32c8daecb1c9f6eae2991") (:authors ("Michael Schierl" . "schierlm-public@gmx.de") ("Štěpán Němec" . "stepnem@gmail.com")) (:maintainer "Štěpán Němec" . "stepnem@gmail.com") (:keywords "convenience" "faces") (:url . "https://gitlab.com/stepnem/stripes-el"))]) + (stripes . [(20230402 1228) ((emacs (24 3))) "highlight alternating lines differently" single ((:commit . "4683c9020da14bb1c1f74b90d27a4d9fdc7a9147") (:authors ("Michael Schierl" . "schierlm-public@gmx.de") ("Štěpán Němec" . "stepnem@smrk.net")) (:maintainer "Štěpán Němec" . "stepnem@smrk.net") (:keywords "convenience" "faces") (:url . "http://git.smrk.net/stripes.el"))]) (stumpwm-mode . [(20171027 214) nil "special lisp mode for evaluating code into running stumpwm" tar ((:commit . "333d210cacc7ebac76e14dfc8c0139f0e399c9a7") (:maintainer "Shawn Betts") (:keywords "comm" "lisp" "tools"))]) (stupid-indent-mode . [(20170525 1117) nil "Plain stupid indentation minor mode" single ((:commit . "3295e7de5e2cfddc3bf0e462e852bf58972f5d70") (:authors ("Mihai Bazon" . "mihai.bazon@gmail.com")) (:maintainer "Mihai Bazon" . "mihai.bazon@gmail.com"))]) (stylefmt . [(20161025 824) nil "Stylefmt interface" single ((:commit . "7a38f26bf8ff947215f34f0a064c7ca80575ccbc") (:authors ("κeen")) (:maintainer "κeen") (:keywords "style" "code" "formatter") (:url . "https://github.com/KeenS/stylefmt.el"))]) @@ -4774,12 +4780,13 @@ (swap-buffers . [(20150506 2139) nil "The quickest way to swap buffers between windows. Based on switch-window package." single ((:commit . "46ab31359b70d935add6c6e9533443116dc51103") (:authors ("Evgeniy Kazakov" . "evgeniy.kazakov@gmail.com")) (:maintainer "Evgeniy Kazakov" . "evgeniy.kazakov@gmail.com") (:keywords "window" "swap" "buffer" "exchange") (:url . "https://github.com/ekazakov/swap-buffers"))]) (swap-regions . [(20180915 1346) ((emacs (24 3))) "Swap text in two regions" single ((:commit . "f4fd9880cf690e003fcde88dcf2b46adbbbb03cd") (:authors ("Xu Chunyang" . "mail@xuchunyang.me")) (:maintainer "Xu Chunyang" . "mail@xuchunyang.me") (:keywords "convenience") (:url . "https://github.com/xuchunyang/swap-regions.el"))]) (sway . [(20221211 1439) ((emacs (27 1)) (dash (2 18 1))) "Communication with the Sway window manager" single ((:commit . "117eb40691e7a4d2dcd6b5a7fd9f803c7d42c32c") (:authors ("Thibault Polge" . "thibault@thb.lt")) (:maintainer "Thibault Polge" . "thibault@thb.lt") (:keywords "frames") (:url . "https://github.com/thblt/sway.el"))]) + (sway-lang-mode . [(20230320 507) ((emacs (25 1)) (lsp-mode (6 0)) (rust-mode (1 0 5))) "Major mode for sway" single ((:commit . "1d4615cc99d57280fb4b301d8339f408d987d317") (:authors ("Hamza Hamud")) (:maintainer "Hamza Hamud") (:keywords "languages") (:url . "https://github.com/hhamud/sway-mode"))]) (sweet-theme . [(20200708 1202) ((emacs (24 1))) "Sweet-looking theme" single ((:commit . "ccbfdb6a17e25ab18a0b64101675bc1dfef44006") (:authors ("2bruh4me")) (:maintainer "2bruh4me") (:keywords "faces") (:url . "https://github.com/2bruh4me/sweet-theme"))]) (sweetgreen . [(20180605 335) ((dash (2 12 1)) (helm (1 5 6)) (request (0 2 0)) (cl-lib (0 5))) "Order Salads from sweetgreen.com" single ((:commit . "e933fe466b5ef0e976967e203f88bd7a012469d1") (:authors ("Diego Berrocal" . "cestdiego@gmail.com")) (:maintainer "Diego Berrocal" . "cestdiego@gmail.com") (:keywords "salad" "food" "sweetgreen" "request") (:url . "https://www.github.com/CestDiego/sweetgreen.el"))]) (swift-helpful . [(20220707 846) ((emacs (25 1)) (dash (2 12 0)) (lsp-mode (6 0)) (swift-mode (8 0 0))) "Show documentation for Swift programs." tar ((:commit . "b46c580e4b8f55761431ec677866de3fc66592e9") (:authors ("Daniel Martín" . "mardani29@yahoo.es")) (:maintainer "Daniel Martín" . "mardani29@yahoo.es") (:keywords "help" "swift") (:url . "https://github.com/danielmartin/swift-helpful"))]) (swift-mode . [(20230117 1113) ((emacs (24 4)) (seq (2 3))) "Major-mode for Apple's Swift programming language" tar ((:commit . "778e9e6f35b41fd171bd9f42fd7b89c1001e2a82") (:authors ("taku0" . "mxxouy6x3m_github@tatapa.org") ("Chris Barrett" . "chris.d.barrett@me.com") ("Bozhidar Batsov" . "bozhidar@batsov.com") ("Arthur Evstifeev" . "lod@pisem.net")) (:maintainer "taku0" . "mxxouy6x3m_github@tatapa.org") (:keywords "languages" "swift") (:url . "https://github.com/swift-emacs/swift-mode"))]) (swift3-mode . [(20160918 1250) ((emacs (24 4))) "Major-mode for Apple's Swift programming language." tar ((:commit . "ea34d46bf9a4293e75ffdac9500d34989316d9e9") (:keywords "languages" "swift") (:url . "https://github.com/taku0/swift3-mode"))]) - (swiper . [(20220430 2247) ((emacs (24 5)) (ivy (0 13 4))) "Isearch with an overview. Oh, man!" single ((:commit . "8bf8027e4bd8c093bddb76a813952d2a0dcbf21d") (:authors ("Oleh Krehel" . "ohwoeowho@gmail.com")) (:maintainer "Oleh Krehel" . "ohwoeowho@gmail.com") (:keywords "matching") (:url . "https://github.com/abo-abo/swiper"))]) + (swiper . [(20230326 1911) ((emacs (24 5)) (ivy (0 13 4))) "Isearch with an overview. Oh, man!" single ((:commit . "e3164aae1e98ab7e3721e983463b6500c30e043f") (:authors ("Oleh Krehel" . "ohwoeowho@gmail.com")) (:maintainer "Oleh Krehel" . "ohwoeowho@gmail.com") (:keywords "matching") (:url . "https://github.com/abo-abo/swiper"))]) (swiper-helm . [(20180131 1744) ((emacs (24 1)) (swiper (0 1 0)) (helm (1 5 3))) "Helm version of Swiper." single ((:commit . "93fb6db87bc6a5967898b5fd3286954cc72a0008") (:authors ("Oleh Krehel" . "ohwoeowho@gmail.com")) (:maintainer "Oleh Krehel" . "ohwoeowho@gmail.com") (:keywords "matching") (:url . "https://github.com/abo-abo/swiper-helm"))]) (swiss-holidays . [(20200526 822) nil "Swiss holidays for the calendar" single ((:commit . "0995c9685033a09466f5b2dceb7316362bde997a") (:authors ("Christian Egli" . "christian.egli@alumni.ethz.ch")) (:maintainer "Christian Egli" . "christian.egli@alumni.ethz.ch") (:keywords "calendar") (:url . "https://github.com/egli/swiss-holidays"))]) (switch-buffer-functions . [(20200127 409) nil "Hook run when current buffer changed" single ((:commit . "40cb0c9e2c84b30e1c5c7458a795cda1bd8ad8fa") (:authors ("10sr <8slashes+el [at] gmail [dot] com>")) (:maintainer "10sr <8slashes+el [at] gmail [dot] com>") (:keywords "hook" "utility") (:url . "https://github.com/10sr/switch-buffer-functions-el"))]) @@ -4792,14 +4799,14 @@ (symbol-overlay . [(20230117 1227) ((emacs (24 3)) (seq (2 2))) "Highlight symbols with keymap-enabled overlays" single ((:commit . "ed007230378b03f384b5a2b643dd857010ef21d3") (:authors ("wolray" . "wolray@foxmail.com")) (:maintainer "wolray" . "wolray@foxmail.com") (:keywords "faces" "matching") (:url . "https://github.com/wolray/symbol-overlay/"))]) (symbolist . [(20211107 1615) ((emacs (24 5))) "List and interactively unbind Emacs Lisp symbols" single ((:commit . "92b712734941a45da7d47fd61b95e4013ff53481") (:authors ("Lassi Kortela" . "lassi@lassi.io")) (:maintainer "Lassi Kortela" . "lassi@lassi.io") (:keywords "lisp" "maint") (:url . "https://github.com/lassik/emacs-symbolist"))]) (symbolword-mode . [(20180401 1427) ((emacs (24)) (f (0 19 0))) "modify word split" single ((:commit . "920e57f4c2b09b28c5a0c8fe9ebdba9961822163") (:authors ("ncaq" . "ncaq@ncaq.net")) (:maintainer "ncaq" . "ncaq@ncaq.net") (:url . "https://github.com/ncaq/symbolword-mode"))]) - (symex . [(20230322 332) ((emacs (25 1)) (tsc (0 15 2)) (tree-sitter (0 15 2)) (lispy (0 26 0)) (paredit (24)) (evil-cleverparens (20170718 413)) (evil (1 2 14)) (evil-surround (1 0 4)) (hydra (0 15 0)) (seq (2 22))) "An evil way to edit Lisp symbolic expressions as trees" tar ((:commit . "b0b59df5ec6d510f3589e79400f9ccfb1cf4f7a2") (:authors ("Siddhartha Kasivajhula" . "sid@countvajhula.com")) (:maintainer "Siddhartha Kasivajhula" . "sid@countvajhula.com") (:keywords "lisp" "convenience" "languages") (:url . "https://github.com/countvajhula/symex.el"))]) + (symex . [(20230322 2003) ((emacs (25 1)) (tsc (0 15 2)) (tree-sitter (0 15 2)) (lispy (0 26 0)) (paredit (24)) (evil-cleverparens (20170718 413)) (evil (1 2 14)) (evil-surround (1 0 4)) (hydra (0 15 0)) (seq (2 22))) "An evil way to edit Lisp symbolic expressions as trees" tar ((:commit . "0b65804d08c9ff61ec6785b48ce9b3c3d4779cfe") (:authors ("Siddhartha Kasivajhula" . "sid@countvajhula.com")) (:maintainer "Siddhartha Kasivajhula" . "sid@countvajhula.com") (:keywords "lisp" "convenience" "languages") (:url . "https://github.com/countvajhula/symex.el"))]) (symon . [(20170224 833) nil "tiny graphical system monitor" single ((:commit . "76461679dfe13a5dccd3c8735fb6f58b26b46733") (:authors ("zk_phi")) (:maintainer "zk_phi") (:url . "http://hins11.yu-yake.com/"))]) (symon-lingr . [(20150719 1342) ((symon (1 1 2)) (cl-lib (0 5))) "A notification-based Lingr client powered by symon.el" single ((:commit . "056d1a473e36992ff5881e5ce6fdc331cead975f") (:authors ("zk_phi")) (:maintainer "zk_phi") (:url . "http://hins11.yu-yake.com/"))]) (sync-recentf . [(20160326 2001) nil "Synchronize the recent files list between Emacs instances" single ((:commit . "0052561d5c5b5c2684faedc3eead776aec06c3ed") (:authors ("François Févotte" . "fevotte@gmail.com")) (:maintainer "François Févotte" . "fevotte@gmail.com") (:keywords "recentf") (:url . "https://github.com/ffevotte/sync-recentf"))]) (synonymous . [(20180325 1817) ((emacs (24)) (cl-lib (0 5)) (request (0 2 0))) "A thesaurus at your fingertips" single ((:commit . "2cb9a674d84fddf3f1b00c9d6b13a853576acb87") (:authors ("Katherine Whitlock" . "toroidalcode@gmail.com") ("Snippets adapted from FlySpell, authored by Manuel Serrano" . "Manuel.Serrano@inria.fr")) (:maintainer "Katherine Whitlock" . "toroidalcode@gmail.com") (:keywords "utility") (:url . "http://github.com/toroidal-code/synonymous.el"))]) (synosaurus . [(20191125 552) ((cl-lib (0 5))) "An extensible thesaurus supporting lookup and substitution." tar ((:commit . "14d34fc92a77c3a916b4d58400424c44ae99cd81") (:authors ("Hans-Peter Deifel" . "hpd@hpdeifel.de")) (:maintainer "Hans-Peter Deifel" . "hpd@hpdeifel.de") (:keywords "wp"))]) (synquid . [(20160930 1550) ((flycheck (27)) (emacs (24 3))) "Major mode for editing Synquid files" single ((:commit . "28701ce1a15437202f53ab93a14bcba1de83fd2c") (:authors ("Clément Pit-Claudel" . "clement.pitclaudel@live.com")) (:maintainer "Clément Pit-Claudel" . "clement.pitclaudel@live.com") (:keywords "languages") (:url . "https://github.com/cpitclaudel/synquid-mode"))]) - (syntactic-close . [(20230316 1400) ((emacs (24)) (cl-lib (0 5))) "Insert closing delimiter" single ((:commit . "43cc17721a567e079c6cd28aa32d3fefcc2945c8") (:authors ("Emacs User Group Berlin" . "emacs-berlin@emacs-berlin.org")) (:maintainer "Emacs User Group Berlin" . "emacs-berlin@emacs-berlin.org") (:keywords "languages" "convenience") (:url . "https://github.com/emacs-berlin/syntactic-close"))]) + (syntactic-close . [(20230326 1211) ((emacs (24)) (cl-lib (0 5))) "Insert closing delimiter" single ((:commit . "5d97262a0210c5fb393a257e4a9f90e0f29bc8fd") (:authors ("Emacs User Group Berlin" . "emacs-berlin@emacs-berlin.org")) (:maintainer "Emacs User Group Berlin" . "emacs-berlin@emacs-berlin.org") (:keywords "languages" "convenience") (:url . "https://github.com/emacs-berlin/syntactic-close"))]) (syntactic-sugar . [(20140508 2041) nil "Effect-free forms such as if/then/else" single ((:commit . "b6a49df4b6056e2619eea9ca554c105ae67e115f") (:authors ("Roland Walker" . "walker@pobox.com")) (:maintainer "Roland Walker" . "walker@pobox.com") (:keywords "extensions") (:url . "http://github.com/rolandwalker/syntactic-sugar"))]) (syntax-subword . [(20160205 2154) nil "make operations on words more fine-grained" single ((:commit . "9aa9b3f846bfe2474370642458a693ac4760d9fe") (:authors ("Jonathan Kotta" . "jpkotta@gmail.com")) (:maintainer "Jonathan Kotta" . "jpkotta@gmail.com"))]) (syntree . [(20221114 1804) ((emacs (27 1)) (org (9 2))) "Draw plain text constituency trees" tar ((:commit . "a36e5eeaeef2a179184883fc0a91b63d653d3cd9") (:authors ("Enrico Flor" . "enrico@eflor.net")) (:maintainer "Enrico Flor" . "enrico@eflor.net") (:url . "https://github.com/enricoflor/syntree"))]) @@ -4828,9 +4835,9 @@ (tango-plus-theme . [(20221011 1012) nil "A color theme based on the tango palette" single ((:commit . "30495d1ab1df6213ecac008c599b91e6f9244c12") (:authors ("Titus von der Malsburg" . "malsburg@posteo.de")) (:maintainer "Titus von der Malsburg" . "malsburg@posteo.de") (:url . "https://github.com/tmalsburg/tango-plus-theme"))]) (tangonov-theme . [(20220923 1513) ((emacs (25))) "A 256 color dark theme featuring bright pastels" single ((:commit . "084e3a7fe3c3af0aef75f2290b939185baa1f4a4") (:authors ("Trevor Richards" . "trev@trevdev.ca")) (:maintainer "Trevor Richards" . "trev@trevdev.ca") (:keywords "faces" "theme" "dark" "fringe") (:url . "https://sr.ht/~trevdev/tangonov-theme/"))]) (tangotango-theme . [(20220714 2034) nil "Tango Palette color theme for Emacs 24." single ((:commit . "9036c4978965149ae9837bc0ad691b2ba9269052") (:authors ("Julien Barnier" . "julien@nozav.org")) (:maintainer "Julien Barnier" . "julien@nozav.org") (:keywords "tango" "palette" "color" "theme" "emacs") (:url . "https://github.com/juba/color-theme-tangotango"))]) - (tao-theme . [(20230311 44) nil "This package provides two parametrized uncoloured color themes for Emacs: tao-yin and tao-yang." tar ((:commit . "14efde1bc97e32dca04e59ca13d8d4ca745e58ce") (:authors ("Peter Kosov" . "11111000000@email.com")) (:maintainer "Peter Kosov" . "11111000000@email.com") (:url . "http://github.com/11111000000/tao-theme-emacs"))]) + (tao-theme . [(20230323 301) nil "This package provides two parametrized uncoloured color themes for Emacs: tao-yin and tao-yang." tar ((:commit . "d44ecab7f68cda9c9f4dd881df5d842e38f44db6") (:authors ("Peter Kosov" . "11111000000@email.com")) (:maintainer "Peter Kosov" . "11111000000@email.com") (:url . "http://github.com/11111000000/tao-theme-emacs"))]) (tardis-theme . [(20230212 2152) ((emacs (25 1))) "Quantum Country Theme" single ((:commit . "352b1579d13e99cff9367b08208c1e241d76c89e") (:authors ("Anton Hibl" . "antonhibl11@gmail.com")) (:maintainer "Anton Hibl" . "antonhibl11@gmail.com") (:keywords "convenience") (:url . "https://github.com/antonhibl/tardis-theme"))]) - (taskpaper-mode . [(20221030 1048) ((emacs (25 1))) "Major mode for working with TaskPaper files" single ((:commit . "9620d66e568c0bbdf033a559bac578e235e66293") (:authors ("Dmitry Safronov" . "saf.dmitry@gmail.com")) (:maintainer "Dmitry Safronov" . "saf.dmitry@gmail.com") (:keywords "outlines" "notetaking" "task management" "productivity" "taskpaper") (:url . "https://github.com/saf-dmitry/taskpaper-mode"))]) + (taskpaper-mode . [(20230329 1135) ((emacs (25 1))) "Major mode for working with TaskPaper files" single ((:commit . "c7fbde266e72378481e8f039347e2c50bafeb98f") (:authors ("Dmitry Safronov" . "saf.dmitry@gmail.com")) (:maintainer "Dmitry Safronov" . "saf.dmitry@gmail.com") (:keywords "outlines" "notetaking" "task management" "productivity" "taskpaper") (:url . "https://github.com/saf-dmitry/taskpaper-mode"))]) (taskrunner . [(20190916 1608) ((emacs (25 1)) (projectile (2 0 0)) (async (1 9 3))) "Retrieve build system/taskrunner tasks" tar ((:commit . "716323aff410b4d864d137c9ebe4bbb5b8587f5e") (:authors ("Yavor Konstantinov ")) (:maintainer "Yavor Konstantinov ") (:keywords "build-system" "taskrunner" "build" "task-runner" "tasks" "convenience") (:url . "https://github.com/emacs-taskrunner/emacs-taskrunner"))]) (tawny-mode . [(20210528 1710) ((cider (0 12)) (emacs (25))) "Ontology Editing with Tawny-OWL" single ((:commit . "5da72b601cb9f052f35e88c41f1a18b326c03791") (:authors ("Phillip Lord" . "phillip.lord@newcastle.ac.uk")) (:maintainer "Phillip Lord" . "phillip.lord@newcastle.ac.uk"))]) (tblui . [(20161007 1912) ((dash (2 12 1)) (magit-popup (2 6 0)) (tablist (0 70)) (cl-lib (0 5))) "Define tabulated list UI easily" single ((:commit . "e280e11b35a2fdbcadf9ce901a2b62684ac7a7a3") (:authors ("Yuki Inoue ")) (:maintainer "Yuki Inoue ") (:url . "https://github.com/Yuki-Inoue/tblui.el"))]) @@ -4840,13 +4847,13 @@ (tea-time . [(20120331 820) nil "Simple timer package, useful to make perfect tea." single ((:commit . "1f6cf0bdd27c5eb3508989c5095427781f858eca") (:authors ("konsty" . "antipin.konstantin@googlemail.com")) (:maintainer "Gabriel Saldana" . "gsaldana@gmail.com") (:keywords "timer" "tea-time"))]) (teacode-expand . [(20181231 640) ((emacs (24 4))) "Expansion of text by TeaCode program." single ((:commit . "7df6f9ec95da1fb47bbae489bb3f2c27ed3a9b3a") (:authors ("Richard Guay" . "raguay@customct.com")) (:maintainer "Richard Guay" . "raguay@customct.com") (:keywords "lisp") (:url . "https://github.com/raguay/TeaCode-Expand"))]) (teco . [(20200707 2309) nil "Teco interpreter" single ((:commit . "2529eb0f7f35c526c1b6fca5250399718ff5138a") (:authors ("Dale R. Worley" . "worley@alum.mit.edu")) (:maintainer "Mark T. Kennedy" . "mtk@acm.org") (:keywords "convenience" "emulations" "files") (:url . "https://github.com/mtk/teco.git"))]) - (telega . [(20230322 726) ((emacs (27 1)) (visual-fill-column (1 9)) (rainbow-identifiers (0 2 2))) "Telegram client (unofficial)" tar ((:commit . "2b284714cd750c7d69c9d452340c1b31b4e01016") (:authors ("Zajcev Evgeny" . "zevlg@yandex.ru")) (:maintainer "Zajcev Evgeny" . "zevlg@yandex.ru") (:keywords "comm") (:url . "https://github.com/zevlg/telega.el"))]) + (telega . [(20230401 1152) ((emacs (27 1)) (visual-fill-column (1 9)) (rainbow-identifiers (0 2 2))) "Telegram client (unofficial)" tar ((:commit . "2cf74907e4b6a109ac01bb52494845176833268c") (:authors ("Zajcev Evgeny" . "zevlg@yandex.ru")) (:maintainer "Zajcev Evgeny" . "zevlg@yandex.ru") (:keywords "comm") (:url . "https://github.com/zevlg/telega.el"))]) (telepathy . [(20131209 1258) nil "Access Telepathy from Emacs" single ((:commit . "211d785b02a29ddc254422fdcc3db45262582f8c") (:authors ("Nicolas Petton" . "petton.nicolas@gmail.com")) (:maintainer "Nicolas Petton" . "petton.nicolas@gmail.com") (:keywords "telepathy" "tools"))]) (telephone-line . [(20230322 442) ((emacs (24 4)) (cl-lib (0 5)) (cl-generic (0 2)) (seq (1 8))) "Rewrite of Powerline" tar ((:commit . "202f9c94f7b86827ab7ebb6dbce8302b0447d6ff") (:authors ("Daniel Bordak" . "dbordak@fastmail.fm")) (:maintainer "Daniel Bordak" . "dbordak@fastmail.fm") (:keywords "mode-line") (:url . "https://github.com/dbordak/telephone-line"))]) (teletext . [(20211203 1111) ((emacs (24 3))) "Teletext broadcast viewer" single ((:commit . "6b003e9dab9bd0c27d188a81f5fff740d66a2282") (:authors ("Lassi Kortela" . "lassi@lassi.io")) (:maintainer "Lassi Kortela" . "lassi@lassi.io") (:keywords "comm" "help" "hypermedia") (:url . "https://github.com/lassik/emacs-teletext"))]) (teletext-yle . [(20210927 825) ((emacs (24 3)) (teletext (0 1))) "Teletext provider for Finnish national network YLE" single ((:commit . "9c8f4b503923c4ec688e2dcc9dff62d71bc55933") (:authors ("Lassi Kortela" . "lassi@lassi.io")) (:maintainer "Lassi Kortela" . "lassi@lassi.io") (:keywords "comm" "help" "hypermedia") (:url . "https://github.com/lassik/emacs-teletext-yle"))]) (tempel . [(20230305 739) ((emacs (27 1)) (compat (29 1 4 0))) "Tempo templates/snippets with in-buffer field editing" single ((:commit . "4ab5f3af92aab2a1aea1ec66d9086812fe310044") (:authors ("Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainer "Daniel Mendler" . "mail@daniel-mendler.de") (:url . "https://github.com/minad/tempel"))]) - (tempel-collection . [(20230310 858) ((tempel (0 5)) (emacs (27 1))) "Collection of templates for Tempel" tar ((:commit . "eeae3ba92612f09d468ac0bd8a15d979c54f8a0c") (:authors ("Vitalii Drevenchuk" . "cradlemann@gmail.com") ("Max Penet" . "mpenetr@s-exp.com") ("Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainer "Vitalii Drevenchuk" . "cradlemann@gmail.com") (:keywords "tools") (:url . "https://github.com/Crandel/tempel-collection"))]) + (tempel-collection . [(20230324 941) ((tempel (0 5)) (emacs (27 1))) "Collection of templates for Tempel" tar ((:commit . "096eff3618f6cd600fdf61859f9e5dd1bae08182") (:authors ("Vitalii Drevenchuk" . "cradlemann@gmail.com") ("Max Penet" . "mpenetr@s-exp.com") ("Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainer "Vitalii Drevenchuk" . "cradlemann@gmail.com") (:keywords "tools") (:url . "https://github.com/Crandel/tempel-collection"))]) (template-overlays . [(20180706 1132) ((emacs (24 4)) (ov (1 0 6))) "Display template regions using overlays" single ((:commit . "3cbc9a4882dcbbddf9b168883d119a6af0848784") (:authors ("Mariano Montone" . "marianomontone@gmail.com")) (:maintainer "Mariano Montone" . "marianomontone@gmail.com") (:keywords "faces" "convenience" "templates" "overlays") (:url . "http://www.github.com/mmontone/template-overlays"))]) (templatel . [(20210902 228) ((emacs (25 1))) "Templating language;" single ((:commit . "e1ccb88cdc4b482b078276960f810b82ba3b7847") (:authors ("Lincoln Clarete" . "lincoln@clarete.li")) (:maintainer "Lincoln Clarete" . "lincoln@clarete.li") (:url . "https://clarete.li/templatel"))]) (temporary-persistent . [(20230115 1425) ((emacs (24 3)) (names (20151201 0)) (dash (2 12 1)) (s (1 10 0))) "Keep temp notes buffers persistent" single ((:commit . "edbde738769e79ac212ae84ae7898ffd5f19e0f1") (:authors ("Kostafey" . "kostafey@gmail.com")) (:maintainer "Kostafey" . "kostafey@gmail.com") (:keywords "temp" "buffers" "notes") (:url . "https://github.com/kostafey/temporary-persistent"))]) @@ -4880,12 +4887,12 @@ (textmate . [(20110816 2146) nil "TextMate minor mode for Emacs" single ((:commit . "350918b070148f0ace6d9d3cd4ebcaf15c1a8781") (:authors ("Chris Wanstrath" . "chris@ozmm.org")) (:maintainer "Chris Wanstrath" . "chris@ozmm.org") (:keywords "textmate" "osx" "mac"))]) (textmate-to-yas . [(20160409 1708) nil "Import Textmate macros into yasnippet syntax" tar ((:commit . "be3a768b7ac4c2e24b9d4aa6e9ac1d916cdc5a73") (:authors ("Matthew L. Fidler")) (:maintainer "Matthew L. Fidler") (:keywords "yasnippet" "textmate") (:url . "https://github.com/mlf176f2/textmate-to-yas.el/"))]) (textsize . [(20220427 1445) ((emacs (26 1))) "Configure frame text size automatically" single ((:commit . "df91392c3c928d7841631f5809716b9cf0f7309e") (:authors ("James Ferguson" . "james@faff.org")) (:maintainer "James Ferguson" . "james@faff.org") (:keywords "convenience") (:url . "https://github.com/WJCFerguson/textsize"))]) - (textx-mode . [(20170516 911) ((emacs (24 3))) "Major mode for editing TextX files" single ((:commit . "72f9f0c5855b382024f0da8f56833c22a70a5cb3") (:authors ("Novak Boškov" . "gnovak.boskov@gmail.com")) (:maintainer "Novak Boškov" . "gnovak.boskov@gmail.com") (:keywords "textx") (:url . "https://github.com/novakboskov/textx-mode"))]) + (textx-mode . [(20230324 2020) ((emacs (24 3))) "Major mode for editing TextX files" single ((:commit . "ecf90abec508cfd82d5da68474e976be907d9a77") (:authors ("Novak Boškov" . "gnovak.boskov@gmail.com")) (:maintainer "Novak Boškov" . "gnovak.boskov@gmail.com") (:keywords "textx") (:url . "https://github.com/novakboskov/textx-mode"))]) (tf2-conf-mode . [(20161209 1620) nil "TF2 Configuration files syntax highlighting" single ((:commit . "94c971da4a78d55da2848d1e76d513e5e0a8f7eb") (:authors ("Guillermo Robles" . "guillerobles1995@gmail.com")) (:maintainer "Guillermo Robles" . "guillerobles1995@gmail.com") (:keywords "languages") (:url . "https://github.com/wynro/emacs-tf2-conf-mode"))]) (tfsmacs . [(20180911 2114) ((emacs (25)) (tablist (0 70))) "MS TFS source control interaction." single ((:commit . "13ee3f528ff616880611f563a68d921250692ef8") (:authors ("Dino Chiesa , Sebastian Monia" . "smonia@outlook.com")) (:maintainer "Dino Chiesa , Sebastian Monia" . "smonia@outlook.com") (:keywords "tfs" "vc") (:url . "http://github.com/sebasmonia/tfsmacs/"))]) - (the-matrix-theme . [(20230317 338) ((emacs (26 1))) "Green-on-black dark theme inspired by \"The Matrix\" movie" single ((:commit . "6e53d899c132d8f083c45aff034e041d5eb4d220") (:authors ("Dan Dee" . "monkeyjunglejuice@pm.me")) (:maintainer "Dan Dee" . "monkeyjunglejuice@pm.me") (:keywords "faces" "theme") (:url . "https://github.com/monkeyjunglejuice/matrix-emacs-theme"))]) + (the-matrix-theme . [(20230402 1218) ((emacs (26 1))) "Green-on-black dark theme inspired by \"The Matrix\" movie" single ((:commit . "b339285651e088bc51fa2fb51aa319fb70cab9a4") (:authors ("Dan Dee" . "monkeyjunglejuice@pm.me")) (:maintainer "Dan Dee" . "monkeyjunglejuice@pm.me") (:keywords "faces" "theme") (:url . "https://github.com/monkeyjunglejuice/matrix-emacs-theme"))]) (theme-anchor . [(20220204 321) ((emacs (26))) "Apply theme in current buffer only" single ((:commit . "c6f715d4ccd30e83922e39cab856578ce19224bb") (:authors ("Liāu, Kiong-Gē" . "gliao.tw@pm.me")) (:maintainer "Liāu, Kiong-Gē" . "gliao.tw@pm.me") (:keywords "extensions" "lisp" "theme") (:url . "https://github.com/GongYiLiao/theme-anchor"))]) - (theme-changer . [(20201226 2256) nil "Sunrise/Sunset Theme Changer for Emacs" single ((:commit . "57b8c579f134374a45bec9043feff6b29bb4f108") (:authors ("Joshua B. Griffith" . "josh.griffith@gmail.com")) (:maintainer "Joshua B. Griffith" . "josh.griffith@gmail.com") (:keywords "color-theme" "deftheme" "solar" "sunrise" "sunset") (:url . "https://github.com/hadronzoo/theme-changer"))]) + (theme-changer . [(20230405 156) ((cl-lib (0))) "Sunrise/Sunset Theme Changer for Emacs" single ((:commit . "e7a97772b22a82c70f2bd34e205d11b0b8a1e972") (:authors ("Joshua B. Griffith" . "josh.griffith@gmail.com")) (:maintainer "Samuel W. Flint" . "swflint@flintfam.org") (:keywords "color-theme" "deftheme" "solar" "sunrise" "sunset") (:url . "https://github.com/hadronzoo/theme-changer"))]) (theme-looper . [(20210827 424) ((emacs (24)) (cl-lib (0 5))) "A package for switching themes in Emacs interactively" single ((:commit . "e6e8efd740df0b68db89805ba72492818dba61ab") (:authors ("Mohammed Ismail Ansari" . "team.terminal@gmail.com")) (:maintainer "Mohammed Ismail Ansari" . "team.terminal@gmail.com") (:keywords "convenience" "color-themes") (:url . "http://ismail.teamfluxion.com"))]) (theme-magic . [(20190711 2034) ((emacs (25)) (seq (1 8))) "Apply your Emacs theme to the rest of Linux" tar ((:commit . "844c4311bd26ebafd4b6a1d72ddcc65d87f074e3") (:authors ("GitHub user \"jcaw\"" . "40725916+jcaw@users.noreply.github.com")) (:maintainer "GitHub user \"jcaw\"" . "40725916+jcaw@users.noreply.github.com") (:keywords "unix" "faces" "terminals" "extensions") (:url . "https://github.com/jcaw/theme-magic.el"))]) (therapy . [(20151113 1953) ((emacs (24))) "Hooks for managing multiple Python major versions" single ((:commit . "775a92bb7b6b0fcc5b38c0b5198a9d0a1bef788a") (:authors ("Austin Bingham" . "austin.bingham@gmail.com")) (:maintainer "Austin Bingham" . "austin.bingham@gmail.com") (:url . "https://github.com/abingham/therapy"))]) @@ -4893,14 +4900,14 @@ (thinks . [(20170802 1128) ((cl-lib (0 5))) "Insert text in a think bubble." single ((:commit . "15e0437f5b635bdcf738ca092e26aa6d8ecdba36") (:authors ("Dave Pearson" . "davep@davep.org")) (:maintainer "Dave Pearson" . "davep@davep.org") (:keywords "convenience" "quoting") (:url . "https://github.com/davep/thinks.el"))]) (thread-dump . [(20170816 1850) nil "Java thread dump viewer" single ((:commit . "204c9600242756d4b514bb5ff6293e052bf4b49d") (:authors ("Dmitry Neverov")) (:maintainer "Dmitry Neverov") (:url . "http://github.com/nd/thread-dump.el"))]) (threes . [(20160820 1242) ((emacs (24)) (seq (1 11))) "A clone of Threes (a tiny puzzle game)" single ((:commit . "6981acb30b856c77cba6aba63fefbf102cbdfbb2") (:authors ("Chunyang Xu" . "xuchunyang.me@gmail.com")) (:maintainer "Chunyang Xu" . "xuchunyang.me@gmail.com") (:keywords "games") (:url . "https://github.com/xuchunyang/threes.el"))]) - (thrift . [(20230222 2028) ((emacs (24))) "major mode for fbthrift and Apache Thrift files" single ((:commit . "cbc3de581fdf36ba474b0c135b9e785e504f1c1e") (:keywords "languages"))]) + (thrift . [(20230402 732) ((emacs (24))) "major mode for fbthrift and Apache Thrift files" single ((:commit . "ea52832e1283042b58262897c97527b8c2f4698f") (:keywords "languages"))]) (thumb-through . [(20120119 534) nil "Plain text reader of HTML documents" single ((:commit . "08d8fb720f93c6172653e035191a8fa9c3305e63") (:keywords "html"))]) (tickscript-mode . [(20171219 203) ((emacs (24 1))) "A major mode for Tickscript files" single ((:commit . "f0579f38ff14954df5002ce30ae6d4a2c978d461") (:authors ("Marc Sherry" . "msherry@gmail.com")) (:maintainer "Marc Sherry" . "msherry@gmail.com") (:keywords "languages") (:url . "https://github.com/msherry/tickscript-mode"))]) (tidal . [(20230312 1245) ((haskell-mode (16)) (emacs (25 1))) "Interact with TidalCycles for live coding patterns" single ((:commit . "3ac320020d809ea626fc283839fecb10c9da4ce2") (:authors (nil . "alex@slab.org")) (:maintainer nil . "alex@slab.org") (:keywords "tools") (:url . "https://github.com/tidalcycles/Tidal"))]) (tide . [(20230129 1346) ((emacs (25 1)) (dash (2 10 0)) (s (1 11 0)) (flycheck (27)) (cl-lib (0 5))) "Typescript Interactive Development Environment" tar ((:commit . "29475d9eee26f4101322209e9b6b199df5386094") (:authors ("Anantha kumaran" . "ananthakumaran@gmail.com")) (:maintainer "Anantha kumaran" . "ananthakumaran@gmail.com") (:keywords "typescript") (:url . "http://github.com/ananthakumaran/tide"))]) (tikz . [(20220526 521) ((emacs (24 1))) "A minor mode to edit TikZ pictures" tar ((:commit . "4b205afc5c88f050639135d1d57f1276db323842") (:authors ("Emilio Torres-Manzanera" . "torres@uniovi.es")) (:maintainer "Emilio Torres-Manzanera" . "torres@uniovi.es") (:keywords "tex") (:url . "https://github.com/emiliotorres/tikz"))]) (tile . [(20161225 357) ((emacs (25 1)) (s (1 9 0)) (dash (2 12 0)) (stream (2 2 3))) "Tile windows with layouts" single ((:commit . "22660f21f6e95de5aba55cd5d293d4841e9a4661") (:authors ("Ivan Malison" . "IvanMalison@gmail.com")) (:maintainer "Ivan Malison" . "IvanMalison@gmail.com") (:keywords "tile" "tiling" "window" "manager" "dynamic" "frames") (:url . "https://github.com/IvanMalison/tile"))]) - (time-block . [(20230210 136) ((emacs (25 1)) (ts (0 1))) "Block running commands using time" single ((:commit . "e0dcf6eb13871df41b081b9cdaadced722c3ba54") (:authors ("Samuel W. Flint" . "swflint@flintfam.org")) (:maintainer "Samuel W. Flint" . "swflint@flintfam.org") (:keywords "tools" "productivity" "convenience") (:url . "https://git.sr.ht/~swflint/time-block"))]) + (time-block . [(20230326 1904) ((emacs (25 1)) (ts (0 1))) "Block running commands using time" single ((:commit . "90831463528a232414895b4905f67fa001550b9b") (:authors ("Samuel W. Flint" . "swflint@flintfam.org")) (:maintainer "Samuel W. Flint" . "swflint@flintfam.org") (:keywords "tools" "productivity" "convenience") (:url . "https://git.sr.ht/~swflint/time-block-command"))]) (time-ext . [(20170126 1215) nil "more function for time/date" single ((:commit . "d128becf660fe3f30178eb1b05cd266741f4784a") (:authors ("rubikitch" . "rubikitch@ruby-lang.org")) (:maintainer "rubikitch" . "rubikitch@ruby-lang.org") (:keywords "lisp") (:url . "http://www.emacswiki.org/cgi-bin/wiki/download/time-ext.el"))]) (time-uuid-mode . [(20230312 2256) ((emacs (24 3))) "Minor mode for previewing time uuids as an overlay" single ((:commit . "6f0768edb7588add3713952e5b20e9df8ee51f89") (:authors ("Robert Plant" . "rob@robertplant.io")) (:maintainer "Robert Plant" . "rob@robertplant.io") (:keywords "extensions" "convenience" "data" "tools") (:url . "https://github.com/RobertPlant/time-uuid-mode"))]) (timecop . [(20160520 1052) ((cl-lib (0 5)) (datetime-format (0 0 1))) "Freeze Time for testing" single ((:commit . "3a1871613facc928ff250ed8f12fbc7073e46b75") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "datetime" "testing") (:url . "https://github.com/zonuexe/emacs-datetime"))]) @@ -4921,7 +4928,7 @@ (tj3-mode . [(20180519 1228) nil "major mode for editing TaskJuggler 3 files" single ((:commit . "1d98eb23f1606392f34ef1b80517cfc940fb9950") (:authors ("Christophe Rhodes" . "christophe@rhodes.io")) (:maintainer "Christophe Rhodes" . "christophe@rhodes.io") (:url . "https://github.com/csrhodes/tj3-mode"))]) (tldr . [(20230301 136) ((emacs (24 3))) "tldr client for Emacs" single ((:commit . "1b09d2032491d3904bd7ee9bf5ba7c7503db6593") (:authors ("Ono Hiroko" . "azazabc123@gmail.com")) (:maintainer "Ono Hiroko" . "azazabc123@gmail.com") (:keywords "tools" "docs") (:url . "https://github.com/kuanyui/tldr.el"))]) (tmmofl . [(20121025 1101) nil "Calls functions dependant on font lock highlighting at point" single ((:commit . "532aa6978e994e2b069ffe37aaf9a0011a07dadc") (:authors ("Phillip Lord" . "p.lord@hgmp.mrc.ac.uk")) (:maintainer "Phillip Lord" . "p.lord@hgmp.mrc.ac.uk") (:keywords "minor mode" "font lock" "toggling."))]) - (tmsu . [(20230308 1935) ((emacs (28 1))) "A basic TMSU interface" tar ((:commit . "edad2cb7ff14d6dda6f98c2c21a134572fcfec8c") (:authors ("Wojciech Siewierski")) (:maintainer "Wojciech Siewierski") (:keywords "files") (:url . "https://github.com/vifon/tmsu.el"))]) + (tmsu . [(20230322 2344) ((emacs (28 1))) "A basic TMSU interface" tar ((:commit . "567ba42958592e632bf611f004d24c09eb2eeac1") (:authors ("Wojciech Siewierski")) (:maintainer "Wojciech Siewierski") (:keywords "files") (:url . "https://github.com/vifon/tmsu.el"))]) (tmux-pane . [(20200730 520) ((names (0 5)) (emacs (24)) (s (0))) "Provide integration between emacs window and tmux pane" single ((:commit . "923524efe8e6e5e0d269de6bb253b45e02d9a663") (:keywords "convenience" "terminals" "tmux" "window" "pane" "navigation" "integration") (:url . "https://github.com/laishulu/emacs-tmux-pane"))]) (toc-mode . [(20220926 530) ((emacs (26 1))) "Manage outlines/table of contents of pdf and djvu documents" single ((:commit . "448a0ac00c110802f3124bbf9c5a72bdfc3c3c28") (:authors ("Daniel Laurens Nicolai" . "dalanicolai@gmail.com")) (:maintainer "Daniel Laurens Nicolai" . "dalanicolai@gmail.com") (:keywords "tools" "outlines" "convenience") (:url . "https://github.com/dalanicolai/toc-mode"))]) (toc-org . [(20220110 1452) nil "add table of contents to org-mode files (formerly, org-toc)" single ((:commit . "bf2e4b358efbd860ecafe6e74776de0885d9d100") (:authors ("Sergei Nosov ")) (:maintainer "Sergei Nosov ") (:keywords "org-mode" "org-toc" "toc-org" "org" "toc" "table" "of" "contents") (:url . "https://github.com/snosov1/toc-org"))]) @@ -4932,7 +4939,7 @@ (toggle-quotes . [(20140710 926) nil "Toggle between single and double quoted string" single ((:commit . "33abc221d6887f0518337851318065cd86c34b03") (:authors ("Jim Tian" . "tianjin.sc@gmail.com")) (:maintainer "Jim Tian" . "tianjin.sc@gmail.com") (:keywords "convenience" "quotes") (:url . "https://github.com/toctan/toggle-quotes.el"))]) (toggle-test . [(20140723 537) nil "Toggle between source and test files in various programming languages" single ((:commit . "a0b64834101c2b8b24da365baea1d36e57b069b5") (:authors ("Raghunandan Rao" . "r.raghunandan@gmail.com")) (:maintainer "Raghunandan Rao" . "r.raghunandan@gmail.com") (:keywords "tdd" "test" "toggle" "productivity") (:url . "https://github.com/rags/toggle-test"))]) (toggle-window . [(20141207 1548) nil "toggle current window size between half and full" single ((:commit . "e82c60e543933880402ede11e9423e48a17dde53") (:authors ("Kenny Liu")) (:maintainer "Kenny Liu") (:keywords "hide" "window") (:url . "https://github.com/deadghost/toggle-window"))]) - (tok-theme . [(20230303 1924) ((emacs (26 1))) "Minimal, calm and light theme for Emacs" single ((:commit . "5ceaecbaf359745d7bc6d407535895b7e84217c1") (:authors ("Topi Kettunen" . "topi@topikettunen.com")) (:maintainer "Topi Kettunen" . "topi@topikettunen.com") (:url . "https://github.com/topikettunen/tok-theme"))]) + (tok-theme . [(20230328 2146) ((emacs (26 1))) "Minimal light monochromatic theme for Emacs in the spirit of Zmacs and Smalltalk-80" single ((:commit . "c56aa7337bf71d4dac491aa2f9623365c078a604") (:authors ("Topi Kettunen" . "topi@topikettunen.com")) (:maintainer "Topi Kettunen" . "topi@topikettunen.com") (:url . "https://github.com/topikettunen/tok-theme"))]) (tokei . [(20220823 2058) ((emacs (27 1)) (magit-section (3 3 0))) "Display codebase statistics" single ((:commit . "86fbca422f580a95eb30247e46891184f3ac5c18") (:authors ("Daniel Nagy ")) (:maintainer "Daniel Nagy" . "danielnagy@posteo.de") (:url . "https://github.com/nagy/tokei.el"))]) (tomatinho . [(20180621 1748) nil "Simple and beautiful pomodoro timer" tar ((:commit . "b53354b9b9f496c0388d6a573b06b7d6fc53d0bd") (:authors ("Konrad Scorciapino" . "scorciapino@gmail.com")) (:maintainer "Konrad Scorciapino" . "scorciapino@gmail.com") (:keywords "time" "productivity" "pomodoro technique"))]) (toml . [(20130903 1255) nil "TOML (Tom's Obvious, Minimal Language) parser" single ((:commit . "9633a6872928e737a2335aae1065768b23d8c3b3") (:authors ("Wataru MIYAGUNI" . "gonngo@gmail.com")) (:maintainer "Wataru MIYAGUNI" . "gonngo@gmail.com") (:keywords "toml" "parser") (:url . "https://github.com/gongo/emacs-toml"))]) @@ -4979,7 +4986,7 @@ (tree-sitter-ispell . [(20230205 533) ((emacs (26 1)) (tree-sitter (0 15 0))) "Run ispell on tree-sitter text nodes" single ((:commit . "d8c33c05f689c2cab36b8a9856811f18a4ab7c59") (:authors ("Erick Navarro" . "erick@navarro.io")) (:maintainer "Erick Navarro" . "erick@navarro.io") (:url . "https://github.com/erickgnavar/tree-sitter-ispell.el"))]) (tree-sitter-langs . [(20230311 1456) ((emacs (25 1)) (tree-sitter (0 15 0))) "Grammar bundle for tree-sitter" tar ((:commit . "ffe9ab0c8ec9e37e70e31d296df3b85bcfc73c5e") (:authors ("Tuấn-Anh Nguyễn" . "ubolonton@gmail.com")) (:maintainer "Tuấn-Anh Nguyễn" . "ubolonton@gmail.com") (:keywords "languages" "tools" "parsers" "tree-sitter") (:url . "https://github.com/emacs-tree-sitter/tree-sitter-langs"))]) (treefactor . [(20200516 1631) ((emacs (26 1)) (dash (2 16 0)) (f (0 20 0)) (org (9 2 6)) (avy (0 5 0))) "Restructure your messy Org documents" single ((:commit . "75357757022a4399ab772ff0d92065bd114dabe9") (:authors ("Leo Littlebook" . "Leo.Littlebook@gmail.com")) (:maintainer "Leo Littlebook" . "Leo.Littlebook@gmail.com") (:keywords "outlines" "files" "convenience") (:url . "https://github.com/cyberthal/treefactor"))]) - (treemacs . [(20230315 1311) ((emacs (26 1)) (cl-lib (0 5)) (dash (2 11 0)) (s (1 12 0)) (ace-window (0 9 0)) (pfuture (1 7)) (hydra (0 13 2)) (ht (2 2)) (cfrs (1 3 2))) "A tree style file explorer package" tar ((:commit . "de52963930311431279c83cd0ea4a49766c76016") (:authors ("Alexander Miller" . "alexanderm@web.de")) (:maintainer "Alexander Miller" . "alexanderm@web.de") (:url . "https://github.com/Alexander-Miller/treemacs"))]) + (treemacs . [(20230323 629) ((emacs (26 1)) (cl-lib (0 5)) (dash (2 11 0)) (s (1 12 0)) (ace-window (0 9 0)) (pfuture (1 7)) (hydra (0 13 2)) (ht (2 2)) (cfrs (1 3 2))) "A tree style file explorer package" tar ((:commit . "a20d49ed62fa64a4164a9a3f25c102ec0a338367") (:authors ("Alexander Miller" . "alexanderm@web.de")) (:maintainer "Alexander Miller" . "alexanderm@web.de") (:url . "https://github.com/Alexander-Miller/treemacs"))]) (treemacs-all-the-icons . [(20220911 1427) ((emacs (26 1)) (all-the-icons (4 0 1)) (treemacs (0 0))) "all-the-icons integration for treemacs" single ((:commit . "861418d9d11b205930bd4555a40b430b9dde9dd4") (:authors ("Eric Dallo" . "ercdll1337@gmail.com")) (:maintainer "Eric Dallo" . "ercdll1337@gmail.com") (:url . "https://github.com/Alexander-Miller/treemacs"))]) (treemacs-evil . [(20220911 1427) ((emacs (26 1)) (evil (1 2 12)) (treemacs (0 0))) "Evil mode integration for treemacs" single ((:commit . "861418d9d11b205930bd4555a40b430b9dde9dd4") (:authors ("Alexander Miller" . "alexanderm@web.de")) (:maintainer "Alexander Miller" . "alexanderm@web.de") (:url . "https://github.com/Alexander-Miller/treemacs"))]) (treemacs-icons-dired . [(20220915 1626) ((treemacs (0 0)) (emacs (26 1))) "Treemacs icons for dired" single ((:commit . "1961981c81122b22ea70962f45c01feeb54c3800") (:authors ("Alexander Miller" . "alexanderm@web.de")) (:maintainer "Alexander Miller" . "alexanderm@web.de") (:url . "https://github.com/Alexander-Miller/treemacs"))]) @@ -5039,7 +5046,7 @@ (undersea-theme . [(20220616 1950) ((emacs (24 3))) "Theme styled after undersea imagery" single ((:commit . "6bc351c4cb49ccc7210801e6b54ecc2993289b92") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "theme" "sea") (:url . "https://github.com/jcs-elpa/undersea-theme"))]) (underwater-theme . [(20131118 2) nil "A gentle, deep blue color theme" single ((:commit . "1fbd4ecd4538256c6c46f9638f883072c73ac927") (:authors ("Jon-Michael Deldin" . "dev@jmdeldin.com")) (:maintainer "Jon-Michael Deldin" . "dev@jmdeldin.com") (:keywords "faces"))]) (undo-fu . [(20230109 2256) ((emacs (25 1))) "Undo helper with redo" single ((:commit . "d59bba01de48a808a42d6e29e011ef641cdb6a77") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:url . "https://codeberg.org/ideasman42/emacs-undo-fu"))]) - (undo-fu-session . [(20230205 310) ((emacs (28 1))) "Persistent undo, available between sessions" single ((:commit . "7b3fd0647dd1fbd02101eec61440e6d44953bcd9") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:keywords "convenience") (:url . "https://codeberg.com/ideasman42/emacs-undo-fu-session"))]) + (undo-fu-session . [(20230405 221) ((emacs (28 1))) "Persistent undo, available between sessions" single ((:commit . "6a306462ee1fa3a7c6303561f9ddf510e448b731") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:keywords "convenience") (:url . "https://codeberg.com/ideasman42/emacs-undo-fu-session"))]) (undo-propose . [(20210207 45) ((emacs (24 3))) "Simple and safe undo navigation" single ((:commit . "91a1dfe516d90dab69c368f6669bacb2458ec5e9") (:authors ("Jack Kamm")) (:maintainer "Jack Kamm") (:keywords "convenience" "files" "undo" "redo" "history") (:url . "https://github.com/jackkamm/undo-propose.el"))]) (undohist . [(20220219 634) ((cl-lib (1 0))) "Persistent undo history for GNU Emacs" single ((:commit . "94959e708d5a74913788324893d0b6dabc88ff18") (:authors ("MATSUYAMA Tomohiro" . "m2ym.pub@gmail.com")) (:maintainer "MATSUYAMA Tomohiro" . "m2ym.pub@gmail.com") (:keywords "convenience"))]) (unfill . [(20230227 1349) ((emacs (24 1))) "Do the opposite of fill-paragraph or fill-region" single ((:commit . "075052ce0b4451d7d3ede013ce5a77e6a7a92360") (:authors ("Steve Purcell" . "steve@sanityinc.com")) (:maintainer "Steve Purcell" . "steve@sanityinc.com") (:keywords "convenience") (:url . "https://github.com/purcell/unfill"))]) @@ -5103,8 +5110,8 @@ (vc-hgcmd . [(20211021 1704) ((emacs (25 1))) "VC mercurial backend that uses hg command server" single ((:commit . "d044448965d31ca8214f8bca48487e4d9b9d9a0f") (:authors ("Andrii Kolomoiets" . "andreyk.mad@gmail.com")) (:maintainer "Andrii Kolomoiets" . "andreyk.mad@gmail.com") (:keywords "vc") (:url . "https://github.com/muffinmad/emacs-vc-hgcmd"))]) (vc-msg . [(20221005 1228) ((emacs (24 4)) (popup (0 5 0))) "Show commit information of current line" tar ((:commit . "027fefad63868cd7695372510c27922656cf996a") (:authors ("Chen Bin ")) (:maintainer "Chen Bin ") (:keywords "git" "vc" "svn" "hg" "messenger") (:url . "http://github.com/redguardtoo/vc-msg"))]) (vc-osc . [(20190402 2349) nil "non-resident support for osc version-control" single ((:commit . "bf5a515ed85f7d7cdfe66ed5bf4ef7554f8561e5") (:authors ("Adam Spiers (see vc.el for full credits)")) (:maintainer "Adam Spiers" . "aspiers@suse.com"))]) - (vcomp . [(20190128 20) nil "compare version strings" single ((:commit . "f839b3b3257a564b19d7f9557dc8bcbbe0b95842") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "versions") (:url . "https://github.com/tarsius/vcomp"))]) - (vcsh . [(20200226 1339) ((emacs (25 1))) "vcsh integration" single ((:commit . "7e376436b8f450a5571e19246136ccf77bbdd4f1") (:authors ("Štěpán Němec" . "stepnem@gmail.com")) (:maintainer "Štěpán Němec" . "stepnem@gmail.com") (:keywords "vc" "files") (:url . "https://gitlab.com/stepnem/vcsh-el"))]) + (vcomp . [(20230406 1934) ((emacs (24 1))) "Compare version strings" single ((:commit . "5e5af87d20f7a7727198c9cb064b39e9fd2c8c08") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "versions") (:url . "https://github.com/tarsius/vcomp"))]) + (vcsh . [(20230402 1229) ((emacs (25 1))) "vcsh integration" single ((:commit . "b9c0109a8c77446980de668785e6af1e46bdcdcd") (:authors ("Štěpán Němec" . "stepnem@smrk.net")) (:maintainer "Štěpán Němec" . "stepnem@smrk.net") (:keywords "vc" "files") (:url . "http://git.smrk.net/vcsh.el"))]) (vdf-mode . [(20210303 714) ((emacs (24 3))) "Major mode for editing Valve VDF files." single ((:commit . "0910d4f847e9c817eb8da5434b3879048ec4ac92") (:authors ("Philipp Middendorf")) (:maintainer "Philipp Middendorf") (:url . "https://github.com/plapadoo/vdf-mode"))]) (vdiff . [(20220830 1450) ((emacs (24 4)) (hydra (0 13 0))) "A diff tool similar to vimdiff" single ((:commit . "d5df45f84395f507aba555a54407b60e284b23cd") (:authors ("Justin Burkett" . "justin@burkett.cc")) (:maintainer "Justin Burkett" . "justin@burkett.cc") (:keywords "diff") (:url . "https://github.com/justbur/emacs-vdiff"))]) (vdiff-magit . [(20220518 1948) ((emacs (24 4)) (vdiff (0 3)) (magit (2 10 0)) (transient (0 1 0))) "magit integration for vdiff" single ((:commit . "413f32c9f7e66f8379c23b5ab6341695dbcc2f20") (:authors ("Justin Burkett" . "justin@burkett.cc")) (:maintainer "Justin Burkett" . "justin@burkett.cc") (:keywords "diff") (:url . "https://github.com/justbur/emacs-vdiff-magit"))]) @@ -5156,7 +5163,7 @@ (vs-light-theme . [(20230310 913) ((emacs (24 1))) "Visual Studio IDE light theme" single ((:commit . "5accd5c1e4581005a0859cf7d85b0191b6b7a30b") (:authors ("Jen-Chieh Shen")) (:maintainer "Jen-Chieh Shen") (:url . "https://github.com/emacs-vs/vs-light-theme"))]) (vscdark-theme . [(20191212 107) ((emacs (24 1))) "VS Code Dark+ like theme" single ((:commit . "f419553e2a2f091a8bc257fb5ab520326e93ddd4") (:authors ("Alexander L. Belikoff")) (:maintainer "Alexander L. Belikoff") (:url . "https://github.com/abelikoff/vscdark-theme"))]) (vscode-dark-plus-theme . [(20221121 1846) nil "Default Visual Studio Code Dark+ theme" single ((:commit . "f33e1f92f6b34bbd7ecc81cb4c6d48f9cab393d9") (:authors ("Ian Y.E. Pan")) (:maintainer "Ian Y.E. Pan") (:url . "https://github.com/ianpan870102/vscode-dark-plus-emacs-theme"))]) - (vscode-icon . [(20201214 2227) ((emacs (25 1))) "Utility package to provide Vscode style icons" tar ((:commit . "909151c8105861aa300f5601e333909d36d0ebf5") (:authors ("James Nguyen" . "james@jojojames.com")) (:maintainer "James Nguyen" . "james@jojojames.com") (:keywords "files" "tools") (:url . "https://github.com/jojojames/vscode-icon-emacs"))]) + (vscode-icon . [(20230330 2206) ((emacs (25 1))) "Utility package to provide Vscode style icons" tar ((:commit . "3976bc2e7e2fe0068ae59c11d226f67e0e87aaea") (:authors ("James Nguyen" . "james@jojojames.com")) (:maintainer "James Nguyen" . "james@jojojames.com") (:keywords "files" "tools") (:url . "https://github.com/jojojames/vscode-icon-emacs"))]) (vterm . [(20230217 228) ((emacs (25 1))) "Fully-featured terminal emulator" tar ((:commit . "3e5a9b754b8e61850bb7d1b63b090b9fbf6687f3") (:authors ("Lukas Fürmetz" . "fuermetz@mailbox.org")) (:maintainer "Lukas Fürmetz" . "fuermetz@mailbox.org") (:keywords "terminals") (:url . "https://github.com/akermu/emacs-libvterm"))]) (vterm-toggle . [(20220820 1608) ((emacs (25 1)) (vterm (0 0 1))) "Toggles between the vterm buffer and other buffers." single ((:commit . "b94522e3a4ddaae098f4711aadce675e891cdec8") (:authors (nil . "jixiuf jixiuf@qq.com")) (:maintainer nil . "jixiuf jixiuf@qq.com") (:keywords "vterm" "terminals") (:url . "https://github.com/jixiuf/vterm-toggle"))]) (vtm . [(20200921 338) nil "Manages vterm buffers with configuration files" tar ((:commit . "d770fd8cff7c24688199392ad93c01485c6a9569") (:keywords "convenience") (:url . "https://github.com/laishulu/emacs-vterm-manager"))]) @@ -5168,7 +5175,7 @@ (vyper-mode . [(20180707 1935) ((emacs (24 3))) "Major mode for the Vyper programming language" single ((:commit . "323dfddfc38f0b11697e9ebaf04d1b53297e54e5") (:authors ("Alex Stokes" . "r.alex.stokes@gmail.com")) (:maintainer "Alex Stokes" . "r.alex.stokes@gmail.com") (:keywords "languages") (:url . "https://github.com/ralexstokes/vyper-mode"))]) (w32-browser . [(20170101 1954) nil "Run Windows application associated with a file." single ((:commit . "e5c60eafd8f8d3546a0fa295ad5af2414d36b4e6") (:authors ("Emacs Wiki, Drew Adams")) (:maintainer nil . "Drew Adams (concat \"drew.adams\" \"@\" \"oracle\" \".com\")") (:keywords "mouse" "dired" "w32" "explorer") (:url . "http://www.emacswiki.org/w32-browser.el"))]) (w32-ime . [(20201107 143) ((emacs (24 4))) "Windows IME UI/UX controler" single ((:commit . "9c62273dce0ba685a591577885b1e216ba832ec1") (:authors ("H.Miyashita") ("MIYOSHI Masanori") ("KOBAYASHI Yasuhiro") ("NTEmacsJP") ("ksugita (gnupack)") ("rzl24ozi") ("TANE") ("Masamichi Hosoda" . "trueroad@trueroad.jp") ("Naoya Yamashita" . "conao3@gmail.com")) (:maintainer "Masamichi Hosoda" . "trueroad@trueroad.jp") (:url . "https://github.com/trueroad/w32-ime.el"))]) - (w3m . [(20230119 418) nil "an Emacs interface to w3m" tar ((:commit . "d7f99ea4561004f7f15e8d17f5f7a084d04f3925") (:keywords "w3m" "www" "hypermedia"))]) + (w3m . [(20230324 125) nil "an Emacs interface to w3m" tar ((:commit . "f8819bca0c97970662cd4214f8f3104ab4a376c1") (:keywords "w3m" "www" "hypermedia"))]) (wacspace . [(20180311 2350) ((dash (1 2 0)) (cl-lib (0 2))) "The WACky WorkSPACE manager for emACS" tar ((:commit . "54d19aab6fd2bc5945b7ffc58104e695064927e2") (:authors ("Emanuel Evans" . "emanuel.evans@gmail.com")) (:maintainer "Emanuel Evans" . "emanuel.evans@gmail.com") (:keywords "workspace") (:url . "http://github.com/shosti/wacspace.el"))]) (waf-mode . [(20170403 1940) nil "Waf integration for Emacs" single ((:commit . "91c761336aa137b85b88b53b3f0cc60786d70800") (:authors ("Denys Valchuk" . "dvalchuk@gmail.com")) (:maintainer "Denys Valchuk" . "dvalchuk@gmail.com") (:url . "https://bitbucket.org/dvalchuk/waf-mode"))]) (waher-theme . [(20141115 1230) ((emacs (24 1))) "Emacs 24 theme based on waher for st2 by dduckster" single ((:commit . "60d31519fcfd8e797723d47961b255ae2f2e2c0a") (:authors ("Jasonm23" . "jasonm23@gmail.com")) (:maintainer "Jasonm23" . "jasonm23@gmail.com") (:url . "https://github.com/jasonm23/emacs-waher-theme"))]) @@ -5181,7 +5188,7 @@ (wallpreview . [(20220703 1108) ((emacs (24 4))) "Set wallpapers with image-dired" single ((:commit . "6eae0549afdfe725b453ca4fb0878c728735892d") (:url . "https://github.com/nryotaro/wallpreview"))]) (wand . [(20220519 1214) nil "Magic wand for Emacs - Select and execute" tar ((:commit . "e4afc0469c818e7ce73ef31c38d911477947d72e") (:authors ("Ha-Duong Nguyen ")) (:maintainer "Ha-Duong Nguyen ") (:keywords "extensions" "tools") (:url . "https://github.com/cmpitg/wand"))]) (wandbox . [(20170603 1231) ((emacs (24)) (request (0 3 0)) (s (1 10 0))) "Wandbox client" tar ((:commit . "e002fe41f2cd9b4ce2b1dc80b83301176e9117f1") (:authors ("KOBAYASHI Shigeru (kosh)" . "shigeru.kb@gmail.com")) (:maintainer "KOBAYASHI Shigeru (kosh)" . "shigeru.kb@gmail.com") (:keywords "tools") (:url . "https://github.com/kosh04/emacs-wandbox"))]) - (wanderlust . [(20230120 904) ((emacs (24 5)) (apel (10 8)) (flim (1 14 9)) (semi (1 14 7))) "Yet Another Message Interface on Emacsen" tar ((:commit . "77662986fd91cff991f502b19262227227740d52"))]) + (wanderlust . [(20230329 931) ((emacs (24 5)) (apel (10 8)) (flim (1 14 9)) (semi (1 14 7))) "Yet Another Message Interface on Emacsen" tar ((:commit . "74b4fe3ebfffbaec85dbc14c09750cc67ca60f9b"))]) (warm-night-theme . [(20161101 1428) ((emacs (24))) "Emacs 24 theme with a dark background." single ((:commit . "020f084d23409b5035150508ba6e57c2509edd64") (:authors ("martin haesler")) (:maintainer "martin haesler"))]) (wasp-mode . [(20230226 2035) ((emacs (24 3))) "A major mode for the Wasp programming language" single ((:commit . "00fc41ecfe0291cc32e012a074d8a3a65e1bfd64") (:authors ("XXIV")) (:maintainer "XXIV") (:keywords "files" "wasp") (:url . "https://github.com/thechampagne/wasp-mode"))]) (watch-buffer . [(20120331 2044) nil "run a shell command when saving a buffer" single ((:commit . "a01cf15608c5bf91df253104053041ca1afdf411") (:authors ("Michael Steger" . "mjsteger1@gmail.com")) (:maintainer "Michael Steger" . "mjsteger1@gmail.com") (:keywords "automation" "convenience") (:url . "https://github.com/mjsteger/watch-buffer"))]) @@ -5194,7 +5201,7 @@ (web . [(20141231 2001) ((dash (2 9 0)) (s (1 5 0))) "useful HTTP client" single ((:commit . "483188dac4bc6b409b985c9dae45f3324a425efd") (:authors ("Nic Ferrier" . "nferrier@ferrier.me.uk")) (:maintainer "Nic Ferrier" . "nferrier@ferrier.me.uk") (:keywords "lisp" "http" "hypermedia") (:url . "http://github.com/nicferrier/emacs-web"))]) (web-beautify . [(20161115 2247) nil "Format HTML, CSS and JavaScript/JSON" single ((:commit . "e1b45321d8c11b404b12c8e55afe55eaa7c84ee9") (:authors ("Yasuyuki Oka" . "yasuyk@gmail.com")) (:maintainer "Yasuyuki Oka" . "yasuyk@gmail.com") (:url . "https://github.com/yasuyk/web-beautify"))]) (web-completion-data . [(20160318 848) nil "Shared completion data for ac-html and company-web" tar ((:commit . "c272c94e8a71b779c29653a532f619acad433a4f") (:authors ("Olexandr Sydorchuk" . "olexandr.syd@gmail.com")) (:maintainer "Olexandr Sydorchuk" . "olexandr.syd@gmail.com") (:keywords "html" "auto-complete" "company") (:url . "https://github.com/osv/web-completion-data"))]) - (web-mode . [(20230317 1031) ((emacs (23 1))) "major mode for editing web templates" single ((:commit . "ff394e83b48e9ae05cf3be854272c1e4550de61a") (:authors ("François-Xavier Bois")) (:maintainer "François-Xavier Bois" . "fxbois@gmail.com") (:keywords "languages") (:url . "https://web-mode.org"))]) + (web-mode . [(20230329 601) ((emacs (23 1))) "major mode for editing web templates" single ((:commit . "57856ba64b9382811b35df0d9ab0a24aede0c1f0") (:authors ("François-Xavier Bois")) (:maintainer "François-Xavier Bois" . "fxbois@gmail.com") (:keywords "languages") (:url . "https://web-mode.org"))]) (web-mode-edit-element . [(20190531 852) ((emacs (24 4)) (web-mode (14))) "Helper-functions for attribute- and element-handling" tar ((:commit . "ad5d7e4dc2420bdd00ce65d9adffbd38a5904afa") (:authors ("Julian T. Knabenschuh" . "jtkdevelopments@gmail.com")) (:maintainer "Julian T. Knabenschuh" . "jtkdevelopments@gmail.com") (:keywords "languages" "convenience") (:url . "https://github.com/jtkDvlp/web-mode-edit-element"))]) (web-narrow-mode . [(20170407 210) ((web-mode (14 0 27))) "quick narrow code block in web-mode" single ((:commit . "b25fae07844875d5b62d14b98442c88817b7e139") (:authors ("Qquanwei" . "quanwei9958@126.com")) (:maintainer "Johan Andersson" . "quanwei9958@126.com") (:keywords "web-mode" "react" "narrow" "web") (:url . "https://github.com/Qquanwei/web-narrow-mode"))]) (web-search . [(20190620 602) ((emacs (24 3))) "Open a web search" tar ((:commit . "a22cbdc663a1895d5a5b69de91e1e3b9eb64b92f") (:authors ("Xu Chunyang" . "mail@xuchunyang.me")) (:maintainer "Xu Chunyang" . "mail@xuchunyang.me") (:keywords "web" "search") (:url . "https://github.com/xuchunyang/web-search.el"))]) @@ -5219,7 +5226,7 @@ (wgrep-pt . [(20230207 1125) ((emacs (25 1)) (wgrep (3 0 0))) "Writable pt buffer" single ((:commit . "edf768732a56840db6879706b64c5773c316d619") (:authors ("Masahiro Hayashi , Bailey Ling" . "bling@live.ca")) (:maintainer "Masahiro Hayashi , Bailey Ling" . "bling@live.ca") (:keywords "grep" "edit" "extensions") (:url . "http://github.com/mhayashi1120/Emacs-wgrep/raw/master/wgrep-pt.el"))]) (wgsl-mode . [(20221127 2129) ((emacs (24))) "Syntax highlighting for the WebGPU Shading Language" single ((:commit . "e7856d6755d93e40ed74598a68ef5f607322618b") (:authors ("Anthony Cowley")) (:maintainer "Anthony Cowley") (:keywords "wgsl" "c") (:url . "https://github.com/acowley/wgsl-mode"))]) (what-the-commit . [(20150901 1316) nil "Random commit message generator" single ((:commit . "42604410cfd5be715c8aa730aef4673773454e8b") (:authors ("Dan Barbarito" . "dan@barbarito.me")) (:maintainer "Dan Barbarito" . "dan@barbarito.me") (:keywords "git" "commit" "message") (:url . "http://barbarito.me/"))]) - (which-key . [(20220811 1616) ((emacs (24 4))) "Display available keybindings in popup" single ((:commit . "8093644032854b1cdf3245ce4e3c7b6673f741bf") (:authors ("Justin Burkett" . "justin@burkett.cc")) (:maintainer "Justin Burkett" . "justin@burkett.cc") (:url . "https://github.com/justbur/emacs-which-key"))]) + (which-key . [(20230330 2121) ((emacs (24 4))) "Display available keybindings in popup" single ((:commit . "bd34ede7bf77ad3988330b37207f3978e7342c79") (:authors ("Justin Burkett" . "justin@burkett.cc")) (:maintainer "Justin Burkett" . "justin@burkett.cc") (:url . "https://github.com/justbur/emacs-which-key"))]) (which-key-posframe . [(20230313 1841) ((emacs (26 0)) (posframe (1 4 0)) (which-key (3 6 0))) "Using posframe to show which-key" single ((:commit . "e4a9ce9a1b20de550fca51f14d055821980d534a") (:authors ("Yanghao Xie" . "yhaoxie@gmail.com")) (:maintainer "Yanghao Xie" . "yhaoxie@gmail.com") (:keywords "convenience" "bindings" "tooltip") (:url . "https://github.com/emacsorphanage/which-key-posframe"))]) (whiley-mode . [(20220501 2219) ((emacs (24 1))) "Major mode for Whiley language" single ((:commit . "e7cc4759d46be589d421a2235af6771bcde9ae33") (:authors ("David J. Pearce" . "dave01001110@gmail.com")) (:maintainer "David J. Pearce" . "dave01001110@gmail.com") (:keywords "languages") (:url . "http://github.com/Whiley/WhileyEmacsMode"))]) (whitaker . [(20210203 1149) ((emacs (25))) "Comint interface for Whitaker's Words" single ((:commit . "a6fda24ccb69a18c0706633326d5cc4fcfaed83a") (:authors ("Matus Goljer" . "matus.goljer@gmail.com")) (:maintainer "Matus Goljer" . "matus.goljer@gmail.com") (:keywords "processes"))]) @@ -5269,11 +5276,11 @@ (wordel . [(20230109 1407) ((emacs (27 1))) "An Elisp implementation of \"Wordle\" (aka \"Lingo\")" tar ((:commit . "77999d75c5eae29e22b8e3f8859b62c6e30aa65f") (:authors ("Nicholas Vollmer" . "iarchivedmywholelife@gmail.com")) (:maintainer "Nicholas Vollmer" . "iarchivedmywholelife@gmail.com") (:keywords "games") (:url . "https://github.com/progfolio/wordel"))]) (wordgen . [(20170803 1820) ((emacs (24)) (cl-lib (0 5))) "Random word generator" single ((:commit . "aacad928ae99a953e034a831dfd0ebdf7d52ac1d") (:authors ("Fanael Linithien" . "fanael4@gmail.com")) (:maintainer "Fanael Linithien" . "fanael4@gmail.com") (:url . "https://github.com/Fanael/wordgen.el"))]) (wordnut . [(20180313 443) ((emacs (24 4))) "Major mode interface to WordNet" tar ((:commit . "feac531404041855312c1a046bde7ea18c674915"))]) - (wordreference . [(20230304 1307) ((emacs (27 1)) (s (1 12 0))) "Interface for wordreference.com" single ((:commit . "ea741be7ff0979552f7dfb591596075add0293b7") (:authors ("Marty Hiatt ")) (:maintainer "Marty Hiatt ") (:keywords "convenience" "translate" "wp" "dictionary") (:url . "https://codeberg.org/martianh/wordreference.el"))]) + (wordreference . [(20230405 1353) ((emacs (28 1))) "Interface for wordreference.com" single ((:commit . "fcc791173a0e9f89d05b651a09f7d64a21aff584") (:authors ("Marty Hiatt ")) (:maintainer "Marty Hiatt ") (:keywords "convenience" "translate" "wp" "dictionary") (:url . "https://codeberg.org/martianh/wordreference.el"))]) (wordsmith-mode . [(20210715 1517) nil "Syntax analysis and NLP text-processing in Emacs (OSX-only)" single ((:commit . "5d40ceaa2b8d41ab3634ca377ceb6a74deeb2287") (:authors ("istib" . "istib@thebati.net")) (:maintainer "istib" . "istib@thebati.net"))]) (worf . [(20220102 835) ((swiper (0 11 0)) (ace-link (0 1 0)) (hydra (0 13 0)) (zoutline (0 1 0))) "A warrior does not press so many keys! (in org-mode)" tar ((:commit . "8681241e118585824cd256e5b026978bf06c7e58") (:authors ("Oleh Krehel" . "ohwoeowho@gmail.com")) (:maintainer "Oleh Krehel" . "ohwoeowho@gmail.com") (:keywords "lisp") (:url . "https://github.com/abo-abo/worf"))]) (workgroups . [(20110726 1641) nil "workgroups for windows (for Emacs)" single ((:commit . "9572b3492ee09054dc329f64ed846c962b395e39") (:authors ("tlh" . "thunkout@gmail.com")) (:maintainer "tlh" . "thunkout@gmail.com") (:keywords "session" "management" "window-configuration" "persistence"))]) - (workgroups2 . [(20220702 842) ((emacs (25 1))) "save&load multiple named workspaces (or \"workgroups\")" tar ((:commit . "a8a4d07bff27f72970fe7e204997f1ba0e80263b") (:authors ("Sergey Pashinin ")) (:maintainer "Sergey Pashinin ") (:keywords "session" "management" "window-configuration" "persistence") (:url . "https://github.com/pashinin/workgroups2"))]) + (workgroups2 . [(20230328 1331) ((emacs (25 1))) "save&load multiple named workspaces (or \"workgroups\")" tar ((:commit . "aff9d76b7be5eed33f30be2fabf111818749cbd5") (:authors ("Sergey Pashinin ")) (:maintainer "Sergey Pashinin ") (:keywords "session" "management" "window-configuration" "persistence") (:url . "https://github.com/pashinin/workgroups2"))]) (workroom . [(20230123 1630) ((emacs (25 1)) (project (0 3 0)) (compat (28 1 2 2))) "Named rooms for work without irrelevant distracting buffers" tar ((:commit . "360420501a239f74bff60941d28052fc19a92bce") (:authors ("Akib Azmain Turja" . "akib@disroot.org")) (:maintainer "Akib Azmain Turja" . "akib@disroot.org") (:keywords "tools" "convenience") (:url . "https://codeberg.org/akib/emacs-workroom"))]) (world-time-mode . [(20140627 807) nil "show whole days of world-time diffs" single ((:commit . "ce7a3b45c87eb24cfe61eee453175d64f741d7cc") (:authors ("Nic Ferrier" . "nferrier@ferrier.me.uk")) (:maintainer "Nic Ferrier" . "nferrier@ferrier.me.uk") (:keywords "tools" "calendar"))]) (wotd . [(20170328 1948) ((emacs (24 4)) (org (8 2 10))) "Fetch word-of-the-day from multiple online sources" single ((:commit . "d2937a3d91e014f8028a1f33d21c18cc0b065a64") (:authors ("Junpeng Qiu" . "qjpchmail@gmail.com")) (:maintainer "Junpeng Qiu" . "qjpchmail@gmail.com") (:keywords "extensions"))]) @@ -5323,7 +5330,7 @@ (xwwp . [(20200917 643) ((emacs (26 1))) "Enhance xwidget webkit browser" tar ((:commit . "f67e070a6e1b233e60274deb717274b000923231") (:authors ("Damien Merenne")) (:maintainer "Damien Merenne") (:keywords "convenience") (:url . "https://github.com/canatella/xwwp"))]) (xwwp-follow-link-helm . [(20200917 642) ((emacs (26 1)) (xwwp (0 1))) "Link navigation in `xwidget-webkit' sessions using `helm'" single ((:commit . "99670ec37e2083eada9691a342441d2fa4589002") (:authors ("Damien Merenne")) (:maintainer "Damien Merenne") (:keywords "convenience") (:url . "https://github.com/canatella/xwwp"))]) (xwwp-follow-link-ivy . [(20200917 642) ((emacs (26 1)) (xwwp (0 1))) "Link navigation in `xwidget-webkit' sessions using `ivy'" single ((:commit . "1f1646feaf3328568da40200cc218337fbbabc1a") (:authors ("Damien Merenne")) (:maintainer "Damien Merenne") (:keywords "convenience") (:url . "https://github.com/canatella/xwwp"))]) - (yabaki-theme . [(20230117 2312) ((emacs (27 1))) "Yabaki, the cast shadow" single ((:commit . "5b0aaaf352384f24b0104065b5c600e8e6fab707") (:authors ("David Goudou" . "david.goudou@gmail.com")) (:maintainer "David Goudou" . "david.goudou@gmail.com") (:url . "https://github.com/seamacs/yabaki-theme"))]) + (yabaki-theme . [(20230327 630) ((emacs (27 1))) "Yabaki, the cast shadow" single ((:commit . "5face6a1194b039e09fe19238aa5db05450d7df1") (:authors ("David Goudou" . "david.goudou@gmail.com")) (:maintainer "David Goudou" . "david.goudou@gmail.com") (:url . "https://github.com/seamacs/yabaki-theme"))]) (yabin . [(20140206 351) nil "Yet Another Bignum package (A thin wrapper of calc.el)." single ((:commit . "db8c404507560ef9147fcce2b94cd706fbfa03b5") (:authors ("Daisuke Kobayashi" . "d5884jp@gmail.com")) (:maintainer "Daisuke Kobayashi" . "d5884jp@gmail.com") (:keywords "data"))]) (yafolding . [(20200119 1353) nil "Folding code blocks based on indentation" single ((:commit . "4c1888ae45f9241516519ae0ae3a899f2efa05ba") (:authors ("Zeno Zeng" . "zenoofzeng@gmail.com")) (:maintainer "Zeno Zeng" . "zenoofzeng@gmail.com") (:keywords "folding"))]) (yagist . [(20160418 508) ((cl-lib (0 3))) "Yet Another Emacs integration for gist.github.com" single ((:commit . "10da4baa272ff0f7052f17debecc340764c7003f") (:maintainer "Masahiro Hayashi" . "mhayashi1120@gmail.com") (:keywords "tools") (:url . "https://github.com/mhayashi1120/yagist.el"))]) @@ -5331,7 +5338,7 @@ (yalinum . [(20130217 1043) nil "yet another display line numbers." single ((:commit . "d3e0cbe3f4f5ca311e3298e684901d6fea3ad973") (:authors ("tm8st" . "tm8st@hotmail.co.jp")) (:maintainer "tm8st" . "tm8st@hotmail.co.jp") (:keywords "convenience" "tools"))]) (yaml . [(20230312 250) ((emacs (25 1))) "YAML parser for Elisp" single ((:commit . "a19fbf948a945571300e5a20ff1dbfa6ecfa0d16") (:authors ("Zachary Romero" . "zkry@posteo.org")) (:maintainer "Zachary Romero" . "zkry@posteo.org") (:keywords "tools") (:url . "https://github.com/zkry/yaml.el"))]) (yaml-imenu . [(20220406 1703) ((emacs (24 4)) (yaml-mode (0))) "Enhancement of the imenu support in yaml-mode." tar ((:commit . "c1fbba8b03a7bef4fc2b87404914fa9c6eb67b55") (:authors ("Akinori MUSHA" . "knu@iDaemons.org")) (:maintainer "Akinori MUSHA" . "knu@iDaemons.org") (:keywords "outlining" "convenience" "imenu") (:url . "https://github.com/knu/yaml-imenu.el"))]) - (yaml-mode . [(20221022 920) ((emacs (24 1))) "Major mode for editing YAML files" single ((:commit . "141b85f9e01589e67955f3785a83b72b42109357") (:authors ("Yoshiki Kurihara" . "clouder@gmail.com") ("Marshall T. Vandegrift" . "llasram@gmail.com")) (:maintainer "Vasilij Schneidermann" . "mail@vasilij.de") (:keywords "data" "yaml") (:url . "https://github.com/yoshiki/yaml-mode"))]) + (yaml-mode . [(20230329 723) ((emacs (24 1))) "Major mode for editing YAML files" single ((:commit . "b153150e0e77b4ec462d741cdb16956c6ae270d6") (:authors ("Yoshiki Kurihara" . "clouder@gmail.com") ("Marshall T. Vandegrift" . "llasram@gmail.com")) (:maintainer "Vasilij Schneidermann" . "mail@vasilij.de") (:keywords "data" "yaml") (:url . "https://github.com/yoshiki/yaml-mode"))]) (yaml-pro . [(20230315 320) ((emacs (26 1)) (yaml (0 5 1))) "Parser-aided YAML editing features" tar ((:commit . "50fc911b9015708b77872dc60c53f4a4740bef1b") (:authors ("Zachary Romero")) (:maintainer "Zachary Romero") (:keywords "tools") (:url . "https://github.com/zkry/yaml-pro"))]) (yaml-tomato . [(20151123 753) ((s (1 9))) "copy or show the yaml path currently under cursor." single ((:commit . "1272c502fac6ce6b0f8b7f8a9beb353f0b35e13c") (:authors ("qrczeno")) (:maintainer "qrczeno") (:keywords "yaml"))]) (yang-mode . [(20190507 724) nil "major mode for editing YANG files" single ((:commit . "4b4ab4d4a79d37d6c31c6ea7cccbc425e0b1eded") (:authors ("Martin Bjorklund" . "mbj4668@gmail.com")) (:maintainer "Martin Bjorklund" . "mbj4668@gmail.com"))]) @@ -5346,7 +5353,7 @@ (yasnippet-lean . [(20220105 2251) ((yasnippet (0 8 0))) "Collection of snippets for the Lean prover" tar ((:commit . "c75485757cc8675ad4f36c1eb028d9d54dc21733") (:maintainer "Simon Hudon" . "simon.hudon@gmail.com") (:keywords "convenience" "snippets" "leanprover") (:url . "https://github.com/leanprover-community/yasnippet-lean"))]) (yasnippet-snippets . [(20230314 2056) ((yasnippet (0 8 0))) "Collection of yasnippet snippets" tar ((:commit . "8e4c521252501dd9ad71ea78fae14683ab7a14cb") (:authors ("Andrea Crotti" . "andrea.crotti.0@gmail.com")) (:maintainer "Andrea Crotti" . "andrea.crotti.0@gmail.com") (:keywords "snippets") (:url . "https://github.com/AndreaCrotti/yasnippet-snippets"))]) (yatemplate . [(20211115 1208) ((yasnippet (0 8 1)) (emacs (24 3))) "File templates with yasnippet" single ((:commit . "275745ce1482edc08efb0b7807bc86d832bcc734") (:authors ("Wieland Hoffmann" . "themineo+yatemplate@gmail.com")) (:maintainer "Wieland Hoffmann" . "themineo+yatemplate@gmail.com") (:keywords "files" "convenience") (:url . "https://github.com/mineo/yatemplate"))]) - (yatex . [(20221216 904) nil "Yet Another tex-mode for emacs //野鳥//" tar ((:commit . "c11261c0960fe44c8664aa017924475dde9d7f71"))]) + (yatex . [(20221225 512) nil "Yet Another tex-mode for emacs //野鳥//" tar ((:commit . "157aa7974191bbb4707d26b05ce830282ad70ef5"))]) (yaxception . [(20150105 1540) nil "Provide framework about exception like Java for Elisp" single ((:commit . "4e94cf3e0b9b5631b0e90eb4b7de597ee7185875") (:authors ("Hiroaki Otsu" . "ootsuhiroaki@gmail.com")) (:maintainer "Hiroaki Otsu" . "ootsuhiroaki@gmail.com") (:keywords "exception" "error" "signal") (:url . "https://github.com/aki2o/yaxception"))]) (ycm . [(20150822 1836) nil "Emacs client for the YouCompleteMe auto-completion server." single ((:commit . "4da8a14abcd0f4fa3235042ade2e12b5068c0601") (:authors ("Ajay Gopinathan" . "ajay@gopinathan.net")) (:maintainer "Ajay Gopinathan" . "ajay@gopinathan.net") (:keywords "c" "abbrev"))]) (ycmd . [(20190416 807) ((emacs (24 4)) (dash (2 13 0)) (s (1 11 0)) (deferred (0 5 1)) (cl-lib (0 6 1)) (let-alist (1 0 5)) (request (0 3 0)) (request-deferred (0 3 0)) (pkg-info (0 6))) "emacs bindings to the ycmd completion server" tar ((:commit . "6f4f7384b82203cccf208e3ec09252eb079439f9") (:url . "https://github.com/abingham/emacs-ycmd"))]) diff --git a/code/elpa/async-20230322.521/async-autoloads.el b/code/elpa/async-20230323.643/async-autoloads.el similarity index 100% rename from code/elpa/async-20230322.521/async-autoloads.el rename to code/elpa/async-20230323.643/async-autoloads.el diff --git a/code/elpa/async-20230322.521/async-bytecomp.el b/code/elpa/async-20230323.643/async-bytecomp.el similarity index 100% rename from code/elpa/async-20230322.521/async-bytecomp.el rename to code/elpa/async-20230323.643/async-bytecomp.el diff --git a/code/elpa/async-20230322.521/async-pkg.el b/code/elpa/async-20230323.643/async-pkg.el similarity index 67% rename from code/elpa/async-20230322.521/async-pkg.el rename to code/elpa/async-20230323.643/async-pkg.el index e540411..38bfbde 100644 --- a/code/elpa/async-20230322.521/async-pkg.el +++ b/code/elpa/async-20230323.643/async-pkg.el @@ -1,6 +1,6 @@ -(define-package "async" "20230322.521" "Asynchronous processing in Emacs" +(define-package "async" "20230323.643" "Asynchronous processing in Emacs" '((emacs "24.4")) - :commit "3f91ce8b963cd6909c6578f87b5545fd761f1547" :authors + :commit "34feabe1142863a2c96f75afda1a2ae4aa0813f6" :authors '(("John Wiegley" . "jwiegley@gmail.com")) :maintainer '("Thierry Volpiatto" . "thievol@posteo.net") diff --git a/code/elpa/async-20230322.521/async.el b/code/elpa/async-20230323.643/async.el similarity index 99% rename from code/elpa/async-20230322.521/async.el rename to code/elpa/async-20230323.643/async.el index aa0ccab..e181773 100644 --- a/code/elpa/async-20230322.521/async.el +++ b/code/elpa/async-20230323.643/async.el @@ -411,7 +411,7 @@ working directory." (set-process-sentinel (get-buffer-process buf-err) (lambda (proc _change) - (unless (or async-debug (buffer-live-p proc)) + (unless (or async-debug (process-live-p proc)) (kill-buffer (process-buffer proc))))) (with-current-buffer buf (set (make-local-variable 'async-callback) finish-func) diff --git a/code/elpa/async-20230322.521/dired-async.el b/code/elpa/async-20230323.643/dired-async.el similarity index 100% rename from code/elpa/async-20230322.521/dired-async.el rename to code/elpa/async-20230323.643/dired-async.el diff --git a/code/elpa/async-20230322.521/smtpmail-async.el b/code/elpa/async-20230323.643/smtpmail-async.el similarity index 100% rename from code/elpa/async-20230322.521/smtpmail-async.el rename to code/elpa/async-20230323.643/smtpmail-async.el diff --git a/code/elpa/burly-20221024.2019/burly-autoloads.el b/code/elpa/burly-20221024.2019/burly-autoloads.el new file mode 100644 index 0000000..111a532 --- /dev/null +++ b/code/elpa/burly-20221024.2019/burly-autoloads.el @@ -0,0 +1,105 @@ +;;; burly-autoloads.el --- automatically extracted autoloads -*- lexical-binding: t -*- +;; +;;; Code: + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + + +;;;### (autoloads nil "burly" "burly.el" (0 0 0 0)) +;;; Generated autoloads from burly.el + +(autoload 'burly-open-last-bookmark "burly" "\ +Open the last-opened Burly bookmark. +Helpful for, e.g. quickly restoring an overview while working on +a project." t nil) + +(autoload 'burly-kill-buffer-url "burly" "\ +Copy BUFFER's URL to the kill ring. + +\(fn BUFFER)" t nil) + +(autoload 'burly-kill-frames-url "burly" "\ +Copy current frameset's URL to the kill ring." t nil) + +(autoload 'burly-kill-windows-url "burly" "\ +Copy current frame's window configuration URL to the kill ring." t nil) + +(autoload 'burly-open-url "burly" "\ +Open Burly URL. + +\(fn URL)" t nil) + +(autoload 'burly-bookmark-frames "burly" "\ +Bookmark the current frames as NAME. + +\(fn NAME)" t nil) + +(autoload 'burly-bookmark-windows "burly" "\ +Bookmark the current frame's window configuration as NAME. + +\(fn NAME)" t nil) + +(autoload 'burly-open-bookmark "burly" "\ +Restore a window configuration to the current frame from a Burly BOOKMARK. + +\(fn BOOKMARK)" t nil) + +(autoload 'burly-bookmark-handler "burly" "\ +Handler function for Burly BOOKMARK. + +\(fn BOOKMARK)" nil nil) + +(register-definition-prefixes "burly" '("burly-")) + +;;;*** + +;;;### (autoloads nil "burly-tabs" "burly-tabs.el" (0 0 0 0)) +;;; Generated autoloads from burly-tabs.el + +(defvar burly-tabs-mode nil "\ +Non-nil if Burly-Tabs mode is enabled. +See the `burly-tabs-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `burly-tabs-mode'.") + +(custom-autoload 'burly-tabs-mode "burly-tabs" nil) + +(autoload 'burly-tabs-mode "burly-tabs" "\ +Integrate Burly with `tab-bar-mode'. +When active, Burly bookmarks are opened in new tabs and named +accordingly. + +This is a minor mode. If called interactively, toggle the +`Burly-Tabs mode' mode. If the prefix argument is positive, +enable the mode, and if it is zero or negative, disable the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `(default-value \\='burly-tabs-mode)'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +\(fn &optional ARG)" t nil) + +(register-definition-prefixes "burly-tabs" '("burly-")) + +;;;*** + +;;;### (autoloads nil nil ("burly-pkg.el") (0 0 0 0)) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; coding: utf-8 +;; End: +;;; burly-autoloads.el ends here diff --git a/code/elpa/burly-20221024.2019/burly-pkg.el b/code/elpa/burly-20221024.2019/burly-pkg.el new file mode 100644 index 0000000..d468d34 --- /dev/null +++ b/code/elpa/burly-20221024.2019/burly-pkg.el @@ -0,0 +1,13 @@ +(define-package "burly" "20221024.2019" "Save and restore frame/window configurations with buffers" + '((emacs "27.1") + (map "2.1")) + :commit "f570fa87ee72a451f535cfb038d81798a01a7e20" :authors + '(("Adam Porter" . "adam@alphapapa.net")) + :maintainer + '("Adam Porter" . "adam@alphapapa.net") + :keywords + '("convenience") + :url "https://github.com/alphapapa/burly.el") +;; Local Variables: +;; no-byte-compile: t +;; End: diff --git a/code/elpa/burly-20221024.2019/burly-tabs.el b/code/elpa/burly-20221024.2019/burly-tabs.el new file mode 100644 index 0000000..65ca18d --- /dev/null +++ b/code/elpa/burly-20221024.2019/burly-tabs.el @@ -0,0 +1,90 @@ +;;; burly-tabs.el --- Burly's support for tab-bar -*- lexical-binding: t; -*- + +;; Copyright (C) 2022 Adam Porter + +;; Author: Adam Porter +;; Keywords: tab-bar, tabs, frames + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; This library provides support for `tab-bar-mode'. + +;;; Code: + +;; TODO: In Emacs 28, add an entry to the tab context menu. See +;; . + +;;;; Requirements + +(require 'cl-lib) +(require 'map) +(require 'tab-bar) + +(require 'burly) + +;;;; Commands + +;;;###autoload +(define-minor-mode burly-tabs-mode + "Integrate Burly with `tab-bar-mode'. +When active, Burly bookmarks are opened in new tabs and named +accordingly." + :global t + :group 'burly + (unless (version<= "28.1" emacs-version) + (user-error "`burly-tabs-mode' requires Emacs 28.1 or later")) + (if burly-tabs-mode + (progn + (advice-add #'burly--windows-set :before #'burly-tabs--windows-set-before-advice) + (advice-add #'burly--windows-set :after #'burly-tabs--windows-set-after-advice)) + ;; Disable mode. + (advice-remove #'burly--windows-set #'burly-tabs--windows-set-before-advice) + (advice-remove #'burly--windows-set #'burly-tabs--windows-set-after-advice))) + +(cl-defun burly-tabs-reset-tab (&optional (tab (tab-bar--current-tab-find))) + "Reset TAB to its saved configuration. +Resets TAB to the Burly bookmark that it was created from." + (interactive) + (pcase-let* ((`(,_ . ,(map burly-bookmark-name)) tab)) + (unless burly-bookmark-name + (user-error "Tab has no associated Burly bookmark (`burly-tabs-mode' must be enabled when opening a bookmark)")) + (burly-open-bookmark burly-bookmark-name))) + +(defalias 'burly-reset-tab #'burly-tabs-reset-tab) + +;;;; Functions + +(defun burly-tabs--windows-set-before-advice (&rest _ignore) + "Cause bookmark to be opened in a tab by that name. +If a tab already exists named the value of +`burly-opened-bookmark-name', select it; otherwise call +`tab-bar-new-tab'. To be used as advice to +`burly-open-bookmark'." + (if (tab-bar--tab-index-by-name burly-opened-bookmark-name) + (tab-bar-select-tab-by-name burly-opened-bookmark-name) + (tab-bar-new-tab))) + +(defun burly-tabs--windows-set-after-advice (&rest _ignore) + "Set current tab's `burly-bookmark-name' to BOOKMARK-NAME. +To be used as advice to `burly--windows-set'." + (tab-rename burly-opened-bookmark-name) + (let ((current-tab (tab-bar--current-tab-find))) + (setf (alist-get 'burly-bookmark-name (cdr current-tab)) + burly-opened-bookmark-name))) + +(provide 'burly-tabs) + +;;; burly-tabs.el ends here diff --git a/code/elpa/burly-20221024.2019/burly.el b/code/elpa/burly-20221024.2019/burly.el new file mode 100644 index 0000000..2f57b06 --- /dev/null +++ b/code/elpa/burly-20221024.2019/burly.el @@ -0,0 +1,590 @@ +;;; burly.el --- Save and restore frame/window configurations with buffers -*- lexical-binding: t; -*- + +;; Copyright (C) 2020 Adam Porter + +;; Author: Adam Porter +;; URL: https://github.com/alphapapa/burly.el +;; Version: 0.3-pre +;; Package-Requires: ((emacs "27.1") (map "2.1")) +;; Keywords: convenience + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; This package provides tools to save and restore frame and window +;; configurations in Emacs, including buffers that may not be live +;; anymore. In this way, it's like a lightweight "workspace" manager, +;; allowing you to easily restore one or more frames, including their +;; windows, the windows' layout, and their buffers. + +;; Internally it uses Emacs's bookmarks system to restore buffers to +;; their previous contents and location. This provides power and +;; extensibility, since many major modes already integrate with +;; Emacs's bookmarks system. However, in case a mode's bookmarking +;; function isn't satisfactory, Burly allows the user to customize +;; buffer-restoring functions for specific modes. + +;; For Org mode, Burly provides such custom functions so that narrowed +;; and indirect Org buffers are properly restored, and headings are +;; located by outline path in case they've moved since a bookmark was +;; made (the org-bookmark-heading package also provides this through +;; the Emacs bookmark system, but users may not have it installed, and +;; the functionality is too useful to not include here by default). + +;; Internally, buffers and window configurations are also encoded as +;; URLs, and users may also save and open those URLs instead of using +;; Emacs bookmarks. (The name "Burly" comes from "buffer URL.") + +;;; Code: + +;;;; Requirements + +(require 'bookmark) +(require 'cl-lib) +(require 'map) +(require 'subr-x) +(require 'thingatpt) +(require 'url-parse) +(require 'url-util) + +;;;; Variables + +(defvar burly--window-state nil + "Used to work around `bookmark--jump-via' affecting window configuration.") + +(defvar burly-opened-bookmark-name nil + "The name of the last bookmark opened by Burly.") + +;;;; Customization + +(defgroup burly nil + "Save and restore window configurations and their buffers." + :group 'convenience + :link '(url-link "https://github.com/alphapapa/burly.el") + :link '(custom-manual "(Burly)Usage")) + +(defcustom burly-bookmark-prefix "Burly: " + "Prefix string for the name of new Burly bookmarks." + :type 'string) + +(defcustom burly-major-mode-alist + (list (cons 'org-mode + (list (cons 'make-url-fn #'burly--org-mode-buffer-url) + (cons 'follow-url-fn #'burly-follow-url-org-mode)))) + "Alist mapping major modes to the appropriate Burly functions." + :type '(alist :key-type symbol + :value-type (set (cons (const make-url-fn) (function :tag "Make-URL function")) + (cons (const follow-url-fn) (function :tag "Follow-URL function"))))) + +(defcustom burly-frameset-filter-alist '((name . nil)) + "Alist of frame parameters and filtering functions. +See variable `frameset-filter-alist'." + :type '(alist :key-type (symbol :tag "Frame parameter") + :value-type (choice (const :tag "Always copied" nil) + (const :tag "Never copied" :never) + (function :tag "Filter function")))) + +(defcustom burly-window-persistent-parameters + (list (cons 'burly-url 'writable) + (cons 'header-line-format 'writable) + (cons 'mode-line-format 'writable) + (cons 'tab-line-format 'writable) + (cons 'no-other-window 'writable) + (cons 'no-delete-other-windows 'writable) + (cons 'window-preserved-size 'writable) + (cons 'window-side 'writable) + (cons 'window-slot 'writable)) + "Additional window parameters to persist. +See Info node `(elisp)Window Parameters'. See also option +`burly-set-window-persistent-parameters'." + :type '(alist :key-type (symbol :tag "Window parameter") + :value-type (choice (const :tag "Not saved" nil) + (const :tag "Saved" writable)))) + +(defcustom burly-set-window-persistent-parameters t + "Sync `window-persistent-parameters' with `burly' option. +When this option is non-nil, `window-persistent-parameters' is +set to the value of `burly-window-persistent-parameters' when +Burly restores a window configuration. + +By default, `window-persistent-parameters' does not save many of +the parameters that are in the default value of +`burly-window-persistent-parameters', which causes, e.g. a +built-in command like `window-toggle-side-windows' to not persist +such parameters when side windows are toggled (which could, +e.g. cause a window's `mode-line-format' to not persist). So +enabling this option solves that. + +Note: When this option is non-nil, +`burly-window-persistent-parameters' should be set heeding the +warning in the manual about not using the `writable' value for +parameters whose values do not have a read syntax." + :type 'boolean) + +;;;; Commands + +;;;###autoload +(defun burly-open-last-bookmark () + "Open the last-opened Burly bookmark. +Helpful for, e.g. quickly restoring an overview while working on +a project." + (interactive) + (unless burly-opened-bookmark-name + (user-error "Use command `burly-open-bookmark' first")) + (burly-open-bookmark burly-opened-bookmark-name)) + +;;;###autoload +(defun burly-kill-buffer-url (buffer) + "Copy BUFFER's URL to the kill ring." + (interactive "bBuffer: ") + (let ((url (burly-buffer-url (get-buffer buffer)))) + (kill-new url) + (message "%s" url))) + +;;;###autoload +(defun burly-kill-frames-url () + "Copy current frameset's URL to the kill ring." + (interactive) + (let ((url (burly-frames-url))) + (kill-new url) + (message "%s" url))) + +;;;###autoload +(defun burly-kill-windows-url () + "Copy current frame's window configuration URL to the kill ring." + (interactive) + (let ((url (burly-windows-url))) + (kill-new url) + (message "%s" url))) + +;;;###autoload +(defun burly-open-url (url) + "Open Burly URL." + ;; FIXME: If point is on an "emacs+burly..." URL, but it's after the "emacs+burly" + ;; part, `thing-at-point-url-at-point' doesn't pick up the whole URL. + (interactive (list (or (thing-at-point-url-at-point t) + (read-string "URL: ")))) + (cl-assert (string-prefix-p "emacs+burly+" url) t "burly-open-url: URL not an emacs+burly one:") + (pcase-let* ((urlobj (url-generic-parse-url url)) + ((cl-struct url type) urlobj) + (subtype (car (last (split-string type "+" 'omit-nulls))))) + (pcase-exhaustive subtype + ((or "bookmark" "file" "name") (pop-to-buffer (burly-url-buffer url))) + ("frames" (burly--frameset-restore urlobj)) + ("windows" (burly--windows-set urlobj))))) + +;;;###autoload +(defun burly-bookmark-frames (name) + "Bookmark the current frames as NAME." + (interactive + (list (completing-read "Save Burly bookmark: " (burly-bookmark-names) + nil nil burly-bookmark-prefix))) + (let ((record (list (cons 'url (burly-frames-url)) + (cons 'handler #'burly-bookmark-handler)))) + (bookmark-store name record nil))) + +;;;###autoload +(defun burly-bookmark-windows (name) + "Bookmark the current frame's window configuration as NAME." + (interactive + (list (completing-read "Save Burly bookmark: " (burly-bookmark-names) + nil nil burly-bookmark-prefix))) + (let ((record (list (cons 'url (burly-windows-url)) + (cons 'handler #'burly-bookmark-handler)))) + (bookmark-store name record nil))) + +;;;###autoload +(defun burly-open-bookmark (bookmark) + "Restore a window configuration to the current frame from a Burly BOOKMARK." + (interactive + (list (completing-read "Open Burly bookmark: " (burly-bookmark-names) + nil nil burly-bookmark-prefix))) + (cl-assert (and bookmark (not (string-empty-p bookmark))) nil + "(burly-open-bookmark): Invalid Burly bookmark: '%s'" bookmark) + (bookmark-jump bookmark)) + +;;;; Functions + +;;;;; Buffers + +(defun burly-url-buffer (url) + "Return buffer for URL." + (cl-assert (string-prefix-p "emacs+burly+" url) t "burly-url-buffer: URL not an emacs+burly one: %s" url) + (pcase-let* ((urlobj (url-generic-parse-url url)) + ((cl-struct url type) urlobj) + (subtype (car (last (split-string type "+" 'omit-nulls))))) + (pcase-exhaustive subtype + ("bookmark" (burly--bookmark-url-buffer urlobj)) + ("file" (burly--file-url-buffer urlobj)) + ("name" (let ((buffer-name (decode-coding-string (cdr (url-path-and-query urlobj)) + 'utf-8-unix))) + (or (get-buffer buffer-name) + (with-current-buffer (get-buffer-create (concat "*Burly (error): " buffer-name "*")) + (insert "Burly was unable to get a buffer named: " buffer-name "\n" + "URL: " url "\n" + "Please report this error to the developer\n\n") + (current-buffer)))))))) + +(defun burly-buffer-url (buffer) + "Return URL for BUFFER." + (let* ((major-mode (buffer-local-value 'major-mode buffer)) + (make-url-fn (map-nested-elt burly-major-mode-alist (list major-mode 'make-url-fn)))) + (cond (make-url-fn (funcall make-url-fn buffer)) + (t (or (with-current-buffer buffer + (when-let* ((record (ignore-errors + (bookmark-make-record)))) + (cl-labels ((encode (element) + (cl-typecase element + (string (encode-coding-string element 'utf-8-unix)) + (proper-list (mapcar #'encode element)) + (cons (cons (encode (car element)) + (encode (cdr element)))) + (t element)))) + ;; Encode all strings in record with UTF-8. + ;; NOTE: If we stop using URLs in the future, maybe this won't be needed. + (setf record (encode record))) + (burly--bookmark-record-url record))) + ;; Buffer can't seem to be bookmarked, so record it as + ;; a name-only buffer. For some reason, it works + ;; better to use the buffer name in the query string + ;; rather than the filename/path part. + (url-recreate-url (url-parse-make-urlobj "emacs+burly+name" nil nil nil nil + (concat "?" (encode-coding-string (buffer-name buffer) + 'utf-8-unix)) + nil nil 'fullness))))))) + +;;;;; Files + +(defun burly--file-url-buffer (urlobj) + "Return buffer for \"emacs+burly+file:\" URLOBJ." + (pcase-let* ((`(,path . ,query-string) (url-path-and-query urlobj)) + (query (url-parse-query-string query-string)) + (buffer (find-file-noselect path)) + (major-mode (buffer-local-value 'major-mode buffer)) + (follow-fn (map-nested-elt burly-major-mode-alist (list major-mode 'follow-url-fn)))) + (cl-assert follow-fn nil "Major mode not in `burly-major-mode-alist': %s" major-mode) + (funcall follow-fn :buffer buffer :query query))) + +;;;;; Frames + +;; Looks like frameset.el should make this pretty easy. + +(require 'frameset) + +(cl-defun burly-frames-url (&optional (frames (frame-list))) + "Return URL for frameset of FRAMES. +FRAMES defaults to all live frames." + (dolist (frame frames) + ;; Set URL window parameter for each window before saving state. + (burly--windows-set-url (window-list frame 'never))) + (let* ((window-persistent-parameters (append burly-window-persistent-parameters + window-persistent-parameters)) + (frameset-filter-alist (append burly-frameset-filter-alist frameset-filter-alist)) + (query (frameset-save frames)) + (print-length nil) ; Important! + (filename (concat "?" (url-hexify-string (prin1-to-string query)))) + (url (url-recreate-url (url-parse-make-urlobj "emacs+burly+frames" nil nil nil nil + filename)))) + (dolist (frame frames) + ;; Clear window parameters. + (burly--windows-set-url (window-list frame 'never) 'nullify)) + url)) + +(defun burly--frameset-restore (urlobj) + "Restore FRAMESET according to URLOBJ." + (setf window-persistent-parameters (copy-sequence burly-window-persistent-parameters)) + (pcase-let* ((`(,_ . ,query-string) (url-path-and-query urlobj)) + (frameset (read (url-unhex-string query-string))) + (frameset-filter-alist (append burly-frameset-filter-alist frameset-filter-alist))) + ;; Restore buffers. (Apparently `cl-loop''s in-ref doesn't work with + ;; its destructuring, so we can't just `setf' on `window-state'.) + (setf (frameset-states frameset) + (cl-loop for (frame-parameters . window-state) in (frameset-states frameset) + collect (cons frame-parameters (burly--bufferize-window-state window-state)))) + (condition-case err + (frameset-restore frameset) + (error (delay-warning 'burly (format "Error while restoring frameset: ERROR:%S FRAMESET:%S" err frameset)))))) + +;;;;; Windows + +(cl-defun burly-windows-url (&optional (frame (selected-frame))) + "Return URL for window configuration on FRAME." + (with-selected-frame frame + (let* ((query (burly--window-state frame)) + (print-length nil) ; Important! + (filename (concat "?" (url-hexify-string (prin1-to-string query))))) + (url-recreate-url (url-parse-make-urlobj "emacs+burly+windows" nil nil nil nil + filename))))) + +(cl-defun burly--window-state (&optional (frame (selected-frame))) + "Return window state for FRAME. +Sets `burly-url' window parameter in each window before +serializing." + (with-selected-frame frame + ;; Set URL window parameter for each window before saving state. + (burly--windows-set-url (window-list nil 'never)) + (let* ((window-persistent-parameters (append burly-window-persistent-parameters + window-persistent-parameters)) + (window-state (window-state-get nil 'writable))) + ;; Clear window parameters we set (because they aren't kept + ;; current, so leaving them could be confusing). + (burly--windows-set-url (window-list nil 'never) 'nullify) + window-state))) + +(defun burly--windows-set-url (windows &optional nullify) + "Set `burly-url' window parameter in WINDOWS. +If NULLIFY, set the parameter to nil." + (dolist (window windows) + (let ((value (if nullify nil (burly-buffer-url (window-buffer window))))) + (set-window-parameter window 'burly-url value)))) + +(defun burly--windows-set (urlobj) + "Set window configuration according to URLOBJ." + (setf window-persistent-parameters (copy-sequence burly-window-persistent-parameters)) + (pcase-let* ((window-persistent-parameters (append burly-window-persistent-parameters + window-persistent-parameters)) + (`(,_ . ,query-string) (url-path-and-query urlobj)) + ;; FIXME: Remove this condition-case eventually, after giving users time to update their bookmarks. + (state (condition-case nil + (read (url-unhex-string query-string)) + (invalid-read-syntax (display-warning 'burly "Please recreate that Burly bookmark (storage format changed)") + (read query-string)))) + (state (burly--bufferize-window-state state))) + (window-state-put state (frame-root-window)) + ;; HACK: Since `bookmark--jump-via' insists on calling a + ;; buffer-display function after handling the bookmark, we add a + ;; function to `bookmark-after-jump-hook' to restore the window + ;; configuration that we just set. + (setf burly--window-state (window-state-get (frame-root-window) 'writable)) + (push #'burly--bookmark-window-state-hack bookmark-after-jump-hook))) + +(defun burly--bufferize-window-state (state) + "Return window state STATE with its buffers reincarnated." + (cl-labels ((bufferize-state + ;; Set windows' buffers in STATE. + (state) (pcase state + (`(leaf . ,_attrs) (bufferize-leaf state)) + ((pred atom) state) + (`(,_key . ,(pred atom)) state) + ((pred list) (mapcar #'bufferize-state state)))) + (bufferize-leaf + (leaf) (pcase-let* ((`(leaf . ,attrs) leaf) + ((map parameters buffer) attrs) + ((map burly-url) parameters) + (`(,_buffer-name . ,buffer-attrs) buffer) + (new-buffer (burly-url-buffer burly-url))) + (setf (map-elt attrs 'buffer) (cons new-buffer buffer-attrs)) + (cons 'leaf attrs)))) + (if-let ((leaf-pos (cl-position 'leaf state))) + ;; A one-window frame: the elements following `leaf' are that window's params. + (append (cl-subseq state 0 leaf-pos) + (bufferize-leaf (cl-subseq state leaf-pos))) + ;; Multi-window frame. + (bufferize-state state)))) + +;;;;; Bookmarks + +(defun burly--bookmark-window-state-hack (&optional _) + "Put window state from `burly--window-state'. +This function is to be called in `bookmark-after-jump-hook' to +work around `bookmark--jump-via's calling a buffer-display +function which changes the window configuration after +`burly--windows-set' has set it. This function removes itself +from the hook." + (unwind-protect + (progn + (cl-assert burly--window-state) + (window-state-put burly--window-state (frame-root-window))) + (setf bookmark-after-jump-hook (delete #'burly--bookmark-window-state-hack bookmark-after-jump-hook) + burly--window-state nil))) + +;;;###autoload +(defun burly-bookmark-handler (bookmark) + "Handler function for Burly BOOKMARK." + (let ((previous-name burly-opened-bookmark-name)) + ;; Set opened bookmark name before actually opening it so that the + ;; tabs-mode advice functions can use it beforehand. + (setf burly-opened-bookmark-name (car bookmark)) + (condition-case err + (burly-open-url (alist-get 'url (bookmark-get-bookmark-record bookmark))) + (error (setf burly-opened-bookmark-name previous-name) + (signal (car err) (cdr err)))))) + +(defun burly--bookmark-record-url (record) + "Return a URL for bookmark RECORD." + (cl-assert record) + (pcase-let* ((`(,name . ,props) record) + (print-length nil) ; Important! + (query (cl-loop for prop in props + ;; HACK: Remove unreadable values from props. + do (cl-loop for value in-ref (cdr prop) + when (or (bufferp value)) + do (setf value nil)) + collect (list (car prop) (prin1-to-string (cdr prop))))) + (filename (concat (url-hexify-string name) "?" (url-build-query-string (remove nil query))))) + (url-recreate-url (url-parse-make-urlobj "emacs+burly+bookmark" nil nil nil nil + filename nil nil 'fullness)))) + +(defun burly--bookmark-url-buffer (urlobj) + "Return buffer for bookmark specified by URLOBJ. +URLOBJ should be a URL object as returned by +`url-generic-parse-url'." + (pcase-let* ((`(,path . ,query-string) (url-path-and-query urlobj)) + (query (url-parse-query-string query-string)) + ;; Convert back to alist. + (props (cl-loop for prop in query + for key = (intern (car prop)) + for value = (pcase key + ('handler (intern (cadr prop))) + ('help-args (read (cadr prop))) + ('help-fn (ignore-errors + ;; NOTE: Due to changes in help-mode.el which serialize natively + ;; compiled subrs in the bookmark record, which cannot be read + ;; back (which actually break the entire bookmark system when + ;; such a record is saved in the bookmarks file), we have to + ;; workaround a failure to read here. See bug#56643. + (read (cadr prop)))) + ('position (cl-parse-integer (cadr prop))) + (_ (read (cadr prop)))) + collect (cons key value))) + (record (cons path props))) + (cl-labels ((decode (element) + (cl-typecase element + (string (decode-coding-string element 'utf-8-unix)) + (proper-list (mapcar #'decode element)) + (cons (cons + (decode (car element)) + (decode (cdr element)))) + (t element)))) + ;; Decode all strings in record with UTF-8. + ;; NOTE: If we stop using URLs in the future, maybe this won't be needed. + (setf record (decode record))) + (save-window-excursion + (condition-case err + (bookmark-jump record) + (error (delay-warning 'burly (format "Error while opening bookmark: ERROR:%S RECORD:%S" err record)))) + (current-buffer)))) + +(defun burly-bookmark-names () + "Return list of all Burly bookmark names." + (cl-loop for bookmark in bookmark-alist + for (_name . params) = bookmark + when (equal #'burly-bookmark-handler (alist-get 'handler params)) + collect (car bookmark))) + +;;;;; Org buffers + +;; We only require Org when compiling the file. At runtime, Org will +;; be loaded before we call any of its functions, because we load the +;; Org file into a buffer first, which activates `org-mode'. + +(eval-when-compile + (require 'org)) + +(declare-function org-before-first-heading-p "org") +(declare-function org-back-to-heading "org") +(declare-function org-find-olp "org") +(declare-function org-tree-to-indirect-buffer "org") +(declare-function org-narrow-to-subtree "org") +(declare-function org-heading-components "org") +(declare-function org-up-heading-safe "org") + +(defun burly--org-mode-buffer-url (buffer) + "Return URL for Org BUFFER." + (with-current-buffer buffer + (cl-assert (or (buffer-file-name buffer) + (buffer-file-name (buffer-base-buffer buffer))) + nil "Buffer has no file name: %s" buffer) + (let* ((narrowed (buffer-narrowed-p)) + (indirect (buffer-base-buffer buffer)) + (top-olp + ;; For narrowing purposes, start with the heading at the top of the buffer. + (when (buffer-narrowed-p) + (save-excursion + (goto-char (point-min)) + ;; `org-get-outline-path' replaces links in headings with their + ;; descriptions, which prevents using them in regexp searches. + (when (org-heading-components) + (org-with-wide-buffer + (nreverse (cl-loop collect (substring-no-properties (nth 4 (org-heading-components))) + while (org-up-heading-safe)))))))) + (point-olp + (when (ignore-errors (org-heading-components)) + (org-with-wide-buffer + (nreverse (cl-loop collect (substring-no-properties (nth 4 (org-heading-components))) + while (org-up-heading-safe)))))) + (pos (point)) + (relative-pos (when top-olp + (- (point) (save-excursion + (org-back-to-heading) + (point))))) + (print-length nil) ; Important! + (query (list (list "pos" pos) + (when top-olp + (list "top-olp" (prin1-to-string top-olp))) + (when point-olp + (list "point-olp" (prin1-to-string point-olp))) + (when relative-pos + (list "relative-pos" relative-pos)) + (when indirect + (list "indirect" "t")) + (when narrowed + (list "narrowed" "t")))) + (buffer-file (or (buffer-file-name buffer) + (buffer-file-name (buffer-base-buffer buffer)))) + (filename (concat buffer-file "?" (url-build-query-string (remove nil query))))) + (url-recreate-url (url-parse-make-urlobj "emacs+burly+file" nil nil nil nil + filename nil nil 'fullness))))) + +(cl-defun burly-follow-url-org-mode (&key buffer query) + "In BUFFER, jump to heading and position from QUERY, and return a buffer. +If QUERY specifies that the buffer should be indirect, a new, +indirect buffer is returned. Otherwise BUFFER is returned." + ;; `pcase's map support uses `alist-get', which does not work with string keys + ;; unless its TESTFN arg is bound to, e.g. `equal', but `map-elt' has deprecated + ;; its TESTFN arg, and there's no way to pass it or bind it when using `pcase' + ;; anyway. So we rebind `alist-get' to a function that uses `assoc-string'. + (with-current-buffer buffer + (cl-letf (((symbol-function 'alist-get) + (lambda (key alist &optional _default _remove _testfn) + ;; Only the first value in the list of values is returned, so multiple + ;; values are not supported. I don't expect this to be a problem... + (cadr (assoc-string key alist))))) + (pcase-let* (((map ("pos" pos) + ("indirect" indirect) + ("narrowed" narrowed) + ("top-olp" top-olp) + ("point-olp" point-olp) + ("relative-pos" relative-pos)) + query) + (heading-pos (when top-olp + (org-find-olp (read top-olp) 'this-buffer)))) + (widen) + (if heading-pos + (goto-char heading-pos) + (goto-char (string-to-number pos))) + (cond (indirect (org-tree-to-indirect-buffer)) + (narrowed (progn + (org-narrow-to-subtree) + (goto-char (org-find-olp (read point-olp) 'this-buffer))))) + (when (and heading-pos relative-pos) + (forward-char (string-to-number relative-pos))) + (current-buffer))))) + +;;;; Footer + +(provide 'burly) + +;;; burly.el ends here diff --git a/code/elpa/burly-20221024.2019/burly.info b/code/elpa/burly-20221024.2019/burly.info new file mode 100644 index 0000000..7480a53 --- /dev/null +++ b/code/elpa/burly-20221024.2019/burly.info @@ -0,0 +1,325 @@ +This is README.info, produced by makeinfo version 5.2 from README.texi. + +INFO-DIR-SECTION Emacs +START-INFO-DIR-ENTRY +* Burly: (burly). Save and restore window configurations and their buffers. +END-INFO-DIR-ENTRY + + +File: README.info, Node: Top, Next: Installation, Up: (dir) + +Burly.el +******** + +This package provides tools to save and restore frame and window +configurations in Emacs, including buffers that may not be live anymore. +In this way, it’s like a lightweight "workspace" manager, allowing you +to easily restore one or more frames, including their windows, the +windows’ layout, and their buffers. + + Internally it uses Emacs’s bookmarks system to restore buffers to +their previous contents and location. This provides power and +extensibility, since many major modes already integrate with Emacs’s +bookmarks system. However, in case a mode’s bookmarking function isn’t +satisfactory, Burly allows the user to customize buffer-restoring +functions for specific modes. + + For Org mode, Burly provides such custom functions so that narrowed +and indirect Org buffers are properly restored, and headings are located +by outline path in case they’ve moved since a bookmark was made (the +org-bookmark-heading (https://github.com/alphapapa/org-bookmark-heading) +package also provides this through the Emacs bookmark system, but users +may not have it installed, and the functionality is too useful to not +include here by default). + + Internally, buffers and frame/window configurations are also encoded +as URLs, and users may also save and open those URLs instead of using +Emacs bookmarks. (The name "Burly" comes from "buffer URL.") For +example, a URL to the ‘Installation/Quelpa’ heading in this file, as I’m +writing it, looks like this: + + emacs+burly+file:///home/me/src/emacs/burly.el/README.org?pos=2651&outline-path=%28%22Installation%22%20%22Quelpa%22%29&relative-pos=308 + + In terms of built-in features, Burly may be seen as integrating or +leveraging the built-in libraries ‘bookmark.el’, ‘window.el’, and +‘frameset.el’. + +* Menu: + +* Installation:: +* Usage:: +* Changelog:: +* Development:: +* Credits:: +* License:: + +— The Detailed Node Listing — + +Installation + +* MELPA:: +* Quelpa:: +* Manual:: + +Usage + +* Bookmark commands:: +* URL commands:: +* Tab bar:: +* Tips:: + +Changelog + +* 0.3-pre: 03-pre. +* 0.2: 02. +* 0.1: 01. + + + +File: README.info, Node: Installation, Next: Usage, Prev: Top, Up: Top + +1 Installation +************** + +* Menu: + +* MELPA:: +* Quelpa:: +* Manual:: + + +File: README.info, Node: MELPA, Next: Quelpa, Up: Installation + +1.1 MELPA +========= + +If you installed from MELPA, you’re done. Just run one of the commands +below. + + +File: README.info, Node: Quelpa, Next: Manual, Prev: MELPA, Up: Installation + +1.2 Quelpa +========== + +The easiest way is to install with quelpa-use-package +(https://github.com/quelpa/quelpa-use-package), like this: + + (use-package burly + :quelpa (burly :fetcher github :repo "alphapapa/burly.el")) + + +File: README.info, Node: Manual, Prev: Quelpa, Up: Installation + +1.3 Manual +========== + + 1. Install version 2.1 or later of the ‘map’ library from GNU ELPA. + 2. Copy ‘burly.el’ into a directory in your ‘load-path’, then + ‘(require 'burly)’. + + +File: README.info, Node: Usage, Next: Changelog, Prev: Installation, Up: Top + +2 Usage +******* + +* Menu: + +* Bookmark commands:: +* URL commands:: +* Tab bar:: +* Tips:: + + +File: README.info, Node: Bookmark commands, Next: URL commands, Up: Usage + +2.1 Bookmark commands +===================== + +Most users will probably use Burly by bookmarking frame and window +configurations and accessing them with these commands: + + • ‘burly-bookmark-frames’: Bookmark the current frames and their + window configurations. + • ‘burly-bookmark-windows’: Bookmark the current frame’s window + configuration. + • ‘burly-open-bookmark’: Select and open a Burly bookmark. + • ‘burly-open-last-bookmark’: Open the last-opened Burly bookmark. + Helpful for, e.g. quickly restoring an overview while working on a + project. + + Note that bookmarks created by Burly are regular Emacs bookmarks, so +they can be managed by Emacs’s built-in bookmark commands, e.g. +‘list-bookmarks’, ‘bookmark-delete’, etc. + + +File: README.info, Node: URL commands, Next: Tab bar, Prev: Bookmark commands, Up: Usage + +2.2 URL commands +================ + +These commands work on URL strings. While most users probably won’t use +these, they may be useful for building custom tooling. + + • ‘burly-open-url’: Open a Burly URL (at point, or prompt for one), + displaying the buffer(s) in the current window or frame. + • ‘burly-kill-buffer-url’: Copy BUFFER’s URL to the kill ring. + • ‘burly-kill-frames-url’: Copy the current frameset’s URL to the + kill ring. + • ‘burly-kill-windows-url’: Copy the current frame’s window + configuration URL to the kill ring. + + +File: README.info, Node: Tab bar, Next: Tips, Prev: URL commands, Up: Usage + +2.3 Tab bar +=========== + +Burly supports Emacs’s ‘tab-bar-mode’ with ‘burly-tabs-mode’. When +active, Burly bookmarks are opened in new tabs, and the tabs are named +according to the bookmarks. Reopening a Burly bookmark uses the +designated tab, if it already exists, and tabs may be reset to their +bookmarked state with the command ‘burly-reset-tab’ (which you might +bind to ‘C-x t R’). + + +File: README.info, Node: Tips, Prev: Tab bar, Up: Usage + +2.4 Tips +======== + + • You can customize settings in the ‘burly’ group. + • An Info manual is included with this package. + + +File: README.info, Node: Changelog, Next: Development, Prev: Usage, Up: Top + +3 Changelog +*********** + +* Menu: + +* 0.3-pre: 03-pre. +* 0.2: 02. +* 0.1: 01. + + +File: README.info, Node: 03-pre, Next: 02, Up: Changelog + +3.1 0.3-pre +=========== + +*Added* + • Command ‘burly-tabs-mode’, which integrates Burly with + ‘tab-bar-mode’. When active, Burly bookmarks are opened in new + tabs, and the tabs are named according to the bookmark. + • Command ‘burly-reset-tab’, which resets a tab to the state of the + bookmark which opened it. + + *Changed* + • Emacs version 28.1 or later is required. + + *Fixed* + • Buffers that can’t be restored by name no longer cause an error + which aborts restoration of the rest of the bookmark’s buffers. + • Added workaround for regression in Emacs 28 regarding bookmarks for + ‘help-mode’ buffers. (See Emacs bug 56643 + (https://debbugs.gnu.org/cgi/bugreport.cgi?bug=56643).) + + +File: README.info, Node: 02, Next: 01, Prev: 03-pre, Up: Changelog + +3.2 0.2 +======= + +*Added* + • Bookmark commands use ‘completing-read’ and offer existing Burly + bookmark names, making it easier to update bookmarks. (Thanks to + Erik Sjöstrand (https://github.com/Kungsgeten).) + • Command ‘burly-open-last-bookmark’. + • Option ‘burly-set-window-persistent-parameters’, which synchronizes + ‘window-persistent-parameters’ with + ‘burly-window-persistent-parameters’, ensuring that built-in Emacs + commands like ‘window-toggle-side-windows’ persist parameters that + are persisted with Burly. + + *Changed* + • Option ‘burly-window-persistent-parameters’’s default value + includes more window parameters, like header/mode line, side, slot, + etc, making it easier to restore an overview of a project or + "workspace." + • Emacs version 27.1 or later is required. + + *Fixed* + • Narrow Org buffers to correct heading (at the top of the buffer + rather than at point). + • Buffers whose names have multibyte characters. (Fixes #43 + (https://github.com/alphapapa/burly.el/issues/43). Thanks to Liu + Hui (https://github.com/ilupin) for reporting.) + • Bind ‘print-level’ to nil where ‘prin1-to-string’ is used (in case + the value is non-nil in a user’s config, which would cause + truncated values). + + +File: README.info, Node: 01, Prev: 02, Up: Changelog + +3.3 0.1 +======= + +Initial release. + + +File: README.info, Node: Development, Next: Credits, Prev: Changelog, Up: Top + +4 Development +************* + +Bug reports, feature requests, suggestions — _oh my_! + + +File: README.info, Node: Credits, Next: License, Prev: Development, Up: Top + +5 Credits +********* + + • Thanks to Clemens Radermacher (https://github.com/clemera) and + Robert Weiner (https://github.com/rswgnu) for their suggestions. + • Thanks to Trey Peacock (https://github.com/tpeacock19) for + extensive feedback on pre-release versions. + + +File: README.info, Node: License, Prev: Credits, Up: Top + +6 License +********* + +GPLv3 + + + +Tag Table: +Node: Top219 +Node: Installation2378 +Node: MELPA2529 +Node: Quelpa2701 +Node: Manual3014 +Node: Usage3283 +Node: Bookmark commands3454 +Node: URL commands4320 +Node: Tab bar5001 +Node: Tips5490 +Node: Changelog5685 +Node: 03-pre5847 +Node: 026658 +Node: 018079 +Node: Development8173 +Node: Credits8344 +Node: License8704 + +End Tag Table + + +Local Variables: +coding: utf-8 +End: diff --git a/code/elpa/burly-20221024.2019/dir b/code/elpa/burly-20221024.2019/dir new file mode 100644 index 0000000..73fee8b --- /dev/null +++ b/code/elpa/burly-20221024.2019/dir @@ -0,0 +1,19 @@ +This is the file .../info/dir, which contains the +topmost node of the Info hierarchy, called (dir)Top. +The first time you invoke Info you start off looking at this node. + +File: dir, Node: Top This is the top of the INFO tree + + This (the Directory node) gives a menu of major topics. + Typing "q" exits, "H" lists all Info commands, "d" returns here, + "h" gives a primer for first-timers, + "mEmacs" visits the Emacs manual, etc. + + In Emacs, you can click mouse button 2 on a menu item or cross reference + to select it. + +* Menu: + +Emacs +* Burly: (burly). Save and restore window configurations and + their buffers. diff --git a/code/elpa/dashboard-20230317.413/banners/1.txt b/code/elpa/dashboard-20230331.2304/banners/1.txt similarity index 100% rename from code/elpa/dashboard-20230317.413/banners/1.txt rename to code/elpa/dashboard-20230331.2304/banners/1.txt diff --git a/code/elpa/dashboard-20230317.413/banners/2.txt b/code/elpa/dashboard-20230331.2304/banners/2.txt similarity index 100% rename from code/elpa/dashboard-20230317.413/banners/2.txt rename to code/elpa/dashboard-20230331.2304/banners/2.txt diff --git a/code/elpa/dashboard-20230317.413/banners/3.txt b/code/elpa/dashboard-20230331.2304/banners/3.txt similarity index 100% rename from code/elpa/dashboard-20230317.413/banners/3.txt rename to code/elpa/dashboard-20230331.2304/banners/3.txt diff --git a/code/elpa/dashboard-20230317.413/banners/4.txt b/code/elpa/dashboard-20230331.2304/banners/4.txt similarity index 100% rename from code/elpa/dashboard-20230317.413/banners/4.txt rename to code/elpa/dashboard-20230331.2304/banners/4.txt diff --git a/code/elpa/dashboard-20230317.413/banners/emacs.png b/code/elpa/dashboard-20230331.2304/banners/emacs.png similarity index 100% rename from code/elpa/dashboard-20230317.413/banners/emacs.png rename to code/elpa/dashboard-20230331.2304/banners/emacs.png diff --git a/code/elpa/dashboard-20230317.413/banners/logo.png b/code/elpa/dashboard-20230331.2304/banners/logo.png similarity index 100% rename from code/elpa/dashboard-20230317.413/banners/logo.png rename to code/elpa/dashboard-20230331.2304/banners/logo.png diff --git a/code/elpa/dashboard-20230317.413/dashboard-autoloads.el b/code/elpa/dashboard-20230331.2304/dashboard-autoloads.el similarity index 100% rename from code/elpa/dashboard-20230317.413/dashboard-autoloads.el rename to code/elpa/dashboard-20230331.2304/dashboard-autoloads.el diff --git a/code/elpa/dashboard-20230317.413/dashboard-pkg.el b/code/elpa/dashboard-20230331.2304/dashboard-pkg.el similarity index 67% rename from code/elpa/dashboard-20230317.413/dashboard-pkg.el rename to code/elpa/dashboard-20230331.2304/dashboard-pkg.el index c32492a..e40f2fd 100644 --- a/code/elpa/dashboard-20230317.413/dashboard-pkg.el +++ b/code/elpa/dashboard-20230331.2304/dashboard-pkg.el @@ -1,6 +1,6 @@ -(define-package "dashboard" "20230317.413" "A startup screen extracted from Spacemacs" +(define-package "dashboard" "20230331.2304" "A startup screen extracted from Spacemacs" '((emacs "26.1")) - :commit "b648a45684677aa29cdb00e4d14d02dd9fa9cb68" :authors + :commit "0f970d298931f9de7b511086728af140bf44a642" :authors '(("Rakan Al-Hneiti" . "rakan.alhneiti@gmail.com")) :maintainer '("Jesús Martínez" . "jesusmartinez93@gmail.com") diff --git a/code/elpa/dashboard-20230317.413/dashboard-widgets.el b/code/elpa/dashboard-20230331.2304/dashboard-widgets.el similarity index 99% rename from code/elpa/dashboard-20230317.413/dashboard-widgets.el rename to code/elpa/dashboard-20230331.2304/dashboard-widgets.el index fbb058e..fff700e 100644 --- a/code/elpa/dashboard-20230317.413/dashboard-widgets.el +++ b/code/elpa/dashboard-20230331.2304/dashboard-widgets.el @@ -69,6 +69,7 @@ (defvar org-todo-keywords-1) (defvar all-the-icons-dir-icon-alist) (defvar package-activated-list) +(defvar elpaca-after-init-time) (declare-function string-pixel-width "subr-x.el") ; TODO: remove this after 29.1 (declare-function shr-string-pixel-width "shr.el") ; TODO: remove this after 29.1 @@ -181,6 +182,8 @@ Example: (when (boundp 'straight--profile-cache) (setq package-count (+ (hash-table-count straight--profile-cache) package-count))) (when (fboundp 'elpaca--queued) + (setq time (format "%f seconds" (float-time (time-subtract elpaca-after-init-time + before-init-time)))) (setq package-count (length (elpaca--queued)))) (if (zerop package-count) (format "Emacs started in %s" time) @@ -472,8 +475,8 @@ If MESSAGEBUF is not nil then MSG is also written in message buffer." "Insert a page break line in dashboard buffer." (dashboard-append dashboard-page-separator)) -(defun dashboard-insert-heading (heading &optional shortcut) - "Insert a widget HEADING in dashboard buffer, adding SHORTCUT if provided." +(defun dashboard-insert-heading (heading &optional shortcut icon) + "Insert a widget HEADING in dashboard buffer, adding SHORTCUT, ICON if provided." (when (and (dashboard-display-icons-p) dashboard-set-heading-icons) ;; Try loading `all-the-icons' (unless (or (fboundp 'all-the-icons-octicon) @@ -497,6 +500,7 @@ If MESSAGEBUF is not nil then MSG is also written in message buffer." ((string-equal heading "Projects:") (all-the-icons-octicon (cdr (assoc 'projects dashboard-heading-icons)) :height 1.2 :v-adjust 0.0 :face 'dashboard-heading)) + ((not (null icon)) icon) (t " "))) (insert " ")) diff --git a/code/elpa/dashboard-20230317.413/dashboard.el b/code/elpa/dashboard-20230331.2304/dashboard.el similarity index 100% rename from code/elpa/dashboard-20230317.413/dashboard.el rename to code/elpa/dashboard-20230331.2304/dashboard.el diff --git a/code/elpa/doom-modeline-20230306.250/doom-modeline-autoloads.el b/code/elpa/doom-modeline-20230406.623/doom-modeline-autoloads.el similarity index 100% rename from code/elpa/doom-modeline-20230306.250/doom-modeline-autoloads.el rename to code/elpa/doom-modeline-20230406.623/doom-modeline-autoloads.el diff --git a/code/elpa/doom-modeline-20230306.250/doom-modeline-core.el b/code/elpa/doom-modeline-20230406.623/doom-modeline-core.el similarity index 94% rename from code/elpa/doom-modeline-20230306.250/doom-modeline-core.el rename to code/elpa/doom-modeline-20230406.623/doom-modeline-core.el index 65d9d49..8b7ee0f 100644 --- a/code/elpa/doom-modeline-20230306.250/doom-modeline-core.el +++ b/code/elpa/doom-modeline-20230406.623/doom-modeline-core.el @@ -568,13 +568,18 @@ inactive windows." :group 'faces :link '(url-link :tag "Homepage" "https://github.com/seagle0128/doom-modeline")) +(defface doom-modeline + '((t ())) + "Default face." + :group 'doom-modeline-faces) + (defface doom-modeline-emphasis - '((t (:inherit mode-line-emphasis))) + '((t (:inherit (doom-modeline mode-line-emphasis)))) "Face used for emphasis." :group 'doom-modeline-faces) (defface doom-modeline-highlight - '((t (:inherit mode-line-highlight))) + '((t (:inherit (doom-modeline mode-line-highlight)))) "Face used for highlighting." :group 'doom-modeline-faces) @@ -584,12 +589,12 @@ inactive windows." :group 'doom-modeline-faces) (defface doom-modeline-buffer-file - '((t (:inherit (mode-line-buffer-id bold)))) + '((t (:inherit (doom-modeline mode-line-buffer-id bold)))) "Face used for the filename part of the mode-line buffer path." :group 'doom-modeline-faces) (defface doom-modeline-buffer-modified - '((t (:inherit (warning bold) :background unspecified))) + '((t (:inherit (doom-modeline warning bold) :background unspecified))) "Face used for the \\='unsaved\\=' symbol in the mode-line." :group 'doom-modeline-faces) @@ -599,17 +604,17 @@ inactive windows." :group 'doom-modeline-faces) (defface doom-modeline-buffer-minor-mode - '((t (:inherit font-lock-doc-face :slant normal))) + '((t (:inherit (doom-modeline font-lock-doc-face) :slant normal))) "Face used for the minor-modes segment in the mode-line." :group 'doom-modeline-faces) (defface doom-modeline-project-parent-dir - '((t (:inherit (font-lock-comment-face bold)))) + '((t (:inherit (doom-modeline font-lock-comment-face bold)))) "Face used for the project parent directory of the mode-line buffer path." :group 'doom-modeline-faces) (defface doom-modeline-project-dir - '((t (:inherit (font-lock-string-face bold)))) + '((t (:inherit (doom-modeline font-lock-string-face bold)))) "Face used for the project directory of the mode-line buffer path." :group 'doom-modeline-faces) @@ -625,7 +630,7 @@ This applies to `anzu', `evil-substitute', `iedit' etc." :group 'doom-modeline-faces) (defface doom-modeline-host - '((t (:inherit italic))) + '((t (:inherit (doom-modeline italic)))) "Face for remote hosts in the mode-line." :group 'doom-modeline-faces) @@ -635,27 +640,27 @@ This applies to `anzu', `evil-substitute', `iedit' etc." :group 'doom-modeline-faces) (defface doom-modeline-input-method-alt - '((t (:inherit (font-lock-doc-face bold) :slant normal))) + '((t (:inherit (doom-modeline font-lock-doc-face bold) :slant normal))) "Alternative face for input method in the mode-line." :group 'doom-modeline-faces) (defface doom-modeline-debug - '((t (:inherit (font-lock-doc-face bold) :slant normal))) + '((t (:inherit (doom-modeline font-lock-doc-face bold) :slant normal))) "Face for debug-level messages in the mode-line. Used by vcs, checker, etc." :group 'doom-modeline-faces) (defface doom-modeline-info - '((t (:inherit (success bold)))) + '((t (:inherit (doom-modeline success bold)))) "Face for info-level messages in the mode-line. Used by vcs, checker, etc." :group 'doom-modeline-faces) (defface doom-modeline-warning - '((t (:inherit (warning bold)))) + '((t (:inherit (doom-modeline warning bold)))) "Face for warnings in the mode-line. Used by vcs, checker, etc." :group 'doom-modeline-faces) (defface doom-modeline-urgent - '((t (:inherit (error bold)))) + '((t (:inherit (doom-modeline error bold)))) "Face for errors in the mode-line. Used by vcs, checker, etc." :group 'doom-modeline-faces) @@ -666,7 +671,7 @@ Also see the face `doom-modeline-unread-number'." :group 'doom-modeline-faces) (defface doom-modeline-unread-number - '((t (:slant italic :weight normal))) + '((t (:inherit doom-modeline :slant italic :weight normal))) "Face for unread number in the mode-line. Used by GitHub, mu4e, etc." :group 'doom-modeline-faces) @@ -681,23 +686,23 @@ Also see the face `doom-modeline-unread-number'." :group 'doom-modeline-faces) (defface doom-modeline-debug-visual - '((((background light)) :foreground "#D4843E") - (((background dark)) :foreground "#915B2D")) + '((((background light)) :foreground "#D4843E" :inherit doom-modeline) + (((background dark)) :foreground "#915B2D" :inherit doom-modeline)) "Face to use for the mode-line while debugging." :group 'doom-modeline-faces) (defface doom-modeline-evil-emacs-state - '((t (:inherit (font-lock-builtin-face bold)))) + '((t (:inherit (doom-modeline font-lock-builtin-face bold)))) "Face for the Emacs state tag in evil indicator." :group 'doom-modeline-faces) (defface doom-modeline-evil-insert-state - '((t (:inherit (font-lock-keyword-face bold)))) + '((t (:inherit (doom-modeline font-lock-keyword-face bold)))) "Face for the insert state tag in evil indicator." :group 'doom-modeline-faces) (defface doom-modeline-evil-motion-state - '((t (:inherit (font-lock-doc-face bold) :slant normal))) + '((t (:inherit (doom-modeline font-lock-doc-face bold) :slant normal))) "Face for the motion state tag in evil indicator." :group 'doom-modeline-faces) @@ -752,12 +757,12 @@ Also see the face `doom-modeline-unread-number'." :group 'doom-modeline-faces) (defface doom-modeline-boon-insert-state - '((t (:inherit (font-lock-keyword-face bold)))) + '((t (:inherit (doom-modeline font-lock-keyword-face bold)))) "Face for the insert state tag in boon indicator." :group 'doom-modeline-faces) (defface doom-modeline-boon-special-state - '((t (:inherit (font-lock-builtin-face bold)))) + '((t (:inherit (doom-modeline font-lock-builtin-face bold)))) "Face for the special state tag in boon indicator." :group 'doom-modeline-faces) @@ -767,72 +772,72 @@ Also see the face `doom-modeline-unread-number'." :group 'doom-modeline-faces) (defface doom-modeline-persp-name - '((t (:inherit (font-lock-comment-face italic)))) + '((t (:inherit (doom-modeline font-lock-comment-face italic)))) "Face for the persp name." :group 'doom-modeline-faces) (defface doom-modeline-persp-buffer-not-in-persp - '((t (:inherit (font-lock-doc-face bold italic)))) + '((t (:inherit (doom-modeline font-lock-doc-face bold italic)))) "Face for the buffers which are not in the persp." :group 'doom-modeline-faces) (defface doom-modeline-repl-success - '((t (:inherit success :weight normal))) + '((t (:inherit doom-modeline-info :weight normal))) "Face for REPL success state." :group 'doom-modeline-faces) (defface doom-modeline-repl-warning - '((t (:inherit warning :weight normal))) + '((t (:inherit doom-modeline-warning :weight normal))) "Face for REPL warning state." :group 'doom-modeline-faces) (defface doom-modeline-lsp-success - '((t (:inherit success :weight normal))) + '((t (:inherit doom-modeline-info :weight normal))) "Face for LSP success state." :group 'doom-modeline-faces) (defface doom-modeline-lsp-warning - '((t (:inherit warning :weight normal))) + '((t (:inherit doom-modeline-warning :weight normal))) "Face for LSP warning state." :group 'doom-modeline-faces) (defface doom-modeline-lsp-error - '((t (:inherit error :weight normal))) + '((t (:inherit doom-modeline-urgent :weight normal))) "Face for LSP error state." :group 'doom-modeline-faces) (defface doom-modeline-lsp-running - '((t (:inherit compilation-mode-line-run :weight normal :slant normal))) + '((t (:inherit (doom-modeline compilation-mode-line-run) :weight normal :slant normal))) "Face for LSP running state." :group 'doom-modeline-faces) (defface doom-modeline-battery-charging - '((t (:inherit success :weight normal))) + '((t (:inherit doom-modeline-info :weight normal))) "Face for battery charging status." :group 'doom-modeline-faces) (defface doom-modeline-battery-full - '((t (:inherit success :weight normal))) + '((t (:inherit doom-modeline-info :weight normal))) "Face for battery full status." :group 'doom-modeline-faces) (defface doom-modeline-battery-normal - '((t (:inherit mode-line :weight normal))) + '((t (:inherit (doom-modeline mode-line) :weight normal))) "Face for battery normal status." :group 'doom-modeline-faces) (defface doom-modeline-battery-warning - '((t (:inherit warning :weight normal))) + '((t (:inherit doom-modeline-warning :weight normal))) "Face for battery warning status." :group 'doom-modeline-faces) (defface doom-modeline-battery-critical - '((t (:inherit error :weight normal))) + '((t (:inherit doom-modeline-urgent :weight normal))) "Face for battery critical status." :group 'doom-modeline-faces) (defface doom-modeline-battery-error - '((t (:inherit error :weight normal))) + '((t (:inherit doom-modeline-urgent :weight normal))) "Face for battery error status." :group 'doom-modeline-faces) @@ -842,12 +847,12 @@ Also see the face `doom-modeline-unread-number'." :group 'doom-modeline-faces) (defface doom-modeline-time - '((t (:inherit (mode-line-buffer-id bold)))) + '((t (:inherit doom-modeline-buffer-file))) "Face for display time." :group 'doom-modeline-faces) (defface doom-modeline-compilation - '((t (:inherit warning :slant italic :height 0.9))) + '((t (:inherit doom-modeline-warning :weight normal :slant italic :height 0.9))) "Face for compilation progress." :group 'doom-modeline-faces) @@ -931,6 +936,10 @@ used as an advice to window creation functions." (display-graphic-p) (featurep 'all-the-icons))) +(defun doom-modeline-mwheel-available-p () + "Whether mouse wheel is available." + (and (featurep 'mwheel) (bound-and-true-p mouse-wheel-mode))) + ;; Keep `doom-modeline-current-window' up-to-date (defun doom-modeline--selected-window () "Get the selected window." @@ -976,6 +985,7 @@ used as an advice to window creation functions." mode-line-emphasis mode-line-highlight mode-line-buffer-id + doom-modeline solaire-mode-line-face solaire-mode-line-active-face paradox-mode-line-face @@ -983,12 +993,6 @@ used as an advice to window creation functions." flycheck-color-mode-line-warning-face flycheck-color-mode-line-info-face flycheck-color-mode-line-success-face)) -(dolist (face (face-list)) - (let ((f (symbol-name face))) - (and - (string-match-p "^\\(doom-modeline\\|all-the-icons\\)" f) - (not (string-match-p "\\(-inactive\\|-dired\\|-ivy\\|-ibuffer\\)" f)) - (add-to-list 'doom-modeline--remap-faces face)))) (defvar doom-modeline--remap-face-cookie-alist nil) (defun doom-modeline-focus () @@ -1199,10 +1203,10 @@ See https://github.com/seagle0128/doom-modeline/issues/301." (when-let ((props (get-text-property 0 'face icon))) (when (listp props) (cl-destructuring-bind (&key family height inherit &allow-other-keys) props - (propertize icon 'face `(:inherit ,(or face inherit props 'mode-line) + (propertize icon 'face `(:inherit (doom-modeline ,(or face inherit props)) :family ,(or family "") :height ,(or height 1.0)))))) - (propertize icon 'face face))) + (propertize icon 'face `(:inherit (doom-modeline ,face))))) (defun doom-modeline-icon (icon-set icon-name unicode text &rest args) "Display icon of ICON-NAME with ARGS in mode-line. @@ -1211,7 +1215,8 @@ ICON-SET includes `octicon', `faicon', `material', `alltheicons' and `fileicon', etc. UNICODE is the unicode char fallback. TEXT is the ASCII char fallback. ARGS is same as `all-the-icons-octicon' and others." - (let ((face (or (plist-get args :face) 'mode-line))) + (let ((face `(:inherit (doom-modeline + ,(or (plist-get args :face) 'mode-line))))) (cond ;; Icon ((and (doom-modeline-icon-displayable-p) @@ -1325,9 +1330,11 @@ Return nil if no project was found." ((and (memq doom-modeline-project-detection '(auto project)) (fboundp 'project-current)) (when-let ((project (project-current))) - (expand-file-name (if (fboundp 'project-root) - (project-root project) - (cdr project))))))))) + (expand-file-name + (if (fboundp 'project-root) + (project-root project) + (car (with-no-warnings + (project-roots project))))))))))) (defun doom-modeline-project-p () "Check if the file is in a project." diff --git a/code/elpa/doom-modeline-20230306.250/doom-modeline-env.el b/code/elpa/doom-modeline-20230406.623/doom-modeline-env.el similarity index 100% rename from code/elpa/doom-modeline-20230306.250/doom-modeline-env.el rename to code/elpa/doom-modeline-20230406.623/doom-modeline-env.el diff --git a/code/elpa/doom-modeline-20230306.250/doom-modeline-pkg.el b/code/elpa/doom-modeline-20230406.623/doom-modeline-pkg.el similarity index 72% rename from code/elpa/doom-modeline-20230306.250/doom-modeline-pkg.el rename to code/elpa/doom-modeline-20230406.623/doom-modeline-pkg.el index c53327d..9a8ba77 100644 --- a/code/elpa/doom-modeline-20230306.250/doom-modeline-pkg.el +++ b/code/elpa/doom-modeline-20230406.623/doom-modeline-pkg.el @@ -1,8 +1,8 @@ -(define-package "doom-modeline" "20230306.250" "A minimal and modern mode-line" +(define-package "doom-modeline" "20230406.623" "A minimal and modern mode-line" '((emacs "25.1") (compat "28.1.1.1") (shrink-path "0.2.0")) - :commit "236fa330c631228e9a513dea2f4598a29b7e8444" :authors + :commit "a86ec8effe242cab8aba09ec0a2c7fed555c1fce" :authors '(("Vincent Zhang" . "seagle0128@gmail.com")) :maintainer '("Vincent Zhang" . "seagle0128@gmail.com") diff --git a/code/elpa/doom-modeline-20230306.250/doom-modeline-segments.el b/code/elpa/doom-modeline-20230406.623/doom-modeline-segments.el similarity index 99% rename from code/elpa/doom-modeline-20230306.250/doom-modeline-segments.el rename to code/elpa/doom-modeline-20230406.623/doom-modeline-segments.el index eb412cb..5c37da7 100644 --- a/code/elpa/doom-modeline-20230306.250/doom-modeline-segments.el +++ b/code/elpa/doom-modeline-20230406.623/doom-modeline-segments.el @@ -260,7 +260,7 @@ :face 'all-the-icons-dsilver :height 0.9 :v-adjust 0.0) - icon) + (doom-modeline-propertize-icon icon)) 'help-echo (format "Major-mode: %s" (format-mode-line mode-name)) 'display '(raise -0.135)))))) (add-hook 'find-file-hook #'doom-modeline-update-buffer-file-icon) @@ -875,7 +875,7 @@ mouse-2: Show help for minor mode") (format "error: %d, warning: %d, info: %d\n" .error .warning .info))) "mouse-1: Show all errors mouse-3: Next error" - (if (featurep 'mwheel) + (if (doom-modeline-mwheel-available-p) "\nwheel-up/wheel-down: Previous/next error"))) ('running "Checking...") ('no-checker "No Checker") @@ -888,7 +888,7 @@ mouse-3: Next error" #'flycheck-list-errors) (define-key map [mode-line mouse-3] #'flycheck-next-error) - (when (featurep 'mwheel) + (when (doom-modeline-mwheel-available-p) (define-key map [mode-line mouse-wheel-down-event] (lambda (event) (interactive "e") @@ -1049,13 +1049,13 @@ mouse-2: Show help for minor mode" (t (format "error: %d, warning: %d, note: %d mouse-1: List all problems%s" .error .warning .note - (if (featurep 'mwheel) + (if (doom-modeline-mwheel-available-p) "\nwheel-up/wheel-down: Previous/next problem")))) 'mouse-face 'doom-modeline-highlight 'local-map (let ((map (make-sparse-keymap))) (define-key map [mode-line mouse-1] #'flymake-show-diagnostics-buffer) - (when (featurep 'mwheel) + (when (doom-modeline-mwheel-available-p) (define-key map (vector 'mode-line mouse-wheel-down-event) (lambda (event) diff --git a/code/elpa/doom-modeline-20230306.250/doom-modeline.el b/code/elpa/doom-modeline-20230406.623/doom-modeline.el similarity index 100% rename from code/elpa/doom-modeline-20230306.250/doom-modeline.el rename to code/elpa/doom-modeline-20230406.623/doom-modeline.el diff --git a/code/elpa/helm-20230319.2009/.dir-locals.el b/code/elpa/helm-20230406.839/.dir-locals.el similarity index 100% rename from code/elpa/helm-20230319.2009/.dir-locals.el rename to code/elpa/helm-20230406.839/.dir-locals.el diff --git a/code/elpa/helm-20230319.2009/emacs-helm.sh b/code/elpa/helm-20230406.839/emacs-helm.sh similarity index 100% rename from code/elpa/helm-20230319.2009/emacs-helm.sh rename to code/elpa/helm-20230406.839/emacs-helm.sh diff --git a/code/elpa/helm-20230319.2009/helm-adaptive.el b/code/elpa/helm-20230406.839/helm-adaptive.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-adaptive.el rename to code/elpa/helm-20230406.839/helm-adaptive.el diff --git a/code/elpa/helm-20230319.2009/helm-autoloads.el b/code/elpa/helm-20230406.839/helm-autoloads.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-autoloads.el rename to code/elpa/helm-20230406.839/helm-autoloads.el diff --git a/code/elpa/helm-20230319.2009/helm-bookmark.el b/code/elpa/helm-20230406.839/helm-bookmark.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-bookmark.el rename to code/elpa/helm-20230406.839/helm-bookmark.el diff --git a/code/elpa/helm-20230319.2009/helm-buffers.el b/code/elpa/helm-20230406.839/helm-buffers.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-buffers.el rename to code/elpa/helm-20230406.839/helm-buffers.el diff --git a/code/elpa/helm-20230319.2009/helm-color.el b/code/elpa/helm-20230406.839/helm-color.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-color.el rename to code/elpa/helm-20230406.839/helm-color.el diff --git a/code/elpa/helm-20230319.2009/helm-comint.el b/code/elpa/helm-20230406.839/helm-comint.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-comint.el rename to code/elpa/helm-20230406.839/helm-comint.el diff --git a/code/elpa/helm-20230319.2009/helm-command.el b/code/elpa/helm-20230406.839/helm-command.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-command.el rename to code/elpa/helm-20230406.839/helm-command.el diff --git a/code/elpa/helm-20230319.2009/helm-dabbrev.el b/code/elpa/helm-20230406.839/helm-dabbrev.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-dabbrev.el rename to code/elpa/helm-20230406.839/helm-dabbrev.el diff --git a/code/elpa/helm-20230319.2009/helm-easymenu.el b/code/elpa/helm-20230406.839/helm-easymenu.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-easymenu.el rename to code/elpa/helm-20230406.839/helm-easymenu.el diff --git a/code/elpa/helm-20230319.2009/helm-elisp-package.el b/code/elpa/helm-20230406.839/helm-elisp-package.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-elisp-package.el rename to code/elpa/helm-20230406.839/helm-elisp-package.el diff --git a/code/elpa/helm-20230319.2009/helm-elisp.el b/code/elpa/helm-20230406.839/helm-elisp.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-elisp.el rename to code/elpa/helm-20230406.839/helm-elisp.el diff --git a/code/elpa/helm-20230319.2009/helm-epa.el b/code/elpa/helm-20230406.839/helm-epa.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-epa.el rename to code/elpa/helm-20230406.839/helm-epa.el diff --git a/code/elpa/helm-20230319.2009/helm-eshell.el b/code/elpa/helm-20230406.839/helm-eshell.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-eshell.el rename to code/elpa/helm-20230406.839/helm-eshell.el diff --git a/code/elpa/helm-20230319.2009/helm-eval.el b/code/elpa/helm-20230406.839/helm-eval.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-eval.el rename to code/elpa/helm-20230406.839/helm-eval.el diff --git a/code/elpa/helm-20230319.2009/helm-external.el b/code/elpa/helm-20230406.839/helm-external.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-external.el rename to code/elpa/helm-20230406.839/helm-external.el diff --git a/code/elpa/helm-20230319.2009/helm-fd.el b/code/elpa/helm-20230406.839/helm-fd.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-fd.el rename to code/elpa/helm-20230406.839/helm-fd.el diff --git a/code/elpa/helm-20230319.2009/helm-files.el b/code/elpa/helm-20230406.839/helm-files.el similarity index 99% rename from code/elpa/helm-20230319.2009/helm-files.el rename to code/elpa/helm-20230406.839/helm-files.el index 29e40a8..1db6d6c 100644 --- a/code/elpa/helm-20230319.2009/helm-files.el +++ b/code/elpa/helm-20230406.839/helm-files.el @@ -190,6 +190,7 @@ This is used only as a let binding.") (define-key map (kbd "M-.") 'helm-ff-run-etags) (define-key map (kbd "M-R") 'helm-ff-run-rename-file) (define-key map (kbd "M-C") 'helm-ff-run-copy-file) + (define-key map (kbd "M-k") 'helm-ff-run-kill-default-directory) (when (executable-find "rsync") (define-key map (kbd "M-V") 'helm-ff-run-rsync-file)) (define-key map (kbd "C-M-SPC") 'helm-ff-mark-similar-files) @@ -3847,6 +3848,16 @@ to avoid an unnecessary call to `file-truename'." "Delete current candidate without quitting." 'quick-delete 'helm-ff-quick-delete) +(defun helm-ff-kill-default-directory (_candidate) + (with-helm-window + (kill-new helm-ff-default-directory) + (message "`%s' copied to kill-ring" helm-ff-default-directory))) + +(helm-make-persistent-command-from-action helm-ff-run-kill-default-directory + "Kill `helm-ff-default-directory'." + 'kill-default-directory + 'helm-ff-kill-default-directory) + (defun helm-ff-dot-file-p (file) "Check if FILE is `.' or `..'." (member (helm-basename file) '("." ".."))) diff --git a/code/elpa/helm-20230319.2009/helm-find.el b/code/elpa/helm-20230406.839/helm-find.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-find.el rename to code/elpa/helm-20230406.839/helm-find.el diff --git a/code/elpa/helm-20230319.2009/helm-font.el b/code/elpa/helm-20230406.839/helm-font.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-font.el rename to code/elpa/helm-20230406.839/helm-font.el diff --git a/code/elpa/helm-20230319.2009/helm-for-files.el b/code/elpa/helm-20230406.839/helm-for-files.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-for-files.el rename to code/elpa/helm-20230406.839/helm-for-files.el diff --git a/code/elpa/helm-20230319.2009/helm-global-bindings.el b/code/elpa/helm-20230406.839/helm-global-bindings.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-global-bindings.el rename to code/elpa/helm-20230406.839/helm-global-bindings.el diff --git a/code/elpa/helm-20230319.2009/helm-grep.el b/code/elpa/helm-20230406.839/helm-grep.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-grep.el rename to code/elpa/helm-20230406.839/helm-grep.el diff --git a/code/elpa/helm-20230319.2009/helm-help.el b/code/elpa/helm-20230406.839/helm-help.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-help.el rename to code/elpa/helm-20230406.839/helm-help.el diff --git a/code/elpa/helm-20230319.2009/helm-id-utils.el b/code/elpa/helm-20230406.839/helm-id-utils.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-id-utils.el rename to code/elpa/helm-20230406.839/helm-id-utils.el diff --git a/code/elpa/helm-20230319.2009/helm-imenu.el b/code/elpa/helm-20230406.839/helm-imenu.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-imenu.el rename to code/elpa/helm-20230406.839/helm-imenu.el diff --git a/code/elpa/helm-20230319.2009/helm-info.el b/code/elpa/helm-20230406.839/helm-info.el similarity index 98% rename from code/elpa/helm-20230319.2009/helm-info.el rename to code/elpa/helm-20230406.839/helm-info.el index 5842fb8..54023bf 100644 --- a/code/elpa/helm-20230319.2009/helm-info.el +++ b/code/elpa/helm-20230406.839/helm-info.el @@ -101,8 +101,10 @@ Argument TOBUF is the `helm-candidate-buffer'." (defun helm-info-goto (node-line) "The helm-info action to jump to NODE-LINE." - (Info-goto-node (car node-line)) - (helm-goto-line (cdr node-line))) + (let ((alive (buffer-live-p (get-buffer "*info*")))) + (Info-goto-node (car node-line)) + (when alive (revert-buffer nil t)) + (helm-goto-line (cdr node-line)))) (defvar helm-info--node-regexp "^\\* +\\(.+\\):[[:space:]]+\\(.*\\)\\(?:[[:space:]]*\\)(line +\\([0-9]+\\))" diff --git a/code/elpa/helm-20230319.2009/helm-locate.el b/code/elpa/helm-20230406.839/helm-locate.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-locate.el rename to code/elpa/helm-20230406.839/helm-locate.el diff --git a/code/elpa/helm-20230319.2009/helm-man.el b/code/elpa/helm-20230406.839/helm-man.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-man.el rename to code/elpa/helm-20230406.839/helm-man.el diff --git a/code/elpa/helm-20230319.2009/helm-misc.el b/code/elpa/helm-20230406.839/helm-misc.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-misc.el rename to code/elpa/helm-20230406.839/helm-misc.el diff --git a/code/elpa/helm-20230319.2009/helm-mode.el b/code/elpa/helm-20230406.839/helm-mode.el similarity index 99% rename from code/elpa/helm-20230319.2009/helm-mode.el rename to code/elpa/helm-20230406.839/helm-mode.el index 07e2ca9..3697fb4 100644 --- a/code/elpa/helm-20230319.2009/helm-mode.el +++ b/code/elpa/helm-20230406.839/helm-mode.el @@ -883,8 +883,8 @@ that use `helm-comp-read'. See `helm-M-x' for example." :history (and (symbolp input-history) input-history) :buffer buffer)) (remove-hook 'helm-after-update-hook 'helm-comp-read--move-to-first-real-candidate)) - ;; If `history' is a symbol save it. - (when (and result history (symbolp history)) + ;; If `history' is a symbol save it, except when it is t. + (when (and result history (symbolp history) (not (eq history t))) (set history ;; RESULT may be a a string or a list of strings bug #2461. (delete-dups (append (mapcar #'substring-no-properties (helm-mklist result)) @@ -1684,7 +1684,6 @@ The `helm-find-files' history `helm-ff-history' is used here." (helm-split-window-default-side (if (eq helm-split-window-default-side 'same) 'below helm-split-window-default-side)) - helm-split-window-inside-p helm-reuse-last-window-split-state ;; Helm handlers should always have a non nil INITIAL arg. (init (or initial dir default-directory))) diff --git a/code/elpa/helm-20230319.2009/helm-net.el b/code/elpa/helm-20230406.839/helm-net.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-net.el rename to code/elpa/helm-20230406.839/helm-net.el diff --git a/code/elpa/helm-20230319.2009/helm-occur.el b/code/elpa/helm-20230406.839/helm-occur.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-occur.el rename to code/elpa/helm-20230406.839/helm-occur.el diff --git a/code/elpa/helm-20230319.2009/helm-pkg.el b/code/elpa/helm-20230406.839/helm-pkg.el similarity index 61% rename from code/elpa/helm-20230319.2009/helm-pkg.el rename to code/elpa/helm-20230406.839/helm-pkg.el index 649c473..bc0fd39 100644 --- a/code/elpa/helm-20230319.2009/helm-pkg.el +++ b/code/elpa/helm-20230406.839/helm-pkg.el @@ -1,7 +1,7 @@ -(define-package "helm" "20230319.2009" "Helm is an Emacs incremental and narrowing framework" +(define-package "helm" "20230406.839" "Helm is an Emacs incremental and narrowing framework" '((helm-core "3.9.0") (popup "0.5.3")) - :commit "f1ef8689514b20cd2c2a6c6be987d2c40a8f4a09" :authors + :commit "5c9d28da67d3f42fd27c7f7fcf0701b899fbaa8a" :authors '(("Thierry Volpiatto" . "thievol@posteo.net")) :maintainer '("Thierry Volpiatto" . "thievol@posteo.net") diff --git a/code/elpa/helm-20230319.2009/helm-regexp.el b/code/elpa/helm-20230406.839/helm-regexp.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-regexp.el rename to code/elpa/helm-20230406.839/helm-regexp.el diff --git a/code/elpa/helm-20230319.2009/helm-ring.el b/code/elpa/helm-20230406.839/helm-ring.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-ring.el rename to code/elpa/helm-20230406.839/helm-ring.el diff --git a/code/elpa/helm-20230319.2009/helm-semantic.el b/code/elpa/helm-20230406.839/helm-semantic.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-semantic.el rename to code/elpa/helm-20230406.839/helm-semantic.el diff --git a/code/elpa/helm-20230319.2009/helm-shell.el b/code/elpa/helm-20230406.839/helm-shell.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-shell.el rename to code/elpa/helm-20230406.839/helm-shell.el diff --git a/code/elpa/helm-20230319.2009/helm-sys.el b/code/elpa/helm-20230406.839/helm-sys.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-sys.el rename to code/elpa/helm-20230406.839/helm-sys.el diff --git a/code/elpa/helm-20230319.2009/helm-tags.el b/code/elpa/helm-20230406.839/helm-tags.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-tags.el rename to code/elpa/helm-20230406.839/helm-tags.el diff --git a/code/elpa/helm-20230319.2009/helm-types.el b/code/elpa/helm-20230406.839/helm-types.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-types.el rename to code/elpa/helm-20230406.839/helm-types.el diff --git a/code/elpa/helm-20230319.2009/helm-utils.el b/code/elpa/helm-20230406.839/helm-utils.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-utils.el rename to code/elpa/helm-20230406.839/helm-utils.el diff --git a/code/elpa/helm-20230319.2009/helm-x-files.el b/code/elpa/helm-20230406.839/helm-x-files.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm-x-files.el rename to code/elpa/helm-20230406.839/helm-x-files.el diff --git a/code/elpa/helm-20230319.2009/helm.el b/code/elpa/helm-20230406.839/helm.el similarity index 100% rename from code/elpa/helm-20230319.2009/helm.el rename to code/elpa/helm-20230406.839/helm.el diff --git a/code/elpa/helm-ls-git-20221007.1113/helm-ls-git-pkg.el b/code/elpa/helm-ls-git-20221007.1113/helm-ls-git-pkg.el deleted file mode 100644 index 27c13b8..0000000 --- a/code/elpa/helm-ls-git-20221007.1113/helm-ls-git-pkg.el +++ /dev/null @@ -1,2 +0,0 @@ -;;; Generated package description from helm-ls-git.el -*- no-byte-compile: t -*- -(define-package "helm-ls-git" "20221007.1113" "list git files." '((helm "1.7.8")) :commit "dbee5c668c49e5b77907f1d9887e2a44f7b196a3") diff --git a/code/elpa/helm-ls-git-20221118.503/helm-ls-git-pkg.el b/code/elpa/helm-ls-git-20221118.503/helm-ls-git-pkg.el deleted file mode 100644 index 6a81fd1..0000000 --- a/code/elpa/helm-ls-git-20221118.503/helm-ls-git-pkg.el +++ /dev/null @@ -1,2 +0,0 @@ -;;; Generated package description from helm-ls-git.el -*- no-byte-compile: t -*- -(define-package "helm-ls-git" "20221118.503" "list git files." '((helm "1.7.8")) :commit "c5893f0cd92b20dcdcd5dc89d9ba6200a95c3f80") diff --git a/code/elpa/helm-ls-git-20221007.1113/helm-ls-git-autoloads.el b/code/elpa/helm-ls-git-20230405.957/helm-ls-git-autoloads.el similarity index 100% rename from code/elpa/helm-ls-git-20221007.1113/helm-ls-git-autoloads.el rename to code/elpa/helm-ls-git-20230405.957/helm-ls-git-autoloads.el diff --git a/code/elpa/helm-ls-git-20230405.957/helm-ls-git-pkg.el b/code/elpa/helm-ls-git-20230405.957/helm-ls-git-pkg.el new file mode 100644 index 0000000..37bc4c1 --- /dev/null +++ b/code/elpa/helm-ls-git-20230405.957/helm-ls-git-pkg.el @@ -0,0 +1,2 @@ +;;; Generated package description from helm-ls-git.el -*- no-byte-compile: t -*- +(define-package "helm-ls-git" "20230405.957" "list git files." '((helm "1.7.8")) :commit "356e7f0c2725fc4ab6d2eb5bb4752ac1a8133039") diff --git a/code/elpa/helm-ls-git-20221118.503/helm-ls-git.el b/code/elpa/helm-ls-git-20230405.957/helm-ls-git.el similarity index 99% rename from code/elpa/helm-ls-git-20221118.503/helm-ls-git.el rename to code/elpa/helm-ls-git-20230405.957/helm-ls-git.el index faee759..d095489 100644 --- a/code/elpa/helm-ls-git-20221118.503/helm-ls-git.el +++ b/code/elpa/helm-ls-git-20230405.957/helm-ls-git.el @@ -3,8 +3,8 @@ ;; Copyright (C) 2012 ~ 2022 Thierry Volpiatto ;; Package-Requires: ((helm "1.7.8")) -;; Package-Version: 20221118.503 -;; Package-Commit: c5893f0cd92b20dcdcd5dc89d9ba6200a95c3f80 +;; Package-Version: 20230405.957 +;; Package-Commit: 356e7f0c2725fc4ab6d2eb5bb4752ac1a8133039 ;; 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 @@ -537,6 +537,7 @@ See docstring of `helm-ls-git-ls-switches'. (lambda (_candidate) (funcall helm-ls-git-status-command (helm-default-directory))) + "Git Log" 'helm-ls-git-show-log-for-file "Switch to shell" 'helm-ls-git-switch-to-shell "Git grep files (`C-u' only current directory)" 'helm-ls-git-grep @@ -655,7 +656,7 @@ See docstring of `helm-ls-git-ls-switches'. (setq unread-command-events nil)) (helm-force-update)))))) -(defun helm-ls-git-log (&optional branch num) +(defun helm-ls-git-log (&optional branch num file) "Run git log branch -n num and return the resulting string." (when (and branch (string-match "->" branch)) (setq branch (car (last (split-string branch "->"))))) @@ -676,6 +677,7 @@ See docstring of `helm-ls-git-ls-switches'. helm-ls-git-log--last-number-commits) ,(or branch ""))) output) + (when file (setq switches (append switches `("--follow" ,file)))) (unless helm-ls-git-log--is-full (setq helm-ls-git-log--last-number-commits (number-to-string @@ -702,7 +704,10 @@ See docstring of `helm-ls-git-ls-switches'. branch helm-ls-git-log--last-number-commits)) helm-ls-git-log--last-log)) -(defun helm-ls-git-show-log (branch) +(defun helm-ls-git-show-log-for-file (file) + (helm-ls-git-show-log (helm-ls-git--branch) file)) + +(defun helm-ls-git-show-log (branch &optional file) (let ((name (if (helm-ls-git-detached-state-p) (helm-ls-git--branch) (replace-regexp-in-string "[ *]" "" branch))) @@ -715,10 +720,12 @@ See docstring of `helm-ls-git-ls-switches'. :header-name (lambda (sname) (format "%s (%s)" sname name)) :init (lambda () (helm-init-candidates-in-buffer 'global - (helm-ls-git-log name (helm-aif (or prefarg - ;; for force-update. - current-prefix-arg) - (prefix-numeric-value it)))) + (helm-ls-git-log + name (helm-aif (or prefarg + ;; for force-update. + current-prefix-arg) + (prefix-numeric-value it)) + file)) (setq prefarg nil)) :get-line 'buffer-substring :marked-with-props 'withprop diff --git a/code/elpa/helpful-20221209.1743/helpful-pkg.el b/code/elpa/helpful-20221209.1743/helpful-pkg.el deleted file mode 100644 index 747c00d..0000000 --- a/code/elpa/helpful-20221209.1743/helpful-pkg.el +++ /dev/null @@ -1,2 +0,0 @@ -;;; Generated package description from helpful.el -*- no-byte-compile: t -*- -(define-package "helpful" "20221209.1743" "A better *help* buffer" '((emacs "25") (dash "2.18.0") (s "1.11.0") (f "0.20.0") (elisp-refs "1.2")) :commit "94c25337b2de2f9da60914a7c0c6cca9584c0231" :authors '(("Wilfred Hughes" . "me@wilfred.me.uk")) :maintainer '("Wilfred Hughes" . "me@wilfred.me.uk") :keywords '("help" "lisp") :url "https://github.com/Wilfred/helpful") diff --git a/code/elpa/helpful-20221024.134/helpful-autoloads.el b/code/elpa/helpful-20230323.414/helpful-autoloads.el similarity index 100% rename from code/elpa/helpful-20221024.134/helpful-autoloads.el rename to code/elpa/helpful-20230323.414/helpful-autoloads.el diff --git a/code/elpa/helpful-20221024.134/helpful-pkg.el b/code/elpa/helpful-20230323.414/helpful-pkg.el similarity index 71% rename from code/elpa/helpful-20221024.134/helpful-pkg.el rename to code/elpa/helpful-20230323.414/helpful-pkg.el index 9bf895b..2026e0d 100644 --- a/code/elpa/helpful-20221024.134/helpful-pkg.el +++ b/code/elpa/helpful-20230323.414/helpful-pkg.el @@ -1,2 +1,2 @@ ;;; Generated package description from helpful.el -*- no-byte-compile: t -*- -(define-package "helpful" "20221024.134" "A better *help* buffer" '((emacs "25") (dash "2.18.0") (s "1.11.0") (f "0.20.0") (elisp-refs "1.2")) :commit "60c1cd49f72e930b8796e5644bd222e8fc466740" :authors '(("Wilfred Hughes" . "me@wilfred.me.uk")) :maintainer '("Wilfred Hughes" . "me@wilfred.me.uk") :keywords '("help" "lisp") :url "https://github.com/Wilfred/helpful") +(define-package "helpful" "20230323.414" "A better *help* buffer" '((emacs "25") (dash "2.18.0") (s "1.11.0") (f "0.20.0") (elisp-refs "1.2")) :commit "e9ec6fc2ae10db2b9b59ed656021845d11881a0a" :authors '(("Wilfred Hughes" . "me@wilfred.me.uk")) :maintainer '("Wilfred Hughes" . "me@wilfred.me.uk") :keywords '("help" "lisp") :url "https://github.com/Wilfred/helpful") diff --git a/code/elpa/helpful-20221209.1743/helpful.el b/code/elpa/helpful-20230323.414/helpful.el similarity index 99% rename from code/elpa/helpful-20221209.1743/helpful.el rename to code/elpa/helpful-20230323.414/helpful.el index 1faeaec..edc7a62 100644 --- a/code/elpa/helpful-20221209.1743/helpful.el +++ b/code/elpa/helpful-20230323.414/helpful.el @@ -4,8 +4,8 @@ ;; Author: Wilfred Hughes ;; URL: https://github.com/Wilfred/helpful -;; Package-Version: 20221209.1743 -;; Package-Commit: 94c25337b2de2f9da60914a7c0c6cca9584c0231 +;; Package-Version: 20230323.414 +;; Package-Commit: e9ec6fc2ae10db2b9b59ed656021845d11881a0a ;; Keywords: help, lisp ;; Version: 0.20 ;; Package-Requires: ((emacs "25") (dash "2.18.0") (s "1.11.0") (f "0.20.0") (elisp-refs "1.2")) @@ -2950,6 +2950,10 @@ See also `helpful-max-buffers'." (defvar helpful-mode-map (let* ((map (make-sparse-keymap))) (define-key map (kbd "g") #'helpful-update) + (define-key map [remap revert-buffer] #'helpful-update) + (when (fboundp 'revert-buffer-quick) + (define-key map [remap revert-buffer-quick] #'helpful-update)) + (define-key map (kbd "RET") #'helpful-visit-reference) (define-key map (kbd "TAB") #'forward-button) diff --git a/code/elpa/markdown-mode-20230306.2344/markdown-mode-pkg.el b/code/elpa/markdown-mode-20230306.2344/markdown-mode-pkg.el deleted file mode 100644 index 3497cd7..0000000 --- a/code/elpa/markdown-mode-20230306.2344/markdown-mode-pkg.el +++ /dev/null @@ -1,2 +0,0 @@ -;;; Generated package description from markdown-mode.el -*- no-byte-compile: t -*- -(define-package "markdown-mode" "20230306.2344" "Major mode for Markdown-formatted text" '((emacs "26.1")) :commit "ece1dd845904b08ab78598dc7e1a2eaf7875d1c4" :authors '(("Jason R. Blevins" . "jblevins@xbeta.org")) :maintainer '("Jason R. Blevins" . "jblevins@xbeta.org") :keywords '("markdown" "github flavored markdown" "itex") :url "https://jblevins.org/projects/markdown-mode/") diff --git a/code/elpa/markdown-mode-20230306.2344/markdown-mode-autoloads.el b/code/elpa/markdown-mode-20230331.913/markdown-mode-autoloads.el similarity index 100% rename from code/elpa/markdown-mode-20230306.2344/markdown-mode-autoloads.el rename to code/elpa/markdown-mode-20230331.913/markdown-mode-autoloads.el diff --git a/code/elpa/markdown-mode-20230331.913/markdown-mode-pkg.el b/code/elpa/markdown-mode-20230331.913/markdown-mode-pkg.el new file mode 100644 index 0000000..4aa41ef --- /dev/null +++ b/code/elpa/markdown-mode-20230331.913/markdown-mode-pkg.el @@ -0,0 +1,2 @@ +;;; Generated package description from markdown-mode.el -*- no-byte-compile: t -*- +(define-package "markdown-mode" "20230331.913" "Major mode for Markdown-formatted text" '((emacs "26.1")) :commit "ad3a816f7be97deb83fc0a7fa41305c79009bac5" :authors '(("Jason R. Blevins" . "jblevins@xbeta.org")) :maintainer '("Jason R. Blevins" . "jblevins@xbeta.org") :keywords '("markdown" "github flavored markdown" "itex") :url "https://jblevins.org/projects/markdown-mode/") diff --git a/code/elpa/markdown-mode-20230306.2344/markdown-mode.el b/code/elpa/markdown-mode-20230331.913/markdown-mode.el similarity index 99% rename from code/elpa/markdown-mode-20230306.2344/markdown-mode.el rename to code/elpa/markdown-mode-20230331.913/markdown-mode.el index 5b4b02c..fff9113 100644 --- a/code/elpa/markdown-mode-20230306.2344/markdown-mode.el +++ b/code/elpa/markdown-mode-20230331.913/markdown-mode.el @@ -7,8 +7,8 @@ ;; Maintainer: Jason R. Blevins ;; Created: May 24, 2007 ;; Version: 2.6-alpha -;; Package-Version: 20230306.2344 -;; Package-Commit: ece1dd845904b08ab78598dc7e1a2eaf7875d1c4 +;; Package-Version: 20230331.913 +;; Package-Commit: ad3a816f7be97deb83fc0a7fa41305c79009bac5 ;; Package-Requires: ((emacs "26.1")) ;; Keywords: Markdown, GitHub Flavored Markdown, itex ;; URL: https://jblevins.org/projects/markdown-mode/ @@ -863,6 +863,10 @@ Group 3 matches the text.") "[^ \n\t][ \t]*\\( \\)\n" "Regular expression for matching line breaks.") +(defconst markdown-regex-escape + "\\(\\\\\\)." + "Regular expression for matching escape sequences.") + (defconst markdown-regex-wiki-link "\\(?:^\\|[^\\]\\)\\(?1:\\(?2:\\[\\[\\)\\(?3:[^]|]+\\)\\(?:\\(?4:|\\)\\(?5:[^]]+\\)\\)?\\(?6:\\]\\]\\)\\)" "Regular expression for matching wiki links. @@ -2218,6 +2222,7 @@ Depending on your font, some reasonable choices are: (4 'markdown-highlighting-face) (5 markdown-markup-properties))) (,markdown-regex-line-break . (1 'markdown-line-break-face prepend)) + (,markdown-regex-escape . ((1 markdown-markup-properties prepend))) (markdown-fontify-sub-superscripts) (markdown-match-inline-attributes . ((0 markdown-markup-properties prepend))) (markdown-match-leanpub-sections . ((0 markdown-markup-properties))) @@ -3506,17 +3511,30 @@ SEQ may be an atom or a sequence." `(display ,display-string)))))))) t)) +(defun markdown--fontify-hrs-view-mode (hr-char) + (if (and hr-char (display-supports-face-attributes-p '(:extend t))) + (add-text-properties + (match-beginning 0) (match-end 0) + `(face + (:inherit markdown-hr-face :underline t :extend t) + font-lock-multiline t + display "\n")) + (let ((hr-len (and hr-char (/ (1- (window-body-width)) (char-width hr-char))))) + (add-text-properties + (match-beginning 0) (match-end 0) + `(face + markdown-hr-face font-lock-multiline t + display ,(make-string hr-len hr-char)))))) + (defun markdown-fontify-hrs (last) "Add text properties to horizontal rules from point to LAST." (when (markdown-match-hr last) - (let* ((hr-char (markdown--first-displayable markdown-hr-display-char)) - (hr-len (and hr-char (/ (window-max-chars-per-line) (char-width hr-char))))) - (add-text-properties - (match-beginning 0) (match-end 0) - `(face markdown-hr-face - font-lock-multiline t - ,@(when (and markdown-hide-markup hr-char) - `(display ,(make-string hr-len hr-char))))) + (let ((hr-char (markdown--first-displayable markdown-hr-display-char))) + (if (and markdown-hide-markup hr-char) + (markdown--fontify-hrs-view-mode hr-char) + (add-text-properties + (match-beginning 0) (match-end 0) + `(face markdown-hr-face font-lock-multiline t))) t))) (defun markdown-fontify-sub-superscripts (last) diff --git a/code/elpa/modus-themes-20230320.449/dir b/code/elpa/modus-themes-20230405.456/dir similarity index 100% rename from code/elpa/modus-themes-20230320.449/dir rename to code/elpa/modus-themes-20230405.456/dir diff --git a/code/elpa/modus-themes-20230320.449/doclicense.info b/code/elpa/modus-themes-20230405.456/doclicense.info similarity index 100% rename from code/elpa/modus-themes-20230320.449/doclicense.info rename to code/elpa/modus-themes-20230405.456/doclicense.info diff --git a/code/elpa/modus-themes-20230320.449/modus-operandi-deuteranopia-theme.el b/code/elpa/modus-themes-20230405.456/modus-operandi-deuteranopia-theme.el similarity index 98% rename from code/elpa/modus-themes-20230320.449/modus-operandi-deuteranopia-theme.el rename to code/elpa/modus-themes-20230405.456/modus-operandi-deuteranopia-theme.el index fff62e3..dd7f146 100644 --- a/code/elpa/modus-themes-20230320.449/modus-operandi-deuteranopia-theme.el +++ b/code/elpa/modus-themes-20230405.456/modus-operandi-deuteranopia-theme.el @@ -1,4 +1,4 @@ -;;; modus-operandi-deuteranopia-theme.el --- Elegant, highly legible and customizable light theme -*- lexical-binding:t -*- +;;; modus-operandi-deuteranopia-theme.el --- Deuteranopia-optimized theme with a white background -*- lexical-binding:t -*- ;; Copyright (C) 2019-2023 Free Software Foundation, Inc. @@ -44,7 +44,7 @@ (require 'modus-themes)) (deftheme modus-operandi-deuteranopia - "Elegant, highly legible and customizable light theme. + "Deuteranopia-optimized theme with a white background. This variant is optimized for users with red-green color deficiency (deuteranopia). It conforms with the highest legibility standard for color contrast between background and diff --git a/code/elpa/modus-themes-20230320.449/modus-operandi-theme.el b/code/elpa/modus-themes-20230405.456/modus-operandi-theme.el similarity index 98% rename from code/elpa/modus-themes-20230320.449/modus-operandi-theme.el rename to code/elpa/modus-themes-20230405.456/modus-operandi-theme.el index 0705f92..f65aca1 100644 --- a/code/elpa/modus-themes-20230320.449/modus-operandi-theme.el +++ b/code/elpa/modus-themes-20230405.456/modus-operandi-theme.el @@ -1,4 +1,4 @@ -;;; modus-operandi-theme.el --- Elegant, highly legible and customizable light theme -*- lexical-binding:t -*- +;;; modus-operandi-theme.el --- Elegant, highly legible theme with a white background -*- lexical-binding:t -*- ;; Copyright (C) 2019-2023 Free Software Foundation, Inc. @@ -44,7 +44,7 @@ (require 'modus-themes)) (deftheme modus-operandi - "Elegant, highly legible and customizable light theme. + "Elegant, highly legible theme with a white background. Conforms with the highest legibility standard for color contrast between background and foreground in any given piece of text, which corresponds to a minimum contrast in relative luminance of diff --git a/code/elpa/modus-themes-20230320.449/modus-operandi-tinted-theme.el b/code/elpa/modus-themes-20230405.456/modus-operandi-tinted-theme.el similarity index 98% rename from code/elpa/modus-themes-20230320.449/modus-operandi-tinted-theme.el rename to code/elpa/modus-themes-20230405.456/modus-operandi-tinted-theme.el index 4bb820c..95cbf41 100644 --- a/code/elpa/modus-themes-20230320.449/modus-operandi-tinted-theme.el +++ b/code/elpa/modus-themes-20230405.456/modus-operandi-tinted-theme.el @@ -1,4 +1,4 @@ -;;; modus-operandi-tinted-theme.el --- Elegant, highly legible and customizable light theme -*- lexical-binding:t -*- +;;; modus-operandi-tinted-theme.el --- Elegant, highly legible theme with a light ochre background -*- lexical-binding:t -*- ;; Copyright (C) 2019-2023 Free Software Foundation, Inc. @@ -43,7 +43,7 @@ (require 'modus-themes)) (deftheme modus-operandi-tinted - "Elegant, highly legible and customizable light theme. + "Elegant, highly legible theme with a light ochre background. Conforms with the highest legibility standard for color contrast between background and foreground in any given piece of text, which corresponds to a minimum contrast in relative luminance of diff --git a/code/elpa/modus-themes-20230320.449/modus-themes-autoloads.el b/code/elpa/modus-themes-20230405.456/modus-themes-autoloads.el similarity index 100% rename from code/elpa/modus-themes-20230320.449/modus-themes-autoloads.el rename to code/elpa/modus-themes-20230405.456/modus-themes-autoloads.el diff --git a/code/elpa/modus-themes-20230320.449/modus-themes-pkg.el b/code/elpa/modus-themes-20230405.456/modus-themes-pkg.el similarity index 73% rename from code/elpa/modus-themes-20230320.449/modus-themes-pkg.el rename to code/elpa/modus-themes-20230405.456/modus-themes-pkg.el index eac5219..abecc22 100644 --- a/code/elpa/modus-themes-20230320.449/modus-themes-pkg.el +++ b/code/elpa/modus-themes-20230405.456/modus-themes-pkg.el @@ -1,6 +1,6 @@ -(define-package "modus-themes" "20230320.449" "Elegant, highly legible and customizable themes" +(define-package "modus-themes" "20230405.456" "Elegant, highly legible and customizable themes" '((emacs "27.1")) - :commit "2c34f81b831e646fa31840be8102ecaf4df6b6bf" :authors + :commit "ede2ab0e0ff43b25fdac24a9946a95be705eff95" :authors '(("Protesilaos Stavrou" . "info@protesilaos.com")) :maintainer '("Modus-Themes Development" . "~protesilaos/modus-themes@lists.sr.ht") diff --git a/code/elpa/modus-themes-20230320.449/modus-themes.el b/code/elpa/modus-themes-20230405.456/modus-themes.el similarity index 99% rename from code/elpa/modus-themes-20230320.449/modus-themes.el rename to code/elpa/modus-themes-20230405.456/modus-themes.el index fa0e755..b5b3d29 100644 --- a/code/elpa/modus-themes-20230320.449/modus-themes.el +++ b/code/elpa/modus-themes-20230405.456/modus-themes.el @@ -1183,14 +1183,19 @@ symbol, which is safe when used as a face attribute's value." (defvar modus-themes--select-theme-history nil "Minibuffer history of `modus-themes--select-prompt'.") +(defun modus-themes--annotate-theme (theme) + "Return completion annotation for THEME." + (format " -- %s" (car (split-string (get (intern theme) 'theme-documentation) "\\.")))) + (defun modus-themes--select-prompt () "Minibuffer prompt to select a Modus theme." - (intern - (completing-read - "Select Modus theme: " - (modus-themes--list-known-themes) - nil t nil - 'modus-themes--select-theme-history))) + (let ((completion-extra-properties `(:annotation-function ,#'modus-themes--annotate-theme))) + (intern + (completing-read + "Select Modus theme: " + (modus-themes--list-known-themes) + nil t nil + 'modus-themes--select-theme-history)))) ;;;###autoload (defun modus-themes-select (theme) @@ -1278,7 +1283,8 @@ color mappings of the palette, instead of its named colors." (defun modus-themes--list-colors-prompt () "Prompt for Modus theme. Helper function for `modus-themes-list-colors'." - (let ((def (format "%s" (modus-themes--current-theme)))) + (let ((def (format "%s" (modus-themes--current-theme))) + (completion-extra-properties `(:annotation-function ,#'modus-themes--annotate-theme))) (completing-read (format "Use palette from theme [%s]: " def) (modus-themes--list-known-themes) nil t nil @@ -1581,7 +1587,10 @@ FG and BG are the main colors." `(modus-themes-slant ((,c ,@(modus-themes--slant)))) `(modus-themes-ui-variable-pitch ((,c ,@(modus-themes--variable-pitch-ui)))) ;;;;; other custom faces - `(modus-themes-button ((,c :inherit variable-pitch :box ,border :background ,bg-button-active :foreground ,fg-button-active))) + `(modus-themes-button ((,c :inherit variable-pitch + :box (:line-width 1 :color ,border :style released-button) + :background ,bg-button-active + :foreground ,fg-button-active))) `(modus-themes-key-binding ((,c :inherit (bold modus-themes-fixed-pitch) :foreground ,keybind))) `(modus-themes-prompt ((,c ,@(modus-themes--prompt fg-prompt bg-prompt)))) `(modus-themes-reset-soft ((,c :background ,bg-main :foreground ,fg-main @@ -1592,9 +1601,9 @@ FG and BG are the main colors." `(default ((,c :background ,bg-main :foreground ,fg-main))) `(cursor ((,c :background ,cursor))) `(fringe ((,c :background ,fringe :foreground ,fg-main))) - `(menu ((,c :background ,bg-tab-bar :foreground ,fg-main))) - `(scroll-bar ((,c :background ,fringe :foreground ,fg-dim))) - `(tool-bar ((,c :background ,bg-tab-bar :foreground ,fg-main))) + `(menu ((,c :background ,bg-dim :foreground ,fg-main))) + `(scroll-bar ((,c :background ,bg-dim :foreground ,fg-dim))) + `(tool-bar ((,c :background ,bg-dim :foreground ,fg-main))) `(vertical-border ((,c :foreground ,border))) ;;;;; basic and/or ungrouped styles `(bold ((,c :weight bold))) @@ -2654,6 +2663,8 @@ FG and BG are the main colors." `(jiralib-link-project-face ((,c :underline t))) ;;;;; jit-spell `(jit-spell-misspelling ((,c :inherit modus-themes-lang-error))) +;;;;; jinx + `(jinx-misspelled ((,c :inherit modus-themes-lang-error))) ;;;;; journalctl-mode `(journalctl-error-face ((,c :inherit error))) `(journalctl-finished-face ((,c :inherit success))) @@ -3757,7 +3768,7 @@ FG and BG are the main colors." `(which-func ((,c :inherit bold :foreground ,modeline-info))) ;;;;; which-key `(which-key-command-description-face ((,c :foreground ,fg-main))) - `(which-key-group-description-face ((,c :foreground ,err))) + `(which-key-group-description-face ((,c :foreground ,keyword))) `(which-key-highlighted-command-face ((,c :foreground ,warning :underline t))) `(which-key-key-face ((,c :inherit modus-themes-key-binding))) `(which-key-local-map-description-face ((,c :foreground ,fg-main))) @@ -3782,7 +3793,7 @@ FG and BG are the main colors." `(window-divider-last-pixel ((,c :foreground ,bg-inactive))) ;;;;; widget `(widget-button ((,c :inherit bold :foreground ,fg-link))) - `(widget-button-pressed ((,c :inherit widget-buton :foreground ,fg-link-visited))) + `(widget-button-pressed ((,c :inherit widget-button :foreground ,fg-link-visited))) `(widget-documentation ((,c :inherit font-lock-doc-face))) `(widget-field ((,c :background ,bg-inactive :foreground ,fg-main :extend nil))) `(widget-inactive ((,c :background ,bg-button-inactive :foreground ,fg-button-inactive))) diff --git a/code/elpa/modus-themes-20230320.449/modus-themes.info b/code/elpa/modus-themes-20230405.456/modus-themes.info similarity index 99% rename from code/elpa/modus-themes-20230320.449/modus-themes.info rename to code/elpa/modus-themes-20230405.456/modus-themes.info index 53a9b25..f1fff7d 100644 --- a/code/elpa/modus-themes-20230320.449/modus-themes.info +++ b/code/elpa/modus-themes-20230405.456/modus-themes.info @@ -3829,6 +3829,7 @@ have lots of extensions, so the “full support” may not be 100% true… • ivy-posframe • jira (org-jira) • jit-spell [Part of 4.2.0-dev] + • jinx [Part of 4.2.0-dev] • journalctl-mode • js2-mode • julia @@ -5233,8 +5234,8 @@ Contributions to code or documentation Stevenson, Mauro Aranda, Nacho Barrientos, Nicolas De Jaeghere, Paul David, Philip Kaludercic, Pierre Téchoueyres, Rudolf Adamkovič, Sergey Nichiporchik, Stephen Gildea, Shreyas Ragavan, - Stefan Kangas, Utkarsh Singh, Vincent Murphy, Xinglu Chen, Yuanchen - Xie, okamsn. + Stefan Kangas, Tomasz Hołubowicz, Utkarsh Singh, Vincent Murphy, + Xinglu Chen, Yuanchen Xie, okamsn. Ideas and user feedback Aaron Jensen, Adam Porter, Adam Spiers, Adrian Manea, Aleksei @@ -5262,8 +5263,8 @@ Ideas and user feedback Téchoueyres, Przemysław Kryger, Robert Hepple, Roman Rudakov, Russell Sim, Ryan Phillips, Rytis Paškauskas, Rudolf Adamkovič, Sam Kleinman, Samuel Culpepper, Saša Janiška, Shreyas Ragavan, Simon - Pugnet, Tassilo Horn, Thanos Apollo, Thibaut Verron, Thomas - Heartman, Togan Muftuoglu, Tony Zorman, Trey Merkley, Tomasz + Pugnet, Steve Downey, Tassilo Horn, Thanos Apollo, Thibaut Verron, + Thomas Heartman, Togan Muftuoglu, Tony Zorman, Trey Merkley, Tomasz Hołubowicz, Toon Claes, Uri Sharf, Utkarsh Singh, Vincent Foley, Zoltan Kiraly. As well as users: Ben, CsBigDataHub1, Emacs Contrib, Eugene, Fourchaux, Fredrik, Moesasji, Nick, Summer Emacs, @@ -5986,47 +5987,47 @@ Node: Custom hl-todo colors150333 Node: Add support for solaire-mode151858 Node: Face coverage154769 Node: Supported packages155221 -Node: Indirectly covered packages160645 -Node: Notes on individual packages161998 -Node: Note on calendarel weekday and weekend colors163098 -Node: Note on git-gutter in Doom Emacs164246 -Node: Note on php-mode multiline comments166590 -Node: Note on underlines in compilation buffers167343 -Node: Note on inline Latex in Org buffers168180 -Node: Note on dimmerel168790 -Node: Note on display-fill-column-indicator-mode170275 -Node: Note on highlight-parenthesesel171674 -Node: Note on mmm-modeel background colors177652 -Node: Note for prism179952 -Node: Note on company-mode overlay pop-up183120 -Ref: Note on company-mode overlay pop-up-Footnote-1183850 -Ref: Note on company-mode overlay pop-up-Footnote-2183917 -Node: Note on ERC escaped color sequences183972 -Ref: Note on ERC escaped color sequences-Footnote-1185400 -Node: Note on powerline or spaceline185510 -Node: Note on SHR colors185924 -Node: Note on SHR fonts186348 -Node: Note on Ement colors and fonts186987 -Node: Note on pdf-tools link hints188497 -Node: Note on the Notmuch logo190957 -Node: Note on goto-address-mode faces191495 -Node: Frequently Asked Questions192607 -Node: Is the contrast ratio about adjacent colors?193238 -Node: What does it mean to avoid exaggerations?194745 -Node: Why are colors mostly variants of blue magenta cyan?196595 -Node: What is the best setup for legibility?200901 -Node: Are these color schemes?203546 -Node: Port the Modus themes to other platforms?207228 -Node: Contributing210000 -Node: Sources of the themes210397 -Node: Issues you can help with211291 -Node: Patches require copyright assignment to the FSF212682 -Node: Acknowledgements214902 -Node: GNU Free Documentation License218856 -Node: Indices244220 -Node: Function index244399 -Node: Variable index245582 -Node: Concept index247481 +Node: Indirectly covered packages160677 +Node: Notes on individual packages162030 +Node: Note on calendarel weekday and weekend colors163130 +Node: Note on git-gutter in Doom Emacs164278 +Node: Note on php-mode multiline comments166622 +Node: Note on underlines in compilation buffers167375 +Node: Note on inline Latex in Org buffers168212 +Node: Note on dimmerel168822 +Node: Note on display-fill-column-indicator-mode170307 +Node: Note on highlight-parenthesesel171706 +Node: Note on mmm-modeel background colors177684 +Node: Note for prism179984 +Node: Note on company-mode overlay pop-up183152 +Ref: Note on company-mode overlay pop-up-Footnote-1183882 +Ref: Note on company-mode overlay pop-up-Footnote-2183949 +Node: Note on ERC escaped color sequences184004 +Ref: Note on ERC escaped color sequences-Footnote-1185432 +Node: Note on powerline or spaceline185542 +Node: Note on SHR colors185956 +Node: Note on SHR fonts186380 +Node: Note on Ement colors and fonts187019 +Node: Note on pdf-tools link hints188529 +Node: Note on the Notmuch logo190989 +Node: Note on goto-address-mode faces191527 +Node: Frequently Asked Questions192639 +Node: Is the contrast ratio about adjacent colors?193270 +Node: What does it mean to avoid exaggerations?194777 +Node: Why are colors mostly variants of blue magenta cyan?196627 +Node: What is the best setup for legibility?200933 +Node: Are these color schemes?203578 +Node: Port the Modus themes to other platforms?207260 +Node: Contributing210032 +Node: Sources of the themes210429 +Node: Issues you can help with211323 +Node: Patches require copyright assignment to the FSF212714 +Node: Acknowledgements214934 +Node: GNU Free Documentation License218922 +Node: Indices244286 +Node: Function index244465 +Node: Variable index245648 +Node: Concept index247547  End Tag Table diff --git a/code/elpa/modus-themes-20230320.449/modus-vivendi-deuteranopia-theme.el b/code/elpa/modus-themes-20230405.456/modus-vivendi-deuteranopia-theme.el similarity index 98% rename from code/elpa/modus-themes-20230320.449/modus-vivendi-deuteranopia-theme.el rename to code/elpa/modus-themes-20230405.456/modus-vivendi-deuteranopia-theme.el index 57241c5..861d7db 100644 --- a/code/elpa/modus-themes-20230320.449/modus-vivendi-deuteranopia-theme.el +++ b/code/elpa/modus-themes-20230405.456/modus-vivendi-deuteranopia-theme.el @@ -1,4 +1,4 @@ -;;; modus-vivendi-deuteranopia-theme.el --- Elegant, highly legible and customizable dark theme -*- lexical-binding:t -*- +;;; modus-vivendi-deuteranopia-theme.el --- Deuteranopia-optimized theme with a black background -*- lexical-binding:t -*- ;; Copyright (C) 2019-2023 Free Software Foundation, Inc. @@ -43,7 +43,7 @@ (require 'modus-themes)) (deftheme modus-vivendi-deuteranopia - "Elegant, highly legible and customizable dark theme. + "Deuteranopia-optimized theme with a black background. This variant is optimized for users with red-green color deficiency (deuteranopia). It conforms with the highest legibility standard for color contrast between background and diff --git a/code/elpa/modus-themes-20230320.449/modus-vivendi-theme.el b/code/elpa/modus-themes-20230405.456/modus-vivendi-theme.el similarity index 98% rename from code/elpa/modus-themes-20230320.449/modus-vivendi-theme.el rename to code/elpa/modus-themes-20230405.456/modus-vivendi-theme.el index 5012f8f..78a35aa 100644 --- a/code/elpa/modus-themes-20230320.449/modus-vivendi-theme.el +++ b/code/elpa/modus-themes-20230405.456/modus-vivendi-theme.el @@ -1,4 +1,4 @@ -;;; modus-vivendi-theme.el --- Elegant, highly legible and customizable dark theme -*- lexical-binding:t -*- +;;; modus-vivendi-theme.el --- Elegant, highly legible theme with a black background -*- lexical-binding:t -*- ;; Copyright (C) 2019-2023 Free Software Foundation, Inc. @@ -43,7 +43,7 @@ (require 'modus-themes)) (deftheme modus-vivendi - "Elegant, highly legible and customizable dark theme. + "Elegant, highly legible theme with a black background. Conforms with the highest legibility standard for color contrast between background and foreground in any given piece of text, which corresponds to a minimum contrast in relative luminance of diff --git a/code/elpa/modus-themes-20230320.449/modus-vivendi-tinted-theme.el b/code/elpa/modus-themes-20230405.456/modus-vivendi-tinted-theme.el similarity index 98% rename from code/elpa/modus-themes-20230320.449/modus-vivendi-tinted-theme.el rename to code/elpa/modus-themes-20230405.456/modus-vivendi-tinted-theme.el index 79e7fc9..3b2d134 100644 --- a/code/elpa/modus-themes-20230320.449/modus-vivendi-tinted-theme.el +++ b/code/elpa/modus-themes-20230405.456/modus-vivendi-tinted-theme.el @@ -1,4 +1,4 @@ -;;; modus-vivendi-tinted-theme.el --- Elegant, highly legible and customizable dark theme -*- lexical-binding:t -*- +;;; modus-vivendi-tinted-theme.el --- Elegant, highly legible theme with a night sky background -*- lexical-binding:t -*- ;; Copyright (C) 2019-2023 Free Software Foundation, Inc. @@ -43,7 +43,7 @@ (require 'modus-themes)) (deftheme modus-vivendi-tinted - "Elegant, highly legible and customizable dark theme. + "Elegant, highly legible theme with a night sky background. Conforms with the highest legibility standard for color contrast between background and foreground in any given piece of text, which corresponds to a minimum contrast in relative luminance of diff --git a/code/elpa/yaml-mode-20221022.920/yaml-mode-autoloads.el b/code/elpa/yaml-mode-20230329.723/yaml-mode-autoloads.el similarity index 100% rename from code/elpa/yaml-mode-20221022.920/yaml-mode-autoloads.el rename to code/elpa/yaml-mode-20230329.723/yaml-mode-autoloads.el diff --git a/code/elpa/yaml-mode-20221022.920/yaml-mode-pkg.el b/code/elpa/yaml-mode-20230329.723/yaml-mode-pkg.el similarity index 58% rename from code/elpa/yaml-mode-20221022.920/yaml-mode-pkg.el rename to code/elpa/yaml-mode-20230329.723/yaml-mode-pkg.el index 82e3380..714ec3e 100644 --- a/code/elpa/yaml-mode-20221022.920/yaml-mode-pkg.el +++ b/code/elpa/yaml-mode-20230329.723/yaml-mode-pkg.el @@ -1,2 +1,2 @@ ;;; Generated package description from yaml-mode.el -*- no-byte-compile: t -*- -(define-package "yaml-mode" "20221022.920" "Major mode for editing YAML files" '((emacs "24.1")) :commit "141b85f9e01589e67955f3785a83b72b42109357" :authors '(("Yoshiki Kurihara" . "clouder@gmail.com") ("Marshall T. Vandegrift" . "llasram@gmail.com")) :maintainer '("Vasilij Schneidermann" . "mail@vasilij.de") :keywords '("data" "yaml") :url "https://github.com/yoshiki/yaml-mode") +(define-package "yaml-mode" "20230329.723" "Major mode for editing YAML files" '((emacs "24.1")) :commit "b153150e0e77b4ec462d741cdb16956c6ae270d6" :authors '(("Yoshiki Kurihara" . "clouder@gmail.com") ("Marshall T. Vandegrift" . "llasram@gmail.com")) :maintainer '("Vasilij Schneidermann" . "mail@vasilij.de") :keywords '("data" "yaml") :url "https://github.com/yoshiki/yaml-mode") diff --git a/code/elpa/yaml-mode-20221022.920/yaml-mode.el b/code/elpa/yaml-mode-20230329.723/yaml-mode.el similarity index 98% rename from code/elpa/yaml-mode-20221022.920/yaml-mode.el rename to code/elpa/yaml-mode-20230329.723/yaml-mode.el index 7afceeb..15c0ddc 100644 --- a/code/elpa/yaml-mode-20221022.920/yaml-mode.el +++ b/code/elpa/yaml-mode-20230329.723/yaml-mode.el @@ -6,8 +6,8 @@ ;; Marshall T. Vandegrift ;; Maintainer: Vasilij Schneidermann ;; URL: https://github.com/yoshiki/yaml-mode -;; Package-Version: 20221022.920 -;; Package-Commit: 141b85f9e01589e67955f3785a83b72b42109357 +;; Package-Version: 20230329.723 +;; Package-Commit: b153150e0e77b4ec462d741cdb16956c6ae270d6 ;; Package-Requires: ((emacs "24.1")) ;; Keywords: data yaml ;; Version: 0.0.15 @@ -370,11 +370,9 @@ back-dent the line by `yaml-indent-offset' spaces. On reaching column (let ((ci (current-indentation)) (need (yaml-compute-indentation))) (save-excursion - (beginning-of-line) - (delete-horizontal-space) (if (and (equal last-command this-command) (/= ci 0)) - (indent-to (* (/ (- ci 1) yaml-indent-offset) yaml-indent-offset)) - (indent-to need))) + (indent-line-to (* (/ (- ci 1) yaml-indent-offset) yaml-indent-offset)) + (indent-line-to need))) (if (< (current-column) (current-indentation)) (forward-to-indentation 0)))) diff --git a/org/elpa/all-the-icons-20220929.2303/all-the-icons-autoloads.el b/org/elpa/all-the-icons-20230316.1906/all-the-icons-autoloads.el similarity index 100% rename from org/elpa/all-the-icons-20220929.2303/all-the-icons-autoloads.el rename to org/elpa/all-the-icons-20230316.1906/all-the-icons-autoloads.el diff --git a/org/elpa/all-the-icons-20220929.2303/all-the-icons-faces.el b/org/elpa/all-the-icons-20230316.1906/all-the-icons-faces.el similarity index 100% rename from org/elpa/all-the-icons-20220929.2303/all-the-icons-faces.el rename to org/elpa/all-the-icons-20230316.1906/all-the-icons-faces.el diff --git a/org/elpa/all-the-icons-20220929.2303/all-the-icons-pkg.el b/org/elpa/all-the-icons-20230316.1906/all-the-icons-pkg.el similarity index 70% rename from org/elpa/all-the-icons-20220929.2303/all-the-icons-pkg.el rename to org/elpa/all-the-icons-20230316.1906/all-the-icons-pkg.el index 62f4f1c..7429a4f 100644 --- a/org/elpa/all-the-icons-20220929.2303/all-the-icons-pkg.el +++ b/org/elpa/all-the-icons-20230316.1906/all-the-icons-pkg.el @@ -1,6 +1,6 @@ -(define-package "all-the-icons" "20220929.2303" "A library for inserting Developer icons" +(define-package "all-the-icons" "20230316.1906" "A library for inserting Developer icons" '((emacs "24.3")) - :commit "51bf77da1ebc3c199dfc11f54c0dce67559f5f40" :authors + :commit "d922aff57ac8308d3ed067f9151cc76d342855f2" :authors '(("Dominic Charlesworth" . "dgc336@gmail.com")) :maintainer '("Dominic Charlesworth" . "dgc336@gmail.com") diff --git a/org/elpa/all-the-icons-20220929.2303/all-the-icons.el b/org/elpa/all-the-icons-20230316.1906/all-the-icons.el similarity index 94% rename from org/elpa/all-the-icons-20220929.2303/all-the-icons.el rename to org/elpa/all-the-icons-20230316.1906/all-the-icons.el index f87483a..e6f5cee 100644 --- a/org/elpa/all-the-icons-20220929.2303/all-the-icons.el +++ b/org/elpa/all-the-icons-20230316.1906/all-the-icons.el @@ -247,6 +247,7 @@ ("sass" all-the-icons-alltheicon "sass" :face all-the-icons-dpink) ("less" all-the-icons-alltheicon "less" :height 0.8 :face all-the-icons-dyellow) ("postcss" all-the-icons-fileicon "postcss" :face all-the-icons-dred) + ("pcss" all-the-icons-fileicon "postcss" :face all-the-icons-dred) ("sss" all-the-icons-fileicon "postcss" :face all-the-icons-dred) ("styl" all-the-icons-alltheicon "stylus" :face all-the-icons-lgreen) ("csv" all-the-icons-octicon "graph" :v-adjust 0.0 :face all-the-icons-dblue) @@ -277,6 +278,7 @@ ("react" all-the-icons-alltheicon "react" :height 1.1 :face all-the-icons-lblue) ("ts" all-the-icons-fileicon "typescript" :height 1.0 :v-adjust -0.1 :face all-the-icons-blue-alt) ("js" all-the-icons-alltheicon "javascript" :height 1.0 :v-adjust 0.0 :face all-the-icons-yellow) + ("mjs" all-the-icons-alltheicon "javascript" :height 1.0 :v-adjust 0.0 :face all-the-icons-yellow) ("es" all-the-icons-alltheicon "javascript" :height 1.0 :v-adjust 0.0 :face all-the-icons-yellow) ("jsx" all-the-icons-fileicon "jsx-2" :height 1.0 :v-adjust -0.1 :face all-the-icons-cyan-alt) ("tsx" all-the-icons-fileicon "tsx" :height 1.0 :v-adjust -0.1 :face all-the-icons-cyan-alt) @@ -380,12 +382,13 @@ ("mov" all-the-icons-faicon "film" :face all-the-icons-blue) ("mp4" all-the-icons-faicon "film" :face all-the-icons-blue) ("ogv" all-the-icons-faicon "film" :face all-the-icons-dblue) - ("mpg" all-the-icons-faicon "film" :face all-the-icons-blue) - ("mpeg" all-the-icons-faicon "film" :face all-the-icons-blue) - ("flv" all-the-icons-faicon "film" :face all-the-icons-blue) - ("ogv" all-the-icons-faicon "film" :face all-the-icons-dblue) + ("mpg" all-the-icons-faicon "film" :face all-the-icons-blue) + ("mpeg" all-the-icons-faicon "film" :face all-the-icons-blue) + ("flv" all-the-icons-faicon "film" :face all-the-icons-blue) + ("ogv" all-the-icons-faicon "film" :face all-the-icons-dblue) ("mkv" all-the-icons-faicon "film" :face all-the-icons-blue) ("webm" all-the-icons-faicon "film" :face all-the-icons-blue) + ("dav" all-the-icons-faicon "film" :face all-the-icons-blue) ;; Fonts ("ttf" all-the-icons-fileicon "font" :v-adjust 0.0 :face all-the-icons-dcyan) ("woff" all-the-icons-fileicon "font" :v-adjust 0.0 :face all-the-icons-cyan) @@ -397,6 +400,8 @@ ("doc" all-the-icons-fileicon "word" :face all-the-icons-blue) ("docx" all-the-icons-fileicon "word" :face all-the-icons-blue) ("docm" all-the-icons-fileicon "word" :face all-the-icons-blue) + ("eml" all-the-icons-faicon "envelope" :face all-the-icons-blue) + ("msg" all-the-icons-faicon "envelope" :face all-the-icons-blue) ("texi" all-the-icons-fileicon "tex" :face all-the-icons-lred) ("tex" all-the-icons-fileicon "tex" :face all-the-icons-lred) ("md" all-the-icons-octicon "markdown" :v-adjust 0.0 :face all-the-icons-lblue) @@ -582,7 +587,9 @@ for performance sake.") (slime-repl-mode all-the-icons-fileicon "clisp" :v-adjust -0.1 :face all-the-icons-orange) (org-mode all-the-icons-fileicon "org" :v-adjust 0.0 :face all-the-icons-lgreen) (typescript-mode all-the-icons-fileicon "typescript" :v-adjust -0.1 :face all-the-icons-blue-alt) + (typescript-ts-mode all-the-icons-fileicon "typescript" :v-adjust -0.1 :face all-the-icons-blue-alt) (typescript-tsx-mode all-the-icons-fileicon "tsx" :v-adjust -0.1 :face all-the-icons-cyan-alt) + (tsx-ts-mode all-the-icons-fileicon "tsx" :v-adjust -0.1 :face all-the-icons-cyan-alt) (js-mode all-the-icons-alltheicon "javascript" :v-adjust -0.1 :face all-the-icons-yellow) (js-jsx-mode all-the-icons-alltheicon "javascript" :v-adjust -0.1 :face all-the-icons-yellow) (js2-mode all-the-icons-alltheicon "javascript" :v-adjust -0.1 :face all-the-icons-yellow) @@ -612,6 +619,10 @@ for performance sake.") (mu4e-main-mode all-the-icons-octicon "mail" :v-adjust 0.0) (mu4e-view-mode all-the-icons-octicon "mail-read" :v-adjust 0.0) (sieve-mode all-the-icons-octicon "mail" :v-adjust 0.0) + (gnus-group-mode all-the-icons-octicon "mail" :v-adjust 0.0) + (gnus-summary-mode all-the-icons-octicon "mail" :v-adjust 0.0) + (gnus-article-mode all-the-icons-octicon "mail-read" :v-adjust 0.0) + (message-mode all-the-icons-octicon "pencil" :v-adjust 0.0) (package-menu-mode all-the-icons-faicon "archive" :height 1.0 :v-adjust 0.0 :face all-the-icons-silver) (paradox-menu-mode all-the-icons-faicon "archive" :height 1.0 :v-adjust 0.0 :face all-the-icons-silver) (Custom-mode all-the-icons-octicon "settings" :v-adjust -0.1) @@ -624,6 +635,7 @@ for performance sake.") (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) + (ruby-ts-mode all-the-icons-alltheicon "ruby-alt" :face all-the-icons-lred) (inf-ruby-mode all-the-icons-alltheicon "ruby-alt" :face all-the-icons-red) (projectile-rails-compilation-mode all-the-icons-alltheicon "ruby-alt" :face all-the-icons-red) (rspec-compilation-mode all-the-icons-alltheicon "ruby-alt" :face all-the-icons-red) @@ -635,19 +647,25 @@ for performance sake.") (apache-mode all-the-icons-alltheicon "apache" :height 0.9 :face all-the-icons-dgreen) (makefile-mode all-the-icons-fileicon "gnu" :face all-the-icons-dorange) (cmake-mode all-the-icons-fileicon "cmake" :face all-the-icons-red) + (cmake-ts-mode all-the-icons-fileicon "cmake" :face all-the-icons-red) (dockerfile-mode all-the-icons-fileicon "dockerfile" :face all-the-icons-blue) + (dockerfile-ts-mode all-the-icons-fileicon "dockerfile" :face all-the-icons-blue) (docker-compose-mode all-the-icons-fileicon "dockerfile" :face all-the-icons-lblue) (nxml-mode all-the-icons-faicon "file-code-o" :height 0.95 :face all-the-icons-lorange) (json-mode all-the-icons-octicon "settings" :face all-the-icons-yellow) + (json-ts-mode all-the-icons-octicon "settings" :face all-the-icons-yellow) (jsonian-mode all-the-icons-octicon "settings" :face all-the-icons-yellow) (yaml-mode all-the-icons-octicon "settings" :v-adjust 0.0 :face all-the-icons-dyellow) + (yaml-ts-mode all-the-icons-octicon "settings" :v-adjust 0.0 :face all-the-icons-dyellow) (elisp-byte-code-mode all-the-icons-octicon "file-binary" :v-adjust 0.0 :face all-the-icons-dsilver) (archive-mode all-the-icons-octicon "file-zip" :v-adjust 0.0 :face all-the-icons-lmaroon) (elm-mode all-the-icons-fileicon "elm" :face all-the-icons-blue) (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) + (java-ts-mode all-the-icons-alltheicon "java" :height 1.0 :face all-the-icons-purple) (go-mode all-the-icons-fileicon "go" :height 1.0 :face all-the-icons-blue) + (go-ts-mode all-the-icons-fileicon "go" :height 1.0 :face all-the-icons-blue) (go-dot-mod-mode all-the-icons-fileicon "config-go" :height 1.0 :face all-the-icons-blue-alt) (go-dot-work-mode all-the-icons-fileicon "config-go" :height 1.0 :face all-the-icons-blue-alt) (graphql-mode all-the-icons-fileicon "graphql" :face all-the-icons-dpink) @@ -658,22 +676,29 @@ for performance sake.") (php-mode all-the-icons-fileicon "php" :face all-the-icons-lsilver) (prolog-mode all-the-icons-alltheicon "prolog" :height 1.1 :face all-the-icons-lmaroon) (python-mode all-the-icons-alltheicon "python" :height 1.0 :face all-the-icons-dblue) + (python-ts-mode all-the-icons-alltheicon "python" :height 1.0 :face all-the-icons-dblue) (inferior-python-mode all-the-icons-alltheicon "python" :height 1.0 :face all-the-icons-dblue) (racket-mode all-the-icons-fileicon "racket" :height 1.2 :face all-the-icons-red) (rust-mode all-the-icons-alltheicon "rust" :height 1.2 :face all-the-icons-maroon) + (rustic-mode all-the-icons-alltheicon "rust" :height 1.2 :face all-the-icons-maroon) + (rust-ts-mode all-the-icons-alltheicon "rust" :height 1.2 :face all-the-icons-maroon) (scala-mode all-the-icons-alltheicon "scala" :face all-the-icons-red) (scheme-mode all-the-icons-fileicon "scheme" :height 1.2 :face all-the-icons-red) (swift-mode all-the-icons-alltheicon "swift" :height 1.0 :v-adjust -0.1 :face all-the-icons-green) (svelte-mode all-the-icons-fileicon "svelte" :v-adjust 0.0 :face all-the-icons-red) (c-mode all-the-icons-alltheicon "c-line" :face all-the-icons-blue) + (c-ts-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) + (c++-ts-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) + (csharp-ts-mode all-the-icons-alltheicon "csharp-line" :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) (css-mode all-the-icons-alltheicon "css3" :face all-the-icons-yellow) + (css-ts-mode all-the-icons-alltheicon "css3" :face all-the-icons-yellow) (scss-mode all-the-icons-alltheicon "sass" :face all-the-icons-pink) (sass-mode all-the-icons-alltheicon "sass" :face all-the-icons-dpink) (less-css-mode all-the-icons-alltheicon "less" :height 0.8 :face all-the-icons-dyellow) @@ -684,6 +709,7 @@ for performance sake.") (literate-haskell-mode all-the-icons-alltheicon "haskell" :height 1.0 :face all-the-icons-red) (haml-mode all-the-icons-fileicon "haml" :face all-the-icons-lyellow) (html-mode all-the-icons-alltheicon "html5" :face all-the-icons-orange) + (html-ts-mode all-the-icons-alltheicon "html5" :face all-the-icons-orange) (rhtml-mode all-the-icons-alltheicon "html5" :face all-the-icons-lred) (mustache-mode all-the-icons-fileicon "moustache" :face all-the-icons-green) (slim-mode all-the-icons-octicon "dashboard" :v-adjust 0.0 :face all-the-icons-yellow) @@ -703,6 +729,7 @@ for performance sake.") (vhdl-mode all-the-icons-fileicon "vhdl" :face all-the-icons-blue) (haskell-cabal-mode all-the-icons-fileicon "cabal" :face all-the-icons-lblue) (kotlin-mode all-the-icons-fileicon "kotlin" :face all-the-icons-orange) + (kotlin-ts-mode all-the-icons-fileicon "kotlin" :face all-the-icons-orange) (nim-mode all-the-icons-fileicon "nimrod" :face all-the-icons-yellow) (sql-mode all-the-icons-octicon "database" :face all-the-icons-silver) (lua-mode all-the-icons-fileicon "lua" :face all-the-icons-dblue) @@ -724,8 +751,15 @@ for performance sake.") (zig-mode all-the-icons-fileicon "zig" :face all-the-icons-orange) (odin-mode all-the-icons-fileicon "odin" :height 1.1 :face all-the-icons-lblue) (pdf-view-mode all-the-icons-octicon "file-pdf" :v-adjust 0.0 :face all-the-icons-dred) + (spacemacs-buffer-mode all-the-icons-fileicon "elisp" :height 1.0 :v-adjust -0.1 :face all-the-icons-purple) (elfeed-search-mode all-the-icons-faicon "rss-square" :face all-the-icons-orange) (elfeed-show-mode all-the-icons-faicon "rss" :face all-the-icons-orange) + (emms-browser-mode all-the-icons-faicon "music" :face all-the-icons-silver) + (emms-lyrics-mode all-the-icons-faicon "music" :face all-the-icons-silver) + (emms-show-all-mode all-the-icons-faicon "music" :face all-the-icons-silver) + (emms-metaplaylist-mode all-the-icons-faicon "music" :face all-the-icons-silver) + (emms-tag-editor-mode all-the-icons-faicon "music" :face all-the-icons-silver) + (emms-playlist-mode all-the-icons-faicon "music" :face all-the-icons-silver) (lilypond-mode all-the-icons-faicon "music" :face all-the-icons-green) (magik-session-mode all-the-icons-alltheicon "terminal" :face all-the-icons-blue) (magik-cb-mode all-the-icons-faicon "book" :face all-the-icons-blue) @@ -916,20 +950,21 @@ inserting functions. Note: You want chevron, please use `all-the-icons-icon-for-dir-with-chevron'." (let* ((dirname (file-name-base (directory-file-name dir))) - (path (expand-file-name dir)) (icon (all-the-icons-match-to-alist dirname all-the-icons-dir-icon-alist)) (args (cdr icon))) (when arg-overrides (setq args (append `(,(car args)) arg-overrides (cdr args)))) - (cond - ((file-remote-p path) - (apply #'all-the-icons-octicon "terminal" (cdr args))) - ((file-symlink-p path) - (apply #'all-the-icons-octicon "file-symlink-directory" (cdr args))) - ((all-the-icons-dir-is-submodule path) - (apply #'all-the-icons-octicon "file-submodule" (cdr args))) - ((file-exists-p (format "%s/.git" path)) - (apply #'all-the-icons-octicon "repo" (cdr args))) - (t (apply (car icon) args))))) + (if (file-remote-p dir) ;; don't call expand-file-name on a remote dir as this can make emacs hang + (apply #'all-the-icons-octicon "terminal" (cdr args)) + (let + ((path (expand-file-name dir))) + (cond + ((file-symlink-p path) + (apply #'all-the-icons-octicon "file-symlink-directory" (cdr args))) + ((all-the-icons-dir-is-submodule path) + (apply #'all-the-icons-octicon "file-submodule" (cdr args))) + ((file-exists-p (format "%s/.git" path)) + (apply #'all-the-icons-octicon "repo" (cdr args))) + (t (apply (car icon) args))))))) ;;;###autoload (defun all-the-icons-icon-for-file (file &rest arg-overrides) @@ -1004,7 +1039,7 @@ inserting functions." (defun all-the-icons-icon-family-for-file (file) "Get the icons font family for FILE." (let* ((ext (file-name-extension file)) - (icon (or (all-the-icons-match-to-alist file all-the-icons-regexp-icon-alist) + (icon (or (all-the-icons-match-to-alist file all-the-icons-regexp-icon-alist) (and ext (cdr (assoc (downcase ext) all-the-icons-extension-icon-alist))) @@ -1164,7 +1199,7 @@ pause for DURATION seconds between printing each character." (mapc (lambda (it) (insert (format "%s - %s\n" (funcall insert-f (car it) :height height) (car it))) - (when duration (sit-for duration 0))) + (when duration (sit-for duration))) data))) (defmacro all-the-icons-define-icon (name alist family &optional font-name) diff --git a/org/elpa/all-the-icons-20220929.2303/data/data-alltheicons.el b/org/elpa/all-the-icons-20230316.1906/data/data-alltheicons.el similarity index 100% rename from org/elpa/all-the-icons-20220929.2303/data/data-alltheicons.el rename to org/elpa/all-the-icons-20230316.1906/data/data-alltheicons.el diff --git a/org/elpa/all-the-icons-20220929.2303/data/data-faicons.el b/org/elpa/all-the-icons-20230316.1906/data/data-faicons.el similarity index 100% rename from org/elpa/all-the-icons-20220929.2303/data/data-faicons.el rename to org/elpa/all-the-icons-20230316.1906/data/data-faicons.el diff --git a/org/elpa/all-the-icons-20220929.2303/data/data-fileicons.el b/org/elpa/all-the-icons-20230316.1906/data/data-fileicons.el similarity index 100% rename from org/elpa/all-the-icons-20220929.2303/data/data-fileicons.el rename to org/elpa/all-the-icons-20230316.1906/data/data-fileicons.el diff --git a/org/elpa/all-the-icons-20220929.2303/data/data-material.el b/org/elpa/all-the-icons-20230316.1906/data/data-material.el similarity index 100% rename from org/elpa/all-the-icons-20220929.2303/data/data-material.el rename to org/elpa/all-the-icons-20230316.1906/data/data-material.el diff --git a/org/elpa/all-the-icons-20220929.2303/data/data-octicons.el b/org/elpa/all-the-icons-20230316.1906/data/data-octicons.el similarity index 100% rename from org/elpa/all-the-icons-20220929.2303/data/data-octicons.el rename to org/elpa/all-the-icons-20230316.1906/data/data-octicons.el diff --git a/org/elpa/all-the-icons-20220929.2303/data/data-weathericons.el b/org/elpa/all-the-icons-20230316.1906/data/data-weathericons.el similarity index 100% rename from org/elpa/all-the-icons-20220929.2303/data/data-weathericons.el rename to org/elpa/all-the-icons-20230316.1906/data/data-weathericons.el diff --git a/org/elpa/archives/melpa/archive-contents b/org/elpa/archives/melpa/archive-contents index b522fa9..b42afe9 100644 --- a/org/elpa/archives/melpa/archive-contents +++ b/org/elpa/archives/melpa/archive-contents @@ -9,12 +9,12 @@ (@ . [(20181225 1438) ((emacs (24 3))) "multiple-inheritance prototype-based objects DSL" tar ((:commit . "0a6189f8be42dbbc5d9358cbd447d471236135a2") (:authors ("Christopher Wellons" . "wellons@nullprogram.com")) (:maintainer "Christopher Wellons" . "wellons@nullprogram.com") (:url . "https://github.com/skeeto/at-el"))]) (a . [(20210929 1510) ((emacs (25))) "Associative data structure functions" single ((:commit . "9ad2d18252b729174fe22ed0b2b7670c88f60c31") (:authors ("Arne Brasseur" . "arne@arnebrasseur.net")) (:maintainer "Arne Brasseur" . "arne@arnebrasseur.net") (:keywords "lisp") (:url . "https://github.com/plexus/a.el"))]) (aa-edit-mode . [(20170119 320) ((emacs (24 3)) (navi2ch (2 0 0))) "Major mode for editing AA(S_JIS Art) and .mlt file" single ((:commit . "1dd801225b7ad3c23ad09698f5e77f0df7012a65") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "wp" "text" "shiftjis" "mlt" "yaruo"))]) - (aas . [(20220930 52) ((emacs (26 3))) "Snippet expansions mid-typing" single ((:commit . "e92b5cffa4e87c221c24f3e72ae33959e1ec2b68") (:authors ("Yoav Marco" . "yoavm448@gmail.com")) (:maintainer "Yoav Marco" . "yoavm448@gmail.com") (:keywords "abbrev" "tools") (:url . "https://github.com/ymarco/auto-activating-snippets"))]) + (aas . [(20230303 2214) ((emacs (26 3))) "Snippet expansions mid-typing" single ((:commit . "ddc2b7a58a2234477006af348b30e970f73bc2c1") (:authors ("Yoav Marco" . "yoavm448@gmail.com")) (:maintainer "Yoav Marco" . "yoavm448@gmail.com") (:keywords "abbrev" "tools") (:url . "https://github.com/ymarco/auto-activating-snippets"))]) (abc-mode . [(20220713 1359) nil "Major mode for editing abc music files" single ((:commit . "45193b67508861cf77da7e76b71711855c002caa") (:authors ("Matthew K. Junker" . "junker@alum.mit.edu")) (:maintainer "Matthew K. Junker" . "junker@alum.mit.edu") (:keywords "local" "docs"))]) (abgaben . [(20171119 646) ((pdf-tools (0 80)) (f (0 19 0)) (s (1 11 0))) "review and correct assignments received by mail" single ((:commit . "966bfcfdd3b2e288576ffe363d676ad282902090") (:authors ("Arne Köhn" . "arne@chark.eu")) (:maintainer "Arne Köhn" . "arne@chark.eu") (:keywords "mail" "outlines" "convenience") (:url . "http://arne.chark.eu/"))]) (abl-mode . [(20210923 950) nil "Python TDD minor mode" single ((:commit . "7f692cf9bb263b26fda51bb56a58f6ac61febe3b") (:authors ("Ulas Tuerkmen ")) (:maintainer "Ulas Tuerkmen ") (:url . "http://github.com/afroisalreadyinu/abl-mode"))]) - (abridge-diff . [(20220716 1641) ((emacs (26 1))) "Abridge long line-based diff hunks, including in magit" single ((:commit . "994bd47a8de5200018450ea19a610782eff3fafc") (:authors ("J.D. Smith ")) (:maintainer "J.D. Smith ") (:keywords "magit" "diffs" "tools") (:url . "https://github.com/jdtsmith/abridge-diff"))]) - (abs-mode . [(20220316 921) ((emacs (26 1)) (erlang (2 8)) (maude-mode (0 3)) (flymake (1 0))) "Major mode for the modeling language Abs" single ((:commit . "d860ddbbd7cb93c7a77980c78c1a2a7634ef01e1") (:authors ("Rudi Schlatte" . "rudi@constantly.at")) (:maintainer "Rudi Schlatte" . "rudi@constantly.at") (:keywords "languages") (:url . "https://github.com/abstools/abs-mode"))]) + (abridge-diff . [(20230307 2159) ((emacs (26 1))) "Abridge long line-based diff hunks, including in magit" single ((:commit . "31e0ccaa9d0bd4ad257f5de25cc3c0b3395fafa1") (:authors ("J.D. Smith ")) (:maintainer "J.D. Smith ") (:keywords "magit" "diffs" "tools") (:url . "https://github.com/jdtsmith/abridge-diff"))]) + (abs-mode . [(20230402 1422) ((emacs (26 1)) (erlang (2 8)) (maude-mode (0 3)) (flymake (1 0)) (yasnippet (0 14 0))) "Major mode for the modeling language Abs" tar ((:commit . "bfeeb70964ee03f7d29ff44959951c713318dee5") (:authors ("Rudi Schlatte" . "rudi@constantly.at")) (:maintainer "Rudi Schlatte" . "rudi@constantly.at") (:keywords "languages") (:url . "https://github.com/abstools/abs-mode"))]) (abyss-theme . [(20170808 1345) ((emacs (24))) "A dark theme with contrasting colours." single ((:commit . "18791c6e8d9cc2b4815c9f08627a2e94fc0eeb14") (:authors ("Matt Russell" . "matt@mgrbyte.co.uk")) (:maintainer "Matt Russell" . "matt@mgrbyte.co.uk") (:keywords "theme" "dark" "contrasting colours") (:url . "https://github.com/mgrbyte/emacs-abyss-theme"))]) (ac-alchemist . [(20150908 656) ((auto-complete (1 5 0)) (alchemist (1 5 0)) (cl-lib (0 5))) "auto-complete source for alchemist" single ((:commit . "b1891c3d41aed83f61d78a609ea97be5cc2758d9") (:authors ("Syohei YOSHIDA" . "syohex@gmail.com")) (:maintainer "Syohei YOSHIDA" . "syohex@gmail.com") (:url . "https://github.com/syohex/emacs-ac-alchemist"))]) (ac-c-headers . [(20200816 1007) ((auto-complete (1 3 1))) "auto-complete source for C headers" single ((:commit . "67e1e86a48c9bed57bc7ce5ce2553ad203f5752e") (:authors ("zk_phi")) (:maintainer "zk_phi") (:url . "http://zk-phi.gitub.io/"))]) @@ -40,7 +40,7 @@ (ac-mozc . [(20150227 1619) ((cl-lib (0 5)) (auto-complete (1 4)) (mozc (0))) "auto-complete sources for Japanese input using Mozc" single ((:commit . "4c6c8be4701010d9362184437c0f783e0335c631") (:authors ("igjit" . "igjit1@gmail.com")) (:maintainer "igjit" . "igjit1@gmail.com") (:url . "https://github.com/igjit/ac-mozc"))]) (ac-octave . [(20180406 334) ((auto-complete (1 4 0))) "An auto-complete source for Octave" single ((:commit . "fe0f931f2024f43de3c4fff4b1ace672413adeae") (:authors ("coldnew" . "coldnew.tw@gmail.com")) (:maintainer "coldnew" . "coldnew.tw@gmail.com") (:keywords "octave" "auto-complete" "completion") (:url . "https://github.com/coldnew/ac-octave"))]) (ac-php . [(20210820 1000) ((ac-php-core (2 0)) (auto-complete (1 4 0)) (yasnippet (0 8 0))) "Auto Completion source for PHP." single ((:commit . "e29075f810af73f6bf7803eebf15d96bffee7154") (:authors ("jim" . "xcwenn@qq.com")) (:maintainer "jim") (:keywords "completion" "convenience" "intellisense") (:url . "https://github.com/xcwen/ac-php"))]) - (ac-php-core . [(20220701 253) ((emacs (24 4)) (dash (1)) (php-mode (1)) (s (1)) (f (0 17 0)) (popup (0 5 0)) (xcscope (1 0))) "The core library of the ac-php" tar ((:commit . "dc563f4b1efeac8ae75f217532f4c99b4ba417de") (:authors ("jim" . "xcwenn@qq.com") ("Serghei Iakovlev" . "sadhooklay@gmail.com")) (:maintainer "jim") (:keywords "completion" "convenience" "intellisense") (:url . "https://github.com/xcwen/ac-php"))]) + (ac-php-core . [(20230224 1507) ((emacs (24 4)) (dash (1)) (php-mode (1)) (s (1)) (f (0 17 0)) (popup (0 5 0)) (xcscope (1 0))) "The core library of the ac-php" tar ((:commit . "35eeaa3aaf1a38b183783dc693012242c7dd2053") (:authors ("jim" . "xcwenn@qq.com") ("Serghei Iakovlev" . "sadhooklay@gmail.com")) (:maintainer "jim") (:keywords "completion" "convenience" "intellisense") (:url . "https://github.com/xcwen/ac-php"))]) (ac-racer . [(20170114 809) ((emacs (24 3)) (auto-complete (1 5 0)) (racer (0 0 2))) "auto-complete source of racer" single ((:commit . "4408c2d652dec0432e20c05e001db8222d778c6b") (:authors ("Syohei YOSHIDA" . "syohex@gmail.com")) (:maintainer "Syohei YOSHIDA" . "syohex@gmail.com") (:url . "https://github.com/syohex/emacs-ac-racer"))]) (ac-rtags . [(20191222 920) ((auto-complete (1 4 0)) (rtags (2 10))) "auto-complete back-end for RTags" single ((:commit . "595055b5316a7c92ba1d638f324f98842a0f41a5") (:authors ("Jan Erik Hanssen" . "jhanssen@gmail.com") ("Anders Bakken" . "agbakken@gmail.com")) (:maintainer "Jan Erik Hanssen" . "jhanssen@gmail.com") (:url . "https://github.com/Andersbakken/rtags"))]) (ac-skk . [(20141230 119) ((auto-complete (1 3 1)) (ddskk (16 0 50)) (tinysegmenter (0)) (cl-lib (0 5))) "auto-complete-mode source for DDSKK a.k.a Japanese input method" single ((:commit . "d25a265930430d080329789fb253d786c01dfa24") (:authors ("lugecy ")) (:maintainer "myuhe") (:keywords "convenience" "auto-complete") (:url . "https://github.com/myuhe/ac-skk.el"))]) @@ -66,13 +66,13 @@ (activity-watch-mode . [(20220111 1121) ((emacs (25)) (request (0)) (json (0)) (cl-lib (0))) "Automatic time tracking extension." single ((:commit . "789ec3425623e43a29755e8daaa02305df8da8ed") (:authors ("Gabor Torok , Alan Hamlett" . "alan@wakatime.com")) (:maintainer "Paul d'Hubert" . "paul.dhubert@ya.ru") (:keywords "calendar" "comm") (:url . "https://github.com/pauldub/activity-watch-mode"))]) (adafruit-wisdom . [(20200217 306) ((emacs (25 1)) (request (0 3 1))) "Get/display adafruit.com quotes" single ((:commit . "c4ae0db35d0be94f0e9c50977758224d7e00234a") (:authors ("Neil Okamoto" . "neil.okamoto+melpa@gmail.com")) (:maintainer "Neil Okamoto" . "neil.okamoto+melpa@gmail.com") (:keywords "games") (:url . "https://github.com/gonewest818/adafruit-wisdom.el"))]) (add-hooks . [(20171217 123) nil "Functions for setting multiple hooks" single ((:commit . "1845137703461fc44bd77cf24014ba58f19c369d") (:authors ("Nick McCurdy" . "nick@nickmccurdy.com")) (:maintainer "Nick McCurdy" . "nick@nickmccurdy.com") (:keywords "lisp") (:url . "https://github.com/nickmccurdy/add-hooks"))]) - (add-node-modules-path . [(20220315 340) ((s (1 12 0))) "Add node_modules to your exec-path" single ((:commit . "63f047fd84b825876152743f66de7ee6f9ed203b") (:authors ("Neri Marschik" . "marschik_neri@cyberagent.co.jp")) (:maintainer "Neri Marschik" . "marschik_neri@cyberagent.co.jp") (:keywords "javascript" "node" "node_modules" "eslint") (:url . "https://github.com/codesuki/add-node-modules-path"))]) + (add-node-modules-path . [(20230307 655) ((s (1 12 0))) "Add node_modules to your exec-path" single ((:commit . "841e93dfed50448da66c89a977c9182bb18796a1") (:authors ("Neri Marschik" . "marschik_neri@cyberagent.co.jp")) (:maintainer "Neri Marschik" . "marschik_neri@cyberagent.co.jp") (:keywords "javascript" "node" "node_modules" "eslint") (:url . "https://github.com/codesuki/add-node-modules-path"))]) (addressbook-bookmark . [(20190612 1638) ((emacs (24))) "An address book based on Standard Emacs bookmarks." single ((:commit . "d8e502fc2f3d3ab1508ce9e50ebf8a9addc6e5b3") (:authors ("Thierry Volpiatto" . "thierry.volpiatto@gmail.com")) (:maintainer "Thierry Volpiatto" . "thierry.volpiatto@gmail.com") (:url . "https://github.com/thierryvolpiatto/addressbook-bookmark"))]) (ado-mode . [(20221023 1422) ((emacs (25 1))) "Major mode for editing Stata-related files" tar ((:commit . "5610074e29ce08631c5210f1873938c3bcd9cbde") (:authors ("Bill Rising" . "brising@alum.mit.edu")) (:maintainer "Bill Rising" . "brising@alum.mit.edu") (:keywords "tools" "languages" "files" "convenience" "stata" "mata" "ado") (:url . "https://github.com/louabill/ado-mode"))]) - (adoc-mode . [(20220919 659) ((emacs (26)) (markup-faces (1 0 0))) "a major-mode for editing AsciiDoc files in Emacs" single ((:commit . "6dc82593f05377a78083ee3f050a159f25a600b1") (:authors ("Florian Kaufmann" . "sensorflo@gmail.com")) (:maintainer "Bozhidar Batsov" . "bozhidar@batsov.dev") (:keywords "asciidoc") (:url . "https://github.com/bbatsov/adoc-mode"))]) + (adoc-mode . [(20230315 1147) ((emacs (26))) "a major-mode for editing AsciiDoc files" single ((:commit . "9e7af55e7eb8c1b19ac46139ce0f79110d1452d4") (:authors ("Florian Kaufmann" . "sensorflo@gmail.com")) (:maintainer "Bozhidar Batsov" . "bozhidar@batsov.dev") (:keywords "docs" "wp") (:url . "https://github.com/bbatsov/adoc-mode"))]) (adwaita-dark-theme . [(20230215 2027) ((emacs (27 1))) "A dark color scheme inspired by Adwaita" single ((:commit . "4792fed63a44a2337832644db909c1663100605e") (:authors ("Jessie Hildebrandt ")) (:maintainer "Jessie Hildebrandt ") (:keywords "mode-line" "faces") (:url . "https://gitlab.com/jessieh/adwaita-dark-theme"))]) (aes . [(20211204 2348) ((emacs (26 1))) "Implementation of AES" single ((:commit . "c9cd12d6c1dbc18603eb4703276132cea59d5c78") (:authors ("Markus Sauermann" . "emacs-aes@sauermann-consulting.de")) (:maintainer "Markus Sauermann" . "emacs-aes@sauermann-consulting.de") (:keywords "data" "tools") (:url . "https://github.com/Sauermann/emacs-aes"))]) - (affe . [(20230215 715) ((emacs (27 1)) (consult (0 32))) "Asynchronous Fuzzy Finder for Emacs" tar ((:commit . "69d9d05200dbf9058b3ae14e37f52944718374d7") (:authors ("Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainer "Daniel Mendler" . "mail@daniel-mendler.de") (:url . "https://github.com/minad/affe"))]) + (affe . [(20230314 1552) ((emacs (27 1)) (consult (0 33))) "Asynchronous Fuzzy Finder for Emacs" tar ((:commit . "4f9763413beab8d8866e6f0d9c02599f3ba0c852") (:authors ("Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainer "Daniel Mendler" . "mail@daniel-mendler.de") (:url . "https://github.com/minad/affe"))]) (afternoon-theme . [(20140104 1859) ((emacs (24 1))) "Dark color theme with a deep blue background" single ((:commit . "89b1d778a1f8b385775c122f2bd1c62f0fbf931a") (:authors ("Ozan Sener" . "ozan@ozansener.com")) (:maintainer "Ozan Sener" . "ozan@ozansener.com") (:keywords "themes") (:url . "http://github.com/osener/emacs-afternoon-theme"))]) (ag . [(20201031 2202) ((dash (2 8 0)) (s (1 9 0)) (cl-lib (0 5))) "A front-end for ag ('the silver searcher'), the C ack replacement." single ((:commit . "ed7e32064f92f1315cecbfc43f120bbc7508672c") (:authors ("Wilfred Hughes" . "me@wilfred.me.uk")) (:maintainer "Wilfred Hughes" . "me@wilfred.me.uk") (:url . "https://github.com/Wilfred/ag.el"))]) (agda-editor-tactics . [(20211024 2357) ((s (1 12 0)) (dash (2 16 0)) (emacs (27 1)) (org (9 1))) "An editor tactic to produce Σ-types from Agda records" single ((:commit . "06e374516cb2ab17018985f3dc4fccdc4acefd08") (:authors ("Musa Al-hassy" . "alhassy@gmail.com")) (:maintainer "Musa Al-hassy" . "alhassy@gmail.com") (:keywords "abbrev" "convenience" "languages" "agda" "tools") (:url . "https://github.com/alhassy/next-700-module-systems"))]) @@ -88,9 +88,9 @@ (airline-themes . [(20211214 1749) ((powerline (2 3))) "vim-airline themes for emacs powerline" tar ((:commit . "6bd102e49a7d87af1a72eb86e953991ff7bc954e") (:authors ("Anthony DiGirolamo" . "anthony.digirolamo@gmail.com")) (:maintainer "Anthony DiGirolamo" . "anthony.digirolamo@gmail.com") (:keywords "evil" "mode-line" "powerline" "airline" "themes") (:url . "http://github.com/AnthonyDiGirolamo/airline-themes"))]) (airplay . [(20130212 1226) ((request (20130110 2144)) (simple-httpd (1 4 1)) (deferred (0 3 1))) "Airplay bindings to Emacs" tar ((:commit . "46fad71d293a3e18551cf464fe6c6208a7a32d9d") (:authors ("Wataru MIYAGUNI" . "gonngo@gmail.com")) (:maintainer "Wataru MIYAGUNI" . "gonngo@gmail.com") (:keywords "appletv" "airplay") (:url . "https://github.com/gongo/airplay-el"))]) (alan-mode . [(20230216 857) ((flycheck (32)) (emacs (25 1)) (s (1 12))) "Major mode for editing Alan files" single ((:commit . "723cf8e8d7e00c1498935553c46f459aa1d26135") (:authors ("Paul van Dam" . "pvandam@kjerner.com")) (:maintainer "Paul van Dam" . "pvandam@kjerner.com") (:keywords "alan" "languages") (:url . "https://github.com/Kjerner/AlanForEmacs"))]) - (alarm-clock . [(20230216 1337) ((emacs (24 4))) "Alarm Clock" tar ((:commit . "3e43ca49804afb06477dbf7ff3d6e9824522be4b") (:authors ("Steve Lemuel" . "wlemuel@hotmail.com")) (:maintainer "Steve Lemuel" . "wlemuel@hotmail.com") (:keywords "calendar" "tools" "convenience") (:url . "https://github.com/wlemuel/alarm-clock"))]) + (alarm-clock . [(20230326 718) ((emacs (24 4))) "Alarm Clock" tar ((:commit . "bcd9158f18ead2aa25f10a48e4a38e2c3ed64217") (:authors ("Steve Lemuel" . "wlemuel@hotmail.com")) (:maintainer "Steve Lemuel" . "wlemuel@hotmail.com") (:keywords "calendar" "tools" "convenience") (:url . "https://github.com/wlemuel/alarm-clock"))]) (alchemist . [(20180312 1304) ((elixir-mode (2 2 5)) (dash (2 11 0)) (emacs (24 4)) (company (0 8 0)) (pkg-info (0 4)) (s (1 11 0))) "Elixir tooling integration into Emacs" tar ((:commit . "6f99367511ae209f8fe2c990779764bbb4ccb6ed") (:authors ("Samuel Tonini" . "tonini.samuel@gmail.com")) (:maintainer "Samuel Tonini" . "tonini.samuel@gmail.com") (:keywords "languages" "elixir" "elixirc" "mix" "hex" "alchemist") (:url . "http://www.github.com/tonini/alchemist.el"))]) - (alda-mode . [(20210705 654) ((emacs (24 0))) "An Alda major mode" single ((:commit . "ae08444d16bd1859a06c8ed6a3e7ae2e9ad397ed") (:authors ("Jay Kamat" . "jaygkamat@gmail.com")) (:maintainer "Jay Kamat" . "jaygkamat@gmail.com") (:keywords "alda" "highlight") (:url . "http://gitlab.com/jgkamat/alda-mode"))]) + (alda-mode . [(20230406 1927) ((emacs (24 0))) "An Alda major mode" single ((:commit . "580f6e94c93aead91406d00a42ccf9040a898cb8") (:authors ("Jay Kamat" . "jaygkamat@gmail.com")) (:maintainer "Jay Kamat" . "jaygkamat@gmail.com") (:keywords "alda" "highlight") (:url . "http://gitlab.com/jgkamat/alda-mode"))]) (alect-themes . [(20211022 1651) ((emacs (24 0))) "Configurable light, dark and black themes for Emacs 24 or later" tar ((:commit . "89560047934c236d05ea6b911c0c63702a8e06f3") (:authors ("Alex Kost" . "alezost@gmail.com")) (:maintainer "Alex Kost" . "alezost@gmail.com") (:keywords "color" "theme") (:url . "https://github.com/alezost/alect-themes"))]) (alectryon . [(20220925 2236) ((flycheck (31)) (emacs (25 1))) "Toggle between Coq and reStructuredText" tar ((:commit . "8a1f3054c97fc86d628413800cfef75577c43485") (:authors ("Clément Pit-Claudel" . "clement.pitclaudel@live.com")) (:maintainer "Clément Pit-Claudel" . "clement.pitclaudel@live.com") (:keywords "convenience" "languages" "tools") (:url . "https://github.com/cpitclaudel/alectryon"))]) (alert . [(20221213 1619) ((gntp (0 1)) (log4e (0 3 0)) (cl-lib (0 5))) "Growl-style notification system for Emacs" single ((:commit . "c762380ff71c429faf47552a83605b2578656380") (:authors ("John Wiegley" . "jwiegley@gmail.com")) (:maintainer "John Wiegley" . "jwiegley@gmail.com") (:keywords "notification" "emacs" "message") (:url . "https://github.com/jwiegley/alert"))]) @@ -98,13 +98,13 @@ (alert-toast . [(20220312 229) ((emacs (25 1)) (alert (1 2)) (f (0 20 0)) (s (1 12 0))) "Windows 10 toast notifications" single ((:commit . "96c88c93c1084de681700f655223142ee0eb944a") (:authors ("Grzegorz Kowzan" . "grzegorz@kowzan.eu")) (:maintainer "Grzegorz Kowzan" . "grzegorz@kowzan.eu") (:url . "https://github.com/gkowzan/alert-toast"))]) (align-cljlet . [(20160112 2101) ((clojure-mode (1 11 5))) "Space align various Clojure forms" single ((:commit . "ebcf0a912e836579a3a9d386e22c1c4bef7fba17") (:url . "https://github.com/gstamp/align-cljlet"))]) (all-ext . [(20200315 1443) ((emacs (24 4)) (all (1 0))) "M-x all with helm-swoop/anything/multiple-cursors/line-number" single ((:commit . "c865c62506af2c9edc7705a7c24dc8b70d5d4de2") (:authors ("rubikitch" . "rubikitch@ruby-lang.org")) (:maintainer "rubikitch" . "rubikitch@ruby-lang.org") (:keywords "matching" "all" "search" "replace" "anything" "helm" "helm-swoop" "occur") (:url . "https://github.com/rubikitch/all-ext"))]) - (all-the-icons . [(20220929 2303) ((emacs (24 3))) "A library for inserting Developer icons" tar ((:commit . "51bf77da1ebc3c199dfc11f54c0dce67559f5f40") (:authors ("Dominic Charlesworth" . "dgc336@gmail.com")) (:maintainer "Dominic Charlesworth" . "dgc336@gmail.com") (:keywords "convenient" "lisp") (:url . "https://github.com/domtronn/all-the-icons.el"))]) - (all-the-icons-completion . [(20221130 2354) ((emacs (26 1)) (all-the-icons (5 0))) "Add icons to completion candidates" single ((:commit . "4da28584a1b36b222e0e78d46fd8d46bbd9116c7") (:authors ("Itai Y. Efrat ")) (:maintainer "Itai Y. Efrat" . "itai3397@gmail.com") (:keywords "convenient" "lisp") (:url . "https://github.com/iyefrat/all-the-icons-completion"))]) + (all-the-icons . [(20230316 1906) ((emacs (24 3))) "A library for inserting Developer icons" tar ((:commit . "d922aff57ac8308d3ed067f9151cc76d342855f2") (:authors ("Dominic Charlesworth" . "dgc336@gmail.com")) (:maintainer "Dominic Charlesworth" . "dgc336@gmail.com") (:keywords "convenient" "lisp") (:url . "https://github.com/domtronn/all-the-icons.el"))]) + (all-the-icons-completion . [(20230224 1610) ((emacs (26 1)) (all-the-icons (5 0))) "Add icons to completion candidates" single ((:commit . "b08f053cee444546ab44a05fd541f59e8bc8983b") (:authors ("Itai Y. Efrat ")) (:maintainer "Itai Y. Efrat" . "itai3397@gmail.com") (:keywords "convenient" "lisp") (:url . "https://github.com/iyefrat/all-the-icons-completion"))]) (all-the-icons-dired . [(20220929 1135) ((emacs (26 1)) (all-the-icons (2 2 0))) "Shows icons for each file in dired mode" single ((:commit . "bcaed35bb3ad7fc46007f16e0d670beb82bb613e") (:authors ("jtbm37")) (:maintainer "Jimmy Yuen Ho Wong" . "wyuenho@gmail.com") (:keywords "files" "icons" "dired") (:url . "https://github.com/wyuenho/all-the-icons-dired"))]) (all-the-icons-gnus . [(20180511 654) ((emacs (24 4)) (dash (2 12 0)) (all-the-icons (3 1 0))) "Shows icons for in Gnus" single ((:commit . "27f78996da0725943bcfb2d18038e6f7bddfa9c7") (:authors ("Nicolas Lamirault" . "nicolas.lamirault@gmail.com")) (:maintainer "Nicolas Lamirault" . "nicolas.lamirault@gmail.com") (:keywords "mail" "tools"))]) - (all-the-icons-ibuffer . [(20220424 1027) ((emacs (24 4)) (all-the-icons (2 2 0))) "Display icons for all buffers in ibuffer" single ((:commit . "0c7221366ceddbf122073ecd07dd86e1baf032ff") (:authors ("Vincent Zhang" . "seagle0128@gmail.com")) (:maintainer "Vincent Zhang" . "seagle0128@gmail.com") (:keywords "convenience" "icons" "ibuffer") (:url . "https://github.com/seagle0128/all-the-icons-ibuffer"))]) + (all-the-icons-ibuffer . [(20230402 1554) ((emacs (24 4)) (all-the-icons (2 2 0))) "Display icons for all buffers in ibuffer" single ((:commit . "22cfc4324cd7ef6473c892f1721a0a144c5aba36") (:authors ("Vincent Zhang" . "seagle0128@gmail.com")) (:maintainer "Vincent Zhang" . "seagle0128@gmail.com") (:keywords "convenience" "icons" "ibuffer") (:url . "https://github.com/seagle0128/all-the-icons-ibuffer"))]) (all-the-icons-ivy . [(20190508 1803) ((emacs (24 4)) (all-the-icons (2 4 0)) (ivy (0 8 0))) "Shows icons while using ivy and counsel" single ((:commit . "babea626db20773de4c408acb2788e2b9c8277e3") (:authors ("asok")) (:maintainer "asok") (:keywords "faces"))]) - (all-the-icons-ivy-rich . [(20230129 1522) ((emacs (25 1)) (ivy-rich (0 1 0)) (all-the-icons (2 2 0))) "Better experience with icons for ivy" single ((:commit . "bc10c105f07c752d82ec7dfd929e5182d3b4a18f") (:authors ("Vincent Zhang" . "seagle0128@gmail.com")) (:maintainer "Vincent Zhang" . "seagle0128@gmail.com") (:keywords "convenience" "icons" "ivy") (:url . "https://github.com/seagle0128/all-the-icons-ivy-rich"))]) + (all-the-icons-ivy-rich . [(20230404 1331) ((emacs (25 1)) (ivy-rich (0 1 0)) (all-the-icons (2 2 0))) "Better experience with icons for ivy" single ((:commit . "cf833e988a953743d5f5bbc799a91a47862d7008") (:authors ("Vincent Zhang" . "seagle0128@gmail.com")) (:maintainer "Vincent Zhang" . "seagle0128@gmail.com") (:keywords "convenience" "icons" "ivy") (:url . "https://github.com/seagle0128/all-the-icons-ivy-rich"))]) (almost-mono-themes . [(20220422 1714) ((emacs (24))) "Almost monochromatic color themes" tar ((:commit . "0641bf565c113caef8d5c2a93f38cff32ebb62b7") (:authors ("John Olsson" . "john@cryon.se")) (:maintainer "John Olsson" . "john@cryon.se") (:keywords "faces") (:url . "https://github.com/cryon/almost-mono-themes"))]) (alsamixer . [(20191002 1133) nil "Functions to call out to amixer." single ((:commit . "1bdb99e433acd38685f05408562746cfbf2bc820") (:authors ("R.W. van 't Veer")) (:maintainer "R.W. van 't Veer") (:keywords "convenience") (:url . "https://github.com/remvee/alsamixer-el"))]) (alt-codes . [(20220704 644) ((emacs (26 1))) "Insert alt codes using meta key" single ((:commit . "36dbcbeb69525cd21caeb4c267421b69fa2fffcb") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "alt" "codes" "insertion" "meta") (:url . "https://github.com/jcs-elpa/alt-codes"))]) @@ -113,10 +113,10 @@ (ample-regexps . [(20200508 1021) nil "ample regular expressions for Emacs" tar ((:commit . "153969ce547afe410b8986f01c9ed4087c9cd20b") (:authors ("immerrr" . "immerrr@gmail.com")) (:maintainer "immerrr" . "immerrr@gmail.com") (:keywords "regexps" "extensions" "tools"))]) (ample-theme . [(20180207 1745) nil "Calm Dark Theme for Emacs" tar ((:commit . "366698400c555211c2082962a5d74f3dd79a78c8") (:authors ("Jordon Biondo" . "jordonbiondo@gmail.com")) (:maintainer "Jordon Biondo" . "jordonbiondo@gmail.com") (:keywords "theme" "dark") (:url . "https://github.com/jordonbiondo/ample-theme"))]) (ample-zen-theme . [(20150119 2154) nil "AmpleZen Theme for Emacs 24" single ((:commit . "b277bb7abd4b6624e8d59f02474b79af50a007bd") (:authors ("Michael Wall")) (:maintainer "Michael Wall") (:keywords "theme" "dark" "emacs 24") (:url . "https://github.com/mjwall/ample-zen"))]) - (amread-mode . [(20230107 1433) ((emacs (24 3)) (cl-lib (0 6 1)) (pyim (5 2 8))) "A minor mode helper user speed-reading" single ((:commit . "4746c6adf81bedf8933faf912c4c65dafea9bb62") (:keywords "wp") (:url . "https://repo.or.cz/amread-mode.git"))]) + (amread-mode . [(20230406 1202) ((emacs (24 3)) (cl-lib (0 6 1)) (pyim (5 2 8))) "A minor mode helper user speed-reading" single ((:commit . "f5b46f83ce205b1f6c1cf54e99da3e46ad17dfad") (:keywords "wp") (:url . "https://repo.or.cz/amread-mode.git"))]) (amsreftex . [(20220115 1838) ((emacs (25 1))) "Add amsrefs bibliography support for reftex" single ((:commit . "facf47b82572e3f62bd8d9b8d4f4d5258f6c8a38") (:authors ("Fran Burstall" . "fran.burstall@gmail.com")) (:maintainer "Fran Burstall" . "fran.burstall@gmail.com") (:keywords "tex") (:url . "https://github.com/franburstall/amsreftex"))]) (amx . [(20210305 118) ((emacs (24 4)) (s (0))) "Alternative M-x with extra features." single ((:commit . "37f9c7ae55eb0331b27200fb745206fc58ceffc0") (:authors ("Ryan C. Thompson" . "rct@thompsonclan.org") ("Cornelius Mika" . "cornelius.mika@gmail.com")) (:maintainer "Ryan C. Thompson" . "rct@thompsonclan.org") (:keywords "convenience" "usability" "completion") (:url . "http://github.com/DarwinAwardWinner/amx/"))]) - (anaconda-mode . [(20220922 741) ((emacs (25 1)) (pythonic (0 1 0)) (dash (2 6 0)) (s (1 9)) (f (0 16 2))) "Code navigation, documentation lookup and completion for Python" tar ((:commit . "ca8edbaa7662d97e4a4416ec9a8d743863303911") (:authors ("Artem Malyshev" . "proofit404@gmail.com")) (:maintainer "Artem Malyshev" . "proofit404@gmail.com") (:url . "https://github.com/proofit404/anaconda-mode"))]) + (anaconda-mode . [(20230306 2112) ((emacs (25 1)) (pythonic (0 1 0)) (dash (2 6 0)) (s (1 9)) (f (0 16 2))) "Code navigation, documentation lookup and completion for Python" tar ((:commit . "e250596f5587129f55f446ef127d0dac5e9730a3") (:authors ("Artem Malyshev" . "proofit404@gmail.com")) (:maintainer "Artem Malyshev" . "proofit404@gmail.com") (:url . "https://github.com/proofit404/anaconda-mode"))]) (anakondo . [(20210221 1727) ((emacs (26 3))) "Adds clj-kondo based Clojure[Script] editing facilities" single ((:commit . "16b0ba14d94a5d7e55655efc9e1d6d069a9306f2") (:authors ("Didier A." . "didibus@users.noreply.github.com")) (:maintainer "Didier A." . "didibus@users.noreply.github.com") (:keywords "clojure" "clojurescript" "cljc" "clj-kondo" "completion" "languages" "tools") (:url . "https://github.com/didibus/anakondo"))]) (anaphora . [(20180618 2200) nil "anaphoric macros providing implicit temp variables" single ((:commit . "3b2da3f759b244975852e79721c4a2dbad3905cf") (:authors ("Roland Walker" . "walker@pobox.com")) (:maintainer "Roland Walker" . "walker@pobox.com") (:keywords "extensions") (:url . "http://github.com/rolandwalker/anaphora"))]) (ancient-one-dark-theme . [(20211030 1358) ((emacs (24 1))) "A color theme based off uetchy's Ancient One Dark Theme" single ((:commit . "a0eaa8bce0ffc25d1469af48a74e80f820bab0ab") (:authors ("Daniils Petrovs")) (:maintainer "Daniils Petrovs") (:url . "https://github.com/DaniruKun/ancient-one-dark-emacs-theme"))]) @@ -130,11 +130,11 @@ (anki-mode . [(20201223 719) ((emacs (24 4)) (dash (2 12 0)) (markdown-mode (2 2)) (s (1 11 0)) (request (0 3 0))) "A major mode for creating anki cards" single ((:commit . "7cde5a68c9d0ef3811b0bd480274ea79909d2ddc") (:authors ("David Shepherd" . "davidshepherd7@gmail.com")) (:maintainer "David Shepherd" . "davidshepherd7@gmail.com") (:keywords "tools") (:url . "https://github.com/davidshepherd7/anki-mode"))]) (anki-vocabulary . [(20200103 325) ((emacs (24 4)) (s (1 0)) (youdao-dictionary (0 4)) (anki-connect (1 0)) (s (1 10))) "Help you to create vocabulary cards in Anki" single ((:commit . "863fe0219577f996ab126f1b7902db3c2cc59b2b") (:authors ("DarkSun" . "lujun9972@gmail.com")) (:maintainer "DarkSun" . "lujun9972@gmail.com") (:keywords "lisp" "anki" "translator" "chinese") (:url . "https://github.com/lujun9972/anki-vocabulary.el"))]) (annalist . [(20190929 207) ((emacs (24 4)) (cl-lib (0 5))) "Record and display information such as keybindings" tar ((:commit . "08df07e4530953a2c0b1aa553adcab37b7b614b0") (:authors ("Fox Kiester" . "noct@posteo.net")) (:maintainer "Fox Kiester" . "noct@posteo.net") (:keywords "convenience" "tools" "keybindings" "org") (:url . "https://github.com/noctuid/annalist.el"))]) - (annotate . [(20230203 1756) nil "annotate files without changing them" single ((:commit . "e433ec6803d773ad2fd92f88b1ffce41ee999c65") (:authors ("Bastian Bechtold")) (:maintainer "Bastian Bechtold , cage" . "cage-dev@twistfold.it") (:url . "https://github.com/bastibe/annotate.el"))]) + (annotate . [(20230401 1613) nil "annotate files without changing them" single ((:commit . "69d7e2138c35f8c8adb33cf27b440eee2591810d") (:authors ("Bastian Bechtold")) (:maintainer "Bastian Bechtold , cage" . "cage-dev@twistfold.it") (:url . "https://github.com/bastibe/annotate.el"))]) (annotate-depth . [(20160520 2040) nil "Annotate buffer if indentation depth is beyond threshold." single ((:commit . "fcb24fa36287250e40d195590c4ca4a8a696277b") (:authors ("Morten Slot Kristensen ")) (:maintainer "Morten Slot Kristensen ") (:keywords "convenience") (:url . "https://github.com/netromdk/annotate-depth"))]) (annotation . [(20200914 644) nil "Functions for annotating text with faces and help bubbles" single ((:commit . "aa5e3a127bf17a8c80d947f3c286758a36dadc36") (:url . "https://github.com/agda/agda"))]) (annoying-arrows-mode . [(20161024 646) ((cl-lib (0 5))) "Ring the bell if using arrows too much" single ((:commit . "3c42e9807d7696da2da2a21b63beebf9cdb3f5dc") (:authors ("Magnar Sveen" . "magnars@gmail.com")) (:maintainer "Magnar Sveen" . "magnars@gmail.com"))]) - (ansi . [(20211104 1420) ((emacs (24 1)) (cl-lib (0 6))) "Turn string into ansi strings" single ((:commit . "2367fba7b3b2340364a30cd6de7f3eb6bb9898a3") (:authors ("Johan Andersson" . "johan.rejeep@gmail.com")) (:maintainer "Johan Andersson" . "johan.rejeep@gmail.com") (:keywords "terminals" "color" "ansi") (:url . "http://github.com/rejeep/ansi"))]) + (ansi . [(20230306 1823) ((emacs (24 1)) (cl-lib (0 6))) "Turn string into ansi strings" single ((:commit . "c79806eacdf96e061abf5334f4c3364a995705d4") (:authors ("Johan Andersson" . "johan.rejeep@gmail.com")) (:maintainer "Johan Andersson" . "johan.rejeep@gmail.com") (:keywords "terminals" "color" "ansi") (:url . "http://github.com/rejeep/ansi"))]) (ansible . [(20220114 45) ((s (1 9 0)) (f (0 16 2))) "Ansible minor mode" tar ((:commit . "d89ac0ee57742cca0f0e0a3453d9dcc521575690") (:authors ("k1LoW (Kenichirou Oyama), ")) (:maintainer "k1LoW (Kenichirou Oyama), ") (:url . "https://github.com/k1LoW/emacs-ansible"))]) (ansible-doc . [(20160924 824) ((emacs (24 3))) "Ansible documentation Minor Mode" single ((:commit . "bc8128a85a79b14f4a121105d87a5eddc33975ad") (:authors ("Sebastian Wiesner" . "swiesner@lunaryorn")) (:maintainer "Sebastian Wiesner" . "swiesner@lunaryorn") (:keywords "tools" "help") (:url . "https://github.com/lunaryorn/ansible-doc.el"))]) (ansible-vault . [(20211119 1459) ((emacs (24 3))) "Minor mode for editing ansible vault files" single ((:commit . "9b3d82ee49d484a494f2d88927b37fcd6245d51e") (:maintainer "Zachary Elliott" . "contact@zell.io") (:keywords "ansible" "ansible-vault" "tools") (:url . "http://github.com/zellio/ansible-vault-mode"))]) @@ -149,14 +149,14 @@ (apache-mode . [(20210519 1931) nil "Major mode for editing Apache httpd configuration files" single ((:commit . "f2c11aac2f5fc598123e04f4604bea248689a117") (:authors ("Karl Chen" . "quarl@nospam.quarl.org")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "languages" "faces") (:url . "https://github.com/emacs-php/apache-mode"))]) (apdl-mode . [(20211023 1831) ((emacs (25 1))) "Major mode for the APDL programming language." tar ((:commit . "ba756eaa1d229c9bf6936fb8d2d4126ad073d488") (:authors ("H. Dieter Wilhelm" . "dieter@duenenhof-wilhelm.de")) (:maintainer "H. Dieter Wilhelm") (:keywords "languages" "convenience" "tools" "ansys" "apdl") (:url . "https://github.com/dieter-wilhelm/apdl-mode"))]) (apel . [(20220720 1308) ((emacs (24 5))) "A Portable Emacs Library provides support for portable Emacs Lisp programs" tar ((:commit . "82eb2325bd149dc57b43a9ce9402c6c6183e4052"))]) - (apheleia . [(20230219 100) ((emacs (26))) "Reformat buffer stably" single ((:commit . "972b9906bf6d23f5a8e92129a4572a906bdfe45e") (:authors ("Radian LLC" . "contact+apheleia@radian.codes")) (:maintainer "Radian LLC" . "contact+apheleia@radian.codes") (:keywords "tools") (:url . "https://github.com/raxod502/apheleia"))]) + (apheleia . [(20230329 2135) ((emacs (26))) "Reformat buffer stably" tar ((:commit . "23c8b7d1ca3d855b38b8fe8bee760fa1234b6143") (:authors ("Radian LLC" . "contact+apheleia@radian.codes")) (:maintainer "Radian LLC" . "contact+apheleia@radian.codes") (:keywords "tools") (:url . "https://github.com/raxod502/apheleia"))]) (apib-mode . [(20200101 1017) ((markdown-mode (2 1))) "Major mode for API Blueprint files" single ((:commit . "c6dd05201f6eb9295736d8668a79a7510d11159e") (:authors ("Vilibald Wanča" . "vilibald@wvi.cz")) (:maintainer "Vilibald Wanča" . "vilibald@wvi.cz") (:keywords "tools" "api-blueprint") (:url . "http://github.com/w-vi/apib-mode"))]) (apiwrap . [(20180602 2231) ((emacs (25))) "api-wrapping macros" single ((:commit . "e4c9c57d6620a788ec8a715ff1bb50542edea3a6") (:authors ("Sean Allred" . "code@seanallred.com")) (:maintainer "Sean Allred" . "code@seanallred.com") (:keywords "tools" "maint" "convenience") (:url . "https://github.com/vermiculus/apiwrap.el"))]) (apparmor-mode . [(20230209 2325) ((emacs (26 1))) "Major mode for editing AppArmor policy files" single ((:commit . "3b641de4e34fb4a0594a461254f1454973b6b7aa") (:authors ("Alex Murray" . "murray.alex@gmail.com")) (:maintainer "Alex Murray" . "murray.alex@gmail.com") (:url . "https://github.com/alexmurray/apparmor-mode"))]) (apples-mode . [(20110121 418) nil "Major mode for editing and executing AppleScript code" tar ((:commit . "83a9ab0d6ba82496e2f7df386909b1a55701fccb") (:authors ("tequilasunset" . "tequilasunset.mac@gmail.com")) (:maintainer "tequilasunset" . "tequilasunset.mac@gmail.com") (:keywords "applescript" "languages"))]) (applescript-mode . [(20210802 1715) ((emacs (24 3))) "major mode for editing AppleScript source" single ((:commit . "00c141bbff46c89a96598b605dee05dd1d89f624") (:authors ("sakito" . "sakito@users.sourceforge.jp")) (:maintainer "sakito" . "sakito@users.sourceforge.jp") (:keywords "languages" "tools") (:url . "https://github.com/emacsorphanage/applescript-mode"))]) (aproject . [(20220410 541) nil "Basic project framework for Emacs" tar ((:commit . "13e176ee69851403bec6471c5cceed17b7912b6f") (:authors ("Vietor Liu" . "vietor.liu@gmail.com")) (:maintainer "Vietor Liu" . "vietor.liu@gmail.com") (:keywords "environment" "project") (:url . "https://github.com/vietor/aproject"))]) - (apropospriate-theme . [(20230117 2123) nil "A colorful, low-contrast, light & dark theme set for Emacs with a fun name." tar ((:commit . "1257880637e03efb885893afbcb88b7a8b20965a") (:authors ("Justin Talbott" . "justin@waymondo.com")) (:maintainer "Justin Talbott" . "justin@waymondo.com") (:url . "http://github.com/waymondo/apropospriate-theme"))]) + (apropospriate-theme . [(20230310 2249) nil "A colorful, low-contrast, light & dark theme set for Emacs with a fun name." tar ((:commit . "99e492804de96a0bb98fa058c4c86908132b4cf7") (:authors ("Justin Talbott" . "justin@waymondo.com")) (:maintainer "Justin Talbott" . "justin@waymondo.com") (:url . "http://github.com/waymondo/apropospriate-theme"))]) (apt-sources-list . [(20180527 1241) ((emacs (24 4))) "Mode for editing APT source.list files" single ((:commit . "44112833b3fa7f4d7e43708e5996782e22bb2fa3") (:authors ("Dr. Rafael Sepúlveda" . "drs@gnulinux.org.mx")) (:maintainer "Joe Wreschnig" . "joe.wreschnig@gmail.com") (:url . "https://git.korewanetadesu.com/apt-sources-list.git"))]) (aqi . [(20200215 1334) ((emacs (25 1)) (request (0 3)) (let-alist (0 0))) "Air quality data from the World Air Quality Index" single ((:commit . "265ab11044b527ca70762fc5d633227001dd4da6") (:authors ("nik gaffney" . "nik@fo.am")) (:maintainer "nik gaffney" . "nik@fo.am") (:keywords "air quality" "aqi" "pollution" "weather" "data") (:url . "https://github.com/zzkt/aqi"))]) (arch-packer . [(20170730 1321) ((emacs (25 1)) (s (1 11 0)) (async (1 9 2)) (dash (2 12 0))) "Arch Linux package management frontend" single ((:commit . "940e96f7d357c6570b675a0f942181c787f1bfd7") (:authors ("Fritz Stelzer" . "brotzeitmacher@gmail.com")) (:maintainer "Fritz Stelzer" . "brotzeitmacher@gmail.com") (:url . "https://github.com/brotzeitmacher/arch-packer"))]) @@ -165,7 +165,7 @@ (archive-rpm . [(20220527 632) ((emacs (24 4))) "RPM and CPIO support for archive-mode" tar ((:commit . "cb48fee04cb0cbb26f760a3b95649f7dac78c6ec") (:authors ("Magnus Henoch" . "magnus.henoch@gmail.com")) (:maintainer "Magnus Henoch" . "magnus.henoch@gmail.com") (:keywords "files"))]) (arduino-cli-mode . [(20210511 653) ((emacs (25 1))) "Arduino-CLI command wrapper" single ((:commit . "9ff2c47a3b56cbffd41a62376f7c2ff16ccbf4e0") (:authors ("Love Lagerkvist")) (:maintainer "Love Lagerkvist") (:keywords "processes" "tools") (:url . "https://github.com/motform/arduino-cli-mode"))]) (arduino-mode . [(20220210 1355) ((emacs (25 1)) (spinner (1 7 3))) "Major mode for editing Arduino code" tar ((:commit . "652c6a328fa8f2db06534d5f231c6b6933be3edc") (:maintainer "stardiviner" . "numbchild@gmail.com") (:keywords "languages" "arduino") (:url . "https://repo.or.cz/arduino-mode.git"))]) - (aria2 . [(20230205 1008) ((emacs (24 4))) "Control aria2c commandline tool from Emacs" single ((:commit . "cc1661525bdf5c908c94a9d891a62d9b2e313670") (:authors ("Łukasz Gruner" . "lukasz@gruner.lu")) (:maintainer "Łukasz Gruner" . "lukasz@gruner.lu") (:keywords "download" "bittorrent" "aria2") (:url . "https://bitbucket.org/ukaszg/aria2-mode"))]) + (aria2 . [(20230314 2131) ((emacs (25 1))) "Control aria2c commandline tool from Emacs" single ((:commit . "1f2cbe624f3a4e0109b5dc123bb4bbed496b15a7") (:authors ("Łukasz Gruner" . "lukasz@gruner.lu")) (:maintainer "Łukasz Gruner" . "lukasz@gruner.lu") (:keywords "download" "bittorrent" "aria2") (:url . "https://bitbucket.org/ukaszg/aria2-mode"))]) (ariadne . [(20131117 1711) ((bert (0 1))) "Ariadne plugin for Emacs" single ((:commit . "6fe401c7f996bcbc2f685e7971324c6f5e5eaf15") (:authors ("Oleksandr Manzyuk" . "manzyuk@gmail.com")) (:maintainer "Oleksandr Manzyuk" . "manzyuk@gmail.com") (:keywords "comm" "convenience" "processes"))]) (arjen-grey-theme . [(20170522 2047) nil "A soothing dark grey theme" single ((:commit . "4cd0be72b65d42390e2105cfdaa408a1ead8d8d1") (:authors ("Arjen Wiersma" . "arjen@wiersma.org")) (:maintainer "Arjen Wiersma" . "arjen@wiersma.org") (:keywords "faces") (:url . "https://github.com/credmp/arjen-grey"))]) (artbollocks-mode . [(20170524 422) nil "Improve your writing (especially about art)" single ((:commit . "4a907e470bf345b88c3802c1241ce2b8cf4123ee") (:authors ("Rob Myers , Sacha Chua" . "sacha@sachachua.com")) (:maintainer "Rob Myers , Sacha Chua" . "sacha@sachachua.com") (:url . "https://github.com/sachac/artbollocks-mode"))]) @@ -179,7 +179,7 @@ (assess . [(20220719 1904) ((emacs (24 4)) (m-buffer (0 15))) "Test support functions" tar ((:commit . "44083d94feb45d3636f7ee6c55e0ef6bbb32b938") (:authors ("Phillip Lord" . "phillip.lord@russet.org.uk")) (:maintainer "Phillip Lord" . "phillip.lord@russet.org.uk"))]) (astyle . [(20200328 616) ((emacs (24 4)) (reformatter (0 3))) "Astyle formatter functions" single ((:commit . "04ff2941f08c4b731fe6a18ee1697436d1ca1cc0") (:authors ("Petter Storvik")) (:maintainer "Petter Storvik") (:keywords "astyle" "c" "c++" "cpp" "reformatter") (:url . "https://github.com/storvik/emacs-astyle"))]) (asx . [(20191024 1100) ((emacs (26 1))) "Ask StackExchange/StackOverflow" single ((:commit . "5ca12cc51bb02b5926adf9a7976ba9ca08a1ea21") (:authors ("Alex Ragone" . "ragonedk@gmail.com")) (:maintainer "Alex Ragone" . "ragonedk@gmail.com") (:keywords "convenience") (:url . "https://github.com/ragone/asx"))]) - (async . [(20230216 559) ((emacs (24 4))) "Asynchronous processing in Emacs" tar ((:commit . "71cc50f27ffc598a89aeaa593488d87818647d02") (:authors ("John Wiegley" . "jwiegley@gmail.com")) (:maintainer "Thierry Volpiatto" . "thievol@posteo.net") (:keywords "async") (:url . "https://github.com/jwiegley/emacs-async"))]) + (async . [(20230323 643) ((emacs (24 4))) "Asynchronous processing in Emacs" tar ((:commit . "34feabe1142863a2c96f75afda1a2ae4aa0813f6") (:authors ("John Wiegley" . "jwiegley@gmail.com")) (:maintainer "Thierry Volpiatto" . "thievol@posteo.net") (:keywords "async") (:url . "https://github.com/jwiegley/emacs-async"))]) (async-await . [(20220827 437) ((emacs (25 1)) (promise (1 1)) (iter2 (0 9 10))) "Async/Await" single ((:commit . "e0d15e8057ed7520100bc50c5552278292ebcb07") (:authors ("chuntaro" . "chuntaro@sakura-games.jp")) (:maintainer "chuntaro" . "chuntaro@sakura-games.jp") (:keywords "async" "await" "convenience") (:url . "https://github.com/chuntaro/emacs-async-await"))]) (async-backup . [(20220131 1438) ((emacs (24 4))) "Backup on each save without freezing Emacs" single ((:commit . "6ddb39fe77d66cdef48b87cb0d0554ad7d132308") (:authors ("contrapunctus" . "xmpp:contrapunctus@jabjab.de")) (:maintainer "contrapunctus" . "xmpp:contrapunctus@jabjab.de") (:keywords "files") (:url . "https://tildegit.org/contrapunctus/async-backup"))]) (atcoder-tools . [(20200109 1236) ((emacs (26)) (f (0 20)) (s (1 12))) "An atcoder-tools client" single ((:commit . "cfe61ed18ea9b3b1bfb6f9e7d80a47599680cd1f") (:authors ("Seong Yong-ju" . "sei40kr@gmail.com")) (:maintainer "Seong Yong-ju" . "sei40kr@gmail.com") (:keywords "extensions" "tools") (:url . "https://github.com/sei40kr/atcoder-tools"))]) @@ -187,8 +187,8 @@ (atl-markup . [(20220704 644) ((emacs (24 3))) "Automatically truncate lines for markup languages" single ((:commit . "8604cd6b0a2473595988d47f41623d2cd06d0a7b") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "automatic" "truncate" "visual" "lines") (:url . "https://github.com/jcs-elpa/atl-markup"))]) (atom-dark-theme . [(20220114 1902) nil "An Emacs port of the Atom Dark theme from Atom.io." single ((:commit . "2b3c7ad42bbcab3214a131f8957b92e717b36ad3") (:authors ("Jeremy Whitlock" . "jwhitlock@apache.org")) (:maintainer "Jeremy Whitlock" . "jwhitlock@apache.org") (:keywords "themes" "atom" "dark") (:url . "https://github.com/whitlockjc/atom-dark-theme-emacs"))]) (atom-one-dark-theme . [(20210128 1640) nil "Atom One Dark color theme" single ((:commit . "b34b62e85593812b55ee552a1cb0eecfb04767bb") (:authors ("Jonathan Chu" . "me@jonathanchu.is")) (:maintainer "Jonathan Chu" . "me@jonathanchu.is") (:url . "https://github.com/jonathanchu/atom-one-dark-theme"))]) - (atomic-chrome . [(20220723 113) ((emacs (24 4)) (let-alist (1 0 4)) (websocket (1 4))) "Edit Chrome text area with Emacs using Atomic Chrome" single ((:commit . "061958ab96c31085b5daf449b1d826b052777b59") (:authors ("alpha22jp" . "alpha22jp@gmail.com")) (:maintainer "alpha22jp" . "alpha22jp@gmail.com") (:keywords "chrome" "edit" "textarea") (:url . "https://github.com/alpha22jp/atomic-chrome"))]) - (attrap . [(20221204 803) ((dash (2 12 0)) (emacs (25 1)) (f (0 19 0)) (s (1 11 0))) "ATtempt To Repair At Point" single ((:commit . "c00f4cc9409dc2fa8c0924f425b2840534b09221") (:authors ("Jean-Philippe Bernardy" . "jeanphilippe.bernardy@gmail.com")) (:maintainer "Jean-Philippe Bernardy" . "jeanphilippe.bernardy@gmail.com") (:keywords "programming" "tools") (:url . "https://github.com/jyp/attrap"))]) + (atomic-chrome . [(20230304 112) ((emacs (24 4)) (let-alist (1 0 4)) (websocket (1 4))) "Edit Chrome text area with Emacs using Atomic Chrome" single ((:commit . "f1b077be7e414f457191d72dcf5eedb4371f9309") (:authors ("alpha22jp" . "alpha22jp@gmail.com")) (:maintainer "alpha22jp" . "alpha22jp@gmail.com") (:keywords "chrome" "edit" "textarea") (:url . "https://github.com/alpha22jp/atomic-chrome"))]) + (attrap . [(20230310 1555) ((dash (2 12 0)) (emacs (25 1)) (f (0 19 0)) (s (1 11 0))) "ATtempt To Repair At Point" single ((:commit . "2df105d0bd23a468e75fad0fed7d39013328526d") (:authors ("Jean-Philippe Bernardy" . "jeanphilippe.bernardy@gmail.com")) (:maintainer "Jean-Philippe Bernardy" . "jeanphilippe.bernardy@gmail.com") (:keywords "programming" "tools") (:url . "https://github.com/jyp/attrap"))]) (auctex-cluttex . [(20220730 1100) ((emacs (24 4)) (auctex (13 1))) "ClutTeX support for AUCTeX" single ((:commit . "f4012ac86e612eac7662c62afd946e59b3b405bd") (:authors ("Masahiro Nakamura" . "tsuucat@icloud.com")) (:maintainer "Masahiro Nakamura" . "tsuucat@icloud.com") (:keywords "tex") (:url . "https://github.com/tsuu32/auctex-cluttex"))]) (auctex-latexmk . [(20221025 1219) ((auctex (11 87))) "Add LatexMk support to AUCTeX" single ((:commit . "b00a95e6b34c94987fda5a57c20cfe2f064b1c7a") (:authors ("Tomoya Tanjo" . "ttanjo@gmail.com")) (:maintainer "Tomoya Tanjo" . "ttanjo@gmail.com") (:keywords "tex") (:url . "https://github.com/tom-tan/auctex-latexmk/"))]) (auctex-lua . [(20151121 1610) ((auctex (11 86)) (lua-mode (20130419))) "Lua editing support for AUCTeX" single ((:commit . "799cd8ac10c96991bb63d9aa60528ae5d8c786b5") (:authors ("Sean Allred" . "seallred@smcm.edu")) (:maintainer "Sean Allred" . "seallred@smcm.edu") (:keywords "latex" "lua") (:url . "http://github.com/vermiculus/auctex-lua"))]) @@ -202,7 +202,7 @@ (auth-source-xoauth2 . [(20220804 2219) ((emacs (26 1))) "Integrate auth-source with XOAUTH2" single ((:commit . "99a03f8ce835412943d311b2746e77fcf5a1b500") (:authors ("Cesar Crusius" . "ccrusius@google.com")) (:maintainer "Cesar Crusius" . "ccrusius@google.com") (:url . "https://github.com/ccrusius/auth-source-xoauth2"))]) (auto-async-byte-compile . [(20160916 454) nil "Automatically byte-compile when saved" single ((:commit . "8681e74ddb8481789c5dbb3cafabb327db4c4484") (:authors ("rubikitch" . "rubikitch@ruby-lang.org")) (:maintainer "rubikitch" . "rubikitch@ruby-lang.org") (:keywords "lisp" "convenience") (:url . "http://www.emacswiki.org/cgi-bin/wiki/download/auto-async-byte-compile.el"))]) (auto-auto-indent . [(20131106 1903) ((es-lib (0 1)) (cl-lib (1 0))) "Indents code as you type" single ((:commit . "0139378577f936d34b20276af6f022fb457af490") (:authors ("sabof")) (:maintainer "sabof") (:url . "https://github.com/sabof/auto-auto-indent"))]) - (auto-compile . [(20230117 1612) ((emacs (25 1))) "Automatically compile Emacs Lisp libraries" single ((:commit . "4cbd304698a897baf438400c9a2b31d3dfb3a7f9") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "compile" "convenience" "lisp") (:url . "https://github.com/emacscollective/auto-compile"))]) + (auto-compile . [(20230312 1636) ((emacs (25 1))) "Automatically compile Emacs Lisp libraries" single ((:commit . "cdb60240000aff141fbe26f1487fbfe499ff64dc") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "compile" "convenience" "lisp") (:url . "https://github.com/emacscollective/auto-compile"))]) (auto-complete . [(20221231 1633) ((popup (0 5 0)) (cl-lib (0 5))) "Auto Completion for GNU Emacs" tar ((:commit . "59c11c453bfa0794302848a004d1be3b1684f17b") (:authors ("Tomohiro Matsuyama" . "m2ym.pub@gmail.com")) (:maintainer "Jen-Chieh Shen" . "jcs090218@gmail.com") (:keywords "completion" "convenience") (:url . "https://github.com/auto-complete/auto-complete"))]) (auto-complete-auctex . [(20140223 1758) ((yasnippet (0 6 1)) (auto-complete (1 4))) "auto-completion for auctex" single ((:commit . "855633f668bcc4b9408396742a7cb84e0c4a2f77") (:authors ("Christopher Monsanto" . "chris@monsan.to")) (:maintainer "Christopher Monsanto" . "chris@monsan.to"))]) (auto-complete-c-headers . [(20150912 323) ((auto-complete (1 4))) "An auto-complete source for C/C++ header files" single ((:commit . "52fef720c6f274ad8de52bef39a343421006c511") (:authors ("Masafumi Oyamada" . "stillpedant@gmail.com")) (:maintainer "Masafumi Oyamada" . "stillpedant@gmail.com") (:keywords "c"))]) @@ -215,7 +215,7 @@ (auto-complete-pcmp . [(20140303 255) ((auto-complete (1 4 0)) (log4e (0 2 0)) (yaxception (0 1))) "Provide auto-complete sources using pcomplete results" single ((:commit . "2595d3dab1ef3549271ca922f212928e9d830eec") (:authors ("Hiroaki Otsu" . "ootsuhiroaki@gmail.com")) (:maintainer "Hiroaki Otsu" . "ootsuhiroaki@gmail.com") (:keywords "completion") (:url . "https://github.com/aki2o/auto-complete-pcmp"))]) (auto-complete-rst . [(20140225 944) ((auto-complete (1 4))) "Auto-complete extension for ReST and Sphinx" tar ((:commit . "4803ce41a96224e6fa54e6741a5b5f40ebed7351") (:authors ("ARAKAKI, Takafumi")) (:maintainer "ARAKAKI, Takafumi") (:url . "https://github.com/tkf/auto-complete-rst"))]) (auto-complete-sage . [(20160514 751) ((auto-complete (1 5 1)) (sage-shell-mode (0 1 0))) "An auto-complete source for sage-shell-mode." single ((:commit . "51b8e3905196d266e1f8aa47881189833151b398") (:authors ("Sho Takemori" . "stakemorii@gmail.com")) (:maintainer "Sho Takemori" . "stakemorii@gmail.com") (:keywords "sage" "math" "auto-complete") (:url . "https://github.com/stakemori/auto-complete-sage"))]) - (auto-dark . [(20230204 129) ((emacs (24 4))) "Automatically sets the dark-mode theme based on macOS/Linux/Windows status" single ((:commit . "ca90fc638cfaf70d5e0b82657d3d26cd0b289059") (:authors ("Rahul M. Juliato") ("Tim Harper ") ("Vincent Zhang" . "seagle0128@gmail.com") ("Jonathan Arnett" . "jonathan.arnett@protonmail.com")) (:maintainer "Rahul M. Juliato") (:keywords "macos" "windows" "linux" "themes" "tools" "faces") (:url . "https://github.com/LionyxML/auto-dark-emacs"))]) + (auto-dark . [(20230307 17) ((emacs (24 4))) "Automatically sets the dark-mode theme based on macOS/Linux/Windows status" single ((:commit . "dcb5b4e6da8553c43b8ad7aff51de477980e23d8") (:authors ("Rahul M. Juliato") ("Tim Harper ") ("Vincent Zhang" . "seagle0128@gmail.com") ("Jonathan Arnett" . "jonathan.arnett@protonmail.com")) (:maintainer "Rahul M. Juliato") (:keywords "macos" "windows" "linux" "themes" "tools" "faces") (:url . "https://github.com/LionyxML/auto-dark-emacs"))]) (auto-dictionary . [(20150410 1610) nil "automatic dictionary switcher for flyspell" single ((:commit . "b364e08009fe0062cf0927d8a0582fad5a12b8e7") (:authors ("Nikolaj Schumacher ")) (:maintainer "Nikolaj Schumacher ") (:keywords "wp") (:url . "http://nschum.de/src/emacs/auto-dictionary/"))]) (auto-dim-other-buffers . [(20220209 2101) nil "Makes windows without focus less prominent" single ((:commit . "33b5f88b799a17947c266b04ad59462c5aeb4ed7") (:authors ("Michal Nazarewicz" . "mina86@mina86.com")) (:maintainer "Michal Nazarewicz" . "mina86@mina86.com") (:url . "https://github.com/mina86/auto-dim-other-buffers.el"))]) (auto-highlight-symbol . [(20221231 1631) ((emacs (26 1)) (ht (2 3))) "Automatic highlighting current symbol minor mode" single ((:commit . "ece5e2c722efa5c9ea32a809b484afc222ebebe5") (:authors ("Mitsuo Saito" . "arch320@NOSPAM.gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "highlight" "face" "match" "convenience") (:url . "http://github.com/jcs-elpa/auto-highlight-symbol"))]) @@ -228,13 +228,12 @@ (auto-rename-tag . [(20220704 639) ((emacs (24 4))) "Automatically rename paired HTML/XML tag" single ((:commit . "58ef595757350f4d8c1cea30d6902b26afaf8743") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "auto-complete" "html" "rename" "tag" "xml") (:url . "https://github.com/jcs-elpa/auto-rename-tag"))]) (auto-save-buffers-enhanced . [(20161109 710) nil "Automatically save buffers in a decent way" single ((:commit . "461e8c816c1b7c650be5f209078b381fe55da8c6") (:authors ("Kentaro Kuribayashi" . "kentarok@gmail.com")) (:maintainer "Kentaro Kuribayashi" . "kentarok@gmail.com"))]) (auto-shell-command . [(20180817 1502) ((deferred (20130312)) (popwin (20130329))) "Run the shell command asynchronously that you specified when you save the file." single ((:commit . "a8f9213e3c773b5687b81881240e6e648f2f56ba") (:authors ("ongaeshi")) (:maintainer "ongaeshi") (:keywords "shell" "save" "async" "deferred" "auto"))]) - (auto-sudoedit . [(20220421 1147) ((emacs (26 1)) (f (0 19 0))) "Auto sudo edit by tramp" single ((:commit . "39cb574a4b5ec74ad62857320bf5fec58abe876f") (:authors ("ncaq" . "ncaq@ncaq.net")) (:maintainer "ncaq" . "ncaq@ncaq.net") (:url . "https://github.com/ncaq/auto-sudoedit"))]) + (auto-sudoedit . [(20230323 650) ((emacs (26 1)) (f (0 19 0))) "Auto sudo edit by tramp" single ((:commit . "7ee72f31e762e225595e330c6108f3a69dbb0187") (:authors ("ncaq" . "ncaq@ncaq.net")) (:maintainer "ncaq" . "ncaq@ncaq.net") (:url . "https://github.com/ncaq/auto-sudoedit"))]) (auto-virtualenv . [(20220712 1612) ((cl-lib (0 5)) (pyvenv (1 9)) (s (1 10 0))) "Auto activate python virtualenvs" single ((:commit . "1e58a878984dbd2c91b4f128ded03fd954336907") (:authors ("Marcwebbie" . "marcwebbie@gmail.com")) (:maintainer "Marcwebbie" . "marcwebbie@gmail.com") (:keywords "python" "virtualenv" "tools") (:url . "http://github.com/marcwebbie/auto-virtualenv"))]) - (auto-virtualenvwrapper . [(20200510 1006) ((cl-lib (0 6)) (s (1 10 0)) (virtualenvwrapper (0))) "Lightweight auto activate python virtualenvs" single ((:commit . "30fb54aa3c99f3c614ea9a92669d634df30c9439") (:authors ("Marcwebbie" . "marcwebbie@gmail.com") ("Robert Zaremba" . "robert-zaremba@scale-it.pl")) (:maintainer "Marcwebbie" . "marcwebbie@gmail.com") (:keywords "python" "virtualenv" "tools"))]) + (auto-virtualenvwrapper . [(20230317 1313) ((cl-lib (1 0)) (s (1 13 0)) (virtualenvwrapper (0))) "Lightweight auto activate python virtualenvs" single ((:commit . "8cc2616af46d7e26c1d9ecea5fffd8974e5b1acb") (:authors ("Marcwebbie" . "marcwebbie@gmail.com") ("Robert Zaremba" . "robert-zaremba@scale-it.pl")) (:maintainer "Marcwebbie" . "marcwebbie@gmail.com") (:keywords "python" "virtualenv" "tools"))]) (auto-yasnippet . [(20230208 331) ((yasnippet (0 14 0)) (emacs (25 1))) "Quickly create disposable yasnippets" single ((:commit . "6a9e406d0d7f9dfd6dff7647f358cb05a0b1637e") (:authors ("Oleh Krehel" . "ohwoeowho@gmail.com") ("Jason Milkins" . "jasonm23@gmail.com")) (:maintainer "Jason Milkins" . "jasonm23@gmail.com") (:url . "https://github.com/abo-abo/auto-yasnippet"))]) (autobookmarks . [(20220509 1712) ((dash (2 10 0)) (cl-lib (0 5))) "Save recently visited files and buffers" single ((:commit . "8acd6f182181e23257e01c1b5cf90b872507a74d") (:authors ("Matúš Goljer" . "matus.goljer@gmail.com")) (:maintainer "Matúš Goljer" . "matus.goljer@gmail.com") (:keywords "files"))]) (autobuild . [(20200713 227) ((cl-lib (0 3)) (emacs (26 1))) "Define and execute build rules and compilation pipelines" single ((:commit . "6c10b13c285cc4180dc64c1f89ead264e6786f53") (:authors ("Ernesto Alfonso")) (:maintainer nil . "(concat \"erjoalgo\" \"@\" \"gmail\" \".com\")") (:keywords "compile" "build" "pipeline" "autobuild" "extensions" "processes" "tools") (:url . "https://github.com/erjoalgo/autobuild"))]) - (autocrypt . [(20221220 2359) ((emacs (24 3))) "Autocrypt implementation" tar ((:commit . "1444f1861fd13367bdf75ec60a83a94dd1802a49") (:authors ("Philip Kaludercic" . "philipk@posteo.net")) (:maintainer "Philip Kaludercic" . "~pkal/public-inbox@lists.sr.ht") (:keywords "comm") (:url . "https://git.sr.ht/~pkal/autocrypt"))]) (autodisass-java-bytecode . [(20211005 1920) nil "Automatically disassemble Java bytecode" tar ((:commit . "9eaddd63645e64825b2d07805999c5a645248c53") (:authors ("George Balatsouras ")) (:maintainer "George Balatsouras ") (:keywords "convenience" "data" "files"))]) (autodisass-llvm-bitcode . [(20150411 125) nil "Automatically disassemble LLVM bitcode" tar ((:commit . "14bb1bfe2be3b04d6e0c87a7a9d1e88ce15506d0") (:authors ("George Balatsouras ")) (:maintainer "George Balatsouras ") (:keywords "convenience" "data" "files"))]) (autotetris-mode . [(20141114 1646) ((cl-lib (0 5))) "automatically play tetris" single ((:commit . "7d348d33829bc89ddbd2b4d5cfe5073c3b0cbaaa") (:authors ("Christopher Wellons" . "wellons@nullprogram.com")) (:maintainer "Christopher Wellons" . "wellons@nullprogram.com") (:url . "https://github.com/skeeto/autotetris-mode"))]) @@ -242,7 +241,7 @@ (autumn-light-theme . [(20150515 1447) nil "A light color theme with muted, autumnal colors." single ((:commit . "26a52a79e7fff401af6d24c4365bb4a250c1136a") (:authors ("Adam Alpern" . "adam.alpern@gmail.com")) (:maintainer "Adam Alpern" . "adam.alpern@gmail.com") (:keywords "color" "theme") (:url . "http://github.com/aalpern/emacs-color-theme-autumn-light"))]) (avandu . [(20221106 834) nil "Gateway to Tiny Tiny RSS" tar ((:commit . "f064cd62f878d945cc2f202cda9a1a82b39d9e22") (:authors ("Tom Willemse" . "tom@ryuslash.org")) (:maintainer "Tom Willemse" . "tom@ryuslash.org") (:keywords "net"))]) (avk-emacs-themes . [(20220908 1022) nil "Collection of avk themes" tar ((:commit . "598a2a56601db1f474ed3f34a1cc4fb37921c21a") (:authors ("Alex V. Koval" . "alex@koval.kharkov.ua")) (:maintainer "Alex V. Koval" . "alex@koval.kharkov.ua") (:keywords "theme") (:url . "https://github.com/avkoval/avk-emacs-themes"))]) - (avy . [(20220910 1936) ((emacs (24 1)) (cl-lib (0 5))) "Jump to arbitrary positions in visible text and select text quickly." single ((:commit . "955c8dedd68c74f3cf692c1249513f048518c4c9") (:authors ("Oleh Krehel" . "ohwoeowho@gmail.com")) (:maintainer "Oleh Krehel" . "ohwoeowho@gmail.com") (:keywords "point" "location") (:url . "https://github.com/abo-abo/avy"))]) + (avy . [(20230316 2259) ((emacs (24 1)) (cl-lib (0 5))) "Jump to arbitrary positions in visible text and select text quickly." single ((:commit . "d9634efe2631b608cb28c420f54d6e6689805cf7") (:authors ("Oleh Krehel" . "ohwoeowho@gmail.com")) (:maintainer "Oleh Krehel" . "ohwoeowho@gmail.com") (:keywords "point" "location") (:url . "https://github.com/abo-abo/avy"))]) (avy-embark-collect . [(20230130 1454) ((emacs (25 1)) (embark (0 9)) (avy (0 5))) "Use avy to jump to Embark Collect entries" single ((:commit . "784ce24a1ad37459041418182af49565cad4974b") (:authors ("Omar Antolín Camarena" . "omar@matem.unam.mx")) (:maintainer "Omar Antolín Camarena" . "omar@matem.unam.mx") (:keywords "convenience") (:url . "https://github.com/oantolin/embark"))]) (avy-flycheck . [(20160720 1500) ((emacs (24 1)) (flycheck (0 14)) (seq (1 11)) (avy (0 4 0))) "Jump to and fix syntax errors using `flycheck' with `avy' interface" single ((:commit . "5522f3bbbed1801d9278ed696ec0cbba38352985") (:authors ("Xu Ma" . "magicdirac@gmail.com")) (:maintainer "Xu Ma" . "magicdirac@gmail.com") (:keywords "tools" "convenience" "avy" "flycheck") (:url . "https://github.com/magicdirac/avy-flycheck"))]) (avy-menu . [(20210321 1732) ((emacs (24 3)) (avy (0 4 0))) "Library providing avy-powered popup menu" single ((:commit . "2c5e0c08d6cb27c213a8eda5c7033e3ff2aa9661") (:authors ("Mark Karpov" . "markkarpov92@gmail.com")) (:maintainer "Mark Karpov" . "markkarpov92@gmail.com") (:keywords "popup" "menu") (:url . "https://github.com/mrkkrp/avy-menu"))]) @@ -253,7 +252,7 @@ (awscli-capf . [(20190930 1517) ((emacs (26))) "Completion at point function for the AWS CLI" single ((:commit . "1a75f88f53a2969fe821c31e6857861d0a0c0a5e") (:authors ("Sebastian Monia" . "smonia@outlook.com")) (:maintainer "Sebastian Monia" . "smonia@outlook.com") (:keywords "tools" "convenience" "abbrev") (:url . "https://github.com/sebasmonia/awscli-capf.git"))]) (axe . [(20230120 1915) ((emacs (25 1)) (hmac (0 0)) (request (0 3 2)) (s (1 12 0)) (xmlgen (0 5)) (dash (2 17 0)) (mimetypes (1 0))) "AWS Extensions" tar ((:commit . "5168d4f4c33861a071285df34f17fce92137d497") (:authors ("Craig Niles ")) (:maintainer "Craig Niles ") (:url . "https://github.com/cniles/axe"))]) (axiom-environment . [(20220612 1535) ((emacs (24 2))) "An environment for using Axiom/OpenAxiom/FriCAS" tar ((:commit . "01d88daa0c864af9918db5a147fbb5e435dec199") (:authors ("Paul Onions" . "paul.onions@acm.org")) (:maintainer "Paul Onions" . "paul.onions@acm.org") (:keywords "axiom" "openaxiom" "fricas"))]) - (ayu-theme . [(20200521 1157) ((emacs (24 1))) "Ayu theme" tar ((:commit . "ed98a9f41d9f0e08458ee71cc1038f66c50e1979") (:authors ("Tran Anh Vu")) (:maintainer "Tran Anh Vu") (:keywords "lisp" "theme" "emacs") (:url . "https://github.com/vutran1710/Ayu-Theme-Emacs"))]) + (ayu-theme . [(20230306 1924) ((emacs (24 1))) "Ayu theme" tar ((:commit . "dc325520c1202463a0f05d4ece1644109830fef4") (:authors ("Tran Anh Vu")) (:maintainer "Tran Anh Vu") (:keywords "lisp" "theme" "emacs") (:url . "https://github.com/vutran1710/Ayu-Theme-Emacs"))]) (babel . [(20210612 640) nil "interface to web translation services such as Babelfish" single ((:commit . "946e69c61188bc41793402ac48466d8967ddb43d") (:authors ("Juergen Hoetzel" . "juergen@hoetzel.info") ("Eric Marsden" . "emarsden@laas.fr")) (:maintainer "Juergen Hoetzel" . "juergen@hoetzel.info") (:keywords "translation" "web") (:url . "http://github.com/juergenhoetzel/babel"))]) (babel-repl . [(20160504 2201) ((emacs (24))) "Run babel REPL" single ((:commit . "0faa2f6518a2b46236f116ca1736a314f7d9c034") (:authors ("Hung Phan")) (:maintainer "Hung Phan") (:keywords "babel" "javascript" "es6") (:url . "https://github.com/hung-phan/babel-repl/"))]) (back-button . [(20220827 1733) ((nav-flash (1 0 0)) (smartrep (0 0 3)) (list-utils (0 4 2)) (persistent-soft (0 8 8)) (pcache (0 2 3))) "Visual navigation through mark rings" single ((:commit . "f8783c98a7fefc1d0419959c1b462c7dcadce5a8") (:authors ("Roland Walker" . "walker@pobox.com")) (:maintainer "Roland Walker" . "walker@pobox.com") (:keywords "convenience" "navigation" "interface") (:url . "http://github.com/rolandwalker/back-button"))]) @@ -271,13 +270,13 @@ (bap-mode . [(20200128 1354) nil "Major-mode for BAP's IR" single ((:commit . "8969679f60db0aa918d35f40d959c0a9c723b111") (:authors ("Thomas Barabosch ")) (:maintainer "Thomas Barabosch" . "thomas.barabosch@fkie.fraunhofer.de") (:keywords "languages") (:url . "https://github.com/fkie-cad/bap-mode"))]) (bar-cursor . [(20201204 2244) nil "package used to switch block cursor to a bar" single ((:commit . "78f195b6db63459033c4f1c7e7add5d82f3ce424") (:authors ("Joe Casadonte" . "emacs@northbound-train.com")) (:maintainer "Andrew Johnson" . "andrew@andrewjamesjohnson.com") (:keywords "files") (:url . "https://github.com/ajsquared/bar-cursor"))]) (bart-mode . [(20190601 1004) ((emacs (24 3))) "Real time BART departures info." single ((:commit . "f70b6c42452e47c0c6b3ebd4c90e555a9bedeec7") (:authors ("Michael Schuldt" . "mbschuldt@gmail.com")) (:maintainer "Michael Schuldt" . "mbschuldt@gmail.com") (:keywords "convenience" "transit") (:url . "https://github.com/mschuldt/bart-mode"))]) - (base16-theme . [(20221218 105) nil "Collection of themes built on combinations of 16 base colors" tar ((:commit . "d113012e4b76bb3ced331480bce33d03241e56bc") (:authors ("Kaleb Elwert" . "belak@coded.io") ("Neil Bhakta")) (:maintainer "Kaleb Elwert" . "belak@coded.io") (:url . "https://github.com/tinted-theming/base16-emacs"))]) - (bash-completion . [(20230208 1903) ((emacs (25 3))) "Bash completion for the shell buffer" single ((:commit . "25611eed1e086c4e8cdd335dbd38b1d796be5b8d") (:authors ("Stephane Zermatten" . "szermatt@gmx.net")) (:maintainer "Stephane Zermatten" . "szermatt@gmail.com") (:keywords "convenience" "unix") (:url . "http://github.com/szermatt/emacs-bash-completion"))]) + (base16-theme . [(20230326 110) nil "Collection of themes built on combinations of 16 base colors" tar ((:commit . "4843c8bb359746ed3a5dd269b1ab86410f9fffc1") (:authors ("Kaleb Elwert" . "belak@coded.io") ("Neil Bhakta")) (:maintainer "Kaleb Elwert" . "belak@coded.io") (:url . "https://github.com/tinted-theming/base16-emacs"))]) + (bash-completion . [(20230315 1918) ((emacs (25 3))) "Bash completion for the shell buffer" single ((:commit . "ae6560fe897ab6fcc0b1c4aac1ac084be5bc632e") (:authors ("Stephane Zermatten" . "szermatt@gmx.net")) (:maintainer "Stephane Zermatten" . "szermatt@gmail.com") (:keywords "convenience" "unix") (:url . "http://github.com/szermatt/emacs-bash-completion"))]) (basic-c-compile . [(20170302 1112) ((cl-lib (0 5)) (f (0 19 0))) "Quickly create a Makefile, compile and run C." single ((:commit . "335e96e19647ad7245fb68cf7e68cf86c5023d23") (:authors ("Nick Spain" . "nicholas.spain96@gmail.com")) (:maintainer "Nick Spain" . "nicholas.spain96@gmail.com") (:keywords "c" "makefile" "compilation" "convenience") (:url . "https://github.com/nick96/basic-c-compile"))]) (basic-ide . [(20230118 1040) ((emacs (25)) (basic-mode (0 4 2)) (company (0 9 12)) (flycheck (0 22)) (dash (2 12 0)) (f (0 17 0))) "BASIC IDE c64" single ((:commit . "e33036f838e61b647927165e81be5d5b855e0518") (:authors ("Fermin MF" . "fmfs@posteo.net")) (:maintainer "Fermin MF" . "fmfs@posteo.net") (:keywords "languages" "basic") (:url . "https://gitlab.com/sasanidas/emacs-c64-basic-ide"))]) - (basic-mode . [(20230213 1822) ((seq (2 20)) (emacs (25 1))) "Major mode for editing BASIC code" single ((:commit . "361dc1ea54bca3ab7a9ff36b64874dbe5c383382") (:authors ("Johan Dykstrom")) (:maintainer "Johan Dykstrom") (:keywords "basic" "languages") (:url . "https://github.com/dykstrom/basic-mode"))]) + (basic-mode . [(20230401 845) ((seq (2 20)) (emacs (25 1))) "Major mode for editing BASIC code" single ((:commit . "2971591510f08ab1645ed8a238b6ad086750f994") (:authors ("Johan Dykstrom")) (:maintainer "Johan Dykstrom") (:keywords "basic" "languages") (:url . "https://github.com/dykstrom/basic-mode"))]) (basic-theme . [(20160817 827) ((emacs (24))) "Minimalistic light color theme" single ((:commit . "9d0fd5f56898a5237c1de3363ad416aeab7f880e") (:authors ("Felix Geller" . "fgeller@gmail.com")) (:maintainer "Felix Geller" . "fgeller@gmail.com") (:keywords "theme" "basic" "minimal" "colors") (:url . "http://github.com/fgeller/basic-theme.el"))]) - (bats-mode . [(20160514 615) nil "Emacs mode for editing and running Bats tests" single ((:commit . "d519f7c89f5ae17dfc33400596df4564b478315f") (:authors ("Doug MacEachern")) (:maintainer "Doug MacEachern") (:keywords "bats" "tests") (:url . "https://github.com/dougm/bats-mode"))]) + (bats-mode . [(20230325 7) nil "Emacs mode for editing and running Bats tests" single ((:commit . "fa88930b1baba101ae6474f289a239a236a7d19f") (:authors ("Doug MacEachern")) (:maintainer "Doug MacEachern") (:keywords "bats" "tests") (:url . "https://github.com/dougm/bats-mode"))]) (battery-notifier . [(20220705 2030) ((alert (1 3))) "Notify when battery capacity is low" single ((:commit . "b7301d3633afff78609afd45dcf78268f98d52d3") (:authors ("Jason Johnson" . "jason@fullsteamlabs.com")) (:maintainer "Jason Johnson" . "jason@fullsteamlabs.com") (:keywords "hardware" "battery") (:url . "https://github.com/jasonmj/battery-notifier"))]) (battle-haxe . [(20210219 354) ((emacs (25)) (company (0 9 9)) (helm (3 0)) (async (1 9 3)) (cl-lib (0 5)) (dash (2 18 0)) (s (1 10 0)) (f (0 19 0))) "A Haxe development system, with code completion and more" single ((:commit . "2f32c81dcecfc68fd410cb9d2aca303d6e3028c7") (:authors ("Alon Tzarafi " . "alontzarafi@gmail.com")) (:maintainer "Alon Tzarafi " . "alontzarafi@gmail.com") (:keywords "programming" "languages" "completion") (:url . "https://github.com/AlonTzarafi/battle-haxe"))]) (bazel . [(20221105 2049) ((emacs (27 1))) "Bazel support for Emacs" single ((:commit . "68d58547dd1df92adc91715f97c3dcd125b00810") (:keywords "build tools" "languages") (:url . "https://github.com/bazelbuild/emacs-bazel-mode"))]) @@ -294,7 +293,7 @@ (bech32 . [(20221210 1154) ((emacs (26 1))) "Bech32 library" single ((:commit . "badbf267fa488df1cb87809ed234ebd67786f2f8") (:authors ("Oscar Najera ")) (:maintainer "Oscar Najera" . "hi@oscarnajera.com") (:url . "https://github.com/Titan-C/cardano.el"))]) (beef-mode . [(20221227 203) ((emacs (24 3))) "A major mode for the Beef programming language" single ((:commit . "20906b41630d74eba56504fbb9fabb79562e0d6e") (:authors ("XXIV")) (:maintainer "XXIV") (:keywords "files" "beef") (:url . "https://github.com/thechampagne/beef-mode"))]) (beeminder . [(20201227 2024) ((emacs (24 3)) (seq (2 16)) (org (7))) "Emacs interface for Beeminder" tar ((:commit . "161d9c94c594614a01cb08219693d9e000af4f69") (:authors ("Phil Newton" . "phil@sodaware.net")) (:maintainer "Phil Newton" . "phil@sodaware.net") (:keywords "tools" "beeminder") (:url . "http://www.philnewton.net/code/beeminder-el/"))]) - (beginend . [(20220824 1605) ((emacs (25 3))) "Redefine M-< and M-> for some modes" single ((:commit . "d0aec04c05911a0d47b34625959e1950ead4e4bd") (:url . "https://github.com/DamienCassou/beginend"))]) + (beginend . [(20230303 754) ((emacs (25 3))) "Redefine M-< and M-> for some modes" single ((:commit . "61f1eb22718fcd9796b47a98702d161ff323a532") (:url . "https://github.com/DamienCassou/beginend"))]) (belarus-holidays . [(20190102 1343) nil "Belarus holidays whith transfers" single ((:commit . "35a18273e19edc3b4c761030ffbd11116483b83e") (:authors ("Yauhen Makei" . "yauhen.makei@gmail.com")) (:maintainer "Yauhen Makei" . "yauhen.makei@gmail.com") (:url . "http://bitbucket.org/EugeneMakei/belarus-holidays.el"))]) (benchmark-init . [(20220414 1612) ((emacs (24 3))) "Benchmarks for require and load calls" tar ((:commit . "02435560415bbadbcf5051fb7042880549170e7e") (:authors ("Steve Purcell")) (:maintainer "David Holm" . "dholmster@gmail.com") (:keywords "convenience" "benchmark") (:url . "https://github.com/dholm/benchmark-init-el"))]) (benchstat . [(20171014 312) nil "proper benchmarking made simple" single ((:commit . "fee86f521f22ef0f99564903d63e2023b591fc7f") (:authors ("Iskander Sharipov" . "quasilyte@gmail.com")) (:maintainer "Iskander Sharipov" . "quasilyte@gmail.com") (:keywords "lisp") (:url . "https://github.com/Quasilyte/benchstat.el"))]) @@ -314,6 +313,7 @@ (bibliothek . [(20190124 1828) ((emacs (24 4)) (pdf-tools (0 70)) (a (0 1 0 -3 4))) "Managing a digital library of PDFs" single ((:commit . "b19b37be332bada6b18d4d895edf6ce78ab420c4") (:authors ("Göktuğ Kayaalp" . "self@gkayaalp.com")) (:maintainer "Göktuğ Kayaalp" . "self@gkayaalp.com") (:keywords "tools") (:url . "https://dev.gkayaalp.com/elisp/index.html#bibliothek-el"))]) (bibretrieve . [(20191124 1855) ((auctex (11 87)) (emacs (24 3))) "Retrieve BibTeX entries from the internet" tar ((:commit . "81dc8e0db3629cc180eafb2bc34b60dcd8980316") (:authors ("Antonio Sartori")) (:maintainer "Pavel Zorin-Kranich" . "pzorin@uni-bonn.de") (:keywords "bibtex" "bibliography" "mathscinet" "arxiv" "zbmath") (:url . "https://github.com/pzorin/bibretrieve"))]) (bibslurp . [(20151202 2346) ((s (1 6 0)) (dash (1 5 0))) "retrieve BibTeX entries from NASA ADS" single ((:commit . "aeba96368f2a06959e4fe945375ce2a54d34b189") (:keywords "bibliography" "nasa ads") (:url . "https://github.com/mkmcc/bibslurp"))]) + (bibtex-capf . [(20230226 2331) ((emacs (27 1)) (parsebib (3 0)) (org (9 5))) "Completion at point for bibtex --- *- lexical-binding: t -*-" single ((:commit . "7635fec3bc565acafbb6e1bff1cc711844f869ce") (:authors ("Colin McLear")) (:maintainer "Colin McLear") (:keywords "bibtex" "convenience") (:url . "https://github.com/mclear-tools/bibtex-capf"))]) (bibtex-completion . [(20221024 857) ((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))) "A BibTeX backend for completion frameworks" single ((:commit . "78f5931e1cc82e7ae2bcf0508cf31d0d1629a8dd") (:authors ("Titus von der Malsburg" . "malsburg@posteo.de") ("Justin Burkett" . "justin@burkett.cc")) (:maintainer "Titus von der Malsburg" . "malsburg@posteo.de") (:url . "https://github.com/tmalsburg/helm-bibtex"))]) (bibtex-utils . [(20190703 2117) nil "Provides utilities for extending BibTeX mode" single ((:commit . "26a8f0909b6adbf545a2b5e57ce7f779bf7a65af") (:authors ("Tyler Smith" . "tyler@plantarum.ca")) (:maintainer "Tyler Smith" . "tyler@plantarum.ca") (:keywords "bibtex") (:url . "https://github.com/plantarum/bibtex-utils"))]) (bicycle . [(20230212 2019) ((emacs (25 1)) (compat (29 1 3 4))) "Cycle outline and code visibility" single ((:commit . "20f0637365a9bf0a899a7663b1f8caec609de19a") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "outlines") (:url . "https://github.com/tarsius/bicycle"))]) @@ -332,9 +332,9 @@ (bitlbee . [(20151203 0) nil "Help get Bitlbee (http://www.bitlbee.org) up and running." single ((:commit . "f3342da46b0864ae8db4e82b553d9e617b090534"))]) (blackboard-bold-mode . [(20160813 206) ((cl-lib (0 5))) "Easily insert Unicode mathematical double-struck characters" single ((:commit . "5299cb064ba71baa3e331b8560bf8dd38cbbc4ed") (:authors ("Grant Rettke" . "gcr@wisdomandwonder.com")) (:maintainer nil . "") (:keywords "unicode" "double struck" "blackboard bold" "math" "mathematical") (:url . "https://github.com/grettke/blackboard-bold-mode"))]) (blackboard-theme . [(20161216 656) ((emacs (24))) "TextMate Blackboard Theme" single ((:commit . "d8b984f2541bb86eb4363a2b4c94631e49843d4a") (:authors ("Dong Zheng")) (:maintainer "Dong Zheng") (:url . "https://github.com/don9z/blackboard-theme"))]) - (blacken . [(20220922 2045) ((emacs (25 2))) "Reformat python buffers using the \"black\" formatter" single ((:commit . "456596e00f8277eafd9a08c62a71df06e8cad2c5") (:authors ("Artem Malyshev" . "proofit404@gmail.com")) (:maintainer "Artem Malyshev" . "proofit404@gmail.com") (:url . "https://github.com/proofit404/blacken"))]) + (blacken . [(20230224 1336) ((emacs (25 2))) "Reformat python buffers using the \"black\" formatter" single ((:commit . "1e80b970b130d5c33031f2539c89eb2f13da2572") (:authors ("Artem Malyshev" . "proofit404@gmail.com")) (:maintainer "Artem Malyshev" . "proofit404@gmail.com") (:url . "https://github.com/proofit404/blacken"))]) (blackout . [(20220509 2350) ((emacs (26))) "Better mode lighter overriding" single ((:commit . "7707211370f03f03a2f74df15f42ac24a1e99300") (:authors ("Radian LLC" . "contact+blackout@radian.codes")) (:maintainer "Radian LLC" . "contact+blackout@radian.codes") (:keywords "extensions") (:url . "https://github.com/radian-software/blackout"))]) - (blamer . [(20230113 2009) ((emacs (27 1)) (posframe (1 1 7))) "Show git blame info about current line" single ((:commit . "d1d5f2dc4d9cd5a47c47b55abb1f3b38911cc2d0") (:authors ("Artur Yaroshenko" . "artawower@protonmail.com")) (:maintainer "Artur Yaroshenko" . "artawower@protonmail.com") (:url . "https://github.com/artawower/blamer.el"))]) + (blamer . [(20230304 2300) ((emacs (27 1)) (posframe (1 1 7))) "Show git blame info about current line" single ((:commit . "50cd50d4541be22091b11d3f6dcf4e9f1b9521af") (:authors ("Artur Yaroshenko" . "artawower@protonmail.com")) (:maintainer "Artur Yaroshenko" . "artawower@protonmail.com") (:url . "https://github.com/artawower/blamer.el"))]) (blgrep . [(20150401 1416) ((clmemo (20140321 715))) "Block grep" tar ((:commit . "605beda210610a5829750a987f5fcebea97af546") (:authors ("Masayuki Ataka" . "masayuki.ataka@gmail.com")) (:maintainer "Masayuki Ataka" . "masayuki.ataka@gmail.com") (:keywords "tools" "convenience"))]) (blimp . [(20180903 2240) ((emacs (25)) (eimp (1 4 0))) "Bustling Image Manipulation Package" single ((:commit . "b048b037129b68674b99310bcc08fb96d44fdbb4") (:authors ("Sebastian Wålinder" . "s.walinder@gmail.com")) (:maintainer "Sebastian Wålinder" . "s.walinder@gmail.com") (:keywords "multimedia" "unix") (:url . "https://github.com/walseb/blimp"))]) (bliss-theme . [(20170808 1307) ((emacs (24 0))) "an Emacs 24 theme based on Bliss (tmTheme)" single ((:commit . "c3cf6d8a666ab26909b7da158f9e94df71a5fbbf") (:authors ("Jason Milkins")) (:maintainer "Jason Milkins") (:url . "https://github.com/emacsfodder/tmtheme-to-deftheme"))]) @@ -345,7 +345,7 @@ (blog-admin . [(20170923 1409) ((ctable (0 1 1)) (s (1 10 0)) (f (0 17 3)) (names (20151201 0)) (cl-lib (0 5))) "Blog admin for emacs with hexo/org-page supported" tar ((:commit . "b5f2e1dad7d68ec903619f7280bb0bcb7e398a1e") (:authors (nil . "code.falling@gmail.com")) (:maintainer nil . "code.falling@gmail.com") (:keywords "tools" "blog" "org" "hexo" "org-page"))]) (blog-minimal . [(20181021 849) ((ht (1 5)) (simple-httpd (1 4 6)) (mustache (0 22)) (s (1 11 0)) (org (9 0 3))) "a simple static site generator based on org mode" tar ((:commit . "a634a2db0b80cb445ef0b072d1a1482ced91f9ad") (:authors ("Thank Fly" . "thiefuniverses@gmail.com")) (:maintainer "Thank Fly" . "thiefuniverses@gmail.com") (:keywords "tools") (:url . "https://github.com/thiefuniverse/blog-minimal"))]) (blox . [(20220521 807) ((emacs (25 1))) "Interaction with Roblox tooling" single ((:commit . "9ebebb65fb38b5570ba8dfbb5ec835633c06b67d") (:authors ("Kenneth Loeffler" . "kenloef@gmail.com")) (:maintainer "Kenneth Loeffler" . "kenloef@gmail.com") (:keywords "roblox" "rojo" "tools") (:url . "https://github.com/kennethloeffler/blox"))]) - (bluesound . [(20221104 656) ((emacs (26 1))) "Play, pause, resume music on a Bluesound player" single ((:commit . "416b9825db5feea326388ca1bec2614046522006") (:authors ("R.W. van 't Veer")) (:maintainer "R.W. van 't Veer") (:keywords "convenience" "multimedia") (:url . "https://git.sr.ht/~rwv/bluesound-el/"))]) + (bluesound . [(20230328 1430) ((emacs (26 1))) "Play, pause, resume music on a Bluesound player" single ((:commit . "f6a43dbe8b5a3d4541170717571c793ae3313c98") (:authors ("R.W. van 't Veer")) (:maintainer "R.W. van 't Veer") (:keywords "convenience" "multimedia") (:url . "https://git.sr.ht/~rwv/bluesound-el/"))]) (bm . [(20210421 1351) nil "Visible bookmarks in buffer." tar ((:commit . "da9735f8b3f833a21b39a7bbfa7f563ba96429f3") (:authors ("Jo Odland ")) (:maintainer "Jo Odland ") (:keywords "bookmark" "highlight" "faces" "persistent") (:url . "https://github.com/joodland/bm"))]) (bmx-mode . [(20210319 620) ((emacs (25 1)) (cl-lib (0 5)) (company (0 9 4)) (dash (2 13 0)) (s (1 12 0))) "Batch Mode eXtras" single ((:commit . "6f008707efe0bb5646f0c1b0d6f57f0a8800e200") (:authors ("Jostein Kjønigsen" . "jostein@gmail.com")) (:maintainer "Jostein Kjønigsen" . "jostein@gmail.com") (:keywords "c" "convenience" "tools") (:url . "http://github.com/josteink/bmx-mode"))]) (bnf-mode . [(20221205 1451) ((cl-lib (0 5)) (emacs (25 1))) "Major mode for editing BNF grammars." tar ((:commit . "dcdb422e219b29d53a9385e19083441c57f0beb3") (:authors ("Serghei Iakovlev" . "egrep@protonmail.ch")) (:maintainer "Serghei Iakovlev" . "egrep@protonmail.ch") (:keywords "languages") (:url . "https://github.com/sergeyklay/bnf-mode"))]) @@ -358,23 +358,24 @@ (bookmark-in-project . [(20230116 1206) ((emacs (27 1))) "Bookmark access within a project" single ((:commit . "a1630443887c7fa190411c45269bde575f0807c5") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:keywords "convenience") (:url . "https://codeberg.org/ideasman42/emacs-bookmark-in-project"))]) (bookmark-view . [(20220403 2204) ((emacs (27 1))) "Bookmark views" single ((:commit . "0d40ac67f53b7fa75fe65c38a5ef65701ce4c3da") (:authors ("Daniel Mendler")) (:maintainer "Daniel Mendler") (:url . "https://github.com/minad/bookmark-view"))]) (bool-flip . [(20161215 1539) ((emacs (24 3))) "flip the boolean under the point" single ((:commit . "0f7cc9b387429239fb929896511727d4e49a795b") (:authors ("Michael Brandt" . "michaelbrandt5@gmail.com")) (:maintainer "Michael Brandt" . "michaelbrandt5@gmail.com") (:keywords "boolean" "convenience" "usability") (:url . "http://github.com/michaeljb/bool-flip/"))]) - (boon . [(20230214 2035) ((emacs (26 1)) (dash (2 12 0)) (expand-region (0 10 0)) (multiple-cursors (1 3 0))) "Ergonomic Command Mode for Emacs." tar ((:commit . "786cf085a9af60083279297c599d5ea0f744efba"))]) - (borg . [(20230215 1517) ((emacs (27 1)) (epkg (3 3 3)) (magit (3 3 0))) "Assimilate Emacs packages as Git submodules" tar ((:commit . "15a89056ceccb611c28aed8943faabec0539494a") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "tools") (:url . "https://github.com/emacscollective/borg"))]) + (boon . [(20230304 1502) ((emacs (26 1)) (dash (2 12 0)) (expand-region (0 10 0)) (multiple-cursors (1 3 0))) "Ergonomic Command Mode for Emacs." tar ((:commit . "1e85d6a11a756519dd4632b1bb2029a1e9c61f5a"))]) + (borg . [(20230319 1956) ((emacs (27 1)) (epkg (3 3 3)) (magit (3 3 0))) "Assimilate Emacs packages as Git submodules" tar ((:commit . "723ffe760d535618794d9e90ff17c18f66120131") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "tools") (:url . "https://github.com/emacscollective/borg"))]) (borland-blue-theme . [(20160117 1321) ((emacs (24 1))) "Blue/yellow theme based on old DOS Borland/Turbo C IDE" single ((:commit . "db74eefebbc89d3c62575f8f50b319e87b4a3470") (:authors ("Alexey Veretennikov ")) (:maintainer "Alexey Veretennikov ") (:keywords "themes") (:url . "http://github.com/fourier/borland-blue-theme"))]) (boron-theme . [(20170808 1308) ((emacs (24 0))) "an Emacs 24 theme based on Boron (tmTheme)" single ((:commit . "87ae1a765e07429fec25d2f29b004f84b52d2e0a") (:authors ("Jason Milkins")) (:maintainer "Jason Milkins") (:url . "https://github.com/emacsfodder/tmtheme-to-deftheme"))]) - (boxes . [(20221213 2047) ((emacs (24 3))) "ASCII boxes unlimited!" single ((:commit . "380e7814acb7de490a3b5729c3b943f875bc6a73") (:authors ("Jason L. Shiffer" . "jshiffer@zerotao.com")) (:maintainer "Jason L. Shiffer" . "jshiffer@zerotao.com") (:keywords "extensions") (:url . "https://boxes.thomasjensen.com"))]) + (boxes . [(20230326 1932) ((emacs (24 3))) "ASCII boxes unlimited!" single ((:commit . "77d02890a749a30bc228c848ec1d4bc9b09ac6c0") (:authors ("Jason L. Shiffer" . "jshiffer@zerotao.com")) (:maintainer "Jason L. Shiffer" . "jshiffer@zerotao.com") (:keywords "extensions") (:url . "https://boxes.thomasjensen.com"))]) (boxquote . [(20220919 714) ((cl-lib (0 5))) "Quote text with a semi-box." single ((:commit . "fe676396fa7e4372e01bf2c3d9a62e8d53615d46") (:authors ("Dave Pearson" . "davep@davep.org")) (:maintainer "Dave Pearson" . "davep@davep.org") (:keywords "quoting") (:url . "https://github.com/davep/boxquote.el"))]) (bpe . [(20141228 2205) ((emacs (24 1))) "Blog from Org mode to Blogger" single ((:commit . "7b5b25f83506e6c9f4075d3803fa32404943a189") (:authors ("Yuta Yamada ")) (:maintainer "Yuta Yamada ") (:keywords "blogger" "blog") (:url . "https://github.com/yuutayamada/bpe"))]) (bpftrace-mode . [(20190608 2201) ((emacs (24 0))) "Major mode for editing bpftrace script files" single ((:commit . "587b39ea7a1d786df5c04796d51bf2a5a4eda0d7") (:authors ("Jay Kamat" . "jaygkamat@gmail.com")) (:maintainer "Jay Kamat" . "jaygkamat@gmail.com") (:keywords "highlight" "c") (:url . "http://gitlab.com/jgkamat/bpftrace-mode"))]) (bpr . [(20180220 1844) ((emacs (24))) "Background Process Runner" tar ((:commit . "af84a83dea09d86e77d87ac30604f2c5b4bf4117") (:authors ("Ilya Babanov" . "ilya-babanov@ya.ru")) (:maintainer "Ilya Babanov" . "ilya-babanov@ya.ru") (:keywords "background" "async" "process" "management") (:url . "https://github.com/ilya-babanov/emacs-bpr"))]) - (bqn-mode . [(20230215 309) ((emacs (26 1))) "Emacs mode for BQN" tar ((:commit . "6089e141dd693f809673c518fa07283ffeadb734") (:authors ("Marshall Lochbaum" . "mwlochbaum@gmail.com")) (:maintainer "Marshall Lochbaum" . "mwlochbaum@gmail.com") (:url . "https://github.com/museoa/bqn-mode"))]) + (bqn-mode . [(20230407 210) ((emacs (26 1))) "Emacs mode for BQN" tar ((:commit . "87677284ae6d01b716f00cb858c22587da2becd3") (:authors ("Marshall Lochbaum" . "mwlochbaum@gmail.com")) (:maintainer "Marshall Lochbaum" . "mwlochbaum@gmail.com") (:url . "https://github.com/museoa/bqn-mode"))]) (bracketed-paste . [(20160407 2348) ((emacs (24 3))) "bracketed paste mode support within emacs -nw" single ((:commit . "843ce3bbb63d560face889e13a57a2f7543957d5") (:authors ("Takeshi Banse" . "takebi@laafc.net")) (:maintainer "Takeshi Banse" . "takebi@laafc.net") (:keywords "terminals"))]) (brainfuck-mode . [(20150113 842) ((langdoc (20130601 1450))) "Brainfuck mode for Emacs" single ((:commit . "36e69552bb3b97a4f888d362c59845651bd0d492") (:authors ("Tomoya Tanjo" . "ttanjo@gmail.com")) (:maintainer "Tomoya Tanjo" . "ttanjo@gmail.com") (:keywords "brainfuck" "langdoc") (:url . "https://github.com/tom-tan/brainfuck-mode/"))]) (brazilian-holidays . [(20220828 2348) ((emacs (26))) "Brazilian holidays" single ((:commit . "03206ea673df49c91a8f924db799620713d86240") (:authors ("Jaguaraquem A. Reinaldo" . "jaguar.adler@gmail.com")) (:maintainer "Jaguaraquem A. Reinaldo" . "jaguar.adler@gmail.com") (:keywords "calendar" "holidays" "brazilian") (:url . "https://github.com/jadler/brazilian-holidays"))]) - (brf . [(20230217 1851) ((fringe-helper (0 1 1)) (emacs (24 3))) "Brf-mode provides features from the legendary editor Brief" tar ((:commit . "3f31b81204dc919cb178df556feed497f3a2a4f5") (:authors ("Mike Woolley" . "mike@bulsara.com")) (:maintainer "Mike Woolley" . "mike@bulsara.com") (:keywords "brief" "crisp" "emulations") (:url . "https://bitbucket.org/MikeWoolley/brf-mode"))]) + (brec-mode . [(20230322 1406) ((emacs (24 3))) "A major mode for editing Breccian text" single ((:commit . "41a83edda400c34857aca5e91b651f2dfb0b8009") (:authors ("Michael Allan" . "mike@reluk.ca")) (:maintainer "Michael Allan" . "mike@reluk.ca") (:keywords "outlines" "wp") (:url . "http://reluk.ca/project/Breccia/Emacs/"))]) + (brf . [(20230321 1843) ((fringe-helper (0 1 1)) (emacs (24 3))) "Brf-mode provides features from the legendary editor Brief" tar ((:commit . "3113bfff9c73d5901e7a684a066bfa7a13ce8f6a") (:authors ("Mike Woolley" . "mike@bulsara.com")) (:maintainer "Mike Woolley" . "mike@bulsara.com") (:keywords "brief" "crisp" "emulations") (:url . "https://bitbucket.org/MikeWoolley/brf-mode"))]) (brightscript-mode . [(20220906 827) ((emacs (26 3))) "Major mode for editing Brightscript files" single ((:commit . "025d6f5a70752c62a28d4f86c053a283b3898a49") (:authors ("Daniel Mircea" . "daniel@viseztrance.com")) (:maintainer nil . "daniel@viseztrance.com") (:keywords "languages") (:url . "https://github.com/viseztrance/brightscript-mode"))]) (broadcast . [(20151205 212) ((emacs (24 4))) "Links buffers together for simultaneous editing." single ((:commit . "f6f9cd2e0e3f8c31d6b8e7446c27eb0e50b25f16") (:authors ("Russell Black" . "killdash9@github")) (:maintainer "Russell Black" . "killdash9@github") (:keywords "convenience" "frames" "link" "cursors") (:url . "https://github.com/killdash9/broadcast.el"))]) - (browse-at-remote . [(20230118 407) ((f (0 20 0)) (s (1 9 0)) (cl-lib (0 5))) "Open github/gitlab/bitbucket/stash/gist/phab/sourcehut page from Emacs" single ((:commit . "c020975a891438e278ad1855213d4f3d62c9fccb") (:authors ("Rustem Muslimov" . "r.muslimov@gmail.com")) (:maintainer "Rustem Muslimov" . "r.muslimov@gmail.com") (:keywords "github" "gitlab" "bitbucket" "gist" "stash" "phabricator" "sourcehut" "pagure") (:url . "https://github.com/rmuslimov/browse-at-remote"))]) + (browse-at-remote . [(20230223 554) ((f (0 20 0)) (s (1 9 0)) (cl-lib (0 5))) "Open github/gitlab/bitbucket/stash/gist/phab/sourcehut page from Emacs" single ((:commit . "1c2a565bb7275bf78f23d471e32dd8c696523b8c") (:authors ("Rustem Muslimov" . "r.muslimov@gmail.com")) (:maintainer "Rustem Muslimov" . "r.muslimov@gmail.com") (:keywords "github" "gitlab" "bitbucket" "gist" "stash" "phabricator" "sourcehut" "pagure") (:url . "https://github.com/rmuslimov/browse-at-remote"))]) (browse-kill-ring . [(20220410 1509) nil "interactively insert items from kill-ring" single ((:commit . "6e06736a8245a8cdf436f6585c71439239219836") (:authors ("Colin Walters" . "walters@verbum.org")) (:maintainer "browse-kill-ring" . "browse-kill-ring@tonotdo.com") (:keywords "convenience") (:url . "https://github.com/browse-kill-ring/browse-kill-ring"))]) (browse-url-dwim . [(20140731 1922) ((string-utils (0 3 2))) "Context-sensitive external browse URL or Internet search" single ((:commit . "11f1c53126619c7ef1bb5f5d6914ce0b3cce0e30") (:authors ("Roland Walker" . "walker@pobox.com")) (:maintainer "Roland Walker" . "walker@pobox.com") (:keywords "hypermedia") (:url . "http://github.com/rolandwalker/browse-url-dwim"))]) (brutalist-theme . [(20220507 909) nil "Brutalist theme" tar ((:commit . "bee6cb25819007e20cde2782a6fcb577028dd038") (:authors ("Gergely Nagy")) (:maintainer "Gergely Nagy") (:url . "https://git.madhouse-project.org/algernon/brutalist-theme.el"))]) @@ -390,7 +391,7 @@ (buffer-manage . [(20211122 1957) ((emacs (26 1)) (choice-program (0 13)) (dash (2 17 0))) "Manage buffers" tar ((:commit . "819bbfd9ae2f028361f484bc3b60d751623a2df5") (:authors ("Paul Landes")) (:maintainer "Paul Landes") (:keywords "internal" "maint") (:url . "https://github.com/plandes/buffer-manage"))]) (buffer-move . [(20220512 755) ((emacs (24 1))) "easily swap buffers" single ((:commit . "e7800b3ab1bd76ee475ef35507ec51ecd5a3f065") (:keywords "convenience") (:url . "https://github.com/lukhas/buffer-move/"))]) (buffer-ring . [(20220120 124) ((emacs (25 1)) (dynaring (0 3)) (s (1 12 0)) (ht (2 0))) "Rings and tori for buffer navigation" single ((:commit . "177d67238c4d126a0270585e21c0f03ae750ca2a") (:authors ("Mike Mattie" . "codermattie@gmail.com") ("Sid Kasivajhula" . "sid@countvajhula.com")) (:maintainer "Sid Kasivajhula" . "sid@countvajhula.com") (:url . "https://github.com/countvajhula/buffer-ring"))]) - (buffer-sets . [(20230220 2122) ((cl-lib (0 5))) "Sets of Buffers for Buffer Management" single ((:commit . "ac40dc72ffd9073f8425e833fda7d29cbce581c4") (:authors ("Samuel W. Flint" . "swflint@flintfam.org")) (:maintainer "Samuel W. Flint" . "swflint@flintfam.org") (:keywords "buffer-management") (:url . "https://git.sr.ht/~swflint/buffer-sets"))]) + (buffer-sets . [(20230319 1822) ((cl-lib (0 5))) "Sets of Buffers for Buffer Management" single ((:commit . "951e894ef96d533324f7f24c2a0def45ae89d558") (:authors ("Samuel W. Flint" . "swflint@flintfam.org")) (:maintainer "Samuel W. Flint" . "swflint@flintfam.org") (:keywords "buffer-management") (:url . "https://git.sr.ht/~swflint/buffer-sets"))]) (buffer-utils . [(20140512 1400) nil "Buffer-manipulation utility functions" single ((:commit . "32e1f23817b9c6caedb53e5359baad29e99eaa2b") (:authors ("Roland Walker" . "walker@pobox.com")) (:maintainer "Roland Walker" . "walker@pobox.com") (:keywords "extensions") (:url . "http://github.com/rolandwalker/buffer-utils"))]) (buffer-watcher . [(20170913 839) ((f (0 16 2)) (cl-lib (0 5))) "Easily run shell scripts per filetype/directory when a buffer is saved" single ((:commit . "b32c67c8a5d724257d759f4c903d0dedc32246ef") (:authors ("Nicolas Petton" . "nicolas@petton.fr")) (:maintainer "Nicolas Petton" . "nicolas@petton.fr"))]) (buffer-wrap . [(20220704 646) ((emacs (24 4))) "Wrap the beginning and the end of buffer" single ((:commit . "b6b2118f59b8152fa02bd0b09d65a1f8ade4141b") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "buffer" "tool" "wrap") (:url . "https://github.com/jcs-elpa/buffer-wrap"))]) @@ -409,9 +410,9 @@ (buster-snippets . [(20151125 1010) ((yasnippet (0 8 0))) "Yasnippets for the Buster javascript testing framework" tar ((:commit . "bb8769dae132659858e74d52f3f4e8790399423a") (:authors ("Magnar Sveen" . "magnars@gmail.com")) (:maintainer "Magnar Sveen" . "magnars@gmail.com") (:keywords "snippets"))]) (busybee-theme . [(20170719 928) nil "port of vim's mustang theme" single ((:commit . "66b2315b030582d0ebee605cf455d386d8c30fcd") (:authors ("martin haesler")) (:maintainer "martin haesler") (:url . "http://github.com/mswift42/busybee-theme"))]) (butler . [(20210928 230) ((deferred (0 3 2)) (json (1 2)) (emacs (24))) "Emacs client for Jenkins" tar ((:commit . "10943ccdf2030187b2f7bd97337d78acb7fd31c9") (:authors ("Ashton Kemerling" . "ashtonkemerling@gmail.com")) (:maintainer "Ashton Kemerling" . "ashtonkemerling@gmail.com") (:keywords "jenkins" "hudson" "ci") (:url . "http://www.github.com/AshtonKem/Butler.git"))]) - (buttercup . [(20230119 2337) ((emacs (24 3))) "Behavior-Driven Emacs Lisp Testing" tar ((:commit . "07a52c99695845a0089e828d43da154c0ba0c178") (:authors ("Jorgen Schaefer" . "contact@jorgenschaefer.de")) (:maintainer "Ola Nilsson" . "ola.nilsson@gmail.com") (:url . "https://github.com/jorgenschaefer/emacs-buttercup"))]) + (buttercup . [(20230309 2206) ((emacs (24 3))) "Behavior-Driven Emacs Lisp Testing" tar ((:commit . "c6693d3667a71e88f459002fecf61df74d9e18ac") (:authors ("Jorgen Schaefer" . "contact@jorgenschaefer.de")) (:maintainer "Ola Nilsson" . "ola.nilsson@gmail.com") (:url . "https://github.com/jorgenschaefer/emacs-buttercup"))]) (buttercup-junit . [(20190802 2258) ((emacs (24 3)) (buttercup (1 15))) "JUnit reporting for Buttercup" single ((:commit . "6bc28b6b0f36fb71b0915c9e45963c840c64a8df") (:authors ("Ola Nilsson" . "ola.nilsson@gmail.com")) (:maintainer "Ola Nilsson" . "ola.nilsson@gmail.com") (:keywords "tools" "test" "unittest" "buttercup" "ci") (:url . "https://bitbucket.org/olanilsson/buttercup-junit"))]) - (button-lock . [(20200309 1323) nil "Clickable text defined by regular expression" single ((:commit . "9afe0f4d05910b0cccc94cb6d4d880119f3b0528") (:authors ("Roland Walker" . "walker@pobox.com")) (:maintainer "Roland Walker" . "walker@pobox.com") (:keywords "mouse" "button" "hypermedia" "extensions") (:url . "http://github.com/rolandwalker/button-lock"))]) + (button-lock . [(20230304 2212) nil "Clickable text defined by regular expression" single ((:commit . "1f7a89ca05b6167af7d1337ad23a5d923486caac") (:authors ("Roland Walker" . "walker@pobox.com")) (:maintainer "Roland Walker" . "walker@pobox.com") (:keywords "mouse" "button" "hypermedia" "extensions") (:url . "http://github.com/rolandwalker/button-lock"))]) (buttons . [(20201123 2333) ((cl-lib (0 3))) "Define and visualize hierarchies of keymaps" single ((:commit . "de41b48244574a13000c4289fdb4216a2b0490ff") (:authors ("Ernesto Alfonso")) (:maintainer nil . "(concat \"erjoalgo\" \"@\" \"gmail\" \".com\")") (:keywords "keymap" "template" "snippet") (:url . "http://github.com/erjoalgo/emacs-buttons"))]) (c-c-combo . [(20151224 255) nil "Make stuff happen when you reach a target wpm" tar ((:commit . "a261a833499a7fdc29610863b3aafc74818770ba") (:authors ("Diego Berrocal" . "cestdiego@gmail.com")) (:maintainer "Diego Berrocal" . "cestdiego@gmail.com") (:url . "https://www.github.com/CestDiego/c-c-combo.el"))]) (c-eldoc . [(20201004 2347) nil "helpful description of the arguments to C functions" single ((:commit . "f4ede1f37f6de583376669735326367d84a0a917") (:authors ("Nathaniel Flath" . "flat0103@gmail.com")) (:maintainer "Nathaniel Flath" . "flat0103@gmail.com") (:url . "http://github.com/nflath/c-eldoc"))]) @@ -435,12 +436,12 @@ (calfw-ical . [(20170411 220) nil "calendar view for ical format" single ((:commit . "c538d3746449b4f0e16b16aad3073d4f7379d805") (:authors ("SAKURAI Masashi ")) (:maintainer "SAKURAI Masashi ") (:keywords "calendar"))]) (calfw-org . [(20170411 220) nil "calendar view for org-agenda" single ((:commit . "c538d3746449b4f0e16b16aad3073d4f7379d805") (:authors ("SAKURAI Masashi ")) (:maintainer "SAKURAI Masashi ") (:keywords "calendar" "org"))]) (calibredb . [(20230118 954) ((emacs (25 1)) (org (9 3)) (transient (0 1 0)) (s (1 12 0)) (dash (2 17 0)) (request (0 3 3)) (esxml (0 3 7))) "Yet another calibre client" tar ((:commit . "0ea8ccc41bbf4c6d105d9d2eddffa25d040f0e8d") (:authors ("Damon Chan" . "elecming@gmail.com")) (:maintainer "Damon Chan" . "elecming@gmail.com") (:keywords "tools") (:url . "https://github.com/chenyanming/calibredb.el"))]) - (call-graph . [(20230220 226) ((emacs (25 1)) (hierarchy (0 7 0)) (tree-mode (1 0 0)) (ivy (0 10 0))) "Generate call graph for c/c++ functions" tar ((:commit . "18a96dbabbedcd9e55817af7b6a0f303aea09faa") (:authors ("Huming Chen" . "chenhuming@gmail.com")) (:maintainer "Huming Chen" . "chenhuming@gmail.com") (:keywords "programming" "convenience") (:url . "https://github.com/beacoder/call-graph"))]) - (calmer-forest-theme . [(20130926 510) nil "Darkish theme with green/orange tint" single ((:commit . "31a0bed8e5db1e314557175a719a10804ac089f4") (:authors ("Artur Hefczyc, created 2003-04-18") ("David Caldwell" . "david@porkrind.org")) (:maintainer "Artur Hefczyc, created 2003-04-18") (:url . "https://github.com/caldwell/calmer-forest-theme"))]) + (call-graph . [(20230222 525) ((emacs (25 1)) (hierarchy (0 7 0)) (tree-mode (1 0 0)) (ivy (0 10 0)) (beacon (1 3 4))) "Generate call graph for c/c++ functions" tar ((:commit . "5fd5f3aad35e3561c253870e4d7fa34353b70b7b") (:authors ("Huming Chen" . "chenhuming@gmail.com")) (:maintainer "Huming Chen" . "chenhuming@gmail.com") (:keywords "programming" "convenience") (:url . "https://github.com/beacoder/call-graph"))]) + (calmer-forest-theme . [(20230302 2149) nil "Darkish theme with green/orange tint" single ((:commit . "09fc50730ea386d3589863f8809e02e5bdd459cf") (:authors ("Artur Hefczyc, created 2003-04-18") ("David Caldwell" . "david@porkrind.org")) (:maintainer "Artur Hefczyc, created 2003-04-18") (:url . "https://github.com/caldwell/calmer-forest-theme"))]) (camcorder . [(20190317 2138) ((emacs (24)) (names (20150000)) (cl-lib (0 5))) "Record screencasts in gif or other formats." single ((:commit . "b11ca61491a27681bb3131b72b51c105fd996bed") (:authors ("Artur Malabarba" . "bruce.connor.am@gmail.com")) (:maintainer "Artur Malabarba" . "bruce.connor.am@gmail.com") (:keywords "multimedia" "screencast") (:url . "http://github.com/Bruce-Connor/camcorder.el"))]) (caml . [(20230129 1145) ((emacs (24 3))) "Caml mode for GNU Emacs" tar ((:commit . "959a5a27bfdbaa43a9ff99be136d62e0798f5e01") (:authors ("Jacques Garrigue" . "garrigue@kurims.kyoto-u.ac.jp") ("Ian T Zimmerman" . "itz@rahul.net") ("Damien Doligez" . "damien.doligez@inria.fr")) (:maintainer "Christophe Troestler" . "Christophe.Troestler@umons.ac.be") (:keywords "ocaml") (:url . "https://github.com/ocaml/caml-mode"))]) (cangjie . [(20230219 1150) ((emacs (24 4)) (s (1 12 0)) (dash (2 14 1)) (f (0 2 0))) "Retrieve cangjie code for han characters" tar ((:commit . "d6882e15f47fdde37e9f739dde604d77d25f11db") (:keywords "convenience" "writing") (:url . "https://github.com/kisaragi-hiu/cangjie.el"))]) - (cape . [(20230215 717) ((emacs (27 1)) (compat (29 1 3 4))) "Completion At Point Extensions" tar ((:commit . "3e796a862d42743d33cd56fca041b6f2194db095") (:authors ("Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainer "Daniel Mendler" . "mail@daniel-mendler.de") (:url . "https://github.com/minad/cape"))]) + (cape . [(20230406 1657) ((emacs (27 1)) (compat (29 1 4 0))) "Completion At Point Extensions" tar ((:commit . "a49e50af8914f5101b3dce07e752516a8136f518") (:authors ("Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainer "Daniel Mendler" . "mail@daniel-mendler.de") (:url . "https://github.com/minad/cape"))]) (capnp-mode . [(20210707 2310) nil "Major mode for editing Capn' Proto Files" single ((:commit . "f7fccad7d737f77896211bec1173117497634143") (:authors ("Brian Taylor" . "el.wubo@gmail.com")) (:maintainer "Brian Taylor" . "el.wubo@gmail.com") (:url . "https://github.com/capnproto/capnproto"))]) (capture . [(20130828 1644) nil "screencasting with \"avconv\" or \"ffmpeg\"" tar ((:commit . "9140c207b48b3520a2f06674b3e1bee2fc92b80c") (:authors ("Sergey Pashinin ")) (:maintainer "Sergey Pashinin "))]) (carbon-now-sh . [(20220701 332) ((emacs (24 4))) "https://carbon.now.sh integration." single ((:commit . "e66f2e43e288f35ad9075f5fc84d59ad348efc88") (:authors ("Vitalii Elenhaupt")) (:maintainer "Vitalii Elenhaupt") (:keywords "convenience") (:url . "https://github.com/veelenga/carbon-now-sh.el"))]) @@ -456,25 +457,25 @@ (cask-package-toolset . [(20170921 2256) ((emacs (24)) (cl-lib (0 3)) (s (1 6 1)) (dash (1 8 0)) (f (0 10 0)) (commander (0 2 0)) (ansi (0 1 0)) (shut-up (0 1 0))) "Toolsettize your package" tar ((:commit . "2c74cd827e88c7f8360581a841e45f0b794510e7") (:authors ("Adrien Becchis" . "adriean.khisbe@live.fr")) (:maintainer "Adrien Becchis" . "adriean.khisbe@live.fr") (:keywords "convenience" "tools") (:url . "http://github.com/AdrieanKhisbe/cask-package-toolset.el"))]) (caskxy . [(20140513 1539) ((log4e (0 2 0)) (yaxception (0 1))) "Control Cask in Emacs" single ((:commit . "279f3ab79bd77fe69cb3148a79896b9bf118a9b3") (:authors ("Hiroaki Otsu" . "ootsuhiroaki@gmail.com")) (:maintainer "Hiroaki Otsu" . "ootsuhiroaki@gmail.com") (:keywords "convenience") (:url . "https://github.com/aki2o/caskxy"))]) (catmacs . [(20170826 1157) ((emacs (24))) "Simple CAT interface for Yaesu Transceivers." single ((:commit . "6ea9ee195661fe95355413856476c45dcc8e24e8") (:authors ("Frank Singleton" . "b17flyboy@gmail.com")) (:maintainer "Frank Singleton" . "b17flyboy@gmail.com") (:keywords "comm" "hardware") (:url . "https://bitbucket.org/pymaximus/catmacs"))]) - (catppuccin-theme . [(20230221 737) ((emacs (25 1))) "Catppuccin for Emacs - 🍄 Soothing pastel theme for Emacs" tar ((:commit . "046358639b3b6948f0779a16bef51cec44c606c3") (:authors ("nyxkrage")) (:maintainer "Carsten Kragelund" . "carsten@kragelund.me") (:url . "https://github.com/catppuccin/emacs"))]) + (catppuccin-theme . [(20230401 622) ((emacs (25 1))) "Catppuccin for Emacs - 🍄 Soothing pastel theme for Emacs" tar ((:commit . "fa9e421b5e041217d4841bea27384faa194deff6") (:authors ("nyxkrage")) (:maintainer "Carsten Kragelund" . "carsten@kragelund.me") (:url . "https://github.com/catppuccin/emacs"))]) (cbm . [(20171116 1240) ((cl-lib (0 5))) "Switch to similar buffers." single ((:commit . "5b41c936ba9f6d170309a85ffebc9939c1050b31") (:authors ("Lukas Fürmetz" . "fuermetz@mailbox.org")) (:maintainer "Lukas Fürmetz" . "fuermetz@mailbox.org") (:keywords "buffers") (:url . "http://github.com/akermu/cbm.el"))]) (cbor . [(20221225 1909) ((emacs (25 1))) "CBOR utilities" single ((:commit . "b369e8ac68c4cbabeb3a57f7db6bd44341523d72") (:authors ("Oscar Najera ")) (:maintainer "Oscar Najera" . "hi@oscarnajera.com") (:url . "https://github.com/Titan-C/cardano.el"))]) (cc-cedict . [(20210814 819) ((emacs (26 1))) "Interface to CC-CEDICT (a Chinese-English dictionary)" single ((:commit . "03fbe7d1589d36f627ef9fe7b86f9fe6f623cbb3") (:authors ("Xu Chunyang")) (:maintainer "Xu Chunyang") (:url . "https://github.com/xuchunyang/cc-cedict.el"))]) (ccc . [(20210501 820) nil "buffer local cursor color control library" single ((:commit . "36fb9f7e527f975d333887fd0cca4d611ae1ab23") (:authors ("Masatake YAMATO" . "masata-y@is.aist-nara.ac.jp")) (:maintainer "SKK Development Team") (:keywords "cursor") (:url . "https://github.com/skk-dev/ddskk"))]) (ccls . [(20230111 1754) ((emacs (25 1)) (lsp-mode (6 3 1)) (dash (2 14 1))) "ccls client for lsp-mode" tar ((:commit . "29d231590fad39b4d658d9262859e60669edb9b0") (:authors ("Tobias Pisani, Fangrui Song")) (:maintainer "Tobias Pisani, Fangrui Song") (:keywords "languages" "lsp" "c++") (:url . "https://github.com/MaskRay/emacs-ccls"))]) (cd-compile . [(20141108 1957) nil "run compile in a specific directory" single ((:commit . "10284ccae86afda4a37b09ba90acd1e2efedec9f") (:authors ("Jamie Nicol" . "jamie@thenicols.net")) (:maintainer "Jamie Nicol" . "jamie@thenicols.net"))]) - (cdb . [(20200904 1431) nil "constant database (cdb) reader for Emacs Lisp" single ((:commit . "2ce65eabea78d1eca10ae0ddf44f5769da1a36be") (:authors ("Yusuke Shinyama ")) (:maintainer "SKK Development Team") (:keywords "cdb") (:url . "https://github.com/skk-dev/ddskk"))]) + (cdb . [(20230318 2152) nil "constant database (cdb) reader for Emacs Lisp" single ((:commit . "3820fa6bb0d53132aafb611a643c1e41e444052b") (:authors ("Yusuke Shinyama ")) (:maintainer "SKK Development Team") (:keywords "cdb") (:url . "https://github.com/skk-dev/ddskk"))]) (cdlatex . [(20220829 1533) nil "Fast input methods for LaTeX environments and math" single ((:commit . "ac024ce29318cab812a743ad132a531c855c27a5") (:authors ("Carsten Dominik" . "carsten.dominik@gmail.com")) (:maintainer "Carsten Dominik" . "carsten.dominik@gmail.com") (:keywords "tex"))]) (cdnjs . [(20161031 1522) ((dash (2 13 0)) (deferred (0 4)) (f (0 17 2)) (pkg-info (0 5))) "A front end for http://cdnjs.com" single ((:commit . "ce19880d3ec3d81e6c665d0b1dfea99cc7a3f908") (:authors ("Yasuyuki Oka" . "yasuyk@gmail.com")) (:maintainer "Yasuyuki Oka" . "yasuyk@gmail.com") (:keywords "tools") (:url . "https://github.com/yasuyk/cdnjs.el"))]) (cedit . [(20200816 526) nil "paredit-like commands for c-like languages" single ((:commit . "cb38316903e6cfa8b8c978defa7e1dafcd4e0c12") (:authors ("zk_phi")) (:maintainer "zk_phi") (:url . "http://zk-phi.gitub.io/"))]) (celery . [(20170225 924) ((emacs (24)) (dash-functional (2 11 0)) (s (1 9 0)) (deferred (0 3 2))) "a minor mode to draw stats from celery and more?" single ((:commit . "b3378dd81e5a717432123fb13d70201da5dc841a") (:authors ("ardumont" . "eniotna.t@gmail.com")) (:maintainer "ardumont" . "eniotna.t@gmail.com") (:keywords "celery" "convenience") (:url . "https://github.com/ardumont/emacs-celery"))]) - (celestial-mode-line . [(20180518 822) ((emacs (24))) "Show lunar phase and sunrise/-set time in modeline" single ((:commit . "3f5794aca99b977f1592cf1ab4516ae7922196a1") (:authors ("Peter" . "craven@gmx.net")) (:maintainer "Peter" . "craven@gmx.net") (:keywords "extensions") (:url . "https://github.com/ecraven/celestial-mode-line"))]) + (celestial-mode-line . [(20230323 737) ((emacs (24))) "Show lunar phase and sunrise/-set time in modeline" single ((:commit . "90056322d6664e2e2b593912e4d5e68f1468cafc") (:authors ("Peter" . "craven@gmx.net")) (:maintainer "Peter" . "craven@gmx.net") (:keywords "extensions") (:url . "https://github.com/ecraven/celestial-mode-line"))]) (centaur-tabs . [(20230109 457) ((emacs (24 4)) (powerline (2 4)) (cl-lib (0 5))) "Aesthetic, modern looking customizable tabs plugin" tar ((:commit . "a2890d968d877b269a814a691356fc5877833c39") (:authors ("Emmanuel Bustos" . "ema2159@gmail.com")) (:maintainer "Emmanuel Bustos" . "ema2159@gmail.com") (:url . "https://github.com/ema2159/centaur-tabs"))]) (centered-cursor-mode . [(20200507 1529) nil "cursor stays vertically centered" single ((:commit . "e9ee518d314ef7fb105a1e0cdc33dbb4dfe9d9e4") (:authors ("André Riemann" . "andre.riemann@web.de")) (:maintainer "André Riemann" . "andre.riemann@web.de") (:keywords "convenience") (:url . "https://github.com/andre-r/centered-cursor-mode.el"))]) (centered-window . [(20220125 804) ((emacs (24 4))) "Center the text when there's only one window" single ((:commit . "80965f6c6afe8d918481433984b493de72af5399") (:authors ("Anler Hernández Peral" . "inbox+emacs@anler.me")) (:maintainer "Anler Hernández Peral" . "inbox+emacs@anler.me") (:keywords "faces" "windows") (:url . "https://github.com/anler/centered-window-mode"))]) (centimacro . [(20201225 1132) nil "Assign multiple macros as global key bindings" single ((:commit . "0149877584b333c4f1953f0767f0cae23881b0df") (:authors ("Oleh Krehel" . "ohwoeowho@gmail.com")) (:maintainer "Oleh Krehel" . "ohwoeowho@gmail.com") (:keywords "macros") (:url . "https://github.com/abo-abo/centimacro"))]) (cerbere . [(20181113 1641) ((pkg-info (0 5))) "Unit testing in Emacs for several programming languages" tar ((:commit . "bb18d932b16541105d41a668dbf6fc4e833a6dc2") (:authors ("Nicolas Lamirault" . "nicolas.lamirault@gmail.com")) (:maintainer "Nicolas Lamirault" . "nicolas.lamirault@gmail.com") (:keywords "python" "go" "php" "phpunit" "elisp" "ert" "tests" "tdd") (:url . "https://github.com/nlamirault/cerbere"))]) - (cern-ldap . [(20221014 1151) ((emacs (27 1))) "Library to interact with CERN's LDAP servers" single ((:commit . "0d188a997f24caaa3da748ad6ca16eb55cecff27") (:authors ("Nacho Barrientos" . "nacho.barrientos@cern.ch")) (:maintainer "Nacho Barrientos" . "nacho.barrientos@cern.ch") (:keywords "tools" "convenience") (:url . "https://git.sr.ht/~nbarrientos/cern-ldap.el"))]) + (cern-ldap . [(20230325 843) ((emacs (27 1))) "Library to interact with CERN's LDAP servers" single ((:commit . "ebb546221eed36616669ea4e42d35aa8b167202c") (:authors ("Nacho Barrientos" . "nacho.barrientos@cern.ch")) (:maintainer "Nacho Barrientos" . "nacho.barrientos@cern.ch") (:keywords "tools" "convenience") (:url . "https://git.sr.ht/~nbarrientos/cern-ldap.el"))]) (cern-root-mode . [(20220905 2016) ((emacs (26 1))) "Major-mode for running C++ code with ROOT" single ((:commit . "a54241681012b00b514fd20ff894e3c4c83b45c7") (:authors ("Jay Morgan" . "jay@morganwastaken.com")) (:maintainer "Jay Morgan" . "jay@morganwastaken.com") (:keywords "languages" "tools") (:url . "https://github.com/jaypmorgan/cern-root-mode"))]) (ceylon-mode . [(20180606 1324) ((emacs (25))) "Major mode for editing Ceylon source code" single ((:commit . "948515672bc596dc118e8e3ede3ede5ec6a3c95a") (:authors ("Lucas Werkmeister" . "mail@lucaswerkmeister.de")) (:maintainer "Lucas Werkmeister" . "mail@lucaswerkmeister.de") (:keywords "languages" "ceylon") (:url . "https://github.com/lucaswerkmeister/ceylon-mode"))]) (cfengine-code-style . [(20171111 1027) nil "C code style for CFEngine project." single ((:commit . "92a25872a6d1de00c5bfc2b9455ccb0082bf6569") (:authors ("Mikhail Gusarov" . "mikhail.gusarov@cfengine.com")) (:maintainer "Mikhail Gusarov" . "mikhail.gusarov@cfengine.com") (:url . "https://github.com/cfengine/core"))]) @@ -483,9 +484,10 @@ (cfn-mode . [(20220221 1029) ((emacs (26 0)) (f (0 20 0)) (s (1 12 0)) (yaml-mode (0 0 13))) "AWS cloudformation mode" tar ((:commit . "4cf56affe3035fda364109836e26499431095185") (:authors ("William Orr" . "will@worrbase.com")) (:maintainer "William Orr" . "will@worrbase.com") (:keywords "convenience" "languages" "tools") (:url . "https://gitlab.com/worr/cfn-mode"))]) (cframe . [(20201222 1930) ((emacs (26)) (buffer-manage (0 11)) (dash (2 17 0))) "Customize a frame and fast switch size and positions" single ((:commit . "38544521e82befc06e397123a118dd96dda2c6b6") (:authors ("Paul Landes")) (:maintainer "Paul Landes") (:keywords "frames") (:url . "https://github.com/plandes/cframe"))]) (cfrs . [(20220129 1149) ((emacs (26 1)) (dash (2 11 0)) (s (1 10 0)) (posframe (0 6 0))) "Child-frame based read-string" single ((:commit . "f3a21f237b2a54e6b9f8a420a9da42b4f0a63121") (:authors ("Alexander Miller" . "alexanderm@web.de")) (:maintainer "Alexander Miller" . "alexanderm@web.de") (:url . "https://github.com/Alexander-Miller/cfrs"))]) - (cg . [(20221007 1727) ((emacs (26 1))) "Major mode for editing Constraint Grammar files" single ((:commit . "a8a369f77d798bf65f65271256980a498fa43564") (:authors ("Kevin Brubeck Unhammer" . "unhammer@fsfe.org")) (:maintainer "Kevin Brubeck Unhammer" . "unhammer@fsfe.org") (:keywords "languages") (:url . "https://visl.sdu.dk/constraint_grammar.html"))]) + (cg . [(20230329 1235) ((emacs (26 1))) "Major mode for editing Constraint Grammar files" single ((:commit . "1a727582f4e929b9850e36adb8a52d6b4fb45075") (:authors ("Kevin Brubeck Unhammer" . "unhammer@fsfe.org")) (:maintainer "Kevin Brubeck Unhammer" . "unhammer@fsfe.org") (:keywords "languages") (:url . "https://visl.sdu.dk/constraint_grammar.html"))]) (challenger-deep-theme . [(20210120 941) ((emacs (24))) "challenger-deep Theme" single ((:commit . "2a799259406a8b96a688873093ffab6630a3ad3b") (:authors ("MaxSt")) (:maintainer "MaxSt") (:url . "https://github.com/challenger-deep-theme/emacs"))]) (change-inner . [(20210126 1456) ((expand-region (0 7))) "Change contents based on semantic units" single ((:commit . "42cad58aed2caec260f8e8ff61f78a7d3db72d1b") (:authors ("Magnar Sveen" . "magnars@gmail.com")) (:maintainer "Magnar Sveen" . "magnars@gmail.com") (:keywords "convenience" "extensions"))]) + (chaos-mode . [(20221227 223) ((emacs (24 3))) "A major mode for the Chaos programming language" single ((:commit . "801d869c461166eb2face2554b9b7883a26374c6") (:authors ("XXIV")) (:maintainer "XXIV") (:keywords "files" "chaos") (:url . "https://github.com/thechampagne/chaos-mode"))]) (chapel-mode . [(20210513 457) ((emacs (25 1)) (hydra (0 15 0))) "A major mode for the Chapel programming language" single ((:commit . "39fd24bb7cf44808200354ac0496be4fc4fddd9a") (:keywords "chapel" "chpl" "programming" "languages") (:url . "https://github.com/damon-kwok/chapel-mode"))]) (char-menu . [(20210321 1657) ((emacs (24 3)) (avy-menu (0 1))) "Create your own menu for fast insertion of arbitrary symbols" single ((:commit . "d77c4d64fc8acc386a0fb9727d346c838e75f011") (:authors ("Mark Karpov" . "markkarpov92@gmail.com")) (:maintainer "Mark Karpov" . "markkarpov92@gmail.com") (:keywords "convenience" "editing") (:url . "https://github.com/mrkkrp/char-menu"))]) (charmap . [(20200616 1418) nil "Unicode table for Emacs" single ((:commit . "feac50b87d2a596c5e5b7b82b79ddd65b6dedd8c") (:authors ("Anan Mikami" . "lateau@gmail.com")) (:maintainer "Anan Mikami" . "lateau@gmail.com") (:keywords "unicode" "character" "ucs") (:url . "https://github.com/lateau/charmap"))]) @@ -497,7 +499,7 @@ (cheerilee . [(20160313 1835) ((xelb (0 1))) "Toolkit library" tar ((:commit . "41bd81b5b0bb657241ceda5be6af5e07254d7376") (:authors ("Alessio Vanni" . "vannilla@firemail.cc")) (:maintainer "Alessio Vanni" . "vannilla@firemail.cc") (:keywords "multimedia" "tools") (:url . "https://github.com/Vannil/cheerilee.el"))]) (chef-mode . [(20180628 1453) nil "minor mode for editing an opscode chef repository" single ((:commit . "048d691cb63981ae235763d4a6ced4af5c729924") (:authors ("Maciej Pasternacki" . "maciej@pasternacki.net")) (:maintainer "Maciej Pasternacki" . "maciej@pasternacki.net") (:keywords "chef" "knife"))]) (chembalance . [(20210601 1653) ((emacs (24 4))) "Balance chemical equations" single ((:commit . "ae36c823ca151f1dc6144ec96b2f5e98181c0dbb") (:authors ("Sergi Ruiz Trepat")) (:maintainer "Sergi Ruiz Trepat") (:keywords "convenience" "chemistry") (:url . "https://github.com/sergiruiztrepat/chembalance"))]) - (chemtable . [(20220921 1721) ((emacs (24 1))) "Periodic table of the elements" single ((:commit . "ba9c3e2ebddf348da462d808fcbce88f37473fd9") (:authors ("Sergi Ruiz Trepat")) (:maintainer "Sergi Ruiz Trepat") (:keywords "convenience" "chemistry") (:url . "https://github.com/sergiruiztrepat/chemtable"))]) + (chemtable . [(20230314 1825) ((emacs (24 1))) "Periodic table of the elements" single ((:commit . "ca0fea2f28162e90a93be242279ec6aee9046475") (:authors ("Sergi Ruiz Trepat")) (:maintainer "Sergi Ruiz Trepat") (:keywords "convenience" "chemistry") (:url . "https://github.com/sergiruiztrepat/chemtable"))]) (cherry-blossom-theme . [(20150622 342) ((emacs (24 0))) "a soothing color theme for Emacs24." single ((:commit . "e5ea23694c0f20ab670c0aa87214c27f2232d922") (:authors ("Ben Yelsey" . "byelsey1@gmail.com")) (:maintainer "Ben Yelsey" . "byelsey1@gmail.com") (:url . "https://github.com/inlinestyle/emacs-cherry-blossom-theme"))]) (chezmoi . [(20230106 1716) ((emacs (26 1))) "A package for interacting with chezmoi" tar ((:commit . "0578f81ab01f5280e6c68d7a8a70ae4b4ba29755") (:authors ("Harrison Pielke-Lombardo")) (:maintainer "Harrison Pielke-Lombardo") (:keywords "vc") (:url . "http://www.github.com/tuh8888/chezmoi.el"))]) (chinese-conv . [(20170807 2128) ((cl-lib (0 5))) "Conversion between Chinese Characters with opencc or cconv" single ((:commit . "b56815bbb163d642e97fa73093b5a7e87cc32574") (:authors ("gucong" . "gucong43216@gmail.com")) (:maintainer "gucong" . "gucong43216@gmail.com") (:url . "https://github.com/gucong/emacs-chinese-conv"))]) @@ -507,15 +509,16 @@ (chinese-yasdcv . [(20171015 144) ((cl-lib (0 5)) (pyim (1 6 0))) "Yet another StarDict frontend" tar ((:commit . "5ab830daf1273d5a5cddcb94b56a9737f12d996f") (:authors ("Feng Shu" . "tumashu@gmail.com")) (:maintainer "Feng Shu" . "tumashu@gmail.com") (:keywords "convenience" "chinese" "dictionary") (:url . "https://github.com/tumashu/chinese-yasdcv"))]) (chocolate-theme . [(20210128 1647) ((emacs (24 1)) (autothemer (0 2))) "A dark chocolaty theme" single ((:commit . "ccc05f7ad96d3d1332727689bf6250443adc7ec0") (:url . "http://github.com/SavchenkoValeriy/emacs-chocolate-theme"))]) (choice-program . [(20201217 1751) ((emacs (26)) (dash (2 17 0))) "Parameter based program" tar ((:commit . "b8b1b6c5568f8778783454d5747912487c8e69b8") (:authors ("Paul Landes")) (:maintainer "Paul Landes") (:keywords "execution" "processes" "unix" "lisp") (:url . "https://github.com/plandes/choice-program"))]) + (chroma . [(20230327 1634) ((emacs (24 1))) "Color manipulation library" single ((:commit . "ace854e577a126f830443de89f617e5ff4b4cfce") (:authors ("Nicolas Martyanoff" . "nicolas@n16f.net")) (:maintainer "Nicolas Martyanoff" . "nicolas@n16f.net") (:url . "https://github.com/galdor/chroma"))]) (chronometer . [(20190304 1528) ((emacs (24))) "a [not so] simple chronometer" single ((:commit . "8457b296ef87be339cbe47730b922757d60bdcd5") (:authors ("Marcelo Toledo" . "marcelo@marcelotoledo.com")) (:maintainer "Marcelo Toledo" . "marcelo@marcelotoledo.com") (:keywords "tools" "convenience") (:url . "https://github.com/marcelotoledo/chronometer"))]) - (chronometrist . [(20230203 557) ((emacs (27 1)) (dash (2 16 0)) (seq (2 20)) (ts (0 2))) "Friendly and powerful personal time tracker and analyzer" tar ((:commit . "f131e996320715238e8403439a18dbc016b09520") (:authors ("contrapunctus" . "xmpp:contrapunctus@jabjab.de")) (:maintainer "contrapunctus" . "xmpp:contrapunctus@jabjab.de") (:keywords "calendar") (:url . "https://tildegit.org/contrapunctus/chronometrist"))]) + (chronometrist . [(20230302 700) ((emacs (27 1)) (dash (2 16 0)) (seq (2 20)) (ts (0 2))) "Friendly and powerful personal time tracker and analyzer" tar ((:commit . "015524bbeb4a112db7bb2af813408cc3c5c93240") (:authors ("contrapunctus" . "xmpp:contrapunctus@jabjab.de")) (:maintainer "contrapunctus" . "xmpp:contrapunctus@jabjab.de") (:keywords "calendar") (:url . "https://tildegit.org/contrapunctus/chronometrist"))]) (chronometrist-goal . [(20210510 1831) ((emacs (25 1)) (alert (1 2)) (chronometrist (0 7 0))) "Adds support for time goals to Chronometrist" single ((:commit . "6cb939d160f5d5966d7853aa23f3ed7c7ef9df44") (:authors ("contrapunctus" . "xmpp:contrapunctus@jabber.fr")) (:maintainer "contrapunctus" . "xmpp:contrapunctus@jabber.fr") (:keywords "calendar") (:url . "https://tildegit.org/contrapunctus/chronometrist-goal"))]) (chronometrist-key-values . [(20220414 726) ((chronometrist (0 7 0))) "add key-values to Chronometrist data" tar ((:commit . "9f970ebb637d57b3234b6e1e85840dcf524037e6") (:authors ("contrapunctus" . "xmpp:contrapunctus@jabjab.de")) (:maintainer "contrapunctus" . "xmpp:contrapunctus@jabjab.de") (:keywords "calendar") (:url . "https://tildegit.org/contrapunctus/chronometrist"))]) (chronometrist-spark . [(20220321 349) ((emacs (25 1)) (chronometrist (0 7 0)) (spark (0 1))) "Show sparklines in Chronometrist buffers" tar ((:commit . "239f733dd8f784a5251ae253d350a99fb739da6e") (:authors ("contrapunctus" . "xmpp:contrapunctus@jabjab.de")) (:maintainer "contrapunctus" . "xmpp:contrapunctus@jabjab.de") (:keywords "calendar") (:url . "https://tildegit.org/contrapunctus/chronometrist"))]) (chronos . [(20150602 1529) nil "multiple simultaneous countdown / countup timers" tar ((:commit . "b360d9dae57aa553cf2a14ffa0756a51ad71de09") (:authors ("David Knight" . "dxknight@opmbx.org")) (:maintainer "David Knight" . "dxknight@opmbx.org") (:keywords "calendar") (:url . "http://github.com/dxknight/chronos"))]) (chruby . [(20180114 1652) ((cl-lib (0 5))) "Emacs integration for chruby" single ((:commit . "42bc6d521f832eca8e2ba210f30d03ad5529788f") (:authors ("Arne Brasseur" . "arne@arnebrasseur.net")) (:maintainer "Arne Brasseur" . "arne@arnebrasseur.net") (:keywords "languages") (:url . "https://github.com/plexus/chruby.el"))]) (chyla-theme . [(20221213 1012) nil "chyla.org - green color theme." single ((:commit . "b24d0379516857ccf75caff9ae1d00b820c9a6f6") (:authors ("Adam Chyła" . "adam@chyla.org")) (:maintainer "Adam Chyła" . "adam@chyla.org") (:url . "https://github.com/chyla/ChylaThemeForEmacs"))]) - (cider . [(20230218 915) ((emacs (26)) (clojure-mode (5 16 0)) (parseedn (1 0 6)) (queue (0 2)) (spinner (1 7)) (seq (2 22)) (sesman (0 3 2))) "Clojure Interactive Development Environment that Rocks" tar ((:commit . "1ed5163433c991c00ea83fdd4447e8daf4aeccbe") (:authors ("Tim King" . "kingtim@gmail.com") ("Phil Hagelberg" . "technomancy@gmail.com") ("Bozhidar Batsov" . "bozhidar@batsov.dev") ("Artur Malabarba" . "bruce.connor.am@gmail.com") ("Hugo Duncan" . "hugo@hugoduncan.org") ("Steve Purcell" . "steve@sanityinc.com")) (:maintainer "Bozhidar Batsov" . "bozhidar@batsov.dev") (:keywords "languages" "clojure" "cider") (:url . "http://www.github.com/clojure-emacs/cider"))]) + (cider . [(20230405 731) ((emacs (26)) (clojure-mode (5 16 0)) (parseedn (1 0 6)) (queue (0 2)) (spinner (1 7)) (seq (2 22)) (sesman (0 3 2))) "Clojure Interactive Development Environment that Rocks" tar ((:commit . "b2d4769db33c000b7b49b94f31935faf4a229ce9") (:authors ("Tim King" . "kingtim@gmail.com") ("Phil Hagelberg" . "technomancy@gmail.com") ("Bozhidar Batsov" . "bozhidar@batsov.dev") ("Artur Malabarba" . "bruce.connor.am@gmail.com") ("Hugo Duncan" . "hugo@hugoduncan.org") ("Steve Purcell" . "steve@sanityinc.com")) (:maintainer "Bozhidar Batsov" . "bozhidar@batsov.dev") (:keywords "languages" "clojure" "cider") (:url . "http://www.github.com/clojure-emacs/cider"))]) (cider-decompile . [(20151122 537) ((cider (0 3 0)) (javap-mode (9))) "decompilation extension for cider" single ((:commit . "5d87035f3c3c14025e8f01c0c53d0ce2c8f56651") (:authors ("Dmitry Bushenko")) (:maintainer "Dmitry Bushenko") (:keywords "languages" "clojure" "cider") (:url . "http://www.github.com/clojure-emacs/cider-decompile"))]) (cider-eval-sexp-fu . [(20190311 2152) ((emacs (24)) (eval-sexp-fu (0 5 0))) "Briefly highlights an evaluated sexp." single ((:commit . "7fd229f1441356866aedba611fd0cf4e89b50921") (:authors ("Sylvain Benner" . "sylvain.benner@gmail.com")) (:maintainer "Sylvain Benner" . "sylvain.benner@gmail.com") (:keywords "languages" "clojure" "cider"))]) (cider-hydra . [(20190816 1121) ((cider (0 22 0)) (hydra (0 13 0))) "Hydras for CIDER." single ((:commit . "c3b8a15d72dddfbc390ab6a454bd7e4c765a2c95") (:authors ("Tianxiang Xiong" . "tianxiang.xiong@gmail.com")) (:maintainer "Tianxiang Xiong" . "tianxiang.xiong@gmail.com") (:keywords "convenience" "tools") (:url . "https://github.com/clojure-emacs/cider-hydra"))]) @@ -527,11 +530,11 @@ (circe . [(20221126 1508) ((emacs (25 1)) (cl-lib (0 5))) "Client for IRC in Emacs" tar ((:commit . "57fe189d7c0b98b9b1b5a59767cea1c7e2c22b13") (:authors ("Jorgen Schaefer" . "forcer@forcix.cx")) (:maintainer "Jorgen Schaefer" . "forcer@forcix.cx") (:keywords "irc" "chat" "comm") (:url . "https://github.com/emacs-circe/circe"))]) (circe-notifications . [(20180102 2318) ((emacs (24 4)) (circe (2 3)) (alert (1 2))) "Add desktop notifications to Circe." single ((:commit . "291149ac12877bbd062da993479d3533a26862b0") (:authors ("Ruben Maher" . "r@rkm.id.au")) (:maintainer "Ruben Maher" . "r@rkm.id.au") (:url . "https://github.com/eqyiel/circe-notifications"))]) (circleci-api . [(20210227 1607) ((emacs (27)) (request (0 3 2))) "Bindings for the CircleCI API" single ((:commit . "1432b0ad0f32b03fec564c0815951d5e096c2f6a") (:authors ("Robin Schroer")) (:maintainer "Robin Schroer") (:url . "https://github.com/sulami/circleci-api"))]) - (citar . [(20230218 2016) ((emacs (27 1)) (parsebib (4 2)) (org (9 5)) (citeproc (0 9))) "Citation-related commands for org, latex, markdown" tar ((:commit . "5dac3d5bf287566f049b44465e415afb42f30ec3") (:authors ("Bruce D'Arcus ")) (:maintainer "Bruce D'Arcus ") (:url . "https://github.com/emacs-citar/citar"))]) - (citar-denote . [(20230211 528) ((emacs (28 1)) (citar (1 0)) (denote (1 2))) "Minor mode to integrate Citar and Denote" single ((:commit . "3f8082fa68effced61a364a1ced333ed4fe33060") (:authors ("Peter Prevos" . "peter@prevos.net")) (:maintainer "Peter Prevos" . "peter@prevos.net") (:url . "https://github.com/pprevos/citar-denote"))]) - (citar-embark . [(20230216 1954) ((emacs (27 1)) (embark (0 17)) (citar (0 9 7))) "Citar/Embark integration" single ((:commit . "a5c769011288d0b1656784931de6ba06e64b2dd1") (:authors ("Bruce D'Arcus" . "bdarcus@gmail.com")) (:maintainer "Bruce D'Arcus" . "bdarcus@gmail.com") (:keywords "bib" "extensions") (:url . "https://github.com/emacs-citar/citar-embark"))]) - (citar-org-roam . [(20230211 117) ((emacs (27 1)) (org-roam (2 2)) (citar (1 0))) "Citar/org-roam integration" single ((:commit . "0690a34c84f3f483c723a69cc54e6a141e199c99") (:authors ("Bruce D'Arcus" . "bdarcus@gmail.com")) (:maintainer "Bruce D'Arcus" . "bdarcus@gmail.com") (:url . "https://github.com/emacs-citar/citar-org-roam"))]) - (citeproc . [(20230125 1818) ((emacs (26)) (dash (2 13 0)) (s (1 12 0)) (f (0 18 0)) (queue (0 2)) (string-inflection (1 0)) (org (9)) (parsebib (2 4))) "A CSL 1.0.2 Citation Processor" tar ((:commit . "2623043b2546ee09a4bd86641870ca86332c0bcf") (:authors ("András Simonyi" . "andras.simonyi@gmail.com")) (:maintainer "András Simonyi" . "andras.simonyi@gmail.com") (:keywords "bib") (:url . "https://github.com/andras-simonyi/citeproc-el"))]) + (citar . [(20230325 136) ((emacs (27 1)) (parsebib (4 2)) (org (9 5)) (citeproc (0 9))) "Citation-related commands for org, latex, markdown" tar ((:commit . "02034795f4c3bb46e782f8bd34dd486ce1fb9244") (:authors ("Bruce D'Arcus ")) (:maintainer "Bruce D'Arcus ") (:url . "https://github.com/emacs-citar/citar"))]) + (citar-denote . [(20230403 1038) ((emacs (28 1)) (citar (1 1)) (denote (1 2 0)) (dash (2 19 1))) "Minor mode to integrate Citar and Denote" single ((:commit . "327c7f386e8660c63b48568d23315cbebf95d151") (:authors ("Peter Prevos" . "peter@prevos.net")) (:maintainer "Peter Prevos" . "peter@prevos.net") (:url . "https://github.com/pprevos/citar-denote"))]) + (citar-embark . [(20230323 1926) ((emacs (27 1)) (embark (0 17)) (citar (0 9 7))) "Citar/Embark integration" single ((:commit . "0c6a8038e9b7f72c2e6837bd3342eab942c08d0d") (:authors ("Bruce D'Arcus" . "bdarcus@gmail.com")) (:maintainer "Bruce D'Arcus" . "bdarcus@gmail.com") (:keywords "bib" "extensions") (:url . "https://github.com/emacs-citar/citar-embark"))]) + (citar-org-roam . [(20230404 1225) ((emacs (27 1)) (org-roam (2 2)) (citar (1 2 0))) "Citar/org-roam integration" single ((:commit . "761eed66782fdbb6d65749098caa42ba43e8441d") (:authors ("Bruce D'Arcus" . "bdarcus@gmail.com")) (:maintainer "Bruce D'Arcus" . "bdarcus@gmail.com") (:url . "https://github.com/emacs-citar/citar-org-roam"))]) + (citeproc . [(20230228 1414) ((emacs (26)) (dash (2 13 0)) (s (1 12 0)) (f (0 18 0)) (queue (0 2)) (string-inflection (1 0)) (org (9)) (parsebib (2 4))) "A CSL 1.0.2 Citation Processor" tar ((:commit . "290320fc579f886255f00d7268600df7fa5cc7e8") (:authors ("András Simonyi" . "andras.simonyi@gmail.com")) (:maintainer "András Simonyi" . "andras.simonyi@gmail.com") (:keywords "bib") (:url . "https://github.com/andras-simonyi/citeproc-el"))]) (citeproc-org . [(20200915 2009) ((emacs (25 1)) (dash (2 12 0)) (org (9)) (f (0 18 0)) (citeproc (0 1)) (org-ref (1 1 1))) "Render org-mode references in CSL styles" tar ((:commit . "22a759c4f0ec80075014dcc594baa4d1b470d995") (:authors ("András Simonyi" . "andras.simonyi@gmail.com")) (:maintainer "András Simonyi" . "andras.simonyi@gmail.com") (:keywords "org-ref" "org-mode" "cite" "bib") (:url . "https://github.com/andras-simonyi/citeproc-org"))]) (citre . [(20230217 1202) ((emacs (26 1))) "Ctags IDE on the True Editor" tar ((:commit . "4626ada80fabea6b62935567acc1cb8dad607016") (:authors ("Hao Wang" . "amaikinono@gmail.com")) (:maintainer "Hao Wang" . "amaikinono@gmail.com") (:keywords "convenience" "tools") (:url . "https://github.com/universal-ctags/citre"))]) (cl-format . [(20210831 530) nil "CL format routine." tar ((:commit . "ad1a4fb6bc91e65ea90bcf6792cc5a1be5380f9d") (:authors ("Andreas Politz" . "politza@fh-trier.de")) (:maintainer "akater" . "nuclearspace@gmail.com") (:keywords "extensions") (:url . "https://gitlab.com/akater/elisp-cl-format"))]) @@ -539,6 +542,7 @@ (clang-capf . [(20221030 1830) ((emacs (24 4))) "Completion-at-point backend for c/c++ using clang" single ((:commit . "5e4dfba90ce86bbc7ee61805edfca04fff93c291") (:authors ("Philip K. ")) (:maintainer "Philip K. ") (:keywords "c" "abbrev" "convenience") (:url . "https://git.sr.ht/~pkal/clang-capf"))]) (clang-format . [(20191106 950) ((cl-lib (0 3))) "Format code using clang-format" single ((:commit . "e48ff8ae18dc7ab6118c1f6752deb48cb1fc83ac") (:keywords "tools" "c"))]) (clang-format+ . [(20190824 2216) ((emacs (25 1)) (clang-format (20180406 1514))) "Minor mode for automatic clang-format application" single ((:commit . "ddd4bfe1a13c2fd494ce339a320a51124c1d2f68") (:keywords "c" "c++" "clang-format") (:url . "https://github.com/SavchenkoValeriy/emacs-clang-format-plus"))]) + (clause . [(20230405 1235) ((emacs (27 1)) (mark-thing-at (0 3))) "Functions to move, mark, kill by clause" single ((:commit . "0ea166fa218618c1b80b60c995f927310c25b02a") (:authors ("Marty Hiatt ")) (:maintainer "Marty Hiatt ") (:keywords "wp" "convenience" "sentences" "text") (:url . "https://codeberg.org/martianh/clause.el"))]) (clean-aindent-mode . [(20171017 2043) nil "Simple indent and unindent, trims indent white-space" single ((:commit . "a97bcae8f43a9ff64e95473e4ef0d8bafe829211") (:authors ("peter marinov" . "efravia@gmail.com")) (:maintainer "peter marinov" . "efravia@gmail.com") (:keywords "indentation" "whitespace" "backspace") (:url . "https://github.com/pmarinov/clean-aindent-mode"))]) (clean-buffers . [(20160529 2259) ((cl-lib (0 5))) "clean useless buffers" single ((:commit . "1be6c54e3095761b6b64bf749faae3dfce94e72a") (:authors ("DarkSun" . "lujun9972@gmail.com")) (:maintainer "DarkSun" . "lujun9972@gmail.com") (:keywords "convenience" "usability" "buffers"))]) (clean-kill-ring . [(20230115 2153) ((emacs (24 4))) "Keep the kill ring clean" single ((:commit . "d05fa7ee97e760d21d533261c7b63eecf223f612") (:authors ("Nicholas Hubbard" . "nicholashubbard@posteo.net")) (:maintainer "Nicholas Hubbard" . "nicholashubbard@posteo.net") (:keywords "kill-ring" "convenience") (:url . "http://github.com/NicholasBHubbard/clean-kill-ring.el"))]) @@ -567,24 +571,24 @@ (clojars . [(20180825 1951) ((request-deferred (0 2 0))) "clojars.org search interface" single ((:commit . "c78e4d5ddacda064c253e2b38d1c35188aa1ad71") (:authors ("Joshua Miller" . "josh@joshmiller.io")) (:maintainer "Joshua Miller" . "josh@joshmiller.io") (:keywords "docs" "help" "tools") (:url . "https://github.com/joshuamiller/clojars.el"))]) (clojure-essential-ref . [(20221215 1427) ((emacs (24)) (cider (0 24 0))) "Cider-doc to \"Clojure, The Essential Reference\"" single ((:commit . "6741bf65cf9b9bc896ab1cc3c384573e8ffe5f96") (:url . "https://github.com/p3r7/clojure-essential-ref"))]) (clojure-essential-ref-nov . [(20221215 1427) ((emacs (24)) (dash (2 16 0)) (nov (0 3 1)) (clojure-essential-ref (0 1 0))) "Cider-doc to \"Clojure, The Essential Reference\" (EPUB)" single ((:commit . "6741bf65cf9b9bc896ab1cc3c384573e8ffe5f96") (:url . "https://github.com/p3r7/clojure-essential-ref"))]) - (clojure-mode . [(20221214 915) ((emacs (25 1))) "Major mode for Clojure code" single ((:commit . "3453cd229b412227aaffd1dc2870fa8fa213c5b1") (:maintainer "Bozhidar Batsov" . "bozhidar@batsov.dev") (:keywords "languages" "clojure" "clojurescript" "lisp") (:url . "http://github.com/clojure-emacs/clojure-mode"))]) + (clojure-mode . [(20230314 758) ((emacs (25 1))) "Major mode for Clojure code" single ((:commit . "906d6a47a646d1191eaead6f8e1ae0810aa9b626") (:maintainer "Bozhidar Batsov" . "bozhidar@batsov.dev") (:keywords "languages" "clojure" "clojurescript" "lisp") (:url . "http://github.com/clojure-emacs/clojure-mode"))]) (clojure-mode-extra-font-locking . [(20221214 915) ((clojure-mode (3 0))) "Extra font-locking for Clojure mode" single ((:commit . "3453cd229b412227aaffd1dc2870fa8fa213c5b1") (:authors ("Bozhidar Batsov" . "bozhidar@batsov.dev")) (:maintainer "Bozhidar Batsov" . "bozhidar@batsov.dev") (:keywords "languages" "lisp") (:url . "http://github.com/clojure-emacs/clojure-mode"))]) (clojure-quick-repls . [(20150814 736) ((cider (0 8 1)) (dash (2 9 0))) "Quickly create Clojure and ClojureScript repls for a project." single ((:commit . "8fe4e44939e8a01a4cdf60c0001d9a6abf8a73c3") (:keywords "languages" "clojure" "cider" "clojurescript") (:url . "https://github.com/symfrog/clojure-quick-repls"))]) (clojure-snippets . [(20220914 950) ((yasnippet (0 10 0))) "Yasnippets for clojure" tar ((:commit . "66d23f0ffedf2cc2be0387c3504b5f89d7300cfa") (:authors ("Max Penet" . "m@qbits.cc")) (:maintainer "Max Penet" . "m@qbits.cc") (:keywords "snippets"))]) (clomacs . [(20220415 1035) ((emacs (24 3)) (cider (0 22 1)) (s (1 12 0)) (simple-httpd (1 4 6)) (dash (2 19 1))) "Simplifies Emacs Lisp interaction with Clojure." single ((:commit . "9cd7c9fd86bc7bc627a31275d1ef131378b90a49") (:authors ("Kostafey" . "kostafey@gmail.com")) (:maintainer "Kostafey" . "kostafey@gmail.com") (:keywords "clojure" "interaction") (:url . "https://github.com/clojure-emacs/clomacs"))]) - (closql . [(20230220 1944) ((emacs (25 1)) (compat (29 1 3 4)) (emacsql (20230220))) "Store EIEIO objects using EmacSQL" single ((:commit . "b670b88c6f2785ddfdff91439ceb332b1bf8a8ce") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "extensions") (:url . "https://github.com/emacscollective/closql"))]) + (closql . [(20230224 1619) ((emacs (25 1)) (compat (29 1 3 4)) (emacsql (20230220))) "Store EIEIO objects using EmacSQL" single ((:commit . "0a7226331ff1f96142199915c0ac7940bac4afdd") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "extensions") (:url . "https://github.com/emacscollective/closql"))]) (closure-lint-mode . [(20101118 2124) nil "minor mode for the Closure Linter" single ((:commit . "bc3d2fd5c35580bf1b8af43b12484c95a343b4b5") (:authors ("Roman Scherer" . "roman@burningswell.com")) (:maintainer "Roman Scherer" . "roman@burningswell.com") (:keywords "tools" "closure" "javascript" "lint" "flymake") (:url . "https://github.com/r0man/closure-lint-mode"))]) (cloud-theme . [(20220205 1336) ((emacs (24))) "A light colored theme" single ((:commit . "16ef7fbf0a423b29e3c3a0a2d9525afaf265aaed") (:authors ("Valerii Lysenko" . "vallyscode@gmail.com")) (:maintainer "Valerii Lysenko" . "vallyscode@gmail.com") (:keywords "color" "theme") (:url . "https://github.com/vallyscode/cloud-theme"))]) (cloud-to-butt-erc . [(20130627 2308) nil "Replace 'the cloud' with 'my butt'" single ((:commit . "6710c03d1bc91736435cbfe845924940cae34e5c") (:authors ("David Leatherman" . "leathekd@gmail.com")) (:maintainer "David Leatherman" . "leathekd@gmail.com") (:url . "http://www.github.com/leathekd/cloud-to-butt-erc"))]) (clues-theme . [(20161213 1127) ((emacs (24 0))) "an Emacs 24 theme which may well be fully awesome..." single ((:commit . "abd61f2b7f3e98de58ca26e6d1230e70c6406cc7") (:authors ("Jason Milkins" . "jasonm23@gmail.com")) (:maintainer "Jason Milkins" . "jasonm23@gmail.com") (:url . "https://github.com/emacsfodder/emacs-clues-theme"))]) (cm-mode . [(20170203 2107) ((cl-lib (0 5))) "Minor mode for CriticMarkup" single ((:commit . "276d49c859822265070ae5dfbb403fd7d8d06436") (:authors ("Joost Kremers" . "joostkremers@fastmail.fm")) (:maintainer "Joost Kremers" . "joostkremers@fastmail.fm") (:keywords "text" "markdown"))]) - (cmake-font-lock . [(20211224 2006) ((cmake-mode (0 0))) "Advanced, type aware, highlight support for CMake" single ((:commit . "0d6111b36a66013aa9b452e664c93308df3b07e1") (:authors ("Anders Lindgren")) (:maintainer "Anders Lindgren") (:keywords "faces" "languages") (:url . "https://github.com/Lindydancer/cmake-font-lock"))]) + (cmake-font-lock . [(20230304 2223) ((cmake-mode (0 0))) "Advanced, type aware, highlight support for CMake" single ((:commit . "a6038e916bcca807ae695f7d7e5c300c3f38f415") (:authors ("Anders Lindgren")) (:maintainer "Anders Lindgren") (:keywords "faces" "languages") (:url . "https://github.com/Lindydancer/cmake-font-lock"))]) (cmake-ide . [(20210610 1525) ((emacs (24 4)) (cl-lib (0 5)) (seq (1 11)) (levenshtein (0)) (s (1 11 0))) "Calls CMake to find out include paths and other compiler flags" single ((:commit . "28dc4ab5bd01d99553901b4efeb7234280928b18") (:authors ("Atila Neves" . "atila.neves@gmail.com")) (:maintainer "Atila Neves" . "atila.neves@gmail.com") (:keywords "languages") (:url . "http://github.com/atilaneves/cmake-ide"))]) - (cmake-mode . [(20230215 1434) ((emacs (24 1))) "major-mode for editing CMake sources" single ((:commit . "037975ef69a0e889f9c17e5e6e6fb87111dfd9df"))]) + (cmake-mode . [(20230404 1329) ((emacs (24 1))) "major-mode for editing CMake sources" single ((:commit . "9831bb160ac94a92ce3f3a4ebea0948971f62f98"))]) (cmake-project . [(20171121 1115) nil "Integrates CMake build process with Emacs" single ((:commit . "d3f408f226eff3f77f7e00dd519f4efc78fd292d") (:authors ("Alexander Lamaison" . "alexander.lamaison@gmail")) (:maintainer "Alexander Lamaison" . "alexander.lamaison@gmail") (:keywords "c" "cmake" "languages" "tools") (:url . "http://github.com/alamaison/emacs-cmake-project"))]) (cmd-to-echo . [(20161203 2133) ((emacs (24 4)) (s (1 11 0)) (shell-split-string (20151224 208))) "Show the output of long-running commands in the echo area" single ((:commit . "e0e874fc0e1ad6d291e39ed76023445297ad438a") (:authors ("Tijs Mallaerts" . "tijs.mallaerts@gmail.com")) (:maintainer "Tijs Mallaerts" . "tijs.mallaerts@gmail.com"))]) (cmm-mode . [(20150225 746) nil "Major mode for C-- source code" single ((:commit . "c3ad514dff3eb30434f6b20d953276d4c00de1ee"))]) - (cnfonts . [(20230216 803) ((emacs (24))) "A simple Chinese fonts config tool" tar ((:commit . "4b1bbf854009992858e86a19de49b8dc91e924eb") (:authors ("Feng Shu" . "tumashu@163.com")) (:maintainer "Feng Shu" . "tumashu@163.com") (:keywords "convenience" "chinese" "font") (:url . "https://github.com/tumashu/cnfonts"))]) + (cnfonts . [(20230228 631) ((emacs (24))) "A simple Chinese fonts config tool" tar ((:commit . "ca8ea16ac3a6faec4ff4cd20514e7d2cffdd70a2") (:authors ("Feng Shu" . "tumashu@163.com")) (:maintainer "Feng Shu" . "tumashu@163.com") (:keywords "convenience" "chinese" "font") (:url . "https://github.com/tumashu/cnfonts"))]) (cobalt . [(20180304 1155) ((emacs (24))) "Easily use the Cobalt.rs static site generator" single ((:commit . "634ace275697e188746ca22a30ff94380ec756be") (:authors ("Juan Karlo Licudine" . "accidentalrebel@gmail.com")) (:maintainer "Juan Karlo Licudine" . "accidentalrebel@gmail.com") (:keywords "convenience") (:url . "https://github.com/cobalt-org/cobalt.el"))]) (cobra-mode . [(20140116 2116) nil "Major mode for .NET-based Cobra language" single ((:commit . "acd6e53f6286af5176471d01f25257e5ddb6dd01") (:authors ("Taylor \"Nekroze\" Lawson")) (:maintainer "Taylor \"Nekroze\" Lawson") (:keywords "languages") (:url . "http://github.com/Nekroze/cobra-mode"))]) (codcut . [(20190915 1009) nil "Share pieces of code to Codcut" single ((:commit . "bf07c3db3900e36b0b87423f3b715d6378f86393") (:authors ("Diego Pasquali" . "hello@dgopsq.space")) (:maintainer "Diego Pasquali" . "hello@dgopsq.space") (:keywords "comm" "tools" "codcut" "share") (:url . "https://github.com/codcut/codcut-emacs"))]) @@ -601,7 +605,7 @@ (coffee-mode . [(20200315 1133) ((emacs (24 3))) "Major mode for CoffeeScript code" single ((:commit . "35a41c7d8233eac0b267d9593e67fb8b6235e134") (:authors ("Chris Wanstrath" . "chris@ozmm.org")) (:maintainer "Chris Wanstrath" . "chris@ozmm.org") (:keywords "coffeescript" "major" "mode") (:url . "http://github.com/defunkt/coffee-mode"))]) (coin-ticker . [(20170611 727) ((request (0 3 0)) (emacs (25))) "Show a cryptocurrency price ticker" single ((:commit . "45108e239e1d129c0cc1ff37f2870cf73087780b") (:authors ("Evan Klitzke" . "evan@eklitzke.org")) (:maintainer "Evan Klitzke" . "evan@eklitzke.org") (:keywords "news") (:url . "https://github.com/eklitzke/coin-ticker-mode"))]) (colonoscopy-theme . [(20170808 1309) ((emacs (24 0))) "an Emacs 24 theme based on Colonoscopy (tmTheme)" single ((:commit . "64bbb322b13dae91ce9f1e3581f836f94f800ead") (:authors ("Jason Milkins")) (:maintainer "Jason Milkins") (:url . "https://github.com/emacsfodder/tmtheme-to-deftheme"))]) - (color-identifiers-mode . [(20230210 2047) ((dash (2 5 0)) (emacs (24))) "Color identifiers based on their names" single ((:commit . "9fd09481bbcdb35712d974d5bc3667f5a5900ddb") (:authors ("Ankur Dave" . "ankurdave@gmail.com")) (:maintainer "Ankur Dave" . "ankurdave@gmail.com") (:keywords "faces" "languages") (:url . "https://github.com/ankurdave/color-identifiers-mode"))]) + (color-identifiers-mode . [(20230405 527) ((dash (2 5 0)) (emacs (24))) "Color identifiers based on their names" single ((:commit . "c4060d1bca6fa2acfe449e086171d4efee62863f") (:authors ("Ankur Dave" . "ankurdave@gmail.com")) (:maintainer "Ankur Dave" . "ankurdave@gmail.com") (:keywords "faces" "languages") (:url . "https://github.com/ankurdave/color-identifiers-mode"))]) (color-moccur . [(20141223 35) nil "multi-buffer occur (grep) mode" single ((:commit . "4f1c59ffd1ccc2ab1a171cd6b721e8cb9e002fb7") (:keywords "convenience") (:url . "http://www.bookshelf.jp/elc/color-moccur.el"))]) (color-theme . [(20190220 1115) nil "An OBSOLETE color-theme implementation" tar ((:commit . "3a2f6b615f5e2401e30d93a3e0adc210bbb4b7aa") (:authors ("Jonadab the Unsightly One" . "jonadab@bright.net")) (:maintainer "Xavier Maillard" . "zedek@gnu.org") (:keywords "faces") (:url . "http://www.emacswiki.org/cgi-bin/wiki.pl?ColorTheme"))]) (color-theme-approximate . [(20140228 436) nil "Makes Emacs theme works on terminal transparently" single ((:commit . "f54301ca39bc5d2ffb000f233f8114184a3e7d71") (:authors ("Tung Dao" . "me@tungdao.com")) (:maintainer "Tung Dao" . "me@tungdao.com"))]) @@ -628,14 +632,14 @@ (commenter . [(20160219 1627) ((emacs (24 4)) (let-alist (1 0 4))) "multiline-comment support package" single ((:commit . "6d1885419434ba779270c6fda0e30d390bb074bd") (:authors ("Yuta Yamada ")) (:maintainer "Yuta Yamada ") (:keywords "comment") (:url . "https://github.com/yuutayamada/commenter"))]) (commify . [(20220531 1301) ((s (1 9 0))) "Toggle grouping commas in numbers" single ((:commit . "c4aeccae5b4a073fc3f4e8bd780a2ebbb7d5e533") (:authors ("Daniel E. Doherty" . "ded-commify@ddoherty.net")) (:maintainer "Daniel E. Doherty" . "ded-commify@ddoherty.net") (:keywords "convenience" "editing" "numbers" "grouping" "commas") (:url . "https://github.com/ddoherty03/commify"))]) (common-lisp-snippets . [(20180226 1523) ((yasnippet (0 8 0))) "Yasnippets for Common Lisp" tar ((:commit . "1ddf808311ba4d9e8444a1cb50bd5ee75e4111f6") (:authors ("Mark Karpov" . "markkarpov92@gmail.com")) (:maintainer "Mark Karpov" . "markkarpov92@gmail.com") (:keywords "snippets") (:url . "https://github.com/mrkkrp/common-lisp-snippets"))]) - (company . [(20230209 134) ((emacs (25 1))) "Modular text completion framework" tar ((:commit . "2ca3e29abf87392714bc2b26e50e1c0f4b9f4e2c") (:authors ("Nikolaj Schumacher")) (:maintainer "Dmitry Gutov" . "dgutov@yandex.ru") (:keywords "abbrev" "convenience" "matching") (:url . "http://company-mode.github.io/"))]) + (company . [(20230404 140) ((emacs (25 1))) "Modular text completion framework" tar ((:commit . "246837b12cbedaac0c9e2b654d97426639e0c778") (:authors ("Nikolaj Schumacher")) (:maintainer "Dmitry Gutov" . "dgutov@yandex.ru") (:keywords "abbrev" "convenience" "matching") (:url . "http://company-mode.github.io/"))]) (company-anaconda . [(20200404 1859) ((company (0 8 0)) (anaconda-mode (0 1 1)) (cl-lib (0 5 0)) (dash (2 6 0)) (s (1 9))) "Anaconda backend for company-mode" single ((:commit . "da1566db41a68809ef7f91ebf2de28118067c89b") (:authors ("Artem Malyshev" . "proofit404@gmail.com")) (:maintainer "Artem Malyshev" . "proofit404@gmail.com") (:url . "https://github.com/proofit404/anaconda-mode"))]) (company-ansible . [(20200306 1441) ((emacs (24 4)) (company (0 8 12))) "A company back-end for ansible" tar ((:commit . "79dd421b161efa49fbdffad57fa40edb41f484a3") (:authors ("Krzysztof Magosa" . "krzysztof@magosa.pl")) (:maintainer "Krzysztof Magosa" . "krzysztof@magosa.pl") (:keywords "ansible") (:url . "https://github.com/krzysztof-magosa/company-ansible"))]) (company-arduino . [(20160306 1739) ((emacs (24 1)) (company (0 8 0)) (irony (0 1 0)) (cl-lib (0 5)) (company-irony (0 1 0)) (company-c-headers (20140930)) (arduino-mode (1 0))) "company-mode for Arduino" single ((:commit . "5958b917cc5cc729dc64d74d947da5ee91c48980") (:authors ("Yuta Yamada" . "sleepboy.zzz@gmail.com")) (:maintainer "Yuta Yamada" . "sleepboy.zzz@gmail.com") (:keywords "convenience" "development" "company") (:url . "https://github.com/yuutayamada/company-arduino"))]) (company-auctex . [(20200529 1835) ((yasnippet (0 8 0)) (company (0 8 0)) (auctex (11 87))) "Company-mode auto-completion for AUCTeX" single ((:commit . "9400a2ec7459dde8cbf1a5d50dfee4e300ed7e18") (:authors ("Christopher Monsanto , Alexey Romanov" . "alexey.v.romanov@gmail.com")) (:maintainer "Christopher Monsanto , Alexey Romanov" . "alexey.v.romanov@gmail.com") (:url . "https://github.com/alexeyr/company-auctex/"))]) (company-axiom . [(20220612 1535) ((emacs (24)) (company (0 9)) (axiom-environment (20171021))) "A company-mode backend for the axiom-environment system" single ((:commit . "01d88daa0c864af9918db5a147fbb5e435dec199") (:authors ("Paul Onions" . "paul.onions@acm.org")) (:maintainer "Paul Onions" . "paul.onions@acm.org") (:keywords "axiom" "openaxiom" "fricas" "axiom-environment"))]) (company-bibtex . [(20171105 644) ((company (0 9 0)) (cl-lib (0 5)) (parsebib (1 0))) "Company completion for bibtex keys" single ((:commit . "225c6f5c0c070c94c8cdbbd452ea548cd94d76f4") (:authors ("GB Gardner" . "gbgar@users.noreply.github.com")) (:maintainer "GB Gardner" . "gbgar@users.noreply.github.com") (:keywords "company-mode" "bibtex") (:url . "https://github.com/gbgar/company-bibtex"))]) - (company-box . [(20221230 1603) ((emacs (26 0 91)) (dash (2 19 0)) (company (0 9 6)) (frame-local (0 0 1))) "Company front-end with icons" tar ((:commit . "766546b2668b5ef4eb4abbde632c9acd370c7788") (:authors ("Sebastien Chapuis" . "sebastien@chapu.is")) (:maintainer "Sebastien Chapuis" . "sebastien@chapu.is") (:keywords "company" "completion" "front-end" "convenience") (:url . "https://github.com/sebastiencs/company-box"))]) + (company-box . [(20230312 1028) ((emacs (26 0 91)) (dash (2 19 0)) (company (0 9 6)) (frame-local (0 0 1))) "Company front-end with icons" tar ((:commit . "b6f53e26adf948aca55c3ff6c22c21a6a6614253") (:authors ("Sebastien Chapuis" . "sebastien@chapu.is")) (:maintainer "Sebastien Chapuis" . "sebastien@chapu.is") (:keywords "company" "completion" "front-end" "convenience") (:url . "https://github.com/sebastiencs/company-box"))]) (company-c-headers . [(20190825 1631) ((emacs (24 1)) (company (0 8))) "Company mode backend for C/C++ header files" single ((:commit . "5e676ab0c2f287c868b1e3931afd4c78895910cd") (:authors ("Alastair Rankine" . "alastair@girtby.net")) (:maintainer "Alastair Rankine" . "alastair@girtby.net") (:keywords "development" "company"))]) (company-cabal . [(20170917 1317) ((cl-lib (0 5)) (company (0 8 0)) (emacs (24))) "company-mode cabal backend" tar ((:commit . "62112a7259e24bd6c08885629a185afe512b7d3d") (:authors ("Iku Iwasa" . "iku.iwasa@gmail.com")) (:maintainer "Iku Iwasa" . "iku.iwasa@gmail.com") (:url . "https://github.com/iquiw/company-cabal"))]) (company-coq . [(20221130 536) ((cl-lib (0 5)) (dash (2 12 1)) (yasnippet (0 11 0)) (company (0 8 12)) (company-math (1 1))) "A collection of extensions for Proof General's Coq mode" tar ((:commit . "5affe7a96a25df9101f9e44bac8a828d8292c2fa") (:authors ("Clément Pit-Claudel" . "clement.pitclaudel@live.com")) (:maintainer "Clément Pit-Claudel" . "clement.pitclaudel@live.com") (:keywords "convenience" "languages") (:url . "https://github.com/cpitclaudel/company-coq"))]) @@ -699,35 +703,36 @@ (company-ycmd . [(20180520 1053) ((ycmd (1 3)) (company (0 9 3)) (deferred (0 5 1)) (s (1 11 0)) (dash (2 13 0)) (let-alist (1 0 5)) (f (0 19 0))) "company-mode backend for ycmd" single ((:commit . "966594701c1eef1f6d4dad0c71c6d43a029977d7") (:url . "https://github.com/abingham/emacs-ycmd"))]) (compdef . [(20200304 611) ((emacs (24 4))) "A local completion definer" single ((:commit . "30fb5846ed851efee641ce8c5d8879ad36cd7ac6") (:authors ("Uros Perisic")) (:maintainer "Uros Perisic") (:keywords "convenience") (:url . "https://gitlab.com/jjzmajic/compdef"))]) (competitive-programming-snippets . [(20201115 1702) ((emacs (26)) (yasnippet (0 8 0))) "Competitive Programming snippets for yasnippet" tar ((:commit . "3b43c1aeaa6676d1d3d0c47e78790db9bee150b6") (:authors ("Seong Yong-ju" . "sei40kr@gmail.com")) (:maintainer "Seong Yong-ju" . "sei40kr@gmail.com") (:keywords "tools") (:url . "https://github.com/sei40kr/competitive-programming-snippets"))]) + (compile-multi . [(20230311 1951) ((emacs (28 0))) "A multi target interface to compile" single ((:commit . "e475a0477e49d5ca48703bea874dfeea786b9af5") (:authors ("mohsin kaleem" . "mohkale@kisara.moe")) (:maintainer "mohsin kaleem" . "mohkale@kisara.moe") (:keywords "tools" "compile" "build") (:url . "https://github.com/mohkale/compile-multi"))]) (compiler-explorer . [(20221108 825) ((emacs (26 1)) (request (0 3 0))) "Compiler explorer client (godbolt.org)" single ((:commit . "36a2cbf0863d4563096546c38ff26db3d7a3e18c") (:authors ("Michał Krzywkowski" . "k.michal@zoho.com")) (:maintainer "Michał Krzywkowski" . "k.michal@zoho.com") (:keywords "c" "tools") (:url . "https://github.com/mkcms/compiler-explorer.el"))]) (composable . [(20220608 1148) ((emacs (25 1))) "composable editing" tar ((:commit . "205a69c64ea95ef67070423c31ed70ec44ec980c") (:authors ("Simon Friis Vindum" . "simon@vindum.io")) (:maintainer "Simon Friis Vindum" . "simon@vindum.io") (:keywords "lisp"))]) (composer . [(20221120 202) ((emacs (25 1)) (seq (1 9)) (php-runtime (0 1 0))) "Interface to PHP Composer" single ((:commit . "2299cd731205906350d615021f99a66d7a8905c2") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "tools" "php" "dependency" "manager") (:url . "https://github.com/zonuexe/composer.el"))]) (comware-router-mode . [(20230107 1624) ((dash (2 16 0)) (emacs (24 3))) "Major mode for editing Comware configuration files" single ((:commit . "cc0c1937e02f84ca8182b2de3ce5cc0982308ab8") (:authors ("Davide Restivo" . "davide.restivo@yahoo.it")) (:maintainer "Davide Restivo" . "davide.restivo@yahoo.it") (:keywords "convenience" "faces") (:url . "https://github.com/daviderestivo/comware-router-mode"))]) (concurrent . [(20170601 435) ((emacs (24 3)) (deferred (0 5 0))) "Concurrent utility functions for emacs lisp" single ((:commit . "d012a1ab50edcc2c44e3e49006f054dbff47cb6c") (:authors ("SAKURAI Masashi ")) (:maintainer "SAKURAI Masashi ") (:keywords "deferred" "async" "concurrent") (:url . "https://github.com/kiwanami/emacs-deferred/blob/master/README-concurrent.markdown"))]) - (conda . [(20230221 1603) ((emacs (25 1)) (pythonic (0 1 0)) (dash (2 13 0)) (s (1 11 0)) (f (0 18 2))) "Work with your conda environments" single ((:commit . "28f51e49fd25abff14c1b46dea196a90a77ced64") (:authors ("Rami Chowdhury" . "rami.chowdhury@gmail.com")) (:maintainer "Rami Chowdhury" . "rami.chowdhury@gmail.com") (:keywords "languages" "local" "tools" "python" "environment" "conda") (:url . "http://github.com/necaris/conda.el"))]) + (conda . [(20230228 322) ((emacs (25 1)) (pythonic (0 1 0)) (dash (2 13 0)) (s (1 11 0)) (f (0 18 2))) "Work with your conda environments" single ((:commit . "f90598f54af78469e61497560ddad05344810a35") (:authors ("Rami Chowdhury" . "rami.chowdhury@gmail.com")) (:maintainer "Rami Chowdhury" . "rami.chowdhury@gmail.com") (:keywords "languages" "local" "tools" "python" "environment" "conda") (:url . "http://github.com/necaris/conda.el"))]) (config-general-mode . [(20171024 1840) nil "Config::General config file mode" single ((:commit . "b4a8e6ba0bb027a77e4a0f701409f3e57bb2e4c0") (:authors ("T.v.Dein" . "tlinden@cpan.org")) (:maintainer "T.v.Dein" . "tlinden@cpan.org") (:keywords "files") (:url . "https://github.com/tlinden/config-general-mode"))]) (config-parser . [(20160426 1219) ((emacs (24 4))) "a library for parsing config file" single ((:commit . "85d559e7889d8f5b98b8794b79426ae25ec3caa5") (:authors ("DarkSun" . "lujun9972@gmail.com")) (:maintainer "DarkSun" . "lujun9972@gmail.com") (:keywords "convenience" "config") (:url . "https://github.com/lujun9972/el-config-parser"))]) (conkeror-minor-mode . [(20150114 1604) nil "Mode for editing conkeror javascript files." single ((:commit . "476e81c27b056e21c192391fe674a2bf875466b0") (:authors ("Artur Malabarba" . "bruce.connor.am@gmail.com>")) (:maintainer "Artur Malabarba" . "bruce.connor.am@gmail.com>") (:keywords "programming" "tools") (:url . "http://github.com/Bruce-Connor/conkeror-minor-mode"))]) (conllu-mode . [(20200501 2328) ((emacs (25)) (cl-lib (0 5)) (flycheck (30)) (hydra (0 13 0)) (s (1 0))) "editing mode for CoNLL-U files" tar ((:commit . "0db3063572b0de08874822e20570bb153747e6ed") (:authors ("bruno cuconato" . "bcclaro+emacs@gmail.com")) (:maintainer "bruno cuconato" . "bcclaro+emacs@gmail.com") (:keywords "extensions") (:url . "https://github.com/odanoburu/conllu-mode"))]) (connection . [(20191111 446) nil "TCP-based client connection" single ((:commit . "c9cad101100975e88873636bfd426b7a19304ebd") (:authors ("Torsten Hilbrich" . "torsten.hilbrich@gmx.net")) (:maintainer "Torsten Hilbrich" . "torsten.hilbrich@gmx.net") (:keywords "network"))]) (constant-theme . [(20180921 1012) ((emacs (24 1))) "A calm, dark, almost monochrome color theme." tar ((:commit . "0feb9f99d708633d62fa548c953ebbe68fd70de0") (:authors ("Jannis Pohlmann" . "contact@jannispohlmann.de")) (:maintainer "Jannis Pohlmann" . "contact@jannispohlmann.de") (:keywords "themes") (:url . "https://github.com/jannis/emacs-constant-theme"))]) - (consult . [(20230218 1212) ((emacs (27 1)) (compat (29 1 3 4))) "Consulting completing-read" tar ((:commit . "ffaaf6da909dc9ff766e5a5f16eb265635aa6149") (:authors ("Daniel Mendler and Consult contributors")) (:maintainer "Daniel Mendler" . "mail@daniel-mendler.de") (:url . "https://github.com/minad/consult"))]) - (consult-ag . [(20220419 1721) ((emacs (27 1)) (consult (0 16))) "The silver searcher integration using Consult" single ((:commit . "2460ae6829e86c9f1186a852304d919526838cb8") (:authors ("Kanon Kakuno" . "yadex205@outlook.jp")) (:maintainer "Kanon Kakuno" . "yadex205@outlook.jp") (:url . "https://github.com/yadex205/consult-ag"))]) - (consult-codesearch . [(20230129 415) ((emacs (27 1)) (codesearch (1)) (consult (0 20))) "Consult interface for codesearch" single ((:commit . "7b666ab50d120b25272183d921d581e01e77789a") (:authors ("Youngjoo Lee" . "youngker@gmail.com")) (:maintainer "Youngjoo Lee" . "youngker@gmail.com") (:keywords "tools") (:url . "https://github.com/youngker/consult-codesearch"))]) - (consult-company . [(20220830 1834) ((emacs (27 1)) (company (0 9)) (consult (0 9))) "Consult frontend for company" single ((:commit . "5d8275bff131ce2aaa678dd46aac345eb4fc8b27") (:authors ("mohsin kaleem" . "mohkale@kisara.moe")) (:maintainer "mohsin kaleem" . "mohkale@kisara.moe") (:url . "https://github.com/mohkale/consult-company"))]) + (consult . [(20230406 1519) ((emacs (27 1)) (compat (29 1 4 1))) "Consulting completing-read" tar ((:commit . "f93949999d3681dbede5cd88c849199d7adf3d8d") (:authors ("Daniel Mendler and Consult contributors")) (:maintainer "Daniel Mendler" . "mail@daniel-mendler.de") (:url . "https://github.com/minad/consult"))]) + (consult-ag . [(20230227 406) ((emacs (27 1)) (consult (0 32))) "The silver searcher integration using Consult" single ((:commit . "9eb4df265aedf2628a714610c2ade6d2f21de053") (:authors ("Kanon Kakuno" . "yadex205@outlook.jp")) (:maintainer "Kanon Kakuno" . "yadex205@outlook.jp") (:url . "https://github.com/yadex205/consult-ag"))]) + (consult-codesearch . [(20230315 1424) ((emacs (27 1)) (consult (0 20))) "Consult interface for codesearch" single ((:commit . "51df545bb57b468058245950322ae15f6c3a0ce2") (:authors ("Youngjoo Lee" . "youngker@gmail.com")) (:maintainer "Youngjoo Lee" . "youngker@gmail.com") (:keywords "tools") (:url . "https://github.com/youngker/consult-codesearch"))]) + (consult-company . [(20230403 1911) ((emacs (27 1)) (company (0 9)) (consult (0 9))) "Consult frontend for company" single ((:commit . "24559103a77210c0178b95a842ad13b555be3d43") (:authors ("mohsin kaleem" . "mohkale@kisara.moe")) (:maintainer "mohsin kaleem" . "mohkale@kisara.moe") (:url . "https://github.com/mohkale/consult-company"))]) (consult-dash . [(20220621 226) ((emacs (27 2)) (dash-docs (1 4 0)) (consult (0 16))) "Consult front-end for dash-docs" single ((:commit . "0eb8e133a12570f482efcf367dcc7887c15def32") (:authors ("Ravi R Kiran" . "lists.ravi@gmail.com")) (:maintainer "Ravi R Kiran" . "lists.ravi@gmail.com") (:keywords "consult" "dash" "docs") (:url . "https://codeberg.org/ravi/consult-dash"))]) (consult-dir . [(20221001 1748) ((emacs (26 1)) (consult (0 9)) (project (0 6 0))) "Insert paths into the minibuffer prompt" single ((:commit . "ed8f0874d26f10f5c5b181ab9f2cf4107df8a0eb") (:authors ("Karthik Chikmagalur")) (:maintainer "Karthik Chikmagalur" . "karthik.chikmagalur@gmail.com") (:keywords "convenience") (:url . "https://github.com/karthink/consult-dir"))]) (consult-eglot . [(20230213 1359) ((emacs (27 1)) (eglot (1 7)) (consult (0 31)) (project (0 3 0))) "A consulting-read interface for eglot" single ((:commit . "6504ccd2b7555452c61cc24a45965f7e2a37c44d") (:authors ("mohsin kaleem" . "mohkale@kisara.moe")) (:maintainer "Mohsin Kaleem") (:keywords "tools" "completion" "lsp") (:url . "https://github.com/mohkale/consult-eglot"))]) (consult-flycheck . [(20230212 26) ((emacs (27 1)) (consult (0 32)) (flycheck (32))) "Provides the command `consult-flycheck'" single ((:commit . "c371996c571b7139ef4d9a8db142bf37a7ee826b") (:authors ("Daniel Mendler and Consult contributors")) (:maintainer "Daniel Mendler" . "mail@daniel-mendler.de") (:url . "https://github.com/minad/consult"))]) - (consult-flyspell . [(20221029 823) ((emacs (25 1)) (consult (0 12))) "Consult integration for flyspell" single ((:commit . "d587961ef0d5f9992cedef3b35b87b11d610a375") (:authors ("Marco Pawłowski")) (:maintainer "Marco Pawłowski") (:keywords "convenience") (:url . "https://gitlab.com/OlMon/consult-flyspell"))]) + (consult-flyspell . [(20230322 204) ((emacs (25 1)) (consult (0 12))) "Consult integration for flyspell" single ((:commit . "7011e6634598530ea2d874e7e7389dc1bb94e1ca") (:authors ("Marco Pawłowski")) (:maintainer "Marco Pawłowski") (:keywords "convenience") (:url . "https://gitlab.com/OlMon/consult-flyspell"))]) (consult-ghq . [(20210606 2047) ((emacs (26 1)) (consult (0 8)) (affe (0 1))) "Ghq interface using consult" single ((:commit . "c8619d66bd8f8728e43ed15096078b89eb4d2083") (:authors ("Tomoya Otake" . "tomoya.ton@gmail.com")) (:maintainer "Tomoya Otake" . "tomoya.ton@gmail.com") (:keywords "convenience" "usability" "consult" "ghq") (:url . "https://github.com/tomoya/consult-ghq"))]) (consult-git-log-grep . [(20230204 1753) ((emacs (27 1)) (consult (0 16))) "Consult integration for git log grep" single ((:commit . "30dfcad5745a6b9882d94fec75d38c345a1eff89") (:authors ("Ghosty")) (:maintainer "Ghosty") (:keywords "git" "convenience") (:url . "https://github.com/Ghosty141/consult-git-log-grep"))]) (consult-hatena-bookmark . [(20221125 109) ((emacs (27 1)) (consult (0 9)) (async-await (1 1))) "Consult commands for the Hatena Bookmark" single ((:commit . "b85484b11705ebd896878d3ac7fdb12bc8c9637a") (:authors ("Yukinori Kitadai")) (:maintainer "Yukinori Kitadai") (:url . "https://github.com/Nyoho/consult-hatena-bookmark"))]) (consult-ls-git . [(20230120 1500) ((emacs (27 1)) (consult (0 16))) "Consult integration for git" single ((:commit . "7ba583abc16f70c497d038bfcbddbadd6894bd3d") (:authors ("Robin Joy")) (:maintainer "Robin Joy") (:keywords "convenience") (:url . "https://github.com/rcj/consult-ls-git"))]) (consult-lsp . [(20230209 714) ((emacs (27 1)) (lsp-mode (5 0)) (consult (0 16)) (f (0 20 0))) "LSP-mode Consult integration" single ((:commit . "f8db3252c0daa41225ba4ed1c0d178b281cd3e90") (:authors ("Gerry Agbobada")) (:maintainer "Gerry Agbobada") (:keywords "tools" "completion" "lsp") (:url . "https://github.com/gagbo/consult-lsp"))]) - (consult-notes . [(20230112 312) ((emacs (27 1)) (consult (0 17)) (s (1 12 0)) (dash (2 19))) "Manage notes with consult" tar ((:commit . "4d92996f676cecfebea6519dadf8cf185621a18a") (:authors ("Colin McLear" . "mclear@fastmail.com")) (:maintainer "Colin McLear") (:keywords "convenience") (:url . "https://github.com/mclear-tools/consult-notes"))]) + (consult-notes . [(20230401 1922) ((emacs (27 1)) (consult (0 17)) (s (1 12 0)) (dash (2 19))) "Manage notes with consult" tar ((:commit . "941325a3484782017c27e3ffe5ddb3b9151b8740") (:authors ("Colin McLear" . "mclear@fastmail.com")) (:maintainer "Colin McLear") (:keywords "convenience") (:url . "https://github.com/mclear-tools/consult-notes"))]) (consult-notmuch . [(20221216 1701) ((emacs (26 1)) (consult (0 9)) (notmuch (0 31))) "Notmuch search using consult" single ((:commit . "d0d4129d45ccceddaeeaa3631eb42d5dd09a758b") (:authors ("Jose A Ortega Ruiz" . "jao@gnu.org")) (:maintainer "Jose A Ortega Ruiz") (:keywords "mail") (:url . "https://codeberg.org/jao/consult-notmuch"))]) - (consult-org-roam . [(20230209 833) ((emacs (27 1)) (org-roam (2 2 0)) (consult (0 16))) "Consult integration for org-roam" tar ((:commit . "8f9f122627a6b4e1613401b06d707e3efdb3c2d0") (:authors ("jgru ")) (:maintainer "jgru ") (:url . "https://github.com/jgru/consult-org-roam"))]) + (consult-org-roam . [(20230301 1555) ((emacs (27 1)) (org-roam (2 2 0)) (consult (0 16))) "Consult integration for org-roam" tar ((:commit . "ede01c2710836f055351d2ef0d9fac70b885ac65") (:authors ("jgru ")) (:maintainer "jgru ") (:url . "https://github.com/jgru/consult-org-roam"))]) (consult-project-extra . [(20221013 1014) ((emacs (27 1)) (consult (0 17)) (project (0 8 1))) "Consult integration for project.el" single ((:commit . "9fdf45fa40471900b0b158d73c4b1521a13d47ef") (:authors ("Enrique Kessler Martínez")) (:maintainer "Enrique Kessler Martínez") (:keywords "convenience" "project" "management") (:url . "https://github.com/Qkessler/consult-project-extra"))]) (consult-projectile . [(20220617 1042) ((emacs (25 1)) (consult (0 12)) (projectile (2 5 0))) "Consult integration for projectile" single ((:commit . "5ef1ada3be767ea766255801050210f5d796deec") (:authors ("Marco Pawłowski")) (:maintainer "Marco Pawłowski") (:keywords "convenience") (:url . "https://gitlab.com/OlMon/consult-projectile"))]) (consult-recoll . [(20221014 2002) ((emacs (26 1)) (consult (0 19))) "Recoll queries using consult" single ((:commit . "8d506e2d01f46fc6b0a0825efb90b062ad6fe3d4") (:authors ("Jose A Ortega Ruiz" . "jao@gnu.org")) (:maintainer "Jose A Ortega Ruiz" . "jao@gnu.org") (:keywords "docs" "convenience") (:url . "https://codeberg.org/jao/consult-recoll"))]) @@ -740,16 +745,15 @@ (conventional-changelog . [(20230101 1656) ((emacs (26 3)) (transient (0 3 7))) "Conventional Changelog Generator" single ((:commit . "56f0e134f0edc1964965575dea259b186d34155a") (:authors ("liuyinz" . "liuyinz95@gmail.com")) (:maintainer "liuyinz" . "liuyinz95@gmail.com") (:keywords "tools") (:url . "https://github.com/liuyinz/emacs-conventional-changelog"))]) (cool-mode . [(20220612 1904) ((emacs (25))) "Major mode for cool compiler language" tar ((:commit . "961e66956412a1dd63f79473a8273da8853f7179") (:authors ("Noah Peart" . "noah.v.peart@gmail.com")) (:maintainer "Noah Peart" . "noah.v.peart@gmail.com") (:url . "https://github.com/nverno/cool-mode"))]) (copy-as-format . [(20190523 258) ((cl-lib (0 5))) "Copy buffer locations as GitHub/Slack/JIRA etc... formatted code" single ((:commit . "a0962b670e26b723ce304b14e3397da453aef84e") (:authors ("Skye Shaw" . "skye.shaw@gmail.com")) (:maintainer "Skye Shaw" . "skye.shaw@gmail.com") (:keywords "github" "slack" "jira" "hipchat" "gitlab" "bitbucket" "org-mode" "pod" "rst" "asciidoc" "tools" "convenience") (:url . "https://github.com/sshaw/copy-as-format"))]) - (copy-file-on-save . [(20200616 518) ((emacs (24 3)) (cl-lib (0 5)) (f (0 17)) (s (1 7 0))) "Copy file on save, automatic deployment it." single ((:commit . "811c8fe638c5616b6471525421e61a4470be3b52") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "files" "comm" "deploy") (:url . "https://github.com/emacs-php/emacs-auto-deployment"))]) + (copy-file-on-save . [(20230402 1829) ((emacs (24 3)) (compat (29))) "Copy file on save, automatic deployment it" single ((:commit . "370b1586feb2690d3c72185bd4f17c31ce03673a") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "files" "comm" "deploy") (:url . "https://github.com/emacs-php/emacs-auto-deployment"))]) (copyit . [(20190919 1258) ((emacs (24 3)) (s (1 9 0))) "Copy it, yank anything!" single ((:commit . "c4f2c28e5b6270e8e3364341619f1154bb4e682e") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "convenience" "yank" "clipboard") (:url . "https://github.com/zonuexe/emacs-copyit"))]) (copyit-pandoc . [(20190919 1258) ((emacs (24 3)) (copyit (0 1 0)) (pandoc (0 0 1))) "Copy it, yank anything!" single ((:commit . "c4f2c28e5b6270e8e3364341619f1154bb4e682e") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "convenience" "yank" "clipboard") (:url . "https://github.com/zonuexe/emacs-copyit"))]) (coq-commenter . [(20170822 2309) ((dash (2 13 0)) (s (1 11 0)) (cl-lib (0 5))) "Coq commenting minor mode for proof" single ((:commit . "7fe9a2cc0ebdb0b1e54a24eb7971d757fb588ac3") (:authors ("Junyoung Clare Jang" . "jjc9310@gmail.com")) (:maintainer "Junyoung Clare Jang" . "jjc9310@gmail.com") (:keywords "comment" "coq" "proof") (:url . "http://github.com/ailrun/coq-commenter"))]) - (corfu-doc . [(20221128 1533) ((emacs (27 1)) (corfu (0 25))) "Documentation popup for Corfu" single ((:commit . "0e6125cd042506a048feb7b6446a5653eccfcff5") (:authors ("Yuwei Tian" . "ibluefocus@NOSPAM.gmail.com")) (:maintainer "Yuwei Tian" . "ibluefocus@NOSPAM.gmail.com") (:keywords "corfu" "popup" "documentation" "convenience") (:url . "https://github.com/galeo/corfu-doc"))]) (corfu-prescient . [(20221216 112) ((emacs (27 1)) (prescient (6 1 0)) (corfu (0 28))) "prescient.el + Corfu" single ((:commit . "72b023f5fc1ae2bbf2f51f1786cc012d40671bf4") (:authors ("Radian LLC" . "contact+prescient@radian.codes")) (:maintainer "Radian LLC" . "contact+prescient@radian.codes") (:keywords "extensions") (:url . "https://github.com/radian-software/prescient.el"))]) (corral . [(20160502 948) nil "Quickly surround text with delimiters" single ((:commit . "e7ab6aa118e46b93d4933d1364bc273f57cd6911") (:authors ("Kevin Liu" . "mail@nivekuil.com")) (:maintainer "Kevin Liu" . "mail@nivekuil.com") (:url . "http://github.com/nivekuil/corral"))]) (cort . [(20211020 18) ((emacs (24 1)) (ansi (0 4)) (cl-lib (0 6))) "Simplify extended unit test framework" single ((:commit . "3f64a7b03a4c5b768ec21fd5987acd0d62d16c7b") (:authors ("Naoya Yamashita" . "conao3@gmail.com")) (:maintainer "Naoya Yamashita" . "conao3@gmail.com") (:keywords "test" "lisp") (:url . "https://github.com/conao3/cort.el"))]) (cosmo . [(20170922 744) ((emacs (24 4))) "Cosmological Calculator" single ((:commit . "dd83b09a49a2843606b28279b674b2207040b36b") (:authors ("Francesco Montanari" . "fmnt@fmnt.info")) (:maintainer "Francesco Montanari" . "fmnt@fmnt.info") (:keywords "tools") (:url . "https://gitlab.com/montanari/cosmo-el"))]) - (counsel . [(20221015 936) ((emacs (24 5)) (ivy (0 13 4)) (swiper (0 13 4))) "Various completion functions using Ivy" single ((:commit . "b8be4913a661b557e0d3275726e36871556569d3") (:authors ("Oleh Krehel" . "ohwoeowho@gmail.com")) (:maintainer "Oleh Krehel" . "ohwoeowho@gmail.com") (:keywords "convenience" "matching" "tools") (:url . "https://github.com/abo-abo/swiper"))]) + (counsel . [(20230327 1216) ((emacs (24 5)) (ivy (0 13 4)) (swiper (0 13 4))) "Various completion functions using Ivy" single ((:commit . "8df9516ae6d2e86ec6104b6783ad380fa3945dec") (:authors ("Oleh Krehel" . "ohwoeowho@gmail.com")) (:maintainer "Oleh Krehel" . "ohwoeowho@gmail.com") (:keywords "convenience" "matching" "tools") (:url . "https://github.com/abo-abo/swiper"))]) (counsel-ag-popup . [(20210121 805) ((emacs (26 1)) (counsel (0 13 0)) (transient (0 3 0))) "Interactive search with counsel-ag" single ((:commit . "41d85fe36edd72da68f5009ad9cf9013cd19960d") (:authors ("Eder Elorriaga" . "gexplorer8@gmail.com")) (:maintainer "Eder Elorriaga" . "gexplorer8@gmail.com") (:keywords "convenience" "matching" "tools") (:url . "https://github.com/gexplorer/counsel-ag-popup"))]) (counsel-at-point . [(20230116 951) ((emacs (26 2)) (counsel (0 13 0))) "Context sensitive project search" single ((:commit . "a84cc0e409325d051208c43dfcabcebaa0d98ba3") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:keywords "convenience") (:url . "https://codeberg.org/ideasman42/emacs-counsel-at-point"))]) (counsel-bbdb . [(20220909 727) ((emacs (24 3)) (bbdb (3 2 2 2))) "Quick search&input email from BBDB based on Emacs API `completing-read'" single ((:commit . "ccae56b0551abb305cad087d85f1b6a97adb7c0f") (:authors ("Chen Bin" . "chenbin.sh@gmail.com")) (:maintainer "Chen Bin" . "chenbin.sh@gmail.com") (:keywords "mail" "abbrev" "convenience" "matching") (:url . "https://github.com/redguard/counsel-bbdb"))]) @@ -799,7 +803,7 @@ (crossword . [(20210614 633) ((emacs (26 1))) "Download and play crossword puzzles" single ((:commit . "e462de8ef15d1f979207a95b224e68d7feead92f") (:keywords "games") (:url . "https://github.com/Boruch-Baum/emacs-crossword"))]) (crux . [(20221121 859) ((seq (1 11))) "A Collection of Ridiculously Useful eXtensions" single ((:commit . "f8789f67a9d2e1eb31a0e4531aec9bb6d6ec1282") (:authors ("Bozhidar Batsov" . "bozhidar@batsov.dev")) (:maintainer "Bozhidar Batsov" . "bozhidar@batsov.dev") (:keywords "convenience") (:url . "https://github.com/bbatsov/crux"))]) (cryptol-mode . [(20190531 2051) nil "Cryptol major mode for Emacs" single ((:commit . "81ebbde83f7cb75b2dfaefc09de6a1703068c769") (:authors (nil . "Austin Seipp ")) (:maintainer nil . "Austin Seipp ") (:keywords "cryptol" "cryptography") (:url . "http://github.com/thoughtpolice/cryptol-mode"))]) - (crystal-mode . [(20221008 1847) ((emacs (24 4))) "Major mode for editing Crystal files" single ((:commit . "9bfb9f0f566e937cc6a2f2913d1b56978b81dc99") (:keywords "languages" "crystal") (:url . "https://github.com/crystal-lang-tools/emacs-crystal-mode"))]) + (crystal-mode . [(20230223 2257) ((emacs (24 4))) "Major mode for editing Crystal files" single ((:commit . "ea2da3c7701542ca4cf703c7c29eb783269d18f6") (:keywords "languages" "crystal") (:url . "https://github.com/crystal-lang-tools/emacs-crystal-mode"))]) (crystal-playground . [(20180830 501) ((emacs (25)) (crystal-mode (0 1 2))) "Local crystal playground for short code snippets." single ((:commit . "532dc7e4239eb4bdd241bc4347d34760344c1ebb") (:authors ("Jason Howell")) (:maintainer "Jason Howell") (:keywords "tools" "crystal") (:url . "https://github.com/jasonrobot/crystal-playground"))]) (csgo-conf-mode . [(20161209 1619) nil "CS:GO Configuration files syntax highlighting" single ((:commit . "df45ca833eb68c394dd03acce5733a33c3b06bf8") (:authors ("Guillermo Robles" . "guillerobles1995@gmail.com")) (:maintainer "Guillermo Robles" . "guillerobles1995@gmail.com") (:keywords "languages") (:url . "https://github.com/wynro/emacs-csgo-conf-mode"))]) (csharp-mode . [(20221126 2005) ((emacs (26 1))) "C# mode derived mode" tar ((:commit . "d8b058c9e9d0429ea7e81d121ce19b064bd7e0f5") (:authors ("Theodor Thornhill" . "theo@thornhill.no")) (:maintainer "Jostein Kjønigsen" . "jostein@gmail.com") (:keywords "c#" "languages" "oop" "mode") (:url . "https://github.com/emacs-csharp/csharp-mode"))]) @@ -850,23 +854,24 @@ (dakrone-theme . [(20170801 1933) nil "dakrone's custom dark theme" single ((:commit . "232ad1be5f3572dcbdf528f1655109aa355a6937") (:authors ("Lee Hinman ")) (:maintainer "Lee Hinman ") (:keywords "color" "themes") (:url . "https://github.com/dakrone/dakrone-theme"))]) (danneskjold-theme . [(20221121 634) nil "Beautiful high-contrast Emacs theme." tar ((:commit . "39ff00f8a40bcab96afd9450195124b57becd625") (:authors ("Dmitry Akatov" . "akatovda@yandex.com")) (:maintainer "Dmitry Akatov" . "akatovda@yandex.com") (:url . "https://github.com/rails-to-cosmos/"))]) (dante . [(20221116 840) ((dash (2 12 0)) (emacs (27 1)) (f (0 19 0)) (flycheck (0 30)) (company (0 9)) (flymake (1 0)) (s (1 11 0)) (lcr (1 5))) "Development mode for Haskell" single ((:commit . "914d4f21252a66fe526abedebe24703bc73397d9") (:authors ("Jean-Philippe Bernardy" . "jeanphilippe.bernardy@gmail.com")) (:maintainer "Jean-Philippe Bernardy" . "jeanphilippe.bernardy@gmail.com") (:keywords "haskell" "tools") (:url . "https://github.com/jyp/dante"))]) - (dap-mode . [(20230220 1618) ((emacs (26 1)) (dash (2 18 0)) (lsp-mode (6 0)) (bui (1 1 0)) (f (0 20 0)) (s (1 12 0)) (lsp-treemacs (0 1)) (posframe (0 7 0)) (ht (2 3)) (lsp-docker (1 0 0))) "Debug Adapter Protocol mode" tar ((:commit . "f5a8f240d85ec4cfe87314a5ac0c245b60a7dfe0") (:authors ("Ivan Yonchovski" . "yyoncho@gmail.com")) (:maintainer "Ivan Yonchovski" . "yyoncho@gmail.com") (:keywords "languages" "debug") (:url . "https://github.com/emacs-lsp/dap-mode"))]) + (dap-mode . [(20230322 1728) ((emacs (26 1)) (dash (2 18 0)) (lsp-mode (6 0)) (bui (1 1 0)) (f (0 20 0)) (s (1 12 0)) (lsp-treemacs (0 1)) (posframe (0 7 0)) (ht (2 3)) (lsp-docker (1 0 0))) "Debug Adapter Protocol mode" tar ((:commit . "18254e16bae53fb4a8c2434764d3cf674644bf2a") (:authors ("Ivan Yonchovski" . "yyoncho@gmail.com")) (:maintainer "Ivan Yonchovski" . "yyoncho@gmail.com") (:keywords "languages" "debug") (:url . "https://github.com/emacs-lsp/dap-mode"))]) (darcsum . [(20190316 2215) nil "a pcl-cvs like interface for managing darcs patches" single ((:commit . "6a8b690539d133c5e3d17cb23fe4365fbb6fb493") (:authors ("John Wiegley" . "johnw@gnu.org")) (:maintainer "John Wiegley" . "johnw@gnu.org") (:keywords "completion" "convenience" "tools" "vc"))]) (darcula-theme . [(20171227 1845) nil "Inspired by IntelliJ's Darcula theme" single ((:commit . "d9b82b58ded9014985be6658f4ab17e26ed9e93e") (:authors ("Sam Halliday" . "Sam.Halliday@gmail.com")) (:maintainer "Sam Halliday" . "Sam.Halliday@gmail.com") (:keywords "faces") (:url . "https://gitlab.com/fommil/emacs-darcula-theme"))]) (dark-krystal-theme . [(20170808 1300) ((emacs (24 0))) "an Emacs 24 theme based on Dark Krystal (tmTheme)" single ((:commit . "79084b99665dc9ffb0ec62cc092349a5ecebebbc") (:authors ("Jason Milkins")) (:maintainer "Jason Milkins") (:url . "https://github.com/emacsfodder/tmtheme-to-deftheme"))]) (dark-mint-theme . [(20160302 642) nil "dark & minty fresh theme" single ((:commit . "c8ad39b7115baf889b54c3e9bffe32daeab93c29"))]) (dark-souls . [(20140314 1128) nil "Prepare to die" single ((:commit . "2c9437265b52f966b2fb13a410a12f3b1e167cb7") (:authors ("Tom Jakubowski" . "tom@crystae.net")) (:maintainer "Tom Jakubowski" . "tom@crystae.net") (:keywords "games") (:url . "http://github.com/tomjakubowski/dark-souls.el"))]) + (darkman . [(20230327 113) ((emacs (28 1))) "Seamless integration with Darkman" tar ((:commit . "3960a534781368c82737ee5d2c4c9e0cef22bf8f") (:authors ("Aziz Ben Ali" . "tahaaziz.benali@esprit.tn")) (:maintainer "Aziz Ben Ali" . "tahaaziz.benali@esprit.tn") (:keywords "convenience") (:url . "https://grtcdr.tn/darkman.el/"))]) (darkmine-theme . [(20160406 624) nil "Yet another emacs dark color theme." single ((:commit . "7f7e82ca03bcad52911fa41fb3e204e32d6ee63e") (:authors ("Pierre Lecocq" . "pierre.lecocq@gmail.com")) (:maintainer "Pierre Lecocq" . "pierre.lecocq@gmail.com") (:url . "https://github.com/pierre-lecocq/darkmine-theme"))]) (darkokai-theme . [(20200614 1452) nil "A darker variant on Monokai." single ((:commit . "5820aeddfc8c869ba840cc534eba776936656a66") (:url . "http://github.com/sjrmanning/darkokai"))]) (darktooth-theme . [(20221014 1418) ((emacs (27 1)) (autothemer (0 2))) "From the darkness... it watches" tar ((:commit . "fd3df73a4d937fa9e12f0b18acb009a9d40f245e") (:url . "http://github.com/emacsfodder/emacs-theme-darktooth"))]) (dart-mode . [(20220401 0) ((emacs (24 3))) "Major mode for editing Dart files" single ((:commit . "ae032b9b30ebadfe1b8a48a4cf278417e506d100") (:authors ("https://github.com/bradyt/dart-mode/issues")) (:maintainer "https://github.com/bradyt/dart-mode/issues") (:keywords "languages") (:url . "https://github.com/bradyt/dart-mode"))]) (dart-server . [(20210501 1445) ((emacs (24 5)) (cl-lib (0 5)) (dash (2 10 0)) (flycheck (0 23)) (s (1 10))) "Minor mode for editing Dart files" single ((:commit . "75562baf9a89b7e314bc2f795f6ecdc5d1f2cc8c") (:authors ("Natalie Weizenbaum") ("Brady Trainor" . "mail@bradyt.com")) (:maintainer "Brady Trainor" . "mail@bradyt.com") (:keywords "languages") (:url . "https://github.com/bradyt/dart-server"))]) - (dash . [(20221013 836) ((emacs (24))) "A modern list library for Emacs" tar ((:commit . "3df46d7d9fe74f52a661565888e4d31fd760f0df") (:authors ("Magnar Sveen" . "magnars@gmail.com")) (:maintainer "Magnar Sveen" . "magnars@gmail.com") (:keywords "extensions" "lisp") (:url . "https://github.com/magnars/dash.el"))]) + (dash . [(20230304 2223) ((emacs (24))) "A modern list library for Emacs" tar ((:commit . "bdf4a5d868618532d34c7b5bae6ac382c3b58f67") (:authors ("Magnar Sveen" . "magnars@gmail.com")) (:maintainer "Magnar Sveen" . "magnars@gmail.com") (:keywords "extensions" "lisp") (:url . "https://github.com/magnars/dash.el"))]) (dash-alfred . [(20191024 450) ((emacs (25 1))) "Search Dash documentation via Dash-Alfred-Workflow" single ((:commit . "fcd21bd6c7eb5cd31377be970406ff3d2454bd5c") (:authors ("Xu Chunyang")) (:maintainer "Xu Chunyang") (:keywords "docs") (:url . "https://github.com/xuchunyang/dash-alfred.el"))]) (dash-at-point . [(20211023 104) nil "Search the word at point with Dash" single ((:commit . "fba1a6f42ea51d05110e12c62bdced664059eb55") (:authors ("Shinji Tanaka" . "shinji.tanaka@gmail.com")) (:maintainer "Shinji Tanaka" . "shinji.tanaka@gmail.com") (:url . "https://github.com/stanaka/dash-at-point"))]) (dash-docs . [(20210830 926) ((emacs (24 4)) (cl-lib (0 5)) (async (1 9 3))) "Offline documentation browser using Dash docsets." tar ((:commit . "29848b6b347ac520f7646c200ed2ec36cea3feda") (:authors ("Raimon Grau" . "raimonster@gmail.com") ("Toni Reina " . "areina0@gmail.com") ("Bryan Gilbert" . "bryan@bryan.sh")) (:maintainer "Raimon Grau" . "raimonster@gmail.com") (:keywords "docs") (:url . "http://github.com/areina/helm-dash"))]) (dash-functional . [(20210826 1149) ((dash (2 18 0))) "Collection of useful combinators for Emacs Lisp" single ((:commit . "39d067b9fbb2db65fc7a6938bfb21489ad990cb4") (:authors ("Matus Goljer" . "matus.goljer@gmail.com") ("Magnar Sveen" . "magnars@gmail.com")) (:maintainer "Matus Goljer" . "matus.goljer@gmail.com") (:keywords "extensions" "lisp") (:url . "https://github.com/magnars/dash.el"))]) - (dashboard . [(20230220 1916) ((emacs (26 1))) "A startup screen extracted from Spacemacs" tar ((:commit . "221ee4b77db77199380c519c4ba52c06abc725e9") (:authors ("Rakan Al-Hneiti" . "rakan.alhneiti@gmail.com")) (:maintainer "Jesús Martínez" . "jesusmartinez93@gmail.com") (:keywords "startup" "screen" "tools" "dashboard") (:url . "https://github.com/emacs-dashboard/emacs-dashboard"))]) + (dashboard . [(20230331 2304) ((emacs (26 1))) "A startup screen extracted from Spacemacs" tar ((:commit . "0f970d298931f9de7b511086728af140bf44a642") (:authors ("Rakan Al-Hneiti" . "rakan.alhneiti@gmail.com")) (:maintainer "Jesús Martínez" . "jesusmartinez93@gmail.com") (:keywords "startup" "screen" "tools" "dashboard") (:url . "https://github.com/emacs-dashboard/emacs-dashboard"))]) (dashboard-hackernews . [(20220516 1809) ((emacs (24)) (dashboard (1 2 5)) (request (0 3 0))) "Display Hacker News on dashboard" single ((:commit . "34d86bffcde7e6d10ffa7c5080a71a144f01f3aa") (:authors ("Hayato KAJIYAMA" . "kaji1216@gmail.com")) (:maintainer "Hayato KAJIYAMA" . "kaji1216@gmail.com") (:url . "https://github.com/hyakt/emacs-dashboard-hackernews"))]) (dashboard-ls . [(20221231 1629) ((emacs (26 1)) (dashboard (1 2 5))) "Display files/directories in current directory on Dashboard" single ((:commit . "b24e0bcb87e20ffcc71efb83a97f9516255fa8e4") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "directory" "file" "show") (:url . "https://github.com/emacs-dashboard/dashboard-ls"))]) (dashboard-project-status . [(20190202 1354) ((emacs (24)) (git (0 1 1)) (dashboard (1 2 5))) "Display a git project status in a dashboard widget." single ((:commit . "7675c138e9df8fe2c626e7ba9bbb8b6717671a41") (:authors ("Jason Duncan" . "jasond496@msn.com")) (:maintainer "Jason Duncan" . "jasond496@msn.com") (:url . "https://github.com/functionreturnfunction/dashboard-project-status"))]) @@ -881,9 +886,9 @@ (db-pg . [(20130131 1902) ((pg (0 12)) (db (0 0 6))) "A PostgreSQL adapter for emacs-db" single ((:commit . "7d5ab86b74b05fe003b3b434d4835f37f3f3eded") (:authors ("Nic Ferrier" . "nic@ferrier.me.uk")) (:maintainer "Nic Ferrier" . "nic@ferrier.me.uk") (:keywords "data" "comm" "database" "postgresql"))]) (dbc . [(20201001 1452) ((emacs (24 4)) (cl-lib (0 5)) (ht (2 3))) "Control how to open buffers" single ((:commit . "6728e72f72347d098b7d75ac4c29a7d687cc9ed3") (:authors ("Matsievskiy S.V.")) (:maintainer "Matsievskiy S.V.") (:keywords "convenience") (:url . "https://gitlab.com/matsievskiysv/display-buffer-control"))]) (ddate . [(20221031 1611) ((emacs (24 4))) "Manage Discordian dates with ddate" single ((:commit . "31576a62792743c614e362688b3752b7a959814e") (:authors ("Erik L. Arneson" . "earneson@arnesonium.com")) (:maintainer "Erik L. Arneson" . "earneson@arnesonium.com") (:keywords "lisp" "dates" "tools" "dashboard") (:url . "https://git.sr.ht/~earneson/emacs-ddate"))]) - (ddskk . [(20221030 2049) ((ccc (1 43)) (cdb (20141201 754))) "Simple Kana to Kanji conversion program." tar ((:commit . "c24a624884a3cfb0c28d6d5b9eb19e01387f0917") (:authors ("Masahiko Sato" . "masahiko@kuis.kyoto-u.ac.jp")) (:maintainer "SKK Development Team") (:keywords "japanese" "mule" "input method") (:url . "https://github.com/skk-dev/ddskk"))]) + (ddskk . [(20230328 1058) ((ccc (1 43)) (cdb (20141201 754))) "Simple Kana to Kanji conversion program." tar ((:commit . "98c103ed697e461439401f731c13b3bda02e5128") (:authors ("Masahiko Sato" . "masahiko@kuis.kyoto-u.ac.jp")) (:maintainer "SKK Development Team") (:keywords "japanese" "mule" "input method") (:url . "https://github.com/skk-dev/ddskk"))]) (ddskk-posframe . [(20200812 917) ((emacs (26 1)) (posframe (0 4 3)) (ddskk (16 2 50))) "Show Henkan tooltip for ddskk via posframe" single ((:commit . "299493dd951e5a0b43b8213321e3dc0bac10f762") (:authors ("Naoya Yamashita" . "conao3@gmail.com")) (:maintainer "Naoya Yamashita" . "conao3@gmail.com") (:keywords "tooltip" "convenience" "posframe") (:url . "https://github.com/conao3/ddskk-posframe.el"))]) - (deadgrep . [(20230201 2329) ((emacs (25 1)) (dash (2 12 0)) (s (1 11 0)) (spinner (1 7 3))) "fast, friendly searching with ripgrep" single ((:commit . "0d3e0725a7fe605978692076ab1d8f1870d8a269") (:authors ("Wilfred Hughes" . "me@wilfred.me.uk")) (:maintainer "Wilfred Hughes" . "me@wilfred.me.uk") (:keywords "tools") (:url . "https://github.com/Wilfred/deadgrep"))]) + (deadgrep . [(20230310 1634) ((emacs (25 1)) (dash (2 12 0)) (s (1 11 0)) (spinner (1 7 3))) "fast, friendly searching with ripgrep" single ((:commit . "aed448bf4c8bdf94564b775aac2429be6ed028b9") (:authors ("Wilfred Hughes" . "me@wilfred.me.uk")) (:maintainer "Wilfred Hughes" . "me@wilfred.me.uk") (:keywords "tools") (:url . "https://github.com/Wilfred/deadgrep"))]) (debian-el . [(20211006 1939) nil "Emacs helpers specific to Debian users" tar ((:commit . "a3ef20c269b9192710567571b20718f572942bc4"))]) (debpaste . [(20161214 2023) ((xml-rpc (1 6 7))) "Interface for getting/posting/deleting pastes from paste.debian.net" single ((:commit . "6f2a400665062468ebd03a2ce1de2a73d9084958") (:authors ("Alex Kost" . "alezost@gmail.com")) (:maintainer "Alex Kost" . "alezost@gmail.com") (:keywords "paste") (:url . "http://github.com/alezost/debpaste.el"))]) (debug-print . [(20140126 19) ((emacs (24))) "A nice printf debugging environment by the way Gauche do" single ((:commit . "d817fd9ea2d3f8d2c1ace4d8af155684f3a99dc5") (:authors ("Ken Okada" . "keno.ss57@gmail.com")) (:maintainer "Ken Okada" . "keno.ss57@gmail.com") (:keywords "extensions" "lisp" "tools" "maint") (:url . "https://github.com/kenoss/debug-print"))]) @@ -909,7 +914,7 @@ (describe-hash . [(20200718 1556) nil "Help function for examining a hash map" single ((:commit . "20dbbbea630055b2401f13a55fbb21216960dc46") (:url . "https://github.com/Junker/describe-hash"))]) (describe-number . [(20151101 55) ((yabin (1 1))) "Describe arbitrarily large number at point." single ((:commit . "40618345a37831804b29589849a785ef5aa5ac24") (:authors ("Morten Slot Kristensen ")) (:maintainer "Morten Slot Kristensen ") (:keywords "describe" "value" "help") (:url . "https://github.com/netromdk/describe-number"))]) (desktop+ . [(20170107 2132) ((emacs (24 4)) (dash (2 11 0)) (f (0 17 2))) "Handle special buffers when saving & restoring sessions" single ((:commit . "d26f369bda96860eef18365cdb5c79f39a2c765c") (:authors ("François Févotte" . "fevotte@gmail.com")) (:maintainer "François Févotte" . "fevotte@gmail.com") (:url . "https://github.com/ffevotte/desktop-plus"))]) - (desktop-environment . [(20230118 820) ((emacs (25 1))) "Helps you control your GNU/Linux computer" single ((:commit . "3b1fe3816ffaef16d210939dc74bd19e0024ff64") (:authors ("Damien Cassou , Nicolas Petton" . "nicolas@petton.fr")) (:maintainer "Damien Cassou , Nicolas Petton" . "nicolas@petton.fr") (:url . "https://gitlab.petton.fr/DamienCassou/desktop-environment"))]) + (desktop-environment . [(20230403 1823) ((emacs (25 1))) "Helps you control your GNU/Linux computer" single ((:commit . "530035e567a95830f1a8b265e026b76d163c7367") (:authors ("Damien Cassou , Nicolas Petton" . "nicolas@petton.fr")) (:maintainer "Damien Cassou , Nicolas Petton" . "nicolas@petton.fr") (:url . "https://gitlab.petton.fr/DamienCassou/desktop-environment"))]) (desktop-mail-user-agent . [(20210519 1008) ((emacs (24 3))) "Call OS default mail program to compose mail" single ((:commit . "caac672ef7e4ddced960fa31cef3a6ba5d7ab451") (:authors ("Lassi Kortela" . "lassi@lassi.io")) (:maintainer "Lassi Kortela" . "lassi@lassi.io") (:keywords "mail") (:url . "https://github.com/lassik/emacs-desktop-mail-user-agent"))]) (desktop-registry . [(20140119 2143) nil "Keep a central registry of desktop files" single ((:commit . "244c2e7f9f0a1050aa8a47ad0b38f4e4584682dd") (:authors ("Tom Willemse" . "tom@ryuslash.org")) (:maintainer "Tom Willemse" . "tom@ryuslash.org") (:keywords "convenience") (:url . "http://projects.ryuslash.org/desktop-registry/"))]) (detached . [(20221129 1430) ((emacs (27 1))) "A package to launch, and manage, detached processes" tar ((:commit . "6b64d4d8064cee781e071e825857b442ea96c3d9") (:authors ("Niklas Eklund" . "niklas.eklund@posteo.net")) (:maintainer "detached.el Development" . "~niklaseklund/detached.el@lists.sr.ht") (:keywords "convenience" "processes") (:url . "https://sr.ht/~niklaseklund/detached.el/"))]) @@ -917,7 +922,7 @@ (devdocs . [(20230220 2042) ((emacs (27 1))) "Emacs viewer for DevDocs" single ((:commit . "2988d4d201df16d72c3bea465d2b93b554dbddfc") (:authors ("Augusto Stoffel" . "arstoffel@gmail.com")) (:maintainer "Augusto Stoffel" . "arstoffel@gmail.com") (:keywords "help") (:url . "https://github.com/astoff/devdocs.el"))]) (devdocs-browser . [(20230112 1554) ((emacs (27 1))) "Browse devdocs.io documents using EWW" single ((:commit . "c316c93306527fcb4069adde94402a48605d42d5") (:authors ("blahgeek" . "i@blahgeek.com")) (:maintainer "blahgeek" . "i@blahgeek.com") (:keywords "docs" "help" "tools") (:url . "https://github.com/blahgeek/emacs-devdocs-browser"))]) (dfmt . [(20170728 1023) nil "Emacs Interface to D indenting/formatting tool dfmt." single ((:commit . "21b9094e907b7ac53f5ecb4ff4539613a9d12434") (:authors ("Per Nordlöw")) (:maintainer "Kirill Babikhin ") (:keywords "tools" "convenience" "languages" "dlang") (:url . "https://github.com/qsimpleq/elisp-dfmt"))]) - (dhall-mode . [(20220519 1115) ((emacs (24 4)) (reformatter (0 3))) "Major mode for the dhall configuration language" single ((:commit . "c77f1c1e75b6d2725019c5275fc102ae98d25628") (:authors ("Sibi Prabakaran" . "sibi@psibi.in")) (:maintainer "Sibi Prabakaran" . "sibi@psibi.in") (:keywords "languages") (:url . "https://github.com/psibi/dhall-mode"))]) + (dhall-mode . [(20230228 1005) ((emacs (24 4)) (reformatter (0 3))) "Major mode for the dhall configuration language" single ((:commit . "87ab69fe765d87b3bb1604a306a8c44d6887681d") (:authors ("Sibi Prabakaran" . "sibi@psibi.in")) (:maintainer "Sibi Prabakaran" . "sibi@psibi.in") (:keywords "languages") (:url . "https://github.com/psibi/dhall-mode"))]) (dianyou . [(20210525 1517) ((emacs (24 4))) "Search and analyze mails in Gnus" single ((:commit . "f77d9e76be5d8022fa6ee5426144f13f38dd09f2") (:authors ("Chen Bin ")) (:maintainer "Chen Bin ") (:keywords "mail") (:url . "http://github.com/redguardtoo/dianyou"))]) (diary-manager . [(20220929 2042) ((emacs (25))) "Simple personal diary" single ((:commit . "56c739224e5bb845d275bfe3f4e420285de3a929") (:authors ("Radian LLC" . "contact+diary-manager@radian.codes")) (:maintainer "Radian LLC" . "contact+diary-manager@radian.codes") (:keywords "extensions") (:url . "https://github.com/radian-software/diary-manager"))]) (dic-lookup-w3m . [(20180526 1621) ((w3m (20120723 324)) (stem (20120826))) "look up dictionaries on the Internet" tar ((:commit . "3254ab10cbf0078c7162557dd1f68dac28459cf9") (:authors ("mcprvmec")) (:maintainer "mcprvmec") (:keywords "emacs-w3m" "w3m" "dictionary"))]) @@ -925,14 +930,14 @@ (dictionary . [(20201001 1727) ((connection (1 11)) (link (1 11))) "Client for rfc2229 dictionary servers" single ((:commit . "bdf0aa7761d1c1a3bc0652b2fdc4a54b3acdb06a") (:authors ("Torsten Hilbrich" . "torsten.hilbrich@gmx.net")) (:maintainer "Torsten Hilbrich" . "torsten.hilbrich@gmx.net") (:keywords "interface" "dictionary"))]) (didyoumean . [(20200905 1843) ((emacs (24 4))) "Did you mean to open another file?" single ((:commit . "ce5edcce160b86e7f6480f0381be785d43f97e19") (:keywords "convenience") (:url . "https://gitlab.com/kisaragi-hiu/didyoumean.el"))]) (diff-ansi . [(20230201 134) ((emacs (27 1))) "Display diff's using alternative diffing tools" single ((:commit . "84446e315a163cecb7259858c9b01d2e6726775e") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:url . "https://codeberg.org/ideasman42/emacs-diff-ansi"))]) - (diff-at-point . [(20230116 951) ((emacs (26 2))) "Diff navigation" single ((:commit . "72079cd8143b949228a51529f897076ead61ff43") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:url . "https://codeberg.org/ideasman42/emacs-diff-at-point"))]) + (diff-at-point . [(20230320 2355) ((emacs (26 2))) "Diff navigation" single ((:commit . "0a4815a364b636eadf2f9ca6f468fb5996ff8d6f") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:url . "https://codeberg.org/ideasman42/emacs-diff-at-point"))]) (diff-hl . [(20230218 2323) ((cl-lib (0 2)) (emacs (25 1))) "Highlight uncommitted changes using VC" tar ((:commit . "d20f16bf5eadd66e775f215e800f25caddae8cb5") (:authors ("Dmitry Gutov" . "dgutov@yandex.ru")) (:maintainer "Dmitry Gutov" . "dgutov@yandex.ru") (:keywords "vc" "diff") (:url . "https://github.com/dgutov/diff-hl"))]) (diffed . [(20230208 1546) ((emacs (27 1))) "Diffed is for recursive diff like Dired is for ls" single ((:commit . "f7dc37f13a4f1660212c41a6e9faba61eb8cc078") (:authors ("Bernhard Rotter" . "bernhard@b-rotter.de")) (:maintainer "Bernhard Rotter" . "bernhard@b-rotter.de") (:keywords "tools") (:url . "https://github.com/ber-ro/diffed"))]) (difflib . [(20210224 2242) ((emacs (24 4)) (cl-generic (0 3)) (ht (2 2)) (s (1 12 0))) "Helpers for computing deltas between sequences." single ((:commit . "646fc4388274fe765bbf4661e17a24e4d081250c") (:authors ("Diego A. Mundo" . "dieggsy@pm.me")) (:maintainer "Diego A. Mundo" . "dieggsy@pm.me") (:keywords "matching" "tools" "string") (:url . "http://github.com/dieggsy/difflib.el"))]) (diffpdf . [(20210626 1447) ((emacs (25 1)) (transient (0 3 0))) "Transient diffpdf" single ((:commit . "a5b203b549e373cb9b0ef3f00c0010bd34dd644a") (:authors ("Shuguang Sun" . "shuguang79@qq.com")) (:maintainer "Shuguang Sun" . "shuguang79@qq.com") (:keywords "tools") (:url . "https://github.com/ShuguangSun/diffpdf.el"))]) (diffscuss-mode . [(20141014 2357) nil "Major mode for diffscuss files." single ((:commit . "bbc6dbed4b97d1eb9ae5dae021ed1e066129bd98") (:authors ("Edmund Jorgensen" . "edmund@hut8labs.com")) (:maintainer "Edmund Jorgensen" . "edmund@hut8labs.com") (:keywords "tools"))]) - (diffview . [(20220322 2334) nil "View diffs in side-by-side format" single ((:commit . "bba07de698b519c143bffb57143a780b3dac299d") (:authors ("Mitchel Humpherys" . "mitch.special@gmail.com")) (:maintainer "Mitchel Humpherys" . "mitch.special@gmail.com") (:keywords "convenience" "diff") (:url . "https://github.com/mgalgs/diffview-mode"))]) - (digistar-mode . [(20221201 2332) nil "major mode for Digistar scripts" single ((:commit . "06795403c30f3b3c7b72d7cb5ca33c32d0aaee49") (:authors ("John Foerch" . "jjfoerch@gmail.com")) (:maintainer "John Foerch" . "jjfoerch@gmail.com") (:keywords "languages"))]) + (diffview . [(20230224 1916) nil "View diffs in side-by-side format" single ((:commit . "8f07c0ff4a1acef990589df0d3e32288f19c9d71") (:authors ("Mitchel Humpherys" . "mitch.special@gmail.com")) (:maintainer "Mitchel Humpherys" . "mitch.special@gmail.com") (:keywords "convenience" "diff") (:url . "https://github.com/mgalgs/diffview-mode"))]) + (digistar-mode . [(20230313 1256) nil "major mode for Digistar scripts" single ((:commit . "2bb1076778468d90a132c04f7b8455fb887b6bfe") (:authors ("John Foerch" . "jjfoerch@gmail.com")) (:maintainer "John Foerch" . "jjfoerch@gmail.com") (:keywords "languages"))]) (digit-groups . [(20200506 37) ((dash (2 11 0))) "Highlight place-value positions in numbers" single ((:commit . "7b81930cad19b8b7913b7eedbcb498964bfdcbdb") (:authors ("Michael D. Adams ")) (:maintainer "Michael D. Adams ") (:url . "https://github.com/adamsmd/digit-groups/"))]) (digitalocean . [(20190607 726) ((request (2 5)) (emacs (24 4))) "Create and manipulate digitalocean droplets" single ((:commit . "6c32d3593286e2a62d9afab0057c829407b0d1e8") (:authors ("Oliver Marks" . "oly@digitaloctave.com")) (:maintainer "Oliver Marks" . "oly@digitaloctave.com") (:keywords "processes" "tools") (:url . "https://github.com/olymk2/emacs-digitalocean"))]) (digitalocean-helm . [(20180610 746) ((emacs (24 3)) (helm (2 5)) (digitalocean (0 1))) "Create and manipulate digitalocean droplets" single ((:commit . "b125c9882eded7d73ec109d152b26625f333440b") (:authors ("Oliver Marks" . "oly@digitaloctave.com")) (:maintainer "Oliver Marks" . "oly@digitaloctave.com") (:keywords "processes" "tools") (:url . "https://gitlab.com/olymk2/digitalocean-api"))]) @@ -965,8 +970,9 @@ (dired-imenu . [(20140109 1610) nil "imenu binding for dired mode" single ((:commit . "610e21fe0988c85931d34894d3eee2442c79ab0a") (:authors ("Damien Cassou" . "damien.cassou@gmail.com")) (:maintainer "Damien Cassou" . "damien.cassou@gmail.com") (:keywords "dired" "imenu") (:url . "https://github.com/DamienCassou/dired-imenu"))]) (dired-k . [(20211002 2358) ((emacs (24 3))) "Highlight dired by size, date, git status" tar ((:commit . "b9507bac79fc8c030abbec389267262bc671f58b") (:authors ("Syohei YOSHIDA" . "syohex@gmail.com")) (:maintainer "Neil Okamoto" . "neil.okamoto+melpa@gmail.com") (:url . "https://github.com/emacsorphanage/dired-k"))]) (dired-launch . [(20220916 1836) ((emacs (24 3))) "Use dired as a launcher" single ((:commit . "519a6a49b56978b53e88a005490175cb913ec7fa") (:authors ("David Thompson")) (:maintainer "David Thompson") (:keywords "dired" "launch") (:url . "https://github.com/thomp/dired-launch"))]) + (dired-list . [(20230316 901) ((dash (2 10 0)) (emacs (24 3)) (dired-hacks-utils (0 0 1))) "Create dired listings from sources" single ((:commit . "10f636d45c94cdc0a724ebb9d5b62a16401c1a74") (:authors ("Matúš Goljer" . "matus.goljer@gmail.com")) (:maintainer "Matúš Goljer" . "matus.goljer@gmail.com") (:keywords "files") (:url . "https://github.com/Fuco1/dired-hacks"))]) (dired-lsi . [(20200812 929) ((emacs (26 1))) "Add memo to directory and show it in dired" single ((:commit . "0f4038c8b47f6cfc70f82062800700c14c9912c2") (:authors ("Naoya Yamashita" . "conao3@gmail.com")) (:maintainer "Naoya Yamashita" . "conao3@gmail.com") (:keywords "convenience") (:url . "https://github.com/conao3/dired-lsi.el"))]) - (dired-narrow . [(20221127 1247) ((dash (2 7 0)) (dired-hacks-utils (0 0 1))) "Live-narrowing of search results for dired" single ((:commit . "41d3eb42195d9f0894c20d18cc8e722b099aa1c1") (:authors ("Matúš Goljer" . "matus.goljer@gmail.com")) (:maintainer "Matúš Goljer" . "matus.goljer@gmail.com") (:keywords "files"))]) + (dired-narrow . [(20230318 2146) ((dash (2 7 0)) (dired-hacks-utils (0 0 1))) "Live-narrowing of search results for dired" single ((:commit . "1596e516835099b96cb65d1dc372cfbdff6aea96") (:authors ("Matúš Goljer" . "matus.goljer@gmail.com")) (:maintainer "Matúš Goljer" . "matus.goljer@gmail.com") (:keywords "files"))]) (dired-open . [(20221127 1247) ((dash (2 5 0)) (dired-hacks-utils (0 0 1))) "Open files from dired using using custom actions" single ((:commit . "41d3eb42195d9f0894c20d18cc8e722b099aa1c1") (:authors ("Matúš Goljer" . "matus.goljer@gmail.com")) (:maintainer "Matúš Goljer" . "matus.goljer@gmail.com") (:keywords "files"))]) (dired-posframe . [(20200817 420) ((emacs (26 1)) (posframe (0 7))) "Peep dired items using posframe" single ((:commit . "1a21eb9ad956a0371dd3c9e1bec53407d685f705") (:authors ("Naoya Yamashita" . "conao3@gmail.com")) (:maintainer "Naoya Yamashita" . "conao3@gmail.com") (:keywords "convenience") (:url . "https://github.com/conao3/dired-posframe.el"))]) (dired-quick-sort . [(20201221 403) ((hydra (0 13 0)) (emacs (24))) "Persistent quick sorting of dired buffers in various ways." single ((:commit . "69b06f306a5fc2b38e707bae3ff1e35db2b39b6b") (:authors ("Hong Xu" . "hong@topbug.net")) (:maintainer "Hong Xu" . "hong@topbug.net") (:keywords "convenience" "files") (:url . "https://gitlab.com/xuhdev/dired-quick-sort#dired-quick-sort"))]) @@ -978,13 +984,13 @@ (dired-rsync . [(20230126 1144) ((s (1 12 0)) (dash (2 0 0)) (emacs (25 1))) "Allow rsync from dired buffers" single ((:commit . "5496bc00f7a32a9d3e54e395f29d44e9df771567") (:authors ("Alex Bennée" . "alex@bennee.com")) (:maintainer "Alex Bennée" . "alex@bennee.com") (:url . "https://github.com/stsquad/dired-rsync"))]) (dired-rsync-transient . [(20221214 1215) ((dired-rsync (0 6)) (transient (0 3 0)) (emacs (24 4))) "Transient command for dired-rsync" single ((:commit . "c0e2168b80df00116ab9071bb214cf05ed943d73") (:authors ("Alex Bennée" . "alex@bennee.com")) (:maintainer "Alex Bennée" . "alex@bennee.com") (:url . "https://github.com/stsquad/dired-rsync"))]) (dired-sidebar . [(20230216 432) ((emacs (25 1)) (dired-subtree (0 0 1))) "Tree browser leveraging dired" single ((:commit . "5569d3b53585f5413cf87a694650d0fd6e040803") (:authors ("James Nguyen" . "james@jojojames.com")) (:maintainer "James Nguyen" . "james@jojojames.com") (:keywords "dired" "files" "tools") (:url . "https://github.com/jojojames/dired-sidebar"))]) - (dired-single . [(20220917 625) nil "Reuse the current dired buffer to visit a directory" single ((:commit . "3bb53664ccdfb2f911667947be6b6c022e4ec758") (:keywords "dired" "reuse" "buffer") (:url . "https://github.com/crocket/dired-single"))]) + (dired-single . [(20230306 626) ((emacs (25 1))) "Reuse the current dired buffer" single ((:commit . "c781b7dcff6e7f9a5060b067d2cdb0acbc840c49") (:url . "https://codeberg.org/amano.kenji/dired-single"))]) (dired-subtree . [(20230118 1953) ((dash (2 5 0)) (dired-hacks-utils (0 0 1))) "Insert subdirectories in a tree-like fashion" single ((:commit . "1382acb219c5e3b179662bcacd9c57463802718a") (:authors ("Matúš Goljer" . "matus.goljer@gmail.com")) (:maintainer "Matúš Goljer" . "matus.goljer@gmail.com") (:keywords "files"))]) (dired-toggle . [(20190616 303) nil "Show dired as sidebar and will not create new buffers when changing dir" single ((:commit . "b694ba91a45d0762bd032ff1bb4109e4c62ca686") (:authors ("Xu FaSheng ")) (:maintainer "Xu FaSheng") (:keywords "dired" "sidebar") (:url . "https://github.com/fasheng/dired-toggle"))]) (dired-toggle-sudo . [(20211216 102) nil "Browse directory with sudo privileges." single ((:commit . "9f86cdf858225b15c20affb97ed105e4109047bf") (:authors ("Sebastien Gross ")) (:maintainer "Sebastien Gross ") (:keywords "emacs" "dired"))]) (dired-view-data . [(20220129 339) ((emacs (26 1)) (ess (18 10 1)) (ess-view-data (1 0))) "View data from dired via ESS and R" single ((:commit . "96d4cb6569fd2be90a516dedd98263374bbc6ead") (:authors ("Shuguang Sun" . "shuguang79@qq.com")) (:maintainer "Shuguang Sun" . "shuguang79@qq.com") (:keywords "tools") (:url . "https://github.com/ShuguangSun/dired-view-data"))]) (diredc . [(20220113 332) ((emacs (26 1)) (key-assist (1 0))) "Extensions for dired" single ((:commit . "7ee68f6b1c87f8ab86cf23416472747e88860717") (:keywords "files") (:url . "https://github.com/Boruch-Baum/emacs-diredc"))]) - (diredfl . [(20220508 805) ((emacs (24))) "Extra font lock rules for a more colourful dired" single ((:commit . "62b559e1d6b69834a56a57eb1832ac6ad4d2e5d0") (:authors ("Steve Purcell" . "steve@sanityinc.com")) (:maintainer "Steve Purcell" . "steve@sanityinc.com") (:keywords "faces") (:url . "https://github.com/purcell/diredfl"))]) + (diredfl . [(20230224 1302) ((emacs (24))) "Extra font lock rules for a more colourful dired" single ((:commit . "17e805763d57370c4eff2c92ed257b72eeb9f94a") (:authors ("Steve Purcell" . "steve@sanityinc.com")) (:maintainer "Steve Purcell" . "steve@sanityinc.com") (:keywords "faces") (:url . "https://github.com/purcell/diredfl"))]) (diredful . [(20160529 2017) nil "colorful file names in dired buffers" single ((:commit . "b17b3087e0084a5571a9ac4d47ccfc36d96b109e") (:authors ("Thamer Mahmoud" . "thamer.mahmoud@gmail.com")) (:maintainer "Thamer Mahmoud" . "thamer.mahmoud@gmail.com") (:keywords "dired" "colors" "extension" "widget") (:url . "https://github.com/thamer/diredful"))]) (direnv . [(20220812 956) ((emacs (25 1)) (dash (2 12 0))) "direnv integration" single ((:commit . "268536f564b7eba99264a89a9149268eb4bc67ac") (:authors ("wouter bolsterlee" . "wouter@bolsterl.ee")) (:maintainer "wouter bolsterlee" . "wouter@bolsterl.ee") (:keywords "direnv" "environment" "processes" "unix" "tools") (:url . "https://github.com/wbolster/emacs-direnv"))]) (direx . [(20170422 1327) nil "Simple Directory Explorer" tar ((:commit . "a79bfdb5980cf6ed7bfb3b41ddc471a7b6c0ede4") (:authors ("Tomohiro Matsuyama" . "m2ym.pub@gmail.com")) (:maintainer "Tomohiro Matsuyama" . "m2ym.pub@gmail.com") (:keywords "convenience"))]) @@ -993,7 +999,7 @@ (dirtree-prosjekt . [(20140129 904) ((prosjekt (0 3)) (dirtree (0 1))) "dirtree integration for prosjekt." single ((:commit . "03e06910589ba5cd736868793eb436b3233c6a26") (:authors ("Austin Bingham" . "austin.bingham@gmail.com")) (:maintainer "Austin Bingham" . "austin.bingham@gmail.com") (:url . "https://github.com/abingham/prosjekt"))]) (dirvish . [(20230123 1201) ((emacs (27 1)) (transient (0 3 7))) "A modern file manager based on dired mode" tar ((:commit . "65954585a9e16a06f6ec1f0dec475b27ec4c218c") (:authors ("Alex Lu ")) (:maintainer "Alex Lu ") (:keywords "files" "convenience") (:url . "https://github.com/alexluigit/dirvish"))]) (disable-mouse . [(20210512 2114) ((emacs (24 1))) "Disable mouse commands globally" single ((:commit . "cae3be9dd012727b40ad3b511731191f79cebe42") (:authors ("Steve Purcell" . "steve@sanityinc.com")) (:maintainer "Steve Purcell" . "steve@sanityinc.com") (:keywords "mouse") (:url . "https://github.com/purcell/disable-mouse"))]) - (disaster . [(20220904 449) ((emacs (27))) "Disassemble C, C++ or Fortran code under cursor" single ((:commit . "0c13bd244cc43773af81e52ce73a55f199d58a61") (:authors ("Justine Tunney" . "jtunney@gmail.com") ("Abdelhak Bougouffa" . "abougouffa@fedoraproject.org")) (:maintainer "Abdelhak Bougouffa" . "abougouffa@fedoraproject.org") (:keywords "tools" "c") (:url . "https://github.com/jart/disaster"))]) + (disaster . [(20230311 2324) ((emacs (27))) "Disassemble C, C++ or Fortran code under cursor" single ((:commit . "16bba9afb92aacf06c088c29ba47813b65a80d87") (:authors ("Justine Tunney" . "jtunney@gmail.com") ("Abdelhak Bougouffa" . "abougouffa@fedoraproject.org")) (:maintainer "Abdelhak Bougouffa" . "abougouffa@fedoraproject.org") (:keywords "tools" "c") (:url . "https://github.com/jart/disaster"))]) (discourse . [(20160911 819) ((cl-lib (0 5)) (request (0 2)) (s (1 11 0))) "discourse api" single ((:commit . "a86c7e608851e186fe12e892a573994f08c8e65e") (:authors ("DarkSun" . "lujun9972@gmail.com")) (:maintainer "DarkSun" . "lujun9972@gmail.com") (:keywords "lisp" "discourse") (:url . "https://github.com/lujun9972/discourse-api"))]) (discover . [(20140103 2139) ((makey (0 3))) "discover more of Emacs" single ((:commit . "bbfda2b4e429985a8fa7971d264c942767cfa816") (:authors ("Mickey Petersen" . "mickey@fyeah.org")) (:maintainer "Mickey Petersen" . "mickey@fyeah.org"))]) (discover-clj-refactor . [(20150328 1459) ((clj-refactor (0 14 0)) (discover (0 3))) "Adds discover context menu for clj-refactor" single ((:commit . "3fbd5c1162739e606d7cf5d4f5d7426547d99647") (:authors ("Marian Schubert" . "marian.schubert@gmail.com")) (:maintainer "Marian Schubert" . "marian.schubert@gmail.com") (:keywords "clj-refactor" "discover" "convenience"))]) @@ -1025,10 +1031,10 @@ (dmacro . [(20200803 633) ((emacs (24 1)) (cl-lib (0 6))) "Repeated detection and execution of key operation" single ((:commit . "0008e7d2403a20f444b29a63fad65819aefabe18") (:authors ("Toshiyuki Masui" . "masui@ptiecan.com") ("Makoto Owada") ("Eiji Obata") ("Nobuyuki Mine")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "convenience") (:url . "https://github.com/emacs-jp/dmacro"))]) (dmenu . [(20190908 44) ((cl-lib (0 5))) "simulate the dmenu command line program" single ((:commit . "e8cc9b27c79d3ecc252267c082ab8e9c82eab264") (:authors ("DarkSun" . "lujun9972@gmail.com")) (:maintainer "DarkSun" . "lujun9972@gmail.com") (:keywords "convenience" "usability"))]) (dna-mode . [(20191001 2108) nil "a major mode for editing dna sequences" tar ((:commit . "7a48393fcf0015eed2368fcb89b3091c9d029dc4") (:authors ("Harley Gorrell" . "harley@panix.com")) (:maintainer "Harley Gorrell" . "harley@panix.com") (:keywords "dna" "emacs" "editing") (:url . "http://www.mahalito.net/~harley/elisp/dna-mode.el"))]) - (doc-show-inline . [(20230116 2310) ((emacs (27 1))) "Show doc-strings found in external files" single ((:commit . "641c2c8bf55ec4a0f9da8dd99b95cd1464997a66") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:keywords "convenience") (:url . "https://codeberg.org/ideasman42/emacs-doc-show-inline"))]) + (doc-show-inline . [(20230319 528) ((emacs (27 1))) "Show doc-strings found in external files" single ((:commit . "261554a788e9cc6c0ba538a732667e514fab70c6") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:keywords "convenience") (:url . "https://codeberg.org/ideasman42/emacs-doc-show-inline"))]) (docbook-snippets . [(20150714 1625) ((yasnippet (0 8 0))) "Yasnippets for DocBook" tar ((:commit . "b06297fdec039a541aaa6312cb328a11062cfab4") (:authors ("Jaromir Hradilek" . "jhradilek@gmail.com")) (:maintainer "Jaromir Hradilek" . "jhradilek@gmail.com") (:keywords "snippets" "docbook") (:url . "https://github.com/jhradilek/emacs-docbook-snippets"))]) (docean . [(20180605 1744) ((emacs (24)) (cl-lib (0 5)) (request (0 2 0))) "Interact with DigitalOcean from Emacs." single ((:commit . "bbe2298fd21f7876fc2d5c52a69b931ff59df979") (:authors ("Mario Rodas" . "marsam@users.noreply.github.com")) (:maintainer "Mario Rodas" . "marsam@users.noreply.github.com") (:keywords "convenience") (:url . "https://github.com/emacs-pe/docean.el"))]) - (docker . [(20221023 1201) ((aio (1 0)) (dash (2 19 1)) (emacs (26 1)) (s (1 12 0)) (tablist (1 0)) (transient (0 3 7))) "Interface to Docker" tar ((:commit . "cc0046e6a557dce0ccc4108dd22e04f21ba8b0dc") (:authors ("Philippe Vaucher" . "philippe.vaucher@gmail.com")) (:maintainer "Philippe Vaucher" . "philippe.vaucher@gmail.com") (:keywords "filename" "convenience") (:url . "https://github.com/Silex/docker.el"))]) + (docker . [(20230302 2046) ((aio (1 0)) (dash (2 19 1)) (emacs (26 1)) (s (1 12 0)) (tablist (1 0)) (transient (0 3 7))) "Interface to Docker" tar ((:commit . "4a308e6b2184a1b7745df5a8b8adafb29b3f7157") (:authors ("Philippe Vaucher" . "philippe.vaucher@gmail.com")) (:maintainer "Philippe Vaucher" . "philippe.vaucher@gmail.com") (:keywords "filename" "convenience") (:url . "https://github.com/Silex/docker.el"))]) (docker-api . [(20160525 720) ((dash (2 12 1)) (request (0 2 0)) (s (1 11 0))) "Emacs interface to the Docker API" tar ((:commit . "206144346b7fa4165223349cfeb64a75d47ddd1b") (:authors ("Philippe Vaucher" . "philippe.vaucher@gmail.com")) (:maintainer "Philippe Vaucher" . "philippe.vaucher@gmail.com") (:url . "https://github.com/Silex/docker-api.el"))]) (docker-cli . [(20190524 1624) nil "Running various commands in docker containers" single ((:commit . "328429219574555c5fb831a421b4b5d9a2338561") (:authors ("Boško Ivanišević" . "bosko.ivanisevic@gmail.com")) (:maintainer "Boško Ivanišević" . "bosko.ivanisevic@gmail.com") (:keywords "processes") (:url . "https://github.com/bosko/docker-cli"))]) (docker-compose-mode . [(20200830 1336) ((emacs (24 3)) (dash (2 12 0)) (yaml-mode (0 0 12))) "Major mode for editing docker-compose files" single ((:commit . "abaa4f3aeb5c62d7d16e186dd7d77f4e846e126a") (:authors ("Ricardo Martins")) (:maintainer "Ricardo Martins") (:keywords "convenience") (:url . "https://github.com/meqif/docker-compose-mode"))]) @@ -1042,7 +1048,7 @@ (dokuwiki-mode . [(20170223 1301) nil "Major mode for DokuWiki document" single ((:commit . "e4e116f6fcc373e3f5937c1a7daa5c2c9c6d3fa1") (:authors ("Tsunenobu Kai" . "kai2nenobu@gmail.com")) (:maintainer "Tsunenobu Kai" . "kai2nenobu@gmail.com") (:keywords "hypermedia" "text" "dokuwiki") (:url . "https://github.com/kai2nenobu/emacs-dokuwiki-mode"))]) (dollaro . [(20151123 1302) ((s (1 6 0))) "simple text templates" single ((:commit . "500127f0172ac7a1eec627e026b59136580a74ac") (:authors ("Alessandro Piras" . "laynor@gmail.com")) (:maintainer "Alessandro Piras" . "laynor@gmail.com") (:keywords "tools" "convenience"))]) (doom . [(20180301 2308) ((cl-lib (0 5))) "DOM implementation and manipulation library" single ((:commit . "e59040aefc92dd9b3134eb623624307fb9e4327b") (:authors ("Alex Schroeder" . "alex@gnu.org") ("Henrik.Motakef" . "elisp@henrik-motakef.de") ("Katherine Whitlock" . "toroidal-code@gmail.com") ("Syohei YOSHIDA" . "syohex@gmail.com")) (:maintainer "Alex Schroeder") (:keywords "xml" "dom") (:url . "http://www.github.com/kensanata/doom.el/"))]) - (doom-modeline . [(20230219 1605) ((emacs (25 1)) (compat (28 1 1 1)) (shrink-path (0 2 0))) "A minimal and modern mode-line" tar ((:commit . "6125309c2caa3c98591a4c802e9b4dd2f7ea83e9") (:authors ("Vincent Zhang" . "seagle0128@gmail.com")) (:maintainer "Vincent Zhang" . "seagle0128@gmail.com") (:keywords "faces" "mode-line") (:url . "https://github.com/seagle0128/doom-modeline"))]) + (doom-modeline . [(20230406 623) ((emacs (25 1)) (compat (28 1 1 1)) (shrink-path (0 2 0))) "A minimal and modern mode-line" tar ((:commit . "a86ec8effe242cab8aba09ec0a2c7fed555c1fce") (:authors ("Vincent Zhang" . "seagle0128@gmail.com")) (:maintainer "Vincent Zhang" . "seagle0128@gmail.com") (:keywords "faces" "mode-line") (:url . "https://github.com/seagle0128/doom-modeline"))]) (doom-modeline-now-playing . [(20210831 1442) ((emacs (24 4)) (doom-modeline (3 0 0)) (async (1 9 3))) "Segment for Doom Modeline to show playerctl information" single ((:commit . "ef9158dfdf32e8eb789b69e7394d0bddaa68f42c") (:authors ("Ellis Kenyő" . "me@elken.dev")) (:maintainer "Ellis Kenyő" . "me@elken.dev") (:url . "https://github.com/elken/doom-modeline-now-playing"))]) (doom-themes . [(20230221 610) ((emacs (25 1)) (cl-lib (0 5))) "an opinionated pack of modern color-themes" tar ((:commit . "4c239dbe42232e81c28901000f435746de2a55ab") (:authors ("Henrik Lissner" . "contact@henrik.io")) (:maintainer "Henrik Lissner" . "contact@henrik.io") (:keywords "themes" "faces") (:url . "https://github.com/doomemacs/themes"))]) (dot-mode . [(20180312 2300) ((emacs (24 3))) "minor mode to repeat typing or commands" single ((:commit . "6ca22b73bcdae2363ee9641b822a60685df16a3e") (:authors ("Robert Wyrick" . "rob@wyrick.org")) (:maintainer "Robert Wyrick" . "rob@wyrick.org") (:keywords "convenience") (:url . "https://github.com/wyrickre/dot-mode"))]) @@ -1056,7 +1062,7 @@ (dpaste_de . [(20131015 1225) ((web (0 3 7))) "Emacs mode to paste to dpaste.de" single ((:commit . "ab041443884a7a4bfdc81b055688821e8efc9b02") (:authors ("Thejaswi Puthraya" . "thejaswi.puthraya@gmail.com")) (:maintainer "Thejaswi Puthraya" . "thejaswi.puthraya@gmail.com") (:keywords "pastebin"))]) (dpkg-dev-el . [(20230220 1635) ((debian-el (37))) "Emacs modes for debian packaging" tar ((:commit . "af9aad721cb263e495e2f77df458e9496549c04b") (:authors ("Peter S Galbraith" . "psg@debian.org")) (:maintainer "Peter S Galbraith" . "psg@debian.org"))]) (dr-racket-like-unicode . [(20220810 2000) ((emacs (24 3))) "DrRacket-style unicode input" single ((:commit . "d09b9be289e91e25c941107be5e8f52e7c8f0065") (:authors ("David Christiansen" . "david@davidchristiansen.dk")) (:maintainer "David Christiansen" . "david@davidchristiansen.dk") (:keywords "i18n" "tools") (:url . "https://github.com/david-christiansen/dr-racket-like-unicode"))]) - (dracula-theme . [(20230118 1201) ((emacs (24 3))) "Dracula Theme" single ((:commit . "be1dd97ef3968bef25b9de89e7dc1251f5aaee10") (:authors ("film42")) (:maintainer "Étienne Deparis" . "etienne@depar.is") (:url . "https://github.com/dracula/emacs"))]) + (dracula-theme . [(20230405 1844) ((emacs (24 3))) "Dracula Theme" single ((:commit . "54c26402555ab5b8b7cfd8ee2488c57b2fa5d32a") (:authors ("film42")) (:maintainer "Étienne Deparis" . "etienne@depar.is") (:url . "https://github.com/dracula/emacs"))]) (draft-mode . [(20160106 859) nil "Rough drafting for Emacs." single ((:commit . "4779fb32daf53746459da2def7e08004492d4f18") (:authors ("Eeli Reilin" . "gaudecker@fea.st")) (:maintainer "Eeli Reilin" . "gaudecker@fea.st") (:keywords "draft" "drafting") (:url . "https://github.com/gaudecker/draft-mode"))]) (drag-stuff . [(20161108 749) nil "Drag stuff (lines, words, region, etc...) around" tar ((:commit . "d49fe376d24f0f8ac5ade67b6d7fccc2487c81db") (:authors ("Johan Andersson" . "johan.rejeep@gmail.com")) (:maintainer "Johan Andersson" . "johan.rejeep@gmail.com") (:keywords "speed" "convenience") (:url . "http://github.com/rejeep/drag-stuff"))]) (drawille . [(20160418 1838) ((cl-lib (0 5))) "Drawille implementation in elisp" tar ((:commit . "d582b455c01432bc80933650c52a1f586bd1b5ad") (:authors ("Josuah Demangeon" . "josuah.demangeon@gmail.com")) (:maintainer "Josuah Demangeon" . "josuah.demangeon@gmail.com") (:keywords "graphics") (:url . "https://github.com/sshbio/elisp-drawille"))]) @@ -1068,20 +1074,20 @@ (drupal-spell . [(20130520 1655) nil "Aspell extra dictionary for Drupal" tar ((:commit . "a69f5e3b62c4c0da74ce26c1d00d5b8f7395e4ae") (:authors ("Arne Jørgensen" . "arne@arnested.dk")) (:maintainer "Arne Jørgensen" . "arne@arnested.dk") (:keywords "wp") (:url . "https://github.com/arnested/drupal-spell"))]) (dsvn . [(20221102 1416) nil "Subversion interface" single ((:commit . "36ecd5219584e46dcf6bd252e2ea1ec517d2fc05") (:authors ("David Kågedal" . "davidk@lysator.liu.se") (" Mattias Engdegård" . "mattiase@acm.org")) (:maintainer "Mattias Engdegård" . "mattiase@acm.org") (:keywords "docs"))]) (dtb-mode . [(20210105 1132) ((emacs (25))) "Show device tree souce in dtbs" single ((:commit . "d5bca7d1afaac5615c586b60c7314a1d0e2514dc") (:authors ("Schspa Shi" . "schspa@gmail.com")) (:maintainer "Schspa Shi" . "schspa@gmail.com") (:keywords "dtb" "dts" "convenience") (:url . "https://github.com/schspa/dtb-mode"))]) - (dtk . [(20220905 1727) ((emacs (24 4)) (cl-lib (0 6 1)) (dash (2 12 0)) (seq (1 9)) (s (1 9))) "access SWORD content via diatheke" single ((:commit . "9710006877ad6e35b1f8f31858835d71917dc347") (:authors ("David Thompson")) (:maintainer "David Thompson") (:keywords "hypermedia") (:url . "https://github.com/dtk01/dtk.el"))]) + (dtk . [(20230406 1321) ((emacs (24 4)) (cl-lib (0 6 1)) (dash (2 12 0)) (seq (1 9)) (s (1 9))) "access SWORD content via diatheke" single ((:commit . "3fc8f3bb8f39840cc5030aca3e3f5c74346d77f2") (:authors ("David Thompson")) (:maintainer "David Thompson") (:keywords "hypermedia") (:url . "https://github.com/dtk01/dtk.el"))]) (dtrace-script-mode . [(20150214 623) nil "DTrace code editing commands for Emacs" single ((:commit . "a92f76c65b9fb64d448e503b4ea7ff06085be8ee"))]) - (dtrt-indent . [(20220725 849) nil "Adapt to foreign indentation offsets" tar ((:commit . "d4fd1b4977eb0d534844fddf01c3c51c70c57205") (:authors ("Julian Scheid" . "julians37@googlemail.com")) (:maintainer "Reuben Thomas" . "rrt@sc3d.org") (:keywords "convenience" "files" "languages" "c"))]) + (dtrt-indent . [(20230302 2151) nil "Adapt to foreign indentation offsets" tar ((:commit . "07364ae07301f6f0a1713a8dff520c813849ffb3") (:authors ("Julian Scheid" . "julians37@googlemail.com")) (:maintainer "Reuben Thomas" . "rrt@sc3d.org") (:keywords "convenience" "files" "languages" "c"))]) (dts-mode . [(20211202 18) nil "Major mode for Devicetree source code" single ((:commit . "32517e7eeeccc785b7c669fd5e93c5df45597ef1") (:authors ("Ben Gamari" . "ben@smart-cactus.org")) (:maintainer "Ben Gamari" . "ben@smart-cactus.org") (:keywords "languages"))]) (ducpel . [(20140702 1154) ((cl-lib (0 5))) "Logic game with sokoban elements" tar ((:commit . "2f2ce2df269d99261c808a5c4ebc00d6d2cddabc") (:authors ("Alex Kost" . "alezost@gmail.com")) (:maintainer "Alex Kost" . "alezost@gmail.com") (:keywords "games") (:url . "https://github.com/alezost/ducpel"))]) (dumb-diff . [(20171211 2122) ((emacs (24 3))) "fast arbitrary diffs" single ((:commit . "1a2331d283049b71a07c1b06b1e0627a950d55f4") (:authors ("jack angers")) (:maintainer "jack angers") (:keywords "programming" "diff"))]) (dumb-jump . [(20220620 2325) ((emacs (24 3)) (s (1 11 0)) (dash (2 9 0)) (popup (0 5 3))) "Jump to definition for 50+ languages without configuration" single ((:commit . "ba4127336d897f5656032694bbe22c490ecbb000") (:authors ("jack angers and contributors")) (:maintainer "jack angers and contributors") (:keywords "programming") (:url . "https://github.com/jacktasia/dumb-jump"))]) (dummyparens . [(20141009 1024) nil "parenthesis auto-pairing and wrapping" single ((:commit . "9798ef1d0eaa24e4fe66f8aa6022a8c62714cc89") (:authors ("Sergei Nosov ")) (:maintainer "Sergei Nosov ") (:keywords "dummyparens" "auto-pair" "wrapping") (:url . "https://github.com/snosov1/dummyparens"))]) - (dune . [(20230217 1444) nil "Integration with the dune build system" tar ((:commit . "d3d628f2eda2278bd2df6e37452d8693f367fcfd") (:url . "https://github.com/ocaml/dune"))]) + (dune . [(20230402 1815) nil "Integration with the dune build system" tar ((:commit . "e53368337be3c353fd654bdbead322605fc875c5") (:url . "https://github.com/ocaml/dune"))]) (dune-format . [(20210505 108) ((reformatter (0 6)) (emacs (24 1))) "Reformat OCaml's dune files automatically" single ((:commit . "eda7a16ae378e7c482c11228c43ef32b893a1520") (:authors ("Steve Purcell" . "steve@sanityinc.com")) (:maintainer "Steve Purcell" . "steve@sanityinc.com") (:keywords "languages") (:url . "https://github.com/purcell/emacs-dune-format"))]) (duplicate-thing . [(20181031 1500) nil "Duplicate current line & selection" single ((:commit . "9d8fd05e3e5caa35d3f2a0c0032c92f0c0908e21") (:authors ("ongaeshi")) (:maintainer "ongaeshi") (:keywords "convenience" "command" "duplicate" "line" "selection") (:url . "https://github.com/ongaeshi/duplicate-thing"))]) (dut-mode . [(20170729 2111) ((emacs (24))) "Major mode for the Dut programming language" single ((:commit . "9235c7acaa6690942e9de8b7acd1e4be0c859dc1") (:authors ("The dut-mode Authors")) (:maintainer "The dut-mode Authors") (:keywords "languages" "gut") (:url . "https://github.com/dut-lang/dut-mode"))]) (dw . [(20210331 2311) ((emacs (25 1))) "Diceware passphrase generation commands" single ((:commit . "61c5718ba64ace4c9e29de18aa2690ecc3f0f258") (:authors ("D. Williams" . "d.williams@posteo.net")) (:maintainer "D. Williams" . "d.williams@posteo.net") (:keywords "convenience" "games") (:url . "https://github.com/integral-dw/dw-passphrase-generator"))]) - (dwim-shell-command . [(20230209 2234) ((emacs (28 1))) "Shell commands with DWIM behaviour" tar ((:commit . "078fb50b15cd024a9ce252ef69b58794df392be0") (:authors ("Alvaro Ramirez")) (:maintainer "Alvaro Ramirez") (:url . "https://github.com/xenodium/dwim-shell-command"))]) + (dwim-shell-command . [(20230407 1000) ((emacs (28 1))) "Shell commands with DWIM behaviour" tar ((:commit . "a4386911668eaccf726a3024d989863be49b62c4") (:authors ("Alvaro Ramirez")) (:maintainer "Alvaro Ramirez") (:url . "https://github.com/xenodium/dwim-shell-command"))]) (dyalog-mode . [(20230214 1027) ((cl-lib (0 2)) (emacs (24 3))) "Major mode for editing Dyalog APL source code" tar ((:commit . "13c0d391aa878a1609259a89fe3e6db8d21935e8") (:authors ("Joakim Hårsman" . "joakim.harsman@gmail.com")) (:maintainer "Joakim Hårsman" . "joakim.harsman@gmail.com") (:keywords "languages") (:url . "https://github.com/harsman/dyalog-mode.git"))]) (dylan . [(20220115 1804) ((emacs (25 1))) "Dylan editing modes" tar ((:commit . "9d2891e3e06405b75072d296f385fa795aeb9835") (:url . "https://opendylan.org/"))]) (dynamic-fonts . [(20140731 1226) ((font-utils (0 7 0)) (persistent-soft (0 8 8)) (pcache (0 2 3))) "Set faces based on available fonts" single ((:commit . "004ee6014dc7dbff8f14d26015c91d9229f6eac0") (:authors ("Roland Walker" . "walker@pobox.com")) (:maintainer "Roland Walker" . "walker@pobox.com") (:keywords "faces" "frames") (:url . "http://github.com/rolandwalker/dynamic-fonts"))]) @@ -1100,16 +1106,16 @@ (e2wm-sww . [(20200805 1339) ((e2wm (1 2))) "Plugin of e2wm.el to switch plugin quickly" single ((:commit . "8926d0c70be05c7b4ef821e22e411e8813973687") (:authors ("Hiroaki Otsu" . "ootsuhiroaki@gmail.com")) (:maintainer "Hiroaki Otsu" . "ootsuhiroaki@gmail.com") (:keywords "tools" "window manager") (:url . "https://github.com/aki2o/e2wm-sww"))]) (e2wm-term . [(20200322 729) ((e2wm (1 2)) (log4e (0 2 0)) (yaxception (0 3 2))) "Perspective of e2wm.el for work in terminal" single ((:commit . "74362d6271e736272df32ea807c5a22e4df54a50") (:authors ("Hiroaki Otsu" . "ootsuhiroaki@gmail.com")) (:maintainer "Hiroaki Otsu" . "ootsuhiroaki@gmail.com") (:keywords "tools" "window manager") (:url . "https://github.com/aki2o/e2wm-term"))]) (eacl . [(20220526 1434) ((emacs (25 1))) "Auto-complete lines by grepping project" single ((:commit . "4fe2cafbfeb73d806ebea8801c3522ff2886f30b") (:authors ("Chen Bin ")) (:maintainer "Chen Bin ") (:keywords "abbrev" "convenience" "matching") (:url . "http://github.com/redguardtoo/eacl"))]) - (earthfile-mode . [(20221018 355) ((emacs (26))) "Major mode for editing Earthly file" single ((:commit . "0427c367768ab52c359c34941ed13dbf419d74d7") (:authors ("Thanabodee Charoenpiriyakij" . "wingyminus@gmail.com")) (:maintainer "Thanabodee Charoenpiriyakij" . "wingyminus@gmail.com") (:url . "https://github.com/earthly/earthly-mode"))]) + (earthfile-mode . [(20230302 1709) ((emacs (26))) "Major mode for editing Earthly file" single ((:commit . "a242a4d68ebefce81879823c54155e0a04d3ea4a") (:authors ("Thanabodee Charoenpiriyakij" . "wingyminus@gmail.com")) (:maintainer "Thanabodee Charoenpiriyakij" . "wingyminus@gmail.com") (:url . "https://github.com/earthly/earthly-mode"))]) (easy-after-load . [(20170817 1231) nil "eval-after-load for all files in a directory" single ((:commit . "29e20145da49ac9ea40463c552130777408040de") (:authors ("Kyle Hargraves")) (:maintainer "Kyle Hargraves") (:url . "https://github.com/pd/easy-after-load"))]) (easy-escape . [(20210917 1254) nil "Improve readability of escape characters in regular expressions" single ((:commit . "938497a21e65ba6b3ff8ec90e93a6d0ab18dc9b4") (:authors ("Clément Pit-Claudel" . "clement.pitclaudel@live.com")) (:maintainer "Clément Pit-Claudel" . "clement.pitclaudel@live.com") (:keywords "convenience" "lisp" "tools") (:url . "https://github.com/cpitclaudel/easy-escape"))]) - (easy-hugo . [(20220928 405) ((emacs (25 1)) (popup (0 5 3)) (request (0 3 0)) (transient (0 3 6))) "Write blogs made with hugo by markdown or org-mode" tar ((:commit . "31e2f6d6d11be17576e135dd28d5ed441462d77d") (:authors ("Masashi Miyaura")) (:maintainer "Masashi Miyaura") (:url . "https://github.com/masasam/emacs-easy-hugo"))]) + (easy-hugo . [(20230314 2338) ((emacs (25 1)) (popup (0 5 3)) (request (0 3 0)) (transient (0 3 6))) "Write blogs made with hugo by markdown or org-mode" tar ((:commit . "a26364acba671e2891ce3aa457103691e10e244e") (:authors ("Masashi Miyaura")) (:maintainer "Masashi Miyaura") (:url . "https://github.com/masasam/emacs-easy-hugo"))]) (easy-jekyll . [(20211217 2311) ((emacs (25 1)) (request (0 3 0))) "Major mode managing jekyll blogs" single ((:commit . "7f19af310162464956f2bc4c38c6b7e95cb20321") (:authors ("Masashi Miyaura")) (:maintainer "Masashi Miyaura") (:url . "https://github.com/masasam/emacs-easy-jekyll"))]) (easy-kill . [(20220511 557) ((emacs (25)) (cl-lib (0 5))) "kill & mark things easily" single ((:commit . "de7d66c3c864a4722a973ee9bc228a14be49ba0c") (:authors ("Leo Liu" . "sdl.web@gmail.com")) (:maintainer "Leo Liu" . "sdl.web@gmail.com") (:keywords "killing" "convenience") (:url . "https://github.com/leoliu/easy-kill"))]) (easy-kill-extras . [(20210529 945) ((easy-kill (0 9 4))) "Extra functions for easy-kill." tar ((:commit . "74e9d0fcafc38d5f24e6209671a552bc1ba5a867") (:authors ("Akinori MUSHA" . "knu@iDaemons.org")) (:maintainer "Akinori MUSHA" . "knu@iDaemons.org") (:keywords "killing" "convenience") (:url . "https://github.com/knu/easy-kill-extras.el"))]) (easy-repeat . [(20150516 848) ((emacs (24 4))) "Repeat easily" single ((:commit . "060f0e6801c82c40c06961dc0528a00e18947a8c") (:authors ("Chunyang Xu" . "xuchunyang56@gmail.com")) (:maintainer "Chunyang Xu" . "xuchunyang56@gmail.com") (:keywords "repeat" "convenience") (:url . "https://github.com/xuchunyang/easy-repeat.el"))]) (ebf . [(20210225 1211) ((dash (2 18 0)) (cl-lib (0 5))) "brainfuck language transpiler to Emacs Lisp" tar ((:commit . "6cbeb4d62416f4cfd5be8906667342af8ecc44a6") (:authors ("Alexey Kutepov" . "reximkut@gmail.com")) (:maintainer "Alexey Kutepov" . "reximkut@gmail.com") (:url . "http://github.com/rexim/ebf"))]) - (ebib . [(20230211 2228) ((parsebib (4 0)) (emacs (26 1))) "a BibTeX database manager" tar ((:commit . "abe6ed461b334673001b930f7e30752aa8aff526") (:authors ("Joost Kremers" . "joostkremers@fastmail.fm")) (:maintainer "Joost Kremers" . "joostkremers@fastmail.fm") (:keywords "text" "bibtex") (:url . "http://joostkremers.github.io/ebib/"))]) + (ebib . [(20230221 2204) ((parsebib (4 0)) (emacs (26 1))) "a BibTeX database manager" tar ((:commit . "5a03e4662dccbffe63605bb8e88bfb691ebe0afa") (:authors ("Joost Kremers" . "joostkremers@fastmail.fm")) (:maintainer "Joost Kremers" . "joostkremers@fastmail.fm") (:keywords "text" "bibtex") (:url . "http://joostkremers.github.io/ebib/"))]) (ebnf-mode . [(20220606 1846) ((emacs (25 1))) "Major mode for EBNF files" single ((:commit . "9bc7242557dcef797afdcb4a50c70bf153aa221d") (:authors ("Noah Peart" . "noah.v.peart@gmail.com")) (:maintainer "Noah Peart" . "noah.v.peart@gmail.com") (:url . "https://github.com/nverno/ebnf-mode"))]) (ebuku . [(20221122 427) ((emacs (25 1))) "Interface to the buku Web bookmark manager" single ((:commit . "0c6cf404a49bd68800221446df186fffa0139325") (:authors ("Alexis , Erik Sjöstrand , Junji Zhi [https://github.com/junjizhi], Hilton Chain" . "hako@ultrarare.space")) (:maintainer "Alexis" . "flexibeast@gmail.com") (:keywords "bookmarks" "buku" "data" "web" "www") (:url . "https://github.com/flexibeast/ebuku"))]) (ecb . [(20170728 1921) nil "a code browser for Emacs" tar ((:commit . "1330a44cf3c171781083b0b926ab7622f64e6e81") (:authors ("Jesper Nordenberg" . "mayhem@home.se") ("Klaus Berndl" . "klaus.berndl@sdm.de") ("Kevin A. Burton" . "burton@openprivacy.org")) (:maintainer "Klaus Berndl" . "klaus.berndl@sdm.de") (:keywords "browser" "code" "programming" "tools"))]) @@ -1133,7 +1139,7 @@ (edit-list . [(20100930 1443) nil "edit a single list" single ((:commit . "f460d3f9e208a4e606fe6ded307f1b011916ca71") (:authors ("Michael Olson" . "mwolson@gnu.org")) (:maintainer "Michael Olson" . "mwolson@gnu.org") (:url . "http://mwolson.org/static/dist/elisp/edit-list.el"))]) (edit-server . [(20220908 1014) nil "server that responds to edit requests from Chrome" single ((:commit . "3ce09c6eb2919d56ef052b1584bba6abb12f7e99") (:authors ("Alex Bennée" . "alex@bennee.com")) (:maintainer "Alex Bennée" . "alex@bennee.com") (:url . "https://github.com/stsquad/emacs_chrome"))]) (edit-server-htmlize . [(20130329 2248) ((edit-server (1 9))) "(de)HTMLization hooks for edit-server.el" single ((:commit . "e7f8dadfabe869c77ca241cd6fbd4c52bd908392") (:authors ("Roland McGrath" . "roland@hack.frob.com")) (:maintainer "Roland McGrath" . "roland@hack.frob.com") (:url . "https://github.com/frobtech/edit-server-htmlize"))]) - (editorconfig . [(20230212 617) ((emacs (26 1)) (nadvice (0 3))) "EditorConfig Emacs Plugin" tar ((:commit . "2d13945c8d4c0ceee1c9310a2c1c4375f88a3b1e") (:authors ("EditorConfig Team" . "editorconfig@googlegroups.com")) (:maintainer "EditorConfig Team" . "editorconfig@googlegroups.com") (:keywords "convenience" "editorconfig") (:url . "https://github.com/editorconfig/editorconfig-emacs#readme"))]) + (editorconfig . [(20230329 118) ((emacs (26 1)) (nadvice (0 3))) "EditorConfig Emacs Plugin" tar ((:commit . "cd5799a6b728cfb9995605cdceffb5bf7c97622d") (:authors ("EditorConfig Team" . "editorconfig@googlegroups.com")) (:maintainer "EditorConfig Team" . "editorconfig@googlegroups.com") (:keywords "convenience" "editorconfig") (:url . "https://github.com/editorconfig/editorconfig-emacs#readme"))]) (editorconfig-charset-extras . [(20180223 457) ((editorconfig (0 6 0))) "Extra EditorConfig Charset Support" single ((:commit . "ddf60923c6f4841cb593b2ea04c9c710a01d262f") (:authors ("10sr" . "8.slashes@gmail.com")) (:maintainer "10sr" . "8.slashes@gmail.com") (:keywords "tools") (:url . "https://github.com/10sr/editorconfig-charset-extras-el"))]) (editorconfig-custom-majormode . [(20180816 244) ((editorconfig (0 6 0))) "Decide major-mode and mmm-mode from EditorConfig" single ((:commit . "13ad1c83f847bedd4b3a19f9df7fd925853b19de") (:authors ("10sr <8slashes+el [at] gmail [dot] com>")) (:maintainer "10sr <8slashes+el [at] gmail [dot] com>") (:keywords "editorconfig" "util") (:url . "https://github.com/10sr/editorconfig-custom-majormode-el"))]) (editorconfig-domain-specific . [(20180505 924) ((cl-lib (0 5)) (editorconfig (0 6 0))) "Apply brace style and other \"domain-specific\" EditorConfig properties" single ((:commit . "e9824160fb2e466afa755240ee3ab7cc5657fb04") (:authors ("Lassi Kortela" . "lassi@lassi.io")) (:maintainer "Lassi Kortela" . "lassi@lassi.io") (:keywords "editorconfig" "util") (:url . "https://github.com/lassik/editorconfig-emacs-domain-specific"))]) @@ -1149,8 +1155,7 @@ (egg . [(20181126 500) nil "Emacs Got Git - Emacs interface to Git" tar ((:commit . "00e768a78ac3d25f457eed667d02cac568480bf9") (:authors ("Bogolisk" . "bogolisk@gmail.com")) (:maintainer "Bogolisk" . "bogolisk@gmail.com") (:keywords "git" "version control" "release management"))]) (egg-timer . [(20200217 1650) ((emacs (25 1))) "Commonly used intervals for setting timers while working" single ((:commit . "53a9e9d20453ea4b0198ca413b8b5069a0b30b38") (:authors ("William Carroll" . "wpcarro@gmail.com")) (:maintainer "William Carroll" . "wpcarro@gmail.com") (:url . "https://github.com/wpcarro/egg-timer.el"))]) (egison-mode . [(20211218 1115) nil "Egison editing mode" tar ((:commit . "dbb395b41a4e4eb69f3f045cbfbe95a1575ac45b") (:authors ("Satoshi Egi" . "egisatoshi@gmail.com")) (:maintainer "Satoshi Egi" . "egisatoshi@gmail.com") (:url . "https://github.com/egisatoshi/egison3/blob/master/elisp/egison-mode.el"))]) - (eglot . [(20221020 1010) ((emacs (26 3)) (jsonrpc (1 0 14)) (flymake (1 2 1)) (project (0 3 0)) (xref (1 0 1)) (eldoc (1 11 0)) (seq (2 23))) "The Emacs Client for LSP servers" single ((:commit . "e501275e06952889056268dabe08ccd0dbaf23e5") (:authors ("João Távora" . "joaotavora@gmail.com")) (:maintainer "João Távora" . "joaotavora@gmail.com") (:keywords "convenience" "languages") (:url . "https://github.com/joaotavora/eglot"))]) - (eglot-fsharp . [(20230219 1511) ((emacs (27 1)) (eglot (1 4)) (fsharp-mode (1 10)) (jsonrpc (1 0 14))) "fsharp-mode eglot integration" single ((:commit . "09fec6c91f9c18173f145e28c55d6f21be678231") (:authors ("Jürgen Hötzel" . "juergen@hoetzel.info")) (:maintainer "Jürgen Hötzel" . "juergen@hoetzel.info") (:keywords "languages") (:url . "https://github.com/fsharp/emacs-fsharp-mode"))]) + (eglot-fsharp . [(20230324 1942) ((emacs (27 1)) (eglot (1 4)) (fsharp-mode (1 10)) (jsonrpc (1 0 14))) "fsharp-mode eglot integration" single ((:commit . "0ce19f272949f9ed335ab7a9fd9454c01f07eb8f") (:authors ("Jürgen Hötzel" . "juergen@hoetzel.info")) (:maintainer "Jürgen Hötzel" . "juergen@hoetzel.info") (:keywords "languages") (:url . "https://github.com/fsharp/emacs-fsharp-mode"))]) (eglot-java . [(20230213 218) ((emacs (26 1)) (eglot (1 0)) (jsonrpc (1 0 0))) "Java extension for the eglot LSP client" single ((:commit . "ff0f9515d78f94b8dfe158bf9a2c4f52216504c0") (:authors ("Yves Zoundi" . "yves_zoundi@hotmail.com")) (:maintainer "Yves Zoundi" . "yves_zoundi@hotmail.com") (:keywords "convenience" "languages") (:url . "https://github.com/yveszoundi/eglot-java"))]) (eglot-jl . [(20230117 1243) ((emacs (25 1)) (eglot (1 4)) (project (0 8 1)) (cl-generic (1 0))) "Julia support for eglot" tar ((:commit . "2e04597223553a369dd5b6520b6365b41e6ea508") (:authors ("Adam Beckmeyer" . "adam_git@thebeckmeyers.xyz")) (:maintainer "Adam Beckmeyer" . "adam_git@thebeckmeyers.xyz") (:keywords "convenience" "languages") (:url . "https://github.com/non-Jedi/eglot-jl"))]) (ego . [(20200803 1101) ((emacs (24 5)) (ht (1 5)) (mustache (0 22)) (htmlize (1 47)) (org (8 0)) (dash (2 0 0))) "a static site generator based on org mode, forked from org-page." tar ((:commit . "211c4cb2af2582849d9df984fb2346deecaf79be") (:authors ("Feng Shu ") ("Kelvin Hu ") ("Kuangdash ")) (:maintainer "Feng Shu ") (:keywords "org-mode" "convenience" "beautify") (:url . "https://github.com/emacs-china/EGO"))]) @@ -1158,9 +1163,9 @@ (eimp . [(20120826 2039) nil "Emacs Image Manipulation Package" single ((:commit . "2e7536fe6d8f7faf1bad7a8ae37faba0162c3b4f") (:authors ("Matthew P. Hodges" . "MPHodges@member.fsf.org")) (:maintainer "Nic Ferrier" . "nferrier@ferrier.me.uk") (:keywords "files" "frames"))]) (ein . [(20220911 1319) ((emacs (25)) (websocket (1 12)) (anaphora (1 0 4)) (request (0 3 3)) (deferred (0 5)) (polymode (0 2 2)) (dash (2 13 0)) (with-editor (0 -1))) "Emacs IPython Notebook" tar ((:commit . "b2410dc96f61aa806a7934099d8f1e40c8f6ca18") (:keywords "jupyter" "literate programming" "reproducible research") (:url . "https://github.com/dickmao/emacs-ipython-notebook"))]) (eink-theme . [(20190219 858) nil "E Ink color theme" single ((:commit . "326b07523dcb076d6209cdbc7fdbb73df296dbdb") (:authors ("Marian Schubert" . "marian.schubert@gmail.com")) (:maintainer "Marian Schubert" . "marian.schubert@gmail.com") (:url . "http://github.com/maio/eink-emacs"))]) - (ejc-sql . [(20230219 605) ((emacs (26 3)) (clomacs (0 0 5)) (dash (2 16 0)) (spinner (1 7 3))) "Emacs SQL client uses Clojure JDBC." tar ((:commit . "c9a602efd4b3a1b607c630e55e3124d4a63048fb") (:authors ("Kostafey" . "kostafey@gmail.com")) (:maintainer "Kostafey" . "kostafey@gmail.com") (:keywords "sql" "jdbc") (:url . "https://github.com/kostafey/ejc-sql"))]) + (ejc-sql . [(20230228 102) ((emacs (26 3)) (clomacs (0 0 5)) (dash (2 16 0)) (spinner (1 7 3))) "Emacs SQL client uses Clojure JDBC." tar ((:commit . "29308faad38e9cabd98fb5a8450df15db1e4a4cb") (:authors ("Kostafey" . "kostafey@gmail.com")) (:maintainer "Kostafey" . "kostafey@gmail.com") (:keywords "sql" "jdbc") (:url . "https://github.com/kostafey/ejc-sql"))]) (ejson-mode . [(20190720 2138) ((emacs (25))) "Major mode for editing ejson files." single ((:commit . "9630dfac9549779711dbe89e621f516bb4b3a354") (:authors ("Dante Catalfamo")) (:maintainer "Dante Catalfamo") (:keywords "convenience" "languages" "tools") (:url . "https://github.com/dantecatalfamo/ejson-mode"))]) - (ekg . [(20230221 602) ((triples (0 2 3)) (emacs (28 1))) "A system for recording and linking information" tar ((:commit . "cb3dfbf8c6faa0aa95f603b855eb37260acdc89d") (:authors ("Andrew Hyatt" . "ahyatt@gmail.com")) (:maintainer "Andrew Hyatt" . "ahyatt@gmail.com") (:keywords "outlines" "hypermedia") (:url . "https://github.com/ahyatt/ekg"))]) + (ekg . [(20230304 619) ((triples (0 2 5)) (emacs (28 1))) "A system for recording and linking information" tar ((:commit . "f19f25279cab76d025f710ce3d373b92f9fad0ca") (:authors ("Andrew Hyatt" . "ahyatt@gmail.com")) (:maintainer "Andrew Hyatt" . "ahyatt@gmail.com") (:keywords "outlines" "hypermedia") (:url . "https://github.com/ahyatt/ekg"))]) (el-autoyas . [(20120918 1317) nil "Automatically create Emacs-Lisp Yasnippets" tar ((:commit . "bde0251ecb504f585dfa27c205c8e312655310cc") (:authors ("Matthew L. Fidler")) (:maintainer "Matthew L. Fidler") (:keywords "emacs" "lisp" "mode" "yasnippet") (:url . "https://github.com/mlf176f2/el-autoyas.el"))]) (el-fetch . [(20230210 1311) ((emacs (25 1))) "Show system information in Neofetch-like style (eg CPU, RAM)" single ((:commit . "0142f58f075ea39aa6cc7ed35dd599afc4b6b450") (:authors ("Maciej Barć" . "xgqt@riseup.net")) (:maintainer "Maciej Barć" . "xgqt@riseup.net") (:url . "https://gitlab.com/xgqt/emacs-el-fetch"))]) (el-fly-indent-mode . [(20180422 243) ((emacs (25))) "Indent Emacs Lisp on the fly" single ((:commit . "1dd4b907ff4d9581c18b4e38e8719e83ba0dace1") (:authors ("Jiahao Li" . "jiahaowork@gmail.com")) (:maintainer "Jiahao Li" . "jiahaowork@gmail.com") (:keywords "lisp" "languages") (:url . "https://github.com/jiahaowork/el-fly-indent-mode.el"))]) @@ -1168,7 +1173,7 @@ (el-init . [(20150728 920) ((emacs (24)) (cl-lib (0 5)) (anaphora (1 0 0))) "A loader inspired by init-loader" single ((:commit . "25fd21d820bca1cf576b8f70c8d5a3bc76792597") (:authors ("Hiroki YAMAKAWA" . "s06139@gmail.com")) (:maintainer "Hiroki YAMAKAWA" . "s06139@gmail.com") (:url . "https://github.com/HKey/el-init"))]) (el-init-viewer . [(20150303 828) ((emacs (24)) (cl-lib (0 5)) (ctable (0 1 2)) (dash (2 10 0)) (anaphora (1 0 0)) (el-init (0 1 4))) "Record viewer for el-init" single ((:commit . "c40417db7808c8b8c9b2f196a69de5da7eee84a2") (:authors ("Hiroki YAMAKAWA" . "s06139@gmail.com")) (:maintainer "Hiroki YAMAKAWA" . "s06139@gmail.com") (:url . "https://github.com/HKey/el-init-viewer"))]) (el-mock . [(20220625 1949) nil "Tiny Mock and Stub framework in Emacs Lisp" single ((:commit . "6cfbc9de8f1927295dca6864907fe4156bd71910") (:authors ("rubikitch" . "rubikitch@ruby-lang.org")) (:maintainer "Johan Andersson" . "johan.rejeep@gmail.com") (:keywords "lisp" "testing" "unittest") (:url . "http://github.com/rejeep/el-mock.el"))]) - (el-patch . [(20230219 214) ((emacs (26))) "Future-proof your Elisp" tar ((:commit . "ad8b18578d224cf8ebb1cce9a3b1b5a3d93a0e69") (:authors ("Radian LLC" . "contact+el-patch@radian.codes")) (:maintainer "Radian LLC" . "contact+el-patch@radian.codes") (:keywords "extensions") (:url . "https://github.com/radian-software/el-patch"))]) + (el-patch . [(20230312 851) ((emacs (26))) "Future-proof your Elisp" tar ((:commit . "c2be85bc1ffdf680a9c796dacb177e4b0cabef6f") (:authors ("Radian LLC" . "contact+el-patch@radian.codes")) (:maintainer "Radian LLC" . "contact+el-patch@radian.codes") (:keywords "extensions") (:url . "https://github.com/radian-software/el-patch"))]) (el-secretario . [(20220426 1905) ((emacs (27 1)) (org-ql (0 6 -1)) (hercules (0 3))) "Unify all your inboxes with the Emacs secretary" tar ((:commit . "575396ca689065188ad0f90c379d9bcf7ff6fc0b") (:authors ("Leo Okawa Ericson ")) (:maintainer "Leo" . "github@relevant-information.com") (:keywords "convenience") (:url . "https://git.sr.ht/~zetagon/el-secretario"))]) (el-secretario-elfeed . [(20211214 1851) ((emacs (27 1)) (el-secretario (0 0 1)) (elfeed (3 4 1))) "Add notmuch email inboxes to el-secretario" single ((:commit . "2a5290ad57d9800d4b56896a768e37631bef06b0") (:authors ("Leo Okawa Ericson ")) (:maintainer "Leo" . "github@relevant-information.com") (:keywords "convenience") (:url . "https://git.sr.ht/~zetagon/el-secretario"))]) (el-secretario-mu4e . [(20220422 2006) ((emacs (27 1)) (org-ql (0 6 -1)) (el-secretario (0 0 1))) "Add mu4e inboxes to el-secretario" single ((:commit . "78a811f02c7104a39b908f9e4c8436abde4b9620") (:authors ("Leo Okawa Ericson ")) (:maintainer "Leo" . "github@relevant-information.com") (:keywords "convenience" "mail") (:url . "https://git.sr.ht/~zetagon/el-secretario"))]) @@ -1182,18 +1187,19 @@ (el2org . [(20200408 146) ((emacs (25 1))) "Convert elisp file to org file" single ((:commit . "7db77fdd73f378d4e60e34c11bbdf00677adc32c") (:authors ("Feng Shu " . "tumashu@163.com")) (:maintainer "Feng Shu " . "tumashu@163.com") (:keywords "convenience") (:url . "https://github.com/tumashu/el2org"))]) (elbank . [(20180316 1343) ((emacs (25)) (seq (2 16))) "Personal finances reporting application" tar ((:commit . "6dbd21e31fdf7cf62491f6d24b8198d4f91a031b") (:authors ("Nicolas Petton" . "nicolas@petton.fr")) (:maintainer "Nicolas Petton" . "nicolas@petton.fr") (:keywords "tools" "personal-finances"))]) (elcontext . [(20210109 1238) ((ht (2 3)) (hydra (0 14 0)) (emacs (24 3)) (f (0 20 0)) (osx-location (0 4)) (uuidgen (0 3))) "Create context specific actions" tar ((:commit . "2efd3dd8c5176c4f071bb048be6cb069b05d6e9e") (:authors ("Thomas Sojka")) (:maintainer "Thomas Sojka") (:keywords "calendar" "convenience") (:url . "https://github.com/rollacaster/elcontext"))]) - (elcord . [(20230203 101) ((emacs (25 1))) "Allows you to integrate Rich Presence from Discord" tar ((:commit . "43ae6c375811754e640b0bae4678bf33e72988e9") (:authors ("heatingdevice") ("Wilfredo Velázquez-Rodríguez" . "zulu.inuoe@gmail.com")) (:maintainer "heatingdevice") (:keywords "games") (:url . "https://github.com/Mstrodl/elcord"))]) + (elcord . [(20230303 457) ((emacs (25 1))) "Allows you to integrate Rich Presence from Discord" tar ((:commit . "e97283f8cdc3ca16a0179a14c78f1ba6e93cef80") (:authors ("heatingdevice") ("Wilfredo Velázquez-Rodríguez" . "zulu.inuoe@gmail.com")) (:maintainer "heatingdevice") (:keywords "games") (:url . "https://github.com/Mstrodl/elcord"))]) (elcouch . [(20201108 955) ((emacs (25 1)) (json-mode (1 0 0)) (libelcouch (0 11 0)) (navigel (0 3 0))) "View and manipulate CouchDB databases" single ((:commit . "3d162dda14411349e12509029d2b621c5d1edea2") (:authors ("Damien Cassou" . "damien@cassou.me")) (:maintainer "Damien Cassou" . "damien@cassou.me") (:keywords "data" "tools") (:url . "https://gitlab.petton.fr/DamienCassou/elcouch"))]) - (eldev . [(20230121 1404) ((emacs (24 4))) "Elisp development tool" tar ((:commit . "a1ea1a3df7602ffab30c15348365d2e6a75063b7") (:authors ("Paul Pogonyshev" . "pogonyshev@gmail.com")) (:maintainer "Paul Pogonyshev" . "pogonyshev@gmail.com") (:keywords "maint" "tools") (:url . "https://github.com/doublep/eldev"))]) - (eldoc-box . [(20221205 638) ((emacs (27 1))) "Display documentation in childframe" single ((:commit . "5c067f5c195198ffd16df2f455da95e46cc8ce02") (:authors ("Sebastien Chapuis" . "sebastien@chapu.is")) (:maintainer "Yuan Fu" . "casouri@gmail.com") (:url . "https://github.com/casouri/eldoc-box"))]) + (eldev . [(20230326 1127) ((emacs (24 4))) "Elisp development tool" tar ((:commit . "3162ae8015ec37ae8560bedc7e0b28f0695dd4d3") (:authors ("Paul Pogonyshev" . "pogonyshev@gmail.com")) (:maintainer "Paul Pogonyshev" . "pogonyshev@gmail.com") (:keywords "maint" "tools") (:url . "https://github.com/doublep/eldev"))]) + (eldoc-box . [(20230404 2324) ((emacs (27 1))) "Display documentation in childframe" single ((:commit . "143d7c5eff5ded45d1e1b9462c93f2a4e603089e") (:authors ("Yuan Fu" . "casouri@gmail.com")) (:maintainer "Yuan Fu" . "casouri@gmail.com") (:url . "https://github.com/casouri/eldoc-box"))]) (eldoc-cmake . [(20190419 2244) ((emacs (25 1))) "Eldoc support for CMake" single ((:commit . "4453c03b5c95ff32842f13db2fc317fb0fe2f79e") (:authors ("Kirill Ignatiev")) (:maintainer "Kirill Ignatiev") (:url . "https://github.com/ikirill/eldoc-cmake"))]) (eldoc-eval . [(20220106 1951) nil "Enable eldoc support when minibuffer is in use." single ((:commit . "e91800503c90cb75dc70abe42f1d6ae499346cc1") (:authors ("Thierry Volpiatto" . "thievol@posteo.net")) (:maintainer "Thierry Volpiatto" . "thievol@posteo.net"))]) - (eldoc-overlay . [(20221007 212) ((emacs (24 4)) (inline-docs (1 0 1)) (quick-peek (1 0))) "Display eldoc with contextual documentation overlay" single ((:commit . "5ae9e062295ea2a2855569826b770f3469f73e2f") (:authors ("stardiviner" . "numbchild@gmail.com")) (:maintainer "stardiviner" . "numbchild@gmail.com") (:keywords "docs" "eldoc" "overlay") (:url . "https://repo.or.cz/eldoc-overlay.git"))]) + (eldoc-overlay . [(20230406 959) ((emacs (24 4)) (inline-docs (1 0 1)) (quick-peek (1 0))) "Display eldoc with contextual documentation overlay" single ((:commit . "14a9e141918c2e18a107920e8631e622c580b3ef") (:authors ("stardiviner" . "numbchild@gmail.com")) (:maintainer "stardiviner" . "numbchild@gmail.com") (:keywords "docs" "eldoc" "overlay") (:url . "https://repo.or.cz/eldoc-overlay.git"))]) (eldoc-stan . [(20211129 2051) ((emacs (25)) (stan-mode (10 3 0))) "Eldoc support for stan functions" tar ((:commit . "150bbbe5fd3ad2b5a3dbfba9d291e66eeea1a581") (:authors ("Kazuki Yoshida" . "kazukiyoshida@mail.harvard.edu")) (:maintainer "Kazuki Yoshida" . "kazukiyoshida@mail.harvard.edu") (:keywords "help" "tools") (:url . "https://github.com/stan-dev/stan-mode/tree/master/eldoc-stan"))]) (eldoc-toml . [(20211026 1122) ((emacs (24 4))) "TOML table name at point for ElDoc" single ((:commit . "61106be3c3f3a5b293c3f285eec8c6f400142b6d") (:authors ("Maor Kadosh" . "git@avocadosh.xyz")) (:maintainer "Maor Kadosh" . "git@avocadosh.xyz") (:keywords "data") (:url . "https://github.com/it-is-wednesday/eldoc-toml"))]) (electric-case . [(20150417 1112) nil "insert camelCase, snake_case words without \"Shift\"ing" single ((:commit . "984b6a4c6c4cdcefeecb59e941f5f184cc1dedff") (:authors ("zk_phi")) (:maintainer "zk_phi") (:url . "http://hins11.yu-yake.com/"))]) (electric-cursor . [(20221221 438) ((emacs (25 1))) "Change cursor automatically depending on mode" single ((:commit . "bc09aa8c5d3cc32e3e6452cbf8018fc1ea772b73") (:authors ("Case Duckworth" . "acdw@acdw.net")) (:maintainer "Case Duckworth" . "acdw@acdw.net") (:keywords "terminals" "frames") (:url . "https://github.com/duckwork/electric-cursor"))]) (electric-operator . [(20220814 1439) ((dash (2 10 0)) (emacs (24 4))) "Automatically add spaces around operators" tar ((:commit . "281abdae033559fa9a8878ed1dd05a7ade118cfd") (:authors ("David Shepherd" . "davidshepherd7@gmail.com")) (:maintainer "David Shepherd" . "davidshepherd7@gmail.com") (:keywords "electric") (:url . "https://github.com/davidshepherd7/electric-operator"))]) + (electric-ospl . [(20230325 1518) ((emacs (26 1))) "Electric OSPL Mode" single ((:commit . "55fa59592d0d3e929bd8646ea691a592965a167a") (:authors ("Samuel W. Flint" . "swflint@flintfam.org")) (:maintainer "Samuel W. Flint" . "swflint@flintfam.org") (:keywords "convenience" "text") (:url . "https://git.sr.ht/~swflint/electric-ospl-mode"))]) (electric-spacing . [(20220220 1540) nil "Insert operators with surrounding spaces smartly" tar ((:commit . "c37b2502512dd49a8311d7c34e9bfd1af3d4dbcd") (:authors ("William Xu" . "william.xwl@gmail.com")) (:maintainer "William Xu" . "william.xwl@gmail.com"))]) (elegant-agenda-mode . [(20210115 353) ((emacs (26 1))) "An elegant theme for your org-agenda" single ((:commit . "5cbc688584ba103ea3be7d7b30e5d94e52f59eb6") (:authors ("Justin Barclay" . "justinbarclay@gmail.com")) (:maintainer "Justin Barclay" . "justinbarclay@gmail.com") (:keywords "faces") (:url . "https://github.com/justinbarclay/elegant-agenda-mode"))]) (elein . [(20120120 1116) nil "running leiningen commands from emacs" single ((:commit . "d4c0c0491dbb7c90e953d7a16172107c37103605") (:authors ("R.W. van 't Veer")) (:maintainer "R.W. van 't Veer") (:keywords "tools" "processes") (:url . "https://github.com/remvee/elein"))]) @@ -1207,13 +1213,13 @@ (elfeed-protocol . [(20220524 336) ((emacs (24 4)) (elfeed (2 1 1)) (cl-lib (0 5))) "Provide fever/newsblur/owncloud/ttrss protocols for elfeed" tar ((:commit . "b813574faefc1ac4825da19b40f620339b6badff") (:authors ("Xu Fasheng ")) (:maintainer "Xu Fasheng ") (:keywords "news") (:url . "https://github.com/fasheng/elfeed-protocol"))]) (elfeed-score . [(20220702 1548) ((emacs (26 1)) (elfeed (3 3 0))) "Gnus-style scoring for Elfeed" tar ((:commit . "ac938fdc617d489eb25f1d8c0bd800bb7693c588") (:authors ("Michael Herstine" . "sp1ff@pobox.com")) (:maintainer "Michael Herstine" . "sp1ff@pobox.com") (:keywords "news") (:url . "https://github.com/sp1ff/elfeed-score"))]) (elfeed-summary . [(20221210 1349) ((emacs (27 1)) (magit-section (3 3 0)) (elfeed (3 4 1))) "Feed summary interface for elfeed" single ((:commit . "ccbaf85d9ea442203027e784a42b21686f3a87d8") (:authors ("Korytov Pavel" . "thexcloud@gmail.com")) (:maintainer "Korytov Pavel" . "thexcloud@gmail.com") (:url . "https://github.com/SqrtMinusOne/elfeed-summary.el"))]) - (elfeed-tube . [(20220823 238) ((emacs (27 1)) (elfeed (3 4 1)) (aio (1 0))) "YouTube integration for Elfeed" tar ((:commit . "18d89f19203423b9e2df59a556c1240746903d8f") (:authors ("Karthik Chikmagalur" . "karthik.chikmagalur@gmail.com")) (:maintainer "Karthik Chikmagalur" . "karthik.chikmagalur@gmail.com") (:keywords "news" "hypermedia" "convenience") (:url . "https://github.com/karthink/elfeed-tube"))]) - (elfeed-tube-mpv . [(20220816 2223) ((emacs (27 1)) (elfeed-tube (0 10)) (mpv (0 2 0))) "Control mpv from Elfeed" single ((:commit . "7e1409e41628d61d8197ca248d910182ae4fc520") (:authors ("Karthik Chikmagalur" . "karthikchikmagalur@gmail.com")) (:maintainer "Karthik Chikmagalur" . "karthikchikmagalur@gmail.com") (:keywords "news" "hypermedia") (:url . "https://github.com/karthink/elfeed-tube"))]) + (elfeed-tube . [(20230316 313) ((emacs (27 1)) (elfeed (3 4 1)) (aio (1 0))) "YouTube integration for Elfeed" tar ((:commit . "194215ae02f4f7bfc4b693317afd6338d30459d1") (:authors ("Karthik Chikmagalur" . "karthik.chikmagalur@gmail.com")) (:maintainer "Karthik Chikmagalur" . "karthik.chikmagalur@gmail.com") (:keywords "news" "hypermedia" "convenience") (:url . "https://github.com/karthink/elfeed-tube"))]) + (elfeed-tube-mpv . [(20230316 11) ((emacs (27 1)) (elfeed-tube (0 10)) (mpv (0 2 0))) "Control mpv from Elfeed" single ((:commit . "4d98e62911fd3cdf623dd09443ef6802c59719de") (:authors ("Karthik Chikmagalur" . "karthikchikmagalur@gmail.com")) (:maintainer "Karthik Chikmagalur" . "karthikchikmagalur@gmail.com") (:keywords "news" "hypermedia") (:url . "https://github.com/karthink/elfeed-tube"))]) (elfeed-web . [(20210226 258) ((simple-httpd (1 5 1)) (elfeed (3 2 0)) (emacs (24 3))) "web interface to Elfeed" tar ((:commit . "0ccd59aaace34546017a1a0d7c393749747d5bc6") (:authors ("Christopher Wellons" . "wellons@nullprogram.com")) (:maintainer "Christopher Wellons" . "wellons@nullprogram.com") (:url . "https://github.com/skeeto/elfeed"))]) (elforth . [(20210522 928) ((emacs (26 1))) "Do you have what it takes to hack Emacs Lisp in Forth?" single ((:commit . "2d8540434a28e7edaa04a992c3c362832b2fd61e") (:authors ("Lassi Kortela" . "lassi@lassi.io")) (:maintainer "Lassi Kortela" . "lassi@lassi.io") (:keywords "games") (:url . "https://github.com/lassik/elforth"))]) (elgrep . [(20211221 852) ((emacs (26 2)) (async (1 5))) "Searching files for regular expressions" single ((:commit . "f8124c699b6a4abfb471269bc26afbcc8136f476") (:authors ("Tobias Zawada" . "i@tn-home.de")) (:maintainer "Tobias Zawada" . "i@tn-home.de") (:keywords "tools" "matching" "files" "unix") (:url . "https://github.com/TobiasZawada/elgrep"))]) (elhome . [(20161025 2042) ((initsplit (20120630))) "A framework for a \"home\" Emacs configuration" tar ((:commit . "e789e806469af3e9705f72298683c21f6c3a516d") (:authors ("Dave Abrahams" . "dave@boostpro.com")) (:maintainer "Demyan Rogozhin" . "demyan.rogozhin@gmail.com") (:keywords "lisp") (:url . "http://github.com/demyanrogozhin/elhome"))]) - (elisp-autofmt . [(20230221 1124) ((emacs (28 1))) "Emacs lisp auto-format" tar ((:commit . "153785d7e7d392ae07fe0f91a8ba3af6dd6d7df6") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:url . "https://codeberg.org/ideasman42/emacs-elisp-autofmt"))]) + (elisp-autofmt . [(20230307 230) ((emacs (28 1))) "Emacs lisp auto-format" tar ((:commit . "13a434ff5a4888fbadd3653f4fe892a55fb51045") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:url . "https://codeberg.org/ideasman42/emacs-elisp-autofmt"))]) (elisp-def . [(20220803 1647) ((dash (2 12 0)) (f (0 19 0)) (s (1 11 0)) (emacs (24 3))) "macro-aware go-to-definition for elisp" single ((:commit . "1d2e88a232ec16bce036b49577c4d4d96035f9f7") (:authors ("Wilfred Hughes" . "me@wilfred.me.uk")) (:maintainer "Wilfred Hughes" . "me@wilfred.me.uk") (:keywords "lisp"))]) (elisp-demos . [(20220903 1232) ((emacs (24 4))) "Elisp API Demos" tar ((:commit . "792be709c82101aea0585ece7429e2fdded74494") (:authors ("Xu Chunyang")) (:maintainer "Xu Chunyang") (:keywords "lisp" "docs") (:url . "https://github.com/xuchunyang/elisp-demos"))]) (elisp-depend . [(20190325 1114) nil "Parse depend libraries of elisp file." single ((:commit . "6679da9a6be5a845bb4804224c8394a9bc62168f"))]) @@ -1221,14 +1227,14 @@ (elisp-docstring-mode . [(20170304 1615) nil "Major mode for editing elisp docstrings." single ((:commit . "b135d95b158048927f12184e5cfb8fe01fc44713") (:authors ("Matúš Goljer" . "matus.goljer@gmail.com")) (:maintainer "Matúš Goljer" . "matus.goljer@gmail.com") (:keywords "languages"))]) (elisp-format . [(20160508 952) nil "Format elisp code" single ((:commit . "9fe516d39b349070537099a01fe34e47fbded2c8") (:authors (nil . "Andy Stewart lazycat.manatee@gmail.com")) (:maintainer "Yuki Inoue inouetakahiroki _at_ gmail.com") (:url . "https://github.com/Yuki-Inoue/elisp-format"))]) (elisp-lint . [(20220419 252) ((emacs (24 4)) (dash (2 15 0)) (package-lint (0 11))) "Basic linting for Emacs Lisp" single ((:commit . "c5765abf75fd1ad22505b349ae1e6be5303426c2") (:authors ("Nikolaj Schumacher ,")) (:maintainer "Neil Okamoto" . "neil.okamoto+melpa@gmail.com") (:keywords "lisp" "maint" "tools") (:url . "http://github.com/gonewest818/elisp-lint/"))]) - (elisp-refs . [(20220704 2141) ((dash (2 12 0)) (s (1 11 0))) "find callers of elisp functions or macros" single ((:commit . "af73739084637c8ebadad337a8fe58ff4f1d2ec1") (:authors ("Wilfred Hughes" . "me@wilfred.me.uk")) (:maintainer "Wilfred Hughes" . "me@wilfred.me.uk") (:keywords "lisp"))]) + (elisp-refs . [(20230309 1638) ((dash (2 12 0)) (s (1 11 0))) "find callers of elisp functions or macros" single ((:commit . "6973912994ade71a3e13a24425f1cc648d8b94bb") (:authors ("Wilfred Hughes" . "me@wilfred.me.uk")) (:maintainer "Wilfred Hughes" . "me@wilfred.me.uk") (:keywords "lisp"))]) (elisp-sandbox . [(20131116 1842) nil "Evaluate EmacsLisp expressions in a sandbox" single ((:commit . "ddd669266ca36d7e4ebba73eb1ab42523787e042") (:authors ("Joel McCracken , D. Goel" . "deego@gnufans.org")) (:maintainer "Joel McCracken , D. Goel" . "deego@gnufans.org") (:keywords "lisp") (:url . "https://github.com/joelmccracken/elisp-sandbox"))]) (elisp-slime-nav . [(20210510 528) ((emacs (24 1)) (cl-lib (0 2))) "Make M-. and M-, work in elisp like they do in slime" single ((:commit . "8588d80d414aee1fafce5b9da0e913612ee0bcdd") (:authors ("Steve Purcell" . "steve@sanityinc.com")) (:maintainer "Steve Purcell" . "steve@sanityinc.com") (:keywords "languages" "navigation" "slime" "elisp" "emacs-lisp") (:url . "https://github.com/purcell/elisp-slime-nav"))]) (elixir-mode . [(20221017 2044) ((emacs (25))) "Major mode for editing Elixir files" tar ((:commit . "4974ff9a83daf50f2f03dc0d6d00871296e088b0") (:keywords "languages" "elixir") (:url . "https://github.com/elixir-editors/emacs-elixir"))]) - (elixir-ts-mode . [(20230219 1338) ((emacs (29)) (heex-ts-mode (1 1))) "Major mode for Elixir with tree-sitter support" single ((:commit . "9a397f8135468a9ec853a869033946a08d57a1c0") (:authors ("Wilhelm H Kirschbaum")) (:maintainer "Wilhelm H Kirschbaum") (:keywords "elixir" "languages" "tree-sitter") (:url . "https://github.com/wkirschbaum/elixir-ts-mode"))]) + (elixir-ts-mode . [(20230403 823) ((emacs (29)) (heex-ts-mode (1 2))) "Major mode for Elixir with tree-sitter support" single ((:commit . "6671c0ffe0e59d82b99948b08d200bd744cc9d26") (:authors ("Wilhelm H Kirschbaum")) (:maintainer "Wilhelm H Kirschbaum") (:keywords "elixir" "languages" "tree-sitter") (:url . "https://github.com/wkirschbaum/elixir-ts-mode"))]) (elixir-yasnippets . [(20150417 1239) ((yasnippet (0 8 0))) "Yasnippets for Elixir" tar ((:commit . "980ca7626c14ef0573bec0035ec7942796062783") (:authors ("Yinghai Zhao" . "zyinghai@gmail.com")) (:maintainer "Yinghai Zhao" . "zyinghai@gmail.com") (:keywords "snippets"))]) (ellocate . [(20200112 1931) ((emacs (25 1)) (s (1 12 0)) (f (0 20 0))) "The locate command reimplemented in Emacs Lisp" single ((:commit . "81405082f68f0577c9f176d3d4f034a7142aba59") (:authors ("Sebastian Wålinder" . "s.walinder@gmail.com")) (:maintainer "Sebastian Wålinder" . "s.walinder@gmail.com") (:keywords "matching") (:url . "https://github.com/walseb/ellocate"))]) - (elm-mode . [(20230102 1737) ((f (0 17)) (s (1 7 0)) (emacs (25 1)) (seq (2 23)) (reformatter (0 3))) "Major mode for Elm" tar ((:commit . "5797500d74dd8544a89938c09d3cd5cdf7b5d7bc") (:authors ("Joseph Collard")) (:maintainer "Joseph Collard") (:url . "https://github.com/jcollard/elm-mode"))]) + (elm-mode . [(20230315 1122) ((f (0 17)) (s (1 7 0)) (emacs (25 1)) (seq (2 23)) (reformatter (0 3))) "Major mode for Elm" tar ((:commit . "699841865e1bd5b7f2077baa7121510b6bcad3c7") (:authors ("Joseph Collard")) (:maintainer "Joseph Collard") (:url . "https://github.com/jcollard/elm-mode"))]) (elm-test-runner . [(20190105 1923) ((emacs (24 4))) "Enhanced support for running elm-test" single ((:commit . "a31d567a64d86d36e3675347abd696824a731e0c") (:authors ("Juan Edi")) (:maintainer "Juan Edi") (:url . "https://github.com/juanedi/elm-test-runner"))]) (elm-yasnippets . [(20160401 524) ((yasnippet (0 8 0))) "Yasnippets for Elm" tar ((:commit . "45a11a0cef0c36633fb3477d3dc4167e82779ba4") (:authors ("Austin Bingham" . "austin.bingham@gmail.com")) (:maintainer "Austin Bingham" . "austin.bingham@gmail.com") (:keywords "snippets"))]) (elmacro . [(20210716 639) ((s (1 11 0)) (dash (2 13 0))) "Convert keyboard macros to emacs lisp" single ((:commit . "d2e05012cee4f54fab6d8d8d6aced6e5eeef4f31") (:authors ("Philippe Vaucher" . "philippe.vaucher@gmail.com")) (:maintainer "Philippe Vaucher" . "philippe.vaucher@gmail.com") (:keywords "macro" "elisp" "convenience") (:url . "https://github.com/Silex/elmacro"))]) @@ -1242,12 +1248,12 @@ (elpa-clone . [(20221201 1227) ((emacs (24 4))) "Clone ELPA archive" single ((:commit . "1d130c251690f24c23b77a4e4570157fca881d8f") (:authors ("ZHANG Weiyi" . "dochang@gmail.com")) (:maintainer "ZHANG Weiyi" . "dochang@gmail.com") (:keywords "comm" "elpa" "clone" "mirror") (:url . "https://github.com/dochang/elpa-clone"))]) (elpa-deploy . [(20191022 718) ((emacs (24 4)) (f (0 0))) "ELPA deployment library" single ((:commit . "f5126a2da1e0e52981fad9c12028814be80328c2") (:authors ("Bruno Félix Rezende Ribeiro" . "oitofelix@gnu.org")) (:maintainer "Bruno Félix Rezende Ribeiro" . "oitofelix@gnu.org") (:keywords "tools") (:url . "https://github.com/oitofelix/elpa-deploy"))]) (elpa-mirror . [(20230208 1148) ((emacs (25 1))) "Create local package repository from installed packages" single ((:commit . "9d7cfbf72ef8c7cd014c91e5bb3d8fbebda56140") (:authors ("Chen Bin" . "chenbin.sh@gmail.com")) (:maintainer "Chen Bin" . "chenbin.sh@gmail.com") (:keywords "tools") (:url . "http://github.com/redguardtoo/elpa-mirror"))]) - (elpher . [(20220809 253) ((emacs (27 1))) "A friendly gopher and gemini client" tar ((:commit . "b5269970249871a8889950a3e47bdff51eb0420c") (:authors ("Tim Vaughan" . "plugd@thelambdalab.xyz")) (:maintainer "Tim Vaughan" . "plugd@thelambdalab.xyz") (:keywords "comm" "gopher") (:url . "https://thelambdalab.xyz/elpher"))]) + (elpher . [(20230331 749) ((emacs (27 1))) "A friendly gopher and gemini client" tar ((:commit . "593310c145f1836781b16abed4503969e642212e") (:authors ("Tim Vaughan" . "plugd@thelambdalab.xyz")) (:maintainer "Tim Vaughan" . "plugd@thelambdalab.xyz") (:keywords "comm" "gopher") (:url . "https://thelambdalab.xyz/elpher"))]) (elpl . [(20220328 316) ((emacs (24 4))) "Emacs Lisp REPL" single ((:commit . "501871ab543b9967bfe87a8a82f83ab96b7f909e") (:authors ("Gong Qijian" . "gongqijian@gmail.com")) (:maintainer "Gong Qijian" . "gongqijian@gmail.com") (:keywords "lisp" "tool") (:url . "https://github.com/twlz0ne/elpl"))]) - (elpy . [(20220922 2253) ((company (0 9 2)) (emacs (24 4)) (highlight-indentation (0 5 0)) (pyvenv (1 3)) (yasnippet (0 8 0)) (s (1 11 0))) "Emacs Python Development Environment" tar ((:commit . "ae7919d94659eb26d4146d4c3422c5f4c3610837") (:authors ("Jorgen Schaefer , Gaby Launay" . "gaby.launay@protonmail.com")) (:maintainer "Jorgen Schaefer , Gaby Launay" . "gaby.launay@protonmail.com") (:keywords "python" "ide" "languages" "tools") (:url . "https://github.com/jorgenschaefer/elpy"))]) + (elpy . [(20230402 1946) ((company (0 9 2)) (emacs (24 4)) (highlight-indentation (0 5 0)) (pyvenv (1 3)) (yasnippet (0 8 0)) (s (1 11 0))) "Emacs Python Development Environment" tar ((:commit . "840713f23af99b83d04034c3703f7e73c3baa7dc") (:authors ("Jorgen Schaefer , Gaby Launay" . "gaby.launay@protonmail.com")) (:maintainer "Jorgen Schaefer , Gaby Launay" . "gaby.launay@protonmail.com") (:keywords "python" "ide" "languages" "tools") (:url . "https://github.com/jorgenschaefer/elpy"))]) (elpygen . [(20171225 1736) ((emacs (25)) (yasnippet (0 8 0))) "Generate a Python function/method using a symbol under point" single ((:commit . "21929c997a05968f9eefe52b85a76ceaab3b0d81") (:authors ("Vladimir Kazanov" . "vkazanov@inbox.ru")) (:maintainer "Vladimir Kazanov" . "vkazanov@inbox.ru") (:keywords "python" "languages" "tools") (:url . "https://github.com/vkazanov/elpygen"))]) (elquery . [(20220331 143) ((emacs (25 1)) (dash (2 13 0))) "The HTML library for elisp" tar ((:commit . "38f3bd41096cb270919b06095da0b9ac1add4598") (:authors ("Adam Niederer")) (:maintainer "Adam Niederer") (:keywords "html" "hypermedia" "tools" "webscale") (:url . "https://github.com/AdamNiederer/elquery"))]) - (elsa . [(20230220 2011) ((emacs (25 1)) (trinary (0)) (f (0)) (dash (2 14)) (cl-lib (0 3)) (lsp-mode (0))) "Emacs Lisp Static Analyser" tar ((:commit . "2776cd0c0617f99cac2da3da764d2f221f62ff2a") (:authors ("Matúš Goljer" . "matus.goljer@gmail.com")) (:maintainer "Matúš Goljer" . "matus.goljer@gmail.com") (:keywords "languages" "lisp"))]) + (elsa . [(20230318 2024) ((emacs (25 1)) (trinary (0)) (f (0)) (dash (2 14)) (cl-lib (0 3)) (lsp-mode (0))) "Emacs Lisp Static Analyser" tar ((:commit . "2aa912dcc7d3732ba04eb96ab1cd186565a48f98") (:authors ("Matúš Goljer" . "matus.goljer@gmail.com")) (:maintainer "Matúš Goljer" . "matus.goljer@gmail.com") (:keywords "languages" "lisp") (:url . "https://github.com/emacs-elsa/Elsa"))]) (elscreen . [(20181009 451) ((emacs (24))) "Emacs window session manager" tar ((:commit . "cc58337faf5ba1eae7e87f75f6ff3758675688f2") (:authors ("Naoto Morishima" . "naoto@morishima.net")) (:maintainer "Akinori MUSHA" . "knu@iDaemons.org") (:keywords "window" "convenience") (:url . "https://github.com/knu/elscreen"))]) (elscreen-buffer-group . [(20200109 2338) ((emacs (24 4)) (elscreen (0)) (cl-lib (0 5))) "elscreen buffer group" single ((:commit . "b48e71d4782adfeb2958f227d78c04164d26e4bd") (:authors ("Jeff Gran" . "jeff@jeffgran.com") ("Author: Ryan C. Thompson")) (:maintainer "Jeff Gran" . "jeff@jeffgran.com") (:keywords "buffer") (:url . "https://github.com/jeffgran/elscreen-buffer-group"))]) (elscreen-fr . [(20160920 953) ((elscreen (0)) (seq (1 11))) "Use frame title as screen tab" single ((:commit . "b9c11f80d277086d5d5bf88623e15fc7adbbbe3c") (:authors ("Francesc Rocher" . "francesc.rocher@gmail.com")) (:maintainer "Francesc Rocher" . "francesc.rocher@gmail.com") (:url . "http://github.com/rocher/elscreen-fr"))]) @@ -1259,29 +1265,28 @@ (elwm . [(20150817 1007) ((dash (1 1 0))) "Minimalistic window manager for emacs" single ((:commit . "c33b183f006ad476c3a44dab316f580f8b369930") (:authors ("Matus Goljer" . "matus.goljer@gmail.com")) (:maintainer "Matus Goljer" . "matus.goljer@gmail.com") (:keywords "docs") (:url . "https://github.com/Fuco1/elwm"))]) (elx . [(20230212 2019) ((emacs (25 1)) (compat (29 1 3 4)) (llama (0 2 0))) "Extract information from Emacs Lisp libraries" single ((:commit . "9daf56b1b11ca267f263f70823ade6f1a92d307c") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "docs" "libraries" "packages") (:url . "https://github.com/emacscollective/elx"))]) (emacs-everywhere . [(20220831 1636) ((emacs (26 3))) "System-wide popup windows for quick edits" single ((:commit . "e1b701894196b0e0aaf18ab88c778877ec87d0c9") (:authors ("TEC ")) (:maintainer "TEC" . "contact@tecosaur.net") (:keywords "conenience" "frames") (:url . "https://github.com/tecosaur/emacs-everywhere"))]) - (emacsc . [(20221105 1715) nil "helper for emacsc(1)" tar ((:commit . "f7634a86c3643a6432dda3897bd524957cf9ff1f") (:authors ("Akinori MUSHA" . "knu@iDaemons.org")) (:maintainer "Akinori MUSHA" . "knu@iDaemons.org") (:keywords "tools") (:url . "https://github.com/knu/emacsc"))]) + (emacsc . [(20230326 1852) nil "helper for emacsc(1)" tar ((:commit . "b4afd616c4ef160c58fc9a9682d3431b30a9d434") (:authors ("Akinori MUSHA" . "knu@iDaemons.org")) (:maintainer "Akinori MUSHA" . "knu@iDaemons.org") (:keywords "tools") (:url . "https://github.com/knu/emacsc"))]) (emacsist-view . [(20160426 1223) nil "Mode for viewing emacsist.com" single ((:commit . "f67761259ed779a9bc95c9a4e0474522990c5c6b") (:authors ("DarkSun" . "lujun9972@gmail.com")) (:maintainer "DarkSun" . "lujun9972@gmail.com") (:keywords "convenience" "usability") (:url . "https://github.com/lujun9972/emacsist-view"))]) - (emacsql . [(20230221 1532) ((emacs (25 1))) "High-level SQL database front-end" tar ((:commit . "f0249f655fd1a2c066c5a1b3daa93c80c5ed9865") (:authors ("Christopher Wellons" . "wellons@nullprogram.com")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:url . "https://github.com/magit/emacsql"))]) - (emacsql-mysql . [(20230221 1532) ((emacs (25 1)) (emacsql (20230220))) "EmacSQL back-end for MySQL" single ((:commit . "f0249f655fd1a2c066c5a1b3daa93c80c5ed9865") (:authors ("Christopher Wellons" . "wellons@nullprogram.com")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:url . "https://github.com/magit/emacsql"))]) - (emacsql-pg . [(20230221 1532) ((emacs (25 1)) (emacsql (20230220)) (pg (0 16))) "EmacSQL back-end for PostgreSQL via pg" single ((:commit . "f0249f655fd1a2c066c5a1b3daa93c80c5ed9865") (:authors ("Christopher Wellons" . "wellons@nullprogram.com")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:url . "https://github.com/magit/emacsql"))]) - (emacsql-psql . [(20230221 1532) ((emacs (25 1)) (emacsql (20230220))) "EmacSQL back-end for PostgreSQL via psql" single ((:commit . "f0249f655fd1a2c066c5a1b3daa93c80c5ed9865") (:authors ("Christopher Wellons" . "wellons@nullprogram.com")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:url . "https://github.com/magit/emacsql"))]) - (emacsql-sqlite . [(20230221 1532) ((emacs (25 1)) (emacsql (20230220))) "EmacSQL back-end for SQLite" tar ((:commit . "f0249f655fd1a2c066c5a1b3daa93c80c5ed9865") (:authors ("Christopher Wellons" . "wellons@nullprogram.com")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:url . "https://github.com/magit/emacsql"))]) - (emacsql-sqlite-builtin . [(20230221 1532) ((emacs (29)) (emacsql (20230220))) "EmacSQL back-end for SQLite using builtin support" single ((:commit . "f0249f655fd1a2c066c5a1b3daa93c80c5ed9865") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:url . "https://github.com/magit/emacsql"))]) - (emacsql-sqlite-module . [(20230221 1532) ((emacs (25)) (emacsql (20230220)) (sqlite3 (0 16))) "EmacSQL back-end for SQLite using a module" single ((:commit . "f0249f655fd1a2c066c5a1b3daa93c80c5ed9865") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:url . "https://github.com/magit/emacsql"))]) - (emacsql-sqlite3 . [(20220304 1014) ((emacs (26 1)) (emacsql (3 0 0))) "Yet another EmacSQL backend for SQLite" single ((:commit . "2113618732665f2112cb932a66c0e89c404d8777") (:authors ("Zhu Zihao" . "all_but_last@163.com")) (:maintainer "Zhu Zihao" . "all_but_last@163.com") (:keywords "extensions") (:url . "https://github.com/cireu/emacsql-sqlite3"))]) + (emacsql . [(20230228 1040) ((emacs (25 1))) "High-level SQL database front-end" tar ((:commit . "415dbfd846f46d921a70a351695f0d0e8f75da35") (:authors ("Christopher Wellons" . "wellons@nullprogram.com")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:url . "https://github.com/magit/emacsql"))]) + (emacsql-mysql . [(20230225 2205) ((emacs (25 1)) (emacsql (20230220))) "EmacSQL back-end for MySQL" single ((:commit . "b436adf09ebe058c28e0f473bed90ccd7084f6aa") (:authors ("Christopher Wellons" . "wellons@nullprogram.com")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:url . "https://github.com/magit/emacsql"))]) + (emacsql-pg . [(20230224 1201) ((emacs (25 1)) (emacsql (20230220)) (pg (0 16))) "EmacSQL back-end for PostgreSQL via pg" single ((:commit . "7c533fb6c27c3a10b6ab05bddf663e37c109e459") (:authors ("Christopher Wellons" . "wellons@nullprogram.com")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:url . "https://github.com/magit/emacsql"))]) + (emacsql-psql . [(20230225 2205) ((emacs (25 1)) (emacsql (20230220))) "EmacSQL back-end for PostgreSQL via psql" single ((:commit . "b436adf09ebe058c28e0f473bed90ccd7084f6aa") (:authors ("Christopher Wellons" . "wellons@nullprogram.com")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:url . "https://github.com/magit/emacsql"))]) + (emacsql-sqlite . [(20230225 2205) ((emacs (25 1)) (emacsql (20230220))) "EmacSQL back-end for SQLite" tar ((:commit . "b436adf09ebe058c28e0f473bed90ccd7084f6aa") (:authors ("Christopher Wellons" . "wellons@nullprogram.com")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:url . "https://github.com/magit/emacsql"))]) + (emacsql-sqlite-builtin . [(20230224 1201) ((emacs (29)) (emacsql (20230220))) "EmacSQL back-end for SQLite using builtin support" single ((:commit . "7c533fb6c27c3a10b6ab05bddf663e37c109e459") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:url . "https://github.com/magit/emacsql"))]) + (emacsql-sqlite-module . [(20230224 1201) ((emacs (25)) (emacsql (20230220)) (sqlite3 (0 16))) "EmacSQL back-end for SQLite using a module" single ((:commit . "7c533fb6c27c3a10b6ab05bddf663e37c109e459") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:url . "https://github.com/magit/emacsql"))]) (emacsshot . [(20191206 944) ((emacs (24 4))) "Snapshot a frame or window from within" tar ((:commit . "fe958b11056f3c671ebdd604d5aa574323284ca5") (:authors ("Marco Wahl" . "marcowahlsoft@gmail.com")) (:maintainer "Marco Wahl") (:keywords "convenience") (:url . "https://gitlab.com/marcowahl/emacsshot"))]) (emamux . [(20200315 1220) ((emacs (24 3))) "Interact with tmux" single ((:commit . "6172131d78038f0b1490e24bac60534bf4ad3b30") (:authors ("Syohei YOSHIDA" . "syohex@gmail.com")) (:maintainer "Syohei YOSHIDA" . "syohex@gmail.com") (:url . "https://github.com/syohex/emacs-emamux"))]) (emamux-ruby-test . [(20130812 1639) ((emamux (0 1)) (projectile (0 9 1))) "Ruby test with emamux" single ((:commit . "785bfd44d097a46bb2ebe1e62ac7595fd4dc9ab5") (:url . "https://github.com/syohex/emamux-ruby-test"))]) (emaps . [(20200508 1759) ((dash (2 17 0)) (emacs (24))) "Utilities for working with keymaps" single ((:commit . "7c561f3ded2015ed3774e5784059d6601082743e") (:authors ("Ben Moon" . "software@guiltydolphin.com")) (:maintainer "Ben Moon" . "software@guiltydolphin.com") (:keywords "convenience" "keyboard" "keymap" "utility") (:url . "https://github.com/GuiltyDolphin/emaps"))]) - (embark . [(20230219 1700) ((emacs (27 1)) (compat (29 1 3 4))) "Conveniently act on minibuffer completions" tar ((:commit . "8e7c53a8ec6969a8d54a22c7cb76f15e2e7fa3f9") (:authors ("Omar Antolín Camarena" . "omar@matem.unam.mx")) (:maintainer "Omar Antolín Camarena" . "omar@matem.unam.mx") (:keywords "convenience") (:url . "https://github.com/oantolin/embark"))]) - (embark-consult . [(20230218 2048) ((emacs (27 1)) (embark (0 20)) (consult (0 17))) "Consult integration for Embark" single ((:commit . "0cc29e67784cff6315ac068bc97b28dc30e6409e") (:authors ("Omar Antolín Camarena" . "omar@matem.unam.mx")) (:maintainer "Omar Antolín Camarena" . "omar@matem.unam.mx") (:keywords "convenience") (:url . "https://github.com/oantolin/embark"))]) + (embark . [(20230328 1813) ((emacs (27 1)) (compat (29 1 4 0))) "Conveniently act on minibuffer completions" tar ((:commit . "846b3fd311d06dd0f9aa20f133907ae10855c9ae") (:authors ("Omar Antolín Camarena" . "omar@matem.unam.mx")) (:maintainer "Omar Antolín Camarena" . "omar@matem.unam.mx") (:keywords "convenience") (:url . "https://github.com/oantolin/embark"))]) + (embark-consult . [(20230327 1843) ((emacs (27 1)) (embark (0 20)) (consult (0 17))) "Consult integration for Embark" single ((:commit . "51b5a693b5fe3d573acac97cfd3ce75e0d41c187") (:authors ("Omar Antolín Camarena" . "omar@matem.unam.mx")) (:maintainer "Omar Antolín Camarena" . "omar@matem.unam.mx") (:keywords "convenience") (:url . "https://github.com/oantolin/embark"))]) (embark-vc . [(20230212 1920) ((emacs (27 1)) (embark (0 21 1)) (forge (0 3)) (compat (29 1 3 0))) "Embark actions for various version control integrations" single ((:commit . "070666b0de8fc2832aa2510b9ba492565cb5e35e") (:authors ("Ellis Kenyő ")) (:maintainer "Ellis Kenyő" . "me@elken.dev") (:keywords "convenience" "matching" "terminals" "tools" "unix" "vc") (:url . "https://github.com/elken/embark-vc"))]) (ember-mode . [(20200208 1423) ((cl-lib (0 5))) "Ember navigation mode for emacs" single ((:commit . "a587c423041b2fcb065fd5b6a03b2899b764e462") (:authors ("Aad Versteden" . "madnificent@gmail.com")) (:maintainer "Aad Versteden" . "madnificent@gmail.com") (:keywords "ember" "ember.js" "emberjs"))]) (ember-yasnippets . [(20160526 1658) ((yasnippet (0 8 0))) "Snippets for Ember.js development" tar ((:commit . "3b5bd01569646237bf1b540d097e12f9118b67f4") (:authors ("Ron White" . "ronco@costite.com")) (:maintainer "Ron White" . "ronco@costite.com") (:keywords "tools" "abbrev" "languages"))]) (embrace . [(20171031 1833) ((cl-lib (0 5)) (expand-region (0 10 0))) "Add/Change/Delete pairs based on `expand-region'" single ((:commit . "dd5da196e5bcc5e6d87e1937eca0c21da4334ef2") (:authors ("Junpeng Qiu" . "qjpchmail@gmail.com")) (:maintainer "Junpeng Qiu" . "qjpchmail@gmail.com") (:keywords "extensions"))]) (emidje . [(20190209 1726) ((emacs (25)) (cider (0 17 0)) (seq (2 16)) (magit-popup (2 4 0))) "Test runner and report viewer for Midje" single ((:commit . "7e92f053964d925c97dc8cca8d4d70a3030021db") (:authors ("Alan Ghelardi" . "alan.ghelardi@nubank.com.br")) (:maintainer "Alan Ghelardi" . "alan.ghelardi@nubank.com.br") (:keywords "tools") (:url . "https://github.com/nubank/emidje"))]) (emmet-mode . [(20221111 329) nil "Unofficial Emmet's support for emacs" single ((:commit . "63b6932603184956b5ea8919036d2b307b48d7fd") (:authors ("Shin Aoyama" . "smihica@gmail.com")) (:maintainer "Shin Aoyama" . "smihica@gmail.com") (:keywords "convenience") (:url . "https://github.com/smihica/emmet-mode"))]) - (emms . [(20230206 1841) ((cl-lib (0 5)) (nadvice (0 3)) (seq (0))) "The Emacs Multimedia System" tar ((:commit . "43c61412492229eb641fe572c89c826d8fcf64d9") (:authors ("Jorgen Schäfer" . "forcer@forcix.cx")) (:maintainer "Yoni Rabkin" . "yrk@gnu.org") (:keywords "emms" "mp3" "ogg" "flac" "music" "mpeg" "video" "multimedia") (:url . "https://www.gnu.org/software/emms/"))]) + (emms . [(20230329 2020) ((cl-lib (0 5)) (nadvice (0 3)) (seq (0))) "The Emacs Multimedia System" tar ((:commit . "0f4bd0c551b6ec1debfa834464f28030ce9c287b") (:authors ("Jorgen Schäfer" . "forcer@forcix.cx")) (:maintainer "Yoni Rabkin" . "yrk@gnu.org") (:keywords "emms" "mp3" "ogg" "flac" "music" "mpeg" "video" "multimedia") (:url . "https://www.gnu.org/software/emms/"))]) (emms-bilibili . [(20180103 418) ((emacs (25)) (cl-lib (0 5))) "Play Bilibili in EMMS." single ((:commit . "294bca3dfc42fe3a55fb326ab39bc0fcfc8c5090") (:keywords "emms" "bilibili") (:url . "https://github.com/stardiviner/emms-bilibili"))]) (emms-info-mediainfo . [(20131223 1300) ((emms (0))) "Info-method for EMMS using medianfo" single ((:commit . "bce16eae9eacd38719fea62a9755225a888da59d") (:authors ("Fabián Ezequiel Gallina" . "fgallina@gnu.org")) (:maintainer "Fabián Ezequiel Gallina" . "fgallina@gnu.org") (:keywords "multimedia" "processes"))]) (emms-mark-ext . [(20130529 327) ((emms (3 0))) "Extra functions for emms-mark-mode and emms-tag-edit-mode" single ((:commit . "ec68129e3e9e469e5bf160c6a1b7030e322f3541") (:authors ("Joe Bloggs" . "vapniks@yahoo.com")) (:maintainer "Joe Bloggs" . "vapniks@yahoo.com") (:keywords "convenience" "multimedia") (:url . "https://github.com/vapniks/emms-mark-ext"))]) @@ -1298,7 +1303,7 @@ (emojify . [(20210108 1111) ((seq (1 11)) (ht (2 0)) (emacs (24 3))) "Display emojis in Emacs" tar ((:commit . "cfa00865388809363df3f884b4dd554a5d44f835") (:authors ("Iqbal Ansari" . "iqbalansari02@yahoo.com")) (:maintainer "Iqbal Ansari" . "iqbalansari02@yahoo.com") (:keywords "multimedia" "convenience") (:url . "https://github.com/iqbalansari/emacs-emojify"))]) (emojify-logos . [(20180814 917) ((emojify (0 4))) "Add logos to emojify" tar ((:commit . "a3e78bcbdf863092d4c9b026ac08bf7d1c7c0e8b") (:authors ("mxgoldstein" . "m_goldstein@gmx.net")) (:maintainer "mxgoldstein" . "m_goldstein@gmx.net") (:url . "https://github.com/mxgoldstein/emojify-logos"))]) (empos . [(20151011 1916) nil "Locate bibtex citations from within emacs" single ((:commit . "7b99ad30e56937adb7e6349777e5a2045597d564") (:authors ("Dimitris Alikaniotis ")) (:maintainer "Dimitris Alikaniotis ") (:keywords "citations" "reference" "bibtex" "reftex") (:url . "http://github.com/dimalik/empos/"))]) - (empv . [(20230203 2159) ((emacs (28 1))) "An interface for MPV" single ((:commit . "a45a2a01a7e629c9126b444d952fe71bcc9a262f") (:authors ("Isa Mert Gurbuz" . "isamertgurbuz@gmail.com")) (:maintainer "Isa Mert Gurbuz" . "isamertgurbuz@gmail.com") (:url . "https://github.com/isamert/empv.el"))]) + (empv . [(20230402 1852) ((emacs (28 1)) (s (1 13 0))) "A multimedia player/manager, YouTube interface" single ((:commit . "643bb7d1f42c627ae28b86d9554198e5b68665b1") (:authors ("Isa Mert Gurbuz" . "isamertgurbuz@gmail.com")) (:maintainer "Isa Mert Gurbuz" . "isamertgurbuz@gmail.com") (:url . "https://github.com/isamert/empv.el"))]) (emr . [(20220108 548) ((s (1 3 1)) (dash (1 2 0)) (cl-lib (0 2)) (popup (0 5 0)) (emacs (24 1)) (list-utils (0 3 0)) (paredit (24 0 0)) (projectile (0 9 1)) (clang-format (0 0 1)) (iedit (0 97))) "Emacs refactoring system." tar ((:commit . "cac1b52932926f56d7f6d2923732d20bbd20670d") (:authors ("Chris Barrett" . "chris.d.barrett@me.com")) (:maintainer "Chris Barrett" . "chris.d.barrett@me.com") (:keywords "tools" "convenience" "refactoring") (:url . "https://github.com/Wilfred/emacs-refactor"))]) (enclose . [(20121008 1614) nil "Enclose cursor within punctuation pairs." tar ((:commit . "2fff3d4fcc1089f87647042d7164ba04282766ae") (:authors ("Johan Andersson" . "johan.rejeep@gmail.com")) (:maintainer "Johan Andersson" . "johan.rejeep@gmail.com") (:keywords "speed" "convenience") (:url . "http://github.com/rejeep/enclose"))]) (encourage-mode . [(20151128 905) ((emacs (24 4))) "Encourages you in your work. :D" single ((:commit . "ca411e6bfd3d0edffe95852127bd995730b942e3") (:authors ("Patrick Mosby" . "patrick@schreiblogade.de")) (:maintainer "Patrick Mosby" . "patrick@schreiblogade.de") (:keywords "fun") (:url . "https://github.com/halbtuerke/encourage-mode.el"))]) @@ -1314,7 +1319,7 @@ (epc . [(20140610 534) ((concurrent (0 3 1)) (ctable (0 1 2))) "A RPC stack for the Emacs Lisp" tar ((:commit . "94cd36a3bec752263ac9b1b3a9dd2def329d2af7") (:authors ("SAKURAI Masashi ")) (:maintainer "SAKURAI Masashi ") (:keywords "lisp" "rpc") (:url . "https://github.com/kiwanami/emacs-epc"))]) (epic . [(20170210 23) ((htmlize (1 47))) "Evernote Picker for Cocoa Emacs" single ((:commit . "a41826c330eb0ea061d58a08cc861b0c4ac8ec4e") (:authors ("Yoshinari Nomura" . "nom@quickhack.net")) (:maintainer "Yoshinari Nomura" . "nom@quickhack.net") (:keywords "evernote" "applescript") (:url . "https://github.com/yoshinari-nomura/epic"))]) (eping . [(20201027 2149) ((emacs (25 1))) "Ping websites to check internet connectivity" tar ((:commit . "004496ee06c0b8ead4a4f49e17109e8eb32eb49d") (:authors ("Sean Hutchings" . "seanhut@yandex.com")) (:maintainer "Sean Hutchings" . "seanhut@yandex.com") (:keywords "comm" "processes" "terminals" "unix") (:url . "https://github.com/sean-hut/eping"))]) - (epkg . [(20230220 1945) ((emacs (25 1)) (compat (29 1 3 4)) (closql (20230220)) (emacsql (20230220)) (llama (0 2 0))) "Browse the Emacsmirror package database" tar ((:commit . "576ba9fedc360d2f7dfb724f9f767cc4688e5b7f") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "tools") (:url . "https://github.com/emacscollective/epkg"))]) + (epkg . [(20230312 1644) ((emacs (25 1)) (compat (29 1 3 4)) (closql (20230220)) (emacsql (20230220)) (llama (0 2 0))) "Browse the Emacsmirror package database" tar ((:commit . "e2021f6cff73902bec79b19c492ea2c5930cdc50") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "tools") (:url . "https://github.com/emacscollective/epkg"))]) (epkg-marginalia . [(20230212 2018) ((emacs (27 1)) (compat (29 1 3 4)) (epkg (3 3 1)) (llama (0 2 0)) (marginalia (0 12))) "Show Epkg information in completion annotations" single ((:commit . "4f3a66946b1be11c40d1635b60ea21941c882e8f") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "tools") (:url . "https://github.com/emacscollective/epkg-marginalia"))]) (epl . [(20180205 2049) ((cl-lib (0 3))) "Emacs Package Library" single ((:commit . "78ab7a85c08222cd15582a298a364774e3282ce6") (:authors ("Sebastian Wiesner" . "swiesner@lunaryorn.com")) (:maintainer "Johan Andersson" . "johan.rejeep@gmail.com") (:keywords "convenience") (:url . "http://github.com/cask/epl"))]) (epm . [(20190509 443) ((emacs (24 3)) (epl (0 8))) "Emacs Package Manager" tar ((:commit . "6375ddbf93c5f25647f6ebb25b54045b3c93a5be") (:authors ("Chunyang Xu" . "xuchunyang.me@gmail.com")) (:maintainer "Chunyang Xu" . "xuchunyang.me@gmail.com") (:url . "https://github.com/xuchunyang/epm"))]) @@ -1346,9 +1351,9 @@ (ergoemacs-status . [(20160318 538) ((powerline (2 3)) (mode-icons (0 1 0))) "Adaptive Status Bar / Mode Line" single ((:commit . "d952cc2361adf6eb4d6af60950ad4ab699c81320") (:authors ("Matthew Fidler")) (:maintainer "Matthew Fidler"))]) (eri . [(20200914 644) nil "Enhanced relative indentation (eri)" single ((:commit . "aa5e3a127bf17a8c80d947f3c286758a36dadc36") (:url . "https://github.com/agda/agda"))]) (erk . [(20230120 622) ((emacs (28 1)) (auto-compile (1 2 0)) (dash (2 18 0))) "Elisp (GitHub) Repository Kit" single ((:commit . "6ca1aabc6c60c8722bc5dca4aedbc033b1d9fff5") (:authors ("")) (:maintainer "") (:keywords "convenience") (:url . "http://github.com/positron-solutions/elisp-repo-kit"))]) - (erlang . [(20230215 909) ((emacs (24 1))) "Erlang major mode" tar ((:commit . "127026003180a834e9fa5d5919c824a184faeb92") (:authors ("Anders Lindgren")) (:maintainer "Anders Lindgren") (:keywords "erlang" "languages" "processes"))]) + (erlang . [(20230322 848) ((emacs (24 1))) "Erlang major mode" tar ((:commit . "dac89a6acc1a93a615930ca18f1dbf4e9323b038") (:authors ("Anders Lindgren")) (:maintainer "Anders Lindgren") (:keywords "erlang" "languages" "processes"))]) (erlstack-mode . [(20230202 1955) ((emacs (25 1)) (dash (2 12 0))) "Minor mode for analysing Erlang stacktraces" single ((:commit . "b0fa450da826b7b9fcfe9b0b209955735830eb38") (:authors ("k32")) (:maintainer "k32") (:keywords "tools" "erlang") (:url . "https://github.com/k32/erlstack-mode"))]) - (eros . [(20180415 618) ((emacs (24 4))) "Evaluation Result OverlayS for Emacs Lisp" single ((:commit . "dd8910279226259e100dab798b073a52f9b4233a") (:authors ("Tianxiang Xiong" . "tianxiang.xiong@gmail.com")) (:maintainer "Tianxiang Xiong" . "tianxiang.xiong@gmail.com") (:keywords "convenience" "lisp") (:url . "https://github.com/xiongtx/eros"))]) + (eros . [(20230309 615) ((emacs (24 4))) "Evaluation Result OverlayS for Emacs Lisp" single ((:commit . "a9a92bdc6be0521a6a06eb464be55ed61946639c") (:authors ("Tianxiang Xiong" . "tianxiang.xiong@gmail.com")) (:maintainer "Tianxiang Xiong" . "tianxiang.xiong@gmail.com") (:keywords "convenience" "lisp") (:url . "https://github.com/xiongtx/eros"))]) (ert-async . [(20200105 1031) ((emacs (24 1))) "Async support for ERT" single ((:commit . "948cf2faa10e085bda3739034ca5ea1912893433") (:authors ("Johan Andersson" . "johan.rejeep@gmail.com")) (:maintainer "Johan Andersson" . "johan.rejeep@gmail.com") (:keywords "lisp" "test") (:url . "http://github.com/rejeep/ert-async.el"))]) (ert-expectations . [(20121009 734) nil "The simplest unit test framework in the world" single ((:commit . "aed70e002c4305b66aed7f6d0d48e9addd2dc1e6") (:authors ("rubikitch" . "rubikitch@ruby-lang.org")) (:maintainer "rubikitch" . "rubikitch@ruby-lang.org") (:keywords "test" "unittest" "ert" "expectations") (:url . "http://www.emacswiki.org/emacs/download/ert-expectations.el"))]) (ert-junit . [(20190802 2232) ((ert (0)) (emacs (23 4))) "JUnit XML reports from ert results" single ((:commit . "65f91c35b088b87943dbbbe7e1ce354bc9bc0992") (:authors ("Ola Nilsson" . "ola.nilsson@gmail.com")) (:maintainer "Ola Nilsson" . "ola.nilsson@gmail.com") (:keywords "tools" "test" "unittest" "ert") (:url . "http://bitbucket.org/olanilsson/ert-junit"))]) @@ -1370,7 +1375,7 @@ (eshell-info-banner . [(20220728 1006) ((emacs (25 1)) (s (1))) "System information as your Eshell banner" single ((:commit . "987e69a66276ca057798896c606e5c5d5fb9ee5c") (:authors ("Lucien Cartier-Tilet" . "lucien@phundrak.com")) (:maintainer "Lucien Cartier-Tilet" . "lucien@phundrak.com") (:url . "https://github.com/Phundrak/eshell-info-banner.el"))]) (eshell-outline . [(20201121 620) ((emacs (25 1))) "Enhanced outline-mode for Eshell" single ((:commit . "6f917afa5b3d36764d76d7864589094647d8c3b4") (:authors ("Jamie Beardslee" . "jdb@jamzattack.xyz")) (:maintainer "Jamie Beardslee" . "jdb@jamzattack.xyz") (:keywords "unix" "eshell" "outline" "convenience") (:url . "https://git.jamzattack.xyz/eshell-outline"))]) (eshell-prompt-extras . [(20210925 110) ((emacs (25))) "Display extra information for your eshell prompt." single ((:commit . "c2078093323206b91a1b1f5786d79faa00b76be7") (:authors ("zwild" . "judezhao@outlook.com")) (:maintainer "Chunyang Xu" . "mail@xuchunyang.me") (:keywords "eshell" "prompt") (:url . "https://github.com/zwild/eshell-prompt-extras"))]) - (eshell-syntax-highlighting . [(20220816 2017) ((emacs (25 1))) "Highlight eshell commands" single ((:commit . "1ba39a9ffb2298cd716a4314cf3f369028c7bafe") (:authors ("Alex Kreisher" . "akreisher18@gmail.com")) (:maintainer "Alex Kreisher" . "akreisher18@gmail.com") (:keywords "convenience") (:url . "https://github.com/akreisher/eshell-syntax-highlighting"))]) + (eshell-syntax-highlighting . [(20230402 2034) ((emacs (25 1))) "Highlight eshell commands" single ((:commit . "0ac5259d497a9794e147d2b9dc23edf5bc844e3c") (:authors ("Alex Kreisher" . "akreisher18@gmail.com")) (:maintainer "Alex Kreisher" . "akreisher18@gmail.com") (:keywords "convenience") (:url . "https://github.com/akreisher/eshell-syntax-highlighting"))]) (eshell-toggle . [(20220718 729) ((emacs (25 1)) (dash (2 11 0))) "Show/hide eshell under active window." single ((:commit . "d4e884624f02e68b267b0044322ad17baa6780f8") (:authors ("Dmitry Cherkassov" . "dcherkassov@gmail.com")) (:maintainer "Dmitry Cherkassov" . "dcherkassov@gmail.com") (:keywords "processes") (:url . "https://github.com/4da/eshell-toggle"))]) (eshell-up . [(20170425 1737) ((emacs (24))) "Quickly go to a specific parent directory in eshell" single ((:commit . "b00e447ad7941ab31bcbb6bc0205fd492e887e7d") (:authors ("Peter W. V. Tran-Jørgensen" . "peter.w.v.jorgensen@gmail.com")) (:maintainer "Peter W. V. Tran-Jørgensen" . "peter.w.v.jorgensen@gmail.com") (:keywords "eshell") (:url . "https://github.com/peterwvj/eshell-up"))]) (eshell-vterm . [(20221229 1328) ((emacs (27 1)) (vterm (0 0 1))) "Vterm for visual commands in eshell" single ((:commit . "e96c30ad5e7d63b778fc3232e81b090b63b13277") (:authors ("Illia Ostapyshyn" . "ilya.ostapyshyn@gmail.com")) (:maintainer "Illia Ostapyshyn" . "ilya.ostapyshyn@gmail.com") (:keywords "eshell" "vterm" "terminals" "shell" "visual" "tools" "processes") (:url . "https://github.com/iostapyshyn/eshell-vterm"))]) @@ -1386,7 +1391,7 @@ (espy . [(20200317 2333) ((emacs (24))) "Emacs Simple Password Yielder" single ((:commit . "2c01be937a5e5bde62921684a0b27300705fb4e0") (:authors ("Sebastian Wålinder" . "s.walinder@gmail.com")) (:maintainer "Sebastian Wålinder" . "s.walinder@gmail.com") (:keywords "convenience") (:url . "https://github.com/walseb/espy"))]) (esqlite . [(20151206 1206) ((pcsv (1 3 3))) "Manipulate sqlite file from Emacs" single ((:commit . "fae9826cbc255b0f0686a801288f1441bda5f631") (:authors ("Masahiro Hayashi" . "mhayashi1120@gmail.com")) (:maintainer "Masahiro Hayashi" . "mhayashi1120@gmail.com") (:keywords "data") (:url . "https://github.com/mhayashi1120/Emacs-esqlite"))]) (esqlite-helm . [(20151116 850) ((esqlite (0 2 0)) (helm (20131207 845))) "Define helm source for sqlite database" single ((:commit . "84d5b16198f30949c544affba751ee0d58a000d9") (:authors ("Masahiro Hayashi" . "mhayashi1120@gmail.com")) (:maintainer "Masahiro Hayashi" . "mhayashi1120@gmail.com") (:keywords "data") (:url . "https://github.com/mhayashi1120/Emacs-esqlite"))]) - (ess . [(20221204 1348) ((emacs (25 1))) "Emacs Speaks Statistics" tar ((:commit . "b6aefb9ca231c3cbb1a6532b8afa4022c2678f81") (:authors ("David Smith" . "dsmith@stats.adelaide.edu.au") ("A.J. Rossini" . "blindglobe@gmail.com") ("Richard M. Heiberger" . "rmh@temple.edu") ("Kurt Hornik" . "Kurt.Hornik@R-project.org") ("Martin Maechler" . "maechler@stat.math.ethz.ch") ("Rodney A. Sparapani" . "rsparapa@mcw.edu") ("Stephen Eglen" . "stephen@gnu.org") ("Sebastian P. Luque" . "spluque@gmail.com") ("Henning Redestig" . "henning.red@googlemail.com") ("Vitalie Spinu" . "spinuvit@gmail.com") ("Lionel Henry" . "lionel.hry@gmail.com") ("J. Alexander Branham" . "alex.branham@gmail.com")) (:maintainer "ESS Core Team" . "ESS-core@r-project.org") (:url . "https://ess.r-project.org/"))]) + (ess . [(20230404 912) ((emacs (25 1))) "Emacs Speaks Statistics" tar ((:commit . "2d6d543946ec959f1c860b28218dcdac8e35168d") (:authors ("David Smith" . "dsmith@stats.adelaide.edu.au") ("A.J. Rossini" . "blindglobe@gmail.com") ("Richard M. Heiberger" . "rmh@temple.edu") ("Kurt Hornik" . "Kurt.Hornik@R-project.org") ("Martin Maechler" . "maechler@stat.math.ethz.ch") ("Rodney A. Sparapani" . "rsparapa@mcw.edu") ("Stephen Eglen" . "stephen@gnu.org") ("Sebastian P. Luque" . "spluque@gmail.com") ("Henning Redestig" . "henning.red@googlemail.com") ("Vitalie Spinu" . "spinuvit@gmail.com") ("Lionel Henry" . "lionel.hry@gmail.com") ("J. Alexander Branham" . "alex.branham@gmail.com")) (:maintainer "ESS Core Team" . "ESS-core@r-project.org") (:url . "https://ess.r-project.org/"))]) (ess-R-data-view . [(20130509 1158) ((ctable (20130313 1743)) (popup (20130324 1305)) (ess (20130225 1754))) "Data viewer for GNU R" single ((:commit . "d6e98d3ae1e2a2ea39a56eebcdb73e99d29562e9") (:authors ("myuhe ")) (:maintainer "myuhe") (:keywords "convenience") (:url . "https://github.com/myuhe/ess-R-data-view.el"))]) (ess-r-insert-obj . [(20220610 1406) ((emacs (26 1)) (ess (18 10 1))) "Insert objects in ESS-R" single ((:commit . "2ded9c23d0af2a7f6c0e02f9ea4af0e5b3cb7fb4") (:authors ("Shuguang Sun" . "shuguang79@qq.com")) (:maintainer "Shuguang Sun" . "shuguang79@qq.com") (:keywords "tools") (:url . "https://github.com/ShuguangSun/ess-r-insert-obj"))]) (ess-smart-equals . [(20210411 1333) ((emacs (25 1)) (ess (18 10))) "flexible, context-sensitive assignment key for R/S" single ((:commit . "fea9eea4b59c3e9559b379508e3500076ca99ef1") (:authors ("Christopher R. Genovese" . "genovese@cmu.edu")) (:maintainer "Christopher R. Genovese" . "genovese@cmu.edu") (:keywords "r" "s" "ess" "convenience") (:url . "https://github.com/genovese/ess-smart-equals"))]) @@ -1394,7 +1399,7 @@ (ess-view . [(20181001 1730) ((ess (15)) (s (1 8 0)) (f (0 16 0))) "View R dataframes in a spreadsheet software" single ((:commit . "d4e5a340b7bcc58c434867b97923094bd0680283") (:authors ("Bocci Gionata" . "boccigionata@gmail.com")) (:maintainer "Bocci Gionata" . "boccigionata@gmail.com") (:keywords "extensions" "ess") (:url . "https://github.com/GioBo/ess-view"))]) (ess-view-data . [(20220927 353) ((emacs (26 1)) (ess (18 10 1)) (csv-mode (1 12))) "View Data" single ((:commit . "1b48afef4dcc8fbaed1af98fade7f0df84bd6871") (:authors ("Shuguang Sun" . "shuguang79@qq.com")) (:maintainer "Shuguang Sun" . "shuguang79@qq.com") (:keywords "tools") (:url . "https://github.com/ShuguangSun/ess-view-data"))]) (esup . [(20220202 2335) ((cl-lib (0 5)) (s (1 2)) (emacs (25 1))) "The Emacs StartUp Profiler (ESUP)" tar ((:commit . "4b49c8d599d4cc0fbf994e9e54a9c78e5ab62a5f") (:authors ("Joe Schafer" . "joe@jschaf.com")) (:maintainer "Serghei Iakovlev" . "egrep@protonmail.ch") (:keywords "convenience" "processes") (:url . "https://github.com/jschaf/esup"))]) - (esxml . [(20220506 759) ((emacs (24 1)) (kv (0 0 5)) (cl-lib (0 5))) "Library for working with xml via esxml and sxml" tar ((:commit . "7ac1fec0e45f12836b301fd9b8e7297434db2f70") (:authors ("Evan Izaksonas-Smith ")) (:maintainer "Evan Izaksonas-Smith") (:keywords "tools" "lisp" "comm") (:url . "https://github.com/tali713/esxml"))]) + (esxml . [(20230308 2254) ((emacs (24 1)) (kv (0 0 5)) (cl-lib (0 5))) "Library for working with xml via esxml and sxml" tar ((:commit . "225693096a587492d76bf696d1f0c25c61f7d531") (:authors ("Vanya Izaksonas-Smith ")) (:maintainer "Vanya Izaksonas-Smith") (:keywords "tools" "lisp" "comm") (:url . "https://github.com/tali713/esxml"))]) (eta . [(20210115 1655) ((emacs (25 1)) (ht (2 2)) (dash (2 17))) "standard and multi dispatch key bind" single ((:commit . "651f96c46eeb7ff8a0f0efcfacad5b4d25bfaa4b") (:authors ("Chris Zheng")) (:maintainer "Chris Zheng") (:keywords "convenience" "usability") (:url . "https://www.github.com/zcaudate/eta"))]) (etable . [(20161028 2009) ((dash (2 9 0)) (interval-list (0 1)) (emacs (24 4))) "Implementation of javax.swing.JTable for Emacs." tar ((:commit . "d502141f0c69bf95256ba5cb9cd15350c7e942d2") (:authors ("Matus Goljer" . "matus.goljer@gmail.com")) (:maintainer "Matus Goljer" . "matus.goljer@gmail.com") (:keywords "convenience") (:url . "https://github.com/Fuco1/ETable"))]) (etc-sudoers-mode . [(20201102 1707) ((sudo-edit (0)) (with-editor (0))) "Edit Sudo security policies" single ((:commit . "74c66c58c9578a0d841206d5dec04d81e7b3d741") (:authors ("Peter Oliver" . "git@mavit.org.uk")) (:maintainer "Peter Oliver" . "git@mavit.org.uk") (:keywords "languages") (:url . "https://gitlab.com/mavit/etc-sudoers-mode/"))]) @@ -1411,7 +1416,7 @@ (evalator-clojure . [(20160208 2148) ((cider (0 10 0)) (evalator (1 0 0))) "Clojure evaluation context for evalator via CIDER." tar ((:commit . "caa4e0a137bdfada86593128a654e16aa617ad50") (:authors ("Sean Irby")) (:maintainer "Sean Irby" . "sean.t.irby@gmail.com") (:keywords "languages" "clojure" "cider" "helm") (:url . "http://www.github.com/seanirby/evalator-clojure"))]) (eve-mode . [(20170822 2231) ((emacs (25)) (polymode (1 0)) (markdown-mode (2 0))) "Major mode for editing Eve documents." single ((:commit . "a4661114d9c18725691b76321d72167ca5a9070a") (:authors ("Joshua Cole" . "joshuafcole@gmail.com")) (:maintainer "Joshua Cole" . "joshuafcole@gmail.com") (:keywords "languages" "wp" "tools") (:url . "https://github.com/witheve/emacs-eve-mode"))]) (everlasting-scratch . [(20230105 507) ((emacs (25 1))) "The *scratch* that lasts forever" single ((:commit . "1b7dac779501dcd988552aa6455a5be89e8b0562") (:authors ("Huming Chen" . "chenhuming@gmail.com")) (:maintainer "Huming Chen" . "chenhuming@gmail.com") (:keywords "convenience" "tool") (:url . "https://github.com/beacoder/everlasting-scratch"))]) - (evil . [(20230220 1805) ((emacs (24 1)) (goto-chg (1 6)) (cl-lib (0 5))) "Extensible Vi layer for Emacs." tar ((:commit . "22d76a4080e40381aae194c94f3bc16ba67a330a") (:maintainer "Tom Dalziel" . "tom.dalziel@gmail.com") (:keywords "emulations") (:url . "https://github.com/emacs-evil/evil"))]) + (evil . [(20230322 1818) ((emacs (24 1)) (goto-chg (1 6)) (cl-lib (0 5))) "Extensible Vi layer for Emacs." tar ((:commit . "c61bc34b40f1f0605a999e874e837d1e8bda85af") (:maintainer "Tom Dalziel" . "tom.dalziel@gmail.com") (:keywords "emulations") (:url . "https://github.com/emacs-evil/evil"))]) (evil-anzu . [(20220911 1939) ((evil (1 0 0)) (anzu (0 46))) "anzu for evil-mode" single ((:commit . "d1e98ee6976437164627542909a25c6946497899") (:authors ("Syohei YOSHIDA" . "syohex@gmail.com") ("Fredrik Bergroth" . "fbergroth@gmail.com")) (:maintainer "Syohei YOSHIDA" . "syohex@gmail.com") (:url . "https://github.com/syohex/emacs-evil-anzu"))]) (evil-args . [(20220125 1626) ((evil (1 0 8))) "Motions and text objects for delimited arguments in Evil." single ((:commit . "2671071a4a57eaee7cc8c27b9e4b6fc60fd2ccd3") (:authors ("Connor Smith" . "wconnorsmith@gmail.com")) (:maintainer "Connor Smith" . "wconnorsmith@gmail.com") (:keywords "evil" "vim-emulation") (:url . "http://github.com/wcsmith/evil-args"))]) (evil-avy . [(20150908 748) ((emacs (24 1)) (cl-lib (0 5)) (avy (0 3 0)) (evil (1 2 3))) "set-based completion" single ((:commit . "2dd955cc3ecaa7ddeb67b295298abdc6d16dd3a5") (:authors ("Yufan Lou" . "loganlyf@gmail.com")) (:maintainer "Yufan Lou" . "loganlyf@gmail.com") (:keywords "point" "location" "evil" "vim") (:url . "https://github.com/louy2/evil-avy"))]) @@ -1419,7 +1424,7 @@ (evil-cleverparens . [(20230216 2148) ((evil (1 0)) (paredit (1)) (smartparens (1 6 1)) (emacs (24 4)) (dash (2 12 0))) "Evil friendly minor-mode for editing lisp." tar ((:commit . "8d92bd47f07ca2dcf15835cfc3cb6e3a29c6146d") (:authors ("Olli Piepponen" . "opieppo@gmail.com")) (:maintainer "Olli Piepponen" . "opieppo@gmail.com") (:keywords "convenience" "emulations") (:url . "https://github.com/emacs-evil/evil-cleverparens"))]) (evil-colemak-basics . [(20221230 1443) ((emacs (24 3)) (evil (1 2 12)) (evil-snipe (2 0 3))) "Basic Colemak key bindings for evil-mode" single ((:commit . "ea519b962f051cabced8aadaf6ed0134b861225c") (:authors ("Wouter Bolsterlee" . "wouter@bolsterl.ee")) (:maintainer "Wouter Bolsterlee" . "wouter@bolsterl.ee") (:keywords "convenience" "emulations" "colemak" "evil") (:url . "https://github.com/wbolster/evil-colemak-basics"))]) (evil-colemak-minimal . [(20171006 1317) ((emacs (24)) (evil (1 2 12))) "Minimal Colemak key bindings for evil-mode" single ((:commit . "6d98b6da60f414524a0d718f76024c26dce742b3") (:authors ("Bryan Allred" . "bryan@revolvingcow.com")) (:maintainer "Bryan Allred" . "bryan@revolvingcow.com") (:keywords "colemak" "evil") (:url . "https://github.com/bmallred/evil-colemak-minimal"))]) - (evil-collection . [(20230214 1800) ((emacs (26 3)) (evil (1 2 13)) (annalist (1 0))) "A set of keybindings for Evil mode" tar ((:commit . "aaf3e0038e9255659fe0455729239c08498c4c0b") (:authors ("James Nguyen" . "james@jojojames.com")) (:maintainer "James Nguyen" . "james@jojojames.com") (:keywords "evil" "tools") (:url . "https://github.com/emacs-evil/evil-collection"))]) + (evil-collection . [(20230312 2309) ((emacs (26 3)) (evil (1 2 13)) (annalist (1 0))) "A set of keybindings for Evil mode" tar ((:commit . "d9a70ef21942c208094acf1e5c65d7f8f0016aca") (:authors ("James Nguyen" . "james@jojojames.com")) (:maintainer "James Nguyen" . "james@jojojames.com") (:keywords "evil" "tools") (:url . "https://github.com/emacs-evil/evil-collection"))]) (evil-commentary . [(20210210 1702) ((evil (1 0 0))) "Comment stuff out. A port of vim-commentary." tar ((:commit . "ca182e27156198db533bf6d48b7e5f6f54081397") (:authors ("Quang Linh LE" . "linktohack@gmail.com")) (:maintainer "Quang Linh LE" . "linktohack@gmail.com") (:keywords "evil" "comment" "commentary" "evil-commentary") (:url . "http://github.com/linktohack/evil-commentary"))]) (evil-dvorak . [(20160416 1841) ((evil (1 0 8))) "evil keybindings for that work with dvorak mode" tar ((:commit . "e7b80077d6f332452049eb3d7ea51f6c8fbf5947") (:authors ("Joshua Branson")) (:maintainer "Joshua Branson") (:keywords "dvorak" "evil" "vim"))]) (evil-easymotion . [(20200424 135) ((emacs (24)) (avy (0 3 0)) (cl-lib (0 5))) "A port of vim's easymotion to emacs" single ((:commit . "f96c2ed38ddc07908db7c3c11bcd6285a3e8c2e9") (:authors ("PythonNut" . "pythonnut@pythonnut.com")) (:maintainer "PythonNut" . "pythonnut@pythonnut.com") (:keywords "convenience" "evil") (:url . "https://github.com/pythonnut/evil-easymotion"))]) @@ -1443,7 +1448,7 @@ (evil-lisp-state . [(20160404 248) ((evil (1 0 9)) (bind-map (0)) (smartparens (1 6 1))) "An evil state to edit Lisp code" single ((:commit . "3c65fecd9917a41eaf6460f22187e2323821f3ce") (:authors ("Sylvain Benner" . "sylvain.benner@gmail.com")) (:maintainer "Sylvain Benner" . "sylvain.benner@gmail.com") (:keywords "convenience" "editing" "evil" "smartparens" "lisp" "mnemonic") (:url . "https://github.com/syl20bnr/evil-lisp-state"))]) (evil-lispy . [(20190502 739) ((lispy (0 26 0)) (evil (1 2 12)) (hydra (0 13 5))) "precision Lisp editing with Evil and Lispy" tar ((:commit . "ed317f7fccbdbeea8aa04a91b1b1f48a0e2ddc4e") (:authors ("Brandon Carrell , Mika Vilpas" . "mika.vilpas@gmail.com")) (:maintainer "Brandon Carrell , Mika Vilpas" . "mika.vilpas@gmail.com") (:keywords "lisp") (:url . "https://github.com/sp3ctum/evil-lispy"))]) (evil-mark-replace . [(20200630 940) ((evil (1 14 0))) "replace the thing in marked area" single ((:commit . "d4fec7b10e93cca149163324cd2b2b2dcc211047") (:authors ("Chen Bin ")) (:maintainer "Chen Bin ") (:keywords "convenience") (:url . "http://github.com/redguardtoo/evil-mark-replace"))]) - (evil-matchit . [(20230205 420) ((emacs (25 1))) "Vim matchit ported to Evil" tar ((:commit . "2218356f05ad19efc9476d0bd10051843d2306da") (:authors ("Chen Bin" . "chenbin.sh@gmail.com")) (:maintainer "Chen Bin" . "chenbin.sh@gmail.com") (:keywords "matchit" "vim" "evil") (:url . "http://github.com/redguardtoo/evil-matchit"))]) + (evil-matchit . [(20230325 618) ((emacs (25 1))) "Vim matchit ported to Evil" tar ((:commit . "3b12ed55d67bb70e8957c0c7fdad4ab4ad79eb2f") (:authors ("Chen Bin" . "chenbin.sh@gmail.com")) (:maintainer "Chen Bin" . "chenbin.sh@gmail.com") (:keywords "matchit" "vim" "evil") (:url . "http://github.com/redguardtoo/evil-matchit"))]) (evil-mc . [(20220118 122) ((emacs (24 3)) (evil (1 2 14)) (cl-lib (0 5))) "Multiple cursors for evil-mode" tar ((:commit . "63fd2fe0c213a4cc31c464d246f92931c4cb720f") (:authors ("Gabriel Adomnicai" . "gabesoft@gmail.com")) (:maintainer "Gabriel Adomnicai" . "gabesoft@gmail.com") (:keywords "evil" "editing" "multiple-cursors" "vim" "evil-multiple-cursors" "evil-mc" "evil-mc") (:url . "https://github.com/gabesoft/evil-mc"))]) (evil-mc-extras . [(20170202 1649) ((emacs (24 3)) (evil (1 2 12)) (cl-lib (0 5)) (evil-mc (0 0 2)) (evil-numbers (0 4))) "Extra functionality for evil-mc" tar ((:commit . "ba3252ae129c3b79aeb70ec3d276cbda32b00421") (:authors ("Gabriel Adomnicai" . "gabesoft@gmail.com")) (:maintainer "Gabriel Adomnicai" . "gabesoft@gmail.com") (:keywords "evil" "editing" "multiple-cursors" "vim" "evil-multiple-cursors" "evil-mc" "evil-mc-extras") (:url . "https://github.com/gabesoft/evil-mc-extras"))]) (evil-mu4e . [(20180613 1039) ((emacs (24 4)) (evil (1 2 10))) "evil-based key bindings for mu4e" single ((:commit . "f4b387ccbd2c49f3bbb5401e93bfcc050ca128ef") (:authors ("Joris Engbers" . "info@jorisengbers.nl")) (:maintainer "Joris Engbers" . "info@jorisengbers.nl") (:url . "https://github.com/JorisE/evil-mu4e"))]) @@ -1480,7 +1485,7 @@ (evil-textobj-entire . [(20150422 1254) ((emacs (24)) (evil (1 0 0))) "text object for entire lines of buffer for evil" single ((:commit . "5b3a98f3a69edc3a788f539f6ffef4a0ef5e853d") (:authors ("supermomonga")) (:maintainer "supermomonga") (:keywords "convenience" "emulations") (:url . "https://github.com/supermomonga/evil-textobj-entire"))]) (evil-textobj-line . [(20211101 1429) ((evil (1 0 0))) "Line text object for Evil" single ((:commit . "9eaf9a5485c2b5c05e16552b34632ca520cd681d") (:authors ("Syohei YOSHIDA" . "syohex@gmail.com")) (:maintainer "Syohei YOSHIDA" . "syohex@gmail.com"))]) (evil-textobj-syntax . [(20181210 1213) ((names (0 5)) (emacs (24)) (evil (0))) "Provides syntax text objects." single ((:commit . "2d9ba8c75c754b409aea7469f46a5cfa52a872f3") (:keywords "evil" "syntax" "highlight" "text-object") (:url . "https://github.com/laishulu/evil-textobj-syntax"))]) - (evil-textobj-tree-sitter . [(20230219 400) ((emacs (25 1)) (evil (1 0 0)) (tree-sitter (0 15 0))) "Provides evil textobjects using tree-sitter" tar ((:commit . "02f8253034042d8f171bc0ef93e3538b71a29153") (:keywords "evil" "tree-sitter" "text-object" "convenience") (:url . "https://github.com/meain/evil-textobj-tree-sitter"))]) + (evil-textobj-tree-sitter . [(20230311 1441) ((emacs (25 1)) (tree-sitter (0 15 0))) "Provides evil textobjects using tree-sitter" tar ((:commit . "11bbbab2412aec2bca16381ff639385644ca4b98") (:keywords "evil" "tree-sitter" "text-object" "convenience") (:url . "https://github.com/meain/evil-textobj-tree-sitter"))]) (evil-traces . [(20191214 558) ((emacs (25 1)) (evil (1 2 13))) "Visual hints for `evil-ex'" single ((:commit . "05e201cd63b549e3c88b5c3fc9b264bd6fe5a42c") (:authors ("Daniel Phan" . "daniel.phan36@gmail.com")) (:maintainer "Daniel Phan" . "daniel.phan36@gmail.com") (:keywords "emulations" "evil" "visual") (:url . "https://github.com/mamapanda/evil-traces"))]) (evil-tree-edit . [(20220425 2355) ((emacs (27 1)) (tree-edit (0 1 0)) (tree-sitter (0 15 0)) (evil (1 0 0)) (avy (0 5 0)) (s (0 0 0))) "Evil structural editing for any language!" tar ((:commit . "eafee31ca4f532a9dbee326d3ec3bdd1e997223b") (:authors ("Ethan Leba" . "ethanleba5@gmail.com")) (:maintainer "Ethan Leba" . "ethanleba5@gmail.com") (:url . "https://github.com/ethan-leba/tree-edit"))]) (evil-tutor . [(20150103 653) ((evil (1 0 9))) "Vimtutor adapted to Evil and wrapped in a major-mode" tar ((:commit . "909273bac88b98a565f1b89bbb13d523b7edce2b") (:authors ("Sylvain Benner" . "sylvain.benner@gmail.com")) (:maintainer "Sylvain Benner" . "sylvain.benner@gmail.com") (:keywords "convenience" "editing" "evil") (:url . "https://github.com/syl20bnr/evil-tutor"))]) @@ -1500,7 +1505,7 @@ (exato . [(20200524 1319) ((evil (1 2 13)) (emacs (24))) "EXATO: Evil XML/HTML Attributes Text Object" single ((:commit . "5e7b5721bf48aa49c6cdb5d41b908ef7d513b2a8") (:authors ("Filipe Silva" . "filipe.silva@gmail.com")) (:maintainer "Filipe Silva" . "filipe.silva@gmail.com") (:url . "https://github.com/ninrod/exato"))]) (exec-path-from-shell . [(20220826 1535) ((emacs (24 1)) (cl-lib (0 6))) "Get environment variables such as $PATH from the shell" single ((:commit . "dff9ce3577bf3f2938d9bde8ec8aa4fef3b061f3") (:authors ("Steve Purcell" . "steve@sanityinc.com")) (:maintainer "Steve Purcell" . "steve@sanityinc.com") (:keywords "unix" "environment") (:url . "https://github.com/purcell/exec-path-from-shell"))]) (execline . [(20190711 2010) ((emacs (26 1)) (s (1 6 0))) "Major mode for editing execline scripts" single ((:commit . "c75dd9b2c54d8e59fc35fd4bd98d8e213948a3f5") (:authors ("Dmitry Bogatov" . "KAction@debian.org")) (:maintainer "Dmitry Bogatov" . "KAction@debian.org") (:keywords "tools" "unix" "languages") (:url . "https://gitlab.com/KAction/emacs-execline"))]) - (exercism . [(20221220 2047) ((emacs (27 1)) (dash (2 19 1)) (a (1 0 0)) (s (1 13 1)) (request (0 3 2)) (async (1 9 6)) (async-await (1 1)) (persist (0 5)) (transient (0 3 7))) "Unofficial https://exercism.org integration" single ((:commit . "a8248e1afdae9155992227611cf134ec49fdd489") (:authors ("Rafael Nicdao ")) (:maintainer "Rafael Nicdao" . "nicdaoraf@gmail.com") (:keywords "exercism" "convenience") (:url . "https://github.com/anonimitoraf/exercism.el"))]) + (exercism . [(20230313 2027) ((emacs (27 1)) (dash (2 19 1)) (a (1 0 0)) (s (1 13 1)) (request (0 3 2)) (async (1 9 6)) (async-await (1 1)) (persist (0 5)) (transient (0 3 7))) "Unofficial https://exercism.org integration" single ((:commit . "1dfee3d12e4bf76647bcaed7ccf36fb0815f068f") (:authors ("Rafael Nicdao ")) (:maintainer "Rafael Nicdao" . "nicdaoraf@gmail.com") (:keywords "exercism" "convenience") (:url . "https://github.com/anonimitoraf/exercism.el"))]) (exiftool . [(20190520 1106) ((emacs (25))) "Elisp wrapper around ExifTool" single ((:commit . "e043df1bcef40cd5934a74c210e1e35d5eb0e5a6") (:authors ("Arun I" . "arunisaac@systemreboot.net")) (:maintainer "Arun I" . "arunisaac@systemreboot.net") (:keywords "data") (:url . "https://git.systemreboot.net/exiftool.el"))]) (exotica-theme . [(20180212 2329) ((emacs (24))) "A dark theme with vibrant colors" single ((:commit . "ff3ef4f6fa38c93b99becad977c7810c990a4d2f") (:authors ("Bharat Joshi" . "jbharat@outlook.com")) (:maintainer "Bharat Joshi" . "jbharat@outlook.com") (:keywords "faces" "theme" "dark" "vibrant colors") (:url . "https://github.com/jbharat/exotica-theme"))]) (expand-line . [(20151006 207) nil "Expand selection by line" single ((:commit . "75a5d0241f35dd0748ab8ecb4ff16891535be372") (:authors ("Kai Yu" . "yeannylam@gmail.com")) (:maintainer "Kai Yu" . "yeannylam@gmail.com"))]) @@ -1510,7 +1515,7 @@ (exsqlaim-mode . [(20170607 1003) ((s (1 10 0))) "Use variables inside sql queries" single ((:commit . "a2e0a62ec8b87193d8eaa695774bfd689324b06c") (:authors ("Ahmad Nazir Raja" . "ahmadnazir@gmail.com")) (:maintainer "Ahmad Nazir Raja" . "ahmadnazir@gmail.com") (:url . "https://github.com/ahmadnazir/exsqlaim-mode"))]) (extempore-mode . [(20220704 2241) ((emacs (24 4))) "Emacs major mode for Extempore source files" single ((:commit . "92e0fff482a0a4dc2971c39581c5ea9e84ae5e1c") (:authors ("Ben Swift" . "ben@benswift.me")) (:maintainer "Ben Swift" . "ben@benswift.me") (:keywords "extempore") (:url . "http://github.com/extemporelang/extempore-emacs-mode"))]) (extend-dnd . [(20151122 1850) nil "R drag and Drop" tar ((:commit . "80c966c93b82c9bb5c6225a432557c39144fc602") (:authors ("Matthew L. Fidler")) (:maintainer "Matthew L. Fidler") (:keywords "extend" "drag and drop") (:url . "https://github.com/mlf176f2/extend-dnd"))]) - (external-dict . [(20221210 407) ((emacs (25 1))) "Query external dictionary like goldendict, Bob.app etc" single ((:commit . "a9ceb6c2e12df460ce1686d47cafd88f212d0291") (:keywords "wp" "processes") (:url . "https://repo.or.cz/external-dict.el.git"))]) + (external-dict . [(20230313 118) ((emacs (25 1))) "Query external dictionary like goldendict, Bob.app etc" single ((:commit . "7ef87709c09792dfa6332fb41a6ec1edd917120a") (:keywords "wp" "processes") (:url . "https://repo.or.cz/external-dict.el.git"))]) (extmap . [(20211023 1904) ((emacs (24 1))) "Externally-stored constant mapping for Elisp" single ((:commit . "5875a4ab27831eb81af6246b12a174c765d52a78") (:authors ("Paul Pogonyshev" . "pogonyshev@gmail.com")) (:maintainer "Paul Pogonyshev" . "pogonyshev@gmail.com") (:keywords "lisp") (:url . "https://github.com/doublep/extmap"))]) (exunit . [(20221019 1320) ((s (1 11 0)) (emacs (24 3)) (f (0 20 0)) (transient (0 3 6))) "ExUnit test runner" single ((:commit . "e0a8c2b81f3d53885ed753b911b3cb6ee9229bec") (:authors ("Anantha kumaran" . "ananthakumaran@gmail.com")) (:maintainer "Anantha kumaran" . "ananthakumaran@gmail.com") (:keywords "processes" "elixir" "exunit") (:url . "http://github.com/ananthakumaran/exunit.el"))]) (exwm-edit . [(20220414 106) ((emacs (25 1))) "Edit mode for EXWM" single ((:commit . "b5b7e950f57e30befd68d51df34540b70e6ac28f") (:authors ("Ag Ibragimov")) (:maintainer "Ag Ibragimov") (:keywords "convenience") (:url . "https://github.com/agzam/exwm-edit"))]) @@ -1518,11 +1523,11 @@ (exwm-firefox-evil . [(20220318 1958) ((emacs (24 4)) (exwm (0 16)) (evil (1 0 0)) (exwm-firefox-core (1 0))) "evil-mode implementation of exwm-firefox-core" single ((:commit . "a377326e2e4ac386a0abb3fc9b1b356a0d955b61") (:authors ("Sebastian Wålinder" . "s.walinder@gmail.com")) (:maintainer "Sebastian Wålinder" . "s.walinder@gmail.com") (:keywords "extensions") (:url . "https://github.com/walseb/exwm-firefox-evil"))]) (exwm-float . [(20210207 2035) ((emacs (25 1)) (xelb (0 18)) (exwm (0 24)) (popwin (1 0 2))) "Convenient modes and bindings for floating EXWM frames" single ((:commit . "047c83aa6b54bfb6ca8cac4d3ea18542611cef77") (:authors ("Mehmet Tekman")) (:maintainer "Mehmet Tekman") (:keywords "outlines") (:url . "https://gitlab.com/mtekman/exwm-float.el"))]) (exwm-mff . [(20210603 1723) ((emacs (25 1))) "Mouse Follows Focus" single ((:commit . "89206f2e3189f589c27c56bd2b6203e906ee7100") (:authors ("Ian Eure" . "public@lowbar.fyi")) (:maintainer "Ian Eure" . "public@lowbar.fyi") (:keywords "unix") (:url . "https://github.com/ieure/exwm-mff"))]) - (exwm-modeline . [(20220131 1520) ((emacs (27 1)) (exwm (0 26))) "A modeline segment for EXWM workspaces" single ((:commit . "86bce1d91089b9a1517e1abfca86bac47be91be3") (:authors ("Korytov Pavel" . "thexcloud@gmail.com")) (:maintainer "Korytov Pavel" . "thexcloud@gmail.com") (:url . "https://github.com/SqrtMinusOne/exwm-modeline"))]) + (exwm-modeline . [(20230331 1747) ((emacs (27 1)) (exwm (0 26))) "A modeline segment for EXWM workspaces" single ((:commit . "852a88a58714e3e59675b79b185f036f7b0300e8") (:authors ("Korytov Pavel" . "thexcloud@gmail.com")) (:maintainer "Korytov Pavel" . "thexcloud@gmail.com") (:url . "https://github.com/SqrtMinusOne/exwm-modeline"))]) (exwm-surf . [(20171204 1140) ((emacs (24 4)) (exwm (0 16))) "Interface for Surf (surf.suckless.org) under exwm" single ((:commit . "6c17e2c1597fe4b7b454a1dac23b9127ac951e94") (:authors ("Peter" . "craven@gmx.net")) (:maintainer "Peter" . "craven@gmx.net") (:keywords "extensions") (:url . "https://github.com/ecraven/exwm-surf"))]) (exwm-x . [(20230119 624) ((cl-lib (0 5)) (async (1 6)) (exwm (0 22))) "A derivative wm based on EXWM (emacs x window manager)" tar ((:commit . "1e2bbfca872ad76eaa8f1c00d17762bed256881a") (:authors ("Feng Shu" . "tumashu@163.com")) (:maintainer "Feng Shu" . "tumashu@163.com") (:keywords "window-manager" "exwm") (:url . "https://github.com/tumashu/exwm-x"))]) (eyebrowse . [(20201107 955) ((dash (2 7 0)) (emacs (24 3 1))) "Easy window config switching" single ((:commit . "bdc626f88ab8e3d88bf5bf2e929707606675ef92") (:authors ("Vasilij Schneidermann" . "mail@vasilij.de")) (:maintainer "Vasilij Schneidermann" . "mail@vasilij.de") (:keywords "convenience") (:url . "https://depp.brause.cc/eyebrowse"))]) - (eyebrowse-restore . [(20230122 1510) ((emacs (26 3)) (eyebrowse (0 7 8)) (dash (2 19 1)) (s (1 13 0))) "Persistent Eyebrowse for all frames" single ((:commit . "77f171de019586a66481bcde6ab11f3689e97bc6") (:authors ("Jakub Kadlčík" . "frostyx@email.cz")) (:maintainer "Jakub Kadlčík" . "frostyx@email.cz") (:keywords "convenience" "eyebrowse" "helm" "persistent") (:url . "https://github.com/FrostyX/eyebrowse-restore"))]) + (eyebrowse-restore . [(20230312 1821) ((emacs (26 3)) (eyebrowse (0 7 8)) (dash (2 19 1)) (s (1 13 0))) "Persistent Eyebrowse for all frames" single ((:commit . "50e8a2cb3c4a64f7fadd0303d178de8a57bb37db") (:authors ("Jakub Kadlčík" . "frostyx@email.cz")) (:maintainer "Jakub Kadlčík" . "frostyx@email.cz") (:keywords "convenience" "eyebrowse" "helm" "persistent") (:url . "https://github.com/FrostyX/eyebrowse-restore"))]) (eyuml . [(20141028 2227) ((request (0 2 0)) (s (1 8 0))) "Write textual uml diagram from emacs using yuml.me" single ((:commit . "2f259c201c6cc63ee608f75cd85c1ae27f9d2532") (:authors ("Anthony HAMON" . "hamon.anth@gmail.com")) (:maintainer "Anthony HAMON" . "hamon.anth@gmail.com") (:keywords "uml") (:url . "http://github.com/antham/eyuml"))]) (ez-query-replace . [(20210724 2247) ((dash (1 2 0)) (s (1 11 0))) "a smarter context-sensitive query-replace that can be reapplied" single ((:commit . "2b68472f4007a73908c3b242e83ac5a7587967ff") (:authors ("Wilfred Hughes" . "me@wilfred.me.uk")) (:maintainer "Wilfred Hughes" . "me@wilfred.me.uk"))]) (eziam-themes . [(20221121 1609) nil "The mostly monochrome Eziam theme family." tar ((:commit . "7fba717293072d0afdbd1c45351ddf47b26b3064") (:authors ("Thibault Polge" . "thibault@thb.lt")) (:maintainer "Thibault Polge" . "thibault@thb.lt") (:keywords "faces") (:url . "https://github.com/thblt/eziam-theme-emacs"))]) @@ -1530,15 +1535,15 @@ (f3 . [(20180130 1158) ((emacs (24 3)) (helm (2 8 8)) (cl-lib (0 5))) "a helm interface to find" tar ((:commit . "000009ce4adf7a57eae80512f29c4ec2a1391ce5") (:authors ("Danny McClanahan")) (:maintainer "Danny McClanahan") (:keywords "find" "file" "files" "helm" "fast" "finder") (:url . "https://github.com/cosmicexplorer/f3"))]) (fabric . [(20171116 656) nil "Launch Fabric using Emacs" tar ((:commit . "df79be341d0b34ed23850f9894136092fa5fea8c") (:authors ("Nicolas Lamirault" . "nicolas.lamirault@chmouel.com")) (:maintainer "Nicolas Lamirault" . "nicolas.lamirault@chmouel.com") (:keywords "python" "fabric") (:url . "https://github.com/nlamirault/fabric.el"))]) (face-explorer . [(20190517 1857) nil "Library and tools for faces and text properties" single ((:commit . "ad1300e13e5643e4c246cabfd91f833d39113052") (:authors ("Anders Lindgren")) (:maintainer "Anders Lindgren") (:keywords "faces") (:url . "https://github.com/Lindydancer/face-explorer"))]) - (face-shift . [(20210725 2146) ((emacs (24 1))) "Shift the colour of certain faces" single ((:commit . "c214be3398a7671c6ea975f97740abdd38e910ea") (:authors ("Philip Kaludercic" . "philipk@posteo.net")) (:maintainer "Philip Kaludercic" . "philipk@posteo.net") (:keywords "faces") (:url . "https://git.sr.ht/~pkal/face-shift"))]) (faceup . [(20170925 1946) nil "Markup language for faces and font-lock regression testing" single ((:commit . "6c92dad56a133e14e7b27831e1bcf9b3a71ff154") (:authors ("Anders Lindgren")) (:maintainer "Anders Lindgren") (:keywords "faces" "languages") (:url . "https://github.com/Lindydancer/faceup"))]) (factlog . [(20130210 140) ((deferred (0 3 1))) "File activity logger" single ((:commit . "38f78132ae311faffba98ed5dd18d661af68678e") (:authors ("Takafumi Arakaki ")) (:maintainer "Takafumi Arakaki ") (:url . "https://github.com/tkf/factlog"))]) (faff-theme . [(20220629 1216) nil "Light Emacs color theme on cornsilk3 background" single ((:commit . "5d3c7e2f32f4dcdb22865c385ec48ababe5f293a") (:authors ("James Ferguson <(concat \"wjcferguson\" at-sign \"gmail.com\")>")) (:maintainer "James Ferguson <(concat \"wjcferguson\" at-sign \"gmail.com\")>") (:keywords "color" "theme") (:url . "https://github.com/WJCFerguson/emacs-faff-theme"))]) (fakir . [(20140729 1652) ((noflet (0 0 8)) (dash (1 3 2)) (kv (0 0 19))) "fakeing bits of Emacs" single ((:commit . "1fca406ad7de80fece6319ff75d4230b648534b0") (:authors ("Nic Ferrier" . "nferrier@ferrier.me.uk")) (:maintainer "Nic Ferrier" . "nferrier@ferrier.me.uk") (:keywords "lisp" "tools") (:url . "http://github.com/nicferrier/emacs-fakir"))]) (fancy-battery . [(20150101 1204) ((emacs (24 1))) "Fancy battery display" single ((:commit . "bcc2d7960ba207b5b4db96fe40f7d72670fdbb68") (:authors ("Sebastian Wiesner" . "swiesner@lunaryorn.com")) (:maintainer "Sebastian Wiesner" . "swiesner@lunaryorn.com") (:keywords "convenience" "tools" "hardware") (:url . "https://github.com/lunaryorn/fancy-battery.el"))]) - (fancy-compilation . [(20230109 536) ((emacs (26 1))) "Enhanced compilation output" single ((:commit . "889e77c899cbf28673915b7b0161d45734bfdcb7") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:url . "https://codeberg.org/ideasman42/emacs-fancy-compilation"))]) + (fancy-compilation . [(20230223 2309) ((emacs (26 1))) "Enhanced compilation output" single ((:commit . "d5d790dee6b07f866d203c5c174440ec8a2b2215") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:url . "https://codeberg.org/ideasman42/emacs-fancy-compilation"))]) (fancy-dabbrev . [(20220211 633) ((emacs (25 1)) (popup (0 5 3))) "Like dabbrev-expand with preview and popup menu" single ((:commit . "cf4a2f7e3e43e07ab9aa9db16532a21010e9fc8c") (:authors ("Joel Rosdahl" . "joel@rosdahl.net")) (:maintainer "Joel Rosdahl" . "joel@rosdahl.net") (:url . "https://github.com/jrosdahl/fancy-dabbrev"))]) (fancy-narrow . [(20171031 16) nil "narrow-to-region with more eye candy." single ((:commit . "9f4a587f6a5a387271fb665e13f59d41fd42504c") (:authors ("Artur Malabarba" . "bruce.connor.am@gmail.com")) (:maintainer "Artur Malabarba" . "bruce.connor.am@gmail.com") (:keywords "faces" "convenience") (:url . "http://github.com/Bruce-Connor/fancy-narrow"))]) + (fantom-mode . [(20221227 218) ((emacs (24 3))) "A major mode for the Fantom programming language" single ((:commit . "51cd82d29a7dca7bfd043971ba1d0fd21ed11693") (:authors ("XXIV")) (:maintainer "XXIV") (:keywords "files" "fantom") (:url . "https://github.com/thechampagne/fantom-mode"))]) (fantom-theme . [(20200328 604) ((emacs (24 1))) "Dark theme based on Phantom Code for VSCode" single ((:commit . "2c1c7fd53086c2ff86ee0961642c3b58e2343c08") (:authors ("Adam Svanberg")) (:maintainer "Adam Svanberg") (:url . "https://github.com/adsva/fantom-emacs-theme"))]) (fanyi . [(20221117 1821) ((emacs (27 1)) (s (1 12 0))) "Not only English-Chinese translator" tar ((:commit . "7181af0d848226ecdb9f517d8e4cf219d00f9000") (:authors ("Zhiwei Chen" . "condy0919@gmail.com")) (:maintainer "Zhiwei Chen" . "condy0919@gmail.com") (:keywords "convenience" "tools") (:url . "https://github.com/condy0919/fanyi.el"))]) (farmhouse-themes . [(20221025 2054) nil "Farmhouse Themes, dark and light versions" tar ((:commit . "30c763d01611dad88f1a1ff88451431e2629016d") (:authors ("Matthew Lyon" . "matthew@lyonheart.us")) (:maintainer "Matthew Lyon" . "matthew@lyonheart.us"))]) @@ -1548,7 +1553,7 @@ (fastnav . [(20120211 1457) nil "Fast navigation and editing routines." single ((:commit . "1019ba2b61d1a070204099b23da347278a61bc89") (:authors ("Zsolt Terek" . "zsolt@google.com")) (:maintainer "Zsolt Terek" . "zsolt@google.com") (:keywords "nav" "fast" "fastnav" "navigation"))]) (faust-mode . [(20201004 1353) nil "Faust syntax colorizer for Emacs." single ((:commit . "2a56cda14b152d5471f21a5d82f23c141dc7134c") (:authors ("rukano" . "rukano@gmail.com")) (:maintainer "Yassin Philip" . "xaccrocheur@gmail.com") (:keywords "languages" "faust") (:url . "https://github.com/rukano/emacs-faust-mode"))]) (faustine . [(20171122 1202) ((emacs (24 3)) (faust-mode (0 3))) "Edit, visualize, build and run Faust code" single ((:commit . "07a38963111518f86123802f9d477be0d4689a3f") (:authors ("Yassin Philip" . "xaccrocheur@gmail.com")) (:maintainer "Yassin Philip" . "xaccrocheur@gmail.com") (:keywords "languages" "faust") (:url . "https://bitbucket.org/yphil/faustine"))]) - (fb2-reader . [(20220820 1607) ((emacs (26 2)) (f (0 17)) (s (1 11 0)) (dash (2 12 0)) (visual-fill-column (2 2)) (async (1 9 4))) "Read FB2 and FB2.ZIP documents" single ((:commit . "8138cc3b674c911e92d280b97a5fdbbdf6e3182d") (:authors ("Dmitriy Pshonko" . "jumper047@gmail.com")) (:maintainer "Dmitriy Pshonko" . "jumper047@gmail.com") (:keywords "multimedia" "ebook" "fb2") (:url . "https://github.com/jumper047/fb2-reader"))]) + (fb2-reader . [(20230305 2309) ((emacs (26 2)) (f (0 17)) (s (1 11 0)) (dash (2 12 0)) (visual-fill-column (2 2)) (async (1 9 4))) "Read FB2 and FB2.ZIP documents" single ((:commit . "9836db284749e0cef4c43c2cb5358c82ae9b8589") (:authors ("Dmitriy Pshonko" . "jumper047@gmail.com")) (:maintainer "Dmitriy Pshonko" . "jumper047@gmail.com") (:keywords "multimedia" "ebook" "fb2") (:url . "https://github.com/jumper047/fb2-reader"))]) (fcitx . [(20190806 1923) nil "Make fcitx better in Emacs" single ((:commit . "12dc2638ddd15c8f6cfaecb20e1f428ab2bb5624") (:authors ("Junpeng Qiu" . "qjpchmail@gmail.com")) (:maintainer "Junpeng Qiu" . "qjpchmail@gmail.com") (:keywords "extensions") (:url . "https://github.com/cute-jumper/fcitx.el"))]) (fcopy . [(20150304 1403) nil "Funny Copy, set past point HERE then search copy text" single ((:commit . "e355f6ec889d8ecbdb096019c2dc660b1cec4941") (:authors ("Masayuki Ataka" . "masayuki.ataka@gmail.com")) (:maintainer "Masayuki Ataka" . "masayuki.ataka@gmail.com") (:keywords "convenience") (:url . "https://github.com/ataka/fcopy"))]) (fd-dired . [(20210723 549) ((emacs (25))) "find-dired alternative using fd" single ((:commit . "458464771bb220b6eb87ccfd4c985c436e57dc7e") (:authors ("Rashawn Zhang" . "namy.19@gmail.com")) (:maintainer "Rashawn Zhang" . "namy.19@gmail.com") (:keywords "tools" "fd" "find" "dired") (:url . "https://github.com/yqrashawn/fd-dired"))]) @@ -1556,14 +1561,15 @@ (feature-mode . [(20220418 848) nil "Major mode for editing Gherkin (i.e. Cucumber) user stories" tar ((:commit . "e204d9e204b767cf95d6a051ff283f05dc51e9d3") (:authors ("Michael Klishin")) (:maintainer "Michael Klishin") (:url . "https://github.com/michaelklishin/cucumber.el"))]) (feebleline . [(20190822 1401) nil "Replace modeline with a slimmer proxy" single ((:commit . "b2f2db25cac77817bf0c49ea2cea6383556faea0") (:authors ("Benjamin Lindqvist" . "benjamin.lindqvist@gmail.com")) (:maintainer "Benjamin Lindqvist" . "benjamin.lindqvist@gmail.com") (:url . "https://github.com/tautologyclub/feebleline"))]) (feed-discovery . [(20200714 1118) ((emacs (25 1)) (dash (2 16 0))) "Discover feed url by RSS/Atom autodiscovery" single ((:commit . "3812439c845c184eaf164d3ac8935de135259855") (:authors ("Hiroki YAMAKAWA" . "s06139@gmail.com")) (:maintainer "Hiroki YAMAKAWA" . "s06139@gmail.com") (:url . "https://github.com/HKey/feed-discovery"))]) + (feline . [(20230315 1821) ((emacs (28 1))) "A modeline with very little" single ((:commit . "3f9247f48058285d3e03957680e011ecf58d6feb") (:authors ("chee" . "emacs@chee.party")) (:maintainer "chee" . "emacs@chee.party") (:url . "https://opensource.chee.party/chee/feline-mode"))]) (fennel-mode . [(20230215 1641) ((emacs (26 1))) "A major-mode for editing Fennel code" tar ((:commit . "52da9715b0d046597cb322d3a98cb27ae6e5719e") (:authors ("Phil Hagelberg")) (:maintainer "Phil Hagelberg") (:keywords "languages" "tools") (:url . "https://git.sr.ht/~technomancy/fennel-mode"))]) (fetch . [(20131201 730) nil "Fetch and unpack resources" single ((:commit . "3f2793afcbbc32f320e572453166f9354ecc6d06") (:authors ("Christian 'crshd' Brassat" . "christian.brassat@gmail.com")) (:maintainer "Christian 'crshd' Brassat" . "christian.brassat@gmail.com") (:url . "https://github.com/crshd/fetch.el"))]) (ffmpeg-player . [(20220704 641) ((emacs (24 4)) (s (1 12 0)) (f (0 20 0))) "Play video using ffmpeg" single ((:commit . "2c41d715b012f399e661a816376824a8dea0b941") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "multimedia" "video" "ffmpeg" "buffering" "images") (:url . "https://github.com/jcs-elpa/ffmpeg-player"))]) - (ffmpeg-utils . [(20230212 55) ((emacs (25 1)) (alert (1 2)) (transient (0 1 0))) "FFmpeg command utilities wrappers" single ((:commit . "7ae311d235514b7b5bf12dc2c214856856c2c411") (:keywords "multimedia") (:url . "https://repo.or.cz/ffmpeg-utils.git"))]) + (ffmpeg-utils . [(20230305 709) ((emacs (25 1)) (alert (1 2)) (transient (0 1 0))) "FFmpeg command utilities wrappers" single ((:commit . "064d61527bc6b6a1d0fb0065f8a7bae3bbd4cefc") (:keywords "multimedia") (:url . "https://repo.or.cz/ffmpeg-utils.git"))]) (fic-mode . [(20180603 2035) nil "Show FIXME/TODO/BUG(...) in special face only in comments and strings" single ((:commit . "a05fc36ed54ba0c6dc22ac216a6a72cf191ca13d") (:url . "https://github.com/lewang/fic-mode"))]) (fifo-class . [(20160425 558) nil "First in first out abstract class" single ((:commit . "8fe4cf690727f4ac7b67f29c55f845df023c3f21") (:authors ("Mola-T" . "Mola@molamola.xyz")) (:maintainer "Mola-T" . "Mola@molamola.xyz") (:keywords "lisp") (:url . "https://github.com/mola-T/fifo-class"))]) (figlet . [(20160218 2237) nil "Annoy people with big, ascii art text" single ((:commit . "19a38783a90e151faf047ff233a21a729db0cea9") (:authors ("Philip Jackson" . "phil@shellarchive.co.uk")) (:maintainer "Philip Jackson" . "phil@shellarchive.co.uk"))]) - (file-info . [(20230214 1955) ((emacs (28 1)) (hydra (0 15 0)) (browse-at-remote (0 15 0))) "Show pretty information about current file" single ((:commit . "0c7717796ed84629145387b4b9ef60b600c3efc0") (:authors ("Artur Yaroshenko" . "artawower@protonmail.com")) (:maintainer "Artur Yaroshenko" . "artawower@protonmail.com") (:url . "https://github.com/artawower/file-info.el"))]) + (file-info . [(20230330 1709) ((emacs (28 1)) (hydra (0 15 0)) (browse-at-remote (0 15 0))) "Show pretty information about current file" single ((:commit . "0c9eb805f5600045cd0870747abc801e8a6e3ffa") (:authors ("Artur Yaroshenko" . "artawower@protonmail.com")) (:maintainer "Artur Yaroshenko" . "artawower@protonmail.com") (:url . "https://github.com/artawower/file-info.el"))]) (filelock . [(20180524 2215) ((emacs (24)) (cl-lib (0)) (f (0))) "Functions for manipulating file locks" single ((:commit . "17a5ca6e0dee14d2e7d92c84be91143bca9d9663") (:authors ("Ryan C. Thompson")) (:maintainer "Ryan C. Thompson") (:keywords "extensions" "files" "tools") (:url . "https://github.com/DarwinAwardWinner/emacs-filelock"))]) (filetags . [(20190706 804) ((emacs (24 4))) "Package to manage filetags in filename" single ((:commit . "71667a819e46eb1f6e30e2fa61321acb7c6ccb3d") (:authors ("Max Beutelspacher")) (:maintainer "Max Beutelspacher") (:keywords "convenience" "files") (:url . "https://github.com/DerBeutlin/filetags.el"))]) (filetree . [(20221108 236) ((dash (2 12 0)) (helm (3 7 0)) (seq (2 23)) (transient (0 3 6))) "File tree view/manipulatation package" single ((:commit . "1c48ef63a639bfe1ae4d5095725ef88a3f2c590d") (:authors ("Ketan Patel" . "knpatel401@gmail.com")) (:maintainer "Ketan Patel" . "knpatel401@gmail.com") (:url . "https://github.com/knpatel401/filetree"))]) @@ -1582,7 +1588,7 @@ (find-things-fast . [(20150519 2226) nil "Find things fast, leveraging the power of git" single ((:commit . "281dcb5a2e2db1013246dcac5111808352a8ea95") (:authors ("Elvio Toccalino and Elliot Glaysher and Phil Hagelberg and Doug Alcorn")) (:maintainer "Elvio Toccalino and Elliot Glaysher and Phil Hagelberg and Doug Alcorn") (:keywords "project" "convenience"))]) (findr . [(20130127 2032) nil "Breadth-first file-finding facility for (X)Emacs" single ((:commit . "1ddbc0464bb05dcda392b62666ad17239a2152d3") (:authors ("David Bakhash" . "cadet@bu.edu")) (:maintainer "David Bakhash" . "cadet@bu.edu") (:keywords "files"))]) (fingers . [(20160817 829) nil "Modal editing with universal text manipulation helpers." tar ((:commit . "7de351448a6f5ea7aa7a25db6c90d5138f87eb16") (:authors ("Felix Geller" . "fgeller@gmail.com")) (:maintainer "Felix Geller" . "fgeller@gmail.com") (:keywords "fingers" "modal" "editing" "workman") (:url . "http://github.com/fgeller/fingers.el"))]) - (finito . [(20230116 1124) ((emacs (27 1)) (dash (2 17 0)) (request (0 3 2)) (f (0 2 0)) (s (1 12 0)) (transient (0 3 0)) (graphql (0 1 1)) (async (1 9 3))) "View and collect books" tar ((:commit . "286bea5b4f27d906aa7fe71baa35c8f2bf55c286") (:authors ("Laurence Warne")) (:maintainer "Laurence Warne") (:keywords "outlines") (:url . "https://github.com/LaurenceWarne/finito.el"))]) + (finito . [(20230225 1326) ((emacs (27 1)) (dash (2 17 0)) (request (0 3 2)) (f (0 2 0)) (s (1 12 0)) (transient (0 3 0)) (graphql (0 1 1)) (async (1 9 3))) "View and collect books" tar ((:commit . "c8143ff6d32d13f809688800e761250b113d1b0f") (:authors ("Laurence Warne")) (:maintainer "Laurence Warne") (:keywords "outlines") (:url . "https://github.com/LaurenceWarne/finito.el"))]) (fiplr . [(20140724 645) ((grizzl (0 1 0)) (cl-lib (0 1))) "Fuzzy Search for Files in Projects" tar ((:commit . "bb6b90ba3c558988c195048c4c40140b2ee17530") (:authors ("Chris Corbyn" . "chris@w3style.co.uk")) (:maintainer "Chris Corbyn" . "chris@w3style.co.uk") (:keywords "convenience" "usability" "project") (:url . "https://github.com/d11wtq/fiplr"))]) (fira-code-mode . [(20220531 1555) ((emacs (24 4))) "Minor mode for Fira Code ligatures using prettify-symbols" single ((:commit . "7b469ca0c22b7e6a907cd65eebdfa9723998a131") (:authors ("Jonathan Ming" . "jming422@gmail.com")) (:maintainer "Jonathan Ming" . "jming422@gmail.com") (:keywords "faces" "ligatures" "fonts" "programming-ligatures") (:url . "https://github.com/jming422/fira-code-mode"))]) (firecode-theme . [(20170808 1311) ((emacs (24 0))) "an Emacs 24 theme based on FireCode (tmTheme)" single ((:commit . "8b7b03ecdd41e70dab145b98906017e1392eaef4") (:authors ("Jason Milkins")) (:maintainer "Jason Milkins") (:url . "https://github.com/emacsfodder/tmtheme-to-deftheme"))]) @@ -1590,7 +1596,7 @@ (firestarter . [(20210508 1626) ((emacs (24 1))) "Execute (shell) commands on save" single ((:commit . "76070c9074aa363350abe6ad06143e90b3e12ab1") (:authors ("Vasilij Schneidermann" . "mail@vasilij.de")) (:maintainer "Vasilij Schneidermann" . "mail@vasilij.de") (:keywords "convenience") (:url . "https://depp.brause.cc/firestarter"))]) (firrtl-mode . [(20200329 2002) ((emacs (24 3))) "mode for working with FIRRTL files" single ((:commit . "fa40141411a876ce7a1a9d6d3fe47134bc1fa954") (:authors ("Schuyler Eldridge" . "schuyler.eldridge@ibm.com")) (:maintainer "Schuyler Eldridge" . "schuyler.eldridge@ibm.com") (:keywords "languages" "firrtl") (:url . "https://github.com/ibm/firrtl-mode"))]) (fish-completion . [(20191103 1210) ((emacs (25 1))) "Fish completion for pcomplete (shell and Eshell)" single ((:commit . "10384881817b5ae38cf6197a077a663420090d2c") (:authors ("Pierre Neidhardt" . "mail@ambrevar.xyz")) (:maintainer "Pierre Neidhardt" . "mail@ambrevar.xyz") (:url . "https://gitlab.com/Ambrevar/emacs-fish-completion"))]) - (fish-mode . [(20220505 1111) ((emacs (24))) "Major mode for fish shell scripts" single ((:commit . "d04478c0aba018cb789d77d591bfe315cb25132a") (:authors ("Tony Wang" . "wwwjfy@gmail.com")) (:maintainer "Tony Wang" . "wwwjfy@gmail.com") (:keywords "fish" "shell"))]) + (fish-mode . [(20230326 1604) ((emacs (24))) "Major mode for fish shell scripts" single ((:commit . "6869efbc05cdb628209338bf57fe52742e53d956") (:authors ("Tony Wang" . "wwwjfy@gmail.com")) (:maintainer "Tony Wang" . "wwwjfy@gmail.com") (:keywords "fish" "shell"))]) (fit-text-scale . [(20211230 2002) ((emacs (25 1))) "Fit text by scaling" single ((:commit . "c53c8ce606380088643463848a9ee3502b0c64f4") (:authors ("Marco Wahl" . "marcowahlsoft@gmail.com")) (:maintainer "Marco Wahl" . "marcowahlsoft@gmail.com") (:keywords "convenience") (:url . "https://gitlab.com/marcowahl/fit-text-scale"))]) (fix-input . [(20210320 1244) ((emacs (24 4))) "Make input methods play nicely with alternative keyboard layout on OS level" single ((:commit . "10b3aebc3d4411e6889f3428e8f097c0fbf8585c") (:authors ("Mark Karpov" . "markkarpov92@gmail.com")) (:maintainer "Mark Karpov" . "markkarpov92@gmail.com") (:keywords "input" "method") (:url . "https://github.com/mrkkrp/fix-input"))]) (fix-muscle-memory . [(20210702 1755) nil "Simple hacks to fix muscle memory problems" single ((:commit . "b8d4b8025d758762f4459c70c3a7a209ead865ed") (:authors ("Jonathan Arkell" . "jonnay@jonnay.net")) (:maintainer "Jonathan Arkell" . "jonnay@jonnay.net") (:keywords "spelling" "typing"))]) @@ -1606,6 +1612,7 @@ (flatland-theme . [(20171113 1521) nil "A simple theme for Emacs based on the Flatland theme for Sublime Text" single ((:commit . "a98a6f19ad4dff0fa3fad1ea487b7d0ef634a19a") (:authors ("Greg Chapple" . "info@gregchapple.com")) (:maintainer "Greg Chapple" . "info@gregchapple.com") (:url . "http://github.com/gregchapple/flatland-emacs"))]) (flatui-dark-theme . [(20170513 1422) ((emacs (24))) "Dark color theme with colors from https://flatuicolors.com/" single ((:commit . "5b959a9f743f891e4660b1b432086417947872ea") (:authors ("Andrew Phillips" . "theasp@gmail.com")) (:maintainer "Andrew Phillips" . "theasp@gmail.com") (:keywords "color" "theme" "dark" "flatui" "faces") (:url . "https://github.com/theasp/flatui-dark-theme"))]) (flatui-theme . [(20160619 127) nil "A color theme for Emacs based on flatuicolors.com" single ((:commit . "9c15db5526c15c8dba55023f5698372b19c2a780") (:authors ("John Louis Del Rosario" . "john2x@gmail.com")) (:maintainer "John Louis Del Rosario" . "john2x@gmail.com") (:url . "https://github.com/john2x/flatui-theme.el"))]) + (fleetish-theme . [(20230407 1438) ((emacs (24))) "A take on the JetBrains Fleet theme" single ((:commit . "482513562b6691c7f3440b62a31033d22378ed96") (:authors ("Scott Raine" . "scott@raine.sh")) (:maintainer "Scott Raine" . "scott@raine.sh") (:url . "https://github.com/nylar/fleetish-emacs-theme"))]) (flex-autopair . [(20120809 1218) nil "Automatically insert pair braces and quotes, insertion conditions & actions are highly customizable." single ((:commit . "55d128749cc070551a1624a4508d1c4f6d76f7cf") (:authors ("Yuuki Arisawa" . "yuuki.ari@gmail.com")) (:maintainer "Yuuki Arisawa" . "yuuki.ari@gmail.com") (:keywords "keyboard" "input") (:url . "https://github.com/uk-ar/flex-autopair.el"))]) (flex-compile . [(20230116 1638) ((emacs (26 1)) (dash (2 17 0)) (buffer-manage (1 1))) "Run, evaluate and compile across many languages" tar ((:commit . "791e297048e02ef1649ad17a5a2bd9d78e766c03") (:authors ("Paul Landes")) (:maintainer "Paul Landes") (:keywords "compilation" "integration" "processes") (:url . "https://github.com/plandes/flex-compile"))]) (flex-isearch . [(20170308 2010) nil "Flex matching (like ido) in isearch." single ((:commit . "b1f7e04de762282c276343cc2709af9ff4abc9d2") (:authors ("Jonathan Kotta" . "jpkotta@gmail.com")) (:maintainer "Jonathan Kotta" . "jpkotta@gmail.com") (:keywords "convenience" "search") (:url . "https://bitbucket.org/jpkotta/flex-isearch"))]) @@ -1623,7 +1630,7 @@ (flx . [(20221213 542) ((cl-lib (0 3))) "fuzzy matching with good sorting" single ((:commit . "7b44a5abb254bbfbeca7a29336f7f4ebd8aabbf2") (:authors ("Le Wang")) (:maintainer "Le Wang") (:url . "https://github.com/lewang/flx"))]) (flx-ido . [(20221213 542) ((flx (0 1)) (cl-lib (0 3))) "flx integration for ido" single ((:commit . "7b44a5abb254bbfbeca7a29336f7f4ebd8aabbf2") (:authors ("Le Wang")) (:maintainer "Le Wang") (:url . "https://github.com/lewang/flx"))]) (flx-isearch . [(20191119 515) ((emacs (24)) (flx (20140821)) (cl-lib (0 5))) "Fuzzy incremental searching for emacs" single ((:commit . "a44097fb8f539a193c2f09a37ea52a68f2c51839") (:authors ("PythonNut" . "pythonnut@pythonnut.com")) (:maintainer "PythonNut" . "pythonnut@pythonnut.com") (:keywords "convenience" "search" "flx") (:url . "https://github.com/pythonnut/flx-isearch"))]) - (flycheck . [(20230218 2135) ((emacs (25 1)) (dash (2 12 1)) (pkg-info (0 4)) (let-alist (1 0 4)) (seq (1 11))) "On-the-fly syntax checking" tar ((:commit . "55614401a955e73f5c0f05c0e098d9e717e3116d") (:authors ("Sebastian Wiesner" . "swiesner@lunaryorn.com")) (:maintainer "Clément Pit-Claudel" . "clement.pitclaudel@live.com") (:keywords "convenience" "languages" "tools") (:url . "http://www.flycheck.org"))]) + (flycheck . [(20230306 414) ((emacs (25 1)) (dash (2 12 1)) (pkg-info (0 4)) (let-alist (1 0 4)) (seq (1 11))) "On-the-fly syntax checking" tar ((:commit . "5f2ef177cb21ae8b73714575802beef04abd0f5e") (:authors ("Sebastian Wiesner" . "swiesner@lunaryorn.com")) (:maintainer "Clément Pit-Claudel" . "clement.pitclaudel@live.com") (:keywords "convenience" "languages" "tools") (:url . "http://www.flycheck.org"))]) (flycheck-ameba . [(20191226 1011) ((emacs (24 4)) (flycheck (30))) "Add support for Ameba to Flycheck" single ((:commit . "b129dbd8e4c43077521d1c77cc94bb3d52d5ee6d") (:keywords "tools" "crystal" "ameba") (:url . "https://github.com/crystal-ameba/ameba.el"))]) (flycheck-apertium . [(20181211 1038) ((flycheck (0 25))) "Apertium checkers in flycheck" tar ((:commit . "22b60a17836477ac1edd15dc85b14f88ca871ba9") (:authors ("Kevin Brubeck Unhammer" . "unhammer+apertium@mm.st")) (:maintainer "Kevin Brubeck Unhammer" . "unhammer+apertium@mm.st") (:keywords "convenience" "tools" "xml") (:url . "http://wiki.apertium.org/wiki/Emacs"))]) (flycheck-aspell . [(20220411 826) ((flycheck (28 0)) (emacs (25 1))) "Aspell checker for flycheck" single ((:commit . "5ec0f9b28b1d86eec192b23bc24d9a33dfe51882") (:authors ("Leo Gaskin" . "leo.gaskin@le0.gs")) (:maintainer "Leo Gaskin" . "leo.gaskin@le0.gs") (:keywords "wp" "flycheck" "spell" "aspell") (:url . "https://github.com/leotaku/flycheck-aspell"))]) @@ -1631,7 +1638,7 @@ (flycheck-bashate . [(20200625 642) ((flycheck (0 24)) (emacs (24 4))) "Integrate bashate with flycheck" single ((:commit . "69e53e84f712bafffd785d84d9304598c2df5615") (:authors ("Alex Murray" . "murray.alex@gmail.com")) (:maintainer "Alex Murray" . "murray.alex@gmail.com") (:url . "https://github.com/alexmurray/flycheck-bashate"))]) (flycheck-cask . [(20200926 1502) ((emacs (24 3)) (flycheck (0 14)) (dash (2 4 0))) "Cask support in Flycheck" single ((:commit . "4b2ede6362ded4a45678dfbef1876faa42edbd58") (:authors ("Sebastian Wiesner" . "swiesner@lunaryorn.com")) (:maintainer "Sebastian Wiesner" . "swiesner@lunaryorn.com") (:keywords "tools" "convenience") (:url . "https://github.com/flycheck/flycheck-cask"))]) (flycheck-cfn . [(20220221 1029) ((emacs (26 1)) (flycheck (31))) "Flycheck backend for AWS cloudformation" single ((:commit . "4cf56affe3035fda364109836e26499431095185") (:authors ("William Orr" . "will@worrbase.com")) (:maintainer "William Orr" . "will@worrbase.com") (:keywords "convenience") (:url . "https://gitlab.com/worr/cfn-mode"))]) - (flycheck-checkbashisms . [(20190403 218) ((emacs (24)) (flycheck (0 25))) "checkbashisms checker for flycheck" single ((:commit . "2e386775f1a0eb5d80e5d70e98474ee32ecafb24") (:authors ("Cuong Le" . "cuong.manhle.vn@gmail.com")) (:maintainer "Cuong Le" . "cuong.manhle.vn@gmail.com") (:keywords "convenience" "tools" "sh" "unix") (:url . "https://github.com/cuonglm/flycheck-checkbashisms"))]) + (flycheck-checkbashisms . [(20230313 1418) ((emacs (24)) (flycheck (0 25))) "checkbashisms checker for flycheck" single ((:commit . "ca8f11679c77d6702f34e773bdde185ceb47a05d") (:authors ("Cuong Le" . "cuong.manhle.vn@gmail.com")) (:maintainer "Cuong Le" . "cuong.manhle.vn@gmail.com") (:keywords "convenience" "tools" "sh" "unix") (:url . "https://github.com/cuonglm/flycheck-checkbashisms"))]) (flycheck-checkpatch . [(20170217 1025) ((emacs (25)) (flycheck (30))) "Flycheck support for checkpatch.pl tool" single ((:commit . "6461fc7b0d493eb9863814055f8bce5fa35739de") (:authors ("Alexander Yarygin" . "yarygin.alexander@gmail.com")) (:maintainer "Alexander Yarygin" . "yarygin.alexander@gmail.com") (:url . "https://github.com/zpp0/flycheck-checkpatch"))]) (flycheck-clang-analyzer . [(20211214 648) ((flycheck (0 24)) (emacs (24 4))) "Integrate Clang Analyzer with flycheck" single ((:commit . "646d9f3a80046ab231a07526778695d5decad92d") (:authors ("Alex Murray" . "murray.alex@gmail.com")) (:maintainer "Alex Murray" . "murray.alex@gmail.com") (:url . "https://github.com/alexmurray/flycheck-clang-analyzer"))]) (flycheck-clang-tidy . [(20201115 1232) ((flycheck (0 30))) "Flycheck syntax checker using clang-tidy" single ((:commit . "3bd947fb0dcc1e97617eab7be9e1b6e57db5e091") (:authors (nil . "Sebastian Nagel")) (:maintainer "tastytea" . "tastytea@tastytea.de") (:keywords "convenience" "languages" "tools") (:url . "https://github.com/ch1bo/flycheck-clang-tidy"))]) @@ -1660,7 +1667,7 @@ (flycheck-elixir . [(20210413 612) ((flycheck (0 25))) "Support Elixir in flycheck" single ((:commit . "b57a77a21d6cf9621b3387831cba34135c4fa35d") (:authors ("Lorenzo Bolla" . "lbolla@gmail.com")) (:maintainer "Lorenzo Bolla" . "lbolla@gmail.com"))]) (flycheck-elm . [(20181107 146) ((flycheck (0 29 -4)) (emacs (24 4)) (let-alist (1 0 5)) (seq (2 20))) "Flycheck support for the elm language" single ((:commit . "debd0af563cb6c2944367a691c7fa3021d9378c1") (:authors ("Brian Sermons")) (:maintainer "Brian Sermons") (:url . "https://github.com/bsermons/flycheck-elm"))]) (flycheck-elsa . [(20230217 1640) ((emacs (25)) (flycheck (0 14)) (seq (2 0))) "Flycheck for Elsa" tar ((:commit . "d60db9544d0c4213f2478bcea0fd0e668e31cf34") (:authors ("Matúš Goljer" . "matus.goljer@gmail.com")) (:maintainer "Matúš Goljer" . "matus.goljer@gmail.com") (:keywords "convenience") (:url . "https://github.com/emacs-elsa/flycheck-elsa"))]) - (flycheck-falco-rules . [(20230213 1603) ((emacs (24 3)) (flycheck (0 25)) (let-alist (1 0 1))) "On-the-fly syntax checking for falco rules files" single ((:commit . "ba359f2d5968df47a100e78758f280fe0c965f07") (:authors ("The Falco Developers (https://falco.org)")) (:maintainer "The Falco Developers (https://falco.org)") (:keywords "tools" "convenience") (:url . "https://github.com/falcosecurity/flycheck-falco-rules"))]) + (flycheck-falco-rules . [(20230302 2340) ((emacs (24 3)) (flycheck (0 25)) (let-alist (1 0 1))) "On-the-fly syntax checking for falco rules files" single ((:commit . "1ad301d497ade9556327053ca571ee51bf0c0633") (:authors ("The Falco Developers (https://falco.org)")) (:maintainer "The Falco Developers (https://falco.org)") (:keywords "tools" "convenience") (:url . "https://github.com/falcosecurity/flycheck-falco-rules"))]) (flycheck-flawfinder . [(20211214 647) ((flycheck (0 24)) (emacs (24 4))) "Integrate flawfinder with flycheck" single ((:commit . "85701b849ea1ed8438ed4b7ae236e99d0f5528c7") (:authors ("Alex Murray" . "murray.alex@gmail.com")) (:maintainer "Alex Murray" . "murray.alex@gmail.com") (:url . "https://github.com/alexmurray/flycheck-flawfinder"))]) (flycheck-flow . [(20190304 1459) ((flycheck (0 18)) (json (1 4))) "Support Flow in flycheck" single ((:commit . "9e8e52cfc98af6a23fd906f9cb5d5d470d8cf82d") (:authors ("Lorenzo Bolla" . "lbolla@gmail.com")) (:maintainer "Lorenzo Bolla" . "lbolla@gmail.com"))]) (flycheck-ghcmod . [(20150114 632) ((flycheck (0 21 -4 1)) (dash (2 0))) "A flycheck checker for Haskell using ghcmod" single ((:commit . "6bb7b7d879f05bbae54e99eb04806c877adf3ccc") (:authors ("Shen Chao" . "scturtle@gmail.com")) (:maintainer "Shen Chao" . "scturtle@gmail.com") (:keywords "convenience" "languages" "tools") (:url . "https://github.com/scturtle/flycheck-ghcmod"))]) @@ -1670,7 +1677,7 @@ (flycheck-gradle . [(20190315 234) ((emacs (25 1)) (flycheck (0 25))) "Flycheck extension for Gradle." single ((:commit . "1ca08bbc343362a923cbdc2010f66e41655e92ab") (:maintainer "James Nguyen" . "james@jojojames.com") (:keywords "languages" "gradle") (:url . "https://github.com/jojojames/flycheck-gradle"))]) (flycheck-grammalecte . [(20221216 1904) ((emacs (26 1)) (flycheck (26))) "Integrate Grammalecte with Flycheck" tar ((:commit . "68c5087c8b31cf10fb9df77478edd24200fb4108") (:authors ("Guilhem Doulcier" . "guilhem.doulcier@espci.fr") ("Étienne Deparis" . "etienne@depar.is")) (:maintainer "Étienne Deparis" . "etienne@depar.is") (:keywords "i18n" "text") (:url . "https://git.umaneti.net/flycheck-grammalecte/"))]) (flycheck-grammarly . [(20221231 1654) ((emacs (25 1)) (flycheck (0 14)) (grammarly (0 3 0)) (s (1 12 0))) "Grammarly support for Flycheck" single ((:commit . "d4a788acc3875a1ffdd7460ab3377a887413c582") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "grammar" "check") (:url . "https://github.com/emacs-grammarly/flycheck-grammarly"))]) - (flycheck-guile . [(20220831 453) ((emacs (25 1)) (flycheck (0 22)) (geiser (0 20))) "A Flycheck checker for GNU Guile" single ((:commit . "e58ceb8b511cd395b9be69f4a1ff85305fbb51c3") (:authors ("Ricardo Wurmus" . "rekado@elephly.net")) (:maintainer "Andrew Whatson" . "whatson@gmail.com") (:url . "https://github.com/flatwhatson/flycheck-guile"))]) + (flycheck-guile . [(20230405 1154) ((emacs (25 1)) (flycheck (0 22)) (geiser (0 20))) "A Flycheck checker for GNU Guile" single ((:commit . "dd7bbdc48fd21cf8d270c913c56cd580f8ec3d03") (:authors ("Ricardo Wurmus" . "rekado@elephly.net")) (:maintainer "Andrew Whatson" . "whatson@tailcall.au") (:url . "https://notabug.org/flatwhatson/flycheck-guile"))]) (flycheck-haskell . [(20221111 59) ((emacs (24 3)) (flycheck (0 25)) (haskell-mode (13 7)) (dash (2 4 0)) (seq (1 11)) (let-alist (1 0 1))) "Flycheck: Automatic Haskell configuration" tar ((:commit . "50425a8b96fea84ea15940a4a07b184e43bb8e7a") (:authors ("Sebastian Wiesner" . "swiesner@lunaryorn.com")) (:maintainer "Sebastian Wiesner" . "swiesner@lunaryorn.com") (:keywords "tools" "convenience") (:url . "https://github.com/flycheck/flycheck-haskell"))]) (flycheck-hdevtools . [(20160926 702) ((flycheck (0 21 -4 1)) (dash (2 0))) "A flycheck checker for Haskell using hdevtools" single ((:commit . "53829f0c57800615718cfce27ffa16d8ba286cee") (:authors ("Steve Purcell" . "steve@sanityinc.com")) (:maintainer "Steve Purcell" . "steve@sanityinc.com") (:keywords "convenience" "languages" "tools") (:url . "https://github.com/flycheck/flycheck-hdevtools"))]) (flycheck-hledger . [(20220715 1115) ((emacs (27 1)) (flycheck (31))) "Flycheck module to check hledger journals" single ((:commit . "c360025b8433abc4da89b0bfcc7ed1ff27004c64") (:authors ("Damien Cassou" . "damien@cassou.me")) (:maintainer "Damien Cassou" . "damien@cassou.me") (:url . "https://github.com/DamienCassou/flycheck-hledger/"))]) @@ -1684,7 +1691,7 @@ (flycheck-julia . [(20170729 2141) ((emacs (24)) (flycheck (0 22))) "Julia support for Flycheck" single ((:commit . "213b60a5a9a1cb7887260e1d159b5bb27167cbb6") (:authors ("Guido Kraemer" . "guido.kraemer@gmx.de")) (:maintainer "Guido Kraemer" . "guido.kraemer@gmx.de") (:keywords "convenience" "tools" "languages") (:url . "https://github.com/gdkrmr/flycheck-julia"))]) (flycheck-keg . [(20200726 218) ((emacs (24 3)) (keg (0 1)) (flycheck (0 1))) "Flycheck for Keg projects" single ((:commit . "926de8f43842380e7150d99971eb73ff84cb59cb") (:authors ("Naoya Yamashita" . "conao3@gmail.com")) (:maintainer "Naoya Yamashita" . "conao3@gmail.com") (:keywords "convenience") (:url . "https://github.com/conao3/keg.el"))]) (flycheck-kotlin . [(20230111 1907) ((flycheck (0 20))) "Support kotlin in flycheck" single ((:commit . "a2a6abb9a7f85c6fb15ce327459ec3c8ff780188") (:authors ("Elric Milon" . "whirm_REMOVETHIS__@gmx.com")) (:maintainer "Elric Milon" . "whirm_REMOVETHIS__@gmx.com"))]) - (flycheck-languagetool . [(20221231 1658) ((emacs (25 1)) (flycheck (0 14))) "Flycheck support for LanguageTool" single ((:commit . "1fe838c8678a9a101935ce4a4f3183a731e38f01") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com") ("Peter Oliver" . "git@mavit.org.uk")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "grammar" "check") (:url . "https://github.com/emacs-languagetool/flycheck-languagetool"))]) + (flycheck-languagetool . [(20230329 1246) ((emacs (25 1)) (flycheck (0 14))) "Flycheck support for LanguageTool" single ((:commit . "04195838e21da84ec46d2940c2b3ee82d8beda70") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com") ("Peter Oliver" . "git@mavit.org.uk")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "grammar" "check") (:url . "https://github.com/emacs-languagetool/flycheck-languagetool"))]) (flycheck-ledger . [(20200304 2204) ((emacs (24 1)) (flycheck (0 15))) "Flycheck integration for ledger files" single ((:commit . "628e25ba66604946085571652a94a54f4d1ad96f") (:authors ("Steve Purcell" . "steve@sanityinc.com")) (:maintainer "Steve Purcell" . "steve@sanityinc.com") (:keywords "convenience" "languages" "tools") (:url . "https://github.com/purcell/flycheck-ledger"))]) (flycheck-lilypond . [(20211006 2102) ((emacs (24 3)) (flycheck (0 22))) "LilyPond support in Flycheck" single ((:commit . "78f8c16cd67f9f6d3f1806e1fd403222723ba400") (:authors ("Hinrik Örn Sigurðsson" . "hinrik.sig@gmail.com")) (:maintainer "Hinrik Örn Sigurðsson" . "hinrik.sig@gmail.com") (:keywords "tools" "convenience") (:url . "https://github.com/hinrik/flycheck-lilypond"))]) (flycheck-liquidhs . [(20170412 2326) ((flycheck (0 15))) "A flycheck checker for Haskell using liquid (i.e. liquidhaskell)" single ((:commit . "c27252ac24d77f4b6eec76a4ba9cd61761a3fba9") (:authors ("Ranjit Jhala" . "jhala@cs.ucsd.edu")) (:maintainer "Ranjit Jhala" . "jhala@cs.ucsd.edu") (:keywords "convenience" "languages" "tools") (:url . "https://github.com/ucsd-progsys/liquidhaskell/flycheck-liquid.el"))]) @@ -1699,7 +1706,7 @@ (flycheck-pact . [(20180920 2052) ((emacs (24 3)) (flycheck (0 25)) (pact-mode (0 0 4))) "Flycheck support for pact-mode" single ((:commit . "0e10045064ef89ec8b6f5a473073d47b976a2ca3") (:authors ("Stuart Popejoy")) (:maintainer "Stuart Popejoy" . "stuart@kadena.io") (:keywords "pact" "lisp" "languages" "blockchain" "smartcontracts" "tools" "linting") (:url . "http://github.com/kadena-io/flycheck-pact"))]) (flycheck-pest . [(20200710 2327) ((emacs (26 3)) (flycheck (31)) (pest-mode (0 1))) "Flycheck integration for Pest -" single ((:commit . "43447a2c70f98edd1139005e32f437d3f142442b") (:authors ("Naoya Yamashita" . "conao3@gmail.com")) (:maintainer "Naoya Yamashita" . "conao3@gmail.com") (:keywords "convenience" "flycheck") (:url . "https://github.com/ksqsf/pest-mode"))]) (flycheck-php-noverify . [(20211005 401) ((flycheck (0 22))) "Flycheck checker for PHP Noverify linter" single ((:commit . "3aa3035c637eb0476f05bd0fbc66c058aa67ffb7") (:url . "https://github.com/Junker/flycheck-php-noverify"))]) - (flycheck-phpstan . [(20220723 1451) ((emacs (24 3)) (flycheck (26)) (phpstan (0 5 0))) "Flycheck integration for PHPStan" single ((:commit . "8928206e16d7408f80d6987390fcebe26e3d30dd") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "tools" "php") (:url . "https://github.com/emacs-php/phpstan.el"))]) + (flycheck-phpstan . [(20230404 1351) ((emacs (24 3)) (flycheck (26)) (phpstan (0 5 0))) "Flycheck integration for PHPStan" single ((:commit . "6dc8f1df29f22f0b0ef839c66822d48e2c7b1848") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "tools" "php") (:url . "https://github.com/emacs-php/phpstan.el"))]) (flycheck-pkg-config . [(20230119 1721) ((dash (2 8 0)) (s (1 9 0)) (flycheck (29))) "configure flycheck using pkg-config" single ((:commit . "c4e4028f6621187365b7362566ac2786206765a1") (:authors ("Wilfred Hughes" . "me@wilfred.me.uk")) (:maintainer "Wilfred Hughes" . "me@wilfred.me.uk") (:keywords "flycheck"))]) (flycheck-plantuml . [(20171018 111) ((flycheck (0 24)) (emacs (24 4)) (plantuml-mode (1 2 2))) "Integrate plantuml with flycheck" single ((:commit . "183be89e1dbba0b38237dd198dff600e0790309d") (:authors ("Alex Murray" . "murray.alex@gmail.com")) (:maintainer "Alex Murray" . "murray.alex@gmail.com") (:url . "https://github.com/alexmurray/flycheck-plantuml"))]) (flycheck-pony . [(20210118 1327) ((flycheck (0 25 1))) "Pony support in Flycheck" single ((:commit . "22787cf8223ca9ec309e30a42c20a8e706d8bfbe") (:keywords "tools" "convenience") (:url . "https://github.com/seantallen/flycheck-pony"))]) @@ -1733,7 +1740,7 @@ (flycheck-ycmd . [(20181016 618) ((emacs (24)) (dash (2 13 0)) (flycheck (0 22)) (ycmd (1 2)) (let-alist (1 0 5))) "flycheck integration for ycmd" single ((:commit . "ef87d020d3314efbac2e8925c115d0ac5c128c2a") (:authors ("Austin Bingham" . "austin.bingham@gmail.com")) (:maintainer "Austin Bingham" . "austin.bingham@gmail.com") (:url . "https://github.com/abingham/emacs-ycmd"))]) (flymake-aspell . [(20230107 748) ((emacs (26 1))) "Aspell checker for flymake" single ((:commit . "1c7fb66f6cb325ee1123094263a8def9bc071768") (:authors ("Leo Gaskin" . "leo.gaskin@le0.gs")) (:maintainer "Leo Gaskin" . "leo.gaskin@le0.gs") (:keywords "wp" "flymake" "spell" "aspell") (:url . "https://github.com/leotaku/flycheck-aspell"))]) (flymake-coffee . [(20170723 146) ((flymake-easy (0 1))) "A flymake handler for coffee script" single ((:commit . "dee295acf30820ed15fe0de17137d50bc27fc80c") (:authors ("Steve Purcell" . "steve@sanityinc.com")) (:maintainer "Steve Purcell" . "steve@sanityinc.com") (:url . "https://github.com/purcell/flymake-coffee"))]) - (flymake-collection . [(20221231 1240) ((emacs (28 1)) (let-alist (1 0)) (flymake (1 2 1))) "Collection of checkers for flymake, bringing flymake to the level of flycheck" tar ((:commit . "a030c282e95d709bbb67a7fc115dde1f0d500ae9") (:authors ("Mohsin Kaleem" . "mohkale@kisara.moe")) (:maintainer "Mohsin Kaleem" . "mohkale@kisara.moe") (:keywords "language" "tools") (:url . "https://github.com/mohkale/flymake-collection"))]) + (flymake-collection . [(20230311 1746) ((emacs (28 1)) (let-alist (1 0)) (flymake (1 2 1))) "Collection of checkers for flymake, bringing flymake to the level of flycheck" tar ((:commit . "0dc266c443bb9553f529a848c20a2b4c00cec649") (:authors ("Mohsin Kaleem" . "mohkale@kisara.moe")) (:maintainer "Mohsin Kaleem" . "mohkale@kisara.moe") (:keywords "language" "tools") (:url . "https://github.com/mohkale/flymake-collection"))]) (flymake-cspell . [(20230208 2155) ((emacs (26 1))) "A Flymake backend for CSpell" single ((:commit . "c68bf7eef99ddb2fbd780f175e869df2db5d768f") (:authors ("Fritz Grabo" . "hello@fritzgrabo.com")) (:maintainer "Fritz Grabo" . "hello@fritzgrabo.com") (:keywords "wp") (:url . "https://github.com/fritzgrabo/flymake-cspell"))]) (flymake-css . [(20170723 146) ((flymake-easy (0 1))) "Flymake support for css using csslint" single ((:commit . "de090163ba289910ceeb61b13368ce42d0f2dfd8") (:authors ("Steve Purcell" . "steve@sanityinc.com")) (:maintainer "Steve Purcell" . "steve@sanityinc.com") (:url . "https://github.com/purcell/flymake-css"))]) (flymake-cursor . [(20220506 1458) ((flymake (0 3))) "Show flymake messages in the minibuffer after delay" single ((:commit . "95806594cacddbbc0c3aa2351a6a7cf28e73a8bf") (:authors ("Unknown Original Author") ("Dino Chiesa" . "dpchiesa@hotmail.com") ("Sam Graham ")) (:maintainer "Sam Graham ") (:keywords "languages" "mode" "flymake") (:url . "https://github.com/flymake/emacs-flymake-cursor"))]) @@ -1741,7 +1748,7 @@ (flymake-easy . [(20141022 1828) nil "Helpers for easily building flymake checkers" single ((:commit . "2a24f260cdc3b9c8f9263b653a475d90efa1d392") (:authors ("Steve Purcell" . "steve@sanityinc.com")) (:maintainer "Steve Purcell" . "steve@sanityinc.com") (:keywords "convenience" "internal") (:url . "https://github.com/purcell/flymake-easy"))]) (flymake-elisp-config . [(20221110 1626) ((emacs (28 1))) "Setup load-path for flymake on Emacs Lisp mode" single ((:commit . "e946d9a761a8427dfdd0ae634bcfce4d56111947") (:authors ("ROCKTAKEY" . "rocktakey@gmail.com")) (:maintainer "ROCKTAKEY" . "rocktakey@gmail.com") (:keywords "lisp") (:url . "https://github.com/ROCKTAKEY/flymake-elisp-config"))]) (flymake-elixir . [(20130810 1417) nil "A flymake handler for elixir-mode .ex files." single ((:commit . "3810566cffe35d04cc3f01e27fe397d68d52f802") (:authors ("Sylvain Benner" . "syl20bnr@gmail.com")) (:maintainer "Sylvain Benner" . "syl20bnr@gmail.com"))]) - (flymake-eslint . [(20221002 2307) ((emacs (26 1))) "A Flymake backend for Javascript using eslint" single ((:commit . "efbf9e1fcc6ba4959c4ad0435742c96099f4f96f") (:authors ("Dan Orzechowski")) (:maintainer "Dan Orzechowski") (:keywords "languages" "tools") (:url . "https://github.com/orzechowskid/flymake-eslint"))]) + (flymake-eslint . [(20230301 1441) ((emacs (26 1))) "A Flymake backend for Javascript using eslint" single ((:commit . "82b1345c699172b6092e13be2c4cc10551d88b90") (:authors ("Dan Orzechowski")) (:maintainer "Dan Orzechowski") (:keywords "languages" "tools") (:url . "https://github.com/orzechowskid/flymake-eslint"))]) (flymake-flycheck . [(20220313 924) ((flycheck (31)) (emacs (26 1))) "Use flycheck checkers as flymake backends" single ((:commit . "850a3f2f6908db5d4a3739e385b2c9fb3ad488f9") (:authors ("Steve Purcell" . "steve@sanityinc.com")) (:maintainer "Steve Purcell" . "steve@sanityinc.com") (:keywords "convenience" "languages" "tools") (:url . "https://github.com/purcell/flymake-flycheck"))]) (flymake-gjshint . [(20130327 1232) nil "A flymake handler for javascript using both jshint and gjslint" single ((:commit . "71495ee5303de18293decd57ab9f9abdbaabfa05") (:authors ("Yasuyuki Oka" . "yasuyk@gmail.com")) (:maintainer "Yasuyuki Oka" . "yasuyk@gmail.com") (:keywords "flymake" "javascript" "jshint" "gjslint"))]) (flymake-go . [(20150714 733) nil "A flymake handler for go-mode files" single ((:commit . "ae83761aa908c1a50ff34af04f00dcc46bca2ce9") (:authors ("Michael Fellinger" . "michael@iron.io") ("Robert Zaremba" . "robert.marek.zaremba@wp.eu")) (:maintainer "Michael Fellinger" . "michael@iron.io") (:keywords "go" "flymake") (:url . "https://github.com/robert-zaremba/flymake-go"))]) @@ -1768,7 +1775,7 @@ (flymake-pest . [(20200710 2327) ((emacs (26 3)) (pest-mode (0 1))) "A flymake handler for Pest files" single ((:commit . "43447a2c70f98edd1139005e32f437d3f142442b") (:authors ("ksqsf" . "i@ksqsf.moe") ("Naoya Yamashita" . "conao3@gmail.com")) (:maintainer "ksqsf" . "i@ksqsf.moe") (:keywords "languages" "flymake") (:url . "https://github.com/ksqsf/pest-mode"))]) (flymake-php . [(20170723 146) ((flymake-easy (0 1))) "A flymake handler for php-mode files" single ((:commit . "c045d01e002ba5e09b05f40e25bf5068d02126bc") (:authors ("Steve Purcell" . "steve@sanityinc.com")) (:maintainer "Steve Purcell" . "steve@sanityinc.com") (:url . "https://github.com/purcell/flymake-php"))]) (flymake-phpcs . [(20210213 732) ((flymake-easy (0 9))) "making flymake work with PHP CodeSniffer" single ((:commit . "f947ba3066c1fa903d2ec69d67bf84413f51eb3f") (:authors ("Akiha Senda")) (:maintainer "Akiha Senda") (:keywords "flymake" "phpcs" "php") (:url . "https://github.com/senda-akiha/flymake-phpcs/"))]) - (flymake-phpstan . [(20210714 1805) ((emacs (26 1)) (phpstan (0 5 0))) "Flymake backend for PHP using PHPStan" single ((:commit . "0869b152f82a76138daa53e953285936b9d558bd") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "tools" "php") (:url . "https://github.com/emacs-php/phpstan.el"))]) + (flymake-phpstan . [(20230404 1351) ((emacs (26 1)) (phpstan (0 5 0))) "Flymake backend for PHP using PHPStan" single ((:commit . "6dc8f1df29f22f0b0ef839c66822d48e2c7b1848") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "tools" "php") (:url . "https://github.com/emacs-php/phpstan.el"))]) (flymake-puppet . [(20170801 554) ((flymake-easy (0 9))) "Flymake handler using puppet-lint" single ((:commit . "9579e5c736cb890195464fabf51df113313de88d") (:authors ("Ben Prew")) (:maintainer "Ben Prew") (:url . "https://github.com/benprew/flymake-puppet"))]) (flymake-python-pyflakes . [(20170723 146) ((flymake-easy (0 8))) "A flymake handler for python-mode files using pyflakes (or flake8)" single ((:commit . "1d65c26bf65a5dcbd29fcd967e2feb90e1e7a33d") (:authors ("Steve Purcell" . "steve@sanityinc.com")) (:maintainer "Steve Purcell" . "steve@sanityinc.com") (:url . "https://github.com/purcell/flymake-python-pyflakes"))]) (flymake-quickdef . [(20200308 2342) ((emacs (26 1))) "Quickly define a new Flymake backend" single ((:commit . "150c5839768a3d32f988f9dc08052978a68f2ad7") (:authors ("Karl Otness")) (:maintainer "Karl Otness") (:keywords "languages" "tools" "convenience" "lisp") (:url . "https://github.com/karlotness/flymake-quickdef"))]) @@ -1783,9 +1790,9 @@ (flymake-sqlfluff . [(20230129 2035) ((emacs (27 1))) "A flymake plugin for SQL files using sqlfluff" single ((:commit . "f7921a5b762eb0675b8fca7cfb00273a76eaee5b") (:authors ("Erick Navarro" . "erick@navarro.io")) (:maintainer "Erick Navarro" . "erick@navarro.io") (:url . "https://github.com/erickgnavar/flymake-sqlfluff"))]) (flymake-swi-prolog . [(20220404 950) ((emacs (26 1))) "A Flymake backend for SWI-Prolog" single ((:commit . "ae0e4b706a40b71c007ed6cb0ec5425d49bea4c3") (:authors ("Eshel Yaron")) (:maintainer "Eshel Yaron") (:keywords "languages") (:url . "https://git.sr.ht/~eshel/flymake-swi-prolog"))]) (flymake-vala . [(20150326 531) ((flymake-easy (0 1))) "A flymake handler for vala-mode files" single ((:commit . "c3674f461fc84fb0300cd3a562fb903a59782745") (:authors ("Daniel Lawrence" . "dannyla@linux.com")) (:maintainer "Daniel Lawrence" . "dannyla@linux.com") (:keywords "convenience" "vala") (:url . "https://github.com/daniellawrence/flymake-vala"))]) - (flymake-vnu . [(20181128 216) ((emacs (26 1))) "Flymake extension for the v.Nu HTML validator." single ((:commit . "7c4ab9d12611756ad5a80d866890b2f9b73fb611") (:maintainer "Stefan Kuznetsov" . "skuznetsov@posteo.net") (:keywords "languages") (:url . "https://github.com/theneosloth/flymake-vnu"))]) + (flymake-vnu . [(20230310 440) ((emacs (26 1))) "Flymake extension for the v.Nu HTML validator." single ((:commit . "e9c6038f69ad1523e603026155d9acd5fc3d5aac") (:maintainer "Stefan Kuznetsov" . "skuznetsov@posteo.net") (:keywords "languages") (:url . "https://github.com/theneosloth/flymake-vnu"))]) (flymake-yaml . [(20130423 1548) ((flymake-easy (0 1))) "A flymake handler for YAML" single ((:commit . "0dd11eed29fe4054ff5b4e06e2c39b4d925d6aae") (:authors ("Yasuyuki Oka" . "yasuyk@gmail.com")) (:maintainer "Yasuyuki Oka" . "yasuyk@gmail.com") (:keywords "yaml") (:url . "https://github.com/yasuyk/flymake-yaml"))]) - (flymake-yamllint . [(20220531 913) ((emacs (26 1))) "YAML linter with yamllint" single ((:commit . "f269e6614993f3c56d545e7d7b225ca2ba1da342") (:authors ("Martin Kjær Jørgensen" . "mkj@gotu.dk")) (:maintainer "Martin Kjær Jørgensen" . "mkj@gotu.dk") (:url . "https://github.com/shaohme/flymake-yamllint"))]) + (flymake-yamllint . [(20230226 1024) ((emacs (26 1))) "YAML linter with yamllint" single ((:commit . "020d2a33568c8069801db9dd6992b8961a58de8d") (:authors ("Martin Kjær Jørgensen" . "mkj@gotu.dk")) (:maintainer "Martin Kjær Jørgensen" . "mkj@gotu.dk") (:url . "https://github.com/shaohme/flymake-yamllint"))]) (flymd . [(20160617 1214) ((cl-lib (0 5))) "On the fly markdown preview" tar ((:commit . "84d5a68bcfed4a295952c33ffcd11e880978d9d7") (:authors ("Mola-T" . "Mola@molamola.xyz")) (:maintainer "Mola-T" . "Mola@molamola.xyz") (:keywords "markdown" "convenience") (:url . "https://github.com/mola-T/flymd"))]) (flyparens . [(20140723 1846) nil "Check for unbalanced parens on the fly" tar ((:commit . "af9b8cfd647d0e5f97684d613dc2eea7cfc19398") (:authors ("Jisang Yoo")) (:maintainer "Jisang Yoo") (:keywords "faces" "convenience" "lisp" "matching" "parentheses" "parens"))]) (flyspell-correct . [(20220520 630) ((emacs (24))) "Correcting words with flyspell via custom interface" tar ((:commit . "7d7b6b01188bd28e20a13736ac9f36c3367bd16e") (:authors ("Boris Buliga" . "boris@d12frosted.io")) (:maintainer "Boris Buliga" . "boris@d12frosted.io") (:url . "https://github.com/d12frosted/flyspell-correct"))]) @@ -1810,14 +1817,14 @@ (fontawesome . [(20170305 1356) ((emacs (24 4))) "fontawesome utility" tar ((:commit . "a743f80bfd53767ca9ee32da34c5ca032172a480") (:authors ("Syohei YOSHIDA" . "syohex@gmail.com")) (:maintainer "Syohei YOSHIDA" . "syohex@gmail.com") (:url . "https://github.com/syohex/emacs-fontawesome"))]) (fontify-face . [(20210503 1956) ((emacs (24))) "Fontify symbols representing faces with that face." single ((:commit . "d1386c88ccc77ccfb40b888ff90d6181325d14f8") (:authors ("Matúš Goljer" . "matus.goljer@gmail.com")) (:maintainer "Matúš Goljer" . "matus.goljer@gmail.com") (:keywords "faces") (:url . "https://github.com/Fuco1/fontify-face"))]) (fontsloth . [(20211118 2018) ((f (0 20 0)) (logito (0 1)) (pcache (0 5)) (stream (2 2 5)) (emacs (28 0))) "Elisp otf/ttf font loader/renderer" tar ((:commit . "615dd846cb80701cda4b34bc1dfb43bf695318b6") (:authors ("Jo Gay" . "jo.gay@mailfence.com")) (:maintainer "Jo Gay" . "jo.gay@mailfence.com") (:keywords "data" "font" "rasterization" "ttf" "otf") (:url . "https://github.com/jollm/fontsloth"))]) - (for . [(20221218 1023) ((emacs (28 1))) "Iteration and sequence" tar ((:commit . "3556d3693288a552a0962ee01ad7ec71caeb0dc8") (:authors ("Wing Hei Chan" . "whmunkchan@outlook.com")) (:maintainer "Wing Hei Chan" . "whmunkchan@outlook.com") (:keywords "extensions") (:url . "https://github.com/usaoc/elisp-for"))]) + (for . [(20230330 2007) ((emacs (28 1))) "Iteration and sequence" tar ((:commit . "db14b5da78feecd5eb139eaadb2accb94eabc347") (:authors ("Wing Hei Chan" . "whmunkchan@outlook.com")) (:maintainer "Wing Hei Chan" . "whmunkchan@outlook.com") (:keywords "extensions") (:url . "https://github.com/usaoc/elisp-for"))]) (forecast . [(20191004 1850) ((emacs (24 4))) "Weather forecasts" single ((:commit . "5f3e67448cc98fe2875115163849acae4d9e8526") (:authors ("Göktuğ Kayaalp" . "self@gkayaalp.com")) (:maintainer "Göktuğ Kayaalp" . "self@gkayaalp.com") (:keywords "weather" "forecast") (:url . "https://dev.gkayaalp.com/elisp/index.html#forecast-el"))]) (foreign-regexp . [(20200325 50) nil "search and replace by foreign regexp." tar ((:commit . "e2dd47f2160cadc194eb156e7c76c3c869e6706e") (:authors ("K-talo Miyazaki ")) (:maintainer "K-talo Miyazaki ") (:keywords "convenience" "emulations" "matching" "tools" "unix" "wp"))]) (foreman-mode . [(20170725 1422) ((s (1 9 0)) (dash (2 10 0)) (dash-functional (1 2 0)) (f (0 17 2)) (emacs (24))) "View and manage Procfile-based applications" single ((:commit . "22b3bb13134b617870ed1e888af739f4818be929") (:authors ("ZHOU Feng" . "zf.pascal@gmail.com")) (:maintainer "ZHOU Feng" . "zf.pascal@gmail.com") (:keywords "foreman") (:url . "http://github.com/zweifisch/foreman-mode"))]) (forest-blue-theme . [(20160627 842) ((emacs (24))) "Emacs theme with a dark background." single ((:commit . "58096ce1a25615d2bae806c3775bae3e2775019d") (:authors ("olkinn")) (:maintainer "olkinn"))]) - (forge . [(20230220 1945) ((emacs (25 1)) (compat (29 1 3 4)) (closql (20230220)) (dash (2 19 1)) (emacsql (20230220)) (ghub (20220621)) (let-alist (1 0 6)) (magit (20220621)) (markdown-mode (2 4)) (transient (0 3 6)) (yaml (0 3 5))) "Access Git forges from Magit." tar ((:commit . "3164739dc70ee5ecf05d87dba9dc803d62a89adf") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "git" "tools" "vc") (:url . "https://github.com/magit/forge"))]) + (forge . [(20230326 2058) ((emacs (25 1)) (compat (29 1 3 4)) (closql (20230220)) (dash (2 19 1)) (emacsql (20230220)) (ghub (20220621)) (let-alist (1 0 6)) (magit (20230319)) (markdown-mode (2 4)) (transient (0 3 6)) (yaml (0 3 5))) "Access Git forges from Magit." tar ((:commit . "422881e552afd9df15e591dbf52aa36e2d481758") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "git" "tools" "vc") (:url . "https://github.com/magit/forge"))]) (form-feed . [(20210508 1627) ((emacs (24 1))) "Display ^L glyphs as horizontal lines" single ((:commit . "ac1f0ef30a11979f5dfe12d8c05a666739e486ff") (:authors ("Vasilij Schneidermann" . "mail@vasilij.de")) (:maintainer "Vasilij Schneidermann" . "mail@vasilij.de") (:keywords "faces") (:url . "https://depp.brause.cc/form-feed"))]) - (format-all . [(20221210 1608) ((emacs (24 4)) (inheritenv (0 1)) (language-id (0 19))) "Auto-format C, C++, JS, Python, Ruby and 50 other languages" single ((:commit . "c156ffe5f3c979ab89fd941658e840801078d091") (:authors ("Lassi Kortela" . "lassi@lassi.io")) (:maintainer "Lassi Kortela" . "lassi@lassi.io") (:keywords "languages" "util") (:url . "https://github.com/lassik/emacs-format-all-the-code"))]) + (format-all . [(20230306 534) ((emacs (24 4)) (inheritenv (0 1)) (language-id (0 19))) "Auto-format C, C++, JS, Python, Ruby and 50 other languages" single ((:commit . "91ea3c16f594294b8064e61c4b14c5264d88e24d") (:authors ("Lassi Kortela" . "lassi@lassi.io")) (:maintainer "Lassi Kortela" . "lassi@lassi.io") (:keywords "languages" "util") (:url . "https://github.com/lassik/emacs-format-all-the-code"))]) (format-sql . [(20150422 1333) nil "Use format-sql to make your SQL readable in directly Emacs." single ((:commit . "97f475c245cd6c81a72a265678e2087cee66ac7b") (:authors ("Friedrich Paetzke" . "paetzke@fastmail.fm")) (:maintainer "Friedrich Paetzke" . "paetzke@fastmail.fm") (:url . "https://github.com/paetzke/format-sql.el"))]) (format-table . [(20181223 1616) ((emacs (25)) (dash (2 14 1))) "Parse and reformat tabular data." single ((:commit . "dfcae3a867e574577fc09a43b045889ff155b58f") (:authors ("Jason Duncan" . "jasond496@msn.com")) (:maintainer "Jason Duncan" . "jasond496@msn.com") (:keywords "data") (:url . "https://github.com/functionreturnfunction/format-table"))]) (forth-mode . [(20220629 519) nil "Programming language mode for Forth" tar ((:commit . "162b79f005a64b1f91e60b8f4c022d1d90cd3d95") (:authors ("Lars Brinkhoff" . "lars@nocrew.org")) (:maintainer "Lars Brinkhoff" . "lars@nocrew.org") (:keywords "languages" "forth") (:url . "http://github.com/larsbrinkhoff/forth-mode"))]) @@ -1865,7 +1872,7 @@ (fwb-cmds . [(20230213 1143) ((emacs (25 1)) (compat (29 1 3 4))) "misc frame, window and buffer commands" single ((:commit . "1b375c6890de61eaccc97c92f2b46de6f9205417") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "convenience") (:url . "https://github.com/tarsius/fwb-cmds"))]) (fxrd-mode . [(20170728 1801) ((s (1 2))) "Major mode for editing fixed field width files" tar ((:commit . "795b969346982b75e24b5c8619b46197982fbb4d") (:authors ("Marc Sherry" . "msherry@gmail.com")) (:maintainer "Marc Sherry" . "msherry@gmail.com") (:keywords "convenience") (:url . "https://github.com/msherry/fxrd-mode"))]) (fyure . [(20130216 1314) nil "An interface to fix Japanese hyoki-yure" tar ((:commit . "b6977f1eb148e8b63259f7233b55bb050e44d9b8") (:authors ("Masafumi Oyamada" . "stillpedant@gmail.com")) (:maintainer "Masafumi Oyamada" . "stillpedant@gmail.com") (:keywords "languages"))]) - (fzf . [(20230114 403) ((emacs (24 4))) "A front-end for fzf." single ((:commit . "1d80e76df0899e26196aea150c29fba95fc73ed6") (:authors ("Bailey Ling")) (:maintainer "Bailey Ling") (:keywords "fzf" "fuzzy" "search") (:url . "https://github.com/bling/fzf.el"))]) + (fzf . [(20230403 1304) ((emacs (24 4))) "A front-end for fzf." single ((:commit . "3a55b983921c620fb5a2cc811f42aa4daaad8266") (:authors ("Bailey Ling")) (:maintainer "Bailey Ling") (:keywords "fzf" "fuzzy" "search") (:url . "https://github.com/bling/fzf.el"))]) (gameoflife . [(20200614 1814) nil "Screensaver running Conway's Game of Life" single ((:commit . "2483f3d98dbcf7f1633f551cc3691f5659b4b942") (:authors ("Anders Lindgren")) (:maintainer "Anders Lindgren") (:keywords "games") (:url . "https://github.com/Lindydancer/gameoflife"))]) (gams-ac . [(20180423 926) ((emacs (24)) (auto-complete (1 0)) (gams-mode (4 0))) "auto-complete source file for GAMS mode" single ((:commit . "66d04ff36033f54205c19bc1d893e926d4dbf02e") (:authors ("Shiro Takeda")) (:maintainer "Shiro Takeda") (:keywords "languages" "tools" "gams-mode" "auto-complete") (:url . "https://github.com/ShiroTakeda/gams-ac"))]) (gams-mode . [(20230214 1359) ((emacs (24 3))) "Major mode for General Algebraic Modeling System (GAMS)" tar ((:commit . "a50a290e5559e9f099e2bbbcecacac9e484ef4d9") (:authors ("Shiro Takeda")) (:maintainer "Shiro Takeda") (:keywords "languages" "tools" "gams") (:url . "http://shirotakeda.org/en/gams/gams-mode/"))]) @@ -1878,8 +1885,8 @@ (geben . [(20220827 105) ((emacs (24 3)) (cl-lib (0 5))) "DBGp protocol frontend, a script debugger" tar ((:commit . "8df1ed2c8ff13b0ca4ef241c95c46f60a5a4fe3c") (:authors ("Matthew Carter" . "m@ahungry.com")) (:maintainer "Matthew Carter" . "m@ahungry.com") (:keywords "c" "comm" "tools") (:url . "https://github.com/ahungry/geben"))]) (geben-helm-projectile . [(20170524 334) ((emacs (24)) (geben (0 26)) (helm-projectile (0 13 0))) "Integrate helm-projectile with geben" single ((:commit . "31ce0faca5dcc71924884f03fd5a7a25d00ccd9b") (:authors ("Matthew Carter" . "m@ahungry.com")) (:maintainer "Matthew Carter" . "m@ahungry.com") (:keywords "ahungry" "emacs" "geben" "helm" "projectile" "debug") (:url . "https://github.com/ahungry/geben-helm-projectile"))]) (geeknote . [(20220213 612) ((emacs (24))) "Use Evernote in Emacs through geeknote" single ((:commit . "ce2738aebeeda35f9d31027e9b7bad0813b975c3") (:authors ("Evan Dale Aromin")) (:maintainer "Evan Dale Aromin") (:keywords "evernote" "geeknote" "note" "emacs-evernote" "evernote-mode") (:url . "http://github.com/avendael/emacs-geeknote"))]) - (geiser . [(20230120 1738) ((emacs (25 1)) (project (0 8 1))) "GNU Emacs and Scheme talk to each other" tar ((:commit . "e54d5e6dc659c252d10c4280f4c4d78d38623df5") (:authors ("Jose Antonio Ortega Ruiz" . "jao@gnu.org")) (:maintainer "Jose Antonio Ortega Ruiz" . "jao@gnu.org") (:keywords "languages" "scheme" "geiser") (:url . "https://gitlab.com/emacs-geiser/"))]) - (geiser-chez . [(20221027 137) ((emacs (26 1)) (geiser (0 19))) "Chez and Geiser talk to each other" tar ((:commit . "d64687c46dcd12aa3225a0fa38269f79a248dfb0") (:authors ("Peter" . "craven@gmx.net")) (:maintainer "Jose A Ortega Ruiz" . "jao@gnu.org") (:keywords "languages" "chez" "scheme" "geiser") (:url . "https://gitlab.com/emacs-geiser/chez"))]) + (geiser . [(20230305 1604) ((emacs (25 1)) (project (0 8 1))) "GNU Emacs and Scheme talk to each other" tar ((:commit . "e6976b5f95f4930c20bd4e775d8b94f9dfc0e6f2") (:authors ("Jose Antonio Ortega Ruiz" . "jao@gnu.org")) (:maintainer "Jose Antonio Ortega Ruiz" . "jao@gnu.org") (:keywords "languages" "scheme" "geiser") (:url . "https://gitlab.com/emacs-geiser/"))]) + (geiser-chez . [(20230228 2253) ((emacs (26 1)) (geiser (0 19))) "Chez and Geiser talk to each other" tar ((:commit . "04ab4387fed68659f21377dbe74513edac2fd134") (:authors ("Peter" . "craven@gmx.net")) (:maintainer "Jose A Ortega Ruiz" . "jao@gnu.org") (:keywords "languages" "chez" "scheme" "geiser") (:url . "https://gitlab.com/emacs-geiser/chez"))]) (geiser-chibi . [(20211204 1938) ((emacs (24 4)) (geiser (0 18))) "Chibi Scheme's implementation of the geiser protocols" tar ((:commit . "5a6a5a580ea45cd4974df21629a8d50cbe3d6e99") (:authors ("Peter" . "craven@gmx.net")) (:maintainer "Jose A Ortega Ruiz" . "jao@gnu.org") (:keywords "languages" "chibi" "scheme" "geiser") (:url . "https://gitlab.com/emacs-geiser/chibi"))]) (geiser-chicken . [(20220717 1130) ((emacs (24 4)) (geiser (0 19))) "Chicken's implementation of the geiser protocols" tar ((:commit . "a480598b5908c95bc8d3178a48f13e9072a9235b") (:authors ("Daniel Leslie")) (:maintainer "Daniel Leslie") (:keywords "languages" "chicken" "scheme" "geiser") (:url . "https://gitlab.com/emacs-geiser/chicken"))]) (geiser-gambit . [(20220208 1356) ((emacs (26 1)) (geiser (0 18))) "Gambit's implementation of the geiser protocols" tar ((:commit . "381d74ca5059b44fe3d8b5daf42214019c6d1a88") (:authors ("Daniel Leslie")) (:maintainer "Jose A Ortega Ruiz" . "jao@gnu.org") (:keywords "languages" "gambit" "scheme" "geiser") (:url . "https://gitlab.com/emacs-geiser/gambit"))]) @@ -1891,7 +1898,7 @@ (geiser-stklos . [(20211117 2114) ((emacs (24 4)) (geiser (0 16))) "STklos Scheme implementation of the geiser protocols" single ((:commit . "9db60a7e751c97e30dd528e2a96ff19575b618d2") (:authors ("Jeronimo Pellegrini" . "j_p@aleph0.info")) (:maintainer "Jeronimo Pellegrini" . "j_p@aleph0.info") (:keywords "languages" "stklos" "scheme" "geiser") (:url . "https://gitlab.com/emacs-geiser/stklos"))]) (gemini-mode . [(20221127 1619) ((emacs (24 4))) "A simple highlighting package for text/gemini" single ((:commit . "a7dd7c6ea4e036d0d5ecc4a5d284874c400f10ba") (:authors ("Jason McBrayer , tastytea , Étienne Deparis" . "etienne@depar.is")) (:maintainer "Jason McBrayer , tastytea , Étienne Deparis" . "etienne@depar.is") (:keywords "languages") (:url . "https://git.carcosa.net/jmcbray/gemini.el"))]) (gemini-write . [(20211114 1032) ((emacs (26)) (elpher (2 8 0)) (gemini-mode (1 0 0))) "Elpher for Titan" single ((:commit . "2a7d07d0ce4c5b8750f3ff1182ad94ee616734c8") (:authors ("Alex Schroeder" . "alex@gnu.org")) (:maintainer "Alex Schroeder" . "alex@gnu.org") (:keywords "comm" "gemini") (:url . "https://alexschroeder.ch/cgit/gemini-write"))]) - (general . [(20211203 120) ((emacs (24 4)) (cl-lib (0 5))) "Convenience wrappers for keybindings." tar ((:commit . "9651024e7f40a8ac5c3f31f8675d3ebe2b667344") (:authors ("Fox Kiester" . "noct@posteo.net")) (:maintainer "Fox Kiester" . "noct@posteo.net") (:keywords "vim" "evil" "leader" "keybindings" "keys") (:url . "https://github.com/noctuid/general.el"))]) + (general . [(20230311 1229) ((emacs (24 4)) (cl-lib (0 5))) "Convenience wrappers for keybindings." tar ((:commit . "7ce8db297e3de258ec43802269438ac7f1918707") (:authors ("Fox Kiester" . "noct@posteo.net")) (:maintainer "Fox Kiester" . "noct@posteo.net") (:keywords "vim" "evil" "leader" "keybindings" "keys") (:url . "https://github.com/noctuid/general.el"))]) (genrnc . [(20140612 1237) ((deferred (0 3 1)) (concurrent (0 3)) (log4e (0 2 0)) (yaxception (0 1))) "generate RELAX NG Compact Schema from RELAX NG Schema, XML Schema and DTD." tar ((:commit . "da75b1966a73ad215ec2ced4522c25f4d0bf1f9a") (:authors ("Hiroaki Otsu" . "ootsuhiroaki@gmail.com")) (:maintainer "Hiroaki Otsu" . "ootsuhiroaki@gmail.com") (:keywords "xml") (:url . "https://github.com/aki2o/emacs-genrnc"))]) (geoip . [(20200310 911) ((emacs (25 1))) "Find out where an IP address is located via GeoIP2" single ((:commit . "b4952890993642c7055f4bbbf05b0384740f8f51") (:authors ("Xu Chunyang")) (:maintainer "Xu Chunyang") (:keywords "tools") (:url . "https://github.com/xuchunyang/geoip.el"))]) (geolocation . [(20200317 1559) ((request-deferred (0 3 2)) (deferred (0 5 1)) (emacs (25 1))) "Get your location on Earth" single ((:commit . "08e3569024659f6f04cb269ad213d144fd8e2a95") (:authors ("Neil Okamoto" . "neil.okamoto+melpa@gmail.com")) (:maintainer "Neil Okamoto" . "neil.okamoto+melpa@gmail.com") (:keywords "hardware") (:url . "https://github.com/gonewest818/geolocation.el"))]) @@ -1910,7 +1917,7 @@ (gherkin-mode . [(20171224 1353) nil "An emacs major mode for editing gherkin files." single ((:commit . "0313492e7da152f0aa73ddf96c0287ded8f51253") (:authors ("Craig Andera")) (:maintainer "Craig Andera") (:keywords "languages"))]) (ghost-blog . [(20171023 742) ((markdown-mode (1 0))) "A package to manage Ghost blog" single ((:commit . "71b358643cc9a2db1bf752281ff94aba9b59e4cc") (:authors ("Javier Aguirre" . "hello@javaguirre.net")) (:maintainer "Javier Aguirre" . "hello@javaguirre.net") (:keywords "ghost" "blog") (:url . "https://github.com/javaguirre/ghost-blog"))]) (ghq . [(20210504 902) nil "Ghq interface for emacs" single ((:commit . "582bd6daa505d04c7cc06d6c82ed8aee0624bfbe") (:authors ("Roman Coedo" . "romancoedo@gmail.com")) (:maintainer "Roman Coedo" . "romancoedo@gmail.com") (:keywords "ghq"))]) - (ghub . [(20230212 2209) ((emacs (25 1)) (compat (29 1 3 4)) (let-alist (1 0 6)) (treepy (0 1 1))) "Client libraries for Git forge APIs." tar ((:commit . "47b7dc9bb299d50647cd24efebaf41dbc07d9e90") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "tools") (:url . "https://github.com/magit/ghub"))]) + (ghub . [(20230301 1402) ((emacs (25 1)) (compat (29 1 3 4)) (let-alist (1 0 6)) (treepy (0 1 1))) "Client libraries for Git forge APIs." tar ((:commit . "6a5de97649ff3eca9aa20b79f3526b4b3ab86b13") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "tools") (:url . "https://github.com/magit/ghub"))]) (ghub+ . [(20191229 1748) ((emacs (25)) (ghub (2 0)) (apiwrap (0 5))) "a thick GitHub API client built on ghub" single ((:commit . "b1adef2402d7599911d4dd447a987a0cea04e6fe") (:authors ("Sean Allred" . "code@seanallred.com")) (:maintainer "Sean Allred" . "code@seanallred.com") (:keywords "extensions" "multimedia" "tools") (:url . "https://github.com/vermiculus/ghub-plus"))]) (gif-screencast . [(20220714 1300) ((emacs (25 1))) "One-frame-per-action GIF recording" single ((:commit . "adec408e6adab2e8e057fe0ad828749f473bfb83") (:authors ("Pierre Neidhardt" . "mail@ambrevar.xyz")) (:maintainer "Pierre Neidhardt" . "mail@ambrevar.xyz") (:keywords "multimedia" "screencast") (:url . "https://gitlab.com/ambrevar/emacs-gif-screencast"))]) (gift-mode . [(20210528 1459) nil "major mode for editing GIFT format quizzes" single ((:commit . "c93354e8fe1173b22f398f17b127875807f15b87") (:authors ("Christophe Rhodes" . "christophe@rhodes.io")) (:maintainer "Christophe Rhodes" . "christophe@rhodes.io") (:url . "https://github.com/csrhodes/gift-mode"))]) @@ -1925,8 +1932,8 @@ (git-backup-ivy . [(20221015 431) ((ivy (0 12 0)) (git-backup (0 0 1)) (emacs (25 1))) "An ivy interface to git-backup" single ((:commit . "e54a3c4b95023c58664a2c59b95a95a07759a1f8") (:authors ("Sebastian Wålinder" . "s.walinder@gmail.com")) (:maintainer "Sebastian Wålinder" . "s.walinder@gmail.com") (:keywords "backup" "convenience" "files" "tools" "vc") (:url . "https://github.com/walseb/git-backup-ivy"))]) (git-blamed . [(20161028 1926) nil "Minor mode for incremental blame for Git" single ((:commit . "cef196abf398e2dd11f775d1e6cd8690567408aa") (:keywords "git" "version control" "release management"))]) (git-command . [(20191028 333) ((term-run (0 1 4)) (with-editor (2 3 1))) "A Git Command-Line interface" single ((:commit . "a773d40da39dfb1c6ecf2b0758aa370ddea8f06d") (:authors ("10sr <8slashes+el [at] gmail [dot] com>")) (:maintainer "10sr <8slashes+el [at] gmail [dot] com>") (:keywords "utility" "git") (:url . "https://github.com/10sr/git-command-el"))]) - (git-commit . [(20230220 1901) ((emacs (25 1)) (compat (29 1 3 4)) (transient (20230201)) (with-editor (20230118))) "Edit Git commit messages." tar ((:commit . "76fe46c098498deab54b6c5b11731e970040a52b") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li") ("Sebastian Wiesner" . "lunaryorn@gmail.com") ("Florian Ragwitz" . "rafl@debian.org") ("Marius Vollmer" . "marius.vollmer@gmail.com")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "git" "tools" "vc") (:url . "https://github.com/magit/magit"))]) - (git-commit-insert-issue . [(20210107 2018) ((emacs (25)) (projectile (0)) (s (0)) (ghub (0)) (bitbucket (0))) "Get issues list when typing \"Fixes #\"" single ((:commit . "6cfb8b4b5b23ae881cf3d005da4d7f60d91cd2cd") (:authors ("Vindarel")) (:maintainer "Vindarel") (:keywords "tools" "vc" "github" "gitlab" "bitbucket" "commit" "issues") (:url . "https://gitlab.com/emacs-stuff/git-commit-insert-issue/"))]) + (git-commit . [(20230313 1724) ((emacs (25 1)) (compat (29 1 3 4)) (transient (20230201)) (with-editor (20230118))) "Edit Git commit messages." tar ((:commit . "a8c92cc35d306c895cd5d9b9b0cbf95d8c7381e8") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li") ("Sebastian Wiesner" . "lunaryorn@gmail.com") ("Florian Ragwitz" . "rafl@debian.org") ("Marius Vollmer" . "marius.vollmer@gmail.com")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "git" "tools" "vc") (:url . "https://github.com/magit/magit"))]) + (git-commit-insert-issue . [(20230314 1504) ((emacs (25)) (projectile (0)) (s (0)) (ghub (0)) (bitbucket (0))) "Get issues list when typing \"Fixes #\"" single ((:commit . "3de5dbb6335a245bb5137e5ad0f3ddb09ac8f183") (:authors ("Vindarel")) (:maintainer "Vindarel") (:keywords "tools" "vc" "github" "gitlab" "bitbucket" "commit" "issues") (:url . "https://gitlab.com/emacs-stuff/git-commit-insert-issue/"))]) (git-dwim . [(20170126 1214) nil "Context-aware git commands such as branch handling" single ((:commit . "485c732130686c2f28a026e385366006435394b9") (:authors ("rubikitch" . "rubikitch@ruby-lang.org")) (:maintainer "rubikitch" . "rubikitch@ruby-lang.org") (:keywords "git" "tools" "convenience") (:url . "http://www.emacswiki.org/cgi-bin/wiki/download/git-dwim.el"))]) (git-grep . [(20200920 1751) ((projectile (0 10 0))) "Search tools using git grep" single ((:commit . "12ff6045e9b6aa42f98abd4ddc44d670268a0849") (:authors ("Sam Kleinman")) (:maintainer "tychoish" . "garen@tychoish.com") (:keywords "matching" "files" "grep" "search" "using" "git-grep") (:url . "https://github.com/tychoish/git-grep.el"))]) (git-gutter . [(20220922 256) ((emacs (25 1))) "Port of Sublime Text plugin GitGutter" single ((:commit . "ec28e85d237065cb3c28db4b66d129da6d309f9c") (:authors ("Syohei YOSHIDA" . "syohex@gmail.com")) (:maintainer "Neil Okamoto" . "neil.okamoto+melpa@gmail.com") (:url . "https://github.com/emacsorphanage/git-gutter"))]) @@ -1934,7 +1941,7 @@ (git-gutter-fringe . [(20211003 2228) ((git-gutter (0 88)) (fringe-helper (0 1 1)) (cl-lib (0 5)) (emacs (24))) "Fringe version of git-gutter.el" single ((:commit . "648cb5b57faec55711803cdc9434e55a733c3eba") (:authors ("Syohei YOSHIDA" . "syohex@gmail.com")) (:maintainer "Neil Okamoto" . "neil.okamoto+melpa@gmail.com") (:url . "https://github.com/emacsorphanage/git-gutter-fringe"))]) (git-gutter-fringe+ . [(20140729 1103) ((git-gutter+ (0 1)) (fringe-helper (1 0 1))) "Fringe version of git-gutter+.el" single ((:commit . "3857d486e5b3eca9281fba1c76756cb39a9f9866") (:authors ("Syohei YOSHIDA" . "syohex@gmail.com")) (:maintainer "Syohei YOSHIDA" . "syohex@gmail.com") (:url . "https://github.com/nonsequitur/git-gutter-fringe-plus"))]) (git-identity . [(20220721 912) ((emacs (25 1)) (dash (2 10)) (hydra (0 14)) (f (0 20))) "Identity management for (ma)git" single ((:commit . "f920916a92fad0c551cd0739e48fc09d8709bd8d") (:authors ("Akira Komamura" . "akira.komamura@gmail.com")) (:maintainer "Akira Komamura" . "akira.komamura@gmail.com") (:keywords "git" "vc" "convenience") (:url . "https://github.com/akirak/git-identity.el"))]) - (git-io . [(20180317 1752) ((emacs (24 4))) "git.io integration" single ((:commit . "48753acba73b48b997bb678fb5e2a938ae63b5d6") (:authors ("Tejas Bubane" . "tejasbubane@gmail.com")) (:maintainer "Tejas Bubane" . "tejasbubane@gmail.com") (:keywords "convenience" "files") (:url . "https://github.com/tejasbubane/emacs-git-io"))]) + (git-io . [(20230322 1038) ((emacs (24 4))) "Integration for git.io URL shortening in buffer" single ((:commit . "fb25f9432e6454edd621a7512ee7abc6220151a5") (:authors ("Tejas Bubane" . "tejasbubane@gmail.com")) (:maintainer "Tejas Bubane" . "tejasbubane@gmail.com") (:keywords "convenience" "files") (:url . "https://github.com/tejasbubane/emacs-git-io"))]) (git-lens . [(20220922 710) ((emacs (24 4))) "Show new, deleted or modified files in branch" single ((:commit . "347832fbdb75a0930aa3eef628ec0069a335f3b7") (:authors ("Peter Stiernström" . "peter@stiernstrom.se")) (:maintainer "Peter Stiernström" . "peter@stiernstrom.se") (:keywords "vc" "convenience") (:url . "https://github.com/pidu/git-lens"))]) (git-link . [(20230216 300) ((emacs (24 3))) "Get the GitHub/Bitbucket/GitLab URL for a buffer location" single ((:commit . "d3ba912079e0ca5fd727b1f617791c6ae1e0da82") (:authors ("Skye Shaw" . "skye.shaw@gmail.com")) (:maintainer "Skye Shaw" . "skye.shaw@gmail.com") (:keywords "git" "vc" "github" "bitbucket" "gitlab" "sourcehut" "aws" "azure" "convenience") (:url . "http://github.com/sshaw/git-link"))]) (git-messenger . [(20201202 1637) ((emacs (24 3)) (popup (0 5 3))) "Popup last commit of current line" single ((:commit . "fb9a049ac3b5fba7369ef1f027b97881f1e377ec") (:authors ("Syohei YOSHIDA" . "syohex@gmail.com")) (:maintainer "Neil Okamoto") (:url . "https://github.com/emacsorphanage/git-messenger"))]) @@ -1986,7 +1993,7 @@ (gntp . [(20141025 250) nil "Growl Notification Protocol for Emacs" single ((:commit . "767571135e2c0985944017dc59b0be79af222ef5") (:authors ("Engelke Eschner" . "tekai@gmx.li")) (:maintainer "Engelke Eschner" . "tekai@gmx.li"))]) (gnu-apl-mode . [(20220404 341) ((emacs (27))) "Integrate GNU APL with Emacs" tar ((:commit . "c8695b0d55b5167263a843252ffd21a589018427") (:authors ("Elias Mårtenson" . "lokedhs@gmail.com")) (:maintainer "Elias Mårtenson" . "lokedhs@gmail.com") (:keywords "languages") (:url . "http://www.gnu.org/software/apl/"))]) (gnu-indent . [(20221127 2112) ((emacs (25 1))) "Indent your code with GNU Indent" single ((:commit . "f31dbe60478b6270bb57b6b05998df8eec56f801") (:authors ("Akib Azmain Turja" . "akib@disroot.org")) (:maintainer "Akib Azmain Turja" . "akib@disroot.org") (:keywords "tools" "c") (:url . "https://codeberg.org/akib/emacs-gnu-indent"))]) - (gnuplot . [(20230218 1717) ((emacs (25 1))) "Major-mode and interactive frontend for gnuplot" tar ((:commit . "663a89d263d4f26b996796d01b6a3b783449e0f5") (:authors ("Jon Oddie, Bruce Ravel, Phil Type")) (:maintainer "Maxime Tréca , Daniel Mendler" . "mail@daniel-mendler.de") (:keywords "data" "gnuplot" "plotting") (:url . "https://github.com/emacs-gnuplot/gnuplot"))]) + (gnuplot . [(20230323 1400) ((emacs (25 1))) "Major-mode and interactive frontend for gnuplot" tar ((:commit . "f99effa21f85a4c0963fec6a38e9112a8157d27e") (:authors ("Jon Oddie, Bruce Ravel, Phil Type")) (:maintainer "Maxime Tréca , Daniel Mendler" . "mail@daniel-mendler.de") (:keywords "data" "gnuplot" "plotting") (:url . "https://github.com/emacs-gnuplot/gnuplot"))]) (gnuplot-mode . [(20171013 1616) nil "Major mode for editing gnuplot scripts" single ((:commit . "601f6392986f0cba332c87678d31ae0d0a496ce7") (:keywords "gnuplot" "plotting") (:url . "https://github.com/mkmcc/gnuplot-mode"))]) (gnus-alias . [(20150316 42) nil "an alternative to gnus-posting-styles" single ((:commit . "9447d3ccb4c0e75d0468899cccff7aa249657bac") (:authors ("Joe Casadonte" . "emacs@northbound-train.com")) (:maintainer "Mark A. Hershberger" . "mah@everybody.org") (:keywords "personality" "identity" "news" "mail" "gnus"))]) (gnus-desktop-notify . [(20180623 1538) ((gnus (1 0))) "Gnus Desktop Notification global minor mode" single ((:commit . "44ebe0241a19f4052cd427dff408206542aa3c8f") (:authors ("Yuri D'Elia ")) (:maintainer "Yuri D'Elia ") (:url . "http://www.thregr.org/~wavexx/software/gnus-desktop-notify.el/"))]) @@ -2005,7 +2012,7 @@ (go-eldoc . [(20170305 1427) ((emacs (24 3)) (go-mode (1 0 0))) "eldoc for go-mode" single ((:commit . "cbbd2ea1e94a36004432a9ac61414cb5a95a39bd") (:authors ("Syohei YOSHIDA" . "syohex@gmail.com")) (:maintainer "Syohei YOSHIDA" . "syohex@gmail.com") (:url . "https://github.com/syohex/emacs-go-eldoc"))]) (go-errcheck . [(20160723 43) nil "errcheck integration for go-mode" single ((:commit . "9db21eccecedc2490793f176246094167164af31") (:authors ("Dominik Honnef" . "dominikh@fork-bomb.org")) (:maintainer "Dominik Honnef" . "dominikh@fork-bomb.org"))]) (go-expr-completion . [(20200817 1750) ((emacs (24 1))) "Complement the return values for Go" single ((:commit . "66bba78f52a732b978848e3a4c99fa2afeb6c25f") (:authors ("Ryo Fujimoto" . "fujimisakri@gmail.com")) (:maintainer "Ryo Fujimoto" . "fujimisakri@gmail.com") (:url . "https://github.com/fujimisakari/emacs-go-expr-completion"))]) - (go-fill-struct . [(20171225 331) ((emacs (24))) "Fill struct for golang." single ((:commit . "a613d0b378473eef39e8fd5724abe790aea84321") (:authors ("Sergey Kostyaev" . "feo.me@ya.ru")) (:maintainer "Sergey Kostyaev" . "feo.me@ya.ru") (:keywords "tools") (:url . "https://github.com/s-kostyaev/go-fill-struct"))]) + (go-fill-struct . [(20230308 1034) ((emacs (24))) "Fill struct for golang." single ((:commit . "9e2e4be5af716ecadba809e73ddc95d4c772b2d9") (:authors ("Sergey Kostyaev" . "feo.me@ya.ru")) (:maintainer "Sergey Kostyaev" . "feo.me@ya.ru") (:keywords "tools") (:url . "https://github.com/s-kostyaev/go-fill-struct"))]) (go-gen-test . [(20230127 1422) ((emacs (24 4))) "Generate tests for go code with gotests" single ((:commit . "f84f4177af7fcbe10ce2116d5417ad5f0485034b") (:authors ("Sergey Kostyaev" . "feo.me@ya.ru")) (:maintainer "Sergey Kostyaev" . "feo.me@ya.ru") (:keywords "languages") (:url . "https://github.com/s-kostyaev/go-gen-test"))]) (go-gopath . [(20160705 1034) ((cl-lib (0 5))) "Will guess GOPATH using gb and projectile." single ((:commit . "5172fc53f21edbf9347d5ee7d1d745da1ec88a15") (:authors ("Andrew Kirilenko" . "andrew.kirilenko.main@gmail.com")) (:maintainer "Andrew Kirilenko" . "andrew.kirilenko.main@gmail.com") (:url . "http://github.com/iced/go-gopath/"))]) (go-guru . [(20220114 2239) ((go-mode (1 3 1)) (cl-lib (0 5))) "Integration of the Go 'guru' analysis tool into Emacs." single ((:commit . "3273fcece5d9ab7edd4f15b2d6bce61f4e5a0666") (:keywords "tools"))]) @@ -2022,7 +2029,7 @@ (go-snippets . [(20180113 611) ((yasnippet (0 8 0))) "Yasnippets for go" tar ((:commit . "d437df148879566ffe7f2e503a3cf2602aa9fb28") (:keywords "snippets"))]) (go-stacktracer . [(20150430 2142) nil "parse Go stack traces" single ((:commit . "a2ac6d801b389f80ca4e2fcc1ab44513a9e55976") (:authors ("Samer Masterson" . "samer@samertm.com")) (:maintainer "Samer Masterson" . "samer@samertm.com") (:keywords "tools") (:url . "https://github.com/samertm/go-stacktracer.el"))]) (go-tag . [(20230111 651) ((emacs (24 0)) (go-mode (1 5 0))) "Edit Golang struct field tag" single ((:commit . "33f2059551d5298ca228d90f525b99d1a8d70364") (:authors ("Brantou" . "brantou89@gmail.com")) (:maintainer "Brantou" . "brantou89@gmail.com") (:keywords "tools") (:url . "https://github.com/brantou/emacs-go-tag"))]) - (go-translate . [(20230112 1532) ((emacs (27 1))) "Translation framework supports multiple engines such as Google/Bing/DeepL" tar ((:commit . "e8343e7d41af67f55c2da9231fb275a93382a4c8") (:authors ("lorniu" . "lorniu@gmail.com")) (:maintainer "lorniu" . "lorniu@gmail.com") (:keywords "convenience") (:url . "https://github.com/lorniu/go-translate"))]) + (go-translate . [(20230304 644) ((emacs (27 1))) "Translation framework supports multiple engines such as Google/Bing/DeepL" tar ((:commit . "cb8002277d44c6b548f7e924fa1715706b5f986a") (:authors ("lorniu" . "lorniu@gmail.com")) (:maintainer "lorniu" . "lorniu@gmail.com") (:keywords "convenience") (:url . "https://github.com/lorniu/go-translate"))]) (gobgen . [(20161020 1523) ((emacs (24 4))) "Generate GObject descendants using a detailed form" single ((:commit . "ed2c2b0d217deae293096f3cf14aa492791ddd4f") (:authors ("Gergely Polonkai" . "gergely@polonkai.eu")) (:maintainer "Gergely Polonkai" . "gergely@polonkai.eu") (:keywords "gobject" "glib" "gtk" "helper" "utilities"))]) (god-mode . [(20221230 708) ((emacs (25 1))) "Minor mode for God-like command entering" tar ((:commit . "607aff10a7b27a8aa0c1a15c2c39337ab17cfda7") (:authors ("Chris Done" . "chrisdone@gmail.com")) (:maintainer "Chris Done" . "chrisdone@gmail.com") (:url . "https://github.com/emacsorphanage/god-mode"))]) (godoctor . [(20180710 2152) nil "Frontend for godoctor" single ((:commit . "4b45ff3d0572f0e84056e4c3ba91fcc178199859") (:authors ("Sangho Na" . "microamp@protonmail.com")) (:maintainer "Sangho Na" . "microamp@protonmail.com") (:keywords "go" "golang" "refactoring") (:url . "https://github.com/microamp/godoctor.el"))]) @@ -2048,18 +2055,19 @@ (goto-char-preview . [(20230111 1525) ((emacs (24 3))) "Preview character when executing `goto-char` command" single ((:commit . "feee79f83194155e67f5b16ca57b51b2d941b2ee") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "character" "navigation") (:url . "https://github.com/emacs-vs/goto-char-preview"))]) (goto-chg . [(20220107 1733) ((emacs (24 1))) "Go to last change" single ((:commit . "278cd3e6d5107693aa2bb33189ca503f22f227d0") (:authors ("David Andersson ")) (:maintainer "Vasilij Schneidermann" . "mail@vasilij.de") (:keywords "convenience" "matching") (:url . "https://github.com/emacs-evil/goto-chg"))]) (goto-last-change . [(20150109 1823) nil "Move point through buffer-undo-list positions" single ((:commit . "58b0928bc255b47aad318cd183a5dce8f62199cc") (:authors ("Kevin Rodgers" . "ihs_4664@yahoo.com")) (:maintainer "Kevin Rodgers" . "ihs_4664@yahoo.com") (:keywords "convenience") (:url . "https://github.com/camdez/goto-last-change.el"))]) - (goto-last-point . [(20220816 153) ((emacs (24 3))) "Record and jump to the last point in the buffer" single ((:commit . "0a006c70719f479bc4e3ae75dd2fc84cbb15f049") (:authors ("Manuel Uberti" . "manuel.uberti@inventati.org")) (:maintainer "Manuel Uberti" . "manuel.uberti@inventati.org") (:keywords "convenience") (:url . "https://github.com/manuel-uberti/goto-last-point"))]) + (goto-last-point . [(20230406 1822) ((emacs (24 3))) "Record and jump to the last point in the buffer" single ((:commit . "2ad8ff095bc34b433803c824ec4f500ff51cd1b2") (:authors ("Manuel Uberti" . "manuel.uberti@inventati.org")) (:maintainer "Manuel Uberti" . "manuel.uberti@inventati.org") (:keywords "convenience") (:url . "https://github.com/manuel-uberti/goto-last-point"))]) (goto-line-preview . [(20230111 1531) ((emacs (25))) "Preview line when executing `goto-line` command" single ((:commit . "c6db484cf401351f7f2f57496b0466b774435947") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "line" "navigation") (:url . "https://github.com/emacs-vs/goto-line-preview"))]) (govc . [(20221216 1712) ((emacs (24 3)) (dash (1 5 0)) (s (1 9 0)) (magit-popup (2 0 50)) (json-mode (1 6 0))) "Interface to govc for managing VMware ESXi and vCenter" single ((:commit . "c82a709c50c0cd1ae560dd4c8da2d5b266114c50") (:authors ("The govc developers")) (:maintainer "The govc developers") (:keywords "convenience") (:url . "https://github.com/vmware/govmomi/tree/main/govc/emacs"))]) (govet . [(20170808 1724) nil "linter/problem finder for the Go source code" single ((:commit . "1b8c044aa856f4b62a682bc57494af19d22a6053") (:url . "https://godoc.org/golang.org/x/tools/cmd/vet"))]) (gpastel . [(20181229 1404) ((emacs (25 1))) "Integrates GPaste with the kill-ring" single ((:commit . "8a5522b274f79d55d7c9a0b2aaf062526f9253c7") (:authors ("Damien Cassou" . "damien@cassou.me")) (:maintainer "Damien Cassou" . "damien@cassou.me") (:keywords "tools") (:url . "https://gitlab.petton.fr/DamienCassou/desktop-environment"))]) (gpt . [(20230204 433) ((emacs (24 4))) "Run instruction-following language models" tar ((:commit . "a5eb9ce9cced47c26ecac5fa6bee044054ef948e") (:authors ("Andreas Stuhlmueller" . "andreas@ought.org")) (:maintainer "Andreas Stuhlmueller" . "andreas@ought.org") (:keywords "gpt3" "language" "copilot" "convenience" "tools") (:url . "https://github.com/stuhlmueller/gpt.el"))]) + (gptai . [(20230318 1547) ((emacs (24 1))) "Integrate with the OpenAI API" tar ((:commit . "5cdea5c85b102e1e57904ea6bb826cccd506067f") (:authors ("Anton Hibl" . "antonhibl11@gmail.com")) (:maintainer "Anton Hibl" . "antonhibl11@gmail.com") (:keywords "comm" "convenience") (:url . "https://github.com/antonhibl/gptai"))]) + (gptel . [(20230407 32) ((emacs (27 1)) (transient (0 3 7))) "A simple ChatGPT client" tar ((:commit . "6c47c0a48306e127557caf54c5a03e162e2d2ed3") (:authors ("Karthik Chikmagalur")) (:maintainer "Karthik Chikmagalur") (:keywords "convenience") (:url . "https://github.com/karthink/gptel"))]) (grab-mac-link . [(20210511 1303) ((emacs (24))) "Grab link from Mac Apps and insert it into Emacs" single ((:commit . "5fdb03bf57bc4a530374b896e0f8b5139dc794e3") (:authors ("Xu Chunyang")) (:maintainer "Xu Chunyang") (:keywords "mac" "hyperlink") (:url . "https://github.com/xuchunyang/grab-mac-link.el"))]) (grab-x-link . [(20191113 848) ((emacs (24)) (cl-lib (0 5))) "Grab links from X11 apps and insert into Emacs" single ((:commit . "d898db46e4864118359fdedfe915e180de3fe290") (:authors ("Xu Chunyang" . "mail@xuchunyang.me")) (:maintainer "Xu Chunyang" . "mail@xuchunyang.me") (:keywords "hyperlink") (:url . "https://github.com/xuchunyang/grab-x-link"))]) (gradle-mode . [(20150313 1905) ((s (1 8 0))) "Gradle integration with Emacs' compile" single ((:commit . "579de06674551919cddac9cfe42129f4fb0155c9") (:authors ("Daniel Mijares" . "daniel.j.mijares@gmail.com")) (:maintainer "Daniel Mijares" . "daniel.j.mijares@gmail.com") (:keywords "gradle") (:url . "http://github.com/jacobono/emacs-gradle-mode"))]) (grails . [(20221110 929) ((emacs (24))) "Minor mode for Grails projects" single ((:commit . "3019f86e555ee94388795a0475cfa213e3897bbb") (:url . "https://github.com/lifeisfoo/emacs-grails"))]) (grails-mode . [(20220407 1954) nil "minor-mode that adds some Grails project management to a grails project" single ((:commit . "29210e5a969c02169b68e04f2e28e3bf2fc13363") (:authors ("Jim Morris" . "morris@wolfman.com")) (:maintainer "Russel Winder" . "russel@winder.org.uk") (:keywords "languages") (:url . "http://blog.wolfman.com"))]) - (grails-projectile-mode . [(20160327 1324) ((projectile (0 10 0)) (emacs (24)) (cl-lib (0 5))) "Grails mode with Projectile for projects management." tar ((:commit . "8efca50ce92b556fe9d467b157d7aec635bcc017") (:authors ("Yves Zoundi" . "rimerosolutions@gmail.com")) (:maintainer "Yves Zoundi") (:keywords "grails" "projectile") (:url . "https://github.com/yveszoundi/grails-projectile-mode"))]) (grammarly . [(20221231 1655) ((emacs (26 1)) (s (1 12 0)) (request (0 3 0)) (websocket (1 6))) "Grammarly API interface" single ((:commit . "0d9fbee337cb8dd316e5dcf0bff91e44c115dd0d") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "grammar" "api" "interface" "english") (:url . "https://github.com/emacs-grammarly/grammarly"))]) (grandshell-theme . [(20180606 517) nil "Dark color theme for Emacs > 24 with intensive colors." tar ((:commit . "0ed8e4273607dd4fcaa742b4097259233b09eda6") (:authors ("steckerhalter")) (:maintainer "steckerhalter") (:keywords "color" "theme" "grand" "shell" "faces") (:url . "https://framagit.org/steckerhalter/grandshell-theme"))]) (graphene . [(20180529 1112) ((dash (2 10 0)) (exec-path-from-shell (1 9)) (ppd-sr-speedbar (0 0 6)) (sr-speedbar (20140505)) (ido-completing-read+ (4 3)) (smex (3 0)) (web-mode (11 2)) (smartparens (1 8 0)) (graphene-meta-theme (0 0 2)) (flycheck (0 23)) (company (0 8 12))) "Friendly Emacs defaults" tar ((:commit . "cc8477fcfb7771ea4e5bbaf3c01f9e679234c1c1") (:authors ("Robert Dallas Gray" . "mail@robertdallasgray.com")) (:maintainer "Robert Dallas Gray" . "mail@robertdallasgray.com") (:keywords "defaults") (:url . "https://github.com/rdallasgray/graphene"))]) @@ -2067,7 +2075,7 @@ (graphql . [(20221128 1106) ((emacs (25))) "GraphQL utilities" tar ((:commit . "b57b5ca5d2d0837e1fb4a4f30c051d5f3e643f0f") (:authors ("Sean Allred" . "code@seanallred.com")) (:maintainer "Sean Allred" . "code@seanallred.com") (:keywords "hypermedia" "tools" "lisp") (:url . "https://github.com/vermiculus/graphql.el"))]) (graphql-doc . [(20220527 1721) ((emacs (26 1)) (request (0 3 2)) (promise (1 1))) "GraphQL Documentation Explorer" single ((:commit . "d37140267e0c426c7c18aff31900aa1650257394") (:authors ("Ian Fitzpatrick")) (:maintainer "Ian Fitzpatrick") (:url . "https://github.com/ifitzpatrick/graphql-doc.el"))]) (graphql-mode . [(20220716 827) ((emacs (24 3))) "Major mode for editing GraphQL schemas" single ((:commit . "92136cf9b5a4dcd8c202c8dba9064b497776d2f7") (:authors ("David Vazquez Pua" . "davazp@gmail.com")) (:maintainer "David Vazquez Pua" . "davazp@gmail.com") (:keywords "languages") (:url . "https://github.com/davazp/graphql-mode"))]) - (graphviz-dot-mode . [(20230213 1945) ((emacs (25 0))) "Mode for the dot-language used by graphviz (att)." single ((:commit . "a3cbfa969051dd638a993e1962e2b965067896f6") (:maintainer "Pieter Pareit" . "pieter.pareit@gmail.com") (:keywords "mode" "dot" "dot-language" "dotlanguage" "graphviz" "graphs" "att") (:url . "https://ppareit.github.io/graphviz-dot-mode/"))]) + (graphviz-dot-mode . [(20230325 1050) ((emacs (25 0))) "Mode for the dot-language used by graphviz (att)." single ((:commit . "8ff793b13707cb511875f56e167ff7f980a31136") (:maintainer "Pieter Pareit" . "pieter.pareit@gmail.com") (:keywords "mode" "dot" "dot-language" "dotlanguage" "graphviz" "graphs" "att") (:url . "https://ppareit.github.io/graphviz-dot-mode/"))]) (grapnel . [(20131001 1534) nil "HTTP request lib with flexible callback dispatch" single ((:commit . "7387234eb3f0285a490fddb1e06a4bf029719fb7") (:authors ("David Leatherman" . "leathekd@gmail.com")) (:maintainer "David Leatherman" . "leathekd@gmail.com") (:url . "http://www.github.com/leathekd/grapnel"))]) (grass-mode . [(20170503 1500) ((cl-lib (0 2)) (dash (2 8 0))) "Provides Emacs modes for interacting with the GRASS GIS program" single ((:commit . "f17e330dfde6a1b81a9b33d019fc0dff890f482d") (:authors ("Tyler Smith" . "tyler@plantarum.ca")) (:maintainer "Tyler Smith" . "tyler@plantarum.ca") (:keywords "grass" "gis"))]) (grayscale-theme . [(20171005 802) nil "A simple grayscale theme" single ((:commit . "917d63c0effc8459502a41e0cad5822d2b200499") (:authors ("Kaleb Elwert" . "belak@coded.io")) (:maintainer "Kaleb Elwert" . "belak@coded.io") (:keywords "lisp") (:url . "https://github.com/belak/emacs-grayscale-theme"))]) @@ -2082,7 +2090,7 @@ (grip-mode . [(20230206 323) ((emacs (24 4))) "Instant GitHub-flavored Markdown/Org preview using grip." single ((:commit . "bdee160db6ab8c988bb0de95ad306ff8b793ec67") (:authors ("Vincent Zhang" . "seagle0128@gmail.com")) (:maintainer "Vincent Zhang" . "seagle0128@gmail.com") (:keywords "convenience" "markdown" "preview") (:url . "https://github.com/seagle0128/grip-mode"))]) (grizzl . [(20160818 737) ((cl-lib (0 5)) (emacs (24 3))) "Fast fuzzy search index for Emacs." single ((:commit . "d554d93afa8519ee3a41340ec8aa6b4555065446") (:authors ("Chris Corbyn" . "chris@w3style.co.uk")) (:maintainer "Bozhidar Batsov" . "bozhidar@batsov.com") (:keywords "convenience" "usability") (:url . "https://github.com/grizzl/grizzl"))]) (groovy-imports . [(20210505 1807) ((emacs (24 4)) (s (1 10 0)) (pcache (0 3 2))) "Code for dealing with Groovy imports" single ((:commit . "a60c3202973e3185091db623d960f71840a22205") (:authors ("Miro Bezjak")) (:maintainer "Miro Bezjak") (:keywords "groovy") (:url . "http://www.github.com/mbezjak/emacs-groovy-imports"))]) - (groovy-mode . [(20220212 646) ((s (1 12 0)) (emacs (24 3)) (dash (2 13 0))) "Major mode for Groovy source files" tar ((:commit . "bf732d367b16887f81d404481c11ed1a58671d4e") (:authors ("Russel Winder" . "russel@winder.org.uk") ("Jim Morris" . "morris@wolfman.com") ("Wilfred Hughes" . "me@wilfred.me.uk")) (:maintainer "Russel Winder" . "russel@winder.org.uk") (:keywords "languages"))]) + (groovy-mode . [(20230318 533) ((s (1 12 0)) (emacs (24 3)) (dash (2 13 0))) "Major mode for Groovy source files" tar ((:commit . "7b8520b2e2d3ab1d62b35c426e17ac25ed0120bb") (:authors ("Russel Winder" . "russel@winder.org.uk") ("Jim Morris" . "morris@wolfman.com") ("Wilfred Hughes" . "me@wilfred.me.uk")) (:maintainer "Russel Winder" . "russel@winder.org.uk") (:keywords "languages") (:url . "https://github.com/Groovy-Emacs-Modes/groovy-emacs-modes"))]) (gruber-darker-theme . [(20221122 1143) nil "Gruber Darker color theme for Emacs 24." single ((:commit . "6de7a37d7b18cf3f0ec51db799f4f2aa6e3e89ff") (:authors ("Alexey Kutepov" . "reximkut@gmail.com")) (:maintainer "Alexey Kutepov" . "reximkut@gmail.com") (:url . "http://github.com/rexim/gruber-darker-theme"))]) (grugru . [(20230121 1825) ((emacs (24 4))) "Rotate text at point" tar ((:commit . "088f26330be161cfad4835e155595ec60dcb335a") (:authors ("ROCKTAKEY" . "rocktakey@gmail.com")) (:maintainer "ROCKTAKEY" . "rocktakey@gmail.com") (:keywords "convenience" "abbrev" "tools") (:url . "https://github.com/ROCKTAKEY/grugru"))]) (grunt . [(20160316 1528) ((dash (2 9 0)) (ansi-color (3 4 2)) (emacs (24 3))) "Some glue to stick Emacs and Gruntfiles together" single ((:commit . "4c269e2738658643ec2ed9ef61a2a3d71b08d304") (:authors ("Daniel Gempesaw" . "dgempesaw@sharecare.com")) (:maintainer "Daniel Gempesaw" . "dgempesaw@sharecare.com") (:keywords "convenience" "grunt") (:url . "https://github.com/gempesaw/grunt.el"))]) @@ -2097,9 +2105,9 @@ (guess-language . [(20220408 1545) ((cl-lib (0 5)) (emacs (24))) "Robust automatic language detection" tar ((:commit . "b1fc363ca2c30b8a8ddaf2e366bca7770c8cfbec") (:authors ("Titus von der Malsburg" . "malsburg@posteo.de")) (:maintainer "Titus von der Malsburg" . "malsburg@posteo.de") (:keywords "wp") (:url . "https://github.com/tmalsburg/guess-language.el"))]) (guide-key . [(20150108 635) ((dash (2 10 0)) (popwin (0 3 0)) (s (1 9 0))) "Guide the following key bindings automatically and dynamically" single ((:commit . "9236d287a7272e307fb941237390a96037c8c0a2") (:authors ("Tsunenobu Kai" . "kai2nenobu@gmail.com")) (:maintainer "Tsunenobu Kai" . "kai2nenobu@gmail.com") (:keywords "help" "convenience") (:url . "https://github.com/kai2nenobu/guide-key"))]) (guide-key-tip . [(20161011 823) ((guide-key (1 2 3)) (pos-tip (0 4 5))) "Show guide-key.el hints using pos-tip.el" single ((:commit . "02c5d4b0b65f3e91be5a47f0ff1ae5e86e00c64e") (:authors ("Hiroaki Otsu" . "ootsuhiroaki@gmail.com")) (:maintainer "Hiroaki Otsu" . "ootsuhiroaki@gmail.com") (:keywords "help" "convenience" "tooltip") (:url . "https://github.com/aki2o/guide-key-tip"))]) - (guix . [(20221011 1244) ((emacs (24 3)) (dash (2 11 0)) (geiser (0 8)) (bui (1 2 0)) (magit-popup (2 1 0)) (edit-indirect (0 1 4))) "Interface for GNU Guix" tar ((:commit . "cf5b7a402ea503c3dcda85a86b9a6c6dd01896e0") (:authors ("Alex Kost" . "alezost@gmail.com")) (:maintainer "Alex Kost" . "alezost@gmail.com") (:keywords "tools") (:url . "https://emacs-guix.gitlab.io/website/"))]) + (guix . [(20230309 955) ((emacs (24 3)) (dash (2 11 0)) (geiser (0 8)) (bui (1 2 0)) (magit-popup (2 1 0)) (edit-indirect (0 1 4))) "Interface for GNU Guix" tar ((:commit . "a85f070c18b915ec50f12cf5375b7a32830d66f9") (:authors ("Alex Kost" . "alezost@gmail.com")) (:maintainer "Alex Kost" . "alezost@gmail.com") (:keywords "tools") (:url . "https://emacs-guix.gitlab.io/website/"))]) (gulp-task-runner . [(20170718 2041) nil "Gulp task runner" single ((:commit . "877990e956b1d71e2d9c7c3e5a129ad199b9debb") (:authors ("Nicolas Petton" . "nicolas@petton.fr")) (:maintainer "Nicolas Petton" . "nicolas@petton.fr") (:keywords "convenience" "javascript"))]) - (gumshoe . [(20230115 2105) ((emacs (25 1))) "Scoped spatial and temporal POINT movement tracking" tar ((:commit . "0ada8c575d4e94b4f3edb0092239cfa835b17726") (:authors ("overdr0ne")) (:maintainer "overdr0ne") (:keywords "tools") (:url . "https://github.com/Overdr0ne/gumshoe"))]) + (gumshoe . [(20230302 457) ((emacs (25 1))) "Scoped spatial and temporal POINT movement tracking" tar ((:commit . "3b65ee2496d6de3c7c47a821b38a5a19e0b64c2a") (:authors ("overdr0ne")) (:maintainer "overdr0ne") (:keywords "tools") (:url . "https://github.com/Overdr0ne/gumshoe"))]) (guru-mode . [(20211025 1157) nil "Become an Emacs guru" single ((:commit . "a3370e547eab260d24774cd50ccbe865373c8631") (:authors ("Bozhidar Batsov" . "bozhidar@batsov.dev")) (:maintainer "Bozhidar Batsov" . "bozhidar@batsov.dev") (:keywords "convenience") (:url . "https://github.com/bbatsov/guru-mode"))]) (gvariant . [(20210507 1310) ((emacs (24)) (parsec (0 1 4))) "GVariant (GLib) helpers" single ((:commit . "f2e87076845800cbaaeed67f175ad4e4a9c01e37") (:authors ("wouter bolsterlee" . "wouter@bolsterl.ee")) (:maintainer "wouter bolsterlee" . "wouter@bolsterl.ee") (:keywords "languages") (:url . "https://github.com/wbolster/emacs-gvariant"))]) (gvpr-mode . [(20201007 2054) nil "A major mode offering basic syntax coloring for gvpr scripts." single ((:commit . "a729fa4623a6d846ab860778842b38f685246c95") (:authors ("Rod Waldhoff" . "r.waldhoff@gmail.com")) (:maintainer "Rod Waldhoff" . "r.waldhoff@gmail.com") (:keywords "graphviz" "gv" "dot" "gvpr" "graph") (:url . "https://raw.github.com/rodw/gvpr-lib/master/extra/gvpr-mode.el"))]) @@ -2107,14 +2115,14 @@ (h5dump-mode . [(20221128 1935) ((emacs (25 1))) "Major mode for navigating h5dump output" single ((:commit . "3c9e4608112da91db76bf316417023bed0422ef3") (:authors ("Eric Berquist")) (:maintainer "Eric Berquist") (:keywords "languages" "hdf5") (:url . "https://github.com/berquist/h5dump-mode"))]) (habamax-theme . [(20181001 850) ((emacs (24))) "Boring white background color that gets the job done." single ((:commit . "6e86a1b23b6e2aaf40d4374b5673da00a28be447") (:authors ("Maxim Kim" . "habamax@gmail.com")) (:maintainer "Maxim Kim" . "habamax@gmail.com") (:url . "https://github.com/habamax/habamax-theme"))]) (habitica . [(20220215 1758) ((org (8 3 5)) (emacs (24 3))) "Interface for habitica.com" single ((:commit . "9e1fde7f359f7f6a6976b857fbbdbc8dd4fd3327") (:authors ("Adrien Brochard")) (:maintainer "Adrien Brochard") (:keywords "habitica" "todo") (:url . "https://github.com/abrochard/emacs-habitica"))]) - (hack-mode . [(20220825 127) ((emacs (25 1)) (s (1 11 0))) "Major mode for the Hack programming language" single ((:commit . "26f06ffe82574f98e7da381e48202eceb8ef0793") (:authors ("John Allen , Wilfred Hughes" . "me@wilfred.me.uk")) (:maintainer "John Allen , Wilfred Hughes" . "me@wilfred.me.uk") (:url . "https://github.com/hhvm/hack-mode"))]) + (hack-mode . [(20230227 1950) ((emacs (25 1)) (s (1 11 0))) "Major mode for the Hack programming language" single ((:commit . "278e4cc4032bff92060496cf1179643cfc6f9c0f") (:authors ("John Allen , Wilfred Hughes" . "me@wilfred.me.uk")) (:maintainer "John Allen , Wilfred Hughes" . "me@wilfred.me.uk") (:url . "https://github.com/hhvm/hack-mode"))]) (hacker-typer . [(20170206 1520) ((emacs (24))) "Pretend to write code like a pro" tar ((:commit . "d5a23714a4ccc5071580622f278597d5973f40bd") (:authors ("Diego A. Mundo" . "diegoamundo@gmail.com")) (:maintainer "Diego A. Mundo" . "diegoamundo@gmail.com") (:keywords "hacker" "typer" "multimedia" "games") (:url . "http://github.com/therockmandolinist/emacs-hacker-typer"))]) (hackernews . [(20210226 1226) nil "Hacker News Client for Emacs" single ((:commit . "cea521750eddb3a70ccd38789d12b09bbdc7e906") (:authors ("Lincoln de Sousa" . "lincoln@comum.org")) (:maintainer "Basil L. Contovounesios" . "contovob@tcd.ie") (:keywords "comm" "hypermedia" "news") (:url . "https://github.com/clarete/hackernews.el"))]) (hal-mode . [(20160704 1746) nil "Major mode for editing HAL files" single ((:commit . "cd2f66f219ee520198d4586fb6b169cef7ad3f21") (:authors ("Alexander Rössler")) (:maintainer "Alexander Rössler") (:keywords "language") (:url . "https://github.com/strahlex/hal-mode/"))]) (ham-mode . [(20150811 1306) ((html-to-markdown (1 2)) (markdown-mode (2 0))) "Html As Markdown. Transparently edit an html file using markdown" single ((:commit . "3a141986a21c2aa6eefb428983352abb8b7907d2") (:authors ("Artur Malabarba" . "bruce.connor.am@gmail.com")) (:maintainer "Artur Malabarba" . "bruce.connor.am@gmail.com") (:keywords "convenience" "emulation" "wp") (:url . "http://github.com/Bruce-Connor/ham-mode"))]) (hamburg-theme . [(20160123 740) ((emacs (24))) "Color Theme with a dark blue background." single ((:commit . "a05bf090e0c57c34cc59e301f95d9961280db244") (:authors ("Martin Haesler")) (:maintainer "Martin Haesler"))]) (hamburger-menu . [(20220509 1341) ((emacs (28 1))) "Mode line hamburger menu" single ((:commit . "06bc9d6872007a31226d7410d497a0acd98b272b") (:authors ("Iain Nicol")) (:maintainer "Iain Nicol") (:keywords "hamburger" "menu") (:url . "https://gitlab.com/iain/hamburger-menu-mode"))]) - (haml-mode . [(20190219 2102) ((emacs (24)) (cl-lib (0 5))) "Major mode for editing Haml files" single ((:commit . "bf5b6c11b1206759d2b28af48765e04882dd1fc4") (:authors ("Natalie Weizenbaum")) (:maintainer "Natalie Weizenbaum") (:keywords "markup" "languages" "html") (:url . "https://github.com/nex3/haml-mode"))]) + (haml-mode . [(20230322 1744) ((emacs (24)) (cl-lib (0 5))) "Major mode for editing Haml files" single ((:commit . "45a0b23db0b8f827c78f7749457f3427263e6ffd") (:authors ("Natalie Weizenbaum")) (:maintainer "Natalie Weizenbaum") (:keywords "markup" "languages" "html") (:url . "https://github.com/nex3/haml-mode"))]) (hamlet-mode . [(20131208 724) ((cl-lib (0 3)) (dash (2 3 0)) (s (1 7 0))) "Hamlet editing mode" single ((:commit . "7362b955e556a3d007fa06945a27e5b99349527d") (:authors (nil . "Kata =v1.4)") ("2003 Dave Love" . "fx@gnu.org") ("2016 Arthur Fayzrakhmanov")) (:maintainer "1992 Simon Marlow") (:keywords "faces" "files" "haskell") (:url . "https://github.com/haskell/haskell-mode"))]) + (haskell-mode . [(20230304 921) ((emacs (25 1))) "A Haskell editing mode" tar ((:commit . "20d4e2300302a9af673e82d0185d3f489bfb0f59") (:authors ("1992 Simon Marlow") ("1997-1998 Graeme E Moss" . "gem@cs.york.ac.uk") ("Tommy Thorn" . "thorn@irisa.fr") ("2001-2002 Reuben Thomas (>=v1.4)") ("2003 Dave Love" . "fx@gnu.org") ("2016 Arthur Fayzrakhmanov")) (:maintainer "1992 Simon Marlow") (:keywords "faces" "files" "haskell") (:url . "https://github.com/haskell/haskell-mode"))]) (haskell-snippets . [(20210228 344) ((cl-lib (0 5)) (yasnippet (0 8 0))) "Yasnippets for Haskell" tar ((:commit . "1c29c4a68ce89848b8d371c6510d1de3b586c8b3") (:authors ("Luke Hoersten" . "luke@hoersten.org")) (:maintainer "Luke Hoersten" . "luke@hoersten.org") (:keywords "snippets" "haskell") (:url . "https://github.com/haskell/haskell-snippets"))]) (haskell-tab-indent . [(20200514 1424) nil "tab-based indentation for haskell-mode" single ((:commit . "1127f46eca40a48be9cd2380df2cfc5f0b694e63") (:authors ("Sean Whitton" . "spwhitton@spwhitton.name")) (:maintainer "Sean Whitton" . "spwhitton@spwhitton.name") (:keywords "indentation" "haskell") (:url . "https://spwhitton.name/tech/code/haskell-tab-indent/"))]) (hasklig-mode . [(20211017 1730) ((emacs (25))) "Hasklig ligatures" single ((:commit . "4b73d61f4ef1c73733f7201fbf0b49ba9e3395b6") (:authors ("Daniel Mendler")) (:maintainer "Daniel Mendler") (:url . "https://github.com/minad/hasklig-mode"))]) @@ -2139,11 +2147,11 @@ (haxor-mode . [(20160618 1129) ((emacs (24 0))) "Major mode for editing Haxor Assembly Files" single ((:commit . "6fa25a8e6b6a59481bc0354c2fe1e0ed53cbdc91") (:authors ("Krzysztof Magosa" . "krzysztof@magosa.pl")) (:maintainer "Krzysztof Magosa" . "krzysztof@magosa.pl") (:keywords "haxor") (:url . "https://github.com/krzysztof-magosa/haxor-mode"))]) (hayoo . [(20140831 1221) ((emacs (24)) (json (1 3))) "Query hayoo and show results in a tabulated buffer." single ((:commit . "3ca2fb0c4d5f337d0410c21b2702dd147014e984") (:authors ("Marko Bencun" . "mbencun@gmail.com")) (:maintainer "Marko Bencun" . "mbencun@gmail.com") (:keywords "hayoo" "haskell") (:url . "https://github.com/benma/hayoo.el/"))]) (hc-zenburn-theme . [(20150928 1633) nil "An higher contrast version of the Zenburn theme." single ((:commit . "fd0024a5191cdce204d91c8f1db99ba31640f6e9") (:authors ("Nantas Nardelli" . "nantas.nardelli@gmail.com")) (:maintainer "Nantas Nardelli" . "nantas.nardelli@gmail.com") (:url . "https:github.com/edran/hc-zenburn-emacs"))]) - (hcl-mode . [(20200315 2129) ((emacs (24 3))) "Major mode for Hashicorp" single ((:commit . "c3d1158ad1a64f06aa8986ab1cdea6b7fbdd4bf7") (:authors ("Syohei YOSHIDA" . "syohex@gmail.com")) (:maintainer "Steve Purcell" . "steve@sanityinc.com") (:url . "https://github.com/purcell/emacs-hcl-mode"))]) + (hcl-mode . [(20230302 1029) ((emacs (24 3))) "Major mode for Hashicorp" single ((:commit . "35784854efd29fa8c9fe827654d747a2ace5cb19") (:authors ("Syohei YOSHIDA" . "syohex@gmail.com")) (:maintainer "Steve Purcell" . "steve@sanityinc.com") (:url . "https://github.com/purcell/emacs-hcl-mode"))]) (headlong . [(20150417 1526) nil "reckless completion" single ((:commit . "f6830f87f236eee88263cb6976125f72422abe72") (:authors ("Oleh Krehel" . "ohwoeowho@gmail.com")) (:maintainer "Oleh Krehel" . "ohwoeowho@gmail.com") (:keywords "completion") (:url . "https://github.com/abo-abo/headlong"))]) (heaven-and-hell . [(20190713 1830) ((emacs (24 4))) "easy toggle light/dark themes" single ((:commit . "e1febfd60d060c110a1e43c5f093cd8537251308") (:authors ("Valentin Ignatev" . "valentignatev@gmail.com")) (:maintainer "Valentin Ignatev" . "valentignatev@gmail.com") (:keywords "faces") (:url . "https://github.com/valignatev/heaven-and-hell"))]) - (heex-ts-mode . [(20230216 554) ((emacs (29))) "Major mode for Heex with tree-sitter support" single ((:commit . "3eecf4dad47a4cb6d92d730021e72cefda267539") (:authors ("Wilhelm H Kirschbaum")) (:maintainer "Wilhelm H Kirschbaum") (:keywords "heex" "languages" "tree-sitter") (:url . "https://github.com/wkirschbaum/elixir-ts-mode"))]) - (helm . [(20230221 819) ((helm-core (3 9 0)) (popup (0 5 3))) "Helm is an Emacs incremental and narrowing framework" tar ((:commit . "fb3df89c7b0a68c79d6725beb20d3dc6ccd348a1") (:authors ("Thierry Volpiatto" . "thievol@posteo.net")) (:maintainer "Thierry Volpiatto" . "thievol@posteo.net") (:url . "https://emacs-helm.github.io/helm/"))]) + (heex-ts-mode . [(20230316 553) ((emacs (29))) "Major mode for Heex with tree-sitter support" single ((:commit . "a61a4b6f158c19c1d583722bc35d95b09152551e") (:authors ("Wilhelm H Kirschbaum")) (:maintainer "Wilhelm H Kirschbaum") (:keywords "heex" "languages" "tree-sitter") (:url . "https://github.com/wkirschbaum/elixir-ts-mode"))]) + (helm . [(20230406 839) ((helm-core (3 9 0)) (popup (0 5 3))) "Helm is an Emacs incremental and narrowing framework" tar ((:commit . "5c9d28da67d3f42fd27c7f7fcf0701b899fbaa8a") (:authors ("Thierry Volpiatto" . "thievol@posteo.net")) (:maintainer "Thierry Volpiatto" . "thievol@posteo.net") (:url . "https://emacs-helm.github.io/helm/"))]) (helm-R . [(20120820 14) ((helm (20120517)) (ess (20120509))) "helm-sources and some utilities for GNU R." single ((:commit . "b0eb9d5f6a483a9dbe6eb6cf1f2024d4f5938bc2") (:authors ("myuhe ")) (:maintainer "myuhe") (:keywords "convenience") (:url . "https://github.com/myuhe/helm-R.el"))]) (helm-ack . [(20141030 1226) ((helm (1 0)) (cl-lib (0 5))) "Ack command with helm interface" single ((:commit . "5982f3cb6ec9f460ebbe06ec0ce7b3590bca3118") (:authors ("Syohei YOSHIDA" . "syohex@gmail.com")) (:maintainer "Syohei YOSHIDA" . "syohex@gmail.com") (:url . "https://github.com/syohex/emacs-helm-ack"))]) (helm-ad . [(20151209 1015) ((dash (2 8 0)) (helm (1 6 2))) "helm source for Active Directory" single ((:commit . "8ac044705d8620ee354a9cfa8cc1b865e83c0d55") (:authors ("Takahiro Noda" . "takahiro.noda+github@gmail.com")) (:maintainer "Takahiro Noda" . "takahiro.noda+github@gmail.com") (:keywords "comm"))]) @@ -2178,7 +2186,7 @@ (helm-codesearch . [(20221219 1219) ((emacs (25 1)) (s (1 11 0)) (dash (2 12 0)) (helm (1 7 7)) (cl-lib (0 5))) "helm interface for codesearch" single ((:commit . "bd5a7e3ece98f2940cb09be56d3e56da97d4c865") (:authors ("Youngjoo Lee" . "youngker@gmail.com")) (:maintainer "Youngjoo Lee" . "youngker@gmail.com") (:keywords "tools"))]) (helm-commandlinefu . [(20150611 545) ((emacs (24 1)) (helm (1 7 0)) (json (1 3)) (let-alist (1 0 3))) "Search and browse commandlinefu.com from helm" single ((:commit . "9ee7e018c5db23ae9c8d1c8fa969876f15b7280d") (:authors ("Chunyang Xu" . "xuchunyang56@gmail.com")) (:maintainer "Chunyang Xu" . "xuchunyang56@gmail.com") (:keywords "commandlinefu.com") (:url . "https://github.com/xuchunyang/helm-commandlinefu"))]) (helm-company . [(20190812 1429) ((helm (1 5 9)) (company (0 6 13))) "Helm interface for company-mode" single ((:commit . "6eb5c2d730a60e394e005b47c1db018697094dde") (:authors ("Yasuyuki Oka" . "yasuyk@gmail.com")) (:maintainer "Daniel Ralston" . "Sodel-the-Vociferous@users.noreply.github.com") (:url . "https://github.com/Sodel-the-Vociferous/helm-company"))]) - (helm-core . [(20230217 602) ((emacs (25 1)) (async (1 9 7))) "Development files for Helm" tar ((:commit . "dfd6403947c5cd9f32afcd6bc92a1756cc958c82") (:authors ("Thierry Volpiatto" . "thievol@posteo.net")) (:maintainer "Thierry Volpiatto" . "thievol@posteo.net") (:url . "https://emacs-helm.github.io/helm/"))]) + (helm-core . [(20230317 1729) ((emacs (25 1)) (async (1 9 7))) "Development files for Helm" tar ((:commit . "e15fd87d85ebb0df9cdd9115257292488c94549f") (:authors ("Thierry Volpiatto" . "thievol@posteo.net")) (:maintainer "Thierry Volpiatto" . "thievol@posteo.net") (:url . "https://emacs-helm.github.io/helm/"))]) (helm-cscope . [(20190615 41) ((xcscope (1 0)) (helm (1 6 7)) (cl-lib (0 5)) (emacs (24 1))) "Helm interface for xcscope.el." single ((:commit . "af1d9e7f4460a88d7400b5a74d5da68084089ac1") (:authors ("alpha22jp" . "alpha22jp@gmail.com")) (:maintainer "alpha22jp" . "alpha22jp@gmail.com") (:keywords "cscope" "helm") (:url . "https://github.com/alpha22jp/helm-cscope.el"))]) (helm-css-scss . [(20191230 1549) ((emacs (24 3)) (helm (1 0))) "CSS/SCSS/LESS Selectors with helm interface" single ((:commit . "48b996f73af1fef8d6e88a1c545d98f8c50b0cf3") (:authors ("Shingo Fukuyama - http://fukuyama.co")) (:maintainer "Shingo Fukuyama - http://fukuyama.co") (:keywords "convenience" "scss" "css" "less" "selector" "helm") (:url . "https://github.com/ShingoFukuyama/helm-css-scss"))]) (helm-ctest . [(20220721 400) ((s (1 9 0)) (dash (2 11 0)) (helm-core (3 6 0))) "Run ctest from within emacs" single ((:commit . "48edc9fa862219da34feb423c06c33d8f6d43722") (:authors ("Dan LaManna" . "me@danlamanna.com")) (:maintainer "Dan LaManna" . "me@danlamanna.com") (:keywords "helm" "ctest"))]) @@ -2218,7 +2226,7 @@ (helm-git-files . [(20141212 1317) ((helm (1 5 9))) "helm for git files" single ((:commit . "43193960774069369ac6964bbf7c026900206fa8") (:authors ("INA Lintaro ") ("TAKAGI Kentaro ")) (:maintainer "INA Lintaro ") (:keywords "helm" "git"))]) (helm-git-grep . [(20170614 1411) ((helm-core (2 2 0))) "helm for git grep, an incremental git-grep(1)" single ((:commit . "744cea07dba6e6a5effbdba83f1b786c78fd86d3") (:authors ("mechairoi")) (:maintainer "Yasuyuki Oka" . "yasuyk@gmail.com") (:url . "https://github.com/yasuyk/helm-git-grep"))]) (helm-github-stars . [(20190428 1047) ((helm (1 6 8)) (emacs (24 4))) "Helm interface for your github's stars" single ((:commit . "c891690218b0d8b957ea6cb45b1b6cffd15a6950") (:authors ("Sliim" . "sliim@mailoo.org") ("xuchunyang" . "xuchunyang56@gmail.com")) (:maintainer "Sliim" . "sliim@mailoo.org") (:keywords "helm" "github" "stars") (:url . "https://github.com/Sliim/helm-github-stars"))]) - (helm-gitignore . [(20170211 8) ((gitignore-mode (1 1 0)) (helm (1 7 0)) (request (0 1 0)) (cl-lib (0 5))) "Generate .gitignore files with gitignore.io." single ((:commit . "2a2e7da7855a6db0ab3bb6a6a087863d7abd4391") (:authors ("Juan Placencia")) (:maintainer "Juan Placencia") (:keywords "helm" "gitignore" "gitignore.io") (:url . "https://github.com/jupl/helm-gitignore"))]) + (helm-gitignore . [(20230310 1829) ((git-modes (1 4 0)) (helm (1 7 0)) (request (0 1 0)) (cl-lib (0 5))) "Generate .gitignore files with gitignore.io." single ((:commit . "85c34065e6fceac8fa7287e6ec79ea3d1182d654") (:authors ("Juan Placencia")) (:maintainer "Juan Placencia") (:keywords "helm" "gitignore" "gitignore.io") (:url . "https://github.com/jupl/helm-gitignore"))]) (helm-gitlab . [(20180312 1647) ((s (1 9 0)) (dash (2 9 0)) (helm (1 0)) (gitlab (0 8 0))) "Helm interface to Gitlab" single ((:commit . "68318aca3206d50701039c9aae39734ca29a49f9") (:authors ("Nicolas Lamirault" . "nicolas.lamirault@gmail.com")) (:maintainer "Nicolas Lamirault" . "nicolas.lamirault@gmail.com") (:keywords "gitlab" "helm") (:url . "https://github.com/nlamirault/emacs-gitlab"))]) (helm-go-package . [(20161103 153) ((emacs (24 4)) (helm-core (2 2 1)) (go-mode (1 4 0)) (deferred (0 4 0))) "helm sources for Go programming language's package" single ((:commit . "bf741f4a455fcb129c1a9dcec710a52621f9719d") (:authors ("Yasuyuki Oka" . "yasuyk@gmail.com")) (:maintainer "Yasuyuki Oka" . "yasuyk@gmail.com") (:url . "https://github.com/yasuyk/helm-go-package"))]) (helm-google . [(20210527 900) ((helm (0))) "Emacs Helm Interface for quick Google searches" single ((:commit . "27834161391c350ef790062391cb7eab1d59fb62") (:authors ("steckerhalter")) (:maintainer "steckerhalter") (:keywords "helm" "google" "search" "browse" "searx") (:url . "https://framagit.org/steckerhalter/helm-google"))]) @@ -2246,7 +2254,7 @@ (helm-lib-babel . [(20180510 1324) ((cl-lib (0 5)) (helm (1 9 2)) (emacs (24 4))) "helm insertion of babel function references" single ((:commit . "41bc0cdea8a604c6c8dc83ed5066644d33688fad") (:authors ("Derek Feichtinger" . "dfeich@gmail.com")) (:maintainer "Derek Feichtinger" . "dfeich@gmail.com") (:keywords "convenience") (:url . "https://github.com/dfeich/helm-lib-babel.el"))]) (helm-lines . [(20220103 1909) ((emacs (24 4)) (helm (1 9 8))) "A helm interface for completing by lines" single ((:commit . "f5ad178818d223f32a0bf60d370b50c01df5f3da") (:authors ("@torgeir")) (:maintainer "@torgeir") (:keywords "files" "helm" "rg" "ag" "pt" "vc" "git" "lines" "complete" "tools" "languages") (:url . "https://github.com/torgeir/helm-lines.el/"))]) (helm-lobsters . [(20150213 1546) ((helm (1 0)) (cl-lib (0 5))) "helm front-end for lobste.rs" single ((:commit . "4121b232aeded2f82ad2c8a85c7dda17ef9d97bb") (:authors ("Julien BLANCHARD" . "julien@sideburns.eu")) (:maintainer "Julien BLANCHARD" . "julien@sideburns.eu") (:url . "https://github.com/julienXX/helm-lobste.rs"))]) - (helm-ls-git . [(20221118 503) ((helm (1 7 8))) "list git files." single ((:commit . "c5893f0cd92b20dcdcd5dc89d9ba6200a95c3f80"))]) + (helm-ls-git . [(20230405 957) ((helm (1 7 8))) "list git files." single ((:commit . "356e7f0c2725fc4ab6d2eb5bb4752ac1a8133039"))]) (helm-ls-hg . [(20150909 543) ((helm (1 7 8))) "List hg files in hg project." single ((:commit . "61b91a22fcfb62d0fc56e361ec01ce96973c7165"))]) (helm-ls-svn . [(20190316 2203) ((emacs (24 1)) (helm (1 7 0)) (cl-lib (0 5))) "helm extension to list svn files" single ((:commit . "a6043e1187282f649e2cb9f0e722a42daf41294b") (:authors ("Chunyang Xu" . "chunyang@macports.org")) (:maintainer "Chunyang Xu" . "chunyang@macports.org") (:keywords "helm" "svn") (:url . "https://svn.macports.org/repository/macports/users/chunyang/helm-ls-svn.el/helm-ls-svn.el"))]) (helm-lsp . [(20210419 2014) ((emacs (25 1)) (dash (2 14 1)) (lsp-mode (5 0)) (helm (2 0))) "LSP helm integration" single ((:commit . "c2c6974dadfac459b1a69a1217441283874cea92") (:authors ("Ivan Yonchovski" . "yyoncho@gmail.com")) (:maintainer "Ivan Yonchovski" . "yyoncho@gmail.com") (:keywords "languages" "debug") (:url . "https://github.com/yyoncho/helm-lsp"))]) @@ -2262,7 +2270,7 @@ (helm-open-github . [(20170220 159) ((emacs (24 4)) (helm-core (1 7 7)) (gh (0 8 2))) "Utilities of Opening Github Page" single ((:commit . "2f03d97552a1233db7694116d5f80ecde7612756") (:authors ("Syohei YOSHIDA" . "syohex@gmail.com")) (:maintainer "Syohei YOSHIDA" . "syohex@gmail.com") (:url . "https://github.com/syohex/emacs-helm-open-github"))]) (helm-org . [(20210324 1927) ((helm (3 3)) (emacs (24 4))) "Helm for org headlines and keywords completion" single ((:commit . "d67186d3a64e610c03a5f3d583488f018fb032e4") (:authors ("Thierry Volpiatto" . "thierry.volpiatto@gmail.com")) (:maintainer "Thierry Volpiatto" . "thierry.volpiatto@gmail.com") (:url . "https://github.com/emacs-helm/helm-org"))]) (helm-org-multi-wiki . [(20210228 1853) ((emacs (26 1)) (org (9 3)) (org-multi-wiki (0 4)) (org-ql (0 5)) (dash (2 18)) (helm-org-ql (0 5)) (helm (3 5))) "Helm interface to org-multi-wiki" single ((:commit . "c85bcaafed749de3efa5e1f4d256e7ac9c5678e2") (:authors ("Akira Komamura" . "akira.komamura@gmail.com")) (:maintainer "Akira Komamura" . "akira.komamura@gmail.com") (:keywords "org" "outlines") (:url . "https://github.com/akirak/org-multi-wiki"))]) - (helm-org-ql . [(20220527 703) ((emacs (26 1)) (dash (2 18 1)) (s (1 12 0)) (helm-org (1 0)) (org-ql (0 6 -1))) "Helm support for org-ql" single ((:commit . "115500c8a0a3190ec6a69d1120fe81944d819125") (:authors ("Adam Porter" . "adam@alphapapa.net")) (:maintainer "Adam Porter" . "adam@alphapapa.net") (:url . "https://github.com/alphapapa/org-ql"))]) + (helm-org-ql . [(20230310 1225) ((emacs (26 1)) (dash (2 18 1)) (s (1 12 0)) (helm-org (1 0)) (org-ql (0 6 -1))) "Helm support for org-ql" single ((:commit . "aadddc4d84a72fa80d3bf909c9a3a4cbce53cd93") (:authors ("Adam Porter" . "adam@alphapapa.net")) (:maintainer "Adam Porter" . "adam@alphapapa.net") (:url . "https://github.com/alphapapa/org-ql"))]) (helm-org-recent-headings . [(20211011 1519) ((emacs (26 1)) (org (9 0 5)) (dash (2 18 0)) (helm (1 9 4)) (org-recent-headings (0 2 -1)) (s (1 12 0))) "Helm source for org-recent-headings" single ((:commit . "97418d581ea030f0718794e50b005e9bae44582e") (:authors ("Adam Porter" . "adam@alphapapa.net")) (:maintainer "Adam Porter" . "adam@alphapapa.net") (:keywords "hypermedia" "outlines" "org") (:url . "http://github.com/alphapapa/org-recent-headings"))]) (helm-org-rifle . [(20221024 1943) ((emacs (24 4)) (dash (2 12)) (f (0 18 1)) (helm (1 9 4)) (s (1 10 0))) "Rifle through your Org files" single ((:commit . "74725b63e71b1c941f354e6c8a2cf8b5ee7ef563") (:authors ("Adam Porter" . "adam@alphapapa.net")) (:maintainer "Adam Porter" . "adam@alphapapa.net") (:keywords "hypermedia" "outlines") (:url . "http://github.com/alphapapa/helm-org-rifle"))]) (helm-orgcard . [(20220721 756) ((helm-core (3 6 0))) "browse the orgcard by helm" single ((:commit . "d58d35627bb1714bb2cb095f696706b6881233ed") (:authors ("Yuhei Maeda ")) (:maintainer "Yuhei Maeda") (:keywords "convenience" "helm" "org") (:url . "https://github.com/emacs-jp/helm-orgcard"))]) @@ -2330,7 +2338,7 @@ (helm-zhihu-daily . [(20160625 1145) ((helm (1 0)) (cl-lib (0 5)) (emacs (24 4))) "Helm interface for 知乎日报 (http://daily.zhihu.com)" single ((:commit . "be27dcc6be1eb97663b65581a9a5c0fc81cfaba7") (:authors ("Chunyang Xu" . "xuchunyang56@gmail.com")) (:maintainer "Chunyang Xu" . "xuchunyang56@gmail.com") (:url . "https://github.com/xuchunyang/helm-zhihu-daily"))]) (help-find . [(20220929 822) ((emacs (25 2)) (dash (2 12))) "Additional help functions for working with keymaps" single ((:commit . "ef7266fc480367c12bff64817c875af940d0c9c0") (:authors ("Duncan Burke" . "duncankburke@gmail.com")) (:maintainer "Duncan Burke" . "duncankburke@gmail.com") (:keywords "help") (:url . "https://github.com/duncanburke/help-find"))]) (help-find-org-mode . [(20181204 234) ((emacs (24 4))) "Advise help to find org source over tangled code" single ((:commit . "c6fa2c8a8e9381572190010a9fa01f2be78f2790") (:authors ("Eric Crosson" . "eric.s.crosson@utexas.com")) (:maintainer "Eric Crosson" . "eric.s.crosson@utexas.com") (:keywords "convenience") (:url . "https://github.com/EricCrosson/help-find-org-mode"))]) - (helpful . [(20221209 1743) ((emacs (25)) (dash (2 18 0)) (s (1 11 0)) (f (0 20 0)) (elisp-refs (1 2))) "A better *help* buffer" single ((:commit . "94c25337b2de2f9da60914a7c0c6cca9584c0231") (:authors ("Wilfred Hughes" . "me@wilfred.me.uk")) (:maintainer "Wilfred Hughes" . "me@wilfred.me.uk") (:keywords "help" "lisp") (:url . "https://github.com/Wilfred/helpful"))]) + (helpful . [(20230323 414) ((emacs (25)) (dash (2 18 0)) (s (1 11 0)) (f (0 20 0)) (elisp-refs (1 2))) "A better *help* buffer" single ((:commit . "e9ec6fc2ae10db2b9b59ed656021845d11881a0a") (:authors ("Wilfred Hughes" . "me@wilfred.me.uk")) (:maintainer "Wilfred Hughes" . "me@wilfred.me.uk") (:keywords "help" "lisp") (:url . "https://github.com/Wilfred/helpful"))]) (hemera-theme . [(20180916 924) ((emacs (24))) "Light theme" single ((:commit . "b67c902b210b37b00cac68726822404543147ba8") (:authors ("Guido Schmidt")) (:maintainer "Guido Schmidt" . "guido.schmidt.2912@gmail.com") (:keywords "themes" "light-theme") (:url . "https://github.com/GuidoSchmidt/emacs-hemera-theme"))]) (hemisu-theme . [(20130508 1844) nil "Hemisu for Emacs." tar ((:commit . "ae593ac58e6bffef97467259c1d1472840385e84") (:authors ("Andrzej Sliwa")) (:maintainer "Andrzej Sliwa") (:url . "http://github/anrzejsliwa/django-theme"))]) (hercules . [(20200420 747) ((emacs (24 4)) (which-key (3 3 2))) "An auto-magical, which-key-based hydra banisher." single ((:commit . "557da39878d0637395fdded91243b340c37eff7b") (:authors ("Uros Perisic")) (:maintainer "Uros Perisic") (:keywords "convenience") (:url . "https://gitlab.com/jjzmajic/hercules"))]) @@ -2379,7 +2387,6 @@ (hiwin . [(20150825 827) nil "Visible active window mode." single ((:commit . "6ee8ed051405653bd9b7332d7e9fbb591d954051") (:authors ("k.sugita")) (:maintainer "k.sugita") (:keywords "faces" "editing" "emulating"))]) (hl-anything . [(20160422 1708) ((emacs (24 3))) "Highlight symbols, selections, enclosing parens and more." tar ((:commit . "c2e50f91a05d6c43e8a1c169f709cd1f23e47b0a") (:authors ("boyw165")) (:maintainer "boyw165"))]) (hl-block-mode . [(20230201 130) ((emacs (26 1))) "Highlighting nested blocks" single ((:commit . "352686955b6e73c6353c640c7d3bc09487c9de69") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:url . "https://codeberg.org/ideasman42/emacs-hl-block-mode"))]) - (hl-fill-column . [(20200607 757) ((names (0 5)) (emacs (24))) "Highlight fill column." single ((:commit . "5782a91ba0182c4e562fa0db6379ff9dd472856b") (:keywords "fill column" "faces") (:url . "https://github.com/laishulu/hl-fill-column"))]) (hl-indent . [(20170429 2104) ((emacs (24)) (cl-lib (0 5))) "Highlight irregular indentation." single ((:commit . "bdb2e0177a7c8b29af26998e688b856adc6ded93") (:authors ("Kirill Ignatiev ")) (:maintainer "Kirill Ignatiev ") (:keywords "convenience" "faces") (:url . "https://github.com/ikirill/hl-indent"))]) (hl-indent-scope . [(20230116 2310) ((emacs (26 1))) "Highlight indentation by scope" tar ((:commit . "5e806bfedd01bf82e4fda27e4b9809662318c287") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:url . "https://codeberg.org/ideasman42/emacs-hl-indent-scope"))]) (hl-prog-extra . [(20230201 140) ((emacs (26 2))) "Customizable highlighting for source-code" tar ((:commit . "a573977f9734b1786a4691c9fb8e5031159027f6") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:keywords "convenience") (:url . "https://codeberg.org/ideasman42/emacs-hl-prog-extra"))]) @@ -2399,7 +2406,7 @@ (hookify . [(20141216 2209) ((s (1 9 0)) (dash (1 5 0))) "Interactive commands to create temporary hooks" single ((:commit . "e76127230716f7fab6662410c03c3872d17a172b") (:authors ("Philippe Vaucher" . "philippe.vaucher@gmail.com")) (:maintainer "Philippe Vaucher" . "philippe.vaucher@gmail.com") (:keywords "hook" "convenience") (:url . "https://github.com/Silex/hookify"))]) (horizon-theme . [(20200720 1832) ((emacs (24 3))) "A beautifully warm dual theme" single ((:commit . "9595549c514a9376c61d5d303405f6a6982e9e46") (:url . "https://github.com/aodhneine/horizon-theme.el"))]) (horoscope . [(20180409 641) ((emacs (24))) "generate horoscopes." single ((:commit . "f4c683e991adce0a8f9023f15050f306f9b9a9ed") (:authors ("Bob Manson" . "manson@cygnus.com")) (:maintainer "Noah Friedman" . "friedman@prep.ai.mit.edu") (:keywords "extensions" "games") (:url . "https://github.com/mschuldt/horoscope.el"))]) - (hotfuzz . [(20230221 844) ((emacs (27 1))) "Fuzzy completion style" single ((:commit . "90d95663f9ff667786b71071a039502d873ef4aa") (:authors ("Axel Forsman" . "axelsfor@gmail.com")) (:maintainer "Axel Forsman" . "axelsfor@gmail.com") (:keywords "matching") (:url . "https://github.com/axelf4/hotfuzz"))]) + (hotfuzz . [(20230322 1318) ((emacs (27 1))) "Fuzzy completion style" single ((:commit . "f02edb699c5b9bb60a1372dde3f187dac7797c48") (:authors ("Axel Forsman" . "axelsfor@gmail.com")) (:maintainer "Axel Forsman" . "axelsfor@gmail.com") (:keywords "matching") (:url . "https://github.com/axelf4/hotfuzz"))]) (hound . [(20200122 1700) ((request (0 2 0)) (cl-lib (0 5))) "Display hound search results in a compilation window" single ((:commit . "35e2cdc81fcc904b450a7ef3ec00fd25df6a4431") (:authors ("Ryan Young")) (:maintainer "Ryan Young"))]) (hover . [(20220129 1935) ((emacs (25 2)) (dash (2 14 1))) "Package to use hover with flutter" single ((:commit . "2b826735bb8d3bcfced489a1e0fa21b10fbc967e") (:authors ("Eric Dallo")) (:maintainer "Eric Dallo") (:keywords "hover" "flutter" "mobile" "tools") (:url . "https://github.com/ericdallo/hover.el"))]) (howdoi . [(20150204 43) nil "Instant coding answers via Emacs." tar ((:commit . "5fbf7069ee160c597a328e5ce5fb32920e1ca88f") (:authors ("Andrey Tykhonov ")) (:maintainer "Andrey Tykhonov" . "atykhonov@gmail.com") (:keywords "howdoi" "convenience") (:url . "https://github.com/atykhonov/emacs-howdoi/"))]) @@ -2421,7 +2428,7 @@ (httprepl . [(20141101 1734) ((s (1 9 0)) (dash (2 5 0)) (emacs (24))) "An HTTP REPL" single ((:commit . "cfa3693267a8ed1c96a86a126823f37dbfe077d8") (:authors ("Greg Sexton" . "gregsexton@gmail.com")) (:maintainer "Greg Sexton" . "gregsexton@gmail.com") (:keywords "http" "repl") (:url . "https://github.com/gregsexton/httprepl.el"))]) (huecycle . [(20210830 340) ((emacs (27 1))) "Idle color animation" single ((:commit . "a05e32351dcff3e61b5f15800556adfe1939c112") (:authors ("Phillip O'Reggio ")) (:maintainer "Phillip O'Reggio") (:keywords "faces") (:url . "https://github.com/pnor/huecycle"))]) (hugsql-ghosts . [(20211124 1646) ((s (1 9 0)) (dash (2 10 0)) (cider (0 14 0))) "Display hugsql defqueries in clojure code as an overlay" single ((:commit . "f9ab314b6a10140041233e65a23e924dcab9a7a3") (:authors ("Roland Kaercher" . "roland.kaercher@gmail.com")) (:maintainer "Roland Kaercher" . "roland.kaercher@gmail.com") (:url . "https://github.com/rkaercher/hugsql-ghosts"))]) - (humanoid-themes . [(20220305 930) ((emacs (24 3))) "Color themes with a dark and light variant" tar ((:commit . "5828705bcc3eab9af9dd36fd7dc96d48c3020d85") (:authors ("Thomas Friese")) (:maintainer "Thomas Friese") (:keywords "faces" "color" "theme") (:url . "https://github.com/humanoid-colors/emacs-humanoid-themes"))]) + (humanoid-themes . [(20230308 2129) ((emacs (24 3))) "Color themes with a dark and light variant" tar ((:commit . "d6d41b365501650c18939c3394762bc163c87e40") (:authors ("Thomas Friese")) (:maintainer "Thomas Friese") (:keywords "faces" "color" "theme") (:url . "https://github.com/humanoid-colors/emacs-humanoid-themes"))]) (hungarian-holidays . [(20161020 1138) nil "Adds a list of Hungarian public holidays to Emacs calendar" single ((:commit . "653108769279499d84a79267c90e640d98823872") (:authors ("Gergely Polonkai" . "gergely@polonkai.eu")) (:maintainer "Gergely Polonkai" . "gergely@polonkai.eu") (:keywords "calendar"))]) (hungry-delete . [(20210409 1643) nil "hungry delete minor mode" single ((:commit . "d919e555e5c13a2edf4570f3ceec84f0ade71657") (:authors ("Nathaniel Flath" . "flat0103@gmail.com")) (:maintainer "Nathaniel Flath" . "flat0103@gmail.com") (:url . "http://github.com/nflath/hungry-delete"))]) (hy-mode . [(20211016 2011) ((dash (2 18 0)) (s (1 11 0)) (emacs (24))) "Major mode for Hylang" tar ((:commit . "df814865a1faa8414dacdbb35b2a9029995312ec") (:keywords "languages" "lisp" "python") (:url . "http://github.com/hylang/hy-mode"))]) @@ -2430,6 +2437,7 @@ (hydandata-light-theme . [(20190809 1925) nil "A light color theme that is easy on your eyes" single ((:commit . "812ffa4bee3163098ef66ee4506feed45018be4e") (:authors ("David Chkhikvadze" . "david@chkhd.net")) (:maintainer "David Chkhikvadze" . "david@chkhd.net") (:keywords "color-theme" "theme") (:url . "https://github.com/chkhd/hydandata-light-theme"))]) (hyde . [(20160508 308) nil "Major mode to help create and manage Jekyll blogs" tar ((:commit . "a8cd6ed00ecd8d7de0ded2f4867015b412b15b76"))]) (hydra . [(20220910 1206) ((cl-lib (0 5)) (lv (0))) "Make bindings that stick around." tar ((:commit . "317e1de33086637579a7aeb60f77ed0405bf359b") (:authors ("Oleh Krehel" . "ohwoeowho@gmail.com")) (:maintainer "Oleh Krehel" . "ohwoeowho@gmail.com") (:keywords "bindings") (:url . "https://github.com/abo-abo/hydra"))]) + (hyperdrive . [(20230404 2049) ((emacs (27 1)) (map (3 0)) (compat (29 1 3 2)) (plz (0 4)) (persist (0 5))) "P2P filesystem in Emacs" tar ((:commit . "349be636e7dc4ba61262c9cf8d669b9b0637cd54") (:authors ("Joseph Turner")) (:maintainer "Joseph Turner" . "joseph@ushin.org") (:url . "https://git.sr.ht/~ushin/hyperdrive.el"))]) (hyperkitty . [(20220226 1951) ((request (0 3 2)) (emacs (25 1))) "Emacs interface for Hyperkitty archives" single ((:commit . "2c1d22ff017d096c359aa151e6a29f7214a58118") (:authors ("Abhilash Raj" . "maxking@asynchronous.in")) (:maintainer "Abhilash Raj" . "maxking@asynchronous.in") (:keywords "mail" "hyperkitty" "mailman") (:url . "https://github.com/maxking/hyperkitty.el"))]) (hyperlist-mode . [(20230119 28) ((emacs (24))) "A major-mode for viewing Hyperlists" single ((:commit . "480dbf33ca72e7b5fade952aaf0d5a5eb43acb1d") (:authors ("Wojciech Siewierski")) (:maintainer "Wojciech Siewierski") (:keywords "outlines") (:url . "https://github.com/vifon/hyperlist-mode"))]) (hyperspace . [(20210603 1825) ((emacs (25)) (s (1 12 0))) "Get there from here" single ((:commit . "c4c363c140250ba6b775516082063878975a6154") (:authors ("Ian Eure" . "ian@retrospec.tv")) (:maintainer "Ian Eure" . "ian@retrospec.tv") (:keywords "tools" "convenience") (:url . "https://github.com/ieure/hyperspace-el"))]) @@ -2456,7 +2464,7 @@ (idea-darkula-theme . [(20160416 2303) ((emacs (24 1))) "Color theme based on IntelliJ IDEA Darkula color theme" single ((:commit . "52602d9b91883e1f297d000951aeed48bf60176e") (:authors ("Alexey Veretennikov ")) (:maintainer "Alexey Veretennikov ") (:keywords "themes") (:url . "http://github.com/fourier/idea-darkula-theme"))]) (identica-mode . [(20130204 2253) nil "Major mode API client for status.net open microblogging" tar ((:commit . "cf9183ee11ac922e85c7c908f04e2d00b03111b3") (:authors ("Gabriel Saldana" . "gsaldana@gmail.com")) (:maintainer "Gabriel Saldana" . "gsaldana@gmail.com") (:keywords "identica" "web") (:url . "http://blog.gabrielsaldana.org/identica-mode-for-emacs/"))]) (idle-highlight-in-visible-buffers-mode . [(20181027 1531) nil "highlight the word the point is on" single ((:commit . "8d8de309d5bd4b035c01bf7f0cfc6e079c79d898") (:authors ("Ignacy Moryc")) (:maintainer "Ignacy Moryc") (:keywords "convenience") (:url . "https://github.com/ignacy/idle-highlight-in-visible-buffers"))]) - (idle-highlight-mode . [(20230208 359) ((emacs (27 1))) "Highlight the word the point is on" single ((:commit . "215d6612b4f8f412c14f9f456106bfa4c5df3d2f") (:authors ("Phil Hagelberg, Cornelius Mika, Campbell Barton")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:keywords "convenience") (:url . "https://codeberg.org/ideasman42/emacs-idle-highlight-mode"))]) + (idle-highlight-mode . [(20230319 810) ((emacs (27 1))) "Highlight the word the point is on" single ((:commit . "f9091c907d41e7b12d99d108a194229b8dbfc5ae") (:authors ("Phil Hagelberg, Cornelius Mika, Campbell Barton")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:keywords "convenience") (:url . "https://codeberg.org/ideasman42/emacs-idle-highlight-mode"))]) (idle-org-agenda . [(20190106 1844) nil "Shows your agenda when editor is idle." single ((:commit . "bfdf1b4f4096acdd081b3549d6b838f4ca4f7d0d") (:authors ("John Wiegley" . "jwiegley@gmail.com")) (:maintainer "Enis Özgen" . "mail@enisozgen.com") (:keywords "org" "org-mode" "org-agenda" "calendar") (:url . "https://github.com/enisozgen/idle-org-agenda"))]) (idle-require . [(20090715 2203) nil "load elisp libraries while Emacs is idle" single ((:commit . "33592bb098223b4432d7a35a1d65ab83f47c1ec1") (:authors ("Nikolaj Schumacher ")) (:maintainer "Nikolaj Schumacher ") (:keywords "internal") (:url . "http://nschum.de/src/emacs/idle-require/"))]) (ido-at-point . [(20151113 1508) ((emacs (24))) "ido-style completion-at-point" single ((:commit . "e5907bbe8a3d148d07698b76bd994dc3076e16ee") (:authors ("katspaugh")) (:maintainer "katspaugh") (:keywords "convenience" "abbrev") (:url . "https://github.com/katspaugh/ido-at-point"))]) @@ -2514,11 +2522,11 @@ (indicators . [(20161211 1126) ((dash (2 13 0)) (cl-lib (0 5 0))) "Display the buffer relative location of line in the fringe." single ((:commit . "f62a1201f21453e3aca93f48483e65ae8251432e") (:authors ("Matus Goljer" . "matus.goljer@gmail.com")) (:maintainer "Matus Goljer" . "matus.goljer@gmail.com") (:keywords "fringe" "frames") (:url . "https://github.com/Fuco1/indicators.el"))]) (indium . [(20210309 1210) ((emacs (25)) (seq (2 16)) (js2-mode (20140114)) (js2-refactor (0 9 0)) (company (0 9 0)) (json-process-client (0 2 0))) "JavaScript Awesome Development Environment" tar ((:commit . "8499e156bf7286846c3a2bf8c9e0c4d4f24b224c") (:authors ("Nicolas Petton" . "nicolas@petton.fr")) (:maintainer "Nicolas Petton" . "nicolas@petton.fr") (:keywords "tools" "javascript") (:url . "https://github.com/NicolasPetton/indium"))]) (indy . [(20190807 625) nil "A minor mode and EDSL to manage your mode's indentation rules." single ((:commit . "abc5bee424780ad2de5520f8fefbf8e120c0d9ed") (:authors ("Kevin W. van Rooijen" . "kevin.van.rooijen@attichacker.com")) (:maintainer "Kevin W. van Rooijen" . "kevin.van.rooijen@attichacker.com") (:keywords "convenience" "matching" "tools"))]) - (inf-clojure . [(20221114 616) ((emacs (25 1)) (clojure-mode (5 11))) "Run an external Clojure process in an Emacs buffer" single ((:commit . "e5ce3839835b9b561fca5810f43f413c96c197d9") (:maintainer "Bozhidar Batsov" . "bozhidar@batsov.dev") (:keywords "processes" "comint" "clojure") (:url . "http://github.com/clojure-emacs/inf-clojure"))]) + (inf-clojure . [(20230326 1946) ((emacs (26 2)) (clojure-mode (5 11))) "Run an external Clojure process in an Emacs buffer" single ((:commit . "8ad2242b75ea1a06fad391deb8f858a392408a94") (:maintainer "Bozhidar Batsov" . "bozhidar@batsov.dev") (:keywords "processes" "comint" "clojure") (:url . "http://github.com/clojure-emacs/inf-clojure"))]) (inf-crystal . [(20180119 211) ((emacs (24 3)) (crystal-mode (0 1 0))) "Run a Inferior-Crystal process in a buffer" single ((:commit . "dd5c85e621976ea09b602182a15396e3b510ec63") (:authors ("Brantou" . "brantou89@gmail.com")) (:maintainer "Brantou" . "brantou89@gmail.com") (:keywords "languages" "crystal") (:url . "https://github.com/brantou/inf-crystal.el"))]) (inf-elixir . [(20221120 2028) ((emacs (25 1))) "Run an interactive Elixir shell" single ((:commit . "6fbb0867b586ad1bf8adc09cc55f33dfa72db833") (:authors ("Jonathan Arnett" . "jonathan.arnett@protonmail.com")) (:maintainer "Jonathan Arnett" . "jonathan.arnett@protonmail.com") (:keywords "languages" "processes" "tools") (:url . "https://github.com/J3RN/inf-elixir"))]) (inf-mongo . [(20180408 1338) nil "Run a MongoDB shell process in a buffer" single ((:commit . "2e498d1c88bd1904eeec18ed06b1a0cf8bdc2a92") (:authors ("Tobias Svensson")) (:maintainer "Tobias Svensson") (:keywords "databases" "mongodb") (:url . "http://github.com/endofunky/inf-mongo"))]) - (inf-ruby . [(20230122 246) ((emacs (24 3))) "Run a Ruby process in a buffer" single ((:commit . "0ce7f4049edcae188b4643b3163e5301f9ef09cc") (:authors ("Yukihiro Matsumoto") ("Nobuyoshi Nakada") ("Cornelius Mika" . "cornelius.mika@gmail.com") ("Dmitry Gutov" . "dgutov@yandex.ru") ("Kyle Hargraves" . "pd@krh.me")) (:maintainer "Dmitry Gutov" . "dgutov@yandex.ru") (:keywords "languages" "ruby") (:url . "http://github.com/nonsequitur/inf-ruby"))]) + (inf-ruby . [(20230304 1512) ((emacs (24 3))) "Run a Ruby process in a buffer" single ((:commit . "6f1df882ab319758af43877fa20465f6566efbf3") (:authors ("Yukihiro Matsumoto") ("Nobuyoshi Nakada") ("Cornelius Mika" . "cornelius.mika@gmail.com") ("Dmitry Gutov" . "dgutov@yandex.ru") ("Kyle Hargraves" . "pd@krh.me")) (:maintainer "Dmitry Gutov" . "dgutov@yandex.ru") (:keywords "languages" "ruby") (:url . "http://github.com/nonsequitur/inf-ruby"))]) (inferior-islisp . [(20220924 1040) ((emacs (26 3)) (islisp-mode (0 2))) "Run inferior ISLisp processes" single ((:commit . "423b84fe4cc6944e36971225b3e19c888e7e4690") (:authors ("Fermin Munoz")) (:maintainer "Fermin Munoz" . "fmfs@posteo.net") (:keywords "islisp" "lisp" "programming") (:url . "https://gitlab.com/sasanidas/islisp-mode"))]) (inflections . [(20210110 2237) ((cl-lib (0 5)) (emacs (24))) "convert english words between singular and plural" single ((:commit . "55caa66a7cc6e0b1a76143fd40eff38416928941") (:authors ("Dmitry Galinsky, Howard Yeh")) (:maintainer "Dmitry Galinsky, Howard Yeh") (:keywords "languages" "tools" "wp") (:url . "https://github.com/eschulte/jump.el"))]) (info-beamer . [(20210427 1033) ((emacs (24 4))) "Utilities for working with info-beamer" single ((:commit . "6b4cc29f1aec72d8e23b2c25a99cdd84e6cdc92b") (:authors ("Daniel Kraus" . "daniel@kraus.my")) (:maintainer "Daniel Kraus" . "daniel@kraus.my") (:keywords "tools" "processes" "comm") (:url . "https://github.com/dakra/info-beamer.el"))]) @@ -2535,9 +2543,9 @@ (init-open-recentf . [(20220220 2004) ((emacs (24 4))) "Invoke a command immediately after startup" single ((:commit . "51463effe54ca9390ec339b9678968f35a40dbfd") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "files" "recentf" "after-init-hook") (:url . "https://github.com/zonuexe/init-open-recentf.el"))]) (initsplit . [(20160919 1818) nil "code to split customizations into different files" single ((:commit . "c941d436eb2b10b01c76a582c5a2b23fb30751aa") (:authors ("John Wiegley , Dave Abrahams" . "dave@boostpro.com")) (:maintainer "John Wiegley , Dave Abrahams" . "dave@boostpro.com") (:keywords "lisp") (:url . "http://www.gci-net.com/users/j/johnw/emacs.html"))]) (ink-mode . [(20201105 2242) ((emacs (26 1))) "Major mode for writing interactive fiction in Ink" tar ((:commit . "71d215712067729eb92e766a3b2067e7f3254183") (:authors ("Erik Sjöstrand") ("Damien Picard")) (:maintainer "Damien Picard") (:keywords "languages" "wp" "hypermedia") (:url . "https://github.com/Kungsgeten/ink-mode"))]) - (inkpot-theme . [(20230110 950) ((emacs (24 1))) "A port of vim's inkpot theme" single ((:commit . "fa0746d927ad205b2f17589e67703c18f42aacf4") (:authors ("Sarah Iovan" . "sarah@hwaetageek.com") ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Sarah Iovan" . "sarah@hwaetageek.com") (:url . "https://codeberg.org/ideasman42/emacs-inkpot-theme"))]) + (inkpot-theme . [(20230404 1301) ((emacs (24 1))) "A port of vim's inkpot theme" single ((:commit . "df3db22bf12246cb96a75aae1e8324555a1212f6") (:authors ("Sarah Iovan" . "sarah@hwaetageek.com") ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Sarah Iovan" . "sarah@hwaetageek.com") (:url . "https://codeberg.org/ideasman42/emacs-inkpot-theme"))]) (inline-crypt . [(20170824 900) nil "Simple inline encryption via openssl" tar ((:commit . "af4981c613bfd355d5ef34da1995a8384f167fd9") (:authors ("Daniel Ralston" . "Wubbulous@gmail.com")) (:maintainer "Daniel Ralston" . "Wubbulous@gmail.com") (:keywords "crypt") (:url . "https://github.com/Sodel-the-Vociferous/inline-crypt-el"))]) - (inline-docs . [(20220210 1402) ((emacs (24 3))) "Show inline contextual docs." single ((:commit . "cda596d9ff4c2aa5035692a97c430f6589eafbb1") (:authors ("stardiviner" . "numbchild@gmail.com")) (:maintainer "stardiviner" . "numbchild@gmail.com") (:keywords "inline" "docs" "overlay") (:url . "https://repo.or.cz/inline-docs.git"))]) + (inline-docs . [(20230406 1002) ((emacs (24 3))) "Show inline contextual docs." single ((:commit . "8eb1c43b53a7f51cf74cb85529d108b5ce5efff5") (:authors ("stardiviner" . "numbchild@gmail.com")) (:maintainer "stardiviner" . "numbchild@gmail.com") (:keywords "inline" "docs" "overlay") (:url . "https://repo.or.cz/inline-docs.git"))]) (inlineR . [(20191017 1920) nil "insert Tag for inline image of R graphics" single ((:commit . "bf6450a3540aa3538546d312324c41befd0a4e54") (:authors ("myuhe ")) (:maintainer "myuhe") (:keywords "convenience" "iimage.el" "cacoo.el") (:url . "https://github.com/myuhe/inlineR.el"))]) (insecure-lock . [(20221111 2002) ((emacs (28 1))) "Extensible screen lock framework" single ((:commit . "2750190c70ebf564fe142ab5ee7e44675609b06a") (:authors ("Qiantan Hong" . "qhong@alum.mit.edu")) (:maintainer "Qiantan Hong" . "qhong@alum.mit.edu") (:keywords "unix" "screensaver" "security") (:url . "https://github.com/BlueFlo0d/insecure-lock"))]) (insert-char-preview . [(20201023 2108) ((emacs (24 1))) "Insert Unicode char" single ((:commit . "8f13262ebcb3f271f1d188584d04ca6d87214111") (:authors ("Matsievskiy S.V.")) (:maintainer "Matsievskiy S.V.") (:keywords "convenience") (:url . "https://gitlab.com/matsievskiysv/insert-char-preview"))]) @@ -2546,6 +2554,7 @@ (insert-random . [(20230212 1710) ((emacs (24 5))) "Insert random characters from various character sets" single ((:commit . "a13827fd68457f939e46f95a662752f6f344107c") (:authors ("Lassi Kortela" . "lassi@lassi.io")) (:maintainer "Lassi Kortela" . "lassi@lassi.io") (:keywords "convenience") (:url . "https://github.com/lassik/emacs-insert-random"))]) (insert-shebang . [(20201203 1648) nil "Insert shebang line automatically." single ((:commit . "cc8cea997a8523bce9f303de993af3a73eb0d2e2") (:authors ("Sachin Patil" . "iclcoolster@gmail.com")) (:maintainer "Sachin Patil" . "iclcoolster@gmail.com") (:keywords "shebang" "tool" "convenience") (:url . "https://gitlab.com/psachin/insert-shebang"))]) (insfactor . [(20141117 2) nil "Client for a Clojure project with insfactor in it" single ((:commit . "7ef5446cebb08a17d4106d2e6f3c053e49e1e829") (:authors ("John D. Hume" . "duelin.markers@gmail.com")) (:maintainer "John D. Hume" . "duelin.markers@gmail.com") (:keywords "clojure") (:url . "http://github.com/duelinmarkers/insfactor.el"))]) + (inspire . [(20230310 1557) ((emacs (27 1))) "an interface for inspirehep.net" single ((:commit . "9d15ced8e852135764de3c434753dbcf485b6bc1") (:authors ("Simon Lin" . "n.sibetz@gmail.com")) (:maintainer "Simon Lin" . "n.sibetz@gmail.com") (:keywords "extensions" "tex") (:url . "https://github.com/Simon-Lin/inspire.el"))]) (instapaper . [(20110419 1355) nil "No description available." single ((:commit . "4714ed1b014615f8213e6f93637e4ec1d9d5a37a") (:authors ("Jason F. McBrayer" . "jmcbray@carcosa.net")) (:maintainer "Jason F. McBrayer" . "jmcbray@carcosa.net") (:url . "htts://bitbucket.org/jfm/emacs-instapaper"))]) (intel-hex-mode . [(20180423 31) nil "Mode for Intel Hex files." single ((:commit . "e83c94e1c31a8435a88b3ae395f2bc842ef83217") (:maintainer "Michael Schuldt" . "mbschuldt@gmail.com") (:keywords "tools" "hex") (:url . "https://github.com/mschuldt/intel-hex-mode"))]) (intellij-theme . [(20171017 1415) nil "Inspired by IntelliJ's default theme" single ((:commit . "1bbfff8e6742d18e9b77ed796f44da3b7bd10606") (:authors ("Vladimir Polushin" . "vovapolu@gmail.com")) (:maintainer "Vladimir Polushin" . "vovapolu@gmail.com") (:keywords "faces"))]) @@ -2558,7 +2567,7 @@ (iodine-theme . [(20151031 1639) ((emacs (24))) "A light emacs color theme" single ((:commit . "02fb780e1d8d8a6b9c709bfac399abe1665c6999") (:authors ("Srđan Panić" . "srdja.panic@gmail.com")) (:maintainer "Srđan Panić" . "srdja.panic@gmail.com") (:keywords "themes") (:url . "https://github.com/srdja/iodine-theme"))]) (ipcalc . [(20210903 958) ((cl-lib (0 5))) "IP subnet calculator" single ((:commit . "05fcb5bb8db3ba0c1f9e5f1bfcf0c183828a2426") (:authors ("\"Aleksandar Simic\"" . "asimic@gmail.com")) (:maintainer "\"Aleksandar Simic\"" . "asimic@gmail.com") (:keywords "networking" "tools") (:url . "http://github.com/dotemacs/ipcalc.el"))]) (iplayer . [(20161120 2120) nil "Browse and download BBC TV/radio shows" single ((:commit . "b788fffa4b36bbd558047ffa6be51b1f0f462f23") (:authors ("Christophe Rhodes" . "csr21@cantab.net")) (:maintainer "Christophe Rhodes" . "csr21@cantab.net") (:keywords "multimedia" "bbc") (:url . "https://github.com/csrhodes/iplayer-el"))]) - (ipp . [(20220830 1336) ((cl-lib (0 5)) (emacs (24 1))) "Implementation of the Internet Printing Protocol" single ((:commit . "21d3b3fd5d1e655126ee03dac9d6b46cad9deef6") (:authors ("Eric Marsden" . "eric.marsden@risk-engineering.org")) (:maintainer "Eric Marsden" . "eric.marsden@risk-engineering.org") (:keywords "printing" "hardware") (:url . "https://github.com/emarsden/ipp-el"))]) + (ipp . [(20230303 1138) ((cl-lib (0 5)) (emacs (24 1))) "Implementation of the Internet Printing Protocol" single ((:commit . "8011ef4f550ebfbeefcacc1196a103580c730cfe") (:authors ("Eric Marsden" . "eric.marsden@risk-engineering.org")) (:maintainer "Eric Marsden" . "eric.marsden@risk-engineering.org") (:keywords "printing" "hardware") (:url . "https://github.com/emarsden/ipp-el"))]) (ipretty . [(20180606 522) nil "Interactive Emacs Lisp pretty-printing" single ((:commit . "042f5cc4e6f81d59115e8335c582bb5c571c2585") (:authors ("steckerhalter")) (:maintainer "steckerhalter") (:keywords "pretty-print" "elisp" "buffer") (:url . "https://framagit.org/steckerhalter/ipretty"))]) (ipython-shell-send . [(20190220 2246) ((emacs (24))) "Send code (including magics) to ipython shell" single ((:commit . "0faed86faff02a361f23ce5fc923d0e9b09bb2da") (:authors ("Jack Kamm" . "jackkamm@gmail.com")) (:maintainer "Jack Kamm" . "jackkamm@gmail.com") (:keywords "tools" "processes") (:url . "https://github.com/jackkamm/ipython-shell-send-el"))]) (iqa . [(20200520 1137) ((emacs (24 3))) "Init file(and directory) Quick Access" single ((:commit . "03f90a2f68b2f05d8a2509bf3612a337d3d5b67f") (:url . "https://github.com/a13/iqa.el"))]) @@ -2582,7 +2591,7 @@ (iterator . [(20210109 1859) ((emacs (24)) (cl-lib (0 5))) "A library to create and use elisp iterators objects." single ((:commit . "b514d4d1d0167e5973afbc93a34070d1aa967d82") (:authors ("Thierry Volpiatto ")) (:maintainer "Thierry Volpiatto ") (:url . "https://github.com/thierryvolpiatto/iterator"))]) (ivariants . [(20170823 224) ((emacs (24 3)) (ivs-edit (1 0))) "Ideographic variants editor and browser" tar ((:commit . "ca0b74d32b5d2d77a45cc6ad6edc00be0ee85284") (:authors ("KAWABATA, Taichi ")) (:maintainer "KAWABATA, Taichi ") (:keywords "i18n" "languages") (:url . "http://github.com/kawabata/ivariants"))]) (ivs-edit . [(20170818 1441) ((emacs (24 3)) (dash (2 6 0)) (cl-lib (1 0))) "IVS (Ideographic Variation Sequence) editing tool" tar ((:commit . "5db39c234aa7393b591168a4fd0a9a4cbbca347d") (:authors ("KAWABATA, Taichi ")) (:maintainer "KAWABATA, Taichi ") (:keywords "text") (:url . "http://github.com/kawabata/ivs-edit"))]) - (ivy . [(20220926 1250) ((emacs (24 5))) "Incremental Vertical completYon" tar ((:commit . "29b61fe1f4d5268d750b666a7ffc1269e22c6477") (:authors ("Oleh Krehel" . "ohwoeowho@gmail.com")) (:maintainer "Oleh Krehel" . "ohwoeowho@gmail.com") (:keywords "matching") (:url . "https://github.com/abo-abo/swiper"))]) + (ivy . [(20230326 1253) ((emacs (24 5))) "Incremental Vertical completYon" tar ((:commit . "24a8262767b7917a91ed7ffc11298f28569e3087") (:authors ("Oleh Krehel" . "ohwoeowho@gmail.com")) (:maintainer "Oleh Krehel" . "ohwoeowho@gmail.com") (:keywords "matching") (:url . "https://github.com/abo-abo/swiper"))]) (ivy-avy . [(20211021 1602) ((emacs (24 5)) (ivy (0 13 4)) (avy (0 5 0))) "Avy integration for Ivy" single ((:commit . "bb77cf058d9fbc0a64e73491179e88c32e0b0b47") (:authors ("Oleh Krehel" . "ohwoeowho@gmail.com")) (:maintainer "Oleh Krehel" . "ohwoeowho@gmail.com") (:keywords "convenience") (:url . "https://github.com/abo-abo/swiper"))]) (ivy-bibtex . [(20210927 1205) ((bibtex-completion (1 0 0)) (ivy (0 13 0)) (cl-lib (0 5))) "A bibliography manager based on Ivy" single ((:commit . "bb47f355b0da8518aa3fb516019120c14c8747c9") (:authors ("Justin Burkett" . "justin@burkett.cc")) (:maintainer "Titus von der Malsburg" . "malsburg@posteo.de") (:url . "https://github.com/tmalsburg/helm-bibtex"))]) (ivy-clipmenu . [(20220202 2122) ((emacs (26 1)) (f (0 20 0)) (s (1 12 0)) (dash (2 16 0)) (ivy (0 13 0))) "Ivy client for clipmenu" single ((:commit . "7c200cd4732821187084fad23547ee3f58365062") (:authors ("William Carroll" . "wpcarro@gmail.com")) (:maintainer "William Carroll" . "wpcarro@gmail.com") (:url . "https://github.com/wpcarro/ivy-clipmenu.el"))]) @@ -2606,7 +2615,7 @@ (ivy-posframe . [(20211217 234) ((emacs (26 0)) (posframe (1 0 0)) (ivy (0 13 0))) "Using posframe to show Ivy" single ((:commit . "533a8e368fcabfd534761a5c685ce713376fa594") (:authors ("Feng Shu" . "tumashu@163.com") ("Naoya Yamashita" . "conao3@gmail.com")) (:maintainer "Feng Shu" . "tumashu@163.com") (:keywords "abbrev" "convenience" "matching" "ivy") (:url . "https://github.com/tumashu/ivy-posframe"))]) (ivy-prescient . [(20221216 112) ((emacs (25 1)) (prescient (6 1 0)) (ivy (0 11 0))) "prescient.el + Ivy" single ((:commit . "72b023f5fc1ae2bbf2f51f1786cc012d40671bf4") (:authors ("Radian LLC" . "contact+prescient@radian.codes")) (:maintainer "Radian LLC" . "contact+prescient@radian.codes") (:keywords "extensions") (:url . "https://github.com/raxod502/prescient.el"))]) (ivy-purpose . [(20160724 1003) ((emacs (24)) (ivy (0 8)) (window-purpose (1 5))) "Ivy Interface for Purpose" single ((:commit . "0495f2f3aed64d7e0028125e76a9a68f8fc4107e") (:authors ("Bar Magal (2016)")) (:maintainer "Bar Magal (2016)") (:url . "https://github.com/bmag/ivy-purpose"))]) - (ivy-rich . [(20210409 931) ((emacs (25 1)) (ivy (0 13 0))) "More friendly display transformer for ivy" single ((:commit . "600b8183ed0be8668dcc548cc2c8cb94b001363b") (:authors ("Yevgnen Koh" . "wherejoystarts@gmail.com")) (:maintainer "Yevgnen Koh" . "wherejoystarts@gmail.com") (:keywords "convenience" "ivy") (:url . "https://github.com/Yevgnen/ivy-rich"))]) + (ivy-rich . [(20230228 608) ((emacs (25 1)) (ivy (0 13 0))) "More friendly display transformer for ivy" single ((:commit . "4fdd4669d69c9e8248b361b6e069b27d10e809e4") (:authors ("Yevgnen Koh" . "wherejoystarts@gmail.com")) (:maintainer "Yevgnen Koh" . "wherejoystarts@gmail.com") (:keywords "convenience" "ivy") (:url . "https://github.com/Yevgnen/ivy-rich"))]) (ivy-rtags . [(20191222 920) ((ivy (0 7 0)) (rtags (2 10))) "RTags completion back-end for ivy" single ((:commit . "595055b5316a7c92ba1d638f324f98842a0f41a5") (:authors ("Jan Erik Hanssen" . "jhanssen@gmail.com") ("Anders Bakken" . "agbakken@gmail.com")) (:maintainer "Jan Erik Hanssen" . "jhanssen@gmail.com") (:url . "https://github.com/Andersbakken/rtags"))]) (ivy-searcher . [(20220704 653) ((emacs (25 1)) (ivy (0 8 0)) (searcher (0 1 8)) (s (1 12 0)) (f (0 20 0))) "Ivy interface to use searcher" single ((:commit . "5ed00a1e273cdb33ce356f373427b65fb131021a") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "ivy" "interface" "searcher" "search" "replace" "grep" "ag" "rg") (:url . "https://github.com/jcs-elpa/ivy-searcher"))]) (ivy-spotify . [(20210329 312) ((emacs (26 1)) (espotify (0 1)) (ivy (0 13 1))) "Search spotify with ivy" single ((:commit . "eefcb49d740570f6c874302d87be33e5b0ec54ff") (:authors ("Jose A Ortega Ruiz" . "jao@gnu.org")) (:maintainer "Jose A Ortega Ruiz") (:keywords "multimedia") (:url . "https://codeberg.org/jao/espotify"))]) @@ -2651,9 +2660,10 @@ (jest-test-mode . [(20220722 1947) ((emacs (25 1))) "Minor mode for running Node.js tests using jest" single ((:commit . "3126c5c5c5632da639ea34867a7342d4410d78aa") (:authors ("Raymond Huang" . "rymndhng@gmail.com")) (:maintainer "Raymond Huang" . "rymndhng@gmail.com") (:url . "https://github.com/rymndhng/jest-test-mode.el"))]) (jet . [(20230213 1615) ((emacs (27 1)) (transient (0 3 7))) "Emacs integration for jet Clojure tool" single ((:commit . "90fcdec479d2b1755a1410ae65d53d421f7683c9") (:authors ("Eric Dallo" . "ercdll1337@gmail.com")) (:maintainer "Eric Dallo" . "ercdll1337@gmail.com") (:keywords "tools") (:url . "https://github.com/ericdallo/jet.el"))]) (jetbrains . [(20180301 502) ((emacs (24 3)) (cl-lib (0 5)) (f (0 17))) "JetBrains IDE bridge" single ((:commit . "56f71a17d455581c10d48f6dbb31d9e2126227bf") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "tools" "php") (:url . "https://github.com/emacs-php/jetbrains.el"))]) - (jetbrains-darcula-theme . [(20210602 1430) nil "A complete port of the default JetBrains Darcula theme" single ((:commit . "f57c359044ff1fa90db62a60b6691ff8d65c82f3") (:authors ("Ian Y.E. Pan")) (:maintainer "Ian Y.E. Pan") (:url . "https://github.com/ianpan870102/jetbrains-darcula-emacs-theme"))]) + (jetbrains-darcula-theme . [(20230223 1901) nil "A complete port of the default JetBrains Darcula theme" single ((:commit . "46f153385e50998826ca13e18056c6a972768cfd") (:authors ("Ian Y.E. Pan")) (:maintainer "Ian Y.E. Pan") (:url . "https://github.com/ianpan870102/jetbrains-darcula-emacs-theme"))]) (jg-quicknav . [(20170809 130) ((s (1 9 0)) (cl-lib (0 5))) "Quickly navigate the file system to find a file." single ((:commit . "c8d53e774d63e68a944092c08a026b57da741038") (:authors ("Jeff Gran" . "jeff@jeffgran.com")) (:maintainer "Jeff Gran" . "jeff@jeffgran.com") (:keywords "navigation") (:url . "https://github.com/jeffgran/jg-quicknav"))]) (jinja2-mode . [(20220117 807) nil "A major mode for jinja2" single ((:commit . "03e5430a7efe1d163a16beaf3c82c5fd2c2caee1") (:authors ("Florian Mounier aka paradoxxxzero")) (:maintainer "Florian Mounier aka paradoxxxzero"))]) + (jinx . [(20230406 2124) ((emacs (27 1)) (compat (29 1 4 0))) "Enchanted Spell Checker" tar ((:commit . "8578f7fa7c94dba34dc5067e2940069df58c4fe4") (:authors ("Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainer "Daniel Mendler" . "mail@daniel-mendler.de") (:url . "https://github.com/minad/jinx"))]) (jira-markup-mode . [(20150601 2109) nil "Emacs Major mode for JIRA-markup-formatted text files" single ((:commit . "53bf083fdbece483f1351f32085b424b38c4c1f2") (:authors ("Matthias Nuessler" . "m.nuessler@web.de>")) (:maintainer "Matthias Nuessler" . "m.nuessler@web.de>") (:keywords "jira" "markup") (:url . "https://github.com/mnuessler/jira-markup-mode"))]) (jiralib2 . [(20200520 2031) ((emacs (25)) (request (0 3)) (dash (2 14 1))) "JIRA REST API bindings to Elisp" single ((:commit . "c21c4e759eff549dbda11099f2f680b78d7f5a01") (:authors ("Henrik Nyman" . "h@nyymanni.com")) (:maintainer "Henrik Nyman" . "h@nyymanni.com") (:keywords "comm" "jira" "rest" "api") (:url . "https://github.com/nyyManni/jiralib2"))]) (jist . [(20161229 1721) ((emacs (24 4)) (dash (2 12 0)) (seq (1 11)) (let-alist (1 0 4)) (magit (2 1 0)) (request (0 2 0))) "Gist integration" single ((:commit . "ec4b27eb4051f0084cb3b1e4f19fab9e2db77665") (:authors ("Mario Rodas" . "marsam@users.noreply.github.com")) (:maintainer "Mario Rodas" . "marsam@users.noreply.github.com") (:keywords "convenience") (:url . "https://github.com/emacs-pe/jist.el"))]) @@ -2669,7 +2679,7 @@ (js-auto-beautify . [(20161031 509) ((web-beautify (0 3 1)) (web-mode (14 0 27))) "auto format you js/jsx file" single ((:commit . "6bc9fef474197ca1722cb1e9051b270f80cdd7cc") (:authors (nil . "quanwei9958@126.com")) (:maintainer nil . "quanwei9958@126.com"))]) (js-auto-format-mode . [(20180807 1352) ((emacs (24))) "Minor mode for auto-formatting JavaScript code" single ((:commit . "29d245b4d126a5fc5153a4d8f17396be4165b4a6") (:authors ("Masafumi Koba" . "ybiquitous@gmail.com")) (:maintainer "Masafumi Koba" . "ybiquitous@gmail.com") (:keywords "languages") (:url . "https://github.com/ybiquitous/js-auto-format-mode"))]) (js-codemod . [(20190921 941) ((emacs (24 4))) "Run js-codemod on current sentence or selected region" tar ((:commit . "056bdf3e5e0c807b8cf17edb5834179a90fb722b") (:authors (nil . "Torgeir Thoresen <@torgeir>")) (:maintainer nil . "Torgeir Thoresen <@torgeir>") (:keywords "js" "codemod" "region"))]) - (js-comint . [(20221201 1150) ((emacs (24 3))) "JavaScript interpreter in window." single ((:commit . "30e521ada5806ab780f68e09529715acb88f32cd") (:authors ("Paul Huff" . "paul.huff@gmail.com")) (:maintainer "Chen Bin ") (:keywords "javascript" "node" "inferior-mode" "convenience") (:url . "https://github.com/redguardtoo/js-comint"))]) + (js-comint . [(20230311 230) ((emacs (24 3))) "JavaScript interpreter in window." single ((:commit . "b788bf5d57ad6b902c4096b666c6d78ceff7c116") (:authors ("Paul Huff" . "paul.huff@gmail.com")) (:maintainer "Chen Bin ") (:keywords "javascript" "node" "inferior-mode" "convenience") (:url . "https://github.com/redguardtoo/js-comint"))]) (js-doc . [(20160715 434) nil "Insert JsDoc style comment easily" single ((:commit . "f0606e89d5aa89146f96edb38cf69af0068a9d1e") (:authors ("mooz" . "stillpedant@gmail.com")) (:maintainer "mooz" . "stillpedant@gmail.com") (:keywords "document" "comment") (:url . "https://github.com/mooz/js-doc"))]) (js-format . [(20170119 102) ((emacs (24 1)) (js2-mode (20101228))) "Format or transform code style using NodeJS server with different javascript formatter" tar ((:commit . "544bda9be72b74ec2d442543ba60cff727d96669") (:authors ("James Yang" . "jamesyang999@gmail.com")) (:maintainer "James Yang" . "jamesyang999@gmail.com") (:keywords "js" "javascript" "format" "standard" "jsbeautify" "esformatter" "airbnb") (:url . "http://github.com/futurist/js-format.el"))]) (js-import . [(20230131 1900) ((emacs (24 4)) (f (0 19 0)) (projectile (0 14 0)) (dash (2 13 0))) "Import Javascript files from your current project or dependencies" single ((:commit . "9f8b6bc4f080c7146ce7ee5dd5a6572aeb6f1cc7") (:authors ("Jakob Lind" . "karl.jakob.lind@gmail.com")) (:maintainer "Jakob Lind" . "karl.jakob.lind@gmail.com") (:keywords "tools") (:url . "https://github.com/jakoblind/js-import"))]) @@ -2681,27 +2691,28 @@ (js2hl . [(20201119 816) ((emacs (25 1)) (js2-mode (20190219))) "Highlight/rename things using js2-mode parser" single ((:commit . "8a9a53a861d20ce51a382d6caef48ccd978d8212") (:authors ("Chen Bin ")) (:maintainer "Chen Bin ") (:keywords "convenience") (:url . "https://github.com/redguardtoo/js2hl"))]) (js3-mode . [(20160515 1550) nil "An improved JavaScript editing mode" tar ((:commit . "7fceb21ec56aac7af4b189bb0c0d0cf620327f5a") (:authors ("Thom Blake" . "webmaster@thomblake.com")) (:maintainer "Thom Blake" . "webmaster@thomblake.com") (:keywords "javascript" "languages"))]) (jscs . [(20151015 1749) ((emacs (24 1)) (cl-lib (0 5))) "Consistent JavaScript editing using JSCS" single ((:commit . "9d39d0f2355e69a020bf76242504f3a33e013ccf") (:authors ("papaeye" . "papaeye@gmail.com")) (:maintainer "papaeye" . "papaeye@gmail.com") (:keywords "languages" "convenience") (:url . "https://github.com/papaeye/emacs-jscs"))]) + (jsdoc . [(20230331 647) ((emacs (29 1)) (dash (2 11 0)) (s (1 12 0))) "Insert JSDoc comments" single ((:commit . "10606a37f70cbf419590bbbc292fe1e800435ed5") (:authors ("Isa Mert Gurbuz" . "isamertgurbuz@gmail.com")) (:maintainer "Isa Mert Gurbuz" . "isamertgurbuz@gmail.com") (:url . "https://github.com/isamert/jsdoc.el"))]) (jsfmt . [(20180920 1008) nil "Interface to jsfmt command for javascript files" single ((:commit . "ca141a135c7700eaedef92561d334e1fb7dc28a1") (:authors ("Brett Langdon" . "brett@blangdon.com")) (:maintainer "Brett Langdon" . "brett@blangdon.com") (:url . "https://github.com/brettlangdon/jsfmt.el"))]) (json-mode . [(20211011 630) ((json-snatcher (1 0 0)) (emacs (24 4))) "Major mode for editing JSON files." single ((:commit . "eedb4560034f795a7950fa07016bd4347c368873") (:authors ("Josh Johnston")) (:maintainer "Josh Johnston") (:url . "https://github.com/joshwnj/json-mode"))]) (json-navigator . [(20191213 755) ((emacs (25 1)) (hierarchy (0 6 0))) "View and navigate JSON structures" single ((:commit . "afd902e0b5cde37fad4786515a695d17f1625286") (:authors ("Damien Cassou" . "damien@cassou.me")) (:maintainer "Damien Cassou" . "damien@cassou.me") (:url . "https://github.com/DamienCassou/json-navigator"))]) - (json-par . [(20220919 652) ((emacs (24 4)) (json-mode (1 7 0))) "Minor mode for structural editing of JSON" tar ((:commit . "2dd58826eef67a656efd9897f65d306b5c3eb8b0") (:authors ("taku0" . "mxxouy6x3m_github@tatapa.org")) (:maintainer "taku0" . "mxxouy6x3m_github@tatapa.org") (:keywords "abbrev" "convenience" "files") (:url . "https://github.com/taku0/json-par"))]) + (json-par . [(20230401 901) ((emacs (24 4)) (json-mode (1 7 0))) "Minor mode for structural editing of JSON" tar ((:commit . "9d4503d595c41c5e501f6ce9067b487f8933cd4b") (:authors ("taku0" . "mxxouy6x3m_github@tatapa.org")) (:maintainer "taku0" . "mxxouy6x3m_github@tatapa.org") (:keywords "abbrev" "convenience" "files") (:url . "https://github.com/taku0/json-par"))]) (json-process-client . [(20210525 733) ((emacs (25 1))) "Interact with a TCP process using JSON" single ((:commit . "373b2cc7e3d26dc00594e0b2c1bb66815aad2826") (:authors ("Nicolas Petton" . "nicolas@petton.fr") ("Damien Cassou" . "damien@cassou.me")) (:maintainer "Nicolas Petton" . "nicolas@petton.fr") (:url . "https://gitlab.petton.fr/nico/json-process-client"))]) (json-reformat . [(20220905 2342) ((emacs (24 3))) "Reformatting tool for JSON" single ((:commit . "e9999b1f1fc933c02ff44f4136602b6a45ed59c6") (:authors ("Wataru MIYAGUNI" . "gonngo@gmail.com")) (:maintainer "Wataru MIYAGUNI" . "gonngo@gmail.com") (:keywords "json") (:url . "https://github.com/gongo/json-reformat"))]) (json-rpc . [(20200417 1629) ((emacs (24 1)) (cl-lib (0 5))) "JSON-RPC library" single ((:commit . "81a5a520072e20d18aeab2aac4d66c046b031e56") (:authors ("Christopher Wellons" . "wellons@nullprogram.com")) (:maintainer "Christopher Wellons" . "wellons@nullprogram.com") (:url . "https://github.com/skeeto/elisp-json-rpc"))]) (json-rpc-server . [(20220205 1504) ((emacs (26))) "Server-side JSON-RPC library." single ((:commit . "349e1f4722474bf1f75dbc8eb9d9c59d790b8083") (:authors ("GitHub user \"Jcaw\"")) (:maintainer "GitHub user \"Jcaw\"") (:keywords "tools" "comm" "json" "rpc") (:url . "https://github.com/jcaw/json-rpc-server.el"))]) (json-snatcher . [(20200916 1717) ((emacs (24))) "Grabs the path to JSON values in a JSON file" single ((:commit . "b28d1c0670636da6db508d03872d96ffddbc10f2") (:authors ("Sterling Graham" . "sterlingrgraham@gmail.com")) (:maintainer "Sterling Graham" . "sterlingrgraham@gmail.com") (:url . "http://github.com/sterlingg/json-snatcher"))]) - (jsonian . [(20230117 2212) ((emacs (27 1))) "A major mode for editing JSON files" single ((:commit . "d0583a890a8e43845935c31de9f069192011451e") (:authors ("Ian Wahbe")) (:maintainer "Ian Wahbe") (:url . "https://github.com/iwahbe/jsonian"))]) + (jsonian . [(20230305 1915) ((emacs (27 1))) "A major mode for editing JSON files" single ((:commit . "8827918900f6c3e77846be0b4ad6fb42f670a84f") (:authors ("Ian Wahbe")) (:maintainer "Ian Wahbe") (:url . "https://github.com/iwahbe/jsonian"))]) (jsonl . [(20190623 509) ((emacs (25))) "Utility functions for working with line-delimited JSON" single ((:commit . "3dd0b7bb2b4bce9f9de7367941f0cc78f82049c9") (:authors ("Erik Anderson" . "erik@ebpa.link")) (:maintainer "Erik Anderson" . "erik@ebpa.link") (:keywords "tools") (:url . "https://github.com/ebpa/jsonl.el"))]) (jsonnet-mode . [(20220121 2109) ((emacs (24)) (dash (2 17 0))) "Major mode for editing jsonnet files" single ((:commit . "cef3d352408599a63655002af655d11757579253") (:authors ("Nick Lanham")) (:maintainer "Nick Lanham") (:keywords "languages") (:url . "https://github.com/mgyucht/jsonnet-mode"))]) (jss . [(20130508 1423) ((emacs (24 1)) (websocket (0)) (js2-mode (0))) "An emacs interface to webkit and mozilla debuggers" tar ((:commit . "41749257aecf13c7bd6ed489b5ab3304d06e40bc") (:authors ("Marco Baringer" . "mb@bese.it")) (:maintainer "Marco Baringer" . "mb@bese.it") (:keywords "languages"))]) (jst . [(20150604 1138) ((s (1 9)) (f (0 17)) (dash (2 10)) (pcache (0 3)) (emacs (24 4))) "JS test mode" single ((:commit . "865ff97449a4cbbcb40d38b4908cf4d7b22a5108") (:authors ("Cheung Hoi Yu" . "yeannylam@gmail.com")) (:maintainer "Cheung Hoi Yu" . "yeannylam@gmail.com") (:keywords "js" "javascript" "jasmine" "coffee" "coffeescript") (:url . "https://github.com/cheunghy/jst-mode"))]) (jtags . [(20160211 2029) nil "enhanced tags functionality for Java development" tar ((:commit . "f7d29e1635ef7ee4ee2cdb8f1f6ab83e1015c84a") (:authors ("Alexander Baltatzis" . "alexander@baltatzis.com") ("Johan Dykstrom" . "jody4711-sf@yahoo.se")) (:maintainer "Johan Dykstrom" . "jody4711-sf@yahoo.se") (:keywords "languages" "tools") (:url . "http://jtags.sourceforge.net"))]) - (julia-formatter . [(20220106 1414) ((emacs (27 1))) "Use JuliaFormatter.jl for julia code" single ((:commit . "a17490fbf8902fc11827651f567924edb22f81cb") (:authors ("Felipe Lema" . "felipe.lema@mortemale.org")) (:maintainer "Felipe Lema" . "felipe.lema@mortemale.org") (:keywords "convenience" "tools") (:url . "https://codeberg.org/FelipeLema/julia-formatter.el"))]) + (julia-formatter . [(20230301 1807) ((emacs (27 1)) (session-async (0 0 4))) "Use JuliaFormatter.jl for julia code" single ((:commit . "6297a3e6b4b24ec0158b43b886be346043c2772f") (:authors ("Felipe Lema" . "felipe.lema@mortemale.org")) (:maintainer "Felipe Lema" . "felipe.lema@mortemale.org") (:keywords "convenience" "tools") (:url . "https://codeberg.org/FelipeLema/julia-formatter.el"))]) (julia-mode . [(20230119 1840) ((emacs (24 3))) "Major mode for editing Julia source code" tar ((:commit . "7aafa8e77df64a47fa4729a0c1ea572b5bc8e30e") (:keywords "languages") (:url . "https://github.com/JuliaEditorSupport/julia-emacs"))]) (julia-repl . [(20230112 1929) ((emacs (25 1)) (s (1 12))) "A minor mode for a Julia REPL" single ((:commit . "57a15dfafed680ad7d81f779d414e8cb6717417c") (:authors ("Tamas Papp" . "tkpapp@gmail.com")) (:maintainer "Tamas Papp" . "tkpapp@gmail.com") (:keywords "languages") (:url . "https://github.com/tpapp/julia-repl"))]) (julia-shell . [(20161125 1910) ((julia-mode (0 3))) "Major mode for an inferior Julia shell" tar ((:commit . "583a0b2ca20461ab4356929fd0f2212c22341b69") (:authors ("Dennis Ogbe" . "dogbe@purdue.edu")) (:maintainer "Dennis Ogbe" . "dogbe@purdue.edu"))]) - (julia-snail . [(20220927 704) ((emacs (26 2)) (dash (2 16 0)) (julia-mode (0 3)) (s (1 12 0)) (spinner (1 7 3)) (vterm (0 0 1)) (popup (0 5 9))) "Julia Snail" tar ((:commit . "0e6fa5180447024c794cb8186c782c5cf28ae68e") (:url . "https://github.com/gcv/julia-snail"))]) - (julia-ts-mode . [(20230124 1427) ((emacs (29)) (julia-mode (0 4))) "Major mode for Julia source code using tree-sitter" single ((:commit . "d78307d95a2a97abc54c918eb8feffa62b26673b") (:authors ("Ronan Arraes Jardim Chagas")) (:maintainer "Ronan Arraes Jardim Chagas") (:keywords "julia" "languages" "tree-sitter") (:url . "https://github.com/ronisbr/julia-ts-mode"))]) + (julia-snail . [(20230331 2240) ((emacs (26 2)) (dash (2 16 0)) (julia-mode (0 3)) (s (1 12 0)) (spinner (1 7 3)) (vterm (0 0 1)) (popup (0 5 9))) "Julia Snail" tar ((:commit . "35e54bdf7d3d585772af6d7b0789bc4ca2d12be3") (:url . "https://github.com/gcv/julia-snail"))]) + (julia-ts-mode . [(20230318 2210) ((emacs (29)) (julia-mode (0 4))) "Major mode for Julia source code using tree-sitter" single ((:commit . "33ea957ef696155ad45a952d653a9ff18d45c866") (:authors ("Ronan Arraes Jardim Chagas")) (:maintainer "Ronan Arraes Jardim Chagas") (:keywords "julia" "languages" "tree-sitter") (:url . "https://github.com/ronisbr/julia-ts-mode"))]) (julia-vterm . [(20220912 246) ((emacs (25 1)) (vterm (0 0 1))) "A mode for Julia REPL using vterm" single ((:commit . "e4d1c28935c47429442ddfcd735cb8d8c2d8db66") (:authors ("Shigeaki Nishina")) (:maintainer "Shigeaki Nishina") (:keywords "languages" "julia") (:url . "https://github.com/shg/julia-vterm.el"))]) (jumblr . [(20170727 2043) ((s (1 8 0)) (dash (2 2 0))) "an anagram game for emacs" tar ((:commit . "34533dfb9db8538c005f4eaffafeff7ed193729f") (:keywords "anagram" "word game" "games") (:url . "https://github.com/mkmcc/jumblr"))]) (jump . [(20210110 2237) ((findr (0 7)) (inflections (2 4)) (cl-lib (0 5))) "build functions which contextually jump between files" single ((:commit . "55caa66a7cc6e0b1a76143fd40eff38416928941") (:authors ("Eric Schulte")) (:maintainer "Eric Schulte") (:keywords "project" "convenience" "navigation") (:url . "http://github.com/eschulte/jump.el"))]) @@ -2710,35 +2721,36 @@ (jump-tree . [(20171014 1551) nil "Treat position history as a tree" tar ((:commit . "282267dc6305889e31d46b405b7ad4dfe5923b66") (:authors ("Wen Yang" . "yangwen0228@foxmail.com")) (:maintainer "Wen Yang" . "yangwen0228@foxmail.com") (:keywords "convenience" "position" "jump" "tree") (:url . "https://github.com/yangwen0228/jump-tree"))]) (jumplist . [(20151120 345) ((cl-lib (0 5))) "Jump like vim jumplist or ex jumplist" single ((:commit . "c482d137d95bc5e1bcd790cdbde25b7f729b2502") (:authors ("ganmacs ")) (:maintainer "ganmacs ") (:keywords "jumplist" "vim") (:url . "https://github.com/ganmacs/jumplist"))]) (jupyter . [(20230214 215) ((emacs (26)) (zmq (0 10 3)) (cl-lib (0 5)) (simple-httpd (1 5 0)) (websocket (1 9))) "Jupyter" tar ((:commit . "eebeef1293287075f65d27f5442bb151bf27d92a") (:authors ("Nathaniel Nicandro" . "nathanielnicandro@gmail.com")) (:maintainer "Nathaniel Nicandro" . "nathanielnicandro@gmail.com") (:url . "https://github.com/dzop/emacs-jupyter"))]) - (just-mode . [(20221107 1633) ((emacs (26 1))) "Justfile editing mode" single ((:commit . "45a221063093f3461816913acdaba898e62b42ce") (:authors ("Leon Barrett" . "leon@barrettnexus.com")) (:maintainer "Leon Barrett" . "leon@barrettnexus.com") (:keywords "files" "languages" "tools") (:url . "https://github.com/leon-barrett/just-mode.el"))]) + (just-mode . [(20230303 2255) ((emacs (26 1))) "Justfile editing mode" single ((:commit . "d7f52eab8fa3828106f80acb1e2176e5877b7191") (:authors ("Leon Barrett" . "leon@barrettnexus.com")) (:maintainer "Leon Barrett" . "leon@barrettnexus.com") (:keywords "files" "languages" "tools") (:url . "https://github.com/leon-barrett/just-mode.el"))]) (justl . [(20221222 1650) ((transient (0 1 0)) (emacs (25 3)) (s (1 2 0)) (f (0 20 0))) "Major mode for driving just files" single ((:commit . "141daaa4b0dc07fe25423609dcd14441a9f2613e") (:authors ("Sibi Prabakaran")) (:maintainer "Sibi Prabakaran") (:keywords "just" "justfile" "tools" "processes") (:url . "https://github.com/psibi/justl.el"))]) (jvm-mode . [(20150422 708) ((dash (2 6 0)) (emacs (24))) "Monitor and manage your JVMs" single ((:commit . "3355dbaf5b0185aadfbad24160399abb32c5bea0") (:authors ("Martin Trojer" . "martin.trojer@gmail.com")) (:maintainer "Martin Trojer" . "martin.trojer@gmail.com") (:keywords "convenience") (:url . "https://github.com/martintrojer/jvm-mode.el"))]) - (k8s-mode . [(20211121 518) ((emacs (24 3)) (yaml-mode (0 0 10))) "Major mode for Kubernetes configuration file" tar ((:commit . "083bcffbfeeaf5e79015a012b4dbf2f283a493ab") (:authors ("Giap Tran" . "txgvnn@gmail.com")) (:maintainer "Giap Tran" . "txgvnn@gmail.com") (:url . "https://github.com/TxGVNN/emacs-k8s-mode"))]) - (kaesar . [(20230212 743) ((emacs (24 3))) "AES algorithm encrypt/decrypt" single ((:commit . "d62b18e888d69d27b0b74cf47224a1ac204dfb0b") (:authors ("Masahiro Hayashi" . "mhayashi1120@gmail.com")) (:maintainer "Masahiro Hayashi" . "mhayashi1120@gmail.com") (:keywords "data") (:url . "https://github.com/mhayashi1120/Emacs-kaesar"))]) - (kaesar-file . [(20230212 743) ((emacs (24 3)) (kaesar (0 1 1))) "AES encrypt/decrypt file" single ((:commit . "d62b18e888d69d27b0b74cf47224a1ac204dfb0b") (:authors ("Masahiro Hayashi" . "mhayashi1120@gmail.com")) (:maintainer "Masahiro Hayashi" . "mhayashi1120@gmail.com") (:keywords "data" "files") (:url . "https://github.com/mhayashi1120/Emacs-kaesar"))]) - (kaesar-mode . [(20230212 755) ((emacs (24 3)) (kaesar (0 1 4))) "AES encrypt/decrypt buffer" single ((:commit . "48b7160a817cb1e430726e1d2243d921c3f0508f") (:authors ("Masahiro Hayashi" . "mhayashi1120@gmail.com")) (:maintainer "Masahiro Hayashi" . "mhayashi1120@gmail.com") (:keywords "data" "convenience") (:url . "https://github.com/mhayashi1120/Emacs-kaesar"))]) + (k8s-mode . [(20230305 1039) ((emacs (24 3)) (yaml-mode (0 0 10))) "Major mode for Kubernetes configuration file" tar ((:commit . "83266cecd6a39cdf57d124270646047860bfb7ab") (:authors ("Giap Tran" . "txgvnn@gmail.com")) (:maintainer "Giap Tran" . "txgvnn@gmail.com") (:url . "https://github.com/TxGVNN/emacs-k8s-mode"))]) + (kaesar . [(20230221 108) ((emacs (24 3)) (kaesar-pbkdf2 (0 9 0))) "AES algorithm encrypt/decrypt" single ((:commit . "75655238e0dcdb77a74d685cc4f3368fcd284020") (:authors ("Masahiro Hayashi" . "mhayashi1120@gmail.com")) (:maintainer "Masahiro Hayashi" . "mhayashi1120@gmail.com") (:keywords "data") (:url . "https://github.com/mhayashi1120/Emacs-kaesar"))]) + (kaesar-file . [(20230221 108) ((emacs (24 3)) (kaesar (0 1 1))) "AES encrypt/decrypt file" single ((:commit . "75655238e0dcdb77a74d685cc4f3368fcd284020") (:authors ("Masahiro Hayashi" . "mhayashi1120@gmail.com")) (:maintainer "Masahiro Hayashi" . "mhayashi1120@gmail.com") (:keywords "data" "files") (:url . "https://github.com/mhayashi1120/Emacs-kaesar"))]) + (kaesar-mode . [(20230221 108) ((emacs (24 3)) (kaesar (0 1 4))) "AES encrypt/decrypt buffer" single ((:commit . "75655238e0dcdb77a74d685cc4f3368fcd284020") (:authors ("Masahiro Hayashi" . "mhayashi1120@gmail.com")) (:maintainer "Masahiro Hayashi" . "mhayashi1120@gmail.com") (:keywords "data" "convenience") (:url . "https://github.com/mhayashi1120/Emacs-kaesar"))]) (kakapo-mode . [(20171004 451) ((cl-lib (0 5))) "TABS (hard or soft) for indentation (leading whitespace), and SPACES for alignment." single ((:commit . "67d516138172fd60782df94454b3d0bd247e84f3") (:keywords "indentation") (:url . "https://github.com/listx/kakapo-mode"))]) (kakoune . [(20230206 2037) ((ryo-modal (0 45)) (multiple-cursors (1 4)) (expand-region (0 11 0)) (emacs (25 1))) "A simulation, but not emulation, of kakoune" tar ((:commit . "b39c5605e896c55ea246f755c46171bd6d0768a8") (:authors ("Joseph Morag" . "jm4157@columbia.edu")) (:maintainer "Joseph Morag" . "jm4157@columbia.edu") (:url . "https://github.com/jmorag/kakoune.el"))]) (kaleidoscope . [(20170808 817) ((s (1 11 0))) "Controlling Kaleidoscope-powered devices." single ((:commit . "b89a243f6024099192f1bc38d8a54e3e7a654090") (:authors ("Gergely Nagy")) (:maintainer "Gergely Nagy") (:url . "https://github.com/algernon/kaleidoscope.el"))]) (kaleidoscope-evil-state-flash . [(20170728 1020) ((evil (1 2 12)) (kaleidoscope (0 1 0)) (s (1 11 0))) "Flash keyboard LEDs when changing Evil state" single ((:commit . "5b88327350c3d6375ef1d43fb31342eaabd88fdc") (:authors ("Gergely Nagy")) (:maintainer "Gergely Nagy") (:url . "https://github.com/algernon/kaleidoscope.el"))]) (kana . [(20210531 1427) ((emacs (24 4)) (dash (2 17 0))) "Learn Japanese hiragana and katakana" single ((:commit . "d3d550aad67ef8625b3860598bf3622f5b2a7d32") (:authors ("Damon Chan" . "elecming@gmail.com")) (:maintainer "Damon Chan" . "elecming@gmail.com") (:keywords "tools") (:url . "https://github.com/chenyanming/kana"))]) - (kanban . [(20230206 2131) nil "Parse org-todo headlines to use org-tables as Kanban tables" single ((:commit . "9b588f94efb5a784c9bc10ad66f424b253c5fe5e") (:authors ("Arne Babenhauserheide" . "arne_bab@web.de")) (:maintainer "Arne Babenhauserheide" . "arne_bab@web.de") (:keywords "outlines" "convenience"))]) + (kanban . [(20230210 1505) nil "Parse org-todo headlines to use org-tables as Kanban tables" single ((:commit . "d70fa7acab2bfcbb7d3da43c1343073f7eff4998") (:authors ("Arne Babenhauserheide" . "arne_bab@web.de")) (:maintainer "Arne Babenhauserheide" . "arne_bab@web.de") (:keywords "outlines" "convenience"))]) (kanji-mode . [(20160826 1139) nil "View stroke order for kanji characters at cursor" tar ((:commit . "5e9d5b72468ece11cfb81b729be6babf63ede425") (:authors ("Wojciech Gac" . "wojciech.s.gac@gmail.com")) (:maintainer "Wojciech Gac" . "wojciech.s.gac@gmail.com") (:url . "http://github.com/wsgac/kanji-mode "))]) (kaocha-runner . [(20190904 1950) ((emacs (26)) (s (1 4 0)) (cider (0 21 0)) (parseedn (0 1 0))) "A package for running Kaocha tests via CIDER." single ((:commit . "c4ec9cdc817e5f4c3f8d6013e44ea2df8f3eb07f") (:authors ("Magnar Sveen" . "magnars@gmail.com")) (:maintainer "Magnar Sveen" . "magnars@gmail.com") (:url . "https://github.com/magnars/kaocha-runner.el"))]) - (kaolin-themes . [(20230126 2302) ((emacs (25 1)) (autothemer (0 2 2)) (cl-lib (0 6))) "A set of eye pleasing themes" tar ((:commit . "e69a183c1173f7f9ee19ad06ab109ade3811ae77") (:authors ("Ogden Webb" . "ogdenwebb@gmail.com")) (:maintainer "Ogden Webb" . "ogdenwebb@gmail.com") (:keywords "dark" "light" "teal" "blue" "violet" "purple" "brown" "theme" "faces") (:url . "https://github.com/ogdenwebb/emacs-kaolin-themes"))]) + (kaolin-themes . [(20230402 1851) ((emacs (25 1)) (autothemer (0 2 2)) (cl-lib (0 6))) "A set of eye pleasing themes" tar ((:commit . "facb2a08d3179103d4c3a9905b37c87831fe1665") (:authors ("Ogden Webb" . "ogdenwebb@gmail.com")) (:maintainer "Ogden Webb" . "ogdenwebb@gmail.com") (:keywords "dark" "light" "teal" "blue" "violet" "purple" "brown" "theme" "faces") (:url . "https://github.com/ogdenwebb/emacs-kaolin-themes"))]) (kaomoji . [(20220721 441) ((emacs (24 3)) (helm-core (3 6 0))) "Input kaomoji superb easily" tar ((:commit . "fba0018a13eba70c2bffc6153dcfee99937fa3d6") (:authors ("Ono Hiroko" . "azazabc123@gmail.com")) (:maintainer "Ono Hiroko" . "azazabc123@gmail.com") (:keywords "tools" "fun") (:url . "https://github.com/kuanyui/kaomoji.el"))]) (kapacitor . [(20190414 1908) ((emacs (25 1)) (magit (2 13 0)) (magit-popup (2 12 4))) "Main file for kapacitor-mode" single ((:commit . "e3300d8b4017a2f66b0d929cb85bcc7ee2612072") (:authors ("Manoj Kumar Manikchand" . "manojm.321@gmail.com")) (:maintainer "Manoj Kumar Manikchand" . "manojm.321@gmail.com") (:keywords "kapacitor" "emacs" "magit" "tools") (:url . "http://github.com/Manoj321/kapacitor-el"))]) (karma . [(20160220 1245) ((pkg-info (0 4)) (emacs (24))) "Karma Test Runner Emacs Integration" single ((:commit . "31d3e7708246183d7ed0686be92bf23140af348c") (:authors ("Samuel Tonini")) (:maintainer "Samuel Tonini") (:keywords "language" "javascript" "js" "karma" "testing") (:url . "http://github.com/tonini/karma.el"))]) (kconfig-mode . [(20220604 1415) ((emacs (24 3))) "Major mode for editing Kconfig files" single ((:commit . "cd87b71c8c1739d026645ece0bbd20055a7a2d4a") (:authors ("Dela Anthonio" . "dell.anthonio@gmail.com")) (:maintainer "Dela Anthonio" . "dell.anthonio@gmail.com") (:keywords "kconfig" "languages" "linux" "kernel") (:url . "https://github.com/delaanthonio/kconfig-mode"))]) + (kconfig-ref . [(20230220 1207) ((emacs (24 4)) (ripgrep (0 4 0)) (projectile (2 7 0))) "A simple package for looking up kconfig symbol quickly" single ((:commit . "dfb127fa5ac003a06f108d2e876c84a1931e5678") (:authors ("Jason Kim" . "sukbeom.kim@gmail.com")) (:maintainer "Jason Kim" . "sukbeom.kim@gmail.com") (:keywords "tools" "kconfig" "linux" "kernel") (:url . "https://github.com/seokbeomkim/kconfig-ref"))]) (kdeconnect . [(20210519 2016) nil "An interface for KDE Connect" single ((:commit . "4977af8cb5fdc21da770f3ee43ad7823f2937da3") (:authors ("Carl Lieberman" . "dev@carl.ac")) (:maintainer "Carl Lieberman" . "dev@carl.ac") (:keywords "kdeconnect" "android"))]) (keepass-mode . [(20211030 958) ((emacs (27))) "Mode for KeePass DB." tar ((:commit . "f432bb60f9f3bd027025140d723906dcabeefaef") (:authors ("Ignasi Fosch" . "natx@y10k.ws")) (:maintainer "Ignasi Fosch" . "natx@y10k.ws") (:keywords "data" "files" "tools") (:url . "https://github.com/ifosch/keepass-mode"))]) (keg . [(20220923 958) ((emacs (24 1))) "Modern Elisp package development system" tar ((:commit . "7fbfd987d35e29eaab2ebad4f0ed6ee2e2adfe28") (:authors ("Naoya Yamashita" . "conao3@gmail.com")) (:maintainer "Naoya Yamashita" . "conao3@gmail.com") (:keywords "convenience") (:url . "https://github.com/conao3/keg.el"))]) (keg-mode . [(20220307 829) ((emacs (24 4))) "Major mode for editing Keg files" single ((:commit . "d2ef9cfaee1256849291cfade3d730667f55aaf2") (:authors ("Naoya Yamashita" . "conao3@gmail.com")) (:maintainer "Naoya Yamashita" . "conao3@gmail.com") (:keywords "convenience") (:url . "https://github.com/conao3/keg.el"))]) - (kele . [(20230205 1814) ((emacs (28 1)) (async (1 9 7)) (dash (2 19 1)) (f (0 20 0)) (ht (2 3)) (plz (0 3)) (s (1 13 0)) (yaml (0 5 1))) "Spritzy Kubernetes cluster management" tar ((:commit . "8faeb28bcef6d4a3d314364f1b7252e7e6f916a8") (:authors ("Jonathan Jin" . "me@jonathanj.in")) (:maintainer "Jonathan Jin" . "me@jonathanj.in") (:keywords "kubernetes" "tools") (:url . "https://github.com/jinnovation/kele.el"))]) + (kele . [(20230326 33) ((emacs (28 1)) (async (1 9 7)) (dash (2 19 1)) (f (0 20 0)) (ht (2 3)) (plz (0 4)) (s (1 13 0)) (yaml (0 5 1))) "Spritzy Kubernetes cluster management" single ((:commit . "15e841fb7bbc08545534e466ce831d6e80fd8901") (:authors ("Jonathan Jin" . "me@jonathanj.in")) (:maintainer "Jonathan Jin" . "me@jonathanj.in") (:keywords "kubernetes" "tools") (:url . "https://github.com/jinnovation/kele.el"))]) (kerl . [(20150424 2005) nil "Emacs integration for kerl" single ((:commit . "1732ee26213f021bf040919c45ad276aafcaae14") (:authors ("Correl Roush" . "correl@gmail.com")) (:maintainer "Correl Roush" . "correl@gmail.com") (:keywords "tools") (:url . "http://github.com/correl/kerl.el/"))]) (key-assist . [(20230122 718) ((emacs (24 3))) "Minibuffer keybinding cheatsheet and launcher" single ((:commit . "41a958ca6b038586bfdcf01045bb8b9d379248fe") (:authors ("Boruch Baum" . "boruch_baum@gmx.com")) (:maintainer "Boruch Baum" . "boruch_baum@gmx.com") (:keywords "abbrev" "convenience" "docs" "help") (:url . "https://github.com/Boruch-Baum/emacs-key-assist"))]) (key-chord . [(20201222 2030) ((emacs (24))) "map pairs of simultaneously pressed keys to commands" single ((:commit . "7f7fd7c5bd2b996fa054779357e1566f7989e07d") (:authors ("David Andersson ")) (:maintainer "David Andersson ") (:keywords "keyboard" "chord" "input"))]) - (key-combo . [(20150324 1439) nil "map key sequence to commands" single ((:commit . "09a917bdfd3b309b4b3cbe3b11212e1ae6fab38d") (:authors ("Yuuki Arisawa" . "yuuki.ari@gmail.com")) (:maintainer "Vitalie Spinu" . "spinuvit@gmail.com") (:keywords "keyboard" "input") (:url . "https://github.com/uk-ar/key-combo"))]) + (key-combo . [(20230323 829) nil "map key sequence to commands" single ((:commit . "16fb73522d53547ef38f3710aff7c0b01005d576") (:authors ("Yuuki Arisawa" . "yuuki.ari@gmail.com")) (:maintainer "Vitalie Spinu" . "spinuvit@gmail.com") (:keywords "keyboard" "input") (:url . "https://github.com/uk-ar/key-combo"))]) (key-intercept . [(20140211 749) nil "Intercept prefix keys" single ((:commit . "d9a60edb4ce893f2d3d94f242164fdcc62d43cf2") (:authors ("INA Lintaro ")) (:maintainer "INA Lintaro ") (:keywords "keyboard") (:url . "http://github.com/tarao/key-intercept-el"))]) (key-leap . [(20160831 1447) ((emacs (24 3))) "Leap between lines by typing keywords" single ((:commit . "b3f6ef15c8a13870475d5af159fa24b30f97dea0") (:authors ("Martin Rykfors" . "martinrykfors@gmail.com")) (:maintainer "Martin Rykfors" . "martinrykfors@gmail.com") (:keywords "point" "convenience") (:url . "https://github.com/MartinRykfors/key-leap"))]) (key-quiz . [(20200226 2129) ((emacs (26))) "Emacs Keys Quiz" single ((:commit . "1ee67f3f8977d95785e021f7896685de1979137e") (:authors ("Federico Tedin" . "federicotedin@gmail.com")) (:maintainer "Federico Tedin" . "federicotedin@gmail.com") (:keywords "games") (:url . "https://github.com/federicotdn/key-quiz"))]) @@ -2758,9 +2770,9 @@ (kfg . [(20140909 538) ((f (0 17 1))) "an emacs configuration system" single ((:commit . "ffc35b77f227d4c64a1271ec30d31333ffeb0013") (:authors ("Austin Bingham" . "austin.bingham@gmail.com")) (:maintainer "Austin Bingham" . "austin.bingham@gmail.com") (:url . "https://github.com/abingham/kfg"))]) (khalel . [(20230122 1139) ((emacs (27 1))) "Import, edit and create calendar events through khal" tar ((:commit . "fbd4b4d6ae8f152140674e843ed7d82d223d52fe") (:authors ("Hanno Perrey ")) (:maintainer "Hanno Perrey" . "hanno@hoowl.se") (:keywords "event" "calendar" "ics" "khal") (:url . "https://gitlab.com/hperrey/khalel"))]) (khardel . [(20220223 934) ((emacs (27 1)) (yaml-mode (0 0 13))) "Integrate with khard" tar ((:commit . "1436ec5ef1b5b26104a4735ee64c0afe148700de") (:authors ("Damien Cassou" . "damien@cassou.me")) (:maintainer "Damien Cassou" . "damien@cassou.me") (:url . "https://github.com/DamienCassou/khardel"))]) - (khoj . [(20230218 231) ((emacs (27 1)) (transient (0 3 0))) "Natural, Incremental Search for your Second Brain" single ((:commit . "61b6ee2857b92721fc2c7e1329ae476a8d41f040") (:authors ("Debanjum Singh Solanky" . "debanjum@gmail.com")) (:maintainer "Debanjum Singh Solanky" . "debanjum@gmail.com") (:keywords "search" "org-mode" "outlines" "markdown" "beancount" "ledger" "image") (:url . "https://github.com/debanjum/khoj/tree/master/src/interface/emacs"))]) + (khoj . [(20230331 1113) ((emacs (27 1)) (transient (0 3 0)) (dash (2 19 1))) "A search assistant for your second brain" single ((:commit . "35aa06067fb2b35ac79344f1af407fcc6b34083d") (:authors ("Debanjum Singh Solanky" . "debanjum@gmail.com")) (:maintainer "Debanjum Singh Solanky" . "debanjum@gmail.com") (:keywords "search" "chat" "org-mode" "outlines" "markdown" "beancount" "image") (:url . "https://github.com/debanjum/khoj/tree/master/src/interface/emacs"))]) (kibit-helper . [(20150508 1533) ((s (0 8)) (emacs (24))) "Conveniently use the Kibit Leiningen plugin from Emacs" single ((:commit . "ec5f154db3bb0c838e86f527353f08644cede926") (:authors ("Jonas Enlund") ("James Elliott" . "james@brunchboy.com")) (:maintainer "Jonas Enlund") (:keywords "languages" "clojure" "kibit") (:url . "http://www.github.com/brunchboy/kibit-helper"))]) - (kill-file-path . [(20221205 1119) ((emacs (26))) "Copy file name into kill ring" single ((:commit . "88de62d038d7e6e0e0a217c4773a1871549c7c3d") (:authors ("Adam Chyła" . "adam@chyla.org")) (:maintainer "Adam Chyła" . "adam@chyla.org") (:keywords "files") (:url . "https://github.com/chyla/kill-file-path/kill-file-path.el"))]) + (kill-file-path . [(20230306 1041) ((emacs (26))) "Copy file name into kill ring" single ((:commit . "5dcbce69cbae17665216a32dd20f27de54c62972") (:authors ("Adam Chyła" . "adam@chyla.org")) (:maintainer "Adam Chyła" . "adam@chyla.org") (:keywords "files") (:url . "https://github.com/chyla/kill-file-path/kill-file-path.el"))]) (kill-or-bury-alive . [(20210320 1231) ((emacs (24 4)) (cl-lib (0 5))) "Precise control over buffer killing in Emacs" single ((:commit . "388067e764bf3922234196e2e9dd9e8f664c634d") (:authors ("Mark Karpov" . "markkarpov92@gmail.com")) (:maintainer "Mark Karpov" . "markkarpov92@gmail.com") (:keywords "buffer" "killing" "convenience") (:url . "https://github.com/mrkkrp/kill-or-bury-alive"))]) (kill-ring-search . [(20140422 1555) nil "incremental search for the kill ring" single ((:commit . "23535b4a01a1cb1574604e36c49614e84e85c883") (:authors ("Nikolaj Schumacher ")) (:maintainer "Nikolaj Schumacher ") (:keywords "convenience" "matching") (:url . "http://nschum.de/src/emacs/kill-ring-search/"))]) (killer . [(20190128 10) nil "kill and delete text" single ((:commit . "ace0547944933440384ceeb5876b1f68c082d540") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "convenience") (:url . "http://github.com/tarsius/killer"))]) @@ -2769,8 +2781,9 @@ (kivy-mode . [(20220306 810) nil "Emacs major mode for editing Kivy files" single ((:commit . "023bd79b90f9831b45bb8eb449346648aa5fe5f8") (:authors ("Dean Serenevy" . "dean@serenevy.net")) (:maintainer "Dean Serenevy" . "dean@serenevy.net"))]) (kiwix . [(20220316 847) ((emacs (25 1)) (request (0 3 0))) "Searching offline Wikipedia through Kiwix." tar ((:commit . "444f686a7f75db788d54f544b923a3532732eb8b") (:authors ("stardiviner" . "numbchild@gmail.com")) (:maintainer "stardiviner" . "numbchild@gmail.com") (:keywords "kiwix" "wikipedia") (:url . "https://repo.or.cz/kiwix.el.git"))]) (kixtart-mode . [(20150611 1604) ((emacs (24))) "major mode for Kixtart scripting files" single ((:commit . "1c2356797e7b766bbaaa2b341176a8b10499cd79") (:authors ("Ryrun ")) (:maintainer "Ryrun ") (:keywords "languages") (:url . "https://github.com/ryrun/kixtart-mode"))]) + (kkp . [(20230403 2156) ((emacs (27 1)) (compat (29 1 3 4))) "Enable support for the Kitty Keyboard Protocol" single ((:commit . "5652ba0bfa7a4c03daffc301c9ca4a9899c4f440") (:authors ("Benjamin Orthen" . "contact@orthen.net")) (:maintainer "Benjamin Orthen" . "contact@orthen.net") (:keywords "terminals") (:url . "https://github.com/benjaminor/kkp"))]) (klere-theme . [(20230214 213) ((emacs (24))) "A dark theme with lambent color highlights and incremental grays" single ((:commit . "61d2cd649a1cf57ce61063f76b395f21f358372e") (:authors ("Wamm K. D." . "jaft.r@outlook.com")) (:maintainer "Wamm K. D." . "jaft.r@outlook.com") (:url . "https://codeberg.org/WammKD/emacs-klere-theme"))]) - (kmacro-x . [(20220323 2215) ((emacs (27 2))) "Keyboard macro helpers and extensions" single ((:commit . "429abd82c97031948b7681197551bb77708bd174") (:authors ("Wojciech Siewierski")) (:maintainer "Wojciech Siewierski") (:keywords "convenience") (:url . "https://github.com/vifon/kmacro-x.el"))]) + (kmacro-x . [(20230313 1051) ((emacs (27 2))) "Keyboard macro helpers and extensions" tar ((:commit . "da76f841776c26f59e31ab17bc942a0b34a18292") (:authors ("Wojciech Siewierski")) (:maintainer "Wojciech Siewierski") (:keywords "convenience") (:url . "https://github.com/vifon/kmacro-x.el"))]) (know-your-http-well . [(20160208 2305) nil "Look up the meaning of HTTP headers, methods, relations, status codes" tar ((:commit . "c381a9735f3ea86ebc9667e35cdfeab0b67fefb7"))]) (kodi-remote . [(20190622 1325) ((request (0 2 0)) (let-alist (1 0 4)) (json (1 4)) (cl-lib (0 5)) (f (20190109 906))) "Remote Control for Kodi" single ((:commit . "f5e932036c16e2b61a63020e006fc601e38d181e") (:authors ("Stefan Huchler" . "stefan.huchler@mail.de")) (:maintainer "Stefan Huchler" . "stefan.huchler@mail.de") (:keywords "kodi" "tools" "convinience") (:url . "http://github.com/spiderbit/kodi-remote.el"))]) (kolon-mode . [(20140122 1134) nil "Syntax highlighting for Text::Xslate's Kolon syntax" single ((:commit . "5af0955e280ae991862189ebecd3937c5fc8fb9f") (:authors ("Sam Tran")) (:maintainer "Sam Tran") (:keywords "xslate" "perl") (:url . "https://github.com/samvtran/kolon-mode"))]) @@ -2795,7 +2808,7 @@ (kuronami-theme . [(20220602 339) ((emacs (24 1))) "A deep blue theme with cool autumnal colors" single ((:commit . "a51d5ff3883bd94d0a181bb5d60f747190eda4f6") (:authors ("Eric Chung <>")) (:maintainer "Eric Chung <>") (:url . "https://github.com/inj0h/kuronami"))]) (kv . [(20140108 1534) nil "key/value data structure functions" single ((:commit . "721148475bce38a70e0b678ba8aa923652e8900e") (:authors ("Nic Ferrier" . "nferrier@ferrier.me.uk")) (:maintainer "Nic Ferrier" . "nferrier@ferrier.me.uk") (:keywords "lisp"))]) (kwin . [(20220120 2125) nil "communicatewith the KWin window manager" single ((:commit . "20fac6508e5535a26df783ba05f04d1800b7382c") (:authors ("Simon Hafner")) (:maintainer "Simon Hafner") (:url . "http://github.com/reactormonk/kwin-minor-mode"))]) - (laas . [(20220509 1234) ((emacs (26 3)) (auctex (11 88)) (aas (1 1)) (yasnippet (0 14))) "A bundle of as-you-type LaTeX snippets" tar ((:commit . "44533de4968fee924d9cc81ce9a23c9d82847db3") (:maintainer "Yoav Marco" . "yoavm448@gmail.com") (:keywords "tools" "tex") (:url . "https://github.com/tecosaur/LaTeX-auto-activating-snippets"))]) + (laas . [(20230331 1806) ((emacs (26 3)) (auctex (11 88)) (aas (1 1))) "A bundle of as-you-type LaTeX snippets" tar ((:commit . "a00f0aba237b85b3e5fd60cf84de5759d1bf5d48") (:maintainer "Yoav Marco" . "yoavm448@gmail.com") (:keywords "tools" "tex") (:url . "https://github.com/tecosaur/LaTeX-auto-activating-snippets"))]) (lab-themes . [(20200815 2104) ((emacs (24))) "A custom theme carefully constructed in the LAB space" tar ((:commit . "9d7deb9635959d3a50ccb1082eb1207275f4b3e8") (:authors ("MetroWind" . "chris.corsair@gmail.com")) (:maintainer "MetroWind" . "chris.corsair@gmail.com") (:keywords "lisp") (:url . "https://github.com/MetroWind/lab-theme"))]) (labburn-theme . [(20221208 1611) nil "A lab color space zenburn theme." single ((:commit . "bd0de2fdcf285d981f32e3e5ebc56fe3c9b589a5") (:authors ("Johannes Goslar")) (:maintainer "Johannes Goslar") (:keywords "theme" "zenburn") (:url . "https://github.com/ksjogo/labburn-theme"))]) (lacquer . [(20230206 756) ((emacs (25 2))) "Switch theme/font by selecting from a cache" tar ((:commit . "8a4e7dc1827862ad025f2af5354ca377cc660939") (:authors ("zakudriver" . "zy.hua1122@gmail.com")) (:maintainer "zakudriver" . "zy.hua1122@gmail.com") (:keywords "tools") (:url . "https://github.com/zakudriver/lacquer"))]) @@ -2804,12 +2817,13 @@ (lammps-mode . [(20180801 1319) ((emacs (24 4))) "basic syntax highlighting for LAMMPS files" single ((:commit . "a5b68d7a59975770b56ee8f6e66fa4f703a72ffe") (:authors ("Aidan Thompson ")) (:maintainer "Rohit Goswami ") (:keywords "languages" "faces") (:url . "https://github.com/lammps/lammps/tree/master/tools/emacs"))]) (lang-refactor-perl . [(20131122 2127) nil "Simple refactorings, primarily for Perl" single ((:commit . "691bd69639de6b7af357e3b7143563ececd9c497") (:authors (nil . "Johan Lindstrom ")) (:maintainer nil . "Johan Lindstrom ") (:keywords "languages" "refactoring" "perl") (:url . "https://github.com/jplindstrom/emacs-lang-refactor-perl"))]) (langdoc . [(20150218 645) ((cl-lib (0 2))) "Help to define help document mode for various languages" single ((:commit . "2c7223bacb116992d700ecb19a60df5c09c63424") (:authors ("Tomoya Tanjo" . "ttanjo@gmail.com")) (:maintainer "Tomoya Tanjo" . "ttanjo@gmail.com") (:keywords "convenience" "eldoc") (:url . "https://github.com/tom-tan/langdoc/"))]) - (langtool . [(20230207 950) ((emacs (24 3))) "Grammar check utility using LanguageTool" single ((:commit . "fc6c046af1c5e4e55331414387865f65afb1bd3c") (:authors ("Masahiro Hayashi" . "mhayashi1120@gmail.com")) (:maintainer "Masahiro Hayashi" . "mhayashi1120@gmail.com") (:keywords "docs") (:url . "https://github.com/mhayashi1120/Emacs-langtool"))]) + (langtool . [(20230222 326) ((emacs (24 3))) "Grammar check utility using LanguageTool" single ((:commit . "416abc7d1c1cbb31a9bddad458366215bad0089b") (:authors ("Masahiro Hayashi" . "mhayashi1120@gmail.com")) (:maintainer "Masahiro Hayashi" . "mhayashi1120@gmail.com") (:keywords "docs") (:url . "https://github.com/mhayashi1120/Emacs-langtool"))]) (langtool-ignore-fonts . [(20210526 2340) ((emacs (25 1)) (langtool (2 2 1))) "Force langtool to ignore certain fonts" single ((:commit . "a5d04c3840c293f1b11db3c28e7210d0d20f53af") (:authors ("Christopher Lloyd" . "cjl8zf@virginia.edu")) (:maintainer "Christopher Lloyd" . "cjl8zf@virginia.edu") (:url . "https://github.com/cjl8zf/langtool-ignore-fonts"))]) - (langtool-popup . [(20230207 319) ((emacs (25 1)) (popup (0 5 9)) (langtool (2 3 2))) "Popup message extension for langtool.el" single ((:commit . "25b23a2dc592cdfe498740af87d975f7ef23a854") (:authors ("Masahiro Hayashi" . "mhayashi1120@gmail.com")) (:maintainer "Masahiro Hayashi" . "mhayashi1120@gmail.com") (:keywords "docs") (:url . "https://github.com/mhayashi1120/Emacs-langtool"))]) + (langtool-popup . [(20230222 401) ((emacs (25 1)) (popup (0 5 9))) "Popup message extension for langtool.el" single ((:commit . "d86101eafe9a994eb0425e08e7c1795e9cb0cd42") (:authors ("Masahiro Hayashi" . "mhayashi1120@gmail.com")) (:maintainer "Masahiro Hayashi" . "mhayashi1120@gmail.com") (:keywords "docs") (:url . "https://github.com/mhayashi1120/Emacs-langtool"))]) (language-detection . [(20161123 1813) ((emacs (24)) (cl-lib (0 5))) "Automatic language detection from code snippets" single ((:commit . "38f5d294870678efc6ccf94ce6e8175a58f93025") (:authors ("Andreas Jansson" . "andreas@jansson.me.uk")) (:maintainer "Andreas Jansson" . "andreas@jansson.me.uk") (:url . "https://github.com/andreasjansson/language-detection.el"))]) (language-id . [(20230214 710) ((emacs (24 3))) "Library to work with programming language identifiers" single ((:commit . "302533245972d9bc7722328742247d2b2b225e01") (:authors ("Lassi Kortela" . "lassi@lassi.io")) (:maintainer "Lassi Kortela" . "lassi@lassi.io") (:keywords "languages" "util") (:url . "https://github.com/lassik/emacs-language-id"))]) - (languagetool . [(20230122 121) ((emacs (27 0))) "LanguageTool integration for grammar and spell check" tar ((:commit . "57af28a0c370866945988461a259b6551a1c4074") (:authors ("Joar Buitrago" . "jebuitragoc@unal.edu.co")) (:maintainer "Joar Buitrago" . "jebuitragoc@unal.edu.co") (:keywords "grammar" "text" "docs" "tools" "convenience" "checker") (:url . "https://github.com/PillFall/Emacs-LanguageTool.el"))]) + (languagetool . [(20230325 507) ((emacs (27 1))) "LanguageTool integration for grammar and spell check" tar ((:commit . "b136d531129eb488dc4134784e34c4afedcb0c2f") (:authors ("Joar Buitrago" . "jebuitragoc@unal.edu.co")) (:maintainer "Joar Buitrago" . "jebuitragoc@unal.edu.co") (:keywords "grammar" "text" "docs" "tools" "convenience" "checker") (:url . "https://github.com/PillFall/Emacs-LanguageTool.el"))]) + (lark-mode . [(20230327 1003) ((emacs (24 3))) "Major mode for editing Lark parser code" single ((:commit . "9e19b40df29d273cf3aec9ddd0e739d3b3d9b3a8") (:authors ("Ta Quang Trung")) (:maintainer "Ta Quang Trung") (:keywords "languages") (:url . "https://github.com/taquangtrung/lark-mode"))]) (lastfm . [(20211018 838) ((emacs (26 1)) (request (0 3 0)) (anaphora (1 0 4)) (memoize (1 1)) (elquery (0 1 0)) (s (1 12 0))) "Last.fm API for Emacs Lisp" single ((:commit . "b4b19f0aadc5087febeeb3f59944a89c4cdcf325") (:authors ("Mihai Olteanu" . "mihai_olteanu@fastmail.fm")) (:maintainer "Mihai Olteanu" . "mihai_olteanu@fastmail.fm") (:keywords "multimedia" "api") (:url . "https://github.com/mihaiolteanu/lastfm.el/"))]) (lastpass . [(20201229 2109) ((emacs (24 4)) (seq (1 9)) (cl-lib (0 5))) "LastPass command wrapper" single ((:commit . "2366de7824b6c5f8e9ec6811d219dc06794e8630") (:authors ("Petter Storvik")) (:maintainer "Petter Storvik") (:keywords "extensions" "processes" "lpass" "lastpass") (:url . "https://github.com/storvik/emacs-lastpass"))]) (latex-change-env . [(20230220 637) ((emacs (27 1)) (auctex (13 1))) "Change in and out of LaTeX environments" single ((:commit . "748cdbb4bbf29a2e5053cf3d965e95cc7db67fac") (:authors ("Tony Zorman" . "soliditsallgood@mailbox.org")) (:maintainer "Tony Zorman" . "soliditsallgood@mailbox.org") (:keywords "convenience" "tex") (:url . "https://gitlab.com/slotThe/change-env"))]) @@ -2820,6 +2834,7 @@ (latex-table-wizard . [(20230103 2241) ((emacs (27 1)) (auctex (12 1)) (transient (0 3 7))) "Magic editing of LaTeX tables" tar ((:commit . "61fb455a1e6a28b93512e63c609ca7ad7dd5bec5") (:authors ("Enrico Flor" . "enrico@eflor.net")) (:maintainer "Enrico Flor" . "enrico@eflor.net") (:keywords "convenience") (:url . "https://github.com/enricoflor/latex-table-wizard"))]) (latex-unicode-math-mode . [(20170123 1816) nil "Input method for Unicode math symbols" tar ((:commit . "e8931e68214ca94e6a04080ebc629693d5881884") (:authors ("Christoph Dittmann" . "github@christoph-d.de")) (:maintainer "Christoph Dittmann" . "github@christoph-d.de") (:url . "https://github.com/Christoph-D/latex-unicode-math-mode"))]) (latexdiff . [(20190827 1651) ((emacs (24 4))) "Latexdiff integration in Emacs" single ((:commit . "56d0b240867527d1b43d3ddec14059361929b971") (:authors ("Launay Gaby" . "gaby.launay@tutanota.com")) (:maintainer "Launay Gaby" . "gaby.launay@tutanota.com") (:keywords "tex" "vc" "tools" "git" "helm") (:url . "http://github.com/galaunay/latexdiff.el"))]) + (latvian-holidays . [(20230326 2030) nil "Latvian holidays for the calendar" single ((:commit . "6b82f3bd9682c97f19a65b7d359ce7a02ec9cfec") (:authors ("Alexander Shumilov" . "alexander.shumilov@me.com")) (:maintainer "Alexander Shumilov" . "alexander.shumilov@me.com") (:keywords "calendar") (:url . "https://github.com/ashumilov/latvian-holidays"))]) (launch . [(20130619 2204) nil "launch files with OS-standard associated applications." single ((:commit . "e7c3b573fc05fe4d3d322389079909311542e799") (:authors ("Simon Law" . "sfllaw@sfllaw.ca")) (:maintainer "Simon Law" . "sfllaw@sfllaw.ca") (:keywords "convenience" "processes") (:url . "https://github.com/sfllaw/emacs-launch"))]) (launch-mode . [(20170106 512) ((emacs (24 4))) "Major mode for launch-formatted text" tar ((:commit . "25ebd4ba77afcbe729901eb74923dbe9ae81c313") (:authors ("iory" . "ab.ioryz@gmail.com")) (:maintainer "iory" . "ab.ioryz@gmail.com") (:url . "https://github.com/iory/launch-mode"))]) (launchctl . [(20210611 2243) ((emacs (24 1))) "Interface to launchctl on Mac OS X." single ((:commit . "c9b7e93f5ec6fa504dfb03d60571cf3e5dc38e12") (:authors ("Peking Duck ")) (:maintainer "Peking Duck ") (:keywords "tools" "convenience") (:url . "http://github.com/pekingduck/launchctl-el"))]) @@ -2838,7 +2853,7 @@ (leanote . [(20161223 139) ((emacs (24 4)) (cl-lib (0 5)) (request (0 2)) (let-alist (1 0 3)) (pcache (0 4 0)) (s (1 10 0)) (async (1 9))) "A minor mode writing markdown leanote" single ((:commit . "d499e7b59bb1f1a2fabc0e4c26fb101ed62ebc7b") (:authors ("Aborn Jiang" . "aborn.jiang@gmail.com")) (:maintainer "Aborn Jiang" . "aborn.jiang@gmail.com") (:keywords "leanote" "note" "markdown") (:url . "https://github.com/aborn/leanote-emacs"))]) (learn-ocaml . [(20211003 1412) ((emacs (25 1))) "Emacs frontend for learn-ocaml" single ((:commit . "abdc263537a6a534152a4eaaa17b2c3e4e10418b") (:url . "https://github.com/pfitaxel/learn-ocaml.el"))]) (ledger-import . [(20210419 818) ((emacs (25 1)) (ledger-mode (3 1 1))) "Fetch OFX files from bank and push them to Ledger" single ((:commit . "f77adf79ce67524c3e08546448ac88ea1a665b64") (:authors ("Damien Cassou" . "damien@cassou.me")) (:maintainer "Damien Cassou" . "damien@cassou.me") (:url . "https://gitlab.petton.fr/mpdel/libmpdel"))]) - (ledger-mode . [(20230106 1610) ((emacs (25 1))) "Helper code for use with the \"ledger\" command-line tool" tar ((:commit . "4b32f701736b37f99048be79583b0bde7cc14c85"))]) + (ledger-mode . [(20230404 855) ((emacs (25 1))) "Helper code for use with the \"ledger\" command-line tool" tar ((:commit . "e74fe9e84f278cedc3b9fc661c243ab5e1bbf434"))]) (leerzeichen . [(20220626 835) nil "Minor mode to display whitespace characters." single ((:commit . "9d4126d5f6563569080845a69b0867119a9fd6ea") (:authors ("Felix Geller" . "fgeller@gmail.com")) (:maintainer "Felix Geller" . "fgeller@gmail.com") (:keywords "whitespace" "characters") (:url . "http://github.com/fgeller/leerzeichen.el"))]) (leetcode . [(20220503 534) ((emacs (26 1)) (dash (2 16 0)) (graphql (0 1 1)) (spinner (1 7 3)) (aio (1 0)) (log4e (0 3 3))) "An leetcode client" single ((:commit . "682f7a44d0bea0daf6f9a2888fa7f905d3a0cd70") (:authors ("Wang Kai" . "kaiwkx@gmail.com")) (:maintainer "Wang Kai" . "kaiwkx@gmail.com") (:keywords "extensions" "tools") (:url . "https://github.com/kaiwk/leetcode.el"))]) (legalese . [(20200119 2248) nil "Add legalese to your program files" single ((:commit . "e465471d2d5a62d35073d93e0f8d40387a82e302") (:authors ("Jorgen Schaefer" . "forcer@forcix.cx")) (:maintainer "Jorgen Schaefer" . "forcer@forcix.cx") (:keywords "convenience") (:url . "https://github.com/jorgenschaefer/legalese"))]) @@ -2855,28 +2870,29 @@ (lexic . [(20220501 1432) ((emacs (26 3))) "A major mode to find out more about words" single ((:commit . "f9b3de4d9c2dd1ce5022383e1a504b87bf7d1b09") (:authors ("pluskid" . "pluskid@gmail.com") ("gucong" . "gucong43216@gmail.com") ("TEC" . "tec@tecosaur.com")) (:maintainer "TEC" . "tec@tecosaur.com") (:url . "https://github.com/tecosaur/lexic"))]) (lf . [(20210808 1921) ((s (1 12 0)) (dash (2 16 0)) (emacs (27 1))) "A Language Features library for Emacs Lisp" single ((:commit . "35db92ca765a0544721fdeea036d77b7d192d083") (:authors ("Musa Al-hassy" . "alhassy@gmail.com")) (:maintainer "Musa Al-hassy" . "alhassy@gmail.com") (:keywords "convenience" "programming") (:url . "https://alhassy.github.io/lf.el/"))]) (lfe-mode . [(20220822 911) nil "Lisp Flavoured Erlang mode" tar ((:commit . "42fc3dc57d4229800f44a0d6907185ebdf7175e2"))]) + (lgr . [(20230313 2155) ((emacs (26 1))) "A fully featured logging framework" single ((:commit . "a46f7e6c58e0c343c81e464f4233acfaa0434b4f") (:authors ("Matúš Goljer" . "matus.goljer@gmail.com")) (:maintainer "Matúš Goljer" . "matus.goljer@gmail.com") (:keywords "tools") (:url . "https://github.com/Fuco1/emacs-lgr"))]) (libbcel . [(20221003 1827) ((emacs (26 1)) (request (0 3 1))) "Library to connect to basecamp 3 API" tar ((:commit . "3d506a3fb5b377bf460e7b8096f7211949567f75") (:authors ("Damien Cassou" . "damien@cassou.me")) (:maintainer "Damien Cassou" . "damien@cassou.me") (:url . "https://gitlab.petton.fr/bcel/libbcel"))]) (libelcouch . [(20230129 1000) ((emacs (26 1)) (request (0 3 0))) "Communication with CouchDB" single ((:commit . "595697f4199519dd018fe489e885f237c54b0675") (:authors ("Damien Cassou" . "damien@cassou.me")) (:maintainer "Damien Cassou" . "damien@cassou.me") (:keywords "tools") (:url . "https://gitlab.petton.fr/elcouch/libelcouch/"))]) (liberime . [(20230113 556) ((emacs (25 1))) "Rime elisp binding" tar ((:commit . "cc9eb9812fd6f68e78ed6a0c0a85da7a18765753") (:authors ("A.I.")) (:maintainer "A.I.") (:keywords "convenience" "chinese" "input-method" "rime") (:url . "https://github.com/merrickluo/liberime"))]) (liblouis . [(20220426 657) ((emacs (26 1))) "Mode for editing liblouis braille translation tables" single ((:commit . "a341a0c434cdbe7f46956c8db13203c3fc941a34") (:authors ("Christian Egli" . "christian.egli@sbs.ch")) (:maintainer "Christian Egli" . "christian.egli@sbs.ch") (:keywords "languages") (:url . "https://github.com/liblouis/liblouis-mode"))]) (libmpdee . [(20220825 957) nil "Client end library for mpd, a music playing daemon" single ((:commit . "9a84e074385cd085622f94e720a968a0e05ceae5") (:authors ("Ramkumar R. Aiyengar" . "andyetitmoves@gmail.com")) (:maintainer "Ramkumar R. Aiyengar" . "andyetitmoves@gmail.com") (:keywords "music" "mpd"))]) (libmpdel . [(20221229 916) ((emacs (25 1))) "Communication with an MPD server" tar ((:commit . "e7d35ba9254ead1516133f182a01f6161ae26388") (:authors ("Damien Cassou" . "damien@cassou.me")) (:maintainer "Damien Cassou" . "damien@cassou.me") (:keywords "multimedia") (:url . "https://github.com/mpdel/libmpdel"))]) - (librera-sync . [(20210827 2300) ((emacs (26 1)) (f (0 17))) "Sync document's position with Librera Reader for Android" tar ((:commit . "b6b97adc08c26b1595249e1c129793100f4ca26e") (:authors ("Dmitriy Pshonko" . "jumper047@gmail.com")) (:maintainer "Dmitriy Pshonko" . "jumper047@gmail.com") (:keywords "multimedia" "sync") (:url . "https://github.com/jumper047/librera-sync"))]) + (librera-sync . [(20230306 17) ((emacs (26 1)) (f (0 17)) (dash (2 12 0))) "Sync document's position with Librera Reader for Android" tar ((:commit . "29e158fc478d5817dffc4045b067feed4c3d0dbe") (:authors ("Dmitriy Pshonko" . "jumper047@gmail.com")) (:maintainer "Dmitriy Pshonko" . "jumper047@gmail.com") (:keywords "multimedia" "sync") (:url . "https://github.com/jumper047/librera-sync"))]) (lice . [(20220312 2215) nil "License And Header Template" tar ((:commit . "0b69ba54057146f1473e85c0760029e584e3eb13") (:authors ("Taiki Sugawara" . "buzz.taiki@gmail.com")) (:maintainer "Taiki Sugawara" . "buzz.taiki@gmail.com") (:keywords "template" "license" "tools") (:url . "https://github.com/buzztaiki/lice-el"))]) (license-snippets . [(20201117 1619) ((emacs (26)) (yasnippet (0 8 0))) "LICENSE templates for yasnippet" tar ((:commit . "a89988b81604fd23c43746912215770a4b861989") (:authors ("Seong Yong-ju" . "sei40kr@gmail.com")) (:maintainer "Seong Yong-ju" . "sei40kr@gmail.com") (:keywords "tools") (:url . "https://github.com/sei40kr/license-snippets"))]) - (license-templates . [(20220918 813) ((emacs (24 3)) (request (0 3 0))) "Create LICENSE using GitHub API" single ((:commit . "cebb88350916e0c808668c06c40d55eb1c9d0b2e") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "license" "api" "template") (:url . "https://github.com/jcs-elpa/license-templates"))]) + (license-templates . [(20230311 11) ((emacs (24 3)) (request (0 3 0))) "Create LICENSE using GitHub API" single ((:commit . "09f1b017c93067c2970a0a63b69026bfc172d2b7") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "license" "api" "template") (:url . "https://github.com/jcs-elpa/license-templates"))]) (ligature . [(20220808 1225) ((emacs (28))) "Display typographical ligatures in major modes" single ((:commit . "89cbd67a815f61e5001f19d64d6ec1771e867742") (:authors ("Mickey Petersen" . "mickey@masteringemacs.org")) (:maintainer "Mickey Petersen" . "mickey@masteringemacs.org") (:keywords "tools" "faces") (:url . "https://www.github.com/mickeynp/ligature.el"))]) (ligature-pragmatapro . [(20221127 2252) ((emacs (28)) (ligature (1 0))) "PragmataPro support for ligature.el" single ((:commit . "85f7b15a5cf5f2ee843bc0469e03602a0251c275") (:authors ("Yuri D'Elia" . "wavexx@thregr.org")) (:maintainer "Yuri D'Elia" . "wavexx@thregr.org") (:keywords "faces" "fonts" "ligatures" "programming-ligatures") (:url . "https://gitlab.com/wavexx/ligature-pragmatapro.el"))]) (light-soap-theme . [(20150607 1445) ((emacs (24))) "Emacs 24 theme with a light background." single ((:commit . "76a787bd40c6b567ae68ced7f5d9f9f10725e00d"))]) - (ligo-mode . [(20230130 541) ((emacs (27 1))) "A major mode for editing LIGO source code" single ((:commit . "fa63e64ff3de4de78f74c2d270c0c0f000abec8f") (:authors ("LigoLang SASU")) (:maintainer "LigoLang SASU") (:keywords "languages") (:url . "https://gitlab.com/ligolang/ligo/-/tree/dev/tools/emacs"))]) - (line-reminder . [(20230104 1211) ((emacs (25 1)) (indicators (0 0 4)) (fringe-helper (1 0 1)) (ov (1 0 6)) (ht (2 0))) "Line annotation for changed and saved lines" single ((:commit . "41a22589ebc3843f6736669a4517014800f09e16") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "annotation") (:url . "https://github.com/emacs-vs/line-reminder"))]) + (ligo-mode . [(20230302 1616) ((emacs (27 1))) "A major mode for editing LIGO source code" single ((:commit . "d1073474efc9e0a020a4bcdf5e0c12a217265a3a") (:authors ("LigoLang SASU")) (:maintainer "LigoLang SASU") (:keywords "languages") (:url . "https://gitlab.com/ligolang/ligo/-/tree/dev/tools/emacs"))]) + (line-reminder . [(20230305 2230) ((emacs (25 1)) (indicators (0 0 4)) (fringe-helper (1 0 1)) (ov (1 0 6)) (ht (2 0))) "Line annotation for changed and saved lines" single ((:commit . "ea916b5c040cbc7e39b46c1137b4d0bf5c19a241") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "annotation") (:url . "https://github.com/emacs-vs/line-reminder"))]) (line-up-words . [(20180219 1024) nil "Align words in an intelligent way" single ((:commit . "2c236f5772e18d0e50d7ca2eee7eebbe356d9b60") (:url . "https://github.com/janestreet/line-up-words"))]) (lines-at-once . [(20180422 247) ((emacs (25))) "Insert and edit multiple lines at once" single ((:commit . "a018ba90549384d52ec58c2685fd14a0f65252be") (:authors ("Jiahao Li" . "jiahaowork@gmail.com")) (:maintainer "Jiahao Li" . "jiahaowork@gmail.com") (:keywords "abbrev" "tools") (:url . "https://github.com/jiahaowork/lines-at-once.el"))]) (lingr . [(20100807 1731) nil "Lingr Client for GNU Emacs" single ((:commit . "4215a8704492d3c860097cbe2649936c22c196df") (:authors ("lugecy" . "lugecy@gmail.com")) (:maintainer "lugecy" . "lugecy@gmail.com") (:keywords "chat" "client" "internet") (:url . "http://github.com/lugecy/lingr-el"))]) (linguistic . [(20181129 2116) nil "A package for basic linguistic analysis." tar ((:commit . "23e47e98cdb09ee61883669b6d8a11bf6449862c") (:authors ("Andrew Favia ")) (:maintainer "Andrew Favia ") (:keywords "linguistics" "text analysis" "matching") (:url . "https://github.com/andcarnivorous/linguistic"))]) (lingva . [(20220910 1435) ((emacs (25 1))) "Access Google Translate without tracking via lingva.ml" single ((:commit . "6c33594068fa33de622172503deeec6778d9c744") (:authors ("marty hiatt ")) (:maintainer "marty hiatt ") (:keywords "convenience" "translation" "wp" "text") (:url . "https://codeberg.org/martianh/lingva.el"))]) (link . [(20191111 446) nil "Hypertext links in text buffers" single ((:commit . "c9cad101100975e88873636bfd426b7a19304ebd") (:authors ("Torsten Hilbrich" . "torsten.hilbrich@gmx.net")) (:maintainer "Torsten Hilbrich" . "torsten.hilbrich@gmx.net") (:keywords "interface" "hypermedia"))]) - (link-hint . [(20221008 1445) ((avy (0 4 0)) (emacs (24 4))) "Use avy to open, copy, etc. visible links" single ((:commit . "1f9bb60289d87f31f92b86ed22d1f2c0a7af0222") (:authors ("Fox Kiester" . "noct@posteo.net")) (:maintainer "Fox Kiester" . "noct@posteo.net") (:keywords "convenience" "url" "avy" "link" "links" "hyperlink") (:url . "https://github.com/noctuid/link-hint.el"))]) + (link-hint . [(20230405 1801) ((avy (0 4 0)) (emacs (24 4))) "Use avy to open, copy, etc. visible links" single ((:commit . "36ce929331f2838213bcaa1145ece4b73ce84afe") (:authors ("Fox Kiester" . "noct@posteo.net")) (:maintainer "Fox Kiester" . "noct@posteo.net") (:keywords "convenience" "url" "avy" "link" "links" "hyperlink") (:url . "https://github.com/noctuid/link-hint.el"))]) (linkode . [(20200607 2152) nil "Generate a linkode snippet with region/buffer content" single ((:commit . "e31bdae11ff38b736b1869fbe94920e862f29794") (:authors ("Erick Navarro" . "erick@navarro.io")) (:maintainer "Erick Navarro" . "erick@navarro.io") (:url . "https://github.com/erickgnavar/linkode.el"))]) (linphone . [(20130524 1109) nil "Emacs interface to Linphone" tar ((:commit . "99af3db941b7f4e5272bb48bff96c1ce4ceac302") (:authors ("Yoni Rabkin" . "yonirabkin@member.fsf.org")) (:maintainer "Yoni Rabkin" . "yonirabkin@member.fsf.org") (:keywords "comm") (:url . "https://github.com/zabbal/emacs-linphone"))]) (linum-off . [(20160217 2137) nil "Provides an interface for turning line-numbering off" single ((:commit . "3e37baaad27d27e405f8dfe01d4ab9cd5b591353") (:authors ("Matthew L. Fidler, Florian Adamsky (see wiki)")) (:maintainer "Matthew L. Fidler") (:keywords "line" "numbering") (:url . "http://www.emacswiki.org/emacs/auto-indent-mode.el "))]) @@ -2888,7 +2904,7 @@ (lisp-extra-font-lock . [(20181008 1921) nil "Highlight bound variables and quoted exprs." single ((:commit . "4605eccbe1a7fcbd3cacf5b71249435413b4db4f") (:authors ("Anders Lindgren")) (:maintainer "Anders Lindgren") (:keywords "languages" "faces") (:url . "https://github.com/Lindydancer/lisp-extra-font-lock"))]) (lisp-local . [(20210605 1347) ((emacs (24 3))) "Allow different Lisp indentation in each buffer" single ((:commit . "22e221c9330d2b5dc07e8b2caa34c83ac7c20b0d") (:authors ("Lassi Kortela" . "lassi@lassi.io")) (:maintainer "Lassi Kortela" . "lassi@lassi.io") (:keywords "languages" "lisp") (:url . "https://github.com/lispunion/emacs-lisp-local"))]) (lispxmp . [(20170926 23) nil "Automagic emacs lisp code annotation" single ((:commit . "7ad077b4ee91ce8a42f84eeddb9fc7ea4eac7814") (:authors ("rubikitch" . "rubikitch@ruby-lang.org")) (:maintainer "rubikitch" . "rubikitch@ruby-lang.org") (:keywords "lisp" "convenience") (:url . "http://www.emacswiki.org/cgi-bin/wiki/download/lispxmp.el"))]) - (lispy . [(20221225 1927) ((emacs (24 3)) (ace-window (0 9 0)) (iedit (0 9 9)) (swiper (0 13 4)) (hydra (0 14 0)) (zoutline (0 2 0))) "vi-like Paredit" tar ((:commit . "097dd66e662c3eee90d112d88bac5345d26e508f") (:authors ("Oleh Krehel" . "ohwoeowho@gmail.com")) (:maintainer "Oleh Krehel" . "ohwoeowho@gmail.com") (:keywords "lisp") (:url . "https://github.com/abo-abo/lispy"))]) + (lispy . [(20230314 1738) ((emacs (24 3)) (ace-window (0 9 0)) (iedit (0 9 9)) (swiper (0 13 4)) (hydra (0 14 0)) (zoutline (0 2 0))) "vi-like Paredit" tar ((:commit . "fe44efd21573868638ca86fc8313241148fabbe3") (:authors ("Oleh Krehel" . "ohwoeowho@gmail.com")) (:maintainer "Oleh Krehel" . "ohwoeowho@gmail.com") (:keywords "lisp") (:url . "https://github.com/abo-abo/lispy"))]) (lispyville . [(20220715 29) ((lispy (0)) (evil (1 2 12)) (cl-lib (0 5)) (emacs (24 4))) "A minor mode for integrating evil with lispy." single ((:commit . "14ee8711d58b649aeac03581d22b10ab077f06bd") (:authors ("Fox Kiester" . "noct@posteo.net")) (:maintainer "Fox Kiester" . "noct@posteo.net") (:keywords "vim" "evil" "lispy" "lisp" "parentheses") (:url . "https://github.com/noctuid/lispyville"))]) (list-environment . [(20210930 1439) nil "A tabulated process environment editor" single ((:commit . "0a72a5a9c1abc090b25202a0387e3f766994b053") (:authors ("Charles L.G. Comstock" . "dgtized@gmail.com")) (:maintainer "Charles L.G. Comstock" . "dgtized@gmail.com") (:keywords "processes" "unix"))]) (list-packages-ext . [(20151115 1716) ((s (1 6 0)) (ht (1 5 0)) (persistent-soft (0 8 6))) "Extras for list-packages" single ((:commit . "b4dd644e4369c9aa66f5bb8895ea49ebbfd0a27a") (:authors ("Alessandro Piras" . "laynor@gmail.com")) (:maintainer "Alessandro Piras" . "laynor@gmail.com") (:keywords "convenience" "tools"))]) @@ -2903,10 +2919,10 @@ (literate-calc-mode . [(20230127 153) ((emacs (25 1)) (s (1 12 0))) "Inline results from calc" single ((:commit . "900bdd12c0a6e6874f60b0df99a72fd329873ea1") (:authors ("Robin Schroer")) (:maintainer "Robin Schroer") (:keywords "calc" "languages" "tools") (:url . "https://github.com/sulami/literate-calc-mode.el"))]) (literate-coffee-mode . [(20170211 1515) ((coffee-mode (0 5 0))) "major-mode for Literate CoffeeScript" single ((:commit . "ef34c3a5b813ef078d44c29887761950ab6821c7") (:authors ("Syohei YOSHIDA" . "syohex@gmail.com")) (:maintainer "Syohei YOSHIDA" . "syohex@gmail.com") (:url . "https://github.com/syohex/emacs-literate-coffee-mode"))]) (literate-elisp . [(20220626 932) ((emacs (26 1))) "Load Emacs Lisp code blocks from Org files" single ((:commit . "bbc4befbf13f63b92cb1d780501482ae5bd8285b") (:authors ("Jingtao Xu" . "jingtaozf@gmail.com")) (:maintainer "Jingtao Xu" . "jingtaozf@gmail.com") (:keywords "lisp" "docs" "extensions" "tools") (:url . "https://github.com/jingtaozf/literate-elisp"))]) - (litex-mode . [(20221108 300) ((emacs (24 4)) (units-mode (0 1 1))) "Minor mode for converting lisp to LaTeX" tar ((:commit . "72e20233db66cb37306bdc066c68e6d7086ab3c4") (:authors ("Gaurav Atreya" . "allmanpride@gmail.com")) (:maintainer "Gaurav Atreya" . "allmanpride@gmail.com") (:keywords "calculator" "lisp" "latex") (:url . "https://github.com/Atreyagaurav/litex-mode"))]) + (litex-mode . [(20221107 147) ((emacs (24 4)) (units-mode (0 1 1))) "Minor mode for converting lisp to LaTeX" tar ((:commit . "45004b3a865771799b739d17ebb7849190fffa63") (:authors ("Gaurav Atreya" . "allmanpride@gmail.com")) (:maintainer "Gaurav Atreya" . "allmanpride@gmail.com") (:keywords "calculator" "lisp" "latex") (:url . "https://github.com/Atreyagaurav/litex-mode"))]) (live-code-talks . [(20180907 1647) ((emacs (24)) (cl-lib (0 5)) (narrowed-page-navigation (0 1))) "Support for slides with live code in them" single ((:commit . "97f16a9ee4e6ff3e0f9291eaead772c66e3e12ae") (:authors ("David Raymond Christiansen" . "david@davidchristiansen.dk")) (:maintainer "David Raymond Christiansen" . "david@davidchristiansen.dk") (:keywords "docs" "multimedia"))]) (live-preview . [(20201010 1948) ((emacs (24 4))) "Live preview by any shell command while editing" single ((:commit . "603a4a1759fbec92e7a1cabc249517c78e59ce7e") (:authors ("Lassi Kortela" . "lassi@lassi.io")) (:maintainer "Lassi Kortela" . "lassi@lassi.io") (:keywords "languages" "util") (:url . "https://github.com/lassik/emacs-live-preview"))]) - (live-py-mode . [(20221203 38) ((emacs (24 3))) "Live Coding in Python" tar ((:commit . "c02c7a5002d817d6e9cd4d7a1551c0ee412a65f1") (:authors ("Don Kirkby http://donkirkby.github.io")) (:maintainer "Don Kirkby http://donkirkby.github.io") (:keywords "live" "coding") (:url . "http://donkirkby.github.io/live-py-plugin/"))]) + (live-py-mode . [(20230330 58) ((emacs (24 3))) "Live Coding in Python" tar ((:commit . "4ea88695df456108adf37a547884cb37ea55438c") (:authors ("Don Kirkby http://donkirkby.github.io")) (:maintainer "Don Kirkby http://donkirkby.github.io") (:keywords "live" "coding") (:url . "http://donkirkby.github.io/live-py-plugin/"))]) (lively . [(20171005 754) nil "interactively updating text" single ((:commit . "348675828c6a81bfa1ac311ca465aad813542c1b") (:authors ("Luke Gorrie" . "luke@bup.co.nz")) (:maintainer "Steve Purcell" . "steve@sanityinc.com"))]) (livereload . [(20170629 650) ((emacs (25)) (websocket (1 8))) "Livereload server" tar ((:commit . "1e501d7e46dbd476c2c7cc9d20b5ac9d41fb1955") (:authors ("João Távora" . "joaotavora@gmail.com")) (:maintainer "João Távora" . "joaotavora@gmail.com") (:keywords "convenience"))]) (livescript-mode . [(20221015 1316) ((emacs (24 3))) "Major mode for editing LiveScript files" single ((:commit . "e71a82a400e9d451c966c397bb8fa7887d35637b") (:authors ("Hisamatsu Yasuyuki" . "yas@null.net")) (:maintainer "Hisamatsu Yasuyuki" . "yas@null.net") (:keywords "languages" "livescript") (:url . "https://github.com/yhisamatsu/livescript-mode"))]) @@ -2914,7 +2930,7 @@ (ll-debug . [(20211002 1031) ((emacs (24 3))) "Low level debug tools" single ((:commit . "a2cfeab46e5100c348b35987fae34f9ea76d7c0b") (:authors ("Claus Brunzema" . "mail@cbrunzema.de")) (:maintainer "Claus Brunzema" . "mail@cbrunzema.de") (:keywords "abbrev" "convenience" "tools" "c" "lisp") (:url . "https://github.com/replrep/ll-debug"))]) (llama . [(20230107 1517) ((seq (2 23))) "Compact syntax for short lambda" single ((:commit . "f76fd445966e3671bb59ba7a0a575f3b2ff59c33") (:keywords "extensions") (:url . "https://git.sr.ht/~tarsius/llama"))]) (lms . [(20210820 2200) ((emacs (25 1))) "Squeezebox / Logitech Media Server frontend" single ((:commit . "29593b4c18a570dfb2e60b196f24d407a1277daa") (:authors ("Iñigo Serna" . "inigoserna@gmx.com")) (:maintainer "Iñigo Serna" . "inigoserna@gmx.com") (:keywords "multimedia") (:url . "https://hg.serna.eu/emacs/lms"))]) - (load-bash-alias . [(20230107 1737) ((emacs (24 1)) (seq (2 16))) "Convert bash aliases into eshell ones" single ((:commit . "68cfd70c339c5213c513f7b802b6b50598c9a159") (:authors ("Davide Restivo" . "davide.restivo@yahoo.it")) (:maintainer "Davide Restivo" . "davide.restivo@yahoo.it") (:keywords "emacs" "bash" "eshell" "alias") (:url . "https://github.com/daviderestivo/load-bash-alias"))]) + (load-bash-alias . [(20230310 1657) ((emacs (24 1)) (seq (2 16))) "Convert bash aliases into eshell ones" single ((:commit . "5daab364e65bdd7abe531b8557d88342b446f0c0") (:authors ("Davide Restivo" . "davide.restivo@yahoo.it")) (:maintainer "Davide Restivo" . "davide.restivo@yahoo.it") (:keywords "emacs" "bash" "eshell" "alias") (:url . "https://github.com/daviderestivo/load-bash-alias"))]) (load-env-vars . [(20180511 2210) ((emacs (24))) "Load environment variables from files" single ((:commit . "5da97fabb4d36a00a29c40375fce9c16d8005ab3") (:authors ("Jorge Dias" . "jorge@mrdias.com")) (:maintainer "Jorge Dias" . "jorge@mrdias.com") (:keywords "lisp") (:url . "https://github.com/diasjorge/emacs-load-env-vars"))]) (load-relative . [(20230214 1032) nil "Relative file load (within a multi-file Emacs package)" single ((:commit . "b7987c265a64435299d6b02f960ed2c894c4a145") (:authors ("Rocky Bernstein" . "rocky@gnu.org")) (:maintainer "Rocky Bernstein" . "rocky@gnu.org") (:keywords "internal") (:url . "https://github.com/rocky/emacs-load-relative"))]) (load-theme-buffer-local . [(20120702 2036) nil "Install emacs24 color themes by buffer." single ((:commit . "bc221a88aefec5bdc137b5d5e449e1f1e55ce901") (:authors ("Victor Borja" . "vic.borja@gmail.com")) (:maintainer "Victor Borja" . "vic.borja@gmail.com") (:keywords "faces") (:url . "http://github.com/vic/color-theme-buffer-local"))]) @@ -2923,7 +2939,7 @@ (lockfile-mode . [(20170625 507) nil "Major mode for .lock files" single ((:commit . "496b6035716df0582f879f9488f296947cabead2") (:authors ("Preetpal S. Sohal")) (:maintainer "Preetpal S. Sohal") (:url . "https://github.com/preetpalS/emacs-lockfile-mode"))]) (lodgeit . [(20190802 1308) nil "Paste to a lodgeit powered pastebin" single ((:commit . "442637194d48a7105b7747b8d98772f5899f9e21") (:authors ("Eric Larson" . "eric@ionrock.org")) (:maintainer "Eric Larson" . "eric@ionrock.org") (:keywords "pastebin" "lodgeit") (:url . "https://github.com/ionrock/lodgeit-el"))]) (log4e . [(20211019 948) nil "provide logging framework for elisp" single ((:commit . "737d275eac28dbdfb0b26d28e99da148bfce9d16") (:authors ("Hiroaki Otsu" . "ootsuhiroaki@gmail.com")) (:maintainer "Hiroaki Otsu" . "ootsuhiroaki@gmail.com") (:keywords "log") (:url . "https://github.com/aki2o/log4e"))]) - (log4j-mode . [(20230219 1433) ((emacs (25 1))) "Major mode for viewing log files" single ((:commit . "5c31af49bfbb2f387fa505ba4aeb2004b249af2c") (:authors ("Johan Dykstrom")) (:maintainer "Johan Dykstrom") (:keywords "tools") (:url . "https://github.com/dykstrom/log4j-mode"))]) + (log4j-mode . [(20230318 1521) ((emacs (25 1))) "Major mode for viewing log files" single ((:commit . "98fbe4d3bc5d5034c3b9901bd43268a8f1501a07") (:authors ("Johan Dykstrom")) (:maintainer "Johan Dykstrom") (:keywords "tools") (:url . "https://github.com/dykstrom/log4j-mode"))]) (logalimacs . [(20131021 1829) ((popwin (0 6 2)) (popup (0 5 0)) (stem (20130120))) "Front-end to logaling-command for Ruby gems" single ((:commit . "8286e39502250fc6c3c6656a7f46a8eee8e9a713") (:authors ("Yuta Yamada ")) (:maintainer "Yuta Yamada ") (:keywords "translation" "logaling-command") (:url . "https://github.com/logaling/logalimacs"))]) (logito . [(20201226 534) ((emacs (25 1))) "logging library for Emacs" single ((:commit . "d5934ce10ba3a70d3fcfb94d742ce3b9136ce124") (:authors ("Yann Hodique" . "yann.hodique@gmail.com")) (:maintainer "Yann Hodique" . "yann.hodique@gmail.com") (:keywords "lisp" "extensions"))]) (logms . [(20220704 654) ((emacs (27 1)) (f (0 20 0)) (s (1 9 0)) (ht (2 3))) "Log message with clickable links to context" single ((:commit . "186478e47265b7d40b87d4b4277275a0031f09f7") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "maint" "debug" "log") (:url . "https://github.com/jcs-elpa/logms"))]) @@ -2938,8 +2954,8 @@ (look-mode . [(20220626 641) nil "quick file viewer for image and text file browsing" single ((:commit . "726c5b9098926278603a83e978b488371c0e9143") (:authors ("Peter H. Mao " . "petermao@jpl.nasa.gov")) (:maintainer "Peter H. Mao " . "petermao@jpl.nasa.gov"))]) (loop . [(20160813 1407) nil "friendly imperative loop structures" single ((:commit . "0ce77271d56b0fcdba4b3b38fed526081cd1f674") (:authors ("Wilfred Hughes" . "me@wilfred.me.uk")) (:maintainer "Wilfred Hughes" . "me@wilfred.me.uk") (:keywords "loop" "while" "for each" "break" "continue"))]) (loophole . [(20221126 1556) ((emacs (27 1))) "Manage temporary key bindings" single ((:commit . "dadc3fadc68b13501c4dbe89109f30deb0d3441a") (:authors ("0x60DF" . "0x60df@gmail.com")) (:maintainer "0x60DF" . "0x60df@gmail.com") (:keywords "convenience") (:url . "https://github.com/0x60df/loophole"))]) - (loopy . [(20230129 151) ((emacs (27 1)) (map (3 0)) (seq (2 22)) (compat (29 1 3))) "A looping macro" tar ((:commit . "85b817f000d922c8e98865bb621b7432dfc0e938") (:authors ("Earl Hyatt")) (:maintainer "Earl Hyatt") (:keywords "extensions") (:url . "https://github.com/okamsn/loopy"))]) - (loopy-dash . [(20221125 2001) ((emacs (25 1)) (loopy (0 11 0)) (dash (2 19))) "Dash destructuring for `loopy'" single ((:commit . "771c1d1edd4dfec96b576b1d2b551e4aae066dc9") (:authors ("Earl Hyatt")) (:maintainer "Earl Hyatt") (:keywords "extensions") (:url . "https://github.com/okamsn/loopy"))]) + (loopy . [(20230316 145) ((emacs (27 1)) (map (3 0)) (seq (2 22)) (compat (29 1 3))) "A looping macro" tar ((:commit . "593a6df2b543546c617759a236272980050341db") (:authors ("Earl Hyatt")) (:maintainer "Earl Hyatt") (:keywords "extensions") (:url . "https://github.com/okamsn/loopy"))]) + (loopy-dash . [(20230314 136) ((emacs (25 1)) (loopy (0 11 1)) (dash (2 19))) "Dash destructuring for `loopy'" single ((:commit . "0cb8714f0a77b257039b5269eb257e83718d1ef0") (:authors ("Earl Hyatt")) (:maintainer "Earl Hyatt") (:keywords "extensions") (:url . "https://github.com/okamsn/loopy"))]) (lorem-ipsum . [(20221214 1857) nil "Insert dummy pseudo Latin text" single ((:commit . "4e87a899868e908a7a9e1812831d76c8d072f885") (:authors ("Jean-Philippe Theberge" . "jphil21@sourceforge.net")) (:maintainer "Joe Schafer" . "joe@jschaf.com") (:keywords "tools" "language" "convenience") (:url . "https://github.com/jschaf/emacs-lorem-ipsum"))]) (lox-mode . [(20200619 1700) ((emacs (24 3))) "Major mode for the Lox programming language" single ((:commit . "083a2299e188a516d1e46ef2dd1cbb89db1aec49") (:authors ("Timmy Jose" . "zoltan.jose@gmail.com")) (:maintainer "Timmy Jose" . "zoltan.jose@gmail.com") (:keywords "languages" "lox") (:url . "https://github.com/timmyjose-projects/lox-mode"))]) (lpy . [(20221106 1310) ((emacs (25 1)) (lispy (0 27 0))) "A lispy interface to Python" tar ((:commit . "fa95b11e1023704510cc7dd2897bf8bcc3027cbb") (:authors ("Oleh Krehel" . "ohwoeowho@gmail.com")) (:maintainer "Oleh Krehel" . "ohwoeowho@gmail.com") (:keywords "python" "lisp") (:url . "https://github.com/abo-abo/lpy"))]) @@ -2955,22 +2971,22 @@ (lsp-javacomp . [(20190124 1755) ((emacs (25 1)) (lsp-mode (3 0)) (s (1 2 0))) "Provide Java IDE features powered by JavaComp." single ((:commit . "82aa4ad6ca03a74565c35e855b318b1887bcd89b") (:keywords "java" "tools" "lsp") (:url . "https://github.com/tigersoldier/lsp-javacomp"))]) (lsp-jedi . [(20220430 18) ((emacs (25 1)) (lsp-mode (6 0))) "Lsp client plugin for Python Jedi Language Server" single ((:commit . "5e3eb3e160c2d38b8bd2b5cd3b86fa4f823f9330") (:authors ("Fred Campos" . "fred.tecnologia@gmail.com")) (:maintainer "Fred Campos") (:keywords "language-server" "tools" "python" "jedi" "ide") (:url . "http://github.com/fredcamps/lsp-jedi"))]) (lsp-julia . [(20211229 1534) ((emacs (25 1)) (lsp-mode (6 3)) (julia-mode (0 3))) "Julia support for lsp-mode" tar ((:commit . "e6ff5c09eb73c9b376bfbbd94f47c0366a01cf44") (:authors ("Martin Wolke" . "vibhavp@gmail.com") ("Adam Beckmeyer" . "adam_git@thebeckmeyers.xyz") ("Guido Kraemer" . "gdkrmr@users.noreply.github.com")) (:maintainer "Guido Kraemer" . "gdkrmr@users.noreply.github.com") (:keywords "languages" "tools") (:url . "https://github.com/gdkrmr/lsp-julia"))]) - (lsp-latex . [(20230121 1846) ((emacs (26 3)) (lsp-mode (6 0))) "LSP-mode client for LaTeX, on texlab" single ((:commit . "de080d83f5759ead46dd7a26bb73b7c3a940ef40") (:authors ("ROCKTAKEY" . "rocktakey@gmail.com")) (:maintainer "ROCKTAKEY" . "rocktakey@gmail.com") (:keywords "languages" "tex") (:url . "https://github.com/ROCKTAKEY/lsp-latex"))]) + (lsp-latex . [(20230316 1906) ((emacs (26 3)) (lsp-mode (6 0))) "LSP-mode client for LaTeX, on texlab" single ((:commit . "4f3d7166aeda16099d226066928d89bb44849624") (:authors ("ROCKTAKEY" . "rocktakey@gmail.com")) (:maintainer "ROCKTAKEY" . "rocktakey@gmail.com") (:keywords "languages" "tex") (:url . "https://github.com/ROCKTAKEY/lsp-latex"))]) (lsp-ltex . [(20221231 1658) ((emacs (27 1)) (lsp-mode (6 1))) "LSP Clients for LTEX" single ((:commit . "d1a599c8ec3748c2b81899d5831b6e7158255479") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "lsp" "languagetool" "checker") (:url . "https://github.com/emacs-languagetool/lsp-ltex"))]) - (lsp-metals . [(20221102 1628) ((emacs (26 1)) (scala-mode (1 1)) (lsp-mode (7 0)) (lsp-treemacs (0 2)) (dap-mode (0 3)) (dash (2 18 0)) (f (0 20 0)) (ht (2 0)) (treemacs (2 5))) "Scala Client settings" tar ((:commit . "9a5c8b0e636e6796e5ce8ccea040a583856fb1f5") (:authors ("Ross A. Baker" . "ross@rossabaker.com") ("Evgeny Kurnevsky" . "kurnevsky@gmail.com")) (:maintainer "Ross A. Baker" . "ross@rossabaker.com") (:keywords "languages" "extensions") (:url . "https://github.com/emacs-lsp/lsp-metals"))]) - (lsp-mode . [(20230221 1558) ((emacs (26 3)) (dash (2 18 0)) (f (0 20 0)) (ht (2 3)) (spinner (1 7 3)) (markdown-mode (2 3)) (lv (0)) (eldoc (1 11))) "LSP mode" tar ((:commit . "e6293251a65554fa23f87d0e883d121b4f0aed4e") (:authors ("Vibhav Pant, Fangrui Song, Ivan Yonchovski")) (:maintainer "Vibhav Pant, Fangrui Song, Ivan Yonchovski") (:keywords "languages") (:url . "https://github.com/emacs-lsp/lsp-mode"))]) - (lsp-mssql . [(20191204 1150) ((emacs (25 1)) (lsp-mode (6 2)) (dash (2 14 1)) (f (0 20 0)) (ht (2 0)) (lsp-treemacs (0 1))) "MSSQL LSP bindings" tar ((:commit . "e16e91d6a2a6cdb406ee9b98cfb47f7a32e41d61") (:authors ("Ivan Yonchovski" . "yyoncho@gmail.com")) (:maintainer "Ivan Yonchovski" . "yyoncho@gmail.com") (:keywords "data" "languages") (:url . "https://github.com/emacs-lsp/lsp-mssql"))]) + (lsp-metals . [(20230406 755) ((emacs (26 1)) (scala-mode (1 1)) (lsp-mode (7 0)) (lsp-treemacs (0 2)) (dap-mode (0 3)) (dash (2 18 0)) (f (0 20 0)) (ht (2 0)) (treemacs (2 5)) (posframe (1 4 1))) "Scala Client settings" tar ((:commit . "a11099b79f032aa2fc92a727d2c1e40987727d65") (:authors ("Ross A. Baker" . "ross@rossabaker.com") ("Evgeny Kurnevsky" . "kurnevsky@gmail.com")) (:maintainer "Ross A. Baker" . "ross@rossabaker.com") (:keywords "languages" "extensions") (:url . "https://github.com/emacs-lsp/lsp-metals"))]) + (lsp-mode . [(20230401 434) ((emacs (26 3)) (dash (2 18 0)) (f (0 20 0)) (ht (2 3)) (spinner (1 7 3)) (markdown-mode (2 3)) (lv (0)) (eldoc (1 11))) "LSP mode" tar ((:commit . "955b2805b4e3488189da9230382de27f74d20290") (:authors ("Vibhav Pant, Fangrui Song, Ivan Yonchovski")) (:maintainer "Vibhav Pant, Fangrui Song, Ivan Yonchovski") (:keywords "languages") (:url . "https://github.com/emacs-lsp/lsp-mode"))]) + (lsp-mssql . [(20230316 1612) ((emacs (25 1)) (lsp-mode (6 2)) (dash (2 14 1)) (f (0 20 0)) (ht (2 0)) (lsp-treemacs (0 1))) "MSSQL LSP bindings" tar ((:commit . "9d9a14a2b40c5fd13b8e33fccd397283a2437526") (:authors ("Ivan Yonchovski" . "yyoncho@gmail.com")) (:maintainer "Ivan Yonchovski" . "yyoncho@gmail.com") (:keywords "data" "languages") (:url . "https://github.com/emacs-lsp/lsp-mssql"))]) (lsp-origami . [(20211016 1045) ((origami (1 0)) (lsp-mode (6 1))) "origami.el support for lsp-mode" single ((:commit . "5b88ab77dc2696c93fa5dd9debe183821c533b71") (:authors ("Vibhav Pant")) (:maintainer "Vibhav Pant") (:keywords "languages" "lsp-mode") (:url . "https://github.com/emacs-lsp/lsp-origami"))]) (lsp-p4 . [(20190127 1049) ((lsp-mode (3 0))) "P4 support for lsp-mode" tar ((:commit . "084e33a5782f9153502d9b03e63d9cbbe81cdaeb") (:authors ("Dmitri Makarov")) (:maintainer "Dmitri Makarov") (:keywords "lsp" "p4") (:url . "https://github.com/dmakarov/p4ls"))]) (lsp-pascal . [(20200422 1610) ((emacs (24 4)) (lsp-mode (6 3))) "LSP client for Pascal" single ((:commit . "9b65bf9e923b1459d1feb1d7528e5855e7bd4ef2") (:authors ("Arjan Adriaanse" . "arjan@adriaan.se")) (:maintainer "Arjan Adriaanse" . "arjan@adriaan.se") (:keywords "languages" "tools") (:url . "https://github.com/arjanadriaanse/lsp-pascal"))]) (lsp-pyre . [(20190406 335) ((lsp-mode (6 0))) "lsp-mode client for python using pyre" single ((:commit . "e177b8f5efd1a955b5753aeb5d1894e6d21be35a") (:authors ("John Allen" . "oss@porcnick.com")) (:maintainer "John Allen" . "oss@porcnick.com") (:url . "https://github.com/jra3/lsp-pyre"))]) - (lsp-pyright . [(20221201 1501) ((emacs (26 1)) (lsp-mode (7 0)) (dash (2 18 0)) (ht (2 0))) "Python LSP client using Pyright" single ((:commit . "4cd2adbb32287278d9d9da59a3212a53ecdf8036") (:authors ("Arif Rezai, Vincent Zhang, Andrew Christianson")) (:maintainer "Arif Rezai, Vincent Zhang, Andrew Christianson") (:keywords "languages" "tools" "lsp") (:url . "https://github.com/emacs-lsp/lsp-pyright"))]) + (lsp-pyright . [(20230225 1118) ((emacs (26 1)) (lsp-mode (7 0)) (dash (2 18 0)) (ht (2 0))) "Python LSP client using Pyright" single ((:commit . "54a2acddfdd7c3d31cb804a042305a3c6e60cf81") (:authors ("Arif Rezai, Vincent Zhang, Andrew Christianson")) (:maintainer "Arif Rezai, Vincent Zhang, Andrew Christianson") (:keywords "languages" "tools" "lsp") (:url . "https://github.com/emacs-lsp/lsp-pyright"))]) (lsp-python-ms . [(20211204 1209) ((emacs (25 1)) (lsp-mode (6 1))) "The lsp-mode client for Microsoft python-language-server" single ((:commit . "abf4d89ecf2fa0871130df5fce6065b7cf0a2721") (:authors ("Charl Botha")) (:maintainer "Andrew Christianson, Vincent Zhang") (:keywords "languages" "tools") (:url . "https://github.com/emacs-lsp/lsp-python-ms"))]) (lsp-rescript . [(20220314 1957) ((lsp-mode (7 0 1)) (emacs (25 1)) (rescript-mode (0 1))) "LSP client configuration for lsp-mode and rescript-vscode" single ((:commit . "7baf9adf10234cf964feefae99050268e9bc5681") (:authors ("John Lee")) (:maintainer "John Lee") (:keywords "languages") (:url . "https://github.com/jjlee/lsp-rescript"))]) (lsp-scheme . [(20221029 816) ((emacs (26 1)) (f (0 20 0)) (lsp-mode (8 0 0))) "Scheme support for lsp-mode" tar ((:commit . "447df67e0347a2f26101432066a8724b1f39446e") (:authors ("Ricardo G. Herdt" . "r.herdt@posteo.de")) (:maintainer "Ricardo G. Herdt" . "r.herdt@posteo.de") (:keywords "languages" "lisp" "tools") (:url . "https://codeberg.org/rgherdt/emacs-lsp-scheme"))]) (lsp-sonarlint . [(20220510 1802) ((emacs (25)) (dash (2 12 0)) (lsp-mode (6 3)) (ht (2 3))) "Emacs Sonarlint lsp client" tar ((:commit . "a429be2aea7797369a3c751ef54e3554733117be") (:authors ("Fermin MF" . "fmfs@posteo.net")) (:maintainer "Fermin MF" . "fmfs@posteo.net") (:keywords "languages" "tools" "php" "javascript" "xml" "ruby" "html" "scala" "java" "python") (:url . "https://github.com/emacs-lsp/lsp-sonarlint"))]) (lsp-sourcekit . [(20210905 2017) ((emacs (25 1)) (lsp-mode (5))) "sourcekit-lsp client for lsp-mode" single ((:commit . "97ff36b228a61e69734c7180f33cc6951b1a600f") (:authors ("Daniel Martín")) (:maintainer "Daniel Martín") (:keywords "languages" "lsp" "swift" "objective-c" "c++") (:url . "https://github.com/emacs-lsp/lsp-sourcekit"))]) - (lsp-tailwindcss . [(20230215 1425) ((lsp-mode (7 1)) (f (0 20 0)) (emacs (26 1))) "A lsp-mode client for tailwindcss" single ((:commit . "563c1dddb26c82b82dcac0b436594b17375a1480") (:authors ("A.I." . "merrick@luois.me")) (:maintainer "A.I." . "merrick@luois.me") (:keywords "language" "tools") (:url . "https://github.com/merrickluo/lsp-tailwindcss"))]) + (lsp-tailwindcss . [(20230407 951) ((lsp-mode (7 1)) (f (0 20 0)) (emacs (26 1))) "A lsp-mode client for tailwindcss" single ((:commit . "6ade9cacd1db89da0e9c0941a86408a42091d479") (:authors ("A.I." . "merrick@luois.me")) (:maintainer "A.I." . "merrick@luois.me") (:keywords "language" "tools") (:url . "https://github.com/merrickluo/lsp-tailwindcss"))]) (lsp-treemacs . [(20221001 1958) ((emacs (26 1)) (dash (2 18 0)) (f (0 20 0)) (ht (2 0)) (treemacs (2 5)) (lsp-mode (6 0))) "LSP treemacs" tar ((:commit . "2894e6dec583eaa77037627e9d8c3bc89cf7273d") (:authors ("Ivan Yonchovski")) (:maintainer "Ivan Yonchovski") (:keywords "languages") (:url . "https://github.com/emacs-lsp/lsp-treemacs"))]) (lsp-ui . [(20230116 2024) ((emacs (26 1)) (dash (2 18 0)) (lsp-mode (6 0)) (markdown-mode (2 3))) "UI modules for lsp-mode" tar ((:commit . "295d8984da06a745b0a36c56e28ce915bc389adb") (:authors ("Sebastien Chapuis , Fangrui Song" . "i@maskray.me")) (:maintainer "Sebastien Chapuis , Fangrui Song" . "i@maskray.me") (:keywords "languages" "tools") (:url . "https://github.com/emacs-lsp/lsp-ui"))]) (lua-mode . [(20221218 605) ((emacs (24 3))) "a major-mode for editing Lua scripts" single ((:commit . "ad639c62e38a110d8d822c4f914af3e20b40ccc4") (:authors ("2011-2013 immerrr" . "immerrr+lua@gmail.com") ("2010-2011 Reuben Thomas" . "rrt@sc3d.org") ("2006 Juergen Hoetzel" . "juergen@hoetzel.info") ("2004 various (support for Lua 5 and byte compilation)") ("2001 Christian Vogler" . "cvogler@gradient.cis.upenn.edu") ("1997 Bret Mogilefsky" . "mogul-lua@gelatinous.com") ("tcl-mode by Gregor Schmid" . "schmid@fb3-s7.math.tu-berlin.de") ("with tons of assistance from") ("Paul Du Bois" . "pld-lua@gelatinous.com") ("Aaron Smith" . "aaron-lua@gelatinous.com")) (:maintainer "2011-2013 immerrr" . "immerrr+lua@gmail.com") (:keywords "languages" "processes" "tools") (:url . "https://immerrr.github.io/lua-mode"))]) @@ -2988,24 +3004,23 @@ (m-buffer . [(20220719 1850) ((seq (2 14))) "List-Oriented, Functional Buffer Manipulation" tar ((:commit . "d2e35bf9293367f1a2d19f259f32a35bd9f4788b") (:authors ("Phillip Lord" . "phillip.lord@russet.org.uk")) (:maintainer "Phillip Lord" . "phillip.lord@russet.rg.uk"))]) (mac-pseudo-daemon . [(20200215 513) ((cl-lib (0 1))) "Daemon mode that plays nice with Mac OS." single ((:commit . "564b006835facc4a8df247d8a47ab1030d7e7beb") (:authors ("Ryan C. Thompson")) (:maintainer "Ryan C. Thompson") (:keywords "convenience" "osx" "mac") (:url . "https://github.com/DarwinAwardWinner/osx-pseudo-daemon"))]) (maces-game . [(20170903 1551) ((dash (2 12 0)) (cl-lib (0 5)) (emacs (24))) "another anagram game." tar ((:commit . "6a067422d305ac51612842930ed6686dc615ffec") (:authors ("Pawel Bokota" . "pawelb.lnx@gmail.com")) (:maintainer "Pawel Bokota" . "pawelb.lnx@gmail.com") (:keywords "games" "word games" "anagram") (:url . "https://github.com/pawelbx/anagram-game"))]) - (macports . [(20230215 142) ((emacs (25 1)) (transient (0 1 0))) "A porcelain for MacPorts" tar ((:commit . "e7b16e8b78db6d7fcc17eb05fa3a2a4ed439f2f2") (:authors ("Aaron Madlon-Kay")) (:maintainer "Aaron Madlon-Kay") (:keywords "convenience") (:url . "https://github.com/amake/macports.el"))]) + (macports . [(20230318 239) ((emacs (25 1)) (transient (0 1 0))) "A porcelain for MacPorts" tar ((:commit . "1c751c20936d8f3d45d5017b66a9b16a65659bf3") (:authors ("Aaron Madlon-Kay")) (:maintainer "Aaron Madlon-Kay") (:keywords "convenience") (:url . "https://github.com/amake/macports.el"))]) (macro-math . [(20130328 1604) nil "in-buffer mathematical operations" single ((:commit . "216e59371e9ee39c34117ba79b9acd78bb415750") (:authors ("Nikolaj Schumacher ")) (:maintainer "Nikolaj Schumacher ") (:keywords "convenience") (:url . "http://nschum.de/src/emacs/macro-math/"))]) - (macrostep . [(20221026 1347) ((cl-lib (0 5))) "interactive macro expander" tar ((:commit . "75ecd041219239f0dceab4883594ea2fe366b484") (:authors ("Jon Oddie" . "j.j.oddie@gmail.com")) (:maintainer "Jon Oddie" . "j.j.oddie@gmail.com") (:keywords "lisp" "languages" "macro" "debugging") (:url . "https://github.com/emacsorphanage/macrostep"))]) + (macrostep . [(20230316 3) ((cl-lib (0 5))) "Interactive macro expander" tar ((:commit . "cdaa3a5e8235b6edd2e862eb272710471a82039d") (:authors ("Jon Oddie" . "j.j.oddie@gmail.com")) (:maintainer "Jon Oddie" . "j.j.oddie@gmail.com") (:keywords "lisp" "languages" "macro" "debugging") (:url . "https://github.com/emacsorphanage/macrostep"))]) (macrostep-geiser . [(20210717 801) ((emacs (24 4)) (macrostep (0 9)) (geiser (0 12))) "Macrostep for `geiser'" single ((:commit . "f6a2d5bb96ade4f23df557649af87ebd0cc45125") (:authors ("Nikita Bloshchanevich")) (:maintainer "Nikita Bloshchanevich") (:keywords "languages" "scheme") (:url . "https://github.com/nbfalcon/macrostep-geiser"))]) (madhat2r-theme . [(20170203 30) ((emacs (24))) "dark color theme that is easy on the eyes" single ((:commit . "6b387f09de055cfcc15d74981cd4f32f8f9a7323") (:authors ("Micah Duke")) (:maintainer "Micah Duke") (:keywords "color" "theme") (:url . "https://github.com/madhat2r/madhat2r-theme"))]) (mag-menu . [(20150505 1850) ((splitter (0 1 0))) "Intuitive keyboard-centric menu system" single ((:commit . "9b9277021cd09fb1dba64b1d2a00705d20914bd6") (:authors ("Steven Thomas")) (:maintainer "Steven Thomas") (:keywords "convenience") (:url . "https://github.com/chumpage/mag-menu"))]) (magic-filetype . [(20180219 1552) ((emacs (24)) (s (1 9 0))) "Enhance filetype major mode" single ((:commit . "019494add5ff02dd36cb3f500142fc51125522cc") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "emulations" "vim" "ft" "file" "magic-mode") (:url . "https://github.com/zonuexe/magic-filetype.el"))]) (magic-latex-buffer . [(20210306 422) ((cl-lib (0 5)) (emacs (25 1))) "Magically enhance LaTeX-mode font-locking for semi-WYSIWYG editing" single ((:commit . "903ec91872760e47c0e5715795f8465173615098") (:authors ("zk_phi")) (:maintainer "zk_phi") (:url . "http://zk-phi.github.io/"))]) (magik-mode . [(20230103 1503) nil "mode for editing Magik + some utils." tar ((:commit . "a2ddc7cad487e6165c2e2ac26acec62b1f7bbeca") (:keywords "languages") (:url . "http://github.com/roadrunner1776/magik"))]) - (magit . [(20230221 648) ((emacs (25 1)) (compat (29 1 3 4)) (dash (20221013)) (git-commit (20230101)) (magit-section (20230101)) (transient (20230201)) (with-editor (20230118))) "A Git porcelain inside Emacs." tar ((:commit . "97a95f70079b6613bf98d2306279d3e03fe51234") (:authors ("Marius Vollmer" . "marius.vollmer@gmail.com") ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "git" "tools" "vc") (:url . "https://github.com/magit/magit"))]) - (magit-annex . [(20220926 300) ((cl-lib (0 3)) (magit (3 0 0))) "Control git-annex from Magit" single ((:commit . "0b3787d2c2ed0603467be8152847b7539c8a955c") (:authors ("Kyle Meyer" . "kyle@kyleam.com") ("Rémi Vanicat" . "vanicat@debian.org")) (:maintainer "Kyle Meyer" . "kyle@kyleam.com") (:keywords "vc" "tools") (:url . "https://github.com/magit/magit-annex"))]) - (magit-circleci . [(20191209 2113) ((dash (2 16 0)) (transient (0 1 0)) (magit (2 90 0)) (emacs (25 3))) "CircleCI integration for Magit" single ((:commit . "3425ad5b16cb48d6802b7e9ed044b4cd7a99c785") (:authors ("Adrien Brochard")) (:maintainer "Adrien Brochard") (:keywords "circleci" "continuous" "integration" "magit" "vc" "tools") (:url . "https://github.com/abrochard/magit-circleci"))]) + (magit . [(20230402 1342) ((emacs (25 1)) (compat (29 1 3 4)) (dash (20221013)) (git-commit (20230101)) (magit-section (20230101)) (transient (20230201)) (with-editor (20230118))) "A Git porcelain inside Emacs." tar ((:commit . "1abfb52886536f90f3561b18a49182ad21b6d8e8") (:authors ("Marius Vollmer" . "marius.vollmer@gmail.com") ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "git" "tools" "vc") (:url . "https://github.com/magit/magit"))]) + (magit-annex . [(20230407 1200) ((cl-lib (0 3)) (magit (3 0 0))) "Control git-annex from Magit" single ((:commit . "255e443e19a32e716ff414e09ad5e00f6f8bc8fb") (:authors ("Kyle Meyer" . "kyle@kyleam.com") ("Rémi Vanicat" . "vanicat@debian.org")) (:maintainer "Kyle Meyer" . "kyle@kyleam.com") (:keywords "vc" "tools") (:url . "https://github.com/magit/magit-annex"))]) (magit-commit-mark . [(20230214 1821) ((emacs (28 1)) (magit (3 3 0))) "Support marking commits as read" single ((:commit . "6ed61986ae28c01d0f8c4f2bcff8ab70707488df") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:url . "https://codeberg.org/ideasman42/emacs-magit-commit-mark"))]) (magit-delta . [(20220125 50) ((emacs (25 1)) (magit (20200426)) (xterm-color (2 0))) "Use Delta when displaying diffs in Magit" single ((:commit . "5fc7dbddcfacfe46d3fd876172ad02a9ab6ac616") (:authors ("Dan Davison" . "dandavison7@gmail.com")) (:maintainer "Dan Davison" . "dandavison7@gmail.com") (:url . "https://github.com/dandavison/magit-delta"))]) (magit-diff-flycheck . [(20190524 551) ((magit (2)) (flycheck (31)) (seq (2)) (emacs (25 1))) "Report errors in diffs" single ((:commit . "ad58efa312d708f25661dfcc2a7f83a833cca328") (:authors ("Alex Ragone" . "ragonedk@gmail.com")) (:maintainer "Alex Ragone" . "ragonedk@gmail.com") (:keywords "convenience" "matching") (:url . "https://github.com/ragone/magit-diff-flycheck"))]) (magit-filenotify . [(20151116 2340) ((magit (1 3 0)) (emacs (24 4))) "Refresh status buffer when git tree changes" single ((:commit . "c0865b3c41af20b6cd89de23d3b0beb54c8401a4") (:authors ("Rüdiger Sonderfeld" . "ruediger@c-plusplus.de")) (:maintainer "Rüdiger Sonderfeld" . "ruediger@c-plusplus.de") (:keywords "tools"))]) (magit-find-file . [(20150702 830) ((magit (2 1 0)) (dash (2 8 0))) "completing-read over all files in Git" single ((:commit . "035da838b1a19e7a5ee135b4ca8475f4e235b61e") (:authors ("Bradley Wright" . "brad@intranation.com")) (:maintainer "Bradley Wright" . "brad@intranation.com") (:keywords "git") (:url . "https://github.com/bradleywright/magit-find-file.el"))]) - (magit-gerrit . [(20210831 1453) ((emacs (25 1)) (magit (2 90 1)) (transient (0 3 0))) "Magit plugin for Gerrit Code Review" single ((:commit . "9104713f6ea918e9faaf25f2cc182c65029db936") (:authors ("Brian Fransioli" . "assem@terranpro.org")) (:maintainer "Brian Fransioli" . "assem@terranpro.org") (:url . "https://github.com/emacsorphanage/magit-gerrit"))]) + (magit-gerrit . [(20230309 2251) ((emacs (25 1)) (magit (2 90 1)) (transient (0 3 0))) "Magit plugin for Gerrit Code Review" single ((:commit . "a97521574c5b7d4b7ab89e25c358c87fd5b1887f") (:authors ("Brian Fransioli" . "assem@terranpro.org")) (:maintainer "Brian Fransioli" . "assem@terranpro.org") (:url . "https://github.com/emacsorphanage/magit-gerrit"))]) (magit-gh-pulls . [(20191230 1944) ((emacs (24 4)) (gh (0 9 1)) (magit (2 12 0)) (pcache (0 2 3)) (s (1 6 1))) "GitHub pull requests extension for Magit" single ((:commit . "57f3a5158bbc7bfd169ee136fde351cce999e0ca") (:authors ("Yann Hodique" . "yann.hodique@gmail.com")) (:maintainer "Yann Hodique" . "yann.hodique@gmail.com") (:keywords "git" "tools") (:url . "https://github.com/sigma/magit-gh-pulls"))]) (magit-gitflow . [(20170929 824) ((magit (2 1 0)) (magit-popup (2 2 0))) "gitflow extension for magit" single ((:commit . "cc41b561ec6eea947fe9a176349fb4f771ed865b") (:authors ("Jan Tatarik" . "Jan.Tatarik@gmail.com")) (:maintainer "Jan Tatarik" . "Jan.Tatarik@gmail.com") (:keywords "vc" "tools") (:url . "https://github.com/jtatarik/magit-gitflow"))]) (magit-imerge . [(20220306 2311) ((emacs (25 1)) (magit (3 0 0))) "Magit extension for git-imerge" single ((:commit . "37bca48218dc32cad964e01e0f9936a90f634fba") (:authors ("Kyle Meyer" . "kyle@kyleam.com")) (:maintainer "Kyle Meyer" . "kyle@kyleam.com") (:keywords "vc" "tools") (:url . "https://github.com/magit/magit-imerge"))]) @@ -3016,23 +3031,24 @@ (magit-popup . [(20200719 1015) ((emacs (24 4)) (dash (2 13 0))) "Define prefix-infix-suffix command combos" tar ((:commit . "d8585fa39f88956963d877b921322530257ba9f5") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "bindings") (:url . "https://github.com/magit/magit-popup"))]) (magit-rbr . [(20181009 2016) ((magit (2 13 0)) (emacs (24 3))) "Support for git rbr in Magit" single ((:commit . "029203b3e48537205052a058e964f058cd802c3c") (:authors ("Anatoly Fayngelerin" . "fanatoly+magitrbr@gmail.com")) (:maintainer "Anatoly Fayngelerin" . "fanatoly+magitrbr@gmail.com") (:keywords "git" "magit" "rbr" "tools") (:url . "https://github.com/fanatoly/magit-rbr"))]) (magit-reviewboard . [(20200727 1748) ((emacs (25 2)) (magit (2 13 0)) (s (1 12 0)) (request (0 3 0))) "Show open Reviewboard reviews in Magit" single ((:commit . "aceedff88921f1dfef8a6b2fb18fe316fb7223a8") (:authors ("Jules Tamagnan" . "jtamagnan@gmail.com")) (:maintainer "Jules Tamagnan" . "jtamagnan@gmail.com") (:keywords "magit" "vc") (:url . "http://github.com/jtamagnan/magit-reviewboard"))]) - (magit-section . [(20230213 2018) ((emacs (25 1)) (compat (29 1 3 4)) (dash (20221013))) "Sections for read-only buffers." tar ((:commit . "deb10e984e16201182b0569f7df7d30ec3b8afa9") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "tools") (:url . "https://github.com/magit/magit"))]) + (magit-section . [(20230314 1653) ((emacs (25 1)) (compat (29 1 3 4)) (dash (20221013))) "Sections for read-only buffers." tar ((:commit . "95781f0c052d254e9217918908295f02c92fb379") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "tools") (:url . "https://github.com/magit/magit"))]) + (magit-stats . [(20230223 1819) ((emacs (25 1))) "Generates GIT Repo Statistics Report" single ((:commit . "41b18e5fc664dba93981a7931f476632c5b54a7d") (:authors ("Rahul M. Juliato")) (:maintainer "Rahul M. Juliato") (:keywords "vc" "convenience") (:url . "https://github.com/LionyxML/magit-stats"))]) (magit-stgit . [(20220914 1349) ((emacs (24 4)) (magit (2 12 0)) (magit-popup (2 12 0))) "StGit extension for Magit" single ((:commit . "bf96fa0f40c087329ad7e6a3b1946de7df03559c") (:authors ("Lluís Vilanova" . "vilanova@ac.upc.edu")) (:maintainer "UNMAINTAINED") (:keywords "vc" "tools"))]) (magit-svn . [(20220314 1451) ((emacs (25 1)) (magit (2 90 1)) (transient (0 3 2))) "Git-Svn extension for Magit" single ((:commit . "b8277081db90977247ae3900ea6afeb0ca644d36") (:authors ("Phil Jackson" . "phil@shellarchive.co.uk")) (:maintainer "Phil Jackson" . "phil@shellarchive.co.uk") (:keywords "vc" "tools"))]) (magit-tbdiff . [(20220527 2213) ((emacs (25 1)) (magit (3 0 0))) "Magit extension for range diffs" single ((:commit . "55e6443710def357f3f78eea27d5bbe023d868f5") (:authors ("Kyle Meyer" . "kyle@kyleam.com")) (:maintainer "Kyle Meyer" . "kyle@kyleam.com") (:keywords "vc" "tools") (:url . "https://github.com/magit/magit-tbdiff"))]) - (magit-todos . [(20220822 2224) ((emacs (26 1)) (async (1 9 2)) (dash (2 13 0)) (f (0 17 2)) (hl-todo (1 9 0)) (magit (2 13 0)) (pcre2el (1 8)) (s (1 12 0)) (transient (0 2 0))) "Show source file TODOs in Magit" single ((:commit . "c5030cc27c7c1a48db52b0134bf2648a59a43176") (:authors ("Adam Porter" . "adam@alphapapa.net")) (:maintainer "Adam Porter" . "adam@alphapapa.net") (:keywords "magit" "vc") (:url . "http://github.com/alphapapa/magit-todos"))]) + (magit-todos . [(20230307 549) ((emacs (26 1)) (async (1 9 2)) (dash (2 13 0)) (f (0 17 2)) (hl-todo (1 9 0)) (magit (2 13 0)) (pcre2el (1 8)) (s (1 12 0)) (transient (0 2 0))) "Show source file TODOs in Magit" single ((:commit . "7724259a008144b8cfc6cacdae3e764f207a03e7") (:authors ("Adam Porter" . "adam@alphapapa.net")) (:maintainer "Adam Porter" . "adam@alphapapa.net") (:keywords "magit" "vc") (:url . "http://github.com/alphapapa/magit-todos"))]) (magit-topgit . [(20161105 1623) ((emacs (24 4)) (magit (2 1 0))) "TopGit extension for Magit" single ((:commit . "11489ea798bc88d0ea5244bbf725285eedfefbef") (:authors ("Yann Hodique" . "yann.hodique@gmail.com")) (:maintainer "Robin Green" . "greenrd@greenrd.org") (:keywords "vc" "tools"))]) - (magit-vcsh . [(20190817 2014) ((magit (2 90 1)) (vcsh (0 4)) (emacs (24 4))) "Magit vcsh integration" single ((:commit . "fcff128cdbe3ef547dc64f2496cb6405b8ee21ca") (:authors ("Štěpán Němec" . "stepnem@gmail.com")) (:maintainer "Štěpán Němec" . "stepnem@gmail.com") (:keywords "vc" "files" "magit") (:url . "https://gitlab.com/stepnem/magit-vcsh-el"))]) + (magit-vcsh . [(20230402 1219) ((magit (2 90 1)) (vcsh (0 4)) (emacs (24 4))) "Magit vcsh integration" single ((:commit . "fd6c86c066b14bbf78644d38eca9711d6d9544a1") (:authors ("Štěpán Němec" . "stepnem@smrk.net")) (:maintainer "Štěpán Němec" . "stepnem@smrk.net") (:keywords "vc" "files" "magit") (:url . "http://git.smrk.net/magit-vcsh.el"))]) (magithub . [(20220315 117) ((emacs (25)) (magit (2 12)) (s (1 12 0)) (ghub+ (0 3)) (git-commit (2 12)) (markdown-mode (2 3))) "Magit interfaces for GitHub" tar ((:commit . "dd62c7057155c0a334e6d9087779a2923d2300b8") (:authors ("Sean Allred" . "code@seanallred.com")) (:maintainer "Sean Allred" . "code@seanallred.com") (:keywords "git" "tools" "vc") (:url . "https://github.com/vermiculus/magithub"))]) (magma-mode . [(20211018 917) ((emacs (24 3)) (cl-lib (0 3)) (dash (2 6 0)) (f (0 17 1))) "Mode for editing Magma source code" tar ((:commit . "11428d18ce3742334923d14ff2a8f493e7bd5ef0") (:url . "https://github.com/ThibautVerron/magma-mode"))]) (magnatune . [(20151030 1935) ((dash (2 9 0)) (s (1 9 0))) "browse magnatune's music catalog" tar ((:commit . "605b01505ba30589c77ebb4c96834b5072ccbdd4"))]) (magrant . [(20210706 1438) ((emacs (25 1)) (dash (2 17 0)) (s (1 12 0)) (tablist (0 70)) (transient (0 2 0)) (friendly-shell-command (0 2 3))) "Transient Interface to Vagrant" tar ((:commit . "6309c001355126e3ade79493479b517925943d17") (:keywords "processes" "terminals") (:url . "https://github.com/p3r7/magrant"))]) - (majapahit-theme . [(20160817 1848) nil "Color theme with a dark and light versions" tar ((:commit . "77c96df7619666b2102d90d452eeadf04adc89a6"))]) + (majapahit-themes . [(20221207 121) nil "Color theme with a dark and light versions" tar ((:commit . "7200f16f0fd4cc18e8c7d82b62cc351b610609af") (:authors ("Alexander F. Adhyatma")) (:maintainer "Alexander F. Adhyatma") (:url . "http:/gitlab.com/franksn/majapahit-theme/"))]) (major-mode-hydra . [(20210221 834) ((dash (2 18 0)) (pretty-hydra (0 2 2)) (emacs (25))) "Major mode keybindings managed by Hydra" single ((:commit . "84c1929a5153be169ca5c36737439d51dffde505") (:authors ("Jerry Peng" . "pr2jerry@gmail.com")) (:maintainer "Jerry Peng" . "pr2jerry@gmail.com") (:url . "https://github.com/jerrypnz/major-mode-hydra.el"))]) (major-mode-icons . [(20220210 1404) ((emacs (24 3)) (powerline (2 4)) (all-the-icons (2 3 0))) "display icon for major-mode on mode-line." tar ((:commit . "b0214e0af13cd3691c4d28f03e3108bd98ec7a85") (:keywords "frames" "multimedia") (:url . "https://repo.or.cz/major-mode-icons.git"))]) (make-color . [(20140625 1150) nil "Alternative to picking color - update fg/bg color by pressing r/g/b/... keys" single ((:commit . "a1b34e95ccd3ebee4fba1489ab613d0b3078026d") (:authors ("Alex Kost" . "alezost@gmail.com")) (:maintainer "Alex Kost" . "alezost@gmail.com") (:keywords "color") (:url . "https://github.com/alezost/make-color.el"))]) (make-it-so . [(20190625 1036) ((swiper (0 8 0)) (emacs (24))) "Transform files with Makefile recipes." tar ((:commit . "b73dfb640588123c9eece230ad72b37604f5c126") (:authors ("Oleh Krehel" . "ohwoeowho@gmail.com")) (:maintainer "Oleh Krehel" . "ohwoeowho@gmail.com") (:keywords "make" "dired") (:url . "https://github.com/abo-abo/make-it-so"))]) - (makefile-executor . [(20220928 936) ((emacs (27 1)) (dash (2 11 0)) (f (0 11 0)) (s (1 10 0))) "Commands for conveniently running makefile targets" single ((:commit . "170d14d834a0d163cd618d642d4580ff75b014be") (:authors ("Lowe Thiderman" . "lowe.thiderman@gmail.com")) (:maintainer "Lowe Thiderman" . "lowe.thiderman@gmail.com") (:keywords "processes") (:url . "https://github.com/thiderman/makefile-executor.el"))]) + (makefile-executor . [(20230224 1329) ((emacs (27 1)) (dash (2 11 0)) (f (0 11 0)) (s (1 10 0))) "Commands for conveniently running makefile targets" single ((:commit . "d1d98eaf522a767561f6c7cbd8d2526be58b3ec5") (:authors ("Olivia Thiderman" . "olivia@thiderman.org")) (:maintainer "Olivia Thiderman" . "olivia@thiderman.org") (:keywords "processes") (:url . "https://github.com/Olivia5k/makefile-executor.el"))]) (makey . [(20131231 1430) ((cl-lib (0 2))) "interactive commandline mode" single ((:commit . "a61781e69d3b451551e269446e1c5f624ab81137") (:authors ("Mickey Petersen" . "mickey@masteringemacs.org")) (:maintainer "Mickey Petersen" . "mickey@masteringemacs.org"))]) (malinka . [(20171202 1021) ((s (1 9 0)) (dash (2 4 0)) (f (0 11 0)) (cl-lib (0 3)) (rtags (0 0)) (projectile (0 11 0))) "A C/C++ project configuration package for Emacs" single ((:commit . "e3dc5b0703a5954057110b82cb397a990ace23e6") (:authors ("Lefteris Karapetsas" . "lefteris@refu.co")) (:maintainer "Lefteris Karapetsas" . "lefteris@refu.co") (:keywords "c" "c++" "project-management") (:url . "https://github.com/LefterisJP/malinka"))]) (mallard-mode . [(20131204 425) nil "Major mode for editing Mallard files" tar ((:commit . "0a4cfede57bc31134495804ce513cc106de8de3c") (:authors ("Jaromir Hradilek" . "jhradilek@gmail.com")) (:maintainer "Jaromir Hradilek" . "jhradilek@gmail.com") (:keywords "xml" "mallard") (:url . "https://github.com/jhradilek/emacs-mallard-mode"))]) @@ -3047,12 +3063,12 @@ (map-progress . [(20190128 16) ((cl-lib (0 6 1))) "mapping macros that report progress" single ((:commit . "1fb916159cd054c233ce3c80d9d01adfae640297") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "convenience") (:url . "https://github.com/tarsius/map-progress"))]) (map-regexp . [(20190128 18) ((cl-lib (0 6 1))) "map over matches of a regular expression" single ((:commit . "ae2d1c22f786ad987aef3e319925e80160a887a0") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "convenience") (:url . "https://github.com/tarsius/map-regexp"))]) (marcopolo . [(20160421 1004) ((s (1 9 0)) (dash (2 9 0)) (pkg-info (0 5 0)) (request (0 1 0))) "Emacs client to the Docker HUB/Registry API" tar ((:commit . "85db828f2bb4346a811b3326349b1c6d0aae4601") (:authors ("Nicolas Lamirault" . "nicolas.lamirault@gmail.com")) (:maintainer "Nicolas Lamirault" . "nicolas.lamirault@gmail.com") (:keywords "docker") (:url . "https://github.com/nlamirault/marcopolo"))]) - (marginalia . [(20230217 2050) ((emacs (27 1)) (compat (29 1 3 4))) "Enrich existing commands with completion annotations" single ((:commit . "ccf573e2145d9deb9d734432351eefc87fc1bc16") (:authors ("Omar Antolín Camarena , Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainer "Omar Antolín Camarena , Daniel Mendler" . "mail@daniel-mendler.de") (:url . "https://github.com/minad/marginalia"))]) + (marginalia . [(20230403 2057) ((emacs (27 1)) (compat (29 1 4 0))) "Enrich existing commands with completion annotations" single ((:commit . "c1ae5807731fea4837d20489436232731ae8fb9f") (:authors ("Omar Antolín Camarena , Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainer "Omar Antolín Camarena , Daniel Mendler" . "mail@daniel-mendler.de") (:url . "https://github.com/minad/marginalia"))]) (mark-multiple . [(20121118 1554) nil "Sorta lets you mark several regions at once." tar ((:commit . "f6a53c7c5283d640ae718f4548b0fda78877a375") (:authors ("Magnar Sveen" . "magnars@gmail.com")) (:maintainer "Magnar Sveen" . "magnars@gmail.com") (:keywords "marking" "library"))]) (mark-thing-at . [(20201219 232) ((emacs (26)) (choice-program (0 13))) "Mark a pattern at the current point" single ((:commit . "a622d128afc8d2d67de897666a1e2eccba8d7818") (:authors ("Paul Landes")) (:maintainer "Paul Landes") (:keywords "mark" "point" "lisp") (:url . "https://github.com/plandes/mark-thing-at"))]) (mark-tools . [(20130614 1025) nil "Some simple tools to access the mark-ring in Emacs" single ((:commit . "a11b61effa90bd0abc876d12573674d36fc17f0c") (:authors ("Alex Bennée" . "alex@bennee.com")) (:maintainer "Alex Bennée" . "alex@bennee.com") (:url . "https://github.com/stsquad/emacs-mark-tools"))]) (markdown-changelog . [(20200120 2253) ((emacs (26)) (dash (2 13 0))) "Maintain changelog entries" single ((:commit . "1a2c3a4c3e4196f2b5dbb145b01b4bc435a93a96") (:authors ("Paul Landes")) (:maintainer "Paul Landes") (:keywords "markdown" "changelog" "files") (:url . "https://github.com/plandes/markdown-changelog"))]) - (markdown-mode . [(20230212 1208) ((emacs (26 1))) "Major mode for Markdown-formatted text" single ((:commit . "c765b73b370f0fcaaa3cee28b2be69652e2d2c39") (:authors ("Jason R. Blevins" . "jblevins@xbeta.org")) (:maintainer "Jason R. Blevins" . "jblevins@xbeta.org") (:keywords "markdown" "github flavored markdown" "itex") (:url . "https://jblevins.org/projects/markdown-mode/"))]) + (markdown-mode . [(20230331 913) ((emacs (26 1))) "Major mode for Markdown-formatted text" single ((:commit . "ad3a816f7be97deb83fc0a7fa41305c79009bac5") (:authors ("Jason R. Blevins" . "jblevins@xbeta.org")) (:maintainer "Jason R. Blevins" . "jblevins@xbeta.org") (:keywords "markdown" "github flavored markdown" "itex") (:url . "https://jblevins.org/projects/markdown-mode/"))]) (markdown-preview-eww . [(20160111 1502) ((emacs (24 4))) "Realtime preview by eww" single ((:commit . "5853f836425c877c8a956501f0adda137ef1d3b7") (:authors ("niku" . "niku@niku.name")) (:maintainer "niku" . "niku@niku.name") (:url . "https://github.com/niku/markdown-preview-eww"))]) (markdown-preview-mode . [(20221006 1601) ((emacs (24 4)) (websocket (1 6)) (markdown-mode (2 0)) (cl-lib (0 5)) (web-server (0 1 1))) "markdown realtime preview minor mode." tar ((:commit . "85fbfec507a222326695a3b91ff7306d0c4f94c6") (:authors ("Igor Shymko" . "igor.shimko@gmail.com")) (:maintainer "Igor Shymko" . "igor.shimko@gmail.com") (:keywords "markdown" "gfm" "convenience") (:url . "https://github.com/ancane/markdown-preview-mode"))]) (markdown-soma . [(20220802 956) ((emacs (25)) (s (1 11 0)) (dash (2 19 1)) (f (0 20 0))) "Live preview for Markdown" single ((:commit . "e604b9e4a65bbd2057befbfaebfa73d00bd9826a") (:authors ("Jason Milkins" . "jasonm23@gmail.com")) (:maintainer "Jason Milkins" . "jasonm23@gmail.com") (:keywords "wp" "docs" "text" "markdown") (:url . "https://github.com/jasonm23/markdown-soma"))]) @@ -3066,7 +3082,7 @@ (marshal . [(20201223 1853) ((emacs (25 1)) (ht (2 0))) "eieio extension for automatic (un)marshalling" single ((:commit . "490496d974d03906f784707ecc2e0ac36ed84b96") (:authors ("Yann Hodique" . "yann.hodique@gmail.com")) (:maintainer "Yann Hodique" . "yann.hodique@gmail.com") (:keywords "extensions") (:url . "https://github.com/sigma/marshal.el"))]) (maruo-macro-mode . [(20160616 1349) ((emacs (24 3))) "Major mode for editing Hidemaru/Maruo macro script" single ((:commit . "8fc9a38ad051eafa8eb94038711acc52c5d1d8d5") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "programming" "editor" "macro"))]) (masm-mode . [(20200308 1450) ((emacs (25 1))) "MASM x86 and x64 assembly major mode" single ((:commit . "ab63524d195332ec9f703783704231606e69c292") (:authors ("YiGeeker" . "zyfchinese@yeah.net")) (:maintainer "YiGeeker" . "zyfchinese@yeah.net") (:keywords "languages") (:url . "https://github.com/YiGeeker/masm-mode"))]) - (mastodon . [(20230219 2053) ((emacs (27 1)) (request (0 3 0)) (persist (0 4)) (ts (0 3))) "Client for Mastodon, a federated social network" tar ((:commit . "4f9a7be4926dbf3f33a717fcbed12de78c22b331") (:authors ("Johnson Denen" . "johnson.denen@gmail.com") ("Marty Hiatt" . "martianhiatus@riseup.net")) (:maintainer "Marty Hiatt" . "martianhiatus@riseup.net") (:url . "https://codeberg.org/martianh/mastodon.el"))]) + (mastodon . [(20230407 848) ((emacs (27 1)) (request (0 3 0)) (persist (0 4)) (ts (0 3))) "Client for Mastodon and compatible fediverse services" tar ((:commit . "319560d2ba769ae43e8a5a19cd3cdfb2d3daf5f0") (:authors ("Johnson Denen" . "johnson.denen@gmail.com") ("Marty Hiatt" . "martianhiatus@riseup.net")) (:maintainer "Marty Hiatt" . "martianhiatus@riseup.net") (:url . "https://codeberg.org/martianh/mastodon.el"))]) (material-theme . [(20210904 1226) ((emacs (24 1))) "A Theme based on the colors of the Google Material Design" tar ((:commit . "6823009bc92f82aa3a90e27e1009f7da8e87b648") (:authors ("Christoph Paulik" . "cpaulik@gmail.com")) (:maintainer "Christoph Paulik" . "cpaulik@gmail.com") (:keywords "themes") (:url . "http://github.com/cpaulik/emacs-material-theme"))]) (math-preview . [(20220830 1740) ((emacs (26 1)) (json (1 4)) (dash (2 18 0)) (s (1 12 0))) "Preview TeX math equations inline" single ((:commit . "dd41b03c64eca324558e6139699cacccfdd0efd2") (:authors ("Matsievskiy S.V.")) (:maintainer "Matsievskiy S.V.") (:keywords "convenience") (:url . "https://gitlab.com/matsievskiysv/math-preview"))]) (math-symbol-lists . [(20220828 2047) nil "Lists of Unicode math symbols and latex commands" tar ((:commit . "ac3eb053d3b576fcdd192b0ac6ad5090ea3a7079") (:authors ("Vitalie Spinu" . "spinuvit@gmail.com")) (:maintainer "Vitalie Spinu" . "spinuvit@gmail.com") (:keywords "unicode" "symbols" "mathematics") (:url . "https://github.com/vspinu/math-symbol-lists"))]) @@ -3088,20 +3104,20 @@ (media-thumbnail . [(20220827 2325) ((emacs (28 1))) "Utility package to provide media icons" single ((:commit . "14e626fe7ee714ab45c9e636d00a26e89aa2832a") (:authors ("James Nguyen" . "james@jojojames.com")) (:maintainer "James Nguyen" . "james@jojojames.com") (:keywords "files" "tools") (:url . "https://github.com/jojojames/media-thumbnail"))]) (mediawiki . [(20220923 1336) nil "mediawiki frontend" single ((:commit . "c28cf78d4fe4969df3af8dcc2adaf71c4212e5ad") (:authors ("Mark A. Hershberger" . "mah@everybody.org")) (:maintainer "Mark A. Hershberger" . "mah@everybody.org") (:keywords "mediawiki" "wikipedia" "network" "wiki") (:url . "https://github.com/hexmode/mediawiki-el"))]) (meghanada . [(20220101 505) ((emacs (24 3)) (yasnippet (0 6 1)) (company (0 9 0)) (flycheck (0 23))) "A better java development mode" tar ((:commit . "59c46cabb7eee715fe810ce59424934a1286df84") (:authors ("Yutaka Matsubara" . "yutaka.matsubara@gmail.com")) (:maintainer "Yutaka Matsubara" . "yutaka.matsubara@gmail.com") (:keywords "languages" "java") (:url . "https://github.com/mopemope/meghanada-emacs"))]) - (melancholy-theme . [(20230204 212) ((emacs (27 1))) "A dark theme that's pretty sad -*- lexical-binding: t; -" single ((:commit . "c29f9c70787f75749a8f5af4b1a650eec5bbf689") (:authors ("@baaash" . "bleat@baaa.sh")) (:maintainer "@baaash" . "bleat@baaa.sh") (:keywords "faces" "frames") (:url . "https://gitlab.com/baaash/melancholy-theme"))]) + (melancholy-theme . [(20230330 835) ((emacs (27 1))) "A dark theme that's pretty sad -*- lexical-binding: t; -" single ((:commit . "a5c4360f57793401b63b0df382e845b4845c8f97") (:authors ("@baaash" . "bleat@baaa.sh")) (:maintainer "@baaash" . "bleat@baaa.sh") (:keywords "faces" "frames") (:url . "https://gitlab.com/baaash/melancholy-theme"))]) (mellow-theme . [(20170808 1317) ((emacs (24 0))) "an Emacs 24 theme based on Mellow (tmTheme)" single ((:commit . "2bdf18f05f5212b6f269d9a94afe2cf201766891") (:authors ("Jason Milkins")) (:maintainer "Jason Milkins") (:url . "https://github.com/emacsfodder/tmtheme-to-deftheme"))]) (melpa-upstream-visit . [(20130720 1033) ((s (1 6 0))) "A set of kludges to visit a melpa-hosted package's homepage" single ((:commit . "7310c74fdead3c0f86ad6eff76cf989e63f70f66") (:authors ("Alessandro Piras" . "laynor@gmail.com")) (:maintainer "Alessandro Piras" . "laynor@gmail.com") (:keywords "convenience"))]) (memento-mori . [(20190628 2147) ((emacs (24)) (cl-lib (0 5))) "Reminder of mortality" single ((:commit . "52f95bd4cf6617b60dc204c9bccb8d8fa17d4f9e") (:authors ("Lassi Kortela" . "lassi@lassi.io")) (:maintainer "Lassi Kortela" . "lassi@lassi.io") (:keywords "help") (:url . "https://github.com/lassik/emacs-memento-mori"))]) (memoize . [(20200103 2036) nil "Memoization functions" single ((:commit . "51b075935ca7070f62fae1d69fe0ff7d8fa56fdd") (:authors ("Christopher Wellons" . "mosquitopsu@gmail.com")) (:maintainer "Christopher Wellons" . "mosquitopsu@gmail.com") (:url . "https://github.com/skeeto/emacs-memoize"))]) (memolist . [(20150804 1721) ((markdown-mode (22 0)) (ag (0 45))) "memolist.el is Emacs port of memolist.vim." single ((:commit . "60c296e202a71e9dcf1c3936d47b5c4b95c5839f") (:authors ("mikanfactory ")) (:maintainer "mikanfactory") (:keywords "markdown" "memo") (:url . "http://github.com/mikanfactory/emacs-memolist"))]) (mentor . [(20230103 1146) ((emacs (25 1)) (xml-rpc (1 6 15)) (seq (1 11)) (async (1 9 3)) (url-scgi (0 8))) "Frontend for the rTorrent bittorrent client" tar ((:commit . "f51dd4f3f87c54b7cc92189924b9d873a53f5a75") (:authors ("Stefan Kangas" . "stefankangas@gmail.com")) (:maintainer "Stefan Kangas" . "stefankangas@gmail.com") (:keywords "comm" "processes" "bittorrent") (:url . "https://github.com/skangas/mentor"))]) - (meow . [(20230213 200) ((emacs (27 1))) "Yet Another modal editing" tar ((:commit . "1e69067c1647ea634c87c021c5acf4a81152f4b2") (:authors ("Shi Tianshu")) (:maintainer "Shi Tianshu") (:keywords "convenience" "modal-editing") (:url . "https://www.github.com/DogLooksGood/meow"))]) + (meow . [(20230327 524) ((emacs (27 1))) "Yet Another modal editing" tar ((:commit . "d80c2ff2f94333492dd7714c4210440162985b20") (:authors ("Shi Tianshu")) (:maintainer "Shi Tianshu") (:keywords "convenience" "modal-editing") (:url . "https://www.github.com/DogLooksGood/meow"))]) (merlin . [(20221222 1239) ((emacs (25 1))) "Mode for Merlin, an assistant for OCaml" tar ((:commit . "41cd949106fbf0769c97e3a56808e4d99fc42c6f") (:authors ("Frédéric Bour ")) (:maintainer "Frédéric Bour ") (:keywords "ocaml" "languages") (:url . "https://github.com/ocaml/merlin"))]) (merlin-ac . [(20221123 1408) ((emacs (25 1)) (merlin (3)) (auto-complete (1 5))) "Merlin and auto-complete integration" single ((:commit . "8bcab034a680f57ddf58092fda6288dc4caddd2a") (:authors ("Simon Castellan ") ("Frédéric Bour ") ("Thomas Refis ")) (:maintainer "Simon Castellan ") (:keywords "ocaml" "languages") (:url . "http://github.com/ocaml/merlin"))]) (merlin-company . [(20221123 1408) ((emacs (25 1)) (merlin (3)) (company (0 9))) "Merlin and company mode integration" single ((:commit . "8bcab034a680f57ddf58092fda6288dc4caddd2a") (:authors ("Simon Castellan ") ("Frédéric Bour ") ("Thomas Refis ")) (:maintainer "Simon Castellan ") (:keywords "ocaml" "languages") (:url . "http://github.com/ocaml/merlin"))]) (merlin-eldoc . [(20230213 555) ((emacs (24 4)) (merlin (3 0))) "eldoc for OCaml and Reason" single ((:commit . "bf8edc63d85b35e4def352fa7ce4ea39f43e1fd8") (:authors ("Louis Roché" . "louis@louisroche.net")) (:maintainer "Louis Roché" . "louis@louisroche.net") (:keywords "merlin" "ocaml" "languages" "eldoc") (:url . "https://github.com/khady/merlin-eldoc"))]) (merlin-iedit . [(20221123 1408) ((emacs (25 1)) (merlin (3)) (iedit (0 9))) "Merlin and iedit integration" single ((:commit . "8bcab034a680f57ddf58092fda6288dc4caddd2a") (:authors ("Simon Castellan ") ("Frédéric Bour ") ("Thomas Refis ")) (:maintainer "Simon Castellan ") (:keywords "ocaml" "languages") (:url . "http://github.com/ocaml/merlin"))]) - (mermaid-mode . [(20230131 1601) ((f (0 20 0)) (emacs (25 3))) "major mode for working with mermaid graphs" single ((:commit . "f0c9b5202d70bce783494a971d3c67d4700cff53") (:authors ("Adrien Brochard")) (:maintainer "Adrien Brochard") (:keywords "mermaid" "graphs" "tools" "processes") (:url . "https://github.com/abrochard/mermaid-mode"))]) + (mermaid-mode . [(20230310 1618) ((f (0 20 0)) (emacs (25 3))) "major mode for working with mermaid graphs" single ((:commit . "e4e4bb8cca72e7eff322229719f028908b52ce3f") (:authors ("Adrien Brochard")) (:maintainer "Adrien Brochard") (:keywords "mermaid" "graphs" "tools" "processes") (:url . "https://github.com/abrochard/mermaid-mode"))]) (meson-mode . [(20210820 905) ((emacs (26 1))) "Major mode for the Meson build system files" tar ((:commit . "1a2e2abb098c9288c2cdb3affbad76edd98abf59") (:authors ("Michal Sojka" . "sojkam1@fel.cvut.cz")) (:maintainer "Michal Sojka" . "sojkam1@fel.cvut.cz") (:keywords "languages" "tools") (:url . "https://github.com/wentasah/meson-mode"))]) (message-attachment-reminder . [(20230124 520) ((emacs (24 1))) "Remind if missing attachment" single ((:commit . "975381d6e7c6771c462e73abd3398a4ed2a9b86b") (:authors ("Alex Murray" . "murray.alex@gmail.com")) (:maintainer "Alex Murray" . "murray.alex@gmail.com") (:url . "https://github.com/alexmurray/message-attachment-reminder"))]) (message-view-patch . [(20210904 2227) ((emacs (24 4)) (magit (3 0 0))) "Colorize patch-like emails in mu4e" single ((:commit . "50dd3d92a1794f24b7e375b74e5199c63b54a2d8") (:authors ("Sean Farley")) (:maintainer "Sean Farley") (:keywords "extensions" "mu4e" "gnus") (:url . "https://github.com/seanfarley/message-view-patch"))]) @@ -3118,12 +3134,11 @@ (mew . [(20230209 1231) nil "Messaging in the Emacs World" tar ((:commit . "2f9143f5865cdbd31701be58093961b41def0edc") (:authors ("Kazu Yamamoto" . "Kazu@Mew.org")) (:maintainer "Kazu Yamamoto" . "Kazu@Mew.org"))]) (mexican-holidays . [(20210604 1421) nil "Mexico holidays for Emacs calendar." single ((:commit . "8e28907ea69f2c0ed9aad9f3b99664ca147379d0") (:authors ("Saúl Gutiérrez" . "me@sggc.me")) (:maintainer "Saúl Gutiérrez" . "me@sggc.me") (:keywords "calendar") (:url . "https://github.com/sggutier/mexican-holidays"))]) (meyvn . [(20221206 2219) ((emacs (25 1)) (cider (0 23)) (projectile (2 1)) (s (1 12)) (dash (2 17)) (parseedn (1 1 0)) (parseclj (1 1 0)) (geiser (0 12))) "Meyvn client" single ((:commit . "493e652b8fffcbed226f69a2ea82e6f9fc51ab08") (:authors ("Daniel Szmulewicz" . "daniel.szmulewicz@gmail.com")) (:maintainer "Daniel Szmulewicz" . "daniel.szmulewicz@gmail.com") (:url . "https://github.com/danielsz/meyvn-el"))]) - (mgmtconfig-mode . [(20220806 306) ((emacs (24 3))) "mgmt configuration management language" single ((:commit . "3cea4223657cdbb32fcb0afc54bb736388dfbd5e") (:authors ("Peter Oliver" . "mgmtconfig@mavit.org.uk")) (:maintainer "Mgmt contributors ") (:keywords "languages") (:url . "https://github.com/purpleidea/mgmt/misc/emacs"))]) + (mgmtconfig-mode . [(20230305 2331) ((emacs (24 3))) "mgmt configuration management language" single ((:commit . "a7624a2bf97c4dd99745935f68883df907c2e9b3") (:authors ("Peter Oliver" . "mgmtconfig@mavit.org.uk")) (:maintainer "Mgmt contributors ") (:keywords "languages") (:url . "https://github.com/purpleidea/mgmt/misc/emacs"))]) (mhc . [(20201227 406) ((calfw (20150703))) "Message Harmonized Calendaring system." tar ((:commit . "1cd9cbc7f8cfe40833d1af726644ae45a3d07dc0") (:authors ("Yoshinari Nomura" . "nom@quickhack.net")) (:maintainer "Yoshinari Nomura" . "nom@quickhack.net") (:keywords "calendar") (:url . "http://www.quickhack.net/mhc"))]) (mic . [(20230123 944) ((emacs (26 1))) "Minimal and combinable configuration manager" tar ((:commit . "7d0a31ace0b801cb8b58a7bb61a981b67508208d") (:authors ("ROCKTAKEY" . "rocktakey@gmail.com")) (:maintainer "ROCKTAKEY" . "rocktakey@gmail.com") (:keywords "convenience") (:url . "https://github.com/ROCKTAKEY/mic"))]) (mic-paren . [(20170731 1907) nil "advanced highlighting of matching parentheses" single ((:commit . "d0410c7d805c9aaf51a1bcefaaef092bed5824c4") (:authors ("Mikael Sjödin" . "mic@docs.uu.se") ("Klaus Berndl " . "berndl@sdm.de") ("Jonathan Kotta" . "jpkotta@gmail.com")) (:maintainer "ttn") (:keywords "languages" "faces" "parenthesis" "matching"))]) (micgoline . [(20160415 326) ((emacs (24 3)) (powerline (2 3))) "powerline mode, color schemes from microsoft and google's logo." single ((:commit . "e3e2effe4846175a3b52b4092c0c134ced5978d8") (:authors ("yzprofile" . "yzprofiles@gmail.com")) (:maintainer "yzprofile" . "yzprofiles@gmail.com") (:keywords "mode-line" "powerline" "theme") (:url . "https://github.com/yzprofile/micgoline"))]) - (midje-mode . [(20170809 403) ((cider (0 1 4)) (clojure-mode (1 0))) "Minor mode for running Midje tests in emacs" tar ((:commit . "10ad5b6084cd03d5cd268b486a7c3c246d85535f"))]) (migemo . [(20200913 12) ((cl-lib (0 5))) "Japanese incremental search through dynamic pattern expansion" single ((:commit . "f756cba3d5268968da361463c2e29b3a659a3de7") (:authors ("Satoru Takabayashi" . "satoru-t@is.aist-nara.ac.jp")) (:maintainer "Satoru Takabayashi" . "satoru-t@is.aist-nara.ac.jp") (:url . "https://github.com/emacs-jp/migemo"))]) (milkode . [(20140927 529) nil "Command line search and direct jump with Milkode" single ((:commit . "ba97e2aeefa1d9d0b3835bf08edd0de248b0c513") (:authors ("ongaeshi")) (:maintainer "ongaeshi") (:keywords "milkode" "search" "grep" "jump" "keyword"))]) (mimetypes . [(20201115 1605) ((emacs (25 1))) "Guess a file's mimetype by extension" single ((:commit . "1663054ce266ed25e47ec707c19f619d33225903") (:authors ("Craig Niles ")) (:maintainer "Craig Niles ") (:url . "https://github.com/cniles/emacs-mimetypes"))]) @@ -3132,7 +3147,7 @@ (mingus . [(20230206 618) ((libmpdee (2 2))) "MPD Interface" tar ((:commit . "f4d1df06f537ae88830a040eea5e23768a0ebd5b") (:authors ("Niels Giesen ")) (:maintainer "Niels Giesen ") (:keywords "multimedia" "elisp" "music" "mpd") (:url . "https://github.com/pft/mingus"))]) (mini-frame . [(20220627 2041) ((emacs (26 1))) "Show minibuffer in child frame on read-from-minibuffer" single ((:commit . "60838f3cab438dcbda8eaa15ab3e5d1af88910e9") (:authors ("Andrii Kolomoiets" . "andreyk.mad@gmail.com")) (:maintainer "Andrii Kolomoiets" . "andreyk.mad@gmail.com") (:keywords "frames") (:url . "https://github.com/muffinmad/emacs-mini-frame"))]) (mini-header-line . [(20170621 1221) ((emacs (24 4))) "a minimal header-line" single ((:commit . "73b6724e0a26c4528d93768191c8aa59e6bce2e5") (:authors ("Johannes Goslar")) (:maintainer "Johannes Goslar") (:keywords "header-line" "mode-line") (:url . "https://github.com/ksjogo/mini-header-line"))]) - (mini-modeline . [(20220910 1508) ((emacs (25 1)) (dash (2 12 0))) "Display modeline in minibuffer" single ((:commit . "55ad82056dd26bbf60585574927ef28441d318d8") (:authors ("Kien Nguyen" . "kien.n.quang@gmail.com")) (:maintainer "Kien Nguyen" . "kien.n.quang@gmail.com") (:keywords "convenience" "tools") (:url . "https://github.com/kiennq/emacs-mini-modeline"))]) + (mini-modeline . [(20230306 1521) ((emacs (25 1)) (dash (2 12 0))) "Display modeline in minibuffer" single ((:commit . "86e753b6c38a06b0fc80d7560aa6a25245fd4d38") (:authors ("Kien Nguyen" . "kien.n.quang@gmail.com")) (:maintainer "Kien Nguyen" . "kien.n.quang@gmail.com") (:keywords "convenience" "tools") (:url . "https://github.com/kiennq/emacs-mini-modeline"))]) (minibuf-isearch . [(20151226 1943) nil "incremental search on minibuffer history" single ((:commit . "2846c6ac369ee623dad4cd3c8a7a6d9078965516") (:authors ("Keiichiro Nagano" . "knagano@sodan.org") ("Hideyuki SHIRAI " . "shirai@meadowy.org")) (:maintainer "Keiichiro Nagano" . "knagano@sodan.org") (:keywords "minibuffer" "history" "incremental search"))]) (minibuffer-complete-cycle . [(20130813 1645) nil "Cycle through the *Completions* buffer" single ((:commit . "3df80135887d0169e02294a948711f6dfeca4a6f") (:authors ("Akinori MUSHA" . "knu@iDaemons.org") ("Kevin Rodgers" . "ihs_4664@yahoo.com")) (:maintainer "Akinori MUSHA" . "knu@iDaemons.org") (:keywords "completion") (:url . "https://github.com/knu/minibuffer-complete-cycle"))]) (minibuffer-cua . [(20130906 1134) nil "Make CUA mode's S-up/S-down work in minibuffer" single ((:commit . "adc4979a64f8b36e05960e9afa0746dfa9e2e4c7") (:authors ("Akinori MUSHA" . "knu@iDaemons.org")) (:maintainer "Akinori MUSHA" . "knu@iDaemons.org") (:keywords "completion" "editing") (:url . "https://github.com/knu/minibuffer-cua.el"))]) @@ -3140,7 +3155,7 @@ (miniedit . [(20100419 1745) nil "Enhanced editing for minibuffer fields." single ((:commit . "e12bf659c3eb92dd8a4cb77642dc0865c54667a3"))]) (minimal-session-saver . [(20140508 2041) nil "Very lean session saver" single ((:commit . "ac42b6835f777a8a7e04599d8f20ec650997ba96") (:authors ("Roland Walker" . "walker@pobox.com")) (:maintainer "Roland Walker" . "walker@pobox.com") (:keywords "tools" "frames" "project") (:url . "http://github.com/rolandwalker/minimal-session-saver"))]) (minimal-theme . [(20190113 2132) nil "A light/dark minimalistic Emacs 24 theme." tar ((:commit . "063b4d8ca33d55d04c341f0b2b777ec241a3e201") (:authors ("Anler Hp ")) (:maintainer "Anler Hp ") (:keywords "color" "theme" "minimal") (:url . "http://github.com/ikame/minimal-theme"))]) - (minions . [(20230212 2213) ((emacs (25 2)) (compat (29 1 3 4))) "A minor-mode menu for the mode line" single ((:commit . "c5e8b65620558409a79766e86e3e8263cef765df") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "convenience") (:url . "https://github.com/tarsius/minions"))]) + (minions . [(20230314 1414) ((emacs (25 2)) (compat (29 1 3 4))) "A minor-mode menu for the mode line" single ((:commit . "e3f3a80a51b0e47f395b6fb202294d6dc8b9e0c7") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "convenience") (:url . "https://github.com/tarsius/minions"))]) (minitest . [(20200506 308) ((dash (1 0 0))) "An Emacs mode for ruby minitest files" tar ((:commit . "ddd152c990a528ad09a696bfad23afa4330ea4d7") (:authors ("Arthur Neves")) (:maintainer "Arthur Neves") (:url . "https://github.com/arthurnn/minitest-emacs"))]) (minizinc-mode . [(20180201 1450) ((emacs (24 1))) "Major mode for MiniZinc code" single ((:commit . "2512521ba7f8e263a06db88df663fc6b3cca7e16") (:keywords "languages" "minizinc") (:url . "http://github.com/m00nlight/minizinc-mode"))]) (minor-mode-hack . [(20170926 34) nil "Change priority of minor-mode keymaps" single ((:commit . "c3aa957602c924c01fe07d48d191b8616fb3696a") (:authors ("rubikitch" . "rubikitch@ruby-lang.org")) (:maintainer "rubikitch" . "rubikitch@ruby-lang.org") (:keywords "lisp") (:url . "http://www.emacswiki.org/cgi-bin/wiki/download/minor-mode-hack.el"))]) @@ -3172,7 +3187,7 @@ (modern-sh . [(20211101 1001) ((emacs (25 1)) (hydra (0 15 0)) (eval-in-repl (0 9 7))) "Minor mode for editing shell script" single ((:commit . "8ebebe77304aa8170f7af809e7564c79d3bd45da") (:keywords "languages" "programming") (:url . "https://github.com/damon-kwok/modern-sh"))]) (modtime-skip-mode . [(20140128 2201) nil "Minor mode for disabling modtime and supersession checks on files." single ((:commit . "c0e49523aa26b2263a8693691ac775988015f592") (:authors ("Jordon Biondo" . "biondoj@mail.gvsu.edu")) (:maintainer "Jordon Biondo" . "biondoj@mail.gvsu.edu") (:url . "http://www.github.com/jordonbiondo/modtime-skip-mode"))]) (modular-config . [(20210726 1614) ((emacs (25 1))) "Organize your config into small and loadable modules" single ((:commit . "043907d96efff70dfaea1e721de90bd35970e8bd") (:authors ("Sidharth Arya" . "sidhartharya10@gmail.com")) (:maintainer "Sidharth Arya" . "sidhartharya10@gmail.com") (:keywords "startup" "lisp" "tools") (:url . "https://github.com/SidharthArya/modular-config.el"))]) - (modus-themes . [(20230220 1859) ((emacs (27 1))) "Elegant, highly legible and customizable themes" tar ((:commit . "f4282839d880a88062acaafbd8acea2708d3932b") (:authors ("Protesilaos Stavrou" . "info@protesilaos.com")) (:maintainer "Modus-Themes Development" . "~protesilaos/modus-themes@lists.sr.ht") (:keywords "faces" "theme" "accessibility") (:url . "https://git.sr.ht/~protesilaos/modus-themes"))]) + (modus-themes . [(20230405 456) ((emacs (27 1))) "Elegant, highly legible and customizable themes" tar ((:commit . "ede2ab0e0ff43b25fdac24a9946a95be705eff95") (:authors ("Protesilaos Stavrou" . "info@protesilaos.com")) (:maintainer "Modus-Themes Development" . "~protesilaos/modus-themes@lists.sr.ht") (:keywords "faces" "theme" "accessibility") (:url . "https://git.sr.ht/~protesilaos/modus-themes"))]) (moe-theme . [(20230110 422) nil "A colorful eye-candy theme. Moe, moe, kyun!" tar ((:commit . "171d76b0c69e42a9d7b62c5c472944951cb2be6c") (:authors ("kuanyui" . "azazabc123@gmail.com")) (:maintainer "kuanyui" . "azazabc123@gmail.com") (:keywords "themes") (:url . "https://github.com/kuanyui/moe-theme.el"))]) (molar-mass . [(20220922 1752) ((emacs (24 3))) "Calculates molar mass of a molecule" single ((:commit . "c3b686c4b621b45fa4b17857b4934eb4487d74f5") (:authors ("Sergi Ruiz Trepat")) (:maintainer "Sergi Ruiz Trepat") (:keywords "convenience" "chemistry") (:url . "https://github.com/sergiruiztrepat/molar-mass.el"))]) (molecule . [(20180527 743) ((emacs (25 1))) "Simple wrapper for molecule" single ((:commit . "2ef72b81d9aa24ea782b71a061a3abdad6cae162") (:authors (": drymer ")) (:maintainer ": drymer ") (:keywords ":" "languages" "terminals") (:url . "https://git.daemons.it/drymer/molecule.el"))]) @@ -3180,7 +3195,8 @@ (mongo . [(20150315 1219) nil "MongoDB driver for Emacs Lisp" tar ((:commit . "595529ddd70ecb9fab8b11daad2c3929941099d6") (:authors ("Tomohiro Matsuyama" . "m2ym.pub@gmail.com")) (:maintainer "Tomohiro Matsuyama" . "m2ym.pub@gmail.com") (:keywords "convenience"))]) (monitor . [(20161018 1144) ((dash (2 13 0))) "Utilities for monitoring expressions." tar ((:commit . "63f4643a0ee81616dbb692b8b03bae21df2283e2") (:authors ("Ben Moon" . "software@guiltydolphin.com")) (:maintainer "Ben Moon" . "software@guiltydolphin.com") (:keywords "lisp" "monitor" "utility") (:url . "https://github.com/guiltydolphin/monitor"))]) (monkeytype . [(20210110 513) ((emacs (25 1)) (scrollable-quick-peek (0 1 0))) "Mode for speed typing" single ((:commit . "0e949d08198c0bd003f1d5c8cdceb7e36bef22f7") (:authors ("Pablo Barrantes" . "xjpablobrx@gmail.com")) (:maintainer "Pablo Barrantes" . "xjpablobrx@gmail.com") (:keywords "games") (:url . "https://github.com/jpablobr/emacs-monkeytype"))]) - (monky . [(20210417 12) nil "Control Hg from Emacs." tar ((:commit . "72c7cd21b7b995c476e938fd0b92a494aa25c3a7") (:authors ("Anantha kumaran" . "ananthakumaran@gmail.com")) (:maintainer "Anantha kumaran" . "ananthakumaran@gmail.com") (:keywords "tools") (:url . "http://github.com/ananthakumaran/monky"))]) + (monky . [(20230222 2153) nil "Control Hg from Emacs." tar ((:commit . "7046eee5fc9ac625924382cb4a82b0d8efcd9ff0") (:authors ("Anantha kumaran" . "ananthakumaran@gmail.com")) (:maintainer "Anantha kumaran" . "ananthakumaran@gmail.com") (:keywords "tools") (:url . "http://github.com/ananthakumaran/monky"))]) + (mono-complete . [(20230405 529) ((emacs (28 1))) "Completion suggestions with multiple back-ends" tar ((:commit . "29436788b9ebe8a147b1deece6e86151528880f5") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:url . "https://codeberg.org/ideasman42/emacs-mono-complete"))]) (monochrome-theme . [(20140326 1050) nil "A dark Emacs 24 theme for your focused hacking sessions" tar ((:commit . "9cf993670c9e8d198f41d840216e13280585b3e1") (:authors ("Xavier Noria" . "fxn@hashref.com")) (:maintainer "Xavier Noria" . "fxn@hashref.com"))]) (monokai-alt-theme . [(20170630 2048) ((emacs (24))) "Theme with a dark background. Based on sublime monokai theme." single ((:commit . "f342b6afc31f929be0626eca2d696ee9fab78011") (:authors ("Dmytro Koval")) (:maintainer "Dmytro Koval") (:url . "https://github.com/dawidof/emacs-monokai-theme"))]) (monokai-pro-theme . [(20210206 1820) nil "A simple theme based on the Monokai Pro Sublime color schemes" tar ((:commit . "d0489741a80d818713c290a1a4bdd985877228bb") (:authors ("Kaleb Elwert" . "belak@coded.io")) (:maintainer "Kaleb Elwert" . "belak@coded.io") (:url . "https://github.com/belak/emacs-monokai-pro-theme"))]) @@ -3190,12 +3206,13 @@ (mood-line . [(20230126 917) ((emacs (25 1))) "A minimal mode line inspired by doom-modeline" tar ((:commit . "58e85c815092ac93d02dab584fe537fd1be3828a") (:authors ("Jessie Hildebrandt ")) (:maintainer "Jessie Hildebrandt ") (:keywords "mode-line" "faces") (:url . "https://gitlab.com/jessieh/mood-line"))]) (mood-one-theme . [(20221222 1214) ((emacs (27 1))) "A dark color scheme inspired by the Doom One theme" single ((:commit . "dfbc81900737d3382a340feeed24d2bcd9bdedb0") (:authors ("Jessie Hildebrandt ")) (:maintainer "Jessie Hildebrandt ") (:keywords "mode-line" "faces") (:url . "https://gitlab.com/jessieh/mood-one-theme"))]) (moody . [(20230212 2015) ((emacs (25 3)) (compat (29 1 3 4))) "Tabs and ribbons for the mode line" single ((:commit . "4c7171cbe39adcf2ab1ae5290bdb0ecfd7d669d1") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "faces") (:url . "https://github.com/tarsius/moody"))]) - (moom . [(20220911 2344) ((emacs (25 1))) "Commands to control frame position and size" tar ((:commit . "9029cd76ba037ca31cc7b91453ff5f8510747cb6") (:authors ("Takaaki ISHIKAWA ")) (:maintainer "Takaaki ISHIKAWA ") (:keywords "frames" "faces" "convenience") (:url . "https://github.com/takaxp/Moom"))]) + (moom . [(20230401 1025) ((emacs (25 1))) "Commands to control frame position and size" tar ((:commit . "c7f319c29e5740b03910e75e89bfb2379d4ed680") (:authors ("Takaaki ISHIKAWA ")) (:maintainer "Takaaki ISHIKAWA ") (:keywords "frames" "faces" "convenience") (:url . "https://github.com/takaxp/Moom"))]) (moonscript . [(20170831 2226) ((cl-lib (0 5)) (emacs (24))) "Major mode for editing MoonScript code" tar ((:commit . "56f90471e2ced2b0a177aed4d8c2f854797e9cc7") (:authors ("@GriffinSchneider, @k2052, @EmacsFodder")) (:maintainer "@GriffinSchneider, @k2052, @EmacsFodder"))]) (moonshot . [(20210627 2244) ((emacs (25 1)) (cl-lib (0 5)) (f (0 18)) (s (1 11 0)) (projectile (2 0 0)) (counsel (0 11 0)) (realgud (1 5 1)) (seq (2 20)) (levenshtein (1 0))) "Run executable file, debug and build commands on project" single ((:commit . "ec37a12825888047a90d9ee8131aa4bea348edf7") (:authors ("Jong-Hyouk Yun" . "ageldama@gmail.com")) (:maintainer "Jong-Hyouk Yun" . "ageldama@gmail.com") (:keywords "convenience" "files" "processes" "tools" "unix") (:url . "https://github.com/ageldama/moonshot"))]) (morganey-mode . [(20170118 934) ((emacs (24 4))) "Major mode for editing Morganey files" single ((:commit . "7e33f1be486f58dfcf02adcbf82ccac47f69bd9b") (:authors ("Alexey Kutepov" . "reximkut@gmail.com")) (:maintainer "Alexey Kutepov" . "reximkut@gmail.com") (:url . "https://github.com/morganey-lang/morganey-mode"))]) (morgentau-theme . [(20220319 1049) ((emacs (24))) "Tango-based custom theme" single ((:commit . "a8da5640b4a9b72a3136901d0a1a03071d9fcb00") (:authors ("Benjamin Vincent Schulenburg")) (:maintainer "Benjamin Vincent Schulenburg") (:keywords "theme" "dark" "faces") (:url . "https://github.com/Melchizedek6809/morgentau-theme"))]) (morlock . [(20230212 2015) ((emacs (25 1)) (compat (29 1 3 4))) "More font-lock keywords for elisp" single ((:commit . "674354d41bd2bccf0590467851796db6d4595873") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "convenience") (:url . "https://github.com/tarsius/morlock"))]) + (morrowind-theme . [(20230311 1919) ((emacs (24 1))) "Theme" single ((:commit . "5253d03e4aba8fe4f9d30c1483c2189616ce8990") (:authors ("Samuel Banya")) (:maintainer "Samuel Banya") (:url . "https://github.com/samuelbanya/morrowind-theme"))]) (mos-mode . [(20221209 1353) ((emacs (24 4)) (lsp-mode (8 0 0)) (dap-mode (0 7)) (dash (2 19 1)) (ht (2 3))) "MOS toolkit usage" single ((:commit . "770f49417e8ad7dbf382c8691f6f689d793b9314") (:url . "https://github.com/themkat/mos-mode"))]) (mosey . [(20180614 1649) ((emacs (24 4))) "Mosey around your buffers" single ((:commit . "2e3ac9d334fa2937ed5267193dfd25d8e1f14dc2") (:authors ("Adam Porter" . "adam@alphapapa.net")) (:maintainer "Adam Porter" . "adam@alphapapa.net") (:keywords "convenience") (:url . "http://github.com/alphapapa/mosey.el"))]) (most-used-words . [(20200808 1353) ((emacs (24 3))) "Display most used words in buffer" single ((:commit . "90c09da92b30c6497e9141f0edfe7842440c4d53") (:authors ("Udyant Wig" . "udyant.wig@gmail.com")) (:maintainer "Udyant Wig" . "udyant.wig@gmail.com") (:keywords "convenience" "wp") (:url . "https://github.com/udyantw/most-used-words"))]) @@ -3245,7 +3262,7 @@ (multi-web-mode . [(20130824 354) nil "multiple major mode support for web editing" tar ((:commit . "ad1c8d1c870334052d244c7ae3636cb7b9357b7c") (:authors ("Fabián E. Gallina" . "fabian@anue.biz")) (:maintainer "Fabián E. Gallina" . "fabian@anue.biz") (:keywords "convenience" "languages" "wp") (:url . "https://github.com/fgallina/multi-web-mode"))]) (multicolumn . [(20150202 2251) nil "Creating and managing multiple side-by-side windows." single ((:commit . "c7a3afecd470859b2e60aa7c554d6e4d436df7fa") (:authors ("Anders Lindgren")) (:maintainer "Anders Lindgren") (:url . "https://github.com/Lindydancer/multicolumn"))]) (multifiles . [(20130615 2133) nil "View and edit parts of multiple files in one buffer" single ((:commit . "dddfe64b8e1c1cd1f9ccc1f03405477fc0d53897") (:authors ("Magnar Sveen" . "magnars@gmail.com")) (:maintainer "Magnar Sveen" . "magnars@gmail.com") (:keywords "multiple" "files"))]) - (multiple-cursors . [(20230113 835) ((cl-lib (0 5))) "Multiple cursors for Emacs." tar ((:commit . "16223efc2d6dece2d43bbccc189d7a4bab6de571") (:authors ("Magnar Sveen" . "magnars@gmail.com")) (:maintainer "Magnar Sveen" . "magnars@gmail.com") (:keywords "editing" "cursors") (:url . "https://github.com/magnars/multiple-cursors.el"))]) + (multiple-cursors . [(20230309 1204) ((cl-lib (0 5))) "Multiple cursors for Emacs." tar ((:commit . "6956e8e12ee191d7c80d042ae8ff495286fcbe38") (:authors ("Magnar Sveen" . "magnars@gmail.com")) (:maintainer "Magnar Sveen" . "magnars@gmail.com") (:keywords "editing" "cursors") (:url . "https://github.com/magnars/multiple-cursors.el"))]) (multistate . [(20210124 2014) ((emacs (25 1)) (ht (2 3))) "Multistate mode" single ((:commit . "a7ab9dc7aac0b6d6d2f872de4e0d1b8550834a9b") (:authors ("Matsievskiy S.V.")) (:maintainer "Matsievskiy S.V.") (:keywords "convenience") (:url . "https://gitlab.com/matsievskiysv/multistate"))]) (multitran . [(20220903 510) ((emacs (24)) (cl-lib (0 5))) "Interface to multitran" single ((:commit . "6244e227bcf57eed391eecb34bae445f9c17e809") (:authors ("Zajcev Evgeny" . "zevlg@yandex.ru")) (:maintainer "Zajcev Evgeny" . "zevlg@yandex.ru") (:keywords "dictionary" "hypermedia"))]) (mustache . [(20210224 710) ((ht (0 9)) (s (1 3 0)) (dash (1 2 0))) "Mustache templating library in emacs lisp" single ((:commit . "6fcb31f5075edc5fc70c63426b2aef91352ca80f") (:authors ("Wilfred Hughes" . "me@wilfred.me.uk")) (:maintainer "Wilfred Hughes" . "me@wilfred.me.uk") (:keywords "convenience" "mustache" "template") (:url . "https://github.com/Wilfred/mustache.el"))]) @@ -3268,7 +3285,7 @@ (mysql-to-org . [(20210622 447) ((emacs (24 3)) (s (1 11 0))) "Minor mode to output the results of mysql queries to org tables" single ((:commit . "c5eefc71200f2e1d0d67a13ed897b3cdfa835117") (:authors ("Tijs Mallaerts" . "tijs.mallaerts@gmail.com")) (:maintainer "Tijs Mallaerts" . "tijs.mallaerts@gmail.com"))]) (myterminal-controls . [(20210904 516) ((emacs (24)) (cl-lib (0 5))) "Quick toggle controls at a key-stroke" single ((:commit . "c635868e13ee898ec77925d98b36421640e22aa4") (:authors ("Mohammed Ismail Ansari" . "team.terminal@gmail.com")) (:maintainer "Mohammed Ismail Ansari" . "team.terminal@gmail.com") (:keywords "convenience" "shortcuts") (:url . "http://ismail.teamfluxion.com"))]) (n4js . [(20150714 231) ((emacs (24)) (cypher-mode (0))) "Neo4j Shell" single ((:commit . "3991ed8975151d5e8d568e952362df810f7ffab7") (:authors ("TruongTx" . "me@truongtx.me")) (:maintainer "TruongTx" . "me@truongtx.me") (:keywords "neo4j" "shell" "comint") (:url . "https://github.com/tmtxt/n4js.el"))]) - (naga-theme . [(20230215 623) ((emacs (24 1))) "Dark color theme with green foreground color" single ((:commit . "508bf3505e9bf60163b68056b89c084df97b48aa") (:authors ("Johannes Maier" . "johannes.maier@mailbox.org")) (:maintainer "Johannes Maier" . "johannes.maier@mailbox.org") (:keywords "faces" "themes") (:url . "https://github.com/kenranunderscore/emacs-naga-theme"))]) + (naga-theme . [(20230304 551) ((emacs (24 1))) "Dark color theme with green foreground color" single ((:commit . "3b5a6eb800a78df66a8e1c08c2465110ec36c10c") (:authors ("Johannes Maier" . "johannes.maier@mailbox.org")) (:maintainer "Johannes Maier" . "johannes.maier@mailbox.org") (:keywords "faces" "themes") (:url . "https://github.com/kenranunderscore/emacs-naga-theme"))]) (name-this-color . [(20151014 2030) ((emacs (24)) (cl-lib (0 5)) (dash (2 11 0))) "Match RGB codes to names easily and precisely" single ((:commit . "e37cd1291d5d68d4c8d6386eab9cb9d94fd3bcfa") (:keywords "lisp" "color" "hex" "rgb" "shade" "name") (:url . "https://github.com/knl/name-this-color.el"))]) (named-timer . [(20181120 2224) ((emacs (24 4))) "Simplified timer management for Emacs Lisp" single ((:commit . "670b81e3eddef2e7353a4eedc9553a85306445db") (:authors ("Ryan C. Thompson")) (:maintainer "Ryan C. Thompson") (:keywords "tools") (:url . "https://github.com/DarwinAwardWinner/emacs-named-timer"))]) (nameframe . [(20221023 957) nil "Manage frames by name." single ((:commit . "06d3400750c6b33ae215b9ac2922ee4dafd6b506") (:authors ("John Del Rosario" . "john2x@gmail.com")) (:maintainer "John Del Rosario" . "john2x@gmail.com") (:url . "https://github.com/john2x/nameframe"))]) @@ -3298,7 +3315,7 @@ (ncl-mode . [(20180129 703) ((emacs (24))) "Major Mode for editing NCL scripts and other goodies" tar ((:commit . "602292712a9e6b7e7c25155978999e77d06b7338") (:authors ("Yagnesh Raghava Yakkala" . "hi@yagnesh.org")) (:maintainer "Yagnesh Raghava Yakkala" . "hi@yagnesh.org") (:keywords "ncl" "major mode" "ncl-mode" "atmospheric science.") (:url . "https://github.com/yyr/ncl-mode"))]) (nclip . [(20130617 2015) nil "Network (HTTP) Clipboard" tar ((:commit . "af88e38b1f04be02bf2e57affc662dbd0f828e67") (:authors ("Marian Schubert" . "marian.schubert@gmail.com")) (:maintainer "Marian Schubert" . "marian.schubert@gmail.com") (:keywords "nclip" "clipboard" "network") (:url . "http://www.github.com/maio/nclip.el"))]) (neato-graph-bar . [(20181130 1649) ((emacs (24 3))) "Neat-o graph bars CPU/memory etc." single ((:commit . "a7ae35afd67911e8924f36e646bce0d3e3c1bbe6") (:authors ("Robert Cochran" . "robert-git@cochranmail.com")) (:maintainer "Robert Cochran" . "robert-git@cochranmail.com") (:url . "https://gitlab.com/RobertCochran/neato-graph-bar"))]) - (neil . [(20230217 957) ((emacs (27 1))) "companion for Babashka Neil" single ((:commit . "abea182499897eda40088d24b647e66099ef94ed") (:authors ("Ag Ibragimov" . "agzam.ibragimov@gmail.com")) (:maintainer "Ag Ibragimov" . "agzam.ibragimov@gmail.com") (:keywords "convenience" "tools") (:url . "https://github.com/babashka/neil"))]) + (neil . [(20230322 2035) ((emacs (27 1))) "companion for Babashka Neil" single ((:commit . "19bc12d1c868eb5c1f200963c240a2a107982556") (:authors ("Ag Ibragimov" . "agzam.ibragimov@gmail.com")) (:maintainer "Ag Ibragimov" . "agzam.ibragimov@gmail.com") (:keywords "convenience" "tools") (:url . "https://github.com/babashka/neil"))]) (nemerle . [(20161029 2023) nil "major mode for editing nemerle programs" single ((:commit . "8818c5af5598e16ea59189e1e3245f0a3d7c78f0") (:authors ("Jacek Sliwerski (rzyjontko)" . "rzyj@o2.pl")) (:maintainer "Jacek Sliwerski (rzyjontko)" . "rzyj@o2.pl") (:keywords "nemerle" "mode" "languages"))]) (neon-mode . [(20180406 1156) nil "Simple major mode for editing neon files" single ((:commit . "99d15e46beaf1e7d71e39a00cce810df1f33229d") (:authors ("Matúš Goljer" . "matus.goljer@gmail.com")) (:maintainer "Matúš Goljer" . "matus.goljer@gmail.com") (:keywords "conf"))]) (neotree . [(20200324 1946) ((cl-lib (0 5))) "A tree plugin like NerdTree for Vim" tar ((:commit . "98fe21334affaffe2334bf7c987edaf1980d2d0b") (:authors ("jaypei" . "jaypei97159@gmail.com")) (:maintainer "jaypei" . "jaypei97159@gmail.com") (:url . "https://github.com/jaypei/emacs-neotree"))]) @@ -3316,17 +3333,18 @@ (ng2-mode . [(20201203 1925) ((typescript-mode (0 1))) "Major modes for editing Angular 2" tar ((:commit . "d341f177c6e4fb9d99b8639943ab5fc9184e2715") (:authors ("Adam Niederer" . "adam.niederer@gmail.com")) (:maintainer "Adam Niederer" . "adam.niederer@gmail.com") (:keywords "typescript" "angular" "angular2" "template") (:url . "http://github.com/AdamNiederer/ng2-mode"))]) (nginx-mode . [(20170612 437) nil "major mode for editing nginx config files" single ((:commit . "a2bab83c2eb233d57d76b236e7c141c2ccc97005") (:authors ("Andrew J Cosgriff" . "andrew@cosgriff.name")) (:maintainer "Andrew J Cosgriff" . "andrew@cosgriff.name") (:keywords "languages" "nginx"))]) (niceify-info . [(20160416 1244) nil "improve usability of Info pages" single ((:commit . "66b45916f1994e16ee023d29fa7cf8fec48078f1"))]) + (nickel-mode . [(20230406 910) ((emacs (24 3))) "A major mode for editing Nickel source code" single ((:commit . "fea2152d591e46e19e4be6a7aca7fb0b1de15dd0") (:authors ("The Nickel Team" . "nickel-lang@tweag.io")) (:maintainer "The Nickel Team" . "nickel-lang@tweag.io") (:keywords "languages" "configuration-language" "configuration" "nickel" "infrastructure") (:url . "https://github.com/nickel-lang/nickel-mode"))]) (niconama . [(20170910 1501) ((emacs (24)) (request (20170131 1747)) (cl-lib (0 5))) "Tools for Niconico Live Broadcast" single ((:commit . "96e7553e50e6bf7b58aac50f52c9b0b8edb41c56") (:keywords "comm") (:url . "https://github.com/NOBUTOKA/niconama.el"))]) (night-owl-theme . [(20200622 1943) ((emacs (24))) "A color theme for the night owls out there" single ((:commit . "50315d6a4e170dccc83bf2d59a8a761f5ea32bb6") (:authors ("Aaron Jensen" . "aaronjensen@gmail.com")) (:maintainer "Aaron Jensen" . "aaronjensen@gmail.com") (:url . "http://github.com/aaronjensen/night-owl-theme"))]) (nikki . [(20210228 428) ((emacs (24 3))) "A simple diary mode" single ((:commit . "b2ea20d04a061df88d72bd8dd0412a6e7876458d") (:authors ("Taiki Harada" . "thdev994@gmail.com")) (:maintainer "Taiki Harada" . "thdev994@gmail.com") (:keywords "convenience") (:url . "https://github.com/th994/nikki"))]) (nikola . [(20170703 2021) ((async (1 5)) (emacs (24 3))) "Simple wrapper for nikola" single ((:commit . "964715ac30943c9d6976999cad208dc60d09def0") (:authors (": drymer ")) (:maintainer ": drymer ") (:keywords ":" "nikola") (:url . ": https://git.daemons.it/drymer/nikola.el"))]) (nim-mode . [(20211102 917) ((emacs (24 4)) (epc (0 1 1)) (let-alist (1 0 1)) (commenter (0 5 1)) (flycheck-nimsuggest (0 8 1))) "A major mode for the Nim programming language" tar ((:commit . "744e076f0bea1c5ddc49f92397d9aa98ffa7eff8") (:authors ("Simon Hafner")) (:maintainer "Simon Hafner" . "hafnersimon@gmail.com") (:keywords "nim" "languages"))]) - (nimbus-theme . [(20230219 1337) ((emacs (24 1))) "Nimbus dark theme" single ((:commit . "b28256c3a3d3d316d09e63a1fdd0817db110c3ce") (:authors ("Marcin Swieczkowski" . "marcin.swieczkowski@gmail.com") ("See README.md for full list of contributors.")) (:maintainer "Marcin Swieczkowski" . "marcin.swieczkowski@gmail.com") (:keywords "faces") (:url . "https://github.com/mrcnski/nimbus-theme"))]) + (nimbus-theme . [(20230403 819) ((emacs (24 1))) "Nimbus dark theme" single ((:commit . "80d5b622dd0c51547235d1e206e7d98cedb5c291") (:authors ("Marcin Swieczkowski" . "marcin.swieczkowski@gmail.com") ("See README.md for full list of contributors.")) (:maintainer "Marcin Swieczkowski" . "marcin.swieczkowski@gmail.com") (:keywords "faces") (:url . "https://github.com/mrcnski/nimbus-theme"))]) (ninja-mode . [(20181024 1439) ((emacs (24))) "Major mode for editing .ninja files" single ((:commit . "d2045dedc39885e702176b2b5e05bc77024ae3aa"))]) (nix-buffer . [(20180212 1518) ((f (0 17 3)) (emacs (24 4))) "Set up buffer environments with nix" single ((:commit . "db57cda36e7477bdc7ef5a136357b971b1d4d099") (:authors ("Shea Levy")) (:maintainer "Shea Levy") (:url . "https://github.com/shlevy/nix-buffer/tree/master/"))]) (nix-env-install . [(20200812 1305) ((emacs (25 1))) "Install packages using nix-env" single ((:commit . "79c34bc117ba1cebeb67fab32c364951d2ec37a0") (:authors ("Akira Komamura" . "akira.komamura@gmail.com")) (:maintainer "Akira Komamura" . "akira.komamura@gmail.com") (:keywords "processes" "tools") (:url . "https://github.com/akirak/nix-env-install"))]) (nix-haskell-mode . [(20190615 135) ((emacs (25)) (haskell-mode (16 0)) (nix-mode (1 3 0))) "haskell-mode integrations for Nix" single ((:commit . "68efbcbf949a706ecca6409506968ed2ef928a20") (:authors ("Matthew Bauer" . "mjbauer95@gmail.com")) (:maintainer "Matthew Bauer" . "mjbauer95@gmail.com") (:keywords "nix" "haskell" "languages" "processes") (:url . "https://github.com/matthewbauer/nix-haskell"))]) - (nix-mode . [(20230210 1540) ((emacs (25 1)) (magit-section (0)) (transient (0 3))) "Major mode for editing .nix files" tar ((:commit . "c18a24e9ac569a221e88ba9d74d52c7b02b6eb77") (:maintainer "Matthew Bauer" . "mjbauer95@gmail.com") (:keywords "nix" "languages" "tools" "unix") (:url . "https://github.com/NixOS/nix-mode"))]) + (nix-mode . [(20230329 1948) ((emacs (25 1)) (magit-section (0)) (transient (0 3))) "Major mode for editing .nix files" tar ((:commit . "8a5c9d3437a7b21e3a10df635c8ec283eda1ad08") (:maintainer "Matthew Bauer" . "mjbauer95@gmail.com") (:keywords "nix" "languages" "tools" "unix") (:url . "https://github.com/NixOS/nix-mode"))]) (nix-modeline . [(20210405 742) ((emacs (25 1))) "Info about in-progress Nix evaluations on your modeline" single ((:commit . "9a6116a11bdacf649f2c50ae1f2f4b12c03bed70") (:authors ("Jordan Mulcahey" . "snhjordy@gmail.com")) (:maintainer "Jordan Mulcahey" . "snhjordy@gmail.com") (:keywords "processes" "unix" "tools") (:url . "https://github.com/ocelot-project/nix-modeline"))]) (nix-sandbox . [(20210325 1622) ((dash (2 12 1)) (s (1 10 0))) "Utility functions to work with nix-shell sandboxes" single ((:commit . "d3ec98405f1f9dac833abf9e146249b1b943870d") (:authors ("Sven Keidel" . "svenkeidel@gmail.com")) (:maintainer "Sven Keidel" . "svenkeidel@gmail.com") (:url . "https://github.com/travisbhartwell/nix-emacs"))]) (nix-update . [(20220816 2212) ((emacs (25))) "Update \"fetch\" blocks in .nix expressions" single ((:commit . "aab70a38165575a9cb41726f1cc67df60fbf2832") (:authors ("John Wiegley" . "johnw@newartisans.com")) (:maintainer "John Wiegley" . "johnw@newartisans.com") (:keywords "nix") (:url . "https://github.com/jwiegley/nix-update-el"))]) @@ -3335,14 +3353,15 @@ (nlinum-hl . [(20211112 1241) ((emacs (24 4)) (nlinum (1 7)) (cl-lib (0 5))) "heal nlinum's line numbers" single ((:commit . "22f8d75ecdaab67e0d6d0d2da4766358456ca4f5") (:authors ("Henrik Lissner ")) (:maintainer "Henrik Lissner" . "git@henrik.io") (:keywords "nlinum" "highlight" "current" "line" "faces") (:url . "https://github.com/hlissner/emacs-nlinum-hl"))]) (nlinum-relative . [(20160526 708) ((emacs (24 4)) (nlinum (1 5))) "Relative line number with nlinum" single ((:commit . "5b9950c97ba79a6f0683e38b13da23f39e01031c") (:authors ("codefalling" . "code.falling@gmail.com")) (:maintainer "codefalling" . "code.falling@gmail.com") (:keywords "convenience"))]) (nndiscourse . [(20220210 1529) ((emacs (25 1)) (dash (2 18 1)) (anaphora (1 0 4)) (rbenv (0 0 3)) (json-rpc (0 0 1))) "Gnus backend for Discourse" tar ((:commit . "1b7d7bfc99b104b7c4948af9f3394b416105e9d9") (:keywords "news") (:url . "https://github.com/dickmao/nndiscourse"))]) - (nnhackernews . [(20220604 2100) ((emacs (25 2)) (request (0 3 3)) (dash (2 18 1)) (anaphora (1 0 4))) "Gnus backend for Hacker News" single ((:commit . "ec99d579b9fa26fdb5f5e00dfd77e968ed8386f0") (:keywords "news") (:url . "https://github.com/dickmao/nnhackernews"))]) + (nnhackernews . [(20230222 1441) ((emacs (25 2)) (request (0 3 3)) (dash (2 18 1)) (anaphora (1 0 4))) "Gnus backend for Hacker News" single ((:commit . "bf0ff5d4a079004f937e7440ba282c156f24dced") (:keywords "news") (:url . "https://github.com/dickmao/nnhackernews"))]) (nnir-est . [(20180710 2103) nil "Gnus nnir interface for HyperEstraier" single ((:commit . "6d0d5c8e33f4e4ccbc22350324c0990d2676fb5a") (:authors ("KAWABATA, Taichi ")) (:maintainer "KAWABATA, Taichi ") (:keywords "mail") (:url . "https://github.com/kawabata/nnir-est"))]) (nnreddit . [(20220423 2302) ((emacs (25 1)) (request (0 3 3)) (anaphora (1 0 4)) (dash (2 18 1)) (json-rpc (0 0 1)) (virtualenvwrapper (20151123)) (s (1 6 1))) "Gnus Backend For Reddit" tar ((:commit . "8f247dce12bd10de37f0903f3027a1ddbc318eff") (:keywords "news") (:url . "https://github.com/dickmao/nnreddit"))]) - (nntwitter . [(20220213 1654) ((emacs (25 1)) (dash (20190401)) (anaphora (20180618)) (request (20190819))) "Gnus Backend For Twitter" tar ((:commit . "f0eb3f6e8040f9064a18d3761b41f41dfd21a6ee") (:keywords "news") (:url . "https://github.com/dickmao/nntwitter"))]) + (nntwitter . [(20230323 1458) ((emacs (25 1)) (dash (20190401)) (anaphora (20180618)) (request (20190819))) "Gnus Backend For Twitter" tar ((:commit . "8189100aa071386665b8616c6b57067383abd47b") (:keywords "news") (:url . "https://github.com/dickmao/nntwitter"))]) + (no-clown-fiesta-theme . [(20230220 1019) ((emacs (26 1)) (autothemer (0 2))) "Not-so-colorful-theme" single ((:commit . "e143cdfa7cecac6383328eca88586105f308bca9") (:authors ("ranmaru22")) (:maintainer "ranmaru22") (:url . "https://github.com/ranmaru22/no-clown-fiesta-theme.el"))]) (no-emoji . [(20180515 1837) ((emacs (24))) "Show :emoji-name: instead of emoji characters" single ((:commit . "ebceeab50dbfe4d60235180a57633745dbc18c77") (:authors ("Peter" . "craven@gmx.net")) (:maintainer "Peter" . "craven@gmx.net") (:keywords "extensions") (:url . "https://github.com/ecraven/no-emoji"))]) (no-littering . [(20230220 1519) ((emacs (25 1)) (compat (29 1 3 4))) "Help keeping ~/.emacs.d clean" single ((:commit . "b1ba75ab9296ada356219ff8ae26333a79871c61") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "convenience") (:url . "https://github.com/emacscollective/no-littering"))]) (no-spam . [(20190724 1854) ((emacs (25 1))) "Add repeat delays to commands" single ((:commit . "860860e4a0d59bd15c8e092dc42f5f7f769a428e") (:authors ("Daniel Phan" . "daniel.phan36@gmail.com")) (:maintainer "Daniel Phan" . "daniel.phan36@gmail.com") (:keywords "keyboard" "tools") (:url . "https://github.com/mamapanda/no-spam"))]) - (noaa . [(20220812 1535) ((emacs (27 1)) (kv (0 0 19)) (request (0 2 0)) (s (1 12 0))) "Get NOAA weather data" single ((:commit . "c691e770da0f1ed5b83c656087dfbc2ff231bef7") (:authors ("David Thompson")) (:maintainer "David Thompson") (:keywords "calendar") (:url . "https://github.com/thomp/noaa"))]) + (noaa . [(20230228 2331) ((emacs (27 1)) (kv (0 0 19)) (request (0 2 0)) (s (1 12 0))) "Get NOAA weather data" single ((:commit . "4a4f2169a840902799348e589c6f0211073c9d96") (:authors ("David Thompson")) (:maintainer "David Thompson") (:keywords "calendar") (:url . "https://github.com/thomp/noaa"))]) (noccur . [(20191015 719) nil "Run multi-occur on project/dired files" single ((:commit . "fa91647a305e89561d3dbe53da002fff49abe0bb") (:authors ("Nicolas Petton" . "petton.nicolas@gmail.com")) (:maintainer "Nicolas Petton" . "petton.nicolas@gmail.com") (:keywords "convenience"))]) (nocomments-mode . [(20170213 2037) nil "Minor mode that makes comments invisible." single ((:commit . "5a41a20cc44dfe4a9ea584354ed6dbc15dd92f46") (:authors ("Anders Lindgren")) (:maintainer "Anders Lindgren") (:url . "https://github.com/Lindydancer/nocomments-mode"))]) (noctilux-theme . [(20161113 1442) ((emacs (24))) "Dark theme inspired by LightTable" single ((:commit . "a3265a1be7f4d73f44acce6d968ca6f7add1f2ca") (:authors ("Simon Manning" . "simon@ecksdee.org")) (:maintainer "Simon Manning" . "simon@ecksdee.org") (:url . "https://github.com/sjrmanning/noctilux-theme"))]) @@ -3351,7 +3370,7 @@ (nodemcu-mode . [(20180501 2225) ((emacs (25))) "Minor mode for NodeMCU" single ((:commit . "8effd9f3df40b6b92a2f05e4d54750b624afc4a7") (:authors ("Andreas Müller" . "code@0x7.ch")) (:maintainer "Andreas Müller" . "code@0x7.ch") (:keywords "tools") (:url . "https://github.com/andrmuel/nodemcu-mode"))]) (noflet . [(20141102 1454) nil "locally override functions" single ((:commit . "7ae84dc3257637af7334101456dafe1759c6b68a") (:authors ("Nic Ferrier" . "nferrier@ferrier.me.uk")) (:maintainer "Nic Ferrier" . "nferrier@ferrier.me.uk") (:keywords "lisp") (:url . "https://github.com/nicferrier/emacs-noflet"))]) (nofrils-acme-theme . [(20180620 1248) ((emacs (24))) "Port of \"No Frils Acme\" Vim theme." tar ((:commit . "98ad7bfaff1d85b33dc162645670285b067c6f92") (:authors ("Eric Sessoms" . "esessoms@protonmail.com")) (:maintainer "Eric Sessoms" . "esessoms@protonmail.com") (:url . "https://gitlab.com/esessoms/nofrils-theme"))]) - (nord-theme . [(20200620 1122) ((emacs (24))) "An arctic, north-bluish clean and elegant theme" single ((:commit . "4f5b64605709d5803285953026137e905756c35f") (:authors ("Arctic Ice Studio" . "development@arcticicestudio.com")) (:maintainer "Arctic Ice Studio" . "development@arcticicestudio.com") (:url . "https://github.com/arcticicestudio/nord-emacs"))]) + (nord-theme . [(20230311 1131) ((emacs (24))) "An arctic, north-bluish clean and elegant theme" single ((:commit . "f9c6ee5928250bc87834bb85e7fabd47b882ca84") (:authors ("Sven Greb" . "development@svengreb.de")) (:maintainer "Sven Greb" . "development@svengreb.de") (:url . "https://github.com/nordtheme/emacs"))]) (nordless-theme . [(20201222 1627) ((colorless-themes (0 2))) "A mostly colorless version of nord-theme" single ((:commit . "1b2a507b3b7f9559c944af8fc7531a60b38ae0c3") (:authors ("Thomas Letan" . "lthms@soap.coffee")) (:maintainer "Thomas Letan" . "lthms@soap.coffee") (:keywords "faces" "theme") (:url . "https://git.sr.ht/~lthms/colorless-themes.el"))]) (norns . [(20220821 1614) ((emacs (27 1)) (dash (2 17 0)) (s (1 12 0)) (f (0 20 0)) (request (0 3 2)) (websocket (1 13))) "Interactive development environment for monome norns" single ((:commit . "387c7ae65383f7e9ff7ae93250ef6cf0e2b1b71a") (:keywords "processes" "terminals") (:url . "https://github.com/p3r7/norns.el"))]) (northcode-theme . [(20180423 1649) ((emacs (24))) "A dark theme focused on blue and orange colors." single ((:commit . "4d3750461ba25ec45321318b5f1af4e8fdf16147") (:authors ("Andreas Larsen" . "andreas@northcode.no")) (:maintainer "Andreas Larsen" . "andreas@northcode.no") (:url . "https://github.com/Northcode/northcode-theme.el"))]) @@ -3363,7 +3382,7 @@ (notmuch-labeler . [(20131230 1719) ((notmuch (0))) "Improve notmuch way of displaying labels" tar ((:commit . "d65d1129555d368243df4770ecc1e7ccb88efc58") (:authors ("Damien Cassou" . "damien.cassou@gmail.com")) (:maintainer "Damien Cassou" . "damien.cassou@gmail.com") (:keywords "emacs" "package" "elisp" "notmuch" "emails") (:url . "https://github.com/DamienCassou/notmuch-labeler"))]) (notmuch-maildir . [(20230212 2014) ((emacs (26 1)) (compat (29 1 3 4)) (notmuch (0 30))) "Visualize maildirs as a tree" single ((:commit . "0d8f1534691e834f26e1899dd54df2db7f810669") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "mail") (:url . "https://git.sr.ht/~tarsius/notmuch-maildir"))]) (notmuch-transient . [(20230212 2014) ((emacs (27 1)) (compat (29 1 3 4)) (notmuch (0 31 4))) "Command dispatchers for Notmuch" single ((:commit . "9d1fa80be0656e712a3f86079ea0abba0542dd88") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "mail") (:url . "https://git.sr.ht/~tarsius/notmuch-transient"))]) - (nov . [(20220805 2031) ((esxml (0 3 6)) (emacs (25 1))) "Featureful EPUB reader mode" single ((:commit . "cb5f45cbcfbcf263cdeb2d263eb15edefc8b07cb") (:authors ("Vasilij Schneidermann" . "mail@vasilij.de")) (:maintainer "Vasilij Schneidermann" . "mail@vasilij.de") (:keywords "hypermedia" "multimedia" "epub") (:url . "https://depp.brause.cc/nov.el"))]) + (nov . [(20230327 1739) ((esxml (0 3 6)) (emacs (25 1))) "Featureful EPUB reader mode" single ((:commit . "6c992c2c5c4ad03a0f432a74fe4d0cde3b6da4bd") (:authors ("Vasilij Schneidermann" . "mail@vasilij.de")) (:maintainer "Vasilij Schneidermann" . "mail@vasilij.de") (:keywords "hypermedia" "multimedia" "epub") (:url . "https://depp.brause.cc/nov.el"))]) (nova-theme . [(20210512 1802) ((emacs (24 3))) "A dark, pastel color theme" single ((:commit . "1498f756a4c1c9ea9740cd3208f74d071283b930") (:authors ("Muir Manders" . "muir+emacs@mnd.rs")) (:maintainer "Muir Manders" . "muir+emacs@mnd.rs") (:keywords "theme" "dark" "nova" "pastel" "faces") (:url . "https://github.com/muirmanders/emacs-nova-theme"))]) (noxml-fold . [(20170823 1357) nil "Fold away XML things." single ((:commit . "46c7f6a008672213238a9f8d7a416ce80916aa62") (:authors ("Patrick McAllister" . "pma@rdorte.org")) (:maintainer "Patrick McAllister" . "pma@rdorte.org") (:keywords "xml" "folding") (:url . "https://github.com/paddymcall/noxml-fold"))]) (npm . [(20220428 927) ((emacs (25 1)) (transient (0 1 0)) (jest (20200625))) "Run your npm workflows" tar ((:commit . "6eb0a58274870dd75bf848cf5a916a9f2c6ddae5") (:authors ("Shane Kennedy")) (:maintainer "Shane Kennedy") (:keywords "tools") (:url . "https://github.com/shaneikennedy/npm.el"))]) @@ -3372,7 +3391,7 @@ (nrepl-sync . [(20140807 1557) ((cider (0 6))) "connect to nrepl port and eval .sync.clj." single ((:commit . "471a08df87687a3eab61b3b8bf25a2e0962b5d5b") (:authors ("Phillip Lord" . "phillip.lord@newcastle.ac.uk")) (:maintainer "Phillip Lord" . "phillip.lord@newcastle.ac.uk") (:url . "https://github.com/phillord/lein-sync"))]) (ns-auto-titlebar . [(20181022 2154) ((emacs (24 4))) "Set the MacOS transparent titlebar to match theme" single ((:commit . "b16092e8058af63ad2bc222f166b0aa3cb66bf9d") (:authors ("Steve Purcell" . "steve@sanityinc.com")) (:maintainer "Steve Purcell" . "steve@sanityinc.com") (:keywords "frames") (:url . "https://github.com/purcell/ns-auto-titlebar"))]) (nsis-mode . [(20190615 1827) nil "NSIS-mode" tar ((:commit . "0a2e6ece2fe682dced4d31688b38bb472a877cdf") (:authors ("Matthew L. Fidler")) (:maintainer "Matthew L. Fidler") (:keywords "nsis") (:url . "http://github.com/mlf176f2/nsis-mode"))]) - (nswbuff . [(20220426 2050) ((emacs (25 1))) "Quick switching between buffers." single ((:commit . "7633674c89e3dbfc0c07cd7fd8b1d206ed4859d3") (:authors ("David Ponce" . "david@dponce.com") ("Kahlil (Kal) HODGSON" . "dorge@tpg.com.au") ("Joost Kremers" . "joostkremers@fastmail.fm")) (:maintainer "Joost Kremers" . "joostkremers@fastmail.fm") (:keywords "extensions" "convenience") (:url . "https://github.com/joostkremers/nswbuff"))]) + (nswbuff . [(20230311 154) ((emacs (25 1))) "Quick switching between buffers." single ((:commit . "dfea30e33ddb212a0d537bc927b4bcdf3ebe2cd1") (:authors ("David Ponce" . "david@dponce.com") ("Kahlil (Kal) HODGSON" . "dorge@tpg.com.au") ("Joost Kremers" . "joostkremers@fastmail.fm")) (:maintainer "Joost Kremers" . "joostkremers@fastmail.fm") (:keywords "extensions" "convenience") (:url . "https://github.com/joostkremers/nswbuff"))]) (nu-mode . [(20190404 2032) ((undo-tree (0 6 5)) (ace-window (0)) (lv (0)) (avy (0)) (which-key (0)) (transpose-frame (0))) "Modern Emacs Prompts Based Keybinding." tar ((:commit . "d5fb4d26d1b0bb383ea2827cc5af5dfb2a269d2b"))]) (nubox . [(20170619 910) nil "Nubox color theme (dark, light and tty versions)" tar ((:commit . "84aa965f0cb4bde293237e4cc586643d1f662f83") (:authors ("Martijn Terpstra" . "bigmartijn@gmail.com")) (:maintainer "Martijn Terpstra" . "bigmartijn@gmail.com") (:keywords "faces"))]) (number . [(20170901 1312) nil "Working with numbers at point." single ((:commit . "bbc278d34dbcca83e70e3be855ec98b23debfb99"))]) @@ -3380,13 +3399,12 @@ (numbers . [(20170802 1134) ((emacs (24))) "Display information and trivia about numbers" single ((:commit . "dd02508b788a13b7d4dbcc4923fa23134b783ab3") (:authors ("Dave Pearson" . "davep@davep.org")) (:maintainer "Dave Pearson" . "davep@davep.org") (:keywords "games" "trivia" "maths" "numbers") (:url . "https://github.com/davep/numbers.el"))]) (numbex . [(20221009 114) ((emacs (26 1))) "Manage numbered examples" single ((:commit . "f3b512453110b0ad0c341159f28f72000fc7731a") (:authors ("Enrico Flor" . "enrico@eflor.net")) (:maintainer "Enrico Flor" . "enrico@eflor.net") (:url . "https://github.com/enricoflor/numbex"))]) (nummm-mode . [(20131117 1014) nil "Display the number of minor modes instead of their names" single ((:commit . "73b1aa8643d86197c82cd28acdaefcb48a1e0abe") (:authors ("Andreu Gil" . "agpchil@gmail.com")) (:maintainer "Andreu Gil" . "agpchil@gmail.com") (:url . "http://github.com/agpchil/nummm-mode"))]) - (numpydoc . [(20220304 1546) ((emacs (25 1)) (s (1 12 0)) (dash (2 18 0))) "NumPy style docstring insertion" single ((:commit . "1b8c5ef3301fed5e5c1941817dbb7435188ff417") (:authors ("Doug Davis" . "ddavis@ddavis.io")) (:maintainer "Doug Davis" . "ddavis@ddavis.io") (:keywords "convenience") (:url . "https://github.com/douglasdavis/numpydoc.el"))]) + (numpydoc . [(20230320 1439) ((emacs (25 1)) (s (1 12 0)) (dash (2 18 0))) "NumPy style docstring insertion" single ((:commit . "f9ec92558a2ac293ab9a2f0611624b6c7d2d5658") (:authors ("Doug Davis" . "ddavis@ddavis.io")) (:maintainer "Doug Davis" . "ddavis@ddavis.io") (:keywords "convenience") (:url . "https://github.com/douglasdavis/numpydoc.el"))]) (nv-delete-back . [(20170224 1249) ((emacs (24))) "backward delete like modern text editors" single ((:commit . "44d506105989873dc1725e0cfc675925b35c9c98") (:authors ("Nicolas Vaughan ")) (:maintainer "Nicolas Vaughan ") (:keywords "lisp"))]) (nvm . [(20210826 1000) ((s (1 8 0)) (dash (2 18 0)) (f (0 14 0))) "Manage Node versions within Emacs" single ((:commit . "c214762fd6f539ec3e1fd8198cefbdb4b428b19c") (:authors ("Johan Andersson" . "johan.rejeep@gmail.com")) (:maintainer "Johan Andersson" . "johan.rejeep@gmail.com") (:keywords "node" "nvm") (:url . "http://github.com/rejeep/nvm.el"))]) (nxml-uxml . [(20220606 1213) ((emacs (25))) "MicroXML support for nXML" single ((:commit . "95bbd0018ab218b9f39f5bf1f1e809f60fbc3edc") (:authors ("Daphne Preston-Kendal")) (:maintainer "Daphne Preston-Kendal") (:keywords "languages" "xml" "microxml") (:url . "https://gitlab.com/dpk/nxml-uxml"))]) (nyan-mode . [(20220408 2334) ((emacs (24 1))) "Nyan Cat shows position in current buffer in mode-line" tar ((:commit . "09904af23adb839c6a9c1175349a1fb67f5b4370") (:authors ("Jacek \"TeMPOraL\" Zlydach" . "temporal.pl@gmail.com")) (:maintainer "Jacek \"TeMPOraL\" Zlydach" . "temporal.pl@gmail.com") (:keywords "convenience" "games" "mouse" "multimedia") (:url . "https://github.com/TeMPOraL/nyan-mode/"))]) (nyx-theme . [(20170910 1307) ((emacs (24))) "Dark theme" single ((:commit . "afe2b8c3b5421b4c292d182dcf77079b278e93d8") (:authors ("Guido Schmidt")) (:maintainer "Guido Schmidt" . "guido.schmidt.2912@gmail.com") (:keywords "themes" "dark-theme") (:url . "https://github.com/GuidoSchmidt/emacs-nyx-theme"))]) - (nz-holidays . [(20190415 703) nil "New Zealand public holidays for calendar." single ((:commit . "afc875cf40789fa45a4a811685b0a7c4f239392f") (:authors ("Sod Oscarfono" . "sod@oscarfono.com")) (:maintainer "Sod Oscarfono" . "sod@oscarfono.com") (:keywords "calendar") (:url . "https://github.com/techquila/nz-holidays"))]) (oauth . [(20130128 151) nil "Oauth library." tar ((:commit . "ee4744ad76a1560281b0c4944575a3bd598c6458") (:authors ("Peter Sanford ")) (:maintainer "Peter Sanford ") (:keywords "comm"))]) (oauth2-request . [(20210215 657) ((emacs (26 1)) (oauth2 (0 14)) (request (0 3))) "OAuth2 request package interface" single ((:commit . "86ff048635e002b00e23d6bed2ec6f36c17bca8e") (:authors ("Naoya Yamashita" . "conao3@gmail.com")) (:maintainer "Naoya Yamashita" . "conao3@gmail.com") (:keywords "convenience") (:url . "https://github.com/conao3/oauth2-request.el"))]) (ob-ada-spark . [(20221114 2007) ((emacs (26 1)) (f (0 20 0))) "Babel functions for Ada & SPARK" single ((:commit . "92978410ca14aa4e84c229a0920ad40be91c35e1") (:authors ("Francesc Rocher")) (:maintainer "Francesc Rocher") (:keywords "languages" "tools" "outlines") (:url . "https://github.com/rocher/ob-ada-spark"))]) @@ -3396,17 +3414,19 @@ (ob-bitfield . [(20220401 600) ((emacs (24 4))) "Babel Functions for bitfield" single ((:commit . "abe3d8fe49dc53c4663def689ceb5c0433638652") (:authors ("Gulshan Singh")) (:maintainer "Gulshan Singh") (:url . "https://github.com/gsingh93/ob-bitfield"))]) (ob-blockdiag . [(20210412 1541) nil "org-babel functions for blockdiag evaluation" single ((:commit . "e997644e81cc67a7092e6e9bb13c66f160491efb") (:authors ("Dmitry Moskowski")) (:maintainer "Dmitry Moskowski") (:keywords "tools" "convenience") (:url . "https://github.com/corpix/ob-blockdiag.el"))]) (ob-browser . [(20170720 1918) ((org (8))) "Render HTML in org-mode blocks." tar ((:commit . "a347d9df1c87b7eb660be8723982c7ad2563631a") (:authors ("Kris Jenkins" . "krisajenkins@gmail.com")) (:maintainer "Kris Jenkins" . "krisajenkins@gmail.com") (:keywords "org" "babel" "browser" "phantomjs") (:url . "https://github.com/krisajenkins/ob-browser"))]) - (ob-cfengine3 . [(20191011 1721) nil "Org Babel functions for CFEngine 3" single ((:commit . "195ba4694a0ec18d3fb89342e8e0988b382a5b1a") (:authors ("Nick Anderson" . "nick@cmdln.org")) (:maintainer "Nick Anderson" . "nick@cmdln.org") (:keywords "tools" "convenience") (:url . "https://github.com/nickanderson/ob-cfengine3"))]) + (ob-cfengine3 . [(20230226 1954) ((emacs (24 1))) "Org Babel functions for CFEngine 3" single ((:commit . "52aa32fdfa412860837e795d17d50dac237e56e4") (:authors ("Nick Anderson" . "nick@cmdln.org")) (:maintainer "Nick Anderson" . "nick@cmdln.org") (:keywords "tools" "convenience") (:url . "https://github.com/nickanderson/ob-cfengine3"))]) (ob-clojurescript . [(20180406 1828) ((emacs (24 4)) (org (9 0))) "org-babel functions for ClojureScript evaluation" single ((:commit . "17ee1558aa94c7b0246fd03f684884122806cfe7") (:authors ("Larry Staton Jr.")) (:maintainer "Larry Staton Jr.") (:keywords "literate programming" "reproducible research") (:url . "https://gitlab.com/statonjr/ob-clojurescript"))]) (ob-coffee . [(20170725 1424) ((org (8))) "org-babel functions for coffee-script evaluation" tar ((:commit . "7f0b330273e8af7777de87a75fe52a89798e4548") (:authors ("ZHOU Feng" . "zf.pascal@gmail.com")) (:maintainer "ZHOU Feng" . "zf.pascal@gmail.com") (:keywords "org" "babel" "coffee-script") (:url . "http://github.com/zweifisch/ob-coffee"))]) (ob-coffeescript . [(20180126 719) ((emacs (24 4))) "org-babel functions for coffee-script evaluation, and fully implementation!" single ((:commit . "5a5bb04aea9c2a6eab5b05f90f5c7cb6de7b4261") (:authors ("Brantou" . "brantou89@gmail.com")) (:maintainer "Brantou" . "brantou89@gmail.com") (:keywords "coffee-script" "literate programming" "reproducible research") (:url . "https://github.com/brantou/ob-coffeescript"))]) (ob-compile . [(20220830 315) ((emacs (24 4))) "Run compile by org-babel" single ((:commit . "9a16b3dd0f467c091e91944b90a2ca3d646d6617") (:authors ("Giap Tran" . "txgvnn@gmail.com")) (:maintainer "Giap Tran" . "txgvnn@gmail.com") (:keywords "literate programming" "reproducible" "processes") (:url . "https://github.com/TxGVNN/ob-compile"))]) (ob-crystal . [(20180126 718) ((emacs (24 3))) "org-babel functions for Crystal evaluation" tar ((:commit . "b3bb27a21a4cefef3f5aeef52718b694bd51245b") (:authors ("Brantou" . "brantou89@gmail.com")) (:maintainer "Brantou" . "brantou89@gmail.com") (:keywords "crystal" "literate programming" "reproducible research") (:url . "https://github.com/brantou/ob-crystal"))]) (ob-cypher . [(20200521 936) ((s (1 9 0)) (cypher-mode (0 0 6)) (dash (2 10 0)) (dash-functional (1 2 0))) "query neo4j using cypher in org-mode blocks" single ((:commit . "da9f97339474a48d759fc128cee610c0bc9ae6c0") (:authors ("ZHOU Feng" . "zf.pascal@gmail.com")) (:maintainer "ZHOU Feng" . "zf.pascal@gmail.com") (:keywords "org" "babel" "cypher" "neo4j") (:url . "http://github.com/zweifisch/ob-cypher"))]) + (ob-d2 . [(20230314 352) ((emacs (24 1))) "Org-babel functions for d2" single ((:commit . "5d197f8225a9fb4da997235b231abe30049c6825") (:authors ("Xavier Capaldi")) (:maintainer "Xavier Capaldi") (:keywords "languages") (:url . "https://github.com/xcapaldi/ob-d2"))]) (ob-dao . [(20170816 1558) ((org (8))) "Org Babel Functions for Dao" single ((:commit . "8c62bd800b1f572860e30be4b72c71fa415a2e31") (:authors ("Chunyang Xu" . "mail@xuchunyang.me")) (:maintainer "Chunyang Xu" . "mail@xuchunyang.me") (:keywords "literate programming" "reproducible research" "org" "babel" "dao") (:url . "https://github.com/xuchunyang/ob-dao"))]) (ob-dart . [(20221201 633) ((emacs (24 4))) "Evaluate Dart source blocks in org-mode" single ((:commit . "f6d5664d5cc8b15e002f6899f8adedcb10ced5f1") (:authors ("Milan Zimmermann")) (:maintainer "Milan Zimmermann") (:keywords "languages") (:url . "http://github.org/mzimmerm/ob-dart"))]) (ob-deno . [(20201019 101) ((emacs (26 1))) "Babel Functions for Javascript/TypeScript with Deno" single ((:commit . "e3b06d7662687e402905b9de4ad1d5816e89b842") (:authors ("HIGASHI Taiju")) (:maintainer "HIGASHI Taiju") (:keywords "literate programming" "reproducible research" "javascript" "typescript" "tools") (:url . "https://github.com/taiju/ob-deno"))]) (ob-diagrams . [(20160407 1237) nil "org-babel functions for diagrams evaluation" single ((:commit . "be45815f5596d181592fae709096b7b5f4a71992") (:authors ("Daniel Bergey")) (:maintainer "Daniel Bergey") (:keywords "literate programming" "reproducible research") (:url . "http://orgmode.org"))]) + (ob-drawtiming . [(20230312 1740) ((emacs (24 1)) (org (8 0))) "Functions for drawtiming evaluation in org-babel" single ((:commit . "813736e20ce1c223700c87a6e70e3f126a11e933") (:authors ("Fabien Perez")) (:maintainer "Fabien Perez") (:keywords "tools" "multimedia") (:url . "https://github.com/perfab71/ob-drawtiming"))]) (ob-dsq . [(20220915 1610) ((emacs (27 1))) "Babel functions for the `dsq` CLI tool by Multiprocess Labs" single ((:commit . "e001b263af87993755319caefaf5d19e196e4e1b") (:authors ("Fritz Grabo" . "hello@fritzgrabo.com")) (:maintainer "Fritz Grabo" . "hello@fritzgrabo.com") (:keywords "data" "tools") (:url . "https://github.com/fritzgrabo/ob-dsq"))]) (ob-elixir . [(20170725 1419) ((org (8))) "org-babel functions for elixir evaluation" single ((:commit . "8990a8178b2f7bd93504a9ab136622aab6e82e32") (:authors ("ZHOU Feng" . "zf.pascal@gmail.com")) (:maintainer "ZHOU Feng" . "zf.pascal@gmail.com") (:keywords "org" "babel" "elixir") (:url . "http://github.com/zweifisch/ob-elixir"))]) (ob-elm . [(20200528 1857) ((emacs (26 1)) (org (9 3))) "Org-babel functions for elm evaluation" single ((:commit . "d3a9fbc2f56416894c9aed65ea9a20cc1d98f15d") (:authors ("Bonface M. K.")) (:maintainer "Bonface M. K.") (:keywords "languages" "tools") (:url . "https://www.bonfacemunyoki.com"))]) @@ -3439,7 +3459,7 @@ (ob-prolog . [(20190410 2130) nil "org-babel functions for prolog evaluation." single ((:commit . "149abd3832fc5a6a1cb01a586a1622a8f25887dc") (:authors ("Bjarte Johansen")) (:maintainer "Bjarte Johansen") (:keywords "literate programming" "reproducible research") (:url . "https://github.com/ljos/ob-prolog"))]) (ob-raku . [(20221013 1938) ((emacs (24 1))) "Provides raku support for org-babel" single ((:commit . "21aa77a0ca70b7bef0ecf7d4d9c5272d71f0210c") (:authors ("Tim Van den Langenbergh https://github.com/tmtvl")) (:maintainer "Tim Van den Langenbergh https://github.com/tmtvl") (:keywords "literate programming" "reproducible research" "languages") (:url . "https://github.com/masukomi/ob-raku"))]) (ob-redis . [(20220221 1249) ((org (8))) "Execute Redis queries within org-mode blocks." single ((:commit . "44c83636ccbea0b3e9838b0180471905c30224c5") (:authors ("stardiviner" . "numbchild@gmail.com")) (:maintainer "stardiviner" . "numbchild@gmail.com") (:keywords "org" "babel" "redis") (:url . "https://repo.or.cz/ob-redis.git"))]) - (ob-restclient . [(20220819 2228) ((restclient (0))) "org-babel functions for restclient-mode" single ((:commit . "1b021ce1c67c97fa1aa4d2c0816edb7add129e48") (:authors ("Alf Lervåg")) (:maintainer "Alf Lervåg") (:keywords "literate programming" "reproducible research") (:url . "https://github.com/alf/ob-restclient.el"))]) + (ob-restclient . [(20230301 1951) ((restclient (0))) "org-babel functions for restclient-mode" single ((:commit . "ded3b7eb7b0592328a7a08ecce6f25278cba4a1d") (:authors ("Alf Lervåg")) (:maintainer "Alf Lervåg") (:keywords "literate programming" "reproducible research") (:url . "https://github.com/alf/ob-restclient.el"))]) (ob-reticulate . [(20210214 2229) ((org (9 4)) (emacs (24 4))) "Babel Functions for reticulate" single ((:commit . "56f4d74f5a2218927aeacce61442b373a0a189e3") (:authors ("Jack Kamm")) (:maintainer "Jack Kamm") (:keywords "literate programming" "reproducible research" "r" "python" "statistics" "languages" "outlines" "processes") (:url . "https://github.com/jackkamm/ob-reticulate"))]) (ob-rust . [(20220824 1923) nil "Org-babel functions for Rust" tar ((:commit . "be059d231fafeb24a658db212a55ccdc55c0c500") (:authors ("Mican Zhang")) (:maintainer "Mican Zhang") (:keywords "rust" "languages" "org" "babel") (:url . "https://github.com/micanzhang/ob-rust"))]) (ob-sagemath . [(20191106 828) ((sage-shell-mode (0 0 8)) (s (1 8 0)) (emacs (24))) "org-babel functions for SageMath evaluation" tar ((:commit . "79645bce0c25a650bae61e550434bed836995dce") (:authors ("Sho Takemori" . "stakemorii@gmail.com")) (:maintainer "Sho Takemori" . "stakemorii@gmail.com") (:keywords "sagemath" "org-babel") (:url . "https://github.com/stakemori/ob-sagemath"))]) @@ -3459,10 +3479,10 @@ (obfusurl . [(20170809 1524) ((cl-lib (0 5))) "Obfuscate URLs so they aren't spoilers" single ((:commit . "7a5a41905000ce2ec1fd72509a5567e5fd9f47e5") (:authors ("Dave Pearson" . "davep@davep.org")) (:maintainer "Dave Pearson" . "davep@davep.org") (:keywords "convenience" "web" "text") (:url . "https://github.com/davep/obfusurl.el"))]) (objc-font-lock . [(20141021 1822) nil "Highlight Objective-C method calls." single ((:commit . "34b457d577f97ca94b8792d025f9a909c7610612") (:authors ("Anders Lindgren")) (:maintainer "Anders Lindgren") (:keywords "languages" "faces") (:url . "https://github.com/Lindydancer/objc-font-lock"))]) (objed . [(20200911 1435) ((emacs (25)) (cl-lib (0 5))) "Navigate and edit text objects." tar ((:commit . "e93dda73bd932563d35e76f1c2f1b50895b640cf") (:authors ("Clemens Radermacher" . "clemera@posteo.net")) (:maintainer "Clemens Radermacher" . "clemera@posteo.net") (:keywords "convenience") (:url . "https://github.com/clemera/objed"))]) - (oblivion-theme . [(20230112 636) ((emacs (24 1))) "A port of GEdit oblivion theme" single ((:commit . "751687dd6163593fca2b21bb06a75ac2597de055") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:url . "https://codeberg.org/ideasman42/emacs-oblivion-theme"))]) + (oblivion-theme . [(20230306 1) ((emacs (24 1))) "A port of GEdit oblivion theme" single ((:commit . "b1181a024a1c2295a42915c0110ac9816844aff6") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:url . "https://codeberg.org/ideasman42/emacs-oblivion-theme"))]) (obsidian . [(20221228 1142) ((emacs (27 2)) (s (1 12 0)) (dash (2 13)) (markdown-mode (2 5)) (elgrep (1 0 0)) (yaml (0 5 1))) "Obsidian Notes interface" single ((:commit . "d9fdc5e2b7ee6602ac99511d670a382c5586f14c") (:authors ("Mykhaylo Bilyanskyy")) (:maintainer "Mykhaylo Bilyanskyy") (:keywords "obsidian" "pkm" "convenience") (:url . "https://github.com./licht1stein/obsidian.el"))]) (obsidian-theme . [(20170719 948) nil "port of the eclipse obsidian theme" single ((:commit . "f45efb2ebe9942466c1db6abbe2d0e6847b785ea") (:authors ("martin haesler")) (:maintainer "martin haesler") (:url . "http://github.com/mswift42/obsidian-theme"))]) - (ocamlformat . [(20220718 1147) ((emacs (24 3))) "Utility functions to format ocaml code" single ((:commit . "86938aa4435b251af1a3b081f7fbed90f982cf62") (:keywords "languages" "ocaml") (:url . "https://github.com/ocaml-ppx/ocamlformat"))]) + (ocamlformat . [(20230306 1907) ((emacs (24 3))) "Utility functions to format ocaml code" single ((:commit . "651f767b48e14ba6b24db9421306942d9e51adcc") (:keywords "languages" "ocaml") (:url . "https://github.com/ocaml-ppx/ocamlformat"))]) (occidental-theme . [(20130312 1958) nil "Custom theme for faces based on Adwaita" single ((:commit . "fd2db7256d4f78c43d99c3cddb1c39106d479816") (:authors ("William Stevenson" . "yhvh2000@gmail.com") ("Erik Timan" . "dev@timan.info")) (:maintainer "William Stevenson" . "yhvh2000@gmail.com") (:url . "http://github.com/olcai/occidental-theme"))]) (occur-context-resize . [(20210121 50) nil "dynamically resize context around matches in occur-mode" single ((:commit . "9d62a5b5c39ab7921dfc12dd0ab139b38dd16582") (:authors ("Charles L.G. Comstock" . "dgtized@gmail.com")) (:maintainer "Charles L.G. Comstock" . "dgtized@gmail.com") (:keywords "matching") (:url . "https://github.com/dgtized/occur-context-resize.el"))]) (occur-x . [(20130610 1343) nil "Extra functionality for occur" single ((:commit . "352f5fab207d8a1d3dd048073ff127a83e97c82b") (:authors ("Juan-Leon Lahoz" . "juanleon1@gmail.com")) (:maintainer "Juan-Leon Lahoz" . "juanleon1@gmail.com") (:keywords "occur" "search" "convenience"))]) @@ -3472,7 +3492,7 @@ (octicons . [(20151101 340) ((cl-lib (0 5))) "octicons utility" tar ((:commit . "229286a6166dba8ddabc8c4d338798c6cd3cf67d") (:authors ("Syohei YOSHIDA" . "syohex@gmail.com")) (:maintainer "Syohei YOSHIDA" . "syohex@gmail.com") (:url . "https://github.com/syohex/emacs-octicons"))]) (octo-mode . [(20161008 1229) ((emacs (24))) "Major mode for Octo assembly language" single ((:commit . "4b2ed4a61674f73a6ccd390b5ae123474bd0c977") (:authors ("John Olsson" . "john@cryon.se")) (:maintainer "John Olsson" . "john@cryon.se") (:keywords "languages") (:url . "https://github.com/cryon/octo-mode"))]) (octopress . [(20190123 107) nil "A lightweight wrapper for Jekyll and Octopress." tar ((:commit . "f2c92d5420f14fc9167c7de1873836510e652de2") (:authors ("Aaron Bieber" . "aaron@aaronbieber.com")) (:maintainer "Aaron Bieber" . "aaron@aaronbieber.com") (:keywords "octopress" "blog") (:url . "https://github.com/aaronbieber/octopress.el"))]) - (oer-reveal . [(20221229 727) ((emacs (24 4)) (org-re-reveal (3 1 0))) "OER with reveal.js, plugins, and org-re-reveal" tar ((:commit . "a2dde292e464bfb9b4d8ab470bb9a6a37b5cb6b9") (:authors ("Jens Lechtenbörger")) (:maintainer "Jens Lechtenbörger") (:keywords "hypermedia" "tools" "slideshow" "presentation" "oer") (:url . "https://gitlab.com/oer/oer-reveal"))]) + (oer-reveal . [(20230403 1322) ((emacs (24 4)) (org-re-reveal (3 1 0))) "OER with reveal.js, plugins, and org-re-reveal" tar ((:commit . "f7b0d952c9ab0969dbb9c003df4f298ec9d3ee79") (:authors ("Jens Lechtenbörger")) (:maintainer "Jens Lechtenbörger") (:keywords "hypermedia" "tools" "slideshow" "presentation" "oer") (:url . "https://gitlab.com/oer/oer-reveal"))]) (offlineimap . [(20150916 1158) nil "Run OfflineIMAP from Emacs" single ((:commit . "cc3e067e6237a1eb7b21c575a41683b1febb47f1") (:authors ("Julien Danjou" . "julien@danjou.info")) (:maintainer "Julien Danjou" . "julien@danjou.info") (:url . "http://julien.danjou.info/offlineimap-el.html"))]) (oj . [(20230212 148) ((emacs (26 1)) (quickrun (2 2))) "Competitive programming tools client for AtCoder, Codeforces" single ((:commit . "6d586cb108c642bc166c64df113e03193f4d1495") (:authors ("Naoya Yamashita" . "conao3@gmail.com")) (:maintainer "Naoya Yamashita" . "conao3@gmail.com") (:keywords "convenience") (:url . "https://github.com/conao3/oj.el"))]) (ol-notmuch . [(20230212 2013) ((emacs (25 1)) (compat (29 1 3 4)) (notmuch (0 32)) (org (9 4 5))) "Links to notmuch messages" single ((:commit . "ee3646627e47312a0c6ab0a5f6eba3baf8b20cb6") (:authors ("Matthieu Lemerre" . "racin@free.fr")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "hypermedia" "mail") (:url . "https://git.sr.ht/~tarsius/ol-notmuch"))]) @@ -3512,6 +3532,7 @@ (ordinal . [(20210519 1442) ((emacs (24 3))) "Convert number to ordinal number notation" single ((:commit . "a7f378306290b6807fb6b87cee3ef79b31cec711") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "lisp") (:url . "https://github.com/zonuexe/ordinal.el"))]) (org-ac . [(20170401 1307) ((auto-complete-pcmp (0 0 1)) (log4e (0 2 0)) (yaxception (0 1))) "Some auto-complete sources for org-mode" single ((:commit . "41e3ef8e4039619d0370c23c66730b3b2e9e32ed") (:authors ("Hiroaki Otsu" . "ootsuhiroaki@gmail.com")) (:maintainer "Hiroaki Otsu" . "ootsuhiroaki@gmail.com") (:keywords "org" "completion") (:url . "https://github.com/aki2o/org-ac"))]) (org-agenda-property . [(20140626 2116) ((emacs (24 2))) "Display org properties in the agenda buffer." single ((:commit . "01afb36072eb27846eb09310dfca7991dbae831e") (:authors ("Artur Malabarba" . "bruce.connor.am@gmail.com")) (:maintainer "Artur Malabarba" . "bruce.connor.am@gmail.com") (:keywords "calendar") (:url . "http://github.com/Bruce-Connor/org-agenda-property"))]) + (org-ai . [(20230407 950) ((emacs (28 2))) "Your AI assistant with ChatGPT, DALL-E, Whisper" tar ((:commit . "17fee8f50328692076e66570ffe5f749c0dc52e7") (:authors ("Robert Krahn" . "robert@kra.hn")) (:maintainer "Robert Krahn" . "robert@kra.hn") (:url . "https://github.com/rksm/org-ai"))]) (org-alert . [(20220721 1721) ((org (9 0)) (alert (1 2))) "Notify org deadlines via notify-send" single ((:commit . "f1801e061722843329b95409957c7dbd5cc223e9") (:authors ("Stephen Pegoraro" . "spegoraro@tutive.com")) (:maintainer "Stephen Pegoraro" . "spegoraro@tutive.com") (:keywords "org" "org-mode" "notify" "notifications" "calendar") (:url . "https://github.com/spegoraro/org-alert"))]) (org-analyzer . [(20191001 1717) nil "org-analyzer is a tool that extracts time tracking data from org files." tar ((:commit . "19da62aa4dcf1090be8f574f6f2d4c7e116163a8") (:authors ("Robert Krahn" . "robert@kra.hn")) (:maintainer "Robert Krahn" . "robert@kra.hn") (:keywords "calendar") (:url . "https://github.com/rksm/clj-org-analyzer"))]) (org-anki . [(20230117 727) ((emacs (27 1)) (request (0 3 2)) (dash (2 17)) (promise (1 1))) "Synchronize org-mode entries to Anki" single ((:commit . "f10feec7bd70916808a3cd8b4c3e3c7f65764acf") (:authors ("Markus Läll" . "markus.l2ll@gmail.com")) (:maintainer "Markus Läll" . "markus.l2ll@gmail.com") (:keywords "outlines" "flashcards" "memory") (:url . "https://github.com/eyeinsky/org-anki"))]) @@ -3524,12 +3545,12 @@ (org-babel-eval-in-repl . [(20201206 1540) ((eval-in-repl (0 9 2)) (matlab-mode (3 3 6)) (ess (16 10)) (emacs (24))) "Eval org-mode babel code blocks in various REPLs." tar ((:commit . "3591f062873de2d64cc6f83b3555d030506e6ee7") (:authors ("Takeshi Teshima" . "diadochos.developer@gmail.com")) (:maintainer "Takeshi Teshima" . "diadochos.developer@gmail.com") (:keywords "literate programming" "reproducible research" "async execution") (:url . "https://github.com/diadochos/org-babel-eval-in-repl"))]) (org-beautify-theme . [(20170908 2218) nil "A sub-theme to make org-mode more beautiful." single ((:commit . "df6a1114fda313e1689363e196c8284fbe2a2738") (:authors ("Jonathan Arkell" . "jonnay@jonnay.net")) (:maintainer "Jonathan Arkell" . "jonnay@jonnay.net") (:keywords "org" "theme"))]) (org-board . [(20200619 1016) nil "bookmarking and web archival system for Org mode." single ((:commit . "1393bd46d11a81328ed4fb8471831415a3efe224") (:authors ("Charles A. Roelli " . "charles@aurox.ch")) (:maintainer "Charles A. Roelli " . "charles@aurox.ch") (:keywords "org" "bookmarks" "archives") (:url . "https://github.com/scallywag/org-board"))]) - (org-bookmark-heading . [(20221022 1422) ((emacs (24 4))) "Emacs bookmark support for Org mode" single ((:commit . "f245c9023df28d6ee545dae4b96a1c237e6965ba") (:authors ("Adam Porter" . "adam@alphapapa.net")) (:maintainer "Adam Porter" . "adam@alphapapa.net") (:keywords "hypermedia" "outlines") (:url . "http://github.com/alphapapa/org-bookmark-heading"))]) + (org-bookmark-heading . [(20230308 31) ((emacs (24 4))) "Emacs bookmark support for Org mode" single ((:commit . "f7b444ab5445e4860ab14fcc2bede3384578b194") (:authors ("Adam Porter" . "adam@alphapapa.net")) (:maintainer "Adam Porter" . "adam@alphapapa.net") (:keywords "hypermedia" "outlines") (:url . "http://github.com/alphapapa/org-bookmark-heading"))]) (org-bookmarks-extractor . [(20220829 146) ((emacs (25 1))) "Extract bookmarks from Org mode" single ((:commit . "26d810d4d58de1f64f0bbd649e13816f96663d73") (:authors ("Xuqing Jia" . "jxq@jxq.me")) (:maintainer "Xuqing Jia" . "jxq@jxq.me") (:keywords "convenience" "org") (:url . "https://github.com/jxq0/org-bookmarks-extractor"))]) (org-books . [(20210408 1913) ((enlive (0 0 1)) (s (1 11 0)) (helm (2 9 2)) (helm-org (1 0)) (dash (2 14 1)) (org (9 3)) (emacs (25))) "Reading list management with Org mode and helm" single ((:commit . "9f4ec4a981bfc5eebff993c3ad49a4bed26aebd1") (:authors ("Abhinav Tushar" . "abhinav@lepisma.xyz")) (:maintainer "Abhinav Tushar" . "abhinav@lepisma.xyz") (:keywords "outlines") (:url . "https://github.com/lepisma/org-books"))]) (org-brain . [(20230217 1908) ((emacs (25 1)) (org (9 2))) "Org-mode concept mapping" single ((:commit . "2bad7732aae1a3051e2a14de2e30f970bbe43c25") (:authors ("Erik Sjöstrand" . "sjostrand.erik@gmail.com")) (:maintainer "Erik Sjöstrand" . "sjostrand.erik@gmail.com") (:keywords "outlines" "hypermedia") (:url . "http://github.com/Kungsgeten/org-brain"))]) (org-bullets . [(20200317 1740) nil "Show bullets in org-mode as UTF-8 characters" single ((:commit . "9ec0dbd30be7c6310804141ee952ac8c5f753557") (:authors ("sabof")) (:maintainer "D. Williams" . "d.williams@posteo.net") (:url . "https://github.com/integral-dw/org-bullets"))]) - (org-caldav . [(20230205 2235) ((emacs (26 3)) (org (9 1))) "Sync org files with external calendar through CalDAV" single ((:commit . "cc1b820773ccab9e3d8f584e96c14cdbb22cdb16") (:authors ("David Engster" . "deng@randomsample.de")) (:maintainer "Jack Kamm" . "jackkamm@tatersworld.org") (:keywords "calendar" "caldav") (:url . "https://github.com/dengste/org-caldav/"))]) + (org-caldav . [(20230331 11) ((emacs (26 3)) (org (9 1))) "Sync org files with external calendar through CalDAV" single ((:commit . "618bf4cdc9be140ca1993901d017b7f18297f1b8") (:authors ("David Engster" . "deng@randomsample.de")) (:maintainer "Jack Kamm" . "jackkamm@tatersworld.org") (:keywords "calendar" "caldav") (:url . "https://github.com/dengste/org-caldav/"))]) (org-calibre-notes . [(20221202 1657) ((emacs (27 1))) "Extract highlights and notes from Calibre EPUB reader" single ((:commit . "3120797ecbcb58827b91e3610e65579593d9a402") (:authors ("Bibek Panthi" . "bpanthi977@gmail.com")) (:maintainer "Bibek Panthi" . "bpanthi977@gmail.com") (:url . "https://github.com/bpanthi977/org-calibre-notes"))]) (org-capture-pop-frame . [(20160518 1008) ((emacs (24 4))) "Run org-capture in a new pop frame" single ((:commit . "b16fd712de62cf0d1f9befd03be6ab5983cb3301") (:authors ("Feng Shu" . "tumashu@163.com")) (:maintainer "Feng Shu" . "tumashu@163.com") (:url . "https://github.com/tumashu/org-capture-pop-frame.git"))]) (org-category-capture . [(20220114 730) ((org (9 0 0)) (emacs (24))) "Contextualy capture of org-mode TODOs." single ((:commit . "bc5a2401b456c42c4346d59fa77d633770b6efea") (:authors ("Ivan Malison" . "IvanMalison@gmail.com")) (:maintainer "Ivan Malison" . "IvanMalison@gmail.com") (:keywords "org-mode" "todo" "tools" "outlines") (:url . "https://github.com/IvanMalison/org-projectile"))]) @@ -3537,11 +3558,11 @@ (org-cliplink . [(20201126 1020) ((emacs (24 4))) "insert org-mode links from the clipboard" tar ((:commit . "13e0940b65d22bec34e2de4bc8cba1412a7abfbc") (:authors ("Alexey Kutepov" . "reximkut@gmail.com")) (:maintainer "Alexey Kutepov" . "reximkut@gmail.com") (:url . "http://github.com/rexim/org-cliplink"))]) (org-clock-convenience . [(20221124 2304) ((org (8)) (emacs (24 3))) "Convenience functions for org time tracking" single ((:commit . "9d21d3a5ba2f8656aa23b8cb557017440f1b74e8") (:authors ("Derek Feichtinger ")) (:maintainer "Derek Feichtinger ") (:keywords "convenience") (:url . "https://github.com/dfeich/org-clock-convenience"))]) (org-clock-csv . [(20201222 1506) ((org (8 3)) (s (1 0))) "Export `org-mode' clock entries to CSV format." single ((:commit . "af94b58c2e179a5bcc938f339e93de0eee3da99c") (:authors ("Aaron Jacobs" . "atheriel@gmail.com")) (:maintainer "Aaron Jacobs" . "atheriel@gmail.com") (:keywords "calendar" "data" "org") (:url . "https://github.com/atheriel/org-clock-csv"))]) - (org-clock-reminder . [(20230217 728) ((emacs (26 1))) "Notifications that remind you about clocked-in tasks" tar ((:commit . "fd3d2ca9d5ca1a804c0e70193f89f650c69a8dc1") (:authors ("Nikolay Brovko" . "i@nickey.ru")) (:maintainer "Nikolay Brovko" . "i@nickey.ru") (:keywords "calendar" "convenience") (:url . "https://github.com/inickey/org-clock-reminder"))]) + (org-clock-reminder . [(20230222 1956) ((emacs (26 1))) "Notifications that remind you about clocked-in tasks" tar ((:commit . "d3bf97113fd519aa08198e2283ba9c236a6df168") (:authors ("Nikolay Brovko" . "i@nickey.ru")) (:maintainer "Nikolay Brovko" . "i@nickey.ru") (:keywords "calendar" "convenience") (:url . "https://github.com/inickey/org-clock-reminder"))]) (org-clock-split . [(20200331 526) ((emacs (24))) "Split clock entries" single ((:commit . "39e1d2912a7a7223e2356a5fc4dff03507ae084d") (:authors ("Justin Taft ")) (:maintainer "Justin Taft ") (:keywords "calendar") (:url . "https://github.com/justintaft/emacs-org-clock-split"))]) (org-clock-today . [(20220918 514) ((emacs (25))) "Show total clocked time of the current day in the mode line" single ((:commit . "b73cca120eb64538ab0666892a8b97b6d65b4d6b") (:authors ("Tijs Mallaerts" . "tijs.mallaerts@gmail.com")) (:maintainer "Tijs Mallaerts" . "tijs.mallaerts@gmail.com") (:url . "https://github.com/mallt/org-clock-today-mode"))]) (org-commentary . [(20160802 637) ((dash (2 0)) (emacs (24 4)) (org (8 0))) "generate or update conventional library headers using Org mode files" tar ((:commit . "821ccb994811359c42f4e3d459e0e88849d42b75") (:authors ("Sergei Maximov" . "s.b.maximov@gmail.com")) (:maintainer "Sergei Maximov" . "s.b.maximov@gmail.com") (:keywords "convenience" "docs" "tools") (:url . "https://github.com/smaximov/org-commentary"))]) - (org-contacts . [(20221221 431) ((emacs (27 1)) (org (9 3 4))) "Contacts management system for Org Mode" single ((:commit . "bb4032eb12c20d34555a4e670f28696cf31a7b54") (:authors ("Julien Danjou" . "julien@danjou.info")) (:maintainer "stardiviner" . "numbchild@gmail.com") (:keywords "contacts" "org-mode" "outlines" "hypermedia" "calendar") (:url . "https://repo.or.cz/org-contacts.git"))]) + (org-contacts . [(20230227 1417) ((emacs (27 1)) (org (9 3 4))) "Contacts management system for Org Mode" single ((:commit . "ae45b9413e24abdc431d12858dced54e0dee6e39") (:authors ("Julien Danjou" . "julien@danjou.info")) (:maintainer "stardiviner" . "numbchild@gmail.com") (:keywords "contacts" "org-mode" "outlines" "hypermedia" "calendar") (:url . "https://repo.or.cz/org-contacts.git"))]) (org-context . [(20220606 1339) nil "Contextual capture and agenda commands for Org-mode" single ((:commit . "47bd45149cb74dab2ebecccfb918f6f8502a4f2c") (:authors ("Sylvain Rousseau ")) (:maintainer "Sylvain Rousseau ") (:keywords "org" "capture" "agenda" "convenience") (:url . "https://github.com/thisirs/org-context"))]) (org-cua-dwim . [(20120203 534) nil "Org-mode and Cua mode compatibility layer" single ((:commit . "a55d6c7009fc0b22f1110c07de629acc955c85e4") (:authors ("Matthew L. Fidler")) (:maintainer "Matthew L. Fidler") (:keywords "org-mode" "cua-mode"))]) (org-custom-cookies . [(20220928 114) ((emacs (25 1)) (org (9 4))) "Custom cookies for org-mode" single ((:commit . "e57e0de5b8200224bf5d44b62481c542986f2f13") (:authors ("Gulshan Singh" . "gsingh2011@gmail.com")) (:maintainer "Gulshan Singh" . "gsingh2011@gmail.com") (:url . "https://github.com/gsingh93/org-custom-cookies"))]) @@ -3569,43 +3590,43 @@ (org-generate . [(20200815 736) ((emacs (26 1)) (org (9 3)) (mustache (0 23))) "Generate template files/folders from org document" single ((:commit . "98825efb73c4537f05f653ce40e639a220d2ee5d") (:authors ("Naoya Yamashita" . "conao3@gmail.com")) (:maintainer "Naoya Yamashita" . "conao3@gmail.com") (:keywords "convenience") (:url . "https://github.com/conao3/org-generate.el"))]) (org-gnome . [(20150614 1457) ((alert (1 2)) (telepathy (0 1)) (gnome-calendar (0 1))) "Orgmode integration with the GNOME desktop" single ((:commit . "1012d47886cfd30eed25b73d9f18e475e0155f88") (:authors ("Nicolas Petton" . "petton.nicolas@gmail.com")) (:maintainer "Nicolas Petton" . "petton.nicolas@gmail.com") (:keywords "org" "gnome"))]) (org-grep . [(20151202 1229) ((cl-lib (0 5))) "Kind of M-x rgrep adapted for Org mode." single ((:commit . "5bdd04c0f53b8a3d656f36ea17bba3df7f0cb684") (:authors ("François Pinard" . "pinard@iro.umontreal.ca")) (:maintainer "François Pinard" . "pinard@iro.umontreal.ca") (:url . "https://github.com/pinard/org-grep"))]) - (org-gtd . [(20230221 1602) ((emacs (27 1)) (org-edna (1 1 2)) (f (0 20 0)) (org (9 6)) (org-agenda-property (1 3 1)) (transient (0 3 7))) "An implementation of GTD." tar ((:commit . "05689a73f9e4841818948e97ecec431b8ca39948") (:authors ("Aldric Giacomoni" . "trevoke@gmail.com")) (:maintainer "Aldric Giacomoni" . "trevoke@gmail.com") (:url . "https://github.com/Trevoke/org-gtd.el"))]) + (org-gtd . [(20230308 1416) ((emacs (27 1)) (org-edna (1 1 2)) (f (0 20 0)) (org (9 6)) (org-agenda-property (1 3 1)) (transient (0 3 7))) "An implementation of GTD." tar ((:commit . "fdc13dc8a5336d933a8a3e8c1c3c4ac6f7838dc2") (:authors ("Aldric Giacomoni" . "trevoke@gmail.com")) (:maintainer "Aldric Giacomoni" . "trevoke@gmail.com") (:url . "https://github.com/Trevoke/org-gtd.el"))]) (org-habit-stats . [(20230210 1859) ((emacs (25 1))) "Display info about habits" single ((:commit . "0e28b1c1ba330d7d07064a7272104f7e793be4ce") (:authors ("ml729")) (:maintainer "ml729") (:keywords "calendar" "org-mode" "org-habit" "habits" "stats" "statistics" "charts" "graphs") (:url . "https://github.com/ml729/org-habit-stats/"))]) (org-hyperscheduler . [(20220704 2140) ((emacs (27 1)) (websocket (1 13)) (log4e (0 3 3))) "UI (web) representation of org-agenda" tar ((:commit . "b7f33e7bf19b7ce7c81dbac4de765a854ee7f52f") (:authors ("Dmitry Markushevich" . "dmitrym@gmail.com")) (:maintainer "Dmitry Markushevich" . "dmitrym@gmail.com") (:keywords "org-mode" "calendar") (:url . "https://github.com/dmitrym0/org-hyperscheduler"))]) - (org-id-cleanup . [(20220228 1653) ((org (9 3)) (dash (2 12)) (emacs (26 3))) "Interactively find, present and maybe clean up unused IDs of org-id" single ((:commit . "b6bf79465cd31d66b547704903b8ba5fcd6dd108") (:authors ("Marc Ihm" . "marc@ihm.name")) (:maintainer "Marc Ihm" . "marc@ihm.name") (:url . "https://github.com/marcIhm/org-id-cleanup"))]) + (org-id-cleanup . [(20230310 1639) ((org (9 3)) (dash (2 12)) (emacs (26 3))) "Interactively find, present and maybe clean up unused IDs of org-id" single ((:commit . "73d3f750d236dd486b8bcc07c88bfda9ce5b384e") (:authors ("Marc Ihm" . "marc@ihm.name")) (:maintainer "Marc Ihm" . "marc@ihm.name") (:url . "https://github.com/marcIhm/org-id-cleanup"))]) (org-if . [(20150920 1513) nil "Interactive Fiction Authoring System for Org-Mode." tar ((:commit . "fab602cc1bbee7a4e99c0083e129219d3f9ed2e8") (:authors ("Philip Woods" . "elzairthesorcerer@gmail.com")) (:maintainer "Philip Woods" . "elzairthesorcerer@gmail.com") (:keywords "if" "org-if" "org org-mode"))]) (org-incoming . [(20230209 1509) ((emacs (24 4)) (dash (2 19 1)) (datetime (0 7 2)) (s (1 13 1))) "Sort incoming PDFs into your org files" single ((:commit . "5c5a5cc034a0b9ed808e5cbbf4876d489a6c7d28") (:authors ("Lukas Barth" . "mail@tinloaf.de")) (:maintainer "Lukas Barth" . "mail@tinloaf.de") (:keywords "files") (:url . "https://github.com/tinloaf/org-incoming"))]) (org-index . [(20230103 1720) ((org (9 3)) (dash (2 12)) (s (1 12)) (emacs (26 3))) "No description available." single ((:commit . "d919b9e2ef8c0f814455b82ffea080e872b89c72") (:authors ("Marc Ihm" . "1@2484.de")) (:maintainer "Marc Ihm" . "1@2484.de") (:url . "https://github.com/marcIhm/org-index"))]) - (org-inline-anim . [(20211101 413) ((emacs (25 3)) (org (9 4))) "Inline playback of animated GIF/PNG for Org" single ((:commit . "1808574ff04ed66b7382247f3f13815fae2a4929") (:authors ("Shigeaki Nishina")) (:maintainer "Shigeaki Nishina") (:keywords "org" "outlines" "hypermedia" "multimedia") (:url . "https://github.com/shg/org-inline-anim.el"))]) + (org-inline-anim . [(20230331 1048) ((emacs (25 3)) (org (9 4))) "Inline playback of animated GIF/PNG for Org" single ((:commit . "9316fe78319fa18c7282993bd547cd33fda1b8ee") (:authors ("Shigeaki Nishina")) (:maintainer "Shigeaki Nishina") (:keywords "org" "outlines" "hypermedia" "multimedia") (:url . "https://github.com/shg/org-inline-anim.el"))]) (org-inline-pdf . [(20221029 751) ((emacs (25 1)) (org (9 4))) "Inline PDF previewing for Org" single ((:commit . "513c0badffcc65d618d43543abd72077e144fd22") (:authors ("Shigeaki Nishina")) (:maintainer "Shigeaki Nishina") (:keywords "org" "outlines" "hypermedia") (:url . "https://github.com/shg/org-inline-pdf.el"))]) (org-iv . [(20171001 1022) ((impatient-mode (1 0 0)) (org (8 0)) (cl-lib (0 5))) "a tool used to view html (in browser) generated by org-file once the org-file changes" tar ((:commit . "7f2bb1b32647655fd9d6684f6f09dcc66b61b0cd") (:authors ("kuangdash" . "kuangdash@163.com")) (:maintainer "kuangdash" . "kuangdash@163.com") (:url . "https://github.com/kuangdash/org-iv"))]) - (org-ivy-search . [(20230220 812) ((emacs (25 1)) (ivy (0 10 0)) (org (0 10 0))) "Full text search for org files powered by ivy" single ((:commit . "e7170ff613734f24edace3309d69e23ef73f4b0f") (:authors ("Huming Chen" . "chenhuming@gmail.com")) (:maintainer "Huming Chen" . "chenhuming@gmail.com") (:keywords "convenience" "tool" "org") (:url . "https://github.com/beacoder/org-ivy-search"))]) - (org-jira . [(20220725 1808) ((emacs (24 5)) (cl-lib (0 5)) (request (0 2 0)) (dash (2 14 1))) "Syncing between Jira and Org-mode." tar ((:commit . "9510f2010750c5c74b6c1be7e06939afd64aa39b") (:maintainer "Matthew Carter" . "m@ahungry.com") (:keywords "ahungry" "jira" "org" "bug" "tracker") (:url . "https://github.com/ahungry/org-jira"))]) - (org-journal . [(20230109 1217) ((emacs (25 1)) (org (9 1))) "a simple org-mode based journaling mode" single ((:commit . "c84f1a771933d662695c20b73832a6415b7d3603") (:authors ("Bastian Bechtold") ("Christian Schwarzgruber")) (:maintainer "Bastian Bechtold") (:url . "http://github.com/bastibe/org-journal"))]) + (org-ivy-search . [(20230222 514) ((emacs (25 1)) (ivy (0 10 0)) (org (0 10 0)) (beacon (1 3 4))) "Full text search for org files powered by ivy" single ((:commit . "7f2afd8c196e3723ae6ac4dd229367ece9acd3bf") (:authors ("Huming Chen" . "chenhuming@gmail.com")) (:maintainer "Huming Chen" . "chenhuming@gmail.com") (:keywords "convenience" "tool" "org") (:url . "https://github.com/beacoder/org-ivy-search"))]) + (org-jira . [(20230329 1527) ((emacs (24 5)) (cl-lib (0 5)) (request (0 2 0)) (dash (2 14 1))) "Syncing between Jira and Org-mode." tar ((:commit . "2ca5df517ca6f47703408b056fde14ac0340cc9e") (:maintainer "Matthew Carter" . "m@ahungry.com") (:keywords "ahungry" "jira" "org" "bug" "tracker") (:url . "https://github.com/ahungry/org-jira"))]) + (org-journal . [(20230309 1240) ((emacs (25 1)) (org (9 1))) "a simple org-mode based journaling mode" single ((:commit . "18df4d5ae5e15580df42562c143d007c6d28d75f") (:authors ("Bastian Bechtold") ("Christian Schwarzgruber")) (:maintainer "Bastian Bechtold") (:url . "http://github.com/bastibe/org-journal"))]) (org-journal-list . [(20190221 2052) ((emacs (25))) "Org mode Journal List" single ((:commit . "2b26d00181bb49bff64b31ad020490acd1b6ae02") (:authors ("Huy Tran" . "huytd189@gmail.com")) (:maintainer "Huy Tran" . "huytd189@gmail.com") (:url . "https://github.com/huytd/org-journal-list"))]) (org-journal-tags . [(20230105 1937) ((emacs (27 1)) (org-journal (2 1 2)) (magit-section (3 3 0)) (transient (0 3 7))) "Tagging and querying system for org-journal" single ((:commit . "dfb3b2d583ceb7ad9fbc8ac23ab6316ae172e9fb") (:authors ("Korytov Pavel" . "thexcloud@gmail.com")) (:maintainer "Korytov Pavel" . "thexcloud@gmail.com") (:url . "https://github.com/SqrtMinusOne/org-journal-tags"))]) (org-kanban . [(20220723 1216) ((s (0)) (dash (2 17 0)) (emacs (24 4)) (org (9 1))) "kanban dynamic block for org-mode." single ((:commit . "e78deb03880ae89d6bceae6563ef1383526233a1") (:authors ("Christian Köstlin" . "christian.koestlin@gmail.com")) (:maintainer "Christian Köstlin" . "christian.koestlin@gmail.com") (:keywords "org-mode" "org" "kanban" "tools") (:url . "http://github.com/gizmomogwai/org-kanban"))]) (org-kindle . [(20220210 1408) ((emacs (25)) (cl-lib (0 5)) (seq (2 20))) "Send org link file to ebook reader." single ((:commit . "fadcfd62e254d0c45e87d63128a82a08ae21869a") (:keywords "org" "link" "ebook" "kindle" "epub" "azw3" "mobi") (:url . "https://repo.or.cz/org-kindle.git"))]) (org-latex-impatient . [(20221111 623) ((emacs (26)) (s (1 8 0)) (posframe (0 8 0)) (org (9 3)) (dash (2 17 0))) "Preview org-latex Fragments Instantly via MathJax" single ((:commit . "031025a8be9bf7255aa047388d027642cd2d6183") (:authors ("Sheng Yang" . "styang@fastmail.com")) (:maintainer "Sheng Yang" . "styang@fastmail.com") (:keywords "tex" "tools") (:url . "https://github.com/yangsheng6810/org-latex-instant-preview"))]) - (org-link-beautify . [(20230221 1311) ((emacs (28 1)) (all-the-icons (5 0 0))) "Beautify Org Links" tar ((:commit . "370535e4259888f686cb6cedcabb79c5b389e6bb") (:keywords "hypermedia") (:url . "https://repo.or.cz/org-link-beautify.git"))]) + (org-link-beautify . [(20230407 916) ((emacs (28 1)) (all-the-icons (5 0 0))) "Beautify Org Links" tar ((:commit . "3d36a4ae5ade049d03b88f635e4b7d1097dafc91") (:keywords "hypermedia") (:url . "https://repo.or.cz/org-link-beautify.git"))]) (org-link-travis . [(20140405 2327) ((org (7))) "Insert/Export the link of Travis CI on org-mode" single ((:commit . "596615ad8373d9090bd4138da683524f0ad0bda5") (:authors ("Hiroaki Otsu" . "ootsuhiroaki@gmail.com")) (:maintainer "Hiroaki Otsu" . "ootsuhiroaki@gmail.com") (:keywords "org") (:url . "https://github.com/aki2o/org-link-travis"))]) (org-linkotron . [(20200112 2235) ((emacs (26 1)) (org (9 3))) "Org-mode link selector" tar ((:commit . "d0adc5247b205bc73d2f1a83d4a512d2be541eb5") (:authors ("Per Weijnitz" . "per.weijnitz@gmail.com")) (:maintainer "Per Weijnitz" . "per.weijnitz@gmail.com") (:keywords "hypermedia" "org") (:url . "https://gitlab.com/perweij/org-linkotron"))]) (org-listcruncher . [(20210706 1741) ((seq (2 3)) (emacs (26 1))) "Planning tool - Parse Org mode lists into table" single ((:commit . "075e0e6d36eb50406a608bc8a2f0dd359ec63938") (:authors ("Derek Feichtinger" . "dfeich@gmail.com")) (:maintainer "Derek Feichtinger" . "dfeich@gmail.com") (:keywords "convenience") (:url . "https://github.com/dfeich/org-listcruncher"))]) - (org-mac-link . [(20220616 2340) ((emacs (27 1))) "Insert org-mode links to items selected in various Mac apps" single ((:commit . "0b18c1d070b9601cc65c40e902169e367e4348c9") (:authors ("Anthony Lander" . "anthony.lander@gmail.com") ("John Wiegley" . "johnw@gnu.org") ("Christopher Suckling ") ("Daniil Frumin" . "difrumin@gmail.com") ("Alan Schmitt" . "alan.schmitt@polytechnique.org") ("Mike McLean" . "mike.mclean@pobox.com")) (:maintainer "Aimé Bertrand" . "aime.bertrand@macowners.club") (:keywords "files" "wp" "url" "org") (:url . "https://gitlab.com/aimebertrand/org-mac-link"))]) + (org-mac-link . [(20230222 2228) ((emacs (27 1))) "Insert org-mode links to items selected in various Mac apps" single ((:commit . "16734797b56b5bd1f49929b59f7cd8fcdcd268e0") (:authors ("Anthony Lander" . "anthony.lander@gmail.com") ("John Wiegley" . "johnw@gnu.org") ("Christopher Suckling ") ("Daniil Frumin" . "difrumin@gmail.com") ("Alan Schmitt" . "alan.schmitt@polytechnique.org") ("Mike McLean" . "mike.mclean@pobox.com")) (:maintainer "Aimé Bertrand" . "aime.bertrand@macowners.club") (:keywords "files" "wp" "url" "org") (:url . "https://gitlab.com/aimebertrand/org-mac-link"))]) (org-make-toc . [(20200409 1436) ((emacs (26 1)) (dash (2 12)) (s (1 10 0)) (org (9 0))) "Automatic tables of contents for Org files" single ((:commit . "43d4a2490a048b01ca5a6f44c5b4f24a458dfc95") (:authors ("Adam Porter" . "adam@alphapapa.net")) (:maintainer "Adam Porter" . "adam@alphapapa.net") (:keywords "org" "convenience") (:url . "http://github.com/alphapapa/org-make-toc"))]) - (org-mime . [(20221003 105) ((emacs (25 1))) "org html export for text/html MIME emails" single ((:commit . "cc00afcf0291633324364c1c83bfe2833cfdc1bf") (:authors ("Eric Schulte")) (:maintainer "Chen Bin" . "chenbin.sh@gmail.com") (:keywords "mime" "mail" "email" "html") (:url . "http://github.com/org-mime/org-mime"))]) + (org-mime . [(20230321 2341) ((emacs (25 1))) "org html export for text/html MIME emails" single ((:commit . "d368bd4119bfcf2997a6a23bbf5f41e043164d29") (:authors ("Eric Schulte")) (:maintainer "Chen Bin" . "chenbin.sh@gmail.com") (:keywords "mime" "mail" "email" "html") (:url . "http://github.com/org-mime/org-mime"))]) (org-mind-map . [(20180826 2340) ((emacs (24)) (dash (1 8 0)) (org (8 2 10))) "Creates a directed graph from org-mode files" single ((:commit . "41df4b2e30455494f1848b4e06cc9208aa9e902b") (:authors ("Ted Wiles" . "theodore.wiles@gmail.com")) (:maintainer "Ted Wiles" . "theodore.wiles@gmail.com") (:keywords "orgmode" "extensions" "graphviz" "dot") (:url . "https://github.com/theodorewiles/org-mind-map"))]) - (org-ml . [(20220711 1528) ((emacs (27 1)) (org (9 3)) (dash (2 17)) (s (1 12))) "Functional Org Mode API" tar ((:commit . "385e3bee497f858705144d7ab5e6570d31d3ffe8") (:authors ("Nathan Dwarshuis" . "ndwar@yavin4.ch")) (:maintainer "Nathan Dwarshuis" . "ndwar@yavin4.ch") (:keywords "org-mode" "outlines") (:url . "https://github.com/ndwarshuis/org-ml"))]) + (org-ml . [(20230401 230) ((emacs (27 1)) (org (9 3)) (dash (2 17)) (s (1 12))) "Functional Org Mode API" tar ((:commit . "d1a942df35c0b37413ac335f89651cf46688df79") (:authors ("Nathan Dwarshuis" . "ndwar@yavin4.ch")) (:maintainer "Nathan Dwarshuis" . "ndwar@yavin4.ch") (:keywords "org-mode" "outlines") (:url . "https://github.com/ndwarshuis/org-ml"))]) (org-mobile-sync . [(20180606 524) ((emacs (24 3 50)) (org (8 0))) "automatically sync org-mobile on changes" single ((:commit . "06764b943a528827df1e2acc6bc7806cc2c1351f") (:authors ("steckerhalter")) (:maintainer "steckerhalter") (:keywords "org-mode" "org" "mobile" "sync" "todo") (:url . "https://framagit.org/steckerhalter/org-mobile-sync"))]) - (org-modern . [(20230215 718) ((emacs (27 1))) "Modern looks for Org" single ((:commit . "42fdbd2d27f5a8652593577a200eeea96555d018") (:authors ("Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainer "Daniel Mendler" . "mail@daniel-mendler.de") (:url . "https://github.com/minad/org-modern"))]) + (org-modern . [(20230312 852) ((emacs (27 1)) (compat (29 1 4 0))) "Modern looks for Org" single ((:commit . "b614ad31d72c49f9eb29d3836995fd7fb0d1fd4a") (:authors ("Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainer "Daniel Mendler" . "mail@daniel-mendler.de") (:url . "https://github.com/minad/org-modern"))]) (org-movies . [(20210920 101) ((emacs (26 1)) (org (9 0)) (request (0 3 0))) "Manage watchlist with Org mode" single ((:commit . "e96fecaffa2924de64a507aa31d2934e667ee1ea") (:authors ("Anh T Nguyen")) (:maintainer "Anh T Nguyen") (:keywords "hypermedia" "outlines" "org") (:url . "https://github.com/teeann/org-movies"))]) - (org-mpv-notes . [(20221202 1657) ((emacs (27 1)) (mpv (0 2 0))) "Take notes in org mode while watching videos in mpv" single ((:commit . "8c123996044cfb87101da6c5f16634188f019cca") (:authors ("Bibek Panthi" . "bpanthi977@gmail.com")) (:maintainer "Bibek Panthi" . "bpanthi977@gmail.com") (:url . "https://github.com/bpanthi977/org-mpv-notes"))]) + (org-mpv-notes . [(20230406 359) ((emacs (27 1)) (mpv (0 2 0))) "Take notes in org mode while watching videos in mpv" single ((:commit . "c437a51aef646839437d6eb699ba86bc530b52b7") (:authors ("Bibek Panthi" . "bpanthi977@gmail.com")) (:maintainer "Bibek Panthi" . "bpanthi977@gmail.com") (:url . "https://github.com/bpanthi977/org-mpv-notes"))]) (org-mru-clock . [(20230104 1922) ((emacs (26 1))) "Clock in/out of tasks with completion and persistent history" single ((:commit . "be90bc9084b384d8a728d68f69da09171ca26d3c") (:authors ("Kevin Brubeck Unhammer" . "unhammer@fsfe.org")) (:maintainer "Kevin Brubeck Unhammer" . "unhammer@fsfe.org") (:keywords "convenience" "calendar") (:url . "https://github.com/unhammer/org-mru-clock"))]) (org-msg . [(20230127 520) ((emacs (24 4)) (htmlize (1 54))) "Org mode to send and reply to email in HTML." single ((:commit . "7b1dfb96d558f6e5626e96d4f4a5150d55cb7eb2") (:authors ("Jérémy Compostella" . "jeremy.compostella@gmail.com")) (:maintainer "Jérémy Compostella" . "jeremy.compostella@gmail.com") (:keywords "extensions" "mail") (:url . "https://github.com/jeremy-compostella/org-msg"))]) (org-multi-wiki . [(20210324 1820) ((emacs (26 1)) (dash (2 12)) (s (1 12)) (org-ql (0 5)) (org (9 3))) "Multiple wikis based on Org mode" single ((:commit . "bf8039aadddaf02569fab473f766071ef7e63563") (:authors ("Akira Komamura" . "akira.komamura@gmail.com")) (:maintainer "Akira Komamura" . "akira.komamura@gmail.com") (:keywords "org" "outlines" "files") (:url . "https://github.com/akirak/org-multi-wiki"))]) (org-multiple-keymap . [(20191017 1920) ((org (8 2 4)) (emacs (24)) (cl-lib (0 5))) "Set keymap to elements, such as timestamp and priority." single ((:commit . "4eb8aa0aada012b2346cc7f0c55e07783141a2c3") (:authors ("myuhe ")) (:maintainer "myuhe") (:keywords "convenience" "org-mode") (:url . "https://github.com/myuhe/org-multiple-keymap.el"))]) (org-notebook . [(20170322 452) ((emacs (24)) (org (8)) (cl-lib (0 5))) "Ease the use of org-mode as a notebook" single ((:commit . "d90c4aeca2442161e6dd89de175561af85aace03") (:authors ("Paul Elder" . "paul.elder@amanokami.net")) (:maintainer "Paul Elder" . "paul.elder@amanokami.net") (:keywords "convenience" "tools"))]) - (org-noter . [(20191020 1212) ((emacs (24 4)) (cl-lib (0 6)) (org (9 0))) "A synchronized, Org-mode, document annotator" single ((:commit . "d051a5909878e2214422fd275968ab4d7ef9bcab") (:authors (nil . "Gonçalo Santos (aka. weirdNox@GitHub)")) (:maintainer nil . "Gonçalo Santos (aka. weirdNox@GitHub)") (:keywords "lisp" "pdf" "interleave" "annotate" "external" "sync" "notes" "documents" "org-mode") (:url . "https://github.com/weirdNox/org-noter"))]) + (org-noter . [(20230404 307) ((emacs (24 4)) (cl-lib (0 6)) (org (9 0))) "A synchronized, Org-mode, document annotator" tar ((:commit . "a24ba82f5c9ad2f2a93bd71ab60b78547a94463d") (:authors ("Gonçalo Santos (github.com/weirdNox)" . "in@bsentia") (" Maintainer Dmitry M" . "dmitrym@gmail.com")) (:maintainer "Peter Mao" . "peter.mao@gmail.com") (:keywords "lisp" "pdf" "interleave" "annotate" "external" "sync" "notes" "documents" "org-mode") (:url . "https://github.com/org-noter/org-noter"))]) (org-noter-pdftools . [(20220320 300) ((emacs (26 1)) (org (9 4)) (pdf-tools (0 8)) (org-pdftools (1 0)) (org-noter (1 4 1))) "Integration between org-pdftools and org-noter" single ((:commit . "c88130c90aac5a4759849df86fb1829db183bed4") (:authors ("Alexander Fu Xi" . "fuxialexander@gmail.com")) (:maintainer "Alexander Fu Xi" . "fuxialexnader@gmail.com") (:keywords "convenience") (:url . "https://github.com/fuxialexander/org-pdftools"))]) (org-notifications . [(20210918 1827) ((emacs (25 1)) (org (9 0)) (sound-wav (0 2)) (alert (1 2)) (seq (2 21))) "Creates notifications for org-mode entries" tar ((:commit . "b8032f8adfbeb328962a5657c6dd173e64cc76e5") (:authors ("doppelc")) (:maintainer "doppelc") (:keywords "outlines") (:url . "https://github.com/doppelc/org-notifications"))]) (org-octopress . [(20170821 415) ((org (9 0)) (orglue (0 1)) (ctable (0 1 1))) "Compose octopress articles using org-mode." tar ((:commit . "38598ef98d04076a8eb78d549907ddfde8d3a652") (:authors ("Yoshinari Nomura" . "nom@quickhack.net")) (:maintainer "Yoshinari Nomura" . "nom@quickhack.net") (:keywords "org" "jekyll" "octopress" "blog"))]) @@ -3625,30 +3646,30 @@ (org-projectile . [(20220114 730) ((projectile (0 11 0)) (dash (2 10 0)) (emacs (24)) (s (1 9 0)) (org-category-capture (0 0 0))) "Repository todo management for org-mode" single ((:commit . "bc5a2401b456c42c4346d59fa77d633770b6efea") (:authors ("Ivan Malison" . "IvanMalison@gmail.com")) (:maintainer "Ivan Malison" . "IvanMalison@gmail.com") (:keywords "org-mode" "projectile" "todo" "tools" "outlines") (:url . "https://github.com/IvanMalison/org-projectile"))]) (org-projectile-helm . [(20180601 1822) ((org-projectile (1 0 0)) (helm (2 3 1)) (emacs (25))) "helm functions for org-projectile" single ((:commit . "674e3cdda4a3ea4bdcc369dae032d49dfb5c5765") (:authors ("Ivan Malison" . "IvanMalison@gmail.com")) (:maintainer "Ivan Malison" . "IvanMalison@gmail.com") (:keywords "org" "projectile" "todo" "helm" "outlines") (:url . "https://github.com/IvanMalison/org-projectile"))]) (org-protocol-jekyll . [(20170328 1639) ((cl-lib (0 5))) "Jekyll's handler for org-protocol" single ((:commit . "dec064a42d6dfe81dfde7ba59ece5ca103ac6334") (:authors ("Vladimir S. Ivanov" . "ivvl82@gmail.com")) (:maintainer "Vladimir S. Ivanov" . "ivvl82@gmail.com"))]) - (org-ql . [(20221225 2351) ((emacs (26 1)) (dash (2 18 1)) (f (0 17 2)) (map (2 1)) (org (9 0)) (org-super-agenda (1 2)) (ov (1 0 6)) (peg (1 0 1)) (s (1 12 0)) (transient (0 1)) (ts (0 2 -1))) "Org Query Language, search command, and agenda-like view" tar ((:commit . "29533525c39e0e243912bb3c807412e4bc3e804e") (:authors ("Adam Porter" . "adam@alphapapa.net")) (:maintainer "Adam Porter" . "adam@alphapapa.net") (:keywords "hypermedia" "outlines" "org" "agenda") (:url . "https://github.com/alphapapa/org-ql"))]) + (org-ql . [(20230312 1433) ((emacs (26 1)) (dash (2 18 1)) (f (0 17 2)) (map (2 1)) (org (9 0)) (org-super-agenda (1 2)) (ov (1 0 6)) (peg (1 0 1)) (s (1 12 0)) (transient (0 1)) (ts (0 2 -1))) "Org Query Language, search command, and agenda-like view" tar ((:commit . "4c1a4b169f54d37ce541902c0ae5043759ef9d9b") (:authors ("Adam Porter" . "adam@alphapapa.net")) (:maintainer "Adam Porter" . "adam@alphapapa.net") (:keywords "hypermedia" "outlines" "org" "agenda") (:url . "https://github.com/alphapapa/org-ql"))]) (org-radiobutton . [(20210519 1225) ((dash (2 13 0)) (emacs (24))) "Radiobutton for org-mode lists." single ((:commit . "4ba26bbd26102c45c234bc6ce9a8e9c655c6a0a2") (:authors ("Matúš Goljer" . "matus.goljer@gmail.com")) (:maintainer "Matúš Goljer" . "matus.goljer@gmail.com") (:keywords "outlines") (:url . "https://github.com/Fuco1/org-radiobutton"))]) (org-rainbow-tags . [(20221114 1307) ((emacs (28 1))) "Colorize org tags automatically" single ((:commit . "6001ec9345bea4e60b2178940ef197c055d5a5d8") (:authors ("Furkan Karataş" . "furkan.karatas02@gmail.com")) (:maintainer "Furkan Karataş" . "furkan.karatas02@gmail.com") (:keywords "faces" "outlines") (:url . "https://github.com/KaratasFurkan/org-rainbow-tags"))]) (org-random-todo . [(20190214 2057) ((emacs (24 3)) (alert (1 3))) "show a random TODO (with alert) every so often" single ((:commit . "4f7677af740e8f3f7cfaf630ae2e594a125af760") (:authors ("Kevin Brubeck Unhammer" . "unhammer@fsfe.org")) (:maintainer "Kevin Brubeck Unhammer" . "unhammer@fsfe.org") (:keywords "org" "todo" "notification" "calendar") (:url . "https://github.com/unhammer/org-random-todo"))]) (org-randomnote . [(20200110 1407) ((f (0 19 0)) (dash (2 12 0)) (org (0))) "Find a random note in your Org-Mode files" single ((:commit . "ea8cf4385970637efffff8f79e14576ba6d7ad13") (:authors ("Michael Fogleman" . "michaelwfogleman@gmail.com")) (:maintainer "Michael Fogleman" . "michaelwfogleman@gmail.com") (:url . "http://github.com/mwfogleman/org-randomnote"))]) - (org-re-reveal . [(20230220 848) ((emacs (24 4)) (org (8 3)) (htmlize (1 34))) "Org export to reveal.js presentations" tar ((:commit . "611d6bd1f66eedf5ee2590426990efd4ca990076") (:keywords "tools" "outlines" "hypermedia" "slideshow" "presentation" "oer") (:url . "https://gitlab.com/oer/org-re-reveal"))]) + (org-re-reveal . [(20230228 1655) ((emacs (24 4)) (org (8 3)) (htmlize (1 34))) "Org export to reveal.js presentations" tar ((:commit . "bf4e23e2ce9109d35957c9f42fafe9c9edb6bf4a") (:keywords "tools" "outlines" "hypermedia" "slideshow" "presentation" "oer") (:url . "https://gitlab.com/oer/org-re-reveal"))]) (org-re-reveal-citeproc . [(20211028 1328) ((emacs (25 1)) (org (9 5)) (citeproc (0 9)) (org-re-reveal (3 0 0))) "Citations and bibliography for org-re-reveal" tar ((:commit . "faa9ea387917b20bd1499ad90199ff3d417c00c2") (:authors ("Jens Lechtenbörger")) (:maintainer "Jens Lechtenbörger") (:keywords "hypermedia" "tools" "slideshow" "presentation" "bibliography") (:url . "https://gitlab.com/oer/org-re-reveal-citeproc"))]) (org-re-reveal-ref . [(20211029 551) ((emacs (25 1)) (org-ref (1 1 1)) (org-re-reveal (0 9 3))) "Citations and bibliography for org-re-reveal" tar ((:commit . "ea9661864d5fbef87b12b78f516c13a40c683f24") (:authors ("Jens Lechtenbörger")) (:maintainer "Jens Lechtenbörger") (:keywords "hypermedia" "tools" "slideshow" "presentation" "bibliography") (:url . "https://gitlab.com/oer/org-re-reveal-ref"))]) (org-recent-headings . [(20211011 1519) ((emacs (26 1)) (org (9 0 5)) (dash (2 18 0)) (frecency (0 1)) (s (1 12 0))) "Jump to recently used Org headings" single ((:commit . "97418d581ea030f0718794e50b005e9bae44582e") (:authors ("Adam Porter" . "adam@alphapapa.net")) (:maintainer "Adam Porter" . "adam@alphapapa.net") (:keywords "hypermedia" "outlines" "org") (:url . "http://github.com/alphapapa/org-recent-headings"))]) (org-recur . [(20230124 1532) ((emacs (24 1)) (org (9 0)) (dash (2 7 0))) "Recurring org-mode tasks" single ((:commit . "628099883a63d219f76cd9631cc914fe6ec8a3e3") (:authors ("Marcin Swieczkowski" . "marcin.swieczkowski@gmail.com")) (:maintainer "Marcin Swieczkowski" . "marcin.swieczkowski@gmail.com") (:url . "https://github.com/mrcnski/org-recur"))]) (org-redmine . [(20160711 1114) nil "Redmine tools using Emacs OrgMode" single ((:commit . "a526c3ac802634486bf10de9c2283ccb1a30ec8d") (:authors ("Wataru MIYAGUNI" . "gonngo@gmail.com")) (:maintainer "Wataru MIYAGUNI" . "gonngo@gmail.com") (:keywords "redmine" "org") (:url . "https://github.com/gongo/org-redmine"))]) - (org-ref . [(20230131 1743) ((org (9 4)) (dash (0)) (s (0)) (f (0)) (htmlize (0)) (hydra (0)) (avy (0)) (parsebib (0)) (bibtex-completion (0)) (citeproc (0)) (ox-pandoc (0))) "citations, cross-references and bibliographies in org-mode" tar ((:commit . "4c691f7b4cafbd9bf8c9608fe9d590f7c4894d67") (:authors ("John Kitchin" . "jkitchin@andrew.cmu.edu")) (:maintainer "John Kitchin" . "jkitchin@andrew.cmu.edu") (:keywords "org-mode" "cite" "ref" "label") (:url . "https://github.com/jkitchin/org-ref"))]) + (org-ref . [(20230312 1711) ((org (9 4)) (dash (0)) (s (0)) (f (0)) (htmlize (0)) (hydra (0)) (avy (0)) (parsebib (0)) (bibtex-completion (0)) (citeproc (0)) (ox-pandoc (0))) "citations, cross-references and bibliographies in org-mode" tar ((:commit . "1af17e6df1a8ad967352edff0223cd8d3cf55836") (:authors ("John Kitchin" . "jkitchin@andrew.cmu.edu")) (:maintainer "John Kitchin" . "jkitchin@andrew.cmu.edu") (:keywords "org-mode" "cite" "ref" "label") (:url . "https://github.com/jkitchin/org-ref"))]) (org-ref-prettify . [(20220507 649) ((emacs (24 3)) (org-ref (3 0)) (bibtex-completion (1 0 0))) "Prettify org-ref citation links" single ((:commit . "0ec3b6e398ee117c8b8a787a0422b95d9e95f7bb") (:authors ("Alex Kost" . "alezost@gmail.com") ("Vitus Schäfftlein" . "vitusschaefftlein@live.de")) (:maintainer "Alex Kost" . "alezost@gmail.com") (:keywords "convenience") (:url . "https://github.com/alezost/org-ref-prettify.el"))]) (org-repo-todo . [(20171228 119) nil "Simple repository todo management with org-mode" single ((:commit . "f73ebd91399c5760ad52c6ad9033de1066042003") (:authors ("justin talbott" . "justin@waymondo.com")) (:maintainer "justin talbott" . "justin@waymondo.com") (:keywords "convenience") (:url . "https://github.com/waymondo/org-repo-todo"))]) (org-reverse-datetree . [(20221203 259) ((emacs (28 1)) (dash (2 19)) (org (9 5))) "Create reverse date trees in org-mode" single ((:commit . "fca95cd22ed29653f3217034c71ec0ab0a7c7734") (:authors ("Akira Komamura" . "akira.komamura@gmail.com")) (:maintainer "Akira Komamura" . "akira.komamura@gmail.com") (:keywords "outlines") (:url . "https://github.com/akirak/org-reverse-datetree"))]) (org-review . [(20230119 1706) nil "schedule reviews for Org entries" single ((:commit . "77211e40db8a9558b866f5660c7127922b459e6c") (:authors ("Alan Schmitt" . "alan.schmitt@polytechnique.org")) (:maintainer "Alan Schmitt" . "alan.schmitt@polytechnique.org") (:keywords "org" "review") (:url . "https://github.com/brabalan/org-review"))]) (org-rich-yank . [(20220227 2154) ((emacs (24 4))) "Paste with org-mode markup and link to source" single ((:commit . "4bcd030f0d736d77c647955739b61fae541417e9") (:authors ("Kevin Brubeck Unhammer" . "unhammer@fsfe.org")) (:maintainer "Kevin Brubeck Unhammer" . "unhammer@fsfe.org") (:keywords "convenience" "hypermedia" "org") (:url . "https://github.com/unhammer/org-rich-yank"))]) - (org-roam . [(20221231 2122) ((emacs (26 1)) (dash (2 13)) (org (9 4)) (emacsql (3 0 0)) (emacsql-sqlite (1 0 0)) (magit-section (3 0 0))) "A database abstraction layer for Org-mode" tar ((:commit . "74422df546a515bc984c2f3d3a681c09d6f43916") (:authors ("Jethro Kuan" . "jethrokuan95@gmail.com")) (:maintainer "Jethro Kuan" . "jethrokuan95@gmail.com") (:keywords "org-mode" "roam" "convenience") (:url . "https://github.com/org-roam/org-roam"))]) + (org-roam . [(20230307 1721) ((emacs (26 1)) (dash (2 13)) (org (9 4)) (emacsql (20230228)) (magit-section (3 0 0))) "A database abstraction layer for Org-mode" tar ((:commit . "5c06471c3a11348342719fd9011486455adeb701") (:authors ("Jethro Kuan" . "jethrokuan95@gmail.com")) (:maintainer "Jethro Kuan" . "jethrokuan95@gmail.com") (:keywords "org-mode" "roam" "convenience") (:url . "https://github.com/org-roam/org-roam"))]) (org-roam-bibtex . [(20230201 1834) ((emacs (27 1)) (org-roam (2 2 0)) (bibtex-completion (2 0 0))) "Org Roam meets BibTeX" tar ((:commit . "c87acc2d5685ba2608e2bd1f128e723f1de9d837") (:authors ("Mykhailo Shevchuk" . "mail@mshevchuk.com") ("Leo Vivier" . "leo.vivier+dev@gmail.com")) (:maintainer "Mykhailo Shevchuk" . "mail@mshevchuk.com") (:keywords "bib" "hypermedia" "outlines" "wp") (:url . "https://github.com/org-roam/org-roam-bibtex"))]) (org-roam-timestamps . [(20221104 1544) ((emacs (26 1)) (org-roam (2 0 0))) "Keep track of modification times for org-roam" single ((:commit . "c4ff1e2f5b0905b5caa917249aab56ddc1de1ab3") (:authors ("Thomas F. K. Jorna ")) (:maintainer "Thomas F. K. Jorna" . "jorna@jtrialerror.com") (:keywords "calendar" "outlines" "files") (:url . "https://github.com/ThomasFKJorna/org-roam-timestamps/"))]) (org-roam-ui . [(20221105 1040) ((emacs (27 1)) (org-roam (2 0 0)) (simple-httpd (20191103 1446)) (websocket (1 13))) "User Interface for Org-roam" tar ((:commit . "5ac74960231db0bf7783c2ba7a19a60f582e91ab") (:authors ("Kirill Rogovoy, Thomas Jorna")) (:maintainer "Kirill Rogovoy, Thomas Jorna") (:keywords "files" "outlines") (:url . "https://github.com/org-roam/org-roam-ui"))]) (org-ros . [(20220320 1705) ((emacs (24 1))) "Rahul's Org-Mode Screenshot" single ((:commit . "70e0f33ee027ca1dce68351ad14a9e47a452fc17") (:authors ("Rahul Martim Juliato" . "rahul.juliato@gmail.com")) (:maintainer "Rahul Martim Juliato" . "rahul.juliato@gmail.com") (:url . "https://github.com/LionyxML/ros"))]) (org-rtm . [(20160214 1236) ((rtm (0 1))) "Simple import/export from rememberthemilk to org-mode" single ((:commit . "adc42ad1fbe92ab447ccc9553780f4456f2508d2") (:authors ("Philipp Middendorf" . "pmidden@secure.mailbox.org")) (:maintainer "Philipp Middendorf" . "pmidden@secure.mailbox.org") (:keywords "outlines" "data") (:url . "https://github.com/pmiddend/org-rtm"))]) - (org-runbook . [(20230120 140) nil "Org mode for runbooks" tar ((:commit . "be8218d66493c122a60049ff5e6bd41abfaabbd8") (:authors ("Tyler Dodge")) (:maintainer "Tyler Dodge") (:keywords "convenience" "processes" "terminals" "files") (:url . "https://github.com/tyler-dodge/org-runbook"))]) + (org-runbook . [(20230330 325) ((emacs (26 1)) (seq (2 3)) (f (0 20 0)) (s (1 12 0)) (dash (2 17 0)) (mustache (0 24)) (ht (0 9)) (ivy (0 8 0))) "Org mode for runbooks" tar ((:commit . "3de6e4e31cd240a2ba128287a3d1bc550c253144") (:authors ("Tyler Dodge")) (:maintainer "Tyler Dodge") (:keywords "convenience" "processes" "terminals" "files") (:url . "https://github.com/tyler-dodge/org-runbook"))]) (org-scrum . [(20200131 1129) ((emacs (24 5)) (org (8 2)) (seq (2 3)) (cl-lib (1 0))) "org mode extensions for scrum planning and reporting" single ((:commit . "a383348ea80c2459bfb96fa0652b98f0059bd311") (:authors ("Ian Martins" . "ianxm@jhu.edu")) (:maintainer "Ian Martins" . "ianxm@jhu.edu") (:url . "https://github.com/ianxm/emacs-scrum"))]) (org-seek . [(20161217 502) ((emacs (24 3)) (ag (0 48))) "Searching Org-mode files with search tools." single ((:commit . "1f51e6634e3b9a6a29d335d0d14370a6ffef2265") (:authors ("stardiviner" . "numbchild@gmail.com")) (:maintainer "stardiviner" . "numbchild@gmail.com") (:keywords "org" "search" "ag" "pt") (:url . "https://github.com/stardiviner/org-seek.el"))]) (org-shoplist . [(20210629 2157) ((emacs (25))) "Eat the world" single ((:commit . "71ea7643e66c97d21df49fb8b600578ca0464f83") (:authors ("lordnik22")) (:maintainer "lordnik22") (:keywords "extensions" "matching") (:url . "https://github.com/lordnik22"))]) @@ -3667,7 +3688,7 @@ (org-table-color . [(20220311 1927) ((emacs (26 1))) "Add color to your org-mode table cells" single ((:commit . "2022f301ef323953c3a0e087a1b601da85e06da1") (:authors ("Colin Woodbury" . "colin@fosskers.ca")) (:maintainer "Colin Woodbury" . "colin@fosskers.ca") (:keywords "data" "faces" "lisp") (:url . "https://github.com/fosskers/org-table-color"))]) (org-table-comment . [(20120209 1851) nil "Org table comment modes." single ((:commit . "33b9966c33ecbc3e27cca67c2f2cdea04364d74e") (:authors ("Matthew L. Fidler ")) (:maintainer "Matthew L. Fidler") (:keywords "org-mode" "orgtbl") (:url . "http://github.com/mlf176f2/org-table-comment.el"))]) (org-table-sticky-header . [(20190924 506) ((org (8 2 10)) (emacs (24 4))) "Sticky header for org-mode tables" single ((:commit . "b65442857128ab04724aaa301e60aa874a31a798") (:authors ("Junpeng Qiu" . "qjpchmail@gmail.com")) (:maintainer "Junpeng Qiu" . "qjpchmail@gmail.com") (:keywords "extensions"))]) - (org-tag-beautify . [(20221211 941) ((emacs (26 1)) (org-pretty-tags (0 2 2)) (all-the-icons (5 0 0))) "Beautify Org mode tags" single ((:commit . "5eb75d86c143c1801c71b54fe0da832affc3adc3") (:keywords "hypermedia") (:url . "https://repo.or.cz/org-tag-beautify.git"))]) + (org-tag-beautify . [(20230402 554) ((emacs (26 1)) (org-pretty-tags (0 2 2)) (all-the-icons (5 0 0))) "Beautify Org mode tags" single ((:commit . "a9ec18a5b8132178b1c9f5a9e00680f4af295ba3") (:keywords "hypermedia") (:url . "https://repo.or.cz/org-tag-beautify.git"))]) (org-tagged . [(20220926 2048) ((s (1 13 0)) (dash (2 19 1)) (emacs (28 1)) (org (9 5 2))) "Dynamic block for tagged org-mode todos" single ((:commit . "4b0174473772fca976426e982bb3f4a3037c1e37") (:authors ("Christian Köstlin" . "christian.koestlin@gmail.com")) (:maintainer "Christian Köstlin" . "christian.koestlin@gmail.com") (:keywords "org-mode" "org" "gtd" "tools") (:url . "http://github.com/gizmomogwai/org-tagged"))]) (org-tanglesync . [(20200127 1616) ((emacs (24 4))) "Syncing org src blocks with tangled external files" single ((:commit . "31aa5502d1d4f8b032807949908c016b00556684") (:authors ("Mehmet Tekman")) (:maintainer "Mehmet Tekman") (:keywords "outlines") (:url . "https://github.com/mtekman/org-tanglesync.el"))]) (org-tfl . [(20170923 1218) ((org (0 16 2)) (cl-lib (0 5)) (emacs (24 1))) "Transport for London meets Orgmode" tar ((:commit . "f0d7d39106a1de5457f5160cddd98ab892b61066") (:authors ("storax (David Zuber), ")) (:maintainer "storax (David Zuber), ") (:keywords "org" "tfl") (:url . "https://github.com/storax/org-tfl"))]) @@ -3677,7 +3698,7 @@ (org-toodledo . [(20150301 1113) ((request-deferred (0 2 0)) (emacs (24)) (cl-lib (0 5))) "Toodledo integration for Emacs Org mode" tar ((:commit . "01b53b637f304b89cd3bf2d29009b5ed6ad9466d") (:authors ("Christopher J. White" . "emacs@grierwhite.com")) (:maintainer "Christopher J. White" . "emacs@grierwhite.com") (:keywords "outlines" "data"))]) (org-tracktable . [(20161118 1329) ((emacs (24)) (cl-lib (0 5))) "Track your writing progress in an org-table" single ((:commit . "8e0e60a582a034bd66d5efb72d513140b7d4d90a") (:authors ("tty-tourist" . "andreasrasholm@protonmail.com")) (:maintainer "tty-tourist" . "andreasrasholm@protonmail.com") (:keywords "org" "writing") (:url . "https://github.com/tty-tourist/org-tracktable"))]) (org-transform-tree-table . [(20200413 1959) ((dash (2 10 0)) (s (1 3 0))) "Transform org-mode tree with properties to a table, and the other way around" single ((:commit . "d84e7fb87bf2d5fc2be252500de0cddf20facf4f") (:authors (nil . "Johan Lindstrom ")) (:maintainer nil . "Johan Lindstrom ") (:keywords "org-mode" "table" "org-table" "tree" "csv" "convert") (:url . "https://github.com/jplindstrom/emacs-org-transform-tree-table"))]) - (org-tree-slide . [(20221016 1623) ((emacs (24 4))) "A presentation tool for org-mode" single ((:commit . "d6529bc2df727d09014e0e56abf4f15a8e8fc20f") (:authors ("Takaaki ISHIKAWA ")) (:maintainer "Takaaki ISHIKAWA ") (:keywords "convenience" "org-mode" "presentation" "narrowing") (:url . "https://github.com/takaxp/org-tree-slide"))]) + (org-tree-slide . [(20230305 441) ((emacs (25 2))) "A presentation tool for org-mode" tar ((:commit . "07906356f0b8d8ac51645b0994b8108deb53003d") (:authors ("Takaaki ISHIKAWA ")) (:maintainer "Takaaki ISHIKAWA ") (:keywords "convenience" "org-mode" "presentation" "narrowing") (:url . "https://github.com/takaxp/org-tree-slide"))]) (org-tree-slide-pauses . [(20201215 146) ((emacs (24 5)) (org-tree-slide (2 8 4))) "Bring the pause command from Beamer to org-tree-slide" single ((:commit . "f02af7102e9ecef7c3dac0d376d85bbb8c4de4cc") (:authors ("cnngimenez")) (:maintainer "cnngimenez") (:keywords "convenience" "org-mode" "presentation") (:url . "https://github.com/cnngimenez/org-tree-slide-pauses"))]) (org-treescope . [(20200503 1609) ((emacs (24 3)) (org (9 2 3)) (org-ql (0 5 -1)) (dash (2 17 0))) "Time scoping sparse trees within org" tar ((:commit . "a7c386ff134c71fd4f1f042e320751f077d57ddb") (:authors ("Mehmet Tekman")) (:maintainer "Mehmet Tekman") (:keywords "outlines") (:url . "https://github.com/mtekman/org-treescope.el"))]) (org-treeusage . [(20221011 1301) ((emacs (26 1)) (dash (2 17 0)) (org (9 1 6))) "Examine the usage of org headings in a tree-like manner" tar ((:commit . "c561b3d468aa35e70a43d9a18a4f505996ae882d") (:authors ("Mehmet Tekman")) (:maintainer "Mehmet Tekman") (:keywords "outlines") (:url . "https://github.com/mtekman/org-treeusage.el"))]) @@ -3689,7 +3710,7 @@ (org-visibility . [(20220929 1415) ((emacs (27 1))) "Persistent org tree visibility" single ((:commit . "afa4b6f8ff274df87eb11f1afd0321084a45a2ab") (:authors ("Kyle W T Sherman" . "kylewsherman@gmail.com")) (:maintainer "Kyle W T Sherman" . "kylewsherman@gmail.com") (:keywords "outlines" "convenience") (:url . "https://github.com/nullman/emacs-org-visibility"))]) (org-wc . [(20200731 2244) nil "Count words in org mode trees." single ((:commit . "dbbf794e4ec6c4080d945f43338185e34a4a582d") (:authors ("Simon Guest")) (:maintainer "Simon Guest"))]) (org-web-tools . [(20201212 1058) ((emacs (25 1)) (org (9 0)) (dash (2 12)) (esxml (0 3 4)) (s (1 10 0)) (request (0 3 0))) "Display and capture web content with Org-mode" tar ((:commit . "b94a07add8558ef7b0666173dbb8a2554f1d41a6") (:authors ("Adam Porter" . "adam@alphapapa.net")) (:maintainer "Adam Porter" . "adam@alphapapa.net") (:keywords "hypermedia" "outlines" "org" "web") (:url . "http://github.com/alphapapa/org-web-tools"))]) - (org-wild-notifier . [(20230211 2354) ((alert (1 2)) (async (1 9 3)) (dash (2 18 0)) (emacs (24 4))) "Customizable org-agenda notifications" single ((:commit . "4bbf7e90886122b1320ee793a00ef6a27a797c25") (:authors ("Artem Khramov" . "akhramov+emacs@pm.me")) (:maintainer "Artem Khramov" . "akhramov+emacs@pm.me") (:keywords "notification" "alert" "org" "org-agenda" "agenda") (:url . "https://github.com/akhramov/org-wild-notifier.el"))]) + (org-wild-notifier . [(20230323 920) ((alert (1 2)) (async (1 9 3)) (dash (2 18 0)) (emacs (24 4))) "Customizable org-agenda notifications" single ((:commit . "cdca8be45b80ab52077a915e77c625bc0ad07dd7") (:authors ("Artem Khramov" . "akhramov+emacs@pm.me")) (:maintainer "Artem Khramov" . "akhramov+emacs@pm.me") (:keywords "notification" "alert" "org" "org-agenda" "agenda") (:url . "https://github.com/akhramov/org-wild-notifier.el"))]) (org-working-set . [(20220414 1402) ((org (9 3)) (dash (2 12)) (s (1 12)) (emacs (26 3))) "Manage and visit a small set of org-nodes." single ((:commit . "6af54ed3a5d9bf90629223157803c42f5d3b152c") (:authors ("Marc Ihm" . "1@2484.de")) (:maintainer "Marc Ihm" . "1@2484.de") (:url . "https://github.com/marcIhm/org-working-set"))]) (org-wunderlist . [(20191017 1917) ((request-deferred (0 2 0)) (alert (1 1)) (emacs (24)) (cl-lib (0 5)) (org (8 2 4)) (s (1 9 0))) "Org sync with Wunderlist" single ((:commit . "1a084bb49be4b5a1066db9cd9b7da2f8efab293f") (:authors ("myuhe ")) (:maintainer "myuhe") (:keywords "convenience") (:url . "https://github.com/myuhe/org-wunderlist.el"))]) (org-zettelkasten . [(20230108 1326) ((emacs (25 1)) (org (9 3))) "A Zettelkasten mode leveraging Org" tar ((:commit . "8002c96d94cb89a0f5af03974f6d1eaea45e1e41") (:authors ("Yann Herklotz" . "yann@ymhg.org")) (:maintainer "Yann Herklotz" . "yann@ymhg.org") (:keywords "files" "hypermedia" "org" "notes") (:url . "https://sr.ht/~ymherklotz/org-zettelkasten"))]) @@ -3706,8 +3727,9 @@ (orgit-forge . [(20230212 2013) ((emacs (25 1)) (compat (29 1 3 4)) (forge (0 3)) (magit (3 3)) (org (9 5)) (orgit (1 8))) "Org links to Forge issue buffers" single ((:commit . "6f424ff3a2df7d9c00c217011949c1367cc15227") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "hypermedia" "vc") (:url . "https://github.com/magit/orgit-forge"))]) (orglink . [(20230212 2213) ((emacs (25 1)) (compat (29 1 3 4)) (org (9 5)) (seq (2 23))) "Use Org Mode links in other modes" single ((:commit . "168d46a33476c4c8ce56818faa6183421b16d211") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "hypermedia") (:url . "https://github.com/tarsius/orglink"))]) (orglue . [(20200411 311) ((org (9 3)) (epic (0 2))) "more functionality to org-mode." tar ((:commit . "9d5a8e24be9acb8c55bb4d6aa8b98e30e2677401") (:authors ("Yoshinari Nomura" . "nom@quickhack.net")) (:maintainer "Yoshinari Nomura" . "nom@quickhack.net") (:keywords "org"))]) + (orgmdb . [(20230312 2231) ((emacs (27 1)) (dash (2 11 0)) (s (1 12 0)) (org (8 0 0))) "An OMDb API client with some convenience functions" single ((:commit . "385a747f41130b714207432045161915eb65b206") (:authors ("Isa Mert Gurbuz" . "isamert@protonmail.com")) (:maintainer "Isa Mert Gurbuz" . "isamert@protonmail.com") (:url . "https://github.com/isamert/orgmdb"))]) (orgnav . [(20170608 1713) ((helm (2 7 0)) (s (1 11 0)) (dash (1 11 0)) (emacs (24))) "Org tree navigation using helm" tar ((:commit . "9e2cac9c1a67af5f0080e60022e821bf7b70312d") (:authors ("Facet Framer" . "facet@facetframer.com")) (:maintainer "Facet Framer" . "facet@facetframer.com") (:keywords "convenience" "outlines") (:url . "http://github.com/facetframer/orgnav"))]) - (orgstrap . [(20230202 235) ((emacs (24 4))) "Bootstrap an Org file using file local variables" single ((:commit . "3cf0fec936fc0dc72bd7bd970fa91d445e763af4") (:authors ("Tom Gillespie")) (:maintainer "Tom Gillespie") (:keywords "lisp" "org" "org-mode" "bootstrap") (:url . "https://github.com/tgbugs/orgstrap"))]) + (orgstrap . [(20230327 650) ((emacs (24 4))) "Bootstrap an Org file using file local variables" single ((:commit . "045600b52dc5277b4fe4ec11fe140b1e7240f1f9") (:authors ("Tom Gillespie")) (:maintainer "Tom Gillespie") (:keywords "lisp" "org" "org-mode" "bootstrap") (:url . "https://github.com/tgbugs/orgstrap"))]) (orgtbl-aggregate . [(20230205 836) ((emacs (26 1))) "Create an aggregated Org table from another one" single ((:commit . "4f9fcb4f7380b247d628b899135df23c8fc8b6f1") (:keywords "data" "extensions") (:url . "https://github.com/tbanel/orgaggregate/blob/master/README.org"))]) (orgtbl-ascii-plot . [(20230122 816) nil "ascii-art bar plots in org-mode tables" single ((:commit . "4160128045b271bc1aef3d14dbf0c5b53ae58bd2") (:authors ("Thierry Banel tbanelwebmin at free dot fr") ("Michael Brand")) (:maintainer "Thierry Banel tbanelwebmin at free dot fr") (:keywords "org" "table" "ascii" "plot"))]) (orgtbl-fit . [(20230110 1544) ((emacs (24 4))) "Regression-fit a column in an Org Mode table" single ((:commit . "5bde4902187b2578dc39ee3a02cd7c84c4470b8a") (:authors ("Thierry Banel tbanelwebmin at free dot fr")) (:maintainer "Thierry Banel tbanelwebmin at free dot fr") (:keywords "data" "extensions") (:url . "https://github.com/tbanel/orgtblfit/blob/master/README.org"))]) @@ -3719,7 +3741,7 @@ (orthodox-christian-new-calendar-holidays . [(20210830 1657) nil "Feasts (NS)" single ((:commit . "6869024ecd45eefd0ec648979c6a59d7c79770e0") (:authors ("Carson Chittom" . "carson@wistly.net")) (:maintainer "Carson Chittom" . "carson@wistly.net") (:keywords "calendar") (:url . "https://github.com/cmchittom/orthodox-christian-new-calendar-holidays"))]) (osa . [(20200522 2103) ((emacs (25 1))) "OSA (JavaScript / AppleScript) bridge" tar ((:commit . "615ca9eef4131a23d9971691fa0d0f20fe59d01b") (:authors ("xristos" . "xristos@sdf.org")) (:maintainer "xristos" . "xristos@sdf.org") (:keywords "extensions") (:url . "https://github.com/atomontage/osa"))]) (osa-chrome . [(20201122 1639) ((emacs (25 1)) (osa (1 0))) "Google Chrome remote tab control" tar ((:commit . "9148e21cf2e91b357f5ea3a349975e8b89c8d5e4") (:authors ("xristos" . "xristos@sdf.org")) (:maintainer "xristos" . "xristos@sdf.org") (:keywords "comm") (:url . "https://github.com/atomontage/osa-chrome"))]) - (osm . [(20230220 1723) ((emacs (27 1)) (compat (29 1 3 4))) "OpenStreetMap viewer" tar ((:commit . "6c0054004174840be106b3627a4b704a197bad6a") (:authors ("Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainer "Daniel Mendler" . "mail@daniel-mendler.de") (:url . "https://github.com/minad/osm"))]) + (osm . [(20230405 1939) ((emacs (27 1)) (compat (29 1 4 0))) "OpenStreetMap viewer" tar ((:commit . "b3d90704b4e3caa5bf94216124ecdb9f9ae15207") (:authors ("Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainer "Daniel Mendler" . "mail@daniel-mendler.de") (:url . "https://github.com/minad/osm"))]) (osx-browse . [(20140508 2041) ((string-utils (0 3 2)) (browse-url-dwim (0 6 6))) "Web browsing helpers for OS X" single ((:commit . "838b81625853e04919fbb56fd21f387762b2e3f5") (:authors ("Roland Walker" . "walker@pobox.com")) (:maintainer "Roland Walker" . "walker@pobox.com") (:keywords "hypermedia" "external") (:url . "http://github.com/rolandwalker/osx-browse"))]) (osx-clipboard . [(20141012 717) nil "Use the OS X clipboard from terminal Emacs" single ((:commit . "e46dd31327a3f92f77b013b4c9b1e5fdd0e5c73d") (:authors ("Jon Oddie ")) (:maintainer "Jon Oddie ") (:url . "https://github.com/joddie/osx-clipboard-mode"))]) (osx-dictionary . [(20220801 1542) ((cl-lib (0 5))) "Interface for OSX Dictionary.app" tar ((:commit . "0715e5a3ac659df32a0f0fabfbbeef0228fbd9a9") (:authors ("Chunyang Xu" . "mail@xuchunyang.me")) (:maintainer "Chunyang Xu" . "mail@xuchunyang.me") (:keywords "mac" "dictionary") (:url . "https://github.com/xuchunyang/osx-dictionary.el"))]) @@ -3733,7 +3755,7 @@ (other-emacs-eval . [(20180408 1348) ((emacs (25 1)) (async (1 9 2))) "Evaluate the Emacs Lisp expression in other Emacs" single ((:commit . "8ace5acafef65daabf0c6619eff60733d7f5d792") (:authors ("Xu Chunyang" . "mail@xuchunyang.me")) (:maintainer "Xu Chunyang" . "mail@xuchunyang.me") (:keywords "tools") (:url . "https://github.com/xuchunyang/other-emacs-eval"))]) (ouroboros . [(20221229 1731) ((emacs (27 1)) (dash (2 19 0)) (cbor (0 2 3)) (bech32 (0 2 1))) "Ouroboros network mini-protocol" single ((:commit . "fb7d4deee41816bf6d79004b2301a1275fa87402") (:authors ("Oscar Najera ")) (:maintainer "Oscar Najera" . "hi@oscarnajera.com") (:url . "https://github.com/Titan-C/cardano.el"))]) (outline-magic . [(20180619 1819) nil "outline mode extensions for Emacs" single ((:commit . "2a5f07417b696cf7541d435c43bafcc64817636b") (:authors ("Carsten Dominik" . "dominik@science.uva.nl")) (:maintainer "Thorsten Jolitz ") (:keywords "outlines"))]) - (outline-minor-faces . [(20230212 2012) ((emacs (25 1)) (compat (29 1 3 4))) "Headings faces for outline-minor-mode" single ((:commit . "2404f29d376fb14f9f38eb09be8f0574f3ca19ac") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "faces" "outlines") (:url . "https://github.com/tarsius/outline-minor-faces"))]) + (outline-minor-faces . [(20230407 1051) ((emacs (25 1)) (compat (29 1 3 4))) "Headings faces for outline-minor-mode" single ((:commit . "0e7cd26d4ebe9a1c842645bd3535fc835d16fdf4") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "faces" "outlines") (:url . "https://github.com/tarsius/outline-minor-faces"))]) (outline-toc . [(20200401 1208) nil "Sidebar showing a \"table of contents\"." single ((:commit . "81d373633b40628cc3a6b6fb534fd7730076bcdb") (:authors ("Austin Bingham" . "austin.bingham@gmail.com")) (:maintainer "Austin Bingham" . "austin.bingham@gmail.com") (:keywords "convenience" "outlines") (:url . "https://github.com/abingham/outline-toc.el"))]) (outlook . [(20180428 1430) ((emacs (24 4))) "send emails in MS Outlook style" tar ((:commit . "b6a7a06b996d84647e8024412876e9e76ca884e4") (:authors ("Andrew Savonichev")) (:maintainer "Andrew Savonichev") (:keywords "mail") (:url . "https://github.com/asavonic/outlook.el"))]) (outorg . [(20190720 2002) ((emacs (24 4))) "Org-style comment editing" single ((:commit . "ef0f86f4b893b30be8bcf8b43a5ec357a6c70f07") (:maintainer "Adam Porter" . "adam@alphapapa.net") (:url . "https://github.com/alphapapa/outorg"))]) @@ -3771,15 +3793,15 @@ (ox-nikola . [(20151114 1116) ((emacs (24 4)) (org (8 2 4)) (ox-rst (0 2))) "Export Nikola articles using org-mode." single ((:commit . "5bcbc1a38f6619f62294194f13ca0cd4ca14dd48") (:authors ("IGARASHI Masanao" . "syoux2@gmail.com")) (:maintainer "IGARASHI Masanao" . "syoux2@gmail.com") (:keywords "org" "nikola") (:url . "https://github.com/masayuko/ox-nikola"))]) (ox-pandoc . [(20230128 1219) ((org (8 2)) (emacs (24 4)) (dash (2 8)) (ht (2 0))) "An Org-mode exporter using pandoc" single ((:commit . "66c32cca4f6047dd7e0f77f10bd565a2d83d4729") (:authors ("KAWABATA, Taichi" . "kawabata.taichi@gmail.com") ("FENTON, Alex" . "a-fent@github")) (:maintainer "FENTON, Alex" . "a-fent@github") (:keywords "tools") (:url . "https://github.com/a-fent/ox-pandoc"))]) (ox-pukiwiki . [(20150124 1716) ((org (8 1))) "Pukiwiki Back-End for Org Export Engine" single ((:commit . "b53920abf698fa6682623d671108393e92c68bd7") (:authors ("Yasushi SHOJI" . "yasushi.shoji@gmail.com")) (:maintainer "Yasushi SHOJI" . "yasushi.shoji@gmail.com") (:keywords "org" "pukiwiki") (:url . "https://github.com/yashi/org-pukiwiki"))]) - (ox-qmd . [(20221127 702) ((emacs (24 4))) "Qiita Markdown Back-End for Org Export Engine" single ((:commit . "026e4bd227589b3500294a56c2eca43b3405f992") (:authors ("0x60DF" . "0x60DF@gmail.com")) (:maintainer "0x60DF" . "0x60DF@gmail.com") (:keywords "wp") (:url . "https://github.com/0x60df/ox-qmd"))]) + (ox-qmd . [(20230325 1315) ((emacs (27 2)) (request (0 3 3)) (mimetypes (1 0))) "Qiita Markdown Back-End for Org Export Engine" tar ((:commit . "0b5fa1e20aaa48d93600e1b8d09c3b6f55af3373") (:authors ("0x60DF" . "0x60DF@gmail.com")) (:maintainer "0x60DF" . "0x60DF@gmail.com") (:keywords "wp") (:url . "https://github.com/0x60df/ox-qmd"))]) (ox-report . [(20220910 951) ((emacs (24 4)) (org-msg (3 9))) "Export your org file to minutes report PDF file" single ((:commit . "029fac8d4c83cc8841ade0dfebc8b7d7508efbb2") (:authors ("Matthias David" . "matthias@gnu.re")) (:maintainer "Matthias David" . "matthias@gnu.re") (:keywords "org" "outlines" "report" "exporter" "meeting" "minutes") (:url . "https://github.com/DarkBuffalo/ox-report"))]) (ox-reveal . [(20221127 814) ((org (8 3))) "reveal.js Presentation Back-End for Org Export Engine" single ((:commit . "f55c851bf6aeb1bb2a7f6cf0f2b7bd0e79c4a5a0") (:authors ("Yujie Wen ")) (:maintainer "Yujie Wen ") (:keywords "outlines" "hypermedia" "slideshow" "presentation"))]) (ox-review . [(20220619 724) ((emacs (26 1)) (org (9))) "Re:VIEW Back-End for Org Export Engine" single ((:commit . "f7dc418f9812088afc0ee0d08f778a5654686ef3") (:authors ("Masashi Fujimoto")) (:maintainer "Masashi Fujimoto") (:keywords "outlines" "hypermedia") (:url . "https://github.com/masfj/ox-review"))]) (ox-rfc . [(20220604 1114) ((emacs (24 3)) (org (8 3))) "RFC Back-End for Org Export Engine" single ((:commit . "f0fe3503f8732ea5e95a4016c6b7ce5b47cf6295") (:authors ("Christian Hopps" . "chopps@devhopps.com")) (:maintainer "Christian Hopps" . "chopps@devhopps.com") (:keywords "org" "rfc" "wp" "xml") (:url . "https://github.com/choppsv1/org-rfc-export"))]) - (ox-rss . [(20230129 1538) ((emacs (26 1)) (org (9 3))) "RSS 2.0 Back-End for Org Export Engine" single ((:commit . "81e2eea65e0654e9022f3f732b6cf9dc942423d1") (:authors ("Bastien Guerry" . "bzg@gnu.org")) (:maintainer "Benedict Wang" . "foss@bhw.name") (:keywords "org" "wp" "blog" "feed" "rss") (:url . "https://github.com/benedicthw/ox-rss.git"))]) + (ox-rss . [(20230324 157) ((emacs (26 1)) (org (9 3))) "RSS 2.0 Back-End for Org Export Engine" single ((:commit . "aceff7c50e9d8ace97cefc09ca265a11e75e4d68") (:authors ("Bastien Guerry" . "bzg@gnu.org")) (:maintainer "Benedict Wang" . "foss@bhw.name") (:keywords "org" "wp" "blog" "feed" "rss") (:url . "https://github.com/benedicthw/ox-rss.git"))]) (ox-rst . [(20200815 1511) ((emacs (25 1)) (org (8 3))) "Export reStructuredText using org-mode." single ((:commit . "99fa790da55b57a3f2e9aa187493ba434a64250e") (:authors ("Masanao Igarashi" . "syoux2@gmail.com")) (:maintainer "Masanao Igarashi" . "syoux2@gmail.com") (:keywords "org" "rst" "rest" "restructuredtext") (:url . "https://github.com/msnoigrs/ox-rst"))]) (ox-slack . [(20200108 1546) ((emacs (24)) (org (9 1 4)) (ox-gfm (1 0))) "Slack Exporter for org-mode" single ((:commit . "c55b003f4ac343d6c6d8ef7cbe01d0d100abac34") (:authors ("Matt Price")) (:maintainer "Matt Price") (:keywords "org" "slack" "outlines") (:url . "https://github.com/titaniumbones/ox-slack"))]) - (ox-spectacle . [(20230210 113) ((emacs (28 1)) (org (8 3))) "Spectacle.js Presentation Back-End for Org Export Engine" single ((:commit . "0bca84ff6d3c49e4ca1bf5c3922ed261aafa3635") (:authors ("lorniu" . "lorniu@gmail.com")) (:maintainer "lorniu" . "lorniu@gmail.com") (:keywords "convenience") (:url . "https://github.com/lorniu/ox-spectacle"))]) + (ox-spectacle . [(20230307 316) ((emacs (28 1)) (org (8 3))) "Spectacle.js Presentation Back-End for Org Export Engine" single ((:commit . "85c617200587eb3f7954c278b6cde44f8d43fd87") (:authors ("lorniu" . "lorniu@gmail.com")) (:maintainer "lorniu" . "lorniu@gmail.com") (:keywords "convenience") (:url . "https://github.com/lorniu/ox-spectacle"))]) (ox-ssh . [(20210917 1517) ((emacs (24 4))) "SSH Config Backend for Org Export Engine" single ((:commit . "be3b39160da6ae37b1f1cd175ed854ac41d1cb63") (:authors ("Dante Catalfamo")) (:maintainer "Dante Catalfamo") (:keywords "outlines" "org" "ssh") (:url . "https://github.com/dantecatalfamo/ox-ssh"))]) (ox-textile . [(20210919 1738) ((org (8 1))) "Textile Back-End for Org Export Engine" single ((:commit . "92764235055bd1b51411d3e9490023bed7437d7b") (:authors ("Yasushi SHOJI" . "yasushi.shoji@gmail.com")) (:maintainer "Yasushi SHOJI" . "yasushi.shoji@gmail.com") (:keywords "org" "textile") (:url . "https://github.com/yashi/org-textile"))]) (ox-tiddly . [(20200927 857) ((org (8)) (emacs (24 4))) "Org TiddlyWiki exporter" single ((:commit . "3377d8732aa916e736ce5822c7a9a4fbdc894e37") (:authors ("Derek Feichtinger" . "derek.feichtinger@psi.ch")) (:maintainer "Derek Feichtinger" . "derek.feichtinger@psi.ch") (:keywords "org") (:url . "https://github.com/dfeich/org8-wikiexporters"))]) @@ -3796,10 +3818,10 @@ (pacfiles-mode . [(20200915 1815) ((emacs (26)) (cl-lib (0 5))) "pacnew and pacsave merging tool" tar ((:commit . "8d06f64abc98c3f3338560c8d6eb47719e034069") (:authors ("Carlos G. Cordero ")) (:maintainer "Carlos G. Cordero" . "pacfiles@binarycharly.com") (:keywords "files" "pacman" "arch" "pacnew" "pacsave" "update" "linux") (:url . "https://github.com/UndeadKernel/pacfiles-mode"))]) (pack . [(20191017 456) ((emacs (24)) (cl-lib (0 5))) "Pack and unpack archive files" single ((:commit . "85cd856fdc00a2365e88b50373b99f1b3d2227be") (:authors ("10sr" . "8.slashes@gmail.com")) (:maintainer "10sr" . "8.slashes@gmail.com") (:keywords "files" "dired") (:url . "https://github.com/10sr/pack-el"))]) (package+ . [(20210124 640) ((emacs (24 3))) "Extensions for the package library." tar ((:commit . "06fbc904e09d3349b669c2624a587fee5accf5ef") (:authors ("Ryan Davis" . "ryand-ruby@zenspider.com")) (:maintainer "Ryan Davis" . "ryand-ruby@zenspider.com") (:keywords "extensions" "tools") (:url . "https://github.com/zenspider/package"))]) - (package-build . [(20230221 1303) ((emacs (26 1))) "Tools for assembling a package archive" tar ((:commit . "9199271d78dc0f4f85047d6daef0e9721a6e63cd") (:authors ("Donald Ephraim Curtis" . "dcurtis@milkbox.net") ("Steve Purcell" . "steve@sanityinc.com") ("Jonas Bernoulli" . "jonas@bernoul.li") ("Phil Hagelberg" . "technomancy@gmail.com")) (:maintainer "Donald Ephraim Curtis" . "dcurtis@milkbox.net") (:keywords "maint" "tools") (:url . "https://github.com/melpa/package-build"))]) + (package-build . [(20230329 1735) ((emacs (26 1))) "Tools for assembling a package archive" tar ((:commit . "70ad610a996f6289cc24586af6ca885f784688fc") (:authors ("Donald Ephraim Curtis" . "dcurtis@milkbox.net") ("Steve Purcell" . "steve@sanityinc.com") ("Jonas Bernoulli" . "jonas@bernoul.li") ("Phil Hagelberg" . "technomancy@gmail.com")) (:maintainer "Donald Ephraim Curtis" . "dcurtis@milkbox.net") (:keywords "maint" "tools") (:url . "https://github.com/melpa/package-build"))]) (package-filter . [(20161122 719) nil "package archive whitelist and blacklist" single ((:commit . "c8e2531227c02c4c5e9d593f2cdb6a4ab4a6849b") (:authors ("Donald Ephraim Curtis" . "dcurtis@milkbox.net")) (:maintainer "Donald Ephraim Curtis" . "dcurtis@milkbox.net") (:url . "https://github.com/milkypostman/package-filter"))]) - (package-lint . [(20221003 1636) ((cl-lib (0 5)) (emacs (24 1)) (let-alist (1 0 6))) "A linting library for elisp package authors" tar ((:commit . "4ea8318c1bf79ccb1b4658d58917bbd9f990c432") (:authors ("Steve Purcell" . "steve@sanityinc.com") ("Fanael Linithien" . "fanael4@gmail.com")) (:maintainer "Steve Purcell" . "steve@sanityinc.com") (:keywords "lisp") (:url . "https://github.com/purcell/package-lint"))]) - (package-lint-flymake . [(20220212 825) ((emacs (26 1)) (package-lint (0 5))) "A package-lint Flymake backend" single ((:commit . "7a83a138e6546f4c4a9988ba6dddc5339fbe7272") (:url . "https://github.com/purcell/package-lint"))]) + (package-lint . [(20230315 1052) ((cl-lib (0 5)) (emacs (24 1)) (let-alist (1 0 6))) "A linting library for elisp package authors" tar ((:commit . "78ae823bd89d83299a0d7a52797d2593d03e9795") (:authors ("Steve Purcell" . "steve@sanityinc.com") ("Fanael Linithien" . "fanael4@gmail.com")) (:maintainer "Steve Purcell" . "steve@sanityinc.com") (:keywords "lisp") (:url . "https://github.com/purcell/package-lint"))]) + (package-lint-flymake . [(20230315 1052) ((emacs (26 1)) (package-lint (0 5))) "A package-lint Flymake backend" single ((:commit . "78ae823bd89d83299a0d7a52797d2593d03e9795") (:url . "https://github.com/purcell/package-lint"))]) (package-loading-notifier . [(20220130 318) ((emacs (25))) "Notify a package is being loaded" single ((:commit . "bc06ba97a0537aa202f277e5597ac96ca39307ab") (:authors ("SeungKi Kim" . "tttuuu888@gmail.com")) (:maintainer "SeungKi Kim" . "tttuuu888@gmail.com") (:keywords "convenience" "faces" "config" "startup") (:url . "https://github.com/tttuuu888/package-loading-notifier"))]) (package-safe-delete . [(20150116 1607) ((emacs (24)) (epl (0 7 -4))) "Safely delete package.el packages" single ((:commit . "138171e4fc03c0ef05a8260cbb5cd2e114c1c194") (:authors ("Fanael Linithien" . "fanael4@gmail.com")) (:maintainer "Fanael Linithien" . "fanael4@gmail.com") (:url . "https://github.com/Fanael/package-safe-delete"))]) (package-utils . [(20220630 2345) ((restart-emacs (0 1 1))) "Extensions for package.el" single ((:commit . "0168172062467b1bff913ea955b2ef709b43ecfa") (:authors ("Philippe Vaucher" . "philippe.vaucher@gmail.com")) (:maintainer "Philippe Vaucher" . "philippe.vaucher@gmail.com") (:keywords "package" "convenience") (:url . "https://github.com/Silex/package-utils"))]) @@ -3819,7 +3841,7 @@ (pandoc . [(20161128 1157) ((emacs (24 4))) "Pandoc interface" single ((:commit . "198d262d09e30448f1672338b0b5a81cf75e1eaa") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "hypermedia" "documentation" "markup" "converter") (:url . "https://github.com/zonuexe/pandoc.el"))]) (pandoc-mode . [(20221128 2034) ((hydra (0 10 0)) (dash (2 10 0))) "Minor mode for interacting with Pandoc" tar ((:commit . "8f955abec9c1d75acd9b03389b90a276ec4e2137") (:authors ("Joost Kremers" . "joostkremers@fastmail.fm")) (:maintainer "Joost Kremers" . "joostkremers@fastmail.fm") (:keywords "text" "pandoc") (:url . "http://joostkremers.github.io/pandoc-mode/"))]) (pangu-spacing . [(20221025 522) nil "Minor-mode to add space between Chinese and English characters." single ((:commit . "2303013e5cd7852136f1429162fea0e1c8cb0221") (:authors ("coldnew" . "coldnew.tw@gmail.com")) (:maintainer "coldnew" . "coldnew.tw@gmail.com") (:url . "http://github.com/coldnew/pangu-spacing"))]) - (paper-theme . [(20230124 2301) ((emacs (24))) "A minimal Emacs colour theme." single ((:commit . "c5c3761b1edbb8afe24425d8610aa368a762ff63") (:authors ("Göktuğ Kayaalp")) (:maintainer "Göktuğ Kayaalp") (:keywords "theme" "paper") (:url . "https://dev.gkayaalp.com/elisp/index.html#paper"))]) + (paper-theme . [(20230318 48) ((emacs (24))) "A minimal Emacs colour theme." single ((:commit . "8d337b85592ae44e1fa3ad03f0c65ca99036f9e2") (:authors ("Göktuğ Kayaalp")) (:maintainer "Göktuğ Kayaalp") (:keywords "theme" "paper") (:url . "https://dev.gkayaalp.com/elisp/index.html#paper"))]) (paperless . [(20230204 1815) ((emacs (29 1)) (f (0 11 0)) (s (1 10 0)) (cl-lib (0 6 1))) "A major mode for sorting and filing PDF documents." tar ((:commit . "e524e31350d74f13319968d24b7326a4a412e105") (:authors ("Anthony Green" . "green@moxielogic.com")) (:maintainer "Anthony Green" . "green@moxielogic.com") (:keywords "pdf" "convenience") (:url . "http://github.com/atgreen/paperless"))]) (paradox . [(20191011 1119) ((emacs (24 4)) (seq (1 7)) (let-alist (1 0 3)) (spinner (1 7 3)) (hydra (0 13 2))) "A modern Packages Menu. Colored, with package ratings, and customizable." tar ((:commit . "96401577ed02f433debe7604e49afd478e9eda61") (:authors ("Artur Malabarba" . "emacs@endlessparentheses.com")) (:maintainer "Artur Malabarba" . "emacs@endlessparentheses.com") (:keywords "package" "packages") (:url . "https://github.com/Malabarba/paradox"))]) (parchment-theme . [(20221206 1541) ((autothemer (0 2))) "Light theme inspired by Acme and Leuven" single ((:commit . "07c9887be6e7d94a8546db625c7d62c54d2e5923") (:authors ("Alex Griffin" . "a@ajgrf.com")) (:maintainer "Alex Griffin" . "a@ajgrf.com") (:url . "https://gitlab.com/ajgrf/parchment"))]) @@ -3833,7 +3855,7 @@ (parrot . [(20220101 518) ((emacs (24 1))) "Party Parrot rotates gracefully in mode-line." tar ((:commit . "1d381f24d74242018e306d1a0c891bed9a465ac3") (:authors ("Daniel Ting" . "deep.paren.12@gmail.com")) (:maintainer "Daniel Ting" . "deep.paren.12@gmail.com") (:keywords "party" "parrot" "rotate" "sirocco" "kakapo" "games") (:url . "https://github.com/dp12/parrot.git"))]) (parse-csv . [(20160512 1723) nil "Parse strings with CSV fields into s-expressions" single ((:commit . "96bef1ffbc89ea12d13311c9fa239c5c3e864890") (:authors ("Edward Marco Baringer (Common Lisp)") ("Matt Curtis" . "matt.r.curtis@gmail.com")) (:maintainer "Matt Curtis" . "matt.r.curtis@gmail.com") (:keywords "csv") (:url . "https://github.com/mrc/el-csv"))]) (parse-it . [(20220704 640) ((emacs (25 1)) (s (1 12 0))) "Basic Parser in Emacs Lisp" tar ((:commit . "c1b5ce15a5bcb80595f45e2fc3bda828f525859f") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "parse" "parser" "lex" "lexer" "ast") (:url . "https://github.com/jcs-elpa/parse-it"))]) - (parsebib . [(20221007 1402) ((emacs (25 1))) "A library for parsing bib files" single ((:commit . "1efca921cbb49380396df9d81308b32e55fc8b63") (:authors ("Joost Kremers" . "joostkremers@fastmail.fm")) (:maintainer "Joost Kremers" . "joostkremers@fastmail.fm") (:keywords "text" "bibtex") (:url . "https://github.com/joostkremers/parsebib"))]) + (parsebib . [(20230228 1530) ((emacs (25 1))) "A library for parsing bib files" single ((:commit . "ace9df707108b17759c004c7387655277122d4c1") (:authors ("Joost Kremers" . "joostkremers@fastmail.fm")) (:maintainer "Joost Kremers" . "joostkremers@fastmail.fm") (:keywords "text" "bibtex") (:url . "https://github.com/joostkremers/parsebib"))]) (parsec . [(20180730 16) ((emacs (24)) (cl-lib (0 5))) "Parser combinator library" single ((:commit . "2cbbbc2254aa7bcaa4fb5e07c8c1bf2f381dba26") (:authors ("Junpeng Qiu" . "qjpchmail@gmail.com")) (:maintainer "Junpeng Qiu" . "qjpchmail@gmail.com") (:keywords "extensions") (:url . "https://github.com/cute-jumper/parsec.el"))]) (parseclj . [(20220422 936) ((emacs (25))) "Clojure/EDN parser" tar ((:commit . "4d0e780e00f1828b00c43099e6eebc6582998f72") (:authors ("Arne Brasseur" . "arne@arnebrasseur.net")) (:maintainer "Arne Brasseur" . "arne@arnebrasseur.net") (:keywords "lisp" "clojure" "edn" "parser"))]) (parseedn . [(20220520 835) ((emacs (26)) (parseclj (1 1 0)) (map (2))) "Clojure/EDN parser" single ((:commit . "a09686fbb9113b8b1b4f20c9e1dc0d6fea01a64f") (:authors ("Arne Brasseur" . "arne@arnebrasseur.net")) (:maintainer "Arne Brasseur" . "arne@arnebrasseur.net") (:keywords "lisp" "clojure" "edn" "parser"))]) @@ -3865,9 +3887,10 @@ (pcomplete-extension . [(20190928 519) ((emacs (24)) (cl-lib (0 5))) "additional completion for pcomplete" single ((:commit . "bc5eb204fee659e0980056009409b44bc7655716") (:authors ("Thierry Volpiatto" . "thierry.volpiatto@gmail.com")) (:maintainer "Thierry Volpiatto" . "thierry.volpiatto@gmail.com") (:url . "https://github.com/thierryvolpiatto/pcomplete-extension"))]) (pcre2el . [(20221018 1608) ((emacs (25 1))) "regexp syntax converter" single ((:commit . "b7f6cc8d447a0e402fface7fac3f5ad02a9f9f6e") (:authors ("joddie ")) (:maintainer "joddie ") (:url . "https://github.com/joddie/pcre2el"))]) (pcsv . [(20230207 757) ((emacs (24 1))) "Parser of csv" single ((:commit . "4b5e801d213a460a6cb3cb2997a0a6cd33c7bc58") (:authors ("Masahiro Hayashi" . "mhayashi1120@gmail.com")) (:maintainer "Masahiro Hayashi" . "mhayashi1120@gmail.com") (:keywords "data") (:url . "https://github.com/mhayashi1120/Emacs-pcsv"))]) + (pd-remote . [(20230314 428) ((emacs (24 3)) (faust-mode (0 6)) (lua-mode (20210802))) "Pd remote control helper" single ((:commit . "dcd68097d2b7468303517d91cb76682bfb47db63") (:authors ("Albert Graef" . "aggraef@gmail.com")) (:maintainer "Albert Graef" . "aggraef@gmail.com") (:keywords "multimedia" "pure-data") (:url . "https://github.com/agraef/pd-remote"))]) (pdb-capf . [(20200419 1237) ((emacs (25 1))) "Completion-at-point function for python debugger" single ((:commit . "2f4099aa1330f87df4e9cd526de057ee9b71de6c") (:authors ("Andrii Kolomoiets" . "andreyk.mad@gmail.com")) (:maintainer "Andrii Kolomoiets" . "andreyk.mad@gmail.com") (:keywords "languages" "abbrev" "convenience") (:url . "https://github.com/muffinmad/emacs-pdb-capf"))]) (pdb-mode . [(20150128 1751) nil "Major mode for editing Protein Data Bank files" single ((:commit . "855fb18ebb73b5df30c8d7677c2bcd0f361b138a") (:authors (nil . "charles.bond@uwa.edu.au")) (:maintainer nil . "aix.bing@gmail.com") (:keywords "data" "pdb") (:url . "http://bondxray.org/software/pdb-mode/"))]) - (pdf-tools . [(20230117 632) ((emacs (26 3)) (tablist (1 0)) (let-alist (1 0 4))) "Support library for PDF documents" tar ((:commit . "bc2ba117e8c3196ff9adf0da4fa1e63a8da3d7c8") (:authors ("Andreas Politz" . "mail@andreas-politz.de")) (:maintainer "Vedang Manerikar" . "vedang.manerikar@gmail.com") (:keywords "files" "multimedia") (:url . "http://github.com/vedang/pdf-tools/"))]) + (pdf-tools . [(20230404 327) ((emacs (26 3)) (tablist (1 0)) (let-alist (1 0 4))) "Support library for PDF documents" tar ((:commit . "7ff6293a25baaae65651b3e1c54b61208279a7ef") (:authors ("Andreas Politz" . "mail@andreas-politz.de")) (:maintainer "Vedang Manerikar" . "vedang.manerikar@gmail.com") (:keywords "files" "multimedia") (:url . "http://github.com/vedang/pdf-tools/"))]) (pdf-view-restore . [(20190904 1708) ((pdf-tools (0 90)) (emacs (26 0))) "Support for opening last known pdf position in pdfview mode" single ((:commit . "5a1947c01a3edecc9e0fe7629041a2f53e0610c9") (:authors ("Kevin Kim" . "kevinkim1991@gmail.com")) (:maintainer "Kevin Kim" . "kevinkim1991@gmail.com") (:keywords "files" "convenience") (:url . "https://github.com/007kevin/pdf-view-restore"))]) (pdfgrep . [(20210203 1730) ((emacs (24 4))) "run `pdfgrep' and display the results." single ((:commit . "a4ca0a1e6521de93f28bb6736a5344b4974d144c") (:authors ("Jérémy Compostella" . "jeremy.compostella@gmail.com")) (:maintainer "Jérémy Compostella" . "jeremy.compostella@gmail.com") (:keywords "extensions" "mail" "pdf" "grep") (:url . "https://github.com/jeremy-compostella/pdfgrep"))]) (peacock-theme . [(20170808 1320) ((emacs (24 0))) "an Emacs 24 theme based on Peacock (tmTheme)" single ((:commit . "9e46fbfb562b6e26c6e3d6d618b044b3694da4c8") (:authors ("Jason Milkins")) (:maintainer "Jason Milkins") (:url . "https://github.com/emacsfodder/tmtheme-to-deftheme"))]) @@ -3879,9 +3902,10 @@ (pepita . [(20200228 2257) ((emacs (25)) (csv (2 1))) "Run Splunk search commands, export results to CSV/HTML/JSON" single ((:commit . "263d6d940d7e4203bbecda46dbaa89b7af1db54f") (:authors ("Sebastian Monia" . "smonia@outlook.com")) (:maintainer "Sebastian Monia" . "smonia@outlook.com") (:keywords "tools" "convenience" "matching") (:url . "https://github.com/sebasmonia/pepita.git"))]) (per-buffer-theme . [(20221002 2219) ((emacs (25 1))) "Change theme and font according to buffer name or major mode." single ((:commit . "2cbb15c05edff4ce23ce61858cf16e8953cd58b3") (:authors ("Iñigo Serna" . "inigoserna@gmx.com")) (:maintainer "Iñigo Serna" . "inigoserna@gmx.com") (:keywords "themes") (:url . "https://hg.serna.eu/emacs/per-buffer-theme"))]) (perfect-margin . [(20220426 1701) ((emacs (24 0)) (cl-lib (0 5))) "auto center windows, work with minimap and/or linum-mode" single ((:commit . "e811665951cd48819a63e477e7206c43232a78bd") (:authors ("Randall Wang" . "randall.wjz@gmail.com")) (:maintainer "Randall Wang" . "randall.wjz@gmail.com") (:keywords "convenience" "frames") (:url . "https://github.com/mpwang/perfect-margin"))]) + (perject . [(20230306 1033) ((emacs (27 1)) (dash (2 10)) (transient (0 3 7))) "Session-persistent project management" tar ((:commit . "82d007ec7201c21d8dd31d95e857632887582be6") (:authors ("overideal")) (:maintainer "overideal") (:url . "https://github.com/overideal/perject"))]) (perlbrew . [(20161109 709) nil "A perlbrew wrapper for Emacs" single ((:commit . "3a3406c3307c92aa30f9400d430925c434a3b6f0") (:authors ("Kentaro Kuribayashi" . "kentarok@gmail.com")) (:maintainer "Kentaro Kuribayashi" . "kentarok@gmail.com") (:keywords "emacs" "perl"))]) (persistent-overlays . [(20161128 700) nil "Minor mode to store selected overlays to be loaded later" tar ((:commit . "f563c8b966edc78c9d806661c4eb80e4781c4eab") (:authors ("Michael Neilly" . "mneilly@yahoo.com")) (:maintainer "Michael Neilly" . "mneilly@yahoo.com") (:keywords "overlays" "persistent") (:url . "https://github.com/mneilly/Emacs-Persistent-Overlays"))]) - (persistent-scratch . [(20230113 318) ((emacs (24))) "Preserve the scratch buffer across Emacs sessions" single ((:commit . "f9c1361ad69073af8133174f9e37b594df9be361") (:authors ("Fanael Linithien" . "fanael4@gmail.com")) (:maintainer "Fanael Linithien" . "fanael4@gmail.com") (:url . "https://github.com/Fanael/persistent-scratch"))]) + (persistent-scratch . [(20230225 1439) ((emacs (24))) "Preserve the scratch buffer across Emacs sessions" single ((:commit . "5ff41262f158d3eb966826314516f23e0cb86c04") (:authors ("Fanael Linithien" . "fanael4@gmail.com")) (:maintainer "Fanael Linithien" . "fanael4@gmail.com") (:url . "https://github.com/Fanael/persistent-scratch"))]) (persistent-soft . [(20150223 1853) ((pcache (0 3 1)) (list-utils (0 4 2))) "Persistent storage, returning nil on failure" single ((:commit . "a1e0ddf2a12a6f18cab565dee250f070384cbe02") (:authors ("Roland Walker" . "walker@pobox.com")) (:maintainer "Roland Walker" . "walker@pobox.com") (:keywords "data" "extensions") (:url . "http://github.com/rolandwalker/persistent-soft"))]) (persp-fr . [(20191108 754) ((emacs (25 1)) (persp-mode (2 9 6)) (dash (2 13 0))) "In persp-mode, show perspective list in the GUI window title" single ((:commit . "1adbb6a9f9a4db580a9b7ed8b4091738e01345e6") (:authors ("Francesc Rocher" . "francesc.rocher@gmail.com")) (:maintainer "Francesc Rocher" . "francesc.rocher@gmail.com") (:keywords "perspectives" "workspace" "windows" "convenience") (:url . "http://github.com/rocher/persp-fr"))]) (persp-mode . [(20230110 1045) ((emacs (24 3))) "windows/buffers sets shared among frames + save/load." single ((:commit . "df95ea710e2a72f7a88293b72137acb0ca024d90") (:authors ("Constantin Kulikov (Bad_ptr)" . "zxnotdead@gmail.com")) (:maintainer "Constantin Kulikov (Bad_ptr)" . "zxnotdead@gmail.com") (:keywords "perspectives" "session" "workspace" "persistence" "windows" "buffers" "convenience") (:url . "https://github.com/Bad-ptr/persp-mode.el"))]) @@ -3892,7 +3916,7 @@ (perspective-exwm . [(20230218 1358) ((emacs (27 1)) (burly (0 2 -1)) (exwm (0 26)) (perspective (2 17))) "Better integration for perspective.el and EXWM" single ((:commit . "01d51f5c92a30b65e8346582ed1ce6513570bb0a") (:authors ("Korytov Pavel" . "thexcloud@gmail.com")) (:maintainer "Korytov Pavel" . "thexcloud@gmail.com") (:url . "https://github.com/SqrtMinusOne/perspective-exwm.el"))]) (perspeen . [(20171203 1021) ((emacs (25 0)) (powerline (2 4))) "An package for multi-workspace" tar ((:commit . "edb70c530bda50ff3d1756e32a703d5fef5e5480") (:authors ("Peng Li" . "seudut@gmail.com")) (:maintainer "Peng Li" . "seudut@gmail.com") (:keywords "lisp") (:url . "https://github.com/seudut/perspeen"))]) (pest-mode . [(20221231 15) ((emacs (26 3))) "Major mode for editing Pest files" single ((:commit . "8023a92ce59c34dcd1587cbd85ed144f206ddb89") (:authors ("ksqsf" . "i@ksqsf.moe")) (:maintainer "ksqsf" . "i@ksqsf.moe") (:keywords "languages") (:url . "https://github.com/ksqsf/pest-mode"))]) - (pet . [(20220917 2111) ((emacs (26 1)) (f (0 6 0))) "Executable and virtualenv tracker for python-mode" single ((:commit . "7620c18223f126c384dbf42b0b167a6066a81dd1") (:authors ("Jimmy Yuen Ho Wong" . "wyuenho@gmail.com")) (:maintainer "Jimmy Yuen Ho Wong" . "wyuenho@gmail.com") (:keywords "tools") (:url . "https://github.com/wyuenho/emacs-pet/"))]) + (pet . [(20230301 111) ((emacs (26 1)) (f (0 6 0))) "Executable and virtualenv tracker for python-mode" single ((:commit . "9d2d747b18c3f1d330bf9f09c9f64af9446c1268") (:authors ("Jimmy Yuen Ho Wong" . "wyuenho@gmail.com")) (:maintainer "Jimmy Yuen Ho Wong" . "wyuenho@gmail.com") (:keywords "tools") (:url . "https://github.com/wyuenho/emacs-pet/"))]) (pfuture . [(20220913 1401) ((emacs (25 2))) "a simple wrapper around asynchronous processes" single ((:commit . "19b53aebbc0f2da31de6326c495038901bffb73c") (:authors ("Alexander Miller" . "alexanderm@web.de")) (:maintainer "Alexander Miller" . "alexanderm@web.de") (:url . "https://github.com/Alexander-Miller/pfuture"))]) (pg . [(20221210 1215) ((emacs (26 1))) "Emacs Lisp socket-level interface to the PostgreSQL RDBMS" single ((:commit . "f91d546a35ed3479cdb656b17525285e11565892") (:authors ("Eric Marsden" . "eric.marsden@risk-engineering.org")) (:maintainer "Eric Marsden" . "eric.marsden@risk-engineering.org") (:keywords "data" "comm" "database" "postgresql") (:url . "https://github.com/emarsden/pg-el"))]) (pgdevenv . [(20150105 2236) nil "Manage your PostgreSQL development envs" tar ((:commit . "7f1d5bc734750aca98cf67a9491cdbd5615fd132") (:authors ("Dimitri Fontaine" . "dim@tapoueh.org")) (:maintainer "Dimitri Fontaine" . "dim@tapoueh.org") (:keywords "emacs" "postgresql" "development" "environment" "shell" "debug" "gdb"))]) @@ -3912,13 +3936,13 @@ (php-boris-minor-mode . [(20140209 1835) ((php-boris (0 0 1)) (highlight (0))) "a minor mode to evaluate PHP code in the Boris repl" single ((:commit . "8648eba604e4ff82ef6594a2c5ee4cb4825e6235") (:authors ("steckerhalter")) (:maintainer "steckerhalter") (:keywords "php" "repl" "eval") (:url . "https://github.com/steckerhalter/php-boris-minor-mode"))]) (php-cs-fixer . [(20220516 1008) ((cl-lib (0 5))) "php-cs-fixer wrapper." single ((:commit . "efe4368d891f1eec6311363cfd6be3e9eadb5e0a") (:authors ("Philippe Ivaldi for OVYA")) (:maintainer "Philippe Ivaldi for OVYA") (:keywords "languages" "php") (:url . "https://github.com/OVYA/php-cs-fixer"))]) (php-eldoc . [(20140202 1941) nil "eldoc backend for php" tar ((:commit . "df05064146b884d9081e10657e32dc480f070cfe") (:authors ("sabof")) (:maintainer "sabof") (:url . "https://github.com/sabof/php-eldoc"))]) - (php-mode . [(20230212 731) ((emacs (25 2))) "Major mode for editing PHP code" tar ((:commit . "fb11df8268b7099766264cd53836ef159746adbd") (:authors ("Eric James Michael Ritz")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "languages" "php") (:url . "https://github.com/emacs-php/php-mode"))]) + (php-mode . [(20230318 2134) ((emacs (26 1))) "Major mode for editing PHP code" tar ((:commit . "47e0813079cea6243139da2b6efedd36940367c8") (:authors ("Eric James Michael Ritz")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "languages" "php") (:url . "https://github.com/emacs-php/php-mode"))]) (php-quickhelp . [(20210819 2025) ((emacs (25 1))) "Quickhelp at point for php" single ((:commit . "d5e11b7a6bad64550521e8822139a33218b8c9bb") (:authors ("Vincenzo Pupillo")) (:maintainer "Vincenzo Pupillo") (:url . "https://github.com/vpxyz/php-quickhelp"))]) (php-refactor-mode . [(20171124 635) nil "Minor mode to quickly and safely perform common refactorings" single ((:commit . "d06dabd9ca743a04067e02282b69d7b7467fb4b7") (:authors ("Matthew M. Keeler" . "keelerm84@gmail.com")) (:maintainer "Matthew M. Keeler" . "keelerm84@gmail.com") (:keywords "php" "refactor") (:url . "https://github.com/keelerm84/php-refactor-mode.el"))]) - (php-runtime . [(20221009 1955) ((emacs (25 1)) (s (1 7))) "Language binding bridge to PHP" single ((:commit . "36e6ae862cb02104b5782a563f0a5846c00e0082") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "processes" "php") (:url . "https://github.com/emacs-php/php-runtime.el"))]) + (php-runtime . [(20230404 1713) ((emacs (25 1)) (compat (29))) "Language binding bridge to PHP" tar ((:commit . "ba64f30e716f89f9cf2c3bd44c5d00da69736868") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "processes" "php" "lisp") (:url . "https://github.com/emacs-php/php-runtime.el"))]) (php-scratch . [(20210706 459) ((emacs (24 3)) (s (1 11 0)) (php-mode (1 17 0))) "A scratch buffer to interactively evaluate php code" single ((:commit . "b6bfd279da8a8ac7fc30459485956f3fd5d02573") (:authors ("Tijs Mallaerts" . "tijs.mallaerts@gmail.com")) (:maintainer "Tijs Mallaerts" . "tijs.mallaerts@gmail.com") (:url . "https://github.com/mallt/php-scratch"))]) (phpactor . [(20221023 608) ((emacs (25 1)) (f (0 17)) (php-runtime (0 2)) (composer (0 2 0)) (async (1 9 3))) "Interface to Phpactor" tar ((:commit . "dde09addf36017527441a855054406f8ffc4e534") (:authors ("USAMI Kenta" . "tadsan@zonu.me") ("Mikael Kermorgant" . "mikael@kgtech.fi")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "tools" "php") (:url . "https://github.com/emacs-php/phpactor.el"))]) - (phpstan . [(20221105 2112) ((emacs (24 3)) (php-mode (1 22 3))) "Interface to PHPStan" single ((:commit . "8b4be09defe5856a1855c976474ada67557780cd") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "tools" "php") (:url . "https://github.com/emacs-php/phpstan.el"))]) + (phpstan . [(20230404 1351) ((emacs (24 3)) (compat (29)) (php-mode (1 22 3)) (php-runtime (0 2))) "Interface to PHPStan" single ((:commit . "6dc8f1df29f22f0b0ef839c66822d48e2c7b1848") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "tools" "php") (:url . "https://github.com/emacs-php/phpstan.el"))]) (phpt-mode . [(20190512 1809) ((emacs (25)) (polymode (0 1 5)) (php-mode (1 21 2))) "Major mode for editing PHPT test code" single ((:commit . "deb386f1a81003074c476f15e1975d445ff6df01") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "languages" "php") (:url . "https://github.com/emacs-php/phpt-mode"))]) (phpunit . [(20230124 743) ((s (1 12 0)) (f (0 19 0)) (pkg-info (0 6)) (cl-lib (0 5)) (emacs (24 3))) "Launch PHP unit tests using phpunit" tar ((:commit . "4a36906344c0abc11f48cc08cd8d50a9f46963f8") (:authors ("Nicolas Lamirault" . "nicolas.lamirault@gmail.com") ("Eric Hansen" . "hansen.c.eric@gmail.com")) (:maintainer "Nicolas Lamirault" . "nicolas.lamirault@gmail.com") (:keywords "tools" "php" "tests" "phpunit") (:url . "https://github.com/nlamirault/phpunit.el"))]) (pianobar . [(20201002 1756) nil "thin wrapper for Pianobar, a Pandora Radio client" single ((:commit . "d708417608df4f09ee565fddaad03dfe181829a8") (:authors ("Aaron Griffith" . "aargri@gmail.com")) (:maintainer "Aaron Griffith" . "aargri@gmail.com") (:url . "http://github.com/agrif/pianobar.el"))]) @@ -3950,7 +3974,7 @@ (plain-org-wiki . [(20201217 1027) ((emacs (24 3)) (ivy (0 12 0))) "Simple jump-to-org-files in a directory package" single ((:commit . "faeeb54ca808bbf0f4380a938e75805b7a78dbf7") (:authors ("Oleh Krehel" . "ohwoeowho@gmail.com")) (:maintainer "Oleh Krehel" . "ohwoeowho@gmail.com") (:keywords "convenience") (:url . "https://github.com/abo-abo/plain-org-wiki"))]) (plain-theme . [(20171124 410) ((emacs (24))) "Plain theme without syntax highlighting" single ((:commit . "2609a811335d58cfb73a65d6307c156fe09037d3"))]) (plan9-theme . [(20180804 1441) nil "A color theme for Emacs based on Plan9" single ((:commit . "4c1050b8ed42e0f99ef64c77ec370a786bd0003c") (:authors ("John Louis Del Rosario" . "john2x@gmail.com")) (:maintainer "John Louis Del Rosario" . "john2x@gmail.com") (:url . "https://github.com/john2x/plan9-theme.el"))]) - (planemo-mode . [(20201216 1122) ((emacs (27 1)) (dash (2 17 0))) "Minor mode for editing Galaxy XML files" single ((:commit . "9a981f79a2727f87689ae5a07368c41d35902a67") (:authors ("Mehmet Tekman")) (:maintainer "Mehmet Tekman") (:keywords "outlines") (:url . "https://gitlab.com/mtekman/planemo-mode.el"))]) + (planemo-mode . [(20230227 1139) ((emacs (27 1)) (dash (2 17 0))) "Minor mode for editing Galaxy XML files" single ((:commit . "537ebe40688ca8f3786aa1e9842265e6f34584d2") (:authors ("Mehmet Tekman")) (:maintainer "Mehmet Tekman") (:keywords "outlines") (:url . "https://gitlab.com/mtekman/planemo-mode.el"))]) (planet-theme . [(20161031 217) ((emacs (24))) "A dark theme inspired by Gmail's 'Planets' theme of yore" single ((:commit . "b0a310ff36565fe22224c407cf59569986698a32") (:authors ("Charlie McMackin" . "charlie.mac@gmail.com")) (:maintainer "Charlie McMackin" . "charlie.mac@gmail.com") (:keywords "themes") (:url . "https://github.com/cmack/emacs-planet-theme"))]) (plantuml-mode . [(20191102 2056) ((dash (2 0 0)) (emacs (25 0))) "Major mode for PlantUML" single ((:commit . "ea45a13707abd2a70df183f1aec6447197fc9ccc") (:authors ("Zhang Weize (zwz)")) (:maintainer "Carlo Sciolla (skuro)") (:keywords "uml" "plantuml" "ascii"))]) (plaster . [(20180127 2050) ((emacs (24 3))) "Pasting to a plaster host with buffers." single ((:commit . "11eb23920410818fe444887b97ad4c8722d66c85") (:authors ("Nicolas Hafner" . "shinmera@tymoon.eu")) (:maintainer "Nicolas Hafner" . "shinmera@tymoon.eu") (:keywords "convenience" "paste service") (:url . "http://github.com/shirakumo/plaster/"))]) @@ -3976,23 +4000,23 @@ (podcaster . [(20200607 1054) ((cl-lib (0 5))) "Podcast client" single ((:commit . "7a21173da0c57e6aa41dbdc33383047386b35eb5") (:authors ("DarkSun" . "lujun9972@gmail.com")) (:maintainer "DarkSun" . "lujun9972@gmail.com") (:url . "https://github.com/lujun9972/podcaster"))]) (poe-lootfilter-mode . [(20190330 1117) ((emacs (24 3))) "Major mode for editing Path of Exile lootfilters" single ((:commit . "5ef06684cb2b17b090ee1f303c2b789fa71bc106") (:authors ("Jeremiah Dodds" . "jeremiah.dodds@gmail.com")) (:maintainer "Jeremiah Dodds" . "jeremiah.dodds@gmail.com") (:keywords "languages" "games") (:url . "https://github.com/jdodds/poe-lootfilter-mode"))]) (poet-theme . [(20200606 2343) ((emacs (24 1))) "A theme for prose" tar ((:commit . "16eb694f0755c04c4db98614d0eca1199fddad70") (:authors ("Kunal Bhalla" . "bhalla.kunal@gmail.com")) (:maintainer "Kunal Bhalla" . "bhalla.kunal@gmail.com") (:keywords "faces" "theme" "prose") (:url . "https://github.com/kunalb/poet/"))]) - (poetry . [(20220915 801) ((transient (0 2 0)) (pyvenv (1 2)) (emacs (25 1))) "Interface to Poetry" single ((:commit . "3da3990d3cea17f84c90257cc206540d4ea1b6c6") (:authors ("Gaby Launay" . "gaby.launay@protonmail.com")) (:maintainer "Gaby Launay" . "gaby.launay@protonmail.com") (:keywords "python" "tools") (:url . "https://github.com/galaunay/poetry.el"))]) + (poetry . [(20230304 1540) ((transient (0 2 0)) (pyvenv (1 2)) (emacs (25 1))) "Interface to Poetry" single ((:commit . "5ca52b221e57bb9dce7c89f62e7b01da1346a273") (:authors ("Gaby Launay" . "gaby.launay@protonmail.com")) (:maintainer "Gaby Launay" . "gaby.launay@protonmail.com") (:keywords "python" "tools") (:url . "https://github.com/galaunay/poetry.el"))]) (point-pos . [(20170421 1632) nil "Save and restore point positions" single ((:commit . "4cd0f8c8d1296c5c64f708b6a5835e8520c51b68") (:authors ("Alex Kost" . "alezost@gmail.com")) (:maintainer "Alex Kost" . "alezost@gmail.com") (:keywords "tools" "convenience") (:url . "https://github.com/alezost/point-pos.el"))]) (point-stack . [(20200427 107) nil "Back and forward navigation through buffer locations" single ((:commit . "cddcea2c91038710c245819b3cda2dd739726134") (:authors ("Matt Harrison" . "matthewharrison@gmail.com") ("Dmitry Gutov" . "dgutov@yandex.ru")) (:maintainer "Matt Harrison" . "matthewharrison@gmail.com"))]) (poke-line . [(20201023 247) ((emacs (24 3))) "Minor mode to show position in a buffer using a Pokemon" tar ((:commit . "8d484dbaa1215d902fbd1e3c9163b39a43ec532a") (:authors ("Ryan Miller" . "ryan@devopsmachine.com")) (:maintainer "Ryan Miller" . "ryan@devopsmachine.com") (:keywords "pokemon" "fun" "mode-line" "mouse") (:url . "https://github.com/RyanMillerC/poke-line/"))]) (pollen-mode . [(20220904 447) ((emacs (24 3)) (cl-lib (0 5))) "major mode for editing pollen files" single ((:commit . "19174fab69ce4d2ae903ef2c3da44054e8b84268") (:authors ("Junsong Li ")) (:maintainer "Junsong Li") (:keywords "languages" "pollen" "pollenpub") (:url . "https://github.com/lijunsong/pollen-mode"))]) - (poly-R . [(20210930 1921) ((emacs (25)) (polymode (0 2 2)) (poly-markdown (0 2 2)) (poly-noweb (0 2 2))) "Various polymodes for R language" single ((:commit . "e4a39caaf48e1c2e5afab3865644267b10610537") (:authors ("Vitalie Spinu")) (:maintainer "Vitalie Spinu") (:keywords "languages" "multi-modes") (:url . "https://github.com/polymode/poly-R"))]) + (poly-R . [(20230303 1140) ((emacs (25)) (polymode (0 2 2)) (poly-markdown (0 2 2)) (poly-noweb (0 2 2))) "Various polymodes for R language" single ((:commit . "f2e85391efe2d5a9516687422b4784d185af5241") (:authors ("Vitalie Spinu")) (:maintainer "Vitalie Spinu") (:keywords "languages" "multi-modes") (:url . "https://github.com/polymode/poly-R"))]) (poly-ansible . [(20220113 1656) ((ansible (0 2)) (ansible-doc (0 4)) (jinja2-mode (0 2)) (polymode (0 1 5)) (yaml-mode (0 0 13))) "Polymode for Ansible: Jinja2 in YAML" tar ((:commit . "6d74fe80b7e61a35aa0fa36a520eaf5c9c027c51") (:authors ("Peter Oliver" . "poly-ansible@mavit.org.uk")) (:maintainer "Peter Oliver" . "poly-ansible@mavit.org.uk") (:keywords "languages") (:url . "https://gitlab.com/mavit/poly-ansible/"))]) (poly-erb . [(20200316 1314) ((emacs (25)) (polymode (0 2 2))) "Polymode for erb" single ((:commit . "56c744b8d87d8cbe0aba2696d4e8525afc4aa0e8") (:authors ("Siavash Sajjadi and Vitalie Spinu")) (:maintainer "Vitalie Spinu") (:keywords "emacs") (:url . "https://github.com/polymode/poly-erb"))]) (poly-markdown . [(20230202 1210) ((emacs (25)) (polymode (0 2 2)) (markdown-mode (2 3))) "Polymode for markdown-mode" single ((:commit . "98695eb7ca4ca11dcec71a1cab64903bbf79b4d3") (:authors ("Vitalie Spinu")) (:maintainer "Vitalie Spinu") (:keywords "emacs") (:url . "https://github.com/polymode/poly-markdown"))]) (poly-noweb . [(20200316 1315) ((emacs (25)) (polymode (0 2 2))) "Polymode for noweb" single ((:commit . "3b0cd36ca9a707e8a09337a3468fa85d81fc461c") (:authors ("Vitalie Spinu")) (:maintainer "Vitalie Spinu") (:keywords "languages" "multi-modes") (:url . "https://github.com/polymode/poly-noweb"))]) - (poly-org . [(20220201 1514) ((emacs (25)) (polymode (0 2 2))) "Polymode for org-mode" single ((:commit . "01fd0f4b7eaeabf070af831f4825993210f64f2e") (:authors ("Vitalie Spinu")) (:maintainer "Vitalie Spinu") (:keywords "languages" "multi-modes") (:url . "https://github.com/polymode/poly-org"))]) + (poly-org . [(20230317 1220) ((emacs (25)) (polymode (0 2 2))) "Polymode for org-mode" single ((:commit . "5ca02279a4e6f5025cd2c7b1196058d3e74dc5d5") (:authors ("Vitalie Spinu")) (:maintainer "Vitalie Spinu") (:keywords "languages" "multi-modes") (:url . "https://github.com/polymode/poly-org"))]) (poly-rst . [(20210418 1009) ((emacs (25)) (polymode (0 2 2))) "poly-rst-mode polymode" single ((:commit . "e71f2ae6a00683cdb8006f953e5db0673043e144") (:authors ("Gustaf Waldemarson, Vitalie Spinu")) (:maintainer "Gustaf Waldemarson, Vitalie Spinu") (:keywords "languages" "multi-modes") (:url . "https://github.com/polymode/poly-rst"))]) (poly-ruby . [(20180905 929) ((emacs (25)) (polymode (0 1 2))) "Provides poly-ruby-mode" single ((:commit . "794ebb926ace23e9c1398da934701951432dcea2") (:authors ("Akinori MUSHA" . "knu@iDaemons.org")) (:maintainer "Akinori MUSHA" . "knu@iDaemons.org") (:keywords "languages") (:url . "https://github.com/knu/poly-ruby.el"))]) (poly-slim . [(20200316 1316) ((emacs (25)) (polymode (0 2 2)) (slim-mode (1 1))) "Polymodes for slim" single ((:commit . "9e9b5164c68955974fd5f5d220aec5af9b5ba3ae") (:authors ("Siavash Sajjadi and Vitalie Spinu")) (:maintainer "Vitalie Spinu") (:keywords "emacs") (:url . "https://github.com/polymode/poly-slim"))]) (poly-wdl . [(20190712 529) ((emacs (25)) (polymode (0 2)) (wdl-mode (20170709))) "Polymode for WDL" single ((:commit . "fe2ee0c441795c35a8c127fa1f7006a5f251f564") (:authors ("Jean Monlong" . "jean.monlong@gmail.com")) (:maintainer "Jean Monlong" . "jean.monlong@gmail.com") (:keywords "languages") (:url . "https://github.com/jmonlong/poly-wdl"))]) (polybar-sesman . [(20210901 1336) ((emacs (25 1)) (dash (2 19 1)) (sesman (0 3 0))) "Display active sesman connections in polybar" single ((:commit . "5b8ff640ada92da98400206ba9a61140093a823f") (:authors ("Mark Dawson" . "markgdawson@gmail.com")) (:maintainer "Mark Dawson" . "markgdawson@gmail.com") (:keywords "project" "convenience") (:url . "https://github.com/markgdawson/polybar-sesman.el"))]) - (polymode . [(20220820 1630) ((emacs (25))) "Extensible framework for multiple major modes" tar ((:commit . "63d2c2184941902e2358d0e9b0deb17b943db61a") (:authors ("Vitalie Spinu")) (:maintainer "Vitalie Spinu" . "spinuvit@gmail.com") (:keywords "languages" "multi-modes" "processes") (:url . "https://github.com/polymode/polymode"))]) + (polymode . [(20230317 1218) ((emacs (25))) "Extensible framework for multiple major modes" tar ((:commit . "ca060e081a1f849a880732670dc15370ac987b89") (:authors ("Vitalie Spinu")) (:maintainer "Vitalie Spinu" . "spinuvit@gmail.com") (:keywords "languages" "multi-modes" "processes") (:url . "https://github.com/polymode/polymode"))]) (pomidor . [(20220714 1932) ((emacs (24 3)) (alert (1 2)) (dash (2 17 0))) "Simple and cool pomodoro timer" tar ((:commit . "394a52f95587b1d10d0c3bdca503d2cc876db35b") (:authors ("TatriX" . "tatrics@gmail.com")) (:maintainer "TatriX" . "tatrics@gmail.com") (:keywords "tools" "time" "applications" "pomodoro technique") (:url . "https://github.com/TatriX/pomidor"))]) (pomm . [(20220815 824) ((emacs (27 1)) (alert (1 2)) (seq (2 22)) (transient (0 3 0))) "Pomodoro and Third Time timers" tar ((:commit . "42f03d6ff29109038b31a8647f1acdc80fb867be") (:authors ("Korytov Pavel" . "thexcloud@gmail.com")) (:maintainer "Korytov Pavel" . "thexcloud@gmail.com") (:url . "https://github.com/SqrtMinusOne/pomm.el"))]) (pomodoro . [(20210225 2018) nil "A timer for the Pomodoro Technique" single ((:commit . "ed888b24d0b89a5dec6f5278b1064c530c827321") (:authors ("David Kerschner" . "dkerschner@gmail.com")) (:maintainer "David Kerschner" . "dkerschner@gmail.com"))]) @@ -4001,7 +4025,7 @@ (ponylang-mode . [(20211015 331) ((emacs (25 1)) (dash (2 17 0)) (hydra (0 15 0)) (hl-todo (3 1 2)) (yafolding (0 4 1)) (yasnippet (0 14 0)) (company-ctags (0 0 4)) (rainbow-delimiters (2 1 4)) (fill-column-indicator (1 90))) "A major mode for the Pony programming language" single ((:commit . "1abf04bc8f4f09a6add4b587c7cf5ca23735e7c0") (:keywords "languages" "programming") (:url . "https://github.com/ponylang/ponylang-mode"))]) (pophint . [(20200420 1429) ((log4e (0 3 3)) (yaxception (0 3))) "Provide navigation using pop-up tips, like Firefox's Vimperator Hint Mode" tar ((:commit . "5e13da4578ae7ba00e6f7bae31eb546d713cc19d") (:authors ("Hiroaki Otsu" . "ootsuhiroaki@gmail.com")) (:maintainer "Hiroaki Otsu" . "ootsuhiroaki@gmail.com") (:keywords "popup") (:url . "https://github.com/aki2o/emacs-pophint"))]) (poporg . [(20170403 751) nil "Pop a comment or string to an empty buffer for text editing" single ((:commit . "2c58d68c81ecca4140bf179f19ed153ec804b65a") (:authors ("François Pinard" . "pinard@iro.umontreal.ca") ("Joseph Rabinoff" . "rabinoff@post.harvard.edu")) (:maintainer "Joseph Rabinoff" . "rabinoff@post.harvard.edu") (:keywords "outlines" "tools") (:url . "https://github.com/QBobWatson/poporg"))]) - (popper . [(20230120 751) ((emacs (26 1))) "Summon and dismiss buffers as popups" tar ((:commit . "da70c8296a3b3b69626b11f2d202a38075f00c7b") (:authors ("Karthik Chikmagalur" . "karthik.chikmagalur@gmail.com")) (:maintainer "Karthik Chikmagalur" . "karthik.chikmagalur@gmail.com") (:keywords "convenience") (:url . "https://github.com/karthink/popper"))]) + (popper . [(20230302 2055) ((emacs (26 1))) "Summon and dismiss buffers as popups" tar ((:commit . "76b1a1f1bce412296d564056c76dd174bcf8ec64") (:authors ("Karthik Chikmagalur" . "karthik.chikmagalur@gmail.com")) (:maintainer "Karthik Chikmagalur" . "karthik.chikmagalur@gmail.com") (:keywords "convenience") (:url . "https://github.com/karthink/popper"))]) (popup . [(20221231 1634) ((emacs (24 3))) "Visual Popup User Interface" single ((:commit . "71cede0588c10526f88dd0375bce776ec2eed05e") (:authors ("Tomohiro Matsuyama" . "m2ym.pub@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "lisp") (:url . "https://github.com/auto-complete/popup-el"))]) (popup-complete . [(20141109 308) ((popup (0 5 0))) "completion with popup" single ((:commit . "e362d4a005b36646ffbaa6be604e9e31bc406ca9") (:authors ("Syohei YOSHIDA" . "syohex@gmail.com")) (:maintainer "Syohei YOSHIDA" . "syohex@gmail.com") (:url . "https://github.com/syohex/emacs-popup-complete"))]) (popup-edit-menu . [(20170404 1425) ((emacs (24))) "a popup context edit menu package" single ((:commit . "925600a6e29183841199e866cf55e566a6a1b002") (:authors ("Debugfan Chin" . "debugfanchin@gmail.com")) (:maintainer "Debugfan Chin" . "debugfanchin@gmail.com") (:keywords "lisp" "pop-up" "context" "edit" "menu"))]) @@ -4012,7 +4036,7 @@ (portage-navi . [(20141208 1355) ((concurrent (0 3 1)) (ctable (0 1 2))) "portage viewer" single ((:commit . "8016c3e99fe6cef101d479a3d69185796b22ca2f") (:authors ("")) (:maintainer "") (:keywords "tools" "gentoo") (:url . "https://github.com/kiwanami/emacs-portage-navi"))]) (porthole . [(20200404 1454) ((emacs (26)) (web-server (0 1 2)) (f (0 19 0)) (json-rpc-server (0 1 2))) "RPC Servers in Emacs" single ((:commit . "9e68b419acf9245208f8094e10041b7f04511473") (:authors ("GitHub user \"Jcaw\"")) (:maintainer "GitHub user \"Jcaw\"") (:keywords "comm" "rpc" "http" "json") (:url . "https://github.com/jcaw/porthole"))]) (pos-tip . [(20220715 1020) nil "Show tooltip at point" single ((:commit . "bfe74204d1201a33ace81898e7c485382817510a") (:authors ("S. Irie")) (:maintainer "S. Irie") (:keywords "tooltip"))]) - (posframe . [(20230212 808) ((emacs (26 1))) "Pop a posframe (just a frame) at point" tar ((:commit . "06b939cfb06168782fc378043ff35bd7fec203b8") (:authors ("Feng Shu" . "tumashu@163.com")) (:maintainer "Feng Shu" . "tumashu@163.com") (:keywords "convenience" "tooltip") (:url . "https://github.com/tumashu/posframe"))]) + (posframe . [(20230321 211) ((emacs (26 1))) "Pop a posframe (just a frame) at point" tar ((:commit . "b00f1386ca4e251a5c3d8985d313217e56e42a7e") (:authors ("Feng Shu" . "tumashu@163.com")) (:maintainer "Feng Shu" . "tumashu@163.com") (:keywords "convenience" "tooltip") (:url . "https://github.com/tumashu/posframe"))]) (posix-manual . [(20200301 1103) ((emacs (24))) "POSIX manual page lookup" tar ((:commit . "ebaacd7266ae7a66605317f57b9f42e9cfb2ce1e") (:authors ("Lassi Kortela" . "lassi@lassi.io")) (:maintainer "Lassi Kortela" . "lassi@lassi.io") (:keywords "languages" "util") (:url . "https://github.com/lassik/emacs-posix-manual"))]) (postcss-sorting . [(20180211 956) ((emacs (24))) "postcss-sorting interface" single ((:commit . "deb0c935d2904c11a965758a9aee5a0e905f21fc") (:authors ("Peiwen Lu" . "hi@peiwen.lu")) (:maintainer "Peiwen Lu" . "hi@peiwen.lu") (:url . "https://github.com/P233/postcss-sorting.el"))]) (pov-mode . [(20161115 743) nil "Major mode for editing POV-Ray scene files." tar ((:commit . "9fc1db3aab7c27155674dd1a87ec62606035d074") (:authors ("Peter Boettcher" . "pwb@andrew.cmu.edu")) (:maintainer "Marco Pessotto" . "melmothx@gmail.com") (:keywords "pov" "povray"))]) @@ -4021,11 +4045,11 @@ (powerline . [(20221110 1956) ((cl-lib (0 2))) "Rewrite of Powerline" tar ((:commit . "c35c35bdf5ce2d992882c1f06f0f078058870d4a") (:authors ("Donald Ephraim Curtis" . "dcurtis@milkbox.net")) (:maintainer "Donald Ephraim Curtis" . "dcurtis@milkbox.net") (:keywords "mode-line") (:url . "http://github.com/milkypostman/powerline/"))]) (powerline-evil . [(20190603 340) ((evil (1 0 8)) (powerline (2 3))) "Utilities for better Evil support for Powerline" tar ((:commit . "b77e2cf571e9990734f2b30d826f3a362b559fd1") (:authors ("Chris Johnson" . "chris@christophermjohnson.net")) (:maintainer "Chris Johnson" . "chris@christophermjohnson.net") (:keywords "evil" "mode-line" "powerline") (:url . "http://github.com/johnson-christopher/powerline-evil/"))]) (powershell . [(20220805 1712) ((emacs (24))) "Mode for editing PowerShell scripts" single ((:commit . "f2da15857e430206e215a3c65289b4058ae3c976") (:authors ("Frédéric Perrin ")) (:maintainer "Frédéric Perrin ") (:keywords "powershell" "languages") (:url . "http://github.com/jschaf/powershell.el"))]) - (powerthesaurus . [(20220414 1453) ((emacs (24)) (request (0 3 0)) (s (1 12 0))) "Powerthesaurus integration" single ((:commit . "88bc5229cba1604c8f74db0a1456d99259d538cc") (:keywords "convenience" "writing") (:url . "http://github.com/SavchenkoValeriy/emacs-powerthesaurus"))]) + (powerthesaurus . [(20230402 1904) ((emacs (26 1)) (jeison (1 0 0)) (s (1 13 0))) "Powerthesaurus integration" single ((:commit . "782df1d92f95acc100bc33d4b5f17fe6bad88682") (:keywords "convenience" "writing") (:url . "http://github.com/SavchenkoValeriy/emacs-powerthesaurus"))]) (ppcompile . [(20220619 1535) ((emacs (25 1))) "Ping-pong compile projects on remote machines" single ((:commit . "4c287c9ebc0e78dbbe75195bb5eb3fe82e0bfaff") (:authors ("Guangwang Huang" . "whatacold@gmail.com")) (:maintainer "Guangwang Huang") (:keywords "tools") (:url . "https://github.com/whatacold/ppcompile"))]) (ppd-sr-speedbar . [(20151108 1224) ((sr-speedbar (20140914 2339)) (project-persist-drawer (0 0 4))) "Sr Speedbar adaptor for project-persist-drawer." tar ((:commit . "19d3e924407f40a6bb38c8fe427a159af755adce") (:authors ("Robert Dallas Gray")) (:maintainer "Robert Dallas Gray") (:keywords "projects" "drawer") (:url . "https://github.com/rdallasgrayppd-sr-speedbar"))]) (ppp . [(20220211 1529) ((emacs (25 1))) "Extended pretty printer for Emacs Lisp" single ((:commit . "d5d854c3006dfd268e62c7f91c2aad6f86a505b5") (:authors ("Naoya Yamashita" . "conao3@gmail.com")) (:maintainer "Naoya Yamashita" . "conao3@gmail.com") (:keywords "tools") (:url . "https://github.com/conao3/ppp.el"))]) - (pr-review . [(20220815 1610) ((emacs (27 1)) (magit-section (3 2)) (magit (3 2)) (markdown-mode (2 5)) (ghub (3 5))) "Review github PR" tar ((:commit . "8033aed0f6c16464b822489b137ba2f3ffe787de") (:authors ("Yikai Zhao" . "yikai@z1k.dev")) (:maintainer "Yikai Zhao" . "yikai@z1k.dev") (:keywords "tools") (:url . "https://github.com/blahgeek/emacs-pr-review"))]) + (pr-review . [(20230320 419) ((emacs (27 1)) (magit-section (3 2)) (magit (3 2)) (markdown-mode (2 5)) (ghub (3 5))) "Review github PR" tar ((:commit . "f11fe37fbbb68485bc3b0ca692f0175e66293f09") (:authors ("Yikai Zhao" . "yikai@z1k.dev")) (:maintainer "Yikai Zhao" . "yikai@z1k.dev") (:keywords "tools") (:url . "https://github.com/blahgeek/emacs-pr-review"))]) (prassee-theme . [(20180709 1004) ((emacs (24))) "A high contrast color theme for Emacs." single ((:commit . "81126f69cdbaab836c00ae7a49aaf89d4229fde1") (:authors ("Prassee " . "prassee.sathian@gmail.com")) (:maintainer "Prassee " . "prassee.sathian@gmail.com") (:keywords "dark" "high-contrast" "faces") (:url . "https://github.com/prassee/prassee-emacs-theme"))]) (prefab . [(20220828 2015) ((emacs (27 1)) (f (0 2 0)) (transient (0 3 7))) "Integration for project generation tools like cookiecutter" single ((:commit . "328c763d67cd53875d729af0bcb89d412455cf60") (:authors ("Laurence Warne")) (:maintainer "Laurence Warne") (:url . "https://github.com/laurencewarne/prefab.el"))]) (preproc-font-lock . [(20151107 2018) nil "Highlight C-style preprocessor directives." single ((:commit . "565fda9f5fdeb0598986174a07e9fb09f7604397") (:authors ("Anders Lindgren")) (:maintainer "Anders Lindgren") (:keywords "c" "languages" "faces") (:url . "https://github.com/Lindydancer/preproc-font-lock"))]) @@ -4064,7 +4088,7 @@ (project-rootfile . [(20220708 1403) ((emacs (27 1))) "Extension of project.el to detect project with root file" single ((:commit . "9259708307c9da6b06f04f5b34ccd28f1fba5eaa") (:authors ("Taiki Sugawara" . "buzz.taiki@gmail.com")) (:maintainer "Taiki Sugawara" . "buzz.taiki@gmail.com") (:url . "https://github.com/buzztaiki/project-rootfile.el"))]) (project-shells . [(20210625 647) ((emacs (24 3)) (seq (2 19))) "Manage the shell buffers of each project" single ((:commit . "900369828f1a213c60a2207a71d46bc43fd5405c") (:authors ("\"Huang, Ying\"" . "huang.ying.caritas@gmail.com")) (:maintainer "\"Huang, Ying\"" . "huang.ying.caritas@gmail.com") (:keywords "processes" "terminals") (:url . "https://github.com/hying-caritas/project-shells"))]) (project-tab-groups . [(20220720 2109) ((emacs (28 1))) "Support a \"one tab group per project\" workflow" single ((:commit . "2d348279876f3073176048d903f9672f3c933ca5") (:authors ("Fritz Grabo" . "hello@fritzgrabo.com")) (:maintainer "Fritz Grabo" . "hello@fritzgrabo.com") (:keywords "convenience") (:url . "https://github.com/fritzgrabo/project-tab-groups"))]) - (projectile . [(20230219 647) ((emacs (25 1))) "Manage and navigate projects in Emacs easily" single ((:commit . "fd257811c46f89f53143dd0ccbc134fc9459d6bb") (:authors ("Bozhidar Batsov" . "bozhidar@batsov.dev")) (:maintainer "Bozhidar Batsov" . "bozhidar@batsov.dev") (:keywords "project" "convenience") (:url . "https://github.com/bbatsov/projectile"))]) + (projectile . [(20230317 1101) ((emacs (25 1))) "Manage and navigate projects in Emacs easily" single ((:commit . "271007c6611fcb08ddd326d7de9727c2ad5ef265") (:authors ("Bozhidar Batsov" . "bozhidar@batsov.dev")) (:maintainer "Bozhidar Batsov" . "bozhidar@batsov.dev") (:keywords "project" "convenience") (:url . "https://github.com/bbatsov/projectile"))]) (projectile-codesearch . [(20180508 1522) ((codesearch (20171122 431)) (projectile (20150405 126))) "Integration of codesearch into projectile" single ((:commit . "e40efc62e9333db0593bd81b5c78d08b19bfb193") (:authors ("Austin Bingham" . "austin.bingham@gmail.com")) (:maintainer "Austin Bingham" . "austin.bingham@gmail.com") (:keywords "tools" "development" "search") (:url . "https://github.com/abingham/emacs-codesearch"))]) (projectile-git-autofetch . [(20200820 2028) ((emacs (25 1)) (projectile (0 14 0))) "automatically fetch git repositories" single ((:commit . "423ed5fa6508c4edc0a837bb585c7e77e99876be") (:authors ("Andreas Müller" . "code@0x7.ch")) (:maintainer "Andreas Müller" . "code@0x7.ch") (:keywords "tools" "vc") (:url . "https://github.com/andrmuel/projectile-git-autofetch"))]) (projectile-rails . [(20221231 1643) ((emacs (25 1)) (projectile (0 12 0)) (inflections (1 1)) (inf-ruby (2 2 6)) (f (0 13 0)) (rake (0 3 2)) (dash (2 18 1))) "Minor mode for Rails projects based on projectile-mode" single ((:commit . "701784df7befe17b861f1b53fe9cbc59d0b94b9f") (:authors ("Adam Sokolnicki" . "adam.sokolnicki@gmail.com")) (:maintainer "Adam Sokolnicki" . "adam.sokolnicki@gmail.com") (:keywords "rails" "projectile") (:url . "https://github.com/asok/projectile-rails"))]) @@ -4080,18 +4104,18 @@ (prompt-text . [(20190408 310) nil "Configure your minibuffer prompt" single ((:commit . "b842bf13c53d0a2bd2bc7a00d37cc713d69fa9e9") (:authors ("10sr <8slashes+el [at] gmail [dot] com>")) (:maintainer "10sr <8slashes+el [at] gmail [dot] com>") (:keywords "utility" "minibuffer") (:url . "https://github.com/10sr/prompt-text-el"))]) (prompts . [(20160916 1041) ((dash (2 13 0))) "utilities for working with text prompts." single ((:commit . "1cd5e732ff2a86b47836eb7252e5b59cd4b6ab26") (:authors ("Ben Moon" . "guiltydolphin@gmail.com")) (:maintainer "Ben Moon" . "guiltydolphin@gmail.com") (:keywords "input" "minibuffer") (:url . "https://github.com/guiltydolphin/prompts.el"))]) (pronto . [(20200218 1633) ((emacs (24))) "Compilation mode for pronto stylechecks" single ((:commit . "c0cd13d8219879610b7fe284b182a9db4d3d40b3") (:authors ("Julian Rubisch" . "julian@julianrubisch.at")) (:maintainer "Julian Rubisch" . "julian@julianrubisch.at") (:keywords "processes" "tools") (:url . "https://github.com/julianrubisch/pronto.el"))]) - (proof-general . [(20230130 1024) ((emacs (25 2))) "A generic Emacs interface for proof assistants" tar ((:commit . "8416875696cb0c4283e96fe721d343277882ecea") (:maintainer nil . "proof-general-maintainers@groupes.renater.fr") (:url . "https://proofgeneral.github.io/"))]) + (proof-general . [(20230407 909) ((emacs (25 2))) "A generic Emacs interface for proof assistants" tar ((:commit . "911cf014b899212815c2ec8d3e8c8b88be0df57b") (:maintainer nil . "proof-general-maintainers@groupes.renater.fr") (:url . "https://proofgeneral.github.io/"))]) (prop-menu . [(20150728 1118) ((emacs (24 3)) (cl-lib (0 5))) "Create and display a context menu based on text and overlay properties" single ((:commit . "50b102c1c0935fd3e0c465feed7f27d66b21cdf3") (:authors ("David Christiansen" . "david@davidchristiansen.dk")) (:maintainer "David Christiansen" . "david@davidchristiansen.dk") (:keywords "convenience") (:url . "https://github.com/david-christiansen/prop-menu-el"))]) (propfont-mixed . [(20150113 2211) ((emacs (24)) (cl-lib (0 5))) "Use proportional fonts with space-based indentation." single ((:commit . "0b461ef4754a469610dba71874a34b6da42176bf") (:authors ("Kirill Ignatiev ")) (:maintainer "Kirill Ignatiev ") (:keywords "faces") (:url . "https://github.com/ikirill/propfont-mixed"))]) (proportional . [(20221205 1417) ((emacs (25 1))) "use a proportional font everywhere" single ((:commit . "6b675694292a5dbebb52b6196e8ccee6e3a73042") (:authors ("Johannes Goslar")) (:maintainer "Johannes Goslar") (:keywords "faces") (:url . "https://github.com/ksjogo/proportional"))]) (prosjekt . [(20151127 1416) ((dash (2 8 0))) "a software project tool for emacs" tar ((:commit . "a864a8be5842223043702395f311e3350c28e9db") (:authors ("Austin Bingham" . "austin.bingham@gmail.com")) (:maintainer "Austin Bingham" . "austin.bingham@gmail.com") (:url . "https://github.com/abingham/prosjekt"))]) - (protobuf-mode . [(20230216 1713) nil "major mode for editing protocol buffers." single ((:commit . "a847a8dc4ba1d99e7ba917146c84438b4de7d085") (:authors ("Alexandre Vassalotti" . "alexandre@peadrop.com")) (:maintainer "Alexandre Vassalotti" . "alexandre@peadrop.com") (:keywords "google" "protobuf" "languages"))]) + (protobuf-mode . [(20230310 1557) nil "major mode for editing protocol buffers." single ((:commit . "81f89d509d6771dcccb619cbe26ac86cec472582") (:authors ("Alexandre Vassalotti" . "alexandre@peadrop.com")) (:maintainer "Alexandre Vassalotti" . "alexandre@peadrop.com") (:keywords "google" "protobuf" "languages"))]) (protobuf-ts-mode . [(20230207 341) ((emacs (29))) "Tree sitter support for Protocol Buffers (proto3 only)" single ((:commit . "3076f25bd5ce05f4a4a5840506c3a5a2c0e839d9") (:authors ("ookami" . "mail@ookami.one")) (:maintainer "ookami" . "mail@ookami.one") (:keywords "protobuf" "languages" "tree-sitter") (:url . "https://git.ookami.one/cgit/protobuf-ts-mode"))]) (protocols . [(20170802 1132) ((cl-lib (0 5))) "Protocol database access functions." single ((:commit . "d0f7c4acb05465f1a0d4be54363bbd2802647e77") (:authors ("Dave Pearson" . "davep@davep.org")) (:maintainer "Dave Pearson" . "davep@davep.org") (:keywords "convenience" "net" "protocols") (:url . "https://github.com/davep/protocols.el"))]) - (proxy-mode . [(20220210 1410) ((emacs (25))) "A minor mode to toggle proxy." single ((:commit . "620e48c6afaf760d0ee9f5bdf583fd91cd9d0ec6") (:keywords "comm" "proxy") (:url . "https://repo.or.cz/proxy-mode.git"))]) + (proxy-mode . [(20230303 706) ((emacs (25))) "A minor mode to toggle proxy." single ((:commit . "eca6f0b8a17fcf9eb961ed0426f57a5b7ca4e1f6") (:keywords "comm" "proxy") (:url . "https://repo.or.cz/proxy-mode.git"))]) (psalm . [(20211002 1552) ((emacs (24 3)) (php-mode (1 22 3))) "Interface to Psalm" single ((:commit . "06434b938485e2540fc97ce6cb017a8a001c1f13") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "tools" "php") (:url . "https://github.com/emacs-php/psalm.el"))]) (psc-ide . [(20210219 2247) ((emacs (25)) (dash (2 18 0)) (company (0 8 7)) (s (1 10 0)) (flycheck (0 24)) (let-alist (1 0 4)) (seq (1 11))) "Minor mode for PureScript's IDE server." tar ((:commit . "ce97d719458ea099b40c02f05b6609601c727e66") (:authors ("Erik Post" . "erik@shinsetsu.nl") ("Dmitry Bushenko" . "d.bushenko@gmail.com") ("Christoph Hegemann" . "christoph.hegemann1337@gmail.com") ("Brian Sermons")) (:maintainer "Erik Post" . "erik@shinsetsu.nl") (:keywords "languages") (:url . "https://github.com/purescript-emacs/psc-ide-emacs"))]) - (psci . [(20191025 830) ((emacs (24 4)) (purescript-mode (13 10)) (dash (2 9 0))) "Major mode for purescript repl psci" tar ((:commit . "95fb5d14033add8fe9c8c6b4379758beb88af1d0") (:authors ("Antoine R. Dumont ")) (:maintainer "Antoine R. Dumont ") (:keywords "languages" "purescript" "psci" "repl") (:url . "https://github.com/purescript-emacs/emacs-psci"))]) + (psci . [(20230313 1333) ((emacs (24 4)) (purescript-mode (13 10)) (dash (2 9 0))) "Major mode for purescript repl psci" tar ((:commit . "9bb6a325325480be704130c9c69731631d2cf3a6") (:authors ("Antoine R. Dumont ")) (:maintainer "Antoine R. Dumont ") (:keywords "languages" "purescript" "psci" "repl") (:url . "https://github.com/purescript-emacs/emacs-psci"))]) (psession . [(20230105 503) ((emacs (24)) (cl-lib (0 5)) (async (1 9 3))) "Persistent save of elisp objects." single ((:commit . "ca5bed69f803aab71851c46b0118b66f58455b8a") (:authors ("Thierry Volpiatto" . "thierry.volpiatto@gmail.com")) (:maintainer "Thierry Volpiatto" . "thierry.volpiatto@gmail.com") (:url . "https://github.com/thierryvolpiatto/psession"))]) (psysh . [(20220607 1642) ((emacs (24 3)) (s (1 9 0)) (php-runtime (0 2))) "PsySH, PHP interactive shell (REPL)" single ((:commit . "796b26a5cd75df9d2ecb206718b310ff21787063") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "processes" "php") (:url . "https://github.com/emacs-php/psysh.el"))]) (pt . [(20161226 1959) nil "A front-end for pt, The Platinum Searcher." single ((:commit . "6d99b2aaded3ece3db19a20f4b8f1d4abe382622") (:authors ("Bailey Ling")) (:maintainer "Bailey Ling") (:keywords "pt" "ack" "ag" "grep" "search") (:url . "https://github.com/bling/pt.el"))]) @@ -4101,13 +4125,13 @@ (pubmed . [(20221023 930) ((emacs (26 1)) (esxml (0 3 4)) (s (1 12 0)) (unidecode (0 2))) "Interface to PubMed" tar ((:commit . "b2fbc124cabf0d373845763adf882e9d89ff5daa") (:authors ("Folkert van der Beek" . "folkertvanderbeek@gmail.com")) (:maintainer "Folkert van der Beek" . "folkertvanderbeek@gmail.com") (:keywords "pubmed" "hypermedia") (:url . "https://gitlab.com/fvdbeek/emacs-pubmed"))]) (pueue . [(20230219 1558) ((emacs (28 1)) (with-editor (3 0 4))) "Interface for pueue" single ((:commit . "386e43d46cbf68470d040b422061ac2ba1629749") (:authors ("Valeriy Litkovskyy" . "vlr.ltkvsk@protonmail.com")) (:maintainer "Valeriy Litkovskyy" . "vlr.ltkvsk@protonmail.com") (:keywords "processes") (:url . "https://github.com/xFA25E/pueue"))]) (pug-mode . [(20211114 1645) ((emacs (24 4)) (cl-lib (0 5))) "Major mode for jade/pug template files" single ((:commit . "73f8c2f95eba695f701df20c8436f49abadebdc1") (:authors ("Nathan Weizenbaum")) (:maintainer "Henrik Lissner" . "contact@henrik.io") (:keywords "markup" "language" "jade" "pug") (:url . "https://github.com/hlissner/emacs-pug-mode"))]) - (pulseaudio-control . [(20230109 246) nil "Use `pactl' to manage PulseAudio volumes." single ((:commit . "34a6114357dbbc6b6720aa013e0f8a48f3739403") (:authors ("Alexis , Ellington Santos , Sergey Trofimov" . "sarg@sarg.org.ru")) (:maintainer "Alexis" . "flexibeast@gmail.com") (:keywords "multimedia" "hardware" "sound" "pulseaudio") (:url . "https://github.com/flexibeast/pulseaudio-control"))]) + (pulseaudio-control . [(20230316 1819) nil "Use `pactl' to manage PulseAudio volumes." single ((:commit . "e917e84661b0e2496b295f1bbfba6ad32a656527") (:authors ("Alexis , Ellington Santos , Sergey Trofimov , conses" . "contact@conses.eu")) (:maintainer "Alexis" . "flexibeast@gmail.com") (:keywords "multimedia" "hardware" "sound" "pulseaudio") (:url . "https://git.sr.ht/~flexibeast/pulseaudio-control"))]) (punctuality-logger . [(20141120 2031) nil "Punctuality logger for Emacs" single ((:commit . "d76c5d5589a4f8a94cc5537686d9a3b46ea7cc59") (:authors ("Philip Woods" . "elzairthesorcerer@gmail.com")) (:maintainer "Philip Woods" . "elzairthesorcerer@gmail.com") (:keywords "reminder" "calendar") (:url . "https://gitlab.com/elzair/punctuality-logger"))]) (pungi . [(20150222 1246) ((jedi (0 2 0 -3 2)) (pyvenv (1 5))) "Integrates jedi with virtualenv and buildout python environments" single ((:commit . "41c9f8b7795e083bfd63ba0d06c789c250998723") (:authors ("Matthew Russell" . "matthew.russell@horizon5.org")) (:maintainer "Matthew Russell" . "matthew.russell@horizon5.org") (:keywords "convenience"))]) (puni . [(20230214 1156) ((emacs (26 1))) "Parentheses Universalistic" single ((:commit . "a39a4ecac7279bed1a150a895bbc80baa7272888") (:authors ("Hao Wang" . "amaikinono@gmail.com")) (:maintainer "Hao Wang" . "amaikinono@gmail.com") (:keywords "convenience" "lisp" "tools") (:url . "https://github.com/AmaiKinono/puni"))]) (punpun-themes . [(20221121 1018) ((emacs (24 1))) "A set of bleak themes" tar ((:commit . "6a7e04de1ad9f7ba9074b7206bffc9241c33349c") (:authors ("Vasilij Schneidermann" . "mail@vasilij.de")) (:maintainer "Vasilij Schneidermann" . "mail@vasilij.de") (:url . "https://depp.brause.cc/punpun-themes"))]) (puppet-mode . [(20210305 645) ((emacs (24 1)) (pkg-info (0 4))) "Major mode for Puppet manifests" single ((:commit . "ab25cf379236f4e1bd4bc9c1d77a93c95800e9bf") (:authors ("Vox Pupuli" . "voxpupuli@groups.io") ("Bozhidar Batsov" . "bozhidar@batsov.com") ("Sebastian Wiesner" . "swiesner@lunaryorn.com") ("Russ Allbery" . "rra@stanford.edu")) (:maintainer "Vox Pupuli" . "voxpupuli@groups.io") (:keywords "languages") (:url . "https://github.com/voxpupuli/puppet-mode"))]) - (purescript-mode . [(20220901 954) ((emacs (25 1))) "A PureScript editing mode" tar ((:commit . "cf113871f98da672bd2e9ae58da9c852236f3934") (:authors ("1992 Simon Marlow") ("1997-1998 Graeme E Moss" . "gem@cs.york.ac.uk") ("Tommy Thorn" . "thorn@irisa.fr") ("2001-2002 Reuben Thomas (>=v1.4)") ("2003 Dave Love" . "fx@gnu.org") ("2014 Tim Dysinger" . "tim@dysinger.net")) (:maintainer "1992 Simon Marlow") (:keywords "faces" "files" "purescript") (:url . "https://github.com/purescript-emacs/purescript-mode"))]) + (purescript-mode . [(20230309 1301) ((emacs (25 1))) "A PureScript editing mode" tar ((:commit . "eacc61aaafe6055b5f278c9843558f220f18b153") (:authors ("1992 Simon Marlow") ("1997-1998 Graeme E Moss" . "gem@cs.york.ac.uk") ("Tommy Thorn" . "thorn@irisa.fr") ("2001-2002 Reuben Thomas (>=v1.4)") ("2003 Dave Love" . "fx@gnu.org") ("2014 Tim Dysinger" . "tim@dysinger.net")) (:maintainer "1992 Simon Marlow") (:keywords "faces" "files" "purescript") (:url . "https://github.com/purescript-emacs/purescript-mode"))]) (purp-theme . [(20210912 1940) nil "A dark color theme with few colors" tar ((:commit . "8d3510e1ed995b8323cd5205626ddde6386a76ca") (:authors ("Vincent Foley" . "vfoley@gmail.com")) (:maintainer "Vincent Foley" . "vfoley@gmail.com") (:keywords "faces") (:url . "https://github.com/gnuvince/purp"))]) (purple-haze-theme . [(20141015 229) ((emacs (24 0))) "an overtly purple color theme for Emacs24." single ((:commit . "3e245cbef7cd09e6b3ee124963e372a04e9a6485") (:authors ("Jason Milkins" . "jasonm23@gmail.com")) (:maintainer "Jason Milkins" . "jasonm23@gmail.com") (:url . "https://github.com/jasonm23/emacs-purple-haze-theme"))]) (purty-mode . [(20131004 2259) nil "Safely pretty-print greek letters, mathematical symbols, or anything else." single ((:commit . "ad48149bfd0c765796a728b22d679e03fc124328") (:authors ("James Atwood" . "jatwood@cs.umass.edu")) (:maintainer "James Atwood" . "jatwood@cs.umass.edu"))]) @@ -4123,13 +4147,13 @@ (py-test . [(20151117 622) ((dash (2 9 0)) (f (0 17)) (emacs (24 4))) "A test runner for Python code." single ((:commit . "3b2a0bdaacb54df6f2bee8317423e5c0d159d5cf") (:authors ("Bogdan Paul Popa" . "popa.bogdanp@gmail.com")) (:maintainer "Bogdan Paul Popa" . "popa.bogdanp@gmail.com") (:keywords "python" "testing" "py.test") (:url . "https://github.com/Bogdanp/py-test.el"))]) (py-yapf . [(20160925 1122) nil "Use yapf to beautify a Python buffer" single ((:commit . "a878304202ad827a1f3de3dce1badd9ca8731146") (:authors ("Friedrich Paetzke" . "f.paetzke@gmail.com")) (:maintainer "Friedrich Paetzke" . "f.paetzke@gmail.com") (:url . "https://github.com/paetzke/py-yapf.el"))]) (pycarddavel . [(20150831 1216) ((helm (1 7 0)) (emacs (24 0))) "Integrate pycarddav" single ((:commit . "6ead921066fa0156f20155b7126e5875ce11c328") (:authors ("Damien Cassou" . "damien@cassou.me")) (:maintainer "Damien Cassou" . "damien@cassou.me") (:keywords "helm" "pyccarddav" "carddav" "message" "mu4e" "contacts"))]) - (pyconf . [(20230127 2046) ((pyvenv (1 21)) (emacs (28 1)) (transient (0 3 7)) (pyenv-mode (0 1 0))) "Set up python execution configurations like dap-mode ones" single ((:commit . "f78e7f269210c7d7e06001752d87c8fbfd8b9084") (:authors ("Andrew Favia ")) (:maintainer "Andrew Favia ") (:keywords "processes" "python") (:url . "https://github.com/andcarnivorous/pyconf"))]) + (pyconf . [(20230308 2000) ((pyvenv (1 21)) (emacs (28 1)) (transient (0 3 7)) (pyenv-mode (0 1 0))) "Set up python execution configurations like dap-mode ones" single ((:commit . "e145e895e265474cb1ef5764d37eb47c6566e97f") (:authors ("Andrew Favia ")) (:maintainer "Andrew Favia ") (:keywords "processes" "python") (:url . "https://github.com/andcarnivorous/pyconf"))]) (pycoverage . [(20200513 2047) ((emacs (24 3))) "Support for coverage stats on Python 2.X and 3" tar ((:commit . "3c69ed312121368f1b24cc04d54a29ce4ed4f743") (:authors ("matt harrison")) (:maintainer "matt harrison") (:keywords "project" "convenience") (:url . "https://github.com/mattharrison/pycoverage.el"))]) (pydoc . [(20221222 1426) nil "functional, syntax highlighted pydoc navigation" single ((:commit . "c9d8b5249c1b3814da062ed9976e4137d6e8d869") (:authors ("John Kitchin" . "jkitchin@andrew.cmu.edu")) (:maintainer "Brian J. Lopes" . "statmobile@gmail.com") (:keywords "pydoc" "python") (:url . "https://github.com/statmobile/pydoc"))]) (pyenv-mode . [(20200518 1521) ((pythonic (0 1 0))) "Integrate pyenv with python-mode" single ((:commit . "d191037fe62ed8d4fee5888845da3e2c386d8e89") (:authors ("Artem Malyshev" . "proofit404@gmail.com")) (:maintainer "Artem Malyshev" . "proofit404@gmail.com") (:url . "https://github.com/proofit404/pyenv-mode"))]) (pygen . [(20161121 506) ((elpy (1 12 0)) (python-mode (6 2 2)) (dash (2 13 0))) "Python code generation using Elpy and Python-mode." single ((:commit . "3a5d1d1a0640865b15be05cd1eeb33bb4793b622") (:authors ("Jack Crawley ")) (:maintainer "Jack Crawley ") (:keywords "python" "code generation") (:url . "https://github.com/JackCrawley/pygen/"))]) - (pygn-mode . [(20220531 1422) ((emacs (26 1)) (tree-sitter (0 15 2)) (tree-sitter-langs (0 10 7)) (uci-mode (0 5 4)) (nav-flash (1 0 0)) (ivy (0 10 0))) "Major-mode for chess PGN files, powered by Python" tar ((:commit . "9a56e701cfcdf9024dda15175e0d0fc645446019") (:authors ("Dodge Coates and Roland Walker")) (:maintainer "Dodge Coates and Roland Walker") (:keywords "data" "games" "chess") (:url . "https://github.com/dwcoates/pygn-mode"))]) - (pyim . [(20230201 203) ((emacs (27 1)) (async (1 6)) (xr (1 13))) "A Chinese input method support quanpin, shuangpin, wubi, cangjie and rime." tar ((:commit . "295a95067eb00a1a8506991ef9a67e3b8d3317f5") (:authors ("Ye Wenbin" . "wenbinye@163.com") ("Feng Shu" . "tumashu@163.com")) (:maintainer "Feng Shu" . "tumashu@163.com") (:keywords "convenience" "chinese" "pinyin" "input-method") (:url . "https://github.com/tumashu/pyim"))]) + (pygn-mode . [(20230401 1858) ((emacs (26 1)) (tree-sitter (0 15 2)) (tree-sitter-langs (0 10 7)) (uci-mode (0 5 4)) (nav-flash (1 0 0)) (ivy (0 10 0))) "Major-mode for chess PGN files, powered by Python" tar ((:commit . "8d290f69ce64a5e6f310ffa42c44fd781c20bcfd") (:authors ("Dodge Coates and Roland Walker")) (:maintainer "Dodge Coates and Roland Walker") (:keywords "data" "games" "chess") (:url . "https://github.com/dwcoates/pygn-mode"))]) + (pyim . [(20230404 244) ((emacs (27 1)) (async (1 6)) (xr (1 13))) "A Chinese input method support quanpin, shuangpin, wubi, cangjie and rime." tar ((:commit . "2a66ab1a02c946e4be0c340639ee897bf0d9e1e5") (:authors ("Ye Wenbin" . "wenbinye@163.com") ("Feng Shu" . "tumashu@163.com")) (:maintainer "Feng Shu" . "tumashu@163.com") (:keywords "convenience" "chinese" "pinyin" "input-method") (:url . "https://github.com/tumashu/pyim"))]) (pyim-basedict . [(20220614 1108) nil "The default pinyin dict of pyim" tar ((:commit . "d61af27686f7a39e6c138b7261a686e7ea7a0ef7") (:authors ("Feng Shu" . "tumashu@163.com")) (:maintainer "Feng Shu" . "tumashu@163.com") (:keywords "convenience" "chinese" "pinyin" "input-method" "complete") (:url . "https://github.com/tumashu/pyim-basedict"))]) (pyim-cangjiedict . [(20210617 934) ((pyim (3 7))) "Some cangjie dicts for pyim" tar ((:commit . "d17e3d32a6480939b350a91a915ebe8e6efad819") (:authors ("Yuanchen Xie" . "yuanchen.gm@gmail.com")) (:maintainer "Yuanchen Xie" . "yuanchen.gm@gmail.com") (:keywords "convenience" "chinese" "pinyin" "input-method" "complete") (:url . "https://github.com/p1uxtar/pyim-cangjiedict"))]) (pyim-smzmdict . [(20210505 1445) ((pyim (3 7))) "Sanma(triple) Zhengma dict for pyim" tar ((:commit . "fcddbde17a04d174c7353548056524687f7be8d2") (:authors ("Yue Shi (Zhizhi)")) (:maintainer "Yuanchen Xie") (:keywords "convenience" "i18n" "pyim" "chinese" "zhengma") (:url . "https://github.com/p1uxtar/pyim-smzmdict"))]) @@ -4142,11 +4166,11 @@ (pyramid . [(20230114 1049) ((emacs (25 2)) (pythonic (0 1 1)) (tablist (0 70))) "Minor mode for working with pyramid projects" tar ((:commit . "c8a8b36725d85664e74f59600fe5d18d06ea907d") (:authors ("Daniel Kraus" . "daniel@kraus.my")) (:maintainer "Daniel Kraus" . "daniel@kraus.my") (:keywords "python" "pyramid" "pylons" "convenience" "tools" "processes") (:url . "https://github.com/dakra/pyramid.el"))]) (pytest . [(20200330 41) ((s (1 9 0))) "Easy Python test running in Emacs" single ((:commit . "6934047242db79b1c53e9fe3e0734cc9719ed1c4") (:keywords "pytest" "python" "testing") (:url . "https://github.com/ionrock/pytest-el"))]) (pytest-pdb-break . [(20200804 848) ((emacs (25))) "A pytest PDB launcher" tar ((:commit . "05d227493b7b96f3556cba22f215cb85f9282020") (:authors ("Jane Soko" . "poppyschmo@protonmail.com")) (:maintainer "Jane Soko" . "poppyschmo@protonmail.com") (:keywords "languages" "tools") (:url . "https://github.com/poppyschmo/pytest-pdb-break"))]) - (python-black . [(20221103 1759) ((emacs (25)) (dash (2 16 0)) (reformatter (0 3))) "Reformat Python using python-black" single ((:commit . "e1bbf574a952562ddeadb0caa42c44016136c2c9") (:authors ("wouter bolsterlee" . "wouter@bolsterl.ee")) (:maintainer "wouter bolsterlee" . "wouter@bolsterl.ee") (:keywords "languages") (:url . "https://github.com/wbolster/emacs-python-black"))]) - (python-cell . [(20220105 2315) ((emacs (25 1))) "Support for MATLAB-like cells in python mode" single ((:commit . "9a111dcee0cbb5922662bfecb37b6983b740950a") (:authors ("Thomas Hisch" . "t.hisch@gmail.com")) (:maintainer "Thomas Hisch" . "t.hisch@gmail.com") (:keywords "extensions" "python" "matlab" "cell") (:url . "https://github.com/thisch/python-cell.el"))]) + (python-black . [(20230313 1037) ((emacs (25)) (dash (2 16 0)) (reformatter (0 3))) "Reformat Python using python-black" single ((:commit . "0714b0007c0b620f88ed9cc91035caea43f3d75f") (:authors ("wouter bolsterlee" . "wouter@bolsterl.ee")) (:maintainer "wouter bolsterlee" . "wouter@bolsterl.ee") (:keywords "languages") (:url . "https://github.com/wbolster/emacs-python-black"))]) + (python-cell . [(20230224 1925) ((emacs (25 1))) "Support for MATLAB-like cells in python mode" single ((:commit . "cb8e6381b1fab16bcf475d115bb22fef503bea32") (:authors ("Thomas Hisch" . "t.hisch@gmail.com")) (:maintainer "Thomas Hisch" . "t.hisch@gmail.com") (:keywords "extensions" "python" "matlab" "cell") (:url . "https://github.com/thisch/python-cell.el"))]) (python-coverage . [(20211224 1420) ((emacs (25 1)) (dash (2 18 0)) (s (1 12 0)) (xml+ (1))) "Show Python coverage via overlays or Flycheck" single ((:commit . "a341615af03dbe3ce0ac9b63cf43dc01c1ae5ebe") (:authors ("wouter bolsterlee" . "wouter@bolsterl.ee")) (:maintainer "wouter bolsterlee" . "wouter@bolsterl.ee") (:keywords "languages" "processes" "tools") (:url . "https://github.com/wbolster/emacs-python-coverage"))]) (python-django . [(20150822 404) nil "A Jazzy package for managing Django projects" single ((:commit . "fc54ad74f0309670359b939f64d0f1fff68aeac4") (:authors ("Fabián E. Gallina" . "fabian@anue.biz")) (:maintainer "FSF") (:keywords "languages") (:url . "https://github.com/fgallina/python-django.el"))]) - (python-docstring . [(20220308 22) nil "Smart Python docstring formatting" tar ((:commit . "01d0470498d08ce9d99dd4ce709c567229f857d2"))]) + (python-docstring . [(20230326 1929) nil "Smart Python docstring formatting" tar ((:commit . "40f0ca57831a71a9e6437088149784f37704ef6c"))]) (python-environment . [(20150310 853) ((deferred (0 3 1))) "virtualenv API for Emacs Lisp" tar ((:commit . "401006584e32864a10c69d29f14414828909362e") (:authors ("Takafumi Arakaki ")) (:maintainer "Takafumi Arakaki ") (:keywords "applications" "tools"))]) (python-info . [(20151228 1852) nil "Python info manual for Emacs" tar ((:commit . "306f15441b54b25757cdfd3b327b84024ea21ed7"))]) (python-insert-docstring . [(20211127 1232) ((emacs (25 1))) "Python Google docstring inserter" single ((:commit . "cd6419b74c99c06d5c48c1b289572acce1fd193b") (:authors ("Marco Vocialta" . "macurovc@tutanota.com")) (:maintainer "Marco Vocialta" . "macurovc@tutanota.com") (:url . "https://github.com/macurovc/insert-docstring"))]) @@ -4162,7 +4186,7 @@ (pyvenv-auto . [(20230106 415) ((emacs (26 3)) (pyvenv (1 21))) "Automatically switch Python venvs" single ((:commit . "b4365e60e3ba747a5fec8ca909f64fe8c73d8db2") (:url . "https://github.com/nryotaro/pyvenv-auto"))]) (q-mode . [(20221224 2024) ((emacs (24))) "A q editing mode" single ((:commit . "e18a7b40e876a5502d9d2d6d16a356295c555fab") (:keywords "faces" "files" "q") (:url . "https://github.com/psaris/q-mode"))]) (qml-mode . [(20161016 31) nil "Major mode for editing QT Declarative (QML) code." single ((:commit . "6c5f33ba88ae010bf201a80ee8095e20a724558c") (:authors ("Yen-Chin Lee" . "coldnew.tw@gmail.com")) (:maintainer "Yen-Chin Lee" . "coldnew.tw@gmail.com") (:keywords "qml" "qt" "qt declarative") (:url . "https://github.com/coldnew/qml-mode"))]) - (qrencode . [(20230129 1750) ((emacs (25 1))) "QRCode encoder" single ((:commit . "449befdf160c62a40961cd97f02bada75ffda5d8") (:authors ("Rüdiger Sonderfeld" . "ruediger@c-plusplus.net")) (:maintainer "Rüdiger Sonderfeld" . "ruediger@c-plusplus.net") (:keywords "qrcode" "comm") (:url . "https://github.com/ruediger/qrencode-el"))]) + (qrencode . [(20230324 2335) ((emacs (25 1))) "QRCode encoder" single ((:commit . "d7896e9594d45d7b2622d4617ff9cb7037378167") (:authors ("Rüdiger Sonderfeld" . "ruediger@c-plusplus.net")) (:maintainer "Rüdiger Sonderfeld" . "ruediger@c-plusplus.net") (:keywords "qrcode" "comm") (:url . "https://github.com/ruediger/qrencode-el"))]) (qt-pro-mode . [(20170604 1841) ((emacs (24))) "Qt Pro/Pri major mode" single ((:commit . "1e0052fcfb89c15cb47714c1546d4e8ec6e01ae6") (:authors ("Todd Neal" . "tolchz@gmail.com")) (:maintainer "Todd Neal" . "tolchz@gmail.com") (:keywords "extensions"))]) (qtcreator-theme . [(20201215 1523) ((emacs (24 3))) "A color theme that mimics Qt Creator IDE" single ((:commit . "515532b05063898459157d2ba5c10ec0d5a4b1bd") (:authors ("Lesley Lai" . "lesley@lesleylai.info")) (:maintainer "Lesley Lai" . "lesley@lesleylai.info") (:keywords "theme" "light" "faces") (:url . "https://github.com/LesleyLai/emacs-qtcreator-theme"))]) (quack . [(20181106 1301) nil "enhanced support for editing and running Scheme code" single ((:commit . "2146805ce2b5a9b155d73929986f11e713787e26"))]) @@ -4182,7 +4206,7 @@ (quiz . [(20190525 1206) ((cl-lib (0 5)) (emacs (25))) "Multiple choice quiz game" single ((:commit . "570bf53926d89282cdb9653bd5aa8fe968f92bbd") (:authors ("Dave Pearson" . "davep@davep.org")) (:maintainer "Dave Pearson" . "davep@davep.org") (:keywords "games" "trivia" "quiz") (:url . "https://github.com/davep/quiz.el"))]) (r-autoyas . [(20140101 1510) ((ess (0)) (yasnippet (0 8 0))) "Provides automatically created yasnippets for R function argument lists." tar ((:commit . "d321a7da0ef2e94668d53e0807277da7b70ea678") (:authors ("Sven Hartenstein & Matthew Fidler")) (:maintainer "Matthew Fidler") (:keywords "r" "yasnippet") (:url . "https://github.com/mlf176f2/r-autoyas.el"))]) (racer . [(20210307 243) ((emacs (25 1)) (rust-mode (0 2 0)) (dash (2 13 0)) (s (1 10 0)) (f (0 18 2)) (pos-tip (0 4 6))) "code completion, goto-definition and docs browsing for Rust via racer" single ((:commit . "1e63e98626737ea9b662d4a9b1ffd6842b1c648c") (:authors ("Phil Dawes")) (:maintainer "Phil Dawes") (:keywords "abbrev" "convenience" "matching" "rust" "tools") (:url . "https://github.com/racer-rust/emacs-racer"))]) - (racket-mode . [(20230209 1424) ((emacs (25 1))) "Racket editing, REPL, and more" tar ((:commit . "947d9806ee27ef241643f978c7901fd1f9e10c98") (:authors ("Greg Hendershott" . "racket-mode-author@greghendershott.com")) (:maintainer "Greg Hendershott") (:url . "https://www.racket-mode.com/"))]) + (racket-mode . [(20230321 1533) ((emacs (25 1))) "Racket editing, REPL, and more" tar ((:commit . "3d122858696f2c81101e52d2f191dd2d11a11daa") (:authors ("Greg Hendershott" . "racket-mode-author@greghendershott.com")) (:maintainer "Greg Hendershott") (:url . "https://www.racket-mode.com/"))]) (rails-i18n . [(20220126 1643) ((emacs (27 2)) (yaml (0 1 0)) (dash (2 19 1))) "Seach and insert i18n on ruby code" single ((:commit . "8e87e4e48e31902b8259ded28a208c2e7efea6e9") (:authors ("Otávio Schwanck dos Santos" . "otavioschwanck@gmail.com")) (:maintainer "Otávio Schwanck dos Santos" . "otavioschwanck@gmail.com") (:keywords "tools" "languages") (:url . "https://github.com/otavioschwanck/rails-i18n.el"))]) (rails-log-mode . [(20140408 425) nil "Major mode for viewing Rails log files" single ((:commit . "ff440003ad7d47cb0ac3300f2a632f4cfd36a446") (:authors ("Anantha kumaran" . "ananthakumaran@gmail.com")) (:maintainer "Anantha kumaran" . "ananthakumaran@gmail.com") (:keywords "rails" "log"))]) (rails-routes . [(20220126 1631) ((emacs (27 2)) (inflections (1 1))) "Search for and insert rails routes" single ((:commit . "eab995a9297ca5bd9bd4f4c2737f2fecfc36def0") (:authors ("Otávio Schwanck" . "otavioschwanck@gmail.com")) (:maintainer "Otávio Schwanck" . "otavioschwanck@gmail.com") (:keywords "tools" "languages") (:url . "https://github.com/otavioschwanck/rails-routes"))]) @@ -4210,7 +4234,7 @@ (rcirc-groups . [(20170731 2101) nil "an emacs buffer in rcirc-groups major mode" single ((:commit . "b68ece9d219b909244d4e3c0d8bf6a746d6fead7") (:authors ("Dimitri Fontaine" . "dim@tapoueh.org")) (:maintainer "Dimitri Fontaine" . "dim@tapoueh.org") (:keywords "comm" "convenience") (:url . "http://tapoueh.org/emacs/rcirc-groups.html"))]) (rcirc-notify . [(20150219 2204) nil "libnotify popups" single ((:commit . "841a7b5a6cdb0c11a812df924d2c6a7d364fd455") (:authors ("Will Farrington, Alex Schroeder , Nic Ferrier" . "nferrier@ferrier.me.uk")) (:maintainer "Nic Ferrier" . "nferrier@ferrier.me.uk") (:keywords "lisp" "rcirc" "irc" "notify" "growl"))]) (rcirc-styles . [(20210414 1712) ((cl-lib (0 5))) "support mIRC-style color and attribute codes" single ((:commit . "dd06ec5fa455131788bbc885fcfaaec16b08f13b"))]) - (rdf-prefix . [(20211209 1952) nil "Prefix lookup for RDF" single ((:commit . "fa4b64bc3e0c1d5b8eed20df8d2daf0dffff2332") (:authors ("Simen Heggestøyl" . "simenheg@gmail.com")) (:maintainer "Simen Heggestøyl" . "simenheg@gmail.com") (:keywords "convenience" "abbrev") (:url . "https://github.com/simenheg/rdf-prefix"))]) + (rdf-prefix . [(20230321 1949) nil "Prefix lookup for RDF" single ((:commit . "70d1ef453fc55f0bfbb4bd3127112332e5b0f623") (:authors ("Simen Heggestøyl" . "simenheg@runbox.com")) (:maintainer "Simen Heggestøyl" . "simenheg@runbox.com") (:keywords "convenience" "abbrev") (:url . "https://github.com/simenheg/rdf-prefix"))]) (rdxmk . [(20170630 134) nil "A small set of tools for redox developments" tar ((:commit . "e78749fb29738365ffa4d863ffabeb969ebb0bcf") (:authors ("Jacob Salzberg" . "jsalzbergedu@yahoo.com")) (:maintainer "Jacob Salzberg" . "jsalzbergedu@yahoo.com") (:keywords "redox" "convenience" "tools") (:url . "https://github.com/jsalzbergedu/rdxmk"))]) (react-snippets . [(20210430 1510) ((yasnippet (0 7 0))) "Yasnippets for React" tar ((:commit . "9d0a1bb90ac36c689cded48b661e81d4544fd719") (:authors ("John Mastro" . "john.b.mastro@gmail.com")) (:maintainer "John Mastro" . "john.b.mastro@gmail.com") (:keywords "snippets"))]) (read-aloud . [(20160923 500) ((emacs (24 4))) "A simple interface to TTS engines" single ((:commit . "d5f80ab72054a957aed25224639c1779cae5f4d1") (:authors ("Alexander Gromnitsky" . "alexander.gromnitsky@gmail.com")) (:maintainer "Alexander Gromnitsky" . "alexander.gromnitsky@gmail.com") (:keywords "multimedia") (:url . "https://github.com/gromnitsky/read-aloud.el"))]) @@ -4230,7 +4254,7 @@ (realgud-rdb2 . [(20190520 1146) ((realgud (1 4 5)) (load-relative (1 2)) (cl-lib (0 5)) (emacs (24))) "Realgud front-end for interacting with Ruby debugger2" tar ((:commit . "3594aa74f7afda3c3251bb2af7fe0e8ec6d621ae") (:authors ("Rocky Bernstein")) (:maintainer "Rocky Bernstein") (:url . "http://github.com/rocky/realgud-ruby-debugger2"))]) (realgud-trepan-ni . [(20210513 2237) ((load-relative (1 2)) (realgud (1 5 0)) (emacs (25))) "Realgud front-end to trepan-ni" tar ((:commit . "0ec088ea343835e24ae73da09bea96bfb02a3130") (:authors ("Rocky Bernstein" . "rocky@gnu.org")) (:maintainer "Rocky Bernstein" . "rocky@gnu.org") (:url . "https://github.com/realgud/realgud-trepan-ni"))]) (reaper . [(20220527 2122) ((emacs (26 2))) "Interact with Harvest time tracking app" single ((:commit . "a8ec93656698c5c02a02279ee7d7976325cc74cd") (:authors ("Thomas Fini Hansen" . "xen@xen.dk")) (:maintainer "Thomas Fini Hansen" . "xen@xen.dk") (:keywords "tools") (:url . "https://github.com/xendk/reaper"))]) - (reason-mode . [(20200929 1606) ((emacs (24 3))) "A major mode for editing ReasonML" tar ((:commit . "5690544a7091630e0ea0023bbbd57a733cea8bde") (:authors ("Mozilla")) (:maintainer "Mozilla") (:keywords "languages" "ocaml") (:url . "https://github.com/reasonml-editor/reason-mode"))]) + (reason-mode . [(20230405 517) ((emacs (24 3))) "A major mode for editing ReasonML" tar ((:commit . "d657ff75572a8ea7eda6fe22ada3a2ebf5bc6119") (:authors ("Mozilla")) (:maintainer "Mozilla") (:keywords "languages" "ocaml") (:url . "https://github.com/reasonml-editor/reason-mode"))]) (reazon . [(20211229 1733) ((emacs (26))) "miniKanren for Emacs" tar ((:commit . "da3c4a8acf236eddb73348056e08bea330e868c0") (:authors ("Nick Drozd" . "nicholasdrozd@gmail.com")) (:maintainer "Nick Drozd" . "nicholasdrozd@gmail.com") (:keywords "languages" "extensions" "lisp") (:url . "https://github.com/nickdrozd/reazon"))]) (rebecca-theme . [(20180324 821) ((emacs (24))) "Rebecca Purple Theme" single ((:commit . "1fe3662d1b02caea96e9a780252b2c45f7a49b1d") (:authors ("vic" . "vborja@apache.org")) (:maintainer "vic" . "vborja@apache.org") (:keywords "theme" "dark") (:url . "https://github.com/vic/rebecca-theme"))]) (rebox2 . [(20121113 1300) nil "Handling of comment boxes in various styles." single ((:commit . "00634eca420cc48657b81e40e599ff8548083985") (:authors ("François Pinard") ("Le Wang")) (:maintainer "Le Wang (lewang.emacs!!!gmayo.com remove exclamations, correct host, hint: google mail)") (:url . "https://github.com/lewang/rebox2"))]) @@ -4259,13 +4283,13 @@ (regex-tool . [(20170104 1918) nil "A regular expression evaluation tool for programmers" single ((:commit . "0b4a0111143c88ef94bec56624cb2e00c1a054e6") (:authors ("John Wiegley" . "johnw@newartisans.com")) (:maintainer "John Wiegley" . "johnw@newartisans.com") (:keywords "regex" "languages" "programming" "development") (:url . "http://www.newartisans.com/"))]) (region-bindings-mode . [(20140407 2214) nil "Enable custom bindings when mark is active." single ((:commit . "3fa5dbdbd7c000bebff6d9d14a4be326ec24b6fc") (:authors ("Fabián E. Gallina" . "fabian@anue.biz")) (:maintainer "Fabián E. Gallina" . "fabian@anue.biz") (:keywords "convenience") (:url . "https://github.com/fgallina/region-bindings-mode"))]) (region-convert . [(20210519 1655) ((emacs (24 3))) "Convert string in region by Lisp function" single ((:commit . "cb3ab0417d7b74e5edd34bf23a70737fc7bf1d3a") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "region" "convenience") (:url . "https://github.com/zonuexe/right-click-context"))]) - (region-occurrences-highlighter . [(20200815 1555) ((emacs (24))) "Mark occurrences of current region (selection)." single ((:commit . "51e4c51e6078ebf0681e65f7dea4f328f0c91cfe") (:authors ("Álvaro González Sotillo" . "alvarogonzalezsotillo@gmail.com")) (:maintainer "Álvaro González Sotillo" . "alvarogonzalezsotillo@gmail.com") (:keywords "convenience") (:url . "https://github.com/alvarogonzalezsotillo/region-occurrences-highlighter"))]) + (region-occurrences-highlighter . [(20230221 1803) ((emacs (24))) "Mark occurrences of current region (selection)." single ((:commit . "9c2a3193ccf32f8fa48578a6b8826b2959dac120") (:authors ("Álvaro González Sotillo" . "alvarogonzalezsotillo@gmail.com")) (:maintainer "Álvaro González Sotillo" . "alvarogonzalezsotillo@gmail.com") (:keywords "convenience") (:url . "https://github.com/alvarogonzalezsotillo/region-occurrences-highlighter"))]) (region-state . [(20181205 1746) nil "Show the number of chars/lines or rows/columns in the region" single ((:commit . "f9e3926036a7c261b20bad9bf46f68ead8c15024") (:authors ("Chunyang Xu" . "mail@xuchunyang.me")) (:maintainer "Chunyang Xu" . "mail@xuchunyang.me") (:keywords "convenience") (:url . "https://github.com/xuchunyang/region-state.el"))]) (register-channel . [(20210120 1618) nil "Jump around fast using registers" single ((:commit . "ed7f563e92170b758dc878fcb5df88d46d5d44cc") (:authors ("Yang Zhao" . "YangZhao11@users.noreply.github.com")) (:maintainer "Yang Zhao" . "YangZhao11@users.noreply.github.com") (:keywords "convenience"))]) (register-quicknav . [(20200524 2006) ((emacs (25 3))) "Quickly jump to next/previous register" single ((:commit . "c15ea92b0946c28b3f14986d42b15b0b534aa6a2") (:authors ("tastytea" . "tastytea@tastytea.de")) (:maintainer "tastytea" . "tastytea@tastytea.de") (:keywords "convenience") (:url . "https://schlomp.space/tastytea/register-quicknav"))]) (rego-mode . [(20201102 1420) ((emacs (24 4)) (reformatter (0 3))) "A major mode for rego language" single ((:commit . "be110e6cef5d34eef0529a8739c68e619cf15310") (:authors ("Sibi Prabakaran" . "sibi@psibi.in")) (:maintainer "Sibi Prabakaran" . "sibi@psibi.in") (:keywords "languages") (:url . "https://github.com/psibi/rego-mode"))]) (related . [(20190327 1024) ((cl-lib (0 5))) "Switch back and forth between similarly named buffers." single ((:commit . "546c7e811b290470288b617f2c27106bd83ccd33") (:authors ("Julien Montmartin")) (:maintainer "Julien Montmartin") (:keywords "file" "buffer" "switch" "selection" "matching" "convenience") (:url . "https://github.com/julien-montmartin/related"))]) - (related-files . [(20221125 1824) ((emacs (28 2))) "Easily find files related to the current one" tar ((:commit . "0c2e38d0bb0db45a50a082d3e8362c07fc60a1f2") (:authors ("Damien Cassou" . "damien@cassou.me")) (:maintainer "Damien Cassou" . "damien@cassou.me") (:keywords "tools") (:url . "https://www.gnu.org/software/emacs/"))]) + (related-files . [(20230324 934) ((emacs (28 2))) "Easily find files related to the current one" tar ((:commit . "f3f841f625a51b964b88cfe08378311124cc5240") (:authors ("Damien Cassou" . "damien@cassou.me")) (:maintainer "Damien Cassou" . "damien@cassou.me") (:keywords "tools") (:url . "https://www.gnu.org/software/emacs/"))]) (remark-mode . [(20221123 2127) ((emacs (25 1)) (markdown-mode (2 0))) "Major mode for the remark slideshow tool" tar ((:commit . "5a2a702d2af8fd007ae02237d5824356d0c1acc6") (:authors ("@torgeir")) (:maintainer "@torgeir") (:keywords "remark" "slideshow" "markdown" "hot reload"))]) (remember-last-theme . [(20170619 2133) ((emacs (24 4))) "Remember the last used theme between sessions." single ((:commit . "57e8e2a475ea89316dbb5c4d2ea047f56a2cbcdf") (:authors ("Anler Hernández Peral" . "inbox+emacs@anler.me")) (:maintainer "Anler Hernández Peral" . "inbox+emacs@anler.me") (:keywords "convenience" "faces") (:url . "https://github.com/anler/remember-last-theme"))]) (remind-bindings . [(20200820 1723) ((emacs (25 1)) (omni-quotes (0 5)) (popwin (1 0)) (map (2 0))) "Reminders for your init bindings" single ((:commit . "c9a327bfd3c68a0c41b5b64df491bdee4c73ca39") (:authors ("Mehmet Tekman")) (:maintainer "Mehmet Tekman") (:keywords "outlines") (:url . "https://github.com/mtekman/remind-bindings.el"))]) @@ -4284,7 +4308,7 @@ (request-deferred . [(20220614 1604) ((emacs (24 1)) (deferred (0 3 1)) (request (0 3))) "Wrap request.el by deferred" single ((:commit . "38ed1d2e64138eb16a9d8ed2987cff2e01b4a93b") (:authors ("Takafumi Arakaki ")) (:maintainer "Takafumi Arakaki ") (:url . "https://github.com/tkf/emacs-request"))]) (requirejs . [(20151204 719) ((js2-mode (20150713)) (popup (0 5 3)) (s (1 9 0)) (cl-lib (0 5)) (yasnippet (20151011 1823))) "Requirejs import manipulation and source traversal." tar ((:commit . "4ea2a5fcbc76e4cbb6a7461e6f05f019b75865b1") (:authors ("Joe Heyming" . "joeheyming@gmail.com")) (:maintainer "Joe Heyming" . "joeheyming@gmail.com") (:keywords "javascript" "requirejs") (:url . "https://github.com/joeheyming/requirejs-emacs"))]) (requirejs-mode . [(20130215 2104) nil "Improved AMD module management" single ((:commit . "011849043098b6c4f27571625ae19071b53b8824") (:authors ("Marc-Olivier Ricard" . "marco.ricard@gmail.com")) (:maintainer "Marc-Olivier Ricard" . "marco.ricard@gmail.com") (:keywords "javascript" "amd" "requirejs"))]) - (rescript-mode . [(20220613 1246) ((emacs (26 1))) "A major mode for editing ReScript" tar ((:commit . "2aae2fbd4971dff965c758ec19688780ed7bff21") (:authors ("Karl Landstrom" . "karl.landstrom@brgeight.se") ("Daniel Colascione" . "dancol@dancol.org") ("John Lee" . "jjl@pobox.com")) (:maintainer "John Lee" . "jjl@pobox.com") (:keywords "languages" "rescript") (:url . "https://github.com/jjlee/rescript-mode"))]) + (rescript-mode . [(20230321 1917) ((emacs (26 1))) "A major mode for editing ReScript" tar ((:commit . "a0a21d1c037c78ba4c05108a5e7afd5f75fe7bd7") (:authors ("Karl Landstrom" . "karl.landstrom@brgeight.se") ("Daniel Colascione" . "dancol@dancol.org") ("John Lee" . "jjl@pobox.com")) (:maintainer "John Lee" . "jjl@pobox.com") (:keywords "languages" "rescript") (:url . "https://github.com/jjlee/rescript-mode"))]) (resize-window . [(20180918 538) ((emacs (24)) (cl-lib (0 5))) "easily resize windows" single ((:commit . "09dc5968f1c988c51fcd6ea5d68bb38b7541eb66") (:authors ("Dan Sutton " . "danielsutton01@gmail.com")) (:maintainer "Dan Sutton " . "danielsutton01@gmail.com") (:keywords "window" "resize") (:url . "https://github.com/dpsutton/resize-mode"))]) (restart-emacs . [(20201127 1425) nil "Restart emacs from within emacs" single ((:commit . "d0fca7fba014b2d0d4dedcb9744a1e73cd9a6409") (:authors ("Iqbal Ansari" . "iqbalansari02@yahoo.com")) (:maintainer "Iqbal Ansari" . "iqbalansari02@yahoo.com") (:keywords "convenience") (:url . "https://github.com/iqbalansari/restart-emacs"))]) (restclient . [(20221203 1808) nil "An interactive HTTP client for Emacs" single ((:commit . "0ba72816f92f3d5906cdf76f418fd0a3ee72809b") (:authors ("Pavel Kurnosov" . "pashky@gmail.com")) (:maintainer "Pavel Kurnosov" . "pashky@gmail.com") (:keywords "http"))]) @@ -4300,8 +4324,8 @@ (revert-buffer-all . [(20230109 536) ((emacs (24 3))) "Revert all open buffers" single ((:commit . "08e90d2d75f5d5900ca2a0d2670592bcf2b2d68f") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:url . "https://codeberg.org/ideasman42/emacs-buffer-revert-all"))]) (review-mode . [(20220817 1010) nil "major mode for ReVIEW" single ((:commit . "2b24db8d85a1c40dbd67be195caa79c9df1e0f4b") (:authors ("Kenshi Muto" . "kmuto@kmuto.jp")) (:maintainer "Kenshi Muto" . "kmuto@kmuto.jp") (:url . "https://github.com/kmuto/review-el"))]) (reykjavik-theme . [(20201219 947) ((emacs (24))) "Theme with a dark background." single ((:commit . "f6d8e83946633603234cd1dac725e17447f40bce") (:authors ("martin haesler")) (:maintainer "martin haesler"))]) - (rfc-mode . [(20221123 1643) ((emacs (25 1))) "RFC document browser and viewer" single ((:commit . "53ec006aa6aa4fae9c6c64004692aa3d01b38275") (:authors ("Nicolas Martyanoff" . "nicolas@n16f.net")) (:maintainer "Nicolas Martyanoff" . "nicolas@n16f.net") (:url . "https://github.com/galdor/rfc-mode"))]) - (rg . [(20230201 1819) ((emacs (25 1)) (transient (0 3 0)) (wgrep (2 1 10))) "A search tool based on ripgrep" tar ((:commit . "e7afc1573922dd6ec8e8ccd178e054ff8c99e5bf") (:authors ("David Landell" . "david.landell@sunnyhill.email") ("Roland McGrath" . "roland@gnu.org")) (:maintainer "David Landell" . "david.landell@sunnyhill.email") (:keywords "matching" "tools") (:url . "https://github.com/dajva/rg.el"))]) + (rfc-mode . [(20230307 937) ((emacs (25 1))) "RFC document browser and viewer" single ((:commit . "c938c8134e7434b623ebfd92ad22586205cb1c92") (:authors ("Nicolas Martyanoff" . "nicolas@n16f.net")) (:maintainer "Nicolas Martyanoff" . "nicolas@n16f.net") (:url . "https://github.com/galdor/rfc-mode"))]) + (rg . [(20230401 1434) ((emacs (26 1)) (transient (0 3 0)) (wgrep (2 1 10))) "A search tool based on ripgrep" tar ((:commit . "e8397ea2f9cadda20bf87e3fae71540511b52d9c") (:authors ("David Landell" . "david.landell@sunnyhill.email") ("Roland McGrath" . "roland@gnu.org")) (:maintainer "David Landell" . "david.landell@sunnyhill.email") (:keywords "matching" "tools") (:url . "https://github.com/dajva/rg.el"))]) (rgb . [(20220717 1940) ((emacs (24 3))) "RGB control via OpenRGB" single ((:commit . "4aab5a5be16b69b47ef5e67d02782df5e41dbd7b") (:url . "https://gitlab.com/cwpitts/rgb.el"))]) (rhq . [(20220916 1632) ((emacs (24 4))) "Client for rhq" single ((:commit . "7d9c5dee2e493eb0c5d41afca1b6049de8c2a26d") (:authors ("ROCKTAKEY" . "rocktakey@gmail.com")) (:maintainer "ROCKTAKEY" . "rocktakey@gmail.com") (:keywords "tools" "extensions") (:url . "https://github.com/ROCKTAKEY/rhq"))]) (rhtml-mode . [(20130422 1311) nil "major mode for editing RHTML files" tar ((:commit . "a6d71b38a3db867ccf82999c99805db1a3a33c33"))]) @@ -4319,8 +4343,8 @@ (riscv-mode . [(20220916 206) ((emacs (24 4))) "Major-mode for RISC V assembly" single ((:commit . "8e335b9c93de93ed8dd063d702b0f5ad48eef6d7") (:authors ("Adam Niederer ")) (:maintainer "Adam Niederer") (:keywords "riscv" "assembly") (:url . "https://github.com/AdamNiederer/riscv-mode"))]) (rivet-mode . [(20201013 1905) ((emacs (24)) (web-mode (16))) "A minor mode for editing Apache Rivet files" single ((:commit . "6cf58cf04fee933113857af07414b3f27c24b505") (:authors ("Jade Michael Thornton")) (:maintainer "Jade Michael Thornton") (:url . "https://gitlab.com/thornjad/rivet-mode"))]) (rjsx-mode . [(20200224 2149) ((emacs (24 4)) (js2-mode (20170504))) "Real support for JSX" single ((:commit . "0061587a06cdc2579a8d0e90863498d96bf982d8") (:authors ("Felipe Ochoa" . "felipe@fov.space")) (:maintainer "Felipe Ochoa" . "felipe@fov.space") (:keywords "languages") (:url . "https://github.com/felipeochoa/rjsx-mode/"))]) - (rmsbolt . [(20220909 130) ((emacs (25 1))) "A compiler output viewer" tar ((:commit . "9aa25c200e6b1709263c0638b1827f36de423519") (:authors ("Jay Kamat" . "jaygkamat@gmail.com")) (:maintainer "Jay Kamat" . "jaygkamat@gmail.com") (:keywords "compilation" "tools") (:url . "http://gitlab.com/jgkamat/rmsbolt"))]) - (robe . [(20221207 225) ((inf-ruby (2 5 1)) (emacs (25 1))) "Code navigation, documentation lookup and completion for Ruby" tar ((:commit . "4ddcc847542ffbba41339e83e462c7d9aaaac860") (:authors ("Dmitry Gutov")) (:maintainer "Dmitry Gutov") (:keywords "ruby" "convenience" "rails") (:url . "https://github.com/dgutov/robe"))]) + (rmsbolt . [(20230309 1751) ((emacs (25 1))) "A compiler output viewer" tar ((:commit . "197fb7b7eeccfa2d3755d723841c7eb1c2a2768c") (:authors ("Jay Kamat" . "jaygkamat@gmail.com")) (:maintainer "Jay Kamat" . "jaygkamat@gmail.com") (:keywords "compilation" "tools") (:url . "http://gitlab.com/jgkamat/rmsbolt"))]) + (robe . [(20230327 113) ((inf-ruby (2 5 1)) (emacs (25 1))) "Code navigation, documentation lookup and completion for Ruby" tar ((:commit . "a8d2c3293f0760194fd138f346bcc8876cbd8640") (:authors ("Dmitry Gutov")) (:maintainer "Dmitry Gutov") (:keywords "ruby" "convenience" "rails") (:url . "https://github.com/dgutov/robe"))]) (robot-log . [(20220719 1301) ((emacs (28 1))) "Major mode for viewing RobotFramework debug log files" single ((:commit . "26da47597aa97be9649cb60f4da6d94d47d0c0ac") (:keywords "convenience" "files") (:url . "https://git.sr.ht/~apteryx/emacs-robot-log"))]) (robot-mode . [(20221109 1630) ((emacs (26 1))) "Major-mode for Robot Framework files" single ((:commit . "fb9be47a1d4e57a80ae2c0d4dff3eba2fe29ebdc") (:authors ("Kalle Kankare" . "kalle.kankare@iki.fi")) (:maintainer "Kalle Kankare" . "kalle.kankare@iki.fi") (:keywords "languages" "files") (:url . "https://github.com/kopoli/robot-mode"))]) (robots-txt-mode . [(20190812 1858) nil "Major mode for editing robots.txt" single ((:commit . "8bf67285a25a6756607354d184e36583f2847e7d") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "languages" "comm" "web") (:url . "https://github.com/emacs-php/robots-txt-mode"))]) @@ -4328,7 +4352,7 @@ (ron-mode . [(20200830 1554) ((emacs (24 5 1))) "Rusty Object Notation mode" single ((:commit . "c5e0454b9916d6b73adc15dab8abbb0b0a68ea22") (:authors ("Daniel Hutzley" . "endergeryt@gmail.com")) (:maintainer "Daniel Hutzley" . "endergeryt@gmail.com") (:keywords "languages") (:url . "https://chiselapp.com/user/Hutzdog/repository/ron-mode/home"))]) (rope-read-mode . [(20211228 1126) ((emacs (24))) "Rearrange lines to read text smoothly" single ((:commit . "6aad44e006a2999980c138f608d28c8ecab92b35") (:authors ("Marco Wahl" . "marcowahlsoft@gmail.com")) (:maintainer "Marco Wahl" . "marcowahlsoft@gmail.com") (:keywords "reading" "convenience" "chill") (:url . "https://gitlab.com/marcowahl/rope-read-mode"))]) (ropgadget . [(20230107 1225) ((emacs (24 4)) (transient (0 3 6))) "Display and filter ROP gadgets of a binary" single ((:commit . "10e9d6f66de1ee805d871c59f4acc078b66747a3") (:keywords "tools" "ctf" "pwn" "rop") (:url . "https://github.com/Dragoncraft89/ropgadget-el"))]) - (ros . [(20221212 1047) ((emacs (25 1))) "Package to write code for ROS systems" single ((:commit . "b437e46bee8f64eec1b8e61f86476977dab6cdb4") (:authors ("Max Beutelspacher ")) (:maintainer "Max Beutelspacher" . "max@beutelspacher.eu") (:keywords "convenience" "tools") (:url . "https://github.com/DerBeutlin/ros.el"))]) + (ros . [(20230320 1657) ((emacs (27 1))) "Package to write code for ROS systems" single ((:commit . "5702a76a055cc0801bc16d50f32973311b894676") (:authors ("Max Beutelspacher ")) (:maintainer "Max Beutelspacher" . "max@beutelspacher.eu") (:keywords "convenience" "tools") (:url . "https://github.com/DerBeutlin/ros.el"))]) (rotate . [(20210126 637) nil "Rotate the layout of emacs" single ((:commit . "4e9ac3ff800880bd9b705794ef0f7c99d72900a6") (:authors ("daichi.hirata ")) (:maintainer "daichi.hirata ") (:keywords "window" "layout") (:url . "https://github.com/daichirata/emacs-rotate"))]) (roy-mode . [(20121208 1158) nil "Roy major mode" single ((:commit . "e1a4fb5ec0f46e82f569865ca47042ba5934e425") (:authors ("Georgii Leontiev")) (:maintainer "Georgii Leontiev") (:keywords "extensions") (:url . "https://github.com/folone/roy-mode"))]) (rpm-spec-mode . [(20160710 1136) nil "RPM spec file editing commands for Emacs/XEmacs" single ((:commit . "c1c38050c48ea330c7cea632b8785d66daeefb2b") (:authors ("Stig Bjørlykke," . "stig@bjorlykke.org")) (:maintainer "Stig Bjørlykke," . "stig@bjorlykke.org") (:keywords "unix" "languages"))]) @@ -4355,9 +4379,9 @@ (rufo . [(20170718 1416) ((emacs (24 3))) "use rufo to automatically format ruby files" single ((:commit . "85a6d80fb05fef396a8029b8f944c92a53faf8fe") (:authors ("Daniel Ma" . "danielhgma@gmail.com")) (:maintainer "Daniel Ma" . "danielhgma@gmail.com") (:url . "https://github.com/danielma/rufo.el"))]) (ruled-switch-buffer . [(20211205 636) ((emacs (24 3))) "Rule based buffer switching" single ((:commit . "99b53f7679e3eb868e4b4585085bbed102e5fce7") (:authors ("Kazuki Nishikawa" . "kzkn@hey.com")) (:maintainer "Kazuki Nishikawa" . "kzkn@hey.com") (:keywords "convenience") (:url . "https://github.com/kzkn/ruled-switch-buffer"))]) (rum-mode . [(20180127 22) ((emacs (24))) "Major mode for Rum programming language" single ((:commit . "161471e6476d232d479f9767535918920811d7bf") (:keywords "rum" "languages" "lisp") (:url . "https://github.com/rumlang/rum-mode"))]) - (run-command . [(20230131 907) ((emacs (27 1))) "Run an external command from a context-dependent list" tar ((:commit . "e44bc5fb9712303150906f05ce7dd41c8c184aea") (:authors ("Massimiliano Mirra" . "hyperstruct@gmail.com")) (:maintainer "Massimiliano Mirra" . "hyperstruct@gmail.com") (:keywords "processes") (:url . "https://github.com/bard/emacs-run-command"))]) - (run-command-recipes . [(20230202 1326) ((emacs (25 1)) (dash (2 18 0)) (f (0 20 0)) (run-command (0 1 0))) "This is collection of recipes to `run-command'" tar ((:commit . "60e6fdbe6e8bea3871674a0e5779324ed5dbd318") (:authors ("semenInRussia" . "hrams205@gmail.com")) (:maintainer "semenInRussia" . "hrams205@gmail.com") (:keywords "extensions" "run-command") (:url . "https://github.com/semenInRussia/emacs-run-command-recipes"))]) - (run-stuff . [(20230115 633) ((emacs (25 1))) "Context based command execution" single ((:commit . "40ac5b62ee655dbba779488d96d844d929a1b6cd") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:keywords "files" "lisp" "files" "convenience" "hypermedia") (:url . "https://codeberg.org/ideasman42/emacs-run-stuff"))]) + (run-command . [(20230317 2004) ((emacs (27 1))) "Run an external command from a context-dependent list" tar ((:commit . "477c42acce9e36ec59d18deaa73992f94faf7b99") (:authors ("Massimiliano Mirra" . "hyperstruct@gmail.com")) (:maintainer "Massimiliano Mirra" . "hyperstruct@gmail.com") (:keywords "processes") (:url . "https://github.com/bard/emacs-run-command"))]) + (run-command-recipes . [(20230406 1757) ((emacs (25 1)) (dash (2 18 0)) (f (0 20 0)) (run-command (0 1 0))) "This is collection of recipes to `run-command'" tar ((:commit . "adbde3fddd67f1f40b3374c1696af03ac9b72e5e") (:authors ("semenInRussia" . "hrams205@gmail.com")) (:maintainer "semenInRussia" . "hrams205@gmail.com") (:keywords "extensions" "run-command") (:url . "https://github.com/semenInRussia/emacs-run-command-recipes"))]) + (run-stuff . [(20230319 459) ((emacs (25 1))) "Context based command execution" single ((:commit . "cd4d250603f0df835dbaf91c45ea603ffd52c416") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:keywords "files" "lisp" "files" "convenience" "hypermedia") (:url . "https://codeberg.org/ideasman42/emacs-run-stuff"))]) (runner . [(20160524 1048) nil "Improved \"open with\" suggestions for dired" single ((:commit . "a211d57ddc600410d07a8b534920ba905b093d87") (:authors ("Thamer Mahmoud" . "thamer.mahmoud@gmail.com")) (:maintainer "Thamer Mahmoud" . "thamer.mahmoud@gmail.com") (:keywords "shell command" "dired" "file extension" "open with") (:url . "https://github.com/thamer/runner"))]) (runtests . [(20150807 831) nil "Run unit tests from Emacs" single ((:commit . "ed90249f24cc48290018df48b9b9b7172440be3e") (:authors ("Sune Simonsen" . "sune@we-knowhow.dk")) (:maintainer "Sune Simonsen" . "sune@we-knowhow.dk") (:keywords "test") (:url . "https://github.com/sunesimonsen/emacs-runtests"))]) (russian-holidays . [(20170109 2140) nil "Russian holidays for the calendar" single ((:commit . "b285a30f29d85c48e3ea4eb93972d34a090c167b") (:authors ("Alexander I.Grafov" . "siberian@laika.name")) (:maintainer "Alexander I.Grafov" . "siberian@laika.name") (:url . "https://github.com/grafov/russian-holidays"))]) @@ -4390,7 +4414,7 @@ (say-what-im-doing . [(20160706 1931) nil "dictate what you're doing with text to speech" single ((:commit . "5b2ce6783b02805bcac1107a149bfba3852cd9d5") (:authors ("Benaiah Mischenko")) (:maintainer "Benaiah Mischenko") (:keywords "text to speech" "dumb" "funny") (:url . "http://github.com/benaiah/say-what-im-doing"))]) (sayid . [(20220101 1357) ((cider (0 21 0))) "sayid nREPL middleware client" single ((:commit . "879aff586336a0ec4d46c0ed4720fb1de22082bd") (:authors ("Bill Piel" . "bill@billpiel.com")) (:maintainer "Bozhidar Batsov" . "bozhidar@batsov.dev") (:keywords "clojure" "cider" "debugger") (:url . "https://github.com/clojure-emacs/sayid"))]) (sbt-mode . [(20211203 1148) ((emacs (24 4))) "Interactive support for sbt projects" tar ((:commit . "9fe1e8807c22cc1dc56a6233e000969518907f4d") (:keywords "languages") (:url . "https://github.com/hvesalai/emacs-sbt-mode"))]) - (scad-mode . [(20230218 2025) ((emacs (27 1)) (compat (29 1 3 4))) "A major mode for editing OpenSCAD code" tar ((:commit . "3be01e4213f6828234e73c1f7ec66c0fb594abef") (:authors ("Len Trigg, Łukasz Stelmach, zk_phi, Daniel Mendler")) (:maintainer "Len Trigg , Daniel Mendler" . "mail@daniel-mendler.de") (:keywords "languages") (:url . "https://github.com/openscad/emacs-scad-mode"))]) + (scad-mode . [(20230315 1950) ((emacs (27 1)) (compat (29 1 4 0))) "A major mode for editing OpenSCAD code" tar ((:commit . "e1af74735ad6113448c99b3ab128a665e6adaaca") (:authors ("Len Trigg, Łukasz Stelmach, zk_phi, Daniel Mendler")) (:maintainer "Len Trigg , Daniel Mendler" . "mail@daniel-mendler.de") (:keywords "languages") (:url . "https://github.com/openscad/emacs-scad-mode"))]) (scad-preview . [(20211212 1128) ((scad-mode (91 0)) (emacs (24 4))) "Preview SCAD models in real-time within Emacs" single ((:commit . "c5449b26c63f3e0a695905a7e4e84f8d844f761b") (:authors ("zk_phi")) (:maintainer "zk_phi") (:url . "https://zk-phi.github.io/"))]) (scala-mode . [(20221025 1502) nil "Major mode for editing Scala" tar ((:commit . "5d7cf21c37e345c49f921fe5111a49fd54efd1e0") (:keywords "languages") (:url . "https://github.com/hvesalai/emacs-scala-mode"))]) (scf-mode . [(20151122 248) nil "shorten file-names in compilation type buffers" single ((:commit . "dbfcdcd89034f208d65e181af58e0d73ad09f8b2") (:authors ("Le Wang")) (:maintainer "Le Wang") (:keywords "compilation") (:url . "https://github.com/lewang/scf-mode"))]) @@ -4398,9 +4422,9 @@ (scholar-import . [(20220730 431) ((emacs (26 1)) (org (9 0)) (request (0 3 0)) (s (1 10 0))) "Import Bibtex & PDF from Google Scholar" single ((:commit . "7cb04af45f1ed1db30d6e7788803e578c641b3b6") (:authors ("Anh T Nguyen ")) (:maintainer "Anh T Nguyen ") (:url . "https://github.com/teeann/scholar-import"))]) (schrute . [(20170521 1840) ((emacs (24 3))) "Help you remember there is a better way to do something." single ((:commit . "59faa6c4232ae183cea93237301acad8c0763997") (:authors ("Jorge Araya Navarro" . "elcorreo@deshackra.com")) (:maintainer "Jorge Araya Navarro" . "elcorreo@deshackra.com") (:keywords "convenience") (:url . "https://bitbucket.org/shackra/dwight-k.-schrute"))]) (scihub . [(20220913 618) ((emacs (27 1))) "Sci-Hub integration" single ((:commit . "56aa7205b5f2a6c9821557f9f1b9ff76dc1bb882") (:authors ("Mario Rodas" . "marsam@users.noreply.github.com")) (:maintainer "Mario Rodas" . "marsam@users.noreply.github.com") (:keywords "convenience") (:url . "https://github.com/emacs-pe/scihub.el"))]) - (scion . [(20130315 1255) nil "Haskell Minor Mode for Interacting with the Scion Library" single ((:commit . "99b4589175665687181a932cd836850205625f71") (:url . "https://code.google.com/p/scion-lib/"))]) (sclang-extensions . [(20160509 338) ((auto-complete (1 4 0)) (s (1 3 1)) (dash (1 2 0)) (emacs (24 1))) "Extensions for the SuperCollider Emacs mode." tar ((:commit . "e9cc79732f16fdb582129303110c163dcc0d6da0") (:authors ("Chris Barrett" . "chris.d.barrett@me.com")) (:maintainer "Chris Barrett" . "chris.d.barrett@me.com") (:keywords "sclang" "supercollider" "languages" "tools"))]) (sclang-snippets . [(20130513 751) ((yasnippet (0 8 0))) "Snippets for the SuperCollider Emacs mode" tar ((:commit . "c840a416b96f83bdd70491e3d1fbe2f1ae8b3f58") (:authors ("ptrv" . "mail@petervasil.net")) (:maintainer "ptrv" . "mail@petervasil.net") (:keywords "snippets"))]) + (scopeline . [(20230327 331) ((emacs (26 1))) "Show scope info of blocks in buffer at end of scope" single ((:commit . "204d2c635e93e0702c15f6d4faf9bffb39ecff7e") (:keywords "scope" "context" "tree-sitter" "convenience") (:url . "https://github.com/meain/scopeline.el"))]) (scpaste . [(20221125 1731) ((htmlize (1 39))) "Paste to the web via scp." single ((:commit . "56c67ef63be86ef1f03e15a62ad17c3983e1e5dc") (:authors ("Phil Hagelberg")) (:maintainer "Phil Hagelberg") (:keywords "convenience" "hypermedia") (:url . "https://git.sr.ht/~technomancy/scpaste"))]) (scratch . [(20220319 1705) ((emacs (25 1))) "Mode-specific scratch buffers" single ((:commit . "f000648c9663833a76a8de9b1e78c99a9d698e48") (:authors ("Ian Eure" . "ian.eure@gmail.com")) (:maintainer "Ian Eure" . "ian.eure@gmail.com") (:keywords "convenience" "tools" "files") (:url . "https://github.com/ieure/scratch-el"))]) (scratch-comment . [(20200812 1025) ((emacs (26 1))) "Insert Elisp result as comment in scratch buffer" single ((:commit . "cf3e967b4def1308b6ef1cfeedd2cf15ee6e226c") (:authors ("Naoya Yamashita" . "conao3@gmail.com")) (:maintainer "Naoya Yamashita" . "conao3@gmail.com") (:keywords "convenience") (:url . "https://github.com/conao3/scratch-comment.el"))]) @@ -4411,7 +4435,7 @@ (scratch-pop . [(20200910 226) nil "Generate, popup (& optionally backup) scratch buffer(s)." single ((:commit . "545badcd840dd50b39dd7dfa37459c6f71d02ea6") (:authors ("zk_phi")) (:maintainer "zk_phi") (:url . "http://hins11.yu-yake.com/"))]) (scratches . [(20151006 416) ((dash (2 11 0)) (f (0 17 0))) "Multiple scratches in any language" single ((:commit . "9441afe6396ca38f08029123fab5d87429cbf315") (:authors ("Zhang Kai Yu" . "yeannylam@gmail.com")) (:maintainer "Zhang Kai Yu" . "yeannylam@gmail.com") (:keywords "scratch"))]) (scribble-mode . [(20190912 200) ((emacs (24))) "Major mode for editing Scribble documents" single ((:commit . "5c3ea3cc9bbad585476eee41ea76dc056c2012bb") (:authors ("Mario Rodas" . "marsam@users.noreply.github.com")) (:maintainer "Mario Rodas" . "marsam@users.noreply.github.com") (:keywords "convenience") (:url . "https://github.com/emacs-pe/scribble-mode"))]) - (scroll-on-drag . [(20230201 128) ((emacs (26 2))) "Interactive scrolling" single ((:commit . "12101b8cae16ef7d22013aa131d8d7c2808b5f48") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:url . "https://codeberg.org/ideasman42/emacs-scroll-on-drag"))]) + (scroll-on-drag . [(20230313 546) ((emacs (26 2))) "Interactive scrolling" single ((:commit . "179c2acecc48d3ceca4b449b2a225d684002bb32") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:url . "https://codeberg.org/ideasman42/emacs-scroll-on-drag"))]) (scroll-on-jump . [(20230201 141) ((emacs (26 2))) "Scroll when jumping to a new point" single ((:commit . "220e4a8f21cc0b430c693a3ecac08156da2602c1") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:url . "https://codeberg.com/ideasman42/emacs-scroll-on-jump"))]) (scrollable-quick-peek . [(20201224 329) ((quick-peek (1 0)) (emacs (24 4))) "Display scrollable overlays" single ((:commit . "3e3492145a61831661d6e97fdcb47b5b66c73287") (:authors ("Pablo Barrantes" . "xjpablobrx@gmail.com")) (:maintainer "Pablo Barrantes" . "xjpablobrx@gmail.com") (:keywords "convenience" "extensions" "help" "tools") (:url . "https://github.com/jpablobr/scrollable-quick-peek"))]) (scrollkeeper . [(20190109 629) ((emacs (25 1))) "Custom scrolling commands with visual guidelines" single ((:commit . "3c4ac6b6b44686d31c260ee0b19daaee59bdccd6") (:authors ("Adam Porter" . "adam@alphapapa.net")) (:maintainer "Adam Porter" . "adam@alphapapa.net") (:keywords "convenience") (:url . "https://github.com/alphapapa/scrollkeeper.el"))]) @@ -4443,7 +4467,7 @@ (sensitive . [(20170818 1251) ((emacs (24)) (sequences (0 1 0))) "A dead simple way to load sensitive information" single ((:commit . "69dd6125a41d8b55f4b6ba61daa4d1aa1f716fa8") (:authors ("Tim Visher" . "tim.visher@gmail.com")) (:maintainer "Tim Visher" . "tim.visher@gmail.com") (:keywords "convenience"))]) (sentence-navigation . [(20220522 1137) ((ample-regexps (0 1)) (cl-lib (0 5)) (emacs (24 4))) "Commands to navigate one-spaced sentences." single ((:commit . "ea6e94a5518643acda5b6e98e4e7f47dfc107d29") (:authors ("Fox Kiester" . "noct@openmailbox.org")) (:maintainer "Fox Kiester" . "noct@openmailbox.org") (:keywords "sentence" "evil") (:url . "https://github.com/noctuid/emacs-sentence-navigation"))]) (seoul256-theme . [(20180505 757) ((emacs (24 3))) "Low-contrast color scheme based on Seoul Colors." single ((:commit . "8e76d0207489964ef780420723d49e409f68f7d1") (:authors ("Anand Iyer" . "anand.ucb@gmail.com")) (:maintainer "Anand Iyer" . "anand.ucb@gmail.com") (:keywords "theme") (:url . "http://github.com/anandpiyer/seoul256-emacs"))]) - (separedit . [(20230201 752) ((emacs (25 1)) (dash (2 18)) (edit-indirect (0 1 5))) "Edit comment/string/docstring/code block in separate buffer" single ((:commit . "03e356f1a645a884921975890899fb47acf7d00d") (:authors ("Gong Qijian" . "gongqijian@gmail.com")) (:maintainer "Gong Qijian" . "gongqijian@gmail.com") (:keywords "tools" "languages" "docs") (:url . "https://github.com/twlz0ne/separedit.el"))]) + (separedit . [(20230403 1242) ((emacs (25 1)) (dash (2 18)) (edit-indirect (0 1 5))) "Edit comment/string/docstring/code block in separate buffer" single ((:commit . "8344e7338a0ab7968cab807e0073934a8444559d") (:authors ("Gong Qijian" . "gongqijian@gmail.com")) (:maintainer "Gong Qijian" . "gongqijian@gmail.com") (:keywords "tools" "languages" "docs") (:url . "https://github.com/twlz0ne/separedit.el"))]) (sequed . [(20220115 743) ((emacs (25 2))) "Major mode for FASTA format DNA alignments" single ((:commit . "c886981c46d199e1522f18c3fc15198ab8c9a02f") (:authors ("Bruce Rannala" . "brannala@ucdavis.edu")) (:maintainer "Bruce Rannala" . "brannala@ucdavis.edu") (:url . "https://github.com/brannala/sequed"))]) (sequences . [(20170818 1252) ((emacs (24))) "Ports of some Clojure sequence functions." single ((:commit . "564ebbd93b0beea4e75acfbf824350e90b5d5738") (:authors ("Tim Visher" . "tim.visher@gmail.com")) (:maintainer "Tim Visher" . "tim.visher@gmail.com") (:keywords "convenience"))]) (sequential-command . [(20170926 40) nil "Many commands into one command" tar ((:commit . "a48cbcbe273b33edd3ae56e68f44b4100fa3a48a") (:authors ("rubikitch" . "rubikitch@ruby-lang.org")) (:maintainer "rubikitch" . "rubikitch@ruby-lang.org") (:keywords "convenience" "lisp") (:url . "http://www.emacswiki.org/cgi-bin/wiki/download/sequential-command.el"))]) @@ -4453,7 +4477,7 @@ (services . [(20170802 1130) ((cl-lib (0 5))) "Services database access functions." single ((:commit . "04c7986041a33dfa0b0ae57c7d6fbd600548c596") (:authors ("Dave Pearson" . "davep@davep.org")) (:maintainer "Dave Pearson" . "davep@davep.org") (:keywords "convenience" "net" "services") (:url . "https://github.com/davep/services.el"))]) (sesman . [(20210901 1134) ((emacs (25))) "Generic Session Manager" tar ((:commit . "e0f555f963c9f02f8e4a50e06fc353eb4c15ee77") (:authors ("Vitalie Spinu")) (:maintainer "Vitalie Spinu") (:keywords "process") (:url . "https://github.com/vspinu/sesman"))]) (session . [(20120511 0) nil "use variables, registers and buffer places across sessions" single ((:commit . "19ea0806873daac3539a4b956e15655e99e3dd6c") (:authors ("Christoph Wedler" . "wedler@users.sourceforge.net")) (:maintainer "Christoph Wedler" . "wedler@users.sourceforge.net") (:keywords "session" "session management" "desktop" "data" "tools") (:url . "http://emacs-session.sourceforge.net/"))]) - (session-async . [(20220302 2008) ((emacs (27 1)) (jsonrpc (1 0 9))) "Asynchronous processing in a forked process session" single ((:commit . "427238bdfde880106dd39cf5845b559975e52f4f") (:authors ("Felipe Lema" . "felipelema@mortemale.org")) (:maintainer "Felipe Lema" . "felipelema@mortemale.org") (:keywords "async" "comm" "data" "files" "internal" "maint" "processes" "tools") (:url . "https://codeberg.org/FelipeLema/session-async.el"))]) + (session-async . [(20230223 313) ((emacs (27 1)) (jsonrpc (1 0 9))) "Asynchronous processing in a forked process session" single ((:commit . "e06835ea181b3a15099280527c9a4590d2fa61d1") (:authors ("Felipe Lema" . "felipelema@mortemale.org")) (:maintainer "Felipe Lema" . "felipelema@mortemale.org") (:keywords "async" "comm" "data" "files" "internal" "maint" "processes" "tools") (:url . "https://codeberg.org/FelipeLema/session-async.el"))]) (seti-theme . [(20190201 1848) nil "A dark colored theme, inspired by Seti Atom Theme" single ((:commit . "9d76db0b91d4f574dd96ac80fad41da35bffa109") (:authors ("Vlad Piersec" . "vlad.piersec@gmail.com")) (:maintainer "Vlad Piersec" . "vlad.piersec@gmail.com") (:keywords "themes") (:url . "https://github.com/caisah/seti-theme"))]) (sexp-diff . [(20200314 2018) ((emacs (25))) "Diff sexps based on Levenshtein-like edit distance" single ((:commit . "4fea80f7b04c64b160a95bdc9d6de68c71096706") (:authors ("Xu Chunyang")) (:maintainer "Xu Chunyang") (:keywords "lisp") (:url . "https://github.com/xuchunyang/sexp-diff.el"))]) (sexp-move . [(20150915 1730) nil "Improved S-Expression Movement" single ((:commit . "117f7a91ab7c25e438413753e916570122011ce7") (:authors ("Philip Woods" . "elzairthesorcerer@gmail.com")) (:maintainer "Philip Woods" . "elzairthesorcerer@gmail.com") (:keywords "sexp") (:url . "https://gitlab.com/elzair/sexp-move"))]) @@ -4481,11 +4505,11 @@ (shelldon . [(20220325 1305) ((emacs (27 1))) "An enhanced shell interface" single ((:commit . "8d073ce580e7782ed863fc6e19dc33b4f73c0d79") (:authors ("overdr0ne" . "scmorris.dev@gmail.com")) (:maintainer "overdr0ne" . "scmorris.dev@gmail.com") (:keywords "tools" "convenience") (:url . "https://github.com/Overdr0ne/shelldon"))]) (shelltest-mode . [(20180501 141) nil "Major mode for shelltestrunner" single ((:commit . "5fea8c9394380e822971a171905b6b5ab9be812d") (:authors ("Dustin Fechner" . "dfe@rtrn.io")) (:maintainer "Dustin Fechner" . "dfe@rtrn.io") (:keywords "languages") (:url . "https://github.com/rtrn/shelltest-mode"))]) (shen-elisp . [(20221211 1313) ((emacs (24 4))) "Shen implementation in Elisp" tar ((:commit . "957ab44654fc7a7cc1b78181d244fa25166f9b09") (:authors ("Aditya Siram" . "aditya.siram@gmail.com")) (:maintainer "Aditya Siram" . "aditya.siram@gmail.com") (:url . "https://github.com/deech/shen-elisp"))]) - (shenshou . [(20230116 805) ((emacs (27 1))) "Download&Extract subtitles from opensubtitles.org" single ((:commit . "763f28b2d132ed94bb57ca08ef12ff1454b7f7d3") (:authors ("Chen Bin ")) (:maintainer "Chen Bin ") (:keywords "convenience" "tools") (:url . "http://github.com/redguardtoo/shenshou"))]) + (shenshou . [(20230226 320) ((emacs (27 1))) "Download&Extract subtitles from opensubtitles.org" single ((:commit . "0a00b9f5a86a54324f88c7d27b603f136ee2fb0b") (:authors ("Chen Bin ")) (:maintainer "Chen Bin ") (:keywords "convenience" "tools") (:url . "http://github.com/redguardtoo/shenshou"))]) (shfmt . [(20220602 1535) ((emacs (24)) (reformatter (0 3))) "Reformat shell scripts using shfmt" single ((:commit . "279a51defa3e0d97dc40b8a26e078699d4e22e90") (:authors ("Steve Purcell" . "steve@sanityinc.com")) (:maintainer "Steve Purcell" . "steve@sanityinc.com") (:keywords "languages") (:url . "https://github.com/purcell/emacs-shfmt"))]) (shift-number . [(20170301 1459) nil "Increase/decrease the number at point" single ((:commit . "94c3713cc11283a831f66d5205d112762edc186b") (:authors ("Alex Kost" . "alezost@gmail.com")) (:maintainer "Alex Kost" . "alezost@gmail.com") (:keywords "convenience") (:url . "https://github.com/alezost/shift-number.el"))]) (shift-text . [(20130831 1655) ((cl-lib (1 0)) (es-lib (0 3))) "Move the region in 4 directions, in a way similar to Eclipse's" single ((:commit . "1be9cbf994000022172ceb746fe1d597f57ea8ba") (:authors ("sabof")) (:maintainer "sabof") (:url . "https://github.com/sabof/shift-text"))]) - (shimbun . [(20230127 612) nil "interfacing with web newspapers" tar ((:commit . "e556f82247918bdc33acf01b29917314b8b9e22b") (:authors ("TSUCHIYA Masatoshi" . "tsuchiya@namazu.org") ("Akihiro Arisawa " . "ari@mbf.sphere.ne.jp") ("Yuuichi Teranishi " . "teranisi@gohome.org") ("Katsumi Yamaoka " . "yamaoka@jpl.org")) (:maintainer "TSUCHIYA Masatoshi" . "tsuchiya@namazu.org") (:keywords "news"))]) + (shimbun . [(20230324 125) nil "interfacing with web newspapers" tar ((:commit . "f8819bca0c97970662cd4214f8f3104ab4a376c1") (:authors ("TSUCHIYA Masatoshi" . "tsuchiya@namazu.org") ("Akihiro Arisawa " . "ari@mbf.sphere.ne.jp") ("Yuuichi Teranishi " . "teranisi@gohome.org") ("Katsumi Yamaoka " . "yamaoka@jpl.org")) (:maintainer "TSUCHIYA Masatoshi" . "tsuchiya@namazu.org") (:keywords "news"))]) (shm . [(20180327 57) nil "Structured Haskell Mode" tar ((:commit . "7f9df73f45d107017c18ce4835bbc190dfe6782e") (:authors ("Chris Done" . "chrisdone@gmail.com")) (:maintainer "Chris Done" . "chrisdone@gmail.com") (:keywords "development" "haskell" "structured"))]) (shoulda . [(20140616 1833) ((cl-lib (0 5))) "Shoulda test support for ruby" single ((:commit . "24dc6b6138a06edde9c8d13a6aaa1654d1d7de54") (:authors ("Marcwebbie" . "marcwebbie@gmail.com")) (:maintainer "Marcwebbie" . "marcwebbie@gmail.com") (:keywords "ruby" "tests" "shoulda"))]) (show-css . [(20160210 1408) ((doom (1 3)) (s (1 10 0))) "Show the css of the html attribute the cursor is on" tar ((:commit . "771daeddd4df7a7c10f66419a837145649bab63b") (:authors ("Sheldon McGrandle" . "developer@rednemesis.com")) (:maintainer "Sheldon McGrandle" . "developer@rednemesis.com") (:keywords "hypermedia") (:url . "https://github.com/smmcg/showcss-mode"))]) @@ -4506,9 +4530,9 @@ (side-notes . [(20210709 1403) ((emacs (24 4))) "Easy access to a directory notes file" single ((:commit . "41fe8544661a772f764a0924e04080f258053955") (:authors ("Paul W. Rankin" . "pwr@bydasein.com")) (:maintainer "Paul W. Rankin" . "pwr@bydasein.com") (:keywords "convenience") (:url . "https://github.com/rnkn/side-notes"))]) (sidecar-locals . [(20230109 536) ((emacs (27 1))) "A flexible alternative to built-in dir-locals" single ((:commit . "882923811e9de84c8ebc2f9fe65e9673d7d1f469") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:keywords "convenience") (:url . "https://codeberg.org/ideasman42/emacs-sidecar-locals"))]) (sideline . [(20230216 843) ((emacs (27 1))) "Show information on the side" single ((:commit . "0441f2c308eb9316f01d721a949ba73b6df8c4c7") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience") (:url . "https://github.com/emacs-sideline/sideline"))]) - (sideline-blame . [(20221231 1636) ((emacs (27 1)) (sideline (0 1 0)) (vc-msg (1 1 1))) "Show blame messages with sideline" single ((:commit . "1a1d80a71bdabe77fe2a33cd681b7188f193acfc") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "blame") (:url . "https://github.com/emacs-sideline/sideline-blame"))]) - (sideline-flycheck . [(20230216 859) ((emacs (27 1)) (sideline (0 1 1)) (flycheck (0 14)) (ht (2 4))) "Show flycheck errors with sideline" single ((:commit . "1f2f82d4383718a8dd2aff40cffafce4a8d0aca1") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "flycheck") (:url . "https://github.com/emacs-sideline/sideline-flycheck"))]) - (sideline-flymake . [(20230216 914) ((emacs (27 1)) (sideline (0 1 0))) "Show flymake errors with sideline" single ((:commit . "e92fa5ca861ff5a54273aecde319974fe4aa9dda") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "flymake") (:url . "https://github.com/emacs-sideline/sideline-flymake"))]) + (sideline-blame . [(20230406 2312) ((emacs (27 1)) (sideline (0 1 0)) (vc-msg (1 1 1))) "Show blame messages with sideline" single ((:commit . "4d3343795bc95662adb65c85bcbb41947862699f") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "blame") (:url . "https://github.com/emacs-sideline/sideline-blame"))]) + (sideline-flycheck . [(20230402 1816) ((emacs (27 1)) (sideline (0 1 1)) (flycheck (0 14)) (ht (2 4))) "Show flycheck errors with sideline" single ((:commit . "3d74a008835eff71899b9455cd00f989378fe70e") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "flycheck") (:url . "https://github.com/emacs-sideline/sideline-flycheck"))]) + (sideline-flymake . [(20230402 1816) ((emacs (27 1)) (sideline (0 1 0))) "Show flymake errors with sideline" single ((:commit . "316325cb050d13f33e83e7d7823e3730a70ecf4e") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "flymake") (:url . "https://github.com/emacs-sideline/sideline-flymake"))]) (sideline-lsp . [(20221231 1636) ((emacs (27 1)) (sideline (0 1 0)) (lsp-mode (6 0)) (dash (2 18 0)) (ht (2 4)) (s (1 12 0))) "Show lsp information with sideline" single ((:commit . "38ba700db1769de216989fb9217795934147d160") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "lsp") (:url . "https://github.com/emacs-sideline/sideline-lsp"))]) (sift . [(20200421 1423) nil "Front-end for sift, a fast and powerful grep alternative" single ((:commit . "cdddba2d183146c340915003f1b5d09d13712c22") (:authors ("Nicolas Lamirault" . "nicolas.lamirault@gmail.com")) (:maintainer "Nicolas Lamirault" . "nicolas.lamirault@gmail.com") (:keywords "sift" "ack" "pt" "ag" "grep" "search") (:url . "https://github.com/nlamirault/sift.el"))]) (signal . [(20160816 1438) ((emacs (24)) (cl-lib (0 5))) "Advanced hook" single ((:commit . "aa58327e2297df921d72a0370468b48663efd438") (:authors ("Mola-T" . "Mola@molamola.xyz")) (:maintainer "Mola-T" . "Mola@molamola.xyz") (:keywords "internal" "lisp" "processes" "tools") (:url . "https://github.com/mola-T/signal"))]) @@ -4530,9 +4554,9 @@ (simplezen . [(20130421 1000) ((s (1 4 0)) (dash (1 1 0))) "A simple subset of zencoding-mode for Emacs." single ((:commit . "9f91554a3f7f4e9b2b5ec009effafbf12b091973") (:authors ("Magnar Sveen" . "magnars@gmail.com")) (:maintainer "Magnar Sveen" . "magnars@gmail.com"))]) (simplicity-theme . [(20221016 1444) ((emacs (24 1))) "A minimalist dark theme" single ((:commit . "f4aab6aa07b536688eb62355b83dde5fcd16e049") (:authors ("Matthieu Petiteau" . "mpetiteau.pro@gmail.com")) (:maintainer "Matthieu Petiteau" . "mpetiteau.pro@gmail.com") (:keywords "faces" "theme" "minimal") (:url . "http://github.com/smallwat3r/emacs-simplicity-theme"))]) (siri-shortcuts . [(20211229 1833) ((emacs (25 2))) "Interact with Siri Shortcuts" single ((:commit . "190f242f71e071adfd89fa1f2f6ea22b62afd133") (:authors ("Daniils Petrovs" . "thedanpetrov@gmail.com")) (:maintainer "Daniils Petrovs" . "thedanpetrov@gmail.com") (:keywords "convenience" "multimedia") (:url . "https://github.com/DaniruKun/siri-shortcuts.el"))]) - (sis . [(20220721 1600) ((emacs (25 1)) (terminal-focus-reporting (0 0))) "Less manual switch for native or OS input source (input method)." single ((:commit . "d7a415b00bb1ddcf940d82afdd01e8b793d5466b") (:keywords "convenience") (:url . "https://github.com/laishulu/emacs-smart-input-source"))]) + (sis . [(20230305 1006) ((emacs (25 1)) (terminal-focus-reporting (0 0))) "Less manual switch for native or OS input source (input method)." single ((:commit . "e4142baa470e5f33dd508bce0264359dc5204b6f") (:keywords "convenience") (:url . "https://github.com/laishulu/emacs-smart-input-source"))]) (sisyphus . [(20230213 1152) ((emacs (27)) (compat (29 1 3 4)) (elx (1 6 0)) (llama (0 3 0)) (magit (3 4 0))) "Create releases of Emacs packages" single ((:commit . "1e6fd5ae0fb5384063e8b59d053bc5df7630cf5c") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "git" "tools" "vc") (:url . "https://github.com/magit/sisyphus"))]) - (sixcolors-mode . [(20221127 1208) ((emacs (27 1))) "A customizable horizontal scrollbar" single ((:commit . "fbcf57749ebc74d7b77d148da6c021b1a8e0f650") (:authors ("Davide Mastromatteo" . "mastro35@gmail.com")) (:maintainer "Davide Mastromatteo" . "mastro35@gmail.com") (:keywords "convenience" "colors") (:url . "https://github.com/mastro35/sixcolors-mode"))]) + (sixcolors-mode . [(20230406 1031) ((emacs (27 1))) "A customizable horizontal scrollbar" single ((:commit . "4124a8cf664b04a4bf4c39f7c3b7da3e480b99c8") (:authors ("Davide Mastromatteo" . "mastro35@gmail.com")) (:maintainer "Davide Mastromatteo" . "mastro35@gmail.com") (:keywords "convenience" "colors") (:url . "https://github.com/mastro35/sixcolors-mode"))]) (skeletor . [(20210129 239) ((s (1 7 0)) (f (0 14 0)) (dash (2 2 0)) (cl-lib (0 3)) (let-alist (1 0 3)) (emacs (24 1))) "Provides project skeletons for Emacs" tar ((:commit . "f6e560a0bfe459e0b8a268047920ce1148f2ebf6") (:authors ("Chris Barrett" . "chris.d.barrett@me.com")) (:maintainer "Chris Barrett" . "chris.d.barrett@me.com"))]) (skerrick . [(20220306 2139) ((emacs (27 1)) (request (0 3 2))) "REPL-driven development for NodeJS" single ((:commit . "015de8369b8b6be0d4d1e21c24239a037350e87e") (:authors ("Rafael Nicdao ")) (:maintainer "Rafael Nicdao" . "nicdaoraf@gmail.com") (:keywords "languages" "javascript" "js" "repl" "repl-driven") (:url . "https://github.com/anonimitoraf/skerrick"))]) (sketch-themes . [(20230210 1507) ((emacs (26 1))) "Sketch color themes" tar ((:commit . "5534254232f1a556ec20952c75b5506625573049") (:authors ("Daw-Ran Liou" . "hi@dawranliou.com")) (:maintainer "Daw-Ran Liou" . "hi@dawranliou.com") (:keywords "faces") (:url . "https://github.com/dawranliou/sketch-themes/"))]) @@ -4544,7 +4568,7 @@ (slack . [(20211129 310) ((websocket (1 8)) (request (0 2 0)) (oauth2 (0 10)) (circe (2 2)) (alert (1 2)) (emojify (0 2))) "Slack client for Emacs" tar ((:commit . "ff46d88726482211e3ac3d0b9c95dd4fdffe11c2") (:authors ("yuya.minami" . "yuya.minami@yuyaminami-no-MacBook-Pro.local")) (:maintainer "yuya.minami" . "yuya.minami@yuyaminami-no-MacBook-Pro.local") (:keywords "tools") (:url . "https://github.com/yuya373/emacs-slack"))]) (slideview . [(20150324 2240) ((cl-lib (0 3))) "File slideshow" single ((:commit . "b6d170bda139aedf81b47dc55cbd1a3af512fb4c") (:authors ("Masahiro Hayashi" . "mhayashi1120@gmail.com")) (:maintainer "Masahiro Hayashi" . "mhayashi1120@gmail.com") (:keywords "files") (:url . "https://github.com/mhayashi1120/Emacs-slideview"))]) (slim-mode . [(20170728 1348) nil "Major mode for editing Slim files" single ((:commit . "3636d18ab1c8b316eea71c4732eb44743e2ded87") (:authors ("Nathan Weizenbaum")) (:maintainer "Nathan Weizenbaum") (:keywords "markup" "language") (:url . "http://github.com/slim-template/emacs-slim"))]) - (slime . [(20230215 2125) ((cl-lib (0 5)) (macrostep (0 9))) "Superior Lisp Interaction Mode for Emacs" tar ((:commit . "5e8fc7cad5ae7dc19b434c559ebaee3185d80b98") (:keywords "languages" "lisp" "slime") (:url . "https://github.com/slime/slime"))]) + (slime . [(20230314 915) ((cl-lib (0 5)) (macrostep (0 9))) "Superior Lisp Interaction Mode for Emacs" tar ((:commit . "dd179f4a0c6874fe0e49fb6c460e9e52a5f58833") (:keywords "languages" "lisp" "slime") (:url . "https://github.com/slime/slime"))]) (slime-company . [(20210124 1627) ((emacs (24 4)) (slime (2 13)) (company (0 9 0))) "slime completion backend for company mode" single ((:commit . "f20ecc4104d4c35052696e7e760109fb02060e72") (:authors ("Ole Arndt" . "anwyn@sugarshark.com")) (:maintainer "Ole Arndt" . "anwyn@sugarshark.com") (:keywords "convenience" "lisp" "abbrev"))]) (slime-docker . [(20210426 1422) ((emacs (24 4)) (slime (2 16)) (docker-tramp (0 1))) "Integration of SLIME with Docker containers" tar ((:commit . "c7d073720f2bd8e9f72a20309fff2afa4c4e798d") (:keywords "docker" "lisp" "slime") (:url . "https://gitlab.common-lisp.net/cl-docker-images/slime-docker"))]) (slime-repl-ansi-color . [(20230214 1453) ((emacs (24)) (slime (2 3 1))) "Turn on ANSI colors in REPL output;" single ((:commit . "9e8af90490332217e45d7568f1690df3f4e25d4b") (:authors ("Max Mikhanosha" . "max@openchat.com")) (:maintainer "Augustin Fabre" . "augustin@augfab.fr") (:keywords "lisp") (:url . "https://gitlab.com/augfab/slime-repl-ansi-color"))]) @@ -4555,7 +4579,7 @@ (slow-keys . [(20220807 1425) ((emacs (24 1))) "Slow keys mode to avoid RSI" single ((:commit . "b951ae4bdcea56ced03f227b82b28c3d91d15e61") (:authors ("Manuel Uberti" . "manuel.uberti@inventati.org")) (:maintainer "Manuel Uberti" . "manuel.uberti@inventati.org") (:keywords "convenience") (:url . "https://github.com/manuel-uberti/slow-keys"))]) (slstats . [(20170823 849) ((cl-lib (0 5)) (emacs (24))) "Acquire and display stats about Second Life" single ((:commit . "e9696066abf3f2b7b818a57c062530dfd9377033") (:authors ("Dave Pearson" . "davep@davep.org")) (:maintainer "Dave Pearson" . "davep@davep.org") (:keywords "games") (:url . "https://github.com/davep/slstats.el"))]) (slurm-mode . [(20210519 1109) nil "Interaction with the SLURM job scheduling system" tar ((:commit . "4e6ac09245313cf4018b8e5784b2fca8604269d7") (:url . "https://github.com/ffevotte/slurm.el"))]) - (sly . [(20230216 1140) ((emacs (24 3))) "Sylvester the Cat's Common Lisp IDE" tar ((:commit . "fa70fc8ab1bc1f1c21661d672834e41b1d0abd39") (:keywords "languages" "lisp" "sly") (:url . "https://github.com/joaotavora/sly"))]) + (sly . [(20230327 1434) ((emacs (24 3))) "Sylvester the Cat's Common Lisp IDE" tar ((:commit . "82b20a9a83209b4dbfbfb62a1536896aed5f85f7") (:keywords "languages" "lisp" "sly") (:url . "https://github.com/joaotavora/sly"))]) (sly-asdf . [(20221119 2235) ((emacs (24 3)) (sly (1 0 0 -2 2)) (popup (0 5 3))) "ASDF system support for SLY" tar ((:commit . "6f9d751469bb82530db1673c22e7437ca6c95f45") (:maintainer "Matt George" . "mmge93@gmail.com") (:keywords "languages" "lisp" "sly" "asdf") (:url . "https://github.com/mmgeorge/sly-asdf"))]) (sly-hello-world . [(20200225 1755) ((sly (1 0 0 -2 2))) "A template SLY contrib" tar ((:commit . "be257e9ad354db690c7378e89899335597348a0d") (:authors ("João Távora" . "joaotavora@gmail.com")) (:maintainer "João Távora" . "joaotavora@gmail.com") (:keywords "languages" "lisp" "sly") (:url . "https://github.com/capitaomorte/sly-hello-world"))]) (sly-macrostep . [(20191211 1630) ((sly (1 0 0 -2 2)) (macrostep (0 9))) "fancy macro-expansion via macrostep.el" tar ((:commit . "5113e4e926cd752b1d0bcc1508b3ebad5def5fad") (:keywords "languages" "lisp" "sly") (:url . "https://github.com/capitaomorte/sly-macrostep"))]) @@ -4582,7 +4606,7 @@ (smart-tab . [(20210530 1743) ((emacs (24 3))) "Intelligent tab completion and indentation" single ((:commit . "2f1b4073904805c8454ebc9bc967b23836a2d577") (:authors ("John SJ Anderson" . "john@genehack.org") ("Sebastien Rocca Serra" . "sroccaserra@gmail.com") ("Daniel Hackney" . "dan@haxney.org")) (:maintainer "John SJ Anderson" . "john@genehack.org") (:keywords "extensions") (:url . "https://git.genehack.net/genehack/smart-tab"))]) (smart-tabs-mode . [(20200907 2025) nil "Intelligently indent with tabs, align with spaces!" single ((:commit . "1044c17e42479de943e69cdeb85e4d05ad9cca8c") (:authors ("John Croisant" . "jacius@gmail.com") ("Alan Pearce" . "alan@alanpearce.co.uk") ("Daniel Dehennin" . "daniel.dehennin@baby-gnu.org") ("Matt Renaud" . "mrenaud92@gmail.com")) (:maintainer "Joel C. Salomon" . "joelcsalomon@gmail.com") (:keywords "languages") (:url . "http://www.emacswiki.org/emacs/SmartTabs"))]) (smart-window . [(20160717 130) ((cl-lib (0 5))) "vim-like window controlling plugin" single ((:commit . "5996461b7cbc5ab4509ac48537916eb29a8e4c16") (:authors ("Felix Chern" . "idryman@gmail.com")) (:maintainer "Felix Chern" . "idryman@gmail.com") (:keywords "window") (:url . "https://github.com/dryman/smart-window.el"))]) - (smartparens . [(20230219 1728) ((dash (2 13 0)) (cl-lib (0 3))) "Automatic insertion, wrapping and paredit-like navigation with user defined pairs." tar ((:commit . "f0c863268d296e38d4b5374f4c165cf9a823cd8c") (:authors ("Matus Goljer" . "matus.goljer@gmail.com")) (:maintainer "Matus Goljer" . "matus.goljer@gmail.com") (:keywords "abbrev" "convenience" "editing") (:url . "https://github.com/Fuco1/smartparens"))]) + (smartparens . [(20230225 1026) ((dash (2 13 0)) (cl-lib (0 3))) "Automatic insertion, wrapping and paredit-like navigation with user defined pairs." tar ((:commit . "1d5cd5e8d46e182b935f8cd3cf29c8c4410aab0a") (:authors ("Matus Goljer" . "matus.goljer@gmail.com")) (:maintainer "Matus Goljer" . "matus.goljer@gmail.com") (:keywords "abbrev" "convenience" "editing") (:url . "https://github.com/Fuco1/smartparens"))]) (smartrep . [(20150509 230) nil "Support sequential operation which omitted prefix keys." single ((:commit . "f0ff5a6d7b8603603598ae3045c98b011e58d86e") (:authors ("myuhe ")) (:maintainer "myuhe") (:keywords "convenience") (:url . "https://github.com/myuhe/smartrep.el"))]) (smartscan . [(20170211 2033) nil "Jumps between other symbols found at point" single ((:commit . "234e077145710a174c20742de792b97ed2f965f6") (:authors ("Mickey Petersen" . "mickey@masteringemacs.org")) (:maintainer "Mickey Petersen" . "mickey@masteringemacs.org") (:keywords "extensions"))]) (smarty-mode . [(20100703 1158) nil "major mode for editing smarty templates" single ((:commit . "3dfdfe1571f5e9ef55a29c51e5a80046d4cb7568") (:maintainer "Benj Carson") (:keywords "smarty" "php" "languages" "templates") (:url . "none yet"))]) @@ -4614,7 +4638,7 @@ (snoopy . [(20171008 2004) ((emacs (24)) (cl-lib (0 6))) "minor mode for number row unshifted character insertion" single ((:commit . "ec4123bdebfe0bb7bf4feaac2dc02b59caffe386") (:authors ("António Nuno Monteiro" . "anmonteiro@gmail.com")) (:maintainer "António Nuno Monteiro" . "anmonteiro@gmail.com") (:keywords "lisp"))]) (snow . [(20221226 2238) ((emacs (26 3))) "Let it snow in Emacs!" single ((:commit . "be17977677fa29709a726715a1a1cba1bd299f68") (:authors ("Adam Porter" . "adam@alphapapa.net")) (:maintainer "Adam Porter" . "adam@alphapapa.net") (:keywords "games") (:url . "https://github.com/alphapapa/snow.el"))]) (soar-mode . [(20190503 1843) nil "A major mode for the Soar language" single ((:commit . "ebb79789cd35530aea2c6d0eb4f4b280e97107d4") (:keywords "languages" "soar") (:url . "https://github.com/adeschamps/soar-mode"))]) - (soccer . [(20221127 1534) ((emacs (26 1)) (dash (2 19 1))) "Fixtures, results, table etc for soccer" tar ((:commit . "49d0db4f6274f1bd39c58255be069f79e310f465") (:authors ("Md Arif Shaikh" . "arifshaikh.astro@gmail.com")) (:maintainer "Md Arif Shaikh" . "arifshaikh.astro@gmail.com") (:keywords "games" "soccer" "football") (:url . "https://github.com/md-arif-shaikh/soccer"))]) + (soccer . [(20230403 1518) ((emacs (26 1)) (dash (2 19 1))) "Fixtures, results, table etc for soccer" tar ((:commit . "4515eaa5e12613185f4569c79772db886dcfa2f7") (:authors ("Md Arif Shaikh" . "arifshaikh.astro@gmail.com")) (:maintainer "Md Arif Shaikh" . "arifshaikh.astro@gmail.com") (:keywords "games" "soccer" "football") (:url . "https://github.com/md-arif-shaikh/soccer"))]) (socyl . [(20170212 642) ((s (1 11 0)) (dash (2 12 0)) (pkg-info (0 5 0)) (cl-lib (0 5))) "Frontend for several search tools" tar ((:commit . "1ef2da42f66f3ab31a34131e51648f352416f0ba") (:authors ("Nicolas Lamirault" . "nicolas.lamirault@gmail.com")) (:maintainer "Nicolas Lamirault" . "nicolas.lamirault@gmail.com") (:keywords "ripgrep" "sift" "ack" "pt" "ag" "grep" "search") (:url . "https://github.com/nlamirault/socyl"))]) (soft-charcoal-theme . [(20140420 1643) nil "Dark charcoal theme with soft colors" single ((:commit . "5607ab977fae6638e78b1495e02da8955c9ba19f") (:authors ("Martin Haesler")) (:maintainer "Martin Haesler") (:url . "http://github.com/mswift42/soft-charcoal-theme"))]) (soft-morning-theme . [(20150918 2041) nil "Emacs24 theme with a light background." single ((:commit . "c0f9c70c97ef2be2a093cf839c4bfe27740a111c") (:authors ("Martin Haesler")) (:maintainer "Martin Haesler") (:url . "http://github.com/mswift42/soft-morning-theme"))]) @@ -4629,7 +4653,7 @@ (soong-mode . [(20221217 1243) ((emacs (27 1))) "Major mode for editing Soong build files" single ((:commit . "bf3dc1070b368b413958f54fbe9bcc2aaf77b56f") (:authors ("Sergey Bobrenok" . "bobrofon@gmail.com")) (:maintainer "Sergey Bobrenok" . "bobrofon@gmail.com") (:keywords "languages") (:url . "https://github.com/bobrofon/soong-mode"))]) (soothe-theme . [(20220922 349) ((emacs (24 3)) (autothemer (0 2))) "A dark colorful theme" tar ((:commit . "d8aee0fca549d535ebb7b5fd1a8017f12925d16b") (:authors ("Jason Milkins" . "jasonm23@gmail.com")) (:maintainer "Jason Milkins" . "jasonm23@gmail.com") (:url . "https://github.com/emacsfodder/emacs-soothe-theme"))]) (sorcery-theme . [(20210101 1352) ((autothemer (0 2))) "A D&D (Dark and Dusty) Theme" single ((:commit . "5a1c4445b9e6e09589a299a9962a6973272a0c2f") (:authors ("Maxime Tréca" . "maxime@gmail.com")) (:maintainer "Maxime Tréca" . "maxime@gmail.com") (:url . "http://github.com/vxid/emacs-theme-sorcery"))]) - (soria-theme . [(20230102 1459) ((emacs (25 1))) "A xoria256 theme with some colors from openSUSE" tar ((:commit . "7669770034f773bd96a71bb5e0cde93a8f0495e9") (:authors ("Miquel Sabaté Solà" . "mikisabate@gmail.com")) (:maintainer "Miquel Sabaté Solà" . "mikisabate@gmail.com") (:keywords "faces") (:url . "https://github.com/mssola/soria"))]) + (soria-theme . [(20230227 1454) ((emacs (25 1))) "A xoria256 theme with some colors from openSUSE" tar ((:commit . "c5275d02fcc9f6af2cfebd69bcf69f8cdccbe3ab") (:authors ("Miquel Sabaté Solà" . "mikisabate@gmail.com")) (:maintainer "Miquel Sabaté Solà" . "mikisabate@gmail.com") (:keywords "faces") (:url . "https://github.com/mssola/soria"))]) (sort-words . [(20160929 1335) nil "Sort words in a selected region" single ((:commit . "7b6e108f80237363faf7ec28b2c58dec270b8601") (:authors ("\"Aleksandar Simic\"" . "asimic@gmail.com")) (:maintainer "\"Aleksandar Simic\"" . "asimic@gmail.com") (:keywords "tools") (:url . "http://github.org/dotemacs/sort-words.el"))]) (sotclojure . [(20170922 8) ((emacs (24 1)) (clojure-mode (4 0 0)) (cider (0 8)) (sotlisp (1 3))) "Write clojure at the speed of thought." tar ((:commit . "ceac82aa691e8d98946471be6aaff9c9a4603c32") (:authors ("Artur Malabarba" . "emacs@endlessparentheses.com")) (:maintainer "Artur Malabarba" . "emacs@endlessparentheses.com") (:keywords "convenience" "clojure") (:url . "https://github.com/Malabarba/speed-of-thought-clojure"))]) (sotlisp . [(20220909 803) ((emacs (24 1))) "Write lisp at the speed of thought." single ((:commit . "04186129f2dccf48e288639b78adeb9c0e94be54") (:authors ("Artur Malabarba" . "emacs@endlessparentheses.com")) (:maintainer "Artur Malabarba" . "emacs@endlessparentheses.com") (:keywords "convenience" "lisp") (:url . "https://github.com/Malabarba/speed-of-thought-lisp"))]) @@ -4642,21 +4666,21 @@ (space-theming . [(20200502 1032) ((emacs (24))) "Easilly override theme faces" single ((:commit . "31dca6954df643255175f7df68a86892aa3c71a7") (:keywords "faces") (:url . "https://github.com/p3r7/space-theming"))]) (spacebar . [(20190719 334) ((eyebrowse (0 7 7)) (emacs (25 4 0))) "Workspaces Bar" single ((:commit . "2b2cd0e786877273103f048e62a06b0027deca2d") (:authors ("Matthias Margush" . "matthias.margush@gmail.com")) (:maintainer "Matthias Margush" . "matthias.margush@gmail.com") (:keywords "convenience") (:url . "https://github.com/matthias-margush/spacebar"))]) (spacegray-theme . [(20150719 1931) ((emacs (24 1))) "A Hyperminimal UI Theme" single ((:commit . "7f70ee36297e5ccf9bc90b1f81472024f5a7a749") (:authors ("Bruce Williams" . "brwcodes@gmail.com")) (:maintainer "Bruce Williams" . "brwcodes@gmail.com") (:keywords "themes") (:url . "http://github.com/bruce/emacs-spacegray-theme"))]) - (spaceline . [(20211120 1636) ((emacs (24 4)) (cl-lib (0 5)) (powerline (2 3)) (dash (2 11 0)) (s (1 10 0))) "Modeline configuration library for powerline" tar ((:commit . "9a81afa52738544ad5e8b71308a37422ca7e25ba") (:authors ("Eivind Fonn" . "evfonn@gmail.com")) (:maintainer "Eivind Fonn" . "evfonn@gmail.com") (:keywords "mode-line" "powerline" "spacemacs") (:url . "https://github.com/TheBB/spaceline"))]) + (spaceline . [(20230221 2314) ((emacs (24 4)) (cl-lib (0 5)) (powerline (2 3)) (dash (2 11 0)) (s (1 10 0))) "Modeline configuration library for powerline" tar ((:commit . "e0f848cc116d9046a04a09f5728fabf892863b7e") (:authors ("Eivind Fonn" . "evfonn@gmail.com")) (:maintainer "Eivind Fonn" . "evfonn@gmail.com") (:keywords "mode-line" "powerline" "spacemacs") (:url . "https://github.com/TheBB/spaceline"))]) (spaceline-all-the-icons . [(20190325 1602) ((emacs (24 4)) (all-the-icons (2 6 0)) (spaceline (2 0 0)) (memoize (1 0 1))) "A Spaceline theme using All The Icons" tar ((:commit . "5afd48c10f1bd42d9b9648c5e64596b72f3e9042") (:authors ("Dominic Charlesworth" . "dgc336@gmail.com")) (:maintainer "Dominic Charlesworth" . "dgc336@gmail.com") (:keywords "convenience" "lisp" "tools") (:url . "https://github.com/domtronn/spaceline-all-the-icons.el"))]) - (spacemacs-theme . [(20221103 1406) nil "Color theme with a dark and light versions" tar ((:commit . "1ec73d68b0f120f92538d9a329a3a46e32f74510"))]) + (spacemacs-theme . [(20230321 2210) nil "Color theme with a dark and light versions" tar ((:commit . "05fe9bc750203960179d456ae4079d582561659c"))]) (spaces . [(20170809 2208) nil "Create and switch between named window configurations." single ((:commit . "6bdb51e9a346907d60a9625f6180bddd06be6674") (:authors ("Steven Thomas")) (:maintainer "Steven Thomas") (:keywords "frames" "convenience") (:url . "https://github.com/chumpage/chumpy-windows"))]) - (spark . [(20211021 1832) ((emacs (24 3))) "sparkline generation" single ((:commit . "c9af24a169b1f1aeba175f1f8d51abda113639af") (:authors ("Alvin Francis Dumalus")) (:maintainer "Alvin Francis Dumalus") (:keywords "lisp" "data") (:url . "https://github.com/alvinfrancis/spark"))]) + (spark . [(20230406 2307) ((emacs (24 3))) "sparkline generation" single ((:commit . "0e58e5122cbb46fb6d850e3b72487431a3696861") (:authors ("Alvin Francis Dumalus")) (:maintainer "Alvin Francis Dumalus") (:keywords "lisp" "data") (:url . "https://github.com/alvinfrancis/spark"))]) (sparkline . [(20150101 1319) ((cl-lib (0 3))) "Make sparkline images from a list of numbers" single ((:commit . "a2b5d817d272d6363b67ed8f8cc75499a19fa8d2") (:authors ("Willem Rein Oudshoorn" . "woudshoo@xs4all.nl")) (:maintainer "Willem Rein Oudshoorn" . "woudshoo@xs4all.nl") (:keywords "extensions"))]) (sparql-mode . [(20230104 1113) ((cl-lib (0 5)) (emacs (24 3))) "Edit and interactively evaluate SPARQL queries." tar ((:commit . "1f6196094ec6626722c6e03a13f6844c68f62703") (:authors ("Craig Andera ")) (:maintainer "Bjarte Johansen ") (:url . "https://github.com/ljos/sparql-mode"))]) (spatial-navigate . [(20230115 633) ((emacs (26 2))) "Directional navigation between white-space blocks" single ((:commit . "11f281ae16b541ede9b4fadf96200e1728eb6ed0") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:url . "https://codeberg.org/ideasman42/emacs-spatial-navigate"))]) - (spdx . [(20230220 118) ((emacs (24 4))) "Insert SPDX license and copyright headers" tar ((:commit . "7ae6710a95a02c90b0f13486e8f20be3a746bee2") (:authors ("Zhiwei Chen" . "condy0919@gmail.com")) (:maintainer "Zhiwei Chen" . "condy0919@gmail.com") (:keywords "license" "tools") (:url . "https://github.com/condy0919/spdx.el"))]) + (spdx . [(20230405 58) ((emacs (24 4))) "Insert SPDX license and copyright headers" tar ((:commit . "b0640e03cc237d2c378a809a6e5acb1ffb2fa97a") (:authors ("Zhiwei Chen" . "condy0919@gmail.com")) (:maintainer "Zhiwei Chen" . "condy0919@gmail.com") (:keywords "license" "tools") (:url . "https://github.com/condy0919/spdx.el"))]) (speech-tagger . [(20170728 1829) ((cl-lib (0 5))) "tag parts of speech using coreNLP" tar ((:commit . "61955b40d4e8b09e66a3e8033e82893f81657c06") (:authors ("Danny McClanahan" . "danieldmcclanahan@gmail.com")) (:maintainer "Danny McClanahan" . "danieldmcclanahan@gmail.com") (:keywords "speech" "tag" "nlp" "language" "corenlp" "parsing" "natural") (:url . "https://github.com/cosmicexplorer/speech-tagger"))]) (speechd-el . [(20220608 1422) nil "Client to speech synthesizers and Braille displays." tar ((:commit . "7e30c439729d5635ddd341ad5ab16f832a4619ea") (:authors ("Milan Zamazal" . "pdm@zamazal.org")) (:maintainer "Milan Zamazal" . "pdm@zamazal.org"))]) (speed-type . [(20230206 1330) ((emacs (26 1)) (compat (29 1 3))) "Practice touch and speed typing" tar ((:commit . "4f8553632d71e827b4da6e091143779d2ad970a8") (:authors ("Gunther Hagleitner")) (:maintainer "Daniel Kraus" . "daniel@kraus.my") (:keywords "games") (:url . "https://github.com/dakra/speed-type"))]) (speedbar-git-respect . [(20200901 246) ((f (0 8 0)) (emacs (25 1))) "Particular respect git repo in speedbar" single ((:commit . "dd8f0849fc1dd21b42380e1a8c28a9a29acd9511") (:authors ("Muromi Ukari" . "chendianbuji@gmail.com")) (:maintainer "Muromi Ukari" . "chendianbuji@gmail.com") (:url . "https://github.com/ukari/speedbar-git-respect"))]) (speeddating . [(20180319 723) ((emacs (25))) "Increase date and time at point" single ((:commit . "eeaf90cd10e376bff5a295590a3d5f7fd1402523") (:authors ("Xu Chunyang" . "mail@xuchunyang.me")) (:maintainer "Xu Chunyang" . "mail@xuchunyang.me") (:keywords "date" "time") (:url . "https://github.com/xuchunyang/emacs-speeddating"))]) - (spell-fu . [(20230205 309) ((emacs (26 2))) "Fast & light spelling highlighter" single ((:commit . "d6c170fa971856f0755c1750e66deadd58a5465a") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:keywords "convenience") (:url . "https://codeberg.org/ideasman42/emacs-spell-fu"))]) + (spell-fu . [(20230326 736) ((emacs (26 2))) "Fast & light spelling highlighter" single ((:commit . "67a26b7a00449ee8ef3a80ab662c93a32adef679") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:keywords "convenience") (:url . "https://codeberg.org/ideasman42/emacs-spell-fu"))]) (sphinx-doc . [(20210213 1250) ((s (1 9 0)) (cl-lib (0 5)) (dash (2 10 0))) "Sphinx friendly docstrings for Python functions" single ((:commit . "1eda612a44ef027e5229895daa77db99a21b8801") (:authors ("Vineet Naik" . "naikvin@gmail.com")) (:maintainer "Vineet Naik" . "naikvin@gmail.com") (:keywords "sphinx" "python") (:url . "https://github.com/naiquevin/sphinx-doc.el"))]) (sphinx-frontend . [(20161025 758) nil "Launch build process for rst documents via sphinx." single ((:commit . "0cbb03361c245382d3e679dded30c4fc1713c252") (:authors ("Kostafey" . "kostafey@gmail.com")) (:maintainer "Kostafey" . "kostafey@gmail.com") (:keywords "compile" "sphinx" "restructuredtext") (:url . "https://github.com/kostafey/sphinx-frontend"))]) (sphinx-mode . [(20220417 1552) ((f (0 20 0)) (dash (2 14 1))) "Minor mode providing sphinx support." tar ((:commit . "77ca51adf9ee877f3a8f43e744f59e650772f121") (:authors ("Matúš Goljer" . "matus.goljer@gmail.com")) (:maintainer "Matúš Goljer" . "matus.goljer@gmail.com") (:keywords "languages"))]) @@ -4679,12 +4703,13 @@ (sql-trino . [(20220826 632) ((emacs (24 4))) "Adds Trino support to SQLi mode" single ((:commit . "624a879ec0d03cae8a92f26d21d88c831e15eb41") (:authors ("Filipe Regadas" . "oss@regadas.email")) (:maintainer "Filipe Regadas" . "oss@regadas.email") (:keywords "tools") (:url . "https://github.com/regadas/sql-trino"))]) (sqlformat . [(20210305 212) ((emacs (24 3)) (reformatter (0 3))) "Reformat SQL using sqlformat or pgformatter" single ((:commit . "0cdb882874ba0853f4f831a07a85b511258472b2") (:authors ("Steve Purcell" . "steve@sanityinc.com")) (:maintainer "Steve Purcell" . "steve@sanityinc.com") (:keywords "languages") (:url . "https://github.com/purcell/sqlformat"))]) (sqlite . [(20201227 1822) ((emacs (24 5))) "Use sqlite via ELisp" single ((:commit . "f3da716302c929b9df4ba0c281968f72a9d1d188") (:authors ("cnngimenez")) (:maintainer "cnngimenez") (:keywords "extensions" "lisp" "sqlite") (:url . "https://gitlab.com/cnngimenez/sqlite.el"))]) - (sqlite3 . [(20221110 1050) ((emacs (25 1))) "Direct access to the core SQLite3 API" tar ((:commit . "108521be0242bedf232775a28728588da9699336") (:authors ("Y. N. Lo" . "gordonynlo@yahoo.com")) (:maintainer "Y. N. Lo" . "gordonynlo@yahoo.com") (:keywords "comm" "data" "sql") (:url . "https://github.com/pekingduck/emacs-sqlite3-api"))]) + (sqlite3 . [(20230315 1221) ((emacs (25 1))) "Direct access to the core SQLite3 API" tar ((:commit . "b513b71012f61895f771fc6948d6511ea8ded0a6") (:authors ("Y. N. Lo" . "elisp@fastmail.com")) (:maintainer "Y. N. Lo" . "elisp@fastmail.com") (:keywords "comm" "data" "sql") (:url . "https://github.com/pekingduck/emacs-sqlite3-api"))]) (sqlup-mode . [(20170610 1537) nil "Upcase SQL words for you" single ((:commit . "04970977b4abb4d44301651618bbf1cdb0b263dd") (:authors ("Aldric Giacomoni" . "trevoke@gmail.com")) (:maintainer "Aldric Giacomoni" . "trevoke@gmail.com") (:keywords "sql" "tools" "redis" "upcase") (:url . "https://github.com/trevoke/sqlup-mode.el"))]) + (squirrel-mode . [(20221227 232) ((emacs (24 3))) "A major mode for the Squirrel programming language" single ((:commit . "1af79dfe70c4c8e6f0f144bfd2eb65c077aca785") (:authors ("XXIV")) (:maintainer "XXIV") (:keywords "files" "squirrel") (:url . "https://github.com/thechampagne/squirrel-mode"))]) (sr-speedbar . [(20161025 831) nil "Same frame speedbar" single ((:commit . "77a83fb50f763a465c021eca7343243f465b4a47") (:authors ("Sebastian Rose" . "sebastian_rose@gmx.de")) (:maintainer "Sebastian Rose" . "sebastian_rose@gmx.de") (:keywords "speedbar" "sr-speedbar.el") (:url . "http://www.emacswiki.org/emacs/download/sr-speedbar.el"))]) (srcery-theme . [(20210601 1247) ((emacs (24))) "Dark color theme" single ((:commit . "58dd21cd63e4a2eed15e0082c2547069363f107b") (:authors ("Daniel Berg")) (:maintainer "Daniel Berg") (:keywords "faces") (:url . "https://github.com/srcery-colors/srcery-emacs"))]) (srefactor . [(20180703 1810) ((emacs (24 4))) "A refactoring tool based on Semantic parser framework" tar ((:commit . "6f2c97d17fb70f4ca2112f5a2b99a8ec162004f5") (:authors ("Tu, Do Hoang" . "tuhdo1710@gmail.com")) (:maintainer "Tu, Do Hoang") (:keywords "c" "languages" "tools") (:url . "https://github.com/tuhdo/semantic-refactor"))]) - (srfi . [(20230205 2247) ((emacs (25 1))) "Scheme Requests for Implementation browser" tar ((:commit . "7e92ae3b4c4a7f3386bf1d7d620e5cd29e6e3b37") (:authors ("Lassi Kortela" . "lassi@lassi.io")) (:maintainer "Lassi Kortela" . "lassi@lassi.io") (:keywords "languages" "util") (:url . "https://github.com/srfi-explorations/emacs-srfi"))]) + (srfi . [(20230324 2) ((emacs (25 1))) "Scheme Requests for Implementation browser" tar ((:commit . "67de3f09d1e51ba8449ebc00748ad2e285d0ae0e") (:authors ("Lassi Kortela" . "lassi@lassi.io")) (:maintainer "Lassi Kortela" . "lassi@lassi.io") (:keywords "languages" "util") (:url . "https://github.com/srfi-explorations/emacs-srfi"))]) (srv . [(20180715 1959) ((emacs (24 3))) "perform SRV DNS requests" single ((:commit . "714387d5a5cf34d8d8cd96bdb1f9cb8ded823ff7") (:authors ("Magnus Henoch" . "magnus.henoch@gmail.com")) (:maintainer "Magnus Henoch" . "magnus.henoch@gmail.com") (:keywords "comm") (:url . "https://github.com/legoscia/srv.el"))]) (ssass-mode . [(20200211 132) ((emacs (24 3))) "Edit Sass without a Turing Machine" single ((:commit . "96f557887ad97a0066a60c54f92b7234b8407016") (:authors ("Adam Niederer" . "adam.niederer@gmail.com")) (:maintainer "Adam Niederer" . "adam.niederer@gmail.com") (:keywords "languages" "sass") (:url . "http://github.com/AdamNiederer/ssass-mode"))]) (ssh . [(20120904 2042) nil "Support for remote logins using ssh." single ((:commit . "c17cf5b43df8ac4662a0580f85898e1f078df0d1") (:authors ("Noah Friedman" . "friedman@splode.com")) (:maintainer "Ian Eure" . "ian.eure@gmail.com") (:keywords "unix" "comm"))]) @@ -4696,7 +4721,7 @@ (stan-snippets . [(20211129 2051) ((emacs (24 3)) (stan-mode (10 3 0)) (yasnippet (0 8 0))) "Yasnippets for Stan" tar ((:commit . "150bbbe5fd3ad2b5a3dbfba9d291e66eeea1a581") (:authors ("Jeffrey Arnold" . "jeffrey.arnold@gmail.com") ("Kazuki Yoshida" . "kazukiyoshida@mail.harvard.edu")) (:maintainer "Kazuki Yoshida" . "kazukiyoshida@mail.harvard.edu") (:keywords "languages" "tools") (:url . "https://github.com/stan-dev/stan-mode/tree/master/stan-snippets"))]) (standard-dirs . [(20200621 1603) ((emacs (26 1)) (f (0 20 0)) (s (1 7 0))) "Platform-specific paths for config, cache, and other data" single ((:commit . "e37b7e1c714c7798cd8e3a6569e4d71b96718a60") (:authors ("Joseph M LaFreniere" . "joseph@lafreniere.xyz")) (:maintainer "Joseph M LaFreniere" . "joseph@lafreniere.xyz") (:keywords "files") (:url . "https://github.com/lafrenierejm/standard-dirs.el"))]) (standoff-mode . [(20210810 1814) nil "Create stand-off markup, also called external markup." tar ((:commit . "5e603092410d9c393d19050bcbed3014a379f0e6") (:authors ("Christian Lück" . "christian.lueck@ruhr-uni-bochum.de")) (:maintainer "Christian Lück" . "christian.lueck@ruhr-uni-bochum.de") (:keywords "text" "annotations" "ner" "humanities") (:url . "https://github.com/lueck/standoff-mode"))]) - (starlit-theme . [(20230209 21) ((emacs (25 1))) "Deep blue dark theme with bright colors from the starlit sky" single ((:commit . "f910112a76f0ec62f7150a3a2d4f1337a1809ff7") (:authors ("Jonas Jelten" . "jj@sft.lol")) (:maintainer "Jonas Jelten" . "jj@sft.lol") (:keywords "faces") (:url . "https://github.com/SFTtech/starlit-emacs"))]) + (starlit-theme . [(20230324 1636) ((emacs (25 1))) "Deep blue dark theme with bright colors from the starlit sky" single ((:commit . "d6f327fb09497be7bee64d5d204d27f655cc5b04") (:authors ("Jonas Jelten" . "jj@sft.lol")) (:maintainer "Jonas Jelten" . "jj@sft.lol") (:keywords "faces") (:url . "https://github.com/SFTtech/starlit-emacs"))]) (start-menu . [(20160426 1225) ((cl-lib (0 5)) (config-parser (0 1))) "start-menu for executing external program like in windows" single ((:commit . "f7d33fed7ad2dc61156f1c1cff9e1805366fbd69") (:authors ("DarkSun" . "lujun9972@gmail.com")) (:maintainer "DarkSun" . "lujun9972@gmail.com") (:keywords "convenience" "menu") (:url . "https://github.com/lujun9972/el-start-menu"))]) (stash . [(20151117 1427) nil "lightweight persistent caching" single ((:commit . "c2e494d20c752b80ebbdffbf66687b3cdfc425ad") (:authors ("Sean Allred" . "code@seanallred.com")) (:maintainer "Sean Allred" . "code@seanallred.com") (:keywords "extensions" "data" "internal" "lisp") (:url . "https://www.github.com/vermiculus/stash.el/"))]) (state . [(20200727 1227) ((emacs (24))) "Quick navigation between workspaces" single ((:commit . "8cd9210f17c1b134274a7352b996839aed9a7d8c") (:authors ("Sylvain Rousseau ")) (:maintainer "Sylvain Rousseau ") (:keywords "convenience" "workspaces") (:url . "https://github.com/thisirs/state.git"))]) @@ -4705,11 +4730,11 @@ (stem . [(20131102 1109) nil "Routines for stemming" single ((:commit . "dd704c3447bd5d3f5ac0a4840f8987d4f855d87e") (:authors ("Tsuchiya Masatoshi" . "tsuchiya@pine.kuee.kyoto-u.ac.jp")) (:maintainer "Tsuchiya Masatoshi" . "tsuchiya@pine.kuee.kyoto-u.ac.jp") (:keywords "stemming") (:url . "https://github.com/yuutayamada/stem"))]) (stem-english . [(20180109 358) ((emacs (24 3))) "- routines for stemming English word" single ((:commit . "c9fc4c6ed6bf82382e479dae80912f4ae17d31f4") (:authors ("Tsuchiya Masatoshi" . "tsuchiya@pine.kuee.kyoto-u.ac.jp")) (:maintainer "KAWABATA, Taichi ") (:keywords "text") (:url . "http://github.com/kawabata/stem-english"))]) (stem-reading-mode . [(20220522 1053) ((emacs (25 1))) "Highlight word stems for speed-reading" single ((:commit . "6efc9962e3a19a452c7ab9636cf1e2566a51bd38") (:authors ("Yuri D'Elia" . "wavexx@thregr.org")) (:maintainer "Yuri D'Elia" . "wavexx@thregr.org") (:keywords "convenience" "wp") (:url . "https://gitlab.com/wavexx/stem-reading-mode.el"))]) - (stgit . [(20221212 1619) nil "major mode for StGit interaction" single ((:commit . "35a9822ba130613b7ae88d241df48556aaff01b3") (:authors ("David Kågedal" . "davidk@lysator.liu.se")) (:maintainer "David Kågedal" . "davidk@lysator.liu.se") (:url . "http://stacked-git.github.io"))]) + (stgit . [(20230401 1354) nil "major mode for StGit interaction" single ((:commit . "bd68bebcb0c3ff0127a18b496a1de38e9bcd8fcc") (:authors ("David Kågedal" . "davidk@lysator.liu.se")) (:maintainer "David Kågedal" . "davidk@lysator.liu.se") (:url . "http://stacked-git.github.io"))]) (sticky . [(20170926 36) nil "Sticky key for capital letters" single ((:commit . "fec4e1af38f17f5cd80eca361d8e8ef8772db366") (:authors ("rubikitch" . "rubikitch@ruby-lang.org")) (:maintainer "rubikitch" . "rubikitch@ruby-lang.org") (:keywords "convenience") (:url . "http://www.emacswiki.org/cgi-bin/wiki/download/sticky.el"))]) (sticky-shell . [(20230207 1454) ((emacs (25 1))) "Minor mode to keep track of previous prompt in your shell" single ((:commit . "030535451b7c12eea3a94dfc1a439b8baa96944b") (:authors ("Andrew De Angelis" . "bobodeangelis@gmail.com")) (:maintainer "Andrew De Angelis" . "bobodeangelis@gmail.com") (:keywords "processes" "terminals" "tools") (:url . "https://github.com/andyjda/sticky-shell"))]) (stickyfunc-enhance . [(20150429 1814) ((emacs (24 3))) "An enhancement to stock `semantic-stickyfunc-mode'" single ((:commit . "13bdba51fcd83ccbc3267959d23afc94d458dcb0") (:authors ("Tu, Do Hoang" . "tuhdo1710@gmail.com")) (:maintainer "Tu, Do Hoang") (:keywords "c" "languages" "tools") (:url . "https://github.com/tuhdo/semantic-stickyfunc-enhance"))]) - (stimmung-themes . [(20230209 1359) ((emacs (25))) "Themes tuned to inner harmonies" tar ((:commit . "518b7ad3b6b8234d5a34dca1301f218f786e0a1c") (:authors ("Love Lagerkvist")) (:maintainer "Love Lagerkvist") (:keywords "faces") (:url . "https://github.com/motform/stimmung-themes"))]) + (stimmung-themes . [(20230328 1245) ((emacs (25))) "Themes tuned to inner harmonies" tar ((:commit . "edd330a418e39ca06c35993fa6ee6f6f4efea9ee") (:authors ("Love Lagerkvist")) (:maintainer "Love Lagerkvist") (:keywords "faces") (:url . "https://github.com/motform/stimmung-themes"))]) (stock-ticker . [(20150204 1052) ((s (1 9 0)) (request (0 2 0))) "Show stock prices in mode line" single ((:commit . "74251cc810604af75f48333d51133326c053dd16") (:authors ("Gunther Hagleitner")) (:maintainer "Gunther Hagleitner") (:keywords "comms") (:url . "https://github.com/hagleitn/stock-ticker"))]) (stock-tracker . [(20230105 503) ((emacs (27 1)) (dash (2 16 0)) (async (1 9 5))) "Track stock price" single ((:commit . "327488e0f1232616bf33ab1a69da1a53aca25371") (:authors ("Huming Chen" . "chenhuming@gmail.com")) (:maintainer "Huming Chen" . "chenhuming@gmail.com") (:keywords "convenience" "stock" "finance") (:url . "https://github.com/beacoder/stock-tracker"))]) (strace-mode . [(20171116 2039) nil "strace output syntax highlighting" single ((:commit . "2901baa968d5180ab985ac40ca22cc20914d01f5") (:authors ("Preston Moore" . "prestonkmoore@gmail.com")) (:maintainer "Preston Moore" . "prestonkmoore@gmail.com") (:keywords "languages"))]) @@ -4720,7 +4745,7 @@ (string-inflection . [(20220910 1306) nil "underscore -> UPCASE -> CamelCase -> lowerCamelCase conversion of names" single ((:commit . "50ad54970b3cc79b6b83979bde9889ad9a9e1a9c") (:authors ("akicho8" . "akicho8@gmail.com")) (:maintainer "akicho8" . "akicho8@gmail.com") (:keywords "elisp"))]) (string-utils . [(20140508 2041) ((list-utils (0 4 2))) "String-manipulation utilities" single ((:commit . "8b56e1f79d2de46d1e9b5e24d889e9f4c3cc85d4") (:authors ("Roland Walker" . "walker@pobox.com")) (:maintainer "Roland Walker" . "walker@pobox.com") (:keywords "extensions") (:url . "http://github.com/rolandwalker/string-utils"))]) (stripe-buffer . [(20141208 1508) ((cl-lib (1 0))) "Use a different background for even and odd lines" single ((:commit . "c252080f55cb78c951b19ebab9687f6d00237baf") (:authors ("Andy Stewart" . "lazycat.manatee@gmail.com")) (:maintainer "sabof" . "esabof@gmail.com") (:url . "https://github.com/sabof/stripe-buffer"))]) - (stripes . [(20220310 2237) ((emacs (24 3))) "highlight alternating lines differently" single ((:commit . "618e40e0a9cf80decea32c8daecb1c9f6eae2991") (:authors ("Michael Schierl" . "schierlm-public@gmx.de") ("Štěpán Němec" . "stepnem@gmail.com")) (:maintainer "Štěpán Němec" . "stepnem@gmail.com") (:keywords "convenience" "faces") (:url . "https://gitlab.com/stepnem/stripes-el"))]) + (stripes . [(20230402 1228) ((emacs (24 3))) "highlight alternating lines differently" single ((:commit . "4683c9020da14bb1c1f74b90d27a4d9fdc7a9147") (:authors ("Michael Schierl" . "schierlm-public@gmx.de") ("Štěpán Němec" . "stepnem@smrk.net")) (:maintainer "Štěpán Němec" . "stepnem@smrk.net") (:keywords "convenience" "faces") (:url . "http://git.smrk.net/stripes.el"))]) (stumpwm-mode . [(20171027 214) nil "special lisp mode for evaluating code into running stumpwm" tar ((:commit . "333d210cacc7ebac76e14dfc8c0139f0e399c9a7") (:maintainer "Shawn Betts") (:keywords "comm" "lisp" "tools"))]) (stupid-indent-mode . [(20170525 1117) nil "Plain stupid indentation minor mode" single ((:commit . "3295e7de5e2cfddc3bf0e462e852bf58972f5d70") (:authors ("Mihai Bazon" . "mihai.bazon@gmail.com")) (:maintainer "Mihai Bazon" . "mihai.bazon@gmail.com"))]) (stylefmt . [(20161025 824) nil "Stylefmt interface" single ((:commit . "7a38f26bf8ff947215f34f0a064c7ca80575ccbc") (:authors ("κeen")) (:maintainer "κeen") (:keywords "style" "code" "formatter") (:url . "https://github.com/KeenS/stylefmt.el"))]) @@ -4755,12 +4780,13 @@ (swap-buffers . [(20150506 2139) nil "The quickest way to swap buffers between windows. Based on switch-window package." single ((:commit . "46ab31359b70d935add6c6e9533443116dc51103") (:authors ("Evgeniy Kazakov" . "evgeniy.kazakov@gmail.com")) (:maintainer "Evgeniy Kazakov" . "evgeniy.kazakov@gmail.com") (:keywords "window" "swap" "buffer" "exchange") (:url . "https://github.com/ekazakov/swap-buffers"))]) (swap-regions . [(20180915 1346) ((emacs (24 3))) "Swap text in two regions" single ((:commit . "f4fd9880cf690e003fcde88dcf2b46adbbbb03cd") (:authors ("Xu Chunyang" . "mail@xuchunyang.me")) (:maintainer "Xu Chunyang" . "mail@xuchunyang.me") (:keywords "convenience") (:url . "https://github.com/xuchunyang/swap-regions.el"))]) (sway . [(20221211 1439) ((emacs (27 1)) (dash (2 18 1))) "Communication with the Sway window manager" single ((:commit . "117eb40691e7a4d2dcd6b5a7fd9f803c7d42c32c") (:authors ("Thibault Polge" . "thibault@thb.lt")) (:maintainer "Thibault Polge" . "thibault@thb.lt") (:keywords "frames") (:url . "https://github.com/thblt/sway.el"))]) + (sway-lang-mode . [(20230320 507) ((emacs (25 1)) (lsp-mode (6 0)) (rust-mode (1 0 5))) "Major mode for sway" single ((:commit . "1d4615cc99d57280fb4b301d8339f408d987d317") (:authors ("Hamza Hamud")) (:maintainer "Hamza Hamud") (:keywords "languages") (:url . "https://github.com/hhamud/sway-mode"))]) (sweet-theme . [(20200708 1202) ((emacs (24 1))) "Sweet-looking theme" single ((:commit . "ccbfdb6a17e25ab18a0b64101675bc1dfef44006") (:authors ("2bruh4me")) (:maintainer "2bruh4me") (:keywords "faces") (:url . "https://github.com/2bruh4me/sweet-theme"))]) (sweetgreen . [(20180605 335) ((dash (2 12 1)) (helm (1 5 6)) (request (0 2 0)) (cl-lib (0 5))) "Order Salads from sweetgreen.com" single ((:commit . "e933fe466b5ef0e976967e203f88bd7a012469d1") (:authors ("Diego Berrocal" . "cestdiego@gmail.com")) (:maintainer "Diego Berrocal" . "cestdiego@gmail.com") (:keywords "salad" "food" "sweetgreen" "request") (:url . "https://www.github.com/CestDiego/sweetgreen.el"))]) (swift-helpful . [(20220707 846) ((emacs (25 1)) (dash (2 12 0)) (lsp-mode (6 0)) (swift-mode (8 0 0))) "Show documentation for Swift programs." tar ((:commit . "b46c580e4b8f55761431ec677866de3fc66592e9") (:authors ("Daniel Martín" . "mardani29@yahoo.es")) (:maintainer "Daniel Martín" . "mardani29@yahoo.es") (:keywords "help" "swift") (:url . "https://github.com/danielmartin/swift-helpful"))]) (swift-mode . [(20230117 1113) ((emacs (24 4)) (seq (2 3))) "Major-mode for Apple's Swift programming language" tar ((:commit . "778e9e6f35b41fd171bd9f42fd7b89c1001e2a82") (:authors ("taku0" . "mxxouy6x3m_github@tatapa.org") ("Chris Barrett" . "chris.d.barrett@me.com") ("Bozhidar Batsov" . "bozhidar@batsov.com") ("Arthur Evstifeev" . "lod@pisem.net")) (:maintainer "taku0" . "mxxouy6x3m_github@tatapa.org") (:keywords "languages" "swift") (:url . "https://github.com/swift-emacs/swift-mode"))]) (swift3-mode . [(20160918 1250) ((emacs (24 4))) "Major-mode for Apple's Swift programming language." tar ((:commit . "ea34d46bf9a4293e75ffdac9500d34989316d9e9") (:keywords "languages" "swift") (:url . "https://github.com/taku0/swift3-mode"))]) - (swiper . [(20220430 2247) ((emacs (24 5)) (ivy (0 13 4))) "Isearch with an overview. Oh, man!" single ((:commit . "8bf8027e4bd8c093bddb76a813952d2a0dcbf21d") (:authors ("Oleh Krehel" . "ohwoeowho@gmail.com")) (:maintainer "Oleh Krehel" . "ohwoeowho@gmail.com") (:keywords "matching") (:url . "https://github.com/abo-abo/swiper"))]) + (swiper . [(20230326 1911) ((emacs (24 5)) (ivy (0 13 4))) "Isearch with an overview. Oh, man!" single ((:commit . "e3164aae1e98ab7e3721e983463b6500c30e043f") (:authors ("Oleh Krehel" . "ohwoeowho@gmail.com")) (:maintainer "Oleh Krehel" . "ohwoeowho@gmail.com") (:keywords "matching") (:url . "https://github.com/abo-abo/swiper"))]) (swiper-helm . [(20180131 1744) ((emacs (24 1)) (swiper (0 1 0)) (helm (1 5 3))) "Helm version of Swiper." single ((:commit . "93fb6db87bc6a5967898b5fd3286954cc72a0008") (:authors ("Oleh Krehel" . "ohwoeowho@gmail.com")) (:maintainer "Oleh Krehel" . "ohwoeowho@gmail.com") (:keywords "matching") (:url . "https://github.com/abo-abo/swiper-helm"))]) (swiss-holidays . [(20200526 822) nil "Swiss holidays for the calendar" single ((:commit . "0995c9685033a09466f5b2dceb7316362bde997a") (:authors ("Christian Egli" . "christian.egli@alumni.ethz.ch")) (:maintainer "Christian Egli" . "christian.egli@alumni.ethz.ch") (:keywords "calendar") (:url . "https://github.com/egli/swiss-holidays"))]) (switch-buffer-functions . [(20200127 409) nil "Hook run when current buffer changed" single ((:commit . "40cb0c9e2c84b30e1c5c7458a795cda1bd8ad8fa") (:authors ("10sr <8slashes+el [at] gmail [dot] com>")) (:maintainer "10sr <8slashes+el [at] gmail [dot] com>") (:keywords "hook" "utility") (:url . "https://github.com/10sr/switch-buffer-functions-el"))]) @@ -4773,14 +4799,14 @@ (symbol-overlay . [(20230117 1227) ((emacs (24 3)) (seq (2 2))) "Highlight symbols with keymap-enabled overlays" single ((:commit . "ed007230378b03f384b5a2b643dd857010ef21d3") (:authors ("wolray" . "wolray@foxmail.com")) (:maintainer "wolray" . "wolray@foxmail.com") (:keywords "faces" "matching") (:url . "https://github.com/wolray/symbol-overlay/"))]) (symbolist . [(20211107 1615) ((emacs (24 5))) "List and interactively unbind Emacs Lisp symbols" single ((:commit . "92b712734941a45da7d47fd61b95e4013ff53481") (:authors ("Lassi Kortela" . "lassi@lassi.io")) (:maintainer "Lassi Kortela" . "lassi@lassi.io") (:keywords "lisp" "maint") (:url . "https://github.com/lassik/emacs-symbolist"))]) (symbolword-mode . [(20180401 1427) ((emacs (24)) (f (0 19 0))) "modify word split" single ((:commit . "920e57f4c2b09b28c5a0c8fe9ebdba9961822163") (:authors ("ncaq" . "ncaq@ncaq.net")) (:maintainer "ncaq" . "ncaq@ncaq.net") (:url . "https://github.com/ncaq/symbolword-mode"))]) - (symex . [(20230119 1943) ((emacs (25 1)) (tsc (0 15 2)) (tree-sitter (0 15 2)) (lispy (0 26 0)) (paredit (24)) (evil-cleverparens (20170718 413)) (evil (1 2 14)) (evil-surround (1 0 4)) (hydra (0 15 0)) (seq (2 22))) "An evil way to edit Lisp symbolic expressions as trees" tar ((:commit . "cddb1644ce1fff6724280cc5eae7f6ed1597ae80") (:authors ("Siddhartha Kasivajhula" . "sid@countvajhula.com")) (:maintainer "Siddhartha Kasivajhula" . "sid@countvajhula.com") (:keywords "lisp" "convenience" "languages") (:url . "https://github.com/countvajhula/symex.el"))]) + (symex . [(20230322 2003) ((emacs (25 1)) (tsc (0 15 2)) (tree-sitter (0 15 2)) (lispy (0 26 0)) (paredit (24)) (evil-cleverparens (20170718 413)) (evil (1 2 14)) (evil-surround (1 0 4)) (hydra (0 15 0)) (seq (2 22))) "An evil way to edit Lisp symbolic expressions as trees" tar ((:commit . "0b65804d08c9ff61ec6785b48ce9b3c3d4779cfe") (:authors ("Siddhartha Kasivajhula" . "sid@countvajhula.com")) (:maintainer "Siddhartha Kasivajhula" . "sid@countvajhula.com") (:keywords "lisp" "convenience" "languages") (:url . "https://github.com/countvajhula/symex.el"))]) (symon . [(20170224 833) nil "tiny graphical system monitor" single ((:commit . "76461679dfe13a5dccd3c8735fb6f58b26b46733") (:authors ("zk_phi")) (:maintainer "zk_phi") (:url . "http://hins11.yu-yake.com/"))]) (symon-lingr . [(20150719 1342) ((symon (1 1 2)) (cl-lib (0 5))) "A notification-based Lingr client powered by symon.el" single ((:commit . "056d1a473e36992ff5881e5ce6fdc331cead975f") (:authors ("zk_phi")) (:maintainer "zk_phi") (:url . "http://hins11.yu-yake.com/"))]) (sync-recentf . [(20160326 2001) nil "Synchronize the recent files list between Emacs instances" single ((:commit . "0052561d5c5b5c2684faedc3eead776aec06c3ed") (:authors ("François Févotte" . "fevotte@gmail.com")) (:maintainer "François Févotte" . "fevotte@gmail.com") (:keywords "recentf") (:url . "https://github.com/ffevotte/sync-recentf"))]) (synonymous . [(20180325 1817) ((emacs (24)) (cl-lib (0 5)) (request (0 2 0))) "A thesaurus at your fingertips" single ((:commit . "2cb9a674d84fddf3f1b00c9d6b13a853576acb87") (:authors ("Katherine Whitlock" . "toroidalcode@gmail.com") ("Snippets adapted from FlySpell, authored by Manuel Serrano" . "Manuel.Serrano@inria.fr")) (:maintainer "Katherine Whitlock" . "toroidalcode@gmail.com") (:keywords "utility") (:url . "http://github.com/toroidal-code/synonymous.el"))]) (synosaurus . [(20191125 552) ((cl-lib (0 5))) "An extensible thesaurus supporting lookup and substitution." tar ((:commit . "14d34fc92a77c3a916b4d58400424c44ae99cd81") (:authors ("Hans-Peter Deifel" . "hpd@hpdeifel.de")) (:maintainer "Hans-Peter Deifel" . "hpd@hpdeifel.de") (:keywords "wp"))]) (synquid . [(20160930 1550) ((flycheck (27)) (emacs (24 3))) "Major mode for editing Synquid files" single ((:commit . "28701ce1a15437202f53ab93a14bcba1de83fd2c") (:authors ("Clément Pit-Claudel" . "clement.pitclaudel@live.com")) (:maintainer "Clément Pit-Claudel" . "clement.pitclaudel@live.com") (:keywords "languages") (:url . "https://github.com/cpitclaudel/synquid-mode"))]) - (syntactic-close . [(20230221 937) ((emacs (24)) (cl-lib (0 5))) "Insert closing delimiter" single ((:commit . "830fc4d4fb5d31a018d32319c6e0d2dc29e3de34") (:authors ("Emacs User Group Berlin" . "emacs-berlin@emacs-berlin.org")) (:maintainer "Emacs User Group Berlin" . "emacs-berlin@emacs-berlin.org") (:keywords "languages" "convenience") (:url . "https://github.com/emacs-berlin/syntactic-close"))]) + (syntactic-close . [(20230326 1211) ((emacs (24)) (cl-lib (0 5))) "Insert closing delimiter" single ((:commit . "5d97262a0210c5fb393a257e4a9f90e0f29bc8fd") (:authors ("Emacs User Group Berlin" . "emacs-berlin@emacs-berlin.org")) (:maintainer "Emacs User Group Berlin" . "emacs-berlin@emacs-berlin.org") (:keywords "languages" "convenience") (:url . "https://github.com/emacs-berlin/syntactic-close"))]) (syntactic-sugar . [(20140508 2041) nil "Effect-free forms such as if/then/else" single ((:commit . "b6a49df4b6056e2619eea9ca554c105ae67e115f") (:authors ("Roland Walker" . "walker@pobox.com")) (:maintainer "Roland Walker" . "walker@pobox.com") (:keywords "extensions") (:url . "http://github.com/rolandwalker/syntactic-sugar"))]) (syntax-subword . [(20160205 2154) nil "make operations on words more fine-grained" single ((:commit . "9aa9b3f846bfe2474370642458a693ac4760d9fe") (:authors ("Jonathan Kotta" . "jpkotta@gmail.com")) (:maintainer "Jonathan Kotta" . "jpkotta@gmail.com"))]) (syntree . [(20221114 1804) ((emacs (27 1)) (org (9 2))) "Draw plain text constituency trees" tar ((:commit . "a36e5eeaeef2a179184883fc0a91b63d653d3cd9") (:authors ("Enrico Flor" . "enrico@eflor.net")) (:maintainer "Enrico Flor" . "enrico@eflor.net") (:url . "https://github.com/enricoflor/syntree"))]) @@ -4799,8 +4825,8 @@ (tab-jump-out . [(20151006 130) ((dash (2 10)) (emacs (24 4))) "Use tab to jump out of delimiter pairs." single ((:commit . "1c3fec1826d2891177ea78e4e7cce1dc67e83e51") (:authors ("Zhang Kai Yu" . "yeannylam@gmail.com")) (:maintainer "Zhang Kai Yu" . "yeannylam@gmail.com") (:keywords "tab" "editing"))]) (tabbar . [(20180726 1735) nil "Display a tab bar in the header line" tar ((:commit . "82bbda31cbe8ef367dd6501c3aa14b7f2c835910") (:authors ("David Ponce" . "david@dponce.com")) (:maintainer "David Ponce" . "david@dponce.com") (:keywords "convenience"))]) (tabbar-ruler . [(20160802 307) ((tabbar (2 0 1)) (powerline (2 3)) (mode-icons (0 4 0)) (cl-lib (0 5))) "Pretty tabbar, autohide, use both tabbar/ruler" tar ((:commit . "535568189aa12a3eff7f977d2783e57b6a65ab6a") (:authors ("Matthew Fidler, Ta Quang Trung, Nathaniel Cunningham")) (:maintainer "Matthew L. Fidler") (:keywords "tabbar" "ruler mode" "menu" "tool bar.") (:url . "http://github.com/mlf176f2/tabbar-ruler.el"))]) - (tablist . [(20200427 2205) ((emacs (24 3))) "Extended tabulated-list-mode" tar ((:commit . "faab7a035ef2258cc4ea2182f67e3aedab7e2af9") (:authors ("Andreas Politz" . "politza@fh-trier.de")) (:maintainer "Andreas Politz" . "politza@fh-trier.de") (:keywords "extensions" "lisp"))]) - (tabspaces . [(20230212 531) ((emacs (27 1)) (project (0 8 1))) "Leverage tab-bar and project for buffer-isolated workspaces" single ((:commit . "6975c51a2154604db70fd38eba27cf784cc3c4a6") (:authors ("Colin McLear" . "mclear@fastmail.com")) (:maintainer "Colin McLear") (:keywords "convenience" "frames") (:url . "https://github.com/mclear-tools/tabspaces"))]) + (tablist . [(20230321 705) ((emacs (24 3))) "Extended tabulated-list-mode" tar ((:commit . "5f7b71a92bfb25418d7da86ad9c45f14b149496f") (:authors ("Andreas Politz" . "politza@fh-trier.de")) (:maintainer "Andreas Politz" . "politza@fh-trier.de") (:keywords "extensions" "lisp"))]) + (tabspaces . [(20230307 2235) ((emacs (27 1)) (project (0 8 1))) "Leverage tab-bar and project for buffer-isolated workspaces" single ((:commit . "315a5b375f9276f9725991c42a7c8a63ff26d51f") (:authors ("Colin McLear" . "mclear@fastmail.com")) (:maintainer "Colin McLear") (:keywords "convenience" "frames") (:url . "https://github.com/mclear-tools/tabspaces"))]) (tabula-rasa . [(20141216 547) ((emacs (24 4))) "Distraction free writing mode" single ((:commit . "e85fff9de18dc31bc6a7aca726e34a95cc5459f5") (:authors ("Ido Magal" . "misc@satans.church")) (:maintainer "Ido Magal" . "misc@satans.church") (:keywords "distraction free" "writing") (:url . "https://github.com/idomagal/Tabula-Rasa/blob/master/tabula-rasa.el"))]) (tagedit . [(20161121 855) ((s (1 3 1)) (dash (1 0 3))) "Some paredit-like features for html-mode" single ((:commit . "b3a70101a0dcf85498c92b7fcfa7fdbac869746c") (:authors ("Magnar Sveen" . "magnars@gmail.com")) (:maintainer "Magnar Sveen" . "magnars@gmail.com") (:keywords "convenience"))]) (take-off . [(20140531 917) ((emacs (24 3)) (web-server (0 1 0))) "Emacs remote web access" tar ((:commit . "aa9ea45566fc74febbb6ee9c409ecc4b59246215") (:authors ("Thomas Burette" . "burettethomas@gmail.com")) (:maintainer "Thomas Burette" . "burettethomas@gmail.com") (:url . "https://github.com/tburette/take-off"))]) @@ -4809,8 +4835,9 @@ (tango-plus-theme . [(20221011 1012) nil "A color theme based on the tango palette" single ((:commit . "30495d1ab1df6213ecac008c599b91e6f9244c12") (:authors ("Titus von der Malsburg" . "malsburg@posteo.de")) (:maintainer "Titus von der Malsburg" . "malsburg@posteo.de") (:url . "https://github.com/tmalsburg/tango-plus-theme"))]) (tangonov-theme . [(20220923 1513) ((emacs (25))) "A 256 color dark theme featuring bright pastels" single ((:commit . "084e3a7fe3c3af0aef75f2290b939185baa1f4a4") (:authors ("Trevor Richards" . "trev@trevdev.ca")) (:maintainer "Trevor Richards" . "trev@trevdev.ca") (:keywords "faces" "theme" "dark" "fringe") (:url . "https://sr.ht/~trevdev/tangonov-theme/"))]) (tangotango-theme . [(20220714 2034) nil "Tango Palette color theme for Emacs 24." single ((:commit . "9036c4978965149ae9837bc0ad691b2ba9269052") (:authors ("Julien Barnier" . "julien@nozav.org")) (:maintainer "Julien Barnier" . "julien@nozav.org") (:keywords "tango" "palette" "color" "theme" "emacs") (:url . "https://github.com/juba/color-theme-tangotango"))]) - (tao-theme . [(20230111 1606) nil "This package provides two parametrized uncoloured color themes for Emacs: tao-yin and tao-yang." tar ((:commit . "5525e49357d066c0dca4ccc12ca69804e46577f2") (:authors ("Peter Kosov" . "11111000000@email.com")) (:maintainer "Peter Kosov" . "11111000000@email.com") (:url . "http://github.com/11111000000/tao-theme-emacs"))]) - (taskpaper-mode . [(20221030 1048) ((emacs (25 1))) "Major mode for working with TaskPaper files" single ((:commit . "9620d66e568c0bbdf033a559bac578e235e66293") (:authors ("Dmitry Safronov" . "saf.dmitry@gmail.com")) (:maintainer "Dmitry Safronov" . "saf.dmitry@gmail.com") (:keywords "outlines" "notetaking" "task management" "productivity" "taskpaper") (:url . "https://github.com/saf-dmitry/taskpaper-mode"))]) + (tao-theme . [(20230323 301) nil "This package provides two parametrized uncoloured color themes for Emacs: tao-yin and tao-yang." tar ((:commit . "d44ecab7f68cda9c9f4dd881df5d842e38f44db6") (:authors ("Peter Kosov" . "11111000000@email.com")) (:maintainer "Peter Kosov" . "11111000000@email.com") (:url . "http://github.com/11111000000/tao-theme-emacs"))]) + (tardis-theme . [(20230212 2152) ((emacs (25 1))) "Quantum Country Theme" single ((:commit . "352b1579d13e99cff9367b08208c1e241d76c89e") (:authors ("Anton Hibl" . "antonhibl11@gmail.com")) (:maintainer "Anton Hibl" . "antonhibl11@gmail.com") (:keywords "convenience") (:url . "https://github.com/antonhibl/tardis-theme"))]) + (taskpaper-mode . [(20230329 1135) ((emacs (25 1))) "Major mode for working with TaskPaper files" single ((:commit . "c7fbde266e72378481e8f039347e2c50bafeb98f") (:authors ("Dmitry Safronov" . "saf.dmitry@gmail.com")) (:maintainer "Dmitry Safronov" . "saf.dmitry@gmail.com") (:keywords "outlines" "notetaking" "task management" "productivity" "taskpaper") (:url . "https://github.com/saf-dmitry/taskpaper-mode"))]) (taskrunner . [(20190916 1608) ((emacs (25 1)) (projectile (2 0 0)) (async (1 9 3))) "Retrieve build system/taskrunner tasks" tar ((:commit . "716323aff410b4d864d137c9ebe4bbb5b8587f5e") (:authors ("Yavor Konstantinov ")) (:maintainer "Yavor Konstantinov ") (:keywords "build-system" "taskrunner" "build" "task-runner" "tasks" "convenience") (:url . "https://github.com/emacs-taskrunner/emacs-taskrunner"))]) (tawny-mode . [(20210528 1710) ((cider (0 12)) (emacs (25))) "Ontology Editing with Tawny-OWL" single ((:commit . "5da72b601cb9f052f35e88c41f1a18b326c03791") (:authors ("Phillip Lord" . "phillip.lord@newcastle.ac.uk")) (:maintainer "Phillip Lord" . "phillip.lord@newcastle.ac.uk"))]) (tblui . [(20161007 1912) ((dash (2 12 1)) (magit-popup (2 6 0)) (tablist (0 70)) (cl-lib (0 5))) "Define tabulated list UI easily" single ((:commit . "e280e11b35a2fdbcadf9ce901a2b62684ac7a7a3") (:authors ("Yuki Inoue ")) (:maintainer "Yuki Inoue ") (:url . "https://github.com/Yuki-Inoue/tblui.el"))]) @@ -4820,13 +4847,13 @@ (tea-time . [(20120331 820) nil "Simple timer package, useful to make perfect tea." single ((:commit . "1f6cf0bdd27c5eb3508989c5095427781f858eca") (:authors ("konsty" . "antipin.konstantin@googlemail.com")) (:maintainer "Gabriel Saldana" . "gsaldana@gmail.com") (:keywords "timer" "tea-time"))]) (teacode-expand . [(20181231 640) ((emacs (24 4))) "Expansion of text by TeaCode program." single ((:commit . "7df6f9ec95da1fb47bbae489bb3f2c27ed3a9b3a") (:authors ("Richard Guay" . "raguay@customct.com")) (:maintainer "Richard Guay" . "raguay@customct.com") (:keywords "lisp") (:url . "https://github.com/raguay/TeaCode-Expand"))]) (teco . [(20200707 2309) nil "Teco interpreter" single ((:commit . "2529eb0f7f35c526c1b6fca5250399718ff5138a") (:authors ("Dale R. Worley" . "worley@alum.mit.edu")) (:maintainer "Mark T. Kennedy" . "mtk@acm.org") (:keywords "convenience" "emulations" "files") (:url . "https://github.com/mtk/teco.git"))]) - (telega . [(20230212 1547) ((emacs (26 1)) (visual-fill-column (1 9)) (rainbow-identifiers (0 2 2))) "Telegram client (unofficial)" tar ((:commit . "37e7eb805bc247ecc644308f1f2a4ed9a6d30624") (:authors ("Zajcev Evgeny" . "zevlg@yandex.ru")) (:maintainer "Zajcev Evgeny" . "zevlg@yandex.ru") (:keywords "comm") (:url . "https://github.com/zevlg/telega.el"))]) + (telega . [(20230401 1152) ((emacs (27 1)) (visual-fill-column (1 9)) (rainbow-identifiers (0 2 2))) "Telegram client (unofficial)" tar ((:commit . "2cf74907e4b6a109ac01bb52494845176833268c") (:authors ("Zajcev Evgeny" . "zevlg@yandex.ru")) (:maintainer "Zajcev Evgeny" . "zevlg@yandex.ru") (:keywords "comm") (:url . "https://github.com/zevlg/telega.el"))]) (telepathy . [(20131209 1258) nil "Access Telepathy from Emacs" single ((:commit . "211d785b02a29ddc254422fdcc3db45262582f8c") (:authors ("Nicolas Petton" . "petton.nicolas@gmail.com")) (:maintainer "Nicolas Petton" . "petton.nicolas@gmail.com") (:keywords "telepathy" "tools"))]) - (telephone-line . [(20221030 2254) ((emacs (24 4)) (cl-lib (0 5)) (cl-generic (0 2)) (seq (1 8))) "Rewrite of Powerline" tar ((:commit . "314187790b5c5e9962c6d8eac9323b5b801e4aef") (:authors ("Daniel Bordak" . "dbordak@fastmail.fm")) (:maintainer "Daniel Bordak" . "dbordak@fastmail.fm") (:keywords "mode-line") (:url . "https://github.com/dbordak/telephone-line"))]) + (telephone-line . [(20230322 442) ((emacs (24 4)) (cl-lib (0 5)) (cl-generic (0 2)) (seq (1 8))) "Rewrite of Powerline" tar ((:commit . "202f9c94f7b86827ab7ebb6dbce8302b0447d6ff") (:authors ("Daniel Bordak" . "dbordak@fastmail.fm")) (:maintainer "Daniel Bordak" . "dbordak@fastmail.fm") (:keywords "mode-line") (:url . "https://github.com/dbordak/telephone-line"))]) (teletext . [(20211203 1111) ((emacs (24 3))) "Teletext broadcast viewer" single ((:commit . "6b003e9dab9bd0c27d188a81f5fff740d66a2282") (:authors ("Lassi Kortela" . "lassi@lassi.io")) (:maintainer "Lassi Kortela" . "lassi@lassi.io") (:keywords "comm" "help" "hypermedia") (:url . "https://github.com/lassik/emacs-teletext"))]) (teletext-yle . [(20210927 825) ((emacs (24 3)) (teletext (0 1))) "Teletext provider for Finnish national network YLE" single ((:commit . "9c8f4b503923c4ec688e2dcc9dff62d71bc55933") (:authors ("Lassi Kortela" . "lassi@lassi.io")) (:maintainer "Lassi Kortela" . "lassi@lassi.io") (:keywords "comm" "help" "hypermedia") (:url . "https://github.com/lassik/emacs-teletext-yle"))]) - (tempel . [(20230220 1700) ((emacs (27 1)) (compat (29 1 3 4))) "Tempo templates/snippets with in-buffer field editing" single ((:commit . "51773e54224bc3f5631105bf6e29cd1b4b5e41b3") (:authors ("Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainer "Daniel Mendler" . "mail@daniel-mendler.de") (:url . "https://github.com/minad/tempel"))]) - (tempel-collection . [(20230103 2244) ((tempel (0 5)) (emacs (27 1))) "Collection of templates for Tempel" tar ((:commit . "7ef22ea7aaf699632a1d02d47a9a505ae8bc52c3") (:authors ("Vitalii Drevenchuk" . "cradlemann@gmail.com") ("Max Penet" . "mpenetr@s-exp.com") ("Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainer "Vitalii Drevenchuk" . "cradlemann@gmail.com") (:keywords "tools") (:url . "https://github.com/Crandel/tempel-collection"))]) + (tempel . [(20230305 739) ((emacs (27 1)) (compat (29 1 4 0))) "Tempo templates/snippets with in-buffer field editing" single ((:commit . "4ab5f3af92aab2a1aea1ec66d9086812fe310044") (:authors ("Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainer "Daniel Mendler" . "mail@daniel-mendler.de") (:url . "https://github.com/minad/tempel"))]) + (tempel-collection . [(20230324 941) ((tempel (0 5)) (emacs (27 1))) "Collection of templates for Tempel" tar ((:commit . "096eff3618f6cd600fdf61859f9e5dd1bae08182") (:authors ("Vitalii Drevenchuk" . "cradlemann@gmail.com") ("Max Penet" . "mpenetr@s-exp.com") ("Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainer "Vitalii Drevenchuk" . "cradlemann@gmail.com") (:keywords "tools") (:url . "https://github.com/Crandel/tempel-collection"))]) (template-overlays . [(20180706 1132) ((emacs (24 4)) (ov (1 0 6))) "Display template regions using overlays" single ((:commit . "3cbc9a4882dcbbddf9b168883d119a6af0848784") (:authors ("Mariano Montone" . "marianomontone@gmail.com")) (:maintainer "Mariano Montone" . "marianomontone@gmail.com") (:keywords "faces" "convenience" "templates" "overlays") (:url . "http://www.github.com/mmontone/template-overlays"))]) (templatel . [(20210902 228) ((emacs (25 1))) "Templating language;" single ((:commit . "e1ccb88cdc4b482b078276960f810b82ba3b7847") (:authors ("Lincoln Clarete" . "lincoln@clarete.li")) (:maintainer "Lincoln Clarete" . "lincoln@clarete.li") (:url . "https://clarete.li/templatel"))]) (temporary-persistent . [(20230115 1425) ((emacs (24 3)) (names (20151201 0)) (dash (2 12 1)) (s (1 10 0))) "Keep temp notes buffers persistent" single ((:commit . "edbde738769e79ac212ae84ae7898ffd5f19e0f1") (:authors ("Kostafey" . "kostafey@gmail.com")) (:maintainer "Kostafey" . "kostafey@gmail.com") (:keywords "temp" "buffers" "notes") (:url . "https://github.com/kostafey/temporary-persistent"))]) @@ -4847,7 +4874,7 @@ (tern-auto-complete . [(20191227 950) ((tern (0 0 1)) (auto-complete (1 4)) (cl-lib (0 5)) (emacs (24))) "Tern Completion by auto-complete.el" single ((:commit . "0d19800db70a6348c627a69f444b91d21ad89629") (:authors ("")) (:maintainer ""))]) (tern-context-coloring . [(20170102 2253) ((emacs (24 3)) (context-coloring (8 1 0)) (tern (0 0 1))) "Use Tern for context coloring" single ((:commit . "3a8e979d6cc83aabcb3dda3f5f31a6422532efba") (:authors ("Jackson Ray Hamilton" . "jackson@jacksonrayhamilton.com")) (:maintainer "Jackson Ray Hamilton" . "jackson@jacksonrayhamilton.com") (:keywords "convenience" "faces" "tools") (:url . "https://github.com/jacksonrayhamilton/tern-context-coloring"))]) (terraform-doc . [(20211003 1333) ((emacs (24 4))) "Look up terraform documentation on the fly" single ((:commit . "16179e57ce290190c222b27961900657a1981330") (:authors ("Giap Tran" . "txgvnn@gmail.com")) (:maintainer "Giap Tran" . "txgvnn@gmail.com") (:keywords "comm") (:url . "https://github.com/TxGVNN/terraform-doc"))]) - (terraform-mode . [(20230130 2153) ((emacs (24 3)) (hcl-mode (0 3)) (dash (2 17 0))) "Major mode for terraform configuration file" single ((:commit . "39d2fd5bfc86c6bf1c7bc38e6f0016d714f2d79d") (:authors ("Syohei YOSHIDA" . "syohex@gmail.com")) (:maintainer "Syohei YOSHIDA" . "syohex@gmail.com") (:url . "https://github.com/syohex/emacs-terraform-mode"))]) + (terraform-mode . [(20230301 1502) ((emacs (24 3)) (hcl-mode (0 3)) (dash (2 17 0))) "Major mode for terraform configuration file" single ((:commit . "7b1e482530c76dcf856ec4a20aee6586eb2e8ccf") (:authors ("Syohei YOSHIDA" . "syohex@gmail.com")) (:maintainer "Syohei YOSHIDA" . "syohex@gmail.com") (:url . "https://github.com/syohex/emacs-terraform-mode"))]) (tesouro . [(20221003 1303) ((request (0 3 2)) (emacs (24 4))) "Brazilian Portuguese synonym search in dicio.com.br" single ((:commit . "3dbfc49209237215163be1ea338dea099ddc0795") (:url . "https://github.com/rberaldo/tesouro.el"))]) (test-c . [(20180423 1720) ((emacs (24 3))) "quickly test c code" single ((:commit . "761a576f62c7021ba941f178f153c51289df1553") (:authors ("Aurélien Aptel" . "aurelien.aptel@gmail.com")) (:maintainer "Aurélien Aptel" . "aurelien.aptel@gmail.com") (:url . "http://github.com/aaptel/test-c"))]) (test-case-mode . [(20130525 1434) ((fringe-helper (0 1 1))) "unit test front-end" single ((:commit . "26e397c0f930b7eb0be413ef7dd257b1da052bec") (:authors ("Nikolaj Schumacher ")) (:maintainer "Nikolaj Schumacher ") (:keywords "tools") (:url . "http://nschum.de/src/emacs/test-case-mode/"))]) @@ -4860,12 +4887,12 @@ (textmate . [(20110816 2146) nil "TextMate minor mode for Emacs" single ((:commit . "350918b070148f0ace6d9d3cd4ebcaf15c1a8781") (:authors ("Chris Wanstrath" . "chris@ozmm.org")) (:maintainer "Chris Wanstrath" . "chris@ozmm.org") (:keywords "textmate" "osx" "mac"))]) (textmate-to-yas . [(20160409 1708) nil "Import Textmate macros into yasnippet syntax" tar ((:commit . "be3a768b7ac4c2e24b9d4aa6e9ac1d916cdc5a73") (:authors ("Matthew L. Fidler")) (:maintainer "Matthew L. Fidler") (:keywords "yasnippet" "textmate") (:url . "https://github.com/mlf176f2/textmate-to-yas.el/"))]) (textsize . [(20220427 1445) ((emacs (26 1))) "Configure frame text size automatically" single ((:commit . "df91392c3c928d7841631f5809716b9cf0f7309e") (:authors ("James Ferguson" . "james@faff.org")) (:maintainer "James Ferguson" . "james@faff.org") (:keywords "convenience") (:url . "https://github.com/WJCFerguson/textsize"))]) - (textx-mode . [(20170516 911) ((emacs (24 3))) "Major mode for editing TextX files" single ((:commit . "72f9f0c5855b382024f0da8f56833c22a70a5cb3") (:authors ("Novak Boškov" . "gnovak.boskov@gmail.com")) (:maintainer "Novak Boškov" . "gnovak.boskov@gmail.com") (:keywords "textx") (:url . "https://github.com/novakboskov/textx-mode"))]) + (textx-mode . [(20230324 2020) ((emacs (24 3))) "Major mode for editing TextX files" single ((:commit . "ecf90abec508cfd82d5da68474e976be907d9a77") (:authors ("Novak Boškov" . "gnovak.boskov@gmail.com")) (:maintainer "Novak Boškov" . "gnovak.boskov@gmail.com") (:keywords "textx") (:url . "https://github.com/novakboskov/textx-mode"))]) (tf2-conf-mode . [(20161209 1620) nil "TF2 Configuration files syntax highlighting" single ((:commit . "94c971da4a78d55da2848d1e76d513e5e0a8f7eb") (:authors ("Guillermo Robles" . "guillerobles1995@gmail.com")) (:maintainer "Guillermo Robles" . "guillerobles1995@gmail.com") (:keywords "languages") (:url . "https://github.com/wynro/emacs-tf2-conf-mode"))]) (tfsmacs . [(20180911 2114) ((emacs (25)) (tablist (0 70))) "MS TFS source control interaction." single ((:commit . "13ee3f528ff616880611f563a68d921250692ef8") (:authors ("Dino Chiesa , Sebastian Monia" . "smonia@outlook.com")) (:maintainer "Dino Chiesa , Sebastian Monia" . "smonia@outlook.com") (:keywords "tfs" "vc") (:url . "http://github.com/sebasmonia/tfsmacs/"))]) - (the-matrix-theme . [(20221025 916) ((emacs (26 1))) "Green-on-black dark theme inspired by \"The Matrix\" movie" single ((:commit . "e1032b8d9f35b3f14042b6f626d3ea5e408b5d70") (:authors ("Dan Dee" . "monkeyjunglejuice@pm.me")) (:maintainer "Dan Dee" . "monkeyjunglejuice@pm.me") (:keywords "faces" "theme") (:url . "https://github.com/monkeyjunglejuice/matrix-emacs-theme"))]) + (the-matrix-theme . [(20230402 1218) ((emacs (26 1))) "Green-on-black dark theme inspired by \"The Matrix\" movie" single ((:commit . "b339285651e088bc51fa2fb51aa319fb70cab9a4") (:authors ("Dan Dee" . "monkeyjunglejuice@pm.me")) (:maintainer "Dan Dee" . "monkeyjunglejuice@pm.me") (:keywords "faces" "theme") (:url . "https://github.com/monkeyjunglejuice/matrix-emacs-theme"))]) (theme-anchor . [(20220204 321) ((emacs (26))) "Apply theme in current buffer only" single ((:commit . "c6f715d4ccd30e83922e39cab856578ce19224bb") (:authors ("Liāu, Kiong-Gē" . "gliao.tw@pm.me")) (:maintainer "Liāu, Kiong-Gē" . "gliao.tw@pm.me") (:keywords "extensions" "lisp" "theme") (:url . "https://github.com/GongYiLiao/theme-anchor"))]) - (theme-changer . [(20201226 2256) nil "Sunrise/Sunset Theme Changer for Emacs" single ((:commit . "57b8c579f134374a45bec9043feff6b29bb4f108") (:authors ("Joshua B. Griffith" . "josh.griffith@gmail.com")) (:maintainer "Joshua B. Griffith" . "josh.griffith@gmail.com") (:keywords "color-theme" "deftheme" "solar" "sunrise" "sunset") (:url . "https://github.com/hadronzoo/theme-changer"))]) + (theme-changer . [(20230405 156) ((cl-lib (0))) "Sunrise/Sunset Theme Changer for Emacs" single ((:commit . "e7a97772b22a82c70f2bd34e205d11b0b8a1e972") (:authors ("Joshua B. Griffith" . "josh.griffith@gmail.com")) (:maintainer "Samuel W. Flint" . "swflint@flintfam.org") (:keywords "color-theme" "deftheme" "solar" "sunrise" "sunset") (:url . "https://github.com/hadronzoo/theme-changer"))]) (theme-looper . [(20210827 424) ((emacs (24)) (cl-lib (0 5))) "A package for switching themes in Emacs interactively" single ((:commit . "e6e8efd740df0b68db89805ba72492818dba61ab") (:authors ("Mohammed Ismail Ansari" . "team.terminal@gmail.com")) (:maintainer "Mohammed Ismail Ansari" . "team.terminal@gmail.com") (:keywords "convenience" "color-themes") (:url . "http://ismail.teamfluxion.com"))]) (theme-magic . [(20190711 2034) ((emacs (25)) (seq (1 8))) "Apply your Emacs theme to the rest of Linux" tar ((:commit . "844c4311bd26ebafd4b6a1d72ddcc65d87f074e3") (:authors ("GitHub user \"jcaw\"" . "40725916+jcaw@users.noreply.github.com")) (:maintainer "GitHub user \"jcaw\"" . "40725916+jcaw@users.noreply.github.com") (:keywords "unix" "faces" "terminals" "extensions") (:url . "https://github.com/jcaw/theme-magic.el"))]) (therapy . [(20151113 1953) ((emacs (24))) "Hooks for managing multiple Python major versions" single ((:commit . "775a92bb7b6b0fcc5b38c0b5198a9d0a1bef788a") (:authors ("Austin Bingham" . "austin.bingham@gmail.com")) (:maintainer "Austin Bingham" . "austin.bingham@gmail.com") (:url . "https://github.com/abingham/therapy"))]) @@ -4873,15 +4900,16 @@ (thinks . [(20170802 1128) ((cl-lib (0 5))) "Insert text in a think bubble." single ((:commit . "15e0437f5b635bdcf738ca092e26aa6d8ecdba36") (:authors ("Dave Pearson" . "davep@davep.org")) (:maintainer "Dave Pearson" . "davep@davep.org") (:keywords "convenience" "quoting") (:url . "https://github.com/davep/thinks.el"))]) (thread-dump . [(20170816 1850) nil "Java thread dump viewer" single ((:commit . "204c9600242756d4b514bb5ff6293e052bf4b49d") (:authors ("Dmitry Neverov")) (:maintainer "Dmitry Neverov") (:url . "http://github.com/nd/thread-dump.el"))]) (threes . [(20160820 1242) ((emacs (24)) (seq (1 11))) "A clone of Threes (a tiny puzzle game)" single ((:commit . "6981acb30b856c77cba6aba63fefbf102cbdfbb2") (:authors ("Chunyang Xu" . "xuchunyang.me@gmail.com")) (:maintainer "Chunyang Xu" . "xuchunyang.me@gmail.com") (:keywords "games") (:url . "https://github.com/xuchunyang/threes.el"))]) - (thrift . [(20230220 336) ((emacs (24))) "major mode for fbthrift and Apache Thrift files" single ((:commit . "1d01d76ff25b7d5c5d36a08f111834082277f8e7") (:keywords "languages"))]) + (thrift . [(20230402 732) ((emacs (24))) "major mode for fbthrift and Apache Thrift files" single ((:commit . "ea52832e1283042b58262897c97527b8c2f4698f") (:keywords "languages"))]) (thumb-through . [(20120119 534) nil "Plain text reader of HTML documents" single ((:commit . "08d8fb720f93c6172653e035191a8fa9c3305e63") (:keywords "html"))]) (tickscript-mode . [(20171219 203) ((emacs (24 1))) "A major mode for Tickscript files" single ((:commit . "f0579f38ff14954df5002ce30ae6d4a2c978d461") (:authors ("Marc Sherry" . "msherry@gmail.com")) (:maintainer "Marc Sherry" . "msherry@gmail.com") (:keywords "languages") (:url . "https://github.com/msherry/tickscript-mode"))]) - (tidal . [(20221223 1759) ((haskell-mode (16)) (emacs (25 1))) "Interact with TidalCycles for live coding patterns" single ((:commit . "14064165cd5b6719af4605087d6e81332920ad60") (:authors (nil . "alex@slab.org")) (:maintainer nil . "alex@slab.org") (:keywords "tools") (:url . "https://github.com/tidalcycles/Tidal"))]) + (tidal . [(20230312 1245) ((haskell-mode (16)) (emacs (25 1))) "Interact with TidalCycles for live coding patterns" single ((:commit . "3ac320020d809ea626fc283839fecb10c9da4ce2") (:authors (nil . "alex@slab.org")) (:maintainer nil . "alex@slab.org") (:keywords "tools") (:url . "https://github.com/tidalcycles/Tidal"))]) (tide . [(20230129 1346) ((emacs (25 1)) (dash (2 10 0)) (s (1 11 0)) (flycheck (27)) (cl-lib (0 5))) "Typescript Interactive Development Environment" tar ((:commit . "29475d9eee26f4101322209e9b6b199df5386094") (:authors ("Anantha kumaran" . "ananthakumaran@gmail.com")) (:maintainer "Anantha kumaran" . "ananthakumaran@gmail.com") (:keywords "typescript") (:url . "http://github.com/ananthakumaran/tide"))]) (tikz . [(20220526 521) ((emacs (24 1))) "A minor mode to edit TikZ pictures" tar ((:commit . "4b205afc5c88f050639135d1d57f1276db323842") (:authors ("Emilio Torres-Manzanera" . "torres@uniovi.es")) (:maintainer "Emilio Torres-Manzanera" . "torres@uniovi.es") (:keywords "tex") (:url . "https://github.com/emiliotorres/tikz"))]) (tile . [(20161225 357) ((emacs (25 1)) (s (1 9 0)) (dash (2 12 0)) (stream (2 2 3))) "Tile windows with layouts" single ((:commit . "22660f21f6e95de5aba55cd5d293d4841e9a4661") (:authors ("Ivan Malison" . "IvanMalison@gmail.com")) (:maintainer "Ivan Malison" . "IvanMalison@gmail.com") (:keywords "tile" "tiling" "window" "manager" "dynamic" "frames") (:url . "https://github.com/IvanMalison/tile"))]) - (time-block . [(20230210 136) ((emacs (25 1)) (ts (0 1))) "Block running commands using time" single ((:commit . "e0dcf6eb13871df41b081b9cdaadced722c3ba54") (:authors ("Samuel W. Flint" . "swflint@flintfam.org")) (:maintainer "Samuel W. Flint" . "swflint@flintfam.org") (:keywords "tools" "productivity" "convenience") (:url . "https://git.sr.ht/~swflint/time-block"))]) + (time-block . [(20230326 1904) ((emacs (25 1)) (ts (0 1))) "Block running commands using time" single ((:commit . "90831463528a232414895b4905f67fa001550b9b") (:authors ("Samuel W. Flint" . "swflint@flintfam.org")) (:maintainer "Samuel W. Flint" . "swflint@flintfam.org") (:keywords "tools" "productivity" "convenience") (:url . "https://git.sr.ht/~swflint/time-block-command"))]) (time-ext . [(20170126 1215) nil "more function for time/date" single ((:commit . "d128becf660fe3f30178eb1b05cd266741f4784a") (:authors ("rubikitch" . "rubikitch@ruby-lang.org")) (:maintainer "rubikitch" . "rubikitch@ruby-lang.org") (:keywords "lisp") (:url . "http://www.emacswiki.org/cgi-bin/wiki/download/time-ext.el"))]) + (time-uuid-mode . [(20230312 2256) ((emacs (24 3))) "Minor mode for previewing time uuids as an overlay" single ((:commit . "6f0768edb7588add3713952e5b20e9df8ee51f89") (:authors ("Robert Plant" . "rob@robertplant.io")) (:maintainer "Robert Plant" . "rob@robertplant.io") (:keywords "extensions" "convenience" "data" "tools") (:url . "https://github.com/RobertPlant/time-uuid-mode"))]) (timecop . [(20160520 1052) ((cl-lib (0 5)) (datetime-format (0 0 1))) "Freeze Time for testing" single ((:commit . "3a1871613facc928ff250ed8f12fbc7073e46b75") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me") (:keywords "datetime" "testing") (:url . "https://github.com/zonuexe/emacs-datetime"))]) (timer-revert . [(20150122 2032) nil "minor mode to revert buffer for a given time interval." tar ((:commit . "615c91dec8b440d2b9b7c725dd733d7432564e45") (:authors ("Yagnesh Raghava Yakkala. http://yagnesh.org")) (:maintainer nil . "hi@yagnesh.org") (:keywords "timer" "revert" "auto-revert.") (:url . "http://github.com/yyr/timer-revert"))]) (timesheet . [(20221004 1702) ((s (1)) (org (9))) "Timesheet management add-on for org-mode" tar ((:commit . "511751b239c84d7619ec1c61d7f108b732b64442") (:authors ("Tom Marble")) (:maintainer "Tom Marble") (:keywords "org" "timesheet") (:url . "https://github.com/tmarble/timesheet.el"))]) @@ -4898,9 +4926,9 @@ (tinysegmenter . [(20141124 1013) ((cl-lib (0 5))) "Super compact Japanese tokenizer in Javascript ported to emacs lisp" single ((:commit . "872134704bd25c13a4c59552433da4c6881b5230") (:authors ("lugecy" . "lugecy@gmail.com")) (:maintainer "myuhe") (:keywords "convenience") (:url . "https://github.com/myuhe/tinysegmenter.el"))]) (titlecase . [(20220728 2253) ((emacs (25 1))) "Title-case phrases" tar ((:commit . "1fc48a505a0bf7d0e8b1bb25425993212576a3ef") (:authors ("Case Duckworth" . "acdw@acdw.net")) (:maintainer "Case Duckworth" . "acdw@acdw.net") (:url . "https://codeberg.org/acdw/titlecase.el"))]) (tj3-mode . [(20180519 1228) nil "major mode for editing TaskJuggler 3 files" single ((:commit . "1d98eb23f1606392f34ef1b80517cfc940fb9950") (:authors ("Christophe Rhodes" . "christophe@rhodes.io")) (:maintainer "Christophe Rhodes" . "christophe@rhodes.io") (:url . "https://github.com/csrhodes/tj3-mode"))]) - (tldr . [(20221109 1501) ((emacs (24 3))) "tldr client for Emacs" single ((:commit . "2b5d53571bd30b75d4f5a642aa129055803a6bfb") (:authors ("Ono Hiroko" . "azazabc123@gmail.com")) (:maintainer "Ono Hiroko" . "azazabc123@gmail.com") (:keywords "tools" "docs") (:url . "https://github.com/kuanyui/tldr.el"))]) + (tldr . [(20230301 136) ((emacs (24 3))) "tldr client for Emacs" single ((:commit . "1b09d2032491d3904bd7ee9bf5ba7c7503db6593") (:authors ("Ono Hiroko" . "azazabc123@gmail.com")) (:maintainer "Ono Hiroko" . "azazabc123@gmail.com") (:keywords "tools" "docs") (:url . "https://github.com/kuanyui/tldr.el"))]) (tmmofl . [(20121025 1101) nil "Calls functions dependant on font lock highlighting at point" single ((:commit . "532aa6978e994e2b069ffe37aaf9a0011a07dadc") (:authors ("Phillip Lord" . "p.lord@hgmp.mrc.ac.uk")) (:maintainer "Phillip Lord" . "p.lord@hgmp.mrc.ac.uk") (:keywords "minor mode" "font lock" "toggling."))]) - (tmsu . [(20230207 1438) ((emacs (28 1))) "A basic TMSU interface" tar ((:commit . "26fb81d2667c88bef4f571c87bd9842d1be21234") (:authors ("Wojciech Siewierski")) (:maintainer "Wojciech Siewierski") (:keywords "files") (:url . "https://github.com/vifon/tmsu.el"))]) + (tmsu . [(20230322 2344) ((emacs (28 1))) "A basic TMSU interface" tar ((:commit . "567ba42958592e632bf611f004d24c09eb2eeac1") (:authors ("Wojciech Siewierski")) (:maintainer "Wojciech Siewierski") (:keywords "files") (:url . "https://github.com/vifon/tmsu.el"))]) (tmux-pane . [(20200730 520) ((names (0 5)) (emacs (24)) (s (0))) "Provide integration between emacs window and tmux pane" single ((:commit . "923524efe8e6e5e0d269de6bb253b45e02d9a663") (:keywords "convenience" "terminals" "tmux" "window" "pane" "navigation" "integration") (:url . "https://github.com/laishulu/emacs-tmux-pane"))]) (toc-mode . [(20220926 530) ((emacs (26 1))) "Manage outlines/table of contents of pdf and djvu documents" single ((:commit . "448a0ac00c110802f3124bbf9c5a72bdfc3c3c28") (:authors ("Daniel Laurens Nicolai" . "dalanicolai@gmail.com")) (:maintainer "Daniel Laurens Nicolai" . "dalanicolai@gmail.com") (:keywords "tools" "outlines" "convenience") (:url . "https://github.com/dalanicolai/toc-mode"))]) (toc-org . [(20220110 1452) nil "add table of contents to org-mode files (formerly, org-toc)" single ((:commit . "bf2e4b358efbd860ecafe6e74776de0885d9d100") (:authors ("Sergei Nosov ")) (:maintainer "Sergei Nosov ") (:keywords "org-mode" "org-toc" "toc-org" "org" "toc" "table" "of" "contents") (:url . "https://github.com/snosov1/toc-org"))]) @@ -4911,7 +4939,7 @@ (toggle-quotes . [(20140710 926) nil "Toggle between single and double quoted string" single ((:commit . "33abc221d6887f0518337851318065cd86c34b03") (:authors ("Jim Tian" . "tianjin.sc@gmail.com")) (:maintainer "Jim Tian" . "tianjin.sc@gmail.com") (:keywords "convenience" "quotes") (:url . "https://github.com/toctan/toggle-quotes.el"))]) (toggle-test . [(20140723 537) nil "Toggle between source and test files in various programming languages" single ((:commit . "a0b64834101c2b8b24da365baea1d36e57b069b5") (:authors ("Raghunandan Rao" . "r.raghunandan@gmail.com")) (:maintainer "Raghunandan Rao" . "r.raghunandan@gmail.com") (:keywords "tdd" "test" "toggle" "productivity") (:url . "https://github.com/rags/toggle-test"))]) (toggle-window . [(20141207 1548) nil "toggle current window size between half and full" single ((:commit . "e82c60e543933880402ede11e9423e48a17dde53") (:authors ("Kenny Liu")) (:maintainer "Kenny Liu") (:keywords "hide" "window") (:url . "https://github.com/deadghost/toggle-window"))]) - (tok-theme . [(20230220 1320) ((emacs (26 1))) "Dark but vibrant theme for Emacs" single ((:commit . "4dd1efcab11576c0989c52f67c89759a43e07f0b") (:authors ("Topi Kettunen" . "topi@topikettunen.com")) (:maintainer "Topi Kettunen" . "topi@topikettunen.com") (:url . "https://github.com/topikettunen/tok-theme"))]) + (tok-theme . [(20230328 2146) ((emacs (26 1))) "Minimal light monochromatic theme for Emacs in the spirit of Zmacs and Smalltalk-80" single ((:commit . "c56aa7337bf71d4dac491aa2f9623365c078a604") (:authors ("Topi Kettunen" . "topi@topikettunen.com")) (:maintainer "Topi Kettunen" . "topi@topikettunen.com") (:url . "https://github.com/topikettunen/tok-theme"))]) (tokei . [(20220823 2058) ((emacs (27 1)) (magit-section (3 3 0))) "Display codebase statistics" single ((:commit . "86fbca422f580a95eb30247e46891184f3ac5c18") (:authors ("Daniel Nagy ")) (:maintainer "Daniel Nagy" . "danielnagy@posteo.de") (:url . "https://github.com/nagy/tokei.el"))]) (tomatinho . [(20180621 1748) nil "Simple and beautiful pomodoro timer" tar ((:commit . "b53354b9b9f496c0388d6a573b06b7d6fc53d0bd") (:authors ("Konrad Scorciapino" . "scorciapino@gmail.com")) (:maintainer "Konrad Scorciapino" . "scorciapino@gmail.com") (:keywords "time" "productivity" "pomodoro technique"))]) (toml . [(20130903 1255) nil "TOML (Tom's Obvious, Minimal Language) parser" single ((:commit . "9633a6872928e737a2335aae1065768b23d8c3b3") (:authors ("Wataru MIYAGUNI" . "gonngo@gmail.com")) (:maintainer "Wataru MIYAGUNI" . "gonngo@gmail.com") (:keywords "toml" "parser") (:url . "https://github.com/gongo/emacs-toml"))]) @@ -4936,8 +4964,11 @@ (tramp-hdfs . [(20210526 339) ((emacs (24 4))) "Tramp extension to access hadoop/hdfs file system in Emacs" single ((:commit . "aa93bdbb3d5619c262ce53af1981edcd2a0705e5") (:authors ("Raghav Kumar Gautam" . "raghav@apache.org")) (:maintainer "Raghav Kumar Gautam" . "raghav@apache.org") (:keywords "tramp" "emacs" "hdfs" "hadoop" "webhdfs" "rest"))]) (tramp-term . [(20220725 1441) nil "Automatic setup of directory tracking in ssh sessions" single ((:commit . "ed75189122737d301f716a30a8013205aa3736f1") (:authors ("Randy Morris" . "randy.morris@archlinux.us")) (:maintainer "Randy Morris" . "randy.morris@archlinux.us") (:keywords "comm" "terminals") (:url . "https://github.com/randymorris/tramp-term.el"))]) (transfer-sh . [(20200601 1708) ((emacs (24 3)) (async (1 0))) "Simple interface for sending buffer contents to transfer.sh" single ((:commit . "0621a66d00ec91a209a542c10b158095088bd44d") (:keywords "comm" "convenience" "files") (:url . "https://gitlab.com/tuedachu/transfer-sh.el"))]) - (transient . [(20230220 1425) ((emacs (25 1)) (compat (29 1 3 4))) "Transient commands" tar ((:commit . "0204a2432862aa187745995f1c378e6d875b35cb") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "extensions") (:url . "https://github.com/magit/transient"))]) + (transient . [(20230315 1520) ((emacs (25 1)) (compat (29 1 3 4))) "Transient commands" tar ((:commit . "0ae0de43590b5b6984a83f9e044e7c426455ac6e") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "extensions") (:url . "https://github.com/magit/transient"))]) (transient-dwim . [(20221225 1630) ((emacs (26 1)) (transient (0 1))) "Useful preset transient commands" single ((:commit . "cb5e0d35729fc6448553b7a17fc5c843f00e8c1d") (:authors ("Naoya Yamashita" . "conao3@gmail.com")) (:maintainer "Naoya Yamashita" . "conao3@gmail.com") (:keywords "tools") (:url . "https://github.com/conao3/transient-dwim.el"))]) + (transient-extras . [(20230303 1511) ((emacs (28 1))) "Extra features for transient" single ((:commit . "e91a1cddb1f0cb8b99d2bd30db64d467e5fa7ea8") (:authors ("Al Haji-Ali , Samuel W. Flint" . "swflint@flintfam.org")) (:maintainer "Al Haji-Ali , Samuel W. Flint" . "swflint@flintfam.org") (:keywords "convenience") (:url . "https://github.com/haji-ali/transient-extras.git"))]) + (transient-extras-a2ps . [(20230303 1511) ((emacs (28 1)) (transient-extras (1 0 0))) "A transient interface to a2ps" single ((:commit . "e91a1cddb1f0cb8b99d2bd30db64d467e5fa7ea8") (:authors ("Samuel W. Flint" . "swflint@flintfam.org")) (:maintainer "Samuel W. Flint" . "swflint@flintfam.org") (:keywords "convenience") (:url . "https://git.sr.ht/~swflint/transient-extras-a2ps"))]) + (transient-extras-lp . [(20230317 1118) ((emacs (28 1)) (transient-extras (1 0 0))) "A transient interface to lp" single ((:commit . "a9edac72cc0e29a8cae4340bcb63a5eae3eac130") (:authors ("Al Haji-Ali" . "abdo.haji.ali@gmail.com")) (:maintainer "Al Haji-Ali" . "abdo.haji.ali@gmail.com") (:keywords "convenience") (:url . "https://github.com/haji-ali/transient-extras.git"))]) (transient-posframe . [(20210102 130) ((emacs (26 0)) (posframe (0 4 3)) (transient (0 2 0))) "Using posframe to show transient" single ((:commit . "5f0874ac3ce6f50968ed5e088d6538a07bdfd11f") (:authors ("Yanghao Xie")) (:maintainer "Yanghao Xie" . "yhaoxie@gmail.com") (:keywords "convenience" "bindings" "tooltip") (:url . "https://github.com/yanghaoxie/transient-posframe"))]) (translate-mode . [(20220511 1357) ((emacs (24 3))) "Paragraph-oriented side-by-side doc translation workflow" single ((:commit . "e1940b333241a4d0c224b7b875962736ca2b693b") (:authors ("Ray Wang" . "rayw.public@gmail.com")) (:maintainer "Ray Wang" . "rayw.public@gmail.com") (:keywords "translate" "convenience" "editing") (:url . "https://github.com/rayw000/translate-mode"))]) (transmission . [(20221130 212) ((emacs (24 4)) (let-alist (1 0 5))) "Interface to a Transmission session" single ((:commit . "243d5dc15917df2611fd0c9f288faea17a00a396") (:authors ("Mark Oteiza" . "mvoteiza@udel.edu")) (:maintainer "Mark Oteiza" . "mvoteiza@udel.edu") (:keywords "comm" "tools"))]) @@ -4953,9 +4984,9 @@ (tree-sitter-ess-r . [(20221012 855) ((emacs (26 1)) (ess (18 10 1)) (tree-sitter (0 12 1)) (tree-sitter-langs (0 12 0))) "R with tree-sitter" single ((:commit . "9669c00f3d3463e6769725af74c392891e269eed") (:authors ("Shuguang Sun" . "shuguang79@qq.com")) (:maintainer "Shuguang Sun" . "shuguang79@qq.com") (:keywords "tools") (:url . "https://github.com/ShuguangSun/tree-sitter-ess-r"))]) (tree-sitter-indent . [(20220411 1439) ((emacs (26 1)) (tree-sitter (0 12 1)) (seq (2 20))) "Provide indentation with a Tree-sitter backend" single ((:commit . "4ef246db3e4ff99f672fe5e4b416c890f885c09e") (:authors ("Felipe Lema" . "felipelema@mortemale.org")) (:maintainer "Felipe Lema" . "felipelema@mortemale.org") (:keywords "convenience" "internal") (:url . "https://codeberg.org/FelipeLema/tree-sitter-indent.el"))]) (tree-sitter-ispell . [(20230205 533) ((emacs (26 1)) (tree-sitter (0 15 0))) "Run ispell on tree-sitter text nodes" single ((:commit . "d8c33c05f689c2cab36b8a9856811f18a4ab7c59") (:authors ("Erick Navarro" . "erick@navarro.io")) (:maintainer "Erick Navarro" . "erick@navarro.io") (:url . "https://github.com/erickgnavar/tree-sitter-ispell.el"))]) - (tree-sitter-langs . [(20230205 2032) ((emacs (25 1)) (tree-sitter (0 15 0))) "Grammar bundle for tree-sitter" tar ((:commit . "d8f8ac4faeb4564fbb61e94a631b4672523d84a9") (:authors ("Tuấn-Anh Nguyễn" . "ubolonton@gmail.com")) (:maintainer "Tuấn-Anh Nguyễn" . "ubolonton@gmail.com") (:keywords "languages" "tools" "parsers" "tree-sitter") (:url . "https://github.com/emacs-tree-sitter/tree-sitter-langs"))]) + (tree-sitter-langs . [(20230311 1456) ((emacs (25 1)) (tree-sitter (0 15 0))) "Grammar bundle for tree-sitter" tar ((:commit . "ffe9ab0c8ec9e37e70e31d296df3b85bcfc73c5e") (:authors ("Tuấn-Anh Nguyễn" . "ubolonton@gmail.com")) (:maintainer "Tuấn-Anh Nguyễn" . "ubolonton@gmail.com") (:keywords "languages" "tools" "parsers" "tree-sitter") (:url . "https://github.com/emacs-tree-sitter/tree-sitter-langs"))]) (treefactor . [(20200516 1631) ((emacs (26 1)) (dash (2 16 0)) (f (0 20 0)) (org (9 2 6)) (avy (0 5 0))) "Restructure your messy Org documents" single ((:commit . "75357757022a4399ab772ff0d92065bd114dabe9") (:authors ("Leo Littlebook" . "Leo.Littlebook@gmail.com")) (:maintainer "Leo Littlebook" . "Leo.Littlebook@gmail.com") (:keywords "outlines" "files" "convenience") (:url . "https://github.com/cyberthal/treefactor"))]) - (treemacs . [(20230104 1319) ((emacs (26 1)) (cl-lib (0 5)) (dash (2 11 0)) (s (1 12 0)) (ace-window (0 9 0)) (pfuture (1 7)) (hydra (0 13 2)) (ht (2 2)) (cfrs (1 3 2))) "A tree style file explorer package" tar ((:commit . "9986d6cd3d2822db7ae0e6d8a275db7057f3e828") (:authors ("Alexander Miller" . "alexanderm@web.de")) (:maintainer "Alexander Miller" . "alexanderm@web.de") (:url . "https://github.com/Alexander-Miller/treemacs"))]) + (treemacs . [(20230323 629) ((emacs (26 1)) (cl-lib (0 5)) (dash (2 11 0)) (s (1 12 0)) (ace-window (0 9 0)) (pfuture (1 7)) (hydra (0 13 2)) (ht (2 2)) (cfrs (1 3 2))) "A tree style file explorer package" tar ((:commit . "a20d49ed62fa64a4164a9a3f25c102ec0a338367") (:authors ("Alexander Miller" . "alexanderm@web.de")) (:maintainer "Alexander Miller" . "alexanderm@web.de") (:url . "https://github.com/Alexander-Miller/treemacs"))]) (treemacs-all-the-icons . [(20220911 1427) ((emacs (26 1)) (all-the-icons (4 0 1)) (treemacs (0 0))) "all-the-icons integration for treemacs" single ((:commit . "861418d9d11b205930bd4555a40b430b9dde9dd4") (:authors ("Eric Dallo" . "ercdll1337@gmail.com")) (:maintainer "Eric Dallo" . "ercdll1337@gmail.com") (:url . "https://github.com/Alexander-Miller/treemacs"))]) (treemacs-evil . [(20220911 1427) ((emacs (26 1)) (evil (1 2 12)) (treemacs (0 0))) "Evil mode integration for treemacs" single ((:commit . "861418d9d11b205930bd4555a40b430b9dde9dd4") (:authors ("Alexander Miller" . "alexanderm@web.de")) (:maintainer "Alexander Miller" . "alexanderm@web.de") (:url . "https://github.com/Alexander-Miller/treemacs"))]) (treemacs-icons-dired . [(20220915 1626) ((treemacs (0 0)) (emacs (26 1))) "Treemacs icons for dired" single ((:commit . "1961981c81122b22ea70962f45c01feeb54c3800") (:authors ("Alexander Miller" . "alexanderm@web.de")) (:maintainer "Alexander Miller" . "alexanderm@web.de") (:url . "https://github.com/Alexander-Miller/treemacs"))]) @@ -4965,10 +4996,10 @@ (treemacs-projectile . [(20220911 1427) ((emacs (26 1)) (projectile (0 14 0)) (treemacs (0 0))) "Projectile integration for treemacs" single ((:commit . "861418d9d11b205930bd4555a40b430b9dde9dd4") (:authors ("Alexander Miller" . "alexanderm@web.de")) (:maintainer "Alexander Miller" . "alexanderm@web.de") (:url . "https://github.com/Alexander-Miller/treemacs"))]) (treemacs-tab-bar . [(20220911 1427) ((emacs (27 1)) (treemacs (0 0)) (dash (2 11 0))) "Tab bar integration for treemacs" single ((:commit . "861418d9d11b205930bd4555a40b430b9dde9dd4") (:authors ("Alexander Miller" . "alexanderm@web.de") ("Jason Dufair" . "jase@dufair.org") ("Aaron Jensen" . "aaronjensen@gmail.com")) (:maintainer "Alexander Miller" . "alexanderm@web.de") (:url . "https://github.com/Alexander-Miller/treemacs"))]) (treepy . [(20221205 2224) ((emacs (25 1))) "Generic tree traversal tools" single ((:commit . "7c4a0d21322506a4d4b2301b4274ec955b429b47") (:authors ("Daniel Barreto" . "daniel.barreto.n@gmail.com")) (:maintainer "Daniel Barreto" . "daniel.barreto.n@gmail.com") (:keywords "lisp" "maint" "tools") (:url . "https://github.com/volrath/treepy.el"))]) - (treesit-auto . [(20230220 1438) ((emacs (29 0))) "Automatically use tree-sitter enhanced major modes" single ((:commit . "ed809a73b3bc418942efee7b682ea4cbd4605844") (:authors ("Robb Enzmann" . "robbenzmann@gmail.com")) (:maintainer "Robb Enzmann" . "robbenzmann@gmail.com") (:keywords "treesitter" "auto" "automatic" "major" "mode" "fallback" "convenience") (:url . "https://github.com/renzmann/treesit-auto.git"))]) + (treesit-auto . [(20230320 1555) ((emacs (29 0))) "Automatically use tree-sitter enhanced major modes" single ((:commit . "bac3b9d1d61a4d759f87c80de7be3b808d19cbf6") (:authors ("Robb Enzmann" . "robbenzmann@gmail.com")) (:maintainer "Robb Enzmann" . "robbenzmann@gmail.com") (:keywords "treesitter" "auto" "automatic" "major" "mode" "fallback" "convenience") (:url . "https://github.com/renzmann/treesit-auto.git"))]) (treeview . [(20220928 43) ((emacs (24 4))) "A generic tree navigation library" single ((:commit . "d9c10feddf3b959e7b33ce83103e1f0a61162723") (:authors ("Tilman Rassy" . "tilman.rassy@googlemail.com")) (:maintainer "Tilman Rassy" . "tilman.rassy@googlemail.com") (:keywords "lisp" "tools" "internal" "convenience") (:url . "https://github.com/tilmanrassy/emacs-treeview"))]) (trident-mode . [(20190410 2036) ((emacs (24)) (slime (20130526)) (skewer-mode (1 5 0)) (dash (1 0 3))) "Live Parenscript interaction" single ((:commit . "109a1bc10bd0c4b47679a6ca5c4cd27c7c8d4ccb") (:authors ("John Mastro" . "john.b.mastro@gmail.com")) (:maintainer "John Mastro" . "john.b.mastro@gmail.com") (:keywords "languages" "lisp" "processes" "tools") (:url . "https://github.com/johnmastro/trident-mode.el"))]) - (trinary . [(20230213 1217) ((emacs (24))) "Trinary logic." single ((:commit . "4268556d89831889a722302241c0de680de3731b") (:authors ("Matúš Goljer" . "matus.goljer@gmail.com")) (:maintainer "Matúš Goljer" . "matus.goljer@gmail.com") (:keywords "languages") (:url . "https://github.com/emacs-elsa/trinary-logic"))]) + (trinary . [(20230301 2044) ((emacs (24))) "Trinary logic" tar ((:commit . "d4869d260f22d13a9a71327a6d40edc6980d022e") (:authors ("Matúš Goljer" . "matus.goljer@gmail.com")) (:maintainer "Matúš Goljer" . "matus.goljer@gmail.com") (:keywords "languages") (:url . "https://github.com/emacs-elsa/trinary-logic"))]) (tron-legacy-theme . [(20230103 617) nil "An original retro-futuristic theme inspired by Tron: Legacy" single ((:commit . "710c5ef80835cc2f6fb40e51f782ab531048f86e") (:authors ("Ian Y.E. Pan")) (:maintainer "Ian Y.E. Pan") (:url . "https://github.com/ianpan870102/tron-legacy-emacs-theme"))]) (trr . [(20191019 1403) nil "a type-writing training program on GNU Emacs." tar ((:commit . "f841173e11213ac6916b2d3394b28fb202543871") (:authors ("YAMAMOTO Hirotaka" . "ymmt@is.s.u-tokyo.ac.jp") ("KATO Kenji" . "kato@suri.co.jp") (" *Original Author") ("INAMURA You" . "inamura@icot.or.jp") (" *Original Author")) (:maintainer "YAMAMOTO Hirotaka" . "ymmt@is.s.u-tokyo.ac.jp") (:keywords "games" "faces"))]) (truthy . [(20140508 2041) ((list-utils (0 4 2))) "Test the content of a value" single ((:commit . "782cee08fbb13f9be71ce8e88d980ec14db24a0f") (:authors ("Roland Walker" . "walker@pobox.com")) (:maintainer "Roland Walker" . "walker@pobox.com") (:keywords "extensions") (:url . "http://github.com/rolandwalker/truthy"))]) @@ -4999,7 +5030,7 @@ (typit . [(20220909 1233) ((emacs (24 4)) (f (0 18)) (mmt (0 1 1))) "Typing game similar to tests on 10 fast fingers" tar ((:commit . "6ad0d5a106c4a4428fd131653bbe7c0aab4b5f60") (:authors ("Mark Karpov" . "markkarpov92@gmail.com")) (:maintainer "Mark Karpov" . "markkarpov92@gmail.com") (:keywords "games") (:url . "https://github.com/mrkkrp/typit"))]) (typo . [(20200706 1714) nil "Minor mode for typographic editing" single ((:commit . "173ebe4fc7ac38f344b16e6eaf41f79e38f20d57") (:authors ("Jorgen Schaefer" . "forcer@forcix.cx")) (:maintainer "Jorgen Schaefer" . "forcer@forcix.cx") (:keywords "convenience" "wp") (:url . "https://github.com/jorgenschaefer/typoel"))]) (typo-suggest . [(20200830 1143) ((emacs (24 3)) (helm (3 0)) (company (0 9 10)) (s (1 12 0)) (dash (2 13 0))) "Don't make typos with the help of helm and company" single ((:commit . "3014d18ae2f0b6b857bb613f373e034c743f4d2e") (:authors ("Kadir Can Çetin" . "kadircancetin@gmail.com")) (:maintainer "Kadir Can Çetin" . "kadircancetin@gmail.com") (:keywords "convenience" "wp") (:url . "https://github.com/kadircancetin/typo-suggest"))]) - (tzc . [(20220520 557) ((emacs (27 1))) "Converts time between different time zones" single ((:commit . "f4e2273b65ace1ea56c9824c3bdb97925c98c8ba") (:authors ("Md Arif Shaikh" . "arifshaikh.astro@gmail.com")) (:maintainer "Md Arif Shaikh" . "arifshaikh.astro@gmail.com") (:keywords "convenience") (:url . "https://github.com/md-arif-shaikh/tzc"))]) + (tzc . [(20230313 1659) ((emacs (27 1))) "Converts time between different time zones" single ((:commit . "6b11c8b2b6f207750d77542ff8e6ea1665be81c4") (:authors ("Md Arif Shaikh" . "arifshaikh.astro@gmail.com")) (:maintainer "Md Arif Shaikh" . "arifshaikh.astro@gmail.com") (:keywords "convenience") (:url . "https://github.com/md-arif-shaikh/tzc"))]) (ubuntu-theme . [(20150805 1506) nil "A theme inspired by the default terminal colors in Ubuntu" single ((:commit . "88b0eefc75d4cbcde103057e1c5968d4c3052f69") (:authors ("Francesc Rocher" . "francesc.rocher@gmail.com")) (:maintainer "Francesc Rocher" . "francesc.rocher@gmail.com") (:url . "http://github.com/rocher/ubuntu-theme"))]) (uci-mode . [(20210626 1956) ((emacs (25 1))) "Major-mode for chess engine interaction" single ((:commit . "2cdf4de5af96d56108a0a5716416ef3c8ac7bb7c") (:authors ("Dodge Coates and Roland Walker")) (:maintainer "Dodge Coates and Roland Walker") (:keywords "data" "games" "chess") (:url . "https://github.com/dwcoates/uci-mode"))]) (ucs-utils . [(20230119 2237) ((emacs (24 3)) (persistent-soft (0 8 10)) (pcache (0 5 1)) (list-utils (0 4 6))) "Utilities for Unicode characters" tar ((:commit . "91b9e0207fff5883383fd39c45ad5522e9b90e65") (:authors ("Roland Walker" . "walker@pobox.com")) (:maintainer "Roland Walker" . "walker@pobox.com") (:keywords "i18n" "extensions") (:url . "http://github.com/rolandwalker/ucs-utils"))]) @@ -5015,10 +5046,10 @@ (undersea-theme . [(20220616 1950) ((emacs (24 3))) "Theme styled after undersea imagery" single ((:commit . "6bc351c4cb49ccc7210801e6b54ecc2993289b92") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "theme" "sea") (:url . "https://github.com/jcs-elpa/undersea-theme"))]) (underwater-theme . [(20131118 2) nil "A gentle, deep blue color theme" single ((:commit . "1fbd4ecd4538256c6c46f9638f883072c73ac927") (:authors ("Jon-Michael Deldin" . "dev@jmdeldin.com")) (:maintainer "Jon-Michael Deldin" . "dev@jmdeldin.com") (:keywords "faces"))]) (undo-fu . [(20230109 2256) ((emacs (25 1))) "Undo helper with redo" single ((:commit . "d59bba01de48a808a42d6e29e011ef641cdb6a77") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:url . "https://codeberg.org/ideasman42/emacs-undo-fu"))]) - (undo-fu-session . [(20230205 310) ((emacs (28 1))) "Persistent undo, available between sessions" single ((:commit . "7b3fd0647dd1fbd02101eec61440e6d44953bcd9") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:keywords "convenience") (:url . "https://codeberg.com/ideasman42/emacs-undo-fu-session"))]) + (undo-fu-session . [(20230405 221) ((emacs (28 1))) "Persistent undo, available between sessions" single ((:commit . "6a306462ee1fa3a7c6303561f9ddf510e448b731") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:keywords "convenience") (:url . "https://codeberg.com/ideasman42/emacs-undo-fu-session"))]) (undo-propose . [(20210207 45) ((emacs (24 3))) "Simple and safe undo navigation" single ((:commit . "91a1dfe516d90dab69c368f6669bacb2458ec5e9") (:authors ("Jack Kamm")) (:maintainer "Jack Kamm") (:keywords "convenience" "files" "undo" "redo" "history") (:url . "https://github.com/jackkamm/undo-propose.el"))]) (undohist . [(20220219 634) ((cl-lib (1 0))) "Persistent undo history for GNU Emacs" single ((:commit . "94959e708d5a74913788324893d0b6dabc88ff18") (:authors ("MATSUYAMA Tomohiro" . "m2ym.pub@gmail.com")) (:maintainer "MATSUYAMA Tomohiro" . "m2ym.pub@gmail.com") (:keywords "convenience"))]) - (unfill . [(20210106 222) ((emacs (24 1))) "Do the opposite of fill-paragraph or fill-region" single ((:commit . "8375d87ec184fbe964189e2f9b7263cdb1396694") (:authors ("Steve Purcell" . "steve@sanityinc.com")) (:maintainer "Steve Purcell" . "steve@sanityinc.com") (:keywords "convenience") (:url . "https://github.com/purcell/unfill"))]) + (unfill . [(20230227 1349) ((emacs (24 1))) "Do the opposite of fill-paragraph or fill-region" single ((:commit . "075052ce0b4451d7d3ede013ce5a77e6a7a92360") (:authors ("Steve Purcell" . "steve@sanityinc.com")) (:maintainer "Steve Purcell" . "steve@sanityinc.com") (:keywords "convenience") (:url . "https://github.com/purcell/unfill"))]) (unicad . [(20200914 1500) ((emacs (24)) (nadvice (0 3))) "An elisp port of Mozilla Universal Charset Auto Detector" single ((:commit . "a5fd4e326a0607acc3776c11f41826e60b6486c6") (:authors ("Qichen Huang" . "unicad.el@gmail.com")) (:maintainer "Qichen Huang" . "unicad.el@gmail.com") (:keywords "i18n") (:url . "https://github.com/ukari/unicad"))]) (unicode-emoticons . [(20150204 1108) nil "Shortcuts for common unicode emoticons" single ((:commit . "52a09955c2afc1807c0f37f1467ccfc1e1da690a") (:authors ("Gunther Hagleitner")) (:maintainer "Gunther Hagleitner") (:keywords "games" "entertainment" "comms") (:url . "https://github.com/hagleitn/unicode-emoticons"))]) (unicode-enbox . [(20140508 2041) ((string-utils (0 3 2)) (ucs-utils (0 7 6)) (list-utils (0 4 2)) (persistent-soft (0 8 8)) (pcache (0 2 3))) "Surround a string with box-drawing characters" single ((:commit . "4e8ac89b0460eaba6d6eaa8c463eb069660218fa") (:authors ("Roland Walker" . "walker@pobox.com")) (:maintainer "Roland Walker" . "walker@pobox.com") (:keywords "extensions" "interface") (:url . "http://github.com/rolandwalker/unicode-enbox"))]) @@ -5055,7 +5086,7 @@ (use-package-hydra . [(20181228 745) ((emacs (24 3)) (use-package (2 4))) "Adds :hydra keyword to use-package macro" single ((:commit . "8cd55a1128fbdf6327bb38a199d206225896d146") (:authors ("Toon Claes" . "toon@iotcl.com")) (:maintainer "Toon Claes" . "toon@iotcl.com") (:keywords "convenience" "extensions" "tools") (:url . "https://gitlab.com/to1ne/use-package-hydra"))]) (use-proxy . [(20201209 853) ((exec-path-from-shell (1 12)) (emacs (26 2))) "Enable/Disable proxies respecting your HTTP/HTTPS env" single ((:commit . "43499194224483b27628fdf99f6f9ff6e731d844") (:authors ("Ray Wang" . "ray.hackmylife@gmail.com")) (:maintainer "Ray Wang" . "ray.hackmylife@gmail.com") (:keywords "proxy" "comm") (:url . "https://github.com/rayw000/use-proxy"))]) (use-ttf . [(20221201 751) ((emacs (26 1))) "Keep font consistency across different OSs" single ((:commit . "3ae1dd908c822e98e017ada034181ad3ffebc1d6") (:authors ("Shen, Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience" "customize" "font" "install" "ttf") (:url . "https://github.com/jcs-elpa/use-ttf"))]) - (utimeclock . [(20230201 143) ((emacs (24 4))) "Simple utility for manual time tracking" single ((:commit . "b5cdcc022dfe248f1fe7d85e735dd7d9434d200a") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:url . "https://codeberg.org/ideasman42/emacs-utimeclock"))]) + (utimeclock . [(20230319 752) ((emacs (24 4))) "Simple utility for manual time tracking" single ((:commit . "de8187371be34b2482730bd6eae1a3187e72fe13") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:url . "https://codeberg.org/ideasman42/emacs-utimeclock"))]) (utop . [(20230105 1430) ((emacs (26)) (tuareg (2 2 0))) "Universal toplevel for OCaml" single ((:commit . "595002e6f07e6a3c6abc6e94a1b2448006115f1b") (:authors ("Jeremie Dimino" . "jeremie@dimino.org")) (:maintainer "Jeremie Dimino" . "jeremie@dimino.org") (:keywords "ocaml" "languages") (:url . "https://github.com/ocaml-community/utop"))]) (uuid . [(20120910 851) nil "UUID's for EmacsLisp" single ((:commit . "1519bfeb0e31602b840bc8dd35d7c7e732c159fe") (:authors ("James Mastros")) (:maintainer "Nic Ferrier" . "nferrier@ferrier.me.uk") (:keywords "lisp"))]) (uuidgen . [(20220405 1345) nil "Provides various UUID generating functions" single ((:commit . "7b728c1d92e196c3acf87a004949335cfc18eab3") (:authors ("Kan-Ru Chen" . "kanru@kanru.info")) (:maintainer "Kan-Ru Chen" . "kanru@kanru.info") (:keywords "extensions" "lisp" "tools"))]) @@ -5073,14 +5104,14 @@ (vbasense . [(20140221 2353) ((auto-complete (1 4 0)) (log4e (0 2 0)) (yaxception (0 1))) "provide a environment like Visual Basic Editor." tar ((:commit . "8c61a492d7c15218ae1a96e2aebfe6f78bfff6db") (:authors ("Hiroaki Otsu" . "ootsuhiroaki@gmail.com")) (:maintainer "Hiroaki Otsu" . "ootsuhiroaki@gmail.com") (:keywords "vba" "completion") (:url . "https://github.com/aki2o/emacs-vbasense"))]) (vc-auto-commit . [(20210216 1517) nil "Auto-committing feature for your repository" tar ((:commit . "56f478016a541b395092a9d3cdc0da84a37b30a1") (:authors ("Sylvain Rousseau ")) (:maintainer "Sylvain Rousseau ") (:keywords "vc" "convenience") (:url . "http://github.com/thisirs/vc-auto-commit.git"))]) (vc-check-status . [(20210216 1525) nil "Warn you when quitting emacs and leaving repo dirty." tar ((:commit . "d95ef8f0799cd3dd83726ffa9b01b076f378ce34") (:authors ("Sylvain Rousseau ")) (:maintainer "Sylvain Rousseau ") (:keywords "vc" "convenience") (:url . "https://github.com/thisirs/vc-check-status"))]) - (vc-darcs . [(20220406 659) ((emacs (24))) "a VC backend for darcs" single ((:commit . "56426a235b742618b48fad8538777a9b3ffb7240") (:authors ("Jorgen Schaefer" . "forcer@forcix.cx") ("Juliusz Chroboczek" . "jch@pps.univ-paris-diderot.fr")) (:maintainer "Libor Čapák" . "capak@inputwish.com") (:keywords "vc"))]) + (vc-darcs . [(20230319 1149) ((emacs (24))) "a VC backend for darcs" single ((:commit . "097e03f119b4fedb0186fd45d730a1c5acac10dc") (:authors ("Jorgen Schaefer" . "forcer@forcix.cx") ("Juliusz Chroboczek" . "jch@pps.univ-paris-diderot.fr")) (:maintainer "Libor Čapák" . "capak@inputwish.com") (:keywords "vc"))]) (vc-defer . [(20201116 701) ((emacs (25 1))) "Defer non-essential vc.el work" single ((:commit . "aeafc419c1788b3ac4f0590c635374eefd7c220c") (:authors ("Matt Armstrong" . "marmstrong@google.com")) (:maintainer "Tom Fitzhenry" . "tomfitzhenry@google.com") (:keywords "vc" "tools") (:url . "https://github.com/google/vc-defer"))]) (vc-fossil . [(20221120 908) nil "VC backend for the fossil sofware configuraiton management system" single ((:commit . "e059ca466cc8914757c6bdb26fa9cc6b0820a9c1") (:authors ("Venkat Iyer" . "venkat@comit.com")) (:maintainer "Alfred M. Szmidt" . "ams@gnu.org"))]) (vc-hgcmd . [(20211021 1704) ((emacs (25 1))) "VC mercurial backend that uses hg command server" single ((:commit . "d044448965d31ca8214f8bca48487e4d9b9d9a0f") (:authors ("Andrii Kolomoiets" . "andreyk.mad@gmail.com")) (:maintainer "Andrii Kolomoiets" . "andreyk.mad@gmail.com") (:keywords "vc") (:url . "https://github.com/muffinmad/emacs-vc-hgcmd"))]) (vc-msg . [(20221005 1228) ((emacs (24 4)) (popup (0 5 0))) "Show commit information of current line" tar ((:commit . "027fefad63868cd7695372510c27922656cf996a") (:authors ("Chen Bin ")) (:maintainer "Chen Bin ") (:keywords "git" "vc" "svn" "hg" "messenger") (:url . "http://github.com/redguardtoo/vc-msg"))]) (vc-osc . [(20190402 2349) nil "non-resident support for osc version-control" single ((:commit . "bf5a515ed85f7d7cdfe66ed5bf4ef7554f8561e5") (:authors ("Adam Spiers (see vc.el for full credits)")) (:maintainer "Adam Spiers" . "aspiers@suse.com"))]) - (vcomp . [(20190128 20) nil "compare version strings" single ((:commit . "f839b3b3257a564b19d7f9557dc8bcbbe0b95842") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "versions") (:url . "https://github.com/tarsius/vcomp"))]) - (vcsh . [(20200226 1339) ((emacs (25 1))) "vcsh integration" single ((:commit . "7e376436b8f450a5571e19246136ccf77bbdd4f1") (:authors ("Štěpán Němec" . "stepnem@gmail.com")) (:maintainer "Štěpán Němec" . "stepnem@gmail.com") (:keywords "vc" "files") (:url . "https://gitlab.com/stepnem/vcsh-el"))]) + (vcomp . [(20230406 1934) ((emacs (24 1))) "Compare version strings" single ((:commit . "5e5af87d20f7a7727198c9cb064b39e9fd2c8c08") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li") (:keywords "versions") (:url . "https://github.com/tarsius/vcomp"))]) + (vcsh . [(20230402 1229) ((emacs (25 1))) "vcsh integration" single ((:commit . "b9c0109a8c77446980de668785e6af1e46bdcdcd") (:authors ("Štěpán Němec" . "stepnem@smrk.net")) (:maintainer "Štěpán Němec" . "stepnem@smrk.net") (:keywords "vc" "files") (:url . "http://git.smrk.net/vcsh.el"))]) (vdf-mode . [(20210303 714) ((emacs (24 3))) "Major mode for editing Valve VDF files." single ((:commit . "0910d4f847e9c817eb8da5434b3879048ec4ac92") (:authors ("Philipp Middendorf")) (:maintainer "Philipp Middendorf") (:url . "https://github.com/plapadoo/vdf-mode"))]) (vdiff . [(20220830 1450) ((emacs (24 4)) (hydra (0 13 0))) "A diff tool similar to vimdiff" single ((:commit . "d5df45f84395f507aba555a54407b60e284b23cd") (:authors ("Justin Burkett" . "justin@burkett.cc")) (:maintainer "Justin Burkett" . "justin@burkett.cc") (:keywords "diff") (:url . "https://github.com/justbur/emacs-vdiff"))]) (vdiff-magit . [(20220518 1948) ((emacs (24 4)) (vdiff (0 3)) (magit (2 10 0)) (transient (0 1 0))) "magit integration for vdiff" single ((:commit . "413f32c9f7e66f8379c23b5ab6341695dbcc2f20") (:authors ("Justin Burkett" . "justin@burkett.cc")) (:maintainer "Justin Burkett" . "justin@burkett.cc") (:keywords "diff") (:url . "https://github.com/justbur/emacs-vdiff-magit"))]) @@ -5091,10 +5122,10 @@ (vector-utils . [(20140508 2041) nil "Vector-manipulation utility functions" single ((:commit . "5f9ced3960a318d611c3d20ffdc9ca74054fa8b7") (:authors ("Roland Walker" . "walker@pobox.com")) (:maintainer "Roland Walker" . "walker@pobox.com") (:keywords "extensions") (:url . "http://github.com/rolandwalker/vector-utils"))]) (vega-view . [(20210401 1115) ((emacs (25)) (cider (0 24 0)) (parseedn (0 1))) "Vega visualization viewer" single ((:commit . "3793025a523a86acc6255b4183b12ebfc95e1116") (:authors ("Jack Rusher" . "jack@appliedscience.studio")) (:maintainer "Jack Rusher" . "jack@appliedscience.studio") (:keywords "multimedia") (:url . "https://www.github.com/applied-science/emacs-vega-view"))]) (vegetative-theme . [(20220822 353) ((autothemer (0 2)) (emacs (24))) "A Theme based on green CRT terminals" single ((:commit . "db60ce0fe327ae7e4371545179ed94483b1132a8") (:url . "http://github.com/emacsfodder/emacs-theme-vegetative"))]) - (verb . [(20221113 2327) ((emacs (25 1))) "Organize and send HTTP requests" tar ((:commit . "b8ff1a0bbf84920fe26c56b9658bd289f43ad100") (:authors ("Federico Tedin" . "federicotedin@gmail.com")) (:maintainer "Federico Tedin" . "federicotedin@gmail.com") (:keywords "tools") (:url . "https://github.com/federicotdn/verb"))]) + (verb . [(20230301 2117) ((emacs (25 1))) "Organize and send HTTP requests" tar ((:commit . "0fa5259eb7e9404a5d665fb3fdf3f2c19d043189") (:authors ("Federico Tedin" . "federicotedin@gmail.com")) (:maintainer "Federico Tedin" . "federicotedin@gmail.com") (:keywords "tools") (:url . "https://github.com/federicotdn/verb"))]) (veri-kompass . [(20200213 934) ((emacs (25)) (cl-lib (0 5)) (org (8 2 0))) "verilog codebase navigation facility" single ((:commit . "271903cdf92db05898ee7cffb65641f30fa08280") (:maintainer nil . "andrea_corallo@yahoo.it") (:keywords "languages" "extensions" "verilog" "hardware" "rtl") (:url . "https://gitlab.com/koral/veri-kompass"))]) (verify-url . [(20160426 1228) ((cl-lib (0 5))) "find out invalid urls in the buffer or region" single ((:commit . "d6f3623cda8cd526a2d198619b137059cb1ba1ab") (:authors ("DarkSun" . "lujun9972@gmail.com")) (:maintainer "DarkSun" . "lujun9972@gmail.com") (:keywords "convenience" "usability" "url") (:url . "https://github.com/lujun9972/verify-url"))]) - (verilog-ext . [(20230220 1852) ((emacs (28 1)) (verilog-mode (2022 12 18 181110314)) (eglot (1 9)) (lsp-mode (8 0 1)) (ag (0 48)) (ripgrep (0 4 0)) (hydra (0 15 0)) (apheleia (3 1)) (yasnippet (0 14 0)) (company (0 9 13)) (flycheck (33 -4)) (imenu-list (0 9)) (outshine (3 1 -1))) "Verilog Extensions" tar ((:commit . "6872a42791c5105bfe1de1d63abae537559c7ca9") (:authors ("Gonzalo Larumbe" . "gonzalomlarumbe@gmail.com")) (:maintainer "Gonzalo Larumbe" . "gonzalomlarumbe@gmail.com") (:keywords "verilog" "ide" "tools") (:url . "https://github.com/gmlarumbe/verilog-ext"))]) + (verilog-ext . [(20230320 1635) ((emacs (28 1)) (verilog-mode (2022 12 18 181110314)) (eglot (1 9)) (lsp-mode (8 0 1)) (ag (0 48)) (ripgrep (0 4 0)) (hydra (0 15 0)) (apheleia (3 1)) (yasnippet (0 14 0)) (company (0 9 13)) (flycheck (33 -4)) (imenu-list (0 9)) (outshine (3 1 -1)) (async (1 9 7))) "SystemVerilog Extensions" tar ((:commit . "ff3ede7a95ad327aad2ae450b35ccb902b318b40") (:authors ("Gonzalo Larumbe" . "gonzalomlarumbe@gmail.com")) (:maintainer "Gonzalo Larumbe" . "gonzalomlarumbe@gmail.com") (:keywords "verilog" "ide" "tools") (:url . "https://github.com/gmlarumbe/verilog-ext"))]) (verona-mode . [(20200823 536) ((emacs (25 1)) (dash (2 17 0)) (hydra (0 15 0))) "A major mode for the Verona programming language" single ((:commit . "72dd31ef847344d79409503f3c42169041eb3da4") (:keywords "languages" "programming") (:url . "https://github.com/damon-kwok/verona-mode"))]) (versuri . [(20211104 1301) ((emacs (26 1)) (dash (2 16 0)) (request (0 3 0)) (anaphora (1 0 4)) (esxml (0 1 0)) (s (1 12 0)) (esqlite (0 3 1))) "The lyrics package" single ((:commit . "c8ea562304194f3379ed8f9c6a785ce8ee72898e") (:authors ("Mihai Olteanu" . "mihai_olteanu@fastmail.fm")) (:maintainer "Mihai Olteanu" . "mihai_olteanu@fastmail.fm") (:keywords "multimedia") (:url . "https://github.com/mihaiolteanu/versuri/"))]) (vertica . [(20131217 1511) ((sql (3 0))) "Vertica SQL mode extension" single ((:commit . "3c9647b425c5c13c30bf0cba483646af18196588") (:authors ("Roman Scherer" . "roman@burningswell.com")) (:maintainer "Roman Scherer" . "roman@burningswell.com") (:keywords "sql" "vertica"))]) @@ -5126,13 +5157,13 @@ (vline . [(20210805 1528) ((emacs (24 3))) "Column highlighting (vertical line displaying) mode" single ((:commit . "f5d7b5743dceca75b81c8c95287cd5b0341debf9") (:authors ("Taiki SUGAWARA" . "buzz.taiki@gmail.com")) (:maintainer "Taiki SUGAWARA" . "buzz.taiki@gmail.com") (:keywords "faces" "editing" "emulating") (:url . "https://www.emacswiki.org/emacs/VlineMode"))]) (vmd-mode . [(20210524 27) ((emacs (24 3))) "Fast Github-flavored Markdown preview using a vmd subprocess." single ((:commit . "b2bdf2ab54f8fc37780e6b473e4ad69c0e9ff4a6") (:authors ("Blake Miller" . "blak3mill3r@gmail.com")) (:maintainer "Blake Miller" . "blak3mill3r@gmail.com") (:keywords "markdown" "preview" "live" "vmd") (:url . "https://github.com/blak3mill3r/vmd-mode"))]) (voca-builder . [(20161101 1645) ((popup (0 5 2))) "Helps you build up your vocabulary" single ((:commit . "51573beec8cd8308477b0faf453aad93e17f57c5") (:authors ("Yi Tang" . "yi.tang.uk@me.com")) (:maintainer "Yi Tang" . "yi.tang.uk@me.com") (:keywords "english" "vocabulary") (:url . "https://github.com/yitang/voca-builder"))]) - (volatile-highlights . [(20230220 1415) nil "Minor mode for visual feedback on some operations." single ((:commit . "513c8b73cd3bc06cb9936a100468c227f649851c") (:authors ("K-talo Miyazaki ")) (:maintainer "K-talo Miyazaki ") (:keywords "emulations" "convenience" "wp") (:url . "http://www.emacswiki.org/emacs/download/volatile-highlights.el"))]) + (volatile-highlights . [(20230301 1402) nil "Minor mode for visual feedback on some operations." single ((:commit . "fcf6e2778454ce514c189a7d1fe70e03ad81c325") (:authors ("K-talo Miyazaki ")) (:maintainer "K-talo Miyazaki ") (:keywords "emulations" "convenience" "wp") (:url . "http://www.emacswiki.org/emacs/download/volatile-highlights.el"))]) (volume . [(20220904 1727) nil "tweak your sound card volume from Emacs" single ((:commit . "050d3e6d2543a6771a13f95612055864679b6301") (:authors ("Daniel Brockman" . "daniel@brockman.se")) (:maintainer "Daniel Brockman" . "daniel@brockman.se") (:url . "http://www.brockman.se/software/volume-el/"))]) - (vs-dark-theme . [(20221231 1702) ((emacs (24 1))) "Visual Studio IDE dark theme" single ((:commit . "636f4db45aa4dac1cda09b54757fdc3584ce6697") (:authors ("Jen-Chieh Shen")) (:maintainer "Jen-Chieh Shen") (:url . "https://github.com/emacs-vs/vs-dark-theme"))]) - (vs-light-theme . [(20221231 1702) ((emacs (24 1))) "Visual Studio IDE light theme" single ((:commit . "988b649dcb9074719c7fd0ad3f289cf2995d7635") (:authors ("Jen-Chieh Shen")) (:maintainer "Jen-Chieh Shen") (:url . "https://github.com/emacs-vs/vs-light-theme"))]) + (vs-dark-theme . [(20230310 914) ((emacs (24 1))) "Visual Studio IDE dark theme" single ((:commit . "1bbf3d580856610a5fe600da9c28ed17e8b4691d") (:authors ("Jen-Chieh Shen")) (:maintainer "Jen-Chieh Shen") (:url . "https://github.com/emacs-vs/vs-dark-theme"))]) + (vs-light-theme . [(20230310 913) ((emacs (24 1))) "Visual Studio IDE light theme" single ((:commit . "5accd5c1e4581005a0859cf7d85b0191b6b7a30b") (:authors ("Jen-Chieh Shen")) (:maintainer "Jen-Chieh Shen") (:url . "https://github.com/emacs-vs/vs-light-theme"))]) (vscdark-theme . [(20191212 107) ((emacs (24 1))) "VS Code Dark+ like theme" single ((:commit . "f419553e2a2f091a8bc257fb5ab520326e93ddd4") (:authors ("Alexander L. Belikoff")) (:maintainer "Alexander L. Belikoff") (:url . "https://github.com/abelikoff/vscdark-theme"))]) (vscode-dark-plus-theme . [(20221121 1846) nil "Default Visual Studio Code Dark+ theme" single ((:commit . "f33e1f92f6b34bbd7ecc81cb4c6d48f9cab393d9") (:authors ("Ian Y.E. Pan")) (:maintainer "Ian Y.E. Pan") (:url . "https://github.com/ianpan870102/vscode-dark-plus-emacs-theme"))]) - (vscode-icon . [(20201214 2227) ((emacs (25 1))) "Utility package to provide Vscode style icons" tar ((:commit . "909151c8105861aa300f5601e333909d36d0ebf5") (:authors ("James Nguyen" . "james@jojojames.com")) (:maintainer "James Nguyen" . "james@jojojames.com") (:keywords "files" "tools") (:url . "https://github.com/jojojames/vscode-icon-emacs"))]) + (vscode-icon . [(20230330 2206) ((emacs (25 1))) "Utility package to provide Vscode style icons" tar ((:commit . "3976bc2e7e2fe0068ae59c11d226f67e0e87aaea") (:authors ("James Nguyen" . "james@jojojames.com")) (:maintainer "James Nguyen" . "james@jojojames.com") (:keywords "files" "tools") (:url . "https://github.com/jojojames/vscode-icon-emacs"))]) (vterm . [(20230217 228) ((emacs (25 1))) "Fully-featured terminal emulator" tar ((:commit . "3e5a9b754b8e61850bb7d1b63b090b9fbf6687f3") (:authors ("Lukas Fürmetz" . "fuermetz@mailbox.org")) (:maintainer "Lukas Fürmetz" . "fuermetz@mailbox.org") (:keywords "terminals") (:url . "https://github.com/akermu/emacs-libvterm"))]) (vterm-toggle . [(20220820 1608) ((emacs (25 1)) (vterm (0 0 1))) "Toggles between the vterm buffer and other buffers." single ((:commit . "b94522e3a4ddaae098f4711aadce675e891cdec8") (:authors (nil . "jixiuf jixiuf@qq.com")) (:maintainer nil . "jixiuf jixiuf@qq.com") (:keywords "vterm" "terminals") (:url . "https://github.com/jixiuf/vterm-toggle"))]) (vtm . [(20200921 338) nil "Manages vterm buffers with configuration files" tar ((:commit . "d770fd8cff7c24688199392ad93c01485c6a9569") (:keywords "convenience") (:url . "https://github.com/laishulu/emacs-vterm-manager"))]) @@ -5144,7 +5175,7 @@ (vyper-mode . [(20180707 1935) ((emacs (24 3))) "Major mode for the Vyper programming language" single ((:commit . "323dfddfc38f0b11697e9ebaf04d1b53297e54e5") (:authors ("Alex Stokes" . "r.alex.stokes@gmail.com")) (:maintainer "Alex Stokes" . "r.alex.stokes@gmail.com") (:keywords "languages") (:url . "https://github.com/ralexstokes/vyper-mode"))]) (w32-browser . [(20170101 1954) nil "Run Windows application associated with a file." single ((:commit . "e5c60eafd8f8d3546a0fa295ad5af2414d36b4e6") (:authors ("Emacs Wiki, Drew Adams")) (:maintainer nil . "Drew Adams (concat \"drew.adams\" \"@\" \"oracle\" \".com\")") (:keywords "mouse" "dired" "w32" "explorer") (:url . "http://www.emacswiki.org/w32-browser.el"))]) (w32-ime . [(20201107 143) ((emacs (24 4))) "Windows IME UI/UX controler" single ((:commit . "9c62273dce0ba685a591577885b1e216ba832ec1") (:authors ("H.Miyashita") ("MIYOSHI Masanori") ("KOBAYASHI Yasuhiro") ("NTEmacsJP") ("ksugita (gnupack)") ("rzl24ozi") ("TANE") ("Masamichi Hosoda" . "trueroad@trueroad.jp") ("Naoya Yamashita" . "conao3@gmail.com")) (:maintainer "Masamichi Hosoda" . "trueroad@trueroad.jp") (:url . "https://github.com/trueroad/w32-ime.el"))]) - (w3m . [(20230119 418) nil "an Emacs interface to w3m" tar ((:commit . "d7f99ea4561004f7f15e8d17f5f7a084d04f3925") (:keywords "w3m" "www" "hypermedia"))]) + (w3m . [(20230324 125) nil "an Emacs interface to w3m" tar ((:commit . "f8819bca0c97970662cd4214f8f3104ab4a376c1") (:keywords "w3m" "www" "hypermedia"))]) (wacspace . [(20180311 2350) ((dash (1 2 0)) (cl-lib (0 2))) "The WACky WorkSPACE manager for emACS" tar ((:commit . "54d19aab6fd2bc5945b7ffc58104e695064927e2") (:authors ("Emanuel Evans" . "emanuel.evans@gmail.com")) (:maintainer "Emanuel Evans" . "emanuel.evans@gmail.com") (:keywords "workspace") (:url . "http://github.com/shosti/wacspace.el"))]) (waf-mode . [(20170403 1940) nil "Waf integration for Emacs" single ((:commit . "91c761336aa137b85b88b53b3f0cc60786d70800") (:authors ("Denys Valchuk" . "dvalchuk@gmail.com")) (:maintainer "Denys Valchuk" . "dvalchuk@gmail.com") (:url . "https://bitbucket.org/dvalchuk/waf-mode"))]) (waher-theme . [(20141115 1230) ((emacs (24 1))) "Emacs 24 theme based on waher for st2 by dduckster" single ((:commit . "60d31519fcfd8e797723d47961b255ae2f2e2c0a") (:authors ("Jasonm23" . "jasonm23@gmail.com")) (:maintainer "Jasonm23" . "jasonm23@gmail.com") (:url . "https://github.com/jasonm23/emacs-waher-theme"))]) @@ -5157,8 +5188,9 @@ (wallpreview . [(20220703 1108) ((emacs (24 4))) "Set wallpapers with image-dired" single ((:commit . "6eae0549afdfe725b453ca4fb0878c728735892d") (:url . "https://github.com/nryotaro/wallpreview"))]) (wand . [(20220519 1214) nil "Magic wand for Emacs - Select and execute" tar ((:commit . "e4afc0469c818e7ce73ef31c38d911477947d72e") (:authors ("Ha-Duong Nguyen ")) (:maintainer "Ha-Duong Nguyen ") (:keywords "extensions" "tools") (:url . "https://github.com/cmpitg/wand"))]) (wandbox . [(20170603 1231) ((emacs (24)) (request (0 3 0)) (s (1 10 0))) "Wandbox client" tar ((:commit . "e002fe41f2cd9b4ce2b1dc80b83301176e9117f1") (:authors ("KOBAYASHI Shigeru (kosh)" . "shigeru.kb@gmail.com")) (:maintainer "KOBAYASHI Shigeru (kosh)" . "shigeru.kb@gmail.com") (:keywords "tools") (:url . "https://github.com/kosh04/emacs-wandbox"))]) - (wanderlust . [(20230120 904) ((emacs (24 5)) (apel (10 8)) (flim (1 14 9)) (semi (1 14 7))) "Yet Another Message Interface on Emacsen" tar ((:commit . "77662986fd91cff991f502b19262227227740d52"))]) + (wanderlust . [(20230329 931) ((emacs (24 5)) (apel (10 8)) (flim (1 14 9)) (semi (1 14 7))) "Yet Another Message Interface on Emacsen" tar ((:commit . "74b4fe3ebfffbaec85dbc14c09750cc67ca60f9b"))]) (warm-night-theme . [(20161101 1428) ((emacs (24))) "Emacs 24 theme with a dark background." single ((:commit . "020f084d23409b5035150508ba6e57c2509edd64") (:authors ("martin haesler")) (:maintainer "martin haesler"))]) + (wasp-mode . [(20230226 2035) ((emacs (24 3))) "A major mode for the Wasp programming language" single ((:commit . "00fc41ecfe0291cc32e012a074d8a3a65e1bfd64") (:authors ("XXIV")) (:maintainer "XXIV") (:keywords "files" "wasp") (:url . "https://github.com/thechampagne/wasp-mode"))]) (watch-buffer . [(20120331 2044) nil "run a shell command when saving a buffer" single ((:commit . "a01cf15608c5bf91df253104053041ca1afdf411") (:authors ("Michael Steger" . "mjsteger1@gmail.com")) (:maintainer "Michael Steger" . "mjsteger1@gmail.com") (:keywords "automation" "convenience") (:url . "https://github.com/mjsteger/watch-buffer"))]) (wavefront-obj-mode . [(20170808 1716) nil "Major mode for Wavefront obj files" single ((:commit . "34027915de6496460d8e68b5991dd24d47d54859") (:authors ("Sasha Kovar" . "sasha-emacs@arcocene.org")) (:maintainer "Sasha Kovar" . "sasha-emacs@arcocene.org") (:url . "http://github.com/abend/wavefront-obj-mode"))]) (wc-goal-mode . [(20140829 1359) nil "Running word count with goals (minor mode)" single ((:commit . "bf21ab9c5a449bcc20dd207a4915dcec218d2699") (:authors ("Benjamin Beckwith")) (:maintainer "Benjamin Beckwith") (:url . "https://github.com/bnbeckwith/wc-goal-mode"))]) @@ -5169,7 +5201,7 @@ (web . [(20141231 2001) ((dash (2 9 0)) (s (1 5 0))) "useful HTTP client" single ((:commit . "483188dac4bc6b409b985c9dae45f3324a425efd") (:authors ("Nic Ferrier" . "nferrier@ferrier.me.uk")) (:maintainer "Nic Ferrier" . "nferrier@ferrier.me.uk") (:keywords "lisp" "http" "hypermedia") (:url . "http://github.com/nicferrier/emacs-web"))]) (web-beautify . [(20161115 2247) nil "Format HTML, CSS and JavaScript/JSON" single ((:commit . "e1b45321d8c11b404b12c8e55afe55eaa7c84ee9") (:authors ("Yasuyuki Oka" . "yasuyk@gmail.com")) (:maintainer "Yasuyuki Oka" . "yasuyk@gmail.com") (:url . "https://github.com/yasuyk/web-beautify"))]) (web-completion-data . [(20160318 848) nil "Shared completion data for ac-html and company-web" tar ((:commit . "c272c94e8a71b779c29653a532f619acad433a4f") (:authors ("Olexandr Sydorchuk" . "olexandr.syd@gmail.com")) (:maintainer "Olexandr Sydorchuk" . "olexandr.syd@gmail.com") (:keywords "html" "auto-complete" "company") (:url . "https://github.com/osv/web-completion-data"))]) - (web-mode . [(20230206 1654) ((emacs (23 1))) "major mode for editing web templates" single ((:commit . "df97ab62c94826a84adbde060a4111ca91deda8e") (:authors ("François-Xavier Bois")) (:maintainer "François-Xavier Bois" . "fxbois@gmail.com") (:keywords "languages") (:url . "https://web-mode.org"))]) + (web-mode . [(20230329 601) ((emacs (23 1))) "major mode for editing web templates" single ((:commit . "57856ba64b9382811b35df0d9ab0a24aede0c1f0") (:authors ("François-Xavier Bois")) (:maintainer "François-Xavier Bois" . "fxbois@gmail.com") (:keywords "languages") (:url . "https://web-mode.org"))]) (web-mode-edit-element . [(20190531 852) ((emacs (24 4)) (web-mode (14))) "Helper-functions for attribute- and element-handling" tar ((:commit . "ad5d7e4dc2420bdd00ce65d9adffbd38a5904afa") (:authors ("Julian T. Knabenschuh" . "jtkdevelopments@gmail.com")) (:maintainer "Julian T. Knabenschuh" . "jtkdevelopments@gmail.com") (:keywords "languages" "convenience") (:url . "https://github.com/jtkDvlp/web-mode-edit-element"))]) (web-narrow-mode . [(20170407 210) ((web-mode (14 0 27))) "quick narrow code block in web-mode" single ((:commit . "b25fae07844875d5b62d14b98442c88817b7e139") (:authors ("Qquanwei" . "quanwei9958@126.com")) (:maintainer "Johan Andersson" . "quanwei9958@126.com") (:keywords "web-mode" "react" "narrow" "web") (:url . "https://github.com/Qquanwei/web-narrow-mode"))]) (web-search . [(20190620 602) ((emacs (24 3))) "Open a web search" tar ((:commit . "a22cbdc663a1895d5a5b69de91e1e3b9eb64b92f") (:authors ("Xu Chunyang" . "mail@xuchunyang.me")) (:maintainer "Xu Chunyang" . "mail@xuchunyang.me") (:keywords "web" "search") (:url . "https://github.com/xuchunyang/web-search.el"))]) @@ -5180,7 +5212,7 @@ (weblorg . [(20220312 2008) ((templatel (0 1 6)) (emacs (26 1))) "Static Site Generator for org-mode" tar ((:commit . "9daa6725919dfebaf6fbe19ed262231c2cbf9f89") (:authors ("Lincoln Clarete" . "lincoln@clarete.li")) (:maintainer "Lincoln Clarete" . "lincoln@clarete.li") (:url . "https://emacs.love/weblorg"))]) (webpaste . [(20220524 1745) ((emacs (24 4)) (request (0 2 0)) (cl-lib (0 5))) "Paste to pastebin-like services" single ((:commit . "d96da58fe42988d5c433c71ee9f8e6fb75d595a9") (:authors ("Elis \"etu\" Hirwing" . "elis@hirwing.se")) (:maintainer "Elis \"etu\" Hirwing" . "elis@hirwing.se") (:keywords "convenience" "comm" "paste") (:url . "https://github.com/etu/webpaste.el"))]) (websearch . [(20230210 1321) ((emacs (24 4))) "Query search engines" tar ((:commit . "aa0d7899e032e330e2980aa4be34ed872395883b") (:authors ("Maciej Barć" . "xgqt@riseup.net")) (:maintainer "Maciej Barć" . "xgqt@riseup.net") (:keywords "convenience" "hypermedia") (:url . "https://gitlab.com/xgqt/emacs-websearch/"))]) - (websocket . [(20230129 1601) ((cl-lib (0 5))) "Emacs WebSocket client and server" single ((:commit . "2c576b6cb8e7b868e09e09c8e9cb6cf66f427bad") (:authors ("Andrew Hyatt" . "ahyatt@gmail.com")) (:maintainer "Andrew Hyatt" . "ahyatt@gmail.com") (:keywords "communication" "websocket" "server") (:url . "https://github.com/ahyatt/emacs-websocket"))]) + (websocket . [(20230305 410) ((cl-lib (0 5))) "Emacs WebSocket client and server" single ((:commit . "1a08093b122d8cf20366a1cba5faddf7a53d08ed") (:authors ("Andrew Hyatt" . "ahyatt@gmail.com")) (:maintainer "Andrew Hyatt" . "ahyatt@gmail.com") (:keywords "communication" "websocket" "server") (:url . "https://github.com/ahyatt/emacs-websocket"))]) (wedge-ws . [(20140714 2149) nil "Wedge whitespace between columns in text" single ((:commit . "4669115f02d9c6fee067cc5369bb38c0f9db88b2") (:authors ("Anders Eurenius" . "aes@spotify.com")) (:maintainer "Anders Eurenius" . "aes@spotify.com") (:keywords "formatting" "indentation"))]) (weechat . [(20190520 1551) ((s (1 3 1)) (cl-lib (0 2)) (emacs (24)) (tracking (1 2))) "Chat via WeeChat's relay protocol in Emacs" tar ((:commit . "d9a13306ea8be27367f92e9202d116a88fa1f441") (:authors ("Moritz Ulrich" . "moritz@tarn-vedra.de") ("Rüdiger Sonderfeld" . "ruediger@c-plusplus.de") ("Aristid Breitkreuz" . "aristidb@gmail.com")) (:maintainer "Moritz Ulrich" . "moritz@tarn-vedra.de") (:keywords "irc" "chat" "network" "weechat") (:url . "https://github.com/the-kenny/weechat.el"))]) (weechat-alert . [(20160416 1248) ((weechat (0 3 1)) (cl-lib (0 5)) (alert (1 2))) "Weechat notifier using alerts" single ((:commit . "a8fd557c8f335322f132c1c6c08b6741d6394e2e") (:authors ("Andreas Klein" . "git@kungi.org")) (:maintainer "Andreas Klein" . "git@kungi.org") (:keywords "irc" "chat" "network" "weechat") (:url . "https://github.com/kungi/weechat-alert"))]) @@ -5194,8 +5226,8 @@ (wgrep-pt . [(20230207 1125) ((emacs (25 1)) (wgrep (3 0 0))) "Writable pt buffer" single ((:commit . "edf768732a56840db6879706b64c5773c316d619") (:authors ("Masahiro Hayashi , Bailey Ling" . "bling@live.ca")) (:maintainer "Masahiro Hayashi , Bailey Ling" . "bling@live.ca") (:keywords "grep" "edit" "extensions") (:url . "http://github.com/mhayashi1120/Emacs-wgrep/raw/master/wgrep-pt.el"))]) (wgsl-mode . [(20221127 2129) ((emacs (24))) "Syntax highlighting for the WebGPU Shading Language" single ((:commit . "e7856d6755d93e40ed74598a68ef5f607322618b") (:authors ("Anthony Cowley")) (:maintainer "Anthony Cowley") (:keywords "wgsl" "c") (:url . "https://github.com/acowley/wgsl-mode"))]) (what-the-commit . [(20150901 1316) nil "Random commit message generator" single ((:commit . "42604410cfd5be715c8aa730aef4673773454e8b") (:authors ("Dan Barbarito" . "dan@barbarito.me")) (:maintainer "Dan Barbarito" . "dan@barbarito.me") (:keywords "git" "commit" "message") (:url . "http://barbarito.me/"))]) - (which-key . [(20220811 1616) ((emacs (24 4))) "Display available keybindings in popup" single ((:commit . "8093644032854b1cdf3245ce4e3c7b6673f741bf") (:authors ("Justin Burkett" . "justin@burkett.cc")) (:maintainer "Justin Burkett" . "justin@burkett.cc") (:url . "https://github.com/justbur/emacs-which-key"))]) - (which-key-posframe . [(20220804 1311) ((emacs (26 0)) (posframe (0 4 3)) (which-key (3 3 2))) "Using posframe to show which-key" single ((:commit . "421cbfbe5d43ca8a48ecb18ea6d3d95f9ca6e9e6") (:authors ("Yanghao Xie")) (:maintainer "Yanghao Xie" . "yhaoxie@gmail.com") (:keywords "convenience" "bindings" "tooltip") (:url . "https://github.com/yanghaoxie/which-key-posframe"))]) + (which-key . [(20230330 2121) ((emacs (24 4))) "Display available keybindings in popup" single ((:commit . "bd34ede7bf77ad3988330b37207f3978e7342c79") (:authors ("Justin Burkett" . "justin@burkett.cc")) (:maintainer "Justin Burkett" . "justin@burkett.cc") (:url . "https://github.com/justbur/emacs-which-key"))]) + (which-key-posframe . [(20230313 1841) ((emacs (26 0)) (posframe (1 4 0)) (which-key (3 6 0))) "Using posframe to show which-key" single ((:commit . "e4a9ce9a1b20de550fca51f14d055821980d534a") (:authors ("Yanghao Xie" . "yhaoxie@gmail.com")) (:maintainer "Yanghao Xie" . "yhaoxie@gmail.com") (:keywords "convenience" "bindings" "tooltip") (:url . "https://github.com/emacsorphanage/which-key-posframe"))]) (whiley-mode . [(20220501 2219) ((emacs (24 1))) "Major mode for Whiley language" single ((:commit . "e7cc4759d46be589d421a2235af6771bcde9ae33") (:authors ("David J. Pearce" . "dave01001110@gmail.com")) (:maintainer "David J. Pearce" . "dave01001110@gmail.com") (:keywords "languages") (:url . "http://github.com/Whiley/WhileyEmacsMode"))]) (whitaker . [(20210203 1149) ((emacs (25))) "Comint interface for Whitaker's Words" single ((:commit . "a6fda24ccb69a18c0706633326d5cc4fcfaed83a") (:authors ("Matus Goljer" . "matus.goljer@gmail.com")) (:maintainer "Matus Goljer" . "matus.goljer@gmail.com") (:keywords "processes"))]) (white-sand-theme . [(20210131 813) ((emacs (24))) "Emacs theme with a light background." single ((:commit . "729dd52cc1936250183d6761eed406c4be514a71") (:authors ("Martin Haesler")) (:maintainer "Martin Haesler"))]) @@ -5207,10 +5239,10 @@ (why-this . [(20221129 817) ((emacs (27 1))) "Why is this line here? Ask version control" single ((:commit . "5203d9379afaf6703746823a580c804e1dd98e08") (:authors ("Akib Azmain Turja" . "akib@disroot.org")) (:maintainer "Akib Azmain Turja" . "akib@disroot.org") (:keywords "tools" "convenience" "vc") (:url . "https://codeberg.org/akib/emacs-why-this"))]) (wide-column . [(20170925 1613) nil "Calls functions dependant on column position." single ((:commit . "ce9ef4675485a7bea381077866368ef875226b10") (:authors ("Phillip Lord" . "p.lord@russet.org.uk")) (:maintainer "Phillip Lord" . "p.lord@russet.org.uk") (:keywords "minor mode" "cursor colour" "column width"))]) (widget-mvc . [(20150102 406) nil "MVC framework for the emacs widgets" single ((:commit . "2576e6f0c35d8dedfa9c2cd6ea4fb4c14cb72b63") (:authors ("SAKURAI Masashi ")) (:maintainer "SAKURAI Masashi ") (:keywords "lisp" "widget"))]) - (wiki-nav . [(20200309 1323) ((button-lock (1 0 2)) (nav-flash (1 0 0))) "Simple file navigation using [[WikiStrings]]" single ((:commit . "9afe0f4d05910b0cccc94cb6d4d880119f3b0528") (:authors ("Roland Walker" . "walker@pobox.com")) (:maintainer "Roland Walker" . "walker@pobox.com") (:keywords "mouse" "button" "hypermedia" "navigation") (:url . "http://github.com/rolandwalker/button-lock"))]) + (wiki-nav . [(20230304 2212) ((button-lock (1 0 2)) (nav-flash (1 0 0))) "Simple file navigation using [[WikiStrings]]" single ((:commit . "1f7a89ca05b6167af7d1337ad23a5d923486caac") (:authors ("Roland Walker" . "walker@pobox.com")) (:maintainer "Roland Walker" . "walker@pobox.com") (:keywords "mouse" "button" "hypermedia" "navigation") (:url . "http://github.com/rolandwalker/button-lock"))]) (wiki-summary . [(20181010 1824) ((emacs (24))) "View Wikipedia summaries in Emacs easily." single ((:commit . "fa41ab6e50b3b80e54148af9d4bac18fd0405000") (:authors ("Danny Gratzer")) (:maintainer "Danny Gratzer") (:keywords "wikipedia" "utility") (:url . "https://github.com/jozefg/wiki-summary.el"))]) (wikinfo . [(20220906 1709) ((emacs (27 1))) "Scrape Wikipedia Infoboxes" single ((:commit . "bf395c9aaf6be7fda371be611005737d52417fec") (:authors ("Nicholas Vollmer" . "progfolio@protonmail.com")) (:maintainer "Nicholas Vollmer" . "progfolio@protonmail.com") (:keywords "org" "convenience") (:url . "https://github.com/progfolio/wikinfo"))]) - (wikinforg . [(20220906 1711) ((emacs (27 1)) (wikinfo (0 0 0)) (org (9 3))) "Org-mode wikinfo integration" single ((:commit . "6ed4463e1b119497dbde1454a9e60b41f2626bd3") (:authors ("Nicholas Vollmer" . "progfolio@protonmail.com")) (:maintainer "Nicholas Vollmer" . "progfolio@protonmail.com") (:keywords "org" "convenience") (:url . "https://github.com/progfolio/wikinforg"))]) + (wikinforg . [(20230317 2050) ((emacs (27 1)) (wikinfo (0 0 0)) (org (9 3))) "Org-mode wikinfo integration" single ((:commit . "fe16cbecc73a41110f2bad95c1f63a97a9da88ca") (:authors ("Nicholas Vollmer" . "progfolio@protonmail.com")) (:maintainer "Nicholas Vollmer" . "progfolio@protonmail.com") (:keywords "org" "convenience") (:url . "https://github.com/progfolio/wikinforg"))]) (wilt . [(20180220 854) ((emacs (24 3)) (dash (2 12 0)) (s (1 10 0))) "An extensions for calculating WILT in a buffer." single ((:commit . "04dbe37fa35d0b24c791421785d2c97a8cbfe2cc") (:authors ("Austin Bingham" . "austin@sixty-north.com")) (:maintainer "Austin Bingham" . "austin@sixty-north.com") (:url . "https://github.com/sixty-north/emacs-wilt"))]) (win-switch . [(20161009 1627) nil "fast, dynamic bindings for window-switching/resizing" single ((:commit . "954eb5e4c5737f0c06368c42a7f1c3dd374d782f") (:authors ("Christopher Genovese" . "genovese@cmu.edu")) (:maintainer "Christopher R. Genovese" . "genovese@cmu.edu") (:keywords "window" "switch" "key bindings" "ergonomic" "efficient") (:url . "http://www.stat.cmu.edu/~genovese/emacs/win-switch/"))]) (windata . [(20090830 1040) nil "convert window configuration to list" single ((:commit . "a723fc446ceaec23d5f29ecc8245d94c99d91625") (:authors (nil . "wenbinye@gmail.com")) (:maintainer nil . "wenbinye@gmail.com") (:keywords "convenience" "frames"))]) @@ -5244,15 +5276,16 @@ (wordel . [(20230109 1407) ((emacs (27 1))) "An Elisp implementation of \"Wordle\" (aka \"Lingo\")" tar ((:commit . "77999d75c5eae29e22b8e3f8859b62c6e30aa65f") (:authors ("Nicholas Vollmer" . "iarchivedmywholelife@gmail.com")) (:maintainer "Nicholas Vollmer" . "iarchivedmywholelife@gmail.com") (:keywords "games") (:url . "https://github.com/progfolio/wordel"))]) (wordgen . [(20170803 1820) ((emacs (24)) (cl-lib (0 5))) "Random word generator" single ((:commit . "aacad928ae99a953e034a831dfd0ebdf7d52ac1d") (:authors ("Fanael Linithien" . "fanael4@gmail.com")) (:maintainer "Fanael Linithien" . "fanael4@gmail.com") (:url . "https://github.com/Fanael/wordgen.el"))]) (wordnut . [(20180313 443) ((emacs (24 4))) "Major mode interface to WordNet" tar ((:commit . "feac531404041855312c1a046bde7ea18c674915"))]) - (wordreference . [(20230214 1735) ((emacs (27 1)) (s (1 12 0))) "Interface for wordreference.com" single ((:commit . "8ccda3422fc30fba23602327cc8e7de9f53bfa1d") (:authors ("Marty Hiatt ")) (:maintainer "Marty Hiatt ") (:keywords "convenience" "translate" "wp" "dictionary") (:url . "https://codeberg.org/martianh/wordreference.el"))]) + (wordreference . [(20230405 1353) ((emacs (28 1))) "Interface for wordreference.com" single ((:commit . "fcc791173a0e9f89d05b651a09f7d64a21aff584") (:authors ("Marty Hiatt ")) (:maintainer "Marty Hiatt ") (:keywords "convenience" "translate" "wp" "dictionary") (:url . "https://codeberg.org/martianh/wordreference.el"))]) (wordsmith-mode . [(20210715 1517) nil "Syntax analysis and NLP text-processing in Emacs (OSX-only)" single ((:commit . "5d40ceaa2b8d41ab3634ca377ceb6a74deeb2287") (:authors ("istib" . "istib@thebati.net")) (:maintainer "istib" . "istib@thebati.net"))]) (worf . [(20220102 835) ((swiper (0 11 0)) (ace-link (0 1 0)) (hydra (0 13 0)) (zoutline (0 1 0))) "A warrior does not press so many keys! (in org-mode)" tar ((:commit . "8681241e118585824cd256e5b026978bf06c7e58") (:authors ("Oleh Krehel" . "ohwoeowho@gmail.com")) (:maintainer "Oleh Krehel" . "ohwoeowho@gmail.com") (:keywords "lisp") (:url . "https://github.com/abo-abo/worf"))]) (workgroups . [(20110726 1641) nil "workgroups for windows (for Emacs)" single ((:commit . "9572b3492ee09054dc329f64ed846c962b395e39") (:authors ("tlh" . "thunkout@gmail.com")) (:maintainer "tlh" . "thunkout@gmail.com") (:keywords "session" "management" "window-configuration" "persistence"))]) - (workgroups2 . [(20220702 842) ((emacs (25 1))) "save&load multiple named workspaces (or \"workgroups\")" tar ((:commit . "a8a4d07bff27f72970fe7e204997f1ba0e80263b") (:authors ("Sergey Pashinin ")) (:maintainer "Sergey Pashinin ") (:keywords "session" "management" "window-configuration" "persistence") (:url . "https://github.com/pashinin/workgroups2"))]) + (workgroups2 . [(20230328 1331) ((emacs (25 1))) "save&load multiple named workspaces (or \"workgroups\")" tar ((:commit . "aff9d76b7be5eed33f30be2fabf111818749cbd5") (:authors ("Sergey Pashinin ")) (:maintainer "Sergey Pashinin ") (:keywords "session" "management" "window-configuration" "persistence") (:url . "https://github.com/pashinin/workgroups2"))]) (workroom . [(20230123 1630) ((emacs (25 1)) (project (0 3 0)) (compat (28 1 2 2))) "Named rooms for work without irrelevant distracting buffers" tar ((:commit . "360420501a239f74bff60941d28052fc19a92bce") (:authors ("Akib Azmain Turja" . "akib@disroot.org")) (:maintainer "Akib Azmain Turja" . "akib@disroot.org") (:keywords "tools" "convenience") (:url . "https://codeberg.org/akib/emacs-workroom"))]) (world-time-mode . [(20140627 807) nil "show whole days of world-time diffs" single ((:commit . "ce7a3b45c87eb24cfe61eee453175d64f741d7cc") (:authors ("Nic Ferrier" . "nferrier@ferrier.me.uk")) (:maintainer "Nic Ferrier" . "nferrier@ferrier.me.uk") (:keywords "tools" "calendar"))]) (wotd . [(20170328 1948) ((emacs (24 4)) (org (8 2 10))) "Fetch word-of-the-day from multiple online sources" single ((:commit . "d2937a3d91e014f8028a1f33d21c18cc0b065a64") (:authors ("Junpeng Qiu" . "qjpchmail@gmail.com")) (:maintainer "Junpeng Qiu" . "qjpchmail@gmail.com") (:keywords "extensions"))]) (wrap-region . [(20140117 720) ((dash (1 0 3))) "Wrap text with punctation or tag" single ((:commit . "5a910ad23ebb0649e644bf62ad042587341da5da") (:authors ("Johan Andersson" . "johan.rejeep@gmail.com")) (:maintainer "Johan Andersson" . "johan.rejeep@gmail.com") (:keywords "speed" "convenience") (:url . "http://github.com/rejeep/wrap-region"))]) + (wren-mode . [(20221227 227) ((emacs (24 3))) "A major mode for the Wren programming language" single ((:commit . "70b1b89f565679a15c8c9c1a9bda98b0d163e83e") (:authors ("XXIV")) (:maintainer "XXIV") (:keywords "files" "wren") (:url . "https://github.com/thechampagne/wren-mode"))]) (writefreely . [(20221221 1456) ((emacs (24 3)) (org (9 0)) (ox-gfm (0 0)) (request (0 3))) "Push your Org files as markdown to a writefreely instance" single ((:commit . "db70444eb5fbe0820754574d70b1ae44967607dc") (:authors ("Daniel Gomez ")) (:maintainer "Daniel Gomez ") (:keywords "convenience") (:url . "https://github.com/dangom/writefreely.el"))]) (writegood-mode . [(20220511 2109) nil "Polish up poor writing on the fly" single ((:commit . "d54eadeedb8bf3aa0e0a584c0a7373c69644f4b8") (:authors ("Benjamin Beckwith")) (:maintainer "Benjamin Beckwith") (:keywords "writing" "weasel-words" "grammar") (:url . "http://github.com/bnbeckwith/writegood-mode"))]) (writeroom-mode . [(20220426 2046) ((emacs (25 1)) (visual-fill-column (2 2))) "Minor mode for distraction-free writing" tar ((:commit . "a736205c194d7525feb1e1f10f4186c7b2b62bef") (:authors ("Joost Kremers" . "joostkremers@fastmail.fm")) (:maintainer "Joost Kremers" . "joostkremers@fastmail.fm") (:keywords "text") (:url . "https://github.com/joostkremers/writeroom-mode"))]) @@ -5288,7 +5321,7 @@ (xref-js2 . [(20210310 1238) ((emacs (25 1)) (js2-mode (20150909))) "Jump to references/definitions using ag & js2-mode's AST" single ((:commit . "fd6b723e7f1f9793d189a815e1904364dc026b03") (:authors ("Nicolas Petton" . "nicolas@petton.fr")) (:maintainer "Nicolas Petton" . "nicolas@petton.fr") (:keywords "javascript" "convenience" "tools") (:url . "https://github.com/NicolasPetton/xref-js2"))]) (xref-rst . [(20230116 1300) ((emacs (28 1))) "Lookup reStructuredText symbols" single ((:commit . "0cc7fadd4698bd5b51ce2a52fcb4de41c7f030f2") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com") (:url . "https://codeberg.org/ideasman42/emacs-xref-rst"))]) (xresources-theme . [(20221208 2015) nil "Use your .Xresources as your emacs theme" single ((:commit . "76532fc4330e9e31accc580708514b83b15d70a7") (:authors ("Marten Lienen" . "marten.lienen@gmail.com")) (:maintainer "Marten Lienen" . "marten.lienen@gmail.com") (:keywords "xresources" "theme"))]) - (xterm-color . [(20200605 2017) ((emacs (24 4))) "ANSI, XTERM 256 and Truecolor support" single ((:commit . "b9b1f84fb10fff5261702e38bf15b3ae75a4b6bb") (:authors ("xristos" . "xristos@sdf.org")) (:maintainer "xristos" . "xristos@sdf.org") (:keywords "faces") (:url . "https://github.com/atomontage/xterm-color"))]) + (xterm-color . [(20230321 3) ((emacs (24 4))) "ANSI, XTERM 256 and Truecolor support" single ((:commit . "2ad407c651e90fff2ea85d17bf074cee2c022912") (:authors ("xristos" . "xristos@sdf.org")) (:maintainer "xristos" . "xristos@sdf.org") (:keywords "faces") (:url . "https://github.com/atomontage/xterm-color"))]) (xterm-keybinder . [(20160523 56) ((emacs (24 3)) (cl-lib (0 5)) (let-alist (1 0 1))) "Let you extra keybinds in xterm/urxvt" tar ((:commit . "b29c4f700b0fa0c9f627f6725b36462b8fab06d6") (:authors ("Yuta Yamada ")) (:maintainer "Yuta Yamada ") (:keywords "convenient"))]) (xtest . [(20141214 1706) ((cl-lib (0 5))) "Simple Testing with Emacs & ERT" single ((:commit . "8099be9c2d856f98489834ddb20a01c6fd8922f1") (:authors ("Mustafa Shameem")) (:maintainer "Mustafa Shameem") (:keywords "testing" "ert") (:url . "https://github.com/promethial/xtest"))]) (xwidgete . [(20171118 2116) ((emacs (25))) "enhances usability of current xwidget browser" single ((:commit . "e4e8410fe32176df85b46234717824519443fb04") (:authors ("Tu, Do Hoang" . "tuhdo1710@gmail.com")) (:maintainer "Tu, Do Hoang") (:keywords "xwidgete" "tools") (:url . "https://github.com/tuhdo/xwidgete"))]) @@ -5297,16 +5330,16 @@ (xwwp . [(20200917 643) ((emacs (26 1))) "Enhance xwidget webkit browser" tar ((:commit . "f67e070a6e1b233e60274deb717274b000923231") (:authors ("Damien Merenne")) (:maintainer "Damien Merenne") (:keywords "convenience") (:url . "https://github.com/canatella/xwwp"))]) (xwwp-follow-link-helm . [(20200917 642) ((emacs (26 1)) (xwwp (0 1))) "Link navigation in `xwidget-webkit' sessions using `helm'" single ((:commit . "99670ec37e2083eada9691a342441d2fa4589002") (:authors ("Damien Merenne")) (:maintainer "Damien Merenne") (:keywords "convenience") (:url . "https://github.com/canatella/xwwp"))]) (xwwp-follow-link-ivy . [(20200917 642) ((emacs (26 1)) (xwwp (0 1))) "Link navigation in `xwidget-webkit' sessions using `ivy'" single ((:commit . "1f1646feaf3328568da40200cc218337fbbabc1a") (:authors ("Damien Merenne")) (:maintainer "Damien Merenne") (:keywords "convenience") (:url . "https://github.com/canatella/xwwp"))]) - (yabaki-theme . [(20230117 2312) ((emacs (27 1))) "Yabaki, the cast shadow" single ((:commit . "5b0aaaf352384f24b0104065b5c600e8e6fab707") (:authors ("David Goudou" . "david.goudou@gmail.com")) (:maintainer "David Goudou" . "david.goudou@gmail.com") (:url . "https://github.com/seamacs/yabaki-theme"))]) + (yabaki-theme . [(20230327 630) ((emacs (27 1))) "Yabaki, the cast shadow" single ((:commit . "5face6a1194b039e09fe19238aa5db05450d7df1") (:authors ("David Goudou" . "david.goudou@gmail.com")) (:maintainer "David Goudou" . "david.goudou@gmail.com") (:url . "https://github.com/seamacs/yabaki-theme"))]) (yabin . [(20140206 351) nil "Yet Another Bignum package (A thin wrapper of calc.el)." single ((:commit . "db8c404507560ef9147fcce2b94cd706fbfa03b5") (:authors ("Daisuke Kobayashi" . "d5884jp@gmail.com")) (:maintainer "Daisuke Kobayashi" . "d5884jp@gmail.com") (:keywords "data"))]) (yafolding . [(20200119 1353) nil "Folding code blocks based on indentation" single ((:commit . "4c1888ae45f9241516519ae0ae3a899f2efa05ba") (:authors ("Zeno Zeng" . "zenoofzeng@gmail.com")) (:maintainer "Zeno Zeng" . "zenoofzeng@gmail.com") (:keywords "folding"))]) (yagist . [(20160418 508) ((cl-lib (0 3))) "Yet Another Emacs integration for gist.github.com" single ((:commit . "10da4baa272ff0f7052f17debecc340764c7003f") (:maintainer "Masahiro Hayashi" . "mhayashi1120@gmail.com") (:keywords "tools") (:url . "https://github.com/mhayashi1120/yagist.el"))]) (yahtzee . [(20220221 803) ((emacs (24 3))) "The yahtzee game" single ((:commit . "9b42ba4612d3043464414c08a3d60f6ad594566c") (:authors ("Dimitar Dimitrov" . "mail.mitko@gmail.com")) (:maintainer "Dimitar Dimitrov" . "mail.mitko@gmail.com") (:keywords "games") (:url . "https://github.com/drdv/yahtzee"))]) (yalinum . [(20130217 1043) nil "yet another display line numbers." single ((:commit . "d3e0cbe3f4f5ca311e3298e684901d6fea3ad973") (:authors ("tm8st" . "tm8st@hotmail.co.jp")) (:maintainer "tm8st" . "tm8st@hotmail.co.jp") (:keywords "convenience" "tools"))]) - (yaml . [(20220720 2359) ((emacs (25 1))) "YAML parser for Elisp" single ((:commit . "73fde9d8fbbaf2596449285df9eb412ae9dd74d9") (:authors ("Zachary Romero" . "zkry@posteo.org")) (:maintainer "Zachary Romero" . "zkry@posteo.org") (:keywords "tools") (:url . "https://github.com/zkry/yaml.el"))]) + (yaml . [(20230312 250) ((emacs (25 1))) "YAML parser for Elisp" single ((:commit . "a19fbf948a945571300e5a20ff1dbfa6ecfa0d16") (:authors ("Zachary Romero" . "zkry@posteo.org")) (:maintainer "Zachary Romero" . "zkry@posteo.org") (:keywords "tools") (:url . "https://github.com/zkry/yaml.el"))]) (yaml-imenu . [(20220406 1703) ((emacs (24 4)) (yaml-mode (0))) "Enhancement of the imenu support in yaml-mode." tar ((:commit . "c1fbba8b03a7bef4fc2b87404914fa9c6eb67b55") (:authors ("Akinori MUSHA" . "knu@iDaemons.org")) (:maintainer "Akinori MUSHA" . "knu@iDaemons.org") (:keywords "outlining" "convenience" "imenu") (:url . "https://github.com/knu/yaml-imenu.el"))]) - (yaml-mode . [(20221022 920) ((emacs (24 1))) "Major mode for editing YAML files" single ((:commit . "141b85f9e01589e67955f3785a83b72b42109357") (:authors ("Yoshiki Kurihara" . "clouder@gmail.com") ("Marshall T. Vandegrift" . "llasram@gmail.com")) (:maintainer "Vasilij Schneidermann" . "mail@vasilij.de") (:keywords "data" "yaml") (:url . "https://github.com/yoshiki/yaml-mode"))]) - (yaml-pro . [(20230115 427) ((emacs (26 1)) (yaml (0 5 1))) "Parser-aided YAML editing features" tar ((:commit . "5b8c236e1a45b4f6e2d32e10b69868634c8152bf") (:authors ("Zachary Romero")) (:maintainer "Zachary Romero") (:keywords "tools") (:url . "https://github.com/zkry/yaml-pro"))]) + (yaml-mode . [(20230329 723) ((emacs (24 1))) "Major mode for editing YAML files" single ((:commit . "b153150e0e77b4ec462d741cdb16956c6ae270d6") (:authors ("Yoshiki Kurihara" . "clouder@gmail.com") ("Marshall T. Vandegrift" . "llasram@gmail.com")) (:maintainer "Vasilij Schneidermann" . "mail@vasilij.de") (:keywords "data" "yaml") (:url . "https://github.com/yoshiki/yaml-mode"))]) + (yaml-pro . [(20230315 320) ((emacs (26 1)) (yaml (0 5 1))) "Parser-aided YAML editing features" tar ((:commit . "50fc911b9015708b77872dc60c53f4a4740bef1b") (:authors ("Zachary Romero")) (:maintainer "Zachary Romero") (:keywords "tools") (:url . "https://github.com/zkry/yaml-pro"))]) (yaml-tomato . [(20151123 753) ((s (1 9))) "copy or show the yaml path currently under cursor." single ((:commit . "1272c502fac6ce6b0f8b7f8a9beb353f0b35e13c") (:authors ("qrczeno")) (:maintainer "qrczeno") (:keywords "yaml"))]) (yang-mode . [(20190507 724) nil "major mode for editing YANG files" single ((:commit . "4b4ab4d4a79d37d6c31c6ea7cccbc425e0b1eded") (:authors ("Martin Bjorklund" . "mbj4668@gmail.com")) (:maintainer "Martin Bjorklund" . "mbj4668@gmail.com"))]) (yankpad . [(20220201 2104) ((emacs (25 1))) "Paste snippets from an org-mode file" single ((:commit . "927e6d26956ac7219b8a69d641acf486854fba16") (:authors ("Erik Sjöstrand")) (:maintainer "Erik Sjöstrand") (:keywords "abbrev" "convenience") (:url . "http://github.com/Kungsgeten/yankpad"))]) @@ -5318,9 +5351,9 @@ (yascroll . [(20220212 1742) ((emacs (26 1))) "Yet Another Scroll Bar Mode" single ((:commit . "b4669a6604a3093d3960c494874a7affc6b9c184") (:authors ("Tomohiro Matsuyama" . "m2ym.pub@gmail.com")) (:maintainer "Shen, Jen-Chieh" . "jcs090218@gmail.com") (:keywords "convenience") (:url . "https://github.com/emacsorphanage/yascroll"))]) (yasnippet . [(20200604 246) ((cl-lib (0 5))) "Yet another snippet extension for Emacs" single ((:commit . "5cbdbf0d2015540c59ed8ee0fcf4788effdf75b6") (:maintainer "Noam Postavsky" . "npostavs@gmail.com") (:keywords "convenience" "emulation") (:url . "http://github.com/joaotavora/yasnippet"))]) (yasnippet-lean . [(20220105 2251) ((yasnippet (0 8 0))) "Collection of snippets for the Lean prover" tar ((:commit . "c75485757cc8675ad4f36c1eb028d9d54dc21733") (:maintainer "Simon Hudon" . "simon.hudon@gmail.com") (:keywords "convenience" "snippets" "leanprover") (:url . "https://github.com/leanprover-community/yasnippet-lean"))]) - (yasnippet-snippets . [(20230220 1659) ((yasnippet (0 8 0))) "Collection of yasnippet snippets" tar ((:commit . "9580874944cce78b3bb2296ae10de1443b0a57e8") (:authors ("Andrea Crotti" . "andrea.crotti.0@gmail.com")) (:maintainer "Andrea Crotti" . "andrea.crotti.0@gmail.com") (:keywords "snippets") (:url . "https://github.com/AndreaCrotti/yasnippet-snippets"))]) + (yasnippet-snippets . [(20230314 2056) ((yasnippet (0 8 0))) "Collection of yasnippet snippets" tar ((:commit . "8e4c521252501dd9ad71ea78fae14683ab7a14cb") (:authors ("Andrea Crotti" . "andrea.crotti.0@gmail.com")) (:maintainer "Andrea Crotti" . "andrea.crotti.0@gmail.com") (:keywords "snippets") (:url . "https://github.com/AndreaCrotti/yasnippet-snippets"))]) (yatemplate . [(20211115 1208) ((yasnippet (0 8 1)) (emacs (24 3))) "File templates with yasnippet" single ((:commit . "275745ce1482edc08efb0b7807bc86d832bcc734") (:authors ("Wieland Hoffmann" . "themineo+yatemplate@gmail.com")) (:maintainer "Wieland Hoffmann" . "themineo+yatemplate@gmail.com") (:keywords "files" "convenience") (:url . "https://github.com/mineo/yatemplate"))]) - (yatex . [(20221216 904) nil "Yet Another tex-mode for emacs //野鳥//" tar ((:commit . "c11261c0960fe44c8664aa017924475dde9d7f71"))]) + (yatex . [(20221225 512) nil "Yet Another tex-mode for emacs //野鳥//" tar ((:commit . "157aa7974191bbb4707d26b05ce830282ad70ef5"))]) (yaxception . [(20150105 1540) nil "Provide framework about exception like Java for Elisp" single ((:commit . "4e94cf3e0b9b5631b0e90eb4b7de597ee7185875") (:authors ("Hiroaki Otsu" . "ootsuhiroaki@gmail.com")) (:maintainer "Hiroaki Otsu" . "ootsuhiroaki@gmail.com") (:keywords "exception" "error" "signal") (:url . "https://github.com/aki2o/yaxception"))]) (ycm . [(20150822 1836) nil "Emacs client for the YouCompleteMe auto-completion server." single ((:commit . "4da8a14abcd0f4fa3235042ade2e12b5068c0601") (:authors ("Ajay Gopinathan" . "ajay@gopinathan.net")) (:maintainer "Ajay Gopinathan" . "ajay@gopinathan.net") (:keywords "c" "abbrev"))]) (ycmd . [(20190416 807) ((emacs (24 4)) (dash (2 13 0)) (s (1 11 0)) (deferred (0 5 1)) (cl-lib (0 6 1)) (let-alist (1 0 5)) (request (0 3 0)) (request-deferred (0 3 0)) (pkg-info (0 6))) "emacs bindings to the ycmd completion server" tar ((:commit . "6f4f7384b82203cccf208e3ec09252eb079439f9") (:url . "https://github.com/abingham/emacs-ycmd"))]) @@ -5330,7 +5363,7 @@ (yesterbox . [(20200327 52) ((emacs (24 3))) "Count number of inbox messages by day" single ((:commit . "7d890ab3f012b1a48a0e8e437f5fcaeba9825fdc") (:authors ("Stephen J. Eglen" . "sje30@cam.ac.uk")) (:maintainer "Stephen J. Eglen" . "sje30@cam.ac.uk") (:keywords "mail") (:url . "http://github.com/sje30/yesterbox"))]) (ynab . [(20200607 2008) ((emacs (26 3)) (cl-lib (0 5)) (ts (0 2))) "Major mode for YNAB (you need a budget)" single ((:commit . "2c6beb4d2c4996017f6b3c62c26db52a61e5c479") (:authors ("Jim Anders ")) (:maintainer "Jim Anders" . "jimanders223@gmail.com") (:keywords "ynab" "budget" "convenience") (:url . "https://github.com/janders223/ynab.el"))]) (yoficator . [(20190509 1620) nil "Interactively yoficate Russian texts" tar ((:commit . "fa914f9648515bca54b5e558ca57d2b65fa57491") (:authors ("Eugene Minkovskii" . "emin@mccme.ru") ("Alexander Krotov" . "ilabdsf@gmail.com")) (:maintainer "Eugene Minkovskii" . "emin@mccme.ru") (:url . "https://gitlab.com/link2xt/yoficator"))]) - (yoshi-theme . [(20221024 20) nil "Theme named after my cat" single ((:commit . "59cf53110ed73344c7f96da8136b88b039b69602") (:authors ("Tom Willemse" . "tom@ryuslash.org")) (:maintainer "Tom Willemse" . "tom@ryuslash.org") (:keywords "faces") (:url . "http://projects.ryuslash.org/yoshi-theme/"))]) + (yoshi-theme . [(20230225 740) nil "Theme named after my cat" single ((:commit . "ba9427329ac49fa2e060da2c16507feed62ad890") (:authors ("Tom Willemse" . "tom@ryuslash.org")) (:maintainer "Tom Willemse" . "tom@ryuslash.org") (:keywords "faces") (:url . "http://projects.ryuslash.org/yoshi-theme/"))]) (youdao-dictionary . [(20200722 1705) ((popup (0 5 0)) (pos-tip (0 4 6)) (chinese-word-at-point (0 2)) (names (0 5)) (emacs (24))) "Youdao Dictionary interface for Emacs" single ((:commit . "8a4815a43565b9bfd257246e4895b8bfafb9d573") (:authors ("Chunyang Xu" . "xuchunyang56@gmail.com")) (:maintainer "Chunyang Xu" . "xuchunyang56@gmail.com") (:keywords "convenience" "chinese" "dictionary") (:url . "https://github.com/xuchunyang/youdao-dictionary.el"))]) (youtube-sub-extractor . [(20221116 653) ((emacs (27 1))) "Extract YouTube video subtitles" single ((:commit . "d69f732299fdf256504e15767c1d7e5de771220e") (:authors ("Ag Ibragimov" . "agzam.ibragimov@gmail.com")) (:maintainer "Ag Ibragimov" . "agzam.ibragimov@gmail.com") (:keywords "convenience" "multimedia") (:url . "https://github.com/agzam/youtube-sub-extractor.el"))]) (ytdious . [(20210228 2111) ((emacs (25 3))) "Query / Preview YouTube via Invidious" single ((:commit . "941460b51e43ef6764e15e2b9c4af54c3e56115f") (:authors ("Stefan Huchler") ("Gabriele Rastello")) (:maintainer "Stefan Huchler") (:keywords "youtube" "matching" "multimedia") (:url . "https://github.com/spiderbit/ytdious"))]) @@ -5342,7 +5375,7 @@ (zeal-at-point . [(20180131 2354) nil "Search the word at point with Zeal" single ((:commit . "0fc3263f44e95acd3e9d91057677621ce4d297ee") (:authors ("Jinzhu" . "wosmvp@gmail.com")) (:maintainer "Jinzhu" . "wosmvp@gmail.com") (:url . "https://github.com/jinzhu/zeal-at-point"))]) (zen-and-art-theme . [(20120622 1437) nil "zen and art color theme for GNU Emacs 24" single ((:commit . "a7226cbce0bca2501d69a620cb2aeabfc396c232") (:authors ("Nick Parker")) (:maintainer "Nick Parker"))]) (zen-mode . [(20200609 822) ((emacs (24 3))) "A major mode for the Zen programming language" single ((:commit . "c1b1806358f3cce6c04b30699987d82dc7d42559") (:authors ("Andrea Orru , Andrew Kelley , kristopher tate , Yoshitaka Takemoto" . "yt.3b8@connectfree.co.jp")) (:maintainer "Andrea Orru , Andrew Kelley , kristopher tate , Yoshitaka Takemoto" . "yt.3b8@connectfree.co.jp") (:keywords "zen" "languages") (:url . "https://github.com/zenlang/zen-mode"))]) - (zenburn-theme . [(20220927 631) nil "A low contrast color theme for Emacs." single ((:commit . "4788de0bcfecf8faec69251decb9924492d008f3") (:authors ("Bozhidar Batsov" . "bozhidar@batsov.com")) (:maintainer "Bozhidar Batsov" . "bozhidar@batsov.com") (:url . "http://github.com/bbatsov/zenburn-emacs"))]) + (zenburn-theme . [(20230315 1004) nil "A low contrast color theme for Emacs." single ((:commit . "8a1f9d28f503615e5d9b3eac59a2f3c14e75fc20") (:authors ("Bozhidar Batsov" . "bozhidar@batsov.com")) (:maintainer "Bozhidar Batsov" . "bozhidar@batsov.com") (:url . "http://github.com/bbatsov/zenburn-emacs"))]) (zencoding-mode . [(20140213 822) nil "Unfold CSS-selector-like expressions to markup" single ((:commit . "58e42af182c98cb9941d27cd042d227fbf4e146c") (:authors ("Chris Done" . "chrisdone@gmail.com")) (:maintainer "Chris Done" . "chrisdone@gmail.com") (:keywords "convenience") (:url . "https://github.com/rooney/zencoding"))]) (zenity-color-picker . [(20160302 1154) ((emacs (24 4))) "Insert and adjust colors using Zenity" single ((:commit . "bdece51052ef7037e0a3481fc1f487939f57777e") (:authors ("Samuel Laurén" . "samuel.lauren@iki.fi")) (:maintainer "Samuel Laurén" . "samuel.lauren@iki.fi") (:keywords "colors") (:url . "https://bitbucket.org/Soft/zenity-color-picker.el"))]) (zeno-theme . [(20211205 2148) ((emacs (24))) "A dark theme using different shades of blue" single ((:commit . "70fa7b7442f24ea25eab538b5a22da690745fef5") (:authors ("Bharat Joshi" . "jbharat@outlook.com")) (:maintainer "Bharat Joshi" . "jbharat@outlook.com") (:keywords "faces" "theme" "dark" "blue") (:url . "https://github.com/jbharat/zeno-theme"))]) @@ -5358,7 +5391,7 @@ (zetteldesk-remark . [(20220702 1527) ((zetteldesk (1 0)) (org-remark (1 0)) (emacs (27 2))) "Org-Remark integration for zetteldesk.el" single ((:commit . "99c5434a809da0b783f31b10872c8cb2a2176e2d") (:authors ("Vidianos Giannitsis" . "vidianosgiannitsis@gmail.com")) (:maintainer "Vidianos Giannitsis" . "vidianosgiannitsis@gmail.com") (:url . "https://github.com/Vidianos-Giannitsis/zetteldesk-remark.el"))]) (zettelkasten . [(20230108 1724) ((emacs (25 1)) (s (1 10 0))) "Helper functions to organise notes in a Zettelkasten style" single ((:commit . "cc4d69c302a46b8f802a1871aae091df1f3398ba") (:authors ("Yann Herklotz" . "yann@ymhg.org")) (:maintainer "Yann Herklotz" . "yann@ymhg.org") (:keywords "files" "hypermedia" "notes") (:url . "https://github.com/ymherklotz/emacs-zettelkasten"))]) (zetz-mode . [(20200823 536) ((emacs (25 1)) (dash (2 17 0)) (hydra (0 15 0))) "A major mode for the ZetZ programming language" single ((:commit . "04da33f4ffa9db5b3556f423276f4fd1db13ec67") (:keywords "languages" "programming") (:url . "https://github.com/damon-kwok/zetz-mode"))]) - (zig-mode . [(20230121 1229) ((emacs (24 3)) (reformatter (0 6))) "A major mode for the Zig programming language" single ((:commit . "3cf8ccb55156677b77e0cafbafee8f63dcebfd49") (:authors ("Andrea Orru , Andrew Kelley" . "superjoe30@gmail.com")) (:maintainer "Andrea Orru , Andrew Kelley" . "superjoe30@gmail.com") (:keywords "zig" "languages") (:url . "https://github.com/zig-lang/zig-mode"))]) + (zig-mode . [(20230307 1215) ((emacs (24 3)) (reformatter (0 6))) "A major mode for the Zig programming language" single ((:commit . "2013d39ee9a62449263939bc8c33a128fe1e90f0") (:authors ("Andrea Orru , Andrew Kelley" . "superjoe30@gmail.com")) (:maintainer "Andrea Orru , Andrew Kelley" . "superjoe30@gmail.com") (:keywords "zig" "languages") (:url . "https://github.com/zig-lang/zig-mode"))]) (zim-wiki-mode . [(20230211 1650) ((emacs (25 1)) (helm-ag (0 58)) (helm-projectile (0 14 0)) (dokuwiki-mode (0 1 1)) (link-hint (0 1)) (pretty-hydra (0 2 2))) "Zim Desktop Wiki edit mode" single ((:commit . "cf3d5a0dfb53d6cba8d7d35420ec18bf81b5bf2f") (:authors ("Will Foran" . "willforan+zim-wiki-mode@gmail.com")) (:maintainer "Will Foran" . "willforan+zim-wiki-mode@gmail.com") (:keywords "outlines") (:url . "https://github.com/WillForan/zim-wiki-mode"))]) (zimports . [(20211011 2059) ((emacs (26 1)) (projectile (2 1 0))) "Reformat python imports with zimports" single ((:commit . "76cf76bdc871cb0454a6fc555aeb1aa94f1b6e57") (:url . "https://github.com/schmir/zimports.el"))]) (zk . [(20221121 1252) ((emacs (25 1))) "Functions for working with Zettelkasten-style linked notes" single ((:commit . "afddac4018c8cf8d8088b4ca128adb01a872e741") (:authors ("Grant Rosson ")) (:maintainer "Grant Rosson ") (:url . "https://github.com/localauthor/zk"))]) diff --git a/org/elpa/async-20230323.643/async-autoloads.el b/org/elpa/async-20230323.643/async-autoloads.el new file mode 100644 index 0000000..8e2db9f --- /dev/null +++ b/org/elpa/async-20230323.643/async-autoloads.el @@ -0,0 +1,224 @@ +;;; async-autoloads.el --- automatically extracted autoloads -*- lexical-binding: t -*- +;; +;;; Code: + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + + +;;;### (autoloads nil "async" "async.el" (0 0 0 0)) +;;; Generated autoloads from async.el + +(autoload 'async-start-process "async" "\ +Start the executable PROGRAM asynchronously named NAME. See `async-start'. +PROGRAM is passed PROGRAM-ARGS, calling FINISH-FUNC with the +process object when done. If FINISH-FUNC is nil, the future +object will return the process object when the program is +finished. Set DEFAULT-DIRECTORY to change PROGRAM's current +working directory. + +\(fn NAME PROGRAM FINISH-FUNC &rest PROGRAM-ARGS)" nil nil) + +(autoload 'async-start "async" "\ +Execute START-FUNC (often a lambda) in a subordinate Emacs process. +When done, the return value is passed to FINISH-FUNC. Example: + + (async-start + ;; What to do in the child process + (lambda () + (message \"This is a test\") + (sleep-for 3) + 222) + + ;; What to do when it finishes + (lambda (result) + (message \"Async process done, result should be 222: %s\" + result))) + +If you call `async-send' from a child process, the message will +be also passed to the FINISH-FUNC. You can test RESULT to see if +it is a message by using `async-message-p'. If nil, it means +this is the final result. Example of the FINISH-FUNC: + + (lambda (result) + (if (async-message-p result) + (message \"Received a message from child process: %s\" result) + (message \"Async process done, result: %s\" result))) + +If FINISH-FUNC is nil or missing, a future is returned that can +be inspected using `async-get', blocking until the value is +ready. Example: + + (let ((proc (async-start + ;; What to do in the child process + (lambda () + (message \"This is a test\") + (sleep-for 3) + 222)))) + + (message \"I'm going to do some work here\") ;; .... + + (message \"Waiting on async process, result should be 222: %s\" + (async-get proc))) + +If you don't want to use a callback, and you don't care about any +return value from the child process, pass the `ignore' symbol as +the second argument (if you don't, and never call `async-get', it +will leave *emacs* process buffers hanging around): + + (async-start + (lambda () + (delete-file \"a remote file on a slow link\" nil)) + \\='ignore) + +Special case: +If the output of START-FUNC is a string with properties +e.g. (buffer-string) RESULT will be transformed in a list where the +car is the string itself (without props) and the cdr the rest of +properties, this allows using in FINISH-FUNC the string without +properties and then apply the properties in cdr to this string (if +needed). +Properties handling special objects like markers are returned as +list to allow restoring them later. +See for more infos. + +Note: Even when FINISH-FUNC is present, a future is still +returned except that it yields no value (since the value is +passed to FINISH-FUNC). Call `async-get' on such a future always +returns nil. It can still be useful, however, as an argument to +`async-ready' or `async-wait'. + +\(fn START-FUNC &optional FINISH-FUNC)" nil nil) + +(register-definition-prefixes "async" '("async-")) + +;;;*** + +;;;### (autoloads nil "async-bytecomp" "async-bytecomp.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from async-bytecomp.el + +(autoload 'async-byte-recompile-directory "async-bytecomp" "\ +Compile all *.el files in DIRECTORY asynchronously. +All *.elc files are systematically deleted before proceeding. + +\(fn DIRECTORY &optional QUIET)" nil nil) + +(defvar async-bytecomp-package-mode nil "\ +Non-nil if Async-Bytecomp-Package mode is enabled. +See the `async-bytecomp-package-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `async-bytecomp-package-mode'.") + +(custom-autoload 'async-bytecomp-package-mode "async-bytecomp" nil) + +(autoload 'async-bytecomp-package-mode "async-bytecomp" "\ +Byte compile asynchronously packages installed with package.el. +Async compilation of packages can be controlled by +`async-bytecomp-allowed-packages'. + +This is a minor mode. If called interactively, toggle the +`Async-Bytecomp-Package mode' mode. If the prefix argument is +positive, enable the mode, and if it is zero or negative, disable +the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `(default-value \\='async-bytecomp-package-mode)'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +\(fn &optional ARG)" t nil) + +(autoload 'async-byte-compile-file "async-bytecomp" "\ +Byte compile Lisp code FILE asynchronously. + +Same as `byte-compile-file' but asynchronous. + +\(fn FILE)" t nil) + +(register-definition-prefixes "async-bytecomp" '("async-")) + +;;;*** + +;;;### (autoloads nil "dired-async" "dired-async.el" (0 0 0 0)) +;;; Generated autoloads from dired-async.el + +(defvar dired-async-mode nil "\ +Non-nil if Dired-Async mode is enabled. +See the `dired-async-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `dired-async-mode'.") + +(custom-autoload 'dired-async-mode "dired-async" nil) + +(autoload 'dired-async-mode "dired-async" "\ +Do dired actions asynchronously. + +This is a minor mode. If called interactively, toggle the +`Dired-Async mode' mode. If the prefix argument is positive, +enable the mode, and if it is zero or negative, disable the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `(default-value \\='dired-async-mode)'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +\(fn &optional ARG)" t nil) + +(autoload 'dired-async-do-copy "dired-async" "\ +Run ‘dired-do-copy’ asynchronously. + +\(fn &optional ARG)" t nil) + +(autoload 'dired-async-do-symlink "dired-async" "\ +Run ‘dired-do-symlink’ asynchronously. + +\(fn &optional ARG)" t nil) + +(autoload 'dired-async-do-hardlink "dired-async" "\ +Run ‘dired-do-hardlink’ asynchronously. + +\(fn &optional ARG)" t nil) + +(autoload 'dired-async-do-rename "dired-async" "\ +Run ‘dired-do-rename’ asynchronously. + +\(fn &optional ARG)" t nil) + +(register-definition-prefixes "dired-async" '("dired-async-")) + +;;;*** + +;;;### (autoloads nil "smtpmail-async" "smtpmail-async.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from smtpmail-async.el + +(register-definition-prefixes "smtpmail-async" '("async-smtpmail-")) + +;;;*** + +;;;### (autoloads nil nil ("async-pkg.el") (0 0 0 0)) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; coding: utf-8 +;; End: +;;; async-autoloads.el ends here diff --git a/org/elpa/async-20230323.643/async-bytecomp.el b/org/elpa/async-20230323.643/async-bytecomp.el new file mode 100644 index 0000000..42dbab3 --- /dev/null +++ b/org/elpa/async-20230323.643/async-bytecomp.el @@ -0,0 +1,211 @@ +;;; async-bytecomp.el --- Compile elisp files asynchronously -*- lexical-binding: t -*- + +;; Copyright (C) 2014-2022 Free Software Foundation, Inc. + +;; Authors: John Wiegley +;; Thierry Volpiatto + +;; Keywords: dired async byte-compile +;; X-URL: https://github.com/jwiegley/emacs-async + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; +;; This package provide the `async-byte-recompile-directory' function +;; which allows, as the name says to recompile a directory outside of +;; your running emacs. +;; The benefit is your files will be compiled in a clean environment without +;; the old *.el files loaded. +;; Among other things, this fix a bug in package.el which recompile +;; the new files in the current environment with the old files loaded, creating +;; errors in most packages after upgrades. +;; +;; NB: This package is advicing the function `package--compile'. + +;;; Code: + +(require 'cl-lib) +(require 'async) +(require 'bytecomp) + +(declare-function package-desc-name "package.el") +(declare-function package-desc-dir "package.el") + +(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' (default), in this case +all packages are always compiled asynchronously." + :group 'async + :type '(choice + (const :tag "All packages" all) + (repeat symbol))) + +(defvar async-byte-compile-log-file + (concat user-emacs-directory "async-bytecomp.log")) + +(defvar async-bytecomp-load-variable-regexp "\\`load-path\\'" + "The variable used by `async-inject-variables' when (re)compiling async.") + +;;;###autoload +(defun async-byte-recompile-directory (directory &optional quiet) + "Compile all *.el files in DIRECTORY asynchronously. +All *.elc files are systematically deleted before proceeding." + (cl-loop with dir = (directory-files directory t "\\.elc\\'") + unless dir return nil + for f in dir + when (file-exists-p f) do (delete-file f)) + ;; Ensure async is reloaded when async.elc is deleted. + ;; This happen when recompiling its own directory. + (load "async") + (let ((call-back + (lambda (&optional _ignore) + (if (file-exists-p async-byte-compile-log-file) + (let ((buf (get-buffer-create byte-compile-log-buffer)) + (n 0)) + (with-current-buffer buf + (goto-char (point-max)) + (let ((inhibit-read-only t)) + (insert-file-contents async-byte-compile-log-file) + (compilation-mode)) + (display-buffer buf) + (delete-file async-byte-compile-log-file) + (unless quiet + (save-excursion + (goto-char (point-min)) + (while (re-search-forward "^.*:Error:" nil t) + (cl-incf n))) + (if (> n 0) + (message "Failed to compile %d files in directory `%s'" n directory) + (message "Directory `%s' compiled asynchronously with warnings" directory))))) + (unless quiet + (message "Directory `%s' compiled asynchronously with success" directory)))))) + (async-start + `(lambda () + (require 'bytecomp) + ,(async-inject-variables async-bytecomp-load-variable-regexp) + (let ((default-directory (file-name-as-directory ,directory)) + error-data) + (add-to-list 'load-path default-directory) + (byte-recompile-directory ,directory 0 t) + (when (get-buffer byte-compile-log-buffer) + (setq error-data (with-current-buffer byte-compile-log-buffer + (buffer-substring-no-properties (point-min) (point-max)))) + (unless (string= error-data "") + (with-temp-file ,async-byte-compile-log-file + (erase-buffer) + (insert error-data)))))) + call-back) + (unless quiet (message "Started compiling asynchronously directory %s" directory)))) + +(defvar package-archive-contents) +(defvar package-alist) +(declare-function package-desc-reqs "package.el" (cl-x)) + +(defun async-bytecomp--get-package-deps (pkgs) + ;; Same as `package--get-deps' but parse instead `package-archive-contents' + ;; because PKG is not already installed and not present in `package-alist'. + ;; However fallback to `package-alist' in case PKG no more present + ;; in `package-archive-contents' due to modification to `package-archives'. + ;; See issue #58. + (let ((seen '())) + (while pkgs + (let ((pkg (pop pkgs))) + (unless (memq pkg seen) + (let ((pkg-desc (cadr (or (assq pkg package-archive-contents) + (assq pkg package-alist))))) + (when pkg-desc + (push pkg seen) + (setq pkgs (append (mapcar #'car (package-desc-reqs pkg-desc)) + pkgs))))))) + seen)) + +(defun async--package-compile (orig-fun pkg-desc &rest args) + (let ((cur-package (package-desc-name pkg-desc)) + (pkg-dir (package-desc-dir pkg-desc))) + (if (or (member async-bytecomp-allowed-packages '(t all (all))) + (memq cur-package (async-bytecomp--get-package-deps + async-bytecomp-allowed-packages))) + (progn + ;; FIXME: Why do we use (eq cur-package 'async) once + ;; and (string= cur-package "async") afterwards? + (when (eq cur-package 'async) + (fmakunbound 'async-byte-recompile-directory)) + ;; Add to `load-path' the latest version of async and + ;; reload it when reinstalling async. + (when (string= cur-package "async") + (cl-pushnew pkg-dir load-path) + (load "async-bytecomp")) + ;; `async-byte-recompile-directory' will add directory + ;; as needed to `load-path'. + (async-byte-recompile-directory (package-desc-dir pkg-desc) t)) + (apply orig-fun pkg-desc args)))) + +;;;###autoload +(define-minor-mode async-bytecomp-package-mode + "Byte compile asynchronously packages installed with package.el. +Async compilation of packages can be controlled by +`async-bytecomp-allowed-packages'." + :group 'async + :global t + (if async-bytecomp-package-mode + (advice-add 'package--compile :around #'async--package-compile) + (advice-remove 'package--compile #'async--package-compile))) + +;;;###autoload +(defun async-byte-compile-file (file) + "Byte compile Lisp code FILE asynchronously. + +Same as `byte-compile-file' but asynchronous." + (interactive "fFile: ") + (let ((call-back + (lambda (&optional _ignore) + (let ((bn (file-name-nondirectory file))) + (if (file-exists-p async-byte-compile-log-file) + (let ((buf (get-buffer-create byte-compile-log-buffer)) + start) + (with-current-buffer buf + (goto-char (setq start (point-max))) + (let ((inhibit-read-only t)) + (insert-file-contents async-byte-compile-log-file) + (compilation-mode)) + (display-buffer buf) + (delete-file async-byte-compile-log-file) + (save-excursion + (goto-char start) + (if (re-search-forward "^.*:Error:" nil t) + (message "Failed to compile `%s'" bn) + (message "`%s' compiled asynchronously with warnings" bn))))) + (message "`%s' compiled asynchronously with success" bn)))))) + (async-start + `(lambda () + (require 'bytecomp) + ,(async-inject-variables async-bytecomp-load-variable-regexp) + (let ((default-directory ,(file-name-directory file))) + (add-to-list 'load-path default-directory) + (byte-compile-file ,file) + (when (get-buffer byte-compile-log-buffer) + (setq error-data (with-current-buffer byte-compile-log-buffer + (buffer-substring-no-properties (point-min) (point-max)))) + (unless (string= error-data "") + (with-temp-file ,async-byte-compile-log-file + (erase-buffer) + (insert error-data)))))) + call-back))) + +(provide 'async-bytecomp) + +;;; async-bytecomp.el ends here diff --git a/org/elpa/async-20230323.643/async-pkg.el b/org/elpa/async-20230323.643/async-pkg.el new file mode 100644 index 0000000..38bfbde --- /dev/null +++ b/org/elpa/async-20230323.643/async-pkg.el @@ -0,0 +1,12 @@ +(define-package "async" "20230323.643" "Asynchronous processing in Emacs" + '((emacs "24.4")) + :commit "34feabe1142863a2c96f75afda1a2ae4aa0813f6" :authors + '(("John Wiegley" . "jwiegley@gmail.com")) + :maintainer + '("Thierry Volpiatto" . "thievol@posteo.net") + :keywords + '("async") + :url "https://github.com/jwiegley/emacs-async") +;; Local Variables: +;; no-byte-compile: t +;; End: diff --git a/org/elpa/async-20230323.643/async.el b/org/elpa/async-20230323.643/async.el new file mode 100644 index 0000000..e181773 --- /dev/null +++ b/org/elpa/async-20230323.643/async.el @@ -0,0 +1,574 @@ +;;; async.el --- Asynchronous processing in Emacs -*- lexical-binding: t -*- + +;; Copyright (C) 2012-2022 Free Software Foundation, Inc. + +;; Author: John Wiegley +;; Maintainer: Thierry Volpiatto + +;; Created: 18 Jun 2012 +;; Version: 1.9.7 +;; Package-Requires: ((emacs "24.4")) + +;; Keywords: async +;; X-URL: https://github.com/jwiegley/emacs-async + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; Adds the ability to call asynchronous functions and process with ease. See +;; the documentation for `async-start' and `async-start-process'. + +;;; Code: + +(eval-when-compile (require 'cl-lib)) + +(defgroup async nil + "Simple asynchronous processing in Emacs" + :group 'lisp) + +(defcustom async-variables-noprops-function #'async--purecopy + "Default function to remove text properties in variables." + :type 'function) + +(defvar async-debug nil) +(defvar async-send-over-pipe t) +(defvar async-in-child-emacs nil) +(defvar async-callback nil) +(defvar async-callback-for-process nil + "Non-nil if the subprocess is not Emacs executing a lisp form.") +(defvar async-callback-value nil) +(defvar async-callback-value-set nil) +(defvar async-current-process nil) +(defvar async--procvar nil) +(defvar async-read-marker nil + "Position from which we read the last message packet. + +Message packets are delivered from client line-by-line as base64 +encoded strings.") +(defvar async-child-init nil + "Initialisation file for async child Emacs. + +If defined this allows for an init file to setup the child Emacs. It +should not be your normal init.el as that would likely load more +things that you require. It should limit itself to ensuring paths have +been setup so any async code can load libraries you expect.") + +;; For emacs<29 (only exists in emacs-29+). +(defvar print-symbols-bare) + +(defun async--purecopy (object) + "Remove text properties in OBJECT. + +Argument OBJECT may be a list or a string, if anything else it +is returned unmodified." + (cond ((stringp object) + (substring-no-properties object)) + ((consp object) + (cl-loop for elm in object + ;; A string. + if (stringp elm) + collect (substring-no-properties elm) + else + ;; Proper lists. + if (and (consp elm) (null (cdr (last elm)))) + collect (async--purecopy elm) + else + ;; Dotted lists. + ;; We handle here only dotted list where car and cdr + ;; are atoms i.e. (x . y) and not (x . (x . y)) or + ;; (x . (x y)) which should fit most cases. + if (and (consp elm) (cdr (last elm))) + collect (let ((key (car elm)) + (val (cdr elm))) + (cons (if (stringp key) + (substring-no-properties key) + key) + (if (stringp val) + (substring-no-properties val) + val))) + else + collect elm)) + (t object))) + +(defun async-inject-variables + (include-regexp &optional predicate exclude-regexp noprops) + "Return a `setq' form that replicates part of the calling environment. + +It sets the value for every variable matching INCLUDE-REGEXP and +also PREDICATE. It will not perform injection for any variable +matching EXCLUDE-REGEXP (if present) or representing a `syntax-table' +i.e. ending by \"-syntax-table\". +When NOPROPS is non nil it tries to strip out text properties of each +variable's value with `async-variables-noprops-function'. + +It is intended to be used as follows: + + (async-start + \\=`(lambda () + (require \\='smtpmail) + (with-temp-buffer + (insert ,(buffer-substring-no-properties (point-min) (point-max))) + ;; Pass in the variable environment for smtpmail + ,(async-inject-variables \"\\\\=`\\(smtpmail\\|\\(user-\\)?mail\\)-\") + (smtpmail-send-it))) + \\='ignore)" + `(setq + ,@(let (bindings) + (mapatoms + (lambda (sym) + (let* ((sname (and (boundp sym) (symbol-name sym))) + (value (and sname (symbol-value sym)))) + (when (and sname + (or (null include-regexp) + (string-match include-regexp sname)) + (or (null exclude-regexp) + (not (string-match exclude-regexp sname))) + (not (string-match "-syntax-table\\'" sname))) + (unless (or (stringp value) + (memq value '(nil t)) + (numberp value) + (vectorp value)) + (setq value `(quote ,value))) + (when noprops + (setq value (funcall async-variables-noprops-function + value))) + (when (or (null predicate) + (funcall predicate sym)) + (setq bindings (cons value bindings) + bindings (cons sym bindings))))))) + bindings))) + +(defalias 'async-inject-environment 'async-inject-variables) + +(defun async-handle-result (func result buf) + (if (null func) + (progn + (set (make-local-variable 'async-callback-value) result) + (set (make-local-variable 'async-callback-value-set) t)) + (unwind-protect + (if (and (listp result) + (eq 'async-signal (nth 0 result))) + (signal (car (nth 1 result)) + (cdr (nth 1 result))) + (funcall func result)) + (unless async-debug + (kill-buffer buf))))) + +(defun async-when-done (proc &optional _change) + "Process sentinel used to retrieve the value from the child process." + (when (eq 'exit (process-status proc)) + (with-current-buffer (process-buffer proc) + (let ((async-current-process proc)) + (if (= 0 (process-exit-status proc)) + (if async-callback-for-process + (if async-callback + (prog1 + (funcall async-callback proc) + (unless async-debug + ;; we need to check this because theoretically + ;; `async-callback' could've killed it already + (when (buffer-live-p (process-buffer proc)) + (kill-buffer (process-buffer proc))))) + (set (make-local-variable 'async-callback-value) proc) + (set (make-local-variable 'async-callback-value-set) t)) + ;; Maybe strip out unreadable "#"; They are replaced by + ;; empty string unless they are prefixing a special + ;; object like a marker. See issue #145. + (widen) + (goto-char (point-min)) + (save-excursion + ;; Transform markers in list like + ;; (marker (moves after insertion) at 2338 in + ;; test\.org) so that remap text properties function + ;; can parse it to restitute marker. + (while (re-search-forward "#<\\([^>]*\\)>" nil t) + (replace-match (concat "(" (match-string 1) ")") t t))) + (while (re-search-forward "#(" nil t) + (replace-match "(" t t)) + (goto-char (point-max)) + (backward-sexp) + (let ((value (read (current-buffer)))) + (async-handle-result async-callback value (current-buffer)))) + (set (make-local-variable 'async-callback-value) + (list 'error + (format "Async process '%s' failed with exit code %d" + (process-name proc) (process-exit-status proc)))) + (set (make-local-variable 'async-callback-value-set) t)))))) + +(defun async-read-from-client (proc string) + "Process text from client process. + +The string chunks usually arrive in maximum of 4096 bytes, so a +long client message might be split into multiple calls of this +function. + +We use a marker `async-read-marker' to track the position of the +lasts complete line. Every time we get new input, we try to look +for newline, and if found, process the entire line and bump the +marker position to the end of this next line." + (with-current-buffer (process-buffer proc) + (goto-char (point-max)) + (save-excursion + (insert string)) + + (while (search-forward "\n" nil t) + (save-excursion + (save-restriction + (widen) + (narrow-to-region async-read-marker (point)) + (goto-char (point-min)) + (let (msg) + (condition-case nil + ;; It is safe to throw errors in the read because we + ;; send messages always on their own line, and they + ;; are always a base64 encoded string, so a message + ;; will always read. We will also ignore the rest + ;; of this line since there won't be anything + ;; interesting. + (while (setq msg (read (current-buffer))) + (let ((msg-decoded (ignore-errors (base64-decode-string msg)))) + (when msg-decoded + (setq msg-decoded (car (read-from-string msg-decoded))) + (when (and (listp msg-decoded) + (async-message-p msg-decoded) + async-callback) + (funcall async-callback msg-decoded))))) + ;; This is OK, we reached the end of the chunk subprocess sent + ;; at this time. + (invalid-read-syntax t) + (end-of-file t))) + (goto-char (point-max)) + (move-marker async-read-marker (point))))))) + +(defun async--receive-sexp (&optional stream) + ;; FIXME: Why use `utf-8-auto' instead of `utf-8-unix'? This is + ;; a communication channel over which we have complete control, + ;; so we get to choose exactly which encoding and EOL we use, isn't + ;; it? + ;; UPDATE: We use now `utf-8-emacs-unix' instead of `utf-8-auto' as + ;; recommended in bug#165. + (let ((sexp (decode-coding-string (base64-decode-string (read stream)) + 'utf-8-emacs-unix)) + ;; Parent expects UTF-8 encoded text. + (coding-system-for-write 'utf-8-emacs-unix)) + (if async-debug + (message "Received sexp {{{%s}}}" (pp-to-string sexp))) + (setq sexp (read sexp)) + (if async-debug + (message "Read sexp {{{%s}}}" (pp-to-string sexp))) + (eval sexp t))) + +(defun async--insert-sexp (sexp) + (let (print-level + print-length + (print-escape-nonascii t) + (print-circle t) + ;; Fix bug#153 in emacs-29 with symbol's positions. + (print-symbols-bare t)) + (prin1 sexp (current-buffer)) + ;; Just in case the string we're sending might contain EOF + (encode-coding-region (point-min) (point-max) 'utf-8-emacs-unix) + (base64-encode-region (point-min) (point-max) t) + (goto-char (point-min)) (insert ?\") + (goto-char (point-max)) (insert ?\" ?\n))) + +(defun async--transmit-sexp (process sexp) + (with-temp-buffer + (if async-debug + (message "Transmitting sexp {{{%s}}}" (pp-to-string sexp))) + (async--insert-sexp sexp) + (process-send-region process (point-min) (point-max)))) + +(defun async-batch-invoke () + "Called from the child Emacs process' command line." + ;; Make sure 'message' and 'prin1' encode stuff in UTF-8, as parent + ;; process expects. + (let ((coding-system-for-write 'utf-8-emacs-unix) + (args-left command-line-args-left)) + (setq async-in-child-emacs t + debug-on-error async-debug + command-line-args-left nil) + (condition-case-unless-debug err + (let ((ret (funcall + (async--receive-sexp (unless async-send-over-pipe + args-left))))) + ;; The newlines makes client messages more robust and also + ;; handle some weird line-buffering issues on windows. + ;; Sometimes, the last "chunk" was not read by the filter, + ;; so a newline here should force a buffer flush. + (princ "\n") + (prin1 ret) + (princ "\n")) + (error + (progn + (princ "\n") + (prin1 (list 'async-signal err)) + (princ "\n")))))) + +(defun async-ready (future) + "Query a FUTURE to see if it is ready. + +I.e., if no blocking would result from a call to `async-get' on that FUTURE." + (and (memq (process-status future) '(exit signal)) + (let ((buf (process-buffer future))) + (if (buffer-live-p buf) + (with-current-buffer buf + async-callback-value-set) + t)))) + +(defun async-wait (future) + "Wait for FUTURE to become ready." + (while (not (async-ready future)) + (sleep-for 0.05))) + +(defun async-get (future) + "Get the value from process FUTURE when it is ready. +FUTURE is returned by `async-start' or `async-start-process' when +its FINISH-FUNC is nil." + (and future (async-wait future)) + (let ((buf (process-buffer future))) + (when (buffer-live-p buf) + (with-current-buffer buf + (async-handle-result + #'identity async-callback-value (current-buffer)))))) + +(defun async-message-p (value) + "Return non-nil if VALUE is an async.el message packet." + (and (listp value) + (plist-get value :async-message))) + +(defun async-send (process-or-key &rest args) + "Send the given message to the asychronous child or parent Emacs. + +To send messages from the parent to a child, PROCESS-OR-KEY is +the child process object. ARGS is a plist. Example: + + (async-send proc :operation :load-file :file \"this file\") + +To send messages from the child to the parent, PROCESS-OR-KEY is +the first key of the plist, ARGS is a value followed by +optionally more key-value pairs. Example: + + (async-send :status \"finished\" :file-size 123)" + (let ((args (append args '(:async-message t)))) + (if async-in-child-emacs + ;; `princ' because async--insert-sexp already quotes everything. + (princ + (with-temp-buffer + (async--insert-sexp (cons process-or-key args)) + ;; always make sure that one message package has its own + ;; line as there can be any random debug garbage printed + ;; above it. + (concat "\n" (buffer-string)))) + (async--transmit-sexp process-or-key (list 'quote args))))) + +(defun async-receive () + "Receive message from parent Emacs. + +The child process blocks until a message is received. + +Message is a plist with one key :async-message set to t always +automatically added to signify this plist is an async message. + +You can use `async-message-p' to test if the payload was a +message. + +Use + + (let ((msg (async-receive))) ...) + +to read and process a message." + (async--receive-sexp)) + +;;;###autoload +(defun async-start-process (name program finish-func &rest program-args) + "Start the executable PROGRAM asynchronously named NAME. See `async-start'. +PROGRAM is passed PROGRAM-ARGS, calling FINISH-FUNC with the +process object when done. If FINISH-FUNC is nil, the future +object will return the process object when the program is +finished. Set DEFAULT-DIRECTORY to change PROGRAM's current +working directory." + (let* ((buf (generate-new-buffer (concat "*" name "*"))) + (buf-err (generate-new-buffer (concat "*" name ":err*"))) + (proc (let ((process-connection-type nil)) + (make-process + :name name + :buffer buf + :stderr buf-err + :command (cons program program-args))))) + (set-process-sentinel + (get-buffer-process buf-err) + (lambda (proc _change) + (unless (or async-debug (process-live-p proc)) + (kill-buffer (process-buffer proc))))) + (with-current-buffer buf + (set (make-local-variable 'async-callback) finish-func) + (set (make-local-variable 'async-read-marker) + (set-marker (make-marker) (point-min) buf)) + (set-marker-insertion-type async-read-marker nil) + + (set-process-sentinel proc #'async-when-done) + (set-process-filter proc #'async-read-from-client) + (unless (string= name "emacs") + (set (make-local-variable 'async-callback-for-process) t)) + proc))) + +(defvar async-quiet-switch "-Q" + "The Emacs parameter to use to call emacs without config. +Can be one of \"-Q\" or \"-q\". +Default is \"-Q\" but it is sometimes useful to use \"-q\" to have a +enhanced config or some more variables loaded.") + +(defun async--emacs-program-args (&optional sexp) + "Return a list of arguments for invoking the child Emacs." + ;; Using `locate-library' ensure we use the right file + ;; when the .elc have been deleted. + (let ((args (list async-quiet-switch "-l" (locate-library "async")))) + (when async-child-init + (setq args (append args (list "-l" async-child-init)))) + (append args (list "-batch" "-f" "async-batch-invoke" + (if sexp + (with-temp-buffer + (async--insert-sexp (list 'quote sexp)) + (buffer-string)) + ""))))) + +;;;###autoload +(defun async-start (start-func &optional finish-func) + "Execute START-FUNC (often a lambda) in a subordinate Emacs process. +When done, the return value is passed to FINISH-FUNC. Example: + + (async-start + ;; What to do in the child process + (lambda () + (message \"This is a test\") + (sleep-for 3) + 222) + + ;; What to do when it finishes + (lambda (result) + (message \"Async process done, result should be 222: %s\" + result))) + +If you call `async-send' from a child process, the message will +be also passed to the FINISH-FUNC. You can test RESULT to see if +it is a message by using `async-message-p'. If nil, it means +this is the final result. Example of the FINISH-FUNC: + + (lambda (result) + (if (async-message-p result) + (message \"Received a message from child process: %s\" result) + (message \"Async process done, result: %s\" result))) + +If FINISH-FUNC is nil or missing, a future is returned that can +be inspected using `async-get', blocking until the value is +ready. Example: + + (let ((proc (async-start + ;; What to do in the child process + (lambda () + (message \"This is a test\") + (sleep-for 3) + 222)))) + + (message \"I'm going to do some work here\") ;; .... + + (message \"Waiting on async process, result should be 222: %s\" + (async-get proc))) + +If you don't want to use a callback, and you don't care about any +return value from the child process, pass the `ignore' symbol as +the second argument (if you don't, and never call `async-get', it +will leave *emacs* process buffers hanging around): + + (async-start + (lambda () + (delete-file \"a remote file on a slow link\" nil)) + \\='ignore) + +Special case: +If the output of START-FUNC is a string with properties +e.g. (buffer-string) RESULT will be transformed in a list where the +car is the string itself (without props) and the cdr the rest of +properties, this allows using in FINISH-FUNC the string without +properties and then apply the properties in cdr to this string (if +needed). +Properties handling special objects like markers are returned as +list to allow restoring them later. +See for more infos. + +Note: Even when FINISH-FUNC is present, a future is still +returned except that it yields no value (since the value is +passed to FINISH-FUNC). Call `async-get' on such a future always +returns nil. It can still be useful, however, as an argument to +`async-ready' or `async-wait'." + (let ((sexp start-func) + ;; Subordinate Emacs will send text encoded in UTF-8. + (coding-system-for-read 'utf-8-emacs-unix)) + (setq async--procvar + (apply 'async-start-process + "emacs" (file-truename + (expand-file-name invocation-name + invocation-directory)) + finish-func + (async--emacs-program-args (if (not async-send-over-pipe) sexp)))) + + (if async-send-over-pipe + (async--transmit-sexp async--procvar (list 'quote sexp))) + async--procvar)) + +(defmacro async-sandbox(func) + "Evaluate FUNC in a separate Emacs process, synchronously." + `(async-get (async-start ,func))) + +(defun async--fold-left (fn forms bindings) + (let ((res forms)) + (dolist (binding bindings) + (setq res (funcall fn res + (if (listp binding) + binding + (list binding))))) + res)) + +(defmacro async-let (bindings &rest forms) + "Implements `let', but each binding is established asynchronously. +For example: + + (async-let ((x (foo)) + (y (bar))) + (message \"%s %s\" x y)) + + expands to ==> + + (async-start (foo) + (lambda (x) + (async-start (bar) + (lambda (y) + (message \"%s %s\" x y)))))" + (declare (indent 1)) + (async--fold-left + (lambda (acc binding) + (let ((fun (pcase (cadr binding) + ((and (pred functionp) f) f) + (f `(lambda () ,f))))) + `(async-start ,fun + (lambda (,(car binding)) + ,acc)))) + `(progn ,@forms) + (reverse bindings))) + +(provide 'async) + +;;; async.el ends here diff --git a/org/elpa/async-20230323.643/dired-async.el b/org/elpa/async-20230323.643/dired-async.el new file mode 100644 index 0000000..9884852 --- /dev/null +++ b/org/elpa/async-20230323.643/dired-async.el @@ -0,0 +1,455 @@ +;;; dired-async.el --- Asynchronous dired actions -*- lexical-binding: t -*- + +;; Copyright (C) 2012-2019 Free Software Foundation, Inc. + +;; Authors: John Wiegley +;; Thierry Volpiatto + +;; Keywords: dired async network +;; X-URL: https://github.com/jwiegley/emacs-async + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; This file provide a redefinition of `dired-create-file' function, +;; performs copies, moves and all what is handled by `dired-create-file' +;; in the background using a slave Emacs process, +;; by means of the async.el module. +;; To use it, put this in your .emacs: + +;; (dired-async-mode 1) + +;; This will enable async copy/rename etc... +;; in dired and helm. + +;;; Code: + +(require 'cl-lib) +(require 'dired-aux) +(require 'async) + +(eval-when-compile + (defvar async-callback)) + +(defgroup dired-async nil + "Copy rename files asynchronously from dired." + :group 'dired) + +(defcustom dired-async-env-variables-regexp + "\\`\\(tramp-\\(default\\|connection\\|remote\\)\\|ange-ftp\\)-.*" + "Variables matching this regexp will be loaded on Child Emacs." + :type 'regexp) + +(defcustom dired-async-message-function 'dired-async-mode-line-message + "Function to use to notify result when operation finish. +Should take same args as `message'." + :type 'function) + +(defcustom dired-async-log-file "/tmp/dired-async.log" + "File use to communicate errors from Child Emacs to host Emacs." + :type 'string) + +(defcustom dired-async-mode-lighter '(:eval + (when (eq major-mode 'dired-mode) + " Async")) + "Mode line lighter used for `dired-async-mode'." + :risky t + :type 'sexp) + +(defcustom dired-async-skip-fast nil + "If non-nil, skip async for fast operations. +Same device renames and copying and renaming files smaller than +`dired-async-small-file-max' are considered fast." + :risky t + :type 'boolean) + +(defcustom dired-async-small-file-max 5000000 + "Files smaller than this in bytes are considered fast to copy +or rename for `dired-async-skip-fast'." + :risky t + :type 'integer) + +(defface dired-async-message + '((t (:foreground "yellow"))) + "Face used for mode-line message.") + +(defface dired-async-failures + '((t (:foreground "red"))) + "Face used for mode-line message.") + +(defface dired-async-mode-message + '((t (:foreground "Gold"))) + "Face used for `dired-async--modeline-mode' lighter.") + +(define-minor-mode dired-async--modeline-mode + "Notify mode-line that an async process run." + :global t + :lighter (:eval (propertize (format " [%s Async job(s) running]" + (length (dired-async-processes))) + 'face 'dired-async-mode-message)) + (unless dired-async--modeline-mode + (let ((visible-bell t)) (ding)))) + +(defun dired-async-mode-line-message (text face &rest args) + "Notify end of operation in `mode-line'." + (message nil) + (let ((mode-line-format (concat + " " (propertize + (if args + (apply #'format text args) + text) + 'face face)))) + (force-mode-line-update) + (sit-for 3) + (force-mode-line-update))) + +(defun dired-async-processes () + (cl-loop for p in (process-list) + when (process-get p 'dired-async-process) + collect p)) + +(defun dired-async-kill-process () + (interactive) + (let* ((processes (dired-async-processes)) + (proc (car (last processes)))) + (and proc (delete-process proc)) + (unless (> (length processes) 1) + (dired-async--modeline-mode -1)))) + +(defun dired-async-after-file-create (total operation failures skipped) + "Callback function used for operation handled by `dired-create-file'." + (unless (dired-async-processes) + ;; Turn off mode-line notification + ;; only when last process end. + (dired-async--modeline-mode -1)) + (when operation + (if (file-exists-p dired-async-log-file) + (progn + (pop-to-buffer (get-buffer-create dired-log-buffer)) + (goto-char (point-max)) + (setq inhibit-read-only t) + (insert "Error: ") + (insert-file-contents dired-async-log-file) + (special-mode) + (shrink-window-if-larger-than-buffer) + (delete-file dired-async-log-file)) + (run-with-timer + 0.1 nil + (lambda () + ;; First send error messages. + (cond (failures + (funcall dired-async-message-function + "%s failed for %d of %d file%s -- See *Dired log* buffer" + 'dired-async-failures + (car operation) (length failures) + total (dired-plural-s total))) + (skipped + (funcall dired-async-message-function + "%s: %d of %d file%s skipped -- See *Dired log* buffer" + 'dired-async-failures + (car operation) (length skipped) total + (dired-plural-s total)))) + (when dired-buffers + (cl-loop for (_f . b) in dired-buffers + when (buffer-live-p b) + do (with-current-buffer b + (when (and (not (file-remote-p default-directory nil t)) + (file-exists-p default-directory)) + (revert-buffer nil t))))) + ;; Finally send the success message. + (funcall dired-async-message-function + "Asynchronous %s of %s on %s file%s done" + 'dired-async-message + (car operation) (cadr operation) + total (dired-plural-s total))))))) + +(defun dired-async-maybe-kill-ftp () + "Return a form to kill ftp process in child emacs." + (quote + (progn + (require 'cl-lib) + (let ((buf (cl-loop for b in (buffer-list) + thereis (and (string-match + "\\`\\*ftp.*" + (buffer-name b)) b)))) + (when buf (kill-buffer buf)))))) + +(defsubst dired-async--directory-p (attributes) + "Return non-nil if ATTRIBUTES is for a directory. +See `file-attributes'." + ;; Can also be a string for symlinks, so check for t explicitly. + (eq (file-attribute-type attributes) t)) + +(defsubst dired-async--same-device-p (f1 f2) + "Return non-nil if F1 and F2 have the same device number." + ;; file-attribute-device-number may be a cons cell, so use equal for + ;; testing (See Emacs bug/58446). + (equal (file-attribute-device-number (file-attributes f1)) + (file-attribute-device-number (file-attributes f2)))) + +(defun dired-async--small-file-p (file) + "Return non-nil if FILE is considered small. + +File is considered small if it size is smaller than +`dired-async-small-file-max'." + (let ((a (file-attributes file))) + ;; Directories are always large since we can't easily figure out + ;; their total size. + (and (not (dired-async--directory-p a)) + (< (file-attribute-size a) dired-async-small-file-max)))) + +(defun dired-async--skip-async-p (file-creator file name-constructor) + "Return non-nil if we should skip async for FILE. +See `dired-create-files' for FILE-CREATOR and NAME-CONSTRUCTOR." + ;; Skip async for small files. + (or (dired-async--small-file-p file) + ;; Also skip async for same device renames. + (and (eq file-creator 'dired-rename-file) + (let ((new (funcall name-constructor file))) + (dired-async--same-device-p file (file-name-directory new)))))) + +(defun dired-async--smart-create-files (old-func file-creator + operation fn-list name-constructor + &optional marker-char) + "Around advice for `dired-create-files'. +Uses async like `dired-async-create-files' but skips certain fast +cases if `dired-async-skip-fast' is non-nil." + (let (async-list quick-list) + (if (or (eq file-creator 'backup-file) + (null dired-async-skip-fast)) + (setq async-list fn-list) + (dolist (old fn-list) + (if (dired-async--skip-async-p file-creator old name-constructor) + (push old quick-list) + (push old async-list)))) + (when async-list + (dired-async-create-files + file-creator operation (nreverse async-list) + name-constructor marker-char)) + (when quick-list + (funcall old-func file-creator operation + (nreverse quick-list) name-constructor marker-char)))) + +(defvar overwrite-query) +(defun dired-async-create-files (file-creator operation fn-list name-constructor + &optional _marker-char) + "Same as `dired-create-files' but asynchronous. + +See `dired-create-files' for the behavior of arguments." + (setq overwrite-query nil) + (let ((total (length fn-list)) + failures async-fn-list skipped callback + async-quiet-switch) + (let (to) + (dolist (from fn-list) + (setq to (funcall name-constructor from)) + (if (and (equal to from) + (null (eq file-creator 'backup-file))) + (progn + (setq to nil) + (dired-log "Cannot %s to same file: %s\n" + (downcase operation) from))) + (if (not to) + (setq skipped (cons (dired-make-relative from) skipped)) + (let* ((overwrite (and (null (eq file-creator 'backup-file)) + (file-exists-p to))) + (dired-overwrite-confirmed ; for dired-handle-overwrite + (and overwrite + (let ((help-form `(format "\ +Type SPC or `y' to overwrite file `%s', +DEL or `n' to skip to next, +ESC or `q' to not overwrite any of the remaining files, +`!' to overwrite all remaining files with no more questions." ,to))) + (dired-query 'overwrite-query "Overwrite `%s'?" to))))) + ;; Handle the `dired-copy-file' file-creator specially + ;; When copying a directory to another directory or + ;; possibly to itself or one of its subdirectories. + ;; e.g "~/foo/" => "~/test/" + ;; or "~/foo/" =>"~/foo/" + ;; or "~/foo/ => ~/foo/bar/") + ;; In this case the 'name-constructor' have set the destination + ;; TO to "~/test/foo" because the old emacs23 behavior + ;; of `copy-directory' was to not create the subdirectory + ;; and instead copy the contents. + ;; With the new behavior of `copy-directory' + ;; (similar to the `cp' shell command) we don't + ;; need such a construction of the target directory, + ;; so modify the destination TO to "~/test/" instead of "~/test/foo/". + (let ((destname (file-name-directory to))) + (when (and (file-directory-p from) + (file-directory-p to) + (eq file-creator 'dired-copy-file)) + (setq to destname)) + ;; If DESTNAME is a subdirectory of FROM, not a symlink, + ;; and the method in use is copying, signal an error. + (and (eq t (car (file-attributes destname))) + (eq file-creator 'dired-copy-file) + (file-in-directory-p destname from) + (error "Cannot copy `%s' into its subdirectory `%s'" + from to))) + (if overwrite + (or (and dired-overwrite-confirmed + (push (cons from to) async-fn-list)) + (progn + (push (dired-make-relative from) failures) + (dired-log "%s `%s' to `%s' failed\n" + operation from to))) + (push (cons from to) async-fn-list))))) + ;; Fix tramp issue #80 with emacs-26, use "-q" only when needed. + (setq async-quiet-switch + (if (and (boundp 'tramp-cache-read-persistent-data) + async-fn-list + (cl-loop for (_from . to) in async-fn-list + thereis (file-remote-p to))) + "-q" "-Q")) + ;; When failures have been printed to dired log add the date at bob. + (when (or failures skipped) (dired-log t)) + ;; When async-fn-list is empty that's mean only one file + ;; had to be copied and user finally answer NO. + ;; In this case async process will never start and callback + ;; will have no chance to run, so notify failures here. + (unless async-fn-list + (cond (failures + (funcall dired-async-message-function + "%s failed for %d of %d file%s -- See *Dired log* buffer" + 'dired-async-failures + operation (length failures) + total (dired-plural-s total))) + (skipped + (funcall dired-async-message-function + "%s: %d of %d file%s skipped -- See *Dired log* buffer" + 'dired-async-failures + operation (length skipped) total + (dired-plural-s total))))) + ;; Setup callback. + (setq callback + (lambda (&optional _ignore) + (dired-async-after-file-create + total (list operation (length async-fn-list)) failures skipped) + (when (string= (downcase operation) "rename") + (cl-loop for (file . to) in async-fn-list + for bf = (get-file-buffer file) + for destp = (file-exists-p to) + do (and bf destp + (with-current-buffer bf + (set-visited-file-name to t t)))))))) + ;; Start async process. + (when async-fn-list + (process-put + (async-start `(lambda () + (require 'cl-lib) (require 'dired-aux) (require 'dired-x) + ,(async-inject-variables dired-async-env-variables-regexp) + (let ((dired-recursive-copies (quote always)) + (dired-copy-preserve-time + ,dired-copy-preserve-time)) + (setq overwrite-backup-query nil) + ;; Inline `backup-file' as long as it is not + ;; available in emacs. + (defalias 'backup-file + ;; Same feature as "cp -f --backup=numbered from to" + ;; Symlinks are copied as file from source unlike + ;; `dired-copy-file' which is same as cp -d. + ;; Directories are omitted. + (lambda (from to ok) + (cond ((file-directory-p from) (ignore)) + (t (let ((count 0)) + (while (let ((attrs (file-attributes to))) + (and attrs (null (nth 0 attrs)))) + (cl-incf count) + (setq to (concat (file-name-sans-versions to) + (format ".~%s~" count))))) + (condition-case err + (copy-file from to ok dired-copy-preserve-time) + (file-date-error + (dired-log "Can't set date on %s:\n%s\n" from err))))))) + ;; Now run the FILE-CREATOR function on files. + (cl-loop with fn = (quote ,file-creator) + for (from . dest) in (quote ,async-fn-list) + do (condition-case err + (funcall fn from dest t) + (file-error + (dired-log "%s: %s\n" (car err) (cdr err)) + nil))) + (when (get-buffer dired-log-buffer) + (dired-log t) + (with-current-buffer dired-log-buffer + (write-region (point-min) (point-max) + ,dired-async-log-file)))) + ,(dired-async-maybe-kill-ftp)) + callback) + 'dired-async-process t) + ;; Run mode-line notifications while process running. + (dired-async--modeline-mode 1) + (message "%s proceeding asynchronously..." operation)))) + +(defvar wdired-use-interactive-rename) +(defun dired-async-wdired-do-renames (old-fn &rest args) + ;; Perhaps a better fix would be to ask for renaming BEFORE starting + ;; OLD-FN when `wdired-use-interactive-rename' is non-nil. For now + ;; just bind it to nil to ensure no questions will be asked between + ;; each rename. + (let (wdired-use-interactive-rename) + (apply old-fn args))) + +;;;###autoload +(define-minor-mode dired-async-mode + "Do dired actions asynchronously." + :lighter dired-async-mode-lighter + :global t + (if dired-async-mode + (progn + (advice-add 'dired-create-files :around #'dired-async--smart-create-files) + (advice-add 'wdired-do-renames :around #'dired-async-wdired-do-renames)) + (progn + (advice-remove 'dired-create-files #'dired-async--smart-create-files) + (advice-remove 'wdired-do-renames #'dired-async-wdired-do-renames)))) + +(defmacro dired-async--with-async-create-files (&rest body) + "Evaluate BODY with ‘dired-create-files’ set to ‘dired-async-create-files’." + (declare (indent 0)) + `(cl-letf (((symbol-function 'dired-create-files) #'dired-async-create-files)) + ,@body)) + +;;;###autoload +(defun dired-async-do-copy (&optional arg) + "Run ‘dired-do-copy’ asynchronously." + (interactive "P") + (dired-async--with-async-create-files + (dired-do-copy arg))) + +;;;###autoload +(defun dired-async-do-symlink (&optional arg) + "Run ‘dired-do-symlink’ asynchronously." + (interactive "P") + (dired-async--with-async-create-files + (dired-do-symlink arg))) + +;;;###autoload +(defun dired-async-do-hardlink (&optional arg) + "Run ‘dired-do-hardlink’ asynchronously." + (interactive "P") + (dired-async--with-async-create-files + (dired-do-hardlink arg))) + +;;;###autoload +(defun dired-async-do-rename (&optional arg) + "Run ‘dired-do-rename’ asynchronously." + (interactive "P") + (dired-async--with-async-create-files + (dired-do-rename arg))) + +(provide 'dired-async) + +;;; dired-async.el ends here diff --git a/org/elpa/async-20230323.643/smtpmail-async.el b/org/elpa/async-20230323.643/smtpmail-async.el new file mode 100644 index 0000000..404b6e0 --- /dev/null +++ b/org/elpa/async-20230323.643/smtpmail-async.el @@ -0,0 +1,71 @@ +;;; smtpmail-async.el --- Send e-mail with smtpmail.el asynchronously -*- lexical-binding: t -*- + +;; Copyright (C) 2012-2022 Free Software Foundation, Inc. + +;; Author: John Wiegley +;; Created: 18 Jun 2012 + +;; Keywords: email async +;; X-URL: https://github.com/jwiegley/emacs-async + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; Send e-mail with smtpmail.el asynchronously. To use: +;; +;; (require 'smtpmail-async) +;; +;; (setq send-mail-function 'async-smtpmail-send-it +;; message-send-mail-function 'async-smtpmail-send-it) +;; +;; This assumes you already have smtpmail.el working. + +;;; Code: + +(defgroup smtpmail-async nil + "Send e-mail with smtpmail.el asynchronously" + :group 'smptmail) + +(require 'async) +(require 'smtpmail) +(require 'message) + +(defvar async-smtpmail-before-send-hook nil + "Hook running in the child emacs in `async-smtpmail-send-it'. +It is called just before calling `smtpmail-send-it'.") + +(defun async-smtpmail-send-it () + (let ((to (message-field-value "To")) + (buf-content (buffer-substring-no-properties + (point-min) (point-max)))) + (message "Delivering message to %s..." to) + (async-start + `(lambda () + (require 'smtpmail) + (with-temp-buffer + (insert ,buf-content) + (set-buffer-multibyte nil) + ;; Pass in the variable environment for smtpmail + ,(async-inject-variables + "\\`\\(smtpmail\\|async-smtpmail\\|\\(user-\\)?mail\\)-\\|auth-sources\\|epg\\|nsm" + nil "\\`\\(mail-header-format-function\\|smtpmail-address-buffer\\|mail-mode-abbrev-table\\)") + (run-hooks 'async-smtpmail-before-send-hook) + (smtpmail-send-it))) + (lambda (&optional _ignore) + (message "Delivering message to %s...done" to))))) + +(provide 'smtpmail-async) + +;;; smtpmail-async.el ends here diff --git a/org/elpa/burly-20221024.2019/burly-autoloads.el b/org/elpa/burly-20221024.2019/burly-autoloads.el new file mode 100644 index 0000000..111a532 --- /dev/null +++ b/org/elpa/burly-20221024.2019/burly-autoloads.el @@ -0,0 +1,105 @@ +;;; burly-autoloads.el --- automatically extracted autoloads -*- lexical-binding: t -*- +;; +;;; Code: + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + + +;;;### (autoloads nil "burly" "burly.el" (0 0 0 0)) +;;; Generated autoloads from burly.el + +(autoload 'burly-open-last-bookmark "burly" "\ +Open the last-opened Burly bookmark. +Helpful for, e.g. quickly restoring an overview while working on +a project." t nil) + +(autoload 'burly-kill-buffer-url "burly" "\ +Copy BUFFER's URL to the kill ring. + +\(fn BUFFER)" t nil) + +(autoload 'burly-kill-frames-url "burly" "\ +Copy current frameset's URL to the kill ring." t nil) + +(autoload 'burly-kill-windows-url "burly" "\ +Copy current frame's window configuration URL to the kill ring." t nil) + +(autoload 'burly-open-url "burly" "\ +Open Burly URL. + +\(fn URL)" t nil) + +(autoload 'burly-bookmark-frames "burly" "\ +Bookmark the current frames as NAME. + +\(fn NAME)" t nil) + +(autoload 'burly-bookmark-windows "burly" "\ +Bookmark the current frame's window configuration as NAME. + +\(fn NAME)" t nil) + +(autoload 'burly-open-bookmark "burly" "\ +Restore a window configuration to the current frame from a Burly BOOKMARK. + +\(fn BOOKMARK)" t nil) + +(autoload 'burly-bookmark-handler "burly" "\ +Handler function for Burly BOOKMARK. + +\(fn BOOKMARK)" nil nil) + +(register-definition-prefixes "burly" '("burly-")) + +;;;*** + +;;;### (autoloads nil "burly-tabs" "burly-tabs.el" (0 0 0 0)) +;;; Generated autoloads from burly-tabs.el + +(defvar burly-tabs-mode nil "\ +Non-nil if Burly-Tabs mode is enabled. +See the `burly-tabs-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `burly-tabs-mode'.") + +(custom-autoload 'burly-tabs-mode "burly-tabs" nil) + +(autoload 'burly-tabs-mode "burly-tabs" "\ +Integrate Burly with `tab-bar-mode'. +When active, Burly bookmarks are opened in new tabs and named +accordingly. + +This is a minor mode. If called interactively, toggle the +`Burly-Tabs mode' mode. If the prefix argument is positive, +enable the mode, and if it is zero or negative, disable the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `(default-value \\='burly-tabs-mode)'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +\(fn &optional ARG)" t nil) + +(register-definition-prefixes "burly-tabs" '("burly-")) + +;;;*** + +;;;### (autoloads nil nil ("burly-pkg.el") (0 0 0 0)) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; coding: utf-8 +;; End: +;;; burly-autoloads.el ends here diff --git a/org/elpa/burly-20221024.2019/burly-pkg.el b/org/elpa/burly-20221024.2019/burly-pkg.el new file mode 100644 index 0000000..d468d34 --- /dev/null +++ b/org/elpa/burly-20221024.2019/burly-pkg.el @@ -0,0 +1,13 @@ +(define-package "burly" "20221024.2019" "Save and restore frame/window configurations with buffers" + '((emacs "27.1") + (map "2.1")) + :commit "f570fa87ee72a451f535cfb038d81798a01a7e20" :authors + '(("Adam Porter" . "adam@alphapapa.net")) + :maintainer + '("Adam Porter" . "adam@alphapapa.net") + :keywords + '("convenience") + :url "https://github.com/alphapapa/burly.el") +;; Local Variables: +;; no-byte-compile: t +;; End: diff --git a/org/elpa/burly-20221024.2019/burly-tabs.el b/org/elpa/burly-20221024.2019/burly-tabs.el new file mode 100644 index 0000000..65ca18d --- /dev/null +++ b/org/elpa/burly-20221024.2019/burly-tabs.el @@ -0,0 +1,90 @@ +;;; burly-tabs.el --- Burly's support for tab-bar -*- lexical-binding: t; -*- + +;; Copyright (C) 2022 Adam Porter + +;; Author: Adam Porter +;; Keywords: tab-bar, tabs, frames + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; This library provides support for `tab-bar-mode'. + +;;; Code: + +;; TODO: In Emacs 28, add an entry to the tab context menu. See +;; . + +;;;; Requirements + +(require 'cl-lib) +(require 'map) +(require 'tab-bar) + +(require 'burly) + +;;;; Commands + +;;;###autoload +(define-minor-mode burly-tabs-mode + "Integrate Burly with `tab-bar-mode'. +When active, Burly bookmarks are opened in new tabs and named +accordingly." + :global t + :group 'burly + (unless (version<= "28.1" emacs-version) + (user-error "`burly-tabs-mode' requires Emacs 28.1 or later")) + (if burly-tabs-mode + (progn + (advice-add #'burly--windows-set :before #'burly-tabs--windows-set-before-advice) + (advice-add #'burly--windows-set :after #'burly-tabs--windows-set-after-advice)) + ;; Disable mode. + (advice-remove #'burly--windows-set #'burly-tabs--windows-set-before-advice) + (advice-remove #'burly--windows-set #'burly-tabs--windows-set-after-advice))) + +(cl-defun burly-tabs-reset-tab (&optional (tab (tab-bar--current-tab-find))) + "Reset TAB to its saved configuration. +Resets TAB to the Burly bookmark that it was created from." + (interactive) + (pcase-let* ((`(,_ . ,(map burly-bookmark-name)) tab)) + (unless burly-bookmark-name + (user-error "Tab has no associated Burly bookmark (`burly-tabs-mode' must be enabled when opening a bookmark)")) + (burly-open-bookmark burly-bookmark-name))) + +(defalias 'burly-reset-tab #'burly-tabs-reset-tab) + +;;;; Functions + +(defun burly-tabs--windows-set-before-advice (&rest _ignore) + "Cause bookmark to be opened in a tab by that name. +If a tab already exists named the value of +`burly-opened-bookmark-name', select it; otherwise call +`tab-bar-new-tab'. To be used as advice to +`burly-open-bookmark'." + (if (tab-bar--tab-index-by-name burly-opened-bookmark-name) + (tab-bar-select-tab-by-name burly-opened-bookmark-name) + (tab-bar-new-tab))) + +(defun burly-tabs--windows-set-after-advice (&rest _ignore) + "Set current tab's `burly-bookmark-name' to BOOKMARK-NAME. +To be used as advice to `burly--windows-set'." + (tab-rename burly-opened-bookmark-name) + (let ((current-tab (tab-bar--current-tab-find))) + (setf (alist-get 'burly-bookmark-name (cdr current-tab)) + burly-opened-bookmark-name))) + +(provide 'burly-tabs) + +;;; burly-tabs.el ends here diff --git a/org/elpa/burly-20221024.2019/burly.el b/org/elpa/burly-20221024.2019/burly.el new file mode 100644 index 0000000..2f57b06 --- /dev/null +++ b/org/elpa/burly-20221024.2019/burly.el @@ -0,0 +1,590 @@ +;;; burly.el --- Save and restore frame/window configurations with buffers -*- lexical-binding: t; -*- + +;; Copyright (C) 2020 Adam Porter + +;; Author: Adam Porter +;; URL: https://github.com/alphapapa/burly.el +;; Version: 0.3-pre +;; Package-Requires: ((emacs "27.1") (map "2.1")) +;; Keywords: convenience + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; This package provides tools to save and restore frame and window +;; configurations in Emacs, including buffers that may not be live +;; anymore. In this way, it's like a lightweight "workspace" manager, +;; allowing you to easily restore one or more frames, including their +;; windows, the windows' layout, and their buffers. + +;; Internally it uses Emacs's bookmarks system to restore buffers to +;; their previous contents and location. This provides power and +;; extensibility, since many major modes already integrate with +;; Emacs's bookmarks system. However, in case a mode's bookmarking +;; function isn't satisfactory, Burly allows the user to customize +;; buffer-restoring functions for specific modes. + +;; For Org mode, Burly provides such custom functions so that narrowed +;; and indirect Org buffers are properly restored, and headings are +;; located by outline path in case they've moved since a bookmark was +;; made (the org-bookmark-heading package also provides this through +;; the Emacs bookmark system, but users may not have it installed, and +;; the functionality is too useful to not include here by default). + +;; Internally, buffers and window configurations are also encoded as +;; URLs, and users may also save and open those URLs instead of using +;; Emacs bookmarks. (The name "Burly" comes from "buffer URL.") + +;;; Code: + +;;;; Requirements + +(require 'bookmark) +(require 'cl-lib) +(require 'map) +(require 'subr-x) +(require 'thingatpt) +(require 'url-parse) +(require 'url-util) + +;;;; Variables + +(defvar burly--window-state nil + "Used to work around `bookmark--jump-via' affecting window configuration.") + +(defvar burly-opened-bookmark-name nil + "The name of the last bookmark opened by Burly.") + +;;;; Customization + +(defgroup burly nil + "Save and restore window configurations and their buffers." + :group 'convenience + :link '(url-link "https://github.com/alphapapa/burly.el") + :link '(custom-manual "(Burly)Usage")) + +(defcustom burly-bookmark-prefix "Burly: " + "Prefix string for the name of new Burly bookmarks." + :type 'string) + +(defcustom burly-major-mode-alist + (list (cons 'org-mode + (list (cons 'make-url-fn #'burly--org-mode-buffer-url) + (cons 'follow-url-fn #'burly-follow-url-org-mode)))) + "Alist mapping major modes to the appropriate Burly functions." + :type '(alist :key-type symbol + :value-type (set (cons (const make-url-fn) (function :tag "Make-URL function")) + (cons (const follow-url-fn) (function :tag "Follow-URL function"))))) + +(defcustom burly-frameset-filter-alist '((name . nil)) + "Alist of frame parameters and filtering functions. +See variable `frameset-filter-alist'." + :type '(alist :key-type (symbol :tag "Frame parameter") + :value-type (choice (const :tag "Always copied" nil) + (const :tag "Never copied" :never) + (function :tag "Filter function")))) + +(defcustom burly-window-persistent-parameters + (list (cons 'burly-url 'writable) + (cons 'header-line-format 'writable) + (cons 'mode-line-format 'writable) + (cons 'tab-line-format 'writable) + (cons 'no-other-window 'writable) + (cons 'no-delete-other-windows 'writable) + (cons 'window-preserved-size 'writable) + (cons 'window-side 'writable) + (cons 'window-slot 'writable)) + "Additional window parameters to persist. +See Info node `(elisp)Window Parameters'. See also option +`burly-set-window-persistent-parameters'." + :type '(alist :key-type (symbol :tag "Window parameter") + :value-type (choice (const :tag "Not saved" nil) + (const :tag "Saved" writable)))) + +(defcustom burly-set-window-persistent-parameters t + "Sync `window-persistent-parameters' with `burly' option. +When this option is non-nil, `window-persistent-parameters' is +set to the value of `burly-window-persistent-parameters' when +Burly restores a window configuration. + +By default, `window-persistent-parameters' does not save many of +the parameters that are in the default value of +`burly-window-persistent-parameters', which causes, e.g. a +built-in command like `window-toggle-side-windows' to not persist +such parameters when side windows are toggled (which could, +e.g. cause a window's `mode-line-format' to not persist). So +enabling this option solves that. + +Note: When this option is non-nil, +`burly-window-persistent-parameters' should be set heeding the +warning in the manual about not using the `writable' value for +parameters whose values do not have a read syntax." + :type 'boolean) + +;;;; Commands + +;;;###autoload +(defun burly-open-last-bookmark () + "Open the last-opened Burly bookmark. +Helpful for, e.g. quickly restoring an overview while working on +a project." + (interactive) + (unless burly-opened-bookmark-name + (user-error "Use command `burly-open-bookmark' first")) + (burly-open-bookmark burly-opened-bookmark-name)) + +;;;###autoload +(defun burly-kill-buffer-url (buffer) + "Copy BUFFER's URL to the kill ring." + (interactive "bBuffer: ") + (let ((url (burly-buffer-url (get-buffer buffer)))) + (kill-new url) + (message "%s" url))) + +;;;###autoload +(defun burly-kill-frames-url () + "Copy current frameset's URL to the kill ring." + (interactive) + (let ((url (burly-frames-url))) + (kill-new url) + (message "%s" url))) + +;;;###autoload +(defun burly-kill-windows-url () + "Copy current frame's window configuration URL to the kill ring." + (interactive) + (let ((url (burly-windows-url))) + (kill-new url) + (message "%s" url))) + +;;;###autoload +(defun burly-open-url (url) + "Open Burly URL." + ;; FIXME: If point is on an "emacs+burly..." URL, but it's after the "emacs+burly" + ;; part, `thing-at-point-url-at-point' doesn't pick up the whole URL. + (interactive (list (or (thing-at-point-url-at-point t) + (read-string "URL: ")))) + (cl-assert (string-prefix-p "emacs+burly+" url) t "burly-open-url: URL not an emacs+burly one:") + (pcase-let* ((urlobj (url-generic-parse-url url)) + ((cl-struct url type) urlobj) + (subtype (car (last (split-string type "+" 'omit-nulls))))) + (pcase-exhaustive subtype + ((or "bookmark" "file" "name") (pop-to-buffer (burly-url-buffer url))) + ("frames" (burly--frameset-restore urlobj)) + ("windows" (burly--windows-set urlobj))))) + +;;;###autoload +(defun burly-bookmark-frames (name) + "Bookmark the current frames as NAME." + (interactive + (list (completing-read "Save Burly bookmark: " (burly-bookmark-names) + nil nil burly-bookmark-prefix))) + (let ((record (list (cons 'url (burly-frames-url)) + (cons 'handler #'burly-bookmark-handler)))) + (bookmark-store name record nil))) + +;;;###autoload +(defun burly-bookmark-windows (name) + "Bookmark the current frame's window configuration as NAME." + (interactive + (list (completing-read "Save Burly bookmark: " (burly-bookmark-names) + nil nil burly-bookmark-prefix))) + (let ((record (list (cons 'url (burly-windows-url)) + (cons 'handler #'burly-bookmark-handler)))) + (bookmark-store name record nil))) + +;;;###autoload +(defun burly-open-bookmark (bookmark) + "Restore a window configuration to the current frame from a Burly BOOKMARK." + (interactive + (list (completing-read "Open Burly bookmark: " (burly-bookmark-names) + nil nil burly-bookmark-prefix))) + (cl-assert (and bookmark (not (string-empty-p bookmark))) nil + "(burly-open-bookmark): Invalid Burly bookmark: '%s'" bookmark) + (bookmark-jump bookmark)) + +;;;; Functions + +;;;;; Buffers + +(defun burly-url-buffer (url) + "Return buffer for URL." + (cl-assert (string-prefix-p "emacs+burly+" url) t "burly-url-buffer: URL not an emacs+burly one: %s" url) + (pcase-let* ((urlobj (url-generic-parse-url url)) + ((cl-struct url type) urlobj) + (subtype (car (last (split-string type "+" 'omit-nulls))))) + (pcase-exhaustive subtype + ("bookmark" (burly--bookmark-url-buffer urlobj)) + ("file" (burly--file-url-buffer urlobj)) + ("name" (let ((buffer-name (decode-coding-string (cdr (url-path-and-query urlobj)) + 'utf-8-unix))) + (or (get-buffer buffer-name) + (with-current-buffer (get-buffer-create (concat "*Burly (error): " buffer-name "*")) + (insert "Burly was unable to get a buffer named: " buffer-name "\n" + "URL: " url "\n" + "Please report this error to the developer\n\n") + (current-buffer)))))))) + +(defun burly-buffer-url (buffer) + "Return URL for BUFFER." + (let* ((major-mode (buffer-local-value 'major-mode buffer)) + (make-url-fn (map-nested-elt burly-major-mode-alist (list major-mode 'make-url-fn)))) + (cond (make-url-fn (funcall make-url-fn buffer)) + (t (or (with-current-buffer buffer + (when-let* ((record (ignore-errors + (bookmark-make-record)))) + (cl-labels ((encode (element) + (cl-typecase element + (string (encode-coding-string element 'utf-8-unix)) + (proper-list (mapcar #'encode element)) + (cons (cons (encode (car element)) + (encode (cdr element)))) + (t element)))) + ;; Encode all strings in record with UTF-8. + ;; NOTE: If we stop using URLs in the future, maybe this won't be needed. + (setf record (encode record))) + (burly--bookmark-record-url record))) + ;; Buffer can't seem to be bookmarked, so record it as + ;; a name-only buffer. For some reason, it works + ;; better to use the buffer name in the query string + ;; rather than the filename/path part. + (url-recreate-url (url-parse-make-urlobj "emacs+burly+name" nil nil nil nil + (concat "?" (encode-coding-string (buffer-name buffer) + 'utf-8-unix)) + nil nil 'fullness))))))) + +;;;;; Files + +(defun burly--file-url-buffer (urlobj) + "Return buffer for \"emacs+burly+file:\" URLOBJ." + (pcase-let* ((`(,path . ,query-string) (url-path-and-query urlobj)) + (query (url-parse-query-string query-string)) + (buffer (find-file-noselect path)) + (major-mode (buffer-local-value 'major-mode buffer)) + (follow-fn (map-nested-elt burly-major-mode-alist (list major-mode 'follow-url-fn)))) + (cl-assert follow-fn nil "Major mode not in `burly-major-mode-alist': %s" major-mode) + (funcall follow-fn :buffer buffer :query query))) + +;;;;; Frames + +;; Looks like frameset.el should make this pretty easy. + +(require 'frameset) + +(cl-defun burly-frames-url (&optional (frames (frame-list))) + "Return URL for frameset of FRAMES. +FRAMES defaults to all live frames." + (dolist (frame frames) + ;; Set URL window parameter for each window before saving state. + (burly--windows-set-url (window-list frame 'never))) + (let* ((window-persistent-parameters (append burly-window-persistent-parameters + window-persistent-parameters)) + (frameset-filter-alist (append burly-frameset-filter-alist frameset-filter-alist)) + (query (frameset-save frames)) + (print-length nil) ; Important! + (filename (concat "?" (url-hexify-string (prin1-to-string query)))) + (url (url-recreate-url (url-parse-make-urlobj "emacs+burly+frames" nil nil nil nil + filename)))) + (dolist (frame frames) + ;; Clear window parameters. + (burly--windows-set-url (window-list frame 'never) 'nullify)) + url)) + +(defun burly--frameset-restore (urlobj) + "Restore FRAMESET according to URLOBJ." + (setf window-persistent-parameters (copy-sequence burly-window-persistent-parameters)) + (pcase-let* ((`(,_ . ,query-string) (url-path-and-query urlobj)) + (frameset (read (url-unhex-string query-string))) + (frameset-filter-alist (append burly-frameset-filter-alist frameset-filter-alist))) + ;; Restore buffers. (Apparently `cl-loop''s in-ref doesn't work with + ;; its destructuring, so we can't just `setf' on `window-state'.) + (setf (frameset-states frameset) + (cl-loop for (frame-parameters . window-state) in (frameset-states frameset) + collect (cons frame-parameters (burly--bufferize-window-state window-state)))) + (condition-case err + (frameset-restore frameset) + (error (delay-warning 'burly (format "Error while restoring frameset: ERROR:%S FRAMESET:%S" err frameset)))))) + +;;;;; Windows + +(cl-defun burly-windows-url (&optional (frame (selected-frame))) + "Return URL for window configuration on FRAME." + (with-selected-frame frame + (let* ((query (burly--window-state frame)) + (print-length nil) ; Important! + (filename (concat "?" (url-hexify-string (prin1-to-string query))))) + (url-recreate-url (url-parse-make-urlobj "emacs+burly+windows" nil nil nil nil + filename))))) + +(cl-defun burly--window-state (&optional (frame (selected-frame))) + "Return window state for FRAME. +Sets `burly-url' window parameter in each window before +serializing." + (with-selected-frame frame + ;; Set URL window parameter for each window before saving state. + (burly--windows-set-url (window-list nil 'never)) + (let* ((window-persistent-parameters (append burly-window-persistent-parameters + window-persistent-parameters)) + (window-state (window-state-get nil 'writable))) + ;; Clear window parameters we set (because they aren't kept + ;; current, so leaving them could be confusing). + (burly--windows-set-url (window-list nil 'never) 'nullify) + window-state))) + +(defun burly--windows-set-url (windows &optional nullify) + "Set `burly-url' window parameter in WINDOWS. +If NULLIFY, set the parameter to nil." + (dolist (window windows) + (let ((value (if nullify nil (burly-buffer-url (window-buffer window))))) + (set-window-parameter window 'burly-url value)))) + +(defun burly--windows-set (urlobj) + "Set window configuration according to URLOBJ." + (setf window-persistent-parameters (copy-sequence burly-window-persistent-parameters)) + (pcase-let* ((window-persistent-parameters (append burly-window-persistent-parameters + window-persistent-parameters)) + (`(,_ . ,query-string) (url-path-and-query urlobj)) + ;; FIXME: Remove this condition-case eventually, after giving users time to update their bookmarks. + (state (condition-case nil + (read (url-unhex-string query-string)) + (invalid-read-syntax (display-warning 'burly "Please recreate that Burly bookmark (storage format changed)") + (read query-string)))) + (state (burly--bufferize-window-state state))) + (window-state-put state (frame-root-window)) + ;; HACK: Since `bookmark--jump-via' insists on calling a + ;; buffer-display function after handling the bookmark, we add a + ;; function to `bookmark-after-jump-hook' to restore the window + ;; configuration that we just set. + (setf burly--window-state (window-state-get (frame-root-window) 'writable)) + (push #'burly--bookmark-window-state-hack bookmark-after-jump-hook))) + +(defun burly--bufferize-window-state (state) + "Return window state STATE with its buffers reincarnated." + (cl-labels ((bufferize-state + ;; Set windows' buffers in STATE. + (state) (pcase state + (`(leaf . ,_attrs) (bufferize-leaf state)) + ((pred atom) state) + (`(,_key . ,(pred atom)) state) + ((pred list) (mapcar #'bufferize-state state)))) + (bufferize-leaf + (leaf) (pcase-let* ((`(leaf . ,attrs) leaf) + ((map parameters buffer) attrs) + ((map burly-url) parameters) + (`(,_buffer-name . ,buffer-attrs) buffer) + (new-buffer (burly-url-buffer burly-url))) + (setf (map-elt attrs 'buffer) (cons new-buffer buffer-attrs)) + (cons 'leaf attrs)))) + (if-let ((leaf-pos (cl-position 'leaf state))) + ;; A one-window frame: the elements following `leaf' are that window's params. + (append (cl-subseq state 0 leaf-pos) + (bufferize-leaf (cl-subseq state leaf-pos))) + ;; Multi-window frame. + (bufferize-state state)))) + +;;;;; Bookmarks + +(defun burly--bookmark-window-state-hack (&optional _) + "Put window state from `burly--window-state'. +This function is to be called in `bookmark-after-jump-hook' to +work around `bookmark--jump-via's calling a buffer-display +function which changes the window configuration after +`burly--windows-set' has set it. This function removes itself +from the hook." + (unwind-protect + (progn + (cl-assert burly--window-state) + (window-state-put burly--window-state (frame-root-window))) + (setf bookmark-after-jump-hook (delete #'burly--bookmark-window-state-hack bookmark-after-jump-hook) + burly--window-state nil))) + +;;;###autoload +(defun burly-bookmark-handler (bookmark) + "Handler function for Burly BOOKMARK." + (let ((previous-name burly-opened-bookmark-name)) + ;; Set opened bookmark name before actually opening it so that the + ;; tabs-mode advice functions can use it beforehand. + (setf burly-opened-bookmark-name (car bookmark)) + (condition-case err + (burly-open-url (alist-get 'url (bookmark-get-bookmark-record bookmark))) + (error (setf burly-opened-bookmark-name previous-name) + (signal (car err) (cdr err)))))) + +(defun burly--bookmark-record-url (record) + "Return a URL for bookmark RECORD." + (cl-assert record) + (pcase-let* ((`(,name . ,props) record) + (print-length nil) ; Important! + (query (cl-loop for prop in props + ;; HACK: Remove unreadable values from props. + do (cl-loop for value in-ref (cdr prop) + when (or (bufferp value)) + do (setf value nil)) + collect (list (car prop) (prin1-to-string (cdr prop))))) + (filename (concat (url-hexify-string name) "?" (url-build-query-string (remove nil query))))) + (url-recreate-url (url-parse-make-urlobj "emacs+burly+bookmark" nil nil nil nil + filename nil nil 'fullness)))) + +(defun burly--bookmark-url-buffer (urlobj) + "Return buffer for bookmark specified by URLOBJ. +URLOBJ should be a URL object as returned by +`url-generic-parse-url'." + (pcase-let* ((`(,path . ,query-string) (url-path-and-query urlobj)) + (query (url-parse-query-string query-string)) + ;; Convert back to alist. + (props (cl-loop for prop in query + for key = (intern (car prop)) + for value = (pcase key + ('handler (intern (cadr prop))) + ('help-args (read (cadr prop))) + ('help-fn (ignore-errors + ;; NOTE: Due to changes in help-mode.el which serialize natively + ;; compiled subrs in the bookmark record, which cannot be read + ;; back (which actually break the entire bookmark system when + ;; such a record is saved in the bookmarks file), we have to + ;; workaround a failure to read here. See bug#56643. + (read (cadr prop)))) + ('position (cl-parse-integer (cadr prop))) + (_ (read (cadr prop)))) + collect (cons key value))) + (record (cons path props))) + (cl-labels ((decode (element) + (cl-typecase element + (string (decode-coding-string element 'utf-8-unix)) + (proper-list (mapcar #'decode element)) + (cons (cons + (decode (car element)) + (decode (cdr element)))) + (t element)))) + ;; Decode all strings in record with UTF-8. + ;; NOTE: If we stop using URLs in the future, maybe this won't be needed. + (setf record (decode record))) + (save-window-excursion + (condition-case err + (bookmark-jump record) + (error (delay-warning 'burly (format "Error while opening bookmark: ERROR:%S RECORD:%S" err record)))) + (current-buffer)))) + +(defun burly-bookmark-names () + "Return list of all Burly bookmark names." + (cl-loop for bookmark in bookmark-alist + for (_name . params) = bookmark + when (equal #'burly-bookmark-handler (alist-get 'handler params)) + collect (car bookmark))) + +;;;;; Org buffers + +;; We only require Org when compiling the file. At runtime, Org will +;; be loaded before we call any of its functions, because we load the +;; Org file into a buffer first, which activates `org-mode'. + +(eval-when-compile + (require 'org)) + +(declare-function org-before-first-heading-p "org") +(declare-function org-back-to-heading "org") +(declare-function org-find-olp "org") +(declare-function org-tree-to-indirect-buffer "org") +(declare-function org-narrow-to-subtree "org") +(declare-function org-heading-components "org") +(declare-function org-up-heading-safe "org") + +(defun burly--org-mode-buffer-url (buffer) + "Return URL for Org BUFFER." + (with-current-buffer buffer + (cl-assert (or (buffer-file-name buffer) + (buffer-file-name (buffer-base-buffer buffer))) + nil "Buffer has no file name: %s" buffer) + (let* ((narrowed (buffer-narrowed-p)) + (indirect (buffer-base-buffer buffer)) + (top-olp + ;; For narrowing purposes, start with the heading at the top of the buffer. + (when (buffer-narrowed-p) + (save-excursion + (goto-char (point-min)) + ;; `org-get-outline-path' replaces links in headings with their + ;; descriptions, which prevents using them in regexp searches. + (when (org-heading-components) + (org-with-wide-buffer + (nreverse (cl-loop collect (substring-no-properties (nth 4 (org-heading-components))) + while (org-up-heading-safe)))))))) + (point-olp + (when (ignore-errors (org-heading-components)) + (org-with-wide-buffer + (nreverse (cl-loop collect (substring-no-properties (nth 4 (org-heading-components))) + while (org-up-heading-safe)))))) + (pos (point)) + (relative-pos (when top-olp + (- (point) (save-excursion + (org-back-to-heading) + (point))))) + (print-length nil) ; Important! + (query (list (list "pos" pos) + (when top-olp + (list "top-olp" (prin1-to-string top-olp))) + (when point-olp + (list "point-olp" (prin1-to-string point-olp))) + (when relative-pos + (list "relative-pos" relative-pos)) + (when indirect + (list "indirect" "t")) + (when narrowed + (list "narrowed" "t")))) + (buffer-file (or (buffer-file-name buffer) + (buffer-file-name (buffer-base-buffer buffer)))) + (filename (concat buffer-file "?" (url-build-query-string (remove nil query))))) + (url-recreate-url (url-parse-make-urlobj "emacs+burly+file" nil nil nil nil + filename nil nil 'fullness))))) + +(cl-defun burly-follow-url-org-mode (&key buffer query) + "In BUFFER, jump to heading and position from QUERY, and return a buffer. +If QUERY specifies that the buffer should be indirect, a new, +indirect buffer is returned. Otherwise BUFFER is returned." + ;; `pcase's map support uses `alist-get', which does not work with string keys + ;; unless its TESTFN arg is bound to, e.g. `equal', but `map-elt' has deprecated + ;; its TESTFN arg, and there's no way to pass it or bind it when using `pcase' + ;; anyway. So we rebind `alist-get' to a function that uses `assoc-string'. + (with-current-buffer buffer + (cl-letf (((symbol-function 'alist-get) + (lambda (key alist &optional _default _remove _testfn) + ;; Only the first value in the list of values is returned, so multiple + ;; values are not supported. I don't expect this to be a problem... + (cadr (assoc-string key alist))))) + (pcase-let* (((map ("pos" pos) + ("indirect" indirect) + ("narrowed" narrowed) + ("top-olp" top-olp) + ("point-olp" point-olp) + ("relative-pos" relative-pos)) + query) + (heading-pos (when top-olp + (org-find-olp (read top-olp) 'this-buffer)))) + (widen) + (if heading-pos + (goto-char heading-pos) + (goto-char (string-to-number pos))) + (cond (indirect (org-tree-to-indirect-buffer)) + (narrowed (progn + (org-narrow-to-subtree) + (goto-char (org-find-olp (read point-olp) 'this-buffer))))) + (when (and heading-pos relative-pos) + (forward-char (string-to-number relative-pos))) + (current-buffer))))) + +;;;; Footer + +(provide 'burly) + +;;; burly.el ends here diff --git a/org/elpa/burly-20221024.2019/burly.info b/org/elpa/burly-20221024.2019/burly.info new file mode 100644 index 0000000..7480a53 --- /dev/null +++ b/org/elpa/burly-20221024.2019/burly.info @@ -0,0 +1,325 @@ +This is README.info, produced by makeinfo version 5.2 from README.texi. + +INFO-DIR-SECTION Emacs +START-INFO-DIR-ENTRY +* Burly: (burly). Save and restore window configurations and their buffers. +END-INFO-DIR-ENTRY + + +File: README.info, Node: Top, Next: Installation, Up: (dir) + +Burly.el +******** + +This package provides tools to save and restore frame and window +configurations in Emacs, including buffers that may not be live anymore. +In this way, it’s like a lightweight "workspace" manager, allowing you +to easily restore one or more frames, including their windows, the +windows’ layout, and their buffers. + + Internally it uses Emacs’s bookmarks system to restore buffers to +their previous contents and location. This provides power and +extensibility, since many major modes already integrate with Emacs’s +bookmarks system. However, in case a mode’s bookmarking function isn’t +satisfactory, Burly allows the user to customize buffer-restoring +functions for specific modes. + + For Org mode, Burly provides such custom functions so that narrowed +and indirect Org buffers are properly restored, and headings are located +by outline path in case they’ve moved since a bookmark was made (the +org-bookmark-heading (https://github.com/alphapapa/org-bookmark-heading) +package also provides this through the Emacs bookmark system, but users +may not have it installed, and the functionality is too useful to not +include here by default). + + Internally, buffers and frame/window configurations are also encoded +as URLs, and users may also save and open those URLs instead of using +Emacs bookmarks. (The name "Burly" comes from "buffer URL.") For +example, a URL to the ‘Installation/Quelpa’ heading in this file, as I’m +writing it, looks like this: + + emacs+burly+file:///home/me/src/emacs/burly.el/README.org?pos=2651&outline-path=%28%22Installation%22%20%22Quelpa%22%29&relative-pos=308 + + In terms of built-in features, Burly may be seen as integrating or +leveraging the built-in libraries ‘bookmark.el’, ‘window.el’, and +‘frameset.el’. + +* Menu: + +* Installation:: +* Usage:: +* Changelog:: +* Development:: +* Credits:: +* License:: + +— The Detailed Node Listing — + +Installation + +* MELPA:: +* Quelpa:: +* Manual:: + +Usage + +* Bookmark commands:: +* URL commands:: +* Tab bar:: +* Tips:: + +Changelog + +* 0.3-pre: 03-pre. +* 0.2: 02. +* 0.1: 01. + + + +File: README.info, Node: Installation, Next: Usage, Prev: Top, Up: Top + +1 Installation +************** + +* Menu: + +* MELPA:: +* Quelpa:: +* Manual:: + + +File: README.info, Node: MELPA, Next: Quelpa, Up: Installation + +1.1 MELPA +========= + +If you installed from MELPA, you’re done. Just run one of the commands +below. + + +File: README.info, Node: Quelpa, Next: Manual, Prev: MELPA, Up: Installation + +1.2 Quelpa +========== + +The easiest way is to install with quelpa-use-package +(https://github.com/quelpa/quelpa-use-package), like this: + + (use-package burly + :quelpa (burly :fetcher github :repo "alphapapa/burly.el")) + + +File: README.info, Node: Manual, Prev: Quelpa, Up: Installation + +1.3 Manual +========== + + 1. Install version 2.1 or later of the ‘map’ library from GNU ELPA. + 2. Copy ‘burly.el’ into a directory in your ‘load-path’, then + ‘(require 'burly)’. + + +File: README.info, Node: Usage, Next: Changelog, Prev: Installation, Up: Top + +2 Usage +******* + +* Menu: + +* Bookmark commands:: +* URL commands:: +* Tab bar:: +* Tips:: + + +File: README.info, Node: Bookmark commands, Next: URL commands, Up: Usage + +2.1 Bookmark commands +===================== + +Most users will probably use Burly by bookmarking frame and window +configurations and accessing them with these commands: + + • ‘burly-bookmark-frames’: Bookmark the current frames and their + window configurations. + • ‘burly-bookmark-windows’: Bookmark the current frame’s window + configuration. + • ‘burly-open-bookmark’: Select and open a Burly bookmark. + • ‘burly-open-last-bookmark’: Open the last-opened Burly bookmark. + Helpful for, e.g. quickly restoring an overview while working on a + project. + + Note that bookmarks created by Burly are regular Emacs bookmarks, so +they can be managed by Emacs’s built-in bookmark commands, e.g. +‘list-bookmarks’, ‘bookmark-delete’, etc. + + +File: README.info, Node: URL commands, Next: Tab bar, Prev: Bookmark commands, Up: Usage + +2.2 URL commands +================ + +These commands work on URL strings. While most users probably won’t use +these, they may be useful for building custom tooling. + + • ‘burly-open-url’: Open a Burly URL (at point, or prompt for one), + displaying the buffer(s) in the current window or frame. + • ‘burly-kill-buffer-url’: Copy BUFFER’s URL to the kill ring. + • ‘burly-kill-frames-url’: Copy the current frameset’s URL to the + kill ring. + • ‘burly-kill-windows-url’: Copy the current frame’s window + configuration URL to the kill ring. + + +File: README.info, Node: Tab bar, Next: Tips, Prev: URL commands, Up: Usage + +2.3 Tab bar +=========== + +Burly supports Emacs’s ‘tab-bar-mode’ with ‘burly-tabs-mode’. When +active, Burly bookmarks are opened in new tabs, and the tabs are named +according to the bookmarks. Reopening a Burly bookmark uses the +designated tab, if it already exists, and tabs may be reset to their +bookmarked state with the command ‘burly-reset-tab’ (which you might +bind to ‘C-x t R’). + + +File: README.info, Node: Tips, Prev: Tab bar, Up: Usage + +2.4 Tips +======== + + • You can customize settings in the ‘burly’ group. + • An Info manual is included with this package. + + +File: README.info, Node: Changelog, Next: Development, Prev: Usage, Up: Top + +3 Changelog +*********** + +* Menu: + +* 0.3-pre: 03-pre. +* 0.2: 02. +* 0.1: 01. + + +File: README.info, Node: 03-pre, Next: 02, Up: Changelog + +3.1 0.3-pre +=========== + +*Added* + • Command ‘burly-tabs-mode’, which integrates Burly with + ‘tab-bar-mode’. When active, Burly bookmarks are opened in new + tabs, and the tabs are named according to the bookmark. + • Command ‘burly-reset-tab’, which resets a tab to the state of the + bookmark which opened it. + + *Changed* + • Emacs version 28.1 or later is required. + + *Fixed* + • Buffers that can’t be restored by name no longer cause an error + which aborts restoration of the rest of the bookmark’s buffers. + • Added workaround for regression in Emacs 28 regarding bookmarks for + ‘help-mode’ buffers. (See Emacs bug 56643 + (https://debbugs.gnu.org/cgi/bugreport.cgi?bug=56643).) + + +File: README.info, Node: 02, Next: 01, Prev: 03-pre, Up: Changelog + +3.2 0.2 +======= + +*Added* + • Bookmark commands use ‘completing-read’ and offer existing Burly + bookmark names, making it easier to update bookmarks. (Thanks to + Erik Sjöstrand (https://github.com/Kungsgeten).) + • Command ‘burly-open-last-bookmark’. + • Option ‘burly-set-window-persistent-parameters’, which synchronizes + ‘window-persistent-parameters’ with + ‘burly-window-persistent-parameters’, ensuring that built-in Emacs + commands like ‘window-toggle-side-windows’ persist parameters that + are persisted with Burly. + + *Changed* + • Option ‘burly-window-persistent-parameters’’s default value + includes more window parameters, like header/mode line, side, slot, + etc, making it easier to restore an overview of a project or + "workspace." + • Emacs version 27.1 or later is required. + + *Fixed* + • Narrow Org buffers to correct heading (at the top of the buffer + rather than at point). + • Buffers whose names have multibyte characters. (Fixes #43 + (https://github.com/alphapapa/burly.el/issues/43). Thanks to Liu + Hui (https://github.com/ilupin) for reporting.) + • Bind ‘print-level’ to nil where ‘prin1-to-string’ is used (in case + the value is non-nil in a user’s config, which would cause + truncated values). + + +File: README.info, Node: 01, Prev: 02, Up: Changelog + +3.3 0.1 +======= + +Initial release. + + +File: README.info, Node: Development, Next: Credits, Prev: Changelog, Up: Top + +4 Development +************* + +Bug reports, feature requests, suggestions — _oh my_! + + +File: README.info, Node: Credits, Next: License, Prev: Development, Up: Top + +5 Credits +********* + + • Thanks to Clemens Radermacher (https://github.com/clemera) and + Robert Weiner (https://github.com/rswgnu) for their suggestions. + • Thanks to Trey Peacock (https://github.com/tpeacock19) for + extensive feedback on pre-release versions. + + +File: README.info, Node: License, Prev: Credits, Up: Top + +6 License +********* + +GPLv3 + + + +Tag Table: +Node: Top219 +Node: Installation2378 +Node: MELPA2529 +Node: Quelpa2701 +Node: Manual3014 +Node: Usage3283 +Node: Bookmark commands3454 +Node: URL commands4320 +Node: Tab bar5001 +Node: Tips5490 +Node: Changelog5685 +Node: 03-pre5847 +Node: 026658 +Node: 018079 +Node: Development8173 +Node: Credits8344 +Node: License8704 + +End Tag Table + + +Local Variables: +coding: utf-8 +End: diff --git a/org/elpa/burly-20221024.2019/dir b/org/elpa/burly-20221024.2019/dir new file mode 100644 index 0000000..73fee8b --- /dev/null +++ b/org/elpa/burly-20221024.2019/dir @@ -0,0 +1,19 @@ +This is the file .../info/dir, which contains the +topmost node of the Info hierarchy, called (dir)Top. +The first time you invoke Info you start off looking at this node. + +File: dir, Node: Top This is the top of the INFO tree + + This (the Directory node) gives a menu of major topics. + Typing "q" exits, "H" lists all Info commands, "d" returns here, + "h" gives a primer for first-timers, + "mEmacs" visits the Emacs manual, etc. + + In Emacs, you can click mouse button 2 on a menu item or cross reference + to select it. + +* Menu: + +Emacs +* Burly: (burly). Save and restore window configurations and + their buffers. diff --git a/org/elpa/dash-20230304.2223/dash-autoloads.el b/org/elpa/dash-20230304.2223/dash-autoloads.el new file mode 100644 index 0000000..6783a8d --- /dev/null +++ b/org/elpa/dash-20230304.2223/dash-autoloads.el @@ -0,0 +1,87 @@ +;;; dash-autoloads.el --- automatically extracted autoloads -*- lexical-binding: t -*- +;; +;;; Code: + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + + +;;;### (autoloads nil "dash" "dash.el" (0 0 0 0)) +;;; Generated autoloads from dash.el + +(autoload 'dash-fontify-mode "dash" "\ +Toggle fontification of Dash special variables. + +This is a minor mode. If called interactively, toggle the +`Dash-Fontify mode' mode. If the prefix argument is positive, +enable the mode, and if it is zero or negative, disable the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `dash-fontify-mode'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +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'. + +\(fn &optional ARG)" t nil) + +(put 'global-dash-fontify-mode 'globalized-minor-mode t) + +(defvar global-dash-fontify-mode nil "\ +Non-nil if Global Dash-Fontify mode is enabled. +See the `global-dash-fontify-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `global-dash-fontify-mode'.") + +(custom-autoload 'global-dash-fontify-mode "dash" nil) + +(autoload 'global-dash-fontify-mode "dash" "\ +Toggle Dash-Fontify mode in all buffers. +With prefix ARG, enable Global Dash-Fontify mode if ARG is positive; +otherwise, disable it. + +If called from Lisp, toggle the mode if ARG is `toggle'. +Enable the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +Dash-Fontify mode is enabled in all buffers where +`dash--turn-on-fontify-mode' would do it. + +See `dash-fontify-mode' for more information on Dash-Fontify mode. + +\(fn &optional ARG)" t nil) + +(autoload 'dash-register-info-lookup "dash" "\ +Register the Dash Info manual with `info-lookup-symbol'. +This allows Dash symbols to be looked up with \\[info-lookup-symbol]." t nil) + +(register-definition-prefixes "dash" '("!cdr" "!cons" "--" "->" "-a" "-butlast" "-c" "-d" "-e" "-f" "-gr" "-i" "-juxt" "-keep" "-l" "-m" "-no" "-o" "-p" "-r" "-s" "-t" "-u" "-value-to-list" "-when-let" "-zip" "dash-")) + +;;;*** + +;;;### (autoloads nil nil ("dash-pkg.el") (0 0 0 0)) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; coding: utf-8 +;; End: +;;; dash-autoloads.el ends here diff --git a/org/elpa/dash-20230304.2223/dash-pkg.el b/org/elpa/dash-20230304.2223/dash-pkg.el new file mode 100644 index 0000000..db4ce58 --- /dev/null +++ b/org/elpa/dash-20230304.2223/dash-pkg.el @@ -0,0 +1,12 @@ +(define-package "dash" "20230304.2223" "A modern list library for Emacs" + '((emacs "24")) + :commit "bdf4a5d868618532d34c7b5bae6ac382c3b58f67" :authors + '(("Magnar Sveen" . "magnars@gmail.com")) + :maintainer + '("Magnar Sveen" . "magnars@gmail.com") + :keywords + '("extensions" "lisp") + :url "https://github.com/magnars/dash.el") +;; Local Variables: +;; no-byte-compile: t +;; End: diff --git a/org/elpa/dash-20230304.2223/dash.el b/org/elpa/dash-20230304.2223/dash.el new file mode 100644 index 0000000..a95ae60 --- /dev/null +++ b/org/elpa/dash-20230304.2223/dash.el @@ -0,0 +1,4054 @@ +;;; dash.el --- A modern list library for Emacs -*- lexical-binding: t -*- + +;; Copyright (C) 2012-2023 Free Software Foundation, Inc. + +;; Author: Magnar Sveen +;; Version: 2.19.1 +;; 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 +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; A modern list API for Emacs. +;; +;; See its overview at https://github.com/magnars/dash.el#functions. + +;;; Code: + +(eval-when-compile + ;; TODO: Emacs 24.3 first introduced `gv', so remove this and all + ;; calls to `defsetf' when support for earlier versions is dropped. + (unless (fboundp 'gv-define-setter) + (require 'cl)) + + ;; TODO: Emacs versions 24.3..24.5 complain about unknown `declare' + ;; props, so remove this when support for those versions is dropped. + (and (< emacs-major-version 25) + (boundp 'defun-declarations-alist) + (dolist (prop '(pure side-effect-free)) + (unless (assq prop defun-declarations-alist) + (push (list prop #'ignore) defun-declarations-alist))))) + +(defgroup dash () + "Customize group for Dash, a modern list library." + :group 'extensions + :group 'lisp + :prefix "dash-") + +(defmacro !cons (car cdr) + "Destructive: Set CDR to the cons of CAR and CDR." + (declare (debug (form symbolp))) + `(setq ,cdr (cons ,car ,cdr))) + +(defmacro !cdr (list) + "Destructive: Set LIST to the cdr of LIST." + (declare (debug (symbolp))) + `(setq ,list (cdr ,list))) + +(defmacro --each (list &rest body) + "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) + (,i 0)) + (while ,l + (let ((it (pop ,l)) (it-index ,i)) + (ignore it it-index) + ,@body) + (setq ,i (1+ ,i)))))) + +(defun -each (list fn) + "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 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))) + +(defmacro --each-while (list pred &rest body) + "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")) + (i (make-symbol "i")) + (elt (make-symbol "elt"))) + `(let ((,l ,list) + (,i 0) + ,elt) + (while (when ,l + (setq ,elt (car-safe ,l)) + (let ((it ,elt) (it-index ,i)) + (ignore it it-index) + ,pred)) + (let ((it ,elt) (it-index ,i)) + (ignore it it-index) + ,@body) + (setq ,i (1+ ,i) ,l (cdr ,l)))))) + +(defun -each-while (list pred fn) + "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))) + +(defmacro --each-r (list &rest body) + "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 the modification was undone before we return. + `(let* ((,v (vconcat ,list)) + (,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 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) + "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)) + (,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 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) + "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) + (,i 0) + it) + (ignore it) + (while (< ,i ,n) + (setq it ,i ,i (1+ ,i)) + ,@body)))) + +(defun -dotimes (num fn) + "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))) + +(defun -map (fn 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) + "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 +FORM. +This is the anaphoric counterpart to `-map'." + (declare (debug (def-form form))) + `(mapcar (lambda (it) (ignore it) ,form) ,list)) + +(defmacro --reduce-from (form init list) + "Accumulate a value by evaluating FORM across LIST. +This macro is like `--each' (which see), but it additionally +provides an accumulator variable `acc' which it successively +binds to the result of evaluating FORM for the current LIST +element before processing the next element. For the first +element, `acc' is initialized with the result of evaluating INIT. +The return value is the resulting value of `acc'. If LIST is +empty, FORM is not evaluated, and the return value is the result +of INIT. +This is the anaphoric counterpart to `-reduce-from'." + (declare (debug (form form form))) + `(let ((acc ,init)) + (--each ,list (setq acc ,form)) + acc)) + +(defun -reduce-from (fn init list) + "Reduce the function FN across LIST, starting with INIT. +Return the result of applying FN to INIT and the first element of +LIST, then applying FN to that result and the second element, +etc. If LIST is empty, return INIT without calling FN. + +This function's anaphoric counterpart is `--reduce-from'. + +For other folds, see also `-reduce' and `-reduce-r'." + (--reduce-from (funcall fn acc it) init list)) + +(defmacro --reduce (form list) + "Accumulate a value by evaluating FORM across LIST. +This macro is like `--reduce-from' (which see), except the first +element of LIST is taken as INIT. Thus if LIST contains a single +item, it is returned without evaluating FORM. If LIST is empty, +FORM is evaluated with `it' and `acc' bound to nil. +This is the anaphoric counterpart to `-reduce'." + (declare (debug (form form))) + (let ((lv (make-symbol "list-value"))) + `(let ((,lv ,list)) + (if ,lv + (--reduce-from ,form (car ,lv) (cdr ,lv)) + ;; Explicit nil binding pacifies lexical "variable left uninitialized" + ;; warning. See issue #377 and upstream https://bugs.gnu.org/47080. + (let ((acc nil) (it nil)) + (ignore acc it) + ,form))))) + +(defun -reduce (fn list) + "Reduce the function FN across LIST. +Return the result of applying FN to the first two elements of +LIST, then applying FN to that result and the third element, etc. +If LIST contains a single element, return it without calling FN. +If LIST is empty, return the result of calling FN with no +arguments. + +This function's anaphoric counterpart is `--reduce'. + +For other folds, see also `-reduce-from' and `-reduce-r'." + (if list + (-reduce-from fn (car list) (cdr list)) + (funcall fn))) + +(defmacro --reduce-r-from (form init list) + "Accumulate a value by evaluating FORM across LIST in reverse. +This macro is like `--reduce-from', except it starts from the end +of LIST. +This is the anaphoric counterpart to `-reduce-r-from'." + (declare (debug (form form form))) + `(let ((acc ,init)) + (--each-r ,list (setq acc ,form)) + acc)) + +(defun -reduce-r-from (fn init list) + "Reduce the function FN across LIST in reverse, starting with INIT. +Return the result of applying FN to the last element of LIST and +INIT, then applying FN to the second-to-last element and the +previous result of FN, etc. That is, the first argument of FN is +the current element, and its second argument the accumulated +value. If LIST is empty, return INIT without calling FN. + +This function is like `-reduce-from' but the operation associates +from the right rather than left. In other words, it starts from +the end of LIST and flips the arguments to FN. Conceptually, it +is like replacing the conses in LIST with applications of FN, and +its last link with INIT, and evaluating the resulting expression. + +This function's anaphoric counterpart is `--reduce-r-from'. + +For other folds, see also `-reduce-r' and `-reduce'." + (--reduce-r-from (funcall fn it acc) init list)) + +(defmacro --reduce-r (form list) + "Accumulate a value by evaluating FORM across LIST in reverse order. +This macro is like `--reduce', except it starts from the end of +LIST. +This is the anaphoric counterpart to `-reduce-r'." + (declare (debug (form form))) + `(--reduce ,form (reverse ,list))) + +(defun -reduce-r (fn list) + "Reduce the function FN across LIST in reverse. +Return the result of applying FN to the last two elements of +LIST, then applying FN to the third-to-last element and the +previous result of FN, etc. That is, the first argument of FN is +the current element, and its second argument the accumulated +value. If LIST contains a single element, return it without +calling FN. If LIST is empty, return the result of calling FN +with no arguments. + +This function is like `-reduce' but the operation associates from +the right rather than left. In other words, it starts from the +end of LIST and flips the arguments to FN. Conceptually, it is +like replacing the conses in LIST with applications of FN, +ignoring its last link, and evaluating the resulting expression. + +This function's anaphoric counterpart is `--reduce-r'. + +For other folds, see also `-reduce-r-from' and `-reduce'." + (if list + (--reduce-r (funcall fn it acc) list) + (funcall fn))) + +(defmacro --reductions-from (form init list) + "Return a list of FORM's intermediate reductions across LIST. +That is, a list of the intermediate values of the accumulator +when `--reduce-from' (which see) is called with the same +arguments. +This is the anaphoric counterpart to `-reductions-from'." + (declare (debug (form form form))) + `(nreverse + (--reduce-from (cons (let ((acc (car acc))) (ignore acc) ,form) acc) + (list ,init) + ,list))) + +(defun -reductions-from (fn init list) + "Return a list of FN's intermediate reductions across LIST. +That is, a list of the intermediate values of the accumulator +when `-reduce-from' (which see) is called with the same +arguments. + +This function's anaphoric counterpart is `--reductions-from'. + +For other folds, see also `-reductions' and `-reductions-r'." + (--reductions-from (funcall fn acc it) init list)) + +(defmacro --reductions (form list) + "Return a list of FORM's intermediate reductions across LIST. +That is, a list of the intermediate values of the accumulator +when `--reduce' (which see) is called with the same arguments. +This is the anaphoric counterpart to `-reductions'." + (declare (debug (form form))) + (let ((lv (make-symbol "list-value"))) + `(let ((,lv ,list)) + (if ,lv + (--reductions-from ,form (car ,lv) (cdr ,lv)) + ;; Explicit nil binding pacifies lexical "variable left uninitialized" + ;; warning. See issue #377 and upstream https://bugs.gnu.org/47080. + (let ((acc nil) (it nil)) + (ignore acc it) + (list ,form)))))) + +(defun -reductions (fn list) + "Return a list of FN's intermediate reductions across LIST. +That is, a list of the intermediate values of the accumulator +when `-reduce' (which see) is called with the same arguments. + +This function's anaphoric counterpart is `--reductions'. + +For other folds, see also `-reductions' and `-reductions-r'." + (if list + (--reductions-from (funcall fn acc it) (car list) (cdr list)) + (list (funcall fn)))) + +(defmacro --reductions-r-from (form init list) + "Return a list of FORM's intermediate reductions across reversed LIST. +That is, a list of the intermediate values of the accumulator +when `--reduce-r-from' (which see) is called with the same +arguments. +This is the anaphoric counterpart to `-reductions-r-from'." + (declare (debug (form form form))) + `(--reduce-r-from (cons (let ((acc (car acc))) (ignore acc) ,form) acc) + (list ,init) + ,list)) + +(defun -reductions-r-from (fn init list) + "Return a list of FN's intermediate reductions across reversed LIST. +That is, a list of the intermediate values of the accumulator +when `-reduce-r-from' (which see) is called with the same +arguments. + +This function's anaphoric counterpart is `--reductions-r-from'. + +For other folds, see also `-reductions' and `-reductions-r'." + (--reductions-r-from (funcall fn it acc) init list)) + +(defmacro --reductions-r (form list) + "Return a list of FORM's intermediate reductions across reversed LIST. +That is, a list of the intermediate values of the accumulator +when `--reduce-re' (which see) is called with the same arguments. +This is the anaphoric counterpart to `-reductions-r'." + (declare (debug (form list))) + (let ((lv (make-symbol "list-value"))) + `(let ((,lv (reverse ,list))) + (if ,lv + (--reduce-from (cons (let ((acc (car acc))) (ignore acc) ,form) acc) + (list (car ,lv)) + (cdr ,lv)) + ;; Explicit nil binding pacifies lexical "variable left uninitialized" + ;; warning. See issue #377 and upstream https://bugs.gnu.org/47080. + (let ((acc nil) (it nil)) + (ignore acc it) + (list ,form)))))) + +(defun -reductions-r (fn list) + "Return a list of FN's intermediate reductions across reversed LIST. +That is, a list of the intermediate values of the accumulator +when `-reduce-r' (which see) is called with the same arguments. + +This function's anaphoric counterpart is `--reductions-r'. + +For other folds, see also `-reductions-r-from' and +`-reductions'." + (if list + (--reductions-r (funcall fn it acc) list) + (list (funcall fn)))) + +(defmacro --filter (form list) + "Return a new list of the items in LIST for which FORM evals to non-nil. +Each element of LIST in turn is bound to `it' and its index +within LIST to `it-index' before evaluating FORM. +This is the anaphoric counterpart to `-filter'. +For the opposite operation, see also `--remove'." + (declare (debug (form form))) + (let ((r (make-symbol "result"))) + `(let (,r) + (--each ,list (when ,form (push it ,r))) + (nreverse ,r)))) + +(defun -filter (pred list) + "Return a new list of the items in LIST for which PRED returns non-nil. + +Alias: `-select'. + +This function's anaphoric counterpart is `--filter'. + +For similar operations, see also `-keep' and `-remove'." + (--filter (funcall pred it) list)) + +(defalias '-select '-filter) +(defalias '--select '--filter) + +(defmacro --remove (form list) + "Return a new list of the items in LIST for which FORM evals to nil. +Each element of LIST in turn is bound to `it' and its index +within LIST to `it-index' before evaluating FORM. +This is the anaphoric counterpart to `-remove'. +For the opposite operation, see also `--filter'." + (declare (debug (form form))) + `(--filter (not ,form) ,list)) + +(defun -remove (pred list) + "Return a new list of the items in LIST for which PRED returns nil. + +Alias: `-reject'. + +This function's anaphoric counterpart is `--remove'. + +For similar operations, see also `-keep' and `-filter'." + (--remove (funcall pred it) list)) + +(defalias '-reject '-remove) +(defalias '--reject '--remove) + +(defmacro --remove-first (form list) + "Remove the first item from LIST for which FORM evals to non-nil. +Each element of LIST in turn is bound to `it' and its index +within LIST to `it-index' before evaluating FORM. This is a +non-destructive operation, but only the front of LIST leading up +to the removed item is a copy; the rest is LIST's original tail. +If no item is removed, then the result is a complete copy. +This is the anaphoric counterpart to `-remove-first'." + (declare (debug (form form))) + (let ((front (make-symbol "front")) + (tail (make-symbol "tail"))) + `(let ((,tail ,list) ,front) + (--each-while ,tail (not ,form) + (push (pop ,tail) ,front)) + (if ,tail + (nconc (nreverse ,front) (cdr ,tail)) + (nreverse ,front))))) + +(defun -remove-first (pred list) + "Remove the first item from LIST for which PRED returns non-nil. +This is a non-destructive operation, but only the front of LIST +leading up to the removed item is a copy; the rest is LIST's +original tail. If no item is removed, then the result is a +complete copy. + +Alias: `-reject-first'. + +This function's anaphoric counterpart is `--remove-first'. + +See also `-map-first', `-remove-item', and `-remove-last'." + (--remove-first (funcall pred it) list)) + +;; TODO: #'-quoting the macro upsets Emacs 24. +(defalias '-reject-first #'-remove-first) +(defalias '--reject-first '--remove-first) + +(defmacro --remove-last (form list) + "Remove the last item from LIST for which FORM evals to non-nil. +Each element of LIST in turn is bound to `it' before evaluating +FORM. The result is a copy of LIST regardless of whether an +element is removed. +This is the anaphoric counterpart to `-remove-last'." + (declare (debug (form form))) + `(nreverse (--remove-first ,form (reverse ,list)))) + +(defun -remove-last (pred list) + "Remove the last item from LIST for which PRED returns non-nil. +The result is a copy of LIST regardless of whether an element is +removed. + +Alias: `-reject-last'. + +This function's anaphoric counterpart is `--remove-last'. + +See also `-map-last', `-remove-item', and `-remove-first'." + (--remove-last (funcall pred it) list)) + +(defalias '-reject-last '-remove-last) +(defalias '--reject-last '--remove-last) + +(defalias '-remove-item #'remove + "Return a copy of LIST with all occurrences of ITEM removed. +The comparison is done with `equal'. +\n(fn ITEM LIST)") + +(defmacro --keep (form list) + "Eval FORM for each item in LIST and return the non-nil results. +Like `--filter', but returns the non-nil results of FORM instead +of the corresponding elements of LIST. Each element of LIST in +turn is bound to `it' and its index within LIST to `it-index' +before evaluating FORM. +This is the anaphoric counterpart to `-keep'." + (declare (debug (form form))) + (let ((r (make-symbol "result")) + (m (make-symbol "mapped"))) + `(let (,r) + (--each ,list (let ((,m ,form)) (when ,m (push ,m ,r)))) + (nreverse ,r)))) + +(defun -keep (fn list) + "Return a new list of the non-nil results of applying FN to each item in LIST. +Like `-filter', but returns the non-nil results of FN instead of +the corresponding elements of LIST. + +Its anaphoric counterpart is `--keep'." + (--keep (funcall fn it) list)) + +(defun -non-nil (list) + "Return a copy of LIST with all nil items removed." + (declare (pure t) (side-effect-free t)) + (--filter it list)) + +(defmacro --map-indexed (form list) + "Eval FORM for each item in LIST and return the list of results. +Each element of LIST in turn is bound to `it' and its index +within LIST to `it-index' before evaluating FORM. This is like +`--map', but additionally makes `it-index' available to FORM. + +This is the anaphoric counterpart to `-map-indexed'." + (declare (debug (form form))) + (let ((r (make-symbol "result"))) + `(let (,r) + (--each ,list + (push ,form ,r)) + (nreverse ,r)))) + +(defun -map-indexed (fn list) + "Apply FN to each index and item in LIST and return the list of results. +This is like `-map', but FN takes two arguments: the index of the +current element within LIST, and the element itself. + +This function's anaphoric counterpart is `--map-indexed'. + +For a side-effecting variant, see also `-each-indexed'." + (--map-indexed (funcall fn it-index it) list)) + +(defmacro --map-when (pred rep list) + "Anaphoric form of `-map-when'." + (declare (debug (form form form))) + (let ((r (make-symbol "result"))) + `(let (,r) + (--each ,list (!cons (if ,pred ,rep it) ,r)) + (nreverse ,r)))) + +(defun -map-when (pred rep list) + "Use PRED to conditionally apply REP to each item in LIST. +Return a copy of LIST where the items for which PRED returns nil +are unchanged, and the rest are mapped through the REP function. + +Alias: `-replace-where' + +See also: `-update-at'" + (--map-when (funcall pred it) (funcall rep it) list)) + +(defalias '-replace-where '-map-when) +(defalias '--replace-where '--map-when) + +(defun -map-first (pred rep list) + "Use PRED to determine the first item in LIST to call REP on. +Return a copy of LIST where the first item for which PRED returns +non-nil is replaced with the result of calling REP on that item. + +See also: `-map-when', `-replace-first'" + (let (front) + (while (and list (not (funcall pred (car list)))) + (push (car list) front) + (!cdr list)) + (if list + (-concat (nreverse front) (cons (funcall rep (car list)) (cdr list))) + (nreverse front)))) + +(defmacro --map-first (pred rep list) + "Anaphoric form of `-map-first'." + (declare (debug (def-form def-form form))) + `(-map-first (lambda (it) (ignore it) ,pred) + (lambda (it) (ignore it) ,rep) + ,list)) + +(defun -map-last (pred rep list) + "Use PRED to determine the last item in LIST to call REP on. +Return a copy of LIST where the last item for which PRED returns +non-nil is replaced with the result of calling REP on that item. + +See also: `-map-when', `-replace-last'" + (nreverse (-map-first pred rep (reverse list)))) + +(defmacro --map-last (pred rep list) + "Anaphoric form of `-map-last'." + (declare (debug (def-form def-form form))) + `(-map-last (lambda (it) (ignore it) ,pred) + (lambda (it) (ignore it) ,rep) + ,list)) + +(defun -replace (old new list) + "Replace all OLD items in LIST with NEW. + +Elements are compared using `equal'. + +See also: `-replace-at'" + (declare (pure t) (side-effect-free t)) + (--map-when (equal it old) new list)) + +(defun -replace-first (old new list) + "Replace the first occurrence of OLD with NEW in LIST. + +Elements are compared using `equal'. + +See also: `-map-first'" + (declare (pure t) (side-effect-free t)) + (--map-first (equal old it) new list)) + +(defun -replace-last (old new list) + "Replace the last occurrence of OLD with NEW in LIST. + +Elements are compared using `equal'. + +See also: `-map-last'" + (declare (pure t) (side-effect-free t)) + (--map-last (equal old it) new list)) + +(defmacro --mapcat (form list) + "Anaphoric form of `-mapcat'." + (declare (debug (form form))) + `(apply #'append (--map ,form ,list))) + +(defun -mapcat (fn list) + "Return the concatenation of the result of mapping FN over LIST. +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")) + (len (make-symbol "n"))) + `(let ((,len ,n)) + (when (> ,len 0) + (let* ((it ,init) + (,res (list it))) + (dotimes (_ (1- ,len)) + (push (setq it ,form) ,res)) + (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. + +Note that because nil represents a list of zero elements (an +empty list), any mention of nil in L will disappear after +flattening. If you need to preserve nils, consider `-flatten-n' +or map them to some unique symbol and then map them back. + +Conses of two atoms are considered \"terminals\", that is, they +aren't flattened further. + +See also: `-flatten-n'" + (declare (pure t) (side-effect-free t)) + (if (and (listp l) (listp (cdr l))) + (-mapcat '-flatten l) + (list l))) + +(defun -flatten-n (num list) + "Flatten NUM levels of a nested LIST. + +See also: `-flatten'" + (declare (pure t) (side-effect-free t)) + (dotimes (_ num) + (setq list (apply #'append (mapcar #'-list list)))) + list) + +(defalias '-concat #'append + "Concatenate all the arguments and make the result a list. +The result is a list whose elements are the elements of all the arguments. +Each argument may be a list, vector or string. + +All arguments except the last argument are copied. The last argument +is just used as the tail of the new list. + +\(fn &rest SEQUENCES)") + +(defalias '-copy #'copy-sequence + "Create a shallow copy of LIST. + +\(fn LIST)") + +(defmacro --splice (pred form list) + "Splice lists generated by FORM in place of items satisfying PRED in LIST. + +Evaluate PRED for each element of LIST in turn bound to `it'. +Whenever the result of PRED is nil, leave that `it' is-is. +Otherwise, evaluate FORM with the same `it' binding still in +place. The result should be a (possibly empty) list of items to +splice in place of `it' in LIST. + +This can be useful as an alternative to the `,@' construct in a +`\\=`' structure, in case you need to splice several lists at +marked positions (for example with keywords). + +This is the anaphoric counterpart to `-splice'." + (declare (debug (form form form))) + (let ((r (make-symbol "result"))) + `(let (,r) + (--each ,list + (if ,pred + (--each ,form (push it ,r)) + (push it ,r))) + (nreverse ,r)))) + +(defun -splice (pred fun list) + "Splice lists generated by FUN in place of items satisfying PRED in LIST. + +Call PRED on each element of LIST. Whenever the result of PRED +is nil, leave that `it' as-is. Otherwise, call FUN on the same +`it' that satisfied PRED. The result should be a (possibly +empty) list of items to splice in place of `it' in LIST. + +This can be useful as an alternative to the `,@' construct in a +`\\=`' structure, in case you need to splice several lists at +marked positions (for example with keywords). + +This function's anaphoric counterpart is `--splice'. + +See also: `-splice-list', `-insert-at'." + (--splice (funcall pred it) (funcall fun it) list)) + +(defun -splice-list (pred new-list list) + "Splice NEW-LIST in place of elements matching PRED in LIST. + +See also: `-splice', `-insert-at'" + (-splice pred (lambda (_) new-list) list)) + +(defmacro --splice-list (pred new-list list) + "Anaphoric form of `-splice-list'." + (declare (debug (def-form form form))) + `(-splice-list (lambda (it) (ignore it) ,pred) ,new-list ,list)) + +(defun -cons* (&rest args) + "Make a new list from the elements of ARGS. +The last 2 elements of ARGS are used as the final cons of the +result, so if the final element of ARGS is not a list, the result +is a dotted list. With no ARGS, return nil." + (declare (pure t) (side-effect-free t)) + (let* ((len (length args)) + (tail (nthcdr (- len 2) args)) + (last (cdr tail))) + (if (null last) + (car args) + (setcdr tail (car last)) + args))) + +(defun -snoc (list elem &rest elements) + "Append ELEM to the end of the list. + +This is like `cons', but operates on the end of list. + +If any ELEMENTS are given, append them to the list as well." + (-concat list (list elem) elements)) + +(defmacro --first (form list) + "Return the first item in LIST for which FORM evals to non-nil. +Return nil if no such element is found. +Each element of LIST in turn is bound to `it' and its index +within LIST to `it-index' before evaluating FORM. +This is the anaphoric counterpart to `-first'." + (declare (debug (form form))) + (let ((n (make-symbol "needle"))) + `(let (,n) + (--each-while ,list (or (not ,form) + (ignore (setq ,n it)))) + ,n))) + +(defun -first (pred list) + "Return the first item in LIST for which PRED returns non-nil. +Return nil if no such element is found. + +To get the first item in the list no questions asked, +use `-first-item'. + +Alias: `-find'. + +This function's anaphoric counterpart is `--first'." + (--first (funcall pred it) list)) + +(defalias '-find #'-first) +(defalias '--find '--first) + +(defmacro --some (form list) + "Return non-nil if FORM evals to non-nil for at least one item in LIST. +If so, return the first such result of FORM. +Each element of LIST in turn is bound to `it' and its index +within LIST to `it-index' before evaluating FORM. +This is the anaphoric counterpart to `-some'." + (declare (debug (form form))) + (let ((n (make-symbol "needle"))) + `(let (,n) + (--each-while ,list (not (setq ,n ,form))) + ,n))) + +(defun -some (pred list) + "Return (PRED x) for the first LIST item where (PRED x) is non-nil, else nil. + +Alias: `-any'. + +This function's anaphoric counterpart is `--some'." + (--some (funcall pred it) list)) + +(defalias '-any '-some) +(defalias '--any '--some) + +(defmacro --every (form list) + "Return non-nil if FORM evals to non-nil for all items in LIST. +If so, return the last such result of FORM. Otherwise, once an +item is reached for which FORM yields nil, return nil without +evaluating FORM for any further LIST elements. +Each element of LIST in turn is bound to `it' and its index +within LIST to `it-index' before evaluating FORM. + +This macro is like `--every-p', but on success returns the last +non-nil result of FORM instead of just t. + +This is the anaphoric counterpart to `-every'." + (declare (debug (form form))) + (let ((a (make-symbol "all"))) + `(let ((,a t)) + (--each-while ,list (setq ,a ,form)) + ,a))) + +(defun -every (pred list) + "Return non-nil if PRED returns non-nil for all items in LIST. +If so, return the last such result of PRED. Otherwise, once an +item is reached for which PRED returns nil, return nil without +calling PRED on any further LIST elements. + +This function is like `-every-p', but on success returns the last +non-nil result of PRED instead of just t. + +This function's anaphoric counterpart is `--every'." + (--every (funcall pred it) list)) + +(defmacro --last (form list) + "Anaphoric form of `-last'." + (declare (debug (form form))) + (let ((n (make-symbol "needle"))) + `(let (,n) + (--each ,list + (when ,form (setq ,n it))) + ,n))) + +(defun -last (pred list) + "Return the last x in LIST where (PRED x) is non-nil, else nil." + (--last (funcall pred it) list)) + +(defalias '-first-item #'car + "Return the first item of LIST, or nil on an empty list. + +See also: `-second-item', `-last-item', etc. + +\(fn LIST)") + +;; Ensure that calls to `-first-item' are compiled to a single opcode, +;; just like `car'. +(put '-first-item 'byte-opcode 'byte-car) +(put '-first-item 'byte-compile 'byte-compile-one-arg) +(put '-first-item 'pure t) +(put '-first-item 'side-effect-free t) + +(defalias '-second-item #'cadr + "Return the second item of LIST, or nil if LIST is too short. + +See also: `-first-item', `-third-item', etc. + +\(fn LIST)") + +(put '-second-item 'pure t) +(put '-second-item 'side-effect-free t) + +(defalias '-third-item + (if (fboundp 'caddr) + #'caddr + (lambda (list) (car (cddr list)))) + "Return the third item of LIST, or nil if LIST is too short. + +See also: `-second-item', `-fourth-item', etc. + +\(fn LIST)") + +(put '-third-item 'pure t) +(put '-third-item 'side-effect-free t) + +(defalias '-fourth-item + (if (fboundp 'cadddr) + #'cadddr + (lambda (list) (cadr (cddr list)))) + "Return the fourth item of LIST, or nil if LIST is too short. + +See also: `-third-item', `-fifth-item', etc. + +\(fn LIST)") + +(put '-fourth-item 'pure t) +(put '-fourth-item 'side-effect-free t) + +(defun -fifth-item (list) + "Return the fifth item of LIST, or nil if LIST is too short. + +See also: `-fourth-item', `-last-item', etc." + (declare (pure t) (side-effect-free t)) + (car (cddr (cddr list)))) + +(defun -last-item (list) + "Return the last item of LIST, or nil on an empty list. + +See also: `-first-item', etc." + (declare (pure t) (side-effect-free t)) + (car (last list))) + +;; Use `with-no-warnings' to suppress unbound `-last-item' or +;; undefined `gv--defsetter' warnings arising from both +;; `gv-define-setter' and `defsetf' in certain Emacs versions. +(with-no-warnings + (if (fboundp 'gv-define-setter) + (gv-define-setter -last-item (val x) `(setcar (last ,x) ,val)) + (defsetf -last-item (x) (val) `(setcar (last ,x) ,val)))) + +(defun -butlast (list) + "Return a list of all items in list except for the last." + ;; no alias as we don't want magic optional argument + (declare (pure t) (side-effect-free t)) + (butlast list)) + +(defmacro --count (pred list) + "Anaphoric form of `-count'." + (declare (debug (form form))) + (let ((r (make-symbol "result"))) + `(let ((,r 0)) + (--each ,list (when ,pred (setq ,r (1+ ,r)))) + ,r))) + +(defun -count (pred list) + "Counts the number of items in LIST where (PRED item) is non-nil." + (--count (funcall pred it) list)) + +(defun ---truthy? (obj) + "Return OBJ as a boolean value (t or nil)." + (declare (pure t) (side-effect-free error-free)) + (and obj t)) + +(defmacro --any? (form list) + "Anaphoric form of `-any?'." + (declare (debug (form form))) + `(and (--some ,form ,list) t)) + +(defun -any? (pred list) + "Return t if (PRED X) is non-nil for any X in LIST, else nil. + +Alias: `-any-p', `-some?', `-some-p'" + (--any? (funcall pred it) list)) + +(defalias '-some? '-any?) +(defalias '--some? '--any?) +(defalias '-any-p '-any?) +(defalias '--any-p '--any?) +(defalias '-some-p '-any?) +(defalias '--some-p '--any?) + +(defmacro --all? (form list) + "Return t if FORM evals to non-nil for all items in LIST. +Otherwise, once an item is reached for which FORM yields nil, +return nil without evaluating FORM for any further LIST elements. +Each element of LIST in turn is bound to `it' and its index +within LIST to `it-index' before evaluating FORM. + +The similar macro `--every' is more widely useful, since it +returns the last non-nil result of FORM instead of just t on +success. + +Alias: `--all-p', `--every-p', `--every?'. + +This is the anaphoric counterpart to `-all?'." + (declare (debug (form form))) + `(and (--every ,form ,list) t)) + +(defun -all? (pred list) + "Return t if (PRED X) is non-nil for all X in LIST, else nil. +In the latter case, stop after the first X for which (PRED X) is +nil, without calling PRED on any subsequent elements of LIST. + +The similar function `-every' is more widely useful, since it +returns the last non-nil result of PRED instead of just t on +success. + +Alias: `-all-p', `-every-p', `-every?'. + +This function's anaphoric counterpart is `--all?'." + (--all? (funcall pred it) list)) + +(defalias '-every? '-all?) +(defalias '--every? '--all?) +(defalias '-all-p '-all?) +(defalias '--all-p '--all?) +(defalias '-every-p '-all?) +(defalias '--every-p '--all?) + +(defmacro --none? (form list) + "Anaphoric form of `-none?'." + (declare (debug (form form))) + `(--all? (not ,form) ,list)) + +(defun -none? (pred list) + "Return t if (PRED X) is nil for all X in LIST, else nil. + +Alias: `-none-p'" + (--none? (funcall pred it) list)) + +(defalias '-none-p '-none?) +(defalias '--none-p '--none?) + +(defmacro --only-some? (form list) + "Anaphoric form of `-only-some?'." + (declare (debug (form form))) + (let ((y (make-symbol "yes")) + (n (make-symbol "no"))) + `(let (,y ,n) + (--each-while ,list (not (and ,y ,n)) + (if ,form (setq ,y t) (setq ,n t))) + (---truthy? (and ,y ,n))))) + +(defun -only-some? (pred list) + "Return t if different LIST items both satisfy and do not satisfy PRED. +That is, if PRED returns both nil for at least one item, and +non-nil for at least one other item in LIST. Return nil if all +items satisfy the predicate or none of them do. + +Alias: `-only-some-p'" + (--only-some? (funcall pred it) list)) + +(defalias '-only-some-p '-only-some?) +(defalias '--only-some-p '--only-some?) + +(defun -slice (list from &optional to step) + "Return copy of LIST, starting from index FROM to index TO. + +FROM or TO may be negative. These values are then interpreted +modulo the length of the list. + +If STEP is a number, only each STEPth item in the resulting +section is returned. Defaults to 1." + (declare (pure t) (side-effect-free t)) + (let ((length (length list)) + (new-list nil)) + ;; to defaults to the end of the list + (setq to (or to length)) + (setq step (or step 1)) + ;; handle negative indices + (when (< from 0) + (setq from (mod from length))) + (when (< to 0) + (setq to (mod to length))) + + ;; iterate through the list, keeping the elements we want + (--each-while list (< it-index to) + (when (and (>= it-index from) + (= (mod (- from it-index) step) 0)) + (push it new-list))) + (nreverse new-list))) + +(defmacro --take-while (form list) + "Take successive items from LIST for which FORM evals to non-nil. +Each element of LIST in turn is bound to `it' and its index +within LIST to `it-index' before evaluating FORM. Return a new +list of the successive elements from the start of LIST for which +FORM evaluates to non-nil. +This is the anaphoric counterpart to `-take-while'." + (declare (debug (form form))) + (let ((r (make-symbol "result"))) + `(let (,r) + (--each-while ,list ,form (push it ,r)) + (nreverse ,r)))) + +(defun -take-while (pred list) + "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. + +This function's anaphoric counterpart is `--take-while'. + +For another variant, see also `-drop-while'." + (--take-while (funcall pred it) list)) + +(defmacro --drop-while (form list) + "Drop successive items from LIST for which FORM evals to non-nil. +Each element of LIST in turn is bound to `it' and its index +within LIST to `it-index' before evaluating FORM. Return the +tail (not a copy) of LIST starting from its first element for +which FORM evaluates to nil. +This is the anaphoric counterpart to `-drop-while'." + (declare (debug (form form))) + (let ((l (make-symbol "list"))) + `(let ((,l ,list)) + (--each-while ,l ,form (pop ,l)) + ,l))) + +(defun -drop-while (pred list) + "Drop successive items from LIST for which PRED returns non-nil. +PRED is a function of one argument. Return the tail (not a copy) +of LIST starting from its first element for which PRED returns +nil. + +This function's anaphoric counterpart is `--drop-while'. + +For another variant, 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))) + +(defalias '-drop #'nthcdr + "Return the tail (not a copy) of LIST without the first N items. +Return nil if LIST contains N items or fewer. +Return LIST if N is zero or less. + +For another variant, see also `-drop-last'. +\n(fn 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) + "Split LIST into two sublists after the Nth element. +The result is a list of two elements (TAKE DROP) where TAKE is a +new list of the first N elements of LIST, and DROP is the +remaining elements of LIST (not a copy). TAKE and DROP are like +the results of `-take' and `-drop', respectively, but the split +is done in a single list traversal." + (declare (pure t) (side-effect-free t)) + (let (result) + (--each-while list (< it-index n) + (push (pop list) result)) + (list (nreverse result) list))) + +(defun -rotate (n list) + "Rotate LIST N places to the right (left if N is negative). +The time complexity is O(n)." + (declare (pure t) (side-effect-free t)) + (cond ((null list) ()) + ((zerop n) (copy-sequence list)) + ((let* ((len (length list)) + (n-mod-len (mod n len)) + (new-tail-len (- len n-mod-len))) + (append (nthcdr new-tail-len list) (-take new-tail-len list)))))) + +(defun -insert-at (n x list) + "Return a list with X inserted into LIST at position N. + +See also: `-splice', `-splice-list'" + (declare (pure t) (side-effect-free t)) + (let ((split-list (-split-at n list))) + (nconc (car split-list) (cons x (cadr split-list))))) + +(defun -replace-at (n x list) + "Return a list with element at Nth position in LIST replaced with X. + +See also: `-replace'" + (declare (pure t) (side-effect-free t)) + (let ((split-list (-split-at n list))) + (nconc (car split-list) (cons x (cdr (cadr split-list)))))) + +(defun -update-at (n func list) + "Use FUNC to update the Nth element of LIST. +Return a copy of LIST where the Nth element is replaced with the +result of calling FUNC on it. + +See also: `-map-when'" + (let ((split-list (-split-at n list))) + (nconc (car split-list) + (cons (funcall func (car (cadr split-list))) + (cdr (cadr split-list)))))) + +(defmacro --update-at (n form list) + "Anaphoric version of `-update-at'." + (declare (debug (form def-form form))) + `(-update-at ,n (lambda (it) (ignore it) ,form) ,list)) + +(defun -remove-at (n list) + "Return LIST with its element at index N removed. +That is, remove any element selected as (nth N LIST) from LIST +and return the result. + +This is a non-destructive operation: parts of LIST (but not +necessarily all of it) are copied as needed to avoid +destructively modifying it. + +See also: `-remove-at-indices', `-remove'." + (declare (pure t) (side-effect-free t)) + (if (zerop n) + (cdr list) + (--remove-first (= it-index n) list))) + +(defun -remove-at-indices (indices list) + "Return LIST with its elements at INDICES removed. +That is, for each index I in INDICES, remove any element selected +as (nth I LIST) from LIST. + +This is a non-destructive operation: parts of LIST (but not +necessarily all of it) are copied as needed to avoid +destructively modifying it. + +See also: `-remove-at', `-remove'." + (declare (pure t) (side-effect-free t)) + (setq indices (--drop-while (< it 0) (-sort #'< indices))) + (let ((i (pop indices)) res) + (--each-while list i + (pop list) + (if (/= it-index i) + (push it res) + (while (and indices (= (car indices) i)) + (pop indices)) + (setq i (pop indices)))) + (nconc (nreverse res) list))) + +(defmacro --split-with (pred list) + "Anaphoric form of `-split-with'." + (declare (debug (form form))) + (let ((l (make-symbol "list")) + (r (make-symbol "result")) + (c (make-symbol "continue"))) + `(let ((,l ,list) + (,r nil) + (,c t)) + (while (and ,l ,c) + (let ((it (car ,l))) + (if (not ,pred) + (setq ,c nil) + (!cons it ,r) + (!cdr ,l)))) + (list (nreverse ,r) ,l)))) + +(defun -split-with (pred list) + "Split LIST into a prefix satisfying PRED, and the rest. +The first sublist is the prefix of LIST with successive elements +satisfying PRED, and the second sublist is the remaining elements +that do not. The result is like performing + + ((-take-while PRED LIST) (-drop-while PRED LIST)) + +but in no more than a single pass through LIST." + (--split-with (funcall pred it) list)) + +(defmacro -split-on (item list) + "Split the LIST each time ITEM is found. + +Unlike `-partition-by', the ITEM is discarded from the results. +Empty lists are also removed from the result. + +Comparison is done by `equal'. + +See also `-split-when'" + (declare (debug (def-form form))) + `(-split-when (lambda (it) (equal it ,item)) ,list)) + +(defmacro --split-when (form list) + "Anaphoric version of `-split-when'." + (declare (debug (def-form form))) + `(-split-when (lambda (it) (ignore it) ,form) ,list)) + +(defun -split-when (fn list) + "Split the LIST on each element where FN returns non-nil. + +Unlike `-partition-by', the \"matched\" element is discarded from +the results. Empty lists are also removed from the result. + +This function can be thought of as a generalization of +`split-string'." + (let (r s) + (while list + (if (not (funcall fn (car list))) + (push (car list) s) + (when s (push (nreverse s) r)) + (setq s nil)) + (!cdr list)) + (when s (push (nreverse s) r)) + (nreverse r))) + +(defmacro --separate (form list) + "Anaphoric form of `-separate'." + (declare (debug (form form))) + (let ((y (make-symbol "yes")) + (n (make-symbol "no"))) + `(let (,y ,n) + (--each ,list (if ,form (!cons it ,y) (!cons it ,n))) + (list (nreverse ,y) (nreverse ,n))))) + +(defun -separate (pred list) + "Split LIST into two sublists based on whether items satisfy PRED. +The result is like performing + + ((-filter PRED LIST) (-remove PRED LIST)) + +but in a single pass through LIST." + (--separate (funcall pred it) list)) + +(defun dash--partition-all-in-steps-reversed (n step list) + "Like `-partition-all-in-steps', but the result is reversed." + (when (< step 1) + (signal 'wrong-type-argument + `("Step size < 1 results in juicy infinite loops" ,step))) + (let (result) + (while list + (push (-take n list) result) + (setq list (nthcdr step list))) + result)) + +(defun -partition-all-in-steps (n step list) + "Partition LIST into sublists of length N that are STEP items apart. +Adjacent groups may overlap if N exceeds the STEP stride. +Trailing groups may contain less than N items." + (declare (pure t) (side-effect-free t)) + (nreverse (dash--partition-all-in-steps-reversed n step list))) + +(defun -partition-in-steps (n step list) + "Partition LIST into sublists of length N that are STEP items apart. +Like `-partition-all-in-steps', but if there are not enough items +to make the last group N-sized, those items are discarded." + (declare (pure t) (side-effect-free t)) + (let ((result (dash--partition-all-in-steps-reversed n step list))) + (while (and result (< (length (car result)) n)) + (pop result)) + (nreverse result))) + +(defun -partition-all (n list) + "Return a new list with the items in LIST grouped into N-sized sublists. +The last group may contain less than N items." + (declare (pure t) (side-effect-free t)) + (-partition-all-in-steps n n list)) + +(defun -partition (n list) + "Return a new list with the items in LIST grouped into N-sized sublists. +If there are not enough items to make the last group N-sized, +those items are discarded." + (declare (pure t) (side-effect-free t)) + (-partition-in-steps n n list)) + +(defmacro --partition-by (form list) + "Anaphoric form of `-partition-by'." + (declare (debug (form form))) + (let ((r (make-symbol "result")) + (s (make-symbol "sublist")) + (v (make-symbol "value")) + (n (make-symbol "new-value")) + (l (make-symbol "list"))) + `(let ((,l ,list)) + (when ,l + (let* ((,r nil) + (it (car ,l)) + (,s (list it)) + (,v ,form) + (,l (cdr ,l))) + (while ,l + (let* ((it (car ,l)) + (,n ,form)) + (unless (equal ,v ,n) + (!cons (nreverse ,s) ,r) + (setq ,s nil) + (setq ,v ,n)) + (!cons it ,s) + (!cdr ,l))) + (!cons (nreverse ,s) ,r) + (nreverse ,r)))))) + +(defun -partition-by (fn list) + "Apply FN to each item in LIST, splitting it each time FN returns a new value." + (--partition-by (funcall fn it) list)) + +(defmacro --partition-by-header (form list) + "Anaphoric form of `-partition-by-header'." + (declare (debug (form form))) + (let ((r (make-symbol "result")) + (s (make-symbol "sublist")) + (h (make-symbol "header-value")) + (b (make-symbol "seen-body?")) + (n (make-symbol "new-value")) + (l (make-symbol "list"))) + `(let ((,l ,list)) + (when ,l + (let* ((,r nil) + (it (car ,l)) + (,s (list it)) + (,h ,form) + (,b nil) + (,l (cdr ,l))) + (while ,l + (let* ((it (car ,l)) + (,n ,form)) + (if (equal ,h ,n) + (when ,b + (!cons (nreverse ,s) ,r) + (setq ,s nil) + (setq ,b nil)) + (setq ,b t)) + (!cons it ,s) + (!cdr ,l))) + (!cons (nreverse ,s) ,r) + (nreverse ,r)))))) + +(defun -partition-by-header (fn list) + "Apply FN to the first item in LIST. That is the header +value. Apply FN to each item in LIST, splitting it each time FN +returns the header value, but only after seeing at least one +other value (the body)." + (--partition-by-header (funcall fn it) list)) + +(defmacro --partition-after-pred (form list) + "Partition LIST after each element for which FORM evaluates to non-nil. +Each element of LIST in turn is bound to `it' before evaluating +FORM. + +This is the anaphoric counterpart to `-partition-after-pred'." + (let ((l (make-symbol "list")) + (r (make-symbol "result")) + (s (make-symbol "sublist"))) + `(let ((,l ,list) ,r ,s) + (when ,l + (--each ,l + (push it ,s) + (when ,form + (push (nreverse ,s) ,r) + (setq ,s ()))) + (when ,s + (push (nreverse ,s) ,r)) + (nreverse ,r))))) + +(defun -partition-after-pred (pred list) + "Partition LIST after each element for which PRED returns non-nil. + +This function's anaphoric counterpart is `--partition-after-pred'." + (--partition-after-pred (funcall pred it) list)) + +(defun -partition-before-pred (pred list) + "Partition directly before each time PRED is true on an element of LIST." + (nreverse (-map #'reverse + (-partition-after-pred pred (reverse list))))) + +(defun -partition-after-item (item list) + "Partition directly after each time ITEM appears in LIST." + (-partition-after-pred (lambda (ele) (equal ele item)) + list)) + +(defun -partition-before-item (item list) + "Partition directly before each time ITEM appears in LIST." + (-partition-before-pred (lambda (ele) (equal ele item)) + list)) + +(defmacro --group-by (form list) + "Anaphoric form of `-group-by'." + (declare (debug t)) + (let ((n (make-symbol "n")) + (k (make-symbol "k")) + (grp (make-symbol "grp"))) + `(nreverse + (-map + (lambda (,n) + (cons (car ,n) + (nreverse (cdr ,n)))) + (--reduce-from + (let* ((,k (,@form)) + (,grp (assoc ,k acc))) + (if ,grp + (setcdr ,grp (cons it (cdr ,grp))) + (push + (list ,k it) + acc)) + acc) + nil ,list))))) + +(defun -group-by (fn list) + "Separate LIST into an alist whose keys are FN applied to the +elements of LIST. Keys are compared by `equal'." + (--group-by (funcall fn it) list)) + +(defun -interpose (sep list) + "Return a new list of all elements in LIST separated by SEP." + (declare (pure t) (side-effect-free t)) + (let (result) + (when list + (!cons (car list) result) + (!cdr list)) + (while list + (setq result (cons (car list) (cons sep result))) + (!cdr list)) + (nreverse result))) + +(defun -interleave (&rest lists) + "Return a new list of the first item in each list, then the second etc." + (declare (pure t) (side-effect-free t)) + (when lists + (let (result) + (while (-none? 'null lists) + (--each lists (!cons (car it) result)) + (setq lists (-map 'cdr lists))) + (nreverse result)))) + +(defmacro --zip-with (form list1 list2) + "Zip LIST1 and LIST2 into a new list according to FORM. +That is, evaluate FORM for each item pair from the two lists, and +return the list of results. The result is as long as the shorter +list. + +Each element of LIST1 and each element of LIST2 in turn are bound +pairwise to `it' and `other', respectively, and their index +within the list to `it-index', before evaluating FORM. + +This is the anaphoric counterpart to `-zip-with'." + (declare (debug (form form form))) + (let ((r (make-symbol "result")) + (l2 (make-symbol "list2"))) + `(let ((,l2 ,list2) ,r) + (--each-while ,list1 ,l2 + (let ((other (pop ,l2))) + (ignore other) + (push ,form ,r))) + (nreverse ,r)))) + +(defun -zip-with (fn list1 list2) + "Zip LIST1 and LIST2 into a new list using the function FN. +That is, apply FN pairwise taking as first argument the next +element of LIST1 and as second argument the next element of LIST2 +at the corresponding position. The result is as long as the +shorter list. + +This function's anaphoric counterpart is `--zip-with'. + +For other zips, see also `-zip-lists' and `-zip-fill'." + (--zip-with (funcall fn it other) list1 list2)) + +(defun -zip-lists (&rest lists) + "Zip LISTS together. + +Group the head of each list, followed by the second element of +each list, and so on. The number of returned groupings is equal +to the length of the shortest input list, and the length of each +grouping is equal to the number of input LISTS. + +The return value is always a list of proper lists, in contrast to +`-zip' which returns a list of dotted pairs when only two input +LISTS are provided. + +See also: `-zip-pair'." + (declare (pure t) (side-effect-free t)) + (when lists + (let (results) + (while (--every it lists) + (push (mapcar #'car lists) results) + (setq lists (mapcar #'cdr lists))) + (nreverse results)))) + +(defun -zip-lists-fill (fill-value &rest lists) + "Zip LISTS together, padding shorter lists with FILL-VALUE. +This is like `-zip-lists' (which see), except it retains all +elements at positions beyond the end of the shortest list. The +number of returned groupings is equal to the length of the +longest input list, and the length of each grouping is equal to +the number of input LISTS." + (declare (pure t) (side-effect-free t)) + (when lists + (let (results) + (while (--some it lists) + (push (--map (if it (car it) fill-value) lists) results) + (setq lists (mapcar #'cdr lists))) + (nreverse results)))) + +(defun -unzip-lists (lists) + "Unzip LISTS. + +This works just like `-zip-lists' (which see), but takes a list +of lists instead of a variable number of arguments, such that + + (-unzip-lists (-zip-lists ARGS...)) + +is identity (given that the lists comprising ARGS are of the same +length)." + (declare (pure t) (side-effect-free t)) + (apply #'-zip-lists lists)) + +(defalias 'dash--length= + (if (fboundp 'length=) + #'length= + (lambda (list length) + (cond ((< length 0) nil) + ((zerop length) (null list)) + ((let ((last (nthcdr (1- length) list))) + (and last (null (cdr last)))))))) + "Return non-nil if LIST is of LENGTH. +This is a compatibility shim for `length=' in Emacs 28. +\n(fn LIST LENGTH)") + +(defun dash--zip-lists-or-pair (_form &rest lists) + "Return a form equivalent to applying `-zip' to LISTS. +This `compiler-macro' warns about discouraged `-zip' usage and +delegates to `-zip-lists' or `-zip-pair' depending on the number +of LISTS." + (if (not (dash--length= lists 2)) + (cons #'-zip-lists lists) + (let ((pair (cons #'-zip-pair lists)) + (msg "Use -zip-pair instead of -zip to get a list of pairs")) + (if (fboundp 'macroexp-warn-and-return) + (macroexp-warn-and-return msg pair) + (message msg) + pair)))) + +(defun -zip (&rest lists) + "Zip LISTS together. + +Group the head of each list, followed by the second element of +each list, and so on. The number of returned groupings is equal +to the length of the shortest input list, and the number of items +in each grouping is equal to the number of input LISTS. + +If only two LISTS are provided as arguments, return the groupings +as a list of dotted pairs. Otherwise, return the groupings as a +list of proper lists. + +Since the return value changes form depending on the number of +arguments, it is generally recommended to use `-zip-lists' +instead, or `-zip-pair' if a list of dotted pairs is desired. + +See also: `-unzip'." + (declare (compiler-macro dash--zip-lists-or-pair) + (pure t) (side-effect-free t)) + ;; For backward compatibility, return a list of dotted pairs if two + ;; arguments were provided. + (apply (if (dash--length= lists 2) #'-zip-pair #'-zip-lists) lists)) + +(defun -zip-pair (&rest lists) + "Zip LIST1 and LIST2 together. + +Make a pair with the head of each list, followed by a pair with +the second element of each list, and so on. The number of pairs +returned is equal to the length of the shorter input list. + +See also: `-zip-lists'." + (declare (advertised-calling-convention (list1 list2) "2.20.0") + (pure t) (side-effect-free t)) + (if (dash--length= lists 2) + (--zip-with (cons it other) (car lists) (cadr lists)) + (apply #'-zip-lists lists))) + +(defun -zip-fill (fill-value &rest lists) + "Zip LISTS together, padding shorter lists with FILL-VALUE. +This is like `-zip' (which see), except it retains all elements +at positions beyond the end of the shortest list. The number of +returned groupings is equal to the length of the longest input +list, and the length of each grouping is equal to the number of +input LISTS. + +Since the return value changes form depending on the number of +arguments, it is generally recommended to use `-zip-lists-fill' +instead, unless a list of dotted pairs is explicitly desired." + (declare (pure t) (side-effect-free t)) + (cond ((null lists) ()) + ((dash--length= lists 2) + (let ((list1 (car lists)) + (list2 (cadr lists)) + results) + (while (or list1 list2) + (push (cons (if list1 (pop list1) fill-value) + (if list2 (pop list2) fill-value)) + results)) + (nreverse results))) + ((apply #'-zip-lists-fill fill-value lists)))) + +(defun -unzip (lists) + "Unzip LISTS. + +This works just like `-zip' (which see), but takes a list of +lists instead of a variable number of arguments, such that + + (-unzip (-zip L1 L2 L3 ...)) + +is identity (given that the lists are of the same length, and +that `-zip' is not called with two arguments, because of the +caveat described in its docstring). + +Note in particular that calling `-unzip' on a list of two lists +will return a list of dotted pairs. + +Since the return value changes form depending on the number of +LISTS, it is generally recommended to use `-unzip-lists' instead." + (declare (pure t) (side-effect-free t)) + (apply #'-zip lists)) + +(defun -cycle (list) + "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)) + ;; Also works with sequences that aren't lists. + (let ((newlist (append list ()))) + (nconc newlist newlist))) + +(defun -pad (fill-value &rest lists) + "Pad each of LISTS with FILL-VALUE until they all have equal lengths. + +Ensure all LISTS are as long as the longest one by repeatedly +appending FILL-VALUE to the shorter lists, and return the +resulting LISTS." + (declare (pure t) (side-effect-free t)) + (let* ((lens (mapcar #'length lists)) + (maxlen (apply #'max 0 lens))) + (--map (append it (make-list (- maxlen (pop lens)) fill-value)) lists))) + +(defmacro --annotate (form list) + "Pair each item in LIST with the result of evaluating FORM. + +Return an alist of (RESULT . ITEM), where each ITEM is the +corresponding element of LIST, and RESULT is the value obtained +by evaluating FORM with ITEM bound to `it'. + +This is the anaphoric counterpart to `-annotate'." + (declare (debug (form form))) + `(--map (cons ,form it) ,list)) + +(defun -annotate (fn list) + "Pair each item in LIST with the result of passing it to FN. + +Return an alist of (RESULT . ITEM), where each ITEM is the +corresponding element of LIST, and RESULT is the value obtained +by calling FN on ITEM. + +This function's anaphoric counterpart is `--annotate'." + (--annotate (funcall fn it) list)) + +(defun dash--table-carry (lists restore-lists &optional re) + "Helper for `-table' and `-table-flat'. + +If a list overflows, carry to the right and reset the list." + (while (not (or (car lists) + (equal lists '(nil)))) + (setcar lists (car restore-lists)) + (pop (cadr lists)) + (!cdr lists) + (!cdr restore-lists) + (when re + (push (nreverse (car re)) (cadr re)) + (setcar re nil) + (!cdr re)))) + +(defun -table (fn &rest lists) + "Compute outer product of LISTS using function FN. + +The function FN should have the same arity as the number of +supplied lists. + +The outer product is computed by applying fn to all possible +combinations created by taking one element from each list in +order. The dimension of the result is (length lists). + +See also: `-table-flat'" + (let ((restore-lists (copy-sequence lists)) + (last-list (last lists)) + (re (make-list (length lists) nil))) + (while (car last-list) + (let ((item (apply fn (-map 'car lists)))) + (push item (car re)) + (setcar lists (cdar lists)) ;; silence byte compiler + (dash--table-carry lists restore-lists re))) + (nreverse (car (last re))))) + +(defun -table-flat (fn &rest lists) + "Compute flat outer product of LISTS using function FN. + +The function FN should have the same arity as the number of +supplied lists. + +The outer product is computed by applying fn to all possible +combinations created by taking one element from each list in +order. The results are flattened, ignoring the tensor structure +of the result. This is equivalent to calling: + + (-flatten-n (1- (length lists)) (apply \\='-table fn lists)) + +but the implementation here is much more efficient. + +See also: `-flatten-n', `-table'" + (let ((restore-lists (copy-sequence lists)) + (last-list (last lists)) + re) + (while (car last-list) + (let ((item (apply fn (-map 'car lists)))) + (push item re) + (setcar lists (cdar lists)) ;; silence byte compiler + (dash--table-carry lists restore-lists))) + (nreverse re))) + +(defmacro --find-index (form list) + "Return the first index in LIST for which FORM evals to non-nil. +Return nil if no such index is found. +Each element of LIST in turn is bound to `it' and its index +within LIST to `it-index' before evaluating FORM. +This is the anaphoric counterpart to `-find-index'." + (declare (debug (form form))) + `(--some (and ,form it-index) ,list)) + +(defun -find-index (pred list) + "Return the index of the first item satisfying PRED in LIST. +Return nil if no such item is found. + +PRED is called with one argument, the current list element, until +it returns non-nil, at which point the search terminates. + +This function's anaphoric counterpart is `--find-index'. + +See also: `-first', `-find-last-index'." + (--find-index (funcall pred it) list)) + +(defun -elem-index (elem list) + "Return the first index of ELEM in LIST. +That is, the index within LIST of the first element that is +`equal' to ELEM. Return nil if there is no such element. + +See also: `-find-index'." + (declare (pure t) (side-effect-free t)) + (--find-index (equal elem it) list)) + +(defmacro --find-indices (form list) + "Return the list of indices in LIST for which FORM evals to non-nil. +Each element of LIST in turn is bound to `it' and its index +within LIST to `it-index' before evaluating FORM. +This is the anaphoric counterpart to `-find-indices'." + (declare (debug (form form))) + `(--keep (and ,form it-index) ,list)) + +(defun -find-indices (pred list) + "Return the list of indices in LIST satisfying PRED. + +Each element of LIST in turn is passed to PRED. If the result is +non-nil, the index of that element in LIST is included in the +result. The returned indices are in ascending order, i.e., in +the same order as they appear in LIST. + +This function's anaphoric counterpart is `--find-indices'. + +See also: `-find-index', `-elem-indices'." + (--find-indices (funcall pred it) list)) + +(defun -elem-indices (elem list) + "Return the list of indices at which ELEM appears in LIST. +That is, the indices of all elements of LIST `equal' to ELEM, in +the same ascending order as they appear in LIST." + (declare (pure t) (side-effect-free t)) + (--find-indices (equal elem it) list)) + +(defmacro --find-last-index (form list) + "Return the last index in LIST for which FORM evals to non-nil. +Return nil if no such index is found. +Each element of LIST in turn is bound to `it' and its index +within LIST to `it-index' before evaluating FORM. +This is the anaphoric counterpart to `-find-last-index'." + (declare (debug (form form))) + (let ((i (make-symbol "index"))) + `(let (,i) + (--each ,list + (when ,form (setq ,i it-index))) + ,i))) + +(defun -find-last-index (pred list) + "Return the index of the last item satisfying PRED in LIST. +Return nil if no such item is found. + +Predicate PRED is called with one argument each time, namely the +current list element. + +This function's anaphoric counterpart is `--find-last-index'. + +See also: `-last', `-find-index'." + (--find-last-index (funcall pred it) list)) + +(defun -select-by-indices (indices list) + "Return a list whose elements are elements from LIST selected +as `(nth i list)` for all i from INDICES." + (declare (pure t) (side-effect-free t)) + (let (r) + (--each indices + (!cons (nth it list) r)) + (nreverse r))) + +(defun -select-columns (columns table) + "Select COLUMNS from TABLE. + +TABLE is a list of lists where each element represents one row. +It is assumed each row has the same length. + +Each row is transformed such that only the specified COLUMNS are +selected. + +See also: `-select-column', `-select-by-indices'" + (declare (pure t) (side-effect-free t)) + (--map (-select-by-indices columns it) table)) + +(defun -select-column (column table) + "Select COLUMN from TABLE. + +TABLE is a list of lists where each element represents one row. +It is assumed each row has the same length. + +The single selected column is returned as a list. + +See also: `-select-columns', `-select-by-indices'" + (declare (pure t) (side-effect-free t)) + (--mapcat (-select-by-indices (list column) it) table)) + +(defmacro -> (x &optional form &rest more) + "Thread the expr through the forms. Insert X as the second item +in the first form, making a list of it if it is not a list +already. If there are more forms, insert the first form as the +second item in second form, etc." + (declare (debug (form &rest [&or symbolp (sexp &rest form)]))) + (cond + ((null form) x) + ((null more) (if (listp form) + `(,(car form) ,x ,@(cdr form)) + (list form x))) + (:else `(-> (-> ,x ,form) ,@more)))) + +(defmacro ->> (x &optional form &rest more) + "Thread the expr through the forms. Insert X as the last item +in the first form, making a list of it if it is not a list +already. If there are more forms, insert the first form as the +last item in second form, etc." + (declare (debug ->)) + (cond + ((null form) x) + ((null more) (if (listp form) + `(,@form ,x) + (list form x))) + (:else `(->> (->> ,x ,form) ,@more)))) + +(defmacro --> (x &rest forms) + "Starting with the value of X, thread each expression through FORMS. + +Insert X at the position signified by the symbol `it' in the first +form. If there are more forms, insert the first form at the position +signified by `it' in in second form, etc." + (declare (debug (form body))) + `(-as-> ,x it ,@forms)) + +(defmacro -as-> (value variable &rest forms) + "Starting with VALUE, thread VARIABLE through FORMS. + +In the first form, bind VARIABLE to VALUE. In the second form, bind +VARIABLE to the result of the first form, and so forth." + (declare (debug (form symbolp body))) + (if (null forms) + `,value + `(let ((,variable ,value)) + (-as-> ,(if (symbolp (car forms)) + (list (car forms) variable) + (car forms)) + ,variable + ,@(cdr forms))))) + +(defmacro -some-> (x &optional form &rest more) + "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)) + (if (null form) x + (let ((result (make-symbol "result"))) + `(-some-> (-when-let (,result ,x) + (-> ,result ,form)) + ,@more)))) + +(defmacro -some->> (x &optional form &rest more) + "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)) + (if (null form) x + (let ((result (make-symbol "result"))) + `(-some->> (-when-let (,result ,x) + (->> ,result ,form)) + ,@more)))) + +(defmacro -some--> (expr &rest forms) + "Thread EXPR through FORMS via `-->', while the result is non-nil. +When EXPR evaluates to non-nil, thread the result through the +first of FORMS, and when that result is non-nil, thread it +through the next form, etc." + (declare (debug (form &rest &or symbolp consp)) (indent 1)) + (if (null forms) expr + (let ((result (make-symbol "result"))) + `(-some--> (-when-let (,result ,expr) + (--> ,result ,(car forms))) + ,@(cdr forms))))) + +(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 &rest &or symbolp consp)) (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. +This yields a permutation vector such that applying this +permutation to LIST sorts it in ascending order." + (->> (--map-indexed (cons it it-index) list) + (-sort (lambda (it other) (funcall comparator (car it) (car other)))) + (mapcar #'cdr))) + +(defun -grade-down (comparator list) + "Grade elements of LIST using COMPARATOR relation. +This yields a permutation vector such that applying this +permutation to LIST sorts it in descending order." + (->> (--map-indexed (cons it it-index) list) + (-sort (lambda (it other) (funcall comparator (car other) (car it)))) + (mapcar #'cdr))) + +(defvar dash--source-counter 0 + "Monotonic counter for generated symbols.") + +(defun dash--match-make-source-symbol () + "Generate a new dash-source symbol. + +All returned symbols are guaranteed to be unique." + (prog1 (make-symbol (format "--dash-source-%d--" dash--source-counter)) + (setq dash--source-counter (1+ dash--source-counter)))) + +(defun dash--match-ignore-place-p (symbol) + "Return non-nil if SYMBOL is a symbol and starts with _." + (and (symbolp symbol) + (eq (aref (symbol-name symbol) 0) ?_))) + +(defun dash--match-cons-skip-cdr (skip-cdr source) + "Helper function generating idiomatic shifting code." + (cond + ((= skip-cdr 0) + `(pop ,source)) + (t + `(prog1 ,(dash--match-cons-get-car skip-cdr source) + (setq ,source ,(dash--match-cons-get-cdr (1+ skip-cdr) source)))))) + +(defun dash--match-cons-get-car (skip-cdr source) + "Helper function generating idiomatic code to get nth car." + (cond + ((= skip-cdr 0) + `(car ,source)) + ((= skip-cdr 1) + `(cadr ,source)) + (t + `(nth ,skip-cdr ,source)))) + +(defun dash--match-cons-get-cdr (skip-cdr source) + "Helper function generating idiomatic code to get nth cdr." + (cond + ((= skip-cdr 0) + source) + ((= skip-cdr 1) + `(cdr ,source)) + (t + `(nthcdr ,skip-cdr ,source)))) + +(defun dash--match-cons (match-form source) + "Setup a cons matching environment and call the real matcher." + (let ((s (dash--match-make-source-symbol)) + (n 0) + (m match-form)) + (while (and (consp m) + (dash--match-ignore-place-p (car m))) + (setq n (1+ n)) (!cdr m)) + (cond + ;; when we only have one pattern in the list, we don't have to + ;; create a temporary binding (--dash-source--) for the source + ;; and just use the input directly + ((and (consp m) + (not (cdr m))) + (dash--match (car m) (dash--match-cons-get-car n source))) + ;; handle other special types + ((> n 0) + (dash--match m (dash--match-cons-get-cdr n source))) + ;; this is the only entry-point for dash--match-cons-1, that's + ;; why we can't simply use the above branch, it would produce + ;; infinite recursion + (t + (cons (list s source) (dash--match-cons-1 match-form s)))))) + +(defun dash--get-expand-function (type) + "Get expand function name for TYPE." + (intern-soft (format "dash-expand:%s" type))) + +(defun dash--match-cons-1 (match-form source &optional props) + "Match MATCH-FORM against SOURCE. + +MATCH-FORM is a proper or improper list. Each element of +MATCH-FORM is either a symbol, which gets bound to the respective +value in source or another match form which gets destructured +recursively. + +If the cdr of last cons cell in the list is nil, matching stops +there. + +SOURCE is a proper or improper list." + (let ((skip-cdr (or (plist-get props :skip-cdr) 0))) + (cond + ((consp match-form) + (cond + ((cdr match-form) + (cond + ((and (symbolp (car match-form)) + (functionp (dash--get-expand-function (car match-form)))) + (dash--match-kv (dash--match-kv-normalize-match-form match-form) (dash--match-cons-get-cdr skip-cdr source))) + ((dash--match-ignore-place-p (car match-form)) + (dash--match-cons-1 (cdr match-form) source + (plist-put props :skip-cdr (1+ skip-cdr)))) + (t + (-concat (dash--match (car match-form) (dash--match-cons-skip-cdr skip-cdr source)) + (dash--match-cons-1 (cdr match-form) source))))) + (t ;; Last matching place, no need for shift + (dash--match (car match-form) (dash--match-cons-get-car skip-cdr source))))) + ((eq match-form nil) + nil) + (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--match-vector (match-form source) + "Setup a vector matching environment and call the real matcher." + (let ((s (dash--match-make-source-symbol))) + (cond + ;; don't bind `s' if we only have one sub-pattern + ((= (length match-form) 1) + (dash--match (aref match-form 0) `(aref ,source 0))) + ;; if the source is a symbol, we don't need to re-bind it + ((symbolp source) + (dash--match-vector-1 match-form source)) + ;; don't bind `s' if we only have one sub-pattern which is not ignored + ((let* ((ignored-places (mapcar 'dash--match-ignore-place-p match-form)) + (ignored-places-n (length (-remove 'null ignored-places)))) + (when (= ignored-places-n (1- (length match-form))) + (let ((n (-find-index 'null ignored-places))) + (dash--match (aref match-form n) `(aref ,source ,n)))))) + (t + (cons (list s source) (dash--match-vector-1 match-form s)))))) + +(defun dash--match-vector-1 (match-form source) + "Match MATCH-FORM against SOURCE. + +MATCH-FORM is a vector. Each element of MATCH-FORM is either a +symbol, which gets bound to the respective value in source or +another match form which gets destructured recursively. + +If second-from-last place in MATCH-FORM is the symbol &rest, the +next element of the MATCH-FORM is matched against the tail of +SOURCE, starting at index of the &rest symbol. This is +conceptually the same as the (head . tail) match for improper +lists, where dot plays the role of &rest. + +SOURCE is a vector. + +If the MATCH-FORM vector is shorter than SOURCE vector, only +the (length MATCH-FORM) places are bound, the rest of the SOURCE +is discarded." + (let ((i 0) + (l (length match-form)) + (re)) + (while (< i l) + (let ((m (aref match-form i))) + (push (cond + ((and (symbolp m) + (eq m '&rest)) + (prog1 (dash--match + (aref match-form (1+ i)) + `(substring ,source ,i)) + (setq i l))) + ((and (symbolp m) + ;; do not match symbols starting with _ + (not (eq (aref (symbol-name m) 0) ?_))) + (list (list m `(aref ,source ,i)))) + ((not (symbolp m)) + (dash--match m `(aref ,source ,i)))) + re) + (setq i (1+ i)))) + (-flatten-n 1 (nreverse re)))) + +(defun dash--match-kv-normalize-match-form (pattern) + "Normalize kv PATTERN. + +This method normalizes PATTERN to the format expected by +`dash--match-kv'. See `-let' for the specification." + (let ((normalized (list (car pattern))) + (skip nil) + (fill-placeholder (make-symbol "--dash-fill-placeholder--"))) + (-each (-zip-fill fill-placeholder (cdr pattern) (cddr pattern)) + (lambda (pair) + (let ((current (car pair)) + (next (cdr pair))) + (if skip + (setq skip nil) + (if (or (eq fill-placeholder next) + (not (or (and (symbolp next) + (not (keywordp next)) + (not (eq next t)) + (not (eq next nil))) + (and (consp next) + (not (eq (car next) 'quote))) + (vectorp next)))) + (progn + (cond + ((keywordp current) + (push current normalized) + (push (intern (substring (symbol-name current) 1)) normalized)) + ((stringp current) + (push current normalized) + (push (intern current) normalized)) + ((and (consp current) + (eq (car current) 'quote)) + (push current normalized) + (push (cadr current) normalized)) + (t (error "-let: found key `%s' in kv destructuring but its pattern `%s' is invalid and can not be derived from the key" current next))) + (setq skip nil)) + (push current normalized) + (push next normalized) + (setq skip t)))))) + (nreverse normalized))) + +(defun dash--match-kv (match-form source) + "Setup a kv matching environment and call the real matcher. + +kv can be any key-value store, such as plist, alist or hash-table." + (let ((s (dash--match-make-source-symbol))) + (cond + ;; don't bind `s' if we only have one sub-pattern (&type key val) + ((= (length match-form) 3) + (dash--match-kv-1 (cdr match-form) source (car match-form))) + ;; if the source is a symbol, we don't need to re-bind it + ((symbolp source) + (dash--match-kv-1 (cdr match-form) source (car match-form))) + (t + (cons (list s source) (dash--match-kv-1 (cdr match-form) s (car match-form))))))) + +(defun dash-expand:&hash (key source) + "Generate extracting KEY from SOURCE for &hash destructuring." + `(gethash ,key ,source)) + +(defun dash-expand:&plist (key source) + "Generate extracting KEY from SOURCE for &plist destructuring." + `(plist-get ,source ,key)) + +(defun dash-expand:&alist (key source) + "Generate extracting KEY from SOURCE for &alist destructuring." + `(cdr (assoc ,key ,source))) + +(defun dash-expand:&hash? (key source) + "Generate extracting KEY from SOURCE for &hash? destructuring. +Similar to &hash but check whether the map is not nil." + (let ((src (make-symbol "src"))) + `(let ((,src ,source)) + (when ,src (gethash ,key ,src))))) + +(defalias 'dash-expand:&keys 'dash-expand:&plist) + +(defun dash--match-kv-1 (match-form source type) + "Match MATCH-FORM against SOURCE of type TYPE. + +MATCH-FORM is a proper list of the form (key1 place1 ... keyN +placeN). Each placeK is either a symbol, which gets bound to the +value of keyK retrieved from the key-value store, or another +match form which gets destructured recursively. + +SOURCE is a key-value store of type TYPE, which can be a plist, +an alist or a hash table. + +TYPE is a token specifying the type of the key-value store. +Valid values are &plist, &alist and &hash." + (-flatten-n 1 (-map + (lambda (kv) + (let* ((k (car kv)) + (v (cadr kv)) + (getter + (funcall (dash--get-expand-function type) k source))) + (cond + ((symbolp v) + (list (list v getter))) + (t (dash--match v getter))))) + (-partition 2 match-form)))) + +(defun dash--match-symbol (match-form source) + "Bind a symbol. + +This works just like `let', there is no destructuring." + (list (list match-form source))) + +(defun dash--match (match-form source) + "Match MATCH-FORM against SOURCE. + +This function tests the MATCH-FORM and dispatches to specific +matchers based on the type of the expression. + +Key-value stores are disambiguated by placing a token &plist, +&alist or &hash as a first item in the MATCH-FORM." + (cond + ((and (symbolp match-form) + ;; Don't bind things like &keys as if they were vars (#395). + (not (functionp (dash--get-expand-function match-form)))) + (dash--match-symbol match-form source)) + ((consp match-form) + (cond + ;; Handle the "x &as" bindings first. + ((and (consp (cdr match-form)) + (symbolp (car match-form)) + (eq '&as (cadr match-form))) + (let ((s (car match-form))) + (cons (list s source) + (dash--match (cddr match-form) s)))) + ((functionp (dash--get-expand-function (car match-form))) + (dash--match-kv (dash--match-kv-normalize-match-form match-form) source)) + (t (dash--match-cons match-form source)))) + ((vectorp match-form) + ;; We support the &as binding in vectors too + (cond + ((and (> (length match-form) 2) + (symbolp (aref match-form 0)) + (eq '&as (aref match-form 1))) + (let ((s (aref match-form 0))) + (cons (list s source) + (dash--match (substring match-form 2) s)))) + (t (dash--match-vector match-form source)))))) + +(defun dash--normalize-let-varlist (varlist) + "Normalize VARLIST so that every binding is a list. + +`let' allows specifying a binding which is not a list but simply +the place which is then automatically bound to nil, such that all +three of the following are identical and evaluate to nil. + + (let (a) a) + (let ((a)) a) + (let ((a nil)) a) + +This function normalizes all of these to the last form." + (--map (if (consp it) it (list it nil)) varlist)) + +(defmacro -let* (varlist &rest body) + "Bind variables according to VARLIST then eval BODY. + +VARLIST is a list of lists of the form (PATTERN SOURCE). Each +PATTERN is matched against the SOURCE structurally. SOURCE is +only evaluated once for each PATTERN. + +Each SOURCE can refer to the symbols already bound by this +VARLIST. This is useful if you want to destructure SOURCE +recursively but also want to name the intermediate structures. + +See `-let' for the list of all possible patterns." + (declare (debug ((&rest [&or (sexp form) sexp]) body)) + (indent 1)) + (let* ((varlist (dash--normalize-let-varlist varlist)) + (bindings (--mapcat (dash--match (car it) (cadr it)) varlist))) + `(let* ,bindings + ,@body))) + +(defmacro -let (varlist &rest body) + "Bind variables according to VARLIST then eval BODY. + +VARLIST is a list of lists of the form (PATTERN SOURCE). Each +PATTERN is matched against the SOURCE \"structurally\". SOURCE +is only evaluated once for each PATTERN. Each PATTERN is matched +recursively, and can therefore contain sub-patterns which are +matched against corresponding sub-expressions of SOURCE. + +All the SOURCEs are evalled before any symbols are +bound (i.e. \"in parallel\"). + +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)) ...) + +becomes + + (-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 +entries you don't care about. However, this is not *always* +possible (as a result of implementation) and these symbols might +get bound to undefined values. + +Following is the overview of supported patterns. Remember that +patterns can be matched recursively, so every a, b, aK in the +following can be a matching construct and not necessarily a +symbol/variable. + +Symbol: + + a - bind the SOURCE to A. This is just like regular `let'. + +Conses and lists: + + (a) - bind `car' of cons/list to A + + (a . b) - bind car of cons to A and `cdr' to B + + (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 ... 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 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 sequence to REST. This is + conceptually the same as improper list + matching (a1 a2 ... aN . rest) + +Key/value stores: + + (&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 + 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 + SOURCE hash table to aK. If the + value is not found, aK is nil. + Uses `gethash' to fetch values. + +Further, special keyword &keys supports \"inline\" matching of +plist-like key-value pairs, similarly to &keys keyword of +`cl-defun'. + + (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). + +A shorthand notation for kv-destructuring exists which allows the +patterns be optionally left out and derived from the key name in +the following fashion: + +- a key :foo is converted into `foo' pattern, +- a key \\='bar is converted into `bar' pattern, +- a key \"baz\" is converted into `baz' pattern. + +That is, the entire value under the key is bound to the derived +variable without any further destructuring. + +This is possible only when the form following the key is not a +valid pattern (i.e. not a symbol, a cons cell or a vector). +Otherwise the matching proceeds as usual and in case of an +invalid spec fails with an error. + +Thus the patterns are normalized as follows: + + ;; derive all the missing patterns + (&plist :foo \\='bar \"baz\") => (&plist :foo foo \\='bar bar \"baz\" baz) + + ;; we can specify some but not others + (&plist :foo \\='bar explicit-bar) => (&plist :foo foo \\='bar explicit-bar) + + ;; nothing happens, we store :foo in x + (&plist :foo x) => (&plist :foo x) + + ;; nothing happens, we match recursively + (&plist :foo (a b c)) => (&plist :foo (a b c)) + +You can name the source using the syntax SYMBOL &as PATTERN. +This syntax works with lists (proper or improper), vectors and +all types of maps. + + (list &as a b c) (list 1 2 3) + +binds A to 1, B to 2, C to 3 and LIST to (1 2 3). + +Similarly: + + (bounds &as beg . end) (cons 1 2) + +binds BEG to 1, END to 2 and BOUNDS to (1 . 2). + + (items &as first . rest) (list 1 2 3) + +binds FIRST to 1, REST to (2 3) and ITEMS to (1 2 3) + + [vect &as _ b c] [1 2 3] + +binds B to 2, C to 3 and VECT to [1 2 3] (_ avoids binding as usual). + + (plist &as &plist :b b) (list :a 1 :b 2 :c 3) + +binds B to 2 and PLIST to (:a 1 :b 2 :c 3). Same for &alist and &hash. + +This is especially useful when we want to capture the result of a +computation and destructure at the same time. Consider the +form (function-returning-complex-structure) returning a list of +two vectors with two items each. We want to capture this entire +result and pass it to another computation, but at the same time +we want to get the second item from each vector. We can achieve +it with pattern + + (result &as [_ a] [_ b]) (function-returning-complex-structure) + +Note: Clojure programmers may know this feature as the \":as +binding\". The difference is that we put the &as at the front +because we need to support improper list binding." + (declare (debug ([&or (&rest [&or (sexp form) sexp]) + (vector [&rest [sexp form]])] + body)) + (indent 1)) + (if (vectorp varlist) + `(let* ,(dash--match (aref varlist 0) (aref varlist 1)) + ,@body) + (let* ((varlist (dash--normalize-let-varlist varlist)) + (inputs (--map-indexed (list (make-symbol (format "input%d" it-index)) (cadr it)) varlist)) + (new-varlist (--zip-with (list (car it) (car other)) + varlist inputs))) + `(let ,inputs + (-let* ,new-varlist ,@body))))) + +(defmacro -lambda (match-form &rest body) + "Return a lambda which destructures its input as MATCH-FORM and executes BODY. + +Note that you have to enclose the MATCH-FORM in a pair of parens, +such that: + + (-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. + +See `-let' for a description of the destructuring mechanism." + (declare (doc-string 2) (indent defun) + (debug (&define sexp + [&optional stringp] + [&optional ("interactive" interactive)] + def-body))) + (cond + ((nlistp match-form) + (signal 'wrong-type-argument (list #'listp match-form))) + ;; No destructuring, so just return regular `lambda' for speed. + ((-all? #'symbolp match-form) + `(lambda ,match-form ,@body)) + ((let ((inputs (--map-indexed + (list it (make-symbol (format "input%d" it-index))) + match-form))) + ;; TODO: because inputs to the `lambda' are evaluated only once, + ;; `-let*' need not create the extra bindings to ensure that. + ;; We should find a way to optimize that. Not critical however. + `(lambda ,(mapcar #'cadr inputs) + (-let* ,inputs ,@body)))))) + +(defmacro -setq (&rest forms) + "Bind each MATCH-FORM to the value of its VAL. + +MATCH-FORM destructuring is done according to the rules of `-let'. + +This macro allows you to bind multiple variables by destructuring +the value, so for example: + + (-setq (a b) x + (&plist :c c) plist) + +expands roughly speaking to the following code + + (setq a (car x) + b (cadr x) + c (plist-get plist :c)) + +Care is taken to only evaluate each VAL once so that in case of +multiple assignments it does not cause unexpected side effects. + +\(fn [MATCH-FORM VAL]...)" + (declare (debug (&rest sexp form)) + (indent 1)) + (when (= (mod (length forms) 2) 1) + (signal 'wrong-number-of-arguments (list '-setq (1+ (length forms))))) + (let* ((forms-and-sources + ;; First get all the necessary mappings with all the + ;; intermediate bindings. + (-map (lambda (x) (dash--match (car x) (cadr x))) + (-partition 2 forms))) + ;; To preserve the logic of dynamic scoping we must ensure + ;; that we `setq' the variables outside of the `let*' form + ;; which holds the destructured intermediate values. For + ;; this we generate for each variable a placeholder which is + ;; bound to (lexically) the result of the destructuring. + ;; Then outside of the helper `let*' form we bind all the + ;; original variables to their respective placeholders. + ;; TODO: There is a lot of room for possible optimization, + ;; for start playing with `special-variable-p' to eliminate + ;; unnecessary re-binding. + (variables-to-placeholders + (-mapcat + (lambda (bindings) + (-map + (lambda (binding) + (let ((var (car binding))) + (list var (make-symbol (concat "--dash-binding-" (symbol-name var) "--"))))) + (--filter (not (string-prefix-p "--" (symbol-name (car it)))) bindings))) + forms-and-sources))) + `(let ,(-map 'cadr variables-to-placeholders) + (let* ,(-flatten-n 1 forms-and-sources) + (setq ,@(-flatten (-map 'reverse variables-to-placeholders)))) + (setq ,@(-flatten variables-to-placeholders))))) + +(defmacro -if-let* (vars-vals then &rest else) + "If all VALS evaluate to true, bind them to their corresponding +VARS and do THEN, otherwise do ELSE. VARS-VALS should be a list +of (VAR VAL) pairs. + +Note: binding is done according to `-let*'. VALS are evaluated +sequentially, and evaluation stops after the first nil VAL is +encountered." + (declare (debug ((&rest (sexp form)) form body)) + (indent 2)) + (->> vars-vals + (--mapcat (dash--match (car it) (cadr it))) + (--reduce-r-from + (let ((var (car it)) + (val (cadr it))) + `(let ((,var ,val)) + (if ,var ,acc ,@else))) + then))) + +(defmacro -if-let (var-val then &rest else) + "If VAL evaluates to non-nil, bind it to VAR and do THEN, +otherwise do ELSE. + +Note: binding is done according to `-let'. + +\(fn (VAR VAL) THEN &rest ELSE)" + (declare (debug ((sexp form) form body)) + (indent 2)) + `(-if-let* (,var-val) ,then ,@else)) + +(defmacro --if-let (val then &rest else) + "If VAL evaluates to non-nil, bind it to symbol `it' and do THEN, +otherwise do ELSE." + (declare (debug (form form body)) + (indent 2)) + `(-if-let (it ,val) ,then ,@else)) + +(defmacro -when-let* (vars-vals &rest body) + "If all VALS evaluate to true, bind them to their corresponding +VARS and execute body. VARS-VALS should be a list of (VAR VAL) +pairs. + +Note: binding is done according to `-let*'. VALS are evaluated +sequentially, and evaluation stops after the first nil VAL is +encountered." + (declare (debug ((&rest (sexp form)) body)) + (indent 1)) + `(-if-let* ,vars-vals (progn ,@body))) + +(defmacro -when-let (var-val &rest body) + "If VAL evaluates to non-nil, bind it to VAR and execute body. + +Note: binding is done according to `-let'. + +\(fn (VAR VAL) &rest BODY)" + (declare (debug ((sexp form) body)) + (indent 1)) + `(-if-let ,var-val (progn ,@body))) + +(defmacro --when-let (val &rest body) + "If VAL evaluates to non-nil, bind it to symbol `it' and +execute body." + (declare (debug (form body)) + (indent 1)) + `(--if-let ,val (progn ,@body))) + +;; TODO: Get rid of this dynamic variable, passing it as an argument +;; instead? +(defvar -compare-fn nil + "Tests for equality use this function, or `equal' if this is nil. + +As a dynamic variable, this should be temporarily bound around +the relevant operation, rather than permanently modified. For +example: + + (let ((-compare-fn #\\='=)) + (-union \\='(1 2 3) \\='(2 3 4)))") + +(defun dash--member-fn () + "Return the flavor of `member' that goes best with `-compare-fn'." + (declare (side-effect-free error-free)) + (let ((cmp -compare-fn)) + (cond ((memq cmp '(nil equal)) #'member) + ((eq cmp #'eq) #'memq) + ((eq cmp #'eql) #'memql) + ((lambda (elt list) + (while (and list (not (funcall cmp elt (car list)))) + (pop list)) + list))))) + +(defun dash--assoc-fn () + "Return the flavor of `assoc' that goes best with `-compare-fn'." + (declare (side-effect-free error-free)) + (let ((cmp -compare-fn)) + (cond ((memq cmp '(nil equal)) #'assoc) + ((eq cmp #'eq) #'assq) + ;; Since Emacs 26, `assoc' accepts a custom `testfn'. + ;; Version testing would be simpler here, but feature + ;; testing gets more brownie points, I guess. + ((condition-case nil + (with-no-warnings (assoc nil () #'eql)) + (wrong-number-of-arguments t)) + (lambda (key alist) + (--first (and (consp it) (funcall cmp (car it) key)) alist))) + ((with-no-warnings + (lambda (key alist) + (assoc key alist cmp))))))) + +(defun dash--hash-test-fn () + "Return the hash table test function corresponding to `-compare-fn'. +Return nil if `-compare-fn' is not a known test function." + (declare (side-effect-free error-free)) + ;; In theory this could also recognize values that are custom + ;; `hash-table-test's, but too often the :test name is different + ;; from the equality function, so it doesn't seem worthwile. + (car (memq (or -compare-fn #'equal) '(equal eq eql)))) + +(defvar dash--short-list-length 32 + "Maximum list length considered short, for optimizations. +For example, the speedup afforded by hash table lookup may start +to outweigh its runtime and memory overhead for problem sizes +greater than this value. See also the discussion in PR #305.") + +(defun -distinct (list) + "Return a copy of LIST with all duplicate elements removed. + +The test for equality is done with `equal', or with `-compare-fn' +if that is non-nil. + +Alias: `-uniq'." + (let (test len) + (cond ((null list) ()) + ;; Use a hash table if `-compare-fn' is a known hash table + ;; test function and the list is long enough. + ((and (setq test (dash--hash-test-fn)) + (> (setq len (length list)) dash--short-list-length)) + (let ((ht (make-hash-table :test test :size len))) + (--filter (unless (gethash it ht) (puthash it t ht)) list))) + ((let ((member (dash--member-fn)) uniq) + (--each list (unless (funcall member it uniq) (push it uniq))) + (nreverse uniq)))))) + +(defalias '-uniq #'-distinct) + +(defun dash--size+ (size1 size2) + "Return the sum of nonnegative fixnums SIZE1 and SIZE2. +Return `most-positive-fixnum' on overflow. This ensures the +result is a valid size, particularly for allocating hash tables, +even in the presence of bignum support." + (declare (side-effect-free t)) + (if (< size1 (- most-positive-fixnum size2)) + (+ size1 size2) + most-positive-fixnum)) + +(defun -union (list1 list2) + "Return a new list of distinct elements appearing in either LIST1 or LIST2. + +The test for equality is done with `equal', or with `-compare-fn' +if that is non-nil." + (let ((lists (list list1 list2)) test len union) + (cond ((null (or list1 list2))) + ;; Use a hash table if `-compare-fn' is a known hash table + ;; test function and the lists are long enough. + ((and (setq test (dash--hash-test-fn)) + (> (setq len (dash--size+ (length list1) (length list2))) + dash--short-list-length)) + (let ((ht (make-hash-table :test test :size len))) + (dolist (l lists) + (--each l (unless (gethash it ht) + (puthash it t ht) + (push it union)))))) + ((let ((member (dash--member-fn))) + (dolist (l lists) + (--each l (unless (funcall member it union) (push it union))))))) + (nreverse union))) + +(defun -intersection (list1 list2) + "Return a new list of distinct elements appearing in both LIST1 and LIST2. + +The test for equality is done with `equal', or with `-compare-fn' +if that is non-nil." + (let (test len) + (cond ((null (and list1 list2)) ()) + ;; Use a hash table if `-compare-fn' is a known hash table + ;; test function and either list is long enough. + ((and (setq test (dash--hash-test-fn)) + (> (setq len (length list2)) dash--short-list-length)) + (let ((ht (make-hash-table :test test :size len))) + (--each list2 (puthash it t ht)) + ;; Remove visited elements to avoid duplicates. + (--filter (when (gethash it ht) (remhash it ht) t) list1))) + ((let ((member (dash--member-fn)) intersection) + (--each list1 (and (funcall member it list2) + (not (funcall member it intersection)) + (push it intersection))) + (nreverse intersection)))))) + +(defun -difference (list1 list2) + "Return a new list with the distinct members of LIST1 that are not in LIST2. + +The test for equality is done with `equal', or with `-compare-fn' +if that is non-nil." + (let (test len1 len2) + (cond ((null list1) ()) + ((null list2) (-distinct list1)) + ;; Use a hash table if `-compare-fn' is a known hash table + ;; test function and the subtrahend is long enough. + ((and (setq test (dash--hash-test-fn)) + (setq len1 (length list1)) + (setq len2 (length list2)) + (> (max len1 len2) dash--short-list-length)) + (let ((ht1 (make-hash-table :test test :size len1)) + (ht2 (make-hash-table :test test :size len2))) + (--each list2 (puthash it t ht2)) + ;; Avoid duplicates by tracking visited items in `ht1'. + (--filter (unless (or (gethash it ht2) (gethash it ht1)) + (puthash it t ht1)) + list1))) + ((let ((member (dash--member-fn)) difference) + (--each list1 + (unless (or (funcall member it list2) + (funcall member it difference)) + (push it difference))) + (nreverse difference)))))) + +(defun -powerset (list) + "Return the power set of LIST." + (if (null list) (list ()) + (let ((last (-powerset (cdr list)))) + (nconc (mapcar (lambda (x) (cons (car list) x)) last) + last)))) + +(defun -frequencies (list) + "Count the occurrences of each distinct element of LIST. + +Return an alist of (ELEMENT . N), where each ELEMENT occurs N +times in LIST. + +The test for equality is done with `equal', or with `-compare-fn' +if that is non-nil. + +See also `-count' and `-group-by'." + (let (test len freqs) + (cond ((null list)) + ((and (setq test (dash--hash-test-fn)) + (> (setq len (length list)) dash--short-list-length)) + (let ((ht (make-hash-table :test test :size len))) + ;; Share structure between hash table and returned list. + ;; This affords a single pass that preserves the input + ;; order, conses less garbage, and is faster than a + ;; second traversal (e.g., with `maphash'). + (--each list + (let ((freq (gethash it ht))) + (if freq + (setcdr freq (1+ (cdr freq))) + (push (puthash it (cons it 1) ht) freqs)))))) + ((let ((assoc (dash--assoc-fn))) + (--each list + (let ((freq (funcall assoc it freqs))) + (if freq + (setcdr freq (1+ (cdr freq))) + (push (cons it 1) freqs))))))) + (nreverse freqs))) + +(defun dash--numbers<= (nums) + "Return non-nil if NUMS is a list of non-decreasing numbers." + (declare (pure t) (side-effect-free t)) + (or (null nums) + (let ((prev (pop nums))) + (and (numberp prev) + (--every (and (numberp it) (<= prev (setq prev it))) nums))))) + +(defun dash--next-lex-perm (array n) + "Update ARRAY of N numbers with its next lexicographic permutation. +Return nil if there is no such successor. N should be nonzero. + +This implements the salient steps of Algorithm L (Lexicographic +permutation generation) as described in DE Knuth's The Art of +Computer Programming, Volume 4A / Combinatorial Algorithms, +Part I, Addison-Wesley, 2011, § 7.2.1.2, p. 319." + (setq n (1- n)) + (let* ((l n) + (j (1- n)) + (al (aref array n)) + (aj al)) + ;; L2. [Find j]. + ;; Decrement j until a[j] < a[j+1]. + (while (and (<= 0 j) + (<= aj (setq aj (aref array j)))) + (setq j (1- j))) + ;; Terminate algorithm if j not found. + (when (>= j 0) + ;; L3. [Increase a[j]]. + ;; Decrement l until a[j] < a[l]. + (while (>= aj al) + (setq l (1- l) al (aref array l))) + ;; Swap a[j] and a[l]. + (aset array j al) + (aset array l aj) + ;; L4. [Reverse a[j+1]...a[n]]. + (setq l n) + (while (< (setq j (1+ j)) l) + (setq aj (aref array j)) + (aset array j (aref array l)) + (aset array l aj) + (setq l (1- l))) + array))) + +(defun dash--lex-perms (vec &optional original) + "Return a list of permutations of VEC in lexicographic order. +Specifically, return only the successors of VEC in lexicographic +order. Each returned permutation is a list. VEC should comprise +one or more numbers, and may be destructively modified. + +If ORIGINAL is a vector, then VEC is interpreted as a set of +indices into ORIGINAL. In this case, the indices are permuted, +and the resulting index permutations are used to dereference +elements of ORIGINAL." + (let ((len (length vec)) perms) + (while vec + (push (if original + (--map (aref original it) vec) + (append vec ())) + perms) + (setq vec (dash--next-lex-perm vec len))) + (nreverse perms))) + +(defun dash--uniq-perms (list) + "Return a list of permutations of LIST. +LIST is treated as if all its elements are distinct." + (let* ((vec (vconcat list)) + (idxs (copy-sequence vec))) + ;; Just construct a vector of the list's indices and permute that. + (dotimes (i (length idxs)) + (aset idxs i i)) + (dash--lex-perms idxs vec))) + +(defun dash--multi-perms (list freqs) + "Return a list of permutations of the multiset LIST. +FREQS should be an alist describing the frequency of each element +in LIST, as returned by `-frequencies'." + (let (;; Distinct items in `list', aka the cars of `freqs'. + (uniq (make-vector (length freqs) nil)) + ;; Indices into `uniq'. + (idxs (make-vector (length list) nil)) + ;; Current index into `idxs'. + (i 0)) + (--each freqs + (aset uniq it-index (car it)) + ;; Populate `idxs' with as many copies of each `it-index' as + ;; there are corresponding duplicates. + (dotimes (_ (cdr it)) + (aset idxs i it-index) + (setq i (1+ i)))) + (dash--lex-perms idxs uniq))) + +(defun -permutations (list) + "Return the distinct permutations of LIST. + +Duplicate elements of LIST are determined by `equal', or by +`-compare-fn' if that is non-nil." + (cond ((null list) (list ())) + ;; Optimization: a traversal of `list' is faster than the + ;; round trip via `dash--uniq-perms' or `dash--multi-perms'. + ((dash--numbers<= list) + (dash--lex-perms (vconcat list))) + ((let ((freqs (-frequencies list))) + ;; Is each element distinct? + (unless (--every (= (cdr it) 1) freqs) + (dash--multi-perms list freqs)))) + ((dash--uniq-perms list)))) + +(defun -inits (list) + "Return all prefixes of LIST." + (let ((res (list list))) + (setq list (reverse list)) + (while list + (push (reverse (!cdr list)) res)) + res)) + +(defun -tails (list) + "Return all suffixes of LIST" + (-reductions-r-from 'cons nil list)) + +(defun -common-prefix (&rest lists) + "Return the longest common prefix of LISTS." + (declare (pure t) (side-effect-free t)) + (--reduce (--take-while (and acc (equal (pop acc) it)) it) + lists)) + +(defun -common-suffix (&rest lists) + "Return the longest common suffix of LISTS." + (nreverse (apply #'-common-prefix (mapcar #'reverse lists)))) + +(defun -contains? (list element) + "Return non-nil if LIST contains ELEMENT. + +The test for equality is done with `equal', or with `-compare-fn' +if that is non-nil. As with `member', the return value is +actually the tail of LIST whose car is ELEMENT. + +Alias: `-contains-p'." + (funcall (dash--member-fn) element list)) + +(defalias '-contains-p #'-contains?) + +(defun -same-items? (list1 list2) + "Return non-nil if LIST1 and LIST2 have the same distinct elements. + +The order of the elements in the lists does not matter. The +lists may be of different lengths, i.e., contain duplicate +elements. The test for equality is done with `equal', or with +`-compare-fn' if that is non-nil. + +Alias: `-same-items-p'." + (let (test len1 len2) + (cond ((null (or list1 list2))) + ((null (and list1 list2)) nil) + ;; Use a hash table if `-compare-fn' is a known hash table + ;; test function and either list is long enough. + ((and (setq test (dash--hash-test-fn)) + (setq len1 (length list1)) + (setq len2 (length list2)) + (> (max len1 len2) dash--short-list-length)) + (let ((ht1 (make-hash-table :test test :size len1)) + (ht2 (make-hash-table :test test :size len2))) + (--each list1 (puthash it t ht1)) + ;; Move visited elements from `ht1' to `ht2'. This way, + ;; if visiting all of `list2' leaves `ht1' empty, then + ;; all elements from both lists have been accounted for. + (and (--every (cond ((gethash it ht1) + (remhash it ht1) + (puthash it t ht2)) + ((gethash it ht2))) + list2) + (zerop (hash-table-count ht1))))) + ((let ((member (dash--member-fn))) + (and (--all? (funcall member it list2) list1) + (--all? (funcall member it list1) list2))))))) + +(defalias '-same-items-p #'-same-items?) + +(defun -is-prefix? (prefix list) + "Return non-nil if PREFIX is a prefix of LIST. + +Alias: `-is-prefix-p'." + (declare (pure t) (side-effect-free t)) + (--each-while list (and (equal (car prefix) it) + (!cdr prefix))) + (null prefix)) + +(defun -is-suffix? (suffix list) + "Return non-nil if SUFFIX is a suffix of LIST. + +Alias: `-is-suffix-p'." + (declare (pure t) (side-effect-free t)) + (equal suffix (last list (length suffix)))) + +(defun -is-infix? (infix list) + "Return non-nil if INFIX is infix of LIST. + +This operation runs in O(n^2) time + +Alias: `-is-infix-p'" + (declare (pure t) (side-effect-free t)) + (let (done) + (while (and (not done) list) + (setq done (-is-prefix? infix list)) + (!cdr list)) + done)) + +(defalias '-is-prefix-p '-is-prefix?) +(defalias '-is-suffix-p '-is-suffix?) +(defalias '-is-infix-p '-is-infix?) + +(defun -sort (comparator list) + "Sort LIST, stably, comparing elements using COMPARATOR. +Return the sorted list. LIST is NOT modified by side effects. +COMPARATOR is called with two elements of LIST, and should return non-nil +if the first element should sort before the second." + (sort (copy-sequence list) comparator)) + +(defmacro --sort (form list) + "Anaphoric form of `-sort'." + (declare (debug (def-form form))) + `(-sort (lambda (it other) (ignore it other) ,form) ,list)) + +(defun -list (&optional arg &rest args) + "Ensure ARG is a list. +If ARG is already a list, return it as is (not a copy). +Otherwise, return a new list with ARG as its only element. + +Another supported calling convention is (-list &rest ARGS). +In this case, if ARG is not a list, a new list with all of +ARGS as elements is returned. This use is supported for +backward compatibility and is otherwise deprecated." + (declare (advertised-calling-convention (arg) "2.18.0") + (pure t) (side-effect-free error-free)) + (if (listp arg) arg (cons arg args))) + +(defun -repeat (n x) + "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)) + (and (>= n 0) (make-list n x))) + +(defun -sum (list) + "Return the sum of LIST." + (declare (pure t) (side-effect-free t)) + (apply #'+ list)) + +(defun -running-sum (list) + "Return a list with running sums of items in LIST. +LIST must be non-empty." + (declare (pure t) (side-effect-free t)) + (or list (signal 'wrong-type-argument (list #'consp list))) + (-reductions #'+ list)) + +(defun -product (list) + "Return the product of LIST." + (declare (pure t) (side-effect-free t)) + (apply #'* list)) + +(defun -running-product (list) + "Return a list with running products of items in LIST. +LIST must be non-empty." + (declare (pure t) (side-effect-free t)) + (or list (signal 'wrong-type-argument (list #'consp list))) + (-reductions #'* list)) + +(defun -max (list) + "Return the largest value from LIST of numbers or markers." + (declare (pure t) (side-effect-free t)) + (apply #'max list)) + +(defun -min (list) + "Return the smallest value from LIST of numbers or markers." + (declare (pure t) (side-effect-free t)) + (apply #'min list)) + +(defun -max-by (comparator list) + "Take a comparison function COMPARATOR and a LIST and return +the greatest element of the list by the comparison function. + +See also combinator `-on' which can transform the values before +comparing them." + (--reduce (if (funcall comparator it acc) it acc) list)) + +(defun -min-by (comparator list) + "Take a comparison function COMPARATOR and a LIST and return +the least element of the list by the comparison function. + +See also combinator `-on' which can transform the values before +comparing them." + (--reduce (if (funcall comparator it acc) acc it) list)) + +(defmacro --max-by (form list) + "Anaphoric version of `-max-by'. + +The items for the comparator form are exposed as \"it\" and \"other\"." + (declare (debug (def-form form))) + `(-max-by (lambda (it other) (ignore it other) ,form) ,list)) + +(defmacro --min-by (form list) + "Anaphoric version of `-min-by'. + +The items for the comparator form are exposed as \"it\" and \"other\"." + (declare (debug (def-form form))) + `(-min-by (lambda (it other) (ignore it other) ,form) ,list)) + +(defun -iota (count &optional start step) + "Return a list containing COUNT numbers. +Starts from START and adds STEP each time. The default START is +zero, the default STEP is 1. +This function takes its name from the corresponding primitive in +the APL language." + (declare (pure t) (side-effect-free t)) + (unless (natnump count) + (signal 'wrong-type-argument (list #'natnump count))) + (or start (setq start 0)) + (or step (setq step 1)) + (if (zerop step) + (make-list count start) + (--iterate (+ it step) start count))) + +(defun -fix (fn list) + "Compute the (least) fixpoint of FN with initial input LIST. + +FN is called at least once, results are compared with `equal'." + (let ((re (funcall fn list))) + (while (not (equal list re)) + (setq list re) + (setq re (funcall fn re))) + re)) + +(defmacro --fix (form list) + "Anaphoric form of `-fix'." + (declare (debug (def-form form))) + `(-fix (lambda (it) (ignore it) ,form) ,list)) + +(defun -unfold (fun seed) + "Build a list from SEED using FUN. + +This is \"dual\" operation to `-reduce-r': while -reduce-r +consumes a list to produce a single value, `-unfold' takes a +seed value and builds a (potentially infinite!) list. + +FUN should return nil to stop the generating process, or a +cons (A . B), where A will be prepended to the result and B is +the new seed." + (let ((last (funcall fun seed)) r) + (while last + (push (car last) r) + (setq last (funcall fun (cdr last)))) + (nreverse r))) + +(defmacro --unfold (form seed) + "Anaphoric version of `-unfold'." + (declare (debug (def-form form))) + `(-unfold (lambda (it) (ignore it) ,form) ,seed)) + +(defun -cons-pair? (obj) + "Return non-nil if OBJ is a true cons pair. +That is, a cons (A . B) where B is not a list. + +Alias: `-cons-pair-p'." + (declare (pure t) (side-effect-free error-free)) + (nlistp (cdr-safe obj))) + +(defalias '-cons-pair-p '-cons-pair?) + +(defun -cons-to-list (con) + "Convert a cons pair to a list with `car' and `cdr' of the pair respectively." + (declare (pure t) (side-effect-free t)) + (list (car con) (cdr con))) + +(defun -value-to-list (val) + "Convert a value to a list. + +If the value is a cons pair, make a list with two elements, `car' +and `cdr' of the pair respectively. + +If the value is anything else, wrap it in a list." + (declare (pure t) (side-effect-free t)) + (if (-cons-pair? val) (-cons-to-list val) (list val))) + +(defun -tree-mapreduce-from (fn folder init-value tree) + "Apply FN to each element of TREE, and make a list of the results. +If elements of TREE are lists themselves, apply FN recursively to +elements of these nested lists. + +Then reduce the resulting lists using FOLDER and initial value +INIT-VALUE. See `-reduce-r-from'. + +This is the same as calling `-tree-reduce-from' after `-tree-map' +but is twice as fast as it only traverse the structure once." + (cond + ((null tree) ()) + ((-cons-pair? tree) (funcall fn tree)) + ((consp tree) + (-reduce-r-from + folder init-value + (mapcar (lambda (x) (-tree-mapreduce-from fn folder init-value x)) tree))) + ((funcall fn tree)))) + +(defmacro --tree-mapreduce-from (form folder init-value tree) + "Anaphoric form of `-tree-mapreduce-from'." + (declare (debug (def-form def-form form form))) + `(-tree-mapreduce-from (lambda (it) (ignore it) ,form) + (lambda (it acc) (ignore it acc) ,folder) + ,init-value + ,tree)) + +(defun -tree-mapreduce (fn folder tree) + "Apply FN to each element of TREE, and make a list of the results. +If elements of TREE are lists themselves, apply FN recursively to +elements of these nested lists. + +Then reduce the resulting lists using FOLDER and initial value +INIT-VALUE. See `-reduce-r-from'. + +This is the same as calling `-tree-reduce' after `-tree-map' +but is twice as fast as it only traverse the structure once." + (cond + ((null tree) ()) + ((-cons-pair? tree) (funcall fn tree)) + ((consp tree) + (-reduce-r folder (mapcar (lambda (x) (-tree-mapreduce fn folder x)) tree))) + ((funcall fn tree)))) + +(defmacro --tree-mapreduce (form folder tree) + "Anaphoric form of `-tree-mapreduce'." + (declare (debug (def-form def-form form))) + `(-tree-mapreduce (lambda (it) (ignore it) ,form) + (lambda (it acc) (ignore it acc) ,folder) + ,tree)) + +(defun -tree-map (fn tree) + "Apply FN to each element of TREE while preserving the tree structure." + (cond + ((null tree) ()) + ((-cons-pair? tree) (funcall fn tree)) + ((consp tree) + (mapcar (lambda (x) (-tree-map fn x)) tree)) + ((funcall fn tree)))) + +(defmacro --tree-map (form tree) + "Anaphoric form of `-tree-map'." + (declare (debug (def-form form))) + `(-tree-map (lambda (it) (ignore it) ,form) ,tree)) + +(defun -tree-reduce-from (fn init-value tree) + "Use FN to reduce elements of list TREE. +If elements of TREE are lists themselves, apply the reduction recursively. + +FN is first applied to INIT-VALUE and first element of the list, +then on this result and second element from the list etc. + +The initial value is ignored on cons pairs as they always contain +two elements." + (cond + ((null tree) ()) + ((-cons-pair? tree) tree) + ((consp tree) + (-reduce-r-from + fn init-value + (mapcar (lambda (x) (-tree-reduce-from fn init-value x)) tree))) + (tree))) + +(defmacro --tree-reduce-from (form init-value tree) + "Anaphoric form of `-tree-reduce-from'." + (declare (debug (def-form form form))) + `(-tree-reduce-from (lambda (it acc) (ignore it acc) ,form) + ,init-value ,tree)) + +(defun -tree-reduce (fn tree) + "Use FN to reduce elements of list TREE. +If elements of TREE are lists themselves, apply the reduction recursively. + +FN is first applied to first element of the list and second +element, then on this result and third element from the list etc. + +See `-reduce-r' for how exactly are lists of zero or one element handled." + (cond + ((null tree) ()) + ((-cons-pair? tree) tree) + ((consp tree) + (-reduce-r fn (mapcar (lambda (x) (-tree-reduce fn x)) tree))) + (tree))) + +(defmacro --tree-reduce (form tree) + "Anaphoric form of `-tree-reduce'." + (declare (debug (def-form form))) + `(-tree-reduce (lambda (it acc) (ignore it acc) ,form) ,tree)) + +(defun -tree-map-nodes (pred fun tree) + "Call FUN on each node of TREE that satisfies PRED. + +If PRED returns nil, continue descending down this node. If PRED +returns non-nil, apply FUN to this node and do not descend +further." + (cond ((funcall pred tree) (funcall fun tree)) + ((and (listp tree) (listp (cdr tree))) + (-map (lambda (x) (-tree-map-nodes pred fun x)) tree)) + (tree))) + +(defmacro --tree-map-nodes (pred form tree) + "Anaphoric form of `-tree-map-nodes'." + (declare (debug (def-form def-form form))) + `(-tree-map-nodes (lambda (it) (ignore it) ,pred) + (lambda (it) (ignore it) ,form) + ,tree)) + +(defun -tree-seq (branch children tree) + "Return a sequence of the nodes in TREE, in depth-first search order. + +BRANCH is a predicate of one argument that returns non-nil if the +passed argument is a branch, that is, a node that can have children. + +CHILDREN is a function of one argument that returns the children +of the passed branch node. + +Non-branch nodes are simply copied." + (cons tree + (and (funcall branch tree) + (-mapcat (lambda (x) (-tree-seq branch children x)) + (funcall children tree))))) + +(defmacro --tree-seq (branch children tree) + "Anaphoric form of `-tree-seq'." + (declare (debug (def-form def-form form))) + `(-tree-seq (lambda (it) (ignore it) ,branch) + (lambda (it) (ignore it) ,children) + ,tree)) + +(defun -clone (list) + "Create a deep copy of LIST. +The new list has the same elements and structure but all cons are +replaced with new ones. This is useful when you need to clone a +structure such as plist or alist." + (declare (pure t) (side-effect-free t)) + (-tree-map #'identity list)) + +;;; Combinators + +(defalias '-partial #'apply-partially) + +(defun -rpartial (fn &rest args) + "Return a function that is a partial application of FN to ARGS. +ARGS is a list of the last N arguments to pass to FN. The result +is a new function which does the same as FN, except that the last +N arguments are fixed at the values with which this function was +called. This is like `-partial', except the arguments are fixed +starting from the right rather than the left." + (declare (pure t) (side-effect-free error-free)) + (lambda (&rest args-before) (apply fn (append args-before args)))) + +(defun -juxt (&rest fns) + "Return a function that is the juxtaposition of FNS. +The returned function takes a variable number of ARGS, applies +each of FNS in turn to ARGS, and returns the list of results." + (declare (pure t) (side-effect-free error-free)) + (lambda (&rest args) (mapcar (lambda (x) (apply x args)) fns))) + +(defun -compose (&rest fns) + "Compose FNS into a single composite function. +Return a function that takes a variable number of ARGS, applies +the last function in FNS to ARGS, and returns the result of +calling each remaining function on the result of the previous +function, right-to-left. If no FNS are given, return a variadic +`identity' function." + (declare (pure t) (side-effect-free error-free)) + (let* ((fns (nreverse fns)) + (head (car fns)) + (tail (cdr fns))) + (cond (tail + (lambda (&rest args) + (--reduce-from (funcall it acc) (apply head args) tail))) + (fns head) + ((lambda (&optional arg &rest _) arg))))) + +(defun -applify (fn) + "Return a function that applies FN to a single list of args. +This changes the arity of FN from taking N distinct arguments to +taking 1 argument which is a list of N arguments." + (declare (pure t) (side-effect-free error-free)) + (lambda (args) (apply fn args))) + +(defun -on (op trans) + "Return a function that calls TRANS on each arg and OP on the results. +The returned function takes a variable number of arguments, calls +the function TRANS on each one in turn, and then passes those +results as the list of arguments to OP, in the same order. + +For example, the following pairs of expressions are morally +equivalent: + + (funcall (-on #\\='+ #\\='1+) 1 2 3) = (+ (1+ 1) (1+ 2) (1+ 3)) + (funcall (-on #\\='+ #\\='1+)) = (+)" + (declare (pure t) (side-effect-free error-free)) + (lambda (&rest args) + ;; This unrolling seems to be a relatively cheap way to keep the + ;; overhead of `mapcar' + `apply' in check. + (cond ((cddr args) + (apply op (mapcar trans args))) + ((cdr args) + (funcall op (funcall trans (car args)) (funcall trans (cadr args)))) + (args + (funcall op (funcall trans (car args)))) + ((funcall op))))) + +(defun -flip (fn) + "Return a function that calls FN with its arguments reversed. +The returned function takes the same number of arguments as FN. + +For example, the following two expressions are morally +equivalent: + + (funcall (-flip #\\='-) 1 2) = (- 2 1) + +See also: `-rotate-args'." + (declare (pure t) (side-effect-free error-free)) + (lambda (&rest args) ;; Open-code for speed. + (cond ((cddr args) (apply fn (nreverse args))) + ((cdr args) (funcall fn (cadr args) (car args))) + (args (funcall fn (car args))) + ((funcall fn))))) + +(defun -rotate-args (n fn) + "Return a function that calls FN with args rotated N places to the right. +The returned function takes the same number of arguments as FN, +rotates the list of arguments N places to the right (left if N is +negative) just like `-rotate', and applies FN to the result. + +See also: `-flip'." + (declare (pure t) (side-effect-free t)) + (if (zerop n) + fn + (let ((even (= (% n 2) 0))) + (lambda (&rest args) + (cond ((cddr args) ;; Open-code for speed. + (apply fn (-rotate n args))) + ((cdr args) + (let ((fst (car args)) + (snd (cadr args))) + (funcall fn (if even fst snd) (if even snd fst)))) + (args + (funcall fn (car args))) + ((funcall fn))))))) + +(defun -const (c) + "Return a function that returns C ignoring any additional arguments. + +In types: a -> b -> a" + (declare (pure t) (side-effect-free error-free)) + (lambda (&rest _) c)) + +(defmacro -cut (&rest params) + "Take n-ary function and n arguments and specialize some of them. +Arguments denoted by <> will be left unspecialized. + +See SRFI-26 for detailed description." + (declare (debug (&optional sexp &rest &or "<>" form))) + (let* ((i 0) + (args (--keep (when (eq it '<>) + (setq i (1+ i)) + (make-symbol (format "D%d" i))) + params))) + `(lambda ,args + ,(let ((body (--map (if (eq it '<>) (pop args) it) params))) + (if (eq (car params) '<>) + (cons #'funcall body) + body))))) + +(defun -not (pred) + "Return a predicate that negates the result of PRED. +The returned predicate passes its arguments to PRED. If PRED +returns nil, the result is non-nil; otherwise the result is nil. + +See also: `-andfn' and `-orfn'." + (declare (pure t) (side-effect-free error-free)) + (lambda (&rest args) (not (apply pred args)))) + +(defun -orfn (&rest preds) + "Return a predicate that returns the first non-nil result of PREDS. +The returned predicate takes a variable number of arguments, +passes them to each predicate in PREDS in turn until one of them +returns non-nil, and returns that non-nil result without calling +the remaining PREDS. If all PREDS return nil, or if no PREDS are +given, the returned predicate returns nil. + +See also: `-andfn' and `-not'." + (declare (pure t) (side-effect-free error-free)) + ;; Open-code for speed. + (cond ((cdr preds) (lambda (&rest args) (--some (apply it args) preds))) + (preds (car preds)) + (#'ignore))) + +(defun -andfn (&rest preds) + "Return a predicate that returns non-nil if all PREDS do so. +The returned predicate P takes a variable number of arguments and +passes them to each predicate in PREDS in turn. If any one of +PREDS returns nil, P also returns nil without calling the +remaining PREDS. If all PREDS return non-nil, P returns the last +such value. If no PREDS are given, P always returns non-nil. + +See also: `-orfn' and `-not'." + (declare (pure t) (side-effect-free error-free)) + ;; Open-code for speed. + (cond ((cdr preds) (lambda (&rest args) (--every (apply it args) preds))) + (preds (car preds)) + ;; As a `pure' function, this runtime check may generate + ;; backward-incompatible bytecode for `(-andfn)' at compile-time, + ;; but I doubt that's a problem in practice (famous last words). + ((fboundp 'always) #'always) + ((lambda (&rest _) t)))) + +(defun -iteratefn (fn n) + "Return a function FN composed N times with itself. + +FN is a unary function. If you need to use a function of higher +arity, use `-applify' first to turn it into a unary function. + +With n = 0, this acts as identity function. + +In types: (a -> a) -> Int -> a -> a. + +This function satisfies the following law: + + (funcall (-iteratefn fn n) init) = (-last-item (-iterate fn init (1+ n)))." + (lambda (x) (--dotimes n (setq x (funcall fn x))) x)) + +(defun -counter (&optional beg end inc) + "Return a closure that counts from BEG to END, with increment INC. + +The closure will return the next value in the counting sequence +each time it is called, and nil after END is reached. BEG +defaults to 0, INC defaults to 1, and if END is nil, the counter +will increment indefinitely. + +The closure accepts any number of arguments, which are discarded." + (let ((inc (or inc 1)) + (n (or beg 0))) + (lambda (&rest _) + (when (or (not end) (< n end)) + (prog1 n + (setq n (+ n inc))))))) + +(defvar -fixfn-max-iterations 1000 + "The default maximum number of iterations performed by `-fixfn' + unless otherwise specified.") + +(defun -fixfn (fn &optional equal-test halt-test) + "Return a function that computes the (least) fixpoint of FN. + +FN must be a unary function. The returned lambda takes a single +argument, X, the initial value for the fixpoint iteration. The +iteration halts when either of the following conditions is satisfied: + + 1. Iteration converges to the fixpoint, with equality being + tested using EQUAL-TEST. If EQUAL-TEST is not specified, + `equal' is used. For functions over the floating point + numbers, it may be necessary to provide an appropriate + approximate comparison test. + + 2. HALT-TEST returns a non-nil value. HALT-TEST defaults to a + simple counter that returns t after `-fixfn-max-iterations', + to guard against infinite iteration. Otherwise, HALT-TEST + must be a function that accepts a single argument, the + current value of X, and returns non-nil as long as iteration + should continue. In this way, a more sophisticated + convergence test may be supplied by the caller. + +The return value of the lambda is either the fixpoint or, if +iteration halted before converging, a cons with car `halted' and +cdr the final output from HALT-TEST. + +In types: (a -> a) -> a -> a." + (let ((eqfn (or equal-test 'equal)) + (haltfn (or halt-test + (-not + (-counter 0 -fixfn-max-iterations))))) + (lambda (x) + (let ((re (funcall fn x)) + (halt? (funcall haltfn x))) + (while (and (not halt?) (not (funcall eqfn x re))) + (setq x re + re (funcall fn re) + halt? (funcall haltfn re))) + (if halt? (cons 'halted halt?) + re))))) + +(defun -prodfn (&rest fns) + "Return a function that applies each of FNS to each of a list of arguments. + +Takes a list of N functions and returns a function that takes a +list of length N, applying Ith function to Ith element of the +input list. Returns a list of length N. + +In types (for N=2): ((a -> b), (c -> d)) -> (a, c) -> (b, d) + +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 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))" + (declare (pure t) (side-effect-free t)) + (lambda (x) (--zip-with (funcall it other) fns x))) + +;;; Font lock + +(defvar dash--keywords + `(;; TODO: Do not fontify the following automatic variables + ;; globally; detect and limit to their local anaphoric scope. + (,(rx symbol-start (| "acc" "it" "it-index" "other") symbol-end) + 0 font-lock-variable-name-face) + ;; Macros in dev/examples.el. Based on `lisp-mode-symbol-regexp'. + (,(rx ?\( (group (| "defexamples" "def-example-group")) symbol-end + (+ (in "\t ")) + (group (* (| (syntax word) (syntax symbol) (: ?\\ nonl))))) + (1 font-lock-keyword-face) + (2 font-lock-function-name-face)) + ;; Symbols in dev/examples.el. + ,(rx symbol-start (| "=>" "~>" "!!>") symbol-end) + ;; Elisp macro fontification was static prior to Emacs 25. + ,@(when (< emacs-major-version 25) + (let ((macs '("!cdr" + "!cons" + "-->" + "--all-p" + "--all?" + "--annotate" + "--any" + "--any-p" + "--any?" + "--count" + "--dotimes" + "--doto" + "--drop-while" + "--each" + "--each-indexed" + "--each-r" + "--each-r-while" + "--each-while" + "--every" + "--every-p" + "--every?" + "--filter" + "--find" + "--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-p" + "--none?" + "--only-some-p" + "--only-some?" + "--partition-after-pred" + "--partition-by" + "--partition-by-header" + "--reduce" + "--reduce-from" + "--reduce-r" + "--reduce-r-from" + "--reductions" + "--reductions-from" + "--reductions-r" + "--reductions-r-from" + "--reject" + "--reject-first" + "--reject-last" + "--remove" + "--remove-first" + "--remove-last" + "--replace-where" + "--select" + "--separate" + "--some" + "--some-p" + "--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->" + "-cut" + "-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") + :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'." + :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) + +(defcustom dash-enable-fontlock nil + "If non-nil, fontify Dash macro calls and special variables." + :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") + +;;; Info + +(defvar dash--info-doc-spec '("(dash) Index" nil "^ -+ .*: " "\\( \\|$\\)") + "The Dash :doc-spec entry for `info-lookup-alist'. +It is based on that for `emacs-lisp-mode'.") + +(defun dash--info-elisp-docs () + "Return the `emacs-lisp-mode' symbol docs from `info-lookup-alist'. +Specifically, return the cons containing their +`info-lookup->doc-spec' so that we can modify it." + (defvar info-lookup-alist) + (nthcdr 3 (assq #'emacs-lisp-mode (cdr (assq 'symbol info-lookup-alist))))) + +;;;###autoload +(defun dash-register-info-lookup () + "Register the Dash Info manual with `info-lookup-symbol'. +This allows Dash symbols to be looked up with \\[info-lookup-symbol]." + (interactive) + (require 'info-look) + (let ((docs (dash--info-elisp-docs))) + (setcar docs (append (car docs) (list dash--info-doc-spec))) + (info-lookup-reset))) + +(defun dash-unload-function () + "Remove Dash from `info-lookup-alist'. +Used by `unload-feature', which see." + (let ((docs (and (featurep 'info-look) + (dash--info-elisp-docs)))) + (when (member dash--info-doc-spec (car docs)) + (setcar docs (remove dash--info-doc-spec (car docs))) + (info-lookup-reset))) + nil) + +(provide 'dash) +;;; dash.el ends here diff --git a/org/elpa/dash-20230304.2223/dash.info b/org/elpa/dash-20230304.2223/dash.info new file mode 100644 index 0000000..b98ef22 --- /dev/null +++ b/org/elpa/dash-20230304.2223/dash.info @@ -0,0 +1,4948 @@ +This is dash.info, produced by makeinfo version 6.7 from dash.texi. + +This manual is for Dash version 2.19.1. + + Copyright © 2012–2023 Free Software Foundation, Inc. + + 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. +END-INFO-DIR-ENTRY + + +File: dash.info, Node: Top, Next: Installation, Up: (dir) + +Dash +**** + +This manual is for Dash version 2.19.1. + + Copyright © 2012–2023 Free Software Foundation, Inc. + + 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:: Installing and configuring Dash. +* Functions:: Dash API reference. +* Development:: Contributing to Dash development. + +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:: Listing Dash as a package dependency. +* Fontification of special variables:: Font Lock of anaphoric macro variables. +* Info symbol lookup:: Looking up Dash symbols in this manual. + +Functions + +* Maps:: +* Sublist selection:: +* List to list:: +* Reductions:: +* Unfolding:: +* Predicates:: +* Partitioning:: +* Indexing:: +* Set operations:: +* Other list operations:: +* Tree operations:: +* Threading macros:: +* Binding:: +* Side effects:: +* Destructive operations:: +* Function combinators:: + +Development + +* Contribute:: How to contribute. +* Contributors:: List of contributors. + + +File: dash.info, Node: Installation, Next: Functions, Prev: Top, Up: Top + +1 Installation +************** + +Dash is available on GNU ELPA (https://elpa.gnu.org/), GNU-devel ELPA +(https://elpa.gnu.org/devel/), 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. + + Alternatively, you can just dump ‘dash.el’ in your ‘load-path’ +somewhere (*note (emacs)Lisp Libraries::). + +* Menu: + +* Using in a package:: Listing Dash as a package dependency. +* Fontification of special variables:: Font Lock of anaphoric macro variables. +* Info symbol lookup:: Looking up Dash symbols in this manual. + + +File: dash.info, Node: Using in a package, Next: Fontification of special variables, Up: Installation + +1.1 Using in a package +====================== + +If you use Dash in your own package, be sure to list it as a dependency +in the library’s headers as follows (*note (elisp)Library Headers::). + + ;; Package-Requires: ((dash "2.19.1")) + + +File: dash.info, Node: Fontification of special variables, Next: Info symbol lookup, Prev: Using in a package, Up: Installation + +1.2 Fontification of special variables +====================================== + +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. + + 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: Info symbol lookup, Prev: Fontification of special variables, Up: Installation + +1.3 Info symbol lookup +====================== + +While editing Elisp files, you can use ‘C-h S’ (‘info-lookup-symbol’) to +look up Elisp symbols in the relevant Info manuals (*note (emacs)Info +Lookup::). To enable the same for Dash symbols, use the command +‘dash-register-info-lookup’. It can be called directly when needed, or +automatically from your ‘user-init-file’. For example: + + (with-eval-after-load 'info-look + (dash-register-info-lookup)) + + +File: dash.info, Node: Functions, Next: Development, Prev: Installation, Up: Top + +2 Functions +*********** + +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 (‘-’). + + 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 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. + + ;; Normal version. + (-map (lambda (n) (* n n)) '(1 2 3 4)) + ⇒ (1 4 9 16) + + ;; Anaphoric version. + (--map (* it it) '(1 2 3 4)) + ⇒ (1 4 9 16) + + The normal version can, of course, also be written as in the +following example, which demonstrates the utility of both versions. + + (defun my-square (n) + "Return N multiplied by itself." + (* n n)) + + (-map #'my-square '(1 2 3 4)) + ⇒ (1 4 9 16) + +* Menu: + +* Maps:: +* Sublist selection:: +* List to list:: +* Reductions:: +* Unfolding:: +* Predicates:: +* Partitioning:: +* Indexing:: +* Set operations:: +* Other list operations:: +* Tree operations:: +* Threading macros:: +* Binding:: +* Side effects:: +* Destructive operations:: +* Function combinators:: + + +File: dash.info, Node: Maps, Next: Sublist selection, Up: Functions + +2.1 Maps +======== + +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 a new list. + + -- Function: -map (fn 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 #'1+ '(1 2 3 4)) + ⇒ (2 3 4 5) + (--map (* it it) '(1 2 3 4)) + ⇒ (1 4 9 16) + + -- Function: -map-when (pred rep list) + Use PRED to conditionally apply REP to each item in LIST. Return a + copy of LIST where the items for which PRED returns ‘nil’ are + unchanged, and the rest are mapped through the REP function. + + Alias: ‘-replace-where’ + + See also: ‘-update-at’ (*note -update-at::) + + (-map-when 'even? 'square '(1 2 3 4)) + ⇒ (1 4 3 16) + (--map-when (> it 2) (* it it) '(1 2 3 4)) + ⇒ (1 2 9 16) + (--map-when (= it 2) 17 '(1 2 3 4)) + ⇒ (1 17 3 4) + + -- Function: -map-first (pred rep list) + Use PRED to determine the first item in LIST to call REP on. + Return a copy of LIST where the first item for which PRED returns + non-‘nil’ is replaced with the result of calling REP on that item. + + See also: ‘-map-when’ (*note -map-when::), ‘-replace-first’ (*note + -replace-first::) + + (-map-first 'even? 'square '(1 2 3 4)) + ⇒ (1 4 3 4) + (--map-first (> it 2) (* it it) '(1 2 3 4)) + ⇒ (1 2 9 4) + (--map-first (= it 2) 17 '(1 2 3 2)) + ⇒ (1 17 3 2) + + -- Function: -map-last (pred rep list) + Use PRED to determine the last item in LIST to call REP on. Return + a copy of LIST where the last item for which PRED returns non-‘nil’ + is replaced with the result of calling REP on that item. + + See also: ‘-map-when’ (*note -map-when::), ‘-replace-last’ (*note + -replace-last::) + + (-map-last 'even? 'square '(1 2 3 4)) + ⇒ (1 2 3 16) + (--map-last (> it 2) (* it it) '(1 2 3 4)) + ⇒ (1 2 3 16) + (--map-last (= it 2) 17 '(1 2 3 2)) + ⇒ (1 2 3 17) + + -- Function: -map-indexed (fn list) + Apply FN to each index and item in LIST and return the list of + results. This is like ‘-map’ (*note -map::), but FN takes two + arguments: the index of the current element within LIST, and the + element itself. + + This function’s anaphoric counterpart is ‘--map-indexed’. + + For a side-effecting variant, see also ‘-each-indexed’ (*note + -each-indexed::). + + (-map-indexed (lambda (index item) (- item index)) '(1 2 3 4)) + ⇒ (1 1 1 1) + (--map-indexed (- it it-index) '(1 2 3 4)) + ⇒ (1 1 1 1) + (-map-indexed #'* '(1 2 3 4)) + ⇒ (0 2 6 12) + + -- Function: -annotate (fn list) + Pair each item in LIST with the result of passing it to FN. + + Return an alist of (RESULT . ITEM), where each ITEM is the + corresponding element of LIST, and RESULT is the value obtained by + calling FN on ITEM. + + This function’s anaphoric counterpart is ‘--annotate’. + + (-annotate #'1+ '(1 2 3)) + ⇒ ((2 . 1) (3 . 2) (4 . 3)) + (-annotate #'length '((f o o) (bar baz))) + ⇒ ((3 f o o) (2 bar baz)) + (--annotate (> it 1) '(0 1 2 3)) + ⇒ ((nil . 0) (nil . 1) (t . 2) (t . 3)) + + -- Function: -splice (pred fun list) + Splice lists generated by FUN in place of items satisfying PRED in + LIST. + + Call PRED on each element of LIST. Whenever the result of PRED is + ‘nil’, leave that ‘it’ as-is. Otherwise, call FUN on the same ‘it’ + that satisfied PRED. The result should be a (possibly empty) list + of items to splice in place of ‘it’ in LIST. + + This can be useful as an alternative to the ‘,@’ construct in a ‘`’ + structure, in case you need to splice several lists at marked + positions (for example with keywords). + + This function’s anaphoric counterpart is ‘--splice’. + + See also: ‘-splice-list’ (*note -splice-list::), ‘-insert-at’ + (*note -insert-at::). + + (-splice #'numberp (lambda (n) (list n n)) '(a 1 b 2)) + ⇒ (a 1 1 b 2 2) + (--splice t (list it it) '(1 2 3 4)) + ⇒ (1 1 2 2 3 3 4 4) + (--splice (eq it :magic) '((magical) (code)) '((foo) :magic (bar))) + ⇒ ((foo) (magical) (code) (bar)) + + -- Function: -splice-list (pred new-list list) + Splice NEW-LIST in place of elements matching PRED in LIST. + + See also: ‘-splice’ (*note -splice::), ‘-insert-at’ (*note + -insert-at::) + + (-splice-list 'keywordp '(a b c) '(1 :foo 2)) + ⇒ (1 a b c 2) + (-splice-list 'keywordp nil '(1 :foo 2)) + ⇒ (1 2) + (--splice-list (keywordp it) '(a b c) '(1 :foo 2)) + ⇒ (1 a b c 2) + + -- Function: -mapcat (fn list) + Return the concatenation of the result of mapping FN over LIST. + Thus function FN should return a list. + + (-mapcat 'list '(1 2 3)) + ⇒ (1 2 3) + (-mapcat (lambda (item) (list 0 item)) '(1 2 3)) + ⇒ (0 1 0 2 0 3) + (--mapcat (list 0 it) '(1 2 3)) + ⇒ (0 1 0 2 0 3) + + -- Function: -copy (list) + Create a shallow copy of LIST. + + (-copy '(1 2 3)) + ⇒ (1 2 3) + (let ((a '(1 2 3))) (eq a (-copy a))) + ⇒ nil + + +File: dash.info, Node: Sublist selection, Next: List to list, Prev: Maps, Up: Functions + +2.2 Sublist selection +===================== + +Functions returning a sublist of the original list. + + -- Function: -filter (pred list) + Return a new list of the items in LIST for which PRED returns + non-‘nil’. + + Alias: ‘-select’. + + This function’s anaphoric counterpart is ‘--filter’. + + For similar operations, see also ‘-keep’ (*note -keep::) and + ‘-remove’ (*note -remove::). + + (-filter (lambda (num) (= 0 (% num 2))) '(1 2 3 4)) + ⇒ (2 4) + (-filter #'natnump '(-2 -1 0 1 2)) + ⇒ (0 1 2) + (--filter (= 0 (% it 2)) '(1 2 3 4)) + ⇒ (2 4) + + -- Function: -remove (pred list) + Return a new list of the items in LIST for which PRED returns + ‘nil’. + + Alias: ‘-reject’. + + This function’s anaphoric counterpart is ‘--remove’. + + For similar operations, see also ‘-keep’ (*note -keep::) and + ‘-filter’ (*note -filter::). + + (-remove (lambda (num) (= 0 (% num 2))) '(1 2 3 4)) + ⇒ (1 3) + (-remove #'natnump '(-2 -1 0 1 2)) + ⇒ (-2 -1) + (--remove (= 0 (% it 2)) '(1 2 3 4)) + ⇒ (1 3) + + -- Function: -remove-first (pred list) + Remove the first item from LIST for which PRED returns non-‘nil’. + This is a non-destructive operation, but only the front of LIST + leading up to the removed item is a copy; the rest is LIST’s + original tail. If no item is removed, then the result is a + complete copy. + + Alias: ‘-reject-first’. + + This function’s anaphoric counterpart is ‘--remove-first’. + + See also ‘-map-first’ (*note -map-first::), ‘-remove-item’ (*note + -remove-item::), and ‘-remove-last’ (*note -remove-last::). + + (-remove-first #'natnump '(-2 -1 0 1 2)) + ⇒ (-2 -1 1 2) + (-remove-first #'stringp '(1 2 "first" "second")) + ⇒ (1 2 "second") + (--remove-first (> it 3) '(1 2 3 4 5 6)) + ⇒ (1 2 3 5 6) + + -- Function: -remove-last (pred list) + Remove the last item from LIST for which PRED returns non-‘nil’. + The result is a copy of LIST regardless of whether an element is + removed. + + Alias: ‘-reject-last’. + + This function’s anaphoric counterpart is ‘--remove-last’. + + See also ‘-map-last’ (*note -map-last::), ‘-remove-item’ (*note + -remove-item::), and ‘-remove-first’ (*note -remove-first::). + + (-remove-last #'natnump '(1 3 5 4 7 8 10 -11)) + ⇒ (1 3 5 4 7 8 -11) + (-remove-last #'stringp '(1 2 "last" "second")) + ⇒ (1 2 "last") + (--remove-last (> it 3) '(1 2 3 4 5 6 7 8 9 10)) + ⇒ (1 2 3 4 5 6 7 8 9) + + -- Function: -remove-item (item list) + Return a copy of LIST with all occurrences of ITEM removed. The + comparison is done with ‘equal’. + + (-remove-item 3 '(1 2 3 2 3 4 5 3)) + ⇒ (1 2 2 4 5) + (-remove-item 'foo '(foo bar baz foo)) + ⇒ (bar baz) + (-remove-item "bob" '("alice" "bob" "eve" "bob")) + ⇒ ("alice" "eve") + + -- Function: -non-nil (list) + Return a copy of LIST with all ‘nil’ items removed. + + (-non-nil '(nil 1 nil 2 nil nil 3 4 nil 5 nil)) + ⇒ (1 2 3 4 5) + (-non-nil '((nil))) + ⇒ ((nil)) + (-non-nil ()) + ⇒ () + + -- Function: -slice (list from &optional to step) + Return copy of LIST, starting from index FROM to index TO. + + FROM or TO may be negative. These values are then interpreted + modulo the length of the list. + + If STEP is a number, only each STEPth item in the resulting section + is returned. Defaults to 1. + + (-slice '(1 2 3 4 5) 1) + ⇒ (2 3 4 5) + (-slice '(1 2 3 4 5) 0 3) + ⇒ (1 2 3) + (-slice '(1 2 3 4 5 6 7 8 9) 1 -1 2) + ⇒ (2 4 6 8) + + -- Function: -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’ (*note -take-last::). + + (-take 3 '(1 2 3 4 5)) + ⇒ (1 2 3) + (-take 17 '(1 2 3 4 5)) + ⇒ (1 2 3 4 5) + (-take 0 '(1 2 3 4 5)) + ⇒ () + + -- Function: -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’ (*note -take::). + + (-take-last 3 '(1 2 3 4 5)) + ⇒ (3 4 5) + (-take-last 17 '(1 2 3 4 5)) + ⇒ (1 2 3 4 5) + (-take-last 1 '(1 2 3 4 5)) + ⇒ (5) + + -- Function: -drop (n list) + Return the tail (not a copy) of LIST without the first N items. + Return ‘nil’ if LIST contains N items or fewer. Return LIST if N + is zero or less. + + For another variant, see also ‘-drop-last’ (*note -drop-last::). + + (-drop 3 '(1 2 3 4 5)) + ⇒ (4 5) + (-drop 17 '(1 2 3 4 5)) + ⇒ () + (-drop 0 '(1 2 3 4 5)) + ⇒ (1 2 3 4 5) + + -- Function: -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’ (*note -drop::). + + (-drop-last 3 '(1 2 3 4 5)) + ⇒ (1 2) + (-drop-last 17 '(1 2 3 4 5)) + ⇒ () + (-drop-last 0 '(1 2 3 4 5)) + ⇒ (1 2 3 4 5) + + -- Function: -take-while (pred list) + 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’. + + This function’s anaphoric counterpart is ‘--take-while’. + + For another variant, see also ‘-drop-while’ (*note -drop-while::). + + (-take-while #'even? '(1 2 3 4)) + ⇒ () + (-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) + Drop successive items from LIST for which PRED returns non-‘nil’. + PRED is a function of one argument. Return the tail (not a copy) + of LIST starting from its first element for which PRED returns + ‘nil’. + + This function’s anaphoric counterpart is ‘--drop-while’. + + For another variant, see also ‘-take-while’ (*note -take-while::). + + (-drop-while #'even? '(1 2 3 4)) + ⇒ (1 2 3 4) + (-drop-while #'even? '(2 4 5 6)) + ⇒ (5 6) + (--drop-while (< it 4) '(1 2 3 4 3 2 1)) + ⇒ (4 3 2 1) + + -- Function: -select-by-indices (indices list) + Return a list whose elements are elements from LIST selected as + ‘(nth i list)‘ for all i from INDICES. + + (-select-by-indices '(4 10 2 3 6) '("v" "e" "l" "o" "c" "i" "r" "a" "p" "t" "o" "r")) + ⇒ ("c" "o" "l" "o" "r") + (-select-by-indices '(2 1 0) '("a" "b" "c")) + ⇒ ("c" "b" "a") + (-select-by-indices '(0 1 2 0 1 3 3 1) '("f" "a" "r" "l")) + ⇒ ("f" "a" "r" "f" "a" "l" "l" "a") + + -- Function: -select-columns (columns table) + Select COLUMNS from TABLE. + + TABLE is a list of lists where each element represents one row. It + is assumed each row has the same length. + + Each row is transformed such that only the specified COLUMNS are + selected. + + See also: ‘-select-column’ (*note -select-column::), + ‘-select-by-indices’ (*note -select-by-indices::) + + (-select-columns '(0 2) '((1 2 3) (a b c) (:a :b :c))) + ⇒ ((1 3) (a c) (:a :c)) + (-select-columns '(1) '((1 2 3) (a b c) (:a :b :c))) + ⇒ ((2) (b) (:b)) + (-select-columns nil '((1 2 3) (a b c) (:a :b :c))) + ⇒ (nil nil nil) + + -- Function: -select-column (column table) + Select COLUMN from TABLE. + + TABLE is a list of lists where each element represents one row. It + is assumed each row has the same length. + + The single selected column is returned as a list. + + See also: ‘-select-columns’ (*note -select-columns::), + ‘-select-by-indices’ (*note -select-by-indices::) + + (-select-column 1 '((1 2 3) (a b c) (:a :b :c))) + ⇒ (2 b :b) + + +File: dash.info, Node: List to list, Next: Reductions, Prev: Sublist selection, Up: Functions + +2.3 List to list +================ + +Functions returning a modified copy of the input list. + + -- Function: -keep (fn list) + Return a new list of the non-‘nil’ results of applying FN to each + item in LIST. Like ‘-filter’ (*note -filter::), but returns the + non-‘nil’ results of FN instead of the corresponding elements of + LIST. + + Its anaphoric counterpart is ‘--keep’. + + (-keep #'cdr '((1 2 3) (4 5) (6))) + ⇒ ((2 3) (5)) + (-keep (lambda (n) (and (> n 3) (* 10 n))) '(1 2 3 4 5 6)) + ⇒ (40 50 60) + (--keep (and (> it 3) (* 10 it)) '(1 2 3 4 5 6)) + ⇒ (40 50 60) + + -- Function: -concat (&rest sequences) + Concatenate all the arguments and make the result a list. The + result is a list whose elements are the elements of all the + arguments. Each argument may be a list, vector or string. + + All arguments except the last argument are copied. The last + argument is just used as the tail of the new list. + + (-concat '(1)) + ⇒ (1) + (-concat '(1) '(2)) + ⇒ (1 2) + (-concat '(1) '(2 3) '(4)) + ⇒ (1 2 3 4) + + -- Function: -flatten (l) + Take a nested list L and return its contents as a single, flat + list. + + Note that because ‘nil’ represents a list of zero elements (an + empty list), any mention of ‘nil’ in L will disappear after + flattening. If you need to preserve nils, consider ‘-flatten-n’ + (*note -flatten-n::) or map them to some unique symbol and then map + them back. + + Conses of two atoms are considered "terminals", that is, they + aren’t flattened further. + + See also: ‘-flatten-n’ (*note -flatten-n::) + + (-flatten '((1))) + ⇒ (1) + (-flatten '((1 (2 3) (((4 (5))))))) + ⇒ (1 2 3 4 5) + (-flatten '(1 2 (3 . 4))) + ⇒ (1 2 (3 . 4)) + + -- Function: -flatten-n (num list) + Flatten NUM levels of a nested LIST. + + See also: ‘-flatten’ (*note -flatten::) + + (-flatten-n 1 '((1 2) ((3 4) ((5 6))))) + ⇒ (1 2 (3 4) ((5 6))) + (-flatten-n 2 '((1 2) ((3 4) ((5 6))))) + ⇒ (1 2 3 4 (5 6)) + (-flatten-n 3 '((1 2) ((3 4) ((5 6))))) + ⇒ (1 2 3 4 5 6) + + -- Function: -replace (old new list) + Replace all OLD items in LIST with NEW. + + Elements are compared using ‘equal’. + + See also: ‘-replace-at’ (*note -replace-at::) + + (-replace 1 "1" '(1 2 3 4 3 2 1)) + ⇒ ("1" 2 3 4 3 2 "1") + (-replace "foo" "bar" '("a" "nice" "foo" "sentence" "about" "foo")) + ⇒ ("a" "nice" "bar" "sentence" "about" "bar") + (-replace 1 2 nil) + ⇒ nil + + -- Function: -replace-first (old new list) + Replace the first occurrence of OLD with NEW in LIST. + + Elements are compared using ‘equal’. + + See also: ‘-map-first’ (*note -map-first::) + + (-replace-first 1 "1" '(1 2 3 4 3 2 1)) + ⇒ ("1" 2 3 4 3 2 1) + (-replace-first "foo" "bar" '("a" "nice" "foo" "sentence" "about" "foo")) + ⇒ ("a" "nice" "bar" "sentence" "about" "foo") + (-replace-first 1 2 nil) + ⇒ nil + + -- Function: -replace-last (old new list) + Replace the last occurrence of OLD with NEW in LIST. + + Elements are compared using ‘equal’. + + See also: ‘-map-last’ (*note -map-last::) + + (-replace-last 1 "1" '(1 2 3 4 3 2 1)) + ⇒ (1 2 3 4 3 2 "1") + (-replace-last "foo" "bar" '("a" "nice" "foo" "sentence" "about" "foo")) + ⇒ ("a" "nice" "foo" "sentence" "about" "bar") + (-replace-last 1 2 nil) + ⇒ nil + + -- Function: -insert-at (n x list) + Return a list with X inserted into LIST at position N. + + See also: ‘-splice’ (*note -splice::), ‘-splice-list’ (*note + -splice-list::) + + (-insert-at 1 'x '(a b c)) + ⇒ (a x b c) + (-insert-at 12 'x '(a b c)) + ⇒ (a b c x) + + -- Function: -replace-at (n x list) + Return a list with element at Nth position in LIST replaced with X. + + See also: ‘-replace’ (*note -replace::) + + (-replace-at 0 9 '(0 1 2 3 4 5)) + ⇒ (9 1 2 3 4 5) + (-replace-at 1 9 '(0 1 2 3 4 5)) + ⇒ (0 9 2 3 4 5) + (-replace-at 4 9 '(0 1 2 3 4 5)) + ⇒ (0 1 2 3 9 5) + + -- Function: -update-at (n func list) + Use FUNC to update the Nth element of LIST. Return a copy of LIST + where the Nth element is replaced with the result of calling FUNC + on it. + + See also: ‘-map-when’ (*note -map-when::) + + (-update-at 0 (lambda (x) (+ x 9)) '(0 1 2 3 4 5)) + ⇒ (9 1 2 3 4 5) + (-update-at 1 (lambda (x) (+ x 8)) '(0 1 2 3 4 5)) + ⇒ (0 9 2 3 4 5) + (--update-at 2 (length it) '("foo" "bar" "baz" "quux")) + ⇒ ("foo" "bar" 3 "quux") + + -- Function: -remove-at (n list) + Return LIST with its element at index N removed. That is, remove + any element selected as (nth N LIST) from LIST and return the + result. + + This is a non-destructive operation: parts of LIST (but not + necessarily all of it) are copied as needed to avoid destructively + modifying it. + + See also: ‘-remove-at-indices’ (*note -remove-at-indices::), + ‘-remove’ (*note -remove::). + + (-remove-at 0 '(a b c)) + ⇒ (b c) + (-remove-at 1 '(a b c)) + ⇒ (a c) + (-remove-at 2 '(a b c)) + ⇒ (a b) + + -- Function: -remove-at-indices (indices list) + Return LIST with its elements at INDICES removed. That is, for + each index I in INDICES, remove any element selected as (nth I + LIST) from LIST. + + This is a non-destructive operation: parts of LIST (but not + necessarily all of it) are copied as needed to avoid destructively + modifying it. + + See also: ‘-remove-at’ (*note -remove-at::), ‘-remove’ (*note + -remove::). + + (-remove-at-indices '(0) '(a b c d e)) + ⇒ (b c d e) + (-remove-at-indices '(1 3) '(a b c d e)) + ⇒ (a c e) + (-remove-at-indices '(4 0 2) '(a b c d e)) + ⇒ (b d) + + +File: dash.info, Node: Reductions, Next: Unfolding, Prev: List to list, Up: Functions + +2.4 Reductions +============== + +Functions reducing lists to a single value (which may also be a list). + + -- Function: -reduce-from (fn init list) + Reduce the function FN across LIST, starting with INIT. Return the + result of applying FN to INIT and the first element of LIST, then + applying FN to that result and the second element, etc. If LIST is + empty, return INIT without calling FN. + + This function’s anaphoric counterpart is ‘--reduce-from’. + + For other folds, see also ‘-reduce’ (*note -reduce::) and + ‘-reduce-r’ (*note -reduce-r::). + + (-reduce-from #'- 10 '(1 2 3)) + ⇒ 4 + (-reduce-from #'list 10 '(1 2 3)) + ⇒ (((10 1) 2) 3) + (--reduce-from (concat acc " " it) "START" '("a" "b" "c")) + ⇒ "START a b c" + + -- Function: -reduce-r-from (fn init list) + Reduce the function FN across LIST in reverse, starting with INIT. + Return the result of applying FN to the last element of LIST and + INIT, then applying FN to the second-to-last element and the + previous result of FN, etc. That is, the first argument of FN is + the current element, and its second argument the accumulated value. + If LIST is empty, return INIT without calling FN. + + This function is like ‘-reduce-from’ (*note -reduce-from::) but the + operation associates from the right rather than left. In other + words, it starts from the end of LIST and flips the arguments to + FN. Conceptually, it is like replacing the conses in LIST with + applications of FN, and its last link with INIT, and evaluating the + resulting expression. + + This function’s anaphoric counterpart is ‘--reduce-r-from’. + + For other folds, see also ‘-reduce-r’ (*note -reduce-r::) and + ‘-reduce’ (*note -reduce::). + + (-reduce-r-from #'- 10 '(1 2 3)) + ⇒ -8 + (-reduce-r-from #'list 10 '(1 2 3)) + ⇒ (1 (2 (3 10))) + (--reduce-r-from (concat it " " acc) "END" '("a" "b" "c")) + ⇒ "a b c END" + + -- Function: -reduce (fn list) + Reduce the function FN across LIST. Return the result of applying + FN to the first two elements of LIST, then applying FN to that + result and the third element, etc. If LIST contains a single + element, return it without calling FN. If LIST is empty, return + the result of calling FN with no arguments. + + This function’s anaphoric counterpart is ‘--reduce’. + + For other folds, see also ‘-reduce-from’ (*note -reduce-from::) and + ‘-reduce-r’ (*note -reduce-r::). + + (-reduce #'- '(1 2 3 4)) + ⇒ -8 + (-reduce #'list '(1 2 3 4)) + ⇒ (((1 2) 3) 4) + (--reduce (format "%s-%d" acc it) '(1 2 3)) + ⇒ "1-2-3" + + -- Function: -reduce-r (fn list) + Reduce the function FN across LIST in reverse. Return the result + of applying FN to the last two elements of LIST, then applying FN + to the third-to-last element and the previous result of FN, etc. + That is, the first argument of FN is the current element, and its + second argument the accumulated value. If LIST contains a single + element, return it without calling FN. If LIST is empty, return + the result of calling FN with no arguments. + + This function is like ‘-reduce’ (*note -reduce::) but the operation + associates from the right rather than left. In other words, it + starts from the end of LIST and flips the arguments to FN. + Conceptually, it is like replacing the conses in LIST with + applications of FN, ignoring its last link, and evaluating the + resulting expression. + + This function’s anaphoric counterpart is ‘--reduce-r’. + + For other folds, see also ‘-reduce-r-from’ (*note -reduce-r-from::) + and ‘-reduce’ (*note -reduce::). + + (-reduce-r #'- '(1 2 3 4)) + ⇒ -2 + (-reduce-r #'list '(1 2 3 4)) + ⇒ (1 (2 (3 4))) + (--reduce-r (format "%s-%d" acc it) '(1 2 3)) + ⇒ "3-2-1" + + -- Function: -reductions-from (fn init list) + Return a list of FN’s intermediate reductions across LIST. That + is, a list of the intermediate values of the accumulator when + ‘-reduce-from’ (*note -reduce-from::) (which see) is called with + the same arguments. + + This function’s anaphoric counterpart is ‘--reductions-from’. + + For other folds, see also ‘-reductions’ (*note -reductions::) and + ‘-reductions-r’ (*note -reductions-r::). + + (-reductions-from #'max 0 '(2 1 4 3)) + ⇒ (0 2 2 4 4) + (-reductions-from #'* 1 '(1 2 3 4)) + ⇒ (1 1 2 6 24) + (--reductions-from (format "(FN %s %d)" acc it) "INIT" '(1 2 3)) + ⇒ ("INIT" "(FN INIT 1)" "(FN (FN INIT 1) 2)" "(FN (FN (FN INIT 1) 2) 3)") + + -- Function: -reductions-r-from (fn init list) + Return a list of FN’s intermediate reductions across reversed LIST. + That is, a list of the intermediate values of the accumulator when + ‘-reduce-r-from’ (*note -reduce-r-from::) (which see) is called + with the same arguments. + + This function’s anaphoric counterpart is ‘--reductions-r-from’. + + For other folds, see also ‘-reductions’ (*note -reductions::) and + ‘-reductions-r’ (*note -reductions-r::). + + (-reductions-r-from #'max 0 '(2 1 4 3)) + ⇒ (4 4 4 3 0) + (-reductions-r-from #'* 1 '(1 2 3 4)) + ⇒ (24 24 12 4 1) + (--reductions-r-from (format "(FN %d %s)" it acc) "INIT" '(1 2 3)) + ⇒ ("(FN 1 (FN 2 (FN 3 INIT)))" "(FN 2 (FN 3 INIT))" "(FN 3 INIT)" "INIT") + + -- Function: -reductions (fn list) + Return a list of FN’s intermediate reductions across LIST. That + is, a list of the intermediate values of the accumulator when + ‘-reduce’ (*note -reduce::) (which see) is called with the same + arguments. + + This function’s anaphoric counterpart is ‘--reductions’. + + For other folds, see also ‘-reductions’ (*note -reductions::) and + ‘-reductions-r’ (*note -reductions-r::). + + (-reductions #'+ '(1 2 3 4)) + ⇒ (1 3 6 10) + (-reductions #'* '(1 2 3 4)) + ⇒ (1 2 6 24) + (--reductions (format "(FN %s %d)" acc it) '(1 2 3)) + ⇒ (1 "(FN 1 2)" "(FN (FN 1 2) 3)") + + -- Function: -reductions-r (fn list) + Return a list of FN’s intermediate reductions across reversed LIST. + That is, a list of the intermediate values of the accumulator when + ‘-reduce-r’ (*note -reduce-r::) (which see) is called with the same + arguments. + + This function’s anaphoric counterpart is ‘--reductions-r’. + + For other folds, see also ‘-reductions-r-from’ (*note + -reductions-r-from::) and ‘-reductions’ (*note -reductions::). + + (-reductions-r #'+ '(1 2 3 4)) + ⇒ (10 9 7 4) + (-reductions-r #'* '(1 2 3 4)) + ⇒ (24 24 12 4) + (--reductions-r (format "(FN %d %s)" it acc) '(1 2 3)) + ⇒ ("(FN 1 (FN 2 3))" "(FN 2 3)" 3) + + -- Function: -count (pred list) + Counts the number of items in LIST where (PRED item) is non-‘nil’. + + (-count 'even? '(1 2 3 4 5)) + ⇒ 2 + (--count (< it 4) '(1 2 3 4)) + ⇒ 3 + + -- Function: -sum (list) + Return the sum of LIST. + + (-sum ()) + ⇒ 0 + (-sum '(1)) + ⇒ 1 + (-sum '(1 2 3 4)) + ⇒ 10 + + -- Function: -running-sum (list) + Return a list with running sums of items in LIST. LIST must be + non-empty. + + (-running-sum '(1 2 3 4)) + ⇒ (1 3 6 10) + (-running-sum '(1)) + ⇒ (1) + (-running-sum ()) + error→ Wrong type argument: consp, nil + + -- Function: -product (list) + Return the product of LIST. + + (-product ()) + ⇒ 1 + (-product '(1)) + ⇒ 1 + (-product '(1 2 3 4)) + ⇒ 24 + + -- Function: -running-product (list) + Return a list with running products of items in LIST. LIST must be + non-empty. + + (-running-product '(1 2 3 4)) + ⇒ (1 2 6 24) + (-running-product '(1)) + ⇒ (1) + (-running-product ()) + error→ Wrong type argument: consp, nil + + -- Function: -inits (list) + Return all prefixes of LIST. + + (-inits '(1 2 3 4)) + ⇒ (nil (1) (1 2) (1 2 3) (1 2 3 4)) + (-inits nil) + ⇒ (nil) + (-inits '(1)) + ⇒ (nil (1)) + + -- Function: -tails (list) + Return all suffixes of LIST + + (-tails '(1 2 3 4)) + ⇒ ((1 2 3 4) (2 3 4) (3 4) (4) nil) + (-tails nil) + ⇒ (nil) + (-tails '(1)) + ⇒ ((1) nil) + + -- Function: -common-prefix (&rest lists) + Return the longest common prefix of LISTS. + + (-common-prefix '(1)) + ⇒ (1) + (-common-prefix '(1 2) '(3 4) '(1 2)) + ⇒ () + (-common-prefix '(1 2) '(1 2 3) '(1 2 3 4)) + ⇒ (1 2) + + -- Function: -common-suffix (&rest lists) + Return the longest common suffix of LISTS. + + (-common-suffix '(1)) + ⇒ (1) + (-common-suffix '(1 2) '(3 4) '(1 2)) + ⇒ () + (-common-suffix '(1 2 3 4) '(2 3 4) '(3 4)) + ⇒ (3 4) + + -- Function: -min (list) + Return the smallest value from LIST of numbers or markers. + + (-min '(0)) + ⇒ 0 + (-min '(3 2 1)) + ⇒ 1 + (-min '(1 2 3)) + ⇒ 1 + + -- Function: -min-by (comparator list) + Take a comparison function COMPARATOR and a LIST and return the + least element of the list by the comparison function. + + See also combinator ‘-on’ (*note -on::) which can transform the + values before comparing them. + + (-min-by '> '(4 3 6 1)) + ⇒ 1 + (--min-by (> (car it) (car other)) '((1 2 3) (2) (3 2))) + ⇒ (1 2 3) + (--min-by (> (length it) (length other)) '((1 2 3) (2) (3 2))) + ⇒ (2) + + -- Function: -max (list) + Return the largest value from LIST of numbers or markers. + + (-max '(0)) + ⇒ 0 + (-max '(3 2 1)) + ⇒ 3 + (-max '(1 2 3)) + ⇒ 3 + + -- Function: -max-by (comparator list) + Take a comparison function COMPARATOR and a LIST and return the + greatest element of the list by the comparison function. + + See also combinator ‘-on’ (*note -on::) which can transform the + values before comparing them. + + (-max-by '> '(4 3 6 1)) + ⇒ 6 + (--max-by (> (car it) (car other)) '((1 2 3) (2) (3 2))) + ⇒ (3 2) + (--max-by (> (length it) (length other)) '((1 2 3) (2) (3 2))) + ⇒ (1 2 3) + + -- Function: -frequencies (list) + Count the occurrences of each distinct element of LIST. + + Return an alist of (ELEMENT . N), where each ELEMENT occurs N + times in LIST. + + The test for equality is done with ‘equal’, or with ‘-compare-fn’ + if that is non-‘nil’. + + See also ‘-count’ (*note -count::) and ‘-group-by’ (*note + -group-by::). + + (-frequencies ()) + ⇒ () + (-frequencies '(1 2 3 1 2 1)) + ⇒ ((1 . 3) (2 . 2) (3 . 1)) + (let ((-compare-fn #'string=)) (-frequencies '(a "a"))) + ⇒ ((a . 2)) + + +File: dash.info, Node: Unfolding, Next: Predicates, Prev: Reductions, Up: Functions + +2.5 Unfolding +============= + +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 the form: + + (INIT (FUN INIT) (FUN (FUN INIT)) ...) + + N is the length of the returned list. + + (-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) + (--iterate (* it it) 2 5) + ⇒ (2 4 16 256 65536) + + -- Function: -unfold (fun seed) + Build a list from SEED using FUN. + + This is "dual" operation to ‘-reduce-r’ (*note -reduce-r::): while + -reduce-r consumes a list to produce a single value, ‘-unfold’ + (*note -unfold::) takes a seed value and builds a (potentially + infinite!) list. + + FUN should return ‘nil’ to stop the generating process, or a cons + (A . B), where A will be prepended to the result and B is the new + seed. + + (-unfold (lambda (x) (unless (= x 0) (cons x (1- x)))) 10) + ⇒ (10 9 8 7 6 5 4 3 2 1) + (--unfold (when it (cons it (cdr it))) '(1 2 3 4)) + ⇒ ((1 2 3 4) (2 3 4) (3 4) (4)) + (--unfold (when it (cons it (butlast it))) '(1 2 3 4)) + ⇒ ((1 2 3 4) (1 2 3) (1 2) (1)) + + -- Function: -repeat (n x) + 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) + (-repeat 1 :a) + ⇒ (:a) + (-repeat 0 :a) + ⇒ () + + -- Function: -cycle (list) + 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) + (-take 7 (-cycle '(1 "and" 3))) + ⇒ (1 "and" 3 1 "and" 3 1) + (-zip-lists (-cycle '(3)) '(1 2)) + ⇒ ((3 1) (3 2)) + + +File: dash.info, Node: Predicates, Next: Partitioning, Prev: Unfolding, Up: Functions + +2.6 Predicates +============== + +Reductions of one or more lists to a boolean value. + + -- Function: -some (pred list) + Return (PRED x) for the first LIST item where (PRED x) is + non-‘nil’, else ‘nil’. + + Alias: ‘-any’. + + This function’s anaphoric counterpart is ‘--some’. + + (-some #'stringp '(1 "2" 3)) + ⇒ t + (--some (string-match-p "x" it) '("foo" "axe" "xor")) + ⇒ 1 + (--some (= it-index 3) '(0 1 2)) + ⇒ nil + + -- Function: -every (pred list) + Return non-‘nil’ if PRED returns non-‘nil’ for all items in LIST. + If so, return the last such result of PRED. Otherwise, once an + item is reached for which PRED returns ‘nil’, return ‘nil’ without + calling PRED on any further LIST elements. + + This function is like ‘-every-p’, but on success returns the last + non-‘nil’ result of PRED instead of just ‘t’. + + This function’s anaphoric counterpart is ‘--every’. + + (-every #'numberp '(1 2 3)) + ⇒ t + (--every (string-match-p "x" it) '("axe" "xor")) + ⇒ 0 + (--every (= it it-index) '(0 1 3)) + ⇒ nil + + -- Function: -any? (pred list) + Return ‘t’ if (PRED X) is non-‘nil’ for any X in LIST, else ‘nil’. + + Alias: ‘-any-p’, ‘-some?’, ‘-some-p’ + + (-any? #'numberp '(nil 0 t)) + ⇒ t + (-any? #'numberp '(nil t t)) + ⇒ nil + (-any? #'null '(1 3 5)) + ⇒ nil + + -- Function: -all? (pred list) + Return ‘t’ if (PRED X) is non-‘nil’ for all X in LIST, else ‘nil’. + In the latter case, stop after the first X for which (PRED X) is + ‘nil’, without calling PRED on any subsequent elements of LIST. + + The similar function ‘-every’ (*note -every::) is more widely + useful, since it returns the last non-‘nil’ result of PRED instead + of just ‘t’ on success. + + Alias: ‘-all-p’, ‘-every-p’, ‘-every?’. + + This function’s anaphoric counterpart is ‘--all?’. + + (-all? #'numberp '(1 2 3)) + ⇒ t + (-all? #'numberp '(2 t 6)) + ⇒ nil + (--all? (= 0 (% it 2)) '(2 4 6)) + ⇒ t + + -- Function: -none? (pred list) + Return ‘t’ if (PRED X) is ‘nil’ for all X in LIST, else ‘nil’. + + Alias: ‘-none-p’ + + (-none? 'even? '(1 2 3)) + ⇒ nil + (-none? 'even? '(1 3 5)) + ⇒ t + (--none? (= 0 (% it 2)) '(1 2 3)) + ⇒ nil + + -- Function: -only-some? (pred list) + Return ‘t’ if different LIST items both satisfy and do not satisfy + PRED. That is, if PRED returns both ‘nil’ for at least one item, + and non-‘nil’ for at least one other item in LIST. Return ‘nil’ if + all items satisfy the predicate or none of them do. + + Alias: ‘-only-some-p’ + + (-only-some? 'even? '(1 2 3)) + ⇒ t + (-only-some? 'even? '(1 3 5)) + ⇒ nil + (-only-some? 'even? '(2 4 6)) + ⇒ nil + + -- Function: -contains? (list element) + Return non-‘nil’ if LIST contains ELEMENT. + + The test for equality is done with ‘equal’, or with ‘-compare-fn’ + if that is non-‘nil’. As with ‘member’, the return value is + actually the tail of LIST whose car is ELEMENT. + + Alias: ‘-contains-p’. + + (-contains? '(1 2 3) 1) + ⇒ (1 2 3) + (-contains? '(1 2 3) 2) + ⇒ (2 3) + (-contains? '(1 2 3) 4) + ⇒ () + + -- Function: -is-prefix? (prefix list) + Return non-‘nil’ if PREFIX is a prefix of LIST. + + Alias: ‘-is-prefix-p’. + + (-is-prefix? '(1 2 3) '(1 2 3 4 5)) + ⇒ t + (-is-prefix? '(1 2 3 4 5) '(1 2 3)) + ⇒ nil + (-is-prefix? '(1 3) '(1 2 3 4 5)) + ⇒ nil + + -- Function: -is-suffix? (suffix list) + Return non-‘nil’ if SUFFIX is a suffix of LIST. + + Alias: ‘-is-suffix-p’. + + (-is-suffix? '(3 4 5) '(1 2 3 4 5)) + ⇒ t + (-is-suffix? '(1 2 3 4 5) '(3 4 5)) + ⇒ nil + (-is-suffix? '(3 5) '(1 2 3 4 5)) + ⇒ nil + + -- Function: -is-infix? (infix list) + Return non-‘nil’ if INFIX is infix of LIST. + + This operation runs in O(n^2) time + + Alias: ‘-is-infix-p’ + + (-is-infix? '(1 2 3) '(1 2 3 4 5)) + ⇒ t + (-is-infix? '(2 3 4) '(1 2 3 4 5)) + ⇒ t + (-is-infix? '(3 4 5) '(1 2 3 4 5)) + ⇒ t + + -- Function: -cons-pair? (obj) + Return non-‘nil’ if OBJ is a true cons pair. That is, a cons (A . + B) where B is not a list. + + Alias: ‘-cons-pair-p’. + + (-cons-pair? '(1 . 2)) + ⇒ t + (-cons-pair? '(1 2)) + ⇒ nil + (-cons-pair? '(1)) + ⇒ nil + + +File: dash.info, Node: Partitioning, Next: Indexing, Prev: Predicates, Up: Functions + +2.7 Partitioning +================ + +Functions partitioning the input list into a list of lists. + + -- Function: -split-at (n list) + Split LIST into two sublists after the Nth element. The result is + a list of two elements (TAKE DROP) where TAKE is a new list of the + first N elements of LIST, and DROP is the remaining elements of + LIST (not a copy). TAKE and DROP are like the results of ‘-take’ + (*note -take::) and ‘-drop’ (*note -drop::), respectively, but the + split is done in a single list traversal. + + (-split-at 3 '(1 2 3 4 5)) + ⇒ ((1 2 3) (4 5)) + (-split-at 17 '(1 2 3 4 5)) + ⇒ ((1 2 3 4 5) nil) + (-split-at 0 '(1 2 3 4 5)) + ⇒ (nil (1 2 3 4 5)) + + -- Function: -split-with (pred list) + Split LIST into a prefix satisfying PRED, and the rest. The first + sublist is the prefix of LIST with successive elements satisfying + PRED, and the second sublist is the remaining elements that do not. + The result is like performing + + ((-take-while PRED LIST) (-drop-while PRED LIST)) + + but in no more than a single pass through LIST. + + (-split-with 'even? '(1 2 3 4)) + ⇒ (nil (1 2 3 4)) + (-split-with 'even? '(2 4 5 6)) + ⇒ ((2 4) (5 6)) + (--split-with (< it 4) '(1 2 3 4 3 2 1)) + ⇒ ((1 2 3) (4 3 2 1)) + + -- Macro: -split-on (item list) + Split the LIST each time ITEM is found. + + Unlike ‘-partition-by’ (*note -partition-by::), the ITEM is + discarded from the results. Empty lists are also removed from the + result. + + Comparison is done by ‘equal’. + + See also ‘-split-when’ (*note -split-when::) + + (-split-on '| '(Nil | Leaf a | Node [Tree a])) + ⇒ ((Nil) (Leaf a) (Node [Tree a])) + (-split-on :endgroup '("a" "b" :endgroup "c" :endgroup "d" "e")) + ⇒ (("a" "b") ("c") ("d" "e")) + (-split-on :endgroup '("a" "b" :endgroup :endgroup "d" "e")) + ⇒ (("a" "b") ("d" "e")) + + -- Function: -split-when (fn list) + Split the LIST on each element where FN returns non-‘nil’. + + Unlike ‘-partition-by’ (*note -partition-by::), the "matched" + element is discarded from the results. Empty lists are also + removed from the result. + + This function can be thought of as a generalization of + ‘split-string’. + + (-split-when 'even? '(1 2 3 4 5 6)) + ⇒ ((1) (3) (5)) + (-split-when 'even? '(1 2 3 4 6 8 9)) + ⇒ ((1) (3) (9)) + (--split-when (memq it '(&optional &rest)) '(a b &optional c d &rest args)) + ⇒ ((a b) (c d) (args)) + + -- Function: -separate (pred list) + Split LIST into two sublists based on whether items satisfy PRED. + The result is like performing + + ((-filter PRED LIST) (-remove PRED LIST)) + + but in a single pass through LIST. + + (-separate (lambda (num) (= 0 (% num 2))) '(1 2 3 4 5 6 7)) + ⇒ ((2 4 6) (1 3 5 7)) + (--separate (< it 5) '(3 7 5 9 3 2 1 4 6)) + ⇒ ((3 3 2 1 4) (7 5 9 6)) + (-separate 'cdr '((1 2) (1) (1 2 3) (4))) + ⇒ (((1 2) (1 2 3)) ((1) (4))) + + -- Function: -partition (n list) + Return a new list with the items in LIST grouped into N-sized + sublists. If there are not enough items to make the last group + N-sized, those items are discarded. + + (-partition 2 '(1 2 3 4 5 6)) + ⇒ ((1 2) (3 4) (5 6)) + (-partition 2 '(1 2 3 4 5 6 7)) + ⇒ ((1 2) (3 4) (5 6)) + (-partition 3 '(1 2 3 4 5 6 7)) + ⇒ ((1 2 3) (4 5 6)) + + -- Function: -partition-all (n list) + Return a new list with the items in LIST grouped into N-sized + sublists. The last group may contain less than N items. + + (-partition-all 2 '(1 2 3 4 5 6)) + ⇒ ((1 2) (3 4) (5 6)) + (-partition-all 2 '(1 2 3 4 5 6 7)) + ⇒ ((1 2) (3 4) (5 6) (7)) + (-partition-all 3 '(1 2 3 4 5 6 7)) + ⇒ ((1 2 3) (4 5 6) (7)) + + -- Function: -partition-in-steps (n step list) + Partition LIST into sublists of length N that are STEP items apart. + Like ‘-partition-all-in-steps’ (*note -partition-all-in-steps::), + but if there are not enough items to make the last group N-sized, + those items are discarded. + + (-partition-in-steps 2 1 '(1 2 3 4)) + ⇒ ((1 2) (2 3) (3 4)) + (-partition-in-steps 3 2 '(1 2 3 4)) + ⇒ ((1 2 3)) + (-partition-in-steps 3 2 '(1 2 3 4 5)) + ⇒ ((1 2 3) (3 4 5)) + + -- Function: -partition-all-in-steps (n step list) + Partition LIST into sublists of length N that are STEP items apart. + Adjacent groups may overlap if N exceeds the STEP stride. Trailing + groups may contain less than N items. + + (-partition-all-in-steps 2 1 '(1 2 3 4)) + ⇒ ((1 2) (2 3) (3 4) (4)) + (-partition-all-in-steps 3 2 '(1 2 3 4)) + ⇒ ((1 2 3) (3 4)) + (-partition-all-in-steps 3 2 '(1 2 3 4 5)) + ⇒ ((1 2 3) (3 4 5) (5)) + + -- Function: -partition-by (fn list) + Apply FN to each item in LIST, splitting it each time FN returns a + new value. + + (-partition-by 'even? ()) + ⇒ () + (-partition-by 'even? '(1 1 2 2 2 3 4 6 8)) + ⇒ ((1 1) (2 2 2) (3) (4 6 8)) + (--partition-by (< it 3) '(1 2 3 4 3 2 1)) + ⇒ ((1 2) (3 4 3) (2 1)) + + -- Function: -partition-by-header (fn list) + Apply FN to the first item in LIST. That is the header value. + Apply FN to each item in LIST, splitting it each time FN returns + the header value, but only after seeing at least one other value + (the body). + + (--partition-by-header (= it 1) '(1 2 3 1 2 1 2 3 4)) + ⇒ ((1 2 3) (1 2) (1 2 3 4)) + (--partition-by-header (> it 0) '(1 2 0 1 0 1 2 3 0)) + ⇒ ((1 2 0) (1 0) (1 2 3 0)) + (-partition-by-header 'even? '(2 1 1 1 4 1 3 5 6 6 1)) + ⇒ ((2 1 1 1) (4 1 3 5) (6 6 1)) + + -- Function: -partition-after-pred (pred list) + Partition LIST after each element for which PRED returns non-‘nil’. + + This function’s anaphoric counterpart is ‘--partition-after-pred’. + + (-partition-after-pred #'booleanp ()) + ⇒ () + (-partition-after-pred #'booleanp '(t t)) + ⇒ ((t) (t)) + (-partition-after-pred #'booleanp '(0 0 t t 0 t)) + ⇒ ((0 0 t) (t) (0 t)) + + -- Function: -partition-before-pred (pred list) + Partition directly before each time PRED is true on an element of + LIST. + + (-partition-before-pred #'booleanp ()) + ⇒ () + (-partition-before-pred #'booleanp '(0 t)) + ⇒ ((0) (t)) + (-partition-before-pred #'booleanp '(0 0 t 0 t t)) + ⇒ ((0 0) (t 0) (t) (t)) + + -- Function: -partition-before-item (item list) + Partition directly before each time ITEM appears in LIST. + + (-partition-before-item 3 ()) + ⇒ () + (-partition-before-item 3 '(1)) + ⇒ ((1)) + (-partition-before-item 3 '(3)) + ⇒ ((3)) + + -- Function: -partition-after-item (item list) + Partition directly after each time ITEM appears in LIST. + + (-partition-after-item 3 ()) + ⇒ () + (-partition-after-item 3 '(1)) + ⇒ ((1)) + (-partition-after-item 3 '(3)) + ⇒ ((3)) + + -- Function: -group-by (fn list) + Separate LIST into an alist whose keys are FN applied to the + elements of LIST. Keys are compared by ‘equal’. + + (-group-by 'even? ()) + ⇒ () + (-group-by 'even? '(1 1 2 2 2 3 4 6 8)) + ⇒ ((nil 1 1 3) (t 2 2 2 4 6 8)) + (--group-by (car (split-string it "/")) '("a/b" "c/d" "a/e")) + ⇒ (("a" "a/b" "a/e") ("c" "c/d")) + + +File: dash.info, Node: Indexing, Next: Set operations, Prev: Partitioning, Up: Functions + +2.8 Indexing +============ + +Functions retrieving or sorting based on list indices and related +predicates. + + -- Function: -elem-index (elem list) + Return the first index of ELEM in LIST. That is, the index within + LIST of the first element that is ‘equal’ to ELEM. Return ‘nil’ if + there is no such element. + + See also: ‘-find-index’ (*note -find-index::). + + (-elem-index 2 '(6 7 8 3 4)) + ⇒ nil + (-elem-index "bar" '("foo" "bar" "baz")) + ⇒ 1 + (-elem-index '(1 2) '((3) (5 6) (1 2) nil)) + ⇒ 2 + + -- Function: -elem-indices (elem list) + Return the list of indices at which ELEM appears in LIST. That is, + the indices of all elements of LIST ‘equal’ to ELEM, in the same + ascending order as they appear in LIST. + + (-elem-indices 2 '(6 7 8 3 4 1)) + ⇒ () + (-elem-indices "bar" '("foo" "bar" "baz")) + ⇒ (1) + (-elem-indices '(1 2) '((3) (1 2) (5 6) (1 2) nil)) + ⇒ (1 3) + + -- Function: -find-index (pred list) + Return the index of the first item satisfying PRED in LIST. Return + ‘nil’ if no such item is found. + + PRED is called with one argument, the current list element, until + it returns non-‘nil’, at which point the search terminates. + + This function’s anaphoric counterpart is ‘--find-index’. + + See also: ‘-first’ (*note -first::), ‘-find-last-index’ (*note + -find-last-index::). + + (-find-index #'numberp '(a b c)) + ⇒ nil + (-find-index #'natnump '(1 0 -1)) + ⇒ 0 + (--find-index (> it 5) '(2 4 1 6 3 3 5 8)) + ⇒ 3 + + -- Function: -find-last-index (pred list) + Return the index of the last item satisfying PRED in LIST. Return + ‘nil’ if no such item is found. + + Predicate PRED is called with one argument each time, namely the + current list element. + + This function’s anaphoric counterpart is ‘--find-last-index’. + + See also: ‘-last’ (*note -last::), ‘-find-index’ (*note + -find-index::). + + (-find-last-index #'numberp '(a b c)) + ⇒ nil + (--find-last-index (> it 5) '(2 7 1 6 3 8 5 2)) + ⇒ 5 + (-find-last-index (-partial #'string< 'a) '(c b a)) + ⇒ 1 + + -- Function: -find-indices (pred list) + Return the list of indices in LIST satisfying PRED. + + Each element of LIST in turn is passed to PRED. If the result is + non-‘nil’, the index of that element in LIST is included in the + result. The returned indices are in ascending order, i.e., in the + same order as they appear in LIST. + + This function’s anaphoric counterpart is ‘--find-indices’. + + See also: ‘-find-index’ (*note -find-index::), ‘-elem-indices’ + (*note -elem-indices::). + + (-find-indices #'numberp '(a b c)) + ⇒ () + (-find-indices #'numberp '(8 1 d 2 b c a 3)) + ⇒ (0 1 3 7) + (--find-indices (> it 5) '(2 4 1 6 3 3 5 8)) + ⇒ (3 7) + + -- Function: -grade-up (comparator list) + Grade elements of LIST using COMPARATOR relation. This yields a + permutation vector such that applying this permutation to LIST + sorts it in ascending order. + + (-grade-up #'< '(3 1 4 2 1 3 3)) + ⇒ (1 4 3 0 5 6 2) + (let ((l '(3 1 4 2 1 3 3))) (-select-by-indices (-grade-up #'< l) l)) + ⇒ (1 1 2 3 3 3 4) + + -- Function: -grade-down (comparator list) + Grade elements of LIST using COMPARATOR relation. This yields a + permutation vector such that applying this permutation to LIST + sorts it in descending order. + + (-grade-down #'< '(3 1 4 2 1 3 3)) + ⇒ (2 0 5 6 3 1 4) + (let ((l '(3 1 4 2 1 3 3))) (-select-by-indices (-grade-down #'< l) l)) + ⇒ (4 3 3 3 2 1 1) + + +File: dash.info, Node: Set operations, Next: Other list operations, Prev: Indexing, Up: Functions + +2.9 Set operations +================== + +Operations pretending lists are sets. + + -- Function: -union (list1 list2) + Return a new list of distinct elements appearing in either LIST1 or + LIST2. + + The test for equality is done with ‘equal’, or with ‘-compare-fn’ + if that is non-‘nil’. + + (-union '(1 2 3) '(3 4 5)) + ⇒ (1 2 3 4 5) + (-union '(1 2 2 4) ()) + ⇒ (1 2 4) + (-union '(1 1 2 2) '(4 4 3 2 1)) + ⇒ (1 2 4 3) + + -- Function: -difference (list1 list2) + Return a new list with the distinct members of LIST1 that are not + in LIST2. + + The test for equality is done with ‘equal’, or with ‘-compare-fn’ + if that is non-‘nil’. + + (-difference () ()) + ⇒ () + (-difference '(1 2 3) '(4 5 6)) + ⇒ (1 2 3) + (-difference '(1 2 3 4) '(3 4 5 6)) + ⇒ (1 2) + + -- Function: -intersection (list1 list2) + Return a new list of distinct elements appearing in both LIST1 and + LIST2. + + The test for equality is done with ‘equal’, or with ‘-compare-fn’ + if that is non-‘nil’. + + (-intersection () ()) + ⇒ () + (-intersection '(1 2 3) '(4 5 6)) + ⇒ () + (-intersection '(1 2 2 3) '(4 3 3 2)) + ⇒ (2 3) + + -- Function: -powerset (list) + Return the power set of LIST. + + (-powerset ()) + ⇒ (nil) + (-powerset '(x y)) + ⇒ ((x y) (x) (y) nil) + (-powerset '(x y z)) + ⇒ ((x y z) (x y) (x z) (x) (y z) (y) (z) nil) + + -- Function: -permutations (list) + Return the distinct permutations of LIST. + + Duplicate elements of LIST are determined by ‘equal’, or by + ‘-compare-fn’ if that is non-‘nil’. + + (-permutations ()) + ⇒ (nil) + (-permutations '(a a b)) + ⇒ ((a a b) (a b a) (b a a)) + (-permutations '(a b c)) + ⇒ ((a b c) (a c b) (b a c) (b c a) (c a b) (c b a)) + + -- Function: -distinct (list) + Return a copy of LIST with all duplicate elements removed. + + The test for equality is done with ‘equal’, or with ‘-compare-fn’ + if that is non-‘nil’. + + Alias: ‘-uniq’. + + (-distinct ()) + ⇒ () + (-distinct '(1 1 2 3 3)) + ⇒ (1 2 3) + (-distinct '(t t t)) + ⇒ (t) + + -- Function: -same-items? (list1 list2) + Return non-‘nil’ if LIST1 and LIST2 have the same distinct + elements. + + The order of the elements in the lists does not matter. The lists + may be of different lengths, i.e., contain duplicate elements. The + test for equality is done with ‘equal’, or with ‘-compare-fn’ if + that is non-‘nil’. + + Alias: ‘-same-items-p’. + + (-same-items? '(1 2 3) '(1 2 3)) + ⇒ t + (-same-items? '(1 1 2 3) '(3 3 2 1)) + ⇒ t + (-same-items? '(1 2 3) '(1 2 3 4)) + ⇒ nil + + +File: dash.info, Node: Other list operations, Next: Tree operations, Prev: Set operations, Up: Functions + +2.10 Other list operations +========================== + +Other list functions not fit to be classified elsewhere. + + -- Function: -rotate (n list) + Rotate LIST N places to the right (left if N is negative). The + time complexity is O(n). + + (-rotate 3 '(1 2 3 4 5 6 7)) + ⇒ (5 6 7 1 2 3 4) + (-rotate -3 '(1 2 3 4 5 6 7)) + ⇒ (4 5 6 7 1 2 3) + (-rotate 16 '(1 2 3 4 5 6 7)) + ⇒ (6 7 1 2 3 4 5) + + -- Function: -cons* (&rest args) + Make a new list from the elements of ARGS. The last 2 elements of + ARGS are used as the final cons of the result, so if the final + element of ARGS is not a list, the result is a dotted list. With + no ARGS, return ‘nil’. + + (-cons* 1 2) + ⇒ (1 . 2) + (-cons* 1 2 3) + ⇒ (1 2 . 3) + (-cons* 1) + ⇒ 1 + + -- Function: -snoc (list elem &rest elements) + Append ELEM to the end of the list. + + This is like ‘cons’, but operates on the end of list. + + If any ELEMENTS are given, append them to the list as well. + + (-snoc '(1 2 3) 4) + ⇒ (1 2 3 4) + (-snoc '(1 2 3) 4 5 6) + ⇒ (1 2 3 4 5 6) + (-snoc '(1 2 3) '(4 5 6)) + ⇒ (1 2 3 (4 5 6)) + + -- Function: -interpose (sep list) + Return a new list of all elements in LIST separated by SEP. + + (-interpose "-" ()) + ⇒ () + (-interpose "-" '("a")) + ⇒ ("a") + (-interpose "-" '("a" "b" "c")) + ⇒ ("a" "-" "b" "-" "c") + + -- Function: -interleave (&rest lists) + Return a new list of the first item in each list, then the second + etc. + + (-interleave '(1 2) '("a" "b")) + ⇒ (1 "a" 2 "b") + (-interleave '(1 2) '("a" "b") '("A" "B")) + ⇒ (1 "a" "A" 2 "b" "B") + (-interleave '(1 2 3) '("a" "b")) + ⇒ (1 "a" 2 "b") + + -- Function: -iota (count &optional start step) + Return a list containing COUNT numbers. Starts from START and adds + STEP each time. The default START is zero, the default STEP is 1. + This function takes its name from the corresponding primitive in + the APL language. + + (-iota 6) + ⇒ (0 1 2 3 4 5) + (-iota 4 2.5 -2) + ⇒ (2.5 0.5 -1.5 -3.5) + (-iota -1) + error→ Wrong type argument: natnump, -1 + + -- Function: -zip-with (fn list1 list2) + Zip LIST1 and LIST2 into a new list using the function FN. That + is, apply FN pairwise taking as first argument the next element of + LIST1 and as second argument the next element of LIST2 at the + corresponding position. The result is as long as the shorter list. + + This function’s anaphoric counterpart is ‘--zip-with’. + + For other zips, see also ‘-zip-lists’ (*note -zip-lists::) and + ‘-zip-fill’ (*note -zip-fill::). + + (-zip-with #'+ '(1 2 3 4) '(5 6 7)) + ⇒ (6 8 10) + (-zip-with #'cons '(1 2 3) '(4 5 6 7)) + ⇒ ((1 . 4) (2 . 5) (3 . 6)) + (--zip-with (format "%s & %s" it other) '(Batman Jekyll) '(Robin Hyde)) + ⇒ ("Batman & Robin" "Jekyll & Hyde") + + -- Function: -zip-pair (list1 list2) + Zip LIST1 and LIST2 together. + + Make a pair with the head of each list, followed by a pair with the + second element of each list, and so on. The number of pairs + returned is equal to the length of the shorter input list. + + See also: ‘-zip-lists’ (*note -zip-lists::). + + (-zip-pair '(1 2 3 4) '(5 6 7)) + ⇒ ((1 . 5) (2 . 6) (3 . 7)) + (-zip-pair '(1 2 3) '(4 5 6)) + ⇒ ((1 . 4) (2 . 5) (3 . 6)) + (-zip-pair '(1 2) '(3)) + ⇒ ((1 . 3)) + + -- Function: -zip-lists (&rest lists) + Zip LISTS together. + + Group the head of each list, followed by the second element of each + list, and so on. The number of returned groupings is equal to the + length of the shortest input list, and the length of each grouping + is equal to the number of input LISTS. + + The return value is always a list of proper lists, in contrast to + ‘-zip’ (*note -zip::) which returns a list of dotted pairs when + only two input LISTS are provided. + + See also: ‘-zip-pair’ (*note -zip-pair::). + + (-zip-lists '(1 2 3) '(4 5 6)) + ⇒ ((1 4) (2 5) (3 6)) + (-zip-lists '(1 2 3) '(4 5 6 7)) + ⇒ ((1 4) (2 5) (3 6)) + (-zip-lists '(1 2) '(3 4 5) '(6)) + ⇒ ((1 3 6)) + + -- Function: -zip-lists-fill (fill-value &rest lists) + Zip LISTS together, padding shorter lists with FILL-VALUE. This is + like ‘-zip-lists’ (*note -zip-lists::) (which see), except it + retains all elements at positions beyond the end of the shortest + list. The number of returned groupings is equal to the length of + the longest input list, and the length of each grouping is equal to + the number of input LISTS. + + (-zip-lists-fill 0 '(1 2) '(3 4 5) '(6)) + ⇒ ((1 3 6) (2 4 0) (0 5 0)) + (-zip-lists-fill 0 '(1 2) '(3 4) '(5 6)) + ⇒ ((1 3 5) (2 4 6)) + (-zip-lists-fill 0 '(1 2 3) nil) + ⇒ ((1 0) (2 0) (3 0)) + + -- Function: -zip (&rest lists) + Zip LISTS together. + + Group the head of each list, followed by the second element of each + list, and so on. The number of returned groupings is equal to the + length of the shortest input list, and the number of items in each + grouping is equal to the number of input LISTS. + + If only two LISTS are provided as arguments, return the groupings + as a list of dotted pairs. Otherwise, return the groupings as a + list of proper lists. + + Since the return value changes form depending on the number of + arguments, it is generally recommended to use ‘-zip-lists’ (*note + -zip-lists::) instead, or ‘-zip-pair’ (*note -zip-pair::) if a list + of dotted pairs is desired. + + See also: ‘-unzip’ (*note -unzip::). + + (-zip '(1 2 3 4) '(5 6 7) '(8 9)) + ⇒ ((1 5 8) (2 6 9)) + (-zip '(1 2 3) '(4 5 6) '(7 8 9)) + ⇒ ((1 4 7) (2 5 8) (3 6 9)) + (-zip '(1 2 3)) + ⇒ ((1) (2) (3)) + + -- Function: -zip-fill (fill-value &rest lists) + Zip LISTS together, padding shorter lists with FILL-VALUE. This is + like ‘-zip’ (*note -zip::) (which see), except it retains all + elements at positions beyond the end of the shortest list. The + number of returned groupings is equal to the length of the longest + input list, and the length of each grouping is equal to the number + of input LISTS. + + Since the return value changes form depending on the number of + arguments, it is generally recommended to use ‘-zip-lists-fill’ + (*note -zip-lists-fill::) instead, unless a list of dotted pairs is + explicitly desired. + + (-zip-fill 0 '(1 2 3) '(4 5)) + ⇒ ((1 . 4) (2 . 5) (3 . 0)) + (-zip-fill 0 () '(1 2 3)) + ⇒ ((0 . 1) (0 . 2) (0 . 3)) + (-zip-fill 0 '(1 2) '(3 4) '(5 6)) + ⇒ ((1 3 5) (2 4 6)) + + -- Function: -unzip-lists (lists) + Unzip LISTS. + + This works just like ‘-zip-lists’ (*note -zip-lists::) (which see), + but takes a list of lists instead of a variable number of + arguments, such that + + (-unzip-lists (-zip-lists ARGS...)) + + is identity (given that the lists comprising ARGS are of the same + length). + + (-unzip-lists (-zip-lists '(1 2) '(3 4) '(5 6))) + ⇒ ((1 2) (3 4) (5 6)) + (-unzip-lists '((1 2 3) (4 5) (6 7) (8 9))) + ⇒ ((1 4 6 8) (2 5 7 9)) + (-unzip-lists '((1 2 3) (4 5 6))) + ⇒ ((1 4) (2 5) (3 6)) + + -- Function: -unzip (lists) + Unzip LISTS. + + This works just like ‘-zip’ (*note -zip::) (which see), but takes a + list of lists instead of a variable number of arguments, such that + + (-unzip (-zip L1 L2 L3 ...)) + + is identity (given that the lists are of the same length, and that + ‘-zip’ (*note -zip::) is not called with two arguments, because of + the caveat described in its docstring). + + Note in particular that calling ‘-unzip’ (*note -unzip::) on a list + of two lists will return a list of dotted pairs. + + Since the return value changes form depending on the number of + LISTS, it is generally recommended to use ‘-unzip-lists’ (*note + -unzip-lists::) instead. + + (-unzip (-zip '(1 2) '(3 4) '(5 6))) + ⇒ ((1 . 2) (3 . 4) (5 . 6)) + (-unzip '((1 2 3) (4 5 6))) + ⇒ ((1 . 4) (2 . 5) (3 . 6)) + (-unzip '((1 2 3) (4 5) (6 7) (8 9))) + ⇒ ((1 4 6 8) (2 5 7 9)) + + -- Function: -pad (fill-value &rest lists) + Pad each of LISTS with FILL-VALUE until they all have equal + lengths. + + Ensure all LISTS are as long as the longest one by repeatedly + appending FILL-VALUE to the shorter lists, and return the resulting + LISTS. + + (-pad 0 ()) + ⇒ (nil) + (-pad 0 '(1 2) '(3 4)) + ⇒ ((1 2) (3 4)) + (-pad 0 '(1 2) '(3 4 5 6) '(7 8 9)) + ⇒ ((1 2 0 0) (3 4 5 6) (7 8 9 0)) + + -- Function: -table (fn &rest lists) + Compute outer product of LISTS using function FN. + + The function FN should have the same arity as the number of + supplied lists. + + The outer product is computed by applying fn to all possible + combinations created by taking one element from each list in order. + The dimension of the result is (length lists). + + See also: ‘-table-flat’ (*note -table-flat::) + + (-table '* '(1 2 3) '(1 2 3)) + ⇒ ((1 2 3) (2 4 6) (3 6 9)) + (-table (lambda (a b) (-sum (-zip-with '* a b))) '((1 2) (3 4)) '((1 3) (2 4))) + ⇒ ((7 15) (10 22)) + (apply '-table 'list (-repeat 3 '(1 2))) + ⇒ ((((1 1 1) (2 1 1)) ((1 2 1) (2 2 1))) (((1 1 2) (2 1 2)) ((1 2 2) (2 2 2)))) + + -- Function: -table-flat (fn &rest lists) + Compute flat outer product of LISTS using function FN. + + The function FN should have the same arity as the number of + supplied lists. + + The outer product is computed by applying fn to all possible + combinations created by taking one element from each list in order. + The results are flattened, ignoring the tensor structure of the + result. This is equivalent to calling: + + (-flatten-n (1- (length lists)) (apply ’-table fn lists)) + + but the implementation here is much more efficient. + + See also: ‘-flatten-n’ (*note -flatten-n::), ‘-table’ (*note + -table::) + + (-table-flat 'list '(1 2 3) '(a b c)) + ⇒ ((1 a) (2 a) (3 a) (1 b) (2 b) (3 b) (1 c) (2 c) (3 c)) + (-table-flat '* '(1 2 3) '(1 2 3)) + ⇒ (1 2 3 2 4 6 3 6 9) + (apply '-table-flat 'list (-repeat 3 '(1 2))) + ⇒ ((1 1 1) (2 1 1) (1 2 1) (2 2 1) (1 1 2) (2 1 2) (1 2 2) (2 2 2)) + + -- Function: -first (pred list) + Return the first item in LIST for which PRED returns non-‘nil’. + Return ‘nil’ if no such element is found. + + To get the first item in the list no questions asked, use + ‘-first-item’ (*note -first-item::). + + Alias: ‘-find’. + + This function’s anaphoric counterpart is ‘--first’. + + (-first #'natnump '(-1 0 1)) + ⇒ 0 + (-first #'null '(1 2 3)) + ⇒ nil + (--first (> it 2) '(1 2 3)) + ⇒ 3 + + -- Function: -last (pred list) + Return the last x in LIST where (PRED x) is non-‘nil’, else ‘nil’. + + (-last 'even? '(1 2 3 4 5 6 3 3 3)) + ⇒ 6 + (-last 'even? '(1 3 7 5 9)) + ⇒ nil + (--last (> (length it) 3) '("a" "looong" "word" "and" "short" "one")) + ⇒ "short" + + -- Function: -first-item (list) + Return the first item of LIST, or ‘nil’ on an empty list. + + See also: ‘-second-item’ (*note -second-item::), ‘-last-item’ + (*note -last-item::), etc. + + (-first-item ()) + ⇒ () + (-first-item '(1 2 3 4 5)) + ⇒ 1 + (let ((list (list 1 2 3))) (setf (-first-item list) 5) list) + ⇒ (5 2 3) + + -- Function: -second-item (list) + Return the second item of LIST, or ‘nil’ if LIST is too short. + + See also: ‘-first-item’ (*note -first-item::), ‘-third-item’ (*note + -third-item::), etc. + + (-second-item ()) + ⇒ () + (-second-item '(1 2 3 4 5)) + ⇒ 2 + (let ((list (list 1 2))) (setf (-second-item list) 5) list) + ⇒ (1 5) + + -- Function: -third-item (list) + Return the third item of LIST, or ‘nil’ if LIST is too short. + + See also: ‘-second-item’ (*note -second-item::), ‘-fourth-item’ + (*note -fourth-item::), etc. + + (-third-item ()) + ⇒ () + (-third-item '(1 2)) + ⇒ () + (-third-item '(1 2 3 4 5)) + ⇒ 3 + + -- Function: -fourth-item (list) + Return the fourth item of LIST, or ‘nil’ if LIST is too short. + + See also: ‘-third-item’ (*note -third-item::), ‘-fifth-item’ (*note + -fifth-item::), etc. + + (-fourth-item ()) + ⇒ () + (-fourth-item '(1 2 3)) + ⇒ () + (-fourth-item '(1 2 3 4 5)) + ⇒ 4 + + -- Function: -fifth-item (list) + Return the fifth item of LIST, or ‘nil’ if LIST is too short. + + See also: ‘-fourth-item’ (*note -fourth-item::), ‘-last-item’ + (*note -last-item::), etc. + + (-fifth-item ()) + ⇒ () + (-fifth-item '(1 2 3 4)) + ⇒ () + (-fifth-item '(1 2 3 4 5)) + ⇒ 5 + + -- Function: -last-item (list) + Return the last item of LIST, or ‘nil’ on an empty list. + + See also: ‘-first-item’ (*note -first-item::), etc. + + (-last-item ()) + ⇒ () + (-last-item '(1 2 3 4 5)) + ⇒ 5 + (let ((list (list 1 2 3))) (setf (-last-item list) 5) list) + ⇒ (1 2 5) + + -- Function: -butlast (list) + Return a list of all items in list except for the last. + + (-butlast '(1 2 3)) + ⇒ (1 2) + (-butlast '(1 2)) + ⇒ (1) + (-butlast '(1)) + ⇒ nil + + -- Function: -sort (comparator list) + Sort LIST, stably, comparing elements using COMPARATOR. Return the + sorted list. LIST is NOT modified by side effects. COMPARATOR is + called with two elements of LIST, and should return non-‘nil’ if + the first element should sort before the second. + + (-sort '< '(3 1 2)) + ⇒ (1 2 3) + (-sort '> '(3 1 2)) + ⇒ (3 2 1) + (--sort (< it other) '(3 1 2)) + ⇒ (1 2 3) + + -- Function: -list (arg) + Ensure ARG is a list. If ARG is already a list, return it as is + (not a copy). Otherwise, return a new list with ARG as its only + element. + + Another supported calling convention is (-list &rest ARGS). In + this case, if ARG is not a list, a new list with all of ARGS as + elements is returned. This use is supported for backward + compatibility and is otherwise deprecated. + + (-list 1) + ⇒ (1) + (-list ()) + ⇒ () + (-list '(1 2 3)) + ⇒ (1 2 3) + + -- Function: -fix (fn list) + Compute the (least) fixpoint of FN with initial input LIST. + + FN is called at least once, results are compared with ‘equal’. + + (-fix (lambda (l) (-non-nil (--mapcat (-split-at (/ (length it) 2) it) l))) '((1 2 3))) + ⇒ ((1) (2) (3)) + (let ((l '((starwars scifi) (jedi starwars warrior)))) (--fix (-uniq (--mapcat (cons it (cdr (assq it l))) it)) '(jedi book))) + ⇒ (jedi starwars warrior scifi book) + + +File: dash.info, Node: Tree operations, Next: Threading macros, Prev: Other list operations, Up: Functions + +2.11 Tree operations +==================== + +Functions pretending lists are trees. + + -- Function: -tree-seq (branch children tree) + Return a sequence of the nodes in TREE, in depth-first search + order. + + BRANCH is a predicate of one argument that returns non-‘nil’ if the + passed argument is a branch, that is, a node that can have + children. + + CHILDREN is a function of one argument that returns the children of + the passed branch node. + + Non-branch nodes are simply copied. + + (-tree-seq 'listp 'identity '(1 (2 3) 4 (5 (6 7)))) + ⇒ ((1 (2 3) 4 (5 (6 7))) 1 (2 3) 2 3 4 (5 (6 7)) 5 (6 7) 6 7) + (-tree-seq 'listp 'reverse '(1 (2 3) 4 (5 (6 7)))) + ⇒ ((1 (2 3) 4 (5 (6 7))) (5 (6 7)) (6 7) 7 6 5 4 (2 3) 3 2 1) + (--tree-seq (vectorp it) (append it nil) [1 [2 3] 4 [5 [6 7]]]) + ⇒ ([1 [2 3] 4 [5 [6 7]]] 1 [2 3] 2 3 4 [5 [6 7]] 5 [6 7] 6 7) + + -- Function: -tree-map (fn tree) + Apply FN to each element of TREE while preserving the tree + structure. + + (-tree-map '1+ '(1 (2 3) (4 (5 6) 7))) + ⇒ (2 (3 4) (5 (6 7) 8)) + (-tree-map '(lambda (x) (cons x (expt 2 x))) '(1 (2 3) 4)) + ⇒ ((1 . 2) ((2 . 4) (3 . 8)) (4 . 16)) + (--tree-map (length it) '("" ("

" "text" "

") "")) + ⇒ (6 (3 4 4) 7) + + -- Function: -tree-map-nodes (pred fun tree) + Call FUN on each node of TREE that satisfies PRED. + + If PRED returns ‘nil’, continue descending down this node. If PRED + returns non-‘nil’, apply FUN to this node and do not descend + further. + + (-tree-map-nodes 'vectorp (lambda (x) (-sum (append x nil))) '(1 [2 3] 4 (5 [6 7] 8))) + ⇒ (1 5 4 (5 13 8)) + (-tree-map-nodes 'keywordp (lambda (x) (symbol-name x)) '(1 :foo 4 ((5 6 :bar) :baz 8))) + ⇒ (1 ":foo" 4 ((5 6 ":bar") ":baz" 8)) + (--tree-map-nodes (eq (car-safe it) 'add-mode) (-concat it (list :mode 'emacs-lisp-mode)) '(with-mode emacs-lisp-mode (foo bar) (add-mode a b) (baz (add-mode c d)))) + ⇒ (with-mode emacs-lisp-mode (foo bar) (add-mode a b :mode emacs-lisp-mode) (baz (add-mode c d :mode emacs-lisp-mode))) + + -- Function: -tree-reduce (fn tree) + Use FN to reduce elements of list TREE. If elements of TREE are + lists themselves, apply the reduction recursively. + + FN is first applied to first element of the list and second + element, then on this result and third element from the list etc. + + See ‘-reduce-r’ (*note -reduce-r::) for how exactly are lists of + zero or one element handled. + + (-tree-reduce '+ '(1 (2 3) (4 5))) + ⇒ 15 + (-tree-reduce 'concat '("strings" (" on" " various") ((" levels")))) + ⇒ "strings on various levels" + (--tree-reduce (cond ((stringp it) (concat it " " acc)) (t (let ((sn (symbol-name it))) (concat "<" sn ">" acc "")))) '(body (p "some words") (div "more" (b "bold") "words"))) + ⇒ "

some words

more bold words
" + + -- Function: -tree-reduce-from (fn init-value tree) + Use FN to reduce elements of list TREE. If elements of TREE are + lists themselves, apply the reduction recursively. + + FN is first applied to INIT-VALUE and first element of the list, + then on this result and second element from the list etc. + + The initial value is ignored on cons pairs as they always contain + two elements. + + (-tree-reduce-from '+ 1 '(1 (1 1) ((1)))) + ⇒ 8 + (--tree-reduce-from (-concat acc (list it)) nil '(1 (2 3 (4 5)) (6 7))) + ⇒ ((7 6) ((5 4) 3 2) 1) + + -- Function: -tree-mapreduce (fn folder tree) + Apply FN to each element of TREE, and make a list of the results. + If elements of TREE are lists themselves, apply FN recursively to + elements of these nested lists. + + Then reduce the resulting lists using FOLDER and initial value + INIT-VALUE. See ‘-reduce-r-from’ (*note -reduce-r-from::). + + This is the same as calling ‘-tree-reduce’ (*note -tree-reduce::) + after ‘-tree-map’ (*note -tree-map::) but is twice as fast as it + only traverse the structure once. + + (-tree-mapreduce 'list 'append '(1 (2 (3 4) (5 6)) (7 (8 9)))) + ⇒ (1 2 3 4 5 6 7 8 9) + (--tree-mapreduce 1 (+ it acc) '(1 (2 (4 9) (2 1)) (7 (4 3)))) + ⇒ 9 + (--tree-mapreduce 0 (max acc (1+ it)) '(1 (2 (4 9) (2 1)) (7 (4 3)))) + ⇒ 3 + + -- Function: -tree-mapreduce-from (fn folder init-value tree) + Apply FN to each element of TREE, and make a list of the results. + If elements of TREE are lists themselves, apply FN recursively to + elements of these nested lists. + + Then reduce the resulting lists using FOLDER and initial value + INIT-VALUE. See ‘-reduce-r-from’ (*note -reduce-r-from::). + + This is the same as calling ‘-tree-reduce-from’ (*note + -tree-reduce-from::) after ‘-tree-map’ (*note -tree-map::) but is + twice as fast as it only traverse the structure once. + + (-tree-mapreduce-from 'identity '* 1 '(1 (2 (3 4) (5 6)) (7 (8 9)))) + ⇒ 362880 + (--tree-mapreduce-from (+ it it) (cons it acc) nil '(1 (2 (4 9) (2 1)) (7 (4 3)))) + ⇒ (2 (4 (8 18) (4 2)) (14 (8 6))) + (concat "{" (--tree-mapreduce-from (cond ((-cons-pair? it) (concat (symbol-name (car it)) " -> " (symbol-name (cdr it)))) (t (concat (symbol-name it) " : {"))) (concat it (unless (or (equal acc "}") (equal (substring it (1- (length it))) "{")) ", ") acc) "}" '((elisp-mode (foo (bar . booze)) (baz . qux)) (c-mode (foo . bla) (bum . bam))))) + ⇒ "{elisp-mode : {foo : {bar -> booze}, baz -> qux}, c-mode : {foo -> bla, bum -> bam}}" + + -- Function: -clone (list) + Create a deep copy of LIST. The new list has the same elements and + structure but all cons are replaced with new ones. This is useful + when you need to clone a structure such as plist or alist. + + (let* ((a '(1 2 3)) (b (-clone a))) (nreverse a) b) + ⇒ (1 2 3) + + +File: dash.info, Node: Threading macros, Next: Binding, Prev: Tree operations, Up: Functions + +2.12 Threading macros +===================== + +Macros that conditionally combine sequential forms for brevity or +readability. + + -- Macro: -> (x &optional form &rest more) + Thread the expr through the forms. Insert X as the second item in + the first form, making a list of it if it is not a list already. + If there are more forms, insert the first form as the second item + in second form, etc. + + (-> '(2 3 5)) + ⇒ (2 3 5) + (-> '(2 3 5) (append '(8 13))) + ⇒ (2 3 5 8 13) + (-> '(2 3 5) (append '(8 13)) (-slice 1 -1)) + ⇒ (3 5 8) + + -- Macro: ->> (x &optional form &rest more) + Thread the expr through the forms. Insert X as the last item in + the first form, making a list of it if it is not a list already. + If there are more forms, insert the first form as the last item in + second form, etc. + + (->> '(1 2 3) (-map 'square)) + ⇒ (1 4 9) + (->> '(1 2 3) (-map 'square) (-remove 'even?)) + ⇒ (1 9) + (->> '(1 2 3) (-map 'square) (-reduce '+)) + ⇒ 14 + + -- Macro: --> (x &rest forms) + Starting with the value of X, thread each expression through FORMS. + + Insert X at the position signified by the symbol ‘it’ in the first + form. If there are more forms, insert the first form at the + position signified by ‘it’ in in second form, etc. + + (--> "def" (concat "abc" it "ghi")) + ⇒ "abcdefghi" + (--> "def" (concat "abc" it "ghi") (upcase it)) + ⇒ "ABCDEFGHI" + (--> "def" (concat "abc" it "ghi") upcase) + ⇒ "ABCDEFGHI" + + -- Macro: -as-> (value variable &rest forms) + Starting with VALUE, thread VARIABLE through FORMS. + + In the first form, bind VARIABLE to VALUE. In the second form, + bind VARIABLE to the result of the first form, and so forth. + + (-as-> 3 my-var (1+ my-var) (list my-var) (mapcar (lambda (ele) (* 2 ele)) my-var)) + ⇒ (8) + (-as-> 3 my-var 1+) + ⇒ 4 + (-as-> 3 my-var) + ⇒ 3 + + -- Macro: -some-> (x &optional form &rest more) + 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. + + (-some-> '(2 3 5)) + ⇒ (2 3 5) + (-some-> 5 square) + ⇒ 25 + (-some-> 5 even? square) + ⇒ nil + + -- Macro: -some->> (x &optional form &rest more) + 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. + + (-some->> '(1 2 3) (-map 'square)) + ⇒ (1 4 9) + (-some->> '(1 3 5) (-last 'even?) (+ 100)) + ⇒ nil + (-some->> '(2 4 6) (-last 'even?) (+ 100)) + ⇒ 106 + + -- Macro: -some--> (expr &rest forms) + Thread EXPR through FORMS via ‘-->’ (*note -->::), while the result + is non-‘nil’. When EXPR evaluates to non-‘nil’, thread the result + through the first of FORMS, and when that result is non-‘nil’, + thread it through the next form, etc. + + (-some--> "def" (concat "abc" it "ghi")) + ⇒ "abcdefghi" + (-some--> nil (concat "abc" it "ghi")) + ⇒ nil + (-some--> '(0 1) (-remove #'natnump it) (append it it) (-map #'1+ it)) + ⇒ () + + -- 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 + +2.13 Binding +============ + +Macros that combine ‘let’ and ‘let*’ with destructuring and flow +control. + + -- Macro: -when-let ((var val) &rest body) + If VAL evaluates to non-‘nil’, bind it to VAR and execute body. + + Note: binding is done according to ‘-let’ (*note -let::). + + (-when-let (match-index (string-match "d" "abcd")) (+ match-index 2)) + ⇒ 5 + (-when-let ((&plist :foo foo) (list :foo "foo")) foo) + ⇒ "foo" + (-when-let ((&plist :foo foo) (list :bar "bar")) foo) + ⇒ nil + + -- Macro: -when-let* (vars-vals &rest body) + If all VALS evaluate to true, bind them to their corresponding VARS + and execute body. VARS-VALS should be a list of (VAR VAL) pairs. + + Note: binding is done according to ‘-let*’ (*note -let*::). VALS + are evaluated sequentially, and evaluation stops after the first + ‘nil’ VAL is encountered. + + (-when-let* ((x 5) (y 3) (z (+ y 4))) (+ x y z)) + ⇒ 15 + (-when-let* ((x 5) (y nil) (z 7)) (+ x y z)) + ⇒ nil + + -- Macro: -if-let ((var val) then &rest else) + If VAL evaluates to non-‘nil’, bind it to VAR and do THEN, + otherwise do ELSE. + + Note: binding is done according to ‘-let’ (*note -let::). + + (-if-let (match-index (string-match "d" "abc")) (+ match-index 3) 7) + ⇒ 7 + (--if-let (even? 4) it nil) + ⇒ t + + -- Macro: -if-let* (vars-vals then &rest else) + If all VALS evaluate to true, bind them to their corresponding VARS + and do THEN, otherwise do ELSE. VARS-VALS should be a list of (VAR + VAL) pairs. + + Note: binding is done according to ‘-let*’ (*note -let*::). VALS + are evaluated sequentially, and evaluation stops after the first + ‘nil’ VAL is encountered. + + (-if-let* ((x 5) (y 3) (z 7)) (+ x y z) "foo") + ⇒ 15 + (-if-let* ((x 5) (y nil) (z 7)) (+ x y z) "foo") + ⇒ "foo" + (-if-let* (((_ _ x) '(nil nil 7))) x) + ⇒ 7 + + -- Macro: -let (varlist &rest body) + Bind variables according to VARLIST then eval BODY. + + VARLIST is a list of lists of the form (PATTERN SOURCE). Each + PATTERN is matched against the SOURCE "structurally". SOURCE is + only evaluated once for each PATTERN. Each PATTERN is matched + recursively, and can therefore contain sub-patterns which are + matched against corresponding sub-expressions of SOURCE. + + All the SOURCEs are evalled before any symbols are bound (i.e. "in + parallel"). + + 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)) ...) + + becomes + + (-let [PATTERN SOURCE] ...). + + ‘-let’ (*note -let::) uses a convention of not binding places + (symbols) starting with _ whenever it’s possible. You can use this + to skip over entries you don’t care about. However, this is not + *always* possible (as a result of implementation) and these symbols + might get bound to undefined values. + + Following is the overview of supported patterns. Remember that + patterns can be matched recursively, so every a, b, aK in the + following can be a matching construct and not necessarily a + symbol/variable. + + Symbol: + + a - bind the SOURCE to A. This is just like regular ‘let’. + + Conses and lists: + + (a) - bind ‘car’ of cons/list to A + + (a . b) - bind car of cons to A and ‘cdr’ to B + + (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 ... 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 + 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 + sequence to REST. This is conceptually the same as improper list + matching (a1 a2 ... aN . rest) + + Key/value stores: + + (&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 + 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 + SOURCE hash table to aK. If the value is not found, aK is ‘nil’. + Uses ‘gethash’ to fetch values. + + Further, special keyword &keys supports "inline" matching of + plist-like key-value pairs, similarly to &keys keyword of + ‘cl-defun’. + + (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). + + A shorthand notation for kv-destructuring exists which allows the + patterns be optionally left out and derived from the key name in + the following fashion: + + - a key :foo is converted into ‘foo’ pattern, - a key ’bar is + converted into ‘bar’ pattern, - a key "baz" is converted into ‘baz’ + pattern. + + That is, the entire value under the key is bound to the derived + variable without any further destructuring. + + This is possible only when the form following the key is not a + valid pattern (i.e. not a symbol, a cons cell or a vector). + Otherwise the matching proceeds as usual and in case of an invalid + spec fails with an error. + + Thus the patterns are normalized as follows: + + ;; derive all the missing patterns (&plist :foo ’bar "baz") => + (&plist :foo foo ’bar bar "baz" baz) + + ;; we can specify some but not others (&plist :foo ’bar + explicit-bar) => (&plist :foo foo ’bar explicit-bar) + + ;; nothing happens, we store :foo in x (&plist :foo x) => (&plist + :foo x) + + ;; nothing happens, we match recursively (&plist :foo (a b c)) => + (&plist :foo (a b c)) + + You can name the source using the syntax SYMBOL &as PATTERN. This + syntax works with lists (proper or improper), vectors and all types + of maps. + + (list &as a b c) (list 1 2 3) + + binds A to 1, B to 2, C to 3 and LIST to (1 2 3). + + Similarly: + + (bounds &as beg . end) (cons 1 2) + + binds BEG to 1, END to 2 and BOUNDS to (1 . 2). + + (items &as first . rest) (list 1 2 3) + + binds FIRST to 1, REST to (2 3) and ITEMS to (1 2 3) + + [vect &as _ b c] [1 2 3] + + binds B to 2, C to 3 and VECT to [1 2 3] (_ avoids binding as + usual). + + (plist &as &plist :b b) (list :a 1 :b 2 :c 3) + + binds B to 2 and PLIST to (:a 1 :b 2 :c 3). Same for &alist and + &hash. + + This is especially useful when we want to capture the result of a + computation and destructure at the same time. Consider the form + (function-returning-complex-structure) returning a list of two + vectors with two items each. We want to capture this entire result + and pass it to another computation, but at the same time we want to + get the second item from each vector. We can achieve it with + pattern + + (result &as [_ a] [_ b]) (function-returning-complex-structure) + + Note: Clojure programmers may know this feature as the ":as + binding". The difference is that we put the &as at the front + because we need to support improper list binding. + + (-let (([a (b c) d] [1 (2 3) 4])) (list a b c d)) + ⇒ (1 2 3 4) + (-let [(a b c . d) (list 1 2 3 4 5 6)] (list a b c d)) + ⇒ (1 2 3 (4 5 6)) + (-let [(&plist :foo foo :bar bar) (list :baz 3 :foo 1 :qux 4 :bar 2)] (list foo bar)) + ⇒ (1 2) + + -- Macro: -let* (varlist &rest body) + Bind variables according to VARLIST then eval BODY. + + VARLIST is a list of lists of the form (PATTERN SOURCE). Each + PATTERN is matched against the SOURCE structurally. SOURCE is only + evaluated once for each PATTERN. + + Each SOURCE can refer to the symbols already bound by this VARLIST. + This is useful if you want to destructure SOURCE recursively but + also want to name the intermediate structures. + + See ‘-let’ (*note -let::) for the list of all possible patterns. + + (-let* (((a . b) (cons 1 2)) ((c . d) (cons 3 4))) (list a b c d)) + ⇒ (1 2 3 4) + (-let* (((a . b) (cons 1 (cons 2 3))) ((c . d) b)) (list a b c d)) + ⇒ (1 (2 . 3) 2 3) + (-let* (((&alist "foo" foo "bar" bar) (list (cons "foo" 1) (cons "bar" (list 'a 'b 'c)))) ((a b c) bar)) (list foo a b c bar)) + ⇒ (1 a b c (a b c)) + + -- Macro: -lambda (match-form &rest body) + Return a lambda which destructures its input as MATCH-FORM and + executes BODY. + + Note that you have to enclose the MATCH-FORM in a pair of parens, + such that: + + (-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. + + See ‘-let’ (*note -let::) for a description of the destructuring + mechanism. + + (-map (-lambda ((x y)) (+ x y)) '((1 2) (3 4) (5 6))) + ⇒ (3 7 11) + (-map (-lambda ([x y]) (+ x y)) '([1 2] [3 4] [5 6])) + ⇒ (3 7 11) + (funcall (-lambda ((_ . a) (_ . b)) (-concat a b)) '(1 2 3) '(4 5 6)) + ⇒ (2 3 5 6) + + -- Macro: -setq ([match-form val] ...) + Bind each MATCH-FORM to the value of its VAL. + + MATCH-FORM destructuring is done according to the rules of ‘-let’ + (*note -let::). + + This macro allows you to bind multiple variables by destructuring + the value, so for example: + + (-setq (a b) x (&plist :c c) plist) + + expands roughly speaking to the following code + + (setq a (car x) b (cadr x) c (plist-get plist :c)) + + Care is taken to only evaluate each VAL once so that in case of + multiple assignments it does not cause unexpected side effects. + + (let (a) (-setq a 1) a) + ⇒ 1 + (let (a b) (-setq (a b) (list 1 2)) (list a b)) + ⇒ (1 2) + (let (c) (-setq (&plist :c c) (list :c "c")) c) + ⇒ "c" + + +File: dash.info, Node: Side effects, Next: Destructive operations, Prev: Binding, Up: Functions + +2.14 Side effects +================= + +Functions iterating over lists for side effect only. + + -- Function: -each (list fn) + 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 (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 + + -- Function: -each-while (list pred fn) + 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 (l) (-each-while '(2 4 5 6) #'even? (lambda (x) (push x l))) l) + ⇒ (4 2) + (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) (< it 5) (setq s (+ s it))) s) + ⇒ 8 + + -- Function: -each-indexed (list fn) + 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::). + + (let (l) (-each-indexed '(a b c) (lambda (i x) (push (list x i) l))) l) + ⇒ ((c 2) (b 1) (a 0)) + (let (l) (--each-indexed '(a b c) (push (list it it-index) l)) l) + ⇒ ((c 2) (b 1) (a 0)) + (let (l) (--each-indexed () (push it l)) l) + ⇒ () + + -- Function: -each-r (list fn) + 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 (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 + + -- Function: -each-r-while (list pred fn) + 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 (l) (-each-r-while '(2 4 5 6) #'even? (lambda (x) (push x l))) l) + ⇒ (6) + (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) (> it 1) (setq s (+ s it))) s) + ⇒ 10 + + -- Function: -dotimes (num fn) + 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) (push n s))) s) + ⇒ (2 1 0) + (let (s) (-dotimes 0 (lambda (n) (push n s))) s) + ⇒ () + (let (s) (--dotimes 5 (push it s)) s) + ⇒ (4 3 2 1 0) + + +File: dash.info, Node: Destructive operations, Next: Function combinators, Prev: Side effects, Up: Functions + +2.15 Destructive operations +=========================== + +Macros that modify variables holding lists. + + -- Macro: !cons (car cdr) + Destructive: Set CDR to the cons of CAR and CDR. + + (let (l) (!cons 5 l) l) + ⇒ (5) + (let ((l '(3))) (!cons 5 l) l) + ⇒ (5 3) + + -- Macro: !cdr (list) + Destructive: Set LIST to the cdr of LIST. + + (let ((l '(3))) (!cdr l) l) + ⇒ () + (let ((l '(3 5))) (!cdr l) l) + ⇒ (5) + + +File: dash.info, Node: Function combinators, Prev: Destructive operations, Up: Functions + +2.16 Function combinators +========================= + +Functions that manipulate and compose other functions. + + -- Function: -partial (fun &rest args) + Return a function that is a partial application of FUN to ARGS. + ARGS is a list of the first N arguments to pass to FUN. The result + is a new function which does the same as FUN, except that the first + N arguments are fixed at the values with which this function was + called. + + (funcall (-partial #'+ 5)) + ⇒ 5 + (funcall (-partial #'- 5) 3) + ⇒ 2 + (funcall (-partial #'+ 5 2) 3) + ⇒ 10 + + -- Function: -rpartial (fn &rest args) + Return a function that is a partial application of FN to ARGS. + ARGS is a list of the last N arguments to pass to FN. The result + is a new function which does the same as FN, except that the last N + arguments are fixed at the values with which this function was + called. This is like ‘-partial’ (*note -partial::), except the + arguments are fixed starting from the right rather than the left. + + (funcall (-rpartial #'- 5)) + ⇒ -5 + (funcall (-rpartial #'- 5) 8) + ⇒ 3 + (funcall (-rpartial #'- 5 2) 10) + ⇒ 3 + + -- Function: -juxt (&rest fns) + Return a function that is the juxtaposition of FNS. The returned + function takes a variable number of ARGS, applies each of FNS in + turn to ARGS, and returns the list of results. + + (funcall (-juxt) 1 2) + ⇒ () + (funcall (-juxt #'+ #'- #'* #'/) 7 5) + ⇒ (12 2 35 1) + (mapcar (-juxt #'number-to-string #'1+) '(1 2)) + ⇒ (("1" 2) ("2" 3)) + + -- Function: -compose (&rest fns) + Compose FNS into a single composite function. Return a function + that takes a variable number of ARGS, applies the last function in + FNS to ARGS, and returns the result of calling each remaining + function on the result of the previous function, right-to-left. If + no FNS are given, return a variadic ‘identity’ function. + + (funcall (-compose #'- #'1+ #'+) 1 2 3) + ⇒ -7 + (funcall (-compose #'identity #'1+) 3) + ⇒ 4 + (mapcar (-compose #'not #'stringp) '(nil "")) + ⇒ (t nil) + + -- Function: -applify (fn) + Return a function that applies FN to a single list of args. This + changes the arity of FN from taking N distinct arguments to taking + 1 argument which is a list of N arguments. + + (funcall (-applify #'+) nil) + ⇒ 0 + (mapcar (-applify #'+) '((1 1 1) (1 2 3) (5 5 5))) + ⇒ (3 6 15) + (funcall (-applify #'<) '(3 6)) + ⇒ t + + -- Function: -on (op trans) + Return a function that calls TRANS on each arg and OP on the + results. The returned function takes a variable number of + arguments, calls the function TRANS on each one in turn, and then + passes those results as the list of arguments to OP, in the same + order. + + For example, the following pairs of expressions are morally + equivalent: + + (funcall (-on #’+ #’1+) 1 2 3) = (+ (1+ 1) (1+ 2) (1+ 3)) (funcall + (-on #’+ #’1+)) = (+) + + (-sort (-on #'< #'length) '((1 2 3) (1) (1 2))) + ⇒ ((1) (1 2) (1 2 3)) + (funcall (-on #'min #'string-to-number) "22" "2" "1" "12") + ⇒ 1 + (-min-by (-on #'> #'length) '((1 2 3) (4) (1 2))) + ⇒ (4) + + -- Function: -flip (fn) + Return a function that calls FN with its arguments reversed. The + returned function takes the same number of arguments as FN. + + For example, the following two expressions are morally equivalent: + + (funcall (-flip #’-) 1 2) = (- 2 1) + + See also: ‘-rotate-args’ (*note -rotate-args::). + + (-sort (-flip #'<) '(4 3 6 1)) + ⇒ (6 4 3 1) + (funcall (-flip #'-) 3 2 1 10) + ⇒ 4 + (funcall (-flip #'1+) 1) + ⇒ 2 + + -- Function: -rotate-args (n fn) + Return a function that calls FN with args rotated N places to the + right. The returned function takes the same number of arguments as + FN, rotates the list of arguments N places to the right (left if N + is negative) just like ‘-rotate’ (*note -rotate::), and applies FN + to the result. + + See also: ‘-flip’ (*note -flip::). + + (funcall (-rotate-args -1 #'list) 1 2 3 4) + ⇒ (2 3 4 1) + (funcall (-rotate-args 1 #'-) 1 10 100) + ⇒ 89 + (funcall (-rotate-args 2 #'list) 3 4 5 1 2) + ⇒ (1 2 3 4 5) + + -- Function: -const (c) + Return a function that returns C ignoring any additional arguments. + + In types: a -> b -> a + + (funcall (-const 2) 1 3 "foo") + ⇒ 2 + (mapcar (-const 1) '("a" "b" "c" "d")) + ⇒ (1 1 1 1) + (-sum (mapcar (-const 1) '("a" "b" "c" "d"))) + ⇒ 4 + + -- Macro: -cut (&rest params) + Take n-ary function and n arguments and specialize some of them. + Arguments denoted by <> will be left unspecialized. + + See SRFI-26 for detailed description. + + (funcall (-cut list 1 <> 3 <> 5) 2 4) + ⇒ (1 2 3 4 5) + (-map (-cut funcall <> 5) `(1+ 1- ,(lambda (x) (/ 1.0 x)))) + ⇒ (6 4 0.2) + (-map (-cut <> 1 2 3) '(list vector string)) + ⇒ ((1 2 3) [1 2 3] "\1\2\3") + + -- Function: -not (pred) + Return a predicate that negates the result of PRED. The returned + predicate passes its arguments to PRED. If PRED returns ‘nil’, the + result is non-‘nil’; otherwise the result is ‘nil’. + + See also: ‘-andfn’ (*note -andfn::) and ‘-orfn’ (*note -orfn::). + + (funcall (-not #'numberp) "5") + ⇒ t + (-sort (-not #'<) '(5 2 1 0 6)) + ⇒ (6 5 2 1 0) + (-filter (-not (-partial #'< 4)) '(1 2 3 4 5 6 7 8)) + ⇒ (1 2 3 4) + + -- Function: -orfn (&rest preds) + Return a predicate that returns the first non-‘nil’ result of + PREDS. The returned predicate takes a variable number of + arguments, passes them to each predicate in PREDS in turn until one + of them returns non-‘nil’, and returns that non-‘nil’ result + without calling the remaining PREDS. If all PREDS return ‘nil’, or + if no PREDS are given, the returned predicate returns ‘nil’. + + See also: ‘-andfn’ (*note -andfn::) and ‘-not’ (*note -not::). + + (-filter (-orfn #'natnump #'booleanp) '(1 nil "a" -4 b c t)) + ⇒ (1 nil t) + (funcall (-orfn #'symbolp (-cut string-match-p "x" <>)) "axe") + ⇒ 1 + (funcall (-orfn #'= #'+) 1 1) + ⇒ t + + -- Function: -andfn (&rest preds) + Return a predicate that returns non-‘nil’ if all PREDS do so. The + returned predicate P takes a variable number of arguments and + passes them to each predicate in PREDS in turn. If any one of + PREDS returns ‘nil’, P also returns ‘nil’ without calling the + remaining PREDS. If all PREDS return non-‘nil’, P returns the last + such value. If no PREDS are given, P always returns non-‘nil’. + + See also: ‘-orfn’ (*note -orfn::) and ‘-not’ (*note -not::). + + (-filter (-andfn #'numberp (-cut < <> 5)) '(a 1 b 6 c 2)) + ⇒ (1 2) + (mapcar (-andfn #'numberp #'1+) '(a 1 b 6)) + ⇒ (nil 2 nil 7) + (funcall (-andfn #'= #'+) 1 1) + ⇒ 2 + + -- Function: -iteratefn (fn n) + Return a function FN composed N times with itself. + + FN is a unary function. If you need to use a function of higher + arity, use ‘-applify’ (*note -applify::) first to turn it into a + unary function. + + With n = 0, this acts as identity function. + + In types: (a -> a) -> Int -> a -> a. + + This function satisfies the following law: + + (funcall (-iteratefn fn n) init) = (-last-item (-iterate fn init + (1+ n))). + + (funcall (-iteratefn (lambda (x) (* x x)) 3) 2) + ⇒ 256 + (funcall (-iteratefn '1+ 3) 1) + ⇒ 4 + (funcall (-iteratefn 'cdr 3) '(1 2 3 4 5)) + ⇒ (4 5) + + -- Function: -fixfn (fn &optional equal-test halt-test) + Return a function that computes the (least) fixpoint of FN. + + FN must be a unary function. The returned lambda takes a single + argument, X, the initial value for the fixpoint iteration. The + iteration halts when either of the following conditions is + satisfied: + + 1. Iteration converges to the fixpoint, with equality being tested + using EQUAL-TEST. If EQUAL-TEST is not specified, ‘equal’ is used. + For functions over the floating point numbers, it may be necessary + to provide an appropriate approximate comparison test. + + 2. HALT-TEST returns a non-‘nil’ value. HALT-TEST defaults to a + simple counter that returns ‘t’ after ‘-fixfn-max-iterations’, to + guard against infinite iteration. Otherwise, HALT-TEST must be a + function that accepts a single argument, the current value of X, + and returns non-‘nil’ as long as iteration should continue. In + this way, a more sophisticated convergence test may be supplied by + the caller. + + The return value of the lambda is either the fixpoint or, if + iteration halted before converging, a cons with car ‘halted’ and + cdr the final output from HALT-TEST. + + In types: (a -> a) -> a -> a. + + (funcall (-fixfn #'cos #'approx=) 0.7) + ⇒ 0.7390851332151607 + (funcall (-fixfn (lambda (x) (expt (+ x 10) 0.25))) 2.0) + ⇒ 1.8555845286409378 + (funcall (-fixfn #'sin #'approx=) 0.1) + ⇒ (halted . t) + + -- Function: -prodfn (&rest fns) + Return a function that applies each of FNS to each of a list of + arguments. + + Takes a list of N functions and returns a function that takes a + list of length N, applying Ith function to Ith element of the input + list. Returns a list of length N. + + In types (for N=2): ((a -> b), (c -> d)) -> (a, c) -> (b, d) + + 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 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)) + + (funcall (-prodfn #'1+ #'1- #'number-to-string) '(1 2 3)) + ⇒ (2 1 "3") + (-map (-prodfn #'1- #'1+) '((1 2) (3 4) (5 6))) + ⇒ ((0 3) (2 5) (4 7)) + (apply #'+ (funcall (-prodfn #'length #'string-to-number) '((t) "5"))) + ⇒ 6 + + +File: dash.info, Node: Development, Next: FDL, Prev: Functions, Up: Top + +3 Development +************* + +The Dash repository is hosted on GitHub at +. + +* Menu: + +* Contribute:: How to contribute. +* Contributors:: List of contributors. + + +File: dash.info, Node: Contribute, Next: Contributors, Up: Development + +3.1 Contribute +============== + +Yes, please do. Pure functions in the list manipulation realm only, +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 ‘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 dev/pre-commit.sh .git/hooks/pre-commit + + 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: Contributors, Prev: Contribute, Up: Development + +3.2 Contributors +================ + + • Matus Goljer (https://github.com/Fuco1) contributed lots of + features and functions. + • Takafumi Arakaki (https://github.com/tkf) contributed ‘-group-by’. + • tali713 (https://github.com/tali713) is the author of ‘-applify’. + • Víctor M. Valenzuela (https://github.com/vemv) contributed + ‘-repeat’. + • Nic Ferrier (https://github.com/nicferrier) contributed ‘-cons*’. + • Wilfred Hughes (https://github.com/Wilfred) contributed ‘-slice’, + ‘-first-item’, and ‘-last-item’. + • Emanuel Evans (https://github.com/shosti) contributed ‘-if-let’, + ‘-when-let’, and ‘-insert-at’. + • Johan Andersson (https://github.com/rejeep) contributed ‘-sum’, + ‘-product’, and ‘-same-items?’. + • Christina Whyte (https://github.com/kurisuwhyte) contributed + ‘-compose’. + • Steve Lamb (https://github.com/steventlamb) contributed ‘-cycle’, + ‘-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 the script for + generating documentation. + • Mark Oteiza (https://github.com/holomorph) contributed ‘-iota’ and + the script 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’, ‘-common-suffix’, and various other + improvements. + • 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: 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 +***** + +[index] +* Menu: + +* !cdr: Destructive operations. + (line 16) +* !cons: Destructive operations. + (line 8) +* -->: Threading macros. (line 35) +* ->: Threading macros. (line 9) +* ->>: Threading macros. (line 22) +* -all?: Predicates. (line 53) +* -andfn: Function combinators. + (line 184) +* -annotate: Maps. (line 86) +* -any?: Predicates. (line 41) +* -applify: Function combinators. + (line 63) +* -as->: Threading macros. (line 49) +* -butlast: Other list operations. + (line 405) +* -clone: Tree operations. (line 123) +* -common-prefix: Reductions. (line 242) +* -common-suffix: Reductions. (line 252) +* -compose: Function combinators. + (line 49) +* -concat: List to list. (line 23) +* -cons*: Other list operations. + (line 19) +* -cons-pair?: Predicates. (line 154) +* -const: Function combinators. + (line 128) +* -contains?: Predicates. (line 100) +* -copy: Maps. (line 151) +* -count: Reductions. (line 172) +* -cut: Function combinators. + (line 140) +* -cycle: Unfolding. (line 55) +* -difference: Set operations. (line 22) +* -distinct: Set operations. (line 73) +* -dotimes: Side effects. (line 80) +* -doto: Threading macros. (line 99) +* -drop: Sublist selection. (line 149) +* -drop-last: Sublist selection. (line 163) +* -drop-while: Sublist selection. (line 194) +* -each: Side effects. (line 8) +* -each-indexed: Side effects. (line 38) +* -each-r: Side effects. (line 52) +* -each-r-while: Side effects. (line 65) +* -each-while: Side effects. (line 24) +* -elem-index: Indexing. (line 9) +* -elem-indices: Indexing. (line 23) +* -every: Predicates. (line 23) +* -fifth-item: Other list operations. + (line 380) +* -filter: Sublist selection. (line 8) +* -find-index: Indexing. (line 35) +* -find-indices: Indexing. (line 73) +* -find-last-index: Indexing. (line 54) +* -first: Other list operations. + (line 300) +* -first-item: Other list operations. + (line 328) +* -fix: Other list operations. + (line 445) +* -fixfn: Function combinators. + (line 224) +* -flatten: List to list. (line 38) +* -flatten-n: List to list. (line 60) +* -flip: Function combinators. + (line 95) +* -fourth-item: Other list operations. + (line 367) +* -frequencies: Reductions. (line 310) +* -grade-down: Indexing. (line 103) +* -grade-up: Indexing. (line 93) +* -group-by: Partitioning. (line 205) +* -if-let: Binding. (line 34) +* -if-let*: Binding. (line 45) +* -inits: Reductions. (line 222) +* -insert-at: List to list. (line 114) +* -interleave: Other list operations. + (line 56) +* -interpose: Other list operations. + (line 46) +* -intersection: Set operations. (line 36) +* -iota: Other list operations. + (line 67) +* -is-infix?: Predicates. (line 140) +* -is-prefix?: Predicates. (line 116) +* -is-suffix?: Predicates. (line 128) +* -iterate: Unfolding. (line 9) +* -iteratefn: Function combinators. + (line 201) +* -juxt: Function combinators. + (line 37) +* -keep: List to list. (line 8) +* -lambda: Binding. (line 247) +* -last: Other list operations. + (line 318) +* -last-item: Other list operations. + (line 393) +* -let: Binding. (line 61) +* -let*: Binding. (line 227) +* -list: Other list operations. + (line 428) +* -map: Maps. (line 10) +* -map-first: Maps. (line 38) +* -map-indexed: Maps. (line 68) +* -map-last: Maps. (line 53) +* -map-when: Maps. (line 22) +* -mapcat: Maps. (line 140) +* -max: Reductions. (line 286) +* -max-by: Reductions. (line 296) +* -min: Reductions. (line 262) +* -min-by: Reductions. (line 272) +* -non-nil: Sublist selection. (line 95) +* -none?: Predicates. (line 73) +* -not: Function combinators. + (line 153) +* -on: Function combinators. + (line 75) +* -only-some?: Predicates. (line 85) +* -orfn: Function combinators. + (line 167) +* -pad: Other list operations. + (line 241) +* -partial: Function combinators. + (line 8) +* -partition: Partitioning. (line 90) +* -partition-after-item: Partitioning. (line 195) +* -partition-after-pred: Partitioning. (line 162) +* -partition-all: Partitioning. (line 102) +* -partition-all-in-steps: Partitioning. (line 126) +* -partition-before-item: Partitioning. (line 185) +* -partition-before-pred: Partitioning. (line 174) +* -partition-by: Partitioning. (line 138) +* -partition-by-header: Partitioning. (line 149) +* -partition-in-steps: Partitioning. (line 113) +* -permutations: Set operations. (line 60) +* -powerset: Set operations. (line 50) +* -prodfn: Function combinators. + (line 258) +* -product: Reductions. (line 201) +* -reduce: Reductions. (line 53) +* -reduce-from: Reductions. (line 8) +* -reduce-r: Reductions. (line 72) +* -reduce-r-from: Reductions. (line 26) +* -reductions: Reductions. (line 136) +* -reductions-from: Reductions. (line 100) +* -reductions-r: Reductions. (line 154) +* -reductions-r-from: Reductions. (line 118) +* -remove: Sublist selection. (line 26) +* -remove-at: List to list. (line 151) +* -remove-at-indices: List to list. (line 170) +* -remove-first: Sublist selection. (line 44) +* -remove-item: Sublist selection. (line 84) +* -remove-last: Sublist selection. (line 65) +* -repeat: Unfolding. (line 44) +* -replace: List to list. (line 72) +* -replace-at: List to list. (line 125) +* -replace-first: List to list. (line 86) +* -replace-last: List to list. (line 100) +* -rotate: Other list operations. + (line 8) +* -rotate-args: Function combinators. + (line 112) +* -rpartial: Function combinators. + (line 22) +* -running-product: Reductions. (line 211) +* -running-sum: Reductions. (line 190) +* -same-items?: Set operations. (line 88) +* -second-item: Other list operations. + (line 341) +* -select-by-indices: Sublist selection. (line 211) +* -select-column: Sublist selection. (line 241) +* -select-columns: Sublist selection. (line 222) +* -separate: Partitioning. (line 75) +* -setq: Binding. (line 270) +* -slice: Sublist selection. (line 105) +* -snoc: Other list operations. + (line 32) +* -some: Predicates. (line 8) +* -some-->: Threading macros. (line 86) +* -some->: Threading macros. (line 62) +* -some->>: Threading macros. (line 74) +* -sort: Other list operations. + (line 415) +* -splice: Maps. (line 102) +* -splice-list: Maps. (line 127) +* -split-at: Partitioning. (line 8) +* -split-on: Partitioning. (line 40) +* -split-when: Partitioning. (line 58) +* -split-with: Partitioning. (line 23) +* -sum: Reductions. (line 180) +* -table: Other list operations. + (line 256) +* -table-flat: Other list operations. + (line 275) +* -tails: Reductions. (line 232) +* -take: Sublist selection. (line 121) +* -take-last: Sublist selection. (line 135) +* -take-while: Sublist selection. (line 177) +* -third-item: Other list operations. + (line 354) +* -tree-map: Tree operations. (line 28) +* -tree-map-nodes: Tree operations. (line 39) +* -tree-mapreduce: Tree operations. (line 85) +* -tree-mapreduce-from: Tree operations. (line 104) +* -tree-reduce: Tree operations. (line 53) +* -tree-reduce-from: Tree operations. (line 70) +* -tree-seq: Tree operations. (line 8) +* -unfold: Unfolding. (line 25) +* -union: Set operations. (line 8) +* -unzip: Other list operations. + (line 215) +* -unzip-lists: Other list operations. + (line 196) +* -update-at: List to list. (line 137) +* -when-let: Binding. (line 9) +* -when-let*: Binding. (line 21) +* -zip: Other list operations. + (line 150) +* -zip-fill: Other list operations. + (line 176) +* -zip-lists: Other list operations. + (line 114) +* -zip-lists-fill: Other list operations. + (line 135) +* -zip-pair: Other list operations. + (line 98) +* -zip-with: Other list operations. + (line 80) +* dash-fontify-mode: Fontification of special variables. + (line 6) +* dash-register-info-lookup: Info symbol lookup. (line 6) +* global-dash-fontify-mode: Fontification of special variables. + (line 12) + + + +Tag Table: +Node: Top742 +Node: Installation2397 +Node: Using in a package3159 +Node: Fontification of special variables3504 +Node: Info symbol lookup4294 +Node: Functions4877 +Node: Maps6361 +Ref: -map6658 +Ref: -map-when7031 +Ref: -map-first7605 +Ref: -map-last8200 +Ref: -map-indexed8790 +Ref: -annotate9476 +Ref: -splice10080 +Ref: -splice-list11155 +Ref: -mapcat11614 +Ref: -copy11987 +Node: Sublist selection12175 +Ref: -filter12368 +Ref: -remove12921 +Ref: -remove-first13470 +Ref: -remove-last14318 +Ref: -remove-item15048 +Ref: -non-nil15448 +Ref: -slice15730 +Ref: -take16259 +Ref: -take-last16677 +Ref: -drop17114 +Ref: -drop-last17561 +Ref: -take-while17993 +Ref: -drop-while18620 +Ref: -select-by-indices19253 +Ref: -select-columns19764 +Ref: -select-column20467 +Node: List to list20930 +Ref: -keep21122 +Ref: -concat21698 +Ref: -flatten22226 +Ref: -flatten-n22988 +Ref: -replace23372 +Ref: -replace-first23833 +Ref: -replace-last24328 +Ref: -insert-at24816 +Ref: -replace-at25141 +Ref: -update-at25528 +Ref: -remove-at26069 +Ref: -remove-at-indices26696 +Node: Reductions27386 +Ref: -reduce-from27582 +Ref: -reduce-r-from28306 +Ref: -reduce29569 +Ref: -reduce-r30320 +Ref: -reductions-from31598 +Ref: -reductions-r-from32404 +Ref: -reductions33234 +Ref: -reductions-r33945 +Ref: -count34690 +Ref: -sum34920 +Ref: -running-sum35108 +Ref: -product35429 +Ref: -running-product35637 +Ref: -inits35978 +Ref: -tails36223 +Ref: -common-prefix36467 +Ref: -common-suffix36761 +Ref: -min37055 +Ref: -min-by37281 +Ref: -max37802 +Ref: -max-by38027 +Ref: -frequencies38553 +Node: Unfolding39168 +Ref: -iterate39409 +Ref: -unfold39856 +Ref: -repeat40661 +Ref: -cycle40945 +Node: Predicates41342 +Ref: -some41519 +Ref: -every41948 +Ref: -any?42662 +Ref: -all?43011 +Ref: -none?43753 +Ref: -only-some?44073 +Ref: -contains?44618 +Ref: -is-prefix?45124 +Ref: -is-suffix?45456 +Ref: -is-infix?45788 +Ref: -cons-pair?46148 +Node: Partitioning46479 +Ref: -split-at46667 +Ref: -split-with47331 +Ref: -split-on47971 +Ref: -split-when48642 +Ref: -separate49285 +Ref: -partition49819 +Ref: -partition-all50268 +Ref: -partition-in-steps50693 +Ref: -partition-all-in-steps51239 +Ref: -partition-by51753 +Ref: -partition-by-header52131 +Ref: -partition-after-pred52732 +Ref: -partition-before-pred53185 +Ref: -partition-before-item53570 +Ref: -partition-after-item53877 +Ref: -group-by54179 +Node: Indexing54612 +Ref: -elem-index54814 +Ref: -elem-indices55301 +Ref: -find-index55760 +Ref: -find-last-index56429 +Ref: -find-indices57080 +Ref: -grade-up57842 +Ref: -grade-down58249 +Node: Set operations58663 +Ref: -union58846 +Ref: -difference59276 +Ref: -intersection59704 +Ref: -powerset60133 +Ref: -permutations60410 +Ref: -distinct60848 +Ref: -same-items?61242 +Node: Other list operations61851 +Ref: -rotate62076 +Ref: -cons*62429 +Ref: -snoc62851 +Ref: -interpose63263 +Ref: -interleave63557 +Ref: -iota63923 +Ref: -zip-with64406 +Ref: -zip-pair65214 +Ref: -zip-lists65780 +Ref: -zip-lists-fill66578 +Ref: -zip67288 +Ref: -zip-fill68315 +Ref: -unzip-lists69229 +Ref: -unzip69852 +Ref: -pad70845 +Ref: -table71330 +Ref: -table-flat72116 +Ref: -first73121 +Ref: -last73654 +Ref: -first-item74000 +Ref: -second-item74412 +Ref: -third-item74829 +Ref: -fourth-item75204 +Ref: -fifth-item75582 +Ref: -last-item75957 +Ref: -butlast76318 +Ref: -sort76563 +Ref: -list77055 +Ref: -fix77624 +Node: Tree operations78113 +Ref: -tree-seq78309 +Ref: -tree-map79170 +Ref: -tree-map-nodes79610 +Ref: -tree-reduce80474 +Ref: -tree-reduce-from81356 +Ref: -tree-mapreduce81956 +Ref: -tree-mapreduce-from82815 +Ref: -clone84100 +Node: Threading macros84427 +Ref: ->84652 +Ref: ->>85140 +Ref: -->85643 +Ref: -as->86199 +Ref: -some->86653 +Ref: -some->>87038 +Ref: -some-->87485 +Ref: -doto88052 +Node: Binding88605 +Ref: -when-let88812 +Ref: -when-let*89273 +Ref: -if-let89802 +Ref: -if-let*90168 +Ref: -let90791 +Ref: -let*96881 +Ref: -lambda97818 +Ref: -setq98624 +Node: Side effects99425 +Ref: -each99619 +Ref: -each-while100146 +Ref: -each-indexed100766 +Ref: -each-r101358 +Ref: -each-r-while101800 +Ref: -dotimes102444 +Node: Destructive operations102997 +Ref: !cons103215 +Ref: !cdr103419 +Node: Function combinators103612 +Ref: -partial103816 +Ref: -rpartial104334 +Ref: -juxt104982 +Ref: -compose105434 +Ref: -applify106041 +Ref: -on106471 +Ref: -flip107243 +Ref: -rotate-args107767 +Ref: -const108396 +Ref: -cut108738 +Ref: -not109218 +Ref: -orfn109762 +Ref: -andfn110555 +Ref: -iteratefn111342 +Ref: -fixfn112044 +Ref: -prodfn113618 +Node: Development114769 +Node: Contribute115058 +Node: Contributors116070 +Node: FDL118163 +Node: GPL143483 +Node: Index181232 + +End Tag Table + + +Local Variables: +coding: utf-8 +End: diff --git a/org/elpa/dash-20230304.2223/dir b/org/elpa/dash-20230304.2223/dir new file mode 100644 index 0000000..7d473f4 --- /dev/null +++ b/org/elpa/dash-20230304.2223/dir @@ -0,0 +1,18 @@ +This is the file .../info/dir, which contains the +topmost node of the Info hierarchy, called (dir)Top. +The first time you invoke Info you start off looking at this node. + +File: dir, Node: Top This is the top of the INFO tree + + This (the Directory node) gives a menu of major topics. + Typing "q" exits, "H" lists all Info commands, "d" returns here, + "h" gives a primer for first-timers, + "mEmacs" visits the Emacs manual, etc. + + In Emacs, you can click mouse button 2 on a menu item or cross reference + to select it. + +* Menu: + +Emacs +* Dash: (dash.info). A modern list library for GNU Emacs. diff --git a/org/elpa/dashboard-20230331.2304/banners/1.txt b/org/elpa/dashboard-20230331.2304/banners/1.txt new file mode 100644 index 0000000..8bd71a7 --- /dev/null +++ b/org/elpa/dashboard-20230331.2304/banners/1.txt @@ -0,0 +1,8 @@ + +######## ## ## ### ###### ###### +## ### ### ## ## ## ## ## ## +## #### #### ## ## ## ## +###### ## ### ## ## ## ## ###### +## ## ## ######### ## ## +## ## ## ## ## ## ## ## ## +######## ## ## ## ## ###### ###### diff --git a/org/elpa/dashboard-20230331.2304/banners/2.txt b/org/elpa/dashboard-20230331.2304/banners/2.txt new file mode 100644 index 0000000..73b761b --- /dev/null +++ b/org/elpa/dashboard-20230331.2304/banners/2.txt @@ -0,0 +1,6 @@ + _______ .___ ___. ___ ______ _______. +| ____|| \/ | / \ / | / | +| |__ | \ / | / ^ \ | ,----' | (----` +| __| | |\/| | / /_\ \ | | \ \ +| |____ | | | | / _____ \ | `----.----) | +|_______||__| |__| /__/ \__\ \______|_______/ diff --git a/org/elpa/dashboard-20230331.2304/banners/3.txt b/org/elpa/dashboard-20230331.2304/banners/3.txt new file mode 100644 index 0000000..3abfd82 --- /dev/null +++ b/org/elpa/dashboard-20230331.2304/banners/3.txt @@ -0,0 +1,8 @@ + _______ _____ ______ ________ ________ ________ +|\ ___ \ |\ _ \ _ \|\ __ \|\ ____\|\ ____\ +\ \ __/|\ \ \\\__\ \ \ \ \|\ \ \ \___|\ \ \___|_ + \ \ \_|/_\ \ \\|__| \ \ \ __ \ \ \ \ \_____ \ + \ \ \_|\ \ \ \ \ \ \ \ \ \ \ \ \____\|____|\ \ + \ \_______\ \__\ \ \__\ \__\ \__\ \_______\____\_\ \ + \|_______|\|__| \|__|\|__|\|__|\|_______|\_________\ + \|_________| diff --git a/org/elpa/dashboard-20230331.2304/banners/4.txt b/org/elpa/dashboard-20230331.2304/banners/4.txt new file mode 100644 index 0000000..d82d67c --- /dev/null +++ b/org/elpa/dashboard-20230331.2304/banners/4.txt @@ -0,0 +1,17 @@ +_ ___ _ _ +_ ___ __ ___ __ _ ___ +__ _ ___ __ ___ + _ ___ _ + _ _ __ _ + ___ __ _ + __ _ + _ _ _ + _ _ _ + _ _ _ + __ ___ + _ _ _ _ + _ _ + _ _ + _ _ + _ +__ diff --git a/org/elpa/dashboard-20230331.2304/banners/emacs.png b/org/elpa/dashboard-20230331.2304/banners/emacs.png new file mode 100644 index 0000000..718b071 Binary files /dev/null and b/org/elpa/dashboard-20230331.2304/banners/emacs.png differ diff --git a/org/elpa/dashboard-20230331.2304/banners/logo.png b/org/elpa/dashboard-20230331.2304/banners/logo.png new file mode 100644 index 0000000..c9de00c Binary files /dev/null and b/org/elpa/dashboard-20230331.2304/banners/logo.png differ diff --git a/org/elpa/dashboard-20230331.2304/dashboard-autoloads.el b/org/elpa/dashboard-20230331.2304/dashboard-autoloads.el new file mode 100644 index 0000000..c82e439 --- /dev/null +++ b/org/elpa/dashboard-20230331.2304/dashboard-autoloads.el @@ -0,0 +1,44 @@ +;;; dashboard-autoloads.el --- automatically extracted autoloads -*- lexical-binding: t -*- +;; +;;; Code: + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + + +;;;### (autoloads nil "dashboard" "dashboard.el" (0 0 0 0)) +;;; Generated autoloads from dashboard.el + +(autoload 'dashboard-open "dashboard" "\ +Open (or refresh) the *dashboard* buffer. + +\(fn &rest _)" t nil) + +(autoload 'dashboard-setup-startup-hook "dashboard" "\ +Setup post initialization hooks. +If a command line argument is provided, assume a filename and skip displaying +Dashboard." nil nil) + +(register-definition-prefixes "dashboard" '("dashboard-")) + +;;;*** + +;;;### (autoloads nil "dashboard-widgets" "dashboard-widgets.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from dashboard-widgets.el + +(register-definition-prefixes "dashboard-widgets" '("dashboard-" "org-time-less-p" "recentf-list")) + +;;;*** + +;;;### (autoloads nil nil ("dashboard-pkg.el") (0 0 0 0)) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; coding: utf-8 +;; End: +;;; dashboard-autoloads.el ends here diff --git a/org/elpa/dashboard-20230331.2304/dashboard-pkg.el b/org/elpa/dashboard-20230331.2304/dashboard-pkg.el new file mode 100644 index 0000000..e40f2fd --- /dev/null +++ b/org/elpa/dashboard-20230331.2304/dashboard-pkg.el @@ -0,0 +1,12 @@ +(define-package "dashboard" "20230331.2304" "A startup screen extracted from Spacemacs" + '((emacs "26.1")) + :commit "0f970d298931f9de7b511086728af140bf44a642" :authors + '(("Rakan Al-Hneiti" . "rakan.alhneiti@gmail.com")) + :maintainer + '("Jesús Martínez" . "jesusmartinez93@gmail.com") + :keywords + '("startup" "screen" "tools" "dashboard") + :url "https://github.com/emacs-dashboard/emacs-dashboard") +;; Local Variables: +;; no-byte-compile: t +;; End: diff --git a/org/elpa/dashboard-20230331.2304/dashboard-widgets.el b/org/elpa/dashboard-20230331.2304/dashboard-widgets.el new file mode 100644 index 0000000..fff700e --- /dev/null +++ b/org/elpa/dashboard-20230331.2304/dashboard-widgets.el @@ -0,0 +1,1399 @@ +;;; dashboard-widgets.el --- A startup screen extracted from Spacemacs -*- lexical-binding: t -*- + +;; Copyright (c) 2016-2023 emacs-dashboard maintainers +;; +;; Author : Rakan Al-Hneiti +;; Maintainer : Jesús Martínez +;; Shen, Jen-Chieh +;; URL : https://github.com/emacs-dashboard/emacs-dashboard +;; +;; This file is not part of GNU Emacs. +;; +;;; License: GPLv3 +;; +;; Created: October 05, 2016 +;; Package-Version: 1.8.0-SNAPSHOT +;; Keywords: startup, screen, tools, dashboard +;; Package-Requires: ((emacs "26.1")) +;;; Commentary: + +;; An extensible Emacs dashboard, with sections for +;; bookmarks, projects (projectile or project.el), org-agenda and more. + +;;; Code: + +(require 'cl-lib) +(require 'image) +(require 'subr-x) + +;; 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") +(declare-function projectile-cleanup-known-projects "ext:projectile.el") +(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 project-forget-zombie-projects "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-get "ext:org.el") +(declare-function org-entry-is-done-p "ext:org.el") +(declare-function org-entry-is-todo-p "ext:org.el") +(declare-function org-get-category "ext:org.el") +(declare-function org-get-deadline-time "ext:org.el") +(declare-function org-get-heading "ext:org.el") +(declare-function org-get-priority "ext:org.el") +(declare-function org-get-scheduled-time "ext:org.el") +(declare-function org-get-tags "ext:org.el") +(declare-function org-get-todo-face "ext:org.el") +(declare-function org-get-todo-state "ext:org.el") +(declare-function org-in-archived-heading-p "ext:org.el") +(declare-function org-map-entries "ext:org.el") +(declare-function org-outline-level "ext:org.el") +(declare-function org-release-buffers "ext:org.el") +(declare-function org-time-string-to-time "ext:org.el") +(declare-function org-today "ext:org.el") +(declare-function recentf-cleanup "ext:recentf.el") +(defalias 'org-time-less-p 'time-less-p) +(defvar org-level-faces) +(defvar org-agenda-new-buffers) +(defvar org-agenda-prefix-format) +(defvar org-agenda-todo-keyword-format) +(defvar org-todo-keywords-1) +(defvar all-the-icons-dir-icon-alist) +(defvar package-activated-list) +(defvar elpaca-after-init-time) +(declare-function string-pixel-width "subr-x.el") ; TODO: remove this after 29.1 +(declare-function shr-string-pixel-width "shr.el") ; TODO: remove this after 29.1 + +(defcustom dashboard-page-separator "\n\n" + "Separator to use between the different pages." + :type 'string + :group 'dashboard) + +(defcustom dashboard-image-banner-max-height 0 + "Maximum height of banner image. + +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 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) + +(defcustom dashboard-set-heading-icons nil + "When non nil, heading sections will have icons." + :type 'boolean + :group 'dashboard) + +(defcustom dashboard-set-file-icons nil + "When non nil, file lists will have icons." + :type 'boolean + :group 'dashboard) + +(defcustom dashboard-set-navigator nil + "When non nil, a navigator will be displayed under the banner." + :type 'boolean + :group 'dashboard) + +(defcustom dashboard-set-init-info t + "When non nil, init info will be displayed under the banner." + :type 'boolean + :group 'dashboard) + +(defcustom dashboard-set-footer t + "When non nil, a footer will be displayed at the bottom." + :type 'boolean + :group 'dashboard) + +(defcustom dashboard-footer-messages + '("The one true editor, Emacs!" + "Who the hell uses VIM anyway? Go Evil!" + "Free as free speech, free as free Beer" + "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") + "A list of messages, one of which dashboard chooses to display." + :type 'list + :group 'dashboard) + +(defcustom dashboard-show-shortcuts t + "Whether to show shortcut keys for each section." + :type 'boolean + :group 'dashboard) + +(defconst dashboard-banners-directory + (concat (file-name-directory (locate-library "dashboard")) "banners/") + "Default banner directory.") + +(defconst dashboard-banner-official-png + (concat dashboard-banners-directory "emacs.png") + "Emacs banner image.") + +(defconst dashboard-banner-logo-png + (concat dashboard-banners-directory "logo.png") + "Emacs banner image.") + +(defcustom dashboard-banner-logo-title "Welcome to Emacs!" + "Specify the startup banner." + :type 'string + :group 'dashboard) + +(defcustom dashboard-banner-ascii "EMACS" + "String to be shown in place of the startup banner +if `dashboard-startup-banner' is set to `ascii'." + :type 'string + :group 'dashboard) + +(defcustom dashboard-navigator-buttons nil + "Specify the navigator buttons. +The format is: `icon title help action face prefix suffix`. + +Example: +`((\"☆\" \"Star\" \"Show stars\" (lambda (&rest _) + (show-stars)) warning \"[\" \"]\"))" + :type '(repeat (repeat (list string string string function symbol string string))) + :group 'dashboard) + +(defcustom dashboard-init-info + (lambda () + (let ((package-count 0) (time (emacs-init-time))) + (when (bound-and-true-p package-alist) + (setq package-count (length package-activated-list))) + (when (boundp 'straight--profile-cache) + (setq package-count (+ (hash-table-count straight--profile-cache) package-count))) + (when (fboundp 'elpaca--queued) + (setq time (format "%f seconds" (float-time (time-subtract elpaca-after-init-time + before-init-time)))) + (setq package-count (length (elpaca--queued)))) + (if (zerop package-count) + (format "Emacs started in %s" time) + (format "%d packages loaded in %s" package-count time)))) + "Init info with packages loaded and init time." + :type '(function string) + :group 'dashboard) + +(defcustom dashboard-footer + (nth (random (1- (1+ (length dashboard-footer-messages)))) dashboard-footer-messages) + "A footer with some short message." + :type 'string + :group 'dashboard) + +(defcustom dashboard-display-icons-p #'display-graphic-p + "Predicate to determine whether dashboard should show icons. +Can be nil to not show icons and any truthy value to show them. When set +to a function the result of the function will be interpreted as the +predicate value." + :type '(choice (function :tag "Predicate function") + (boolean :tag "Predicate value")) + :group 'dashboard) + +(defun dashboard-display-icons-p () + "Assert whether to show icons based on the `dashboard-display-icons-p' variable." + (if (functionp dashboard-display-icons-p) + (funcall dashboard-display-icons-p) + dashboard-display-icons-p)) + +(defcustom dashboard-footer-icon + (if (and (dashboard-display-icons-p) + (or (fboundp 'all-the-icons-fileicon) + (require 'all-the-icons nil 'noerror))) + (all-the-icons-fileicon "emacs" + :height 1.1 + :v-adjust -0.05 + :face 'font-lock-keyword-face) + (propertize ">" 'face 'dashboard-footer)) + "Footer's icon." + :type 'string + :group 'dashboard) + +(defcustom dashboard-startup-banner 'official + "Specify the startup banner. +Default value is `official', it displays the Emacs logo. `logo' displays Emacs +alternative logo. If set to `ascii', the value of `dashboard-banner-ascii' +will be used as the banner. An integer value is the index of text 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 "no banner" nil) + (const :tag "offical" official) + (const :tag "logo" logo) + (const :tag "ascii" ascii) + (integer :tag "index of a text banner") + (string :tag "a path to an image or text banner") + (cons :tag "an image and text banner" + (string :tag "image banner path") + (string :tag "text banner path"))) + :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)) + "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', +`agenda' ,`registers'." + :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)) + "Association list of items to show in the startup buffer. +Will be of the form `(list-type . list-size)'. +If nil it is disabled. Possible values for list-type are: +`recents' `bookmarks' `projects' `agenda' `registers'." + :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-item-names nil + "Association list of item heading names. +When an item is nil or not present, the default name is used. +Will be of the form `(default-name . new-name)'." + :type '(alist :key-type string :value-type string) + :options '("Recent Files:" "Bookmarks:" "Agenda for today:" + "Agenda for the coming week:" "Registers:" "Projects:") + :group 'dashboard) + +(defcustom dashboard-items-default-length 20 + "Length used for startup lists with otherwise unspecified bounds. +Set to nil for unbounded." + :type 'integer + :group 'dashboard) + +(defcustom dashboard-heading-icons + '((recents . "history") + (bookmarks . "bookmark") + (agenda . "calendar") + (projects . "rocket") + (registers . "database")) + "Association list for the icons of the heading sections. +Will be of the form `(list-type . icon-name-string)`. +If nil it is disabled. Possible values for list-type are: +`recents' `bookmarks' `projects' `agenda' `registers'" + :type '(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 +;; +(defface dashboard-text-banner + '((t (:inherit font-lock-keyword-face))) + "Face used for text banners." + :group 'dashboard) + +(defface dashboard-banner-logo-title + '((t :inherit default)) + "Face used for the banner title." + :group 'dashboard) + +(defface dashboard-navigator + '((t (:inherit font-lock-keyword-face))) + "Face used for the navigator." + :group 'dashboard) + +(defface dashboard-heading + '((t (:inherit font-lock-keyword-face))) + "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." + :group 'dashboard) + +(define-obsolete-face-alias + 'dashboard-text-banner-face 'dashboard-text-banner "1.2.6") +(define-obsolete-face-alias + 'dashboard-banner-logo-title-face 'dashboard-banner-logo-title "1.2.6") +(define-obsolete-face-alias + 'dashboard-heading-face 'dashboard-heading "1.2.6") + +;; +;; Util +;; +(defmacro dashboard-mute-apply (&rest body) + "Execute BODY without message." + (declare (indent 0) (debug t)) + `(let (message-log-max) + (with-temp-message (or (current-message) nil) + (let ((inhibit-message t)) ,@body)))) + +(defun dashboard-funcall-fboundp (fnc &rest args) + "Call FNC with ARGS if exists." + (when (fboundp fnc) (if args (funcall fnc args) (funcall fnc)))) + +;; TODO: Use function `string-pixel-width' after 29.1 +(defun dashboard-string-pixel-width (str) + "Return the width of STR in pixels." + (if (fboundp #'string-pixel-width) + (string-pixel-width str) + (require 'shr) + (shr-string-pixel-width str))) + +(defun dashboard-str-len (str) + "Calculate STR in pixel width." + (let ((width (frame-char-width)) + (len (dashboard-string-pixel-width str))) + (+ (/ len width) + (if (zerop (% len width)) 0 1)))) ; add one if exceeed + +;; +;; Generic widget helpers +;; +(defun dashboard-subseq (seq end) + "Return the subsequence of SEQ from 0 to END." + (let ((len (length seq))) (butlast seq (- len (min len end))))) + +(defun dashboard-get-shortcut-name (item) + "Get the shortcut name to be used for ITEM." + (let ((elem (rassoc item dashboard-item-shortcuts))) + (and elem (car elem)))) + +(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-id + 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." + (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)))) + ;; remove symbol quote + (sym (intern (replace-regexp-in-string "'" "" (format "dashboard-jump-to-%s" shortcut-id))))) + `(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))))) + +(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-buffer-name) + (goto-char (point-max)) + (let ((inhibit-read-only t)) (insert msg)))) + +(defun dashboard-modify-heading-icons (alist) + "Append ALIST items to `dashboard-heading-icons' to modify icons." + (dolist (icon alist) + (add-to-list 'dashboard-heading-icons icon))) + +(defun dashboard-insert-page-break () + "Insert a page break line in dashboard buffer." + (dashboard-append dashboard-page-separator)) + +(defun dashboard-insert-heading (heading &optional shortcut icon) + "Insert a widget HEADING in dashboard buffer, adding SHORTCUT, ICON if provided." + (when (and (dashboard-display-icons-p) dashboard-set-heading-icons) + ;; Try loading `all-the-icons' + (unless (or (fboundp 'all-the-icons-octicon) + (require 'all-the-icons nil 'noerror)) + (error "Package `all-the-icons' isn't installed")) + + (insert (cond + ((string-equal heading "Recent Files:") + (all-the-icons-octicon (cdr (assoc 'recents dashboard-heading-icons)) + :height 1.2 :v-adjust 0.0 :face 'dashboard-heading)) + ((string-equal heading "Bookmarks:") + (all-the-icons-octicon (cdr (assoc 'bookmarks dashboard-heading-icons)) + :height 1.2 :v-adjust 0.0 :face 'dashboard-heading)) + ((or (string-equal heading "Agenda for today:") + (string-equal heading "Agenda for the coming week:")) + (all-the-icons-octicon (cdr (assoc 'agenda dashboard-heading-icons)) + :height 1.2 :v-adjust 0.0 :face 'dashboard-heading)) + ((string-equal heading "Registers:") + (all-the-icons-octicon (cdr (assoc 'registers dashboard-heading-icons)) + :height 1.2 :v-adjust 0.0 :face 'dashboard-heading)) + ((string-equal heading "Projects:") + (all-the-icons-octicon (cdr (assoc 'projects dashboard-heading-icons)) + :height 1.2 :v-adjust 0.0 :face 'dashboard-heading)) + ((not (null icon)) icon) + (t " "))) + (insert " ")) + + (insert (propertize heading 'face 'dashboard-heading)) + + ;; Turn the inserted heading into an overlay, so that we may freely change + ;; its name without breaking any of the functions that expect the default name. + ;; If there isn't a suitable entry in `dashboard-item-names', + ;; we fallback to using HEADING. In that case we still want it to be an + ;; overlay to maintain consistent behavior (such as the point movement) + ;; between modified and default headings. + (let ((ov (make-overlay (- (point) (length heading)) (point) nil t))) + (overlay-put ov 'display (or (cdr (assoc heading dashboard-item-names)) heading)) + (overlay-put ov 'face 'dashboard-heading)) + (when shortcut (insert (format " (%s)" shortcut)))) + +(defun dashboard-center-text (start end) + "Center the text between START and END." + (save-excursion + (goto-char start) + (let ((width 0)) + (while (< (point) end) + (let* ((line-str (buffer-substring (line-beginning-position) (line-end-position))) + (line-length (dashboard-str-len line-str))) + (setq width (max width line-length))) + (forward-line 1)) + (let ((prefix (propertize " " 'display `(space . (:align-to (- center ,(/ width 2))))))) + (add-text-properties start end `(line-prefix ,prefix indent-prefix ,prefix)))))) + +(defun dashboard-insert-center (&rest strings) + "Insert STRINGS in the center of the buffer." + (let ((start (point))) + (apply #'insert strings) + (dashboard-center-text start (point)))) + +;; +;; BANNER +;; + +(defun dashboard-get-banner-path (index) + "Return the full path to banner with index INDEX." + (concat dashboard-banners-directory (format "%d.txt" index))) + +(defun dashboard--image-supported-p (img) + "Return non-nil if IMG exists and is a supported image type." + ;; In Emacs 29.1 we could use `image-supported-file-p'. However: + ;; - We need to support Emacs 26. + ;; - That function will only look at filenames, this one will inspect the file data itself. + (and (file-exists-p img) (ignore-errors (image-type-available-p (image-type img))))) + +(defun dashboard-choose-banner () + "Return a plist specifying the chosen banner based on `dashboard-startup-banner'." + (pcase dashboard-startup-banner + ('nil nil) + ('official + (append (when (image-type-available-p 'png) + (list :image dashboard-banner-official-png)) + (list :text (dashboard-get-banner-path 1)))) + ('logo + (append (when (image-type-available-p 'png) + (list :image dashboard-banner-logo-png)) + (list :text (dashboard-get-banner-path 1)))) + ('ascii + (append (list :text dashboard-banner-ascii))) + ((pred integerp) + (list :text (dashboard-get-banner-path dashboard-startup-banner))) + ((pred stringp) + (pcase dashboard-startup-banner + ((pred (lambda (f) (not (file-exists-p f)))) + (message "could not find banner %s, use default instead" dashboard-startup-banner) + (list :text (dashboard-get-banner-path 1))) + ((pred (string-suffix-p ".txt")) + (list :text (if (file-exists-p dashboard-startup-banner) + dashboard-startup-banner + (message "could not find banner %s, use default instead" dashboard-startup-banner) + (dashboard-get-banner-path 1)))) + ((pred dashboard--image-supported-p) + (list :image dashboard-startup-banner + :text (dashboard-get-banner-path 1))) + (_ + (message "unsupported file type %s" (file-name-nondirectory dashboard-startup-banner)) + (list :text (dashboard-get-banner-path 1))))) + (`(,img . ,txt) + (list :image (if (dashboard--image-supported-p img) + img + (message "could not find banner %s, use default instead" img) + dashboard-banner-official-png) + :text (if (and (file-exists-p txt) (string-suffix-p ".txt" txt)) + txt + (message "could not find banner %s, use default instead" txt) + (dashboard-get-banner-path 1)))) + (_ + (message "unsupported banner config %s" dashboard-startup-banner)))) + +(defun dashboard--type-is-gif-p (image-path) + "Return if image is a gif. +String -> bool. +Argument IMAGE-PATH path to the image." + (eq 'gif (image-type image-path))) + +(defun dashboard-insert-banner () + "Insert the banner at the top of the dashboard." + (goto-char (point-max)) + (when-let (banner (dashboard-choose-banner)) + (insert "\n") + (let ((start (point)) + buffer-read-only + text-width + image-spec) + (insert "\n") + ;; If specified, insert a text banner. + (when-let (txt (plist-get banner :text)) + (if (eq dashboard-startup-banner 'ascii) + (save-excursion (insert txt)) + (insert-file-contents txt)) + (put-text-property (point) (point-max) 'face 'dashboard-text-banner) + (setq text-width 0) + (while (not (eobp)) + (let ((line-length (- (line-end-position) (line-beginning-position)))) + (if (< text-width line-length) + (setq text-width line-length))) + (forward-line 1))) + ;; If specified, insert an image banner. When displayed in a graphical frame, this will + ;; replace the text banner. + (when-let (img (plist-get banner :image)) + (let ((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))))) + (setq image-spec + (cond ((dashboard--type-is-gif-p img) + (create-image img)) + ((image-type-available-p 'imagemagick) + (apply 'create-image img 'imagemagick nil size-props)) + (t + (apply 'create-image img nil nil + (when (and (fboundp 'image-transforms-p) + (memq 'scale (funcall 'image-transforms-p))) + size-props)))))) + (add-text-properties start (point) `(display ,image-spec)) + (when (dashboard--type-is-gif-p img) (image-animate image-spec 0 t))) + ;; Finally, center the banner (if any). + (when-let* ((text-align-spec `(space . (:align-to (- center ,(/ text-width 2))))) + (image-align-spec `(space . (:align-to (- center (0.5 . ,image-spec))))) + (prop + (cond + ;; Both an image & text banner. + ((and image-spec text-width) + ;; The quoting is intentional. This is a conditional display spec that will + ;; align the banner at redisplay time. + `((when (display-graphic-p) . ,image-align-spec) + (when (not (display-graphic-p)) . ,text-align-spec))) + ;; One or the other. + (text-width text-align-spec) + (image-spec image-align-spec) + ;; No banner. + (t nil))) + (prefix (propertize " " 'display prop))) + (add-text-properties start (point) `(line-prefix ,prefix wrap-prefix ,prefix))) + (insert "\n\n") + (add-text-properties start (point) '(cursor-intangible t inhibit-isearch t)))) + (when dashboard-banner-logo-title + (dashboard-insert-center (propertize dashboard-banner-logo-title 'face 'dashboard-banner-logo-title)) + (insert "\n\n")) + (dashboard-insert-navigator) + (dashboard-insert-init-info)) + +;; +;; INIT INFO +;; +(defun dashboard-insert-init-info () + "Insert init info when `dashboard-set-init-info' is t." + (when dashboard-set-init-info + (let ((init-info (if (functionp dashboard-init-info) + (funcall dashboard-init-info) + dashboard-init-info))) + (dashboard-insert-center (propertize init-info 'face 'font-lock-comment-face))))) + +(defun dashboard-insert-navigator () + "Insert Navigator of the dashboard." + (when (and dashboard-set-navigator dashboard-navigator-buttons) + (dolist (line dashboard-navigator-buttons) + (dolist (btn line) + (let* ((icon (car btn)) + (title (cadr btn)) + (help (or (cadr (cdr btn)) "")) + (action (or (cadr (cddr btn)) #'ignore)) + (face (or (cadr (cddr (cdr btn))) 'dashboard-navigator)) + (prefix (or (cadr (cddr (cddr btn))) (propertize "[" 'face face))) + (suffix (or (cadr (cddr (cddr (cdr btn)))) (propertize "]" 'face face)))) + (widget-create 'item + :tag (concat + (when icon + (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 ""))) + (propertize " " 'face 'variable-pitch)) + (when title (propertize title 'face face))) + :help-echo help + :action action + :button-face 'dashboard-items-face + :mouse-face 'highlight + :button-prefix prefix + :button-suffix suffix + :format "%[%t%]") + (insert " "))) + (dashboard-center-text (line-beginning-position) (line-end-position)) + (insert "\n")) + (insert "\n"))) + +(defmacro dashboard-insert-section (section-name list list-size shortcut-id shortcut-char action &rest widget-params) + "Add a section with SECTION-NAME and LIST of LIST-SIZE items to the dashboard. + +SHORTCUT-CHAR is the keyboard shortcut used to access the section. +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 ,shortcut-char dashboard-show-shortcuts) ,shortcut-char)) + (if ,list + (when (and (dashboard-insert-section-list + ,section-name + (dashboard-subseq ,list ,list-size) + ,action + ,@widget-params) + ,shortcut-id ,shortcut-char) + (dashboard-insert-shortcut ,shortcut-id ,shortcut-char ,section-name)) + (insert (propertize "\n --- No items ---" 'face 'dashboard-no-items-face))))) + +;; +;; Section list +;; +(defmacro dashboard-insert-section-list (section-name list action &rest rest) + "Insert into SECTION-NAME a LIST of items, expanding ACTION and passing REST +to widget creation." + `(when (car ,list) + (mapc + (lambda (el) + (let ((tag ,@rest)) + (insert "\n ") + + (when (and (dashboard-display-icons-p) + dashboard-set-file-icons + (or (fboundp 'all-the-icons-icon-for-dir) + (require 'all-the-icons nil 'noerror))) + (let* ((path (car (last (split-string ,@rest " - ")))) + (icon (if (and (not (file-remote-p path)) + (file-directory-p path)) + (all-the-icons-icon-for-dir path nil "") + (cond + ((or (string-equal ,section-name "Agenda for today:") + (string-equal ,section-name "Agenda for the coming week:")) + (all-the-icons-octicon "primitive-dot" :height 1.0 :v-adjust 0.01)) + ((file-remote-p path) + (all-the-icons-octicon "radio-tower" :height 1.0 :v-adjust 0.01)) + (t (all-the-icons-icon-for-file (file-name-nondirectory path) + :v-adjust -0.05)))))) + (setq tag (concat icon " " ,@rest)))) + + (widget-create 'item + :tag tag + :action ,action + :button-face 'dashboard-items-face + :mouse-face 'highlight + :button-prefix "" + :button-suffix "" + :format "%[%t%]"))) + ,list))) + +;; Footer +(defun dashboard-random-footer () + "Return a random footer from `dashboard-footer-messages'." + (nth (random (length dashboard-footer-messages)) dashboard-footer-messages)) + +(defun dashboard-insert-footer () + "Insert footer of dashboard." + (when-let ((footer (and dashboard-set-footer (dashboard-random-footer)))) + (insert "\n") + (dashboard-insert-center + dashboard-footer-icon + " " + (propertize footer 'face 'dashboard-footer) + "\n"))) + +;; +;; Truncate +;; +(defcustom dashboard-shorten-by-window-width nil + "Shorten path by window edges." + :type 'boolean + :group 'dashboard) + +(defcustom dashboard-shorten-path-offset 0 + "Shorten path offset on the edges." + :type 'integer + :group 'dashboard) + +(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)) + (slen-path (dashboard-str-len path)) + (len-rep (dashboard-str-len dashboard-path-shorten-string)) + (len-total (- dashboard-path-max-length len-rep)) + front) + (if (<= slen-path dashboard-path-max-length) path + (setq front (ignore-errors (substring path (- slen-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)) + (slen-path (dashboard-str-len path)) + (len-rep (dashboard-str-len dashboard-path-shorten-string)) + (len-total (- dashboard-path-max-length len-rep)) + (center (/ len-total 2)) + (end-back center) + (start-front (- slen-path center)) + back front) + (if (<= slen-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)) + (slen-path (dashboard-str-len path)) + (len-rep (dashboard-str-len dashboard-path-shorten-string)) + (diff (- slen-path len-path)) + (len-total (- dashboard-path-max-length len-rep diff)) + back) + (if (<= slen-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--get-base-length (path type) + "Return the length of the base from the PATH by TYPE." + (let* ((is-dir (file-directory-p path)) + (base (if is-dir (dashboard-f-base path) (dashboard-f-filename path))) + (option (cl-case type + (recents 'dashboard-recentf-show-base) + (bookmarks 'dashboard-bookmarks-show-base) + (projects 'dashboard-projects-show-base))) + (option-val (symbol-value option)) + base-len) + (cl-case option-val + (`align (setq base-len (dashboard--align-length-by-type type))) + (`nil (setq base-len 0)) + (t (setq base-len (length base)))) + base-len)) + +(defun dashboard-shorten-path (path type) + "Shorten the PATH by TYPE." + (setq path (abbreviate-file-name path)) + (let ((dashboard-path-max-length + (if (and dashboard-path-style dashboard-shorten-by-window-width) + (- (window-width) (dashboard--get-base-length path type) + dashboard-shorten-path-offset) + dashboard-path-max-length))) + (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 type) + "Shorten all path from PATHS by TYPE 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 type) + ;; 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--align-length-by-type (type) + "Return the align length by TYPE of the section." + (let ((len-item (cdr (assoc type dashboard-items))) (count 0) (align-length -1) + len-list base) + (cl-case type + (`recents + (require 'recentf) + (setq len-list (length recentf-list)) + (while (and (< count len-item) (< count len-list)) + (setq base (nth count recentf-list) + align-length (max align-length (dashboard-str-len (dashboard-f-filename base)))) + (cl-incf count))) + (`bookmarks + (let ((bookmarks-lst (bookmark-all-names))) + (setq len-list (length bookmarks-lst)) + (while (and (< count len-item) (< count len-list)) + (setq base (nth count bookmarks-lst) + align-length (max align-length (dashboard-str-len base))) + (cl-incf count)))) + (`projects + (let ((projects-lst (dashboard-projects-backend-load-projects))) + (setq len-list (length projects-lst)) + (while (and (< count len-item) (< count len-list)) + (setq base (nth count projects-lst) + align-length (max align-length (dashboard-str-len (dashboard-f-base base)))) + (cl-incf count)))) + (t (error "Unknown type for align length: %s" type))) + 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) + (dashboard-mute-apply (recentf-mode 1) (recentf-cleanup)) + (dashboard-insert-section + "Recent Files:" + (dashboard-shorten-paths recentf-list 'dashboard-recentf-alist 'recents) + list-size + 'recents + (dashboard-get-shortcut 'recents) + `(lambda (&rest _) + (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--align-length-by-type 'recents)) + (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 path) + (t (format dashboard-recentf-item-format filename path)))))) + +;; +;; Bookmarks +;; +(defcustom dashboard-bookmarks-show-base t + "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-bookmarks-item-format "%s - %s" + "Format to use when showing the base of the file name." + :type 'string + :group 'dashboard) + +(defvar dashboard--bookmarks-cache-item-format nil + "Cache to record the new generated align format.") + +(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) list-size) + list-size + 'bookmarks + (dashboard-get-shortcut 'bookmarks) + `(lambda (&rest _) (bookmark-jump ,el)) + (if-let* ((filename el) + (path (bookmark-get-filename el)) + (path-shorten (dashboard-shorten-path path 'bookmarks))) + (cl-case dashboard-bookmarks-show-base + (`align + (unless dashboard--bookmarks-cache-item-format + (let* ((len-align (dashboard--align-length-by-type 'bookmarks)) + (new-fmt (dashboard--generate-align-format + dashboard-bookmarks-item-format len-align))) + (setq dashboard--bookmarks-cache-item-format new-fmt))) + (format dashboard--bookmarks-cache-item-format filename path-shorten)) + (`nil path-shorten) + (t (format dashboard-bookmarks-item-format filename path-shorten))) + el))) + +;; +;; 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." + (setq dashboard--projects-cache-item-format nil) + (dashboard-insert-section + "Projects:" + (dashboard-shorten-paths + (dashboard-subseq (dashboard-projects-backend-load-projects) list-size) + 'dashboard-projects-alist 'projects) + list-size + 'projects + (dashboard-get-shortcut 'projects) + `(lambda (&rest _) + (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--align-length-by-type 'projects)) + (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 path) + (t (format dashboard-projects-item-format filename path)))))) + +(defun dashboard-projects-backend-load-projects () + "Depending on `dashboard-projects-backend' load corresponding backend. +Return function that returns a list of projects." + (cl-case dashboard-projects-backend + (`projectile + (require 'projectile) + (dashboard-mute-apply (projectile-cleanup-known-projects)) + (projectile-load-known-projects)) + (`project-el + (require 'project) + (dashboard-mute-apply (dashboard-funcall-fboundp #'project-forget-zombie-projects)) + (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 + (cl-case dashboard-projects-backend + (`projectile 'projectile-switch-project-by-name) + (`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 +;; +(defcustom dashboard-week-agenda t + "Show agenda weekly if its not nil." + :type 'boolean + :group 'dashboard) + +(defcustom dashboard-agenda-time-string-format "%Y-%m-%d" + "Format time of agenda entries." + :type 'string + :group 'dashboard) + +(defcustom dashboard-match-agenda-entry nil + "Match agenda to extra filter. +It is the MATCH attribute for `org-map-entries'" + :type 'string + :group 'dashboard) + +(defcustom dashboard-agenda-release-buffers nil + "If not nil use `org-release-buffers' after getting the entries." + :type 'boolean + :group 'dashboard) + +(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) + +(defcustom dashboard-agenda-sort-strategy nil + "A list of strategies to sort the agenda. If nil agenda is not sorted." + :type '(repeat (choice (const priority-up) (const priority-down) + (const time-up) (const time-down) + (const todo-state-up) (const todo-state-down))) + :group 'dashboard) + +(defcustom dashboard-agenda-prefix-format " %i %-12:c %s " + "Format for each entry in the agenda. +When the dashboard-agenda is created this format is inserted into +`org-agenda-prefix-format' as `dashboard-agenda' and compiled with +`org-compile-prefix-format' previous calling `dashboard-agenda-entry-format' for +each agenda entry." + :type 'string + :group 'dashboard) + +(defcustom dashboard-agenda-tags-format 'identity + "Function to format the org agenda tags. +Any custom function would receives the tags from `org-get-tags'" + :type '(choice + (const :tag "Show tags" identity) + (const :tag "Hide tags" ignore) + (function :tag "Custom function")) + :group 'dashboard) + +(defun dashboard-agenda-entry-format () + "Format agenda entry to show it on dashboard. +Also,it set text properties that latter are used to sort entries and perform different actions." + (let* ((scheduled-time (org-get-scheduled-time (point))) + (deadline-time (org-get-deadline-time (point))) + (entry-timestamp (dashboard-agenda--entry-timestamp (point))) + (entry-time (or scheduled-time deadline-time entry-timestamp)) + (item (org-agenda-format-item + (dashboard-agenda--formatted-time) + (dashboard-agenda--formatted-headline) + (org-outline-level) + (org-get-category) + (dashboard-agenda--formatted-tags))) + (todo-state (org-get-todo-state)) + (item-priority (org-get-priority (org-get-heading t t t t))) + (todo-index (and todo-state + (length (member todo-state org-todo-keywords-1)))) + (entry-data (list 'dashboard-agenda-file (buffer-file-name) + 'dashboard-agenda-loc (point) + 'dashboard-agenda-priority item-priority + 'dashboard-agenda-todo-index todo-index + 'dashboard-agenda-time entry-time))) + (add-text-properties 0 (length item) entry-data item) + item)) + +(defun dashboard-agenda--entry-timestamp (point) + "Get the timestamp from an entry at POINT." + (when-let ((timestamp (org-entry-get point "TIMESTAMP"))) + (org-time-string-to-time timestamp))) + +(defun dashboard-agenda--formatted-headline () + "Set agenda faces to `HEADLINE' when face text property is nil." + (let* ((headline (org-get-heading t t t t)) + (todo (or (org-get-todo-state) "")) + (org-level-face (nth (- (org-outline-level) 1) org-level-faces)) + (todo-state (format org-agenda-todo-keyword-format todo))) + (dashboard-agenda--set-face org-level-face headline) + (dashboard-agenda--set-face (org-get-todo-face todo) todo-state) + (concat todo-state " " headline))) + +(defun dashboard-agenda--set-face (face text) + "Add FACE to TEXT but inherit height from `dashboard-items-face'. +If not height is found on FACE or `dashboard-items-face' use `default'." + (let ((height (face-attribute 'dashboard-items-face :height nil 'default))) + (add-face-text-property 0 (length text) `((:height ,height) ,face) nil text))) + +(defun dashboard-agenda--formatted-time () + "Get the scheduled or dead time of an entry. If no time is found return nil." + (when-let ((time (or (org-get-scheduled-time (point)) (org-get-deadline-time (point)) + (dashboard-agenda--entry-timestamp (point))))) + (format-time-string dashboard-agenda-time-string-format time))) + +(defun dashboard-agenda--formatted-tags () + "Apply `dashboard-agenda-tags-format' to org-element tags." + (when dashboard-agenda-tags-format + (funcall dashboard-agenda-tags-format (org-get-tags)))) + +(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 scheduled-time or deadline-time in the future. +An entry is included if this function returns nil and excluded if returns a +point." + (let ((scheduled-time (org-get-scheduled-time (point))) + (deadline-time (org-get-deadline-time (point))) + (entry-timestamp (dashboard-agenda--entry-timestamp (point))) + (due-date (dashboard-due-date-for-agenda)) + (now (current-time))) + (unless (and (not (org-entry-is-done-p)) + (not (org-in-archived-heading-p)) + (or (and scheduled-time + (org-time-less-p scheduled-time due-date)) + (and deadline-time + (org-time-less-p deadline-time due-date)) + (and entry-timestamp + (org-time-less-p now entry-timestamp) + (org-time-less-p entry-timestamp 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)) + (not (org-in-archived-heading-p))) + (point))) + +(defun dashboard-no-filter-agenda () + "No filter agenda entries." + (when (org-entry-is-done-p) (point))) + +(defun dashboard-get-agenda () + "Get agenda items for today or for a week from now." + (if-let ((prefix-format (assoc 'dashboard-agenda org-agenda-prefix-format))) + (setcdr prefix-format dashboard-agenda-prefix-format) + (push (cons 'dashboard-agenda dashboard-agenda-prefix-format) org-agenda-prefix-format)) + (org-compile-prefix-format 'dashboard-agenda) + (prog1 (org-map-entries 'dashboard-agenda-entry-format + dashboard-match-agenda-entry + 'agenda + dashboard-filter-agenda-entry) + (dashboard-agenda--release-buffers))) + +(defun dashboard-agenda--release-buffers () + "Release agenda buffers buffers. +This is what `org-agenda-exit' do." + (when dashboard-agenda-release-buffers + (org-release-buffers org-agenda-new-buffers) + (setq org-agenda-new-buffers nil))) + +(defun dashboard-agenda--sorted-agenda () + "Return agenda sorted by time. + +For now, it only works when dashboard-agenda has been filter by time and +dashboard-agenda-sort is not nil." + (let ((agenda (dashboard-get-agenda)) + (sort-function (dashboard-agenda--sort-function))) + (sort agenda sort-function))) + +(defun dashboard-agenda--sort-function () + "Get the function use to sorted the agenda. + +Depending on the list `dashboard-agenda-sorting-strategy' use this strategies to +build a predicate to compare each enty. +This is similar as `org-entries-lessp' but with a different aproach." + (dashboard-agenda--build-sort-function dashboard-agenda-sort-strategy)) + +(defun dashboard-agenda--build-sort-function (strategies) + "Build a predicate to sort the dashboard agenda. + +If `STRATEGIES' is nil then sort using the nil predicate. Look for the strategy +predicate, the attributes of the entry and compare entries. If no predicate is +found for the strategy it uses nil predicate." + (if (null strategies) (lambda (_dont _care) nil) + (let ((predicate (dashboard-agenda--build-sort-function-predicate + (car strategies))) + (attribute (dashboard-agenda--build-sort-function-attribute + (car strategies)))) + (if (null predicate) (lambda (_dont _care) nil) + (lambda (entry1 entry2) + (dashboard-agenda--compare-entries entry1 entry2 (cdr strategies) + predicate attribute)))))) + +(defun dashboard-agenda--build-sort-function-predicate (strategy) + "Return the predicate to compare two entryes depending on the `STRATEGY'." + (cl-case strategy + (`priority-up '>) + (`priority-down '<) + (`time-up 'org-time-less-p) + (`time-down (lambda (a b) (org-time-less-p b a))) + (`todo-state-up '>) + (`todo-state-down '<))) + +(defun dashboard-agenda--build-sort-function-attribute (strategy) + "Return the argument to compare two entries depending to the `STRATEGY'." + (cond + ((memq strategy '(priority-up priority-down)) 'dashboard-agenda-priority) + ((memq strategy '(time-up time-down)) 'dashboard-agenda-time) + ((memq strategy '(todo-state-up todo-state-down)) 'dashboard-agenda-todo-index) + (t nil))) + +(defun dashboard-agenda--compare-entries (entry1 entry2 strategies predicate attribute) + "Compare `ENTRY1' and `ENTRY2' by `ATTRIBUTE' using `PREDICATE'. +If both attributes are nil or equals the next strategy in `STRATEGIES' is used +to compare." + (let ((arg1 (get-text-property 0 attribute entry1)) + (arg2 (get-text-property 0 attribute entry2))) + (cond + ((or (and (null arg1) (null arg2)) (equal arg1 arg2)) + (apply (dashboard-agenda--build-sort-function strategies) (list entry1 entry2))) + ((null arg1) nil) + ((null arg2) t) + (t (apply predicate (list arg1 arg2)))))) + +(defun dashboard-insert-agenda (list-size) + "Add the list of LIST-SIZE items of agenda." + (require 'org-agenda) + (dashboard-insert-section + (if dashboard-week-agenda + "Agenda for the coming week:" + "Agenda for today:") + (dashboard-agenda--sorted-agenda) + list-size + 'agenda + (dashboard-get-shortcut 'agenda) + `(lambda (&rest _) + (let ((buffer (find-file-other-window (get-text-property 0 'dashboard-agenda-file ,el)))) + (with-current-buffer buffer + (goto-char (get-text-property 0 'dashboard-agenda-loc ,el)) + (switch-to-buffer buffer)))) + (format "%s" el))) + +;; +;; Registers +;; +(defun dashboard-insert-registers (list-size) + "Add the list of LIST-SIZE items of registers." + (require 'register) + (dashboard-insert-section + "Registers:" + register-alist + list-size + 'registers + (dashboard-get-shortcut 'registers) + (lambda (&rest _) (jump-to-register (car el))) + (format "%c - %s" (car el) (register-describe-oneline (car el))))) + +(provide 'dashboard-widgets) +;;; dashboard-widgets.el ends here diff --git a/org/elpa/dashboard-20230331.2304/dashboard.el b/org/elpa/dashboard-20230331.2304/dashboard.el new file mode 100644 index 0000000..88ea969 --- /dev/null +++ b/org/elpa/dashboard-20230331.2304/dashboard.el @@ -0,0 +1,472 @@ +;;; dashboard.el --- A startup screen extracted from Spacemacs -*- lexical-binding: t -*- + +;; Copyright (c) 2016-2023 emacs-dashboard maintainers +;; +;; Author : Rakan Al-Hneiti +;; Maintainer : Jesús Martínez +;; Shen, Jen-Chieh +;; URL : https://github.com/emacs-dashboard/emacs-dashboard +;; +;; This file is not part of GNU Emacs. +;; +;;; License: GPLv3 +;; +;; Created: October 05, 2016 +;; Package-Version: 1.8.0-SNAPSHOT +;; Keywords: startup, screen, tools, dashboard +;; Package-Requires: ((emacs "26.1")) +;;; Commentary: + +;; An extensible Emacs dashboard, with sections for +;; bookmarks, projects (projectile or project.el), org-agenda and more. + +;;; Code: + +(require 'ffap) +(require 'recentf) + +(require 'dashboard-widgets) + +(declare-function bookmark-get-filename "ext:bookmark.el") +(declare-function bookmark-all-names "ext:bookmark.el") +(declare-function dashboard-ls--dirs "ext:dashboard-ls.el") +(declare-function dashboard-ls--files "ext:dashboard-ls.el") +(declare-function page-break-lines-mode "ext:page-break-lines.el") +(declare-function projectile-remove-known-project "ext:projectile.el") +(declare-function project-forget-projects-under "ext:project.el") +(declare-function linum-mode "linum.el") + +(declare-function dashboard-refresh-buffer "dashboard.el") + +(defgroup dashboard nil + "Extensible startup screen." + :group 'applications) + +;; Custom splash screen +(defvar dashboard-mode-map + (let ((map (make-sparse-keymap))) + (define-key map (kbd "C-p") 'dashboard-previous-line) + (define-key map (kbd "C-n") 'dashboard-next-line) + (define-key map (kbd "") 'dashboard-previous-line) + (define-key map (kbd "") 'dashboard-next-line) + (define-key map (kbd "k") 'dashboard-previous-line) + (define-key map (kbd "j") 'dashboard-next-line) + (define-key map [tab] 'widget-forward) + (define-key map (kbd "C-i") 'widget-forward) + (define-key map [backtab] 'widget-backward) + (define-key map (kbd "RET") 'dashboard-return) + (define-key map [mouse-1] 'dashboard-mouse-1) + (define-key map (kbd "}") #'dashboard-next-section) + (define-key map (kbd "{") #'dashboard-previous-section) + + (define-key map (kbd "") #'dashboard-remove-item-under) + (define-key map (kbd "") #'dashboard-remove-item-under) + (define-key map (kbd "DEL") #'dashboard-remove-item-under) + + (define-key map (kbd "1") #'dashboard-section-1) + (define-key map (kbd "2") #'dashboard-section-2) + (define-key map (kbd "3") #'dashboard-section-3) + (define-key map (kbd "4") #'dashboard-section-4) + (define-key map (kbd "5") #'dashboard-section-5) + (define-key map (kbd "6") #'dashboard-section-6) + (define-key map (kbd "7") #'dashboard-section-7) + (define-key map (kbd "8") #'dashboard-section-8) + (define-key map (kbd "9") #'dashboard-section-9) + 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." + :group 'dashboard + :syntax-table nil + :abbrev-table nil + (buffer-disable-undo) + (when (featurep 'whitespace) (whitespace-mode -1)) + (when (featurep 'linum) (linum-mode -1)) + (when (featurep 'display-line-numbers) (display-line-numbers-mode -1)) + (when (featurep 'page-break-lines) (page-break-lines-mode 1)) + (setq-local revert-buffer-function #'dashboard-refresh-buffer) + (setq inhibit-startup-screen t + buffer-read-only t + truncate-lines t)) + +(defcustom dashboard-center-content nil + "Whether to center content within the window." + :type 'boolean + :group 'dashboard) + +(defconst dashboard-buffer-name "*dashboard*" + "Dashboard's buffer name.") + +(defvar dashboard-force-refresh nil + "If non-nil, force refresh dashboard buffer.") + +(defvar dashboard--section-starts nil + "List of section starting positions.") + +;; +;; Util +;; +(defun dashboard--goto-line (line) + "Goto LINE." + (goto-char (point-min)) (forward-line (1- line))) + +(defmacro dashboard--save-excursion (&rest body) + "Execute BODY save window point." + (declare (indent 0) (debug t)) + `(let ((line (line-number-at-pos nil t)) + (column (current-column))) + ,@body + (dashboard--goto-line line) + (move-to-column column))) + +;; +;; Core +;; +(defun dashboard--current-section () + "Return section symbol in dashboard." + (save-excursion + (if (and (search-backward dashboard-page-separator nil t) + (search-forward dashboard-page-separator nil t)) + (let ((ln (thing-at-point 'line))) + (cond ((string-match-p "Recent Files:" ln) 'recents) + ((string-match-p "Bookmarks:" ln) 'bookmarks) + ((string-match-p "Projects:" ln) 'projects) + ((string-match-p "Agenda for " ln) 'agenda) + ((string-match-p "Registers:" ln) 'registers) + ((string-match-p "List Directories:" ln) 'ls-directories) + ((string-match-p "List Files:" ln) 'ls-files) + (t (user-error "Unknown section from dashboard")))) + (user-error "Failed searching dashboard section")))) + +;; +;; Navigation +;; +(defun dashboard-previous-section () + "Navigate back to previous section." + (interactive) + (let ((current-position (point)) current-section-start previous-section-start) + (dolist (elt dashboard--section-starts) + (when (and current-section-start (not previous-section-start)) + (setq previous-section-start elt)) + (when (and (not current-section-start) (< elt current-position)) + (setq current-section-start elt))) + (goto-char (if (eq current-position current-section-start) + previous-section-start + current-section-start)))) + +(defun dashboard-next-section () + "Navigate forward to next section." + (interactive) + (let ((current-position (point)) next-section-start + (section-starts (reverse dashboard--section-starts))) + (dolist (elt section-starts) + (when (and (not next-section-start) + (> elt current-position)) + (setq next-section-start elt))) + (when next-section-start + (goto-char next-section-start)))) + +(defun dashboard--section-lines () + "Return a list of integer represent the starting line number of each section." + (let (pb-lst) + (save-excursion + (goto-char (point-min)) + (while (search-forward dashboard-page-separator nil t) + (when (ignore-errors (dashboard--current-section)) + (push (line-number-at-pos) pb-lst)))) + (setq pb-lst (reverse pb-lst)) + pb-lst)) + +(defun dashboard--goto-section-by-index (index) + "Navigate to item section by INDEX." + (let* ((pg-lst (dashboard--section-lines)) + (items-id (1- index)) + (items-pg (nth items-id pg-lst)) + (items-len (length pg-lst))) + (when (and items-pg (< items-id items-len)) + (dashboard--goto-line items-pg)))) + +(defun dashboard-section-1 () + "Navigate to section 1." (interactive) (dashboard--goto-section-by-index 1)) +(defun dashboard-section-2 () + "Navigate to section 2." (interactive) (dashboard--goto-section-by-index 2)) +(defun dashboard-section-3 () + "Navigate to section 3." (interactive) (dashboard--goto-section-by-index 3)) +(defun dashboard-section-4 () + "Navigate to section 4." (interactive) (dashboard--goto-section-by-index 4)) +(defun dashboard-section-5 () + "Navigate to section 5." (interactive) (dashboard--goto-section-by-index 5)) +(defun dashboard-section-6 () + "Navigate to section 6." (interactive) (dashboard--goto-section-by-index 6)) +(defun dashboard-section-7 () + "Navigate to section 7." (interactive) (dashboard--goto-section-by-index 7)) +(defun dashboard-section-8 () + "Navigate to section 8." (interactive) (dashboard--goto-section-by-index 8)) +(defun dashboard-section-9 () + "Navigate to section 9." (interactive) (dashboard--goto-section-by-index 9)) + +(defun dashboard-previous-line (arg) + "Move point up and position it at that line’s item. +Optional prefix ARG says how many lines to move; default is one line." + (interactive "^p") + (dashboard-next-line (- arg))) + +(defun dashboard-next-line (arg) + "Move point down and position it at that line’s item. +Optional prefix ARG says how many lines to move; default is one line." + ;; code heavily inspired by `dired-next-line' + (interactive "^p") + (let (line-move-visual goal-column) + (line-move arg t)) + ;; We never want to move point into an invisible line. Dashboard doesn’t + ;; use invisible text currently but when it does we’re ready! + (while (and (invisible-p (point)) + (not (if (and arg (< arg 0)) (bobp) (eobp)))) + (forward-char (if (and arg (< arg 0)) -1 1))) + (beginning-of-line-text)) + +;; +;; ffap +;; +(defun dashboard--goto-section (section) + "Move to SECTION declares in variable `dashboard-item-shortcuts'." + (let ((fnc (intern (format "dashboard-jump-to-%s" section)))) + (dashboard-funcall-fboundp fnc))) + +(defun dashboard--current-index (section &optional pos) + "Return the idex by SECTION from POS." + (let (target-ln section-line) + (save-excursion + (when pos (goto-char pos)) + (setq target-ln (line-number-at-pos)) + (dashboard--goto-section section) + (setq section-line (line-number-at-pos))) + (- target-ln section-line))) + +(defun dashboard--section-list (section) + "Return the list from SECTION." + (cl-case section + (`recents recentf-list) + (`bookmarks (bookmark-all-names)) + (`projects (dashboard-projects-backend-load-projects)) + (`ls-directories (dashboard-ls--dirs)) + (`ls-files (dashboard-ls--files)) + (t (user-error "Unknown section for search: %s" section)))) + +(defun dashboard--current-item-in-path () + "Return the path from current dashboard section in path." + (let ((section (dashboard--current-section)) path) + (cl-case section + (`bookmarks (setq path (bookmark-get-filename path))) + (t + (let ((lst (dashboard--section-list section)) + (index (dashboard--current-index section))) + (setq path (nth index lst))))) + path)) + +(defun dashboard--on-path-item-p () + "Return non-nil if current point is on the item path from dashboard." + (save-excursion + (when (= (point) (line-end-position)) (ignore-errors (forward-char -1))) + (eq (get-char-property (point) 'face) 'dashboard-items-face))) + +(defun dashboard--ffap-guesser--adv (fnc &rest args) + "Advice execution around function `ffap-guesser'. + +Argument FNC is the adviced function. +Optional argument ARGS adviced function arguments." + (cl-case major-mode + (`dashboard-mode + (or (and (dashboard--on-path-item-p) + (dashboard--current-item-in-path)) + (apply fnc args))) ; fallback + (t (apply fnc args)))) +(advice-add 'ffap-guesser :around #'dashboard--ffap-guesser--adv) + +;; +;; Removal +;; +(defun dashboard-remove-item-under () + "Remove a item from the current item section." + (interactive) + (cl-case (dashboard--current-section) + (`recents (dashboard-remove-item-recentf)) + (`bookmarks (dashboard-remove-item-bookmarks)) + (`projects (dashboard-remove-item-projects)) + (`agenda (dashboard-remove-item-agenda)) + (`registers (dashboard-remove-item-registers))) + (dashboard--save-excursion (dashboard-refresh-buffer))) + +(defun dashboard-remove-item-recentf () + "Remove a file from `recentf-list'." + (interactive) + (let ((path (save-excursion (end-of-line) (ffap-guesser)))) + (setq recentf-list (delete path recentf-list))) + (dashboard-mute-apply (recentf-save-list))) + +(defun dashboard-remove-item-projects () + "Remove a path from `project--list'." + (interactive) + (let ((path (save-excursion (end-of-line) (ffap-guesser)))) + (dashboard-mute-apply + (cl-case dashboard-projects-backend + (`projectile (projectile-remove-known-project path)) + (`project-el (project-forget-projects-under path)))))) + +(defun dashboard-remove-item-bookmarks () + "Remove a bookmarks from `bookmark-alist'." + (interactive)) ; TODO: .. + +(defun dashboard-remove-item-agenda () + "Remove an agenda from `org-agenda-files'." + (interactive "P") + (let ((agenda-file (get-text-property (point) 'dashboard-agenda-file)) + (agenda-loc (get-text-property (point) 'dashboard-agenda-loc))) + (with-current-buffer (find-file-noselect agenda-file) + (goto-char agenda-loc) + (call-interactively 'org-todo)))) + +(defun dashboard-remove-item-registers () + "Remove a registers from `register-alist'." + (interactive)) ; TODO: .. + +;; +;; Confirmation +;; +(defun dashboard-return () + "Hit return key in dashboard buffer." + (interactive) + (let ((start-ln (line-number-at-pos)) (fd-cnt 0) diff-line entry-pt) + (save-excursion + (while (and (not diff-line) + (not (= (point) (point-min))) + (not (get-char-property (point) 'button)) + (not (= (point) (point-max)))) + (forward-char 1) + (setq fd-cnt (1+ fd-cnt)) + (unless (= start-ln (line-number-at-pos)) + (setq diff-line t))) + (unless (= (point) (point-max)) + (setq entry-pt (point)))) + (when (= fd-cnt 1) + (setq entry-pt (1- (point)))) + (if entry-pt + (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)))) + +;; +;; Insertion +;; +(defmacro dashboard--with-buffer (&rest body) + "Execute BODY in dashboard buffer." + (declare (indent 0)) + `(with-current-buffer (get-buffer-create dashboard-buffer-name) + (let ((inhibit-read-only t)) ,@body) + (current-buffer))) + +(defun dashboard-maximum-section-length () + "For the just-inserted section, calculate the length of the longest line." + (let ((max-line-length 0)) + (save-excursion + (dashboard-previous-section) + (while (not (eobp)) + (setq max-line-length + (max max-line-length + (- (line-end-position) (line-beginning-position)))) + (forward-line 1))) + max-line-length)) + +(defun dashboard-insert-startupify-lists () + "Insert the list of widgets into the buffer." + (interactive) + (let ((inhibit-redisplay t) + (recentf-is-on (recentf-enabled-p)) + (origial-recentf-list recentf-list) + (dashboard-num-recents (or (cdr (assoc 'recents dashboard-items)) 0)) + (max-line-length 0)) + (when recentf-is-on + (setq recentf-list (dashboard-subseq recentf-list dashboard-num-recents))) + (dashboard--with-buffer + (when (or dashboard-force-refresh (not (eq major-mode 'dashboard-mode))) + (erase-buffer) + (dashboard-insert-banner) + (insert "\n") + (setq dashboard--section-starts nil) + (mapc (lambda (els) + (let* ((el (or (car-safe els) els)) + (list-size + (or (cdr-safe els) + dashboard-items-default-length)) + (item-generator + (cdr-safe (assoc el dashboard-item-generators)))) + (push (point) dashboard--section-starts) + (funcall item-generator list-size) + (goto-char (point-max)) + ;; add a newline so the next section-name doesn't get include + ;; on the same line. + (insert "\n") + (when recentf-is-on + (setq recentf-list origial-recentf-list)) + (setq max-line-length + (max max-line-length (dashboard-maximum-section-length))))) + dashboard-items) + (when dashboard-center-content + (dashboard-center-text + (if dashboard--section-starts + (car (last dashboard--section-starts)) + (point)) + (point-max))) + (save-excursion + (dolist (start dashboard--section-starts) + (goto-char start) + (delete-char -1) ; delete the newline we added previously + (insert dashboard-page-separator))) + (progn + (delete-char -1) + (insert dashboard-page-separator)) + (dashboard-insert-footer) + (goto-char (point-min)) + (dashboard-mode))) + (when recentf-is-on + (setq recentf-list origial-recentf-list)))) + + +;;;###autoload +(defun dashboard-open (&rest _) + "Open (or refresh) the *dashboard* buffer." + (interactive) + (let ((dashboard-force-refresh t)) (dashboard-insert-startupify-lists)) + (switch-to-buffer dashboard-buffer-name)) + +(defalias #'dashboard-refresh-buffer #'dashboard-open) + +;;;###autoload +(defun dashboard-setup-startup-hook () + "Setup post initialization hooks. +If a command line argument is provided, assume a filename and skip displaying +Dashboard." + (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-buffer-name) + (goto-char (point-min)) + (redisplay) + (run-hooks 'dashboard-after-initialize-hook))))) + +(provide 'dashboard) +;;; dashboard.el ends here diff --git a/org/elpa/dired-single-20230306.626/dired-single-autoloads.el b/org/elpa/dired-single-20230306.626/dired-single-autoloads.el new file mode 100644 index 0000000..19097d9 --- /dev/null +++ b/org/elpa/dired-single-20230306.626/dired-single-autoloads.el @@ -0,0 +1,75 @@ +;;; dired-single-autoloads.el --- automatically extracted autoloads -*- lexical-binding: t -*- +;; +;;; Code: + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + + +;;;### (autoloads nil "dired-single" "dired-single.el" (0 0 0 0)) +;;; Generated autoloads from dired-single.el + +(autoload 'dired-single-buffer "dired-single" "\ +Visit selected directory in current buffer. + +Visits the selected directory in the current buffer, replacing the + current contents with the contents of the new directory. This doesn't + prevent you from having more than one Dired buffer. The main difference + is that a given Dired buffer will not spawn off a new buffer every time + a new directory is visited. + +If the variable `dired-single-use-magic-buffer' is non-nil, and the current + buffer's name is the same as that specified by the variable +`dired-single-magic-buffer-name', then the new directory's buffer will retain + that same name (i.e. not only will Dired only use a single buffer, but +its name will not change every time a new directory is entered). + +Optional argument DEFAULT-DIRNAME specifies the directory to visit; if not +specified, the directory or file on the current line is used (assuming it's +a Dired buffer). If the current line represents a file, the file is visited +in another window. + +\(fn &optional DEFAULT-DIRNAME)" t nil) + +(autoload 'dired-single-buffer-mouse "dired-single" "\ +Mouse-initiated version of `dired-single-buffer' (which see). + +Argument CLICK is the mouse-click event. + +\(fn CLICK)" t nil) + +(autoload 'dired-single-magic-buffer "dired-single" "\ +Switch to buffer whose name is the value of `dired-single-magic-buffer-name'. + +If no such buffer exists, launch Dired in a new buffer and rename that buffer +to the value of `dired-single-magic-buffer-name'. If the current buffer is the +magic buffer, it will prompt for a new directory to visit. + +Optional argument DEFAULT-DIRNAME specifies the directory to visit (defaults to +the currently displayed directory). + +\(fn &optional DEFAULT-DIRNAME)" t nil) + +(autoload 'dired-single-toggle-buffer-name "dired-single" "\ +Toggle between the 'magic' buffer name and the 'real' Dired buffer name. + +Will also seek to uniquify the 'real' buffer name." t nil) + +(autoload 'dired-single-up-directory "dired-single" "\ +Like `dired-up-directory' but with `dired-single-buffer'. + +If (as OTHER-WINDOW) is non-nil, open the parent directory in a new window. + +\(fn &optional OTHER-WINDOW)" t nil) + +(register-definition-prefixes "dired-single" '("dired-single-")) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; coding: utf-8 +;; End: +;;; dired-single-autoloads.el ends here diff --git a/org/elpa/dired-single-20230306.626/dired-single-pkg.el b/org/elpa/dired-single-20230306.626/dired-single-pkg.el new file mode 100644 index 0000000..226921b --- /dev/null +++ b/org/elpa/dired-single-20230306.626/dired-single-pkg.el @@ -0,0 +1,2 @@ +;;; Generated package description from dired-single.el -*- no-byte-compile: t -*- +(define-package "dired-single" "20230306.626" "Reuse the current dired buffer" '((emacs "25.1")) :commit "c781b7dcff6e7f9a5060b067d2cdb0acbc840c49" :url "https://codeberg.org/amano.kenji/dired-single") diff --git a/org/elpa/dired-single-20230306.626/dired-single.el b/org/elpa/dired-single-20230306.626/dired-single.el new file mode 100644 index 0000000..1eb3510 --- /dev/null +++ b/org/elpa/dired-single-20230306.626/dired-single.el @@ -0,0 +1,220 @@ +;;; dired-single.el --- Reuse the current dired buffer -*- lexical-binding: t; -*- + +;; Version: 0.3.1 +;; Package-Version: 20230306.626 +;; Package-Commit: c781b7dcff6e7f9a5060b067d2cdb0acbc840c49 +;; URL: https://codeberg.org/amano.kenji/dired-single +;; License: 0BSD +;; Package-Requires: ((emacs "25.1")) + +;;; Commentary: + +;; This package reuses the current Dired buffer to visit a directory without +;; creating a new buffer. + +;;; Code: +(require 'dired) +(eval-when-compile + (require 'cl-lib) + (require 'subr-x)) + +;;; ************************************************************************** +;;; ***** customization routines +;;; ************************************************************************** +(defgroup dired-single nil + "Package customization for dired-single." + :group 'tools) + +;; --------------------------------------------------------------------------- +(defun dired-single-customize () + "Customization of the group `dired-single'." + (interactive) + (customize-group "dired-single")) + +;; --------------------------------------------------------------------------- +(defcustom dired-single-use-magic-buffer t + "Boolean that indicates the use of a single Dired buffer name. + +It is used to determine if the dired-single functions should look for and +retain a specific buffer name. The buffer name to look for is specified +with `dired-single-magic-buffer-name'." + :group 'dired-single + :type 'boolean) + +;; --------------------------------------------------------------------------- +(defcustom dired-single-magic-buffer-name "*dired*" + "Name of buffer to use if `dired-single-use-magic-buffer' is true. + +Once a Dired buffer has this name, it will always keep this name (unless it's + explicitly renamed by you)." + :group 'dired-single + :type 'string) + +;; --------------------------------------------------------------------------- +(defcustom dired-single-load-hook nil + "Hook to run when package is loaded." + :type 'hook + :group 'dired-single) + +;;; ************************************************************************** +;;; ***** version related routines +;;; ************************************************************************** +(defconst dired-single-version + "$Revision: 1.7 $" + "Version number for dired-single package.") + +;; --------------------------------------------------------------------------- +(defun dired-single-version-number () + "Return dired-single version number." + (string-match "[0123456789.]+" dired-single-version) + (match-string 0 dired-single-version)) + +;; --------------------------------------------------------------------------- +(defun dired-single-display-version () + "Display dired-single version." + (interactive) + (message "dired-single version <%s>." (dired-single-version-number))) + +;;; ************************************************************************** +;;; ***** interactive functions +;;; ************************************************************************** +;;;###autoload +(defun dired-single-buffer (&optional default-dirname) + "Visit selected directory in current buffer. + +Visits the selected directory in the current buffer, replacing the + current contents with the contents of the new directory. This doesn't + prevent you from having more than one Dired buffer. The main difference + is that a given Dired buffer will not spawn off a new buffer every time + a new directory is visited. + +If the variable `dired-single-use-magic-buffer' is non-nil, and the current + buffer's name is the same as that specified by the variable +`dired-single-magic-buffer-name', then the new directory's buffer will retain + that same name (i.e. not only will Dired only use a single buffer, but +its name will not change every time a new directory is entered). + +Optional argument DEFAULT-DIRNAME specifies the directory to visit; if not +specified, the directory or file on the current line is used (assuming it's +a Dired buffer). If the current line represents a file, the file is visited +in another window." + (interactive) + ;; use arg passed in or find name of current line + (when-let ((name (or default-dirname (dired-get-filename nil t)))) + (save-excursion + (save-match-data + ;; See if the selection is a directory or not. + (end-of-line) + (let ((eol (point))) + (beginning-of-line) + ;; assume directory if arg passed in + (if (or default-dirname (re-search-forward "^ d" eol t)) + ;; save current buffer's name + (let ((current-buffer-name (buffer-name))) + ;; go ahead and read in the directory + (find-alternate-file name) + ;; if the saved buffer's name was the magic name, rename this buffer + (if (and dired-single-use-magic-buffer + (string= current-buffer-name dired-single-magic-buffer-name)) + (rename-buffer dired-single-magic-buffer-name))) + ;; it's just a file + (find-file name))))))) + +;;;; ------------------------------------------------------------------------ +;;;###autoload +(defun dired-single-buffer-mouse (click) + "Mouse-initiated version of `dired-single-buffer' (which see). + +Argument CLICK is the mouse-click event." + (interactive "e") + (let* ( (start (event-start click)) + (window (car start)) + (pos (car (cdr start))) ) + (select-window window) + (goto-char pos)) + (dired-single-buffer)) + +;;;; ------------------------------------------------------------------------ +;;;###autoload +(defun dired-single-magic-buffer (&optional default-dirname) + "Switch to buffer whose name is the value of `dired-single-magic-buffer-name'. + +If no such buffer exists, launch Dired in a new buffer and rename that buffer +to the value of `dired-single-magic-buffer-name'. If the current buffer is the +magic buffer, it will prompt for a new directory to visit. + +Optional argument DEFAULT-DIRNAME specifies the directory to visit (defaults to +the currently displayed directory)." + (interactive) + ;; do we not have one or are we already in it? + (let ((magic-dired-buffer (get-buffer dired-single-magic-buffer-name))) + (if (or (eq magic-dired-buffer nil) + (eq magic-dired-buffer (current-buffer))) + ;; nothing to switch to + ;; get directory name to start in + (let ((dirname (or default-dirname + (read-file-name (format "Dired %s(directory): " "") + nil default-directory t)))) + + ;; make sure it's really a directory + (if (not (file-directory-p dirname)) + (error "Error: <%s> is not a directory" dirname)) + + ;; do we need a new buffer? + (if (eq magic-dired-buffer nil) + ;; find the file in new buffer, current window + (find-file dirname) + ;; just find in place of current buffer + (find-alternate-file dirname)) + ;; rename the buffer, where ever we found it + (rename-buffer dired-single-magic-buffer-name)) + ;; we're not there (we have one already), so simply switch to it + (switch-to-buffer magic-dired-buffer) + ;; if called with a default, try it again + (if default-dirname + (dired-single-magic-buffer default-dirname))))) + +;;;; ------------------------------------------------------------------------ +;;;###autoload +(defun dired-single-toggle-buffer-name () + "Toggle between the 'magic' buffer name and the 'real' Dired buffer name. + +Will also seek to uniquify the 'real' buffer name." + (interactive) + + ;; make sure it's a dired buffer + (if (not (string= major-mode "dired-mode")) + (error "Error: not a Dired buffer")) + + ;; do we have magic name currently? + (if (string= (buffer-name) dired-single-magic-buffer-name) + (rename-buffer + (abbreviate-file-name + (expand-file-name (directory-file-name default-directory))) t) + + ;; make sure the buffer doesn't currently exist + (let ((existing-buffer (get-buffer dired-single-magic-buffer-name))) + (if existing-buffer + (kill-buffer existing-buffer)) + (rename-buffer dired-single-magic-buffer-name)))) + +;;;; ------------------------------------------------------------------------ +;;;###autoload +(defun dired-single-up-directory (&optional other-window) + "Like `dired-up-directory' but with `dired-single-buffer'. + +If (as OTHER-WINDOW) is non-nil, open the parent directory in a new window." + (interactive) + ;; replace dired with dired-single-buffer + (cl-letf (((symbol-function 'dired) (symbol-function 'dired-single-buffer)) + ;; Emacs 28 version of dired-up-directory implementation + ((symbol-function 'dired--find-possibly-alternative-file) (symbol-function 'dired-single-buffer))) + (dired-up-directory other-window))) + +;;; ************************************************************************** +;;; ***** we're done +;;; ************************************************************************** +(provide 'dired-single) +(run-hooks 'dired-single-load-hook) + +;;; dired-single.el ends here diff --git a/org/elpa/diredfl-20230224.1302/diredfl-autoloads.el b/org/elpa/diredfl-20230224.1302/diredfl-autoloads.el new file mode 100644 index 0000000..bf75f23 --- /dev/null +++ b/org/elpa/diredfl-20230224.1302/diredfl-autoloads.el @@ -0,0 +1,69 @@ +;;; diredfl-autoloads.el --- automatically extracted autoloads -*- lexical-binding: t -*- +;; +;;; Code: + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + + +;;;### (autoloads nil "diredfl" "diredfl.el" (0 0 0 0)) +;;; Generated autoloads from diredfl.el + +(autoload 'diredfl-mode "diredfl" "\ +Enable additional font locking in `dired-mode'. + +This is a minor mode. If called interactively, toggle the +`Diredfl mode' mode. If the prefix argument is positive, enable +the mode, and if it is zero or negative, disable the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `diredfl-mode'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +\(fn &optional ARG)" t nil) + +(put 'diredfl-global-mode 'globalized-minor-mode t) + +(defvar diredfl-global-mode nil "\ +Non-nil if Diredfl-Global mode is enabled. +See the `diredfl-global-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `diredfl-global-mode'.") + +(custom-autoload 'diredfl-global-mode "diredfl" nil) + +(autoload 'diredfl-global-mode "diredfl" "\ +Toggle Diredfl mode in all buffers. +With prefix ARG, enable Diredfl-Global mode if ARG is positive; +otherwise, disable it. + +If called from Lisp, toggle the mode if ARG is `toggle'. +Enable the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +Diredfl mode is enabled in all buffers where `(lambda nil (when +\(derived-mode-p 'dired-mode) (diredfl-mode)))' would do it. + +See `diredfl-mode' for more information on Diredfl mode. + +\(fn &optional ARG)" t nil) + +(register-definition-prefixes "diredfl" '("diredfl-")) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; coding: utf-8 +;; End: +;;; diredfl-autoloads.el ends here diff --git a/org/elpa/diredfl-20230224.1302/diredfl-pkg.el b/org/elpa/diredfl-20230224.1302/diredfl-pkg.el new file mode 100644 index 0000000..aaa140c --- /dev/null +++ b/org/elpa/diredfl-20230224.1302/diredfl-pkg.el @@ -0,0 +1,2 @@ +;;; Generated package description from diredfl.el -*- no-byte-compile: t -*- +(define-package "diredfl" "20230224.1302" "Extra font lock rules for a more colourful dired" '((emacs "24")) :commit "17e805763d57370c4eff2c92ed257b72eeb9f94a" :authors '(("Steve Purcell" . "steve@sanityinc.com")) :maintainer '("Steve Purcell" . "steve@sanityinc.com") :keywords '("faces") :url "https://github.com/purcell/diredfl") diff --git a/org/elpa/diredfl-20230224.1302/diredfl.el b/org/elpa/diredfl-20230224.1302/diredfl.el new file mode 100644 index 0000000..0d0bf41 --- /dev/null +++ b/org/elpa/diredfl-20230224.1302/diredfl.el @@ -0,0 +1,382 @@ +;;; diredfl.el --- Extra font lock rules for a more colourful dired -*- lexical-binding: t; -*- + +;; Copyright (C) 2017 Steve Purcell + +;; Author: Steve Purcell +;; Author: Drew Adams +;; Keywords: faces +;; Package-Commit: 17e805763d57370c4eff2c92ed257b72eeb9f94a +;; URL: https://github.com/purcell/diredfl +;; Package-Requires: ((emacs "24")) +;; Package-Version: 20230224.1302 +;; Package-X-Original-Version: 0 + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; This is adapted from the extra font lock rules provided by Drew +;; Adams' `dired+' package, but published via a modern means, and with +;; support for older Emacsen removed. + +;; Enable in all Dired buffers by calling or customising `diredfl-global-mode'. + +;; Alternatively: + +;; (add-hook 'dired-mode-hook 'diredfl-mode) + +;;; Code: + +(require 'dired) + +(defgroup diredfl () + "Extra font lock rules for a more colourful Dired." + :group 'dired) + +(defcustom diredfl-compressed-extensions '(".tar" ".taz" ".tgz" ".arj" ".lzh" + ".lzma" ".xz" ".zip" ".z" ".Z" ".gz" ".bz2") + "*List of compressed-file extensions, for highlighting." + :type '(repeat string) :group 'diredfl) + +(defcustom diredfl-ignore-compressed-flag t + "*Non-nil means to font-lock names of compressed files as ignored files. +This applies to filenames whose extensions are in +`diredfl-compressed-extensions'. If nil they are highlighted using +face `diredfl-compressed-file-name'." + :type 'boolean :group 'diredfl) + +(defface diredfl-autofile-name + '((((background dark)) (:background "#111313F03181")) ; Very dark blue + (t (:background "#EEECEC0FCE7E"))) ; Very pale goldenrod + "*Face used in Dired for names of files that are autofile bookmarks." + :group 'diredfl) +(defvar diredfl-autofile-name 'diredfl-autofile-name) + +(defface diredfl-compressed-file-name + '((((background dark)) (:foreground "Blue")) + (t (:foreground "Brown"))) + "*Face used for compressed file names." + :group 'diredfl) +(defvar diredfl-compressed-file-name 'diredfl-compressed-file-name) + +(defface diredfl-compressed-file-suffix + '((((background dark)) (:foreground "Blue")) + (t (:foreground "Yellow"))) + "*Face used for compressed file suffixes in Dired buffers. +This means the `.' plus the file extension. Example: `.zip'." + :group 'diredfl) +(defvar diredfl-compressed-file-suffix 'diredfl-compressed-file-suffix) + +(defface diredfl-date-time + '((((background dark)) (:foreground "#74749A9AF7F7")) ; ~ med blue + (t (:foreground "DarkGoldenrod4"))) + "*Face used for date and time in Dired buffers." + :group 'diredfl) +(defvar diredfl-date-time 'diredfl-date-time) + +(defface diredfl-deletion + '((t (:foreground "Yellow" :background "Red"))) + "*Face used for deletion flags (D) in Dired buffers." + :group 'diredfl) +(defvar diredfl-deletion 'diredfl-deletion) + +(defface diredfl-deletion-file-name + '((t (:foreground "Red"))) + "*Face used for names of deleted files in Dired buffers." + :group 'diredfl) +(defvar diredfl-deletion-file-name 'diredfl-deletion-file-name) + +(defface diredfl-dir-heading + '((((background dark)) (:foreground "Yellow" :background "#00003F3F3434")) ; ~ dark green + (t (:foreground "Blue" :background "Pink"))) + "*Face used for directory headings in Dired buffers." + :group 'diredfl) +(defvar diredfl-dir-heading 'diredfl-dir-heading) + +(defface diredfl-dir-name + '((((background dark)) + (:foreground "#7474FFFFFFFF" :background "#2C2C2C2C2C2C")) ; ~ cyan, dark gray + (t (:foreground "DarkRed" :background "LightGray"))) + "*Face used for directory names." + :group 'diredfl) +(defvar diredfl-dir-name 'diredfl-dir-name) + +(defface diredfl-dir-priv + '((((background dark)) + (:foreground "#7474FFFFFFFF" :background "#2C2C2C2C2C2C")) ; ~ cyan, dark gray + (t (:foreground "DarkRed" :background "LightGray"))) + "*Face used for directory privilege indicator (d) in Dired buffers." + :group 'diredfl) +(defvar diredfl-dir-priv 'diredfl-dir-priv) + +(defface diredfl-exec-priv + '((((background dark)) (:background "#4F4F3B3B2121")) ; ~ dark brown + (t (:background "LightSteelBlue"))) + "*Face used for execute privilege indicator (x) in Dired buffers." + :group 'diredfl) +(defvar diredfl-exec-priv 'diredfl-exec-priv) + +;; For this to show up, you need `F' among the options in `dired-listing-switches'. +;; For example, I use "-alF" for `dired-listing-switches'. +(defface diredfl-executable-tag + '((t (:foreground "Red"))) + "*Face used for executable tag (*) on file names in Dired buffers." + :group 'diredfl) +(defvar diredfl-executable-tag 'diredfl-executable-tag) + +(defface diredfl-file-name + '((((background dark)) (:foreground "Yellow")) + (t (:foreground "Blue"))) + "*Face used for file names (without suffixes) in Dired buffers. +This means the base name. It does not include the `.'." + :group 'diredfl) +(defvar diredfl-file-name 'diredfl-file-name) + +(defface diredfl-file-suffix + '((((background dark)) (:foreground "#7474FFFF7474")) ; ~ light green + (t (:foreground "DarkMagenta"))) + "*Face used for file suffixes in Dired buffers. +This means the `.' plus the file extension. Example: `.elc'." + :group 'diredfl) +(defvar diredfl-file-suffix 'diredfl-file-suffix) + +(defface diredfl-flag-mark + '((((background dark)) (:foreground "Blue" :background "#7575D4D41D1D")) ; ~ olive green + (t (:foreground "Yellow" :background "Blueviolet"))) + "*Face used for flags and marks (except D) in Dired buffers." + :group 'diredfl) +(defvar diredfl-flag-mark 'diredfl-flag-mark) + +(defface diredfl-flag-mark-line + '((((background dark)) (:background "#787831311414")) ; ~ dark red brown + (t (:background "Skyblue"))) + "*Face used for flagged and marked lines in Dired buffers." + :group 'diredfl) +(defvar diredfl-flag-mark-line 'diredfl-flag-mark-line) + +(defface diredfl-ignored-file-name + '(;; (((background dark)) (:foreground "#FFFF921F921F")) ; ~ salmon + ;; (((background dark)) (:foreground "#A71F5F645F64")) ; ~ dark salmon + (((background dark)) (:foreground "#C29D6F156F15")) ; ~ salmon + (t (:foreground "#00006DE06DE0"))) ; ~ dark cyan + "*Face used for ignored file names in Dired buffers." + :group 'diredfl) +(defvar diredfl-ignored-file-name 'diredfl-ignored-file-name) + +(defface diredfl-link-priv + '((((background dark)) (:foreground "#00007373FFFF")) ; ~ blue + (t (:foreground "DarkOrange"))) + "*Face used for link privilege indicator (l) in Dired buffers." + :group 'diredfl) +(defvar diredfl-link-priv 'diredfl-link-priv) + +(defface diredfl-no-priv + '((((background dark)) (:background "#2C2C2C2C2C2C")) ; ~ dark gray + (t (:background "LightGray"))) + "*Face used for no privilege indicator (-) in Dired buffers." + :group 'diredfl) +(defvar diredfl-no-priv 'diredfl-no-priv) + +(defface diredfl-number + '((((background dark)) (:foreground "#FFFFFFFF7474")) ; ~ light yellow + (t (:foreground "DarkBlue"))) + "*Face used for numerical fields in Dired buffers. +In particular, inode number, number of hard links, and file size." + :group 'diredfl) +(defvar diredfl-number 'diredfl-number) + +(defface diredfl-other-priv + '((((background dark)) (:background "#111117175555")) ; ~ dark blue + (t (:background "PaleGoldenrod"))) + "*Face used for l,s,S,t,T privilege indicators in Dired buffers." + :group 'diredfl) +(defvar diredfl-other-priv 'diredfl-other-priv) + +(defface diredfl-rare-priv + '((((background dark)) (:foreground "Green" :background "#FFFF00008080")) ; ~ hot pink + (t (:foreground "Magenta" :background "SpringGreen"))) + "*Face used for rare privilege indicators (b,c,s,m,p,S) in Dired buffers." + :group 'diredfl) +(defvar diredfl-rare-priv 'diredfl-rare-priv) + +(defface diredfl-read-priv + '((((background dark)) (:background "#999932325555")) ; ~ burgundy / dark magenta + (t (:background "MediumAquamarine"))) + "*Face used for read privilege indicator (w) in Dired buffers." + :group 'diredfl) +(defvar diredfl-read-priv 'diredfl-read-priv) + +(defface diredfl-symlink + '((((background dark)) (:foreground "#00007373FFFF")) ; ~ blue + (t (:foreground "DarkOrange"))) + "*Face used for symbolic links in Dired buffers." + :group 'diredfl) +(defvar diredfl-symlink 'diredfl-symlink) + +(defface diredfl-tagged-autofile-name + '((((background dark)) (:background "#328C0411328C")) ; Very dark magenta + (t (:background "#CD73FBEECD73"))) ; Very pale green + "*Face used in Dired for names of files that are autofile bookmarks." + :group 'diredfl) +(defvar diredfl-tagged-autofile-name 'diredfl-tagged-autofile-name) + +(defface diredfl-write-priv + '((((background dark)) (:background "#25258F8F2929")) ; ~ dark green + (t (:background "Orchid"))) + "*Face used for write privilege indicator (w) in Dired buffers." + :group 'diredfl) +(defvar diredfl-write-priv 'diredfl-write-priv) + +(defun diredfl-match-ignored-extensions (limit) + "A matcher of ignored filename extensions for use in `font-lock-keywords'. +LIMIT is the extent of the search." + (let ((ignored-extensions + (append (if (boundp 'dired-omit-extensions) + dired-omit-extensions + completion-ignored-extensions) + (when diredfl-ignore-compressed-flag + diredfl-compressed-extensions)))) + (when ignored-extensions + (re-search-forward + (concat "^ \\(.*" + (regexp-opt ignored-extensions) + ;; Optional executable flag + "[*]?\\)$") + limit + t)))) + +;;; Define second level of fontifying. +(defconst diredfl-font-lock-keywords-1 + (list + '("^ \\(.+:\\)$" 1 diredfl-dir-heading) ; Directory headers + '("^ wildcard.*$" 0 'default) ; Override others, e.g. `l' for `diredfl-other-priv'. + '("^ (No match).*$" 0 'default) ; Override others, e.g. `t' for `diredfl-other-priv'. + '("[^ .]\\(\\.[^. /]+\\)$" 1 diredfl-file-suffix) ; Suffix, including `.'. + '("\\([^ ]+\\) -> .+$" 1 diredfl-symlink) ; Symbolic links + + ;; 1) Date/time and 2) filename w/o suffix. + ;; This is a bear, and it is fragile - Emacs can change `dired-move-to-filename-regexp'. + `(,dired-move-to-filename-regexp + (7 diredfl-date-time t t) ; Date/time, locale (western or eastern) + (2 diredfl-date-time t t) ; Date/time, ISO + (,(concat "\\(.+\\)\\(" (concat (funcall #'regexp-opt diredfl-compressed-extensions) + "\\)[*]?$")) + nil nil (0 diredfl-compressed-file-name keep t))) ; Compressed-file suffix + `(,dired-move-to-filename-regexp + (7 diredfl-date-time t t) ; Date/time, locale (western or eastern) + (2 diredfl-date-time t t) ; Date/time, ISO + ("\\(.+\\)$" nil nil (0 diredfl-file-name keep t))) ; Filename (not a compressed file) + + ;; Files to ignore + '(diredfl-match-ignored-extensions 1 diredfl-ignored-file-name t) + + ;; Compressed-file (suffix) + (list (concat "\\(" (concat (funcall #'regexp-opt diredfl-compressed-extensions) "\\)[*]?$")) + 1 diredfl-compressed-file-suffix t) + '("\\([*]\\)$" 1 diredfl-executable-tag t) ; Executable (*) + + ;; Inode, hard-links, & file size (. and , are for the decimal point, depending on locale) + ;; See comment for `directory-listing-before-filename-regexp' in `files.el' or `files+.el'. + '("\\_<\\(\\([0-9]+\\([.,][0-9]+\\)?\\)[BkKMGTPEZY]?[ /]?\\)" 1 'diredfl-number) + + ;; Directory names - exclude d:/..., Windows drive letter in a dir heading. + (list (concat dired-re-maybe-mark dired-re-inode-size "\\(d\\)[^:]") + '(1 diredfl-dir-priv t) '(".+" (dired-move-to-filename) nil (0 diredfl-dir-name t))) + + (list (concat dired-re-maybe-mark dired-re-inode-size "[-dl]........\\(x\\)") ; o x + '(1 diredfl-exec-priv)) + (list (concat dired-re-maybe-mark dired-re-inode-size "[-dl]........\\([lsStT]\\)") ; o misc + '(1 diredfl-other-priv)) + (list (concat dired-re-maybe-mark dired-re-inode-size "[-dl].......\\(w\\).") ; o w + '(1 diredfl-write-priv)) + (list (concat dired-re-maybe-mark dired-re-inode-size "[-dl]......\\(r\\)..") ; o r + '(1 diredfl-read-priv)) + (list (concat dired-re-maybe-mark dired-re-inode-size "[-dl].....\\(x\\)...") ; g x + '(1 diredfl-exec-priv)) + (list (concat dired-re-maybe-mark dired-re-inode-size "[-dl].....\\([lsStT]\\)...") ; g misc + '(1 diredfl-other-priv)) + (list (concat dired-re-maybe-mark dired-re-inode-size "[-dl]....\\(w\\)....") ; g w + '(1 diredfl-write-priv)) + (list (concat dired-re-maybe-mark dired-re-inode-size "[-dl]...\\(r\\).....") ; g r + '(1 diredfl-read-priv)) + (list (concat dired-re-maybe-mark dired-re-inode-size "[-dl]..\\(x\\)...") ; u x + '(1 diredfl-exec-priv)) + (list (concat dired-re-maybe-mark dired-re-inode-size "[-dl]..\\([lsStT]\\)...") ; u misc + '(1 diredfl-other-priv)) + (list (concat dired-re-maybe-mark dired-re-inode-size "[-dl].\\(w\\)....") ; u w + '(1 diredfl-write-priv)) + (list (concat dired-re-maybe-mark dired-re-inode-size "[-dl]\\(r\\).....") ; u r + '(1 diredfl-read-priv)) + + (list (concat dired-re-maybe-mark dired-re-inode-size "[-dl]........\\([-rwxlsStT]\\)") ; o - + '(1 diredfl-no-priv keep)) + (list (concat dired-re-maybe-mark dired-re-inode-size "[-dl].......\\([-rwxlsStT]\\).") ; g - + '(1 diredfl-no-priv keep)) + (list (concat dired-re-maybe-mark dired-re-inode-size "[-dl]......\\([-rwxlsStT]\\)..") ; u - + '(1 diredfl-no-priv keep)) + (list (concat dired-re-maybe-mark dired-re-inode-size "[-dl].....\\([-rwxlsStT]\\)...") ; o - + '(1 diredfl-no-priv keep)) + (list (concat dired-re-maybe-mark dired-re-inode-size "[-dl]....\\([-rwxlsStT]\\)....") ; g - + '(1 diredfl-no-priv keep)) + (list (concat dired-re-maybe-mark dired-re-inode-size "[-dl]...\\([-rwxlsStT]\\).....") ; u - + '(1 diredfl-no-priv keep)) + (list (concat dired-re-maybe-mark dired-re-inode-size "[-dl]..\\([-rwxlsStT]\\)......") ; o - + '(1 diredfl-no-priv keep)) + (list (concat dired-re-maybe-mark dired-re-inode-size "[-dl].\\([-rwxlsStT]\\).......") ; g - + '(1 diredfl-no-priv keep)) + (list (concat dired-re-maybe-mark dired-re-inode-size "[-dl]\\([-rwxlsStT]\\)........") ; u - + '(1 diredfl-no-priv keep)) + (list (concat dired-re-maybe-mark dired-re-inode-size "\\(-\\)") + '(1 diredfl-no-priv keep)) + + (list (concat dired-re-maybe-mark dired-re-inode-size "\\([bcsmpS]\\)") ; (rare) + '(1 diredfl-rare-priv keep)) + (list (concat dired-re-maybe-mark dired-re-inode-size "\\(l\\)[-rwxlsStT]") ; l + '(1 diredfl-link-priv keep)) + + (list (concat "^\\([^\n " (char-to-string dired-del-marker) "].*$\\)") + '(1 diredfl-flag-mark-line prepend)) ; Flag/mark lines + (list (concat "^\\([^\n " (char-to-string dired-del-marker) "]\\)") ; Flags, marks (except D) + '(1 diredfl-flag-mark prepend)) + + (list (concat "^\\([" (char-to-string dired-del-marker) "].*$\\)") ; Deletion-flagged lines + '(1 diredfl-deletion-file-name prepend)) + (list (concat "^\\([" (char-to-string dired-del-marker) "]\\)") ; Deletion flags (D) + '(1 diredfl-deletion prepend))) + "2nd level of Dired highlighting. See `font-lock-maximum-decoration'.") + + +;;;###autoload +(define-minor-mode diredfl-mode + "Enable additional font locking in `dired-mode'." + :global nil + (setq font-lock-defaults + (if diredfl-mode + '((dired-font-lock-keywords + dired-font-lock-keywords + diredfl-font-lock-keywords-1) + t nil nil beginning-of-line) + '(dired-font-lock-keywords t nil nil beginning-of-line))) + (font-lock-refresh-defaults)) + +;;;###autoload +(define-globalized-minor-mode diredfl-global-mode diredfl-mode + (lambda () + (when (derived-mode-p 'dired-mode) + (diredfl-mode))) + :require 'diredfl) + + +(provide 'diredfl) +;;; diredfl.el ends here diff --git a/org/elpa/doom-modeline-20230406.623/doom-modeline-autoloads.el b/org/elpa/doom-modeline-20230406.623/doom-modeline-autoloads.el new file mode 100644 index 0000000..7c5c34c --- /dev/null +++ b/org/elpa/doom-modeline-20230406.623/doom-modeline-autoloads.el @@ -0,0 +1,91 @@ +;;; doom-modeline-autoloads.el --- automatically extracted autoloads -*- lexical-binding: t -*- +;; +;;; Code: + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + + +;;;### (autoloads nil "doom-modeline" "doom-modeline.el" (0 0 0 0)) +;;; Generated autoloads from doom-modeline.el + +(autoload 'doom-modeline-set-main-modeline "doom-modeline" "\ +Set main mode-line. +If DEFAULT is non-nil, set the default mode-line for all buffers. + +\(fn &optional DEFAULT)" nil nil) + +(defvar doom-modeline-mode nil "\ +Non-nil if Doom-Modeline mode is enabled. +See the `doom-modeline-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `doom-modeline-mode'.") + +(custom-autoload 'doom-modeline-mode "doom-modeline" nil) + +(autoload 'doom-modeline-mode "doom-modeline" "\ +Toggle `doom-modeline' on or off. + +This is a minor mode. If called interactively, toggle the +`Doom-Modeline mode' mode. If the prefix argument is positive, +enable the mode, and if it is zero or negative, disable the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `(default-value \\='doom-modeline-mode)'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +\(fn &optional ARG)" t nil) + +(register-definition-prefixes "doom-modeline" '("doom-modeline-")) + +;;;*** + +;;;### (autoloads nil "doom-modeline-core" "doom-modeline-core.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from doom-modeline-core.el + +(register-definition-prefixes "doom-modeline-core" '("doom-modeline")) + +;;;*** + +;;;### (autoloads nil "doom-modeline-env" "doom-modeline-env.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from doom-modeline-env.el + (autoload 'doom-modeline-env-setup-python "doom-modeline-env") + (autoload 'doom-modeline-env-setup-ruby "doom-modeline-env") + (autoload 'doom-modeline-env-setup-perl "doom-modeline-env") + (autoload 'doom-modeline-env-setup-go "doom-modeline-env") + (autoload 'doom-modeline-env-setup-elixir "doom-modeline-env") + (autoload 'doom-modeline-env-setup-rust "doom-modeline-env") + +(register-definition-prefixes "doom-modeline-env" '("doom-modeline-")) + +;;;*** + +;;;### (autoloads nil "doom-modeline-segments" "doom-modeline-segments.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from doom-modeline-segments.el + +(register-definition-prefixes "doom-modeline-segments" '("doom-modeline-")) + +;;;*** + +;;;### (autoloads nil nil ("doom-modeline-pkg.el") (0 0 0 0)) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; coding: utf-8 +;; End: +;;; doom-modeline-autoloads.el ends here diff --git a/org/elpa/doom-modeline-20230406.623/doom-modeline-core.el b/org/elpa/doom-modeline-20230406.623/doom-modeline-core.el new file mode 100644 index 0000000..8b7ee0f --- /dev/null +++ b/org/elpa/doom-modeline-20230406.623/doom-modeline-core.el @@ -0,0 +1,1481 @@ +;;; doom-modeline-core.el --- The core libraries for doom-modeline -*- lexical-binding: t; -*- + +;; Copyright (C) 2018-2020 Vincent Zhang + +;; This file is not part of GNU Emacs. + +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . +;; + +;;; Commentary: +;; +;; The core libraries for doom-modeline. +;; + +;;; Code: + +(require 'cl-lib) +(require 'subr-x) + +(require 'compat) +(require 'shrink-path) + +(require 'all-the-icons nil t) + + +;; +;; Externals +;; + +(declare-function all-the-icons--function-name "ext:all-the-icons") + + +;; +;; Optimization +;; + +;; Don’t compact font caches during GC. +(when (eq system-type 'windows-nt) + (setq inhibit-compacting-font-caches t)) + +;; For better performance, because `window-font-width' consumes a lot. +(defvar doom-modeline--font-width-cache nil) +(defun doom-modeline--font-width () + "Cache the font width for better performance." + (if (display-graphic-p) + (let ((attributes (face-all-attributes 'mode-line))) + (or (cdr (assoc attributes doom-modeline--font-width-cache)) + (let ((width (window-font-width nil 'mode-line))) + (push (cons attributes width) doom-modeline--font-width-cache) + width))) + 1)) + +;; Refresh the font width after setting frame parameters +;; to ensure the font width is correct. +(defun doom-modeline-refresh-font-width-cache (&rest _) + "Refresh the font width cache." + (setq doom-modeline--font-width-cache nil) + (doom-modeline--font-width)) + +(add-hook 'window-setup-hook #'doom-modeline-refresh-font-width-cache) +(add-hook 'after-make-frame-functions #'doom-modeline-refresh-font-width-cache) +(add-hook 'after-setting-font-hook #'doom-modeline-refresh-font-width-cache) +(add-hook 'server-after-make-frame-hook #'doom-modeline-refresh-font-width-cache) + + +;; +;; Customization +;; + +(defgroup doom-modeline nil + "A minimal and modern mode-line." + :group 'mode-line + :link '(url-link :tag "Homepage" "https://github.com/seagle0128/doom-modeline")) + +(defcustom doom-modeline-support-imenu nil + "If non-nil, cause imenu to see `doom-modeline' declarations. +This is done by adjusting `lisp-imenu-generic-expression' to +include support for finding `doom-modeline-def-*' forms. + +Must be set before loading `doom-modeline'." + :type 'boolean + :set (lambda (_sym val) + (if val + (add-hook 'emacs-lisp-mode-hook #'doom-modeline-add-imenu) + (remove-hook 'emacs-lisp-mode-hook #'doom-modeline-add-imenu))) + :group 'doom-modeline) + +(defcustom doom-modeline-height 25 + "How tall the mode-line should be. It's only respected in GUI. +If the actual char height is larger, it respects the actual char height." + :type 'integer + :group 'doom-modeline) + +(defcustom doom-modeline-bar-width 4 + "How wide the mode-line bar should be. It's only respected in GUI." + :type 'integer + :set (lambda (sym val) + (set sym (if (> val 0) val 1))) + :group 'doom-modeline) + +(defcustom doom-modeline-hud nil + "Whether to use hud instead of default bar. It's only respected in GUI." + :type 'boolean + :group 'doom-modeline) + +(defcustom doom-modeline-hud-min-height 2 + "Minimum height in pixels of the \"thumb\" of the hud. +Only respected in GUI." + :type 'integer + :set (lambda (sym val) + (set sym (if (> val 1) val 1))) + :group 'doom-modeline) + +(defcustom doom-modeline-window-width-limit 85 + "The limit of the window width. + +If `window-width' is smaller than the limit, some information won't be +displayed. It can be an integer or a float number. nil means no limit." + :type '(choice integer + float + (const :tag "Disable" nil)) + :group 'doom-modeline) + +(defcustom doom-modeline-project-detection 'auto + "How to detect the project root. + +nil means to use `default-directory'. + +The project management packages have some issues on detecting project root. +e.g. `projectile' doesn't handle symlink folders well, while `project' is +unable to handle sub-projects. +Specify another one if you encounter the issue." + :type '(choice (const :tag "Auto-detect" auto) + (const :tag "Find File in Project" ffip) + (const :tag "Projectile" projectile) + (const :tag "Built-in Project" project) + (const :tag "Disable" nil)) + :group 'doom-modeline) + +(defcustom doom-modeline-buffer-file-name-style 'auto + "Determines the style used by `doom-modeline-buffer-file-name'. + +Given ~/Projects/FOSS/emacs/lisp/comint.el + auto => emacs/l/comint.el (in a project) or comint.el + truncate-upto-project => ~/P/F/emacs/lisp/comint.el + truncate-from-project => ~/Projects/FOSS/emacs/l/comint.el + truncate-with-project => emacs/l/comint.el + truncate-except-project => ~/P/F/emacs/l/comint.el + truncate-upto-root => ~/P/F/e/lisp/comint.el + truncate-all => ~/P/F/e/l/comint.el + truncate-nil => ~/Projects/FOSS/emacs/lisp/comint.el + relative-from-project => emacs/lisp/comint.el + relative-to-project => lisp/comint.el + file-name => comint.el + buffer-name => comint.el<2> (uniquify buffer name)" + :type '(choice (const auto) + (const truncate-upto-project) + (const truncate-upto-project) + (const truncate-from-project) + (const truncate-with-project) + (const truncate-except-project) + (const truncate-upto-root) + (const truncate-all) + (const truncate-nil) + (const relative-from-project) + (const relative-to-project) + (const file-name) + (const buffer-name)) + :group'doom-modeline) + +(defcustom doom-modeline-icon t + "Whether display the icons in the mode-line. + +While using the server mode in GUI, should set the value explicitly." + :type 'boolean + :group 'doom-modeline) + +(defcustom doom-modeline-major-mode-icon t + "Whether display the icon for `major-mode'. + +It respects variable `doom-modeline-icon'." + :type 'boolean + :group'doom-modeline) + +(defcustom doom-modeline-major-mode-color-icon t + "Whether display the colorful icon for `major-mode'. + +It respects `all-the-icons-color-icons'." + :type 'boolean + :group'doom-modeline) + +(defcustom doom-modeline-buffer-state-icon t + "Whether display the icon for the buffer state. + +It respects variable `doom-modeline-icon'." + :type 'boolean + :group 'doom-modeline) + +(defcustom doom-modeline-buffer-modification-icon t + "Whether display the modification icon for the buffer. + +It respects variable `doom-modeline-icon' and `doom-modeline-buffer-state-icon'." + :type 'boolean + :group 'doom-modeline) + +(defcustom doom-modeline-time-icon t + "Whether display the time icon. + +It respects variable `doom-modeline-icon'." + :type 'boolean + :group 'doom-modeline) + +(defcustom doom-modeline-unicode-fallback nil + "Whether to use unicode as a fallback (instead of ASCII) when not using icons." + :type 'boolean + :group 'doom-modeline) + +(defcustom doom-modeline-buffer-name t + "Whether display the buffer name." + :type 'boolean + :group 'doom-modeline) + +(defcustom doom-modeline-highlight-modified-buffer-name t + "Whether highlight the modified buffer name." + :type 'boolean + :group 'doom-modeline) + +(defcustom doom-modeline-minor-modes nil + "Whether display the minor modes in the mode-line." + :type 'boolean + :group 'doom-modeline) + +(defcustom doom-modeline-enable-word-count nil + "If non-nil, a word count will be added to the selection-info modeline segment." + :type 'boolean + :group 'doom-modeline) + +(defcustom doom-modeline-continuous-word-count-modes + '(markdown-mode gfm-mode org-mode) + "Major modes in which to display word count continuously. + +It respects `doom-modeline-enable-word-count'." + :type '(repeat (symbol :tag "Major-Mode") ) + :group 'doom-modeline) + +(defcustom doom-modeline-buffer-encoding t + "Whether display the buffer encoding." + :type '(choice (const :tag "Always" t) + (const :tag "When non-default" nondefault) + (const :tag "Never" nil)) + :group 'doom-modeline) + +(defcustom doom-modeline-default-coding-system 'utf-8 + "Default coding system for `doom-modeline-buffer-encoding' `nondefault'." + :type 'coding-system + :group 'doom-modeline) + +(defcustom doom-modeline-default-eol-type 0 + "Default EOL type for `doom-modeline-buffer-encoding' `nondefault'." + :type '(choice (const :tag "Unix-style LF" 0) + (const :tag "DOS-style CRLF" 1) + (const :tag "Mac-style CR" 2)) + :group 'doom-modeline) + +(defcustom doom-modeline-indent-info nil + "Whether display the indentation information." + :type 'boolean + :group 'doom-modeline) + +;; It is based upon `editorconfig-indentation-alist' but is used to read indentation levels instead +;; of setting them. (https://github.com/editorconfig/editorconfig-emacs) +(defcustom doom-modeline-indent-alist + '((apache-mode apache-indent-level) + (awk-mode c-basic-offset) + (bpftrace-mode c-basic-offset) + (c++-mode c-basic-offset) + (c-mode c-basic-offset) + (cmake-mode cmake-tab-width) + (coffee-mode coffee-tab-width) + (cperl-mode cperl-indent-level) + (crystal-mode crystal-indent-level) + (csharp-mode c-basic-offset) + (css-mode css-indent-offset) + (d-mode c-basic-offset) + (emacs-lisp-mode lisp-indent-offset) + (enh-ruby-mode enh-ruby-indent-level) + (erlang-mode erlang-indent-level) + (ess-mode ess-indent-offset) + (f90-mode f90-associate-indent + f90-continuation-indent + f90-critical-indent + f90-do-indent + f90-if-indent + f90-program-indent + f90-type-indent) + (feature-mode feature-indent-offset + feature-indent-level) + (fsharp-mode fsharp-continuation-offset + fsharp-indent-level + fsharp-indent-offset) + (groovy-mode groovy-indent-offset) + (haskell-mode haskell-indent-spaces + haskell-indent-offset + haskell-indentation-layout-offset + haskell-indentation-left-offset + haskell-indentation-starter-offset + haskell-indentation-where-post-offset + haskell-indentation-where-pre-offset + shm-indent-spaces) + (haxor-mode haxor-tab-width) + (idl-mode c-basic-offset) + (jade-mode jade-tab-width) + (java-mode c-basic-offset) + (js-mode js-indent-level) + (js-jsx-mode js-indent-level + sgml-basic-offset) + (js2-mode js2-basic-offset) + (js2-jsx-mode js2-basic-offset + sgml-basic-offset) + (js3-mode js3-indent-level) + (json-mode js-indent-level) + (julia-mode julia-indent-offset) + (kotlin-mode kotlin-tab-width) + (latex-mode tex-indent-basic) + (lisp-mode lisp-indent-offset) + (livescript-mode livescript-tab-width) + (lua-mode lua-indent-level) + (matlab-mode matlab-indent-level) + (mips-mode mips-tab-width) + (mustache-mode mustache-basic-offset) + (nasm-mode nasm-basic-offset) + (nginx-mode nginx-indent-level) + (nxml-mode nxml-child-indent) + (objc-mode c-basic-offset) + (octave-mode octave-block-offset) + (perl-mode perl-indent-level) + (php-mode c-basic-offset) + (pike-mode c-basic-offset) + (ps-mode ps-mode-tab) + (pug-mode pug-tab-width) + (puppet-mode puppet-indent-level) + (python-mode python-indent-offset) + (ruby-mode ruby-indent-level) + (rust-mode rust-indent-offset) + (rustic-mode rustic-indent-offset) + (scala-mode scala-indent:step) + (scss-mode css-indent-offset) + (sgml-mode sgml-basic-offset) + (sh-mode sh-basic-offset + sh-indentation) + (slim-mode slim-indent-offset) + (sml-mode sml-indent-level) + (tcl-mode tcl-indent-level + tcl-continued-indent-level) + (terra-mode terra-indent-level) + (typescript-mode typescript-indent-level) + (verilog-mode verilog-indent-level + verilog-indent-level-behavioral + verilog-indent-level-declaration + verilog-indent-level-module + verilog-cexp-indent + verilog-case-indent) + (web-mode web-mode-attr-indent-offset + web-mode-attr-value-indent-offset + web-mode-code-indent-offset + web-mode-css-indent-offset + web-mode-markup-indent-offset + web-mode-sql-indent-offset + web-mode-block-padding + web-mode-script-padding + web-mode-style-padding) + (yaml-mode yaml-indent-offset)) + "Indentation retrieving variables matched to major modes. + +Which is used when `doom-modeline-indent-info' is non-nil. +When multiple variables are specified for a mode, they will be tried resolved +in the given order." + :type '(alist :key-type symbol :value-type sexp) + :group 'doom-modeline) + +(defcustom doom-modeline-checker-simple-format t + "If non-nil, only display one number for checker information if applicable." + :type 'boolean + :group 'doom-modeline) + +(defcustom doom-modeline-number-limit 99 + "The maximum number displayed for notifications." + :type 'integer + :group 'doom-modeline) + +(defcustom doom-modeline-vcs-max-length 12 + "The maximum displayed length of the branch name of version control." + :type 'integer + :group 'doom-modeline) + +(defcustom doom-modeline-workspace-name t + "Whether display the workspace name. + +Non-nil to display in the mode-line." + :type 'boolean + :group 'doom-modeline) + +(defcustom doom-modeline-persp-name t + "Whether display the perspective name. + +Non-nil to display in the mode-line." + :type 'boolean + :group 'doom-modeline) + +(defcustom doom-modeline-display-default-persp-name nil + "If non nil the default perspective name is displayed in the mode-line." + :type 'boolean + :group 'doom-modeline) + +(defcustom doom-modeline-persp-icon t + "If non nil the perspective name is displayed alongside a folder icon." + :type 'boolean + :group 'doom-modeline) + +(defcustom doom-modeline-repl t + "Whether display the `repl' state. + +Non-nil to display in the mode-line." + :type 'boolean + :group 'doom-modeline) + +(defcustom doom-modeline-lsp t + "Whether display the `lsp' state. + +Non-nil to display in the mode-line." + :type 'boolean + :group 'doom-modeline) + +(defcustom doom-modeline-github nil + "Whether display the GitHub notifications. + +It requires `ghub' and `async' packages." + :type 'boolean + :group 'doom-modeline) + +(defcustom doom-modeline-github-interval 1800 ; (* 30 60) + "The interval of checking GitHub." + :type 'integer + :group 'doom-modeline) + +(defcustom doom-modeline-env-version t + "Whether display the environment version." + :type 'boolean + :group 'doom-modeline) + +(defcustom doom-modeline-modal t + "Whether display the modal state. + +Including `evil', `overwrite', `god', `ryo' and `xah-fly-keys', etc." + :type 'boolean + :group 'doom-modeline) + +(defcustom doom-modeline-modal-icon t + "Whether display the modal state icon. + +Including `evil', `overwrite', `god', `ryo' and `xah-fly-keys', etc." + :type 'boolean + :group 'doom-modeline) + +(defcustom doom-modeline-mu4e nil + "Whether display the mu4e notifications. + +It requires `mu4e-alert' package." + :type 'boolean + :group 'doom-modeline) + +(defcustom doom-modeline-gnus nil + "Whether to display notifications from gnus. + +It requires `gnus' to be setup" + :type 'boolean + :group 'doom-modeline) + +(defcustom doom-modeline-gnus-timer 2 + "The wait time in minutes before gnus fetches mail. + +If nil, don't set up a hook." + :type 'integer + :group 'doom-modeline) + +(defcustom doom-modeline-gnus-idle nil + "Whether to wait an idle time to scan for news. + +When t, sets `doom-modeline-gnus-timer' as an idle timer. If a +number, Emacs must have been idle this given time, checked after +reach the defined timer, to fetch news. The time step can be +configured in `gnus-demon-timestep'." + :type '(choice + (boolean :tag "Set `doom-modeline-gnus-timer' as an idle timer") + (number :tag "Set a custom idle timer")) + :group 'doom-modeline) + +(defcustom doom-modeline-gnus-excluded-groups nil + "A list of groups to be excluded from the unread count. +Groups' names list in `gnus-newsrc-alist'`" + :type '(repeat string) + :group 'doom-modeline) + +(defcustom doom-modeline-irc t + "Whether display the irc notifications. + +It requires `circe' or `erc' package." + :type 'boolean + :group 'doom-modeline) + +(defcustom doom-modeline-irc-buffers nil + "Whether display the unread irc buffers." + :type 'boolean + :group 'doom-modeline) + +(defcustom doom-modeline-irc-stylize 'identity + "Function to stylize the irc buffer names." + :type 'function + :group 'doom-modeline) + +(defcustom doom-modeline-battery t + "Whether display the battery status. + +It respects `display-battery-mode'." + :type 'boolean + :group 'doom-modeline) + +(defcustom doom-modeline-time t + "Whether display the time. + +It respects `display-time-mode'." + :type 'boolean + :group 'doom-modeline) + +(defcustom doom-modeline-display-misc-in-all-mode-lines t + "Whether display the misc segment on all mode lines. + +If nil, display only if the mode line is active." + :type 'boolean + :group 'doom-modeline) + +(defcustom doom-modeline-always-visible-segments nil + "A list of segments that should be visible even in +inactive windows." + :type '(repeat symbol) + :group 'doom-modeline) + + +;; +;; Faces +;; + +(defgroup doom-modeline-faces nil + "The faces of `doom-modeline'." + :group 'doom-modeline + :group 'faces + :link '(url-link :tag "Homepage" "https://github.com/seagle0128/doom-modeline")) + +(defface doom-modeline + '((t ())) + "Default face." + :group 'doom-modeline-faces) + +(defface doom-modeline-emphasis + '((t (:inherit (doom-modeline mode-line-emphasis)))) + "Face used for emphasis." + :group 'doom-modeline-faces) + +(defface doom-modeline-highlight + '((t (:inherit (doom-modeline mode-line-highlight)))) + "Face used for highlighting." + :group 'doom-modeline-faces) + +(defface doom-modeline-buffer-path + '((t (:inherit (doom-modeline-emphasis bold)))) + "Face used for the dirname part of the buffer path." + :group 'doom-modeline-faces) + +(defface doom-modeline-buffer-file + '((t (:inherit (doom-modeline mode-line-buffer-id bold)))) + "Face used for the filename part of the mode-line buffer path." + :group 'doom-modeline-faces) + +(defface doom-modeline-buffer-modified + '((t (:inherit (doom-modeline warning bold) :background unspecified))) + "Face used for the \\='unsaved\\=' symbol in the mode-line." + :group 'doom-modeline-faces) + +(defface doom-modeline-buffer-major-mode + '((t (:inherit (doom-modeline-emphasis bold)))) + "Face used for the major-mode segment in the mode-line." + :group 'doom-modeline-faces) + +(defface doom-modeline-buffer-minor-mode + '((t (:inherit (doom-modeline font-lock-doc-face) :slant normal))) + "Face used for the minor-modes segment in the mode-line." + :group 'doom-modeline-faces) + +(defface doom-modeline-project-parent-dir + '((t (:inherit (doom-modeline font-lock-comment-face bold)))) + "Face used for the project parent directory of the mode-line buffer path." + :group 'doom-modeline-faces) + +(defface doom-modeline-project-dir + '((t (:inherit (doom-modeline font-lock-string-face bold)))) + "Face used for the project directory of the mode-line buffer path." + :group 'doom-modeline-faces) + +(defface doom-modeline-project-root-dir + '((t (:inherit (doom-modeline-emphasis bold)))) + "Face used for the project part of the mode-line buffer path." + :group 'doom-modeline-faces) + +(defface doom-modeline-panel + '((t (:inherit doom-modeline-highlight))) + "Face for \\='X out of Y\\=' segments. +This applies to `anzu', `evil-substitute', `iedit' etc." + :group 'doom-modeline-faces) + +(defface doom-modeline-host + '((t (:inherit (doom-modeline italic)))) + "Face for remote hosts in the mode-line." + :group 'doom-modeline-faces) + +(defface doom-modeline-input-method + '((t (:inherit (doom-modeline-emphasis bold)))) + "Face for input method in the mode-line." + :group 'doom-modeline-faces) + +(defface doom-modeline-input-method-alt + '((t (:inherit (doom-modeline font-lock-doc-face bold) :slant normal))) + "Alternative face for input method in the mode-line." + :group 'doom-modeline-faces) + +(defface doom-modeline-debug + '((t (:inherit (doom-modeline font-lock-doc-face bold) :slant normal))) + "Face for debug-level messages in the mode-line. Used by vcs, checker, etc." + :group 'doom-modeline-faces) + +(defface doom-modeline-info + '((t (:inherit (doom-modeline success bold)))) + "Face for info-level messages in the mode-line. Used by vcs, checker, etc." + :group 'doom-modeline-faces) + +(defface doom-modeline-warning + '((t (:inherit (doom-modeline warning bold)))) + "Face for warnings in the mode-line. Used by vcs, checker, etc." + :group 'doom-modeline-faces) + +(defface doom-modeline-urgent + '((t (:inherit (doom-modeline error bold)))) + "Face for errors in the mode-line. Used by vcs, checker, etc." + :group 'doom-modeline-faces) + +(defface doom-modeline-notification + '((t (:inherit doom-modeline-warning))) + "Face for notifications in the mode-line. Used by GitHub, mu4e, etc. +Also see the face `doom-modeline-unread-number'." + :group 'doom-modeline-faces) + +(defface doom-modeline-unread-number + '((t (:inherit doom-modeline :slant italic :weight normal))) + "Face for unread number in the mode-line. Used by GitHub, mu4e, etc." + :group 'doom-modeline-faces) + +(defface doom-modeline-bar + '((t (:inherit doom-modeline-highlight))) + "The face used for the left-most bar in the mode-line of an active window." + :group 'doom-modeline-faces) + +(defface doom-modeline-bar-inactive + `((t (:background ,(face-foreground 'mode-line-inactive)))) + "The face used for the left-most bar in the mode-line of an inactive window." + :group 'doom-modeline-faces) + +(defface doom-modeline-debug-visual + '((((background light)) :foreground "#D4843E" :inherit doom-modeline) + (((background dark)) :foreground "#915B2D" :inherit doom-modeline)) + "Face to use for the mode-line while debugging." + :group 'doom-modeline-faces) + +(defface doom-modeline-evil-emacs-state + '((t (:inherit (doom-modeline font-lock-builtin-face bold)))) + "Face for the Emacs state tag in evil indicator." + :group 'doom-modeline-faces) + +(defface doom-modeline-evil-insert-state + '((t (:inherit (doom-modeline font-lock-keyword-face bold)))) + "Face for the insert state tag in evil indicator." + :group 'doom-modeline-faces) + +(defface doom-modeline-evil-motion-state + '((t (:inherit (doom-modeline font-lock-doc-face bold) :slant normal))) + "Face for the motion state tag in evil indicator." + :group 'doom-modeline-faces) + +(defface doom-modeline-evil-normal-state + '((t (:inherit doom-modeline-info))) + "Face for the normal state tag in evil indicator." + :group 'doom-modeline-faces) + +(defface doom-modeline-evil-operator-state + '((t (:inherit doom-modeline-buffer-file))) + "Face for the operator state tag in evil indicator." + :group 'doom-modeline-faces) + +(defface doom-modeline-evil-visual-state + '((t (:inherit doom-modeline-warning))) + "Face for the visual state tag in evil indicator." + :group 'doom-modeline-faces) + +(defface doom-modeline-evil-replace-state + '((t (:inherit doom-modeline-urgent))) + "Face for the replace state tag in evil indicator." + :group 'doom-modeline-faces) + +(defface doom-modeline-overwrite + '((t (:inherit doom-modeline-urgent))) + "Face for overwrite indicator." + :group 'doom-modeline-faces) + +(defface doom-modeline-god + '((t (:inherit doom-modeline-info))) + "Face for god-mode indicator." + :group 'doom-modeline-faces) + +(defface doom-modeline-ryo + '((t (:inherit doom-modeline-ryo))) + "Face for RYO indicator." + :group 'doom-modeline-faces) + +(defface doom-modeline-fly-insert-state + '((t (:inherit (font-lock-keyword-face bold)))) + "Face for the insert state in xah-fly-keys indicator." + :group 'doom-modeline-faces) + +(defface doom-modeline-fly-normal-state + '((t (:inherit doom-modeline-info))) + "Face for the normal state in xah-fly-keys indicator." + :group 'doom-modeline-faces) + +(defface doom-modeline-boon-command-state + '((t (:inherit doom-modeline-info))) + "Face for the command state tag in boon indicator." + :group 'doom-modeline-faces) + +(defface doom-modeline-boon-insert-state + '((t (:inherit (doom-modeline font-lock-keyword-face bold)))) + "Face for the insert state tag in boon indicator." + :group 'doom-modeline-faces) + +(defface doom-modeline-boon-special-state + '((t (:inherit (doom-modeline font-lock-builtin-face bold)))) + "Face for the special state tag in boon indicator." + :group 'doom-modeline-faces) + +(defface doom-modeline-boon-off-state + '((t (:inherit doom-modeline-buffer-file))) + "Face for the off state tag in boon indicator." + :group 'doom-modeline-faces) + +(defface doom-modeline-persp-name + '((t (:inherit (doom-modeline font-lock-comment-face italic)))) + "Face for the persp name." + :group 'doom-modeline-faces) + +(defface doom-modeline-persp-buffer-not-in-persp + '((t (:inherit (doom-modeline font-lock-doc-face bold italic)))) + "Face for the buffers which are not in the persp." + :group 'doom-modeline-faces) + +(defface doom-modeline-repl-success + '((t (:inherit doom-modeline-info :weight normal))) + "Face for REPL success state." + :group 'doom-modeline-faces) + +(defface doom-modeline-repl-warning + '((t (:inherit doom-modeline-warning :weight normal))) + "Face for REPL warning state." + :group 'doom-modeline-faces) + +(defface doom-modeline-lsp-success + '((t (:inherit doom-modeline-info :weight normal))) + "Face for LSP success state." + :group 'doom-modeline-faces) + +(defface doom-modeline-lsp-warning + '((t (:inherit doom-modeline-warning :weight normal))) + "Face for LSP warning state." + :group 'doom-modeline-faces) + +(defface doom-modeline-lsp-error + '((t (:inherit doom-modeline-urgent :weight normal))) + "Face for LSP error state." + :group 'doom-modeline-faces) + +(defface doom-modeline-lsp-running + '((t (:inherit (doom-modeline compilation-mode-line-run) :weight normal :slant normal))) + "Face for LSP running state." + :group 'doom-modeline-faces) + +(defface doom-modeline-battery-charging + '((t (:inherit doom-modeline-info :weight normal))) + "Face for battery charging status." + :group 'doom-modeline-faces) + +(defface doom-modeline-battery-full + '((t (:inherit doom-modeline-info :weight normal))) + "Face for battery full status." + :group 'doom-modeline-faces) + +(defface doom-modeline-battery-normal + '((t (:inherit (doom-modeline mode-line) :weight normal))) + "Face for battery normal status." + :group 'doom-modeline-faces) + +(defface doom-modeline-battery-warning + '((t (:inherit doom-modeline-warning :weight normal))) + "Face for battery warning status." + :group 'doom-modeline-faces) + +(defface doom-modeline-battery-critical + '((t (:inherit doom-modeline-urgent :weight normal))) + "Face for battery critical status." + :group 'doom-modeline-faces) + +(defface doom-modeline-battery-error + '((t (:inherit doom-modeline-urgent :weight normal))) + "Face for battery error status." + :group 'doom-modeline-faces) + +(defface doom-modeline-buffer-timemachine + '((t (:inherit doom-modeline-buffer-file :slant italic))) + "Face for timemachine status." + :group 'doom-modeline-faces) + +(defface doom-modeline-time + '((t (:inherit doom-modeline-buffer-file))) + "Face for display time." + :group 'doom-modeline-faces) + +(defface doom-modeline-compilation + '((t (:inherit doom-modeline-warning :weight normal :slant italic :height 0.9))) + "Face for compilation progress." + :group 'doom-modeline-faces) + +;; +;; Externals +;; + +(declare-function face-remap-remove-relative "face-remap") +(declare-function ffip-project-root "ext:find-file-in-project") +(declare-function project-root "project") +(declare-function projectile-project-root "ext:projectile") + + +;; +;; Utilities +;; + +(defun doom-modeline-add-font-lock () + "Fontify `doom-modeline-def-*' statements." + (font-lock-add-keywords + 'emacs-lisp-mode + '(("(\\(doom-modeline-def-.+\\)\\_> +\\(.*?\\)\\_>" + (1 font-lock-keyword-face) + (2 font-lock-constant-face))))) +(doom-modeline-add-font-lock) + +(defun doom-modeline-add-imenu () + "Add to `imenu' index." + (add-to-list + 'imenu-generic-expression + '("Modelines" + "^\\s-*(\\(doom-modeline-def-modeline\\)\\s-+\\(\\(?:\\sw\\|\\s_\\|\\s'\\|\\\\.\\)+\\)" + 2)) + (add-to-list + 'imenu-generic-expression + '("Segments" + "^\\s-*(\\(doom-modeline-def-segment\\)\\s-+\\(\\(?:\\sw\\|\\s_\\|\\\\.\\)+\\)" + 2)) + (add-to-list + 'imenu-generic-expression + '("Envs" + "^\\s-*(\\(doom-modeline-def-env\\)\\s-+\\(\\(?:\\sw\\|\\s_\\|\\\\.\\)+\\)" + 2))) + + +;; +;; Core helpers +;; + +;; FIXME #183: Force to calculate mode-line height +;; @see https://github.com/seagle0128/doom-modeline/issues/183 +;; @see https://github.com/seagle0128/doom-modeline/issues/483 +(defun doom-modeline-redisplay (&rest _) + "Call `redisplay' to trigger mode-line height calculations. + +Certain functions, including e.g. `fit-window-to-buffer', base +their size calculations on values which are incorrect if the +mode-line has a height different from that of the `default' face +and certain other calculations have not yet taken place for the +window in question. + +These calculations can be triggered by calling `redisplay' +explicitly at the appropriate time and this functions purpose +is to make it easier to do so. + +This function is like `redisplay' with non-nil FORCE argument, +but it will only trigger a redisplay when there is a non nil +`mode-line-format' and the height of the mode-line is different +from that of the `default' face. This function is intended to be +used as an advice to window creation functions." + (when (and (bound-and-true-p doom-modeline-mode) + mode-line-format + (/= (frame-char-height) (window-mode-line-height))) + (redisplay t))) +(unless (>= emacs-major-version 29) + (advice-add #'fit-window-to-buffer :before #'doom-modeline-redisplay)) + +(defun doom-modeline-icon-displayable-p () + "Return non-nil if icons are displayable." + (and doom-modeline-icon + (display-graphic-p) + (featurep 'all-the-icons))) + +(defun doom-modeline-mwheel-available-p () + "Whether mouse wheel is available." + (and (featurep 'mwheel) (bound-and-true-p mouse-wheel-mode))) + +;; Keep `doom-modeline-current-window' up-to-date +(defun doom-modeline--selected-window () + "Get the selected window." + (frame-selected-window)) + +(defvar doom-modeline-current-window (doom-modeline--selected-window) + "Current window.") + +(defun doom-modeline--active () + "Whether is an active window." + (unless (and (bound-and-true-p mini-frame-frame) + (and (frame-live-p mini-frame-frame) + (frame-visible-p mini-frame-frame))) + (and doom-modeline-current-window + (eq (doom-modeline--selected-window) doom-modeline-current-window)))) + +(defvar-local doom-modeline--limited-width-p nil) + +(defun doom-modeline--segment-visible (name) + "Whether a segment should be displayed" + (and + (or (doom-modeline--active) + (member name doom-modeline-always-visible-segments)) + (not doom-modeline--limited-width-p))) + +(defun doom-modeline-set-selected-window (&rest _) + "Set `doom-modeline-current-window' appropriately." + (let ((win (doom-modeline--selected-window))) + (setq doom-modeline-current-window + (if (minibuffer-window-active-p win) + (minibuffer-selected-window) + win)))) + +(defun doom-modeline-unset-selected-window () + "Unset `doom-modeline-current-window' appropriately." + (setq doom-modeline-current-window nil)) + +(add-hook 'pre-redisplay-functions #'doom-modeline-set-selected-window) + +;; Ensure modeline is inactive when Emacs is unfocused +(defvar doom-modeline--remap-faces '(mode-line + mode-line-active + mode-line-emphasis + mode-line-highlight + mode-line-buffer-id + doom-modeline + solaire-mode-line-face + solaire-mode-line-active-face + paradox-mode-line-face + flycheck-color-mode-line-error-face + flycheck-color-mode-line-warning-face + flycheck-color-mode-line-info-face + flycheck-color-mode-line-success-face)) + +(defvar doom-modeline--remap-face-cookie-alist nil) +(defun doom-modeline-focus () + "Focus mode-line." + (mapc #'face-remap-remove-relative doom-modeline--remap-face-cookie-alist)) + +(defun doom-modeline-unfocus () + "Unfocus mode-line." + (dolist (face doom-modeline--remap-faces) + (add-to-list 'doom-modeline--remap-face-cookie-alist + (face-remap-add-relative face 'mode-line-inactive)))) + +(with-no-warnings + (if (boundp 'after-focus-change-function) + (progn + (defun doom-modeline-focus-change (&rest _) + (if (frame-focus-state (frame-parent)) + (progn + (doom-modeline-focus) + ;; HACK: pulse after focusing in the frame to refresh the buffer name. + ;; @see https://github.com/seagle0128/doom-modeline/issues/591 + (when (fboundp 'pulse-momentary-highlight-region) + (pulse-momentary-highlight-region 0 0))) + (doom-modeline-unfocus))) + (advice-add #'handle-switch-frame :after #'doom-modeline-focus-change) + (add-function :after after-focus-change-function #'doom-modeline-focus-change)) + (progn + (add-hook 'focus-in-hook #'doom-modeline-focus) + (add-hook 'focus-out-hook #'doom-modeline-unfocus)))) + + +;; +;; Core +;; + +(defvar doom-modeline-fn-alist ()) +(defvar doom-modeline-var-alist ()) + +(defmacro doom-modeline-def-segment (name &rest body) + "Define a modeline segment NAME with BODY and byte compiles it." + (declare (indent defun) (doc-string 2)) + (let ((sym (intern (format "doom-modeline-segment--%s" name))) + (docstring (if (stringp (car body)) + (pop body) + (format "%s modeline segment" name)))) + (cond ((and (symbolp (car body)) + (not (cdr body))) + (add-to-list 'doom-modeline-var-alist (cons name (car body))) + `(add-to-list 'doom-modeline-var-alist (cons ',name ',(car body)))) + (t + (add-to-list 'doom-modeline-fn-alist (cons name sym)) + `(progn + (defun ,sym () ,docstring ,@body) + (add-to-list 'doom-modeline-fn-alist (cons ',name ',sym)) + ,(unless (bound-and-true-p byte-compile-current-file) + `(let (byte-compile-warnings) + (unless (and (fboundp 'subr-native-elisp-p) + (subr-native-elisp-p (symbol-function #',sym))) + (byte-compile #',sym))))))))) + +(defun doom-modeline--prepare-segments (segments) + "Prepare mode-line `SEGMENTS'." + (let (forms it) + (dolist (seg segments) + (cond ((stringp seg) + (push seg forms)) + ((symbolp seg) + (cond ((setq it (cdr (assq seg doom-modeline-fn-alist))) + (push (list :eval (list it)) forms)) + ((setq it (cdr (assq seg doom-modeline-var-alist))) + (push it forms)) + ((error "%s is not a defined segment" seg)))) + ((error "%s is not a valid segment" seg)))) + (nreverse forms))) + +(defun doom-modeline-def-modeline (name lhs &optional rhs) + "Define a modeline format and byte-compiles it. +NAME is a symbol to identify it (used by `doom-modeline' for retrieval). +LHS and RHS are lists of symbols of modeline segments defined with +`doom-modeline-def-segment'. + +Example: + (doom-modeline-def-modeline \\='minimal + \\='(bar matches \" \" buffer-info) + \\='(media-info major-mode)) + (doom-modeline-set-modeline \\='minimal t)" + (let ((sym (intern (format "doom-modeline-format--%s" name))) + (lhs-forms (doom-modeline--prepare-segments lhs)) + (rhs-forms (doom-modeline--prepare-segments rhs))) + (defalias sym + (lambda () + (list lhs-forms + (propertize + " " + 'face (doom-modeline-face) + 'display `(space + :align-to + (- (+ right right-fringe right-margin scroll-bar) + ,(let ((rhs-str (format-mode-line (cons "" rhs-forms)))) + (if (and (>= emacs-major-version 29) + (fboundp 'string-pixel-width)) + (/ (string-pixel-width rhs-str) + (doom-modeline--font-width) + 1.0) + (* (string-width rhs-str) + (if (display-graphic-p) + (/ (doom-modeline--font-width) (frame-char-width) 0.95) + 1.0))))))) + rhs-forms)) + (concat "Modeline:\n" + (format " %s\n %s" + (prin1-to-string lhs) + (prin1-to-string rhs)))))) +(put 'doom-modeline-def-modeline 'lisp-indent-function 'defun) + +(defun doom-modeline (key) + "Return a mode-line configuration associated with KEY (a symbol). +Throws an error if it doesn't exist." + (let ((fn (intern-soft (format "doom-modeline-format--%s" key)))) + (when (functionp fn) + `(:eval (,fn))))) + +(defun doom-modeline-set-modeline (key &optional default) + "Set the modeline format. Does nothing if the modeline KEY doesn't exist. +If DEFAULT is non-nil, set the default mode-line for all buffers." + (when-let ((modeline (doom-modeline key))) + (setf (if default + (default-value 'mode-line-format) + mode-line-format) + (list "%e" modeline)))) + + +;; +;; Helpers +;; + +(defconst doom-modeline-ellipsis + (if (char-displayable-p ?…) "…" "...") + "Ellipsis.") + +(defsubst doom-modeline-spc () + "Whitespace." + (propertize " " 'face (doom-modeline-face))) + +(defsubst doom-modeline-wspc () + "Wide Whitespace." + (propertize " " 'face (doom-modeline-face))) + +(defsubst doom-modeline-vspc () + "Thin whitespace." + (propertize " " + 'face (doom-modeline-face) + 'display '((space :relative-width 0.5)))) + +(defun doom-modeline-face (&optional face inactive-face) + "Display FACE in active window, and INACTIVE-FACE in inactive window. +IF FACE is nil, `mode-line' face will be used. +If INACTIVE-FACE is nil, `mode-line-inactive' face will be used." + (if (doom-modeline--active) + (or (and (facep face) face) + (and (facep 'mode-line-active) 'mode-line-active) + 'mode-line) + (or (and (facep face) `(:inherit (mode-line-inactive ,face))) + (and (facep inactive-face) inactive-face) + 'mode-line-inactive))) + +;; Since 27, the calculation of char height was changed +;; @see https://github.com/seagle0128/doom-modeline/issues/271 +(defun doom-modeline--font-height () + "Calculate the actual char height of the mode-line." + (let ((height (face-attribute 'mode-line :height)) + (char-height (window-font-height nil 'mode-line))) + (round + (* (pcase system-type + ('darwin (if doom-modeline-icon 1.7 1.0)) + ('windows-nt (if doom-modeline-icon 1.3 1.0)) + (_ (if (and doom-modeline-icon (< emacs-major-version 27)) 1.4 1.0))) + (cond ((integerp height) (/ height 10)) + ((floatp height) (* height char-height)) + (t char-height)))))) + +(defun doom-modeline--original-value (sym) + "Return the original value for SYM, if any. + +If SYM has an original value, return it in a list. Return nil +otherwise." + (let* ((orig-val-expr (get sym 'standard-value))) + (when (consp orig-val-expr) + (ignore-errors + (list + (eval (car orig-val-expr))))))) + +(defun doom-modeline-add-variable-watcher (symbol watch-function) + "Cause WATCH-FUNCTION to be called when SYMBOL is set if possible. + +See docs of `add-variable-watcher'." + (when (fboundp 'add-variable-watcher) + (add-variable-watcher symbol watch-function))) + +(defun doom-modeline-propertize-icon (icon &optional face) + "Propertize the ICON with the specified FACE. + +The face should be the first attribute, or the font family may be overridden. +So convert the face \":family XXX :height XXX :inherit XXX\" to +\":inherit XXX :family XXX :height XXX\". +See https://github.com/seagle0128/doom-modeline/issues/301." + (if (doom-modeline-icon-displayable-p) + (when-let ((props (get-text-property 0 'face icon))) + (when (listp props) + (cl-destructuring-bind (&key family height inherit &allow-other-keys) props + (propertize icon 'face `(:inherit (doom-modeline ,(or face inherit props)) + :family ,(or family "") + :height ,(or height 1.0)))))) + (propertize icon 'face `(:inherit (doom-modeline ,face))))) + +(defun doom-modeline-icon (icon-set icon-name unicode text &rest args) + "Display icon of ICON-NAME with ARGS in mode-line. + +ICON-SET includes `octicon', `faicon', `material', `alltheicons' and `fileicon', +etc. +UNICODE is the unicode char fallback. TEXT is the ASCII char fallback. +ARGS is same as `all-the-icons-octicon' and others." + (let ((face `(:inherit (doom-modeline + ,(or (plist-get args :face) 'mode-line))))) + (cond + ;; Icon + ((and (doom-modeline-icon-displayable-p) + icon-name + (not (string-empty-p icon-name))) + (when-let* ((func (all-the-icons--function-name icon-set)) + (icon (and (fboundp func) + (apply func icon-name args)))) + (doom-modeline-propertize-icon icon face))) + ;; Unicode fallback + ((and doom-modeline-unicode-fallback + unicode + (not (string-empty-p unicode)) + (char-displayable-p (string-to-char unicode))) + (propertize unicode 'face face)) + ;; ASCII text + (text + (propertize text 'face face)) + ;; Fallback + (t "")))) + +(defun doom-modeline-display-icon (icon) + "Display ICON in mode-line." + (if (doom-modeline--active) + icon + (doom-modeline-propertize-icon icon 'mode-line-inactive))) + +(defun doom-modeline-display-text (text) + "Display TEXT in mode-line." + (if (doom-modeline--active) + text + (propertize text 'face 'mode-line-inactive))) + +(defun doom-modeline--create-bar-image (face width height) + "Create the bar image. + +Use FACE for the bar, WIDTH and HEIGHT are the image size in pixels." + (when (and (display-graphic-p) + (image-type-available-p 'pbm) + (numberp width) (> width 0) + (numberp height) (> height 0)) + (propertize + " " 'display + (let ((color (or (face-background face nil t) "None"))) + (ignore-errors + (create-image + (concat (format "P1\n%i %i\n" width height) + (make-string (* width height) ?1) + "\n") + 'pbm t :scale 1 :foreground color :ascent 'center)))))) + +(defun doom-modeline--create-hud-image + (face1 face2 width height top-margin bottom-margin) + "Create the hud image. + +Use FACE1 for the bar, FACE2 for the background. +WIDTH and HEIGHT are the image size in pixels. +TOP-MARGIN and BOTTOM-MARGIN are the size of the margin above and below the bar, +respectively." + (when (and (display-graphic-p) + (image-type-available-p 'pbm) + (numberp width) (> width 0) + (numberp height) (> height 0)) + (let ((min-height (min height doom-modeline-hud-min-height))) + (unless (> (- height top-margin bottom-margin) min-height) + (let ((margin (- height min-height))) + (setq top-margin (/ (* margin top-margin) (+ top-margin bottom-margin)) + bottom-margin (- margin top-margin))))) + (propertize + " " 'display + (let ((color1 (or (face-background face1 nil t) "None")) + (color2 (or (face-background face2 nil t) "None"))) + (create-image + (concat + (format "P1\n%i %i\n" width height) + (make-string (* top-margin width) ?0) + (make-string (* (- height top-margin bottom-margin) width) ?1) + (make-string (* bottom-margin width) ?0) + "\n") + 'pbm t :foreground color1 :background color2 :ascent 'center))))) + +;; Check whether `window-total-width' is smaller than the limit +(defun doom-modeline-window-size-change-function (&rest _) + "Function for `window-size-change-functions'." + (setq doom-modeline--limited-width-p + (cond + ((integerp doom-modeline-window-width-limit) + (<= (window-total-width) doom-modeline-window-width-limit)) + ((floatp doom-modeline-window-width-limit) + (<= (/ (window-total-width) (frame-width) 1.0) + doom-modeline-window-width-limit))))) + +(add-hook 'after-revert-hook #'doom-modeline-window-size-change-function) +(add-hook 'buffer-list-update-hook #'doom-modeline-window-size-change-function) +(add-hook 'window-size-change-functions #'doom-modeline-window-size-change-function) + +(defvar-local doom-modeline--project-root nil) +(defun doom-modeline--project-root () + "Get the path to the project root. +Return nil if no project was found." + (or doom-modeline--project-root + (setq doom-modeline--project-root + (cond + ((and (memq doom-modeline-project-detection '(auto ffip)) + (fboundp 'ffip-project-root)) + (let ((inhibit-message t)) + (ffip-project-root))) + ((and (memq doom-modeline-project-detection '(auto projectile)) + (bound-and-true-p projectile-mode)) + (projectile-project-root)) + ((and (memq doom-modeline-project-detection '(auto project)) + (fboundp 'project-current)) + (when-let ((project (project-current))) + (expand-file-name + (if (fboundp 'project-root) + (project-root project) + (car (with-no-warnings + (project-roots project))))))))))) + +(defun doom-modeline-project-p () + "Check if the file is in a project." + (doom-modeline--project-root)) + +(defun doom-modeline-project-root () + "Get the path to the root of your project. +Return `default-directory' if no project was found." + (or (doom-modeline--project-root) default-directory)) + +(defun doom-modeline-buffer-file-name () + "Propertize file name based on `doom-modeline-buffer-file-name-style'." + (let* ((buffer-file-name (file-local-name (or (buffer-file-name (buffer-base-buffer)) ""))) + (buffer-file-truename (file-local-name + (or buffer-file-truename (file-truename buffer-file-name) ""))) + (file-name + (pcase doom-modeline-buffer-file-name-style + ('auto + (if (doom-modeline-project-p) + (doom-modeline--buffer-file-name buffer-file-name buffer-file-truename 'shrink 'shrink 'hide) + (propertize "%b" 'face 'doom-modeline-buffer-file))) + ('truncate-upto-project + (doom-modeline--buffer-file-name buffer-file-name buffer-file-truename 'shrink)) + ('truncate-from-project + (doom-modeline--buffer-file-name buffer-file-name buffer-file-truename nil 'shrink)) + ('truncate-with-project + (doom-modeline--buffer-file-name buffer-file-name buffer-file-truename 'shrink 'shink 'hide)) + ('truncate-except-project + (doom-modeline--buffer-file-name buffer-file-name buffer-file-truename 'shrink 'shink)) + ('truncate-upto-root + (doom-modeline--buffer-file-name-truncate buffer-file-name buffer-file-truename)) + ('truncate-all + (doom-modeline--buffer-file-name-truncate buffer-file-name buffer-file-truename t)) + ('truncate-nil + (doom-modeline--buffer-file-name buffer-file-name buffer-file-truename)) + ('relative-to-project + (doom-modeline--buffer-file-name-relative buffer-file-name buffer-file-truename)) + ('relative-from-project + (doom-modeline--buffer-file-name buffer-file-name buffer-file-truename nil nil 'hide)) + ('file-name + (propertize (file-name-nondirectory buffer-file-name) + 'face 'doom-modeline-buffer-file)) + ((or 'buffer-name _) + (propertize "%b" 'face 'doom-modeline-buffer-file))))) + (propertize (if (string-empty-p file-name) + (propertize "%b" 'face 'doom-modeline-buffer-file) + file-name) + 'mouse-face 'mode-line-highlight + 'help-echo (concat buffer-file-truename + (unless (string= (file-name-nondirectory buffer-file-truename) + (buffer-name)) + (concat "\n" (buffer-name))) + "\nmouse-1: Previous buffer\nmouse-3: Next buffer") + 'local-map mode-line-buffer-identification-keymap))) + +(defun doom-modeline--buffer-file-name-truncate (file-path true-file-path &optional truncate-tail) + "Propertize file name that truncates every dir along path. + +If TRUNCATE-TAIL is t also truncate the parent directory of the file." + (let ((dirs (shrink-path-prompt (file-name-directory true-file-path)))) + (if (null dirs) + (propertize "%b" 'face 'doom-modeline-buffer-file) + (let ((dirname (car dirs)) + (basename (cdr dirs))) + (concat (propertize (concat dirname + (if truncate-tail (substring basename 0 1) basename) + "/") + 'face 'doom-modeline-project-root-dir) + (propertize (file-name-nondirectory file-path) + 'face 'doom-modeline-buffer-file)))))) + +(defun doom-modeline--buffer-file-name-relative (_file-path true-file-path &optional include-project) + "Propertize file name showing directories relative to project's root only. + +If INCLUDE-PROJECT is non-nil, the project path will be included." + (let ((root (file-local-name (doom-modeline-project-root)))) + (if (null root) + (propertize "%b" 'face 'doom-modeline-buffer-file) + (let ((relative-dirs (file-relative-name (file-name-directory true-file-path) + (if include-project (concat root "../") root)))) + (and (equal "./" relative-dirs) (setq relative-dirs "")) + (concat (propertize relative-dirs 'face 'doom-modeline-buffer-path) + (propertize (file-name-nondirectory true-file-path) + 'face 'doom-modeline-buffer-file)))))) + +(defun doom-modeline--buffer-file-name (file-path + _true-file-path + &optional + truncate-project-root-parent + truncate-project-relative-path + hide-project-root-parent) + "Propertize buffer name given by FILE-PATH. + +If TRUNCATE-PROJECT-ROOT-PARENT is non-nil will be saved by truncating project +root parent down fish-shell style. + +Example: + ~/Projects/FOSS/emacs/lisp/comint.el => ~/P/F/emacs/lisp/comint.el + +If TRUNCATE-PROJECT-RELATIVE-PATH is non-nil will be saved by truncating project +relative path down fish-shell style. + +Example: + ~/Projects/FOSS/emacs/lisp/comint.el => ~/Projects/FOSS/emacs/l/comint.el + +If HIDE-PROJECT-ROOT-PARENT is non-nil will hide project root parent. + +Example: + ~/Projects/FOSS/emacs/lisp/comint.el => emacs/lisp/comint.el" + (let ((project-root (file-local-name (doom-modeline-project-root)))) + (concat + ;; Project root parent + (unless hide-project-root-parent + (when-let (root-path-parent + (file-name-directory (directory-file-name project-root))) + (propertize + (if (and truncate-project-root-parent + (not (string-empty-p root-path-parent)) + (not (string= root-path-parent "/"))) + (shrink-path--dirs-internal root-path-parent t) + (abbreviate-file-name root-path-parent)) + 'face 'doom-modeline-project-parent-dir))) + ;; Project directory + (propertize + (concat (file-name-nondirectory (directory-file-name project-root)) "/") + 'face 'doom-modeline-project-dir) + ;; relative path + (propertize + (when-let (relative-path (file-relative-name + (or (file-name-directory file-path) "./") + project-root)) + (if (string= relative-path "./") + "" + (if truncate-project-relative-path + (substring (shrink-path--dirs-internal relative-path t) 1) + relative-path))) + 'face 'doom-modeline-buffer-path) + ;; File name + (propertize (file-name-nondirectory file-path) + 'face 'doom-modeline-buffer-file)))) + +(provide 'doom-modeline-core) + +;;; doom-modeline-core.el ends here diff --git a/org/elpa/doom-modeline-20230406.623/doom-modeline-env.el b/org/elpa/doom-modeline-20230406.623/doom-modeline-env.el new file mode 100644 index 0000000..e4fd95c --- /dev/null +++ b/org/elpa/doom-modeline-20230406.623/doom-modeline-env.el @@ -0,0 +1,276 @@ +;;; doom-modeline-env.el --- A environment parser for doom-modeline -*- lexical-binding: t -*- + +;; Copyright (C) 2019-2020 Justin Barclay, Vincent Zhang + +;; This file is not part of GNU Emacs. + +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . +;; +;;; Commentary: +;; +;; Parse programming environment. +;; + +;;; Code: + +(require 'subr-x) +(require 'doom-modeline-core) + + +;; Externals +(defvar python-shell-interpreter) + + +;; Customization + +(defgroup doom-modeline-env nil + "The environment parser for `doom-modeline'." + :group 'doom-modeline + :link '(url-link :tag "Homepage" "https://github.com/seagle0128/doom-modeline")) + +(defcustom doom-modeline-env-load-string doom-modeline-ellipsis + "What to display as the version while a new one is being loaded." + :type 'string + :group 'doom-modeline-env) + +(defcustom doom-modeline-before-update-env-hook nil + "Hooks that run before the modeline version string is updated." + :type 'hook + :group 'doom-modeline-env) + +(defcustom doom-modeline-after-update-env-hook nil + "Hooks that run after the modeline version string is updated." + :type 'hook + :group 'doom-modeline-env) + + +;; Variables + +;; Show version string for multi-version managers like rvm, rbenv, pyenv, etc. +(defvar-local doom-modeline-env--version nil + "The version to display with major-mode in mode-line. +Example: \"2.6.0\"") + +(defvar-local doom-modeline-env--command nil + "A program that we're looking to extract version information from. +Example: \"ruby\"") + +(defvar-local doom-modeline-env--command-args nil + "A list of arguments for the command to extract the version from. +Example: \\='(\"--version\")") + +(defvar-local doom-modeline-env--parser nil + "A function that returns version number from a command --version (or similar). +Example: \\='doom-modeline-env--ruby") + + +;; Functions & Macros + +(defun doom-modeline-update-env () + "Update environment info on mode-line." + (when (and doom-modeline-env-version + doom-modeline-env--command + (executable-find doom-modeline-env--command) + doom-modeline-env--command-args + doom-modeline-env--parser) + (let ((default-directory (doom-modeline-project-root)) + (buffer (current-buffer))) + (run-hooks 'doom-modeline-before-update-env-hook) + (setq doom-modeline-env--version doom-modeline-env-load-string) + (doom-modeline-env--get + doom-modeline-env--command + doom-modeline-env--command-args + (lambda (prog-version) + (with-current-buffer buffer + (setq doom-modeline-env--version + (funcall doom-modeline-env--parser prog-version)) + (run-hooks 'doom-modeline-after-update-env-hook))))))) + +(add-hook 'find-file-hook #'doom-modeline-update-env) +(with-no-warnings + (if (boundp 'after-focus-change-function) + (add-function + :after after-focus-change-function + (lambda () + (if (frame-focus-state) + (doom-modeline-update-env)))) + (add-hook 'focus-in-hook #'doom-modeline-update-env))) + +(defun doom-modeline-env--get (prog args callback) + "Start a sub process using PROG and apply the ARGS to the sub process. +Once it receives information from STDOUT, it closes off the subprocess and +passes on the information into the CALLBACK. +Example: + (doom-modeline-env--get + \"ruby\" + \\='(\"--version\") + (lambda (line) + (message (doom-modeline-parser--ruby line)))" + (when-let ((proc (ignore-errors + (apply 'start-process + ;; Flaten process-args into a single list so we can handle + ;; variadic length args + (append + (list "doom-modeline-env" nil prog) + args)))) + (parser callback)) + (set-process-filter proc + (lambda (_proc line) + (ignore-errors + (funcall parser line)))))) + +(cl-defmacro doom-modeline-def-env (name &key hooks command parser) + "Define a handler for updating & displaying a version string for a language. + +NAME is an unquoted symbol representing the handler's unique ID. +HOOKS is a list of hook symbols where this handler should be triggered. +COMMAND should be a function that returns a shell command and its arguments (as + a list). It is run on HOOKS. It takes no arguments. +PARSER should be a function for parsing COMMAND's output line-by-line, to + extract the version string." + (declare (indent defun)) + (unless (and hooks command parser) + (error "'%s' env is missing either :hooks, :command or :parser" name)) + (let ((parse-fn (intern (format "doom-modeline-env--%s-parse" name))) + (action-fn (intern (format "doom-modeline-env--%s-args" name))) + (setup-fn (intern (format "doom-modeline-env-setup-%s" name))) + (update-fn (intern (format "doom-modeline-env-update-%s" name))) + (enable-var (intern (format "doom-modeline-env-enable-%s" name))) + (command-var (intern (format "doom-modeline-env-%s-command" name))) + (parser-var (intern (format "doom-modeline-env-%s-parser-fn" name))) + (exe-var (intern (format "doom-modeline-env-%s-executable" name)))) + (macroexp-progn + `((defcustom ,enable-var t + ,(format "Whether to display the version string for %s buffers." name) + :type 'boolean + :group 'doom-modeline-env) + (defvar ,command-var ',action-fn + ,(concat "A function that returns the shell command and arguments (as a list) to\n" + "produce a version string.")) + (defvar ,parser-var ',parse-fn + ,(format "The function to parse each line of `%s'\'s output." command-var)) + (defcustom ,exe-var nil + ,(format (concat "What executable to use for the version indicator in %s buffers.\n\n" + "If nil, the default binary for this language is used.") + name) + :type 'string + :group 'doom-modeline-env) + (defalias ',parse-fn ,parser + (format "The line parser for %s buffers.\n\nUsed by `%s'." + ',name ',update-fn)) + (defalias ',action-fn ,command + (format "The command resolver for %s buffers.\n\nUsed by `%s'." + ',name ',update-fn)) + (defalias ',setup-fn + (lambda () + (if enable-local-variables + (add-hook 'hack-local-variables-hook #',update-fn nil t) + (,update-fn))) + (format "Prepares the modeline to later display the %s version string." + ',name)) + (defalias ',update-fn + (lambda () + (when ,enable-var + (when-let* ((command-list (funcall ,command-var)) + (exe (executable-find (car command-list)))) + (setq doom-modeline-env--command exe + doom-modeline-env--command-args (cdr command-list) + doom-modeline-env--parser ,parser-var) + (doom-modeline-update-env)))) + (format "Updates the %s version string in the modeline." ',name)) + (let ((hooks ',(eval hooks))) + (dolist (hook (if (listp hooks) hooks (list hooks))) + (add-hook hook #',setup-fn))))))) + + +;; Bootstrap +;; Versions, support Python, Ruby, Perl and Golang, etc. + +;;;###autoload (autoload 'doom-modeline-env-setup-python "doom-modeline-env") +(doom-modeline-def-env python + :hooks 'python-mode-hook + :command (lambda () (cond ((and (fboundp 'pipenv-project-p) + (pipenv-project-p)) + (list "pipenv" "run" + (or doom-modeline-env-python-executable + python-shell-interpreter + "python") + "--version")) + ((executable-find "pyenv") (list "pyenv" "version-name")) + ((list (or doom-modeline-env-python-executable + python-shell-interpreter + "python") + "--version")))) + :parser (lambda (line) (let ((version (split-string line))) + (if (length> version 1) + (cadr version) + (car version))))) + +;;;###autoload (autoload 'doom-modeline-env-setup-ruby "doom-modeline-env") +(doom-modeline-def-env ruby + :hooks '(ruby-mode-hook enh-ruby-mode-hook) + :command (lambda () (list (or doom-modeline-env-ruby-executable "ruby") "--version")) + :parser (lambda (line) + (car (split-string + (cadr + (split-string line)) + "p")))) + +;;;###autoload (autoload 'doom-modeline-env-setup-perl "doom-modeline-env") +(doom-modeline-def-env perl + :hooks 'perl-mode-hook + :command (lambda () (list (or doom-modeline-env-perl-executable "perl") "--version")) + :parser (lambda (line) + (cadr + (split-string + (car + (split-string + (cadr + (split-string line "(")) + ")")) + "v")))) + +;;;###autoload (autoload 'doom-modeline-env-setup-go "doom-modeline-env") +(doom-modeline-def-env go + :hooks 'go-mode-hook + :command (lambda () (list (or doom-modeline-env-go-executable "go") "version")) + :parser (lambda (line) + (cadr + (split-string + (cadr + (cdr + (split-string line))) + "go")))) + +;;;###autoload (autoload 'doom-modeline-env-setup-elixir "doom-modeline-env") +(doom-modeline-def-env elixir + :hooks 'elixir-mode-hook + :command (lambda () (list (or doom-modeline-env-elixir-executable "elixir") "--version")) + :parser (lambda (line) (cadr (split-string line)))) + +;;;###autoload (autoload 'doom-modeline-env-setup-rust "doom-modeline-env") +(doom-modeline-def-env rust + :hooks 'rust-mode-hook + :command (lambda () (list (or doom-modeline-env-rust-executable "rustc") "--version")) + :parser (lambda (line) + (car + (split-string + (cadr + (split-string line)) + "-")))) + +(provide 'doom-modeline-env) + +;;; doom-modeline-env.el ends here diff --git a/org/elpa/doom-modeline-20230406.623/doom-modeline-pkg.el b/org/elpa/doom-modeline-20230406.623/doom-modeline-pkg.el new file mode 100644 index 0000000..9a8ba77 --- /dev/null +++ b/org/elpa/doom-modeline-20230406.623/doom-modeline-pkg.el @@ -0,0 +1,14 @@ +(define-package "doom-modeline" "20230406.623" "A minimal and modern mode-line" + '((emacs "25.1") + (compat "28.1.1.1") + (shrink-path "0.2.0")) + :commit "a86ec8effe242cab8aba09ec0a2c7fed555c1fce" :authors + '(("Vincent Zhang" . "seagle0128@gmail.com")) + :maintainer + '("Vincent Zhang" . "seagle0128@gmail.com") + :keywords + '("faces" "mode-line") + :url "https://github.com/seagle0128/doom-modeline") +;; Local Variables: +;; no-byte-compile: t +;; End: diff --git a/org/elpa/doom-modeline-20230406.623/doom-modeline-segments.el b/org/elpa/doom-modeline-20230406.623/doom-modeline-segments.el new file mode 100644 index 0000000..5c37da7 --- /dev/null +++ b/org/elpa/doom-modeline-20230406.623/doom-modeline-segments.el @@ -0,0 +1,3027 @@ +;;; doom-modeline-segments.el --- The segments for doom-modeline -*- lexical-binding: t; -*- + +;; Copyright (C) 2018-2020 Vincent Zhang + +;; This file is not part of GNU Emacs. + +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . +;; + +;;; Commentary: +;; +;; The segments for doom-modeline. +;; Use `doom-modeline-def-segment' to create a new segment. +;; + +;;; Code: + +(require 'cl-lib) +(require 'seq) +(require 'subr-x) +(require 'doom-modeline-core) +(require 'doom-modeline-env) + + +;; +;; Externals +;; + +(defvar Info-current-file) +(defvar Info-current-node) +(defvar Info-mode-line-node-keymap) +(defvar anzu--cached-count) +(defvar anzu--current-position) +(defvar anzu--overflow-p) +(defvar anzu--state) +(defvar anzu--total-matched) +(defvar anzu-cons-mode-line-p) +(defvar aw-keys) +(defvar battery-echo-area-format) +(defvar battery-load-critical) +(defvar battery-mode-line-format) +(defvar battery-mode-line-limit) +(defvar battery-status-function) +(defvar boon-command-state) +(defvar boon-insert-state) +(defvar boon-off-state) +(defvar boon-special-state) +(defvar edebug-execution-mode) +(defvar eglot--managed-mode) +(defvar erc-modified-channels-alist) +(defvar evil-ex-active-highlights-alist) +(defvar evil-ex-argument) +(defvar evil-ex-range) +(defvar evil-mc-frozen) +(defvar evil-state) +(defvar evil-visual-beginning) +(defvar evil-visual-end) +(defvar evil-visual-selection) +(defvar flycheck--automatically-enabled-checkers) +(defvar flycheck-current-errors) +(defvar flycheck-mode-menu-map) +(defvar flymake--mode-line-format) +(defvar flymake--state) +(defvar flymake-menu) +(defvar gnus-newsrc-alist) +(defvar gnus-newsrc-hashtb) +(defvar grip--process) +(defvar helm--mode-line-display-prefarg) +(defvar iedit-occurrences-overlays) +(defvar meow--indicator) +(defvar minions-mode-line-lighter) +(defvar minions-mode-line-minor-modes-map) +(defvar mlscroll-minimum-current-width) +(defvar mlscroll-right-align) +(defvar mu4e-alert-mode-line) +(defvar mu4e-alert-modeline-formatter) +(defvar nyan-minimum-window-width) +(defvar objed--obj-state) +(defvar objed--object) +(defvar objed-modeline-setup-func) +(defvar persp-nil-name) +(defvar phi-replace--mode-line-format) +(defvar phi-search--overlays) +(defvar phi-search--selection) +(defvar phi-search-mode-line-format) +(defvar poke-line-minimum-window-width) +(defvar rcirc-activity) +(defvar sml-modeline-len) +(defvar symbol-overlay-keywords-alist) +(defvar symbol-overlay-temp-symbol) +(defvar text-scale-mode-amount) +(defvar tracking-buffers) +(defvar winum-auto-setup-mode-line) +(defvar xah-fly-insert-state-p) +(defvar display-time-string) + +(declare-function all-the-icons-icon-for-buffer "ext:all-the-icons") +(declare-function anzu--reset-status "ext:anzu") +(declare-function anzu--where-is-here "ext:anzu") +(declare-function async-inject-variables "ext:async") +(declare-function async-start "ext:async") +(declare-function avy-traverse "ext:avy") +(declare-function avy-tree "ext:avy") +(declare-function aw-update "ext:ace-window") +(declare-function aw-window-list "ext:ace-window") +(declare-function battery-format "battery") +(declare-function battery-update "battery") +(declare-function boon-modeline-string "ext:boon") +(declare-function boon-state-string "ext:boon") +(declare-function cider--connection-info "ext:cider") +(declare-function cider-connected-p "ext:cider") +(declare-function cider-current-repl "ext:cider") +(declare-function cider-jack-in "ext:cider") +(declare-function cider-quit "ext:cider") +(declare-function citre-mode "ext:citre-basic-tools") +(declare-function compilation-goto-in-progress-buffer "compile") +(declare-function dap--cur-session "ext:dap-mode") +(declare-function dap--debug-session-name "ext:dap-mode") +(declare-function dap--debug-session-state "ext:dap-mode") +(declare-function dap--session-running "ext:dap-mode") +(declare-function dap-debug-recent "ext:dap-mode") +(declare-function dap-disconnect "ext:dap-mode") +(declare-function dap-hydra "ext:dap-hydra") +(declare-function edebug-help "edebug") +(declare-function edebug-next-mode "edebug") +(declare-function edebug-stop "edebug") +(declare-function eglot "ext:eglot") +(declare-function eglot--major-modes "ext:eglot" t t) +(declare-function eglot--project-nickname "ext:eglot" t t) +(declare-function eglot-clear-status "ext:eglot") +(declare-function eglot-current-server "ext:eglot") +(declare-function eglot-events-buffer "ext:eglot") +(declare-function eglot-forget-pending-continuations "ext:eglot") +(declare-function eglot-managed-p "ext:glot") +(declare-function eglot-reconnect "ext:eglot") +(declare-function eglot-shutdown "ext:eglot") +(declare-function eglot-stderr-buffer "ext:eglot") +(declare-function erc-switch-to-buffer "erc") +(declare-function erc-track-switch-buffer "erc-track") +(declare-function evil-delimited-arguments "ext:evil-common") +(declare-function evil-emacs-state-p "ext:evil-states" t t) +(declare-function evil-force-normal-state "ext:evil-commands" t t) +(declare-function evil-insert-state-p "ext:evil-states" t t) +(declare-function evil-motion-state-p "ext:evil-states" t t) +(declare-function evil-normal-state-p "ext:evil-states" t t) +(declare-function evil-operator-state-p "ext:evil-states" t t) +(declare-function evil-replace-state-p "ext:evil-states" t t) +(declare-function evil-state-property "ext:evil-common") +(declare-function evil-visual-state-p "ext:evil-states" t t) +(declare-function eyebrowse--get "ext:eyebrowse") +(declare-function face-remap-remove-relative "face-remap") +(declare-function fancy-narrow-active-p "ext:fancy-narrow") +(declare-function flycheck-buffer "ext:flycheck") +(declare-function flycheck-count-errors "ext:flycheck") +(declare-function flycheck-error-level-compilation-level "ext:flycheck") +(declare-function flycheck-list-errors "ext:flycheck") +(declare-function flycheck-next-error "ext:flycheck") +(declare-function flycheck-previous-error "ext:flycheck") +(declare-function flymake--diag-type "ext:flymake" t t) +(declare-function flymake--handle-report "ext:flymake") +(declare-function flymake--lookup-type-property "ext:flymake") +(declare-function flymake--state-diags "ext:flymake" t t) +(declare-function flymake-disabled-backends "ext:flymake") +(declare-function flymake-goto-next-error "ext:flymake") +(declare-function flymake-goto-prev-error "ext:flymake") +(declare-function flymake-reporting-backends "ext:flymake") +(declare-function flymake-running-backends "ext:flymake") +(declare-function flymake-show-buffer-diagnostics "ext:flymake") +(declare-function flymake-show-diagnostics-buffer "ext:flymake") +(declare-function flymake-start "ext:flymake") +(declare-function follow-all-followers "follow") +(declare-function gnus-demon-add-handler "gnus-demon") +(declare-function grip--preview-url "ext:grip-mode") +(declare-function grip-browse-preview "ext:grip-mode") +(declare-function grip-restart-preview "ext:grip-mode") +(declare-function grip-stop-preview "ext:grip-mode") +(declare-function helm-candidate-number-at-point "ext:helm-core") +(declare-function helm-get-candidate-number "ext:helm-core") +(declare-function iedit-find-current-occurrence-overlay "ext:iedit-lib") +(declare-function iedit-prev-occurrence "ext:iedit-lib") +(declare-function image-get-display-property "image-mode") +(declare-function jsonrpc--request-continuations "ext:jsonrpc" t t) +(declare-function jsonrpc-last-error "ext:jsonrpc" t t) +(declare-function lsp--workspace-print "ext:lsp-mode") +(declare-function lsp-describe-session "ext:lsp-mode") +(declare-function lsp-workspace-folders-open "ext:lsp-mode") +(declare-function lsp-workspace-restart "ext:lsp-mode") +(declare-function lsp-workspace-shutdown "ext:lsp-mode") +(declare-function lsp-workspaces "ext:lsp-mode") +(declare-function lv-message "ext:lv") +(declare-function mc/num-cursors "ext:multiple-cursors-core") +(declare-function minions--prominent-modes "ext:minions") +(declare-function mlscroll-mode-line "ext:mlscroll") +(declare-function mu4e-alert-default-mode-line-formatter "ext:mu4e-alert") +(declare-function mu4e-alert-enable-mode-line-display "ext:mu4e-alert") +(declare-function nyan-create "ext:nyan-mode") +(declare-function org-edit-src-save "ext:org-src") +(declare-function parrot-create "ext:parrot") +(declare-function pdf-cache-number-of-pages "ext:pdf-cache" t t) +(declare-function persp-add-buffer "ext:persp-mode") +(declare-function persp-contain-buffer-p "ext:persp-mode") +(declare-function persp-switch "ext:persp-mode") +(declare-function phi-search--initialize "ext:phi-search") +(declare-function poke-line-create "ext:poke-line") +(declare-function popup-create "ext:popup") +(declare-function popup-delete "ext:popup") +(declare-function rcirc-next-active-buffer "rcirc") +(declare-function rcirc-short-buffer-name "rcirc") +(declare-function rcirc-switch-to-server-buffer "rcirc") +(declare-function rcirc-window-configuration-change "rcirc") +(declare-function rime--should-enable-p "ext:rime") +(declare-function rime--should-inline-ascii-p "ext:rime") +(declare-function sml-modeline-create "ext:sml-modeline") +(declare-function symbol-overlay-assoc "ext:symbol-overlay") +(declare-function symbol-overlay-get-list "ext:symbol-overlay") +(declare-function symbol-overlay-get-symbol "ext:symbol-overlay") +(declare-function symbol-overlay-rename "ext:symbol-overlay") +(declare-function tab-bar--current-tab "tab-bar") +(declare-function tab-bar--current-tab-index "tab-bar") +(declare-function tracking-next-buffer "ext:tracking") +(declare-function tracking-previous-buffer "ext:tracking") +(declare-function tracking-shorten "ext:tracking") +(declare-function undo-tree-redo-1 "ext:undo-tree") +(declare-function undo-tree-undo-1 "ext:undo-tree") +(declare-function warning-numeric-level "warnings") +(declare-function window-numbering-clear-mode-line "ext:window-numbering") +(declare-function window-numbering-get-number-string "ext:window-numbering") +(declare-function window-numbering-install-mode-line "ext:window-numbering") +(declare-function winum--clear-mode-line "ext:winum") +(declare-function winum--install-mode-line "ext:winum") +(declare-function winum-get-number-string "ext:winum") + + + +;; +;; Buffer information +;; + +(defvar-local doom-modeline--buffer-file-icon nil) +(defun doom-modeline-update-buffer-file-icon (&rest _) + "Update file icon in mode-line." + (setq doom-modeline--buffer-file-icon + (when (and doom-modeline-major-mode-icon + (doom-modeline-icon-displayable-p)) + (let ((icon (all-the-icons-icon-for-buffer))) + (propertize (if (or (null icon) (symbolp icon)) + (doom-modeline-icon 'faicon "file-o" nil nil + :face 'all-the-icons-dsilver + :height 0.9 + :v-adjust 0.0) + (doom-modeline-propertize-icon icon)) + 'help-echo (format "Major-mode: %s" (format-mode-line mode-name)) + 'display '(raise -0.135)))))) +(add-hook 'find-file-hook #'doom-modeline-update-buffer-file-icon) +(add-hook 'after-change-major-mode-hook #'doom-modeline-update-buffer-file-icon) +(add-hook 'clone-indirect-buffer-hook #'doom-modeline-update-buffer-file-icon) + +(doom-modeline-add-variable-watcher + 'doom-modeline-icon + (lambda (_sym val op _where) + (when (eq op 'set) + (setq doom-modeline-icon val) + (dolist (buf (buffer-list)) + (with-current-buffer buf + (doom-modeline-update-buffer-file-icon)))))) + +(defun doom-modeline-buffer-file-state-icon (icon unicode text face) + "Displays an ICON of buffer state with FACE. +UNICODE and TEXT are the alternatives if it is not applicable. +Uses `all-the-icons-material' to fetch the icon." + (doom-modeline-icon 'material icon unicode text + :face face + :height 1.1 + :v-adjust -0.225)) + +(defvar-local doom-modeline--buffer-file-state-icon nil) +(defun doom-modeline-update-buffer-file-state-icon (&rest _) + "Update the buffer or file state in mode-line." + (setq doom-modeline--buffer-file-state-icon + (when doom-modeline-buffer-state-icon + (ignore-errors + (concat + (cond (buffer-read-only + (doom-modeline-buffer-file-state-icon + "lock" "🔒" "%1*" `(:inherit doom-modeline-warning + :weight ,(if doom-modeline-icon + 'normal + 'bold)))) + ((and buffer-file-name (buffer-modified-p) + doom-modeline-buffer-modification-icon) + (doom-modeline-buffer-file-state-icon + "save" "💾" "%1*" `(:inherit doom-modeline-buffer-modified + :weight ,(if doom-modeline-icon + 'normal + 'bold)))) + ((and buffer-file-name + (not (file-remote-p buffer-file-name)) ; Avoid freezing while connection is lost + (not (file-exists-p buffer-file-name))) + (doom-modeline-buffer-file-state-icon + "do_not_disturb_alt" "🚫" "!" 'doom-modeline-urgent)) + (t "")) + (when (or (buffer-narrowed-p) + (and (bound-and-true-p fancy-narrow-mode) + (fancy-narrow-active-p)) + (bound-and-true-p dired-narrow-mode)) + (doom-modeline-buffer-file-state-icon + "vertical_align_center" "↕" "><" 'doom-modeline-warning))))))) + +(defvar-local doom-modeline--buffer-file-name nil) +(defun doom-modeline-update-buffer-file-name (&rest _) + "Update buffer file name in mode-line." + (setq doom-modeline--buffer-file-name + (ignore-errors + (save-match-data + (if buffer-file-name + (doom-modeline-buffer-file-name) + (propertize "%b" + 'face 'doom-modeline-buffer-file + 'mouse-face 'doom-modeline-highlight + 'help-echo "Buffer name +mouse-1: Previous buffer\nmouse-3: Next buffer" + 'local-map mode-line-buffer-identification-keymap)))))) +(add-hook 'find-file-hook #'doom-modeline-update-buffer-file-name) +(add-hook 'after-save-hook #'doom-modeline-update-buffer-file-name) +(add-hook 'clone-indirect-buffer-hook #'doom-modeline-update-buffer-file-name) +(add-hook 'evil-insert-state-exit-hook #'doom-modeline-update-buffer-file-name) +(add-hook 'Info-selection-hook #'doom-modeline-update-buffer-file-name) +(advice-add #'rename-buffer :after #'doom-modeline-update-buffer-file-name) +(advice-add #'set-visited-file-name :after #'doom-modeline-update-buffer-file-name) +(advice-add #'pop-to-buffer :after #'doom-modeline-update-buffer-file-name) +(advice-add #'popup-create :after #'doom-modeline-update-buffer-file-name) +(advice-add #'popup-delete :after #'doom-modeline-update-buffer-file-name) +;; (advice-add #'primitive-undo :after #'doom-modeline-update-buffer-file-name) +;; (advice-add #'set-buffer-modified-p :after #'doom-modeline-update-buffer-file-name) + +(with-no-warnings + (if (boundp 'after-focus-change-function) + (progn + (advice-add #'handle-switch-frame :after #'doom-modeline-update-buffer-file-name) + (add-function :after after-focus-change-function #'doom-modeline-update-buffer-file-name)) + (progn + (add-hook 'focus-in-hook #'doom-modeline-update-buffer-file-name) + (add-hook 'focus-out-hook #'doom-modeline-update-buffer-file-name)))) + +(doom-modeline-add-variable-watcher + 'doom-modeline-buffer-file-name-style + (lambda (_sym val op _where) + (when (eq op 'set) + (setq doom-modeline-buffer-file-name-style val) + (dolist (buf (buffer-list)) + (with-current-buffer buf + (when buffer-file-name + (doom-modeline-update-buffer-file-name))))))) + +(defsubst doom-modeline--buffer-mode-icon () + "The icon of the current major mode." + (when (and doom-modeline-icon doom-modeline-major-mode-icon) + (when-let ((icon (or doom-modeline--buffer-file-icon + (doom-modeline-update-buffer-file-icon)))) + (unless (string-empty-p icon) + (concat + (if doom-modeline-major-mode-color-icon + (doom-modeline-display-icon icon) + (doom-modeline-propertize-icon + icon + (doom-modeline-face))) + (doom-modeline-vspc)))))) + +(defsubst doom-modeline--buffer-state-icon () + "The icon of the current buffer state." + (when doom-modeline-buffer-state-icon + (when-let ((icon (doom-modeline-update-buffer-file-state-icon))) + (unless (string-empty-p icon) + (concat + (doom-modeline-display-icon icon) + (doom-modeline-vspc)))))) + +(defsubst doom-modeline--buffer-simple-name () + "The buffer simple name." + (propertize "%b" + 'face (doom-modeline-face + (if (and doom-modeline-highlight-modified-buffer-name + (buffer-modified-p)) + 'doom-modeline-buffer-modified + 'doom-modeline-buffer-file)) + 'mouse-face 'doom-modeline-highlight + 'help-echo "Buffer name +mouse-1: Previous buffer\nmouse-3: Next buffer" + 'local-map mode-line-buffer-identification-keymap)) + +(defsubst doom-modeline--buffer-name () + "The current buffer name." + (when doom-modeline-buffer-name + (if (and (not (eq doom-modeline-buffer-file-name-style 'file-name)) + doom-modeline--limited-width-p) + ;; Only display the buffer name if the window is small, and doesn't + ;; need to respect file-name style. + (doom-modeline--buffer-simple-name) + (when-let ((name (or doom-modeline--buffer-file-name + (doom-modeline-update-buffer-file-name)))) + ;; Check if the buffer is modified + (if (and doom-modeline-highlight-modified-buffer-name + (buffer-modified-p)) + (propertize name 'face (doom-modeline-face 'doom-modeline-buffer-modified)) + (doom-modeline-display-text name)))))) + +(doom-modeline-def-segment buffer-info + "Combined information about the current buffer. + +Including the current working directory, the file name, and its state (modified, +read-only or non-existent)." + (concat + (doom-modeline-spc) + (doom-modeline--buffer-mode-icon) + (doom-modeline--buffer-state-icon) + (doom-modeline--buffer-name))) + +(doom-modeline-def-segment buffer-info-simple + "Display only the current buffer's name, but with fontification." + (concat + (doom-modeline-spc) + (doom-modeline--buffer-mode-icon) + (doom-modeline--buffer-state-icon) + (doom-modeline--buffer-simple-name))) + +(doom-modeline-def-segment calc + "Display calculator icons and info." + (concat + (doom-modeline-spc) + (when-let ((icon (doom-modeline-icon 'faicon "calculator" nil nil + :height 0.85 :v-adjust -0.05))) + (concat + (doom-modeline-display-icon icon) + (doom-modeline-vspc))) + (doom-modeline--buffer-simple-name))) + +(doom-modeline-def-segment buffer-default-directory + "Displays `default-directory' with the icon and state. + +This is for special buffers like the scratch buffer where knowing the current +project directory is important." + (let ((face (doom-modeline-face + (if (and buffer-file-name (buffer-modified-p)) + 'doom-modeline-buffer-modified + 'doom-modeline-buffer-path)))) + (concat (doom-modeline-spc) + (and doom-modeline-major-mode-icon + (concat (doom-modeline-icon + 'octicon "file-directory" "🖿" "" + :face face :v-adjust -0.05 :height 1.25) + (doom-modeline-vspc))) + (doom-modeline--buffer-state-icon) + (propertize (abbreviate-file-name default-directory) 'face face)))) + +(doom-modeline-def-segment buffer-default-directory-simple + "Displays `default-directory'. + +This is for special buffers like the scratch buffer where knowing the current +project directory is important." + (let ((face (doom-modeline-face 'doom-modeline-buffer-path))) + (concat (doom-modeline-spc) + (and doom-modeline-major-mode-icon + (concat (doom-modeline-icon + 'octicon "file-directory" "🖿" "" + :face face :v-adjust -0.05 :height 1.25) + (doom-modeline-vspc))) + (propertize (abbreviate-file-name default-directory) 'face face)))) + + +;; +;; Encoding +;; + +(doom-modeline-def-segment buffer-encoding + "Displays the eol and the encoding style of the buffer." + (when doom-modeline-buffer-encoding + (let ((mouse-face 'doom-modeline-highlight)) + (concat + (doom-modeline-spc) + + ;; eol type + (let ((eol (coding-system-eol-type buffer-file-coding-system))) + (when (or (eq doom-modeline-buffer-encoding t) + (and (eq doom-modeline-buffer-encoding 'nondefault) + (not (equal eol doom-modeline-default-eol-type)))) + (propertize + (pcase eol + (0 "LF ") + (1 "CRLF ") + (2 "CR ") + (_ "")) + 'face (doom-modeline-face) + 'mouse-face mouse-face + 'help-echo (format "End-of-line style: %s\nmouse-1: Cycle" + (pcase eol + (0 "Unix-style LF") + (1 "DOS-style CRLF") + (2 "Mac-style CR") + (_ "Undecided"))) + 'local-map (let ((map (make-sparse-keymap))) + (define-key map [mode-line mouse-1] 'mode-line-change-eol) + map)))) + + ;; coding system + (let* ((sys (coding-system-plist buffer-file-coding-system)) + (cat (plist-get sys :category)) + (sym (if (memq cat + '(coding-category-undecided coding-category-utf-8)) + 'utf-8 + (plist-get sys :name)))) + (when (or (eq doom-modeline-buffer-encoding t) + (and (eq doom-modeline-buffer-encoding 'nondefault) + (not (eq cat 'coding-category-undecided)) + (not (eq sym doom-modeline-default-coding-system)))) + (propertize + (upcase (symbol-name sym)) + 'face (doom-modeline-face) + 'mouse-face mouse-face + 'help-echo 'mode-line-mule-info-help-echo + 'local-map mode-line-coding-system-map))) + + (doom-modeline-spc))))) + + +;; +;; Indentation +;; + +(doom-modeline-def-segment indent-info + "Displays the indentation information." + (when doom-modeline-indent-info + (let ((do-propertize + (lambda (mode size) + (propertize + (format " %s %d " mode size) + 'face (doom-modeline-face))))) + (if indent-tabs-mode + (funcall do-propertize "TAB" tab-width) + (let ((lookup-var + (seq-find (lambda (var) + (and var (boundp var) (symbol-value var))) + (cdr (assoc major-mode doom-modeline-indent-alist)) nil))) + (funcall do-propertize "SPC" + (if lookup-var + (symbol-value lookup-var) + tab-width))))))) + +;; +;; Remote host +;; + +(doom-modeline-def-segment remote-host + "Hostname for remote buffers." + (when default-directory + (when-let ((host (file-remote-p default-directory 'host))) + (propertize + (concat "@" host) + 'face (doom-modeline-face 'doom-modeline-host))))) + + +;; +;; Major mode +;; + +(doom-modeline-def-segment major-mode + "The major mode, including environment and text-scale info." + (propertize + (concat + (doom-modeline-spc) + (propertize (format-mode-line + (or (and (boundp 'delighted-modes) + (cadr (assq major-mode delighted-modes))) + mode-name)) + 'help-echo "Major mode\n\ + mouse-1: Display major mode menu\n\ + mouse-2: Show help for major mode\n\ + mouse-3: Toggle minor modes" + 'mouse-face 'doom-modeline-highlight + 'local-map mode-line-major-mode-keymap) + (when (and doom-modeline-env-version doom-modeline-env--version) + (format "%s%s" (doom-modeline-vspc) doom-modeline-env--version)) + (and (boundp 'text-scale-mode-amount) + (/= text-scale-mode-amount 0) + (format + (if (> text-scale-mode-amount 0) + " (%+d)" + " (%-d)") + text-scale-mode-amount)) + (doom-modeline-spc)) + 'face (doom-modeline-face 'doom-modeline-buffer-major-mode))) + + +;; +;; Process +;; + +(doom-modeline-def-segment process + "The process info." + (doom-modeline-display-text + (format-mode-line mode-line-process))) + + +;; +;; Minor modes +;; + +(doom-modeline-def-segment minor-modes + (when doom-modeline-minor-modes + (let ((face (doom-modeline-face 'doom-modeline-buffer-minor-mode)) + (mouse-face 'doom-modeline-highlight) + (help-echo "Minor mode + mouse-1: Display minor mode menu + mouse-2: Show help for minor mode + mouse-3: Toggle minor modes")) + (if (bound-and-true-p minions-mode) + `((:propertize ("" ,(minions--prominent-modes)) + face ,face + mouse-face ,mouse-face + help-echo ,help-echo + local-map ,mode-line-minor-mode-keymap) + ,(doom-modeline-spc) + (:propertize ("" ,(doom-modeline-icon 'octicon "gear" "⚙" + minions-mode-line-lighter + :face face :v-adjust -0.05)) + mouse-face ,mouse-face + help-echo "Minions +mouse-1: Display minor modes menu" + local-map ,minions-mode-line-minor-modes-map) + ,(doom-modeline-spc)) + `((:propertize ("" minor-mode-alist) + face ,face + mouse-face ,mouse-face + help-echo ,help-echo + local-map ,mode-line-minor-mode-keymap) + ,(doom-modeline-spc)))))) + + +;; +;; VCS +;; + +(defun doom-modeline-vcs-icon (icon &optional unicode text face voffset) + "Displays the vcs ICON with FACE and VOFFSET. + +UNICODE and TEXT are fallbacks. +Uses `all-the-icons-octicon' to fetch the icon." + (doom-modeline-icon 'octicon icon unicode text + :face face :v-adjust (or voffset -0.1))) + +(defvar-local doom-modeline--vcs-icon nil) +(defun doom-modeline-update-vcs-icon (&rest _) + "Update icon of vcs state in mode-line." + (setq doom-modeline--vcs-icon + (when (and vc-mode buffer-file-name) + (let* ((backend (vc-backend buffer-file-name)) + (state (vc-state buffer-file-name backend))) + (cond ((memq state '(edited added)) + (doom-modeline-vcs-icon "git-compare" "🔃" "*" 'doom-modeline-info -0.05)) + ((eq state 'needs-merge) + (doom-modeline-vcs-icon "git-merge" "🔀" "?" 'doom-modeline-info)) + ((eq state 'needs-update) + (doom-modeline-vcs-icon "arrow-down" "⬇" "!" 'doom-modeline-warning)) + ((memq state '(removed conflict unregistered)) + (doom-modeline-vcs-icon "alert" "⚠" "!" 'doom-modeline-urgent)) + (t + (doom-modeline-vcs-icon "git-branch" "" "@" 'doom-modeline-info -0.05))))))) +(add-hook 'find-file-hook #'doom-modeline-update-vcs-icon) +(add-hook 'after-save-hook #'doom-modeline-update-vcs-icon) +(advice-add #'vc-refresh-state :after #'doom-modeline-update-vcs-icon) + +(doom-modeline-add-variable-watcher + 'doom-modeline-icon + (lambda (_sym val op _where) + (when (eq op 'set) + (setq doom-modeline-icon val) + (dolist (buf (buffer-list)) + (with-current-buffer buf + (doom-modeline-update-vcs-icon)))))) + +(doom-modeline-add-variable-watcher + 'doom-modeline-unicode-fallback + (lambda (_sym val op _where) + (when (eq op 'set) + (setq doom-modeline-unicode-fallback val) + (dolist (buf (buffer-list)) + (with-current-buffer buf + (doom-modeline-update-vcs-icon)))))) + +(defvar-local doom-modeline--vcs-text nil) +(defun doom-modeline-update-vcs-text (&rest _) + "Update text of vcs state in mode-line." + (setq doom-modeline--vcs-text + (when (and vc-mode buffer-file-name) + (let* ((backend (vc-backend buffer-file-name)) + (state (vc-state buffer-file-name backend)) + (str (if vc-display-status + (substring vc-mode (+ (if (eq backend 'Hg) 2 3) 2)) + ""))) + (propertize (if (length> str doom-modeline-vcs-max-length) + (concat + (substring str 0 (- doom-modeline-vcs-max-length 3)) + doom-modeline-ellipsis) + str) + 'mouse-face 'doom-modeline-highlight + 'face (cond ((eq state 'needs-update) + 'doom-modeline-warning) + ((memq state '(removed conflict unregistered)) + 'doom-modeline-urgent) + (t 'doom-modeline-info))))))) +(add-hook 'find-file-hook #'doom-modeline-update-vcs-text) +(add-hook 'after-save-hook #'doom-modeline-update-vcs-text) +(advice-add #'vc-refresh-state :after #'doom-modeline-update-vcs-text) + +(doom-modeline-def-segment vcs + "Displays the current branch, colored based on its state." + (when-let ((icon doom-modeline--vcs-icon) + (text doom-modeline--vcs-text)) + (concat + (doom-modeline-spc) + (propertize (concat + (doom-modeline-display-icon icon) + (doom-modeline-vspc) + (doom-modeline-display-text text)) + 'mouse-face 'doom-modeline-highlight + 'help-echo (get-text-property 1 'help-echo vc-mode) + 'local-map (get-text-property 1 'local-map vc-mode)) + (doom-modeline-spc)))) + + +;; +;; Checker +;; + +(defun doom-modeline-checker-icon (icon unicode text face) + "Displays the checker ICON with FACE. + +UNICODE and TEXT are fallbacks. +Uses `all-the-icons-material' to fetch the icon." + (doom-modeline-icon 'material icon unicode text + :face face :height 1.0 :v-adjust -0.225)) + +(defun doom-modeline-checker-text (text &optional face) + "Displays TEXT with FACE." + (propertize text 'face (or face 'mode-line))) + +;; Flycheck + +(defun doom-modeline--flycheck-count-errors () + "Count the number of ERRORS, grouped by level. + +Return an alist, where each ITEM is a cons cell whose `car' is an +error level, and whose `cdr' is the number of errors of that +level." + (let ((info 0) (warning 0) (error 0)) + (mapc + (lambda (item) + (let ((count (cdr item))) + (pcase (flycheck-error-level-compilation-level (car item)) + (0 (cl-incf info count)) + (1 (cl-incf warning count)) + (2 (cl-incf error count))))) + (flycheck-count-errors flycheck-current-errors)) + `((info . ,info) (warning . ,warning) (error . ,error)))) + +(defvar-local doom-modeline--flycheck-icon nil) +(defun doom-modeline-update-flycheck-icon (&optional status) + "Update flycheck icon via STATUS." + (setq doom-modeline--flycheck-icon + (when-let + ((icon + (pcase status + ('finished (if flycheck-current-errors + (let-alist (doom-modeline--flycheck-count-errors) + (doom-modeline-checker-icon + "error_outline" "❗" "!" + (cond ((> .error 0) 'doom-modeline-urgent) + ((> .warning 0) 'doom-modeline-warning) + (t 'doom-modeline-info)))) + (doom-modeline-checker-icon "check" "✔" "-" 'doom-modeline-info))) + ('running (doom-modeline-checker-icon "hourglass_empty" "⏳" "*" 'doom-modeline-debug)) + ('no-checker (doom-modeline-checker-icon "sim_card_alert" "⚠" "-" 'doom-modeline-debug)) + ('errored (doom-modeline-checker-icon "sim_card_alert" "⚠" "-" 'doom-modeline-urgent)) + ('interrupted (doom-modeline-checker-icon "pause_circle_outline" "⏸" "=" 'doom-modeline-debug)) + ('suspicious (doom-modeline-checker-icon "info_outline" "❓" "?" 'doom-modeline-debug)) + (_ nil)))) + (propertize icon + 'help-echo (concat "Flycheck\n" + (pcase status + ('finished "mouse-1: Display minor mode menu +mouse-2: Show help for minor mode") + ('running "Checking...") + ('no-checker "No Checker") + ('errored "Error") + ('interrupted "Interrupted") + ('suspicious "Suspicious"))) + 'mouse-face 'doom-modeline-highlight + 'local-map (let ((map (make-sparse-keymap))) + (define-key map [mode-line down-mouse-1] + flycheck-mode-menu-map) + (define-key map [mode-line mouse-2] + (lambda () + (interactive) + (describe-function 'flycheck-mode))) + map))))) +(add-hook 'flycheck-status-changed-functions #'doom-modeline-update-flycheck-icon) +(add-hook 'flycheck-mode-hook #'doom-modeline-update-flycheck-icon) + +(doom-modeline-add-variable-watcher + 'doom-modeline-icon + (lambda (_sym val op _where) + (when (eq op 'set) + (setq doom-modeline-icon val) + (dolist (buf (buffer-list)) + (with-current-buffer buf + (when (bound-and-true-p flycheck-mode) + (flycheck-buffer))))))) + +(doom-modeline-add-variable-watcher + 'doom-modeline-unicode-fallback + (lambda (_sym val op _where) + (when (eq op 'set) + (setq doom-modeline-unicode-fallback val) + (dolist (buf (buffer-list)) + (with-current-buffer buf + (when (bound-and-true-p flycheck-mode) + (flycheck-buffer))))))) + +(defvar-local doom-modeline--flycheck-text nil) +(defun doom-modeline-update-flycheck-text (&optional status) + "Update flycheck text via STATUS." + (setq doom-modeline--flycheck-text + (when-let + ((text + (pcase status + ('finished (when flycheck-current-errors + (let-alist (doom-modeline--flycheck-count-errors) + (if doom-modeline-checker-simple-format + (doom-modeline-checker-text + (number-to-string (+ .error .warning .info)) + (cond ((> .error 0) 'doom-modeline-urgent) + ((> .warning 0) 'doom-modeline-warning) + (t 'doom-modeline-info))) + (format "%s/%s/%s" + (doom-modeline-checker-text (number-to-string .error) + 'doom-modeline-urgent) + (doom-modeline-checker-text (number-to-string .warning) + 'doom-modeline-warning) + (doom-modeline-checker-text (number-to-string .info) + 'doom-modeline-info)))))) + ;; ('running nil) + ;; ('no-checker nil) + ;; ('errored (doom-modeline-checker-text "Error" 'doom-modeline-urgent)) + ;; ('interrupted (doom-modeline-checker-text "Interrupted" 'doom-modeline-debug)) + ;; ('suspicious (doom-modeline-checker-text "Suspicious" 'doom-modeline-urgent)) + (_ nil)))) + (propertize + text + 'help-echo (pcase status + ('finished + (concat + (when flycheck-current-errors + (let-alist (doom-modeline--flycheck-count-errors) + (format "error: %d, warning: %d, info: %d\n" .error .warning .info))) + "mouse-1: Show all errors +mouse-3: Next error" + (if (doom-modeline-mwheel-available-p) + "\nwheel-up/wheel-down: Previous/next error"))) + ('running "Checking...") + ('no-checker "No Checker") + ('errored "Error") + ('interrupted "Interrupted") + ('suspicious "Suspicious")) + 'mouse-face 'doom-modeline-highlight + 'local-map (let ((map (make-sparse-keymap))) + (define-key map [mode-line mouse-1] + #'flycheck-list-errors) + (define-key map [mode-line mouse-3] + #'flycheck-next-error) + (when (doom-modeline-mwheel-available-p) + (define-key map [mode-line mouse-wheel-down-event] + (lambda (event) + (interactive "e") + (with-selected-window (posn-window (event-start event)) + (flycheck-previous-error 1)))) + (define-key map [mode-line mouse-wheel-up-event] + (lambda (event) + (interactive "e") + (with-selected-window (posn-window (event-start event)) + (flycheck-next-error 1)))) + map)))))) +(add-hook 'flycheck-status-changed-functions #'doom-modeline-update-flycheck-text) +(add-hook 'flycheck-mode-hook #'doom-modeline-update-flycheck-text) + +;; Flymake + +;; Compatibility +;; @see https://github.com/emacs-mirror/emacs/commit/6e100869012da9244679696634cab6b9cac96303. +(with-eval-after-load 'flymake + (unless (boundp 'flymake--state) + (defvaralias 'flymake--state 'flymake--backend-state)) + (unless (fboundp 'flymake--state-diags) + (defalias 'flymake--state-diags 'flymake--backend-state-diags))) + +(defvar-local doom-modeline--flymake-icon nil) +(defun doom-modeline-update-flymake-icon (&rest _) + "Update flymake icon." + (setq flymake--mode-line-format nil) ; remove the lighter of minor mode + (setq doom-modeline--flymake-icon + (let* ((known (hash-table-keys flymake--state)) + (running (flymake-running-backends)) + (disabled (flymake-disabled-backends)) + (reported (flymake-reporting-backends)) + (all-disabled (and disabled (null running))) + (some-waiting (cl-set-difference running reported))) + (when-let + ((icon + (cond + (some-waiting (doom-modeline-checker-icon "hourglass_empty" "⏳" "*" 'doom-modeline-urgent)) + ((null known) (doom-modeline-checker-icon "sim_card_alert" "⚠" "-" 'doom-modeline-debug)) + (all-disabled (doom-modeline-checker-icon "sim_card_alert" "⚠" "-" 'doom-modeline-warning)) + (t (let ((.error 0) + (.warning 0) + (.note 0)) + (progn + (cl-loop + with warning-level = (warning-numeric-level :warning) + with note-level = (warning-numeric-level :debug) + for state being the hash-values of flymake--state + do (cl-loop + with diags = (flymake--state-diags state) + for diag in diags do + (let ((severity (flymake--lookup-type-property (flymake--diag-type diag) 'severity + (warning-numeric-level :error)))) + (cond ((> severity warning-level) (cl-incf .error)) + ((> severity note-level) (cl-incf .warning)) + (t (cl-incf .note)))))) + (if (> (+ .error .warning .note) 0) + (doom-modeline-checker-icon "error_outline" "❗" "!" + (cond ((> .error 0) 'doom-modeline-urgent) + ((> .warning 0) 'doom-modeline-warning) + (t 'doom-modeline-info))) + (doom-modeline-checker-icon "check" "✔" "-" 'doom-modeline-info)))))))) + (propertize + icon + 'help-echo (concat "Flymake\n" + (cond + (some-waiting "Checking...") + ((null known) "No Checker") + (all-disabled "All Checkers Disabled") + (t (format "%d/%d backends running +mouse-1: Display minor mode menu +mouse-2: Show help for minor mode" + (length running) (length known))))) + 'mouse-face 'doom-modeline-highlight + 'local-map (let ((map (make-sparse-keymap))) + (define-key map [mode-line down-mouse-1] + flymake-menu) + (define-key map [mode-line mouse-2] + (lambda () + (interactive) + (describe-function 'flymake-mode))) + map)))))) +(advice-add #'flymake--handle-report :after #'doom-modeline-update-flymake-icon) + +(doom-modeline-add-variable-watcher + 'doom-modeline-icon + (lambda (_sym val op _where) + (when (eq op 'set) + (setq doom-modeline-icon val) + (dolist (buf (buffer-list)) + (with-current-buffer buf + (when (bound-and-true-p flymake-mode) + (flymake-start))))))) + +(doom-modeline-add-variable-watcher + 'doom-modeline-unicode-fallback + (lambda (_sym val op _where) + (when (eq op 'set) + (setq doom-modeline-unicode-fallback val) + (dolist (buf (buffer-list)) + (with-current-buffer buf + (when (bound-and-true-p flymake-mode) + (flymake-start))))))) + +(defvar-local doom-modeline--flymake-text nil) +(defun doom-modeline-update-flymake-text (&rest _) + "Update flymake text." + (setq flymake--mode-line-format nil) ; remove the lighter of minor mode + (setq doom-modeline--flymake-text + (let* ((known (hash-table-keys flymake--state)) + (running (flymake-running-backends)) + (disabled (flymake-disabled-backends)) + (reported (flymake-reporting-backends)) + (all-disabled (and disabled (null running))) + (some-waiting (cl-set-difference running reported)) + (warning-level (warning-numeric-level :warning)) + (note-level (warning-numeric-level :debug)) + (.error 0) + (.warning 0) + (.note 0)) + (maphash (lambda (_b state) + (cl-loop + with diags = (flymake--state-diags state) + for diag in diags do + (let ((severity (flymake--lookup-type-property (flymake--diag-type diag) 'severity + (warning-numeric-level :error)))) + (cond ((> severity warning-level) (cl-incf .error)) + ((> severity note-level) (cl-incf .warning)) + (t (cl-incf .note)))))) + flymake--state) + (when-let + ((text + (cond + (some-waiting doom-modeline--flymake-text) + ((null known) nil) + (all-disabled nil) + (t (let ((num (+ .error .warning .note))) + (when (> num 0) + (if doom-modeline-checker-simple-format + (doom-modeline-checker-text (number-to-string num) + (cond ((> .error 0) 'doom-modeline-urgent) + ((> .warning 0) 'doom-modeline-warning) + (t 'doom-modeline-info))) + (format "%s/%s/%s" + (doom-modeline-checker-text (number-to-string .error) + 'doom-modeline-urgent) + (doom-modeline-checker-text (number-to-string .warning) + 'doom-modeline-warning) + (doom-modeline-checker-text (number-to-string .note) + 'doom-modeline-info))))))))) + (propertize + text + 'help-echo (cond + (some-waiting "Checking...") + ((null known) "No Checker") + (all-disabled "All Checkers Disabled") + (t (format "error: %d, warning: %d, note: %d +mouse-1: List all problems%s" + .error .warning .note + (if (doom-modeline-mwheel-available-p) + "\nwheel-up/wheel-down: Previous/next problem")))) + 'mouse-face 'doom-modeline-highlight + 'local-map (let ((map (make-sparse-keymap))) + (define-key map [mode-line mouse-1] + #'flymake-show-diagnostics-buffer) + (when (doom-modeline-mwheel-available-p) + (define-key map (vector 'mode-line + mouse-wheel-down-event) + (lambda (event) + (interactive "e") + (with-selected-window (posn-window (event-start event)) + (flymake-goto-prev-error 1 nil t)))) + (define-key map (vector 'mode-line + mouse-wheel-up-event) + (lambda (event) + (interactive "e") + (with-selected-window (posn-window (event-start event)) + (flymake-goto-next-error 1 nil t)))) + map))))))) +(advice-add #'flymake--handle-report :after #'doom-modeline-update-flymake-text) + +(doom-modeline-def-segment checker + "Displays color-coded error status in the current buffer with pretty icons." + (let* ((seg (cond + ((and (bound-and-true-p flymake-mode) + (bound-and-true-p flymake--state)) ; only support 26+ + `(,doom-modeline--flymake-icon . ,doom-modeline--flymake-text)) + ((and (bound-and-true-p flycheck-mode) + (bound-and-true-p flycheck--automatically-enabled-checkers)) + `(,doom-modeline--flycheck-icon . ,doom-modeline--flycheck-text)))) + (icon (car seg)) + (text (cdr seg))) + (concat + (and (or icon text) (doom-modeline-spc)) + (and icon (doom-modeline-display-icon icon)) + (and text + (concat + (and icon (doom-modeline-vspc)) + (doom-modeline-display-text text))) + (and (or icon text) (doom-modeline-spc))))) + + +;; +;; Word Count +;; + +(doom-modeline-def-segment word-count + "The buffer word count. +Displayed when in a major mode in `doom-modeline-continuous-word-count-modes'. +Respects `doom-modeline-enable-word-count'." + (when (and doom-modeline-enable-word-count + (member major-mode doom-modeline-continuous-word-count-modes)) + (propertize (format " %dW" (count-words (point-min) (point-max))) + 'face (doom-modeline-face)))) + + +;; +;; Selection +;; + +(defsubst doom-modeline-column (pos) + "Get the column of the position `POS'." + (save-excursion (goto-char pos) + (current-column))) + +(doom-modeline-def-segment selection-info + "Information about the current selection. + +Such as how many characters and lines are selected, or the NxM dimensions of a +block selection." + (when (and (or mark-active (and (bound-and-true-p evil-local-mode) + (eq evil-state 'visual))) + (doom-modeline--active)) + (cl-destructuring-bind (beg . end) + (if (and (bound-and-true-p evil-local-mode) (eq evil-state 'visual)) + (cons evil-visual-beginning evil-visual-end) + (cons (region-beginning) (region-end))) + (propertize + (let ((lines (count-lines beg (min end (point-max))))) + (concat (doom-modeline-spc) + (cond ((or (bound-and-true-p rectangle-mark-mode) + (and (bound-and-true-p evil-visual-selection) + (eq 'block evil-visual-selection))) + (let ((cols (abs (- (doom-modeline-column end) + (doom-modeline-column beg))))) + (format "%dx%dB" lines cols))) + ((and (bound-and-true-p evil-visual-selection) + (eq evil-visual-selection 'line)) + (format "%dL" lines)) + ((> lines 1) + (format "%dC %dL" (- end beg) lines)) + (t + (format "%dC" (- end beg)))) + (when doom-modeline-enable-word-count + (format " %dW" (count-words beg end))) + (doom-modeline-spc))) + 'face 'doom-modeline-emphasis)))) + + +;; +;; Matches (macro, anzu, evil-substitute, iedit, symbol-overlay and multi-cursors) +;; + +(defsubst doom-modeline--macro-recording () + "Display current Emacs or evil macro being recorded." + (when (and (doom-modeline--active) + (or defining-kbd-macro executing-kbd-macro)) + (let ((sep (propertize " " 'face 'doom-modeline-panel )) + (vsep (propertize " " 'face + '(:inherit (doom-modeline-panel variable-pitch))))) + (concat + sep + (doom-modeline-icon 'material "fiber_manual_record" "●" + (if (bound-and-true-p evil-this-macro) + (char-to-string evil-this-macro) + "Macro") + :face 'doom-modeline-panel + :v-adjust -0.225) + vsep + (doom-modeline-icon 'octicon "triangle-right" "▶" ">" + :face 'doom-modeline-panel + :v-adjust -0.05) + sep)))) + +;; `anzu' and `evil-anzu' expose current/total state that can be displayed in the +;; mode-line. +(defun doom-modeline-fix-anzu-count (positions here) + "Calulate anzu count via POSITIONS and HERE." + (cl-loop for (start . end) in positions + collect t into before + when (and (>= here start) (<= here end)) + return (length before) + finally return 0)) + +(advice-add #'anzu--where-is-here :override #'doom-modeline-fix-anzu-count) + +(setq anzu-cons-mode-line-p nil) ; manage modeline segment ourselves +;; Ensure anzu state is cleared when searches & iedit are done +(with-eval-after-load 'anzu + (add-hook 'isearch-mode-end-hook #'anzu--reset-status t) + (add-hook 'iedit-mode-end-hook #'anzu--reset-status) + (advice-add #'evil-force-normal-state :after #'anzu--reset-status) + ;; Fix matches segment mirroring across all buffers + (mapc #'make-variable-buffer-local + '(anzu--total-matched + anzu--current-position anzu--state anzu--cached-count + anzu--cached-positions anzu--last-command + anzu--last-isearch-string anzu--overflow-p))) + +(defsubst doom-modeline--anzu () + "Show the match index and total number thereof. +Requires `anzu', also `evil-anzu' if using `evil-mode' for compatibility with +`evil-search'." + (when (and (bound-and-true-p anzu--state) + (not (bound-and-true-p iedit-mode))) + (propertize + (let ((here anzu--current-position) + (total anzu--total-matched)) + (cond ((eq anzu--state 'replace-query) + (format " %d replace " anzu--cached-count)) + ((eq anzu--state 'replace) + (format " %d/%d " here total)) + (anzu--overflow-p + (format " %s+ " total)) + (t + (format " %s/%d " here total)))) + 'face (doom-modeline-face 'doom-modeline-panel)))) + +(defsubst doom-modeline--evil-substitute () + "Show number of matches for evil-ex substitutions and highlights in real time." + (when (and (bound-and-true-p evil-local-mode) + (or (assq 'evil-ex-substitute evil-ex-active-highlights-alist) + (assq 'evil-ex-global-match evil-ex-active-highlights-alist) + (assq 'evil-ex-buffer-match evil-ex-active-highlights-alist))) + (propertize + (let ((range (if evil-ex-range + (cons (car evil-ex-range) (cadr evil-ex-range)) + (cons (line-beginning-position) (line-end-position)))) + (pattern (car-safe (evil-delimited-arguments evil-ex-argument 2)))) + (if pattern + (format " %s matches " (how-many pattern (car range) (cdr range))) + " - ")) + 'face (doom-modeline-face 'doom-modeline-panel)))) + +(defun doom-modeline-themes--overlay-sort (a b) + "Sort overlay A and B." + (< (overlay-start a) (overlay-start b))) + +(defsubst doom-modeline--iedit () + "Show the number of iedit regions matches + what match you're on." + (when (and (bound-and-true-p iedit-mode) + (bound-and-true-p iedit-occurrences-overlays)) + (propertize + (let ((this-oc (or (let ((inhibit-message t)) + (iedit-find-current-occurrence-overlay)) + (save-excursion (iedit-prev-occurrence) + (iedit-find-current-occurrence-overlay)))) + (length (length iedit-occurrences-overlays))) + (format " %s/%d " + (if this-oc + (- length + (length (memq this-oc (sort (append iedit-occurrences-overlays nil) + #'doom-modeline-themes--overlay-sort))) + -1) + "-") + length)) + 'face (doom-modeline-face 'doom-modeline-panel)))) + +(defsubst doom-modeline--symbol-overlay () + "Show the number of matches for symbol overlay." + (when (and (doom-modeline--active) + (bound-and-true-p symbol-overlay-keywords-alist) + (not (bound-and-true-p symbol-overlay-temp-symbol)) + (not (bound-and-true-p iedit-mode))) + (let* ((keyword (symbol-overlay-assoc (symbol-overlay-get-symbol t))) + (symbol (car keyword)) + (before (symbol-overlay-get-list -1 symbol)) + (after (symbol-overlay-get-list 1 symbol)) + (count (length before))) + (if (symbol-overlay-assoc symbol) + (propertize + (format (concat " %d/%d " (and (cadr keyword) "in scope ")) + (+ count 1) + (+ count (length after))) + 'face (doom-modeline-face 'doom-modeline-panel)))))) + +(defsubst doom-modeline--multiple-cursors () + "Show the number of multiple cursors." + (cl-destructuring-bind (count . face) + (cond ((bound-and-true-p multiple-cursors-mode) + (cons (mc/num-cursors) + (doom-modeline-face 'doom-modeline-panel))) + ((bound-and-true-p evil-mc-cursor-list) + (cons (length evil-mc-cursor-list) + (doom-modeline-face (if evil-mc-frozen + 'doom-modeline-bar + 'doom-modeline-panel)))) + ((cons nil nil))) + (when count + (concat (propertize " " 'face face) + (or (doom-modeline-icon 'faicon "i-cursor" nil nil + :face face :v-adjust -0.0575) + (propertize "I" + 'face `(:inherit ,face :height 1.4 :weight normal) + 'display '(raise -0.1))) + (propertize (doom-modeline-vspc) + 'face `(:inherit (variable-pitch ,face))) + (propertize (format "%d " count) + 'face face))))) + +(defsubst doom-modeline--phi-search () + "Show the number of matches for `phi-search' and `phi-replace'." + (when (and (doom-modeline--active) + (bound-and-true-p phi-search--overlays)) + (let ((total (length phi-search--overlays)) + (selection phi-search--selection)) + (when selection + (propertize + (format " %d/%d " (1+ selection) total) + 'face (doom-modeline-face 'doom-modeline-panel)))))) + +(defun doom-modeline--override-phi-search (orig-fun &rest args) + "Override the mode-line of `phi-search' and `phi-replace'." + (if (bound-and-true-p doom-modeline-mode) + (apply orig-fun mode-line-format (cdr args)) + (apply orig-fun args))) +(advice-add #'phi-search--initialize :around #'doom-modeline--override-phi-search) + +(defsubst doom-modeline--buffer-size () + "Show buffer size." + (when size-indication-mode + (concat (doom-modeline-spc) + (propertize "%I" + 'face (doom-modeline-face) + 'help-echo "Buffer size +mouse-1: Display Line and Column Mode Menu" + 'mouse-face 'doom-modeline-highlight + 'local-map mode-line-column-line-number-mode-map) + (doom-modeline-spc)))) + +(doom-modeline-def-segment matches + "Displays matches. + +Including: +1. the currently recording macro, 2. A current/total for the +current search term (with `anzu'), 3. The number of substitutions being +conducted with `evil-ex-substitute', and/or 4. The number of active `iedit' +regions, 5. The current/total for the highlight term (with `symbol-overlay'), +6. The number of active `multiple-cursors'." + (let ((meta (concat (doom-modeline--macro-recording) + (doom-modeline--anzu) + (doom-modeline--phi-search) + (doom-modeline--evil-substitute) + (doom-modeline--iedit) + (doom-modeline--symbol-overlay) + (doom-modeline--multiple-cursors)))) + (or (and (not (string-empty-p meta)) meta) + (doom-modeline--buffer-size)))) + +(doom-modeline-def-segment buffer-size + "Display buffer size." + (doom-modeline--buffer-size)) + +;; +;; Media +;; + +(doom-modeline-def-segment media-info + "Metadata regarding the current file, such as dimensions for images." + ;; TODO: Include other information + (cond ((eq major-mode 'image-mode) + (cl-destructuring-bind (width . height) + (when (fboundp 'image-size) + (image-size (image-get-display-property) :pixels)) + (format " %dx%d " width height))))) + + +;; +;; Bars +;; + +(defvar doom-modeline--bar-active nil) +(defvar doom-modeline--bar-inactive nil) + +(defsubst doom-modeline--bar () + "The default bar regulates the height of the mode-line in GUI." + (unless (and doom-modeline--bar-active doom-modeline--bar-inactive) + (let ((width doom-modeline-bar-width) + (height (max doom-modeline-height (doom-modeline--font-height)))) + (setq doom-modeline--bar-active + (doom-modeline--create-bar-image 'doom-modeline-bar width height) + doom-modeline--bar-inactive + (doom-modeline--create-bar-image + 'doom-modeline-bar-inactive width height)))) + (if (doom-modeline--active) + doom-modeline--bar-active + doom-modeline--bar-inactive)) + +(defun doom-modeline-refresh-bars () + "Refresh mode-line bars on next redraw." + (setq doom-modeline--bar-active nil + doom-modeline--bar-inactive nil)) + +(cl-defstruct doom-modeline--hud-cache active inactive top-margin bottom-margin) + +(defsubst doom-modeline--hud () + "Powerline's hud segment reimplemented in the style of Doom's bar segment." + (let* ((ws (window-start)) + (we (window-end)) + (bs (buffer-size)) + (height (max doom-modeline-height (doom-modeline--font-height))) + (top-margin (if (zerop bs) + 0 + (/ (* height (1- ws)) bs))) + (bottom-margin (if (zerop bs) + 0 + (max 0 (/ (* height (- bs we 1)) bs)))) + (cache (or (window-parameter nil 'doom-modeline--hud-cache) + (set-window-parameter + nil + 'doom-modeline--hud-cache + (make-doom-modeline--hud-cache))))) + (unless (and (doom-modeline--hud-cache-active cache) + (doom-modeline--hud-cache-inactive cache) + (= top-margin (doom-modeline--hud-cache-top-margin cache)) + (= bottom-margin + (doom-modeline--hud-cache-bottom-margin cache))) + (setf (doom-modeline--hud-cache-active cache) + (doom-modeline--create-hud-image + 'doom-modeline-bar 'default doom-modeline-bar-width + height top-margin bottom-margin) + (doom-modeline--hud-cache-inactive cache) + (doom-modeline--create-hud-image + 'doom-modeline-bar-inactive 'default doom-modeline-bar-width + height top-margin bottom-margin) + (doom-modeline--hud-cache-top-margin cache) top-margin + (doom-modeline--hud-cache-bottom-margin cache) bottom-margin)) + (if (doom-modeline--active) + (doom-modeline--hud-cache-active cache) + (doom-modeline--hud-cache-inactive cache)))) + +(defun doom-modeline-invalidate-huds () + "Invalidate all cached hud images." + (dolist (frame (frame-list)) + (dolist (window (window-list frame)) + (set-window-parameter window 'doom-modeline--hud-cache nil)))) + +(doom-modeline-add-variable-watcher + 'doom-modeline-height + (lambda (_sym val op _where) + (when (and (eq op 'set) (integerp val)) + (doom-modeline-refresh-bars) + (doom-modeline-invalidate-huds)))) + +(doom-modeline-add-variable-watcher + 'doom-modeline-bar-width + (lambda (_sym val op _where) + (when (and (eq op 'set) (integerp val)) + (doom-modeline-refresh-bars) + (doom-modeline-invalidate-huds)))) + +(doom-modeline-add-variable-watcher + 'doom-modeline-icon + (lambda (_sym _val op _where) + (when (eq op 'set) + (doom-modeline-refresh-bars) + (doom-modeline-invalidate-huds)))) + +(doom-modeline-add-variable-watcher + 'doom-modeline-unicode-fallback + (lambda (_sym _val op _where) + (when (eq op 'set) + (doom-modeline-refresh-bars) + (doom-modeline-invalidate-huds)))) + +(add-hook 'window-configuration-change-hook #'doom-modeline-refresh-bars) +(add-hook 'window-configuration-change-hook #'doom-modeline-invalidate-huds) + +(doom-modeline-def-segment bar + "The bar regulates the height of the `doom-modeline' in GUI." + (if doom-modeline-hud + (doom-modeline--hud) + (doom-modeline--bar))) + +(doom-modeline-def-segment hud + "Powerline's hud segment reimplemented in the style of Doom's bar segment." + (doom-modeline--hud)) + + +;; +;; Window number +;; + +;; HACK: `ace-window-display-mode' should respect the ignore buffers. +(defun doom-modeline-aw-update () + "Update ace-window-path window parameter for all windows. +Ensure all windows are labeled so the user can select a specific +one. The ignored buffers are excluded unless `aw-ignore-on' is nil." + (let ((ignore-window-parameters t)) + (avy-traverse + (avy-tree (aw-window-list) aw-keys) + (lambda (path leaf) + (set-window-parameter + leaf 'ace-window-path + (propertize + (apply #'string (reverse path)) + 'face 'aw-mode-line-face)))))) +(advice-add #'aw-update :override #'doom-modeline-aw-update) + +;; Remove original window number of `ace-window-display-mode'. +(add-hook 'ace-window-display-mode-hook + (lambda () + (setq-default mode-line-format + (assq-delete-all 'ace-window-display-mode + (default-value 'mode-line-format))))) + +(advice-add #'window-numbering-install-mode-line :override #'ignore) +(advice-add #'window-numbering-clear-mode-line :override #'ignore) +(advice-add #'winum--install-mode-line :override #'ignore) +(advice-add #'winum--clear-mode-line :override #'ignore) + +(doom-modeline-def-segment window-number + "The current window number." + (let ((num (cond + ((bound-and-true-p ace-window-display-mode) + (aw-update) + (window-parameter (selected-window) 'ace-window-path)) + ((bound-and-true-p winum-mode) + (setq winum-auto-setup-mode-line nil) + (winum-get-number-string)) + ((bound-and-true-p window-numbering-mode) + (window-numbering-get-number-string)) + (t "")))) + (if (and (length> num 0) + (length> (cl-mapcan + (lambda (frame) + ;; Exclude minibuffer and child frames + (unless (and (fboundp 'frame-parent) + (frame-parent frame)) + (window-list frame 'never))) + (visible-frame-list)) + 1)) + (propertize (format " %s " num) + 'face (doom-modeline-face 'doom-modeline-buffer-major-mode)) + (doom-modeline-spc)))) + + +;; +;; Workspace +;; + +(doom-modeline-def-segment workspace-name + "The current workspace name or number. +Requires `eyebrowse-mode' to be enabled or `tab-bar-mode' tabs to be created." + (when doom-modeline-workspace-name + (when-let + ((name (cond + ((and (bound-and-true-p eyebrowse-mode) + (length> (eyebrowse--get 'window-configs) 1)) + (assq-delete-all 'eyebrowse-mode mode-line-misc-info) + (when-let* + ((num (eyebrowse--get 'current-slot)) + (tag (nth 2 (assoc num (eyebrowse--get 'window-configs))))) + (if (length> tag 0) tag (int-to-string num)))) + ((and (fboundp 'tab-bar-mode) + (length> (frame-parameter nil 'tabs) 1)) + (let* ((current-tab (tab-bar--current-tab)) + (tab-index (tab-bar--current-tab-index)) + (explicit-name (alist-get 'explicit-name current-tab)) + (tab-name (alist-get 'name current-tab))) + (if explicit-name tab-name (+ 1 tab-index))))))) + (propertize (format " %s " name) + 'face (doom-modeline-face 'doom-modeline-buffer-major-mode))))) + + +;; +;; Perspective +;; + +(defvar-local doom-modeline--persp-name nil) +(defun doom-modeline-update-persp-name (&rest _) + "Update perspective name in mode-line." + (setq doom-modeline--persp-name + ;; Support `persp-mode', while not support `perspective' + (when (and doom-modeline-persp-name + (bound-and-true-p persp-mode) + (fboundp 'safe-persp-name) + (fboundp 'get-current-persp)) + (let* ((persp (get-current-persp)) + (name (safe-persp-name persp)) + (face (if (and persp + (not (persp-contain-buffer-p (current-buffer) persp))) + 'doom-modeline-persp-buffer-not-in-persp + 'doom-modeline-persp-name)) + (icon (doom-modeline-icon 'material "folder" "🖿" "#" + :face `(:inherit ,face :slant normal) + :height 1.1 + :v-adjust -0.225))) + (when (or doom-modeline-display-default-persp-name + (not (string-equal persp-nil-name name))) + (concat (doom-modeline-spc) + (propertize (concat (and doom-modeline-persp-icon + (concat icon (doom-modeline-vspc))) + (propertize name 'face face)) + 'help-echo "mouse-1: Switch perspective +mouse-2: Show help for minor mode" + 'mouse-face 'doom-modeline-highlight + 'local-map (let ((map (make-sparse-keymap))) + (define-key map [mode-line mouse-1] + #'persp-switch) + (define-key map [mode-line mouse-2] + (lambda () + (interactive) + (describe-function 'persp-mode))) + map)) + (doom-modeline-spc))))))) + +(add-hook 'buffer-list-update-hook #'doom-modeline-update-persp-name) +(add-hook 'find-file-hook #'doom-modeline-update-persp-name) +(add-hook 'persp-activated-functions #'doom-modeline-update-persp-name) +(add-hook 'persp-renamed-functions #'doom-modeline-update-persp-name) +(advice-add #'lv-message :after #'doom-modeline-update-persp-name) + +(doom-modeline-def-segment persp-name + "The current perspective name." + (when (doom-modeline--segment-visible 'persp-name) + doom-modeline--persp-name)) + + +;; +;; Misc info +;; + +(doom-modeline-def-segment misc-info + "Mode line construct for miscellaneous information. +By default, this shows the information specified by `global-mode-string'." + (when (and (doom-modeline--segment-visible 'misc-info) + (or doom-modeline-display-misc-in-all-mode-lines + (doom-modeline--active))) + (doom-modeline-display-text + (format-mode-line mode-line-misc-info)))) + + +;; +;; Position +;; + +;; Be compatible with Emacs 25. +(defvar doom-modeline-column-zero-based + (if (boundp 'column-number-indicator-zero-based) + column-number-indicator-zero-based + t) + "When non-nil, mode line displays column numbers zero-based. +See `column-number-indicator-zero-based'.") + +(defvar doom-modeline-percent-position + (if (boundp 'mode-line-percent-position) + mode-line-percent-position + '(-3 "%p")) + "Specification of \"percentage offset\" of window through buffer. +See `mode-line-percent-position'.") + +(doom-modeline-add-variable-watcher + 'column-number-indicator-zero-based + (lambda (_sym val op _where) + (when (eq op 'set) + (setq doom-modeline-column-zero-based val)))) + +(doom-modeline-add-variable-watcher + 'mode-line-percent-position + (lambda (_sym val op _where) + (when (eq op 'set) + (setq doom-modeline-percent-position val)))) + +(doom-modeline-def-segment buffer-position + "The buffer position information." + (let ((visible (doom-modeline--segment-visible 'buffer-position)) + (lc '(line-number-mode + (column-number-mode + (doom-modeline-column-zero-based "%l:%c" "%l:%C") + "%l") + (column-number-mode (doom-modeline-column-zero-based ":%c" ":%C")))) + (mouse-face 'doom-modeline-highlight) + (local-map mode-line-column-line-number-mode-map)) + (concat + (doom-modeline-wspc) + + ;; Line and column + (propertize (format-mode-line lc) + 'face (doom-modeline-face) + 'help-echo "Buffer position\n\ +mouse-1: Display Line and Column Mode Menu" + 'mouse-face mouse-face + 'local-map local-map) + + ;; Position + (cond ((and visible + (bound-and-true-p nyan-mode) + (>= (window-width) nyan-minimum-window-width)) + (concat + (doom-modeline-wspc) + (propertize (nyan-create) 'mouse-face mouse-face))) + ((and visible + (bound-and-true-p poke-line-mode) + (>= (window-width) poke-line-minimum-window-width)) + (concat + (doom-modeline-wspc) + (propertize (poke-line-create) 'mouse-face mouse-face))) + ((and visible + (bound-and-true-p mlscroll-mode) + (>= (window-width) mlscroll-minimum-current-width)) + (concat + (doom-modeline-wspc) + (let ((mlscroll-right-align nil)) + (format-mode-line (mlscroll-mode-line))))) + ((and visible + (bound-and-true-p sml-modeline-mode) + (>= (window-width) sml-modeline-len)) + (concat + (doom-modeline-wspc) + (propertize (sml-modeline-create) 'mouse-face mouse-face))) + (t "")) + + ;; Percent position + (when doom-modeline-percent-position + (concat + (doom-modeline-spc) + (propertize (format-mode-line '("" doom-modeline-percent-position "%%")) + 'face (doom-modeline-face) + 'help-echo "Buffer percentage\n\ +mouse-1: Display Line and Column Mode Menu" + 'mouse-face mouse-face + 'local-map local-map))) + + (when (or line-number-mode column-number-mode doom-modeline-percent-position) + (doom-modeline-spc))))) + +;; +;; Party parrot +;; +(doom-modeline-def-segment parrot + "The party parrot animated icon. Requires `parrot-mode' to be enabled." + (when (and (doom-modeline--segment-visible 'parrot) + (bound-and-true-p parrot-mode)) + (concat (doom-modeline-wspc) + (parrot-create) + (doom-modeline-spc)))) + +;; +;; Modals (evil, overwrite, god, ryo and xah-fly-keys, etc.) +;; + +(defun doom-modeline--modal-icon (text face help-echo &optional icon unicode) + "Display the model icon with FACE and HELP-ECHO. +TEXT is alternative if icon is not available." + (propertize (doom-modeline-icon + 'material + (when doom-modeline-modal-icon + (or icon "fiber_manual_record")) + (or unicode "●") + text + :face (doom-modeline-face face) + :v-adjust -0.225) + 'help-echo help-echo)) + +(defsubst doom-modeline--evil () + "The current evil state. Requires `evil-mode' to be enabled." + (when (bound-and-true-p evil-local-mode) + (doom-modeline--modal-icon + (let ((tag (evil-state-property evil-state :tag t))) + (if (stringp tag) tag (funcall tag))) + (cond + ((evil-normal-state-p) 'doom-modeline-evil-normal-state) + ((evil-emacs-state-p) 'doom-modeline-evil-emacs-state) + ((evil-insert-state-p) 'doom-modeline-evil-insert-state) + ((evil-motion-state-p) 'doom-modeline-evil-motion-state) + ((evil-visual-state-p) 'doom-modeline-evil-visual-state) + ((evil-operator-state-p) 'doom-modeline-evil-operator-state) + ((evil-replace-state-p) 'doom-modeline-evil-replace-state) + (t 'doom-modeline-evil-normal-state)) + (evil-state-property evil-state :name t)))) + +(defsubst doom-modeline--overwrite () + "The current overwrite state which is enabled by command `overwrite-mode'." + (when (and (bound-and-true-p overwrite-mode) + (not (bound-and-true-p evil-local-mode))) + (doom-modeline--modal-icon + "" 'doom-modeline-overwrite "Overwrite mode" + "border_color" "🧷"))) + +(defsubst doom-modeline--god () + "The current god state which is enabled by the command `god-mode'." + (when (bound-and-true-p god-local-mode) + (doom-modeline--modal-icon + "" 'doom-modeline-god "God mode" + "account_circle" "🙇"))) + +(defsubst doom-modeline--ryo () + "The current ryo-modal state which is enabled by the command `ryo-modal-mode'." + (when (bound-and-true-p ryo-modal-mode) + (doom-modeline--modal-icon + "" 'doom-modeline-ryo "Ryo modal" + "add_circle" "✪"))) + +(defsubst doom-modeline--xah-fly-keys () + "The current `xah-fly-keys' state." + (when (bound-and-true-p xah-fly-keys) + (if xah-fly-insert-state-p + (doom-modeline--modal-icon + "" 'doom-modeline-fly-insert-state "Xah-fly insert mode" + "flight" "🛧") + (doom-modeline--modal-icon + "" 'doom-modeline-fly-normal-state "Xah-fly command mode" + "flight" "🛧")))) + +(defsubst doom-modeline--boon () + "The current Boon state. Requires `boon-mode' to be enabled." + (when (bound-and-true-p boon-local-mode) + (doom-modeline--modal-icon + (boon-state-string) + (cond + (boon-command-state 'doom-modeline-boon-command-state) + (boon-insert-state 'doom-modeline-boon-insert-state) + (boon-special-state 'doom-modeline-boon-special-state) + (boon-off-state 'doom-modeline-boon-off-state) + (t 'doom-modeline-boon-off-state)) + (boon-modeline-string) + "local_cafe" "🍵"))) + +(defsubst doom-modeline--meow () + "The current Meow state. Requires `meow-mode' to be enabled." + (when (bound-and-true-p meow-mode) + (if (doom-modeline--active) + meow--indicator + (propertize (substring-no-properties meow--indicator) + 'face + 'mode-line-inactive)))) + +(doom-modeline-def-segment modals + "Displays modal editing states. + +Including `evil', `overwrite', `god', `ryo' and `xha-fly-kyes', etc." + (when doom-modeline-modal + (let* ((evil (doom-modeline--evil)) + (ow (doom-modeline--overwrite)) + (god (doom-modeline--god)) + (ryo (doom-modeline--ryo)) + (xf (doom-modeline--xah-fly-keys)) + (boon (doom-modeline--boon)) + (vsep (doom-modeline-vspc)) + (meow (doom-modeline--meow)) + (sep (and (or evil ow god ryo xf boon) (doom-modeline-spc)))) + (concat sep + (and evil (concat evil (and (or ow god ryo xf boon meow) vsep))) + (and ow (concat ow (and (or god ryo xf boon meow) vsep))) + (and god (concat god (and (or ryo xf boon meow) vsep))) + (and ryo (concat ryo (and (or xf boon meow) vsep))) + (and xf (concat xf (and (or boon meow) vsep))) + (and boon (concat boon (and meow vsep))) + meow + sep)))) + +;; +;; Objed state +;; + +(defvar doom-modeline--objed-active nil) + +(defun doom-modeline-update-objed (_ &optional reset) + "Update `objed' status, inactive when RESET is true." + (setq doom-modeline--objed-active (not reset))) + +(setq objed-modeline-setup-func #'doom-modeline-update-objed) + +(doom-modeline-def-segment objed-state () + "The current objed state." + (when (and doom-modeline--objed-active + (doom-modeline--active)) + (propertize (format " %s(%s) " + (symbol-name objed--object) + (char-to-string (aref (symbol-name objed--obj-state) 0))) + 'face 'doom-modeline-evil-emacs-state + 'help-echo (format "Objed object: %s (%s)" + (symbol-name objed--object) + (symbol-name objed--obj-state))))) + + +;; +;; Input method +;; + +(doom-modeline-def-segment input-method + "The current input method." + (propertize (cond (current-input-method + (concat (doom-modeline-spc) + current-input-method-title + (doom-modeline-spc))) + ((and (bound-and-true-p evil-local-mode) + (bound-and-true-p evil-input-method)) + (concat + (doom-modeline-spc) + (nth 3 (assoc default-input-method input-method-alist)) + (doom-modeline-spc))) + (t "")) + 'face (doom-modeline-face + (if (and (bound-and-true-p rime-mode) + (equal current-input-method "rime")) + (if (and (rime--should-enable-p) + (not (rime--should-inline-ascii-p))) + 'doom-modeline-input-method + 'doom-modeline-input-method-alt) + 'doom-modeline-input-method)) + 'help-echo (concat + "Current input method: " + current-input-method + "\n\ +mouse-2: Disable input method\n\ +mouse-3: Describe current input method") + 'mouse-face 'doom-modeline-highlight + 'local-map mode-line-input-method-map)) + + +;; +;; Info +;; + +(doom-modeline-def-segment info-nodes + "The topic and nodes in the Info buffer." + (concat + " (" + ;; topic + (propertize (if (stringp Info-current-file) + (replace-regexp-in-string + "%" "%%" + (file-name-sans-extension + (file-name-nondirectory Info-current-file))) + (format "*%S*" Info-current-file)) + 'face (doom-modeline-face 'doom-modeline-info)) + ") " + ;; node + (when Info-current-node + (propertize (replace-regexp-in-string + "%" "%%" Info-current-node) + 'face (doom-modeline-face 'doom-modeline-buffer-path) + 'help-echo + "mouse-1: scroll forward, mouse-3: scroll back" + 'mouse-face 'doom-modeline-highlight + 'local-map Info-mode-line-node-keymap)))) + + +;; +;; REPL +;; + +(defun doom-modeline-repl-icon (text face) + "Display REPL icon (or TEXT in terminal) with FACE." + (doom-modeline-icon 'faicon "terminal" "$" text + :face face :height 1.0 :v-adjust -0.0575)) + +(defvar doom-modeline--cider nil) + +(defun doom-modeline-update-cider () + "Update cider repl state." + (setq doom-modeline--cider + (let* ((connected (cider-connected-p)) + (face (if connected 'doom-modeline-repl-success 'doom-modeline-repl-warning)) + (repl-buffer (cider-current-repl nil nil)) + (cider-info (when repl-buffer + (cider--connection-info repl-buffer t))) + (icon (doom-modeline-repl-icon "REPL" face))) + (propertize icon + 'help-echo + (if connected + (format "CIDER Connected %s\nmouse-2: CIDER quit" cider-info) + "CIDER Disconnected\nmouse-1: CIDER jack-in") + 'mouse-face 'doom-modeline-highlight + 'local-map (let ((map (make-sparse-keymap))) + (if connected + (define-key map [mode-line mouse-2] + #'cider-quit) + (define-key map [mode-line mouse-1] + #'cider-jack-in)) + map))))) + +(add-hook 'cider-connected-hook #'doom-modeline-update-cider) +(add-hook 'cider-disconnected-hook #'doom-modeline-update-cider) +(add-hook 'cider-mode-hook #'doom-modeline-update-cider) + +(doom-modeline-def-segment repl + "The REPL state." + (when doom-modeline-repl + (when-let (icon (when (bound-and-true-p cider-mode) + doom-modeline--cider)) + (concat + (doom-modeline-spc) + (doom-modeline-display-icon icon) + (doom-modeline-spc))))) + + +;; +;; LSP +;; + +(defun doom-modeline-lsp-icon (text face) + "Display LSP icon (or TEXT in terminal) with FACE." + (doom-modeline-icon 'faicon "rocket" "🚀" text + :face face :height 1.0 :v-adjust -0.0575)) + +(defvar-local doom-modeline--lsp nil) +(defun doom-modeline-update-lsp (&rest _) + "Update `lsp-mode' state." + (setq doom-modeline--lsp + (let* ((workspaces (lsp-workspaces)) + (face (if workspaces 'doom-modeline-lsp-success 'doom-modeline-lsp-warning)) + (icon (doom-modeline-lsp-icon "LSP" face))) + (propertize icon + 'help-echo + (if workspaces + (concat "LSP Connected " + (string-join + (mapcar (lambda (w) + (format "[%s]\n" (lsp--workspace-print w))) + workspaces)) + "C-mouse-1: Switch to another workspace folder +mouse-1: Describe current session +mouse-2: Quit server +mouse-3: Reconnect to server") + "LSP Disconnected +mouse-1: Reload to start server") + 'mouse-face 'doom-modeline-highlight + 'local-map (let ((map (make-sparse-keymap))) + (if workspaces + (progn + (define-key map [mode-line C-mouse-1] + #'lsp-workspace-folders-open) + (define-key map [mode-line mouse-1] + #'lsp-describe-session) + (define-key map [mode-line mouse-2] + #'lsp-workspace-shutdown) + (define-key map [mode-line mouse-3] + #'lsp-workspace-restart)) + (progn + (define-key map [mode-line mouse-1] + (lambda () + (interactive) + (ignore-errors (revert-buffer t t)))))) + map))))) +(add-hook 'lsp-before-initialize-hook #'doom-modeline-update-lsp) +(add-hook 'lsp-after-initialize-hook #'doom-modeline-update-lsp) +(add-hook 'lsp-after-uninitialized-functions #'doom-modeline-update-lsp) +(add-hook 'lsp-before-open-hook #'doom-modeline-update-lsp) +(add-hook 'lsp-after-open-hook #'doom-modeline-update-lsp) + +(defvar-local doom-modeline--eglot nil) +(defun doom-modeline-update-eglot () + "Update `eglot' state." + (setq doom-modeline--eglot + (pcase-let* ((server (and (eglot-managed-p) (eglot-current-server))) + (nick (and server (eglot--project-nickname server))) + (pending (and server (hash-table-count + (jsonrpc--request-continuations server)))) + (last-error (and server (jsonrpc-last-error server))) + (face (cond (last-error 'doom-modeline-lsp-error) + ((and pending (cl-plusp pending)) 'doom-modeline-lsp-warning) + (nick 'doom-modeline-lsp-success) + (t 'doom-modeline-lsp-warning))) + (icon (doom-modeline-lsp-icon "EGLOT" face))) + (propertize icon + 'help-echo (cond + (last-error + (format "EGLOT\nAn error occured: %s +mouse-3: Clear this status" (plist-get last-error :message))) + ((and pending (cl-plusp pending)) + (format "EGLOT\n%d outstanding requests" pending)) + (nick (format "EGLOT Connected (%s/%s) +C-mouse-1: Go to server errors +mouse-1: Go to server events +mouse-2: Quit server +mouse-3: Reconnect to server" nick (eglot--major-modes server))) + (t "EGLOT Disconnected +mouse-1: Start server")) + 'mouse-face 'doom-modeline-highlight + 'local-map (let ((map (make-sparse-keymap))) + (cond (last-error + (define-key map [mode-line mouse-3] + #'eglot-clear-status)) + ((and pending (cl-plusp pending)) + (define-key map [mode-line mouse-3] + #'eglot-forget-pending-continuations)) + (nick + (define-key map [mode-line C-mouse-1] + #'eglot-stderr-buffer) + (define-key map [mode-line mouse-1] + #'eglot-events-buffer) + (define-key map [mode-line mouse-2] + #'eglot-shutdown) + (define-key map [mode-line mouse-3] + #'eglot-reconnect)) + (t (define-key map [mode-line mouse-1] + #'eglot))) + map))))) +(add-hook 'eglot-managed-mode-hook #'doom-modeline-update-eglot) + +(defvar-local doom-modeline--tags nil) +(defun doom-modeline-update-tags () + "Update tags state." + (setq doom-modeline--tags + (propertize + (doom-modeline-lsp-icon "LSP" 'doom-modeline-lsp-success) + 'help-echo "TAGS: Citre mode +mouse-1: Toggle citre mode" + 'mouse-face 'doom-modeline-highlight + 'local-map (make-mode-line-mouse-map 'mouse-1 #'citre-mode)))) +(add-hook 'citre-mode-hook #'doom-modeline-update-tags) + +(defun doom-modeline-update-lsp-icon () + "Update lsp icon." + (cond ((bound-and-true-p lsp-mode) + (doom-modeline-update-lsp)) + ((bound-and-true-p eglot--managed-mode) + (doom-modeline-update-eglot)) + ((bound-and-true-p citre-mode) + (doom-modeline-update-tags)))) + +(doom-modeline-add-variable-watcher + 'doom-modeline-icon + (lambda (_sym val op _where) + (when (eq op 'set) + (setq doom-modeline-icon val) + (dolist (buf (buffer-list)) + (with-current-buffer buf + (doom-modeline-update-lsp-icon)))))) + +(doom-modeline-add-variable-watcher + 'doom-modeline-unicode-fallback + (lambda (_sym val op _where) + (when (eq op 'set) + (setq doom-modeline-unicode-fallback val) + (dolist (buf (buffer-list)) + (with-current-buffer buf + (doom-modeline-update-lsp-icon)))))) + +(doom-modeline-def-segment lsp + "The LSP server state." + (when doom-modeline-lsp + (let ((icon (cond ((bound-and-true-p lsp-mode) + doom-modeline--lsp) + ((bound-and-true-p eglot--managed-mode) + doom-modeline--eglot) + ((bound-and-true-p citre-mode) + doom-modeline--tags)))) + (when icon + (concat + (doom-modeline-spc) + (doom-modeline-display-icon icon) + (doom-modeline-spc)))))) + +(defun doom-modeline-override-eglot () + "Override `eglot' mode-line." + (if (and doom-modeline-lsp + (bound-and-true-p doom-modeline-mode)) + (setq mode-line-misc-info + (delq (assq 'eglot--managed-mode mode-line-misc-info) mode-line-misc-info)) + (add-to-list 'mode-line-misc-info + `(eglot--managed-mode (" [" eglot--mode-line-format "] "))))) +(add-hook 'eglot-managed-mode-hook #'doom-modeline-override-eglot) +(add-hook 'doom-modeline-mode-hook #'doom-modeline-override-eglot) + +(doom-modeline-add-variable-watcher + 'doom-modeline-battery + (lambda (_sym val op _where) + (when (eq op 'set) + (setq doom-modeline-lsp val) + (doom-modeline-override-eglot)))) + + +;; +;; GitHub +;; + +(defvar doom-modeline--github-notification-number 0) +(defvar doom-modeline-before-github-fetch-notification-hook nil + "Hooks before fetching GitHub notifications. +Example: + (add-hook \\='doom-modeline-before-github-fetch-notification-hook + #\\='auth-source-pass-enable)") +(defun doom-modeline--github-fetch-notifications () + "Fetch GitHub notifications." + (when (and doom-modeline-github + (require 'async nil t)) + (async-start + `(lambda () + ,(async-inject-variables + "\\`\\(load-path\\|auth-sources\\|doom-modeline-before-github-fetch-notification-hook\\)\\'") + (run-hooks 'doom-modeline-before-github-fetch-notification-hook) + (when (require 'ghub nil t) + (with-timeout (10) + (ignore-errors + (when-let* ((username (ghub--username ghub-default-host)) + (token (ghub--token ghub-default-host username 'ghub t))) + (ghub-get "/notifications" nil + :query '((notifications . "true")) + :username username + :auth token + :noerror t)))))) + (lambda (result) + (message "") ; suppress message + (setq doom-modeline--github-notification-number (length result)))))) + +(defvar doom-modeline--github-timer nil) +(defun doom-modeline-github-timer () + "Start/Stop the timer for GitHub fetching." + (if (timerp doom-modeline--github-timer) + (cancel-timer doom-modeline--github-timer)) + (setq doom-modeline--github-timer + (and doom-modeline-github + (run-with-idle-timer 30 + doom-modeline-github-interval + #'doom-modeline--github-fetch-notifications)))) + +(doom-modeline-add-variable-watcher + 'doom-modeline-github + (lambda (_sym val op _where) + (when (eq op 'set) + (setq doom-modeline-github val) + (doom-modeline-github-timer)))) + +(doom-modeline-github-timer) + +(doom-modeline-def-segment github + "The GitHub notifications." + (when (and doom-modeline-github + (doom-modeline--segment-visible 'github) + (numberp doom-modeline--github-notification-number) + (> doom-modeline--github-notification-number 0)) + (concat + (doom-modeline-spc) + (propertize + (concat + (doom-modeline-icon 'faicon "github" "🔔" "#" + :face 'doom-modeline-notification + :v-adjust -0.0575) + (doom-modeline-vspc) + ;; GitHub API is paged, and the limit is 50 + (propertize + (if (>= doom-modeline--github-notification-number 50) + "50+" + (number-to-string doom-modeline--github-notification-number)) + 'face '(:inherit + (doom-modeline-unread-number doom-modeline-notification)))) + 'help-echo "Github Notifications +mouse-1: Show notifications +mouse-3: Fetch notifications" + 'mouse-face 'doom-modeline-highlight + 'local-map (let ((map (make-sparse-keymap))) + (define-key map [mode-line mouse-1] + (lambda () + "Open GitHub notifications page." + (interactive) + (run-with-idle-timer 300 nil #'doom-modeline--github-fetch-notifications) + (browse-url "https://github.com/notifications"))) + (define-key map [mode-line mouse-3] + (lambda () + "Fetching GitHub notifications." + (interactive) + (message "Fetching GitHub notifications...") + (doom-modeline--github-fetch-notifications))) + map)) + (doom-modeline-spc)))) + + +;; +;; Debug states +;; + +;; Highlight the doom-modeline while debugging. +(defvar-local doom-modeline--debug-cookie nil) +(defun doom-modeline--debug-visual (&rest _) + "Update the face of mode-line for debugging." + (mapc (lambda (buffer) + (with-current-buffer buffer + (setq doom-modeline--debug-cookie + (face-remap-add-relative 'doom-modeline 'doom-modeline-debug-visual)) + (force-mode-line-update))) + (buffer-list))) + +(defun doom-modeline--normal-visual (&rest _) + "Restore the face of mode-line." + (mapc (lambda (buffer) + (with-current-buffer buffer + (when doom-modeline--debug-cookie + (face-remap-remove-relative doom-modeline--debug-cookie) + (force-mode-line-update)))) + (buffer-list))) + +(add-hook 'dap-session-created-hook #'doom-modeline--debug-visual) +(add-hook 'dap-terminated-hook #'doom-modeline--normal-visual) + +(defun doom-modeline-debug-icon (face &rest args) + "Display debug icon with FACE and ARGS." + (doom-modeline-icon 'faicon "bug" "🐛" "!" :face face :v-adjust -0.0575 args)) + +(defun doom-modeline--debug-dap () + "The current `dap-mode' state." + (when (and (bound-and-true-p dap-mode) + (bound-and-true-p lsp-mode)) + (when-let ((session (dap--cur-session))) + (when (dap--session-running session) + (propertize (doom-modeline-debug-icon 'doom-modeline-info) + 'help-echo (format "DAP (%s - %s) +mouse-1: Display debug hydra +mouse-2: Display recent configurations +mouse-3: Disconnect session" + (dap--debug-session-name session) + (dap--debug-session-state session)) + 'mouse-face 'doom-modeline-highlight + 'local-map (let ((map (make-sparse-keymap))) + (define-key map [mode-line mouse-1] + #'dap-hydra) + (define-key map [mode-line mouse-2] + #'dap-debug-recent) + (define-key map [mode-line mouse-3] + #'dap-disconnect) + map)))))) + +(defvar-local doom-modeline--debug-dap nil) +(defun doom-modeline-update-debug-dap (&rest _) + "Update dap debug state." + (setq doom-modeline--debug-dap (doom-modeline--debug-dap))) + +(add-hook 'dap-session-created-hook #'doom-modeline-update-debug-dap) +(add-hook 'dap-session-changed-hook #'doom-modeline-update-debug-dap) +(add-hook 'dap-terminated-hook #'doom-modeline-update-debug-dap) + +(defsubst doom-modeline--debug-edebug () + "The current `edebug' state." + (when (bound-and-true-p edebug-mode) + (propertize (doom-modeline-debug-icon 'doom-modeline-info) + 'help-echo (format "EDebug (%s) +mouse-1: Show help +mouse-2: Next +mouse-3: Stop debugging" + edebug-execution-mode) + 'mouse-face 'doom-modeline-highlight + 'local-map (let ((map (make-sparse-keymap))) + (define-key map [mode-line mouse-1] + #'edebug-help) + (define-key map [mode-line mouse-2] + #'edebug-next-mode) + (define-key map [mode-line mouse-3] + #'edebug-stop) + map)))) + +(defsubst doom-modeline--debug-on-error () + "The current `debug-on-error' state." + (when debug-on-error + (propertize (doom-modeline-debug-icon 'doom-modeline-urgent) + 'help-echo "Debug on Error +mouse-1: Toggle Debug on Error" + 'mouse-face 'doom-modeline-highlight + 'local-map (make-mode-line-mouse-map 'mouse-1 #'toggle-debug-on-error)))) + +(defsubst doom-modeline--debug-on-quit () + "The current `debug-on-quit' state." + (when debug-on-quit + (propertize (doom-modeline-debug-icon 'doom-modeline-warning) + 'help-echo "Debug on Quit +mouse-1: Toggle Debug on Quit" + 'mouse-face 'doom-modeline-highlight + 'local-map (make-mode-line-mouse-map 'mouse-1 #'toggle-debug-on-quit)))) + +(doom-modeline-def-segment debug + "The current debug state." + (when (doom-modeline--segment-visible 'debug) + (let* ((dap doom-modeline--debug-dap) + (edebug (doom-modeline--debug-edebug)) + (on-error (doom-modeline--debug-on-error)) + (on-quit (doom-modeline--debug-on-quit)) + (vsep (doom-modeline-vspc)) + (sep (and (or dap edebug on-error on-quit) (doom-modeline-spc)))) + (concat sep + (and dap (concat dap (and (or edebug on-error on-quit) vsep))) + (and edebug (concat edebug (and (or on-error on-quit) vsep))) + (and on-error (concat on-error (and on-quit vsep))) + on-quit + sep)))) + + +;; +;; PDF pages +;; + +(defvar-local doom-modeline--pdf-pages nil) +(defun doom-modeline-update-pdf-pages () + "Update PDF pages." + (setq doom-modeline--pdf-pages + (format " P%d/%d " + (or (eval `(pdf-view-current-page)) 0) + (pdf-cache-number-of-pages)))) +(add-hook 'pdf-view-change-page-hook #'doom-modeline-update-pdf-pages) + +(doom-modeline-def-segment pdf-pages + "Display PDF pages." + doom-modeline--pdf-pages) + + +;; +;; `mu4e-alert' notifications +;; + +(doom-modeline-def-segment mu4e + "Show notifications of any unread emails in `mu4e'." + (when (and doom-modeline-mu4e + (doom-modeline--segment-visible 'mu4e) + (bound-and-true-p mu4e-alert-mode-line) + (numberp mu4e-alert-mode-line) + ;; don't display if the unread mails count is zero + (> mu4e-alert-mode-line 0)) + (concat + (doom-modeline-spc) + (propertize + (concat + (doom-modeline-icon 'material "email" "📧" "#" + :face 'doom-modeline-notification + :height 1.1 :v-adjust -0.2) + (doom-modeline-vspc) + (propertize + (if (> mu4e-alert-mode-line doom-modeline-number-limit) + (format "%d+" doom-modeline-number-limit) + (number-to-string mu4e-alert-mode-line)) + 'face '(:inherit + (doom-modeline-unread-number doom-modeline-notification)))) + 'mouse-face 'doom-modeline-highlight + 'keymap '(mode-line keymap + (mouse-1 . mu4e-alert-view-unread-mails) + (mouse-2 . mu4e-alert-view-unread-mails) + (mouse-3 . mu4e-alert-view-unread-mails)) + 'help-echo (concat (if (= mu4e-alert-mode-line 1) + "You have an unread email" + (format "You have %s unread emails" mu4e-alert-mode-line)) + "\nClick here to view " + (if (= mu4e-alert-mode-line 1) "it" "them"))) + (doom-modeline-spc)))) + +(defun doom-modeline-override-mu4e-alert (&rest _) + "Delete `mu4e-alert-mode-line' from global modeline string." + (when (featurep 'mu4e-alert) + (if (and doom-modeline-mu4e + (bound-and-true-p doom-modeline-mode)) + ;; Delete original modeline + (progn + (setq global-mode-string + (delete '(:eval mu4e-alert-mode-line) global-mode-string)) + (setq mu4e-alert-modeline-formatter #'identity)) + ;; Recover default settings + (setq mu4e-alert-modeline-formatter #'mu4e-alert-default-mode-line-formatter)))) +(advice-add #'mu4e-alert-enable-mode-line-display + :after #'doom-modeline-override-mu4e-alert) +(add-hook 'doom-modeline-mode-hook #'doom-modeline-override-mu4e-alert) + +(doom-modeline-add-variable-watcher + 'doom-modeline-mu4e + (lambda (_sym val op _where) + (when (eq op 'set) + (setq doom-modeline-mu4e val) + (doom-modeline-override-mu4e-alert)))) + + +;; +;; `gnus' notifications +;; + +(defvar doom-modeline--gnus-unread-mail 0) +(defvar doom-modeline--gnus-started nil + "Used to determine if gnus has started.") +(defun doom-modeline-update-gnus-status (&rest _) + "Get the total number of unread news of gnus group." + (setq doom-modeline--gnus-unread-mail + (when (and doom-modeline-gnus + doom-modeline--gnus-started) + (let ((total-unread-news-number 0)) + (mapc (lambda (g) + (let* ((group (car g)) + (unread (eval `(gnus-group-unread ,group)))) + (when (and (not (seq-contains-p doom-modeline-gnus-excluded-groups group)) + (numberp unread) + (> unread 0)) + (setq total-unread-news-number (+ total-unread-news-number unread))))) + gnus-newsrc-alist) + total-unread-news-number)))) + +;; Update the modeline after changes have been made +(add-hook 'gnus-group-update-hook #'doom-modeline-update-gnus-status) +(add-hook 'gnus-summary-update-hook #'doom-modeline-update-gnus-status) +(add-hook 'gnus-group-update-group-hook #'doom-modeline-update-gnus-status) +(add-hook 'gnus-after-getting-new-news-hook #'doom-modeline-update-gnus-status) + +;; Only start to listen to gnus when gnus is actually running +(defun doom-modeline-start-gnus-listener () + "Start GNUS listener." + (when (and doom-modeline-gnus + (not doom-modeline--gnus-started)) + (setq doom-modeline--gnus-started t) + ;; Scan gnus in the background if the timer is higher than 0 + (doom-modeline-update-gnus-status) + (if (> doom-modeline-gnus-timer 0) + (gnus-demon-add-handler 'gnus-demon-scan-news doom-modeline-gnus-timer doom-modeline-gnus-idle)))) +(add-hook 'gnus-started-hook #'doom-modeline-start-gnus-listener) + +;; Stop the listener if gnus isn't running +(defun doom-modeline-stop-gnus-listener () + "Stop GNUS listener." + (setq doom-modeline--gnus-started nil)) +(add-hook 'gnus-exit-gnus-hook #'doom-modeline-stop-gnus-listener) + +(doom-modeline-def-segment gnus + "Show notifications of any unread emails in `gnus'." + (when (and (doom-modeline--segment-visible 'gnus) + doom-modeline-gnus + doom-modeline--gnus-started + ;; Don't display if the unread mails count is zero + (numberp doom-modeline--gnus-unread-mail) + (> doom-modeline--gnus-unread-mail 0)) + (concat + (doom-modeline-spc) + (propertize + (concat + (doom-modeline-icon 'material "email" "📧" "#" + :face 'doom-modeline-notification + :height 1.1 :v-adjust -0.2) + (doom-modeline-vspc) + (propertize + (if (> doom-modeline--gnus-unread-mail doom-modeline-number-limit) + (format "%d+" doom-modeline-number-limit) + (number-to-string doom-modeline--gnus-unread-mail)) + 'face '(:inherit + (doom-modeline-unread-number doom-modeline-notification)))) + 'mouse-face 'doom-modeline-highlight + 'help-echo (if (= doom-modeline--gnus-unread-mail 1) + "You have an unread email" + (format "You have %s unread emails" doom-modeline--gnus-unread-mail))) + (doom-modeline-spc)))) + + +;; +;; IRC notifications +;; + +(defun doom-modeline--shorten-irc (name) + "Wrapper for `tracking-shorten' and `erc-track-shorten-function' with NAME. + +One key difference is that when `tracking-shorten' and +`erc-track-shorten-function' returns nil we will instead return the original +value of name. This is necessary in cases where the user has stylized the name +to be an icon and we don't want to remove that so we just return the original." + (or (and (boundp 'tracking-shorten) + (car (tracking-shorten (list name)))) + (and (boundp 'erc-track-shorten-function) + (functionp erc-track-shorten-function) + (car (funcall erc-track-shorten-function (list name)))) + (and (boundp 'rcirc-short-buffer-name) + (rcirc-short-buffer-name name)) + name)) + +(defun doom-modeline--tracking-buffers (buffers) + "Logic to convert some irc BUFFERS to their font-awesome icon." + (mapconcat + (lambda (b) + (propertize + (doom-modeline--shorten-irc (funcall doom-modeline-irc-stylize b)) + 'face '(:inherit (doom-modeline-unread-number doom-modeline-notification)) + 'help-echo (format "IRC Notification: %s\nmouse-1: Switch to buffer" b) + 'mouse-face 'doom-modeline-highlight + 'local-map (make-mode-line-mouse-map + 'mouse-1 + (lambda () + (interactive) + (when (buffer-live-p (get-buffer b)) + (switch-to-buffer b)))))) + buffers + (doom-modeline-vspc))) + +(defun doom-modeline--circe-p () + "Check if `circe' is in use." + (boundp 'tracking-mode-line-buffers)) + +(defun doom-modeline--erc-p () + "Check if `erc' is in use." + (boundp 'erc-modified-channels-alist)) + +(defun doom-modeline--rcirc-p () + "Check if `rcirc' is in use." + (bound-and-true-p rcirc-track-minor-mode)) + +(defun doom-modeline--get-buffers () + "Gets the buffers that have activity." + (cond + ((doom-modeline--circe-p) + tracking-buffers) + ((doom-modeline--erc-p) + (mapcar (lambda (l) + (buffer-name (car l))) + erc-modified-channels-alist)) + ((doom-modeline--rcirc-p) + (mapcar (lambda (b) + (buffer-name b)) + rcirc-activity)))) + +;; Create a modeline segment that contains all the irc tracked buffers +(doom-modeline-def-segment irc-buffers + "The list of shortened, unread irc buffers." + (when (and doom-modeline-irc + (doom-modeline--segment-visible 'irc-buffers)) + (let* ((buffers (doom-modeline--get-buffers)) + (number (length buffers))) + (when (> number 0) + (concat + (doom-modeline-spc) + (doom-modeline--tracking-buffers buffers) + (doom-modeline-spc)))))) + +(doom-modeline-def-segment irc + "A notification icon for any unread irc buffer." + (when (and doom-modeline-irc + (doom-modeline--segment-visible 'irc)) + (let* ((buffers (doom-modeline--get-buffers)) + (number (length buffers))) + (when (> number 0) + (concat + (doom-modeline-spc) + + (propertize (concat + (doom-modeline-icon 'material "message" "🗊" "#" + :face 'doom-modeline-notification + :height 1.0 :v-adjust -0.225) + (doom-modeline-vspc) + ;; Display the number of unread buffers + (propertize (number-to-string number) + 'face '(:inherit + (doom-modeline-unread-number + doom-modeline-notification)))) + 'help-echo (format "IRC Notifications: %s\n%s" + (mapconcat + (lambda (b) (funcall doom-modeline-irc-stylize b)) + buffers + ", ") + (cond + ((doom-modeline--circe-p) + "mouse-1: Switch to previous unread buffer +mouse-3: Switch to next unread buffer") + ((doom-modeline--erc-p) + "mouse-1: Switch to buffer +mouse-3: Switch to next unread buffer") + ((doom-modeline--rcirc-p) + "mouse-1: Switch to server buffer +mouse-3: Switch to next unread buffer"))) + 'mouse-face 'doom-modeline-highlight + 'local-map (let ((map (make-sparse-keymap))) + (cond + ((doom-modeline--circe-p) + (define-key map [mode-line mouse-1] + #'tracking-previous-buffer) + (define-key map [mode-line mouse-3] + #'tracking-next-buffer)) + ((doom-modeline--erc-p) + (define-key map [mode-line mouse-1] + #'erc-switch-to-buffer) + (define-key map [mode-line mouse-3] + #'erc-track-switch-buffer)) + ((doom-modeline--rcirc-p) + (define-key map [mode-line mouse-1] + #'rcirc-switch-to-server-buffer) + (define-key map [mode-line mouse-3] + #'rcirc-next-active-buffer))) + map)) + + ;; Display the unread irc buffers as well + (when doom-modeline-irc-buffers + (concat (doom-modeline-spc) + (doom-modeline--tracking-buffers buffers))) + + (doom-modeline-spc)))))) + +(defun doom-modeline-override-rcirc () + "Override default `rcirc' mode-line." + (if (and doom-modeline-irc + (bound-and-true-p doom-modeline-mode)) + (setq global-mode-string + (delq 'rcirc-activity-string global-mode-string)) + (when (and rcirc-track-minor-mode + (not (memq 'rcirc-activity-string global-mode-string))) + (setq global-mode-string + (append global-mode-string '(rcirc-activity-string)))))) +(add-hook 'rcirc-track-minor-mode-hook #'doom-modeline-override-rcirc) +(add-hook 'doom-modeline-mode-hook #'doom-modeline-override-rcirc) + +(doom-modeline-add-variable-watcher + 'doom-modeline-irc + (lambda (_sym val op _where) + (when (eq op 'set) + (setq doom-modeline-irc val) + (doom-modeline-override-rcirc)))) + + +;; +;; Battery status +;; + +(defvar doom-modeline--battery-status nil) +(defun doom-modeline-update-battery-status () + "Update battery status." + (setq doom-modeline--battery-status + (when (and doom-modeline-battery + (bound-and-true-p display-battery-mode)) + (let* ((data (and battery-status-function + (functionp battery-status-function) + (funcall battery-status-function))) + (charging? (string-equal "AC" (cdr (assoc ?L data)))) + (percentage (car (read-from-string (or (cdr (assq ?p data)) "ERR")))) + (valid-percentage? (and (numberp percentage) + (>= percentage 0) + (<= percentage battery-mode-line-limit))) + (face (if valid-percentage? + (cond (charging? 'doom-modeline-battery-charging) + ((< percentage battery-load-critical) 'doom-modeline-battery-critical) + ((< percentage 25) 'doom-modeline-battery-warning) + ((< percentage 95) 'doom-modeline-battery-normal) + (t 'doom-modeline-battery-full)) + 'doom-modeline-battery-error)) + (icon (if valid-percentage? + (cond (charging? + (doom-modeline-icon 'alltheicon "battery-charging" "🔋" "+" + :face face :height 1.4 :v-adjust -0.1)) + ((> percentage 95) + (doom-modeline-icon 'faicon "battery-full" "🔋" "-" + :face face :v-adjust -0.0575)) + ((> percentage 70) + (doom-modeline-icon 'faicon "battery-three-quarters" "🔋" "-" + :face face :v-adjust -0.0575)) + ((> percentage 40) + (doom-modeline-icon 'faicon "battery-half" "🔋" "-" + :face face :v-adjust -0.0575)) + ((> percentage battery-load-critical) + (doom-modeline-icon 'faicon "battery-quarter" "🔋" "-" + :face face :v-adjust -0.0575)) + (t (doom-modeline-icon 'faicon "battery-empty" "🔋" "!" + :face face :v-adjust -0.0575))) + (doom-modeline-icon 'faicon "battery-empty" "⚠" "N/A" + :face face :v-adjust -0.0575))) + (text (if valid-percentage? (format "%d%s" percentage "%%") "")) + (help-echo (if (and battery-echo-area-format data valid-percentage?) + (battery-format battery-echo-area-format data) + "Battery status not available"))) + (cons (propertize icon 'help-echo help-echo) + (propertize text 'face face 'help-echo help-echo)))))) + +(doom-modeline-add-variable-watcher + 'doom-modeline-icon + (lambda (_sym val op _where) + (when (eq op 'set) + (setq doom-modeline-icon val) + (doom-modeline-update-battery-status)))) + +(doom-modeline-add-variable-watcher + 'doom-modeline-unicode-fallback + (lambda (_sym val op _where) + (when (eq op 'set) + (setq doom-modeline-unicode-fallback val) + (doom-modeline-update-battery-status)))) + +(doom-modeline-def-segment battery + "Display battery status." + (when (and doom-modeline-battery + (bound-and-true-p display-battery-mode) + (doom-modeline--segment-visible 'battery)) + (concat (doom-modeline-spc) + (concat + (car doom-modeline--battery-status) + (doom-modeline-vspc) + (cdr doom-modeline--battery-status)) + (doom-modeline-spc)))) + +(defun doom-modeline-override-battery () + "Override default battery mode-line." + (if (and doom-modeline-battery + (bound-and-true-p doom-modeline-mode)) + (progn + (advice-add #'battery-update :override #'doom-modeline-update-battery-status) + (setq global-mode-string + (delq 'battery-mode-line-string global-mode-string)) + (and (bound-and-true-p display-battery-mode) (battery-update))) + (progn + (advice-remove #'battery-update #'doom-modeline-update-battery-status) + (when (and display-battery-mode battery-status-function battery-mode-line-format + (not (memq 'battery-mode-line-string global-mode-string))) + (setq global-mode-string + (append global-mode-string '(battery-mode-line-string))))))) +(add-hook 'display-battery-mode-hook #'doom-modeline-override-battery) +(add-hook 'doom-modeline-mode-hook #'doom-modeline-override-battery) + +(doom-modeline-add-variable-watcher + 'doom-modeline-battery + (lambda (_sym val op _where) + (when (eq op 'set) + (setq doom-modeline-battery val) + (doom-modeline-override-battery)))) + + +;; +;; Package information +;; + +(doom-modeline-def-segment package + "Show package information via `paradox'." + (concat + (doom-modeline-display-text + (format-mode-line 'mode-line-front-space)) + + (when (and doom-modeline-icon doom-modeline-major-mode-icon) + (concat + (doom-modeline-spc) + (doom-modeline-icon 'faicon "archive" nil nil + :face (doom-modeline-face + (if doom-modeline-major-mode-color-icon + 'all-the-icons-silver + 'mode-line)) + :height 1.0 + :v-adjust -0.0575))) + (doom-modeline-display-text + (format-mode-line 'mode-line-buffer-identification)))) + + +;; +;; Helm +;; + +(defvar doom-modeline--helm-buffer-ids + '(("*helm*" . "HELM") + ("*helm M-x*" . "HELM M-x") + ("*swiper*" . "SWIPER") + ("*Projectile Perspectives*" . "HELM Projectile Perspectives") + ("*Projectile Layouts*" . "HELM Projectile Layouts") + ("*helm-ag*" . (lambda () + (format "HELM Ag: Using %s" + (car (split-string helm-ag-base-command)))))) + "Alist of custom helm buffer names to use. +The cdr can also be a function that returns a name to use.") + +(doom-modeline-def-segment helm-buffer-id + "Helm session identifier." + (when (bound-and-true-p helm-alive-p) + (concat + (doom-modeline-spc) + (when doom-modeline-icon + (concat + (doom-modeline-icon 'fileicon "elisp" nil nil + :face (doom-modeline-face + (and doom-modeline-major-mode-color-icon + 'all-the-icons-blue)) + :height 1.0 + :v-adjust -0.15) + (doom-modeline-spc))) + (propertize + (let ((custom (cdr (assoc (buffer-name) doom-modeline--helm-buffer-ids))) + (case-fold-search t) + (name (replace-regexp-in-string "-" " " (buffer-name)))) + (cond ((stringp custom) custom) + ((functionp custom) (funcall custom)) + (t + (string-match "\\*helm:? \\(mode \\)?\\([^\\*]+\\)\\*" name) + (concat "HELM " (capitalize (match-string 2 name)))))) + 'face (doom-modeline-face 'doom-modeline-buffer-file)) + (doom-modeline-spc)))) + +(doom-modeline-def-segment helm-number + "Number of helm candidates." + (when (bound-and-true-p helm-alive-p) + (concat + (propertize (format " %d/%d" + (helm-candidate-number-at-point) + (helm-get-candidate-number t)) + 'face (doom-modeline-face 'doom-modeline-buffer-path)) + (propertize (format " (%d total) " (helm-get-candidate-number)) + 'face (doom-modeline-face 'doom-modeline-info))))) + +(doom-modeline-def-segment helm-help + "Helm keybindings help." + (when (bound-and-true-p helm-alive-p) + (mapcar + (lambda (s) + (if (string-prefix-p "\\<" s) + (propertize (substitute-command-keys s) + 'face (doom-modeline-face + 'doom-modeline-buffer-file)) + s)) + '("\\\\[helm-help]" "(help) " + "\\\\[helm-select-action]" "(actions) " + "\\\\[helm-maybe-exit-minibuffer]/F1/F2..." "(action) ")))) + +(doom-modeline-def-segment helm-prefix-argument + "Helm prefix argument." + (when (and (bound-and-true-p helm-alive-p) + helm--mode-line-display-prefarg) + (let ((arg (prefix-numeric-value (or prefix-arg current-prefix-arg)))) + (unless (= arg 1) + (propertize (format "C-u %s" arg) + 'face (doom-modeline-face 'doom-modeline-info)))))) + +(defvar doom-modeline--helm-current-source nil + "The currently active helm source.") +(doom-modeline-def-segment helm-follow + "Helm follow indicator." + (and (bound-and-true-p helm-alive-p) + doom-modeline--helm-current-source + (eq 1 (cdr (assq 'follow doom-modeline--helm-current-source))) + "HF")) + +;; +;; Git timemachine +;; + +(doom-modeline-def-segment git-timemachine + (concat + (doom-modeline-spc) + (doom-modeline--buffer-mode-icon) + (doom-modeline--buffer-state-icon) + (propertize + "*%b*" + 'face (doom-modeline-face 'doom-modeline-buffer-timemachine)))) + +;; +;; Markdown/Org preview +;; + +(doom-modeline-def-segment grip + (when (bound-and-true-p grip-mode) + (concat + (doom-modeline-spc) + (let ((face (doom-modeline-face + (if grip--process + (pcase (process-status grip--process) + ('run 'doom-modeline-buffer-path) + ('exit 'doom-modeline-warning) + (_ 'doom-modeline-urgent)) + 'doom-modeline-urgent)))) + (propertize (doom-modeline-icon 'material "pageview" "🗐" "@" + :face (if doom-modeline-icon + `(:inherit ,face :weight normal) + face) + :height 1.2 :v-adjust -0.2) + 'help-echo (format "Preview on %s +mouse-1: Preview in browser +mouse-2: Stop preview +mouse-3: Restart preview" + (grip--preview-url)) + 'mouse-face 'doom-modeline-highlight + 'local-map (let ((map (make-sparse-keymap))) + (define-key map [mode-line mouse-1] + #'grip-browse-preview) + (define-key map [mode-line mouse-2] + #'grip-stop-preview) + (define-key map [mode-line mouse-3] + #'grip-restart-preview) + map))) + (doom-modeline-spc)))) + +;; +;; Follow mode +;; + +(doom-modeline-def-segment follow + (when (bound-and-true-p follow-mode) + (let* ((windows (follow-all-followers)) + (nwindows (length windows)) + (nfollowing (- (length (memq (selected-window) windows)) 1))) + (concat + (doom-modeline-spc) + (propertize (format "Follow %d/%d" (- nwindows nfollowing) nwindows) + 'face 'doom-modeline-buffer-minor-mode))))) + +;; +;; Display time +;; + +(doom-modeline-def-segment time + (when (and doom-modeline-time + (bound-and-true-p display-time-mode) + (doom-modeline--segment-visible 'time)) + (concat + (doom-modeline-spc) + (when doom-modeline-time-icon + (concat + (doom-modeline-icon 'octicon "calendar" "📅" "" + :face 'doom-modeline-time + :v-adjust -0.05) + (and (or doom-modeline-icon doom-modeline-unicode-fallback) + (doom-modeline-spc)))) + (propertize display-time-string + 'face (doom-modeline-face 'doom-modeline-time))))) + +(defun doom-modeline-override-time () + "Override default display-time mode-line." + (or global-mode-string (setq global-mode-string '(""))) + (if (and doom-modeline-time + (bound-and-true-p doom-modeline-mode)) + (setq global-mode-string (delq 'display-time-string global-mode-string)) + (setq global-mode-string (append global-mode-string '(display-time-string))))) +(add-hook 'display-time-mode-hook #'doom-modeline-override-time) +(add-hook 'doom-modeline-mode-hook #'doom-modeline-override-time) + +(doom-modeline-add-variable-watcher + 'doom-modeline-time + (lambda (_sym val op _where) + (when (eq op 'set) + (setq doom-modeline-time val) + (doom-modeline-override-time)))) + +;; +;; Compilation +;; + +(doom-modeline-def-segment compilation + (and (bound-and-true-p compilation-in-progress) + (propertize "[Compiling] " + 'face (doom-modeline-face 'doom-modeline-compilation) + 'help-echo "Compiling; mouse-2: Goto Buffer" + 'mouse-face 'doom-modeline-highlight + 'local-map + (make-mode-line-mouse-map + 'mouse-2 + #'compilation-goto-in-progress-buffer)))) + +(provide 'doom-modeline-segments) + +;;; doom-modeline-segments.el ends here diff --git a/org/elpa/doom-modeline-20230406.623/doom-modeline.el b/org/elpa/doom-modeline-20230406.623/doom-modeline.el new file mode 100644 index 0000000..a40cab8 --- /dev/null +++ b/org/elpa/doom-modeline-20230406.623/doom-modeline.el @@ -0,0 +1,249 @@ +;;; doom-modeline.el --- A minimal and modern mode-line -*- lexical-binding: t; -*- + +;; Copyright (C) 2018-2020 Vincent Zhang + +;; Author: Vincent Zhang +;; Homepage: https://github.com/seagle0128/doom-modeline +;; Version: 3.3.3 +;; Package-Requires: ((emacs "25.1") (compat "28.1.1.1") (shrink-path "0.2.0")) +;; Keywords: faces mode-line + +;; This file is not part of GNU Emacs. + +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . +;; + +;;; Commentary: +;; +;; This package offers a fancy and fast mode-line inspired by minimalism design. +;; +;; It's integrated into Doom Emacs (https://github.com/hlissner/doom-emacs) and +;; Centaur Emacs (https://github.com/seagle0128/.emacs.d). +;; +;; The doom-modeline offers: +;; - A match count panel (for anzu, iedit, multiple-cursors, symbol-overlay, +;; evil-search and evil-substitute) +;; - An indicator for recording a macro +;; - Current environment version (e.g. python, ruby, go, etc.) in the major-mode +;; - A customizable mode-line height (see doom-modeline-height) +;; - A minor modes segment which is compatible with minions +;; - An error/warning count segment for flymake/flycheck +;; - A workspace number segment for eyebrowse +;; - A perspective name segment for persp-mode +;; - A window number segment for winum and window-numbering +;; - An indicator for modal editing state, including evil, overwrite, god, ryo +;; and xah-fly-keys, etc. +;; - An indicator for battery status +;; - An indicator for current input method +;; - An indicator for debug state +;; - An indicator for remote host +;; - An indicator for LSP state with lsp-mode or eglot +;; - An indicator for github notifications +;; - An indicator for unread emails with mu4e-alert +;; - An indicator for unread emails with gnus (basically builtin) +;; - An indicator for irc notifications with circe, rcirc or erc. +;; - An indicator for buffer position which is compatible with nyan-mode or poke-line +;; - An indicator for party parrot +;; - An indicator for PDF page number with pdf-tools +;; - An indicator for markdown/org previews with grip +;; - Truncated file name, file icon, buffer state and project name in buffer +;; information segment, which is compatible with project, find-file-in-project +;; and projectile +;; - New mode-line for Info-mode buffers +;; - New package mode-line for paradox +;; - New mode-line for helm buffers +;; - New mode-line for git-timemachine buffers +;; +;; Installation: +;; From melpa, `M-x package-install RET doom-modeline RET`. +;; In `init.el`, +;; (require 'doom-modeline) +;; (doom-modeline-mode 1) +;; or +;; (use-package doom-modeline +;; :ensure t +;; :hook (after-init . doom-modeline-mode)) +;; + +;;; Code: + +(require 'doom-modeline-core) +(require 'doom-modeline-segments) + + +;; +;; Mode lines +;; + +(doom-modeline-def-modeline 'main + '(bar workspace-name window-number modals matches follow buffer-info remote-host buffer-position word-count parrot selection-info) + '(compilation objed-state misc-info persp-name battery grip irc mu4e gnus github debug repl lsp minor-modes input-method indent-info buffer-encoding major-mode process vcs checker time)) + +(doom-modeline-def-modeline 'minimal + '(bar matches buffer-info-simple) + '(media-info major-mode time)) + +(doom-modeline-def-modeline 'special + '(bar window-number modals matches buffer-info remote-host buffer-position word-count parrot selection-info) + '(compilation objed-state misc-info battery irc-buffers debug minor-modes input-method indent-info buffer-encoding major-mode process time)) + +(doom-modeline-def-modeline 'project + '(bar window-number modals buffer-default-directory remote-host buffer-position) + '(compilation misc-info battery irc mu4e gnus github debug minor-modes input-method major-mode process time)) + +(doom-modeline-def-modeline 'dashboard + '(bar window-number buffer-default-directory-simple remote-host) + '(compilation misc-info battery irc mu4e gnus github debug minor-modes input-method major-mode process time)) + +(doom-modeline-def-modeline 'vcs + '(bar window-number modals matches buffer-info remote-host buffer-position parrot selection-info) + '(compilation misc-info battery irc mu4e gnus github debug minor-modes buffer-encoding major-mode process time)) + +(doom-modeline-def-modeline 'package + '(bar window-number package) + '(compilation misc-info major-mode process time)) + +(doom-modeline-def-modeline 'info + '(bar window-number buffer-info info-nodes buffer-position parrot selection-info) + '(compilation misc-info buffer-encoding major-mode time)) + +(doom-modeline-def-modeline 'media + '(bar window-number buffer-size buffer-info) + '(compilation misc-info media-info major-mode process vcs time)) + +(doom-modeline-def-modeline 'message + '(bar window-number modals matches buffer-info-simple buffer-position word-count parrot selection-info) + '(compilation objed-state misc-info battery debug minor-modes input-method indent-info buffer-encoding major-mode time)) + +(doom-modeline-def-modeline 'pdf + '(bar window-number matches buffer-info pdf-pages) + '(compilation misc-info major-mode process vcs time)) + +(doom-modeline-def-modeline 'org-src + '(bar window-number modals matches buffer-info buffer-position word-count parrot selection-info) + '(compilation objed-state misc-info debug lsp minor-modes input-method indent-info buffer-encoding major-mode process checker time)) + +(doom-modeline-def-modeline 'helm + '(bar helm-buffer-id helm-number helm-follow helm-prefix-argument) + '(helm-help time)) + +(doom-modeline-def-modeline 'timemachine + '(bar window-number modals matches git-timemachine buffer-position word-count parrot selection-info) + '(misc-info minor-modes indent-info buffer-encoding major-mode time)) + +(doom-modeline-def-modeline 'calculator + '(window-number modals matches calc buffer-position) + '(misc-info minor-modes major-mode process)) + + +;; +;; Interfaces +;; + +;;;###autoload +(defun doom-modeline-set-main-modeline (&optional default) + "Set main mode-line. +If DEFAULT is non-nil, set the default mode-line for all buffers." + (doom-modeline-set-modeline 'main default)) + + +;; +;; Minor mode +;; + +;; Suppress warnings +(defvar 2C-mode-line-format) +(defvar helm-ag-show-status-function) +(declare-function helm-display-mode-line "ext:helm-core") + +(defvar doom-modeline-mode-map (make-sparse-keymap)) + +(defvar doom-modeline-mode-alist + '((message-mode . message) + (git-commit-mode . message) + (magit-mode . vcs) + (dashboard-mode . dashboard) + (Info-mode . info) + (image-mode . media) + (pdf-view-mode . pdf) + (org-src-mode . org-src) + (paradox-menu-mode . package) + (xwidget-webkit-mode . minimal) + (git-timemachine-mode . timemachine) + (calc-mode . calculator) + (calc-trail-mode . calculator) + (circe-mode . special) + (erc-mode . special) + (rcirc-mode . special)) + "Alist of major modes and mode-lines.") + +(defun doom-modeline-auto-set-modeline () + "Set mode-line base on major-mode." + (catch 'found + (dolist (x doom-modeline-mode-alist) + (when (derived-mode-p (car x)) + (doom-modeline-set-modeline (cdr x)) + (throw 'found x))))) + +(defun doom-modeline-set-helm-modeline (&rest _) ; To advice helm + "Set helm mode-line." + (doom-modeline-set-modeline 'helm)) + +;;;###autoload +(define-minor-mode doom-modeline-mode + "Toggle `doom-modeline' on or off." + :group 'doom-modeline + :global t + :lighter nil + :keymap doom-modeline-mode-map + (if doom-modeline-mode + (progn + (doom-modeline-refresh-bars) ; Create bars + (doom-modeline-set-main-modeline t) ; Set default mode-line + + ;; Apply to all existing buffers. + (dolist (buf (buffer-list)) + (with-current-buffer buf + (unless (doom-modeline-auto-set-modeline) + (doom-modeline-set-main-modeline)))) + + ;; For two-column editing + (setq 2C-mode-line-format (doom-modeline 'special)) + + ;; Automatically set mode-lines + (add-hook 'after-change-major-mode-hook #'doom-modeline-auto-set-modeline) + + ;; Special handles + (advice-add #'helm-display-mode-line :after #'doom-modeline-set-helm-modeline) + (setq helm-ag-show-status-function #'doom-modeline-set-helm-modeline)) + (progn + ;; Restore mode-line + (let ((original-format (doom-modeline--original-value 'mode-line-format))) + (setq-default mode-line-format original-format) + (dolist (buf (buffer-list)) + (with-current-buffer buf + (setq mode-line-format original-format)))) + + ;; For two-column editing + (setq 2C-mode-line-format (doom-modeline--original-value '2C-mode-line-format)) + + ;; Cleanup + (remove-hook 'after-change-major-mode-hook #'doom-modeline-auto-set-modeline) + (advice-remove #'helm-display-mode-line #'doom-modeline-set-helm-modeline) + (setq helm-ag-show-status-function (default-value 'helm-ag-show-status-function))))) + +(provide 'doom-modeline) + +;;; doom-modeline.el ends here diff --git a/org/elpa/elisp-refs-20230309.1638/elisp-refs-autoloads.el b/org/elpa/elisp-refs-20230309.1638/elisp-refs-autoloads.el new file mode 100644 index 0000000..fa7786a --- /dev/null +++ b/org/elpa/elisp-refs-20230309.1638/elisp-refs-autoloads.el @@ -0,0 +1,68 @@ +;;; elisp-refs-autoloads.el --- automatically extracted autoloads -*- lexical-binding: t -*- +;; +;;; Code: + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + + +;;;### (autoloads nil "elisp-refs" "elisp-refs.el" (0 0 0 0)) +;;; Generated autoloads from elisp-refs.el + +(autoload 'elisp-refs-function "elisp-refs" "\ +Display all the references to function SYMBOL, in all loaded +elisp files. + +If called with a prefix, prompt for a directory to limit the search. + +This searches for functions, not macros. For that, see +`elisp-refs-macro'. + +\(fn SYMBOL &optional PATH-PREFIX)" t nil) + +(autoload 'elisp-refs-macro "elisp-refs" "\ +Display all the references to macro SYMBOL, in all loaded +elisp files. + +If called with a prefix, prompt for a directory to limit the search. + +This searches for macros, not functions. For that, see +`elisp-refs-function'. + +\(fn SYMBOL &optional PATH-PREFIX)" t nil) + +(autoload 'elisp-refs-special "elisp-refs" "\ +Display all the references to special form SYMBOL, in all loaded +elisp files. + +If called with a prefix, prompt for a directory to limit the search. + +\(fn SYMBOL &optional PATH-PREFIX)" t nil) + +(autoload 'elisp-refs-variable "elisp-refs" "\ +Display all the references to variable SYMBOL, in all loaded +elisp files. + +If called with a prefix, prompt for a directory to limit the search. + +\(fn SYMBOL &optional PATH-PREFIX)" t nil) + +(autoload 'elisp-refs-symbol "elisp-refs" "\ +Display all the references to SYMBOL in all loaded elisp files. + +If called with a prefix, prompt for a directory to limit the +search. + +\(fn SYMBOL &optional PATH-PREFIX)" t nil) + +(register-definition-prefixes "elisp-refs" '("elisp-")) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; coding: utf-8 +;; End: +;;; elisp-refs-autoloads.el ends here diff --git a/org/elpa/elisp-refs-20230309.1638/elisp-refs-pkg.el b/org/elpa/elisp-refs-20230309.1638/elisp-refs-pkg.el new file mode 100644 index 0000000..015e399 --- /dev/null +++ b/org/elpa/elisp-refs-20230309.1638/elisp-refs-pkg.el @@ -0,0 +1,2 @@ +;;; Generated package description from elisp-refs.el -*- no-byte-compile: t -*- +(define-package "elisp-refs" "20230309.1638" "find callers of elisp functions or macros" '((dash "2.12.0") (s "1.11.0")) :commit "6973912994ade71a3e13a24425f1cc648d8b94bb" :authors '(("Wilfred Hughes" . "me@wilfred.me.uk")) :maintainer '("Wilfred Hughes" . "me@wilfred.me.uk") :keywords '("lisp")) diff --git a/org/elpa/elisp-refs-20230309.1638/elisp-refs.el b/org/elpa/elisp-refs-20230309.1638/elisp-refs.el new file mode 100644 index 0000000..ea914d7 --- /dev/null +++ b/org/elpa/elisp-refs-20230309.1638/elisp-refs.el @@ -0,0 +1,911 @@ +;;; elisp-refs.el --- find callers of elisp functions or macros -*- lexical-binding: t; -*- + +;; Copyright (C) 2016-2020 Wilfred Hughes + +;; Author: Wilfred Hughes +;; Version: 1.6 +;; Package-Version: 20230309.1638 +;; Package-Commit: 6973912994ade71a3e13a24425f1cc648d8b94bb +;; Keywords: lisp +;; Package-Requires: ((dash "2.12.0") (s "1.11.0")) + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; elisp-refs.el is an Emacs package for finding references to +;; functions, macros or variables. Unlike a dumb text search, +;; elisp-refs.el actually parses the code, so it's never confused by +;; comments or `foo-bar' matching `foo'. +;; +;; See https://github.com/Wilfred/refs.el/blob/master/README.md for +;; more information. + +;;; Code: + +(require 'dash) +(require 's) +(require 'format) +(eval-when-compile (require 'cl-lib)) + +;;; Internal + +(defvar elisp-refs-verbose t) + +(defun elisp-refs--format-int (integer) + "Format INTEGER as a string, with , separating thousands." + (let ((number (abs integer)) + (parts nil)) + (while (> number 999) + (push (format "%03d" (mod number 1000)) + parts) + (setq number (/ number 1000))) + (push (format "%d" number) parts) + (concat + (if (< integer 0) "-" "") + (s-join "," parts)))) + +(defsubst elisp-refs--start-pos (end-pos) + "Find the start position of form ending at END-POS +in the current buffer." + (let ((parse-sexp-ignore-comments t)) + (scan-sexps end-pos -1))) + +(defun elisp-refs--sexp-positions (buffer start-pos end-pos) + "Return a list of start and end positions of all the sexps +between START-POS and END-POS (inclusive) in BUFFER. + +Positions exclude quote characters, so given 'foo or `foo, we +report the position of the symbol foo. + +Not recursive, so we don't consider subelements of nested sexps." + (let ((positions nil)) + (with-current-buffer buffer + (condition-case _err + (catch 'done + (while t + (let* ((sexp-end-pos (let ((parse-sexp-ignore-comments t)) + (scan-sexps start-pos 1)))) + ;; If we've reached a sexp beyond the range requested, + ;; or if there are no sexps left, we're done. + (when (or (null sexp-end-pos) (> sexp-end-pos end-pos)) + (throw 'done nil)) + ;; Otherwise, this sexp is in the range requested. + (push (list (elisp-refs--start-pos sexp-end-pos) sexp-end-pos) + positions) + (setq start-pos sexp-end-pos)))) + ;; Terminate when we see "Containing expression ends prematurely" + (scan-error nil))) + (nreverse positions))) + +(defun elisp-refs--read-buffer-form (symbols-with-pos) + "Read a form from the current buffer, starting at point. +Returns a list: +\(form form-start-pos form-end-pos symbol-positions read-start-pos) + +In Emacs 28 and earlier, SYMBOL-POSITIONS is a list of 0-indexed +symbol positions relative to READ-START-POS, according to +`read-symbol-positions-list'. + +In Emacs 29+, SYMBOL-POSITIONS is nil. If SYMBOLS-WITH-POS is +non-nil, forms are read with `read-positioning-symbols'." + (let* ((read-with-symbol-positions t) + (read-start-pos (point)) + (form (if (and symbols-with-pos (fboundp 'read-positioning-symbols)) + (read-positioning-symbols (current-buffer)) + (read (current-buffer)))) + (symbols (if (boundp 'read-symbol-positions-list) + read-symbol-positions-list + nil)) + (end-pos (point)) + (start-pos (elisp-refs--start-pos end-pos))) + (list form start-pos end-pos symbols read-start-pos))) + +(defvar elisp-refs--path nil + "A buffer-local variable used by `elisp-refs--contents-buffer'. +Internal implementation detail.") + +(defun elisp-refs--read-all-buffer-forms (buffer symbols-with-pos) + "Read all the forms in BUFFER, along with their positions." + (with-current-buffer buffer + (goto-char (point-min)) + (let ((forms nil)) + (condition-case err + (while t + (push (elisp-refs--read-buffer-form symbols-with-pos) forms)) + (error + (if (or (equal (car err) 'end-of-file) + ;; TODO: this shouldn't occur in valid elisp files, + ;; but it's happening in helm-utils.el. + (equal (car err) 'scan-error)) + ;; Reached end of file, we're done. + (nreverse forms) + ;; Some unexpected error, propagate. + (error "Unexpected error whilst reading %s position %s: %s" + (abbreviate-file-name elisp-refs--path) (point) err))))))) + +(defun elisp-refs--proper-list-p (val) + "Is VAL a proper list?" + (if (fboundp 'proper-list-p) + ;; `proper-list-p' was added in Emacs 27.1. + ;; http://git.savannah.gnu.org/cgit/emacs.git/commit/?id=2fde6275b69fd113e78243790bf112bbdd2fe2bf + (with-no-warnings (proper-list-p val)) + ;; Earlier Emacs versions only had format-proper-list-p. + (with-no-warnings (format-proper-list-p val)))) + +(defun elisp-refs--walk (buffer form start-pos end-pos symbol match-p &optional path) + "Walk FORM, a nested list, and return a list of sublists (with +their positions) where MATCH-P returns t. FORM is traversed +depth-first (pre-order traversal, left-to-right). + +MATCH-P is called with three arguments: +\(SYMBOL CURRENT-FORM PATH). + +PATH is the first element of all the enclosing forms of +CURRENT-FORM, innermost first, along with the index of the +current form. + +For example if we are looking at h in (e f (g h)), PATH takes the +value ((g . 1) (e . 2)). + +START-POS and END-POS should be the position of FORM within BUFFER." + (cond + ((funcall match-p symbol form path) + ;; If this form matches, just return it, along with the position. + (list (list form start-pos end-pos))) + ;; Otherwise, recurse on the subforms. + ((consp form) + (let ((matches nil) + ;; Find the positions of the subforms. + (subforms-positions + (if (eq (car-safe form) '\`) + ;; Kludge: `elisp-refs--sexp-positions' excludes the ` when + ;; calculating positions. So, to find the inner + ;; positions when walking from `(...) to (...), we + ;; don't need to increment the start position. + (cons nil (elisp-refs--sexp-positions buffer start-pos end-pos)) + ;; Calculate the positions after the opening paren. + (elisp-refs--sexp-positions buffer (1+ start-pos) end-pos)))) + ;; For each subform, recurse if it's a list, or a matching symbol. + (--each (-zip form subforms-positions) + (-let [(subform subform-start subform-end) it] + (when (or + (and (consp subform) (elisp-refs--proper-list-p subform)) + (and (symbolp subform) (eq subform symbol))) + (-when-let (subform-matches + (elisp-refs--walk + buffer subform + subform-start subform-end + symbol match-p + (cons (cons (car-safe form) it-index) path))) + (push subform-matches matches))))) + + ;; Concat the results from all the subforms. + (apply #'append (nreverse matches)))))) + +;; TODO: condition-case (condition-case ... (error ...)) is not a call +;; TODO: (cl-destructuring-bind (foo &rest bar) ...) is not a call +;; TODO: letf, cl-letf, -let, -let* +(defun elisp-refs--function-p (symbol form path) + "Return t if FORM looks like a function call to SYMBOL." + (cond + ((not (consp form)) + nil) + ;; Ignore (defun _ (SYMBOL ...) ...) + ((or (equal (car path) '(defsubst . 2)) + (equal (car path) '(defun . 2)) + (equal (car path) '(defmacro . 2)) + (equal (car path) '(cl-defun . 2))) + nil) + ;; Ignore (lambda (SYMBOL ...) ...) + ((equal (car path) '(lambda . 1)) + nil) + ;; Ignore (let (SYMBOL ...) ...) + ;; and (let* (SYMBOL ...) ...) + ((or + (equal (car path) '(let . 1)) + (equal (car path) '(let* . 1))) + nil) + ;; Ignore (let ((SYMBOL ...)) ...) + ((or + (equal (cl-second path) '(let . 1)) + (equal (cl-second path) '(let* . 1))) + nil) + ;; Ignore (declare-function NAME (ARGS...)) + ((equal (car path) '(declare-function . 3)) + nil) + ;; (SYMBOL ...) + ((eq (car form) symbol) + t) + ;; (foo ... #'SYMBOL ...) + ((--any-p (equal it (list 'function symbol)) form) + t) + ;; (funcall 'SYMBOL ...) + ((and (eq (car form) 'funcall) + (equal `',symbol (cl-second form))) + t) + ;; (apply 'SYMBOL ...) + ((and (eq (car form) 'apply) + (equal `',symbol (cl-second form))) + t))) + +(defun elisp-refs--macro-p (symbol form path) + "Return t if FORM looks like a macro call to SYMBOL." + (cond + ((not (consp form)) + nil) + ;; Ignore (defun _ (SYMBOL ...) ...) + ((or (equal (car path) '(defsubst . 2)) + (equal (car path) '(defun . 2)) + (equal (car path) '(defmacro . 2))) + nil) + ;; Ignore (lambda (SYMBOL ...) ...) + ((equal (car path) '(lambda . 1)) + nil) + ;; Ignore (let (SYMBOL ...) ...) + ;; and (let* (SYMBOL ...) ...) + ((or + (equal (car path) '(let . 1)) + (equal (car path) '(let* . 1))) + nil) + ;; Ignore (let ((SYMBOL ...)) ...) + ((or + (equal (cl-second path) '(let . 1)) + (equal (cl-second path) '(let* . 1))) + nil) + ;; (SYMBOL ...) + ((eq (car form) symbol) + t))) + +;; Looking for a special form is exactly the same as looking for a +;; macro. +(defalias 'elisp-refs--special-p 'elisp-refs--macro-p) + +(defun elisp-refs--variable-p (symbol form path) + "Return t if this looks like a variable reference to SYMBOL. +We consider parameters to be variables too." + (cond + ((consp form) + nil) + ;; Ignore (defun _ (SYMBOL ...) ...) + ((or (equal (car path) '(defsubst . 1)) + (equal (car path) '(defun . 1)) + (equal (car path) '(defmacro . 1)) + (equal (car path) '(cl-defun . 1))) + nil) + ;; (let (SYMBOL ...) ...) is a variable, not a function call. + ((or + (equal (cl-second path) '(let . 1)) + (equal (cl-second path) '(let* . 1))) + t) + ;; (lambda (SYMBOL ...) ...) is a variable + ((equal (cl-second path) '(lambda . 1)) + t) + ;; (let ((SYMBOL ...)) ...) is also a variable. + ((or + (equal (cl-third path) '(let . 1)) + (equal (cl-third path) '(let* . 1))) + t) + ;; Ignore (SYMBOL ...) otherwise, we assume it's a function/macro + ;; call. + ((equal (car path) (cons symbol 0)) + nil) + ((eq form symbol) + t))) + +;; TODO: benchmark building a list with `push' rather than using +;; mapcat. +(defun elisp-refs--read-and-find (buffer symbol match-p) + "Read all the forms in BUFFER, and return a list of all forms that +contain SYMBOL where MATCH-P returns t. + +For every matching form found, we return the form itself along +with its start and end position." + (-non-nil + (--mapcat + (-let [(form start-pos end-pos symbol-positions _read-start-pos) it] + ;; Optimisation: if we have a list of positions for the current + ;; form (Emacs 28 and earlier), and it doesn't contain the + ;; symbol we're looking for, don't bother walking the form. + (when (or (null symbol-positions) (assq symbol symbol-positions)) + (elisp-refs--walk buffer form start-pos end-pos symbol match-p))) + (elisp-refs--read-all-buffer-forms buffer nil)))) + +(defun elisp-refs--walk-positioned-symbols (forms symbol) + "Given a nested list of FORMS, return a list of all positions of SYMBOL. +Assumes `symbol-with-pos-pos' is defined (Emacs 29+)." + (cond + ((symbol-with-pos-p forms) + (let ((symbols-with-pos-enabled t)) + (if (eq forms symbol) + (list (list symbol + (symbol-with-pos-pos forms) + (+ (symbol-with-pos-pos forms) (length (symbol-name symbol)))))))) + ((elisp-refs--proper-list-p forms) + ;; Proper list, use `--mapcat` to reduce how much we recurse. + (--mapcat (elisp-refs--walk-positioned-symbols it symbol) forms)) + ((consp forms) + ;; Improper list, we have to recurse on head and tail. + (append (elisp-refs--walk-positioned-symbols (car forms) symbol) + (elisp-refs--walk-positioned-symbols (cdr forms) symbol))) + ((vectorp forms) + (--mapcat (elisp-refs--walk-positioned-symbols it symbol) forms)))) + +(defun elisp-refs--read-and-find-symbol (buffer symbol) + "Read all the forms in BUFFER, and return a list of all +positions of SYMBOL." + (let* ((symbols-with-pos (fboundp 'symbol-with-pos-pos)) + (forms (elisp-refs--read-all-buffer-forms buffer symbols-with-pos))) + + (if symbols-with-pos + (elisp-refs--walk-positioned-symbols forms symbol) + (-non-nil + (--mapcat + (-let [(_ _ _ symbol-positions read-start-pos) it] + (--map + (-let [(sym . offset) it] + (when (eq sym symbol) + (-let* ((start-pos (+ read-start-pos offset)) + (end-pos (+ start-pos (length (symbol-name sym))))) + (list sym start-pos end-pos)))) + symbol-positions)) + forms))))) + +(defun elisp-refs--filter-obarray (pred) + "Return a list of all the items in `obarray' where PRED returns t." + (let (symbols) + (mapatoms (lambda (symbol) + (when (and (funcall pred symbol) + (not (equal (symbol-name symbol) ""))) + (push symbol symbols)))) + symbols)) + +(defun elisp-refs--loaded-paths () + "Return a list of all files that have been loaded in Emacs. +Where the file was a .elc, return the path to the .el file instead." + (let ((elc-paths (-non-nil (mapcar #'-first-item load-history)))) + (-non-nil + (--map + (let ((el-name (format "%s.el" (file-name-sans-extension it))) + (el-gz-name (format "%s.el.gz" (file-name-sans-extension it)))) + (cond ((file-exists-p el-name) el-name) + ((file-exists-p el-gz-name) el-gz-name) + ;; Ignore files where we can't find a .el file. + (t nil))) + elc-paths)))) + +(defun elisp-refs--contents-buffer (path) + "Read PATH into a disposable buffer, and return it. +Works around the fact that Emacs won't allow multiple buffers +visiting the same file." + (let ((fresh-buffer (generate-new-buffer (format " *refs-%s*" path))) + ;; Be defensive against users overriding encoding + ;; configurations (Helpful bugs #75 and #147). + (coding-system-for-read nil) + (file-name-handler-alist + '(("\\(?:\\.dz\\|\\.txz\\|\\.xz\\|\\.lzma\\|\\.lz\\|\\.g?z\\|\\.\\(?:tgz\\|svgz\\|sifz\\)\\|\\.tbz2?\\|\\.bz2\\|\\.Z\\)\\(?:~\\|\\.~[-[:alnum:]:#@^._]+\\(?:~[[:digit:]]+\\)?~\\)?\\'" . + jka-compr-handler) + ("\\`/:" . file-name-non-special)))) + (with-current-buffer fresh-buffer + (setq-local elisp-refs--path path) + (insert-file-contents path) + ;; We don't enable emacs-lisp-mode because it slows down this + ;; function significantly. We just need the syntax table for + ;; scan-sexps to do the right thing with comments. + (set-syntax-table emacs-lisp-mode-syntax-table)) + fresh-buffer)) + +(defvar elisp-refs--highlighting-buffer + nil + "A temporary buffer used for highlighting. +Since `elisp-refs--syntax-highlight' is a hot function, we +don't want to create lots of temporary buffers.") + +(defun elisp-refs--syntax-highlight (str) + "Apply font-lock properties to a string STR of Emacs lisp code." + ;; Ensure we have a highlighting buffer to work with. + (unless (and elisp-refs--highlighting-buffer + (buffer-live-p elisp-refs--highlighting-buffer)) + (setq elisp-refs--highlighting-buffer + (generate-new-buffer " *refs-highlighting*")) + (with-current-buffer elisp-refs--highlighting-buffer + (delay-mode-hooks (emacs-lisp-mode)))) + + (with-current-buffer elisp-refs--highlighting-buffer + (erase-buffer) + (insert str) + (if (fboundp 'font-lock-ensure) + (font-lock-ensure) + (with-no-warnings + (font-lock-fontify-buffer))) + (buffer-string))) + +(defun elisp-refs--replace-tabs (string) + "Replace tabs in STRING with spaces." + ;; This is important for unindenting, as we may unindent by less + ;; than one whole tab. + (s-replace "\t" (s-repeat tab-width " ") string)) + +(defun elisp-refs--lines (string) + "Return a list of all the lines in STRING. +'a\nb' -> ('a\n' 'b')" + (let ((lines nil)) + (while (> (length string) 0) + (let ((index (s-index-of "\n" string))) + (if index + (progn + (push (substring string 0 (1+ index)) lines) + (setq string (substring string (1+ index)))) + (push string lines) + (setq string "")))) + (nreverse lines))) + +(defun elisp-refs--map-lines (string fn) + "Execute FN for each line in string, and join the result together." + (let ((result nil)) + (dolist (line (elisp-refs--lines string)) + (push (funcall fn line) result)) + (apply #'concat (nreverse result)))) + +(defun elisp-refs--unindent-rigidly (string) + "Given an indented STRING, unindent rigidly until +at least one line has no indent. + +STRING should have a 'elisp-refs-start-pos property. The returned +string will have this property updated to reflect the unindent." + (let* ((lines (s-lines string)) + ;; Get the leading whitespace for each line. + (indents (--map (car (s-match (rx bos (+ whitespace)) it)) + lines)) + (min-indent (-min (--map (length it) indents)))) + (propertize + (elisp-refs--map-lines + string + (lambda (line) (substring line min-indent))) + 'elisp-refs-unindented min-indent))) + +(defun elisp-refs--containing-lines (buffer start-pos end-pos) + "Return a string, all the lines in BUFFER that are between +START-POS and END-POS (inclusive). + +For the characters that are between START-POS and END-POS, +propertize them." + (let (expanded-start-pos expanded-end-pos) + (with-current-buffer buffer + ;; Expand START-POS and END-POS to line boundaries. + (goto-char start-pos) + (beginning-of-line) + (setq expanded-start-pos (point)) + (goto-char end-pos) + (end-of-line) + (setq expanded-end-pos (point)) + + ;; Extract the rest of the line before and after the section we're interested in. + (let* ((before-match (buffer-substring expanded-start-pos start-pos)) + (after-match (buffer-substring end-pos expanded-end-pos)) + ;; Concat the extra text with the actual match, ensuring we + ;; highlight the match as code, but highlight the rest as as + ;; comments. + (text (concat + (propertize before-match + 'face 'font-lock-comment-face) + (elisp-refs--syntax-highlight (buffer-substring start-pos end-pos)) + (propertize after-match + 'face 'font-lock-comment-face)))) + (-> text + (elisp-refs--replace-tabs) + (elisp-refs--unindent-rigidly) + (propertize 'elisp-refs-start-pos expanded-start-pos + 'elisp-refs-path elisp-refs--path)))))) + +(defun elisp-refs--find-file (button) + "Open the file referenced by BUTTON." + (find-file (button-get button 'path)) + (goto-char (point-min))) + +(define-button-type 'elisp-refs-path-button + 'action 'elisp-refs--find-file + 'follow-link t + 'help-echo "Open file") + +(defun elisp-refs--path-button (path) + "Return a button that navigates to PATH." + (with-temp-buffer + (insert-text-button + (abbreviate-file-name path) + :type 'elisp-refs-path-button + 'path path) + (buffer-string))) + +(defun elisp-refs--describe (button) + "Show *Help* for the symbol referenced by BUTTON." + (let ((symbol (button-get button 'symbol)) + (kind (button-get button 'kind))) + (cond ((eq kind 'symbol) + (describe-symbol symbol)) + ((eq kind 'variable) + (describe-variable symbol)) + (t + ;; Emacs uses `describe-function' for functions, macros and + ;; special forms. + (describe-function symbol))))) + +(define-button-type 'elisp-refs-describe-button + 'action 'elisp-refs--describe + 'follow-link t + 'help-echo "Describe") + +(defun elisp-refs--describe-button (symbol kind) + "Return a button that shows *Help* for SYMBOL. +KIND should be 'function, 'macro, 'variable, 'special or 'symbol." + (with-temp-buffer + (insert (symbol-name kind) " ") + (insert-text-button + (symbol-name symbol) + :type 'elisp-refs-describe-button + 'symbol symbol + 'kind kind) + (buffer-string))) + +(defun elisp-refs--pluralize (number thing) + "Human-friendly description of NUMBER occurrences of THING." + (format "%s %s%s" + (elisp-refs--format-int number) + thing + (if (equal number 1) "" "s"))) + +(defun elisp-refs--format-count (symbol ref-count file-count + searched-file-count prefix) + (let* ((file-str (if (zerop file-count) + "" + (format " in %s" (elisp-refs--pluralize file-count "file")))) + (found-str (format "Found %s to %s%s." + (elisp-refs--pluralize ref-count "reference") + symbol + file-str)) + (searched-str (if prefix + (format "Searched %s in %s." + (elisp-refs--pluralize searched-file-count "loaded file") + (elisp-refs--path-button (file-name-as-directory prefix))) + (format "Searched all %s loaded in Emacs." + (elisp-refs--pluralize searched-file-count "file"))))) + (s-word-wrap 70 (format "%s %s" found-str searched-str)))) + +;; TODO: if we have multiple matches on one line, we repeatedly show +;; that line. That's slightly confusing. +(defun elisp-refs--show-results (symbol description results + searched-file-count prefix) + "Given a RESULTS list where each element takes the form \(forms . buffer\), +render a friendly results buffer." + (let ((buf (get-buffer-create (format "*refs: %s*" symbol)))) + (switch-to-buffer buf) + (let ((inhibit-read-only t)) + (erase-buffer) + (save-excursion + ;; Insert the header. + (insert + (elisp-refs--format-count + description + (-sum (--map (length (car it)) results)) + (length results) + searched-file-count + prefix) + "\n\n") + ;; Insert the results. + (--each results + (-let* (((forms . buf) it) + (path (with-current-buffer buf elisp-refs--path))) + (insert + (propertize "File: " 'face 'bold) + (elisp-refs--path-button path) "\n") + (--each forms + (-let [(_ start-pos end-pos) it] + (insert (elisp-refs--containing-lines buf start-pos end-pos) + "\n"))) + (insert "\n"))) + ;; Prepare the buffer for the user. + (elisp-refs-mode))) + ;; Cleanup buffers created when highlighting results. + (when elisp-refs--highlighting-buffer + (kill-buffer elisp-refs--highlighting-buffer)))) + +(defun elisp-refs--loaded-bufs () + "Return a list of open buffers, one for each path in `load-path'." + (mapcar #'elisp-refs--contents-buffer (elisp-refs--loaded-paths))) + +(defun elisp-refs--search-1 (bufs match-fn) + "Call MATCH-FN on each buffer in BUFS, reporting progress +and accumulating results. + +BUFS should be disposable: we make no effort to preserve their +state during searching. + +MATCH-FN should return a list where each element takes the form: +\(form start-pos end-pos)." + (let* (;; Our benchmark suggests we spend a lot of time in GC, and + ;; performance improves if we GC less frequently. + (gc-cons-percentage 0.8) + (total-bufs (length bufs))) + (let ((searched 0) + (forms-and-bufs nil)) + (dolist (buf bufs) + (let* ((matching-forms (funcall match-fn buf))) + ;; If there were any matches in this buffer, push the + ;; matches along with the buffer into our results + ;; list. + (when matching-forms + (push (cons matching-forms buf) forms-and-bufs)) + ;; Give feedback to the user on our progress, because + ;; searching takes several seconds. + (when (and (zerop (mod searched 10)) + elisp-refs-verbose) + (message "Searched %s/%s files" searched total-bufs)) + (cl-incf searched))) + (when elisp-refs-verbose + (message "Searched %s/%s files" total-bufs total-bufs)) + forms-and-bufs))) + +(defun elisp-refs--search (symbol description match-fn &optional path-prefix) + "Find references to SYMBOL in all loaded files; call MATCH-FN on each buffer. +When PATH-PREFIX, limit to loaded files whose path starts with that prefix. + +Display the results in a hyperlinked buffer. + +MATCH-FN should return a list where each element takes the form: +\(form start-pos end-pos)." + (let* ((loaded-paths (elisp-refs--loaded-paths)) + (matching-paths (if path-prefix + (--filter (s-starts-with? path-prefix it) loaded-paths) + loaded-paths)) + (loaded-src-bufs (mapcar #'elisp-refs--contents-buffer matching-paths))) + ;; Use unwind-protect to ensure we always cleanup temporary + ;; buffers, even if the user hits C-g. + (unwind-protect + (progn + (let ((forms-and-bufs + (elisp-refs--search-1 loaded-src-bufs match-fn))) + (elisp-refs--show-results symbol description forms-and-bufs + (length loaded-src-bufs) path-prefix))) + ;; Clean up temporary buffers. + (--each loaded-src-bufs (kill-buffer it))))) + +(defun elisp-refs--completing-read-symbol (prompt &optional filter) + "Read an interned symbol from the minibuffer, +defaulting to the symbol at point. PROMPT is the string to prompt +with. + +If FILTER is given, only offer symbols where (FILTER sym) returns +t." + (let ((filter (or filter (lambda (_) t)))) + (read + (completing-read prompt + (elisp-refs--filter-obarray filter) + nil nil nil nil + (-if-let (sym (thing-at-point 'symbol)) + (when (funcall filter (read sym)) + sym)))))) + +;;; Commands + +;;;###autoload +(defun elisp-refs-function (symbol &optional path-prefix) + "Display all the references to function SYMBOL, in all loaded +elisp files. + +If called with a prefix, prompt for a directory to limit the search. + +This searches for functions, not macros. For that, see +`elisp-refs-macro'." + (interactive + (list (elisp-refs--completing-read-symbol "Function: " #'functionp) + (when current-prefix-arg + (read-directory-name "Limit search to loaded files in: ")))) + (when (not (functionp symbol)) + (if (macrop symbol) + (user-error "%s is a macro. Did you mean elisp-refs-macro?" + symbol) + (user-error "%s is not a function. Did you mean elisp-refs-symbol?" + symbol))) + (elisp-refs--search symbol + (elisp-refs--describe-button symbol 'function) + (lambda (buf) + (elisp-refs--read-and-find buf symbol #'elisp-refs--function-p)) + path-prefix)) + +;;;###autoload +(defun elisp-refs-macro (symbol &optional path-prefix) + "Display all the references to macro SYMBOL, in all loaded +elisp files. + +If called with a prefix, prompt for a directory to limit the search. + +This searches for macros, not functions. For that, see +`elisp-refs-function'." + (interactive + (list (elisp-refs--completing-read-symbol "Macro: " #'macrop) + (when current-prefix-arg + (read-directory-name "Limit search to loaded files in: ")))) + (when (not (macrop symbol)) + (if (functionp symbol) + (user-error "%s is a function. Did you mean elisp-refs-function?" + symbol) + (user-error "%s is not a function. Did you mean elisp-refs-symbol?" + symbol))) + (elisp-refs--search symbol + (elisp-refs--describe-button symbol 'macro) + (lambda (buf) + (elisp-refs--read-and-find buf symbol #'elisp-refs--macro-p)) + path-prefix)) + +;;;###autoload +(defun elisp-refs-special (symbol &optional path-prefix) + "Display all the references to special form SYMBOL, in all loaded +elisp files. + +If called with a prefix, prompt for a directory to limit the search." + (interactive + (list (elisp-refs--completing-read-symbol "Special form: " #'special-form-p) + (when current-prefix-arg + (read-directory-name "Limit search to loaded files in: ")))) + (elisp-refs--search symbol + (elisp-refs--describe-button symbol 'special-form) + (lambda (buf) + (elisp-refs--read-and-find buf symbol #'elisp-refs--special-p)) + path-prefix)) + +;;;###autoload +(defun elisp-refs-variable (symbol &optional path-prefix) + "Display all the references to variable SYMBOL, in all loaded +elisp files. + +If called with a prefix, prompt for a directory to limit the search." + (interactive + ;; This is awkward. We don't want to just offer defvar variables, + ;; because then we can't search for code which uses `let' to bind + ;; symbols. There doesn't seem to be a good way to only offer + ;; variables that have been bound at some point. + (list (elisp-refs--completing-read-symbol "Variable: " ) + (when current-prefix-arg + (read-directory-name "Limit search to loaded files in: ")))) + (elisp-refs--search symbol + (elisp-refs--describe-button symbol 'variable) + (lambda (buf) + (elisp-refs--read-and-find buf symbol #'elisp-refs--variable-p)) + path-prefix)) + +;;;###autoload +(defun elisp-refs-symbol (symbol &optional path-prefix) + "Display all the references to SYMBOL in all loaded elisp files. + +If called with a prefix, prompt for a directory to limit the +search." + (interactive + (list (elisp-refs--completing-read-symbol "Symbol: " ) + (when current-prefix-arg + (read-directory-name "Limit search to loaded files in: ")))) + (elisp-refs--search symbol + (elisp-refs--describe-button symbol 'symbol) + (lambda (buf) + (elisp-refs--read-and-find-symbol buf symbol)) + path-prefix)) + +;;; Mode + +(defvar elisp-refs-mode-map + (let ((map (make-sparse-keymap))) + ;; TODO: it would be nice for TAB to navigate to file buttons too, + ;; like *Help* does. + (set-keymap-parent map special-mode-map) + (define-key map (kbd "") #'elisp-refs-next-match) + (define-key map (kbd "") #'elisp-refs-prev-match) + (define-key map (kbd "n") #'elisp-refs-next-match) + (define-key map (kbd "p") #'elisp-refs-prev-match) + (define-key map (kbd "q") #'kill-this-buffer) + (define-key map (kbd "RET") #'elisp-refs-visit-match) + map) + "Keymap for `elisp-refs-mode'.") + +(define-derived-mode elisp-refs-mode special-mode "Refs" + "Major mode for refs results buffers.") + +(defun elisp--refs-visit-match (open-fn) + "Go to the search result at point. +Open file with function OPEN_FN. `find-file` or `find-file-other-window`" + (interactive) + (let* ((path (get-text-property (point) 'elisp-refs-path)) + (pos (get-text-property (point) 'elisp-refs-start-pos)) + (unindent (get-text-property (point) 'elisp-refs-unindented)) + (column-offset (current-column)) + (line-offset -1)) + (when (null path) + (user-error "No match here")) + + ;; If point is not on the first line of the match, work out how + ;; far away the first line is. + (save-excursion + (while (equal pos (get-text-property (point) 'elisp-refs-start-pos)) + (forward-line -1) + (cl-incf line-offset))) + + (funcall open-fn path) + (goto-char pos) + ;; Move point so we're on the same char in the buffer that we were + ;; on in the results buffer. + (forward-line line-offset) + (beginning-of-line) + (let ((target-offset (+ column-offset unindent)) + (i 0)) + (while (< i target-offset) + (if (looking-at "\t") + (cl-incf i tab-width) + (cl-incf i)) + (forward-char 1))))) + +(defun elisp-refs-visit-match () + "Goto the search result at point." + (interactive) + (elisp--refs-visit-match #'find-file)) + +(defun elisp-refs-visit-match-other-window () + "Goto the search result at point, opening in another window." + (interactive) + (elisp--refs-visit-match #'find-file-other-window)) + + +(defun elisp-refs--move-to-match (direction) + "Move point one match forwards. +If DIRECTION is -1, moves backwards instead." + (let* ((start-pos (point)) + (match-pos (get-text-property start-pos 'elisp-refs-start-pos)) + current-match-pos) + (condition-case _err + (progn + ;; Move forward/backwards until we're on the next/previous match. + (catch 'done + (while t + (setq current-match-pos + (get-text-property (point) 'elisp-refs-start-pos)) + (when (and current-match-pos + (not (equal match-pos current-match-pos))) + (throw 'done nil)) + (forward-char direction))) + ;; Move to the beginning of that match. + (while (equal (get-text-property (point) 'elisp-refs-start-pos) + (get-text-property (1- (point)) 'elisp-refs-start-pos)) + (forward-char -1)) + ;; Move forward until we're on the first char of match within that + ;; line. + (while (or + (looking-at " ") + (eq (get-text-property (point) 'face) + 'font-lock-comment-face)) + (forward-char 1))) + ;; If we're at the last result, don't move point. + (end-of-buffer + (progn + (goto-char start-pos) + (signal 'end-of-buffer nil)))))) + +(defun elisp-refs-prev-match () + "Move to the previous search result in the Refs buffer." + (interactive) + (elisp-refs--move-to-match -1)) + +(defun elisp-refs-next-match () + "Move to the next search result in the Refs buffer." + (interactive) + (elisp-refs--move-to-match 1)) + +(provide 'elisp-refs) +;;; elisp-refs.el ends here diff --git a/org/elpa/esxml-20230308.2254/esxml-autoloads.el b/org/elpa/esxml-20230308.2254/esxml-autoloads.el new file mode 100644 index 0000000..9eed98d --- /dev/null +++ b/org/elpa/esxml-20230308.2254/esxml-autoloads.el @@ -0,0 +1,33 @@ +;;; esxml-autoloads.el --- automatically extracted autoloads -*- lexical-binding: t -*- +;; +;;; Code: + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + + +;;;### (autoloads nil "esxml" "esxml.el" (0 0 0 0)) +;;; Generated autoloads from esxml.el + +(register-definition-prefixes "esxml" '("attr" "esxml-" "pp-esxml-to-xml" "string-trim-whitespace" "sxml-to-" "xml-to-esxml")) + +;;;*** + +;;;### (autoloads nil "esxml-query" "esxml-query.el" (0 0 0 0)) +;;; Generated autoloads from esxml-query.el + +(register-definition-prefixes "esxml-query" '("esxml-")) + +;;;*** + +;;;### (autoloads nil nil ("esxml-pkg.el") (0 0 0 0)) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; coding: utf-8 +;; End: +;;; esxml-autoloads.el ends here diff --git a/org/elpa/esxml-20230308.2254/esxml-pkg.el b/org/elpa/esxml-20230308.2254/esxml-pkg.el new file mode 100644 index 0000000..33cdd1e --- /dev/null +++ b/org/elpa/esxml-20230308.2254/esxml-pkg.el @@ -0,0 +1,14 @@ +(define-package "esxml" "20230308.2254" "Library for working with xml via esxml and sxml" + '((emacs "24.1") + (kv "0.0.5") + (cl-lib "0.5")) + :commit "225693096a587492d76bf696d1f0c25c61f7d531" :authors + '(("Vanya Izaksonas-Smith ")) + :maintainer + '("Vanya Izaksonas-Smith") + :keywords + '("tools" "lisp" "comm") + :url "https://github.com/tali713/esxml") +;; Local Variables: +;; no-byte-compile: t +;; End: diff --git a/org/elpa/esxml-20230308.2254/esxml-query.el b/org/elpa/esxml-20230308.2254/esxml-query.el new file mode 100644 index 0000000..2ce1e40 --- /dev/null +++ b/org/elpa/esxml-20230308.2254/esxml-query.el @@ -0,0 +1,783 @@ +;;; esxml-query.el --- select esxml nodes jQuery-style + +;; Copyright (C) 2017 Vasilij Schneidermann + +;; Author: Vasilij Schneidermann +;; Maintainer: Vasilij Schneidermann +;; Version: 0.1.1 +;; Keywords: data, lisp +;; Package-Requires: ((cl-lib "0.1")) +;; +;; This program is free software; you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation, either version 3 of the +;; License, or (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; Traditionally people pick one of the following options when faced +;; with the task of extracting data from XML in Emacs Lisp: +;; +;; - Using regular expressions on the unparsed document +;; - Manual tree traversal with `assoc', `car' and `cdr' +;; +;; Browsers faced a similar problem until jQuery happened, shortly +;; afterwards they started providing the `node.querySelector' and +;; `node.querySelectorAll' API for retrieving one or all nodes +;; matching a given CSS selector. This code implements the same API +;; with the `esxml-query' and `esxml-query-all' functions. The +;; following table summarizes the currently supported modifiers and +;; combinators: +;; +;; | Name | Supported? | Syntax | +;; |------------------------------------+------------+-------------| +;; | Namespaces | No | foo|bar | +;; | Commas | Yes | foo, bar | +;; | Descendant combinator | Yes | foo bar | +;; | Child combinator | Yes | foo>bar | +;; | Adjacent sibling combinator | No | foo+bar | +;; | General sibling combinator | No | foo~bar | +;; | Universal selector | Yes | * | +;; | Type selector | Yes | tag | +;; | ID selector | Yes | #foo | +;; | Class selector | Yes | .foo | +;; | Attribute selector | Yes | [foo] | +;; | Exact match attribute selector | Yes | [foo=bar] | +;; | Prefix match attribute selector | Yes | [foo^=bar] | +;; | Suffix match attribute selector | Yes | [foo$=bar] | +;; | Substring match attribute selector | Yes | [foo*=bar] | +;; | Include match attribute selector | Yes | [foo~=bar] | +;; | Dash match attribute selector | Yes | [foo|=bar] | +;; | Attribute selector modifiers | No | [foo=bar i] | +;; | Pseudo elements | No | ::foo | +;; | Pseudo classes | No | :foo | + +;;; Code: + +(require 'cl-lib) + + +;;; CSS selector parsing + +;; https://www.w3.org/TR/selectors/#w3cselgrammar +;; https://www.w3.org/TR/selectors4/#grammar +;; https://www.w3.org/TR/2003/WD-css3-syntax-20030813/#detailed-grammar +;; https://www.w3.org/TR/2003/WD-css3-syntax-20030813/#tokenization + +;; you might be wondering why I'm using both level 3 and 4 standards, +;; well, the level 3 one has a buggy lexer section whereas level 4 +;; omits crucial parser definitions, so both have to be used... + +;; TODO: support :not +(defvar esxml--css-selector-token-matchers + (let* ((h "[0-9a-f]") + (nl "\n\\|\r\n\\|\r\\|\f") + (nonascii "[\200-\U0010ffff]") + (unicode (format "\\\\%s\\{1,6\\}[ \t\r\n\f]?" h)) + (escape (format "\\(?:%s\\)\\|\\\\[ -~\200-\U0010ffff]" unicode)) + (nmstart (format "[a-z_]\\|%s\\|\\(?:%s\\)" nonascii escape)) + (nmchar (format "[a-z0-9_-]\\|%s\\|\\(?:%s\\)" nonascii escape)) + (num "[0-9]+\\|[0-9]*\\.[0-9]+") + (string1 (format "\"\\(?:[\t !#$%%&(-~]\\|\\\\\\(?:%s\\)\\|'\\|%s\\|\\(?:%s\\)\\)*\"" nl nonascii escape)) + (string2 (format "'\\(?:[\t !#$%%&(-~]\\|\\\\\\(?:%s\\)\\|\"\\|%s\\|\\(?:%s\\)\\)*'" nl nonascii escape)) + (ident (format "[-]?\\(?:%s\\)\\(?:%s\\)*" nmstart nmchar)) + (unit (format "[-]?\\(?:%s\\)\\(?:%s\\)+" nmstart nmchar)) + (name (format "\\(?:%s\\)+" nmchar))) + + `((whitespace . "[ \t\r\n\f]+") + (string . ,(format "\\(?:%s\\|%s\\)" string1 string2)) + (ident . ,ident) + (hash . ,(format "#%s" name)) + (function . ,(format "%s(" ident)) + (number . ,num) + (dimension . ,(format "\\(?:%s\\)%s" num unit)) + (prefix-match . "\\^=") + (suffix-match . "\\$=") + (substring-match . "\\*=") + (include-match . "~=") + (dash-match . "|=") + (comma . ",") + (gt . ">") + (plus . "\\+") + (minus . "-") + (tilde . "~") + (asterisk . "\\*") + (period . "\\.") + (equals . "=") + (colon . ":") + (lbracket . "\\[") + (rbracket . "\\]") + (rparen . ")")))) + +(defun esxml--tokenize-css-selector (string) + (let (result) + (with-temp-buffer + (insert string) + (goto-char (point-min)) + (while (not (eobp)) + (let ((max-length 0) + longest) + (dolist (matcher esxml--css-selector-token-matchers) + (let ((id (car matcher)) + (re (cdr matcher))) + (when (looking-at re) + (let* ((token (match-string 0)) + (length (length token))) + (when (> length max-length) + (setq max-length length) + (setq longest (cons id token))))))) + (when (not longest) + (error "Invalid token detected: %s" + (buffer-substring (point) (point-max)))) + (push longest result) + (goto-char (+ (point) max-length))))) + (nreverse result))) + +;; the alternative is creating a mutable object with peek/next methods +;; and passing it around, so I chose the one requiring less typing, a +;; dynamically bound variable :< + +(defvar esxml--token-stream) + +;; TODO: support :not +;; css-selector: +;; css-selector-list; +;; css-selector-list: +;; complex-css-selector [ comma whitespace* complex-css-selector ]*; +;; complex-css-selector: +;; compound-css-selector [ css-combinator compound-css-selector ]* whitespace*; +;; css-combinator: +;; whitespace+ | whitespace* [ '>' | '+' | '~' ] whitespace*; +;; compound-css-selector: +;; css-type-selector css-modifier* | css-modifier+; +;; css-type-selector: +;; IDENT | *; +;; css-modifier: +;; css-id | css-class | css-attrib | css-pseudo; +;; css-id: +;; HASH; +;; css-class: +;; '.' IDENT; +;; css-attrib: +;; '[' whitespace* css-attrib-name ']' +;; | '[' whitespace* css-attrib-name css-attrib-match css-attrib-value whitespace* ']'; +;; css-attrib-name: +;; IDENT whitespace*; +;; css-attrib-match: +;; [ '=' | PREFIX-MATCH | SUFFIX-MATCH | SUBSTRING-MATCH | INCLUDE-MATCH | DASH-MATCH ] whitespace*; +;; css-attrib-value: +;; IDENT | STRING; +;; css-pseudo: +;; ':' ':'? [ IDENT | css-functional-pseudo ]; +;; css-functional-pseudo: +;; FUNCTION whitespace* [ css-expression whitespace* ]+ ')'; +;; css-expression: +;; '+' | '-' | DIMENSION | NUMBER | STRING | IDENT + +(defun esxml-query-css-escape (string) + "Returns escaped version of STRING for use in selectors. +The logic used here corresponds to the CSS.escape API as +specified in https://drafts.csswg.org/cssom/#the-css.escape()-method." + (let (chars) + (dotimes (i (length string)) + (let* ((char (aref string i)) + (unprintablep (or (and (>= char ?\u0001) (<= char ?\u001f)) + (= char ?\u007f))) + (nonasciip (>= char ?\u0080)) + (digitp (and (>= char ?\u0030) (<= char ?\u0039))) + (upperp (and (>= char ?\u0041) (<= char ?\u005a))) + (lowerp (and (>= char ?\u0061) (<= char ?\u007a)))) + (cond + ((= char ?\u0000) + (push ?\ufffd chars)) + (unprintablep + (dolist (char (string-to-list (format "\\%x " char))) + (push char chars))) + ((and (= i 0) digitp) + (dolist (char (string-to-list (format "\\%x " char))) + (push char chars))) + ((and (= i 1) digitp (= (aref string 0) ?-)) + (dolist (char (string-to-list (format "\\%x " char))) + (push char chars))) + ((and (= i 0) (= char ?-) (= (length string) 1)) + (push ?\\ chars) + (push char chars)) + ((or nonasciip (= char ?-) (= char ?_) digitp upperp lowerp) + (push char chars)) + (t + (push ?\\ chars) + (push char chars))))) + (concat (nreverse chars)))) + +(defun esxml--parse-css-identifier (string) + ;; https://www.w3.org/TR/css-syntax-3/#consume-string-token + (let* ((code-points (string-to-list string)) + chars + token) + (while code-points + (let ((char (pop code-points))) + (if (= char ?\\) + (let ((char (pop code-points))) + (cond + ((not char)) + ((= char ?\n)) + ((or (and (>= char ?0) (<= char ?9)) + (and (>= char ?a) (<= char ?f)) + (and (>= char ?A) (<= char ?F))) + (let ((i 0) + (hex-chars (list char))) + (while (and (< i 5) code-points) + (let ((char (car code-points))) + (if (or (and (>= char ?0) (<= char ?9)) + (and (>= char ?a) (<= char ?f)) + (and (>= char ?A) (<= char ?F))) + (push (pop code-points) hex-chars) + (setq i 5))) + (setq i (1+ i))) + (let ((char (car code-points))) + (when (and char (= char ?\s)) + (pop code-points))) + (let* ((hex-token (concat (nreverse hex-chars))) + (code-point (string-to-number hex-token 16))) + (if (or (zerop code-point) + (and (>= code-point ?\ud800) (<= code-point ?\udfff)) + (> code-point ?\U0010ffff)) + (push ?\ufffd chars) + (push code-point chars))))) + (t ; unspecified: non-hex digit + (push char chars)))) + (push char chars)))) + (concat (nreverse chars)))) + +(defun esxml--parse-css-string-literal (string) + (esxml--parse-css-identifier (substring string 1 -1))) + +(defmacro esxml--with-parse-shorthands (&rest body) + `(cl-macrolet ((peek () '(car esxml--token-stream)) + (next () '(pop esxml--token-stream)) + (accept (type) `(and (peek) (eq (car (peek)) ,type) + (cdr (next)))) + (eat-whitespace () '(while (accept 'whitespace)))) + ,@body)) +(def-edebug-spec esxml--with-parse-shorthands (body)) + +(defun esxml-parse-css-selector (string) + "Parse CSS selector STRING into a list of alists. +Each alist represents a complex CSS selector. The result can be +passed to `esxml-query' and `esxml-query-all' as the selector +argument." + (let* ((esxml--token-stream (esxml--tokenize-css-selector string)) + (result (esxml--parse-css-selector-list))) + (when esxml--token-stream + (error "Trailing garbage: %s" + (mapconcat 'cdr esxml--token-stream ""))) + result)) + +(defun esxml--parse-css-selector-list () + (esxml--with-parse-shorthands + (let ((first (esxml--parse-complex-css-selector)) + result) + (when (not first) + (error "Expected at least one selector")) + (push first result) + + (while (accept 'comma) + (eat-whitespace) + (let ((selector (esxml--parse-complex-css-selector))) + (when (not selector) + (error "Expected selector after comma")) + (push selector result))) + (nreverse result)))) + +(defun esxml--parse-complex-css-selector () + (esxml--with-parse-shorthands + (let ((first (esxml--parse-compound-css-selector)) + result done) + (when first + (push first result) + + (while (not done) + (let ((combinator (esxml--parse-css-combinator))) + (if combinator + (let ((compound (esxml--parse-compound-css-selector))) + (cond + (compound + (setq result (append (list compound combinator) result))) + ;; allow whitespace before comma + ((not (eq (car (peek)) 'comma)) + (error "Trailing combinator")))) + (setq done t)))) + (nreverse result))))) + +(defun esxml--parse-css-combinator () + (esxml--with-parse-shorthands + ;; NOTE: whitespace-surrounded combinators are distinguished from + ;; whitespace-only ones by checking whether there has been + ;; whitespace followed by a non-blank combinator + (let ((leading-whitespace-p (eq (car (peek)) 'whitespace)) + result) + (eat-whitespace) + (let ((type (car (peek)))) + (cond + ((member type '(gt plus tilde)) + (next) + (cond + ((eq type 'gt) + (setq result '((combinator . child)))) + ((eq type 'plus) + (setq result '((combinator . direct-sibling)))) + ((eq type 'tilde) + (setq result '((combinator . indirect-sibling))))) + (eat-whitespace)) + (leading-whitespace-p + (setq result '((combinator . descendant)))) + (t nil))) + result))) + +(defun esxml--parse-compound-css-selector () + (esxml--with-parse-shorthands + (let ((type-selector (esxml--parse-css-type-selector)) + done + result) + ;; NOTE: css-type-selector css-modifier* | css-modifier+; is + ;; equivalent to: [ css-type-selector | css-modifier ] css-modifier*; + (if type-selector + (push type-selector result) + (let ((modifier (esxml--parse-css-modifier))) + (if modifier + (push modifier result) + ;; NOTE: this allows the trailing combinator error to be thrown + (setq done t)))) + + (while (not done) + (let ((modifier (esxml--parse-css-modifier))) + (if modifier + (push modifier result) + (setq done t)))) + (when (> (cl-count 'id result :key 'car) 1) + (error "Only one id selector allowed per compound")) + (nreverse result)))) + +(defun esxml--parse-css-type-selector () + (esxml--with-parse-shorthands + (let ((token (peek))) + (cond + ((eq (car token) 'ident) + (next) + (cons 'tag (intern (esxml--parse-css-identifier (cdr token))))) + ((eq (car token) 'asterisk) + (next) + '(wildcard)) + (t nil))))) + +(defun esxml--parse-css-modifier () + (or (esxml--parse-css-id) + (esxml--parse-css-class) + (esxml--parse-css-attrib) + (esxml--parse-css-pseudo))) + +(defun esxml--parse-css-id () + (esxml--with-parse-shorthands + (let ((value (accept 'hash))) + (when value + (cons 'id (substring value 1)))))) + +(defun esxml--parse-css-class () + (esxml--with-parse-shorthands + (when (accept 'period) + (let ((value (accept 'ident))) + (if value + (cons 'class value) + (error "Expected identifier after period")))))) + +(defun esxml--parse-css-attrib () + (esxml--with-parse-shorthands + (let (result) + (when (accept 'lbracket) + (eat-whitespace) + (let ((name (esxml--parse-css-attrib-name))) + (when (not name) + (error "Expected attribute name")) + (push (cons 'name (esxml--parse-css-identifier name)) result) + (when (not (accept 'rbracket)) + (let ((match (esxml--parse-css-attrib-match))) + (when (not match) + (error "Expected attribute matcher")) + (let ((value (esxml--parse-css-attrib-value))) + (when (not value) + (error "Expected attribute value")) + (eat-whitespace) + (when (not (accept 'rbracket)) + (error "Unterminated attribute")) + (push (cons match value) result))))) + (cons 'attribute (nreverse result)))))) + +(defun esxml--parse-css-attrib-name () + (esxml--with-parse-shorthands + (let ((name (accept 'ident))) + (when name + (eat-whitespace) + name)))) + +(defun esxml--parse-css-attrib-match () + (esxml--with-parse-shorthands + (let (result) + (cond + ((accept 'equals) + (setq result 'exact-match)) + ((accept 'prefix-match) + (setq result 'prefix-match)) + ((accept 'suffix-match) + (setq result 'suffix-match)) + ((accept 'substring-match) + (setq result 'substring-match)) + ((accept 'include-match) + (setq result 'include-match)) + ((accept 'dash-match) + (setq result 'dash-match))) + (eat-whitespace) + result))) + +(defun esxml--parse-css-attrib-value () + (esxml--with-parse-shorthands + (let ((token (peek))) + (cond + ((eq (car token) 'ident) + (next) + (esxml--parse-css-identifier (cdr token))) + ((eq (car token) 'string) + (next) + (esxml--parse-css-string-literal (cdr token))) + (t nil))))) + +(defun esxml--parse-css-pseudo () + (esxml--with-parse-shorthands + (let (result type) + (when (accept 'colon) + (if (accept 'colon) + (setq type 'pseudo-element) + (setq type 'pseudo-class)) + (let ((functional (esxml--parse-css-functional-pseudo))) + (if functional + (if (eq type 'pseudo-class) + (let ((value (car functional)) + (args (cdr functional))) + (push (cons 'name (esxml--parse-css-identifier value)) result) + (push (cons 'args args) result)) + (error "Pseudo-elements may not have arguments")) + (let ((value (accept 'ident))) + (if value + (push (cons 'name (esxml--parse-css-identifier value)) result) + (error "Expected function or identifier"))))) + (cons type (nreverse result)))))) + +(defun esxml--parse-css-functional-pseudo () + (esxml--with-parse-shorthands + (let ((function (accept 'function)) + result) + (when function + (push (substring function 0 -1) result) + (eat-whitespace) + (let ((expression (esxml--parse-css-expression)) + done) + (eat-whitespace) + (when (not expression) + (error "Expected at least one expression for function")) + (push expression result) + (while (not done) + (setq expression (esxml--parse-css-expression)) + (if expression + (progn + (push expression result) + (eat-whitespace)) + (setq done t)))) + (when (not (accept 'rparen)) + (error "Unterminated function argument list")) + (nreverse result))))) + +(defun esxml--parse-css-expression () + (esxml--with-parse-shorthands + (let ((token (peek))) + (cond + ((accept 'plus) + '(operator . +)) + ((accept 'minus) + '(operator . -)) + ((eq (car token) 'dimension) + (next) + (cons 'dimension (esxml--parse-css-identifier (cdr token)))) + ((eq (car token) 'number) + (next) + (cons 'number (string-to-number (cdr token)))) + ((eq (car token) 'string) + (next) + (cons 'string (esxml--parse-css-string-literal (cdr token)))) + ((eq (car token) 'ident) + (next) + (cons 'ident (esxml--parse-css-identifier (cdr token)))) + (t nil))))) + + +;;; tree traversal + +;; TODO: these helpers should be part of esxml.el +(defun esxml-branch-p (node) + "Non-nil if NODE refers to an esxml branch." + (and (listp node) + (>= (length node) 2) + (symbolp (car node)) + (listp (cadr node)))) + +(defun esxml-node-tag (node) + "Returns the tag of NODE if available." + (and (esxml-branch-p node) + (car node))) + +(defun esxml-node-attributes (node) + "Returns the attributes of NODE if available." + (and (esxml-branch-p node) + (cadr node))) + +(defun esxml-node-attribute (attribute node) + "Returns the attribute ATTRIBUTE of NODE if available." + (and (esxml-branch-p node) + (cdr (assq attribute (cadr node))))) + +(defun esxml-node-children (node) + "Returns the children of NODE if available." + (and (esxml-branch-p node) + (nthcdr 2 node))) + +(defun esxml-find-node (pred root) + "Locates a node satisfying PRED starting from ROOT. +Returns the node or nil if none found." + (if (funcall pred root) + root + (cl-some (lambda (node) (esxml-find-node pred node)) + (esxml-node-children root)))) + +(defun esxml-visit-nodes (function root) + "Visit nodes by calling FUNCTION on each starting from ROOT." + (funcall function root) + (mapc (lambda (node) (esxml-visit-nodes function node)) + (esxml-node-children root))) + +(defun esxml-find-nodes (pred root) + "Locates all nodes satisfying PRED starting from ROOT. +Returns a list of the nodes or nil if none found." + (let ((acc '())) + (esxml-visit-nodes + (lambda (node) + (when (funcall pred node) + (push node acc))) + root) + (nreverse acc))) + +(defun esxml-find-descendant (pred root) + "Locates a node satisfying PRED starting from ROOT's children. +Returns the node or nil if none found." + (cl-some (lambda (node) (esxml-find-node pred node)) + (esxml-node-children root))) + +(defun esxml-find-descendants (pred root) + "Locates all nodes satisfying PRED starting from ROOT's children. +Returns a list of the nodes or nil if none found." + (cl-mapcan (lambda (node) (esxml-find-nodes pred node)) + (esxml-node-children root))) + +(defun esxml-find-child (pred root) + "Locates a node satisfying PRED among ROOT's children. +Returns the node or nil if none found." + (cl-some (lambda (node) (when (funcall pred node) node)) + (esxml-node-children root))) + +(defun esxml-find-children (pred root) + "Locates all nodes satisfying PRED among ROOT's children. +Returns a list of the nodes or nil if none found." + (mapcar (lambda (node) (when (funcall pred node) node)) + (esxml-node-children root))) + +(defun esxml--node-with-children (node children) + (let ((tag (esxml-node-tag node)) + (attributes (esxml-node-attributes node))) + (append (list tag attributes) children))) + +(defun esxml--node-with-attributes (node attributes) + (let ((tag (esxml-node-tag node)) + (children (esxml-node-children node))) + (append (list tag attributes) children))) + +(defun esxml-tree-map (function root) + "Returns a copy of ROOT with FUNCTION applied to each node." + (if (esxml-branch-p root) + (esxml--node-with-children + (funcall function root) + (mapcar (lambda (node) (esxml-tree-map function node)) + (esxml-node-children root))) + (funcall function root))) + +(defvar esxml--symbol (make-symbol "id")) + +(defun esxml--decorate-tree (root) + (let ((i 0)) + (esxml-tree-map + (lambda (node) + (let ((attribute (cons esxml--symbol i)) + (attributes (esxml-node-attributes node))) + (setq attributes (append (list attribute) attributes)) + (setq i (1+ i)) + (if (esxml-branch-p node) + (esxml--node-with-attributes node attributes) + node))) + root))) + +(defun esxml--undecorate-node (node) + (if (esxml-branch-p node) + (let ((attributes (esxml-node-attributes node))) + (esxml--node-with-attributes node (assq-delete-all esxml--symbol + attributes))) + node)) + +(defun esxml--retrieve-decoration (node) + (esxml-node-attribute esxml--symbol node)) + + +;;; querying + +;; NOTE: supporting structural pseudo functions, direct siblings and +;; indirect siblings requires breadth instead of depth traversal, +;; something that could be emulated without zippers if you had the +;; parent of the node (and the position of the child)... + +(defun esxml--node-matches-attribute-p (node modifier) + (let ((attributes (esxml-node-attributes node)) + haystack) + (cl-every + (lambda (item) + (let ((type (car item)) + (value (cdr item))) + (cond + ((eq type 'name) + (let ((match (assq (intern value) attributes))) + (setq haystack (cdr match)) + match)) + ((eq type 'exact-match) + (equal haystack value)) + ((eq type 'prefix-match) + (string-prefix-p value haystack)) + ((eq type 'suffix-match) + (string-suffix-p value haystack)) + ((eq type 'substring-match) + (string-match-p (regexp-quote value) haystack)) + ((eq type 'include-match) + (member value (split-string haystack " "))) + ((eq type 'dash-match) + (or (equal value haystack) + (string-match-p (format "^%s-" (regexp-quote value)) haystack))) + (t (error "Unknown attribute modifier"))))) + modifier))) + +(defun esxml--node-matches-modifier-p (node type value) + (cond + ((eq type 'wildcard) + t) + ((eq type 'tag) + (equal (esxml-node-tag node) value)) + ((eq type 'id) + (equal (esxml-node-attribute 'id node) value)) + ((eq type 'class) + (let ((class (esxml-node-attribute 'class node))) + (and class (member value (split-string class " "))))) + ((eq type 'attribute) + (esxml--node-matches-attribute-p node value)) + ;; TODO: support structural pseudo functions + ;; TODO: error out on invalid pseudo-class arguments + (t (error "Unimplemented attribute type: %s" type)))) + +(defun esxml--find-node-for (attributes) + (lambda (node) + (cl-every + (lambda (attribute) + (let ((type (car attribute)) + (value (cdr attribute))) + (esxml--node-matches-modifier-p node type value))) + attributes))) + +(defun esxml--find-nodes (root combinator attributes) + (let* ((type (cdr (assq 'combinator combinator))) + (walker (cond + ((not type) + 'esxml-find-nodes) + ((eq type 'descendant) + 'esxml-find-descendants) + ((eq type 'child) + 'esxml-find-children) + ;; TODO: support direct sibling + ;; TODO: support indirect sibling + (t (error "Unimplemented combinator %s" combinator))))) + (funcall walker (esxml--find-node-for attributes) root))) + +(defun esxml--query (selector root) + (let* ((attributes (pop selector)) + combinator + (result (esxml--find-nodes root nil attributes))) + (while (and result selector) + (setq combinator (pop selector)) + (setq attributes (pop selector)) + (setq result (cl-mapcan + (lambda (node) + (esxml--find-nodes node combinator attributes)) + result)) + (setq result (delq nil result))) + result)) + +(defun esxml--delete-dups (items test) + (let ((seen (make-hash-table :test test)) + result) + (while items + (let ((item (pop items))) + (when (not (gethash item seen)) + (push item result) + (puthash item t seen)))) + (nreverse result))) + +(defun esxml-query-all (selector root) + "Locates all nodes satisfying SELECTOR starting from ROOT. +SELECTOR must be a string containing a CSS selector or a parsed +CSS selector returned by `esxml-parse-css-selector'. Returns a +list of the nodes or nil if none found." + (when (stringp selector) + (setq selector (esxml-parse-css-selector selector))) + (if (= (length selector) 1) + ;; no commas, we can only get the same nodes repeatedly + (esxml--delete-dups (esxml--query (car selector) root) 'eq) + ;; commas, nodes might be the same *and* in the wrong order + (setq root (esxml--decorate-tree root)) + (let (result) + (while selector + (setq result (nconc result (esxml--query (pop selector) root)))) + (setq result (cl-sort result '< :key 'esxml--retrieve-decoration)) + (setq result (cl-delete-duplicates result :test '= + :key 'esxml--retrieve-decoration)) + (mapcar (lambda (node) (esxml--undecorate-node node)) result)))) + +(defun esxml-query (selector root) + "Locates a node satisfying SELECTOR starting from ROOT. +SELECTOR must be a string containing a CSS selector or a parsed +CSS selector returned by `esxml-parse-css-selector'. Returns the +node or nil if none found." + ;; NOTE: you can do a bit less work (the savings decrease the more + ;; branches the query discards), but it's simpler and safer to just + ;; have the same algorithm for both entry points + (car (esxml-query-all selector root))) + +(provide 'esxml-query) +;;; esxml-query.el ends here diff --git a/org/elpa/esxml-20230308.2254/esxml.el b/org/elpa/esxml-20230308.2254/esxml.el new file mode 100644 index 0000000..6d17dce --- /dev/null +++ b/org/elpa/esxml-20230308.2254/esxml.el @@ -0,0 +1,297 @@ +;;; esxml.el --- Library for working with xml via esxml and sxml +;; Copyright (C) 2012 + +;; Author: Vanya Izaksonas-Smith +;; Maintainer: Vanya Izaksonas-Smith +;; URL: https://github.com/tali713/esxml +;; Created: 15th August 2012 +;; Version: 0.3.7 +;; Keywords: tools, lisp, comm +;; Description: A library for easily generating XML/XHTML in elisp +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; This is XML/XHTML done with S-Expressions in EmacsLisp. Simply, +;; this is the easiest way to write HTML or XML in Lisp. +;; +;; This library uses the native form of XML representation as used by +;; many libraries already included within emacs. This representation +;; will be referred to as "esxml" throughout this library. See +;; `esxml-to-xml' for a concise description of the format. +;; +;; This library is not intended to be used directly by a user, though +;; it certainly could be. It could be used to generate static html, +;; or use a library like `elnode' to serve dynamic pages. Or even to +;; extract a form from a site to produce an API. +;; +;; TODO: Better documentation, more convenience. +;; +;; NOTICE: Code base will be transitioning to using pcase instead of +;; destructuring bind wherever possible. If this leads to hard to +;; debug code, please let me know, and I will do whatever I can to +;; resolve these issues. +;; +;;; Code: +(require 'cl-lib) +(require 'xml) +(require 'pcase) + +(defun string-trim-whitespace (string) + "A simple function, strips the whitespace from beginning and +end of the string. Leaves all other whitespace untouched." + (replace-regexp-in-string + (rx string-start (* whitespace) + (group (+? anything)) + (* whitespace) string-end) + "\\1" + string)) + +(defun esxml-trim-ws (esxml) + "This may cause problems, is intended for parsing xml into sxml +but may eroneously delete desirable white space." + (if (stringp esxml) (string-trim-whitespace esxml) + (pcase-let ((`(,tag ,attrs . ,body) esxml)) + `(,tag ,attrs + ,@(mapcar 'esxml-trim-ws body))))) + +(defun attrp (attr) + "Returns t if attr is a an esxml attribute. +An esxml attribute is a cons of the form (symbol . string)" + (and (consp attr) + (symbolp (car attr)) + (stringp (cdr attr)))) + +(defun esxml--convert-pair (attr) + "Converts from cons cell to attribute pair. Not intended for +general use." + (pcase-let ((`(,car . ,cdr) attr)) + (cl-check-type cdr string) + (concat (symbol-name car) + "=" + (prin1-to-string (xml-escape-string cdr))))) + +(defun attrsp (attrs) + "Returns t if attrs is a list of esxml attributes. + +See: `attrp'" + (and (listp attrs) + (cl-every (lambda (attr) + (and (consp attr) + (symbolp (car attr)) + (stringp (cdr attr)))) + attrs))) + +(defun esxml-validate-form (esxml) + "A fast esxml validator. Will error on invalid subparts making +it suitable for hindsight testing." + (cond ((stringp esxml) nil) + ((< (length esxml) 2) + (error "%s is too short to be a valid esxml expression" esxml)) + (t (pcase-let ((`(,tag ,attrs . ,body) esxml)) + (cl-check-type tag symbol) + (cl-check-type attrs attrs) + (mapcar 'esxml-validate-form body))))) + +;; While the following could certainly have been written using format, +;; concat makes them easier to read. Update later if neccesary for +;; efficiency. + +;; Though at first glance the recursive nature of this function might +;; give one pause, since xml is a recursive data type, a recursive +;; parser is an optimal strategy. each node will be visited exactly +;; once during the transformation. +;; +;; Further, since a string is a terminal node and since xml can be +;; represented as a string, non dynamic portions of the page may be +;; precached quite easily. +(defun esxml--to-xml-recursive (esxml) + (pcase esxml + ((pred stringp) + (xml-escape-string esxml)) + (`(raw-string ,string) + (cl-check-type string stringp) + string) + (`(comment nil ,body) + (concat "")) + (`(,tag ,attrs . ,body) + ;; code goes here to catch invalid data. + (concat "<" (symbol-name tag) + (when attrs + (concat " " (mapconcat 'esxml--convert-pair attrs " "))) + (if body + (concat ">" (mapconcat 'esxml--to-xml-recursive body "") + "") + "/>"))))) + +(defun esxml-to-xml (esxml) + "This translates an esxml expression, i.e. that which is returned +by xml-parse-region. The structure is defined as any of the +following forms: + +- A string. + + STRING + +STRING: the string it is returned with entities escaped + +- A list where the first element is the raw-string symbol and the + second is a string. + + (raw-string STRING) + +STRING: the string is returned unchanged. This allows for caching + of any constant parts, such as headers and footers. + +- A list where the first element is the comment symbol and the + second is a string. + + (comment STRING) + +STRING: the string is embedded in a HTML comment. + +- A list where the first element is the tag, the second is +an alist of attribute value pairs and the remainder of the list +is 0 or more esxml elements. + + (TAG ATTRS &rest BODY) + +TAG: is the tag and must be a symbol. + +ATTRS: is an alist of attribute pairs each pair must be of the + form (KEY . VALUE). + +KEY: is the name of the attribute and must be a symbol. + +VALUE: is the value of the attribute and must be a string. + +BODY: is zero or more esxml expressions. Having no body forms + implies that the tag should be self closed. If there is + one or more body forms the tag will always be explicitly + closed, even if they are the empty string." + (condition-case nil + (esxml--to-xml-recursive esxml) + (error (esxml-validate-form esxml)))) + +(defun pp-esxml-to-xml (esxml) + "This translates an esxml expresion as `esxml-to-xml' but +indents it for ease of human readability, it is necessarily +slower and will produce longer output." + (pcase esxml + ((pred stringp) + (xml-escape-string esxml)) + (`(raw-string ,string) + (cl-check-type string stringp) + string) + (`(comment nil ,body) + (concat "")) + (`(,tag ,attrs . ,body) + (cl-check-type tag symbol) + (cl-check-type attrs attrs) + (concat "<" (symbol-name tag) + (when attrs + (concat " " (mapconcat 'esxml--convert-pair attrs " "))) + (if body + (concat ">" (if (cl-every 'stringp body) + (mapconcat 'identity body " ") + (concat "\n" + (replace-regexp-in-string + "^" " " + (mapconcat 'pp-esxml-to-xml body "\n")) + "\n")) + "") + "/>"))) + (_ + (error "%s is not a valid esxml expression" esxml)))) + +(defun sxml-to-esxml (sxml) + "Translates sxml to esxml so the common standard can be used. +See: http://okmij.org/ftp/Scheme/SXML.html. Additionally, +(*RAW-STRING* \"string\") is translated to (raw-string +\"string\")." + (pcase sxml + (`(*RAW-STRING* ,body) + `(raw-string ,body)) + (`(*COMMENT* ,body) + `(comment nil ,body)) + (`(,tag (@ . ,attrs) . ,body) + `(,tag ,(mapcar (lambda (attr) + (cons (car attr) + (or (cadr attr) + (prin1-to-string (car attr))))) + attrs) + ,@(mapcar 'sxml-to-esxml body))) + (`(,tag . ,body) + `(,tag nil + ,@(mapcar 'sxml-to-esxml body))) + ((and sxml (pred stringp)) sxml))) + +(defun sxml-to-xml (sxml) + "Translates sxml to xml, via esxml, hey it's only a constant +factor. :)" + (esxml-to-xml (sxml-to-esxml sxml))) + + + +;; TODO: make agnostic with respect to libxml vs xml.el +(defun xml-to-esxml (string &optional trim) + (with-temp-buffer + (insert string) + (let ((parse-tree (libxml-parse-xml-region (point-min) + (point-max)))) + (if trim + (esxml-trim-ws parse-tree) + parse-tree)))) + +;; TODO, move to esxpath when mature +(defun esxml-get-by-key (esxml key value) + "Returns a list of all elements whose wttribute KEY match +VALUE. KEY should be a symbol, and VALUE should be a string. +Will not recurse below a match." + (unless (stringp esxml) + (pcase-let ((`(,tag ,attrs . ,body) esxml)) + (if (equal value + (assoc-default key attrs)) + (list esxml) + (apply 'append (mapcar (lambda (sexp) + (esxml-get-by-key sexp key value)) + body)))))) + +(defun esxml-get-tags (esxml tags) + "Returns a list of all elements whose tag is a member of TAGS. +TAGS should be a list of tags to be matched against. Will not +recurse below a match." + (unless (stringp esxml) + (pcase-let ((`(,tag ,attrs . ,body) esxml)) + (if (member tag tags) + (list esxml) + (apply 'append (mapcar (lambda (sexp) + (esxml-get-tags sexp tags)) + body)))))) + +(defun esxml-get-forms (esxml) + "Returns a list of all forms." + (esxml-get-tags esxml '(form))) + +;; taken from kv +(defmacro esxml-destructuring-mapcar (args sexp seq) + (declare (indent 2)) + (let ((entry (make-symbol "entry"))) + `(mapcar (lambda (,entry) + (cl-destructuring-bind ,args ,entry ,sexp)) + ,seq))) + +(provide 'esxml) +;;; esxml.el ends here diff --git a/org/elpa/helm-20230406.839/.dir-locals.el b/org/elpa/helm-20230406.839/.dir-locals.el new file mode 100644 index 0000000..ded5c00 --- /dev/null +++ b/org/elpa/helm-20230406.839/.dir-locals.el @@ -0,0 +1,9 @@ +;;; Directory Local Variables +;;; For more information see (info "(emacs) Directory Variables") + +((nil . ((bug-reference-bug-regexp . "\\(\\b\\(?:[Ii]ssue ?#?\\|[Bb]ug ?#?\\|[Pp]atch ?#\\|RFE ?#\\|PR [a-z+-]+/\\)\\([0-9]+\\(?:#[0-9]+\\)?\\)\\)") + (bug-reference-url-format . "https://github.com/emacs-helm/helm/issues/%s") + (byte-compile-warnings . (not obsolete docstrings docstrings-non-ascii-quotes)))) + (emacs-lisp-mode . ((mode . bug-reference-prog) + (indent-tabs-mode . nil) + (fill-column . 80)))) diff --git a/org/elpa/helm-20230406.839/emacs-helm.sh b/org/elpa/helm-20230406.839/emacs-helm.sh new file mode 100644 index 0000000..e84e99d --- /dev/null +++ b/org/elpa/helm-20230406.839/emacs-helm.sh @@ -0,0 +1,261 @@ +#!/usr/bin/env sh + + +## Copyright (C) 2012 ~ 2023 Thierry Volpiatto +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program. If not, see . + +## Commentary: +# Preconfigured `emacs -Q' with a basic Helm configuration. + + +# If TEMP env var exists, use it, otherwise declare it. +test -z "$TEMP" && TEMP="/tmp" + +CONF_FILE="$TEMP/helm-cfg.el" +EMACS=emacs +TOOLBARS=-1 +LOAD_PACKAGES= + +usage () { + cat >&1 < $CONF_FILE <\`helm-find-files'\\n\ +;; - \`occur'(M-s o) =>\`helm-occur'\\n\ +;; - \`list-buffers'(C-x C-b) =>\`helm-buffers-list'\\n\ +;; - \`completion-at-point'(M-tab) =>\`helm-lisp-completion-at-point'[1]\\n\ +;; - \`apropos-command'(C-h a) =>\`helm-apropos'\\n\ +;; - \`dabbrev-expand'(M-/) =>\`helm-dabbrev'\\n\ +;; - \`execute-extended-command'(M-x) =>\`helm-M-x'\\n\\n +;; Some other Emacs commands are \"helmized\" by \`helm-mode'.\\n\ +;; [1] Coming with emacs-24.4, \`completion-at-point' is \"helmized\" by \`helm-mode'\\n\ + +;; which provides Helm completion in many places like \`shell-mode'.\\n\ +;; Find context help for most Helm commands with \`C-h m'.\\n\ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\\n\\n")) + +(setq load-path (quote $LOAD_PATH)) + +(defvar default-package-manager nil) +;; /home/you/.emacs.d/.local/straight/build-27.1/helm +(defvar initial-package-directory (file-name-directory (file-truename "$0"))) + +(defvar bootstrap-version) +(let* ((packages "$LOAD_PACKAGES") + (pkg-list (and packages + (not (equal packages "")) + (split-string packages ","))) + ;; /home/you/.emacs.d/.local/straight/build-27.1 + (straight-path (file-name-directory (directory-file-name initial-package-directory))) + ;; /home/you/.emacs.d/.local/straight/build-27.1/async + (async-path (expand-file-name "async" straight-path)) + ;; /home/you/.emacs.d/.local/straight/repos/straight.el/bootstrap.el + (bootstrap-file + (expand-file-name "repos/straight.el/bootstrap.el" + (file-name-directory (directory-file-name straight-path)))) + (bootstrap-version 5)) + (when (file-exists-p bootstrap-file) + (setq default-package-manager 'straight) + (load bootstrap-file nil 'nomessage) + (add-to-list 'load-path async-path) + (when pkg-list + (dolist (pkg pkg-list) + (let* ((pkg-path (expand-file-name pkg straight-path)) + (autoload-file (expand-file-name + (format "%s-autoloads.el" pkg) + pkg-path))) + (add-to-list 'load-path pkg-path) + (if (file-exists-p autoload-file) + (load autoload-file nil 'nomessage) + (straight-use-package (intern pkg)))))))) + +(unless (eq default-package-manager 'straight) + (require 'package) + ;; User may be using a non standard \`package-user-dir'. + ;; Modify \`package-directory-list' instead of \`package-user-dir' + ;; in case the user starts Helm from a non-ELPA installation. + (unless (file-equal-p package-user-dir (locate-user-emacs-file "elpa")) + ;; Something like /home/you/.emacs.d/somedir/else/elpa/ + ;; starting from default-directory is wrong in case helm.sh is a symlink + ;; or e.g. helm --chdir foo have been used. + (add-to-list 'package-directory-list (directory-file-name + (file-name-directory + (directory-file-name initial-package-directory))))) + + (let* ((str-lst "$LOAD_PACKAGES") + (load-packages (and str-lst + (not (string= str-lst "")) + (split-string str-lst ",")))) + (setq package-load-list + (if (equal load-packages '("all")) + '(all) + (append '((helm-core t) (helm t) (async t) (popup t)) + (mapcar (lambda (p) (list (intern p) t)) load-packages))))) + + (package-initialize)) + +(add-to-list 'load-path initial-package-directory) + +(unless (> $TOOLBARS 0) + (setq default-frame-alist '((vertical-scroll-bars . nil) + (tool-bar-lines . 0) + (menu-bar-lines . 0) + (fullscreen . nil)))) +(blink-cursor-mode -1) +(load "helm-autoloads" nil t) +(helm-mode 1) +(with-eval-after-load 'tramp-cache (setq tramp-cache-read-persistent-data t)) +(with-eval-after-load 'auth-source (setq auth-source-save-behavior nil)) +(define-key global-map [remap find-file] 'helm-find-files) +(define-key global-map [remap occur] 'helm-occur) +(define-key global-map [remap list-buffers] 'helm-buffers-list) +(define-key global-map [remap dabbrev-expand] 'helm-dabbrev) +(define-key global-map [remap execute-extended-command] 'helm-M-x) +(define-key global-map [remap apropos-command] 'helm-apropos) +(unless (boundp 'completion-in-region-function) + (define-key lisp-interaction-mode-map [remap completion-at-point] 'helm-lisp-completion-at-point) + (define-key emacs-lisp-mode-map [remap completion-at-point] 'helm-lisp-completion-at-point)) +(add-hook 'kill-emacs-hook #'(lambda () (and (file-exists-p "$CONF_FILE") (delete-file "$CONF_FILE")))) +EOF + +$EMACS -Q -l "$CONF_FILE" "$@" diff --git a/org/elpa/helm-20230406.839/helm-adaptive.el b/org/elpa/helm-20230406.839/helm-adaptive.el new file mode 100644 index 0000000..98be39a --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-adaptive.el @@ -0,0 +1,284 @@ +;;; helm-adaptive.el --- Adaptive Sorting of Candidates. -*- lexical-binding: t -*- + +;; Original Author: Tamas Patrovics + +;; Copyright (C) 2007 Tamas Patrovics +;; Copyright (C) 2012 ~ 2023 Thierry Volpiatto + +;; 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 . + +;;; Code: + +(require 'cl-lib) +(require 'helm) + + +(defgroup helm-adapt nil + "Adaptative sorting of candidates for Helm." + :group 'helm) + +(defcustom helm-adaptive-history-file + (locate-user-emacs-file "helm-adaptive-history") + "Path of file where history information is stored. +When nil history is not saved nor restored after Emacs restart +unless you save/restore `helm-adaptive-history' with something +else like psession or desktop." + :type 'string) + +(defcustom helm-adaptive-history-length 50 + "Maximum number of candidates stored for a source." + :type 'number) + +(defcustom helm-adaptive-sort-by-frequent-recent-usage t + "Try to sort on an average of frequent and recent usage when non-nil. + +When nil sort on frequency usage only. + +Only frequency: +When candidate have low frequency, you have to hit on it many +times to make it going up on top. + +Frequency+recent: +Even with a low frequency, candidate go up on top. If a candidate +have a high frequency but it is not used since some time, it goes +down slowly, but as soon you reuse it it go up on top quickly." + :type 'boolean) + +;; Internal +(defvar helm-adaptive-done nil + "nil if history information is not yet stored for the current +selection.") + +(defvar helm-adaptive-history nil + "Contains the stored history information. +Format: ((SOURCE-NAME + (SELECTED-CANDIDATE (PATTERN . NUMBER-OF-USE) ...) ...) ...)") + +(defconst helm-adaptive-freq-coefficient 5) +(defconst helm-adaptive-recent-coefficient 2) + +(defun helm-adaptive-done-reset () + (setq helm-adaptive-done nil)) + +;;;###autoload +(define-minor-mode helm-adaptive-mode + "Toggle adaptive sorting in all sources." + :global t + (if helm-adaptive-mode + (progn + (unless helm-adaptive-history + (helm-adaptive-maybe-load-history)) + (add-hook 'kill-emacs-hook #'helm-adaptive-save-history) + ;; Should run at beginning of `helm-initial-setup'. + (add-hook 'helm-before-initialize-hook #'helm-adaptive-done-reset) + ;; Should run at beginning of `helm-exit-minibuffer'. + (add-hook 'helm-before-action-hook #'helm-adaptive-store-selection) + ;; Should run at beginning of `helm-select-action'. + (add-hook 'helm-select-action-hook #'helm-adaptive-store-selection)) + (helm-adaptive-save-history) + (setq helm-adaptive-history nil) + (remove-hook 'kill-emacs-hook #'helm-adaptive-save-history) + (remove-hook 'helm-before-initialize-hook #'helm-adaptive-done-reset) + (remove-hook 'helm-before-action-hook #'helm-adaptive-store-selection) + (remove-hook 'helm-select-action-hook #'helm-adaptive-store-selection))) + +(defun helm-adapt-use-adaptive-p (&optional source-name) + "Return current source only if it use adaptive history, nil otherwise." + (when helm-adaptive-mode + (let* ((source (or source-name (helm-get-current-source))) + (adapt-source (or (assoc-default 'filtered-candidate-transformer source) + (assoc-default 'candidate-transformer source)))) + (if (listp adapt-source) + (and (memq 'helm-adaptive-sort adapt-source) source) + (and (eq adapt-source 'helm-adaptive-sort) source))))) + +(defun helm-adaptive-store-selection () + "Store history information for the selected candidate." + (unless helm-adaptive-done + (setq helm-adaptive-done t) + (let ((source (helm-adapt-use-adaptive-p))) + (when source + (let* ((source-name (assoc-default 'name source)) + (source-info (or (assoc source-name helm-adaptive-history) + (progn + (push (list source-name) helm-adaptive-history) + (car helm-adaptive-history)))) + (selection (helm-get-selection nil t)) + (selection-info (progn + (setcdr source-info + (cons + (let ((found (assoc selection (cdr source-info)))) + (if (not found) + ;; new entry + (list selection) + ;; move entry to the beginning of the + ;; list, so that it doesn't get + ;; trimmed when the history is + ;; truncated + (setcdr source-info + (delete found (cdr source-info))) + found)) + (cdr source-info))) + (cadr source-info))) + (pattern-info (progn + (setcdr selection-info + (cons + (let ((found (assoc helm-pattern (cdr selection-info)))) + (if (not found) + ;; new entry + (cons helm-pattern 0) + ;; move entry to the beginning of the + ;; list, so if two patterns used the + ;; same number of times then the one + ;; used last appears first in the list + (setcdr selection-info + (delete found (cdr selection-info))) + found)) + (cdr selection-info))) + (cadr selection-info))) + (timestamp-info (helm-aif (assq 'timestamp (cdr selection-info)) + it + (setcdr selection-info (cons (cons 'timestamp 0) (cdr selection-info))) + (cadr selection-info)))) + ;; Increase usage count. + (setcdr pattern-info (1+ (cdr pattern-info))) + ;; Update timestamp. + (setcdr timestamp-info (float-time)) + ;; Truncate history if needed. + (if (> (length (cdr selection-info)) helm-adaptive-history-length) + (setcdr selection-info + (helm-take (cdr selection-info) helm-adaptive-history-length)))))))) + +(defun helm-adaptive-maybe-load-history () + "Load `helm-adaptive-history-file' which contain `helm-adaptive-history'. +Returns nil if `helm-adaptive-history-file' doesn't exist." + (when (and helm-adaptive-history-file + (file-readable-p helm-adaptive-history-file)) + (load-file helm-adaptive-history-file))) + +(defun helm-adaptive-save-history (&optional arg) + "Save history information to the file given by `helm-adaptive-history-file'." + (interactive "p") + (when helm-adaptive-history-file + (with-temp-buffer + (insert + ";; -*- mode: emacs-lisp -*-\n" + ";; History entries used for helm adaptive display.\n") + (let (print-length print-level) + (prin1 `(setq helm-adaptive-history ',helm-adaptive-history) + (current-buffer))) + (insert ?\n) + (write-region (point-min) (point-max) helm-adaptive-history-file nil + (unless arg 'quiet))))) + +(defun helm-adaptive-sort (candidates source) + "Sort the CANDIDATES for SOURCE by usage frequency. +This is a filtered candidate transformer you can use with the +`filtered-candidate-transformer' attribute." + (let* ((source-name (assoc-default 'name source)) + (source-info (assoc source-name helm-adaptive-history))) + (if source-info + (let ((usage + ;; Loop in the SOURCE entry of `helm-adaptive-history' + ;; and assemble a list containing the (CANDIDATE + ;; . USAGE-COUNT) pairs. + (cl-loop with cf = (if helm-adaptive-sort-by-frequent-recent-usage + helm-adaptive-freq-coefficient 1) + with cr = helm-adaptive-recent-coefficient + for (src-cand . infos) in (cdr source-info) + for count-freq = 0 + for count-rec = + (helm-aif (and helm-adaptive-sort-by-frequent-recent-usage + (assq 'timestamp infos)) + (* cr (+ (float-time) (cdr it))) + 0) + do (cl-loop for (pattern . score) in + (remove (assq 'timestamp infos) infos) + ;; If current pattern is equal to + ;; the previously used one then + ;; this candidate has priority + ;; (that's why its count-freq is + ;; boosted by 10000) and it only + ;; has to compete with other + ;; candidates which were also + ;; selected with the same pattern. + if (equal pattern helm-pattern) + return (setq count-freq (+ 10000 score)) + else do (cl-incf count-freq score)) + and collect (cons src-cand (+ (* count-freq cf) count-rec)) + into results + ;; Sort the list in descending order, so + ;; candidates with highest priority come + ;; first. + finally return + (sort results (lambda (first second) + (> (cdr first) (cdr second))))))) + (if (consp usage) + ;; Put those candidates first which have the highest usage count. + (cl-loop for (cand . _freq) in usage + for info = (or (and (assq 'multiline source) + (replace-regexp-in-string + "\n\\'" "" cand)) + ;; Some transformers like in + ;; bookmarks may add a leading + ;; space to provide additional + ;; infos like an icon as a + ;; display prop, strip out this + ;; leading space for + ;; comparison. Same for a + ;; trailing space (helm + ;; boookmark add bmk location as + ;; a display prop when + ;; displaying it). + (helm-aand (replace-regexp-in-string "\\` " "" cand) + (replace-regexp-in-string " \\'" "" it))) + when (cl-member info candidates + :test 'helm-adaptive-compare) + collect (car it) into sorted + and do (setq candidates + (cl-remove info candidates + :test 'helm-adaptive-compare)) + finally return (append sorted candidates)) + (message "Your `%s' is maybe corrupted or too old, \ +you should reinitialize it with `helm-reset-adaptive-history'" + helm-adaptive-history-file) + (sit-for 1) + candidates)) + ;; if there is no information stored for this source then do nothing + candidates))) + +;;;###autoload +(defun helm-reset-adaptive-history () + "Delete all `helm-adaptive-history' and his file. +Useful when you have a old or corrupted +`helm-adaptive-history-file'." + (interactive) + (when (y-or-n-p "Really delete all your `helm-adaptive-history'? ") + (setq helm-adaptive-history nil) + (when (and helm-adaptive-history-file + (file-exists-p helm-adaptive-history-file)) + (delete-file helm-adaptive-history-file)))) + +(defun helm-adaptive-compare (x y) + "Compare display parts if some of candidates X and Y. + +Arguments X and Y are cons cell in (DISPLAY . REAL) format or +atoms." + (equal (if (listp x) (car x) x) + (if (listp y) (car y) y))) + + +(provide 'helm-adaptive) + +;;; helm-adaptive.el ends here diff --git a/org/elpa/helm-20230406.839/helm-autoloads.el b/org/elpa/helm-20230406.839/helm-autoloads.el new file mode 100644 index 0000000..3c2604b --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-autoloads.el @@ -0,0 +1,1187 @@ +;;; helm-autoloads.el --- automatically extracted autoloads -*- lexical-binding: t -*- +;; +;;; Code: + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + + +;;;### (autoloads nil "helm-adaptive" "helm-adaptive.el" (0 0 0 0)) +;;; Generated autoloads from helm-adaptive.el + +(defvar helm-adaptive-mode nil "\ +Non-nil if Helm-Adaptive mode is enabled. +See the `helm-adaptive-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `helm-adaptive-mode'.") + +(custom-autoload 'helm-adaptive-mode "helm-adaptive" nil) + +(autoload 'helm-adaptive-mode "helm-adaptive" "\ +Toggle adaptive sorting in all sources. + +This is a minor mode. If called interactively, toggle the +`Helm-Adaptive mode' mode. If the prefix argument is positive, enable +the mode, and if it is zero or negative, disable the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable the +mode if ARG is nil, omitted, or is a positive number. Disable the +mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `(default-value \\='helm-adaptive-mode)'. + +The mode's hook is called both when the mode is enabled and when it is +disabled. + +\(fn &optional ARG)" t nil) + +(autoload 'helm-reset-adaptive-history "helm-adaptive" "\ +Delete all `helm-adaptive-history' and his file. +Useful when you have a old or corrupted +`helm-adaptive-history-file'." t nil) + +(register-definition-prefixes "helm-adaptive" '("helm-adapt")) + +;;;*** + +;;;### (autoloads nil "helm-bookmark" "helm-bookmark.el" (0 0 0 0)) +;;; Generated autoloads from helm-bookmark.el + +(autoload 'helm-bookmarks "helm-bookmark" "\ +Preconfigured `helm' for bookmarks." t nil) + +(autoload 'helm-filtered-bookmarks "helm-bookmark" "\ +Preconfigured `helm' for bookmarks (filtered by category). +Optional source `helm-source-bookmark-addressbook' is loaded only +if external addressbook-bookmark package is installed." t nil) + +(register-definition-prefixes "helm-bookmark" '("bmkext-jump-" "bookmark" "helm-")) + +;;;*** + +;;;### (autoloads nil "helm-buffers" "helm-buffers.el" (0 0 0 0)) +;;; Generated autoloads from helm-buffers.el + +(autoload 'helm-buffers-list "helm-buffers" "\ +Preconfigured `helm' to list buffers." t nil) + +(autoload 'helm-mini "helm-buffers" "\ +Preconfigured `helm' displaying `helm-mini-default-sources'." t nil) + +(register-definition-prefixes "helm-buffers" '("helm-")) + +;;;*** + +;;;### (autoloads nil "helm-color" "helm-color.el" (0 0 0 0)) +;;; Generated autoloads from helm-color.el + +(autoload 'helm-colors "helm-color" "\ +Preconfigured `helm' for color." t nil) + +(register-definition-prefixes "helm-color" '("helm-")) + +;;;*** + +;;;### (autoloads nil "helm-comint" "helm-comint.el" (0 0 0 0)) +;;; Generated autoloads from helm-comint.el + +(autoload 'helm-comint-prompts "helm-comint" "\ +Pre-configured `helm' to browse the prompts of the current comint buffer." t nil) + +(autoload 'helm-comint-prompts-all "helm-comint" "\ +Pre-configured `helm' to browse the prompts of all comint sessions." t nil) + +(autoload 'helm-comint-input-ring "helm-comint" "\ +Preconfigured `helm' that provide completion of `comint' history." t nil) + +(register-definition-prefixes "helm-comint" '("helm-")) + +;;;*** + +;;;### (autoloads nil "helm-command" "helm-command.el" (0 0 0 0)) +;;; Generated autoloads from helm-command.el + +(autoload 'helm-M-x "helm-command" "\ +Preconfigured `helm' for Emacs commands. +It is `helm' replacement of regular `M-x' +`execute-extended-command'. + +Unlike regular `M-x' Emacs vanilla `execute-extended-command' +command, the prefix args if needed, can be passed AFTER starting +`helm-M-x'. When a prefix arg is passed BEFORE starting +`helm-M-x', the first `C-u' while in `helm-M-x' session will +disable it. + +You can get help on each command by persistent action. + +\(fn ARG)" t nil) + +(register-definition-prefixes "helm-command" '("helm-")) + +;;;*** + +;;;### (autoloads nil "helm-dabbrev" "helm-dabbrev.el" (0 0 0 0)) +;;; Generated autoloads from helm-dabbrev.el + +(autoload 'helm-dabbrev "helm-dabbrev" "\ +Preconfigured helm for dynamic abbreviations." t nil) + +(register-definition-prefixes "helm-dabbrev" '("helm-dabbrev-")) + +;;;*** + +;;;### (autoloads nil "helm-elisp" "helm-elisp.el" (0 0 0 0)) +;;; Generated autoloads from helm-elisp.el + +(autoload 'helm-lisp-completion-at-point "helm-elisp" "\ +Preconfigured Helm for Lisp symbol completion at point." t nil) + +(autoload 'helm-get-first-line-documentation "helm-elisp" "\ +Return first line documentation of symbol SYM truncated at END-COLUMN. +If SYM is not documented, return \"Not documented\". +Argument NAME allows specifiying what function to use to display +documentation when SYM name is the same for function and variable. + +\(fn SYM &optional (NAME \"describe-function\") (END-COLUMN 72))" nil nil) + +(autoload 'helm-complete-file-name-at-point "helm-elisp" "\ +Preconfigured Helm to complete file name at point. + +\(fn &optional FORCE)" t nil) + +(autoload 'helm-lisp-indent "helm-elisp" nil t nil) + +(autoload 'helm-lisp-completion-or-file-name-at-point "helm-elisp" "\ +Preconfigured Helm to complete Lisp symbol or filename at point. +Filename completion happens if string start after or between a +double quote." t nil) + +(autoload 'helm-apropos "helm-elisp" "\ +Preconfigured Helm to describe commands, functions, variables and faces. +In non interactives calls DEFAULT argument should be provided as +a string, i.e. the `symbol-name' of any existing symbol. + +\(fn DEFAULT)" t nil) + +(autoload 'helm-manage-advice "helm-elisp" "\ +Preconfigured `helm' to disable/enable function advices." t nil) + +(autoload 'helm-locate-library "helm-elisp" "\ +Preconfigured helm to locate elisp libraries." t nil) + +(autoload 'helm-timers "helm-elisp" "\ +Preconfigured `helm' for timers." t nil) + +(autoload 'helm-complex-command-history "helm-elisp" "\ +Preconfigured `helm' for complex command history." t nil) + +(register-definition-prefixes "helm-elisp" '("helm-" "with-helm-show-completion")) + +;;;*** + +;;;### (autoloads nil "helm-elisp-package" "helm-elisp-package.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from helm-elisp-package.el + +(autoload 'helm-list-elisp-packages "helm-elisp-package" "\ +Preconfigured `helm' for listing and handling Emacs packages. + +\(fn ARG)" t nil) + +(autoload 'helm-list-elisp-packages-no-fetch "helm-elisp-package" "\ +Preconfigured Helm for Emacs packages. + +Same as `helm-list-elisp-packages' but don't fetch packages on +remote. Called with a prefix ARG always fetch packages on +remote. + +\(fn ARG)" t nil) + +(register-definition-prefixes "helm-elisp-package" '("helm-")) + +;;;*** + +;;;### (autoloads nil "helm-epa" "helm-epa.el" (0 0 0 0)) +;;; Generated autoloads from helm-epa.el + +(defvar helm-epa-mode nil "\ +Non-nil if Helm-Epa mode is enabled. +See the `helm-epa-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `helm-epa-mode'.") + +(custom-autoload 'helm-epa-mode "helm-epa" nil) + +(autoload 'helm-epa-mode "helm-epa" "\ +Enable helm completion on gpg keys in epa functions. + +This is a minor mode. If called interactively, toggle the `Helm-Epa +mode' mode. If the prefix argument is positive, enable the mode, and +if it is zero or negative, disable the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable the +mode if ARG is nil, omitted, or is a positive number. Disable the +mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `(default-value \\='helm-epa-mode)'. + +The mode's hook is called both when the mode is enabled and when it is +disabled. + +\(fn &optional ARG)" t nil) + +(autoload 'helm-epa-list-keys "helm-epa" "\ +List all gpg keys. +This is the helm interface for `epa-list-keys'." t nil) + +(register-definition-prefixes "helm-epa" '("helm-epa")) + +;;;*** + +;;;### (autoloads nil "helm-eshell" "helm-eshell.el" (0 0 0 0)) +;;; Generated autoloads from helm-eshell.el + +(autoload 'helm-esh-pcomplete "helm-eshell" "\ +Preconfigured `helm' to provide Helm completion in Eshell." t nil) + +(autoload 'helm-eshell-history "helm-eshell" "\ +Preconfigured Helm for Eshell history." t nil) + +(autoload 'helm-eshell-prompts "helm-eshell" "\ +Pre-configured `helm' to browse the prompts of the current Eshell." t nil) + +(autoload 'helm-eshell-prompts-all "helm-eshell" "\ +Pre-configured `helm' to browse the prompts of all Eshell sessions." t nil) + +(register-definition-prefixes "helm-eshell" '("helm-e")) + +;;;*** + +;;;### (autoloads nil "helm-eval" "helm-eval.el" (0 0 0 0)) +;;; Generated autoloads from helm-eval.el + +(autoload 'helm-eval-expression "helm-eval" "\ +Preconfigured `helm' for `helm-source-evaluation-result'. + +\(fn ARG)" t nil) + +(autoload 'helm-eval-expression-with-eldoc "helm-eval" "\ +Preconfigured `helm' for `helm-source-evaluation-result' with `eldoc' support." t nil) + +(autoload 'helm-calcul-expression "helm-eval" "\ +Preconfigured `helm' for `helm-source-calculation-result'." t nil) + +(register-definition-prefixes "helm-eval" '("helm-")) + +;;;*** + +;;;### (autoloads nil "helm-external" "helm-external.el" (0 0 0 0)) +;;; Generated autoloads from helm-external.el + +(autoload 'helm-run-external-command "helm-external" "\ +Preconfigured `helm' to run External PROGRAM asyncronously from Emacs. +If program is already running try to run `helm-raise-command' if +defined otherwise exit with error. You can set your own list of +commands with `helm-external-commands-list'." t nil) + +(register-definition-prefixes "helm-external" '("helm-")) + +;;;*** + +;;;### (autoloads nil "helm-fd" "helm-fd.el" (0 0 0 0)) +;;; Generated autoloads from helm-fd.el + +(register-definition-prefixes "helm-fd" '("helm-fd-")) + +;;;*** + +;;;### (autoloads nil "helm-files" "helm-files.el" (0 0 0 0)) +;;; Generated autoloads from helm-files.el + +(defvar helm-ff-icon-mode nil "\ +Non-nil if Helm-Ff-Icon mode is enabled. +See the `helm-ff-icon-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `helm-ff-icon-mode'.") + +(custom-autoload 'helm-ff-icon-mode "helm-files" nil) + +(autoload 'helm-ff-icon-mode "helm-files" "\ +Display icons from `all-the-icons' package in HFF when enabled. + +This is a minor mode. If called interactively, toggle the +`Helm-Ff-Icon mode' mode. If the prefix argument is positive, enable +the mode, and if it is zero or negative, disable the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable the +mode if ARG is nil, omitted, or is a positive number. Disable the +mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `(default-value \\='helm-ff-icon-mode)'. + +The mode's hook is called both when the mode is enabled and when it is +disabled. + +NOTE: This mode is building `helm-source-find-files', so if you enable +it from your init file, ensure to call it _after_ your defmethod's +`helm-setup-user-source' definitions (if some) to ensure they are called. + +\(fn &optional ARG)" t nil) + +(autoload 'helm-ff-clear-image-dired-thumbnails-cache "helm-files" "\ +Clear `helm-ff-image-dired-thumbnails-cache'. +You may want to do this after customizing +`image-dired-thumbnail-storage' which may change the place where +thumbnail files are stored." t nil) + +(autoload 'helm-ff-cleanup-image-dired-dir-and-cache "helm-files" "\ +Cleanup `image-dired-dir' directory. +Delete all thumb files that are no more associated with an existing +image file in `helm-ff-image-dired-thumbnails-cache'." t nil) + +(autoload 'helm-projects-history "helm-files" "\ + + +\(fn ARG)" t nil) + +(autoload 'helm-browse-project "helm-files" "\ +Preconfigured helm to browse projects. +Browse files and see status of project with its VCS. +Only HG and GIT are supported for now. +Fall back to `helm-browse-project-find-files' if current +directory is not under control of one of those VCS. +With a prefix ARG browse files recursively, with two prefix ARG +rebuild the cache. +If the current directory is found in the cache, start +`helm-browse-project-find-files' even with no prefix ARG. +NOTE: The prefix ARG have no effect on the VCS controlled +directories. + +Needed dependencies for VCS: + +and +. + +\(fn ARG)" t nil) + +(autoload 'helm-find-files "helm-files" "\ +Preconfigured `helm' for helm implementation of `find-file'. +Called with a prefix arg show history if some. +Don't call it from programs, use `helm-find-files-1' instead. +This is the starting point for nearly all actions you can do on +files. + +\(fn ARG)" t nil) + +(register-definition-prefixes "helm-files" '("eshell-command-aliases-list" "helm-")) + +;;;*** + +;;;### (autoloads nil "helm-find" "helm-find.el" (0 0 0 0)) +;;; Generated autoloads from helm-find.el + +(autoload 'helm-find "helm-find" "\ +Preconfigured `helm' for the find shell command. + +Recursively find files whose names are matched by all specified +globbing PATTERNs under the current directory using the external +program specified in `find-program' (usually \"find\"). Every +input PATTERN is silently wrapped into two stars: *PATTERN*. + +With prefix argument, prompt for a directory to search. + +When user option `helm-findutils-search-full-path' is non-nil, +match against complete paths, otherwise, against file names +without directory part. + +The (possibly empty) list of globbing PATTERNs can be followed by +the separator \"*\" plus any number of additional arguments that +are passed to \"find\" literally. + +\(fn ARG)" t nil) + +(register-definition-prefixes "helm-find" '("helm-")) + +;;;*** + +;;;### (autoloads nil "helm-font" "helm-font.el" (0 0 0 0)) +;;; Generated autoloads from helm-font.el + +(autoload 'helm-select-xfont "helm-font" "\ +Preconfigured `helm' to select Xfont." t nil) + +(autoload 'helm-ucs "helm-font" "\ +Preconfigured `helm' for `ucs-names'. + +Called with a prefix arg force reloading cache. + +\(fn ARG)" t nil) + +(register-definition-prefixes "helm-font" '("helm-")) + +;;;*** + +;;;### (autoloads nil "helm-for-files" "helm-for-files.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from helm-for-files.el + +(autoload 'helm-for-files "helm-for-files" "\ +Preconfigured `helm' for opening files. +Run all sources defined in `helm-for-files-preferred-list'." t nil) + +(autoload 'helm-multi-files "helm-for-files" "\ +Preconfigured helm like `helm-for-files' but running locate only on demand. + +Allow toggling back and forth from locate to others sources with +`helm-multi-files-toggle-locate-binding' key. +This avoids launching locate needlessly when what you are +searching for is already found." t nil) + +(autoload 'helm-recentf "helm-for-files" "\ +Preconfigured `helm' for `recentf'." t nil) + +(register-definition-prefixes "helm-for-files" '("helm-")) + +;;;*** + +;;;### (autoloads nil "helm-global-bindings" "helm-global-bindings.el" +;;;;;; (0 0 0 0)) +;;; Generated autoloads from helm-global-bindings.el + +(register-definition-prefixes "helm-global-bindings" '("helm-command-")) + +;;;*** + +;;;### (autoloads nil "helm-grep" "helm-grep.el" (0 0 0 0)) +;;; Generated autoloads from helm-grep.el + +(autoload 'helm-goto-precedent-file "helm-grep" "\ +Go to previous file in Helm grep/etags buffers." t nil) + +(autoload 'helm-goto-next-file "helm-grep" "\ +Go to previous file in Helm grep/etags buffers." t nil) + +(autoload 'helm-revert-next-error-last-buffer "helm-grep" "\ +Revert last `next-error' buffer from `current-buffer'. + +Accept to revert only `helm-grep-mode' or `helm-occur-mode' buffers. +Use this when you want to revert the `next-error' buffer after +modifications in `current-buffer'." t nil) + +(autoload 'helm-do-grep-ag "helm-grep" "\ +Preconfigured `helm' for grepping with AG in `default-directory'. +With prefix arg prompt for type if available with your AG +version. + +\(fn ARG)" t nil) + +(autoload 'helm-grep-do-git-grep "helm-grep" "\ +Preconfigured `helm' for git-grepping `default-directory'. +With a prefix arg ARG git-grep the whole repository. + +\(fn ARG)" t nil) + +(register-definition-prefixes "helm-grep" '("helm-")) + +;;;*** + +;;;### (autoloads nil "helm-help" "helm-help.el" (0 0 0 0)) +;;; Generated autoloads from helm-help.el + +(autoload 'helm-documentation "helm-help" "\ +Preconfigured `helm' for Helm documentation. +With a prefix arg refresh the documentation. + +Find here the documentation of all documented sources." t nil) + +(defvar helm-comp-read-mode-line "\\C/\\[helm-cr-empty-string]:Empty \\\\[helm-help]:Help \\[helm-select-action]:Act \\[helm-maybe-exit-minibuffer]/f1/f2/f-n:NthAct \\[helm-toggle-suspend-update]:Tog.suspend \\[helm-customize-group]:Conf") + +(defvar helm-read-file-name-mode-line-string "\\\\[helm-help]:Help C/\\[helm-cr-empty-string]:Empty \\\\[helm-select-action]:Act \\[helm-maybe-exit-minibuffer]/f1/f2/f-n:NthAct \\[helm-toggle-suspend-update]:Tog.suspend \\[helm-customize-group]:Conf" "\ +String displayed in mode-line in `helm-source-find-files'.") + +(defvar helm-top-mode-line "\\\\[helm-help]:Help \\\\[helm-select-action]:Act \\[helm-maybe-exit-minibuffer]/f1/f2/f-n:NthAct \\[helm-toggle-suspend-update]:Tog.suspend \\[helm-customize-group]:Conf") + +(register-definition-prefixes "helm-help" '("helm-")) + +;;;*** + +;;;### (autoloads nil "helm-id-utils" "helm-id-utils.el" (0 0 0 0)) +;;; Generated autoloads from helm-id-utils.el + +(autoload 'helm-gid "helm-id-utils" "\ +Preconfigured `helm' for `gid' command line of `ID-Utils'. +Need A database created with the command `mkid' above +`default-directory'. +Need id-utils as dependency which provide `mkid', `gid' etc.. +See ." t nil) + +(register-definition-prefixes "helm-id-utils" '("helm-gid-")) + +;;;*** + +;;;### (autoloads nil "helm-imenu" "helm-imenu.el" (0 0 0 0)) +;;; Generated autoloads from helm-imenu.el + +(autoload 'helm-imenu "helm-imenu" "\ +Preconfigured `helm' for `imenu'." t nil) + +(autoload 'helm-imenu-in-all-buffers "helm-imenu" "\ +Fetch Imenu entries in all buffers with similar mode as current. +A mode is similar as current if it is the same, it is derived +i.e. `derived-mode-p' or it have an association in +`helm-imenu-all-buffer-assoc'." t nil) + +(register-definition-prefixes "helm-imenu" '("helm-")) + +;;;*** + +;;;### (autoloads nil "helm-info" "helm-info.el" (0 0 0 0)) +;;; Generated autoloads from helm-info.el + +(autoload 'helm-info "helm-info" "\ +Preconfigured `helm' for searching Info files' indices. + +With a prefix argument \\[universal-argument], set REFRESH to +non-nil. + +Optional parameter REFRESH, when non-nil, re-evaluates +`helm-default-info-index-list'. If the variable has been +customized, set it to its saved value. If not, set it to its +standard value. See `custom-reevaluate-setting' for more. + +REFRESH is useful when new Info files are installed. If +`helm-default-info-index-list' has not been customized, the new +Info files are made available. + +\(fn &optional REFRESH)" t nil) + +(autoload 'helm-info-at-point "helm-info" "\ +Preconfigured `helm' for searching info at point." t nil) + +(register-definition-prefixes "helm-info" '("helm-")) + +;;;*** + +;;;### (autoloads nil "helm-locate" "helm-locate.el" (0 0 0 0)) +;;; Generated autoloads from helm-locate.el + +(autoload 'helm-projects-find-files "helm-locate" "\ +Find files with locate in `helm-locate-project-list'. +With a prefix arg refresh the database in each project. + +\(fn UPDATE)" t nil) + +(autoload 'helm-locate "helm-locate" "\ +Preconfigured `helm' for Locate. +Note: you can add locate options after entering pattern. +See \\='man locate' for valid options and also `helm-locate-command'. + +You can specify a local database with prefix argument ARG. +With two prefix arg, refresh the current local db or create it if +it doesn't exists. + +To create a user specific db, use +\"updatedb -l 0 -o db_path -U directory\". +Where db_path is a filename matched by +`helm-locate-db-file-regexp'. + +\(fn ARG)" t nil) + +(register-definition-prefixes "helm-locate" '("helm-")) + +;;;*** + +;;;### (autoloads nil "helm-man" "helm-man.el" (0 0 0 0)) +;;; Generated autoloads from helm-man.el + +(autoload 'helm-man-woman "helm-man" "\ +Preconfigured `helm' for Man and Woman pages. +With a prefix arg reinitialize the cache. + +\(fn ARG)" t nil) + +(register-definition-prefixes "helm-man" '("helm-")) + +;;;*** + +;;;### (autoloads nil "helm-misc" "helm-misc.el" (0 0 0 0)) +;;; Generated autoloads from helm-misc.el + +(defvar helm-minibuffer-history-mode nil "\ +Non-nil if Helm-Minibuffer-History mode is enabled. +See the `helm-minibuffer-history-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `helm-minibuffer-history-mode'.") + +(custom-autoload 'helm-minibuffer-history-mode "helm-misc" nil) + +(autoload 'helm-minibuffer-history-mode "helm-misc" "\ +Bind `helm-minibuffer-history-key' in al minibuffer maps. +This mode is enabled by `helm-mode', so there is no need to enable it directly. + +This is a minor mode. If called interactively, toggle the +`Helm-Minibuffer-History mode' mode. If the prefix argument is +positive, enable the mode, and if it is zero or negative, disable the +mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable the +mode if ARG is nil, omitted, or is a positive number. Disable the +mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `(default-value \\='helm-minibuffer-history-mode)'. + +The mode's hook is called both when the mode is enabled and when it is +disabled. + +\(fn &optional ARG)" t nil) + +(autoload 'helm-world-time "helm-misc" "\ +Preconfigured `helm' to show world time. +Default action change TZ environment variable locally to emacs." t nil) + +(autoload 'helm-insert-latex-math "helm-misc" "\ +Preconfigured helm for latex math symbols completion." t nil) + +(autoload 'helm-ratpoison-commands "helm-misc" "\ +Preconfigured `helm' to execute ratpoison commands." t nil) + +(autoload 'helm-stumpwm-commands "helm-misc" "\ +Preconfigured helm for stumpwm commands." t nil) + +(autoload 'helm-minibuffer-history "helm-misc" "\ +Preconfigured `helm' for `minibuffer-history'." t nil) + +(register-definition-prefixes "helm-misc" '("helm-")) + +;;;*** + +;;;### (autoloads nil "helm-mode" "helm-mode.el" (0 0 0 0)) +;;; Generated autoloads from helm-mode.el + +(autoload 'helm-comp-read "helm-mode" "\ +Read a string in the minibuffer, with helm completion. + +It is helm `completing-read' equivalent. + +- PROMPT is the prompt name to use. + +- COLLECTION can be a list, alist, vector, obarray or hash-table. + For alists and hash-tables their car are use as real value of + candidate unless ALISTP is non-nil. + It can be also a function that receives three arguments: + the values string, predicate and t. See `all-completions' for more details. + +Keys description: + +- TEST: A predicate called with one arg i.e candidate. + +- INITIAL-INPUT: Same as input arg in `helm'. + +- PRESELECT: See preselect arg of `helm'. + +- DEFAULT: This option is used only for compatibility with regular + Emacs `completing-read' (Same as DEFAULT arg of `completing-read'). + +- BUFFER: Name of helm-buffer. + +- MUST-MATCH: Candidate selected must be one of COLLECTION. + +- FUZZY: Enable fuzzy matching. + +- REVERSE-HISTORY: When non--nil display history source after current + source completion. + +- REQUIRES-PATTERN: Same as helm attribute, default is 0. + +- HISTORY: A symbol where each result will be saved. + If not specified as a symbol an error will popup. + When specified, all elements of HISTORY are displayed in + a special source before or after COLLECTION according to REVERSE-HISTORY. + The main difference with INPUT-HISTORY is that the result of the + completion is saved whereas in INPUT-HISTORY it is the minibuffer + contents which is saved when you exit. + Don't use the same symbol for INPUT-HISTORY and HISTORY. + NOTE: As mentionned above this has nothing to do with + `minibuffer-history-variable', therefore if you want to save this + history persistently, you will have to add this variable to the + relevant variable of your favorite tool for persistent emacs session + i.e. psession, desktop etc... + +- RAW-HISTORY: When non-nil do not remove backslashs if some in + HISTORY candidates. + +- INPUT-HISTORY: A symbol. The minibuffer input history will be + stored there, if nil or not provided, `minibuffer-history' + will be used instead. You can navigate in this history with + `M-p' and `M-n'. + Don't use the same symbol for INPUT-HISTORY and HISTORY. + +- CASE-FOLD: Same as `helm-case-fold-search'. + +- PERSISTENT-ACTION: A function called with one arg i.e candidate. + +- PERSISTENT-HELP: A string to document PERSISTENT-ACTION. + +- MODE-LINE: A string or list to display in mode line. + Default is `helm-comp-read-mode-line'. + +- KEYMAP: A keymap to use in this `helm-comp-read'. + (the keymap will be shared with history source) + +- NAME: The name related to this local source. + +- HEADER-NAME: A function to alter NAME, see `helm'. + +- EXEC-WHEN-ONLY-ONE: Bound `helm-execute-action-at-once-if-one' + to non--nil. (possibles values are t or nil). + +- VOLATILE: Use volatile attribute. + +- SORT: A predicate to give to `sort' e.g `string-lessp' + Use this only on small data as it is inefficient. + If you want to sort faster add a sort function to + FC-TRANSFORMER. + Note that FUZZY when enabled is already providing a sort function. + +- FC-TRANSFORMER: A `filtered-candidate-transformer' function + or a list of functions. + +- HIST-FC-TRANSFORMER: A `filtered-candidate-transformer' + function for the history source. + +- MARKED-CANDIDATES: If non-nil return candidate or marked candidates as a list. + +- NOMARK: When non--nil don't allow marking candidates. + +- ALISTP: + When non-nil (default) pass the value of (DISPLAY . REAL) + candidate in COLLECTION to action when COLLECTION is an alist or a + hash-table, otherwise DISPLAY is always returned as result on exit, + which is the default when using `completing-read'. + See `helm-comp-read-get-candidates'. + +- CANDIDATES-IN-BUFFER: when non--nil use a source build with + `helm-source-in-buffer' which is much faster. + Argument VOLATILE have no effect when CANDIDATES-IN-BUFFER is non--nil. + +- MATCH-PART: Allow matching only one part of candidate. + See match-part documentation in `helm-source'. + +- MATCH-DYNAMIC: See match-dynamic in `helm-source-sync' + It has no effect when used with CANDIDATES-IN-BUFFER. + +- ALLOW-NEST: Allow nesting this `helm-comp-read' in a helm session. + See `helm'. + +- MULTILINE: See multiline in `helm-source'. + +- COERCE: See coerce in `helm-source'. + +- GROUP: See group in `helm-source'. + +Any prefix args passed during `helm-comp-read' invocation will be recorded +in `helm-current-prefix-arg', otherwise if prefix args were given before +`helm-comp-read' invocation, the value of `current-prefix-arg' will be used. +That means you can pass prefix args before or after calling a command +that use `helm-comp-read'. See `helm-M-x' for example. + +\(fn PROMPT COLLECTION &key TEST INITIAL-INPUT DEFAULT PRESELECT (BUFFER \"*Helm Completions*\") MUST-MATCH FUZZY REVERSE-HISTORY (REQUIRES-PATTERN 0) (HISTORY nil SHISTORY) RAW-HISTORY INPUT-HISTORY (CASE-FOLD helm-comp-read-case-fold-search) (PERSISTENT-ACTION nil) (PERSISTENT-HELP \"DoNothing\") (MODE-LINE helm-comp-read-mode-line) HELP-MESSAGE (KEYMAP helm-comp-read-map) (NAME \"Helm Completions\") HEADER-NAME CANDIDATES-IN-BUFFER DIACRITICS MATCH-PART MATCH-DYNAMIC EXEC-WHEN-ONLY-ONE QUIT-WHEN-NO-CAND (VOLATILE t) SORT FC-TRANSFORMER HIST-FC-TRANSFORMER (MARKED-CANDIDATES helm-comp-read-use-marked) NOMARK (ALISTP t) (CANDIDATE-NUMBER-LIMIT helm-candidate-number-limit) MULTILINE ALLOW-NEST COERCE (GROUP \\='helm))" nil nil) + +(autoload 'helm-read-file-name "helm-mode" "\ +Read a file name with helm completion. + +It is helm `read-file-name' emulation. + +Argument PROMPT is the default prompt to use. + +Keys description: + +- NAME: Source name, default to \"Read File Name\". + +- INITIAL-INPUT: Where to start reading file name, + default to `default-directory' or $HOME. + +- BUFFER: `helm-buffer' name, defaults to \"*Helm Completions*\". + +- TEST: A predicate called with one arg \\='candidate'. + +- NORET: Allow disabling helm-ff-RET (have no effect if helm-ff-RET + isn't bound to RET). + +- CASE-FOLD: Same as `helm-case-fold-search'. + +- PRESELECT: helm preselection. + +- HISTORY: Display HISTORY in a special source. + +- MUST-MATCH: Can be \\='confirm, nil, or t. + +- FUZZY: Enable fuzzy matching when non-nil (Enabled by default). + +- MARKED-CANDIDATES: When non--nil return a list of marked candidates. + +- NOMARK: When non--nil don't allow marking candidates. + +- ALISTP: Don't use `all-completions' in history + (take effect only on history). + +- PERSISTENT-ACTION-IF: a persistent if action function. + +- PERSISTENT-HELP: persistent help message. + +- MODE-LINE: A mode line message, default is + `helm-read-file-name-mode-line-string'. + +\(fn PROMPT &key (NAME \"Read File Name\") INITIAL-INPUT (BUFFER \"*Helm file completions*\") TEST NORET (CASE-FOLD helm-file-name-case-fold-search) PRESELECT HISTORY MUST-MATCH (FUZZY t) DEFAULT MARKED-CANDIDATES (CANDIDATE-NUMBER-LIMIT helm-ff-candidate-number-limit) NOMARK (ALISTP t) (PERSISTENT-ACTION-IF \\='helm-find-files-persistent-action-if) (PERSISTENT-HELP \"Hit1 Expand Candidate, Hit2 or (C-u) Find file\") (MODE-LINE helm-read-file-name-mode-line-string))" nil nil) + +(defvar helm-mode nil "\ +Non-nil if Helm mode is enabled. +See the `helm-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `helm-mode'.") + +(custom-autoload 'helm-mode "helm-mode" nil) + +(autoload 'helm-mode "helm-mode" "\ +Toggle generic helm completion. + +All functions in Emacs that use `completing-read', +`read-file-name', `completion-in-region' and friends will use helm +interface when this mode is turned on. + +However you can modify this behavior for functions of your choice +with `helm-completing-read-handlers-alist'. + +Called with a positive arg, turn on unconditionally, with a +negative arg turn off. +You can toggle it with M-x `helm-mode'. + +About `ido-mode': +DO NOT enable `ido-everywhere' when using `helm-mode'. Instead of +using `ido-mode', add the commands where you want to use ido to +`helm-completing-read-handlers-alist' with `ido' as value. + +Note: This mode is incompatible with Emacs23. + +\(fn &optional ARG)" t nil) + +(register-definition-prefixes "helm-mode" '("helm-")) + +;;;*** + +;;;### (autoloads nil "helm-net" "helm-net.el" (0 0 0 0)) +;;; Generated autoloads from helm-net.el + +(autoload 'helm-browse-url-firefox "helm-net" "\ +Same as `browse-url-firefox' but detach from Emacs. + +So when you quit Emacs you can keep your Firefox session open and +not be prompted to kill the Firefox process. + +NOTE: Probably not supported on some systems (e.g., Windows). + +\(fn URL &optional IGNORE)" t nil) + +(autoload 'helm-browse-url-opera "helm-net" "\ +Browse URL with Opera browser and detach from Emacs. + +So when you quit Emacs you can keep your Opera session open and +not be prompted to kill the Opera process. + +NOTE: Probably not supported on some systems (e.g., Windows). + +\(fn URL &optional IGNORE)" t nil) + +(autoload 'helm-browse-url-chromium "helm-net" "\ +Browse URL with Google Chrome browser. + +\(fn URL &optional IGNORE)" t nil) + +(autoload 'helm-browse-url-uzbl "helm-net" "\ +Browse URL with uzbl browser. + +\(fn URL &optional IGNORE)" t nil) + +(autoload 'helm-browse-url-conkeror "helm-net" "\ +Browse URL with conkeror browser. + +\(fn URL &optional IGNORE)" t nil) + +(autoload 'helm-browse-url-nyxt "helm-net" "\ +Browse URL with nyxt browser. + +\(fn URL &optional IGNORE)" t nil) + +(autoload 'helm-surfraw "helm-net" "\ +Preconfigured `helm' to search PATTERN with search ENGINE. + +\(fn PATTERN ENGINE)" t nil) + +(autoload 'helm-google-suggest "helm-net" "\ +Preconfigured `helm' for Google search with Google suggest." t nil) + +(register-definition-prefixes "helm-net" '("helm-")) + +;;;*** + +;;;### (autoloads nil "helm-occur" "helm-occur.el" (0 0 0 0)) +;;; Generated autoloads from helm-occur.el + +(autoload 'helm-occur "helm-occur" "\ +Preconfigured helm for searching lines matching pattern in `current-buffer'. + +When `helm-source-occur' is member of +`helm-sources-using-default-as-input' which is the default, +symbol at point is searched at startup. + +When a region is marked search only in this region by narrowing. + +To search in multiples buffers start from one of the commands listing +buffers (i.e. a helm command using `helm-source-buffers-list' like +`helm-mini') and use the multi occur buffers action. + +This is the helm implementation that collect lines matching pattern +like vanilla Emacs `occur' but have nothing to do with it, the search +engine beeing completely different and also much faster." t nil) + +(autoload 'helm-occur-visible-buffers "helm-occur" "\ +Run helm-occur on all visible buffers in frame." t nil) + +(autoload 'helm-occur-from-isearch "helm-occur" "\ +Invoke `helm-occur' from isearch. + +To use this bind it to a key in `isearch-mode-map'." t nil) + +(autoload 'helm-multi-occur-from-isearch "helm-occur" "\ +Invoke `helm-multi-occur' from isearch. + +With a prefix arg, reverse the behavior of +`helm-moccur-always-search-in-current'. +The prefix arg can be set before calling +`helm-multi-occur-from-isearch' or during the buffer selection. + +To use this bind it to a key in `isearch-mode-map'." t nil) + +(register-definition-prefixes "helm-occur" '("helm-")) + +;;;*** + +;;;### (autoloads nil "helm-regexp" "helm-regexp.el" (0 0 0 0)) +;;; Generated autoloads from helm-regexp.el + +(autoload 'helm-regexp "helm-regexp" "\ +Preconfigured helm to build regexps. +`query-replace-regexp' can be run from there against found regexp." t nil) + +(register-definition-prefixes "helm-regexp" '("helm-")) + +;;;*** + +;;;### (autoloads nil "helm-ring" "helm-ring.el" (0 0 0 0)) +;;; Generated autoloads from helm-ring.el + +(autoload 'helm-mark-ring "helm-ring" "\ +Preconfigured `helm' for `helm-source-mark-ring'." t nil) + +(autoload 'helm-global-mark-ring "helm-ring" "\ +Preconfigured `helm' for `helm-source-global-mark-ring'." t nil) + +(autoload 'helm-all-mark-rings "helm-ring" "\ +Preconfigured `helm' for mark rings. +Source used are `helm-source-global-mark-ring' and +`helm-source-mark-ring'." t nil) + +(autoload 'helm-register "helm-ring" "\ +Preconfigured `helm' for Emacs registers." t nil) + +(autoload 'helm-show-kill-ring "helm-ring" "\ +Preconfigured `helm' for `kill-ring'. +It is drop-in replacement of `yank-pop'. + +First call open the kill-ring browser, next calls move to next line." t nil) + +(autoload 'helm-execute-kmacro "helm-ring" "\ +Preconfigured helm for keyboard macros. +Define your macros with `f3' and `f4'. +See (info \"(emacs) Keyboard Macros\") for detailed infos. +This command is useful when used with persistent action." t nil) + +(register-definition-prefixes "helm-ring" '("helm-")) + +;;;*** + +;;;### (autoloads nil "helm-semantic" "helm-semantic.el" (0 0 0 0)) +;;; Generated autoloads from helm-semantic.el + +(autoload 'helm-semantic "helm-semantic" "\ +Preconfigured `helm' for `semantic'. +If ARG is supplied, pre-select symbol at point instead of current. + +\(fn ARG)" t nil) + +(autoload 'helm-semantic-or-imenu "helm-semantic" "\ +Preconfigured helm for `semantic' or `imenu'. +If ARG is supplied, pre-select symbol at point instead of current +semantic tag in scope. + +If `semantic-mode' is active in the current buffer, then use +semantic for generating tags, otherwise fall back to `imenu'. +Fill in the symbol at point by default. + +\(fn ARG)" t nil) + +(register-definition-prefixes "helm-semantic" '("helm-s")) + +;;;*** + +;;;### (autoloads nil "helm-shell" "helm-shell.el" (0 0 0 0)) +;;; Generated autoloads from helm-shell.el + +(defalias 'helm-shell-prompts 'helm-comint-prompts) + +(defalias 'helm-shell-prompts-all 'helm-comint-prompts-all) + +;;;*** + +;;;### (autoloads nil "helm-sys" "helm-sys.el" (0 0 0 0)) +;;; Generated autoloads from helm-sys.el + +(defvar helm-top-poll-mode nil "\ +Non-nil if Helm-Top-Poll mode is enabled. +See the `helm-top-poll-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `helm-top-poll-mode'.") + +(custom-autoload 'helm-top-poll-mode "helm-sys" nil) + +(autoload 'helm-top-poll-mode "helm-sys" "\ +Refresh automatically helm top buffer once enabled. + +This is a minor mode. If called interactively, toggle the +`Helm-Top-Poll mode' mode. If the prefix argument is positive, enable +the mode, and if it is zero or negative, disable the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable the +mode if ARG is nil, omitted, or is a positive number. Disable the +mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `(default-value \\='helm-top-poll-mode)'. + +The mode's hook is called both when the mode is enabled and when it is +disabled. + +\(fn &optional ARG)" t nil) + +(autoload 'helm-top "helm-sys" "\ +Preconfigured `helm' for top command." t nil) + +(autoload 'helm-list-emacs-process "helm-sys" "\ +Preconfigured `helm' for Emacs process." t nil) + +(autoload 'helm-xrandr-set "helm-sys" "\ +Preconfigured helm for xrandr." t nil) + +(register-definition-prefixes "helm-sys" '("helm-")) + +;;;*** + +;;;### (autoloads nil "helm-tags" "helm-tags.el" (0 0 0 0)) +;;; Generated autoloads from helm-tags.el + +(autoload 'helm-etags-select "helm-tags" "\ +Preconfigured helm for etags. +If called with a prefix argument REINIT +or if any of the tag files have been modified, reinitialize cache. + +This function aggregates three sources of tag files: + + 1) An automatically located file in the parent directories, + by `helm-etags-get-tag-file'. + 2) `tags-file-name', which is commonly set by `find-tag' command. + 3) `tags-table-list' which is commonly set by `visit-tags-table' command. + +\(fn REINIT)" t nil) + +(register-definition-prefixes "helm-tags" '("helm-")) + +;;;*** + +;;;### (autoloads nil "helm-types" "helm-types.el" (0 0 0 0)) +;;; Generated autoloads from helm-types.el + +(register-definition-prefixes "helm-types" '("helm-")) + +;;;*** + +;;;### (autoloads nil "helm-utils" "helm-utils.el" (0 0 0 0)) +;;; Generated autoloads from helm-utils.el + +(defvar helm-popup-tip-mode nil "\ +Non-nil if Helm-Popup-Tip mode is enabled. +See the `helm-popup-tip-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `helm-popup-tip-mode'.") + +(custom-autoload 'helm-popup-tip-mode "helm-utils" nil) + +(autoload 'helm-popup-tip-mode "helm-utils" "\ +Show help-echo informations in a popup tip at end of line. + +This is a minor mode. If called interactively, toggle the +`Helm-Popup-Tip mode' mode. If the prefix argument is positive, +enable the mode, and if it is zero or negative, disable the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable the +mode if ARG is nil, omitted, or is a positive number. Disable the +mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `(default-value \\='helm-popup-tip-mode)'. + +The mode's hook is called both when the mode is enabled and when it is +disabled. + +\(fn &optional ARG)" t nil) + +(register-definition-prefixes "helm-utils" '("helm-" "with-helm-display-marked-candidates")) + +;;;*** + +;;;### (autoloads nil "helm-x-files" "helm-x-files.el" (0 0 0 0)) +;;; Generated autoloads from helm-x-files.el + +(register-definition-prefixes "helm-x-files" '("helm-")) + +;;;*** + +;;;### (autoloads nil nil ("helm-easymenu.el" "helm-pkg.el" "helm.el") +;;;;;; (0 0 0 0)) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; coding: utf-8 +;; End: +;;; helm-autoloads.el ends here diff --git a/org/elpa/helm-20230406.839/helm-bookmark.el b/org/elpa/helm-20230406.839/helm-bookmark.el new file mode 100644 index 0000000..e34ed40 --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-bookmark.el @@ -0,0 +1,823 @@ +;;; helm-bookmark.el --- Helm for Emacs regular Bookmarks. -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2023 Thierry Volpiatto + +;; 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 . + +;;; Code: +(require 'cl-lib) +(require 'bookmark) +(require 'helm) +(require 'helm-lib) +(require 'helm-help) +(require 'helm-types) +(require 'helm-utils) +(require 'helm-info) +(require 'helm-adaptive) +(require 'helm-net) + +(declare-function helm-browse-project "helm-files" (arg)) +(declare-function addressbook-bookmark-edit "ext:addressbook-bookmark.el" (bookmark)) +(declare-function all-the-icons-fileicon "ext:all-the-icons.el") +(declare-function all-the-icons-icon-for-file"ext:all-the-icons.el") +(declare-function all-the-icons-octicon "ext:all-the-icons.el") + + +(defgroup helm-bookmark nil + "Predefined configurations for `helm.el'." + :group 'helm) + +(defcustom helm-bookmark-show-location nil + "Show location of bookmark on display." + :type 'boolean) + +(defcustom helm-bookmark-default-filtered-sources + (append '(helm-source-bookmark-org + helm-source-bookmark-files&dirs + helm-source-bookmark-helm-find-files + helm-source-bookmark-info + helm-source-bookmark-gnus + helm-source-bookmark-mu4e + helm-source-bookmark-man + helm-source-bookmark-images + helm-source-bookmark-w3m) + (list 'helm-source-bookmark-uncategorized + 'helm-source-bookmark-set)) + "List of sources to use in `helm-filtered-bookmarks'." + :type '(repeat (choice symbol))) + +(defcustom helm-bookmark-use-icon nil + "Display candidates with an icon with `all-the-icons' when non nil." + :type 'boolean) + +(defcustom helm-bookmark-default-sort-method 'adaptive + "Sort method for `helm-filtered-bookmarks'. + +Value can be either \\='native' or \\='adaptive'. + +Once you use \\='native' the bookmark variable `bookmark-sort-flag' +will be honored." + :type '(choice + (symbol :tag "Helm adaptive sort method" adaptive) + (symbol :tag "Native bookmark sort method" native)) + ;; Don't use the :set function until functions and variables below + ;; are not loaded i.e. use set-default only for now. + :initialize 'custom-initialize-changed + :set (lambda (var val) + (set var val) + (cl-loop for s in (remove 'helm-source-bookmark-set + helm-bookmark-default-filtered-sources) + for fn = (intern (format "%s-builder" s)) + do (set s (funcall fn))))) + +(defgroup helm-bookmark-faces nil + "Customize the appearance of helm-bookmark." + :prefix "helm-" + :group 'helm-bookmark + :group 'helm-faces) + +(defface helm-bookmark-info + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "green")) + "Face used for W3m Emacs bookmarks (not w3m bookmarks)." + :group 'helm-bookmark-faces) + +(defface helm-bookmark-w3m + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "yellow")) + "Face used for W3m Emacs bookmarks (not w3m bookmarks)." + :group 'helm-bookmark-faces) + +(defface helm-bookmark-gnus + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "magenta")) + "Face used for Gnus bookmarks." + :group 'helm-bookmark-faces) + +(defface helm-bookmark-man + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "Orange4")) + "Face used for Woman/man bookmarks." + :group 'helm-bookmark-faces) + +(defface helm-bookmark-file + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "Deepskyblue2")) + "Face used for file bookmarks." + :group 'helm-bookmark-faces) + +(defface helm-bookmark-file-not-found + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "Slategray4")) + "Face used for file bookmarks." + :group 'helm-bookmark-faces) + +(defface helm-bookmark-directory + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :inherit helm-ff-directory)) + "Face used for file bookmarks." + :group 'helm-bookmark-faces) + +(defface helm-bookmark-addressbook + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "tomato")) + "Face used for addressbook bookmarks." + :group 'helm-bookmark-faces) + + +(defvar helm-bookmark-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map helm-map) + (define-key map (kbd "C-c o") #'helm-bookmark-run-jump-other-window) + (define-key map (kbd "C-c C-o") #'helm-bookmark-run-jump-other-frame) + (define-key map (kbd "C-c C-t") #'helm-bookmark-run-jump-other-tab) + (define-key map (kbd "C-d") #'helm-bookmark-run-delete) + (define-key map (kbd "C-]") #'helm-bookmark-toggle-filename) + (define-key map (kbd "M-e") #'helm-bookmark-run-edit) + map) + "Generic Keymap for Emacs bookmark sources.") + +(defclass helm-source-basic-bookmarks (helm-source-in-buffer helm-type-bookmark) + ((init :initform (lambda () + (bookmark-maybe-load-default-file) + (helm-init-candidates-in-buffer + 'global + (if (and (fboundp 'bookmark-maybe-sort-alist) + (fboundp 'bookmark-name-from-full-record)) + (mapcar 'bookmark-name-from-full-record + (bookmark-maybe-sort-alist)) + (bookmark-all-names))))) + (filtered-candidate-transformer :initform 'helm-bookmark-transformer) + (find-file-target :initform #'helm-bookmarks-quit-an-find-file-fn))) + +(defvar helm-source-bookmarks + (helm-make-source "Bookmarks" 'helm-source-basic-bookmarks) + "See (info \"(emacs)Bookmarks\").") + +(defun helm-bookmark-transformer (candidates _source) + (cl-loop for i in candidates + for loc = (bookmark-location i) + for len = (string-width i) + for trunc = (if (> len bookmark-bmenu-file-column) + (helm-substring i bookmark-bmenu-file-column) + i) + for sep = (make-string (- (+ bookmark-bmenu-file-column 2) + (length trunc)) + ? ) + if helm-bookmark-show-location + collect (cons (concat trunc sep (if (listp loc) (car loc) loc)) i) + else collect i)) + +(defun helm-bookmark-toggle-filename-1 (_candidate) + (let* ((real (helm-get-selection helm-buffer)) + (trunc (if (> (string-width real) bookmark-bmenu-file-column) + (helm-substring real bookmark-bmenu-file-column) + real))) + (setq helm-bookmark-show-location (not helm-bookmark-show-location)) + (helm-update (if helm-bookmark-show-location + (regexp-quote trunc) + (regexp-quote real))))) + +(helm-make-persistent-command-from-action helm-bookmark-toggle-filename + "Toggle bookmark location visibility." + 'toggle-filename 'helm-bookmark-toggle-filename-1) + +(defun helm-bookmark-jump-1 (candidate &optional fn) + (let (;; FIXME Why is prefarg necessary here? + (current-prefix-arg helm-current-prefix-arg) + non-essential) + (bookmark-jump candidate fn))) + +(defun helm-bookmark-jump (candidate) + "Jump to bookmark action." + (helm-bookmark-jump-1 candidate)) + +(defun helm-bookmark-jump-other-frame (candidate) + "Jump to bookmark in other frame action." + (helm-bookmark-jump-1 candidate #'switch-to-buffer-other-frame)) + +(defun helm-bookmark-jump-other-window (candidate) + "Jump to bookmark in other window action." + (helm-bookmark-jump-1 candidate #'switch-to-buffer-other-window)) + +(defun helm-bookmark-jump-other-tab (candidate) + "Jump to bookmark action." + (cl-assert (fboundp 'tab-bar-mode) nil "Tab-bar-mode not available") + (helm-bookmark-jump-1 candidate #'switch-to-buffer-other-tab)) + +;;; bookmark-set +;; +(defvar helm-source-bookmark-set + (helm-build-dummy-source "Set Bookmark" + :filtered-candidate-transformer + (lambda (_candidates _source) + (list (or (and (not (string= helm-pattern "")) + helm-pattern) + "Enter a bookmark name to record"))) + :action '(("Set bookmark" . (lambda (candidate) + (if (string= helm-pattern "") + (message "No bookmark name given for record") + (bookmark-set candidate)))))) + "See (info \"(emacs)Bookmarks\").") + + +;;; Predicates +;; +(defconst helm-bookmark--non-file-filename " - no file -" + "Name to use for `filename' entry, for non-file bookmarks.") + +(defun helm-bookmark-gnus-bookmark-p (bookmark) + "Return non-nil if BOOKMARK is a Gnus bookmark. +BOOKMARK is a bookmark name or a bookmark record." + (or (eq (bookmark-get-handler bookmark) 'bmkext-jump-gnus) + (eq (bookmark-get-handler bookmark) 'gnus-summary-bookmark-jump) + (eq (bookmark-get-handler bookmark) 'bookmarkp-jump-gnus))) + +(defun helm-bookmark-mu4e-bookmark-p (bookmark) + "Return non nil if BOOKMARK is a mu4e bookmark. +BOOKMARK is a bookmark name or a bookmark record." + (memq (bookmark-get-handler bookmark) + '(mu4e-bookmark-jump mu4e--jump-to-bookmark))) + +(defun helm-bookmark-w3m-bookmark-p (bookmark) + "Return non-nil if BOOKMARK is a W3m bookmark. +BOOKMARK is a bookmark name or a bookmark record." + (or (eq (bookmark-get-handler bookmark) 'bmkext-jump-w3m) + (eq (bookmark-get-handler bookmark) 'bookmark-w3m-bookmark-jump) + (eq (bookmark-get-handler bookmark) 'bookmarkp-jump-w3m))) + +(defun helm-bookmark-woman-bookmark-p (bookmark) + "Return non-nil if BOOKMARK is a Woman bookmark. +BOOKMARK is a bookmark name or a bookmark record." + (or (eq (bookmark-get-handler bookmark) 'bmkext-jump-woman) + (eq (bookmark-get-handler bookmark) 'woman-bookmark-jump) + (eq (bookmark-get-handler bookmark) 'bookmarkp-jump-woman))) + +(defun helm-bookmark-man-bookmark-p (bookmark) + "Return non-nil if BOOKMARK is a Man bookmark. +BOOKMARK is a bookmark name or a bookmark record." + (or (eq (bookmark-get-handler bookmark) 'bmkext-jump-man) + (eq (bookmark-get-handler bookmark) 'Man-bookmark-jump) + (eq (bookmark-get-handler bookmark) 'bookmarkp-jump-man))) + +(defun helm-bookmark-woman-man-bookmark-p (bookmark) + "Return non-nil if BOOKMARK is a Man or Woman bookmark. +BOOKMARK is a bookmark name or a bookmark record." + (or (helm-bookmark-man-bookmark-p bookmark) + (helm-bookmark-woman-bookmark-p bookmark))) + +(defun helm-bookmark-info-bookmark-p (bookmark) + "Return non-nil if BOOKMARK is an Info bookmark. +BOOKMARK is a bookmark name or a bookmark record." + (eq (bookmark-get-handler bookmark) 'Info-bookmark-jump)) + +(defun helm-bookmark-image-bookmark-p (bookmark) + "Return non-nil if BOOKMARK bookmarks an image file." + (if (stringp bookmark) + (assq 'image-type (assq bookmark bookmark-alist)) + (assq 'image-type bookmark))) + +(defun helm-bookmark-file-p (bookmark) + "Return non-nil if BOOKMARK bookmarks a file or directory. +BOOKMARK is a bookmark name or a bookmark record. +This excludes bookmarks of a more specific kind (Info, Gnus, and W3m)." + (let* ((filename (bookmark-get-filename bookmark)) + (isnonfile (equal filename helm-bookmark--non-file-filename))) + (and filename (not isnonfile) (not (bookmark-get-handler bookmark))))) + +(defun helm-bookmark-org-file-p (bookmark) + (let* ((filename (bookmark-get-filename bookmark))) + (or (string-suffix-p ".org" filename t) + (string-suffix-p ".org_archive" filename t)))) + +(defun helm-bookmark-helm-find-files-p (bookmark) + "Return non-nil if BOOKMARK bookmarks a `helm-find-files' session. +BOOKMARK is a bookmark name or a bookmark record." + (eq (bookmark-get-handler bookmark) 'helm-ff-bookmark-jump)) + +(defun helm-bookmark-addressbook-p (bookmark) + "Return non--nil if BOOKMARK is a contact recorded with addressbook-bookmark. +BOOKMARK is a bookmark name or a bookmark record." + (if (listp bookmark) + (string= (assoc-default 'type bookmark) "addressbook") + (string= (assoc-default + 'type (assoc bookmark bookmark-alist)) "addressbook"))) + +(defun helm-bookmark-uncategorized-bookmark-p (bookmark) + "Return non--nil if BOOKMARK match no known category." + (cl-loop for pred in '(helm-bookmark-org-file-p + helm-bookmark-addressbook-p + helm-bookmark-gnus-bookmark-p + helm-bookmark-mu4e-bookmark-p + helm-bookmark-w3m-bookmark-p + helm-bookmark-woman-man-bookmark-p + helm-bookmark-info-bookmark-p + helm-bookmark-image-bookmark-p + helm-bookmark-file-p + helm-bookmark-helm-find-files-p + helm-bookmark-addressbook-p) + never (funcall pred bookmark))) + +(defun helm-bookmark-filter-setup-alist (fn) + "Return a filtered `bookmark-alist' sorted alphabetically." + (cl-loop for b in (if (and (fboundp 'bookmark-maybe-sort-alist) + (eq helm-bookmark-default-sort-method 'native)) + (bookmark-maybe-sort-alist) + bookmark-alist) + for name = (car b) + when (funcall fn b) collect + (propertize name 'location (bookmark-location name)))) + +;;; Bookmark handlers +;; +(defvar w3m-async-exec) +(defun helm-bookmark-jump-w3m (bookmark) + "Jump to W3m bookmark BOOKMARK, setting a new tab. +If `browse-url-browser-function' is set to something else than +`w3m-browse-url' use it." + (require 'helm-net) + (let* ((file (or (bookmark-prop-get bookmark 'filename) + (bookmark-prop-get bookmark 'url))) + (buf (generate-new-buffer-name "*w3m*")) + (w3m-async-exec nil) + ;; If user don't have anymore w3m installed let it browse its + ;; bookmarks with default browser otherwise assume bookmark + ;; have been bookmarked from w3m and use w3m. + (browse-url-browser-function (or (and (fboundp 'w3m-browse-url) + (executable-find "w3m") + 'w3m-browse-url) + browse-url-browser-function)) + (really-use-w3m (equal browse-url-browser-function 'w3m-browse-url))) + (helm-browse-url file really-use-w3m) + (when really-use-w3m + (bookmark-default-handler + `("" (buffer . ,buf) . ,(bookmark-get-bookmark-record bookmark)))))) + +;; All bookmarks recorded with the handler provided with w3m +;; (`bookmark-w3m-bookmark-jump') will use our handler which open +;; the bookmark in a new tab or in an external browser depending +;; on `browse-url-browser-function'. +(defalias 'bookmark-w3m-bookmark-jump #'helm-bookmark-jump-w3m) + +;; Provide compatibility with old handlers provided in external +;; packages bookmark-extensions.el and bookmark+. +(defalias 'bmkext-jump-woman #'woman-bookmark-jump) +(defalias 'bmkext-jump-man #'Man-bookmark-jump) +(defalias 'bmkext-jump-w3m #'helm-bookmark-jump-w3m) +(defalias 'bmkext-jump-gnus #'gnus-summary-bookmark-jump) +(defalias 'bookmarkp-jump-gnus #'gnus-summary-bookmark-jump) +(defalias 'bookmarkp-jump-w3m #'helm-bookmark-jump-w3m) +(defalias 'bookmarkp-jump-woman #'woman-bookmark-jump) +(defalias 'bookmarkp-jump-man #'Man-bookmark-jump) + + +;;;; Filtered bookmark sources +;; +;; +(defclass helm-source-filtered-bookmarks (helm-source-in-buffer helm-type-bookmark) + ((filtered-candidate-transformer + :initform (delq nil + `(,(and (eq helm-bookmark-default-sort-method 'adaptive) + 'helm-adaptive-sort) + helm-highlight-bookmark))) + (find-file-target :initform #'helm-bookmarks-quit-an-find-file-fn))) + +(defun helm-bookmarks-quit-an-find-file-fn (source) + (let* ((sel (helm-get-selection nil nil source)) + (bmk (assoc (replace-regexp-in-string "\\`\\*" "" sel) + bookmark-alist))) + (helm-aif (bookmark-get-filename bmk) + (if (and helm--url-regexp + (string-match helm--url-regexp it)) + it (expand-file-name it)) + (expand-file-name default-directory)))) + +(defun helm-bookmark-build-source (name buildfn &optional class &rest args) + (apply #'helm-make-source name + (or class 'helm-source-filtered-bookmarks) + :init (lambda () + (bookmark-maybe-load-default-file) + (helm-init-candidates-in-buffer + 'global (funcall buildfn))) + args)) + +;;; W3m bookmarks. +;; +(defun helm-bookmark-w3m-setup-alist () + "Specialized filter function for bookmarks w3m." + (helm-bookmark-filter-setup-alist 'helm-bookmark-w3m-bookmark-p)) + +(defun helm-source-bookmark-w3m-builder () + (helm-bookmark-build-source "Bookmark W3m" #'helm-bookmark-w3m-setup-alist)) + +(defvar helm-source-bookmark-w3m (helm-source-bookmark-w3m-builder)) + +;;; Images +;; +(defun helm-bookmark-images-setup-alist () + "Specialized filter function for images bookmarks." + (helm-bookmark-filter-setup-alist 'helm-bookmark-image-bookmark-p)) + +(defun helm-source-bookmark-images-builder () + (helm-bookmark-build-source "Bookmark Images" #'helm-bookmark-images-setup-alist)) + +(defvar helm-source-bookmark-images (helm-source-bookmark-images-builder)) + +;;; Woman Man +;; +(defun helm-bookmark-man-setup-alist () + "Specialized filter function for bookmarks w3m." + (helm-bookmark-filter-setup-alist 'helm-bookmark-woman-man-bookmark-p)) + +(defun helm-source-bookmark-man-builder () + (helm-bookmark-build-source "Bookmark Woman&Man" #'helm-bookmark-man-setup-alist)) + +(defvar helm-source-bookmark-man (helm-source-bookmark-man-builder)) + +;;; Org files +;; +(defun helm-bookmark-org-setup-alist () + "Specialized filter function for Org file bookmarks." + (helm-bookmark-filter-setup-alist 'helm-bookmark-org-file-p)) + +(defun helm-source-bookmark-org-builder () + (helm-bookmark-build-source "Bookmark Org files" #'helm-bookmark-org-setup-alist)) + +(defvar helm-source-bookmark-org (helm-source-bookmark-org-builder)) + +;;; Gnus +;; +(defun helm-bookmark-gnus-setup-alist () + "Specialized filter function for bookmarks gnus." + (helm-bookmark-filter-setup-alist 'helm-bookmark-gnus-bookmark-p)) + +(defun helm-source-bookmark-gnus-builder () + (helm-bookmark-build-source "Bookmark Gnus" #'helm-bookmark-gnus-setup-alist)) + +(defvar helm-source-bookmark-gnus (helm-source-bookmark-gnus-builder)) + +;;; Mu4e +;; +(defun helm-bookmark-mu4e-setup-alist () + (helm-bookmark-filter-setup-alist 'helm-bookmark-mu4e-bookmark-p)) + +(defun helm-source-bookmark-mu4e-builder () + (helm-bookmark-build-source "Bookmark Mu4e" #'helm-bookmark-mu4e-setup-alist)) + +(defvar helm-source-bookmark-mu4e (helm-source-bookmark-mu4e-builder)) + +;;; Info +;; +(defun helm-bookmark-info-setup-alist () + "Specialized filter function for bookmarks info." + (helm-bookmark-filter-setup-alist 'helm-bookmark-info-bookmark-p)) + +(defun helm-source-bookmark-info-builder () + (helm-bookmark-build-source "Bookmark Info" #'helm-bookmark-info-setup-alist)) + +(defvar helm-source-bookmark-info (helm-source-bookmark-info-builder)) + +;;; Files and directories +;; +(defun helm-bookmark-local-files-setup-alist () + "Specialized filter function for bookmarks locals files." + (helm-bookmark-filter-setup-alist 'helm-bookmark-file-p)) + +(defun helm-source-bookmark-files&dirs-builder () + (helm-bookmark-build-source + "Bookmark Files&Directories" #'helm-bookmark-local-files-setup-alist)) + +(defvar helm-source-bookmark-files&dirs + (helm-source-bookmark-files&dirs-builder)) + +;;; Helm find files sessions. +;; +(defun helm-bookmark-helm-find-files-setup-alist () + "Specialized filter function for `helm-find-files' bookmarks." + (helm-bookmark-filter-setup-alist 'helm-bookmark-helm-find-files-p)) + +(defun helm-bookmark-browse-project (candidate) + "Run `helm-browse-project' from action." + (with-helm-default-directory + (bookmark-get-filename candidate) + (helm-browse-project nil))) + +(helm-make-command-from-action helm-bookmark-run-browse-project + "Run `helm-bookmark-browse-project' from keyboard." + 'helm-bookmark-browse-project) + +(defvar helm-bookmark-find-files-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map helm-bookmark-map) + (define-key map (kbd "C-x C-d") #'helm-bookmark-run-browse-project) + map)) + +;; Same as `helm-source-filtered-bookmarks' but override actions and keymap +;; specifically for helm-find-files bookmarks. +(defclass helm-bookmark-override-inheritor (helm-source) ()) + +(cl-defmethod helm--setup-source ((source helm-bookmark-override-inheritor)) + ;; Ensure `helm-source-in-buffer' method is called. + (cl-call-next-method) + (setf (slot-value source 'action) + (helm-append-at-nth + (cl-loop for (name . action) in helm-type-bookmark-actions + ;; We don't want those actions in helm-find-files bookmarks. + unless (memq action '(helm-bookmark-jump-other-frame + helm-bookmark-jump-other-window + helm-bookmark-jump-other-tab)) + collect (cons name action)) + '(("Browse project" . helm-bookmark-browse-project)) 1)) + (setf (slot-value source 'keymap) helm-bookmark-find-files-map)) + +(defclass helm-bookmark-find-files-class (helm-source-filtered-bookmarks + helm-bookmark-override-inheritor) + ()) + +(defun helm-source-bookmark-helm-find-files-builder () + (helm-bookmark-build-source + "Bookmark helm-find-files sessions" + #'helm-bookmark-helm-find-files-setup-alist + 'helm-bookmark-find-files-class + :persistent-action (lambda (_candidate) (ignore)) + :persistent-help "Do nothing")) + +(defvar helm-source-bookmark-helm-find-files + (helm-source-bookmark-helm-find-files-builder)) + +;;; Uncategorized bookmarks +;; +(defun helm-bookmark-uncategorized-setup-alist () + "Specialized filter function for uncategorized bookmarks." + (helm-bookmark-filter-setup-alist 'helm-bookmark-uncategorized-bookmark-p)) + +(defun helm-source-bookmark-uncategorized-builder () + (helm-bookmark-build-source + "Bookmark uncategorized" #'helm-bookmark-uncategorized-setup-alist)) + +(defvar helm-source-bookmark-uncategorized + (helm-source-bookmark-uncategorized-builder)) + + +;;; Transformer +;; +(defun helm-highlight-bookmark (bookmarks _source) + "Used as `filtered-candidate-transformer' to colorize bookmarks." + (let ((non-essential t)) + (cl-loop for i in bookmarks + for isfile = (bookmark-get-filename i) + for hff = (helm-bookmark-helm-find-files-p i) + for handlerp = (and (fboundp 'bookmark-get-handler) + (bookmark-get-handler i)) + for isw3m = (and (fboundp 'helm-bookmark-w3m-bookmark-p) + (helm-bookmark-w3m-bookmark-p i)) + for isgnus = (and (fboundp 'helm-bookmark-gnus-bookmark-p) + (helm-bookmark-gnus-bookmark-p i)) + for ismu4e = (and (fboundp 'helm-bookmark-mu4e-bookmark-p) + (helm-bookmark-mu4e-bookmark-p i)) + for isman = (and (fboundp 'helm-bookmark-man-bookmark-p) ; Man + (helm-bookmark-man-bookmark-p i)) + for iswoman = (and (fboundp 'helm-bookmark-woman-bookmark-p) ; Woman + (helm-bookmark-woman-bookmark-p i)) + for isannotation = (bookmark-get-annotation i) + for isabook = (string= (bookmark-prop-get i 'type) + "addressbook") + for isinfo = (eq handlerp 'Info-bookmark-jump) + for loc = (bookmark-location i) + for len = (string-width i) + for trunc = (if (and helm-bookmark-show-location + (> len bookmark-bmenu-file-column)) + (helm-substring + i bookmark-bmenu-file-column) + i) + for icon = (when helm-bookmark-use-icon + (cond ((and isfile hff) + (all-the-icons-octicon "file-directory")) + ((and isfile isinfo) (all-the-icons-octicon "info")) + (isfile (all-the-icons-icon-for-file isfile)) + ((or iswoman isman) + (all-the-icons-fileicon "man-page")) + ((or isgnus ismu4e) + (all-the-icons-octicon "mail-read")))) + ;; Add a * if bookmark have annotation + if (and isannotation (not (string-equal isannotation ""))) + do (setq trunc (concat "*" (if helm-bookmark-show-location trunc i))) + for sep = (and helm-bookmark-show-location + (make-string (- (+ bookmark-bmenu-file-column 2) + (string-width trunc)) + ? )) + for bmk = (cond ( ;; info buffers + isinfo + (propertize trunc 'face 'helm-bookmark-info + 'help-echo isfile)) + ( ;; w3m buffers + isw3m + (propertize trunc 'face 'helm-bookmark-w3m + 'help-echo isfile)) + ( ;; gnus buffers + isgnus + (propertize trunc 'face 'helm-bookmark-gnus + 'help-echo isfile)) + ( ;; Man Woman + (or iswoman isman) + (propertize trunc 'face 'helm-bookmark-man + 'help-echo isfile)) + ( ;; Addressbook + isabook + (propertize trunc 'face 'helm-bookmark-addressbook)) + (;; Directories (helm-find-files) + hff + (if (and (file-remote-p isfile) + (not (file-remote-p isfile nil t))) + (propertize trunc 'face 'helm-bookmark-file-not-found + 'help-echo isfile) + (propertize trunc 'face 'helm-bookmark-directory + 'help-echo isfile))) + ( ;; Directories (dired) + (and isfile + ;; This is needed because `non-essential' + ;; is not working on Emacs-24.2 and the behavior + ;; of tramp seems to have changed since previous + ;; versions (Need to reenter password even if a + ;; first connection have been established, + ;; probably when host is named differently + ;; i.e machine/localhost) + (and (not (file-remote-p isfile)) + (file-directory-p isfile))) + (propertize trunc 'face 'helm-bookmark-directory + 'help-echo isfile)) + ( ;; Non existing files. + (and isfile + ;; Be safe and call `file-exists-p' + ;; only if file is not remote or + ;; remote but connected. + (or (and (file-remote-p isfile) + (not (file-remote-p isfile nil t))) + (not (file-exists-p isfile)))) + (propertize trunc 'face 'helm-bookmark-file-not-found + 'help-echo isfile)) + ( ;; regular files + t + (propertize trunc 'face 'helm-bookmark-file + 'help-echo isfile))) + collect (if helm-bookmark-show-location + (cons (concat (and icon (propertize " " 'display (concat icon " "))) + bmk + (propertize + " " 'display + (concat sep (if (listp loc) (car loc) loc)))) + i) + (cons (concat (and icon (propertize " " 'display (concat icon " "))) + bmk) + i))))) + + +;;; Edit/rename/save bookmarks. +;; +;; +(defun helm-bookmark-edit-bookmark (bookmark-name) + "Edit bookmark's name and file name, and maybe save them. +BOOKMARK-NAME is the current (old) name of the bookmark to be +renamed." + (let ((bmk (helm-bookmark-get-bookmark-from-name bookmark-name)) + (handler (bookmark-prop-get bookmark-name 'handler))) + (if (eq handler 'addressbook-bookmark-jump) + (addressbook-bookmark-edit + (assoc bmk bookmark-alist)) + (helm-bookmark-edit-bookmark-1 bookmark-name handler)))) + +(defun helm-bookmark-edit-bookmark-1 (bookmark-name handler) + (let* ((helm--reading-passwd-or-string t) + (bookmark-fname (bookmark-get-filename bookmark-name)) + (bookmark-loc (bookmark-prop-get bookmark-name 'location)) + (message-id (bookmark-prop-get bookmark-name 'message-id)) + (new-name (read-from-minibuffer "Name: " bookmark-name)) + (new-loc (and (or bookmark-fname bookmark-loc) + (read-from-minibuffer "FileName or Location: " + (or bookmark-fname + (if (consp bookmark-loc) + (car bookmark-loc) + bookmark-loc))))) + (new-message-id (and (memq handler '(mu4e--jump-to-bookmark + mu4e-bookmark-jump)) + (read-string "Message-id: " message-id)))) + (when (and (not (equal new-name "")) + (or (not (equal new-loc "")) + (not (equal new-message-id ""))) + (y-or-n-p "Save changes? ")) + (if bookmark-fname + (progn + (helm-bookmark-rename bookmark-name new-name 'batch) + (bookmark-set-filename new-name new-loc)) + (bookmark-prop-set + (bookmark-get-bookmark bookmark-name) + (cond (new-loc 'location) + (new-message-id 'message-id)) + (or new-loc new-message-id)) + (helm-bookmark-rename bookmark-name new-name 'batch)) + (helm-bookmark-maybe-save-bookmark) + (list new-name new-loc)))) + +(defun helm-bookmark-maybe-save-bookmark () + "Increment save counter and maybe save `bookmark-alist'." + (setq bookmark-alist-modification-count (1+ bookmark-alist-modification-count)) + (when (bookmark-time-to-save-p) (bookmark-save))) + +(defun helm-bookmark-rename (old &optional new batch) + "Change bookmark's name from OLD to NEW. +Interactively: + If called from the keyboard, then prompt for OLD. + If called from the menubar, select OLD from a menu. +If NEW is nil, then prompt for its string value. + +If BATCH is non-nil, then do not rebuild the menu list. + +While the user enters the new name, repeated `C-w' inserts +consecutive words from the buffer into the new bookmark name." + (interactive (list (bookmark-completing-read "Old bookmark name"))) + (bookmark-maybe-historicize-string old) + (bookmark-maybe-load-default-file) + (save-excursion (skip-chars-forward " ") (setq bookmark-yank-point (point))) + (setq bookmark-current-buffer (current-buffer)) + (let ((newname (or new (read-from-minibuffer + "New name: " nil + (let ((now-map (copy-keymap minibuffer-local-map))) + (define-key now-map "\C-w" #'bookmark-yank-word) + now-map) + nil 'bookmark-history)))) + (bookmark-set-name old newname) + (setq bookmark-current-bookmark newname) + (unless batch (bookmark-bmenu-surreptitiously-rebuild-list)) + (helm-bookmark-maybe-save-bookmark) newname)) + +(helm-make-command-from-action helm-bookmark-run-edit + "Run `helm-bookmark-edit-bookmark' from keyboard." + 'helm-bookmark-edit-bookmark) + + +(helm-make-command-from-action helm-bookmark-run-jump-other-frame + "Jump to bookmark other frame from keyboard." + 'helm-bookmark-jump-other-frame) + +(helm-make-command-from-action helm-bookmark-run-jump-other-window + "Jump to bookmark other window from keyboard." + 'helm-bookmark-jump-other-window) + +(helm-make-command-from-action helm-bookmark-run-jump-other-tab + "Jump to bookmark other tab from keyboard." + 'helm-bookmark-jump-other-tab) + +(helm-make-command-from-action helm-bookmark-run-delete + "Delete bookmark from keyboard." + 'helm-delete-marked-bookmarks) + +(defun helm-bookmark-get-bookmark-from-name (bmk) + "Return bookmark name even if it is a bookmark with annotation. +E.g. prepended with *." + (let ((bookmark (replace-regexp-in-string "\\`\\*" "" bmk))) + (if (assoc bookmark bookmark-alist) bookmark bmk))) + +(defun helm-delete-marked-bookmarks (_ignore) + "Delete this bookmark or all marked bookmarks." + (dolist (i (helm-marked-candidates)) + (bookmark-delete (helm-bookmark-get-bookmark-from-name i) + 'batch))) + + +;;;###autoload +(defun helm-bookmarks () + "Preconfigured `helm' for bookmarks." + (interactive) + (helm :sources '(helm-source-bookmarks + helm-source-bookmark-set) + :buffer "*helm bookmarks*" + :default (buffer-name helm-current-buffer))) + +;;;###autoload +(defun helm-filtered-bookmarks () + "Preconfigured `helm' for bookmarks (filtered by category). +Optional source `helm-source-bookmark-addressbook' is loaded only +if external addressbook-bookmark package is installed." + (interactive) + (when helm-bookmark-use-icon + (require 'all-the-icons)) + (helm :sources helm-bookmark-default-filtered-sources + :prompt "Search Bookmark: " + :buffer "*helm filtered bookmarks*" + :default (list (thing-at-point 'symbol) + (buffer-name helm-current-buffer)))) + +(provide 'helm-bookmark) + +;;; helm-bookmark.el ends here diff --git a/org/elpa/helm-20230406.839/helm-buffers.el b/org/elpa/helm-20230406.839/helm-buffers.el new file mode 100644 index 0000000..d9bf199 --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-buffers.el @@ -0,0 +1,1177 @@ +;;; helm-buffers.el --- helm support for buffers. -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2023 Thierry Volpiatto + +;; 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 . + +;;; Code: + +(require 'cl-lib) +(require 'helm) +(require 'helm-types) +(require 'helm-utils) +(require 'helm-grep) +(require 'helm-regexp) +(require 'helm-help) +(require 'helm-occur) + +(declare-function helm-comp-read "helm-mode") +(declare-function helm-browse-project "helm-files") +(declare-function helm-ff-switch-to-shell "helm-files") +(declare-function all-the-icons-icon-for-file "ext:all-the-icons.el") +(declare-function all-the-icons-octicon "ext:all-the-icons.el") + +(defvar all-the-icons-mode-icon-alist) +(defvar dired-buffers) +(defvar org-directory) +(defvar helm-ff-default-directory) + + +(defgroup helm-buffers nil + "Buffers related Applications and libraries for Helm." + :group 'helm) + +(defcustom helm-boring-buffer-regexp-list + '("\\` " "\\`\\*helm" "\\`\\*Echo Area" "\\`\\*Minibuf") + "The regexp list that match boring buffers. +Buffer candidates matching these regular expression will be +filtered from the list of candidates if the +`helm-skip-boring-buffers' candidate transformer is used." + :type '(repeat (choice regexp))) + +(defcustom helm-white-buffer-regexp-list nil + "The regexp list of not boring buffers. +These buffers will be displayed even if they match one of +`helm-boring-buffer-regexp-list'." + :type '(repeat (choice regexp))) + +(defcustom helm-buffers-favorite-modes '(lisp-interaction-mode + emacs-lisp-mode + text-mode + org-mode) + "List of preferred mode to open new buffers with." + :type '(repeat (choice function))) + +(defcustom helm-buffer-max-length 20 + "Max length of buffer names before truncate. +When disabled (nil) use the longest `buffer-name' length found." + :type '(choice (const :tag "Disabled" nil) + (integer :tag "Length before truncate"))) + +(defcustom helm-buffer-details-flag t + "Always show details in buffer list when non-nil." + :type 'boolean) + +(defcustom helm-buffers-fuzzy-matching nil + "Fuzzy matching buffer names when non-nil. +Only buffer names are fuzzy matched when this is enabled, +`major-mode' matching is not affected by this." + :type 'boolean) + +(defcustom helm-buffer-skip-remote-checking nil + "Ignore checking for `file-exists-p' on remote files." + :type 'boolean) + +(defcustom helm-buffers-truncate-lines t + "Truncate lines in `helm-buffers-list' when non-nil." + :type 'boolean) + +(defcustom helm-buffers-left-margin-width helm-left-margin-width + "`left-margin-width' value for `helm-mini' and `helm-buffers-list'." + :type 'integer) + +(defcustom helm-mini-default-sources '(helm-source-buffers-list + helm-source-recentf + helm-source-buffer-not-found) + "Default sources list used in `helm-mini'. + +When adding a source here it is up to you to ensure the library +of this source is accessible and properly loaded." + :type '(repeat (choice symbol))) + +(defcustom helm-buffers-end-truncated-string "..." + "The string to display at end of truncated buffer names." + :type 'string) + +(defcustom helm-buffers-column-separator " " + "Separator for columns in buffer listing." + :type 'string) + +(defcustom helm-buffer--pretty-names '((dired-mode . "Dired") + (lisp-interaction-mode . "Lisp Inter")) + "An alist specifying pretty names for modes. +Most of the time buffer's `mode-name' is a string so no need to +add it here as there is no need to compute it, but sometimes it +may be a mode-line specification which may be costly to compute, +in this case add here the pretty name as a string to avoid this +costly computation. Also if some pretty names are too long you +can add your own abbreviation here." + :type '(alist :key-type symbol :value-type string)) + +(defcustom helm-buffers-maybe-switch-to-tab nil + "Switch to buffer in its tab when non nil. +This has no effect when `tab-bar-mode' is not available." + :type 'boolean) + +(defcustom helm-buffer-list-reorder-fn #'helm-buffers-reorder-buffer-list + "A function in charge of ordering the initial buffer list. +It takes two arguments VISIBLES buffers and OTHERS buffers. +Arg VISIBLES handles the buffers visibles in this frame. +Arg OTHERS handles all the other buffers. +You can write a function that reorder VISIBLES and OTHERS as you +want. +Default function returns OTHERS buffers on top and VISIBLES +buffer at the end. See `helm-buffers-reorder-buffer-list'." + :type 'function) + +(defcustom helm-buffers-sort-fn helm-fuzzy-sort-fn + "The sort function to use in `helm-buffers-list'. + +Default to `helm-fuzzy-sort-fn' you can use +`helm-fuzzy-matching-sort-fn-preserve-ties-order' as alternative if +you want to keep the recentest order when narrowing candidates." + :type 'function) + +(defcustom helm-buffers-show-icons nil + "Prefix buffer names with an icon when non nil." + :type 'boolean) + + +;;; Faces +;; +;; +(defgroup helm-buffers-faces nil + "Customize the appearance of helm-buffers." + :prefix "helm-" + :group 'helm-buffers + :group 'helm-faces) + +(defface helm-buffer-saved-out + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "red" :background "black")) + "Face used for buffer files modified outside of emacs." + :group 'helm-buffers-faces) + +(defface helm-buffer-not-saved + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "Indianred2")) + "Face used for buffer files not already saved on disk." + :group 'helm-buffers-faces) + +(defface helm-buffer-modified + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :inherit font-lock-comment-face)) + "Face used for modified buffers." + :group 'helm-buffers-faces) + +(defface helm-no-file-buffer-modified + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "orange" :background "black")) + "Face used for modified buffers." + :group 'helm-buffers-faces) + +(defface helm-buffer-size + `((((background dark)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "RosyBrown") + (((background light)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "SlateGray")) + "Face used for buffer size." + :group 'helm-buffers-faces) + +(defface helm-buffer-process + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "Sienna3")) + "Face used for process status in buffer." + :group 'helm-buffers-faces) + +(defface helm-buffer-directory + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "DarkRed" :background "LightGray")) + "Face used for directories in `helm-buffers-list'." + :group 'helm-buffers-faces) + +(defface helm-buffer-file + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :inherit font-lock-builtin-face)) + "Face for buffer file names in `helm-buffers-list'." + :group 'helm-buffers-faces) + +(defface helm-buffer-archive + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "Gold")) + "Face for archive file names in `helm-buffers-list'." + :group 'helm-buffers-faces) + +(defface helm-non-file-buffer + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :inherit italic)) + "Face used for non-file buffers in `helm-buffers-list'." + :group 'helm-buffers-faces) + +(defvar helm-buffers-tick-counter nil + "Allows recording local changes to a non-file buffer. +Typical usage of this var is for modes that want to see if their +buffers have changed since last visit. +Such programs may want to record tick counter after visiting +their buffers like this: + + (setq helm-buffers-tick-counter (buffer-modified-tick)) + +See bug#1917. + +Note that this variable is buffer-local.") +(make-variable-buffer-local 'helm-buffers-tick-counter) + + +;;; Buffers keymap +;; +(defvar helm-buffer-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map helm-map) + ;; No need to have separate command for grep and zgrep + ;; as we don't use recursivity for buffers. + ;; So use zgrep for both as it is capable to handle non--compressed files. + (define-key map (kbd "M-g s") #'helm-buffer-run-zgrep) + (define-key map (kbd "C-s") #'helm-buffers-run-occur) + (define-key map (kbd "C-x C-d") #'helm-buffers-run-browse-project) + (define-key map (kbd "C-c o") #'helm-buffer-switch-other-window) + (define-key map (kbd "C-c C-o") #'helm-buffer-switch-other-frame) + (define-key map (kbd "M-g M-g") #'helm-buffer-run-goto-line) + (define-key map (kbd "C-c =") #'helm-buffer-run-ediff) + (define-key map (kbd "M-=") #'helm-buffer-run-ediff-merge) + (define-key map (kbd "C-=") #'helm-buffer-diff-persistent) + (define-key map (kbd "M-G") #'helm-buffer-revert-persistent) + (define-key map (kbd "C-c d") #'helm-buffer-run-kill-persistent) + (define-key map (kbd "M-D") #'helm-buffer-run-kill-buffers) + (define-key map (kbd "C-x C-s") #'helm-buffer-save-persistent) + (define-key map (kbd "C-x s") #'helm-buffer-run-save-some-buffers) + (define-key map (kbd "C-M-%") #'helm-buffer-run-query-replace-regexp) + (define-key map (kbd "M-%") #'helm-buffer-run-query-replace) + (define-key map (kbd "M-R") #'helm-buffer-run-rename-buffer) + (define-key map (kbd "M-e") #'helm-buffer-run-switch-to-shell) + (define-key map (kbd "C-]") #'helm-toggle-buffers-details) + (define-key map (kbd "C-c a") #'helm-buffers-toggle-show-hidden-buffers) + (define-key map (kbd "C-M-SPC") #'helm-buffers-mark-similar-buffers) + (when (fboundp 'tab-bar-mode) + (define-key map (kbd "C-c C-t") #'helm-buffers-switch-to-buffer-new-tab)) + map) + "Keymap for buffer sources in helm.") + + +(defvar helm-buffer-max-len-mode nil) +(defvar helm-buffers-in-project-p nil) +(defvar helm-source-buffers-list nil) + +(defun helm-buffers-list--init () + (require 'dired) + ;; Bug#51 Create the list before `helm-buffer' creation. + ;; We were using a global cache in the past and 'candidates was + ;; bound to this cache, this was a problem when using more than one + ;; source with a different 'buffer-list fn as the same cache was + ;; reused in each source (Bug#1907), now 'candidates attr is set + ;; directly so that each list of candidates is local to source. + (helm-set-attr 'candidates (funcall (helm-get-attr 'buffer-list))) + (let ((result (cl-loop with allbufs = (memq 'helm-shadow-boring-buffers + (helm-get-attr + 'filtered-candidate-transformer + helm-source-buffers-list)) + for b in (if allbufs + (helm-get-attr 'candidates) + (helm-skip-boring-buffers + (helm-get-attr 'candidates) + helm-source-buffers-list)) + maximize (length b) into len-buf + maximize (length (helm-buffer--format-mode-name b)) + into len-mode + finally return (cons len-buf len-mode)))) + (unless (default-value 'helm-buffer-max-length) + (helm-set-local-variable 'helm-buffer-max-length (car result))) + (unless (default-value 'helm-buffer-max-len-mode) + (helm-set-local-variable 'helm-buffer-max-len-mode (cdr result))))) + +(defclass helm-source-buffers (helm-source-sync helm-type-buffer) + ((buffer-list + :initarg :buffer-list + :initform #'helm-buffer-list + :custom function + :documentation + " A function with no arguments to create buffer list.") + (init :initform 'helm-buffers-list--init) + (multimatch :initform nil) + (match :initform 'helm-buffers-match-function) + (persistent-action :initform 'helm-buffers-list-persistent-action) + (keymap :initform 'helm-buffer-map) + (find-file-target :initform #'helm-buffers-quit-and-find-file-fn) + (migemo :initform 'nomultimatch) + (volatile :initform t) + (nohighlight :initform t) + (resume :initform (lambda () (setq helm-buffers-in-project-p nil))) + (help-message :initform 'helm-buffer-help-message))) + +(cl-defun helm-buffers-create-new-buffer-1 (candidate &optional (display-func 'switch-to-buffer)) + (let ((mjm (or (and helm-current-prefix-arg + (intern-soft (helm-comp-read + "Major-mode: " + helm-buffers-favorite-modes))) + (cl-loop for (r . m) in auto-mode-alist + when (string-match r candidate) + return m))) + (buffer (get-buffer-create candidate))) + (if mjm + (with-current-buffer buffer (funcall mjm)) + (set-buffer-major-mode buffer)) + (funcall display-func buffer))) + +(defun helm-buffers-create-new-buffer (candidate) + (helm-buffers-create-new-buffer-1 candidate)) + +(defun helm-buffers-create-new-buffer-ow (candidate) + (helm-buffers-create-new-buffer-1 candidate 'switch-to-buffer-other-window)) + +(helm-make-command-from-action helm-buffers-not-found-run-switch-ow + "Run create new buffer other window action from keymap." + 'helm-buffers-create-new-buffer-ow) + +(defun helm-buffers-create-new-buffer-of (candidate) + (helm-buffers-create-new-buffer-1 candidate 'switch-to-buffer-other-frame)) + +(helm-make-command-from-action helm-buffers-not-found-run-switch-of + "Run create new buffer other frame action from keymap." + 'helm-buffers-create-new-buffer-of) + +(defvar helm-buffer-not-found-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map helm-map) + (define-key map (kbd "C-c o") #'helm-buffers-not-found-run-switch-ow) + (define-key map (kbd "C-c C-o") #'helm-buffers-not-found-run-switch-of) + map) + "Keymap for `helm-source-buffer-not-found' source.") + +(defvar helm-source-buffer-not-found + (helm-build-dummy-source + "Create buffer" + :action (helm-make-actions + "Create buffer (C-u choose mode)" + #'helm-buffers-create-new-buffer + "Create buffer other window (C-u choose mode)" + #'helm-buffers-create-new-buffer-ow + "Create buffer other frame (C-u choose mode)" + #'helm-buffers-create-new-buffer-of) + :keymap helm-buffer-not-found-map)) + + +(defun helm-buffers-get-visible-buffers () + "Returns buffers visibles on current frame." + (let (result) + (walk-windows + (lambda (x) + (push (buffer-name (window-buffer x)) result)) + nil 'visible) + result)) + +(defun helm-buffer-list-1 (&optional visibles) + (cl-loop for b in (buffer-list) + for bn = (buffer-name b) + unless (member bn visibles) + collect bn)) + +(defun helm-buffers-reorder-buffer-list (visibles others) + "Default function to reorder buffer-list. +Arg VISIBLES handles the buffers visibles in this frame. +Arg OTHERS handles all the other buffers. +This function returns OTHERS buffers on top and VISIBLES buffer +at the end." + (nconc others visibles)) + +(defun helm-buffer-list () + "Return the current list of buffers. +The list is reordered with `helm-buffer-list-reorder-fn'." + (let* ((visibles (helm-buffers-get-visible-buffers)) + (others (helm-buffer-list-1 visibles))) + (funcall helm-buffer-list-reorder-fn visibles others))) + +(defun helm-buffer-size (buffer) + "Return size of BUFFER." + (with-current-buffer buffer + (save-restriction + (widen) + (helm-file-human-size + (- (position-bytes (point-max)) + (position-bytes (point-min))))))) + +(defun helm-buffer--show-details (buf-name prefix help-echo + size mode dir face1 face2 + proc details type) + (append + (list + (let* ((buf-fname (buffer-file-name (get-buffer buf-name))) + (ext (if buf-fname (helm-file-name-extension buf-fname) "")) + (bmode (with-current-buffer buf-name major-mode)) + (icon (when helm-buffers-show-icons + (helm-aif (assq bmode all-the-icons-mode-icon-alist) + (apply (cadr it) (cddr it)) + (cond ((eq type 'dired) + (all-the-icons-octicon "file-directory")) + (buf-fname + (all-the-icons-icon-for-file buf-fname)) + (t (all-the-icons-octicon "star" :v-adjust 0.0)))))) + (buf-name (propertize buf-name 'face face1 + 'help-echo help-echo + 'type type))) + (when (condition-case _err + (string-match (format "\\.\\(%s\\)" ext) buf-name) + (invalid-regexp nil)) + (add-face-text-property + (match-beginning 1) (match-end 1) + 'helm-ff-file-extension nil buf-name)) + (if icon + (concat icon " " prefix buf-name) + (concat prefix buf-name)))) + (and details + (list size mode + (propertize + (if proc + (format "(%s %s in `%s')" + (process-name proc) + (process-status proc) dir) + (format "(in `%s')" dir)) + 'face face2))))) + +(defun helm-buffer--format-mode-name (buf) + "Prevent using `format-mode-line' as much as possible." + (with-current-buffer buf + (helm-acond ((assq major-mode helm-buffer--pretty-names) + (cdr it)) + ((stringp mode-name) mode-name) + (t (format-mode-line mode-name nil nil (get-buffer buf)))))) + +(defun helm-buffer--details (buffer &optional details) + (require 'dired) + (let* ((mode (helm-buffer--format-mode-name buffer)) + (buf (get-buffer buffer)) + (size (propertize (helm-buffer-size buf) + 'face 'helm-buffer-size)) + (proc (get-buffer-process buf)) + (dir (with-current-buffer buffer + (helm-aif default-directory (abbreviate-file-name it)))) + (file-name (helm-aif (buffer-file-name buf) (abbreviate-file-name it))) + (name (buffer-name buf)) + (name-prefix (when (and dir (file-remote-p dir)) + (propertize "@ " 'face 'helm-ff-prefix))) + (archive-p (and (fboundp 'tramp-archive-file-name-p) + (tramp-archive-file-name-p dir)))) + (when name-prefix + ;; Remote tramp buffer names may be hexified, make them more readable. + (setq dir (helm-url-unhex-string dir) + name (helm-url-unhex-string name))) + ;; Handle tramp archive buffers specially. + (if archive-p + (helm-buffer--show-details + name name-prefix file-name size mode dir + 'helm-buffer-archive 'helm-buffer-process nil details 'filebuf) + ;; No fancy things on remote buffers. + (if (and name-prefix helm-buffer-skip-remote-checking) + (helm-buffer--show-details + name name-prefix file-name size mode dir + 'helm-buffer-file 'helm-buffer-process nil details 'filebuf) + (cond + (;; A dired buffer. + (rassoc buf dired-buffers) + (helm-buffer--show-details + name name-prefix dir size mode dir + 'helm-buffer-directory 'helm-buffer-process nil details 'dired)) + ;; A buffer file modified somewhere outside of emacs.=>red + ((and file-name + (file-exists-p file-name) + (not (verify-visited-file-modtime buf))) + (helm-buffer--show-details + name name-prefix file-name size mode dir + 'helm-buffer-saved-out 'helm-buffer-process nil details 'modout)) + ;; A new buffer file not already saved on disk (or a deleted file) .=>indianred2 + ((and file-name (not (file-exists-p file-name))) + (helm-buffer--show-details + name name-prefix file-name size mode dir + 'helm-buffer-not-saved 'helm-buffer-process nil details 'notsaved)) + ;; A buffer file modified and not saved on disk.=>orange + ((and file-name (buffer-modified-p buf)) + (helm-buffer--show-details + name name-prefix file-name size mode dir + 'helm-buffer-modified 'helm-buffer-process nil details 'mod)) + ;; A buffer file not modified and saved on disk.=>green + (file-name + (helm-buffer--show-details + name name-prefix file-name size mode dir + 'helm-buffer-file 'helm-buffer-process nil details 'filebuf)) + ;; A non-file, modified buffer See bug#1917 + ((with-current-buffer name + (and helm-buffers-tick-counter + (/= helm-buffers-tick-counter (buffer-modified-tick)))) + (helm-buffer--show-details + name (and proc name-prefix) dir size mode dir + 'helm-no-file-buffer-modified 'helm-buffer-process proc details 'nofile-mod)) + ;; Any non--file buffer.=>italic + (t + (helm-buffer--show-details + name (and proc name-prefix) dir size mode dir + 'helm-non-file-buffer 'helm-buffer-process proc details 'nofile))))))) + +(defun helm-highlight-buffers (buffers _source) + "Transformer function to highlight BUFFERS list. +Should be called after others transformers i.e. (boring +buffers)." + (cl-assert helm-fuzzy-matching-highlight-fn nil "Wrong type argument functionp: nil") + (cl-loop with helm-buffers-show-icons = (and (featurep 'all-the-icons) + (default-toplevel-value + 'helm-buffers-show-icons)) + for i in buffers + for (name size mode meta) = (if helm-buffer-details-flag + (helm-buffer--details i 'details) + (helm-buffer--details i)) + for truncbuf = (if (> (string-width name) helm-buffer-max-length) + (helm-substring-by-width + name helm-buffer-max-length + helm-buffers-end-truncated-string) + (concat name + (make-string + (- (+ helm-buffer-max-length + (length + helm-buffers-end-truncated-string)) + (string-width name)) + ? ))) + for len = (length mode) + when (> len helm-buffer-max-len-mode) + do (setq helm-buffer-max-len-mode len) + for fmode = (concat (make-string + (- (max helm-buffer-max-len-mode len) len) ? ) + mode) + ;; The max length of a number should be 1023.9X where X is the + ;; units, this is 7 characters. + for formatted-size = (and size (format "%7s" size)) + collect (let ((helm-pattern (helm-buffers--pattern-sans-filters + (and helm-buffers-fuzzy-matching "")))) + (cons (if helm-buffer-details-flag + (concat + (funcall helm-fuzzy-matching-highlight-fn + truncbuf) + helm-buffers-column-separator + formatted-size + helm-buffers-column-separator + fmode + helm-buffers-column-separator + meta) + (funcall helm-fuzzy-matching-highlight-fn name)) + (get-buffer i))))) + +(defun helm-buffer--get-preselection (buffer) + (let* ((bufname (buffer-name buffer)) + (dispbuf (car (helm-buffer--details buffer))) + (len-dispbuf (string-width dispbuf)) + (len-prefix (- len-dispbuf (string-width bufname)))) + (when (and bufname + (file-remote-p (with-current-buffer bufname + default-directory))) + (setq bufname (concat "@ " (helm-url-unhex-string bufname)))) + (concat "^[[:multibyte:] ]*" + (if (and (null helm-buffer-details-flag) + (numberp helm-buffer-max-length) + (> len-dispbuf helm-buffer-max-length)) + (regexp-quote + (helm-substring-by-width + bufname + (- helm-buffer-max-length len-prefix) + helm-buffers-end-truncated-string)) + (concat (regexp-quote bufname) + (if helm-buffer-details-flag + "$" "[[:blank:]]+")))))) + +(defun helm-toggle-buffers-details () + (interactive) + (with-helm-alive-p + (let* ((buf (helm-get-selection)) + (preselect (helm-buffer--get-preselection buf))) + (setq helm-buffer-details-flag (not helm-buffer-details-flag)) + (helm-force-update (lambda () + (helm-awhile (re-search-forward preselect nil t) + (helm-mark-current-line) + (when (equal buf (helm-get-selection)) + (cl-return t)))))))) +(put 'helm-toggle-buffers-details 'helm-only t) + +(defun helm-buffers--pattern-sans-filters (&optional separator) + (cl-loop for p in (helm-mm-split-pattern helm-pattern) + unless (member (substring p 0 1) '("*" "/" "@" "!")) + collect p into lst + finally return (mapconcat #'identity lst (or separator " ")))) + +(defun helm-buffers-sort-transformer (candidates source) + (cl-assert helm-buffers-sort-fn nil "Wrong type argument functionp: nil") + (if (string= helm-pattern "") + candidates + (let ((helm-pattern (helm-buffers--pattern-sans-filters))) + (funcall helm-buffers-sort-fn candidates source)))) + +(defun helm-buffers-mark-similar-buffers-1 (&optional type) + (with-helm-window + (let* ((src (helm-get-current-source)) + (sel (helm-get-selection nil 'withprop src)) + (type (or type (get-text-property + (min 2 (length sel)) 'type sel)))) + (helm-map-candidates-in-source src + (lambda (_cand) (helm-make-visible-mark)) + (lambda (cand) + (and (not (helm-this-visible-mark)) + (eq (get-text-property 2 'type cand) type)))) + (helm-mark-current-line) + (helm-display-mode-line src t) + (when helm-marked-candidates + (message "%s candidates marked" (length helm-marked-candidates)) + (set-window-margins (selected-window) 1))))) + +(defun helm-buffers-mark-similar-buffers () + "Mark All buffers that have same property `type' than current. +I.e. same color." + (interactive) + (with-helm-alive-p + (let ((marked (helm-marked-candidates))) + (if (and (>= (length marked) 1) + (with-helm-window helm-visible-mark-overlays)) + (helm-unmark-all) + (helm-buffers-mark-similar-buffers-1))))) +(put 'helm-buffers-mark-similar-buffers 'helm-only t) + + +;;; match functions +;; +(defun helm-buffer--match-mjm (pattern mjm) + (when (string-match "\\`\\*" pattern) + (cl-loop with patterns = (split-string (substring pattern 1) ",") + for pat in patterns + if (string-match "\\`!" pat) + collect (string-match (substring pat 1) mjm) into neg + else collect (string-match pat mjm) into pos + finally return + (let ((neg-test (cl-loop for i in neg thereis (numberp i))) + (pos-test (cl-loop for i in pos thereis (numberp i)))) + (or + (and neg (not pos) (not neg-test)) + (and pos pos-test) + (and neg neg-test (not neg-test))))))) + +(defvar helm-buffer--memo-hash (make-hash-table :test 'equal)) +(defun helm-buffer--memo-pattern (pattern) + (or (gethash pattern helm-buffer--memo-hash) + (puthash pattern (helm--mapconcat-pattern pattern) + helm-buffer--memo-hash))) + +(defun helm-buffer--match-pattern (pattern candidate &optional nofuzzy) + (let ((bfn (if (and helm-buffers-fuzzy-matching + (not nofuzzy) + (not helm-migemo-mode) + (not (string-match "\\`\\^" pattern))) + #'helm-buffer--memo-pattern + #'identity)) + (mfn (if helm-migemo-mode + #'helm-mm-migemo-string-match #'string-match))) + (if (string-match "\\`!" pattern) + (not (funcall mfn (funcall bfn (substring pattern 1)) + candidate)) + (funcall mfn (funcall bfn pattern) candidate)))) + +(defun helm-buffers--match-from-mjm (candidate) + (let* ((cand (replace-regexp-in-string "^\\s-\\{1\\}" "" candidate)) + (buf (get-buffer cand)) + (regexp (cl-loop with pattern = helm-pattern + for p in (helm-mm-split-pattern pattern) + when (string-match "\\`\\*" p) + return p))) + (if regexp + (when buf + (with-current-buffer buf + (let ((mjm (symbol-name major-mode))) + (helm-buffer--match-mjm regexp mjm)))) + t))) + +(defun helm-buffers--match-from-pat (candidate) + (let* ((regexp-list (cl-loop with pattern = helm-pattern + for p in (helm-mm-split-pattern pattern) + unless (string-match + "\\`\\(\\*\\|/\\|@\\)" p) + collect p)) + (nofuzzy (cdr regexp-list))) + (if regexp-list + (cl-loop for re in regexp-list + always (helm-buffer--match-pattern re candidate nofuzzy)) + t))) + +(defun helm-buffers--match-from-inside (candidate) + (let* ((cand (replace-regexp-in-string "^\\s-\\{1\\}" "" candidate)) + (buf (get-buffer cand)) + (pattern (cl-loop with pat = helm-pattern + for p in (helm-mm-split-pattern pat) + when (string-match "\\`@\\(.*\\)" p) + collect (match-string 1 p) into lst + finally return (mapconcat #'identity lst " "))) + (patterns (helm-mm-3-get-patterns pattern))) + (if (and buf patterns) + (with-current-buffer buf + (save-excursion + (goto-char (point-min)) + (cl-loop for (pred . regexp) in patterns + always + (save-excursion + (funcall + pred + (if helm-migemo-mode + (helm-mm-migemo-forward regexp nil t) + (re-search-forward regexp nil t))))))) + t))) + +(defun helm-buffers--match-from-directory (candidate) + (let* ((cand (replace-regexp-in-string "^\\s-\\{1\\}" "" candidate)) + (buf (get-buffer cand)) + (buf-fname (or (buffer-file-name buf) + (car-safe (rassoc buf dired-buffers)))) + (regexps (cl-loop with pattern = helm-pattern + for p in (helm-mm-split-pattern pattern) + when (string-match "\\`/" p) + collect p))) + (if regexps + (cl-loop for re in regexps + thereis + (and buf-fname + (string-match + (substring re 1) (helm-basedir buf-fname)))) + t))) + +(defun helm-buffers-match-function (candidate) + "Default function to match buffers." + (and (helm-buffers--match-from-pat candidate) + (helm-buffers--match-from-mjm candidate) + (helm-buffers--match-from-inside candidate) + (helm-buffers--match-from-directory candidate))) + + +(defun helm-buffer-query-replace-1 (&optional regexp-flag buffers) + "Query replace in marked buffers. +If REGEXP-FLAG is given use `query-replace-regexp'." + (let ((prompt (if regexp-flag "Query replace regexp" "Query replace")) + (bufs (or buffers (helm-marked-candidates))) + (helm--reading-passwd-or-string t)) + (cl-loop with args = (query-replace-read-args prompt regexp-flag t) + for buf in bufs + do + (save-window-excursion + (switch-to-buffer buf) + (save-excursion + (let ((case-fold-search t)) + (goto-char (point-min)) + (apply #'perform-replace + (list (nth 0 args) (nth 1 args) + t regexp-flag (nth 2 args) nil + multi-query-replace-map)))))))) + +(defun helm-buffer-query-replace-regexp (_candidate) + (helm-buffer-query-replace-1 'regexp)) + +(defun helm-buffer-query-replace (_candidate) + (helm-buffer-query-replace-1)) + +(defun helm-buffer-toggle-diff (candidate) + "Toggle diff buffer CANDIDATE with it's file." + (helm-aif (get-buffer-window "*Diff*" 'visible) + (progn (kill-buffer "*Diff*") + (set-window-buffer it helm-current-buffer)) + (let ((buf (get-buffer candidate))) + (if (buffer-file-name buf) + (diff-buffer-with-file buf) + (user-error "Buffer `%s' is not associated to a file" + (buffer-name buf)))))) + +(helm-make-persistent-command-from-action helm-buffer-diff-persistent + "Toggle diff buffer without quitting helm." + 'diff-action 'helm-buffer-toggle-diff) + +(defun helm-revert-buffer (candidate) + (with-current-buffer candidate + (helm-aif (buffer-file-name) + (and (file-exists-p it) (revert-buffer t t))))) + +(defun helm-revert-marked-buffers (_ignore) + (mapc #'helm-revert-buffer (helm-marked-candidates))) + +(defun helm-buffer-revert-and-update (_candidate) + (with-helm-buffer + (let ((marked (helm-marked-candidates)) + (preselect (helm-buffers--quote-truncated-buffer + (helm-get-selection)))) + (cl-loop for buf in marked do (helm-revert-buffer buf)) + (when helm-marked-candidates (helm-unmark-all)) + (helm-force-update preselect)))) + +(helm-make-persistent-command-from-action helm-buffer-revert-persistent + "Revert buffer without quitting helm." + 'revert-action 'helm-buffer-revert-and-update) + +(defun helm-buffer-save-and-update (_candidate) + (with-helm-buffer + (let ((marked (helm-marked-candidates)) + (preselect (helm-get-selection nil t)) + (enable-recursive-minibuffers t)) + (cl-assert marked nil "No buffers need to be saved") + (cl-loop for buf in marked do + (with-current-buffer (get-buffer buf) + (when (buffer-file-name) (save-buffer)))) + (when helm-marked-candidates (helm-unmark-all)) + (helm-force-update (regexp-quote preselect))))) + +(defun helm-buffer-save-some-buffers (_candidate) + (helm-buffers-mark-similar-buffers-1 'mod) + (helm-buffer-save-and-update nil)) + +(helm-make-persistent-command-from-action helm-buffer-run-save-some-buffers + "Save unsaved file buffers without quitting Helm." + 'save-some-action 'helm-buffer-save-some-buffers) + +(helm-make-persistent-command-from-action helm-buffer-save-persistent + "Save buffer without quitting Helm." +'save-action 'helm-buffer-save-and-update) + +(defun helm-buffers-rename-buffer (candidate) + (with-current-buffer candidate + (rename-buffer (helm-read-string "New name: " (buffer-name)) t))) + +(helm-make-command-from-action helm-buffer-run-rename-buffer + "Run rename buffer action from `helm-source-buffers-list'." + 'helm-buffers-rename-buffer) + +(defun helm-switch-to-buffer-at-linum (candidate) + (let ((linum (read-number + "Line number: " + (with-current-buffer candidate + (line-number-at-pos))))) + (switch-to-buffer candidate) + (goto-char (point-min)) + (forward-line (1- linum)))) + +(helm-make-command-from-action helm-buffer-run-goto-line + "Switch to buffer at line number." + 'helm-switch-to-buffer-at-linum) + +(helm-make-persistent-command-from-action helm-buffer-run-kill-persistent + "Kill buffer without quitting Helm." + 'kill-action 'helm-buffers-persistent-kill) + +(defun helm-kill-marked-buffers (_ignore) + (let* ((bufs (helm-marked-candidates)) + (killed-bufs (cl-count-if 'kill-buffer bufs))) + (when (buffer-live-p helm-buffer) + (with-helm-buffer + (setq helm-marked-candidates nil + helm-visible-mark-overlays nil))) + (message "Killed %s buffer(s)" killed-bufs))) + +(helm-make-command-from-action helm-buffer-run-kill-buffers + "Run kill buffer action from `helm-source-buffers-list'." + 'helm-kill-marked-buffers) + +(defun helm-buffer-switch-to-shell (candidate) + (require 'helm-files) + (let ((helm-ff-default-directory + (with-current-buffer candidate + default-directory))) + (helm-ff-switch-to-shell nil))) + +(helm-make-command-from-action helm-buffer-run-switch-to-shell + "Run switch to shell action from helm-buffers-list." + 'helm-buffer-switch-to-shell) + +(helm-make-command-from-action helm-buffer-run-grep + "Run Grep action from `helm-source-buffers-list'." + 'helm-grep-buffers) + +(helm-make-command-from-action helm-buffer-run-zgrep + "Run Grep action from `helm-source-buffers-list'." + 'helm-zgrep-buffers) + +(helm-make-command-from-action helm-buffer-run-query-replace-regexp + "Run Query replace regexp action from `helm-source-buffers-list'." +'helm-buffer-query-replace-regexp) + +(helm-make-command-from-action helm-buffer-run-query-replace + "Run Query replace action from `helm-source-buffers-list'." +'helm-buffer-query-replace) + +(helm-make-command-from-action helm-buffer-switch-other-window + "Run switch to other window action from `helm-source-buffers-list'." + 'helm-buffer-switch-buffers-other-window) + +(defun helm-buffer-switch-to-buffer-other-frame (_candidate) + "Display marked buffers in other frame." + (let ((bufs (helm-marked-candidates))) + (select-frame (make-frame)) + (helm-window-show-buffers bufs))) + +(defun helm-buffers-maybe-raise-buffer-frame (candidate) + "Raise buffer frame handling buffer CANDIDATE and switch to it." + (let ((oframe (window-frame (get-buffer-window candidate 0)))) + (unless (eql oframe (selected-frame)) + (raise-frame oframe)) + (with-selected-frame oframe + (switch-to-buffer candidate)))) + +(helm-make-command-from-action helm-buffer-switch-other-frame + "Run switch to other frame action from `helm-source-buffers-list'." + 'helm-buffer-switch-to-buffer-other-frame) + +(defun helm-buffers-switch-to-buffer-other-tab (_candidate) + (when (fboundp 'switch-to-buffer-other-tab) + (let ((bufs (helm-marked-candidates))) + (cl-loop for buf in bufs + do (switch-to-buffer-other-tab buf))))) + +(helm-make-command-from-action helm-buffers-switch-to-buffer-new-tab + "Run switch to buffer in other tab action from `helm-source-buffers-list'." + 'helm-buffers-switch-to-buffer-other-tab + (cl-assert (fboundp 'tab-bar-mode) nil "Tab-bar-mode not available")) + +(defun helm-buffer-switch-buffers (_candidate) + "Switch to buffer candidates and replace current buffer. + +If more than one buffer marked switch to these buffers in +separate windows. If a prefix arg is given split windows +vertically." + (let ((buffers (helm-marked-candidates))) + (helm-window-show-buffers buffers))) + +(defun helm-buffer-switch-buffers-other-window (_candidate) + "Switch to marked buffers in other windows." + (let ((buffers (helm-marked-candidates))) + (helm-window-show-buffers buffers t))) + +(helm-make-command-from-action helm-buffer-run-ediff + "Run ediff action from `helm-source-buffers-list'." + 'helm-ediff-marked-buffers) + +(helm-make-command-from-action helm-buffer-run-ediff-merge + "Run ediff action from `helm-source-buffers-list'." + 'helm-ediff-marked-buffers-merge) + +(defun helm-buffers-persistent-kill-1 (buffer-or-name) + "Persistent action to kill buffer." + (let ((buf (get-buffer buffer-or-name)) helm-buf-or-cur) + (if (or (and (eql buf (get-buffer helm-current-buffer)) + (setq helm-buf-or-cur "helm-current-buffer")) + (and (eql buf (get-buffer helm-buffer)) + (setq helm-buf-or-cur "helm-buffer"))) + (progn + (message "Can't kill `%s' without quitting session" helm-buf-or-cur) + (sit-for 1)) + (kill-buffer buf) + (helm-delete-current-selection)))) + +(defun helm-buffers--quote-truncated-buffer (buffer) + (let ((bufname (and (bufferp buffer) + (buffer-name buffer)))) + (when (and bufname + (file-remote-p (with-current-buffer bufname + default-directory))) + (setq bufname (concat "@ " (helm-url-unhex-string bufname)))) + (when bufname + (regexp-quote + (if (and helm-buffer-max-length + helm-buffer-details-flag) + (helm-substring-by-width + bufname helm-buffer-max-length + "") + bufname))))) + +(defun helm-buffers-persistent-kill (_buffer) + (let ((marked (helm-marked-candidates)) + (sel (helm-get-selection))) + (unwind-protect + (cl-loop for b in marked + do (progn + ;; We need to preselect each marked because + ;; helm-buffers-persistent-kill is deleting + ;; current selection. + (helm-preselect + (format "^%s" + (helm-buffers--quote-truncated-buffer b))) + (helm-buffers-persistent-kill-1 b) + (message nil) + (helm--remove-marked-and-update-mode-line b))) + (with-helm-buffer + (setq helm-marked-candidates nil + helm-visible-mark-overlays nil)) + (helm-force-update (helm-buffers--quote-truncated-buffer sel))))) + +(defun helm-buffers-list-persistent-action (candidate) + (let ((current (window-buffer helm-persistent-action-display-window))) + (if (or (helm-follow-mode-p) + (eql current (get-buffer helm-current-buffer)) + (not (eql current (get-buffer candidate)))) + (switch-to-buffer candidate) + (if (and helm-persistent-action-display-window + (window-dedicated-p + (next-window helm-persistent-action-display-window 1))) + (delete-window helm-persistent-action-display-window) + (switch-to-buffer helm-current-buffer))))) + +(defun helm-ediff-marked-buffers (_candidate &optional merge) + "Ediff 2 marked buffers or CANDIDATE and `helm-current-buffer'. +With optional arg MERGE call `ediff-merge-buffers'." + (let* ((mkd (helm-marked-candidates)) + (lg-lst (length mkd)) + buf1 buf2) + (cl-case lg-lst + (0 + (error "Error:You have to mark at least 1 buffer")) + (1 + (setq buf1 helm-current-buffer + buf2 (cl-first mkd))) + (2 + (setq buf1 (cl-first mkd) + buf2 (cl-second mkd))) + (t + (error "Error:Too many buffers marked!"))) + (if merge + (ediff-merge-buffers buf1 buf2) + (ediff-buffers buf1 buf2)))) + +(defun helm-ediff-marked-buffers-merge (candidate) + "Ediff merge `helm-current-buffer' with CANDIDATE. +See `helm-ediff-marked-buffers'." + (helm-ediff-marked-buffers candidate t)) + +(defun helm-multi-occur-as-action (_candidate) + "Multi occur action for `helm-source-buffers-list'. +Can be used by any source that list buffers." + (let ((helm-occur-always-search-in-current + (if helm-current-prefix-arg + (not helm-occur-always-search-in-current) + helm-occur-always-search-in-current)) + (buffers (helm-marked-candidates)) + (input (cl-loop for i in (split-string (or (buffer-local-value + 'helm-input-local + (get-buffer helm-buffer)) + helm-pattern) + " " t) + thereis (and (string-match "\\`@\\([^!]*\\)" i) + (match-string 1 i))))) + (helm-multi-occur-1 buffers input))) + +(helm-make-command-from-action helm-buffers-run-occur + "Run `helm-multi-occur-as-action' by key." + 'helm-multi-occur-as-action) + +(defun helm-buffers-toggle-show-hidden-buffers () + (interactive) + (with-helm-alive-p + (let ((filter-attrs (helm-get-attr 'filtered-candidate-transformer + helm-source-buffers-list)) + (sel (helm-get-selection))) + (if (memq 'helm-shadow-boring-buffers filter-attrs) + (helm-set-attr 'filtered-candidate-transformer + (cons 'helm-skip-boring-buffers + (remove 'helm-shadow-boring-buffers + filter-attrs)) + helm-source-buffers-list) + (helm-set-attr 'filtered-candidate-transformer + (cons 'helm-shadow-boring-buffers + (remove 'helm-skip-boring-buffers + filter-attrs)) + helm-source-buffers-list)) + (helm-force-update (helm-buffers--quote-truncated-buffer sel))))) +(put 'helm-buffers-toggle-show-hidden-buffers 'helm-only t) + +(defun helm-buffers-browse-project (buf) + "Browse project from buffer BUF." + (with-current-buffer buf + (helm-browse-project helm-current-prefix-arg))) + +(helm-make-command-from-action helm-buffers-run-browse-project + "Run `helm-buffers-browse-project' from key." + 'helm-buffers-browse-project + (cl-assert (not helm-buffers-in-project-p) + nil "You are already browsing this project")) + +(defun helm-buffers-quit-and-find-file-fn (source) + (let* ((sel (helm-get-selection nil nil source)) + (buf (helm-aand (bufferp sel) + (get-buffer sel) + (buffer-name it)))) + (when buf + (or (buffer-file-name sel) + (car (rassoc buf dired-buffers)) + (and (with-current-buffer buf + (eq major-mode 'org-agenda-mode)) + org-directory + (expand-file-name org-directory)) + (with-current-buffer buf + (expand-file-name default-directory)))))) + +;;; Candidate Transformers +;; +;; +(defun helm-skip-boring-buffers (buffers _source) + "Remove buffers matching `helm-boring-buffer-regexp-list' in BUFFERS. +Where BUFFERS is a list of buffer names." + (helm-skip-entries buffers + helm-boring-buffer-regexp-list + helm-white-buffer-regexp-list)) + +(defun helm-shadow-boring-buffers (buffers _source) + "Buffers matching `helm-boring-buffer-regexp' will be +displayed with the `file-name-shadow' face if available." + (helm-shadow-entries buffers helm-boring-buffer-regexp-list)) + + +;;;###autoload +(defun helm-buffers-list () + "Preconfigured `helm' to list buffers." + (interactive) + (unless helm-source-buffers-list + (setq helm-source-buffers-list + (helm-make-source "Buffers" 'helm-source-buffers))) + (helm :sources '(helm-source-buffers-list + helm-source-buffer-not-found) + :buffer "*helm buffers*" + :truncate-lines helm-buffers-truncate-lines + :left-margin-width helm-buffers-left-margin-width)) + +;;;###autoload +(defun helm-mini () + "Preconfigured `helm' displaying `helm-mini-default-sources'." + (interactive) + (require 'helm-x-files) + (unless helm-source-buffers-list + (setq helm-source-buffers-list + (helm-make-source "Buffers" 'helm-source-buffers))) + (helm :sources helm-mini-default-sources + :buffer "*helm mini*" + :ff-transformer-show-only-basename nil + :truncate-lines helm-buffers-truncate-lines + :left-margin-width helm-buffers-left-margin-width)) + +(defun helm-quit-and-helm-mini () + "Drop into `helm-mini' from `helm'." + (interactive) + (with-helm-alive-p + (helm-run-after-exit 'helm-mini))) + +(provide 'helm-buffers) + +;;; helm-buffers.el ends here diff --git a/org/elpa/helm-20230406.839/helm-color.el b/org/elpa/helm-20230406.839/helm-color.el new file mode 100644 index 0000000..f636918 --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-color.el @@ -0,0 +1,159 @@ +;;; helm-color.el --- colors and faces -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2023 Thierry Volpiatto + +;; 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 . + +;;; Code: +(require 'cl-lib) +(require 'helm) +(require 'helm-help) +(require 'helm-elisp) + +(declare-function list-colors-display "facemenu") + +;;; Customize Face +;; +;; +(defun helm-custom-faces-init () + "Initialize buffer for `helm-source-customize-face'." + (unless (helm-candidate-buffer) + (save-selected-window + (list-faces-display) + (message nil)) + (helm-init-candidates-in-buffer + 'global + (with-current-buffer (get-buffer "*Faces*") + (buffer-substring + (next-single-char-property-change (point-min) 'face) + (point-max)))) + (kill-buffer "*Faces*"))) + +(defvar helm-source-customize-face + (helm-build-in-buffer-source "Customize Face" + :init 'helm-custom-faces-init + :get-line 'buffer-substring + :persistent-action (lambda (candidate) + (helm-elisp--persistent-help + (intern (car (split-string candidate))) + 'helm-describe-face)) + :persistent-help "Describe face" + :action '(("Customize" + . (lambda (line) + (customize-face (intern (car (split-string line)))))) + ("Copy name" + . (lambda (line) + (kill-new (car (split-string line " " t))))))) + "See (info \"(emacs)Faces\")") + +;;; Colors browser +;; +;; +(defun helm-colors-init () + (require 'facemenu) + (unless (helm-candidate-buffer) + (save-selected-window + (list-colors-display) + (message nil)) + (helm-init-candidates-in-buffer + 'global + (with-current-buffer (get-buffer "*Colors*") + (buffer-string))) + (kill-buffer "*Colors*"))) + +(defun helm-color-insert-name (candidate) + (with-helm-current-buffer + (insert (helm-colors-get-name candidate)))) + +(defun helm-color-kill-name (candidate) + (kill-new (helm-colors-get-name candidate))) + +(defun helm-color-insert-rgb (candidate) + (with-helm-current-buffer + (insert (helm-colors-get-rgb candidate)))) + +(defun helm-color-kill-rgb (candidate) + (kill-new (helm-colors-get-rgb candidate))) + +(helm-make-command-from-action helm-color-run-insert-name + "Insert name of color from `helm-source-colors'." + 'helm-color-insert-name) + +(helm-make-command-from-action helm-color-run-kill-name + "Kill name of color from `helm-source-colors'." + 'helm-color-kill-name) + +(helm-make-command-from-action helm-color-run-insert-rgb + "Insert RGB of color from `helm-source-colors'." + 'helm-color-insert-rgb) + +(helm-make-command-from-action helm-color-run-kill-rgb + "Kill RGB of color from `helm-source-colors'." + 'helm-color-kill-rgb) + +(defvar helm-color-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map helm-map) + (define-key map (kbd "C-c n") #'helm-color-run-insert-name) + (define-key map (kbd "C-c N") #'helm-color-run-kill-name) + (define-key map (kbd "C-c r") #'helm-color-run-insert-rgb) + (define-key map (kbd "C-c R") #'helm-color-run-kill-rgb) + map)) + +(defvar helm-source-colors + (helm-build-in-buffer-source "Colors" + :init 'helm-colors-init + :get-line 'buffer-substring + :keymap helm-color-map + :persistent-help "Kill entry in RGB format." + :persistent-action 'helm-color-kill-rgb + :help-message 'helm-colors-help-message + :action + '(("Copy Name (C-c N)" . helm-color-kill-name) + ("Copy RGB (C-c R)" . helm-color-kill-rgb) + ("Insert Name (C-c n)" . helm-color-insert-name) + ("Insert RGB (C-c r)" . helm-color-insert-rgb)))) + +(defun helm-colors-get-name (candidate) + "Get color name." + (replace-regexp-in-string + " " "" + (with-temp-buffer + (insert (capitalize candidate)) + (goto-char (point-min)) + (search-forward-regexp "\\s-\\{2,\\}") + (delete-region (point) (point-max)) + (buffer-string)))) + +(defun helm-colors-get-rgb (candidate) + "Get color RGB." + (replace-regexp-in-string + " " "" + (with-temp-buffer + (insert (capitalize candidate)) + (goto-char (point-max)) + (search-backward-regexp "\\s-\\{2,\\}") + (delete-region (point) (point-min)) + (buffer-string)))) + +;;;###autoload +(defun helm-colors () + "Preconfigured `helm' for color." + (interactive) + (helm :sources '(helm-source-colors helm-source-customize-face) + :buffer "*helm colors*")) + +(provide 'helm-color) + +;;; helm-color.el ends here diff --git a/org/elpa/helm-20230406.839/helm-comint.el b/org/elpa/helm-20230406.839/helm-comint.el new file mode 100644 index 0000000..c81805b --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-comint.el @@ -0,0 +1,226 @@ +;;; helm-comint.el --- Comint prompt navigation for helm. -*- lexical-binding: t -*- + +;; Copyright (C) 2020 Pierre Neidhardt + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; +;; You can bind this as follows in .emacs: +;; +;; (add-hook 'comint-mode-hook +;; (lambda () +;; (define-key comint-mode-map (kbd "M-s f") 'helm-comint-prompts-all))) + +;;; Code: +(require 'cl-lib) +(require 'helm) +(require 'helm-lib) +(require 'helm-help) +(require 'helm-elisp) + +;;; Comint prompts +;; +(defface helm-comint-prompts-promptidx + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + (:foreground "cyan"))) + "Face used to highlight comint prompt index." + :group 'helm-comint-faces) + +(defface helm-comint-prompts-buffer-name + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + (:foreground "green"))) + "Face used to highlight comint buffer name." + :group 'helm-comint-faces) + +(defcustom helm-comint-prompts-promptidx-p t + "Show prompt number." + :group 'helm-comint + :type 'boolean) + +(defcustom helm-comint-mode-list '(comint-mode slime-repl-mode sly-mrepl-mode sql-interactive-mode) + "Supported modes for prompt navigation. +Derived modes (e.g., Geiser's REPL) are automatically supported." + :group 'helm-comint + :type '(repeat (choice symbol))) + +(defcustom helm-comint-next-prompt-function '((sly-mrepl-mode . (lambda () + (sly-mrepl-next-prompt) + (point)))) + "Alist of (MODE . NEXT-PROMPT-FUNCTION) to use. + If the current major mode is a key in this list, the associated + function will be used to navigate the prompts. + The function must return the point after the prompt. + Otherwise (comint-next-prompt 1) will be used." + :group 'helm-comint + :type '(alist :key-type symbol :value-type function)) + +(defcustom helm-comint-max-offset 400 + "Max number of chars displayed per candidate in comint-input-ring browser. +When t, don't truncate candidate, show all. +By default it is approximatively the number of bits contained in +five lines of 80 chars each i.e 80*5. +Note that if you set this to nil multiline will be disabled, i.e +you will not have anymore separators between candidates." + :type '(choice (const :tag "Disabled" t) + (integer :tag "Max candidate offset")) + :group 'helm-misc) + +(defvar helm-comint-prompts-keymap + (let ((map (make-sparse-keymap))) + (set-keymap-parent map helm-map) + (define-key map (kbd "C-c o") #'helm-comint-prompts-other-window) + (define-key map (kbd "C-c C-o") #'helm-comint-prompts-other-frame) + map) + "Keymap for `helm-comint-prompt-all'.") + +(defun helm-comint-prompts-list (mode &optional buffer) + "List the prompts in BUFFER in mode MODE. + +Return a list of (\"prompt\" (point) (buffer-name) prompt-index)) +E.g. (\"ls\" 162 \"*shell*\" 3). +If BUFFER is nil, use current buffer." + (with-current-buffer (or buffer (current-buffer)) + (when (derived-mode-p mode) + (save-excursion + (goto-char (point-min)) + (let (result (count 1)) + (save-mark-and-excursion + (helm-awhile (and (not (eobp)) + (helm-aif (alist-get major-mode helm-comint-next-prompt-function) + (funcall it) + (comint-next-prompt 1))) + (push (list (buffer-substring-no-properties + it (point-at-eol)) + it (buffer-name) count) + result) + (setq count (1+ count)))) + (nreverse result)))))) + +(defun helm-comint-prompts-list-all (mode) + "List the prompts of all buffers in mode MODE. +See `helm-comint-prompts-list'." + (cl-loop for b in (buffer-list) + append (helm-comint-prompts-list mode b))) + +(defun helm-comint-prompts-transformer (candidates &optional all) + ;; ("ls" 162 "*shell*" 3) => ("*shell*:3:ls" . ("ls" 162 "*shell*" 3)) + (cl-loop for (prt pos buf id) in candidates + collect `(,(concat + (when all + (concat (propertize + buf + 'face 'helm-comint-prompts-buffer-name) + ":")) + (when helm-comint-prompts-promptidx-p + (concat (propertize + (number-to-string id) + 'face 'helm-comint-prompts-promptidx) + ":")) + prt) + . ,(list prt pos buf id)))) + +(defun helm-comint-prompts-all-transformer (candidates) + (helm-comint-prompts-transformer candidates t)) + +(cl-defun helm-comint-prompts-goto (candidate &optional (action 'switch-to-buffer)) + ;; Candidate format: ("ls" 162 "*shell*" 3) + (let ((buf (nth 2 candidate))) + (unless (and (string= (buffer-name) buf) + (eq action 'switch-to-buffer)) + (funcall action buf)) + (goto-char (nth 1 candidate)) + (recenter))) + +(defun helm-comint-prompts-goto-other-window (candidate) + (helm-comint-prompts-goto candidate 'switch-to-buffer-other-window)) + +(defun helm-comint-prompts-goto-other-frame (candidate) + (helm-comint-prompts-goto candidate 'switch-to-buffer-other-frame)) + +(helm-make-command-from-action helm-comint-prompts-other-window + "Switch to comint prompt in other window." + 'helm-comint-prompts-goto-other-window) + +(helm-make-command-from-action helm-comint-prompts-other-frame + "Switch to comint prompt in other frame." + 'helm-comint-prompts-goto-other-frame) + +;;;###autoload +(defun helm-comint-prompts () + "Pre-configured `helm' to browse the prompts of the current comint buffer." + (interactive) + (if (apply #'derived-mode-p helm-comint-mode-list) + (helm :sources + (helm-build-sync-source "Comint prompts" + :candidates (helm-comint-prompts-list major-mode) + :candidate-transformer #'helm-comint-prompts-transformer + :action '(("Go to prompt" . helm-comint-prompts-goto))) + :buffer "*helm comint prompts*") + (message "Current buffer is not a comint buffer"))) + +;;;###autoload +(defun helm-comint-prompts-all () + "Pre-configured `helm' to browse the prompts of all comint sessions." + (interactive) + (if (apply #'derived-mode-p helm-comint-mode-list) + (helm :sources + (helm-build-sync-source "All comint prompts" + :candidates (helm-comint-prompts-list-all major-mode) + :candidate-transformer #'helm-comint-prompts-all-transformer + :action (quote (("Go to prompt" . helm-comint-prompts-goto) + ("Go to prompt in other window `C-c o`" . + helm-comint-prompts-goto-other-window) + ("Go to prompt in other frame `C-c C-o`" . + helm-comint-prompts-goto-other-frame))) + :keymap helm-comint-prompts-keymap) + :buffer "*helm comint all prompts*") + (message "Current buffer is not a comint buffer"))) + +;;; Comint history +;; +;; +(defun helm-comint-input-ring-action (candidate) + "Default action for comint history." + (with-helm-current-buffer + (delete-region (comint-line-beginning-position) (point-max)) + (insert candidate))) + +(defvar helm-source-comint-input-ring + (helm-build-sync-source "Comint history" + :candidates (lambda () + (with-helm-current-buffer + (cl-loop for elm in (ring-elements comint-input-ring) + unless (string= elm "") + collect elm))) + :action 'helm-comint-input-ring-action + ;; Multiline does not work for `shell' because of an Emacs bug. + ;; It works in other REPLs like Geiser. + :multiline 'helm-comint-max-offset) + "Source that provides Helm completion against `comint-input-ring'.") + +;;;###autoload +(defun helm-comint-input-ring () + "Preconfigured `helm' that provide completion of `comint' history." + (interactive) + (when (or (derived-mode-p 'comint-mode) + (member major-mode helm-comint-mode-list)) + (helm :sources 'helm-source-comint-input-ring + :input (buffer-substring-no-properties (comint-line-beginning-position) + (point-at-eol)) + :buffer "*helm comint history*"))) + +(provide 'helm-comint) + +;;; helm-comint.el ends here diff --git a/org/elpa/helm-20230406.839/helm-command.el b/org/elpa/helm-20230406.839/helm-command.el new file mode 100644 index 0000000..6d18eff --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-command.el @@ -0,0 +1,413 @@ +;;; helm-command.el --- Helm execute-exended-command. -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2023 Thierry Volpiatto + +;; 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 . + +;;; Code: + +(require 'cl-lib) +(require 'helm) +(require 'helm-help) +(require 'helm-mode) +(require 'helm-elisp) + + +(defvar helm-M-x-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map helm-comp-read-map) + (define-key map (kbd "C-u") nil) + (define-key map (kbd "C-u") #'helm-M-x-universal-argument) + (define-key map (kbd "C-]") #'helm-M-x-toggle-short-doc) + map)) + + +(defgroup helm-command nil + "Emacs command related Applications and libraries for Helm." + :group 'helm) + +(defcustom helm-M-x-always-save-history nil + "`helm-M-x' save command in `extended-command-history' even when it fails." + :type 'boolean) + +(defcustom helm-M-x-reverse-history nil + "The history source of `helm-M-x' appear in second position when non-nil." + :type 'boolean) + +(defcustom helm-M-x-fuzzy-match t + "Helm-M-x fuzzy matching when non nil." + :type 'boolean) + +(defcustom helm-M-x-show-short-doc nil + "Show short docstring of command when non nil. +This value can be toggled with +\\\\[helm-M-x-toggle-short-doc] while in helm-M-x session." + :type 'boolean) + + +;;; Faces +;; +;; +(defgroup helm-command-faces nil + "Customize the appearance of helm-command." + :prefix "helm-" + :group 'helm-command + :group 'helm-faces) + +(defface helm-M-x-key + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "orange" :box (:line-width -1))) + "Face used in helm-M-x to show keybinding." + :group 'helm-command-faces) + +(defface helm-command-active-mode + '((t :inherit font-lock-builtin-face)) + "Face used by `helm-M-x' for activated modes." + :group 'helm-command-faces) + +(defface helm-M-x-short-doc + '((t :box (:line-width -1) :foreground "DimGray")) + "Face used by `helm-M-x' for short docstring." + :group 'helm-command-faces) + +(defvar helm-M-x-input-history nil) +(defvar helm-M-x-prefix-argument nil + "Prefix argument before calling `helm-M-x'.") +(defvar helm-M-x--timer nil) +(defvar helm-M-x--unwind-forms-done nil) + +(defun helm-M-x-get-major-mode-command-alist (mode-map) + "Return alist of MODE-MAP." + (when mode-map + (cl-loop for key being the key-seqs of mode-map using (key-bindings com) + for str-key = (key-description key) + for ismenu = (string-match "" str-key) + unless ismenu collect (cons str-key com)))) + +(defun helm-get-mode-map-from-mode (mode) + "Guess the mode-map name according to MODE. +Some modes don't use conventional mode-map name so we need to +guess mode-map name. E.g. `python-mode' ==> py-mode-map. +Return nil if no mode-map found." + (cl-loop ;; Start with a conventional mode-map name. + with mode-map = (intern-soft (format "%s-map" mode)) + with mode-string = (symbol-name mode) + with mode-name = (replace-regexp-in-string "-mode" "" mode-string) + while (not mode-map) + for count downfrom (length mode-name) + ;; Return when no result after parsing entire string. + when (eq count 0) return nil + for sub-name = (substring mode-name 0 count) + do (setq mode-map (intern-soft (format "%s-map" (concat sub-name "-mode")))) + finally return mode-map)) + +(defun helm-M-x-current-mode-map-alist () + "Return mode-map alist of current `major-mode'." + (let ((map-sym (helm-get-mode-map-from-mode major-mode))) + (when (and map-sym (boundp map-sym)) + (helm-M-x-get-major-mode-command-alist (symbol-value map-sym))))) + +(defun helm-M-x-toggle-short-doc () + "Toggle short doc display in helm-M-x." + (interactive) + (setq helm-M-x-show-short-doc (not helm-M-x-show-short-doc)) + (helm-force-update (concat "^" (helm-get-selection)) (helm-get-current-source))) +(put 'helm-M-x-toggle-short-doc 'no-helm-mx t) + +(defun helm-M-x-transformer-1 (candidates &optional sort ignore-props) + "Transformer function to show bindings in emacs commands. +Show global bindings and local bindings according to current +`major-mode'. +If SORT is non nil sort list with `helm-generic-sort-fn'. +Note that SORT should not be used when fuzzy matching because +fuzzy matching is running its own sort function with a different +algorithm." + (with-helm-current-buffer + (cl-loop with max-len = (when helm-M-x-show-short-doc + (buffer-local-value 'helm-candidate-buffer-longest-len + (get-buffer (helm-candidate-buffer)))) + with local-map = (helm-M-x-current-mode-map-alist) + for cand in candidates + for local-key = (car (rassq cand local-map)) + for key = (substitute-command-keys (format "\\[%s]" cand)) + for sym = (intern (if (consp cand) (car cand) cand)) + for doc = (when max-len + (helm-get-first-line-documentation (intern-soft cand))) + for disp = (if (or (eq sym major-mode) + (and (memq sym minor-mode-list) + (boundp sym) + (buffer-local-value sym helm-current-buffer))) + (propertize cand 'face 'helm-command-active-mode) + cand) + unless (and (null ignore-props) (or (get sym 'helm-only) (get sym 'no-helm-mx))) + collect + (cons (cond ((and (string-match "^M-x" key) local-key) + (format "%s%s%s %s" + disp + (if doc (make-string (+ 1 (- max-len (length cand))) ? ) "") + (if doc (propertize doc 'face 'helm-M-x-short-doc) "") + (propertize + " " 'display + (propertize local-key 'face 'helm-M-x-key)))) + ((string-match "^M-x" key) + (format "%s%s%s" + disp + (if doc (make-string (+ 1 (- max-len (length cand))) ? ) "") + (if doc (propertize doc 'face 'helm-M-x-short-doc) ""))) + (t (format "%s%s%s %s" + disp + (if doc (make-string (+ 1 (- max-len (length cand))) ? ) "") + (if doc (propertize doc 'face 'helm-M-x-short-doc) "") + (propertize + " " 'display + (propertize key 'face 'helm-M-x-key))))) + cand) + into ls + finally return + (if sort (sort ls #'helm-generic-sort-fn) ls)))) + +(defun helm-M-x-transformer (candidates _source) + "Transformer function for `helm-M-x' candidates." + ;; Generic sort function is handling helm-flex. + (helm-M-x-transformer-1 candidates (null helm--in-fuzzy))) + +(defun helm-M-x-transformer-no-sort (candidates _source) + "Transformer function for `helm-M-x' candidates." + (helm-M-x-transformer-1 candidates)) + +(defun helm-M-x-transformer-no-sort-no-props (candidates _source) + "Transformer function for `helm-M-x' candidates." + (helm-M-x-transformer-1 candidates nil t)) + +(defun helm-M-x--notify-prefix-arg () + ;; Notify a prefix-arg set AFTER calling M-x. + (when prefix-arg + (with-helm-window + (helm-display-mode-line (helm-get-current-source) 'force)))) + +(defun helm-cmd--get-current-function-name () + (save-excursion + (beginning-of-defun) + (cadr (split-string (buffer-substring-no-properties + (point-at-bol) (point-at-eol)))))) + +(defun helm-cmd--get-preconfigured-commands (&optional dir) + (let* ((helm-dir (or dir (helm-basedir (locate-library "helm")))) + (helm-autoload-file (expand-file-name "helm-autoloads.el" helm-dir)) + results) + (when (file-exists-p helm-autoload-file) + (with-temp-buffer + (insert-file-contents helm-autoload-file) + (while (re-search-forward "Preconfigured" nil t) + (push (substring (helm-cmd--get-current-function-name) 1) results)))) + results)) + +(defun helm-M-x-universal-argument () + "Same as `universal-argument' but for `helm-M-x'." + (interactive) + (if helm-M-x-prefix-argument + (progn (setq helm-M-x-prefix-argument nil) + (let ((inhibit-read-only t)) + (with-selected-window (minibuffer-window) + (save-excursion + (goto-char (point-min)) + (delete-char (- (minibuffer-prompt-width) (length "M-x ")))))) + (message "Initial prefix arg disabled")) + (setq prefix-arg (list 4)) + (universal-argument--mode))) +(put 'helm-M-x-universal-argument 'helm-only t) + +(defun helm-M-x-persistent-action (candidate) + (helm-elisp--persistent-help + candidate 'helm-describe-function)) + +(defun helm-M-x--move-selection-after-hook () + (setq current-prefix-arg nil)) + +(defun helm-M-x--before-action-hook () + (remove-hook 'helm-move-selection-after-hook + #'helm-M-x--move-selection-after-hook)) + +(defclass helm-M-x-class (helm-source-in-buffer helm-type-command) + ((requires-pattern :initform 0) + (must-match :initform t) + (filtered-candidate-transformer :initform 'helm-M-x-transformer-no-sort) + (persistent-help :initform "Describe this command") + (help-message :initform 'helm-M-x-help-message) + (nomark :initform t) + (cleanup :initform #'helm-M-x--unwind-forms) + (keymap :initform 'helm-M-x-map) + (resume :initform 'helm-M-x-resume-fn))) + +(defun helm-M-x-resume-fn () + (when (and helm-M-x--timer (timerp helm-M-x--timer)) + (cancel-timer helm-M-x--timer) + (setq helm-M-x--timer nil)) + (setq helm-M-x--timer (run-at-time 1 0.1 #'helm-M-x--notify-prefix-arg)) + (setq helm--mode-line-display-prefarg t) + ;; Prevent displaying a wrong prefix arg when helm-resume is called + ;; from prefix arg. + (setq current-prefix-arg nil)) + +(defun helm-M-x-read-extended-command (collection &optional predicate history) + "Read or execute action on command name in COLLECTION or HISTORY. + +When `helm-M-x-use-completion-styles' is used, Emacs +`completion-styles' mechanism is used, otherwise standard helm +completion and helm fuzzy matching are used together. + +Helm completion is not provided when executing or defining kbd +macros. + +Arg COLLECTION should be an `obarray' but can be any object +suitable for `try-completion'. Arg PREDICATE is a function that +default to `commandp' see also `try-completion'. Arg HISTORY +default to `extended-command-history'." + (setq helm--mode-line-display-prefarg t) + (let* ((pred (or predicate #'commandp)) + (helm-fuzzy-sort-fn (lambda (candidates _source) + ;; Sort on real candidate otherwise + ;; "symbol ()" is used when sorting. + (helm-fuzzy-matching-default-sort-fn-1 candidates t))) + (sources `(,(helm-make-source "Emacs Commands history" 'helm-M-x-class + :data (lambda () + (helm-comp-read-get-candidates + ;; History should be quoted to + ;; force `helm-comp-read-get-candidates' + ;; to use predicate against + ;; symbol and not string. + (or history 'extended-command-history) + ;; Ensure using empty string to + ;; not defeat helm matching fns [1] + pred nil nil "")) + :fuzzy-match helm-M-x-fuzzy-match) + ,(helm-make-source "Emacs Commands" 'helm-M-x-class + :data (lambda () + (helm-comp-read-get-candidates + ;; [1] Same comment as above. + collection pred nil nil "")) + :fuzzy-match helm-M-x-fuzzy-match))) + (prompt (concat (cond + ((eq helm-M-x-prefix-argument '-) "- ") + ((and (consp helm-M-x-prefix-argument) + (eq (car helm-M-x-prefix-argument) 4)) + "C-u ") + ((and (consp helm-M-x-prefix-argument) + (integerp (car helm-M-x-prefix-argument))) + (format "%d " (car helm-M-x-prefix-argument))) + ((integerp helm-M-x-prefix-argument) + (format "%d " helm-M-x-prefix-argument))) + "M-x "))) + (setq helm-M-x--timer (run-at-time 1 0.1 #'helm-M-x--notify-prefix-arg)) + ;; Fix Bug#2250, add `helm-move-selection-after-hook' which + ;; reset prefix arg to nil only for this helm session. + (add-hook 'helm-move-selection-after-hook + #'helm-M-x--move-selection-after-hook) + (add-hook 'helm-before-action-hook + #'helm-M-x--before-action-hook) + (when (and sources helm-M-x-reverse-history) + (setq sources (nreverse sources))) + (unwind-protect + (progn + (setq current-prefix-arg nil) + (helm :sources sources + :prompt prompt + :buffer "*helm M-x*" + :history 'helm-M-x-input-history + :truncate-lines t)) + (helm-M-x--unwind-forms)))) + +;; When running a command involving again helm from helm-M-x, the +;; unwind-protect UNWINDS forms are executed only once this helm +;; command exit leaving the helm-M-x timer running and other variables +;; and hooks not unset, so the timer is now in a global var and all +;; the forms that should normally run in unwind-protect are running as +;; well as soon as helm-M-x-execute-command is called. +(defun helm-M-x--unwind-forms (&optional done) + ;; helm-M-x--unwind-forms-done is non nil when it have been called + ;; once from helm-M-x-execute-command. + (unless helm-M-x--unwind-forms-done + (when (timerp helm-M-x--timer) + (cancel-timer helm-M-x--timer) + (setq helm-M-x--timer nil)) + (setq helm--mode-line-display-prefarg nil + helm-fuzzy-sort-fn (default-toplevel-value 'helm-fuzzy-sort-fn)) + ;; Be sure to remove it here as well in case of quit. + (remove-hook 'helm-move-selection-after-hook + #'helm-M-x--move-selection-after-hook) + (remove-hook 'helm-before-action-hook + #'helm-M-x--before-action-hook)) + ;; Reset helm-M-x--unwind-forms-done to nil when DONE is + ;; unspecified. + (setq helm-M-x--unwind-forms-done done)) + +(defun helm-M-x-execute-command (command) + "Execute COMMAND as an editor command. +COMMAND must be a symbol that satisfies the `commandp' predicate. +Save COMMAND to `extended-command-history'." + (helm-M-x--unwind-forms t) + (when command + ;; Avoid having `this-command' set to *exit-minibuffer. + (setq this-command command + ;; Handle C-x z (repeat) Bug#322 + real-this-command command) + ;; If helm-M-x is called with regular emacs completion (kmacro) + ;; use the value of arg otherwise use helm-current-prefix-arg. + (let ((prefix-arg (or helm-current-prefix-arg helm-M-x-prefix-argument)) + (command-name (symbol-name command))) + (condition-case-unless-debug err + (progn + (command-execute command 'record) + (add-to-history 'extended-command-history command-name)) + (error + (when helm-M-x-always-save-history + (add-to-history 'extended-command-history command-name)) + (signal (car err) (cdr err))))))) + +(defun helm-M-x--vanilla-M-x () + (helm-M-x-execute-command + (intern-soft + (if helm-mode + (unwind-protect + (progn + (helm-mode -1) + (read-extended-command)) + (helm-mode 1)) + (read-extended-command))))) + +;;;###autoload +(defun helm-M-x (_arg) + "Preconfigured `helm' for Emacs commands. +It is `helm' replacement of regular `M-x' +`execute-extended-command'. + +Unlike regular `M-x' Emacs vanilla `execute-extended-command' +command, the prefix args if needed, can be passed AFTER starting +`helm-M-x'. When a prefix arg is passed BEFORE starting +`helm-M-x', the first `C-u' while in `helm-M-x' session will +disable it. + +You can get help on each command by persistent action." + (interactive + (progn + (setq helm-M-x-prefix-argument current-prefix-arg) + (list current-prefix-arg))) + (if (or defining-kbd-macro executing-kbd-macro) + (helm-M-x--vanilla-M-x) + (helm-M-x-read-extended-command obarray))) +(put 'helm-M-x 'interactive-only 'command-execute) + +(provide 'helm-command) + +;;; helm-command.el ends here diff --git a/org/elpa/helm-20230406.839/helm-dabbrev.el b/org/elpa/helm-20230406.839/helm-dabbrev.el new file mode 100644 index 0000000..28ec983 --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-dabbrev.el @@ -0,0 +1,388 @@ +;;; helm-dabbrev.el --- Helm implementation of dabbrev. -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2023 Thierry Volpiatto + +;; 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 . + +;;; Code: + +(require 'helm) +(require 'helm-lib) +(require 'helm-help) +(require 'helm-elisp) ; For show-completion. + +(defgroup helm-dabbrev nil + "Dabbrev related Applications and libraries for Helm." + :group 'helm) + +(defcustom helm-dabbrev-always-search-all t + "Always search in all buffers when non--nil. +Note that even if nil, a search in all buffers will occur if the +length of candidates is <= than +`helm-dabbrev-max-length-result'." + :type 'boolean) + +(defcustom helm-dabbrev-candidates-number-limit 1000 + "Maximum number of candidates to collect. + +The higher this number is, the slower the computation of +candidates will be. You can use safely a higher value with +emacs-26+. +Note that this have nothing to do with +`helm-candidate-number-limit', this means that computation of +candidates stop when this value is reached but only +`helm-candidate-number-limit' candidates are displayed in the +Helm buffer." + :type 'integer) + +(defcustom helm-dabbrev-ignored-buffers-regexps + '("\\*helm" "\\*Messages" "\\*Echo Area" "\\*Buffer List") + "List of regexps matching names of buffers that `helm-dabbrev' should not check." + :type '(repeat regexp)) + +(defcustom helm-dabbrev-related-buffer-fn #'helm-dabbrev--same-major-mode-p + "A function that decide if a buffer to search in its related to `current-buffer'. + +This is actually determined by comparing `major-mode' of the +buffer to search and the `current-buffer'. + +The function take one arg, the buffer which is current, look at +`helm-dabbrev--same-major-mode-p' for an example. + +When nil all buffers are considered related to `current-buffer'." + :type 'function) + +(defcustom helm-dabbrev-major-mode-assoc nil + "Major mode association alist. + +This allow helm-dabbrev searching in buffers with the associated +`major-mode'. +E.g. (emacs-lisp-mode . lisp-interaction-mode) + +will allow searching in the lisp-interaction-mode buffer when +`current-buffer' is an `emacs-lisp-mode' buffer and vice versa +i.e. no need to provide (lisp-interaction-mode . +emacs-lisp-mode) association. + +When nil check is the searched buffer has same `major-mode' than +the `current-buffer'. + +This has no effect when `helm-dabbrev-related-buffer-fn' is nil +or of course bound to a function that doesn't handle this var." + :type '(alist :key-type symbol :value-type symbol)) + +(defcustom helm-dabbrev-lineno-around 30 + "Search first in this number of lines before and after point." + :type 'integer) + +(defcustom helm-dabbrev-cycle-threshold 5 + "Number of time helm-dabbrev cycle before displaying helm completion. +When nil or 0 disable cycling." + :type '(choice (const :tag "Cycling disabled" nil) integer)) + +(defcustom helm-dabbrev-case-fold-search 'smart + "Set `case-fold-search' in `helm-dabbrev'. +Same as `helm-case-fold-search' but for `helm-dabbrev'. +Note that this is not affecting searching in Helm buffer, but the +initial search for all candidates in buffer(s)." + :type '(choice (const :tag "Ignore case" t) + (const :tag "Respect case" nil) + (other :tag "Smart" smart))) + +(defvaralias 'helm-dabbrev--regexp 'helm-dabbrev-separator-regexp) +(make-obsolete-variable 'helm-dabbrev--regexp + 'helm-dabbrev-separator-regexp "2.8.3") +;; Check for beginning of line should happen last (^\n\\|^). +(defvar helm-dabbrev-separator-regexp + "\\s-\\|\t\\|[(\\[\\{\"'`=<>$;,@.#+]\\|\\s\\\\|^\n\\|^" + "Regexp matching the start of a dabbrev candidate.") + + +(defvar helm-dabbrev-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map helm-map) + (define-key map (kbd "M-/") #'helm-next-line) + (define-key map (kbd "M-:") #'helm-previous-line) + map)) + +;; Internal +(defvar helm-dabbrev--cache nil) +(defvar helm-dabbrev--data nil) +(cl-defstruct helm-dabbrev-info dabbrev limits iterator) +(defvar helm-dabbrev--already-tried nil) +(defvar helm-dabbrev--computing-cache nil + "[INTERNAL] Flag to notify helm-dabbrev is blocked. +Do nothing when non nil.") + +(defun helm-dabbrev--buffer-list () + (cl-loop for buf in (buffer-list) + unless (cl-loop for r in helm-dabbrev-ignored-buffers-regexps + thereis (string-match r (buffer-name buf))) + collect buf)) + +(defun helm-dabbrev--same-major-mode-p (start-buffer) + "Decide if current-buffer is related to START-BUFFER." + (helm-same-major-mode-p start-buffer helm-dabbrev-major-mode-assoc)) + +(defun helm-dabbrev--collect (str limit ignore-case all) + (let* ((case-fold-search ignore-case) + (buffer1 (current-buffer)) ; start buffer. + (minibuf (minibufferp buffer1)) + results pos-before pos-after) + (catch 'break + (dolist (buf (if all (helm-dabbrev--buffer-list) + (list (current-buffer)))) + (with-current-buffer buf + (when (or minibuf ; check against all buffers when in minibuffer. + (if helm-dabbrev-related-buffer-fn + (funcall helm-dabbrev-related-buffer-fn buffer1) + t)) + (save-excursion + ;; Start searching before thing before point. + (goto-char (- (point) (length str))) + ;; Search the last 30 lines BEFORE point and set POS-BEFORE. + (cl-multiple-value-bind (res _pa pb) + (helm-dabbrev--search-and-store str -2 limit results) + (setq results res + ;; No need to set POS-AFTER here. + pos-before pb))) + (save-excursion + ;; Search the next 30 lines AFTER point and set POS-AFTER. + (cl-multiple-value-bind (res pa _pb) + (helm-dabbrev--search-and-store str 2 limit results) + (setq results res + ;; No need to set POS-BEFORE, we keep the last + ;; value found. + pos-after pa))) + (save-excursion + ;; Search all BEFORE point maybe starting from + ;; POS-BEFORE to not search again what previously found. + ;; If limit is reached in previous call of + ;; `helm-dabbrev--search-and-store' POS-BEFORE is nil and + ;; goto-char will fail, so check it. + (when pos-before (goto-char pos-before)) + (cl-multiple-value-bind (res _pa _pb) + (helm-dabbrev--search-and-store str -1 limit results) + ;; No need to set POS-BEFORE and POS-AFTER here. + (setq results res))) + (save-excursion + ;; Search all AFTER point maybe starting from POS-AFTER. + ;; Same comment as above for POS-AFTER. + (when pos-after (goto-char pos-after)) + (cl-multiple-value-bind (res _pa _pb) + (helm-dabbrev--search-and-store str 1 limit results) + ;; No need to set POS-BEFORE and POS-AFTER here. + (setq results res))))) + (when (>= (length results) limit) (throw 'break nil)))) + (nreverse results))) + +(defun helm-dabbrev--search-and-store (pattern direction limit results) + "Search words or symbols matching PATTERN in DIRECTION up to LIMIT. +Finally returns all matched candidates appended to RESULTS. +Argument DIRECTION can be: + - (1): Search forward from point. + - (-1): Search backward from point. + - (2): Search forward from the + `helm-dabbrev-lineno-around' + lines after point. + - (-2): Search backward from the + `helm-dabbrev-lineno-around' + lines before point." + (let ((res results) + after before) + (while (and (<= (length res) limit) + (cl-case direction + (1 (search-forward pattern nil t)) + (-1 (search-backward pattern nil t)) + (2 (let ((pos + (save-excursion + (forward-line + helm-dabbrev-lineno-around) + (point)))) + (setq after pos) + (search-forward pattern pos t))) + (-2 (let ((pos + (save-excursion + (forward-line + (- helm-dabbrev-lineno-around)) + (point)))) + (setq before pos) + (search-backward pattern pos t))))) + (let* ((mb (match-beginning 0)) + (replace-regexp (concat "\\(" helm-dabbrev-separator-regexp + "\\)\\'")) + (match-word (helm-dabbrev--search + pattern mb replace-regexp))) + (when (and match-word (not (member match-word res))) + (push match-word res)))) + (list res after before))) + +(defun helm-dabbrev--search (pattern beg sep-regexp) + "Search word or symbol at point matching PATTERN. +Argument BEG is corresponding to the previous `match-beginning' +search. +The search starts at (1- BEG) with a regexp starting with +`helm-dabbrev-separator-regexp' followed by PATTERN followed by a +regexp matching syntactically any word or symbol. +The possible false positives matching SEP-REGEXP at end are +finally removed." + (let ((eol (point-at-eol))) + (save-excursion + (goto-char (1- beg)) + (when (re-search-forward + (concat "\\(" + helm-dabbrev-separator-regexp + "\\)" + "\\(?99:\\(" + (regexp-quote pattern) + "\\(\\sw\\|\\s_\\)+\\)\\)") + eol t) + (replace-regexp-in-string + sep-regexp "" + (match-string-no-properties 99)))))) + +(defun helm-dabbrev--get-candidates (dabbrev &optional limit) + (cl-assert dabbrev nil "[No Match]") + (helm-dabbrev--collect + dabbrev (or limit helm-dabbrev-candidates-number-limit) + (cl-case helm-dabbrev-case-fold-search + (smart (helm-set-case-fold-search-1 dabbrev)) + (t helm-dabbrev-case-fold-search)) + helm-dabbrev-always-search-all)) + +(defun helm-dabbrev-default-action (candidate) + (with-helm-current-buffer + (let* ((limits (helm-bounds-of-thing-before-point + helm-dabbrev-separator-regexp)) + (beg (car limits)) + (end (point))) + (run-with-timer + 0.01 nil + #'helm-insert-completion-at-point + beg end candidate)))) + +;;;###autoload +(cl-defun helm-dabbrev () + "Preconfigured helm for dynamic abbreviations." + (interactive) + (unless helm-dabbrev--computing-cache + (let ((dabbrev (helm-thing-before-point + nil helm-dabbrev-separator-regexp)) + (limits (helm-bounds-of-thing-before-point + helm-dabbrev-separator-regexp)) + (enable-recursive-minibuffers t) + (cycling-disabled-p (or (null helm-dabbrev-cycle-threshold) + (zerop helm-dabbrev-cycle-threshold))) + (helm-execute-action-at-once-if-one t) + (helm-quit-if-no-candidate + (lambda () + (message "[Helm-dabbrev: No expansion found]")))) + (cl-assert (and (stringp dabbrev) (not (string= dabbrev ""))) + nil "[Helm-dabbrev: Nothing found before point]") + (when (and + ;; have been called at least once. + (helm-dabbrev-info-p helm-dabbrev--data) + ;; But user have moved with some other command + ;; in the meaning time. + (not (eq last-command 'helm-dabbrev))) + (setq helm-dabbrev--data nil)) + ;; When candidates are requested in helm directly without cycling, + ;; we need them right now before running helm. + (when cycling-disabled-p + (message "Waiting for helm-dabbrev candidates...") + (setq helm-dabbrev--cache (helm-dabbrev--get-candidates dabbrev))) + (unless (or cycling-disabled-p + (helm-dabbrev-info-p helm-dabbrev--data)) + (setq helm-dabbrev--data + (make-helm-dabbrev-info + :dabbrev dabbrev + :limits limits + :iterator + (helm-iter-list + (cl-loop for i in (helm-dabbrev--get-candidates + dabbrev helm-dabbrev-cycle-threshold) + when (string-match-p + (concat "^" (regexp-quote dabbrev)) i) + collect i))))) + (let ((iter (and (helm-dabbrev-info-p helm-dabbrev--data) + (helm-dabbrev-info-iterator helm-dabbrev--data))) + deactivate-mark) + ;; Cycle until iterator is consumed. + (helm-aif (and iter (helm-iter-next iter)) + (progn + (helm-insert-completion-at-point + (car (helm-dabbrev-info-limits helm-dabbrev--data)) + ;; END is the end of the previous inserted string, not + ;; the end (apart for first insertion) of the initial string. + (cdr limits) it) + ;; Move already tried candidates to end of list. + (push it helm-dabbrev--already-tried)) + ;; Iterator is now empty, or cycling was disabled, maybe + ;; reset dabbrev to initial value and start helm completion. + (let* ((old-dabbrev (if (helm-dabbrev-info-p helm-dabbrev--data) + (helm-dabbrev-info-dabbrev helm-dabbrev--data) + dabbrev)) + (only-one (eq (length helm-dabbrev--already-tried) 1))) + (unless helm-dabbrev--cache ; Already computed when + ; cycling is disabled. + (message "Waiting for helm-dabbrev candidates...") + (setq helm-dabbrev--computing-cache t) + (setq helm-dabbrev--cache + (helm-dabbrev--get-candidates old-dabbrev)) + ;; If user continues typing M-/ while display is blocked by + ;; helm-dabbrev--get-candidates delete these events. + (setq unread-command-events nil)) + ;; If the length of candidates is only one when computed + ;; that's mean the unique matched item have already been + ;; inserted by the iterator, so no need to reinsert the old dabbrev, + ;; just let helm exiting with "No expansion found". + (unless (or only-one cycling-disabled-p) + (setq dabbrev old-dabbrev + limits (helm-dabbrev-info-limits helm-dabbrev--data)) + (setq helm-dabbrev--data nil) + (delete-region (car limits) (point)) + (insert dabbrev)) + (when (and (null cycling-disabled-p) only-one) + (setq helm-dabbrev--cache nil + helm-dabbrev--already-tried nil + helm-dabbrev--computing-cache nil) + (cl-return-from helm-dabbrev + (message "[Helm-dabbrev: No expansion found]"))) + (with-helm-show-completion (car limits) (cdr limits) + (unwind-protect + (helm :sources + (helm-build-in-buffer-source "Dabbrev Expand" + :data + (append + (cl-loop with lst = helm-dabbrev--cache + for cand in helm-dabbrev--already-tried + do (setq lst (delete cand lst)) + finally return lst) + helm-dabbrev--already-tried) + :persistent-action 'ignore + :persistent-help "DoNothing" + :keymap helm-dabbrev-map + :action 'helm-dabbrev-default-action + :group 'helm-dabbrev) + :buffer "*helm dabbrev*" + :input (concat "^" dabbrev " ") + :resume 'noresume + :allow-nest t) + (setq helm-dabbrev--computing-cache nil + helm-dabbrev--already-tried nil + helm-dabbrev--cache nil))))))))) + +(provide 'helm-dabbrev) + +;;; helm-dabbrev.el ends here diff --git a/org/elpa/helm-20230406.839/helm-easymenu.el b/org/elpa/helm-20230406.839/helm-easymenu.el new file mode 100644 index 0000000..690c1c1 --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-easymenu.el @@ -0,0 +1,84 @@ +;;; helm-easymenu.el --- Helm easymenu definitions. -*- lexical-binding: t -*- + +;; Copyright (C) 2015 ~ 2020 Thierry Volpiatto + +;; 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 . + +;;; Code: + +(require 'easymenu) + +(easy-menu-add-item + nil '("Tools") + '("Helm" + ["Find any Files/Buffers" helm-multi-files t] + ["Helm Everywhere (Toggle)" helm-mode t] + ["Helm resume" helm-resume t] + "----" + ("Files" + ["Find files" helm-find-files t] + ["Recent Files" helm-recentf t] + ["Locate" helm-locate t] + ["Search Files with find" helm-find t] + ["Bookmarks" helm-filtered-bookmarks t]) + ("Buffers" + ["Find buffers" helm-buffers-list t]) + ("Projects" + ["Browse project" helm-browse-project] + ["Projects history" helm-projects-history]) + ("Commands" + ["Emacs Commands" helm-M-x t] + ["Externals Commands" helm-run-external-command t]) + ("Help" + ["Helm Apropos" helm-apropos t]) + ("Info" + ["Info at point" helm-info-at-point t] + ["Emacs Manual index" helm-info-emacs t] + ["Gnus Manual index" helm-info-gnus t] + ["Helm documentation" helm-documentation t]) + ("Elpa" + ["Elisp packages" helm-list-elisp-packages t] + ["Elisp packages no fetch" helm-list-elisp-packages-no-fetch t]) + ("Tools" + ["Occur" helm-occur t] + ["Grep current directory with AG" helm-do-grep-ag t] + ["Gid" helm-gid t] + ["Etags" helm-etags-select t] + ["Lisp complete at point" helm-lisp-completion-at-point t] + ["Browse Kill ring" helm-show-kill-ring t] + ["Browse register" helm-register t] + ["Mark Ring" helm-all-mark-rings t] + ["Regexp handler" helm-regexp t] + ["Colors & Faces" helm-colors t] + ["Show xfonts" helm-select-xfont t] + ["Ucs Symbols" helm-ucs t] + ["Imenu" helm-imenu t] + ["Imenu all" helm-imenu-in-all-buffers t] + ["Semantic or Imenu" helm-semantic-or-imenu t] + ["Google Suggest" helm-google-suggest t] + ["Eval expression" helm-eval-expression-with-eldoc t] + ["Calcul expression" helm-calcul-expression t] + ["Man pages" helm-man-woman t] + ["Top externals process" helm-top t] + ["Emacs internals process" helm-list-emacs-process t]) + "----" + ["Preferred Options" helm-configuration t]) + "Spell Checking") + +(easy-menu-add-item nil '("Tools") '("----") "Spell Checking") + + +(provide 'helm-easymenu) + +;;; helm-easymenu.el ends here diff --git a/org/elpa/helm-20230406.839/helm-elisp-package.el b/org/elpa/helm-20230406.839/helm-elisp-package.el new file mode 100644 index 0000000..31564ab --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-elisp-package.el @@ -0,0 +1,483 @@ +;;; helm-elisp-package.el --- helm interface for package.el -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2023 Thierry Volpiatto + +;; 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 . + +;;; Code: +(require 'cl-lib) +(require 'helm) +(require 'helm-help) +(require 'package) + +(defgroup helm-el-package nil + "helm elisp packages." + :group 'helm) + +(defcustom helm-el-package-initial-filter 'all + "Show only installed, upgraded or all packages at startup." + :type '(radio :tag "Initial filter for elisp packages" + (const :tag "Show all packages" all) + (const :tag "Show installed packages" installed) + (const :tag "Show not installed packages" uninstalled) + (const :tag "Show upgradable packages" upgrade))) + +(defcustom helm-el-truncate-lines t + "Truncate lines in `helm-buffer' when non-nil." + :type 'boolean) + + +(defcustom helm-el-package-upgrade-on-start nil + "Show package upgrades on startup when non nil." + :type 'boolean) + +(defcustom helm-el-package-autoremove-on-start nil + "Try to autoremove no more needed packages on startup. +See `package-autoremove'." + :type 'boolean) + +;; internals vars +(defvar helm-el-package--show-only 'all) +(defvar helm-el-package--initialized-p nil) +(defvar helm-el-package--tabulated-list nil) +(defvar helm-el-package--upgrades nil) +(defvar helm-el-package--removable-packages nil) + +;; Shutup bytecompiler for emacs-24* +(defvar package-menu-async) ; Only available on emacs-25. +(defvar helm-marked-buffer-name) +(declare-function async-byte-recompile-directory "ext:async-bytecomp.el") +(declare-function with-helm-display-marked-candidates "helm-utils.el") + + +(defun helm-el-package--init () + ;; In emacs-27 package-show-package-list returns an empty buffer + ;; until package-initialize have been called. + (unless (or package--initialized + (null (boundp 'package-quickstart))) + (package-initialize)) + (let (package-menu-async + (inhibit-read-only t)) + (when (null package-alist) + (setq helm-el-package--show-only 'all)) + (unless (consp package-selected-packages) + (helm-aif (package--find-non-dependencies) + (setq package-selected-packages it))) + (when (and (setq helm-el-package--removable-packages + (package--removable-packages)) + helm-el-package-autoremove-on-start) + (package-autoremove)) + (unwind-protect + (progn + (save-selected-window + (if helm-el-package--initialized-p + ;; Use this as `list-packages' doesn't work + ;; properly (empty buffer) when called from lisp + ;; with 'no-fetch (emacs-25 WA). + (package-show-package-list) + (when helm--force-updating-p (message "Refreshing packages list...")) + (list-packages helm-el-package--initialized-p)) + (setq helm-el-package--initialized-p t) + (message nil)) + (helm-init-candidates-in-buffer + 'global + (with-current-buffer (get-buffer "*Packages*") + (setq helm-el-package--tabulated-list tabulated-list-entries) + (remove-text-properties (point-min) (point-max) + '(read-only button follow-link category)) + (goto-char (point-min)) + (while (re-search-forward "^[ \t]+" nil t) + (replace-match "")) + (buffer-string))) + (setq helm-el-package--upgrades (helm-el-package-menu--find-upgrades)) + (if helm--force-updating-p + (if helm-el-package--upgrades + (message "Refreshing packages list done, [%d] package(s) to upgrade" + (length helm-el-package--upgrades)) + (message "Refreshing packages list done, no upgrades available")) + (setq helm-el-package--show-only (if (and helm-el-package-upgrade-on-start + helm-el-package--upgrades) + 'upgrade + helm-el-package-initial-filter)))) + (kill-buffer "*Packages*")))) + +(defun helm-el-package-describe (candidate) + (let ((id (get-text-property 0 'tabulated-list-id candidate))) + (describe-package (package-desc-name id)))) + +(defun helm-el-package-visit-homepage (candidate) + (let* ((id (get-text-property 0 'tabulated-list-id candidate)) + (pkg (package-desc-name id)) + (desc (cadr (assoc pkg package-archive-contents))) + (extras (package-desc-extras desc)) + (url (and (listp extras) (cdr-safe (assoc :url extras))))) + (if (stringp url) + (browse-url url) + (message "Package %s has no homepage" + (propertize (symbol-name pkg) + 'face 'font-lock-keyword-face))))) + +(helm-make-command-from-action helm-el-run-visit-homepage + "Visit package homepage from helm elisp packages." + 'helm-el-package-visit-homepage) + +(defun helm-elisp-package--pkg-name (pkg) + (if (package-desc-p pkg) + (package-desc-name pkg) + pkg)) + +(defun helm-el-package-install-1 (pkg-list) + (cl-loop with mkd = pkg-list + for p in mkd + for id = (get-text-property 0 'tabulated-list-id p) + for name = (helm-elisp-package--pkg-name id) + do (package-install id t) + when (helm-aand (assq name package-alist) + (package-desc-dir (cadr it)) + (file-exists-p it)) + collect id into installed-list and + do (unless (package--user-selected-p name) + (package--save-selected-packages + (cons name package-selected-packages))) + finally do (message (format "%d packages installed:\n(%s)" + (length installed-list) + (mapconcat #'package-desc-full-name + installed-list ", "))))) + +(defun helm-el-package-install (_candidate) + (helm-el-package-install-1 (helm-marked-candidates))) + +(helm-make-command-from-action helm-el-run-package-install + "Install package from helm elisp packages." + 'helm-el-package-install) + +(defun helm-el-package-uninstall-1 (pkg-list &optional force) + (cl-loop with mkd = pkg-list + for p in mkd + for id = (get-text-property 0 'tabulated-list-id p) + do + (condition-case-unless-debug err + (package-delete id force) + (error (message (cadr err)))) + ;; Seems like package-descs are symbols with props instead of + ;; vectors in emacs-27, use package-desc-name to ensure + ;; compatibility in all emacs versions. + unless (assoc (package-desc-name id) package-alist) + collect id into delete-list + finally do (if delete-list + (message (format "%d packages deleted:\n(%s)" + (length delete-list) + (mapconcat #'package-desc-full-name + delete-list ", "))) + "No package deleted"))) + +(defun helm-el-package-uninstall (_candidate) + (helm-el-package-uninstall-1 (helm-marked-candidates) helm-current-prefix-arg)) + +(helm-make-command-from-action helm-el-run-package-uninstall + "Uninstall package from helm elisp packages." + 'helm-el-package-uninstall) + +(defun helm-el-package-menu--find-upgrades () + (cl-loop for entry in helm-el-package--tabulated-list + for pkg-desc = (car entry) + for status = (package-desc-status pkg-desc) + ;; A dependency. + when (string= status "dependency") + collect pkg-desc into dependencies + ;; An installed package used as dependency (user have + ;; installed this package explicitely). + when (package--used-elsewhere-p pkg-desc) + collect pkg-desc into installed-as-dep + ;; An installed package. + when (member status '("installed" "unsigned")) + collect pkg-desc into installed + when (member status '("available" "new")) + collect (cons (package-desc-name pkg-desc) pkg-desc) into available + finally return + ;; Always try to upgrade dependencies before installed. + (cl-loop with all = (append dependencies installed-as-dep installed) + for pkg in all + for name = (package-desc-name pkg) + for avail-pkg = (assq name available) + when (and avail-pkg + (version-list-< + (package-desc-version pkg) + (package-desc-version (cdr avail-pkg)))) + collect avail-pkg))) + +(defun helm-el-package--user-installed-p (package) + "Return non-nil if PACKAGE is a user-installed package." + (let* ((assoc (assq package package-alist)) + (pkg-desc (and assoc (cadr assoc))) + (dir (and pkg-desc (package-desc-dir pkg-desc)))) + (when dir + (file-in-directory-p dir package-user-dir)))) + +(defun helm-el-package-upgrade-1 (pkg-list) + (cl-loop for p in pkg-list + for pkg-desc = (car p) + for pkg-name = (package-desc-name pkg-desc) + for upgrade = (cdr (assq pkg-name + helm-el-package--upgrades)) + do + (cond (;; Install. + (equal pkg-desc upgrade) + (message "Installing package `%s'" pkg-name) + (package-install pkg-desc t)) + (;; Do nothing. + (or (null upgrade) + ;; This may happen when a Elpa version of pkg + ;; is installed and need upgrade and pkg is as + ;; well a builtin package. + (package-built-in-p pkg-name)) + (ignore)) + (;; Delete. + t + (message "Deleting package `%s'" pkg-name) + (package-delete pkg-desc t t))))) + +(defun helm-el-package-upgrade (_candidate) + (helm-el-package-upgrade-1 + (cl-loop with pkgs = (helm-marked-candidates) + for p in helm-el-package--tabulated-list + for pkg = (car p) + if (member (symbol-name (package-desc-name pkg)) pkgs) + collect p))) + +(helm-make-command-from-action helm-el-run-package-upgrade + "Uninstall package from helm elisp packages." + 'helm-el-package-upgrade) + +(defun helm-el-package-upgrade-all () + (if helm-el-package--upgrades + (with-helm-display-marked-candidates + helm-marked-buffer-name (helm-fast-remove-dups + (mapcar (lambda (x) (symbol-name (car x))) + helm-el-package--upgrades) + :test 'equal) + (when (y-or-n-p "Upgrade all packages? ") + (helm-el-package-upgrade-1 helm-el-package--tabulated-list))) + (message "No packages to upgrade actually!"))) + +(defun helm-el-package-upgrade-all-action (_candidate) + (helm-el-package-upgrade-all)) + +(helm-make-command-from-action helm-el-run-package-upgrade-all + "Upgrade all packages from helm elisp packages." + 'helm-el-package-upgrade-all-action) + +(defun helm-el-package--transformer (candidates _source) + (cl-loop for c in candidates + for disp = (concat " " c) + for id = (get-text-property 0 'tabulated-list-id c) + for name = (and id (package-desc-name id)) + for desc = (package-desc-status id) + for built-in-p = (and (package-built-in-p name) + (not (member desc '("available" "new" + "installed" "dependency")))) + for installed-p = (member desc '("installed" "dependency")) + for upgrade-p = (assq name helm-el-package--upgrades) + for user-installed-p = (memq name package-selected-packages) + do (when (and user-installed-p (not upgrade-p)) + (put-text-property 0 2 'display "S " disp)) + do (when (or (memq name helm-el-package--removable-packages) + (and upgrade-p installed-p)) + (put-text-property 0 2 'display "U " disp) + (put-text-property + 2 (+ (length (symbol-name name)) 2) + 'face 'font-lock-variable-name-face disp)) + do (when (and upgrade-p (not installed-p) (not built-in-p)) + (put-text-property 0 2 'display "I " disp)) + for cand = (cons disp (car (split-string disp))) + when (or (and built-in-p + (eq helm-el-package--show-only 'built-in)) + (and upgrade-p + (eq helm-el-package--show-only 'upgrade)) + (and installed-p + (eq helm-el-package--show-only 'installed)) + (and (not installed-p) + (not built-in-p) + (eq helm-el-package--show-only 'uninstalled)) + (eq helm-el-package--show-only 'all)) + collect cand)) + +(defun helm-el-package-show-built-in () + (interactive) + (with-helm-alive-p + (setq helm-el-package--show-only 'built-in) + (helm-update))) +(put 'helm-el-package-show-built-in 'helm-only t) + +(defun helm-el-package-show-upgrade () + (interactive) + (with-helm-alive-p + (setq helm-el-package--show-only 'upgrade) + (helm-update))) +(put 'helm-el-package-show-upgrade 'helm-only t) + +(defun helm-el-package-show-installed () + (interactive) + (with-helm-alive-p + (setq helm-el-package--show-only 'installed) + (helm-update))) +(put 'helm-el-package-show-installed 'helm-only t) + +(defun helm-el-package-show-all () + (interactive) + (with-helm-alive-p + (setq helm-el-package--show-only 'all) + (helm-update))) +(put 'helm-el-package-show-all 'helm-only t) + +(defun helm-el-package-show-uninstalled () + (interactive) + (with-helm-alive-p + (setq helm-el-package--show-only 'uninstalled) + (helm-update))) +(put 'helm-el-package-show-uninstalled 'helm-only t) + +(defvar helm-el-package-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map helm-map) + (define-key map (kbd "M-I") #'helm-el-package-show-installed) + (define-key map (kbd "M-O") #'helm-el-package-show-uninstalled) + (define-key map (kbd "M-U") #'helm-el-package-show-upgrade) + (define-key map (kbd "M-B") #'helm-el-package-show-built-in) + (define-key map (kbd "M-A") #'helm-el-package-show-all) + (define-key map (kbd "C-c i") #'helm-el-run-package-install) + (define-key map (kbd "C-c r") #'helm-el-run-package-reinstall) + (define-key map (kbd "C-c d") #'helm-el-run-package-uninstall) + (define-key map (kbd "C-c u") #'helm-el-run-package-upgrade) + (define-key map (kbd "C-c U") #'helm-el-run-package-upgrade-all) + (define-key map (kbd "C-c @") #'helm-el-run-visit-homepage) + map)) + +(defvar helm-source-list-el-package nil) +(defclass helm-list-el-package-source (helm-source-in-buffer) + ((init :initform 'helm-el-package--init) + (get-line :initform 'buffer-substring) + (filtered-candidate-transformer :initform 'helm-el-package--transformer) + (action-transformer :initform 'helm-el-package--action-transformer) + (help-message :initform 'helm-el-package-help-message) + (keymap :initform 'helm-el-package-map) + (update :initform 'helm-el-package--update) + (candidate-number-limit :initform 9999) + (action :initform '(("Describe package" . helm-el-package-describe) + ("Visit homepage" . helm-el-package-visit-homepage))) + (find-file-target :initform #'helm-el-package-quit-an-find-file-fn) + (group :initform 'helm-el-package))) + +(defun helm-el-package-quit-an-find-file-fn (source) + (let* ((sel (helm-get-selection nil nil source)) + (pkg (and (stringp sel) + (get-text-property 0 'tabulated-list-id sel)))) + (when (and pkg (package-installed-p pkg)) + (expand-file-name (package-desc-dir pkg))))) + +(defun helm-el-package--action-transformer (actions candidate) + (let* ((pkg-desc (get-text-property 0 'tabulated-list-id candidate)) + (status (package-desc-status pkg-desc)) + (pkg-name (package-desc-name pkg-desc)) + (built-in (and (package-built-in-p pkg-name) + (not (member status '("available" "new" + "installed" "dependency"))))) + (acts (if helm-el-package--upgrades + (append actions '(("Upgrade all packages" + . helm-el-package-upgrade-all-action))) + actions))) + (cond (built-in '(("Describe package" . helm-el-package-describe))) + ((and (package-installed-p pkg-name) + (cdr (assq pkg-name helm-el-package--upgrades)) + (member status '("installed" "dependency"))) + (append '(("Upgrade package(s)" . helm-el-package-upgrade) + ("Uninstall package(s)" . helm-el-package-uninstall)) + acts)) + ((and (package-installed-p pkg-name) + (cdr (assq pkg-name helm-el-package--upgrades)) + (string= status "available")) + (append '(("Upgrade package(s)" . helm-el-package-upgrade)) + acts)) + ((and (package-installed-p pkg-name) + (or (null (package-built-in-p pkg-name)) + (and (package-built-in-p pkg-name) + (assq pkg-name package-alist)))) + (append acts '(("Reinstall package(s)" . helm-el-package-reinstall) + ("Recompile package(s)" . helm-el-package-recompile) + ("Uninstall package(s)" . helm-el-package-uninstall)))) + (t (append acts '(("Install packages(s)" . helm-el-package-install))))))) + +(defun helm-el-package--update () + (setq helm-el-package--initialized-p nil)) + +(defun helm-el-package-recompile (_pkg) + (cl-loop for p in (helm-marked-candidates) + do (helm-el-package-recompile-1 p))) + +(defun helm-el-package-recompile-1 (pkg) + (let* ((pkg-desc (get-text-property 0 'tabulated-list-id pkg)) + (dir (package-desc-dir pkg-desc))) + (async-byte-recompile-directory dir))) + +(defun helm-el-package-reinstall (_pkg) + (cl-loop for p in (helm-marked-candidates) + for pkg-desc = (get-text-property 0 'tabulated-list-id p) + do (helm-el-package-reinstall-1 pkg-desc))) + +(defun helm-el-package-reinstall-1 (pkg-desc) + (let ((name (package-desc-name pkg-desc))) + (package-delete pkg-desc 'force 'nosave) + ;; pkg-desc contain the description + ;; of the installed package just removed + ;; and is BTW no more valid. + ;; Use the entry in package-archive-content + ;; which is the non--installed package entry. + ;; For some reason `package-install' + ;; need a pkg-desc (package-desc-p) for the build-in + ;; packages already installed, the name (as symbol) + ;; fails with such packages. + (package-install + (cadr (assq name package-archive-contents)) t))) + +(helm-make-command-from-action helm-el-run-package-reinstall + "Reinstall package from helm elisp packages." + 'helm-el-package-reinstall) + +;;;###autoload +(defun helm-list-elisp-packages (arg) + "Preconfigured `helm' for listing and handling Emacs packages." + (interactive "P") + (when arg (setq helm-el-package--initialized-p nil)) + (unless helm-source-list-el-package + (setq helm-source-list-el-package + (helm-make-source "list packages" 'helm-list-el-package-source))) + (helm :sources 'helm-source-list-el-package + :truncate-lines helm-el-truncate-lines + :full-frame t + :buffer "*helm list packages*")) + +;;;###autoload +(defun helm-list-elisp-packages-no-fetch (arg) + "Preconfigured Helm for Emacs packages. + +Same as `helm-list-elisp-packages' but don't fetch packages on +remote. Called with a prefix ARG always fetch packages on +remote." + (interactive "P") + (let ((helm-el-package--initialized-p (null arg))) + (helm-list-elisp-packages nil))) + +(provide 'helm-elisp-package) + +;;; helm-elisp-package.el ends here diff --git a/org/elpa/helm-20230406.839/helm-elisp.el b/org/elpa/helm-20230406.839/helm-elisp.el new file mode 100644 index 0000000..0b6a030 --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-elisp.el @@ -0,0 +1,1051 @@ +;;; helm-elisp.el --- Elisp symbols completion for helm. -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2023 Thierry Volpiatto + +;; 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 . + +;;; Code: +(require 'cl-lib) +(require 'helm) +(require 'helm-lib) +(require 'helm-help) +(require 'helm-types) +(require 'helm-utils) +(require 'helm-info) +(require 'helm-eval) +(require 'helm-files) + +(declare-function helm-describe-function "helm-lib") +(declare-function helm-describe-variable "helm-lib") +(declare-function helm-describe-face "helm-lib") +(declare-function helm-read-file-name "helm-mode") +(declare-function helm-comp-read "helm-mode") +(declare-function helm-M-x-transformer-no-sort-no-props "helm-command") +(defvar helm-M-x-show-short-doc) + +;;; Customizable values + +(defgroup helm-elisp nil + "Elisp related Applications and libraries for Helm." + :group 'helm) + +(defcustom helm-turn-on-show-completion t + "Display candidate in `current-buffer' while moving selection when non--nil." + :group 'helm-elisp + :type 'boolean) + +(defcustom helm-show-completion-min-window-height 7 + "Minimum completion window height used in show completion. +This is used in macro `with-helm-show-completion'." + :group 'helm-elisp + :type 'integer) + +(defcustom helm-lisp-quoted-function-list + '(funcall apply mapc cl-mapc mapcar cl-mapcar + callf callf2 cl-callf cl-callf2 fset + fboundp fmakunbound symbol-function) + "List of function where quoted function completion happen. +E.g. give only function names after (funcall \\='." + :group 'helm-elisp + :type '(repeat (choice symbol))) + +(defcustom helm-lisp-unquoted-function-list + '(function defadvice) + "List of function where unquoted function completion happen. +E.g. give only function names after (function ." + :group 'helm-elisp + :type '(repeat (choice symbol))) + +(defcustom helm-apropos-fuzzy-match nil + "Enable fuzzy matching for `helm-apropos' when non-nil." + :group 'helm-elisp + :type 'boolean) + +(defcustom helm-lisp-fuzzy-completion nil + "Enable fuzzy matching in emacs-lisp completion when non-nil. +NOTE: This enables fuzzy matching in Helm native implementation of +elisp completion, but not on helmized elisp completion, i.e. fuzzy +completion is not available in `completion-at-point'." + :group 'helm-elisp + :type 'boolean) + +(defcustom helm-apropos-function-list '(helm-def-source--emacs-commands + helm-def-source--emacs-functions + helm-def-source--eieio-classes + helm-def-source--eieio-generic + helm-def-source--emacs-variables + helm-def-source--emacs-faces) + "A list of functions that build helm sources to use in `helm-apropos'." + :group 'helm-elisp + :type '(repeat (choice symbol))) + +(defcustom helm-apropos-defaut-info-lookup-sources '(helm-source-info-elisp + helm-source-info-cl + helm-source-info-eieio) + "A list of sources to look into when searching info page of a symbol." + :group 'helm-elisp + :type '(repeat (choice symbol))) + +(defcustom helm-show-completion-display-function + (if (display-graphic-p) + #'helm-display-buffer-in-own-frame + #'helm-show-completion-default-display-function) + "The function used to display helm completion buffer. + +This function is used by `with-helm-show-completion', when nil +fallback to `helm-default-display-buffer'. + +Default is to use a separate frame on graphic display and +`helm-show-completion-default-display-function' on non graphic +display." + :group 'helm-elisp + :type 'function) + +;;; Faces +;; +;; +(defgroup helm-elisp-faces nil + "Customize the appearance of helm-elisp." + :prefix "helm-" + :group 'helm-elisp + :group 'helm-faces) + +(defface helm-lisp-show-completion + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "DarkSlateGray")) + "Face used for showing candidates in `helm-lisp-completion'." + :group 'helm-elisp-faces) + +(defface helm-lisp-completion-info + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "red")) + "Face used for showing info in `helm-lisp-completion'." + :group 'helm-elisp-faces) + +(defcustom helm-elisp-help-function + 'helm-elisp-show-help + "Function for displaying help for Lisp symbols." + :group 'helm-elisp + :type '(choice (function :tag "Open help for the symbol." + helm-elisp-show-help) + (function :tag "Show one liner in modeline." + helm-elisp-show-doc-modeline))) + +(defcustom helm-locate-library-fuzzy-match t + "Enable fuzzy-matching in `helm-locate-library' when non--nil." + :type 'boolean + :group 'helm-elisp) + + +;;; Show completion. +;; +;; Provide show completion with macro `with-helm-show-completion'. + +(defvar helm-show-completion-overlay nil) + +;; Called each time cursor move in helm-buffer. +(defun helm-show-completion () + (with-helm-current-buffer + (overlay-put helm-show-completion-overlay + 'display (substring-no-properties + (helm-get-selection))))) + +(defun helm-show-completion-init-overlay (beg end) + (setq helm-show-completion-overlay (make-overlay beg end)) + (overlay-put helm-show-completion-overlay + 'face 'helm-lisp-show-completion)) + +(defun helm-show-completion-default-display-function (buffer &rest _args) + "A special resized Helm window is used depending on position in BUFFER." + (with-selected-window (selected-window) + (if (window-dedicated-p) + (helm-default-display-buffer buffer) + (let* ((screen-size (+ (count-screen-lines (window-start) (point) t) + 1 ; mode-line + (if header-line-format 1 0))) ; header-line + (def-size (- (window-height) + helm-show-completion-min-window-height)) + (upper-height (max window-min-height (min screen-size def-size))) + split-window-keep-point) + (recenter -1) + (set-window-buffer (if (active-minibuffer-window) + (minibuffer-selected-window) + (split-window nil upper-height + helm-split-window-default-side)) + buffer))))) + +(defmacro with-helm-show-completion (beg end &rest body) + "Show Helm candidate in an overlay at point. +BEG and END are the beginning and end position of the current +completion in `helm-current-buffer'. +BODY is an Helm call where we want to enable show completion. +If `helm-turn-on-show-completion' is nil do nothing." + (declare (indent 2) (debug t)) + `(unwind-protect + (if helm-turn-on-show-completion + (let ((helm-move-selection-after-hook + (append (list 'helm-show-completion) + helm-move-selection-after-hook)) + (helm-split-window-default-side + (if (eq helm-split-window-default-side 'same) + 'below helm-split-window-default-side)) + helm-split-window-inside-p + helm-reuse-last-window-split-state) + (helm-set-local-variable + 'helm-display-function + (or helm-show-completion-display-function + 'helm-default-display-buffer)) + (helm-show-completion-init-overlay ,beg ,end) + ,@body) + ,@body) + (when (and helm-show-completion-overlay + (overlayp helm-show-completion-overlay)) + (delete-overlay helm-show-completion-overlay)))) + + +;;; Lisp symbol completion. +;; +;; +(defun helm-lisp-completion--predicate-at-point (beg) + ;; Return a predicate for `all-completions'. + (let ((fn-sym-p (lambda () + (or + (and (eq (char-before) ?\ ) + (save-excursion + (skip-syntax-backward " " (point-at-bol)) + (memq (symbol-at-point) + helm-lisp-unquoted-function-list))) + (and (eq (char-before) ?\') + (save-excursion + (forward-char -1) + (eq (char-before) ?\#))))))) + (save-excursion + (goto-char beg) + (if (or + ;; Complete on all symbols in non--lisp modes (logs mail etc..) + (not (memq major-mode '(emacs-lisp-mode + lisp-interaction-mode + inferior-emacs-lisp-mode))) + (not (or (funcall fn-sym-p) + (and (eq (char-before) ?\') + (save-excursion + (forward-char (if (funcall fn-sym-p) -2 -1)) + (skip-syntax-backward " " (point-at-bol)) + (memq (symbol-at-point) + helm-lisp-quoted-function-list))) + (eq (char-before) ?\())) ; no paren before str. + ;; Looks like we are in a let statement. + (condition-case nil + (progn (up-list -2) (forward-char 1) + (eq (char-after) ?\()) + (error nil))) + (lambda (sym) + (or (boundp sym) (fboundp sym) (symbol-plist sym))) + #'fboundp)))) + +(defun helm-thing-before-point (&optional limits regexp) + "Return symbol name before point. +If REGEXP is specified return what REGEXP find before point. +By default match the beginning of symbol before point. +With LIMITS arg specified return the beginning and end position +of symbol before point." + (save-excursion + (let (beg + (end (point)) + (boundary (field-beginning nil nil (point-at-bol)))) + (if (re-search-backward (or regexp "\\_<") boundary t) + (setq beg (match-end 0)) + (setq beg boundary)) + (unless (= beg end) + (if limits + (cons beg end) + (buffer-substring-no-properties beg end)))))) + +(defun helm-bounds-of-thing-before-point (&optional regexp) + "Get the beginning and end position of `helm-thing-before-point'. +Return a cons (beg . end)." + (helm-thing-before-point 'limits regexp)) + +(defun helm-insert-completion-at-point (beg end str) + ;; When there is no space after point + ;; we are completing inside a symbol or + ;; after a partial symbol with the next arg aside + ;; without space, in this case mark the region. + ;; deleting it would remove the + ;; next arg which is unwanted. + (delete-region beg end) + (insert str) + (let ((pos (cdr (or (bounds-of-thing-at-point 'symbol) + ;; needed for helm-dabbrev. + (bounds-of-thing-at-point 'filename))))) + (when (and pos (< (point) pos)) + (push-mark pos t t)))) + +(defvar helm-lisp-completion--cache nil) +(defvar helm-lgst-len nil) +;;;###autoload +(defun helm-lisp-completion-at-point () + "Preconfigured Helm for Lisp symbol completion at point." + (interactive) + (setq helm-lgst-len 0) + (let* ((target (helm-thing-before-point)) + (beg (car (helm-bounds-of-thing-before-point))) + (end (point)) + (pred (and beg (helm-lisp-completion--predicate-at-point beg))) + (loc-vars (and (fboundp 'elisp--local-variables) + (ignore-errors + (mapcar #'symbol-name (elisp--local-variables))))) + (glob-syms (and target pred (all-completions target obarray pred))) + (candidates (append loc-vars glob-syms)) + (helm-quit-if-no-candidate t) + (helm-execute-action-at-once-if-one t) + (enable-recursive-minibuffers t)) + (setq helm-lisp-completion--cache (cl-loop for sym in candidates + for len = (length sym) + when (> len helm-lgst-len) + do (setq helm-lgst-len len) + collect sym)) + (if candidates + (with-helm-show-completion beg end + ;; Overlay is initialized now in helm-current-buffer. + (helm + :sources (helm-build-in-buffer-source "Lisp completion" + :data helm-lisp-completion--cache + :persistent-action `(helm-lisp-completion-persistent-action . + ,(and (eq helm-elisp-help-function + 'helm-elisp-show-doc-modeline) + 'never-split)) + :nomark t + :match-part (lambda (c) (car (split-string c))) + :fuzzy-match helm-lisp-fuzzy-completion + :persistent-help (helm-lisp-completion-persistent-help) + :filtered-candidate-transformer + #'helm-lisp-completion-transformer + :action (lambda (candidate) + (with-helm-current-buffer + (run-with-timer + 0.01 nil + #'helm-insert-completion-at-point + beg end candidate)))) + :input (if helm-lisp-fuzzy-completion + target (concat target " ")) + :resume 'noresume + :truncate-lines t + :buffer "*helm lisp completion*" + :allow-nest t)) + (message "[No Match]")))) + +(defun helm-lisp-completion-persistent-action (candidate &optional name) + "Show documentation for the function. +Documentation is shown briefly in mode-line or completely in +other window according to the value of +`helm-elisp-help-function'." + (funcall helm-elisp-help-function candidate name)) + +(defun helm-lisp-completion-persistent-help () + "Return persistent-help according to the value of `helm-elisp-help-function'" + (cl-ecase helm-elisp-help-function + (helm-elisp-show-doc-modeline "Show brief doc in mode-line") + (helm-elisp-show-help "Toggle show help for the symbol"))) + +(defun helm-elisp--show-help-1 (candidate &optional name) + (let ((sym (intern-soft candidate))) + (pcase sym + ((and (pred fboundp) (pred boundp)) + (if (member name `(,helm-describe-function-function ,helm-describe-variable-function)) + (funcall (intern (format "helm-%s" name)) sym) + ;; When there is no way to know what to describe + ;; prefer describe-function. + (helm-describe-function sym))) + ((pred fboundp) (helm-describe-function sym)) + ((pred boundp) (helm-describe-variable sym)) + ((pred facep) (helm-describe-face sym))))) + +(defun helm-elisp-show-help (candidate &optional name) + "Show full help for the function CANDIDATE. +Arg NAME specifies the name of the top level function calling +Helm generic completion (e.g., \"describe-function\") which +allows calling the right function when CANDIDATE symbol refers at +the same time to variable and a function." + (helm-elisp--persistent-help + candidate 'helm-elisp--show-help-1 name)) + +(defun helm-elisp-show-doc-modeline (candidate &optional name) + "Show brief documentation for the function in the mode-line." + (let ((cursor-in-echo-area t) + mode-line-in-non-selected-windows) + (helm-show-info-in-mode-line + (propertize + (helm-get-first-line-documentation + (intern candidate) name) + 'face 'helm-lisp-completion-info)))) + +(defun helm-lisp-completion-transformer (candidates _source) + "Helm candidates transformer for Lisp completion." + (cl-loop for c in candidates + for sym = (intern c) + for annot = (pcase sym + ((pred commandp) " (Com)") + ((pred class-p) " (Class)") + ((pred cl-generic-p) " (Gen)") + ((pred fboundp) " (Fun)") + ((pred boundp) " (Var)") + ((pred facep) " (Face)")) + for spaces = (make-string (- helm-lgst-len (length c)) ? ) + collect (cons (concat c spaces annot) c) into lst + finally return (sort lst #'helm-generic-sort-fn))) + +;;;###autoload +(cl-defun helm-get-first-line-documentation (sym &optional + (name "describe-function") + (end-column 72)) + "Return first line documentation of symbol SYM truncated at END-COLUMN. +If SYM is not documented, return \"Not documented\". +Argument NAME allows specifiying what function to use to display +documentation when SYM name is the same for function and variable." + (let ((doc (condition-case _err + (pcase sym + ((and (pred fboundp) (pred boundp)) + (pcase name + ("describe-function" + (documentation sym t)) + ("describe-variable" + (documentation-property sym 'variable-documentation t)) + (_ (documentation sym t)))) + ((pred fboundp) (documentation sym t)) + ((pred boundp) (documentation-property + sym 'variable-documentation t)) + ((pred facep) (face-documentation sym))) + (void-function "Void function -- Not documented")))) + (if (and doc (not (string= doc "")) + ;; `documentation' return "\n\n(args...)" + ;; for CL-style functions. + (not (string-match-p "\\`\n\n" doc))) + ;; Some commands specify key bindings in their first line. + (truncate-string-to-width + (substitute-command-keys (car (split-string doc "\n"))) + end-column nil nil t) + "Not documented"))) + +;;; File completion. +;; +;; Complete file name at point. + +;;;###autoload +(defun helm-complete-file-name-at-point (&optional force) + "Preconfigured Helm to complete file name at point." + (interactive) + (require 'helm-mode) + (let* ((tap (or (thing-at-point 'filename) "")) + beg + (init (and tap + (or force + (save-excursion + (end-of-line) + (search-backward tap (point-at-bol) t) + (setq beg (point)) + (looking-back "[^'`( ]" (1- (point))))) + (expand-file-name + (substring-no-properties tap)))) + (end (point)) + (helm-quit-if-no-candidate t) + (helm-execute-action-at-once-if-one t) + completion) + (with-helm-show-completion beg end + (setq completion (helm-read-file-name "FileName: " + :initial-input init))) + (when (and completion (not (string= completion ""))) + (delete-region beg end) (insert (if (string-match "^~" tap) + (abbreviate-file-name completion) + completion))))) + +;;;###autoload +(defun helm-lisp-indent () + ;; It is meant to use with `helm-define-multi-key' which + ;; does not support args for functions yet, so use `current-prefix-arg' + ;; for now instead of (interactive "P"). + (interactive) + (let ((tab-always-indent (or (eq tab-always-indent 'complete) + tab-always-indent))) + (indent-for-tab-command current-prefix-arg))) + +;;;###autoload +(defun helm-lisp-completion-or-file-name-at-point () + "Preconfigured Helm to complete Lisp symbol or filename at point. +Filename completion happens if string start after or between a +double quote." + (interactive) + (let* ((tap (thing-at-point 'filename))) + (if (and tap (save-excursion + (end-of-line) + (search-backward tap (point-at-bol) t) + (looking-back "[^'`( ]" (1- (point))))) + (helm-complete-file-name-at-point) + (helm-lisp-completion-at-point)))) + + +;;; Apropos +;; +;; +(defvar helm-apropos-history nil) + +(defcustom helm-apropos-show-short-doc nil + "Show short docstring of symbols when non nil. + +NOTE: When displaying helm-apropos in a frame, i.e. when +`helm-apropos' is member of `helm-commands-using-frame' setting this +to non nil have no effect, you have first to remove `helm-apropos' +from `helm-commands-using-frame'." + :group 'helm-elisp + :type 'boolean) + +(defvar helm-apropos-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map helm-map) + (define-key map (kbd "C-]") #'helm-apropos-toggle-details) + map)) + +(defun helm-apropos-init (test default &optional fn) + "Setup `helm-candidate-buffer' for `helm-apropos' sources. +A list of symbols fetched with FN is inserted in +`helm-candidate-buffer', if FN is not provided symbols are fetched +against obarray with predicate TEST. When FN is provided predicate TEST +is only used to test DEFAULT." + (require 'helm-help) + (helm-init-candidates-in-buffer 'global + (let ((default-symbol (and (stringp default) + (intern-soft default))) + (symbols (if fn (funcall fn) (all-completions "" obarray test)))) + (if (and default-symbol (funcall test default-symbol)) + (cons default-symbol symbols) + symbols)))) + +(defun helm-apropos-short-doc-transformer (candidates _source) + (if helm-apropos-show-short-doc + (cl-loop with max-len = (buffer-local-value 'helm-candidate-buffer-longest-len + (get-buffer (helm-candidate-buffer))) + for cand in candidates + for doc = (helm-get-first-line-documentation (intern-soft cand)) + collect (cons (format "%s%s%s" + cand + (if doc + (make-string (+ 1 (if (zerop max-len) + max-len + (- max-len (string-width cand)))) + ? ) + "") + (if doc (propertize doc 'face 'helm-M-x-short-doc) "")) + cand)) + candidates)) + +(defun helm-apropos-default-sort-fn (candidates _source) + (if (string= helm-pattern "") + candidates + (sort candidates #'helm-generic-sort-fn))) + +(defun helm-apropos-clean-history-variable (candidate) + (with-helm-current-buffer ; var is maybe local + (let* ((sym (intern-soft candidate)) + (cands (symbol-value sym)) + (mkds (and (listp cands) + (helm-comp-read "Delete entry: " + cands :marked-candidates t)))) + (cl-assert (listp mkds) nil "Variable value is not a list") + (cl-loop for elm in mkds do + (if (local-variable-p sym) + (set (make-local-variable sym) + (setq cands (delete elm cands))) + (set sym (setq cands (delete elm cands)))))))) + +(defun helm-apropos-clean-ring (candidate) + (with-helm-current-buffer ; var is maybe local + (let* ((sym (intern-soft candidate)) + (val (symbol-value sym)) + (cands (and (ring-p val) (ring-elements val))) + (mkds (and cands (helm-comp-read + "Delete entry: " + cands :marked-candidates t)))) + (when mkds + (cl-loop for elm in mkds do + (ring-remove + val (helm-position + elm + (ring-elements val) + :test 'equal)) + and do (if (local-variable-p sym) + (set (make-local-variable sym) val) + (set sym val))))))) + +(defun helm-apropos-action-transformer (actions candidate) + (let* ((sym (helm-symbolify candidate)) + (val (with-helm-current-buffer (symbol-value sym)))) + (cond ((custom-variable-p sym) + (append + actions + (let ((standard-value (eval (car (get sym 'standard-value)) t))) + (unless (equal standard-value (symbol-value sym)) + `(("Reset Variable to default value" + . ,(lambda (candidate) + (let ((sym (helm-symbolify candidate))) + (set sym standard-value))))))) + '(("Customize variable" . + (lambda (candidate) + (customize-option (helm-symbolify candidate))))))) + ((and val (with-helm-current-buffer (ring-p (symbol-value sym)))) + (append actions + '(("Clean ring" . helm-apropos-clean-ring)))) + ((and (string-match-p "history" candidate) (listp val)) + (append actions + '(("Clean variable" . + helm-apropos-clean-history-variable)))) + (t actions)))) + +(defun helm-def-source--emacs-variables (&optional default) + (helm-build-in-buffer-source "Variables" + :init (lambda () + (helm-apropos-init + (lambda (x) (and (boundp x) (not (keywordp x)))) default)) + :fuzzy-match helm-apropos-fuzzy-match + :filtered-candidate-transformer + (delq nil (list (and (null helm-apropos-fuzzy-match) + 'helm-apropos-default-sort-fn) + (and (null (memq 'helm-apropos helm-commands-using-frame)) + #'helm-apropos-short-doc-transformer))) + :nomark t + :persistent-action (lambda (candidate) + (helm-elisp--persistent-help + candidate 'helm-describe-variable)) + :persistent-help "Toggle describe variable" + :keymap helm-apropos-map + :action '(("Describe variable" . helm-describe-variable) + ("Find variable" . helm-find-variable) + ("Info lookup" . helm-info-lookup-symbol) + ("Set variable" . helm-set-variable)) + :action-transformer 'helm-apropos-action-transformer)) + +(defun helm-def-source--emacs-faces (&optional default) + "Create `helm' source for faces to be displayed with +`helm-apropos'." + (helm-build-in-buffer-source "Faces" + :init (lambda () (helm-apropos-init 'facep default #'face-list)) + :fuzzy-match helm-apropos-fuzzy-match + :filtered-candidate-transformer + (delq nil (list + (and (null helm-apropos-fuzzy-match) + #'helm-apropos-default-sort-fn) + (lambda (candidates _source) + (cl-loop for c in candidates + collect (propertize c 'face (intern c)))) + (and (null (memq 'helm-apropos helm-commands-using-frame)) + #'helm-apropos-short-doc-transformer))) + :persistent-action (lambda (candidate) + (helm-elisp--persistent-help + candidate 'helm-describe-face)) + :persistent-help "Toggle describe face" + :keymap helm-apropos-map + :action '(("Describe face" . helm-describe-face) + ("Find face" . helm-find-face-definition) + ("Customize face" . (lambda (candidate) + (customize-face (helm-symbolify candidate))))))) + +(defun helm-def-source--emacs-commands (&optional default) + (require 'helm-command) + (helm-build-in-buffer-source "Commands" + :init (lambda () + (helm-apropos-init 'commandp default)) + :fuzzy-match helm-apropos-fuzzy-match + :filtered-candidate-transformer + (append (list #'helm-M-x-transformer-no-sort-no-props) + (and (null helm-apropos-fuzzy-match) + '(helm-apropos-default-sort-fn))) + :display-to-real 'helm-symbolify + :nomark t + :persistent-action (lambda (candidate) + (helm-elisp--persistent-help + candidate 'helm-describe-function)) + :persistent-help "Toggle describe command" + :keymap helm-apropos-map + :action 'helm-type-function-actions)) + +(defun helm-def-source--emacs-functions (&optional default) + (helm-build-in-buffer-source "Functions" + :init (lambda () + (helm-apropos-init (lambda (x) + (and (fboundp x) + (not (commandp x)) + (not (cl-generic-p x)) + (not (class-p x)))) + default)) + :fuzzy-match helm-apropos-fuzzy-match + :filtered-candidate-transformer + (delq nil (list (and (null helm-apropos-fuzzy-match) + 'helm-apropos-default-sort-fn) + (and (null (memq 'helm-apropos helm-commands-using-frame)) + #'helm-apropos-short-doc-transformer))) + :display-to-real 'helm-symbolify + :persistent-action (lambda (candidate) + (helm-elisp--persistent-help + candidate 'helm-describe-function)) + :persistent-help "Toggle describe function" + :keymap helm-apropos-map + :nomark t + :action 'helm-type-function-actions)) + +(defun helm-def-source--eieio-classes (&optional default) + (helm-build-in-buffer-source "Classes" + :init (lambda () + (helm-apropos-init (lambda (x) + (class-p x)) + default)) + :fuzzy-match helm-apropos-fuzzy-match + :filtered-candidate-transformer + (delq nil (list (and (null helm-apropos-fuzzy-match) + 'helm-apropos-default-sort-fn) + (and (null (memq 'helm-apropos helm-commands-using-frame)) + #'helm-apropos-short-doc-transformer))) + :nomark t + :persistent-action (lambda (candidate) + (helm-elisp--persistent-help + candidate 'helm-describe-class)) + :persistent-help "Toggle describe class" + :keymap helm-apropos-map + :action '(("Describe Class" . helm-describe-class) + ("Find Class" . helm-find-function) + ("Info lookup" . helm-info-lookup-symbol)))) + +(defun helm-def-source--eieio-generic (&optional default) + (helm-build-in-buffer-source "Generic functions" + :init (lambda () + (helm-apropos-init (lambda (x) + (cl-generic-p x)) + default)) + :fuzzy-match helm-apropos-fuzzy-match + :filtered-candidate-transformer + (delq nil (list (and (null helm-apropos-fuzzy-match) + 'helm-apropos-default-sort-fn) + (and (null (memq 'helm-apropos helm-commands-using-frame)) + #'helm-apropos-short-doc-transformer))) + :nomark t + :persistent-action (lambda (candidate) + (helm-elisp--persistent-help + candidate 'helm-describe-function)) + :persistent-help "Toggle describe generic function" + :keymap helm-apropos-map + :action '(("Describe function" . helm-describe-function) + ("Find function" . helm-find-function) + ("Info lookup" . helm-info-lookup-symbol)))) + +(defun helm-info-lookup-fallback-source (candidate) + (let ((sym (helm-symbolify candidate)) + src-name fn) + (cond ((class-p sym) + (setq fn #'helm-describe-function + src-name "Describe class")) + ((cl-generic-p sym) + (setq fn #'helm-describe-function + src-name "Describe generic function")) + ((fboundp sym) + (setq fn #'helm-describe-function + src-name "Describe function")) + ((facep sym) + (setq fn #'helm-describe-face + src-name "Describe face")) + (t + (setq fn #'helm-describe-variable + src-name "Describe variable"))) + (helm-build-sync-source src-name + :candidates (list candidate) + :persistent-action (lambda (candidate) + (helm-elisp--persistent-help + candidate fn)) + :persistent-help src-name + :nomark t + :action fn))) + +(defun helm-info-lookup-symbol-1 (c) + (let ((helm-execute-action-at-once-if-one 'current-source)) + (helm :sources (append helm-apropos-defaut-info-lookup-sources + (list (helm-info-lookup-fallback-source c))) + :resume 'noresume + :buffer "*helm lookup*" + :input (helm-stringify c)))) + +(defun helm-info-lookup-symbol (candidate) + ;; ???:Running an idle-timer allows not catching RET when exiting + ;; with the fallback source. + ;; (run-with-idle-timer 0.01 nil #'helm-info-lookup-symbol-1 candidate) + (helm-info-lookup-symbol-1 candidate)) + +(defun helm-apropos-toggle-details () + "Toggle details in `helm-apropos'." + (interactive) + (with-helm-buffer + (unless (memq 'helm-apropos helm-commands-using-frame) + (setq helm-M-x-show-short-doc (not helm-M-x-show-short-doc) + helm-apropos-show-short-doc (not helm-apropos-show-short-doc)) + (helm-force-update (concat "^" (helm-stringify (helm-get-selection))) + (helm-get-current-source))))) + +(defun helm-apropos-get-default () + (with-syntax-table emacs-lisp-mode-syntax-table + (symbol-name (intern-soft (thing-at-point 'symbol))))) + +;;;###autoload +(defun helm-apropos (default) + "Preconfigured Helm to describe commands, functions, variables and faces. +In non interactives calls DEFAULT argument should be provided as +a string, i.e. the `symbol-name' of any existing symbol." + (interactive (list (helm-apropos-get-default))) + (let ((helm-M-x-show-short-doc + (and helm-apropos-show-short-doc + (null (memq 'helm-apropos helm-commands-using-frame))))) + (helm :sources + (mapcar (lambda (func) + (funcall func default)) + helm-apropos-function-list) + :history 'helm-apropos-history + :buffer "*helm apropos*" + :preselect (and default (concat "^\\_<" (regexp-quote default) "\\_>")) + :truncate-lines t))) + + +;;; Advices +;; +;; +(defvar ad-advised-functions) +(defvar ad-advice-classes) +(declare-function ad-make-single-advice-docstring "advice") +(declare-function ad-get-advice-info-field "advice") +(declare-function ad-advice-set-enabled "advice") +(declare-function ad-advice-set-enabled "advice") +(declare-function ad-advice-enabled "advice") + +(defvar helm-source-advice + (helm-build-sync-source "Function Advice" + :init (lambda () (require 'advice)) + :candidates 'helm-advice-candidates + :action (helm-make-actions "Toggle Enable/Disable" 'helm-advice-toggle) + :persistent-action 'helm-advice-persistent-action + :nomark t + :multiline t + :persistent-help "Toggle describe function / C-u C-j: Toggle advice")) + +(defun helm-advice-candidates () + (cl-loop for (fname) in ad-advised-functions + for function = (intern fname) + append + (cl-loop for class in ad-advice-classes append + (cl-loop for advice in (ad-get-advice-info-field function class) + for enabled = (ad-advice-enabled advice) + collect + (cons (format + "%s %s %s" + (if enabled "Enabled " "Disabled") + (propertize fname 'face 'font-lock-function-name-face) + (ad-make-single-advice-docstring advice class nil)) + (list function class advice)))))) + +(defun helm-advice-persistent-action (func-class-advice) + (if current-prefix-arg + (helm-advice-toggle func-class-advice) + (describe-function (car func-class-advice)))) + +(defun helm-advice-toggle (func-class-advice) + (cl-destructuring-bind (function _class advice) func-class-advice + (cond ((ad-advice-enabled advice) + (ad-advice-set-enabled advice nil) + (message "Disabled")) + (t + (ad-advice-set-enabled advice t) + (message "Enabled"))) + (ad-activate function) + (and helm-in-persistent-action + (helm-advice-update-current-display-string)))) + +(defun helm-advice-update-current-display-string () + (helm-edit-current-selection + (let ((newword (cond ((looking-at "Disabled") "Enabled") + ((looking-at "Enabled") "Disabled")))) + (when newword + (delete-region (point) (progn (forward-word 1) (point))) + (insert newword))))) + +;;;###autoload +(defun helm-manage-advice () + "Preconfigured `helm' to disable/enable function advices." + (interactive) + (helm-other-buffer 'helm-source-advice "*helm advice*")) + + +;;; Locate elisp library +;; +;; +(defun helm-locate-library-scan-list () + (cl-loop for dir in load-path + with load-suffixes = '(".el") + when (file-directory-p dir) + append (directory-files + dir t (concat (regexp-opt (get-load-suffixes)) + "\\'")))) + +;;;###autoload +(defun helm-locate-library () + "Preconfigured helm to locate elisp libraries." + (interactive) + (helm :sources (helm-build-in-buffer-source "Elisp libraries (Scan)" + :data #'helm-locate-library-scan-list + :fuzzy-match helm-locate-library-fuzzy-match + :keymap helm-generic-files-map + :search (unless helm-locate-library-fuzzy-match + (lambda (regexp) + (re-search-forward + (if helm-ff-transformer-show-only-basename + (replace-regexp-in-string + "\\`\\^" "" regexp) + regexp) + nil t))) + :match-part (lambda (candidate) + (with-helm-buffer + (if helm-ff-transformer-show-only-basename + (helm-basename candidate) candidate))) + :filter-one-by-one (lambda (c) + (with-helm-buffer + (if helm-ff-transformer-show-only-basename + (cons (helm-basename c) c) c))) + :action (helm-actions-from-type-file)) + :ff-transformer-show-only-basename nil + :buffer "*helm locate library*")) + +(defun helm-set-variable (var) + "Set VAR value interactively." + (let* ((sym (helm-symbolify var)) + (val (default-value sym))) + (set-default sym (eval-minibuffer + (format "Set `%s': " var) + (if (or (stringp val) + (memq val '(nil t)) + (numberp val)) + (prin1-to-string val) + (format "'%s" (prin1-to-string val))))))) + + +;;; Elisp Timers. +;; +;; +(defclass helm-absolute-time-timers-class (helm-source-sync helm-type-timers) + ((candidates :initform 'timer-list) + (allow-dups :initform t) + (candidate-transformer + :initform + (lambda (candidates) + (cl-loop for timer in candidates + collect (cons (helm-elisp--format-timer timer) timer)))))) + +(defvar helm-source-absolute-time-timers + (helm-make-source "Absolute Time Timers" 'helm-absolute-time-timers-class)) + +(defclass helm-idle-time-timers-class (helm-source-sync helm-type-timers) + ((candidates :initform 'timer-idle-list) + (allow-dups :initform t) + (candidate-transformer + :initform + (lambda (candidates) + (cl-loop for timer in candidates + collect (cons (helm-elisp--format-timer timer) timer)))))) + +(defvar helm-source-idle-time-timers + (helm-make-source "Idle Time Timers" 'helm-idle-time-timers-class)) + +(defun helm-elisp--format-timer (timer) + (format "%s repeat=%s %s(%s)" + (let ((time (timer--time timer))) + (if (timer--idle-delay timer) + (format "idle-for=[%s]" + (format-seconds "%dd %hh %mmin %z%,3ss" + (time-to-seconds time))) + (format-time-string "%m/%d %T" time))) + (or (timer--repeat-delay timer) "nil") + (mapconcat #'identity (split-string + (prin1-to-string (timer--function timer)) + "\n") + " ") + (mapconcat #'prin1-to-string (timer--args timer) " "))) + +;;;###autoload +(defun helm-timers () + "Preconfigured `helm' for timers." + (interactive) + (helm :sources '(helm-source-absolute-time-timers + helm-source-idle-time-timers) + :buffer "*helm timers*")) + + +;;; Complex command history +;; +;; + +(defvar helm-sexp--last-sexp nil) +;; This wont work compiled. +(defun helm-sexp-eval-1 () + (interactive) + (unwind-protect + (progn + ;; Trick called-interactively-p into thinking that `cand' is + ;; an interactive call, See `repeat-complex-command'. + (add-hook 'called-interactively-p-functions + #'helm-complex-command-history--called-interactively-skip) + (eval (read helm-sexp--last-sexp) t)) + (remove-hook 'called-interactively-p-functions + #'helm-complex-command-history--called-interactively-skip))) + +(defun helm-complex-command-history--called-interactively-skip (i _frame1 frame2) + (and (eq 'eval (cadr frame2)) + (eq 'helm-sexp-eval-1 + (cadr (backtrace-frame (+ i 2) #'called-interactively-p))) + 1)) + +(defun helm-sexp-eval (_candidate) + (call-interactively #'helm-sexp-eval-1)) + +(defvar helm-source-complex-command-history + (helm-build-sync-source "Complex Command History" + :candidates (lambda () + ;; Use cdr to avoid adding + ;; `helm-complex-command-history' here. + (cl-loop for i in command-history + unless (equal i '(helm-complex-command-history)) + collect (prin1-to-string i))) + :action (helm-make-actions + "Eval" (lambda (candidate) + (and (boundp 'helm-sexp--last-sexp) + (setq helm-sexp--last-sexp candidate)) + (let ((command (read candidate))) + (unless (equal command (car command-history)) + (setq command-history (cons command command-history)))) + (run-with-timer 0.1 nil #'helm-sexp-eval candidate)) + "Edit and eval" (lambda (candidate) + (edit-and-eval-command "Eval: " (read candidate)))) + :persistent-action #'helm-sexp-eval + :multiline t)) + +;;;###autoload +(defun helm-complex-command-history () + "Preconfigured `helm' for complex command history." + (interactive) + (helm :sources 'helm-source-complex-command-history + :buffer "*helm complex commands*")) + +(provide 'helm-elisp) + +;;; helm-elisp.el ends here diff --git a/org/elpa/helm-20230406.839/helm-epa.el b/org/elpa/helm-20230406.839/helm-epa.el new file mode 100644 index 0000000..2358455 --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-epa.el @@ -0,0 +1,254 @@ +;;; helm-epa.el --- helm interface for epa/epg -*- lexical-binding: t; -*- + +;; Copyright (C) 2012 ~ 2023 Thierry Volpiatto + +;; 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 . + + +;;; Code: + +(require 'helm) + +(eval-when-compile (require 'epg)) +(defvar epa-protocol) +(defvar epa-last-coding-system-specified) +(defvar epg-key-validity-alist) +(defvar mail-header-separator) +(declare-function epg-list-keys "epg") +(declare-function epg-make-context "epg") +(declare-function epg-key-sub-key-list "epg") +(declare-function epg-sub-key-id "epg") +(declare-function epg-key-user-id-list "epg") +(declare-function epg-user-id-string "epg") +(declare-function epg-user-id-validity "epg") +(declare-function epa-sign-region "epa") +(declare-function epa--read-signature-type "epa") +(declare-function epa-display-error "epa") +(declare-function epg-export-keys-to-string "epg") +(declare-function epg-context-armor "epg") +(declare-function epg-context-set-armor "epg") +(declare-function epg-delete-keys "epg") +(declare-function helm-read-file-name "helm-mode") + +(defvar helm-epa--list-only-secrets nil + "[INTERNAL] Used to pass MODE argument to `epg-list-keys'.") + +(defcustom helm-epa-actions '(("Show key" . epa--show-key) + ("encrypt file with key" . helm-epa-encrypt-file) + ("Copy keys to kill ring" . helm-epa-kill-keys-armor) + ("Delete keys" . helm-epa-delete-keys)) + "Actions for `helm-epa-list-keys'." + :type '(alist :key-type string :value-type symbol) + :group 'helm-misc) + +(defclass helm-epa (helm-source-sync) + ((init :initform (lambda () + (require 'epg) + (require 'epa))) + (candidates :initform 'helm-epa-get-key-list) + (keymap :initform 'helm-comp-read-map) + (mode-line :initform 'helm-comp-read-mode-line)) + "Allow building helm sources for GPG keys.") + +(defun helm-epa-get-key-list (&optional keys) + "Build candidate list for `helm-epa-list-keys'." + (cl-loop with all-keys = (or keys (epg-list-keys (epg-make-context epa-protocol) + nil helm-epa--list-only-secrets)) + for key in all-keys + for sublist = (car (epg-key-sub-key-list key)) + for subkey-id = (epg-sub-key-id sublist) + for uid-list = (epg-key-user-id-list key) + for uid = (epg-user-id-string (car uid-list)) + for validity = (epg-user-id-validity (car uid-list)) + collect (cons (format " %s %s %s" + (helm-aif (rassq validity epg-key-validity-alist) + (string (car it)) + "?") + (propertize + subkey-id + 'face (cl-case validity + (none 'epa-validity-medium) + ((revoked expired) + 'epa-validity-disabled) + (t 'epa-validity-high))) + (propertize + uid 'face 'font-lock-warning-face)) + key))) + +(defun helm-epa--select-keys (prompt keys) + "A helm replacement for `epa--select-keys'." + (let ((result (helm :sources (helm-make-source "Epa select keys" 'helm-epa + :candidates (lambda () + (helm-epa-get-key-list keys))) + :prompt (and prompt (helm-epa--format-prompt prompt)) + :buffer "*helm epa*"))) + (unless (equal result "") + result))) + +(defun helm-epa--format-prompt (prompt) + (let ((split (split-string prompt "\n"))) + (if (cdr split) + (format "%s\n(%s): " + (replace-regexp-in-string "\\.[\t ]*\\'" "" (car split)) + (replace-regexp-in-string "\\.[\t ]*\\'" "" (cadr split))) + (format "%s: " (replace-regexp-in-string "\\.[\t ]*\\'" "" (car split)))))) + +(defun helm-epa--read-signature-type () + "A helm replacement for `epa--read-signature-type'." + (let ((answer (helm-read-answer "Signature type: +(n - Create a normal signature) +(c - Create a cleartext signature) +(d - Create a detached signature)" + '("n" "c" "d")))) + (helm-acase answer + ("n" 'normal) + ("c" 'clear) + ("d" 'detached)))) + +(defun helm-epa-collect-keys-from-candidates (candidates) + (cl-loop for c in candidates + collect (epg-sub-key-id + (car (epg-key-sub-key-list c))))) + +(defun helm-epa-collect-id-from-candidates (candidates) + (cl-loop for c in candidates + collect (epg-user-id-string + (car (epg-key-user-id-list c))))) + +(defun helm-epa-success-message (str keys ids) + (message str + (mapconcat (lambda (pair) + (concat (car pair) " " (cdr pair))) + (cl-loop for k in keys + for i in ids + collect (cons k i)) + "\n"))) + +;;;###autoload +(define-minor-mode helm-epa-mode + "Enable helm completion on gpg keys in epa functions." + :group 'helm-misc + :global t + (require 'epa) + (if helm-epa-mode + (progn + (advice-add 'epa--select-keys :override #'helm-epa--select-keys) + (advice-add 'epa--read-signature-type :override #'helm-epa--read-signature-type)) + (advice-remove 'epa-select-keys #'helm-epa--select-keys) + (advice-remove 'epa--read-signature-type #'helm-epa--read-signature-type))) + +(defun helm-epa-action-transformer (actions _candidate) + "Helm epa action transformer function." + (cond ((with-helm-current-buffer + (derived-mode-p 'message-mode 'mail-mode)) + (helm-append-at-nth + actions '(("Sign mail with key" . helm-epa-mail-sign) + ("Encrypt mail with key" . helm-epa-mail-encrypt)) + 3)) + (t actions))) + +(defun helm-epa-delete-keys (_candidate) + "Delete gpg marked keys from helm-epa." + (let ((context (epg-make-context epa-protocol)) + (keys (helm-marked-candidates))) + (message "Deleting gpg keys..") + (condition-case error + (epg-delete-keys context keys) + (error + (epa-display-error context) + (signal (car error) (cdr error)))) + (message "Deleting gpg keys done"))) + +(defun helm-epa-encrypt-file (_candidate) + "Select a file to encrypt with key CANDIDATE." + (let* ((file (helm-read-file-name "Encrypt file: ")) + (cands (helm-marked-candidates)) + (keys (helm-epa-collect-keys-from-candidates cands)) + (ids (helm-epa-collect-id-from-candidates cands))) + (epa-encrypt-file file cands) + (helm-epa-success-message "File encrypted with key(s):\n %s" + keys ids))) + +(defun helm-epa-kill-keys-armor (_candidate) + "Copy marked keys to kill ring." + (let ((keys (helm-marked-candidates)) + (context (epg-make-context epa-protocol))) + (with-no-warnings + (setf (epg-context-armor context) t)) + (condition-case error + (kill-new (epg-export-keys-to-string context keys)) + (error + (epa-display-error context) + (signal (car error) (cdr error)))))) + +(defun helm-epa-mail-sign (candidate) + "Sign email with key CANDIDATE." + (let ((key (epg-sub-key-id (car (epg-key-sub-key-list candidate)))) + (id (epg-user-id-string (car (epg-key-user-id-list candidate)))) + start end mode) + (save-excursion + (goto-char (point-min)) + (if (search-forward mail-header-separator nil t) + (forward-line)) + (setq epa-last-coding-system-specified + (or coding-system-for-write + (select-safe-coding-system (point) (point-max)))) + (let ((verbose current-prefix-arg)) + (setq start (point) + end (point-max) + mode (if verbose + (epa--read-signature-type) + 'clear)))) + ;; TODO Make non-interactive functions to replace epa-sign-region + ;; and epa-encrypt-region and inline them. + (with-no-warnings + (epa-sign-region start end candidate mode)) + (message "Mail signed with key `%s %s'" key id))) + +(defun helm-epa-mail-encrypt (_candidate) + "Encrypt email with key CANDIDATE." + (let ((cands (helm-marked-candidates)) + start end) + (save-excursion + (goto-char (point-min)) + (when (search-forward mail-header-separator nil t) + (forward-line)) + (setq start (point) + end (point-max)) + (setq epa-last-coding-system-specified + (or coding-system-for-write + (select-safe-coding-system start end)))) + ;; Don't let some read-only text stop us from encrypting. + (let ((inhibit-read-only t) + (keys (helm-epa-collect-keys-from-candidates cands)) + (ids (helm-epa-collect-id-from-candidates cands))) + (with-no-warnings + (epa-encrypt-region start end cands nil nil)) + (helm-epa-success-message "Mail encrypted with key(s):\n %s" + keys ids)))) + +;;;###autoload +(defun helm-epa-list-keys () + "List all gpg keys. +This is the helm interface for `epa-list-keys'." + (interactive) + (helm :sources + (helm-make-source "Epg list keys" 'helm-epa + :action-transformer 'helm-epa-action-transformer + :action 'helm-epa-actions) + :buffer "*helm epg list keys*")) + +(provide 'helm-epa) + +;;; helm-epa.el ends here diff --git a/org/elpa/helm-20230406.839/helm-eshell.el b/org/elpa/helm-20230406.839/helm-eshell.el new file mode 100644 index 0000000..2fda09d --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-eshell.el @@ -0,0 +1,494 @@ +;;; helm-eshell.el --- pcomplete and eshell completion for helm. -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2023 Thierry Volpiatto + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; +;; Enable like this in .emacs: +;; (add-hook 'eshell-mode-hook +;; (lambda () +;; (eshell-cmpl-initialize) +;; (define-key eshell-mode-map [remap eshell-pcomplete] 'helm-esh-pcomplete) +;; (define-key eshell-mode-map (kbd "M-s f") 'helm-eshell-prompts-all))) +;; (define-key eshell-mode-map (kbd "M-r") 'helm-eshell-history))) + + +;;; Code: +(require 'cl-lib) +(require 'helm) +(require 'helm-lib) +(require 'helm-help) +(require 'helm-elisp) + +(declare-function eshell-read-aliases-list "em-alias") +(declare-function eshell-send-input "esh-mode" (&optional use-region queue-p no-newline)) +(declare-function eshell-bol "esh-mode") +(declare-function eshell-parse-arguments "esh-arg" (beg end)) +(declare-function eshell-backward-argument "esh-mode" (&optional arg)) +(declare-function helm-quote-whitespace "helm-lib") +(declare-function eshell-skip-prompt "em-prompt") +(defvar eshell-special-chars-outside-quoting) + + +(defgroup helm-eshell nil + "Helm completion and history for Eshell." + :group 'helm) + + +(defcustom helm-eshell-fuzzy-match nil + "Enable fuzzy matching in `helm-esh-pcomplete' when non-nil." + :type 'boolean) + + +(defvar helm-eshell-history-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map helm-map) + (define-key map (kbd "M-p") #'helm-next-line) + map) + "Keymap for `helm-eshell-history'.") + +(defvar helm-esh-completion-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map helm-map) + (define-key map (kbd "TAB") #'helm-next-line) + map) + "Keymap for `helm-esh-pcomplete'.") + +(defvar helm-eshell--quit-flag nil) + + +;; Internal. +(defvar helm-ec-target "") +(defun helm-ec-insert (_candidate) + "Replace text at point with CANDIDATE. +The function that call this should set `helm-ec-target' to thing +at point." + (set (make-local-variable 'comint-file-name-quote-list) + eshell-special-chars-outside-quoting) + (let ((pt (point))) + (when (and helm-ec-target + (search-backward helm-ec-target nil t) + (string= (buffer-substring (point) pt) helm-ec-target)) + (delete-region (point) pt))) + (when (string-match "\\`\\*" helm-ec-target) (insert "*")) + (let ((marked (helm-marked-candidates))) + (prog1 t ;; Makes helm returns t on action. + (insert + (mapconcat + (lambda (x) + (cond ((string-match "\\`~/" helm-ec-target) + ;; Strip out the first escape char added by + ;; `comint-quote-filename' before "~" (Bug#1803). + (substring (comint-quote-filename (abbreviate-file-name x)) 1)) + ((string-match "\\`/" helm-ec-target) + (comint-quote-filename x)) + (t + (concat (and (string-match "\\`[.]/" helm-ec-target) "./") + (comint-quote-filename + (file-relative-name x)))))) + marked " ") + (or (helm-aand (car (last marked)) + (string-match-p "/\\'" it) + "") + " "))))) + +(defun helm-esh-transformer (candidates _sources) + (cl-loop + for i in candidates + collect + (cond ((string-match "\\`~/?" helm-ec-target) + (abbreviate-file-name i)) + ((string-match "\\`/" helm-ec-target) i) + (t + (file-relative-name i))) + into lst + finally return (sort lst #'helm-generic-sort-fn))) + +(defclass helm-esh-source (helm-source-sync) + ((init :initform (lambda () + (setq pcomplete-current-completions nil + pcomplete-last-completion-raw nil) + ;; Eshell-command add this hook in all minibuffers + ;; Remove it for the helm one. (Fixed in Emacs24) + (remove-hook 'minibuffer-setup-hook 'eshell-mode))) + (candidates :initform 'helm-esh-get-candidates) + ;(nomark :initform t) + (persistent-action :initform 'ignore) + (nohighlight :initform t) + (filtered-candidate-transformer :initform #'helm-esh-transformer) + (action :initform 'helm-ec-insert)) + "Helm class to define source for Eshell completion.") + +(defun helm-esh-get-candidates () + "Get candidates for Eshell completion using `pcomplete'." + (catch 'pcompleted + (with-helm-current-buffer + (let* ((pcomplete-stub) + pcomplete-seen pcomplete-norm-func + pcomplete-args pcomplete-last pcomplete-index + (pcomplete-autolist pcomplete-autolist) + (pcomplete-suffix-list pcomplete-suffix-list) + (table (pcomplete-completions)) + (entry (or (try-completion helm-pattern + (pcomplete-entries)) + helm-pattern))) + (cl-loop ;; expand entry too to be able to compare it with file-cand. + with exp-entry = (and (stringp entry) + (not (string= entry "")) + (file-name-as-directory + (expand-file-name entry default-directory))) + with comps = (all-completions pcomplete-stub table) + unless comps return (prog1 nil + ;; Don't add final space when + ;; there is no completion (Bug#1990). + (setq helm-eshell--quit-flag t) + (message "No completions of %s" pcomplete-stub)) + for i in comps + ;; Transform the relative names to abs names. + for file-cand = (and exp-entry + (if (file-remote-p i) i + (expand-file-name + i (file-name-directory + (if (directory-name-p pcomplete-stub) + entry + (directory-file-name entry)))))) + ;; Compare them to avoid dups. + for file-entry-p = (and (stringp exp-entry) + (stringp file-cand) + ;; Fix :/tmp/foo/ $ cd foo + (not (file-directory-p file-cand)) + (file-equal-p exp-entry file-cand)) + if (and file-cand (or (file-remote-p file-cand) + (file-exists-p file-cand)) + (not file-entry-p)) + collect file-cand into ls + else + ;; Avoid adding entry here. + unless file-entry-p collect i into ls + finally return + (if (and exp-entry + (file-directory-p exp-entry) + ;; If the car of completion list is + ;; an executable, probably we are in + ;; command completion, so don't add a + ;; possible file related entry here. + (and ls (not (executable-find (car ls)))) + ;; Don't add entry if already in prompt. + (not (file-equal-p exp-entry pcomplete-stub))) + (append (list exp-entry) + ;; Entry should not be here now but double check. + (remove entry ls)) + ls)))))) + +;;; Eshell history. +;; +;; +(defclass helm-eshell-history-source (helm-source-sync) + ((init :initform + (lambda () + ;; Same comment as in `helm-source-esh'. + (remove-hook 'minibuffer-setup-hook 'eshell-mode))) + (candidates + :initform + (lambda () + (with-helm-current-buffer + (cl-loop for c from 0 to (ring-length eshell-history-ring) + for elm = (eshell-get-history c) + unless (and (member elm lst) + eshell-hist-ignoredups) + collect elm into lst + finally return lst)))) + (nomark :initform t) + (multiline :initform t) + (keymap :initform 'helm-eshell-history-map) + (candidate-number-limit :initform 9999) + (action :initform (lambda (candidate) + (eshell-kill-input) + (insert candidate)))) + "Helm class to define source for Eshell history.") + + +(defun helm-esh-pcomplete-input (target users-comp last) + (if (and (stringp last) + (not (string= last "")) + (not users-comp) + ;; Fix completion on "../" see Bug#1832. + (or (file-exists-p last) + (helm-aand + (file-name-directory last) + (file-directory-p it)))) + (if (and (file-directory-p last) + (string-match "\\`[~.]*.*/[.]\\'" target)) + ;; Fix completion on "~/.", "~/[...]/.", and "../." + (expand-file-name + (concat (helm-basedir (file-name-as-directory last)) + (regexp-quote (helm-basename target)))) + (expand-file-name last)) + ;; Don't add "~" to input to provide completion on all users instead of only + ;; on current $HOME (#1832). + (unless users-comp last))) + +(defun helm-esh-pcomplete-default-source () + "Make and return the default source for Eshell completion." + (helm-make-source "Eshell completions" 'helm-esh-source + :fuzzy-match helm-eshell-fuzzy-match + :keymap helm-esh-completion-map)) + +(defvar helm-esh-pcomplete-build-source-fn #'helm-esh-pcomplete-default-source + "Function that builds a source or a list of sources.") + +(defun helm-esh-pcomplete--make-helm (&optional input) + (helm :sources (funcall helm-esh-pcomplete-build-source-fn) + :buffer "*helm pcomplete*" + :resume 'noresume + :input input)) + +;;;###autoload +(defun helm-esh-pcomplete () + "Preconfigured `helm' to provide Helm completion in Eshell." + (interactive) + (let* ((helm-quit-if-no-candidate t) + (helm-execute-action-at-once-if-one t) + (end (point-marker)) + (beg (save-excursion (eshell-bol) (point))) + (args (catch 'eshell-incomplete + (eshell-parse-arguments beg end))) + (target + (or (and (looking-back " " (1- (point))) " ") + (buffer-substring-no-properties + (save-excursion + (eshell-backward-argument 1) (point)) + end))) + (users-comp (string= target "~")) + (first (car args)) ; Maybe lisp delimiter "(". + last ; Will be the last but parsed by pcomplete. + del-space + del-dot) + (setq helm-ec-target (or target " ") + end (point) + ;; Reset beg for `with-helm-show-completion'. + beg (or (and target (not (string= target " ")) + (- end (length target))) + ;; Nothing at point. + (progn (insert " ") (setq del-space t) (point)))) + (when (string-match "\\`[~.]*.*/[.]\\'" target) + ;; Fix completion on + ;; "~/.", "~/[...]/.", and "../." + (delete-char -1) (setq del-dot t) + (setq helm-ec-target (substring helm-ec-target 0 (1- (length helm-ec-target))))) + (cond ((eq first ?\() + (helm-lisp-completion-or-file-name-at-point)) + ;; In eshell `pcomplete-parse-arguments' is called + ;; with `pcomplete-parse-arguments-function' + ;; locally bound to `eshell-complete-parse-arguments' + ;; which is calling `lisp-complete-symbol', + ;; calling it before would popup the + ;; *completions* buffer. + (t (setq last (replace-regexp-in-string + "\\`\\*" "" + (car (last (ignore-errors + (pcomplete-parse-arguments)))))) + ;; Set helm-eshell--quit-flag to non-nil only on + ;; quit, this tells to not add final suffix when quitting + ;; helm. + (add-hook 'helm-quit-hook #'helm-eshell--quit-hook-fn) + (with-helm-show-completion beg end + (unwind-protect + (or (helm-esh-pcomplete--make-helm + (helm-esh-pcomplete-input target users-comp last)) + ;; Delete removed dot on quit + (and del-dot (prog1 t (insert "."))) + ;; A space is needed to have completion, remove + ;; it when nothing found. + (and del-space (looking-back "\\s-" (1- (point))) + (delete-char -1)) + (if (and (null helm-eshell--quit-flag) + (and (stringp last) (file-directory-p last)) + (looking-back "\\([.]\\{1,2\\}\\|[^/]\\)\\'" + (1- (point)))) + (prog1 t (insert "/")) + ;; We need another flag for space here, but + ;; global to pass it to `helm-quit-hook', this + ;; space is added when point is just after + ;; previous completion and there is no + ;; more completion, see Bug#1832. + (unless (or helm-eshell--quit-flag + (looking-back "/\\'" (1- (point)))) + (prog1 t (insert " "))) + (when (and helm-eshell--quit-flag + (string-match-p "[.]\\{2\\}\\'" last)) + (insert "/")))) + (remove-hook 'helm-quit-hook #'helm-eshell--quit-hook-fn) + (setq helm-eshell--quit-flag nil))))))) + +(defun helm-eshell--quit-hook-fn () + (setq helm-eshell--quit-flag t)) + +;;;###autoload +(defun helm-eshell-history () + "Preconfigured Helm for Eshell history." + (interactive) + (let* ((end (point)) + (beg (save-excursion (eshell-bol) (point))) + (input (buffer-substring beg end)) + flag-empty) + (when (eq beg end) + (insert " ") + (setq flag-empty t) + (setq end (point))) + (unwind-protect + (with-helm-show-completion beg end + (helm :sources (helm-make-source "Eshell history" + 'helm-eshell-history-source + :fuzzy-match helm-eshell-fuzzy-match) + :buffer "*helm eshell history*" + :resume 'noresume + :input input)) + (when (and flag-empty + (looking-back " " (1- (point)))) + (delete-char -1))))) + + +;;; Eshell prompts +;; +(defface helm-eshell-prompts-promptidx + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "cyan")) + "Face used to highlight Eshell prompt index.") + +(defface helm-eshell-prompts-buffer-name + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "green")) + "Face used to highlight Eshell buffer name.") + +(defcustom helm-eshell-prompts-promptidx-p t + "Show prompt number." + :type 'boolean) + +(defvar helm-eshell-prompts-keymap + (let ((map (make-sparse-keymap))) + (set-keymap-parent map helm-map) + (define-key map (kbd "C-c o") #'helm-eshell-prompts-other-window) + (define-key map (kbd "C-c C-o") #'helm-eshell-prompts-other-frame) + map) + "Keymap for `helm-eshell-prompt-all'.") + +(defvar eshell-prompt-regexp) +(defvar eshell-highlight-prompt) + +(defun helm-eshell-prompts-list (&optional buffer) + "List the prompts in Eshell BUFFER. + +Return a list of (\"prompt\" (point) (buffer-name) prompt-index)) +E.g. (\"ls\" 162 \"*eshell*\" 3). +If BUFFER is nil, use current buffer." + (with-current-buffer (or buffer (current-buffer)) + (when (eq major-mode 'eshell-mode) + (save-excursion + (goto-char (point-min)) + (let (result (count 1)) + (helm-awhile (re-search-forward eshell-prompt-regexp nil t) + (when (or (and eshell-highlight-prompt + (get-text-property (match-beginning 0) 'read-only)) + (null eshell-highlight-prompt)) + (push (list (buffer-substring-no-properties + it (point-at-eol)) + it (buffer-name) count) + result) + (setq count (1+ count)))) + (nreverse result)))))) + +(defun helm-eshell-prompts-list-all () + "List the prompts of all Eshell buffers. +See `helm-eshell-prompts-list'." + (cl-loop for b in (buffer-list) + append (helm-eshell-prompts-list b))) + +(defun helm-eshell-prompts-transformer (candidates &optional all) + ;; ("ls" 162 "*eshell*" 3) => ("*eshell*:3:ls" . ("ls" 162 "*eshell*" 3)) + (cl-loop for (prt pos buf id) in candidates + collect `(,(concat + (when all + (concat (propertize + buf + 'face 'helm-eshell-prompts-buffer-name) + ":")) + (when helm-eshell-prompts-promptidx-p + (concat (propertize + (number-to-string id) + 'face 'helm-eshell-prompts-promptidx) + ":")) + prt) + . ,(list prt pos buf id)))) + +(defun helm-eshell-prompts-all-transformer (candidates) + (helm-eshell-prompts-transformer candidates t)) + +(cl-defun helm-eshell-prompts-goto (candidate &optional (action 'switch-to-buffer)) + ;; Candidate format: ("ls" 162 "*eshell*" 3) + (let ((buf (nth 2 candidate))) + (unless (and (string= (buffer-name) buf) + (eq action 'switch-to-buffer)) + (funcall action buf)) + (goto-char (nth 1 candidate)) + (recenter))) + +(defun helm-eshell-prompts-goto-other-window (candidate) + (helm-eshell-prompts-goto candidate 'switch-to-buffer-other-window)) + +(defun helm-eshell-prompts-goto-other-frame (candidate) + (helm-eshell-prompts-goto candidate 'switch-to-buffer-other-frame)) + +(helm-make-command-from-action helm-eshell-prompts-other-window + "Switch to eshell prompt in other window." + 'helm-eshell-prompts-goto-other-window) + +(helm-make-command-from-action helm-eshell-prompts-other-frame + "Switch to eshell prompt in other frame." + 'helm-eshell-prompts-goto-other-frame) + +;;;###autoload +(defun helm-eshell-prompts () + "Pre-configured `helm' to browse the prompts of the current Eshell." + (interactive) + (if (eq major-mode 'eshell-mode) + (helm :sources + (helm-build-sync-source "Eshell prompts" + :candidates (helm-eshell-prompts-list) + :candidate-transformer 'helm-eshell-prompts-transformer + :action '(("Go to prompt" . helm-eshell-prompts-goto))) + :buffer "*helm Eshell prompts*") + (message "Current buffer is not an Eshell buffer"))) + +;;;###autoload +(defun helm-eshell-prompts-all () + "Pre-configured `helm' to browse the prompts of all Eshell sessions." + (interactive) + (helm :sources + (helm-build-sync-source "All Eshell prompts" + :candidates (helm-eshell-prompts-list-all) + :candidate-transformer 'helm-eshell-prompts-all-transformer + :action '(("Go to prompt" . helm-eshell-prompts-goto) + ("Go to prompt in other window `C-c o`" . + helm-eshell-prompts-goto-other-window) + ("Go to prompt in other frame `C-c C-o`" . + helm-eshell-prompts-goto-other-frame)) + :keymap helm-eshell-prompts-keymap) + :buffer "*helm Eshell all prompts*")) + +(provide 'helm-eshell) + +;;; helm-eshell ends here diff --git a/org/elpa/helm-20230406.839/helm-eval.el b/org/elpa/helm-20230406.839/helm-eval.el new file mode 100644 index 0000000..5495374 --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-eval.el @@ -0,0 +1,215 @@ +;;; helm-eval.el --- eval expressions from helm. -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2023 Thierry Volpiatto + +;; 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 . + +;;; Code: +(require 'cl-lib) +(require 'helm) +(require 'helm-help) +(require 'eldoc) +(require 'edebug) + +(declare-function helm-lisp-completion-at-point "helm-elisp.el") + + +(defgroup helm-eval nil + "Eval related Applications and libraries for Helm." + :group 'helm) + +(defcustom helm-eldoc-in-minibuffer-show-fn + 'helm-show-info-in-mode-line + "A function to display eldoc info. +Should take one arg: the string to display." + :group 'helm-eval + :type 'symbol) + +(defcustom helm-show-info-in-mode-line-delay 12 + "Eldoc will show info in mode-line during this delay if user is idle." + :type 'integer + :group 'helm-eval) + + +;;; Eldoc compatibility between emacs-24 and emacs-25 +;; +(if (require 'elisp-mode nil t) ; emacs-25 + ;; Maybe the eldoc functions have been + ;; already aliased by eldoc-eval. + (cl-loop for (f . a) in '((eldoc-current-symbol . + elisp--current-symbol) + (eldoc-fnsym-in-current-sexp . + elisp--fnsym-in-current-sexp) + (eldoc-get-fnsym-args-string . + elisp-get-fnsym-args-string) + (eldoc-get-var-docstring . + elisp-get-var-docstring)) + unless (fboundp f) + do (defalias f a)) + ;; Emacs-24. + (declare-function eldoc-current-symbol "eldoc") + (declare-function eldoc-get-fnsym-args-string "eldoc" (sym &optional index)) + (declare-function eldoc-get-var-docstring "eldoc" (sym)) + (declare-function eldoc-fnsym-in-current-sexp "eldoc")) + +;;; Evaluation Result +;; +;; +;; Internal +(defvar helm-eldoc-active-minibuffers-list nil) + +(defvar helm-eval-expression-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map helm-map) + (define-key map (kbd "") #'helm-eval-new-line-and-indent) + (define-key map (kbd "") #'lisp-indent-line) + (define-key map (kbd "") #'helm-lisp-completion-at-point) + (define-key map (kbd "C-p") #'previous-line) + (define-key map (kbd "C-n") #'next-line) + (define-key map (kbd "") #'previous-line) + (define-key map (kbd "") #'next-line) + (define-key map (kbd "") #'forward-char) + (define-key map (kbd "") #'backward-char) + map)) + +(defun helm-build-evaluation-result-source () + (helm-build-dummy-source "Evaluation Result" + :multiline t + :mode-line "C-RET: nl-and-indent, M-tab: reindent, C-tab:complete, C-p/n: next/prec-line." + :filtered-candidate-transformer + (lambda (_candidates _source) + (list + (condition-case nil + (with-helm-current-buffer + (pp-to-string + (if edebug-active + (edebug-eval-expression + (read helm-pattern)) + (eval (read helm-pattern) t)))) + (error "Error")))) + :nohighlight t + :keymap helm-eval-expression-map + :action '(("Copy result to kill-ring" . (lambda (candidate) + (kill-new + (replace-regexp-in-string + "\n" "" candidate)) + (message "Result copied to kill-ring"))) + ("copy sexp to kill-ring" . (lambda (_candidate) + (kill-new helm-input) + (message "Sexp copied to kill-ring")))))) + +(defun helm-eval-new-line-and-indent () + (interactive) + (newline) (lisp-indent-line)) + +(defun helm-eldoc-store-minibuffer () + "Store minibuffer buffer name in `helm-eldoc-active-minibuffers-list'." + (with-selected-window (minibuffer-window) + (push (current-buffer) helm-eldoc-active-minibuffers-list))) + +;; From emacs-28.1: As the eldoc API is nowaday a pain to use, try to +;; provide some eldoc in mode-line the best as possible (may break at +;; some point). +(defun helm-eldoc-show-in-eval () + "Return eldoc in mode-line for current minibuffer input." + (let ((buf (window-buffer (active-minibuffer-window)))) + (condition-case err + (when (member buf helm-eldoc-active-minibuffers-list) + (with-current-buffer buf + (let* ((info-fn (eldoc-fnsym-in-current-sexp)) + (vsym (eldoc-current-symbol)) + (sym (car info-fn)) + (vardoc (eldoc-get-var-docstring vsym)) + (doc (or vardoc + (eldoc-get-fnsym-args-string + sym (cadr info-fn)))) + (all (format "%s: %s" + (propertize + (symbol-name (if vardoc vsym sym)) + 'face (if vardoc + 'font-lock-variable-name-face + 'font-lock-function-name-face)) + doc))) + (when doc (funcall helm-eldoc-in-minibuffer-show-fn all))))) + (error (message "Eldoc in minibuffer error: %S" err) nil)))) + +(defun helm-show-info-in-mode-line (str) + "Display string STR in mode-line." + (save-selected-window + (with-helm-window + (let ((mode-line-format (concat " " str))) + (force-mode-line-update) + (sit-for helm-show-info-in-mode-line-delay)) + (force-mode-line-update)))) + +;;; Calculation Result +;; +;; +(defvar helm-source-calculation-result + (helm-build-dummy-source "Calculation Result" + :filtered-candidate-transformer (lambda (_candidates _source) + (list + (condition-case err + (let ((result (calc-eval helm-pattern))) + (if (listp result) + (error "At pos %s: %s" + (car result) (cadr result)) + result)) + (error (cdr err))))) + :nohighlight t + :action '(("Copy result to kill-ring" . (lambda (candidate) + (kill-new candidate) + (message "Result \"%s\" copied to kill-ring" + candidate))) + ("Copy operation to kill-ring" . (lambda (_candidate) + (kill-new helm-input) + (message "Calculation copied to kill-ring")))))) + +;;;###autoload +(defun helm-eval-expression (arg) + "Preconfigured `helm' for `helm-source-evaluation-result'." + (interactive "P") + (let ((helm-elisp-help-function #'helm-elisp-show-doc-modeline)) + (helm :sources (helm-build-evaluation-result-source) + :input (when arg (thing-at-point 'sexp)) + :buffer "*helm eval*" + :echo-input-in-header-line nil + :history 'read-expression-history))) + +(defvar eldoc-idle-delay) +;;;###autoload +(defun helm-eval-expression-with-eldoc () + "Preconfigured `helm' for `helm-source-evaluation-result' with `eldoc' support." + (interactive) + (let ((timer (run-with-idle-timer + eldoc-idle-delay 'repeat + #'helm-eldoc-show-in-eval))) + (unwind-protect + (minibuffer-with-setup-hook + #'helm-eldoc-store-minibuffer + (call-interactively 'helm-eval-expression)) + (and timer (cancel-timer timer)) + (setq helm-eldoc-active-minibuffers-list + (cdr helm-eldoc-active-minibuffers-list))))) + +;;;###autoload +(defun helm-calcul-expression () + "Preconfigured `helm' for `helm-source-calculation-result'." + (interactive) + (helm :sources 'helm-source-calculation-result + :buffer "*helm calcul*")) + +(provide 'helm-eval) + +;;; helm-eval.el ends here diff --git a/org/elpa/helm-20230406.839/helm-external.el b/org/elpa/helm-20230406.839/helm-external.el new file mode 100644 index 0000000..2ed7733 --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-external.el @@ -0,0 +1,265 @@ +;;; helm-external.el --- Run Externals commands within Emacs with helm completion. -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2023 Thierry Volpiatto + +;; 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 . + +;;; Code: + +(require 'cl-lib) +(require 'helm) +(require 'helm-help) +(require 'helm-net) + +(declare-function helm-comp-read "helm-mode") + + +(defgroup helm-external nil + "External related Applications and libraries for Helm." + :group 'helm) + +(defcustom helm-raise-command nil + "A shell command to jump to a window running specific program. +Need external program wmctrl. +This will be use with `format', so use something like \"wmctrl -xa %s\"." + :type 'string + :group 'helm-external) + +(defcustom helm-external-programs-associations nil + "Alist to store externals programs associated with file extension. +This variable overhide setting in .mailcap file. +E.g.: \\='((\"jpg\" . \"gqview\") (\"pdf\" . \"xpdf\")) " + :type '(alist :key-type string :value-type string) + :group 'helm-external) + +(defcustom helm-default-external-file-browser "nautilus" + "Default external file browser for your system. +Directories will be opened externally with it when opening file +externally in `helm-find-files'. +Set to nil if you do not have an external file browser or do not +want to use it. +Windows users should set that to \"explorer.exe\"." + :group 'helm-external + :type 'string) + +(defvar helm-open-file-externally-after-hook nil + "Hook that run after opening a file with external program.") + +(defvar helm-open-file-externally-after-finish-hook nil + "Hook that run after external program finish.") + +;;; Internals +(defvar helm-external-command-history nil) +(defvar helm-external-commands-list nil + "A list of all external commands the user can execute. +If this variable is not set by the user, it will be calculated +automatically.") + +(defun helm-external-commands-list-1 (&optional sort) + "Returns a list of all external commands the user can execute. +If `helm-external-commands-list' is non-nil it will return its +contents. Else it calculates all external commands and sets +`helm-external-commands-list'." + (helm-aif helm-external-commands-list + it + (setq helm-external-commands-list + (cl-loop + for dir in (split-string (getenv "PATH") path-separator) + when (and (file-exists-p dir) (file-accessible-directory-p dir)) + for lsdir = (cl-loop for i in (directory-files dir t) + for bn = (file-name-nondirectory i) + when (and (not (member bn completions)) + (not (file-directory-p i)) + (file-executable-p i)) + collect bn) + append lsdir into completions + finally return + (if sort (sort completions 'string-lessp) completions))))) + +(defun helm-run-or-raise (exe &optional files detached) + "Run asynchronously EXE or jump to the application window. +If EXE is already running just jump to his window if +`helm-raise-command' is non-nil. +When FILES argument is provided run EXE with FILES. +When argument DETACHED is non nil, detach process from Emacs." + (let* ((proc-name (replace-regexp-in-string + "(" "" (car (split-string exe)))) + (fmt-file (lambda (file) + (shell-quote-argument + (if (eq system-type 'windows-nt) + (helm-w32-prepare-filename file) + (expand-file-name file))))) + (file-arg (and files (mapconcat fmt-file files " "))) + process-connection-type proc) + (when (and files detached (not (string-match "%s &)\\'" exe))) + (setq exe (format "(%s &)" exe))) + (when (member proc-name helm-external-commands-list) + ;; Allow adding more files to the current process if it is + ;; already running (i.e. Don't just raise it without sending + ;; files) we assume program doesn't start a new + ;; process (like firefox, transmission etc...). + (if files + (cond ((string-match "%s &)\\'" exe) + (message "Starting and detaching `%s' from Emacs" proc-name) + (call-process-shell-command (format exe file-arg))) + (t + (message "Starting %s..." proc-name) + (setq proc + (start-process-shell-command + proc-name nil (if (string-match "%s" exe) + (format exe file-arg) + (format "%s %s" exe file-arg)))))) + ;; Just jump to the already running program instance or start + ;; a new process. + (if (get-process proc-name) + (if helm-raise-command + (run-at-time 0.1 nil #'shell-command + (format helm-raise-command proc-name)) + (error "Error: %s is already running" proc-name)) + (if (and detached (not (memq system-type '(windows-nt ms-dos)))) + (progn + (message "Starting and detaching `%s' from Emacs" proc-name) + (call-process-shell-command (format "(%s &)" exe))) + (when detached + (user-error "Detaching programs not supported on `%s'" system-type)) + (setq proc (start-process-shell-command proc-name nil exe))))) + (when proc + (set-process-sentinel + proc + (lambda (process event) + (when (and (string= event "finished\n") + helm-raise-command + (not (helm-get-pid-from-process-name proc-name))) + (run-hooks 'helm-open-file-externally-after-finish-hook) + (shell-command (format helm-raise-command "emacs"))) + (message "%s process...Finished." process)))) + ;; Move command on top list. + (setq helm-external-commands-list + (cons proc-name + (delete proc-name helm-external-commands-list)))))) + +(defun helm-get-mailcap-for-file (filename) + "Get the command to use for FILENAME from mailcap files." + (mailcap-parse-mailcaps) + (let* ((ext (file-name-extension filename)) + (mime (when ext (mailcap-extension-to-mime ext))) + (result (when mime (mailcap-mime-info mime)))) + ;; If elisp file have no associations in .mailcap + ;; `mailcap-maybe-eval' is returned, in this case just return nil. + (when (stringp result) (helm-basename result)))) + +(defun helm-get-default-program-for-file (filename) + "Try to find a default program to open FILENAME. +Try first in `helm-external-programs-associations' and then in +mailcap file. If nothing found return nil." + (let* ((ext (file-name-extension filename)) + (def-prog (assoc-default ext helm-external-programs-associations))) + (cond ((and def-prog (not (string= def-prog ""))) def-prog) + ((and helm-default-external-file-browser (file-directory-p filename)) + helm-default-external-file-browser) + (t (helm-get-mailcap-for-file filename))))) + +(defun helm-open-file-externally (_file) + "Open FILE with an external program. +Try to guess which program to use with +`helm-get-default-program-for-file'. +If not found or a prefix arg is given query the user which tool +to use." + (let* ((files (helm-marked-candidates :with-wildcard t)) + (fname (expand-file-name (car files))) + (collection (helm-external-commands-list-1 'sort)) + (def-prog (helm-get-default-program-for-file fname)) + (program (if (or helm-current-prefix-arg (not def-prog)) + ;; Prefix arg or no default program. + (prog1 + (helm-comp-read + "Program: " collection + :must-match t + :name "Open file Externally" + :history 'helm-external-command-history) + ;; Always prompt to set this program as default. + (setq def-prog nil)) + ;; No prefix arg or default program exists. + def-prog))) + (unless (or def-prog ; Association exists, no need to record it. + ;; Don't try to record non--filenames associations (e.g urls). + (not (file-exists-p fname))) + (when + (y-or-n-p + (format + "Do you want to make `%s' the default program for this kind of files? " + program)) + (helm-aif (assoc (file-name-extension fname) + helm-external-programs-associations) + (setq helm-external-programs-associations + (delete it helm-external-programs-associations))) + (push (cons (file-name-extension fname) + (helm-read-string + "Program (Add args maybe and confirm): " program)) + helm-external-programs-associations) + (customize-save-variable 'helm-external-programs-associations + helm-external-programs-associations))) + (helm-run-or-raise program files) + (run-hooks 'helm-open-file-externally-after-hook) + (setq helm-external-command-history + (cl-loop for i in helm-external-command-history + when (executable-find i) collect i)))) + +(defun helm-run-external-command-action (candidate &optional detached) + (helm-run-or-raise candidate nil detached) + (setq helm-external-command-history + (cons candidate + (delete candidate + helm-external-command-history)))) + +(defclass helm-external-commands (helm-source-in-buffer) + ((filtered-candidate-transformer + :initform (lambda (candidates _source) + (cl-loop for c in candidates + if (get-process c) + collect (propertize c 'face 'font-lock-type-face) + else collect c))) + (must-match :initform t) + (nomark :initform t) + (action :initform + (helm-make-actions + "Run program" 'helm-run-external-command-action + (lambda () + (unless (memq system-type '(windows-nt ms-dos)) + "Run program detached")) + (lambda (candidate) + (helm-run-external-command-action candidate 'detached)))))) + +;;;###autoload +(defun helm-run-external-command () + "Preconfigured `helm' to run External PROGRAM asyncronously from Emacs. +If program is already running try to run `helm-raise-command' if +defined otherwise exit with error. You can set your own list of +commands with `helm-external-commands-list'." + (interactive) + (helm :sources `(,(helm-make-source "External Commands history" 'helm-external-commands + :data helm-external-command-history) + ,(helm-make-source "External Commands" 'helm-external-commands + :data (helm-external-commands-list-1 'sort))) + :buffer "*helm externals commands*" + :prompt "RunProgram: ") + ;; Remove from history no more valid executables. + (setq helm-external-command-history + (cl-loop for i in helm-external-command-history + when (executable-find i) collect i))) + + +(provide 'helm-external) + +;;; helm-external ends here diff --git a/org/elpa/helm-20230406.839/helm-fd.el b/org/elpa/helm-20230406.839/helm-fd.el new file mode 100644 index 0000000..2b427b1 --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-fd.el @@ -0,0 +1,143 @@ +;;; helm-fd.el --- helm interface for fd command line tool. -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2023 Thierry Volpiatto + +;; 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 . + +;;; Code: + +(require 'helm) +(require 'helm-types) + +(declare-function ansi-color-apply "ansi-color.el") + +(defvar helm-fd-executable "fd" + "The fd shell command executable.") + +(defcustom helm-fd-switches '("--no-ignore" "--hidden" "--type" "f" "--type" "d" "--color" "always") + "A list of options to pass to fd shell command." + :type '(repeat string) + :group 'helm-files) + +(defcustom helm-fd-mode-line-function 'helm-fd-default-mode-line + "Function called when `fd' process is finished to format mode-line." + :type 'function + :group 'helm-files) + +(defface helm-fd-finish + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "Green")) + "Face used in mode line when fd process ends." + :group 'helm-grep-faces) + +(defvar helm-fd-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map helm-generic-files-map) + (define-key map (kbd "C-]") 'undefined) + (define-key map (kbd "DEL") 'helm-delete-backward-no-update) + (define-key map (kbd "M-") 'helm-fd-next-directory) + (define-key map (kbd "M-") 'helm-fd-previous-directory) + map)) + +(defun helm-fd-next-directory-1 (arg) + (with-helm-window + (let ((cur-dir (helm-basedir (helm-get-selection)))) + (while (equal cur-dir (helm-basedir (helm-get-selection))) + (if (> arg 0) + (helm-next-line) + (helm-previous-line)))))) + +(defun helm-fd-next-directory () + "Move to next directory in a helm-fd source." + (interactive) + (with-helm-alive-p + (helm-fd-next-directory-1 1))) + +(defun helm-fd-previous-directory () + "Move to previous directory in a helm-fd source." + (interactive) + (with-helm-alive-p + (helm-fd-next-directory-1 -1))) + +(defclass helm-fd-class (helm-source-async) + ((candidates-process :initform 'helm-fd-process) + (requires-pattern :initform 2) + (candidate-number-limit :initform 20000) + (nohighlight :initform t) + (help-message :initform 'helm-fd-help-message) + (filtered-candidate-transformer :initform 'helm-fd-fct) + (action :initform 'helm-type-file-actions) + (keymap :initform 'helm-fd-map))) + +(defun helm-fd-process () + "Initialize fd process in an helm async source." + (let* (process-connection-type + (cmd (append helm-fd-switches + (or (and (fboundp #'split-string-shell-command) + (split-string-shell-command helm-pattern)) + (split-string helm-pattern)))) + (proc (apply #'start-process "fd" nil helm-fd-executable cmd)) + (start-time (float-time)) + (fd-version (replace-regexp-in-string + "\n" "" + (shell-command-to-string + (concat helm-fd-executable " --version"))))) + (helm-log "helm-fd-process" "Fd command:\nfd %s" + (mapconcat 'identity cmd " ")) + (helm-log "helm-fd-process" "VERSION: %s" fd-version) + (prog1 + proc + (set-process-sentinel + proc (lambda (_process event) + (if (string= event "finished\n") + (with-helm-window + (when helm-fd-mode-line-function + (funcall helm-fd-mode-line-function start-time fd-version) + (force-mode-line-update))) + (helm-log "helm-fd-process sentinel" "Error: Fd %s" + (replace-regexp-in-string "\n" "" event)))))))) + +(defun helm-fd-default-mode-line (start-time fd-version) + "Format mode-line with START-TIME and FD-VERSION, as well as `fd' results." + (setq mode-line-format + `(" " mode-line-buffer-identification " " + (:eval (format "L%s" (helm-candidate-number-at-point))) " " + (:eval (propertize + (format + "[%s process finished in %.2fs - (%s results)] " + ,fd-version + ,(- (float-time) start-time) + (helm-get-candidate-number)) + 'face 'helm-fd-finish))))) + +(defun helm-fd-fct (candidates _source) + "The filtered-candidate-transformer function for helm-fd." + (cl-loop for i in candidates + collect (ansi-color-apply i))) + +(defun helm-fd-1 (directory) + "Run fd shell command on DIRECTORY with helm interface." + (cl-assert (executable-find helm-fd-executable) nil "Could not find fd executable") + (cl-assert (not (file-remote-p directory)) nil "Fd not supported on remote directories") + (let ((default-directory directory)) + (helm :sources (helm-make-source + (format "fd (%s)" + (abbreviate-file-name default-directory)) + 'helm-fd-class) + :buffer "*helm fd*"))) + + +(provide 'helm-fd) + +;;; helm-fd.el ends here diff --git a/org/elpa/helm-20230406.839/helm-files.el b/org/elpa/helm-20230406.839/helm-files.el new file mode 100644 index 0000000..1db6d6c --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-files.el @@ -0,0 +1,6679 @@ +;;; helm-files.el --- helm file browser and related. -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2023 Thierry Volpiatto + +;; 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 . + +;;; Code: + +(require 'cl-lib) +(require 'helm) +(require 'helm-types) +(require 'helm-utils) +(require 'helm-grep) +(require 'helm-help) +(require 'helm-locate) +(require 'helm-tags) +(require 'helm-buffers) +(require 'tramp) +(eval-when-compile + (require 'thingatpt) + (require 'ffap) + (require 'dired-aux) + (require 'dired-x)) +(require 'filenotify) +(require 'image-mode) +(require 'image-dired) + +(declare-function find-library-name "find-func.el" (library)) +(declare-function w32-shell-execute "ext:w32fns.c" (operation document &optional parameters show-flag)) +(declare-function gnus-dired-attach "ext:gnus-dired.el" (files-to-attach)) +(declare-function eshell-read-aliases-list "em-alias") +(declare-function eshell-send-input "esh-mode" (&optional use-region queue-p no-newline)) +(declare-function eshell-kill-input "esh-mode") +(declare-function eshell-bol "esh-mode") +(declare-function eshell-reset "esh-mode.el") +(declare-function eshell/cd "em-dirs.el") +(declare-function eshell-next-prompt "em-prompt.el") +(declare-function eshell-resume-eval "esh-cmd") +(declare-function helm-ls-git "ext:helm-ls-git") +(declare-function helm-hg-find-files-in-project "ext:helm-ls-hg") +(declare-function helm-gid "helm-id-utils.el") +(declare-function helm-find-1 "helm-find") +(declare-function helm-fd-1 "helm-fd") +(declare-function helm-get-default-program-for-file "helm-external") +(declare-function helm-open-file-externally "helm-external") +(declare-function helm-comp-read "helm-mode") +(declare-function helm-read-file-name "helm-mode") +(declare-function term-line-mode "term") +(declare-function term-char-mode "term") +(declare-function term-send-input "term") +(declare-function term-next-prompt "term") +(declare-function term-process-mark "term") +(declare-function bookmark-prop-get "bookmark") +(declare-function comint-next-prompt "comint") +(declare-function comint-delete-input "comint") +(declare-function comint-send-input "comint") +(declare-function comint-goto-process-mark "comint") +(declare-function tramp-dissect-file-name "tramp") +(declare-function tramp-get-completion-function "tramp") +(declare-function seconds-to-time "time-date") +(declare-function ffap-fixup-url "ffap") +(declare-function ffap-url-at-point "ffap") +(declare-function ffap-file-at-point "ffap") +(declare-function dired-create-files "dired-aux") +(declare-function dired-goto-file "dired") +(declare-function dired-move-to-filename "dired") +(declare-function dired-move-to-end-of-filename "dired") +(declare-function dired-get-filename "dired") +(declare-function dired-get-marked-files "dired") +(declare-function tramp-list-connections "tramp-cache") +(declare-function tramp-get-connection-process "tramp") +(declare-function tramp-buffer-name "tramp") +(declare-function tramp-make-tramp-file-name "tramp") +(declare-function tramp-cleanup-connection "tramp-cmds") +(declare-function dired-async-processes "ext:dired-async.el") +(declare-function dired-async-mode-line-message "ext:dired-async.el") +(declare-function dired-async--modeline-mode "ext:dired-async.el") +(declare-function all-the-icons-icon-for-file "ext:all-the-icons.el") +(declare-function all-the-icons-octicon "ext:all-the-icons.el") +(declare-function all-the-icons-match-to-alist "ext:all-the-icons.el") +(declare-function helm-adaptive-sort "ext:helm-adaptive.el") +(declare-function wfnames-setup-buffer "ext:wfnames.el") + +(defvar all-the-icons-dir-icon-alist) +(defvar term-char-mode-point-at-process-mark) +(defvar term-char-mode-buffer-read-only) +(defvar recentf-list) +(defvar helm-mm-matching-method) +(defvar dired-async-mode) +(defvar org-directory) +(defvar eshell-current-command) +(defvar eshell-debug-command) +(defvar eshell-current-command) +(defvar tramp-archive-enabled) +(defvar tramp-tolerate-tilde) +(defvar password-cache) +(defvar helm-fd-executable) + +;;; Internal vars +;; +(defvar helm-ff-last-expanded-candidate-regexp "^[[:multibyte:] ]*%s" + "Regexp that retrieve previous candidate when going up one level. +The default value matching a multibyte char at bol allows +prefixing candidate with an icon. The format part will be +replaced by the display part of the candidate regexp quoted. +This should be used for all preselection code for helm-find-files +to handle icons.") + +(defvar helm-find-files-doc-header " (\\\\[helm-find-files-up-one-level]: Go up one level)" + "*The doc that is inserted in the Name header of a find-files or dired source.") +(defvar helm-ff-auto-update-flag nil + "Internal, flag to turn on/off auto-update in `helm-find-files'. +Don't set it directly, use instead `helm-ff-auto-update-initial-value'.") +(defvar helm-ff-last-expanded nil + "Store last expanded directory or file.") +(defvar helm-ff-default-directory nil) +(defvar helm-ff-history nil) +(defvar helm-ff-url-regexp + "\\`\\(news\\(post\\)?:\\|nntp:\\|mailto:\\|file:\\|\\(ftp\\|https?\\|telnet\\|gopher\\|www\\|wais\\):/?/?\\).*" + "Same as `ffap-url-regexp' but match earlier possible url.") +;; helm-tramp-file-name-regexp is based on old version of +;; tramp-file-name-regexp i.e. "\\`/\\([^[/:]+\\|[^/]+]\\):" but it +;; seems it is wrong and a simpler regexp is enough, let's try it and +;; watch out! +(defvar helm-tramp-file-name-regexp "\\`/\\([^/:|]+\\):") +(defvar helm-ff-tramp-method-regexp "[/|]:\\([^:]*\\)") +(defvar helm-marked-buffer-name "*helm marked*") +(defvar helm-ff--auto-update-state nil) +(defvar helm-ff--deleting-char-backward nil) +(defvar helm-multi-files--toggle-locate nil) +(defvar helm-ff--move-to-first-real-candidate t) +(defvar helm-find-files--toggle-bookmark nil) +(defvar helm-ff--tramp-methods nil) +(defvar helm-ff--directory-files-length (make-hash-table :test 'equal) + "Used to count number of candidates in directory. +candidate-number-limit is set to this value if this value is bigger +than `helm-candidate-number-limit'.") +(defvar helm-ff--list-directory-cache (make-hash-table :test 'equal) + "Cache for `helm-find-files' candidates.") +(defvar helm-ff--file-notify-watchers (make-hash-table :test 'equal) + "File-notify watchers for `helm-find-files' are stored here.") +(defvar helm-ff-history-buffer-name "*helm-find-files history*") +(defvar helm-rsync-command-history nil) +(defvar helm-rsync--last-progress-bar-alist nil + "Used to store last valid rsync progress bar.") +(defvar helm-rsync-process-buffer "*helm-rsync*") +(defvar helm-rsync-progress-str-alist nil) +(defvar helm-ff--trash-directory-regexp "\\.?Trash[/0-9]+files/?\\'") +(defvar helm-ff--show-directories-only nil) +(defvar helm-ff--show-files-only nil) +(defvar helm-ff--trashed-files nil + "[INTERNAL] Files already trashed are stored here during file deletion. +This is used only as a let binding.") +(defvar helm-ff--show-thumbnails nil) +(defvar helm-ff--thumbnailed-directories nil) + + +;;; Helm-find-files - The helm file browser. +;; +;; Keymaps + +(defvar helm-find-files-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map helm-map) + (define-key map (kbd "RET") 'helm-ff-RET) + (define-key map (kbd "C-]") 'helm-ff-run-toggle-basename) + (define-key map (kbd "C-x C-f") 'helm-ff-run-locate) + (define-key map (kbd "C-x C-d") 'helm-ff-run-browse-project) + (define-key map (kbd "C-x r m") 'helm-ff-bookmark-set) + (define-key map (kbd "C-x r b") 'helm-find-files-switch-to-bookmark) + (define-key map (kbd "C-x C-q") 'helm-ff-run-edit-marked-files) + (define-key map (kbd "C-s") 'helm-ff-run-grep) + (define-key map (kbd "M-g s") 'helm-ff-run-grep) + (define-key map (kbd "M-g p") 'helm-ff-run-pdfgrep) + (define-key map (kbd "M-g z") 'helm-ff-run-zgrep) + (define-key map (kbd "M-g a") 'helm-ff-run-grep-ag) + (define-key map (kbd "M-g g") 'helm-ff-run-git-grep) + (define-key map (kbd "M-g i") 'helm-ff-run-gid) + (define-key map (kbd "M-.") 'helm-ff-run-etags) + (define-key map (kbd "M-R") 'helm-ff-run-rename-file) + (define-key map (kbd "M-C") 'helm-ff-run-copy-file) + (define-key map (kbd "M-k") 'helm-ff-run-kill-default-directory) + (when (executable-find "rsync") + (define-key map (kbd "M-V") 'helm-ff-run-rsync-file)) + (define-key map (kbd "C-M-SPC") 'helm-ff-mark-similar-files) + (define-key map (kbd "C-M-c") 'helm-ff-run-mcp) + (define-key map (kbd "M-B") 'helm-ff-run-byte-compile-file) + (define-key map (kbd "M-L") 'helm-ff-run-load-file) + (define-key map (kbd "M-S") 'helm-ff-run-symlink-file) + (define-key map (kbd "M-Y") 'helm-ff-run-relsymlink-file) + (define-key map (kbd "M-H") 'helm-ff-run-hardlink-file) + (define-key map (kbd "M-D") 'helm-ff-run-delete-file) + (define-key map (kbd "M-K") 'helm-ff-run-kill-buffer-persistent) + (define-key map (kbd "M-T") 'helm-ff-run-touch-files) + (define-key map (kbd "M-M") 'helm-ff-run-chmod) + (define-key map (kbd "C-c d") 'helm-ff-persistent-delete) + (define-key map (kbd "M-e") 'helm-ff-run-switch-to-shell) + (define-key map (kbd "C-c i") 'helm-ff-run-complete-fn-at-point) + (define-key map (kbd "C-c o") 'helm-ff-run-switch-other-window) + (define-key map (kbd "C-c C-o") 'helm-ff-run-switch-other-frame) + (define-key map (kbd "C-c C-x") 'helm-ff-run-open-file-externally) + (define-key map (kbd "C-c C-v") 'helm-ff-run-preview-file-externally) + (define-key map (kbd "C-c X") 'helm-ff-run-open-file-with-default-tool) + (define-key map (kbd "C-c t") 'helm-ff-toggle-thumbnails) + (define-key map (kbd "M-!") 'helm-ff-run-eshell-command-on-file) + (define-key map (kbd "M-@") 'helm-ff-run-query-replace-fnames-on-marked) + (define-key map (kbd "M-%") 'helm-ff-run-query-replace) + (define-key map (kbd "C-M-%") 'helm-ff-run-query-replace-regexp) + (define-key map (kbd "C-c =") 'helm-ff-run-ediff-file) + (define-key map (kbd "M-=") 'helm-ff-run-ediff-merge-file) + (define-key map (kbd "M-p") 'helm-find-files-history) + (define-key map (kbd "C-c h") 'helm-ff-file-name-history) + (define-key map (kbd "M-i") 'helm-ff-properties-persistent) + (define-key map (kbd "C-}") 'helm-narrow-window) + (define-key map (kbd "C-{") 'helm-enlarge-window) + (define-key map (kbd "C-") 'helm-ff-run-toggle-auto-update) + (define-key map (kbd "C-c ") 'helm-ff-run-toggle-auto-update) + (define-key map (kbd "C-c C-a") 'helm-ff-run-mail-attach-files) + (define-key map (kbd "C-c p") 'helm-ff-run-print-file) + (define-key map (kbd "C-c /") 'helm-ff-run-find-sh-command) + (define-key map (kbd "C-/") 'helm-ff-run-fd) + ;; Next 2 have no effect if candidate is not an image file. + (define-key map (kbd "M-l") 'helm-ff-rotate-left-persistent) + (define-key map (kbd "M-r") 'helm-ff-rotate-right-persistent) + (define-key map (kbd "M-+") 'helm-ff-increase-image-size-persistent) + (define-key map (kbd "M--") 'helm-ff-decrease-image-size-persistent) + (define-key map (kbd "C-l") 'helm-find-files-up-one-level) + (define-key map (kbd "C-:") 'helm-ff-complete-tramp-methods) + (define-key map (kbd "C-_") 'helm-ff-undo) + (define-key map (kbd "C-r") 'helm-find-files-down-last-level) + (define-key map (kbd "C-c r") 'helm-ff-run-find-file-as-root) + (define-key map (kbd "C-x C-v") 'helm-ff-run-find-alternate-file) + (define-key map (kbd "C-c @") 'helm-ff-run-insert-org-link) + (define-key map (kbd "S-") 'helm-ff-sort-alpha) + (define-key map (kbd "S-") 'helm-ff-sort-by-newest) + (define-key map (kbd "S-") 'helm-ff-sort-by-size) + (define-key map (kbd "S-") 'helm-ff-toggle-dirs-only) + (define-key map (kbd "S-") 'helm-ff-toggle-files-only) + (define-key map (kbd "S-") 'helm-ff-sort-by-ext) + (helm-define-key-with-subkeys map (kbd "DEL") ?\d 'helm-ff-delete-char-backward + '((C-backspace . helm-ff-run-toggle-auto-update) + ([C-c DEL] . helm-ff-run-toggle-auto-update)) + nil 'helm-ff-delete-char-backward--exit-fn) + (when (fboundp 'tab-bar-mode) + (define-key map (kbd "C-c C-t") 'helm-ff-find-file-other-tab)) + map) + "Keymap for `helm-find-files'.") + +(defvar helm-read-file-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map helm-map) + (define-key map (kbd "") 'helm-cr-empty-string) + (define-key map (kbd "M-RET") 'helm-cr-empty-string) + (define-key map (kbd "C-]") 'helm-ff-run-toggle-basename) + (define-key map (kbd "C-.") 'helm-find-files-up-one-level) + (define-key map (kbd "C-l") 'helm-find-files-up-one-level) + (define-key map (kbd "C-:") 'helm-ff-complete-tramp-methods) + (define-key map (kbd "C-_") 'helm-ff-undo) + (define-key map (kbd "C-r") 'helm-find-files-down-last-level) + (define-key map (kbd "C-c h") 'helm-ff-file-name-history) + (define-key map (kbd "C-") 'helm-ff-run-toggle-auto-update) + (define-key map (kbd "C-c ") 'helm-ff-run-toggle-auto-update) + (define-key map (kbd "C-c t") 'helm-ff-toggle-thumbnails) + (define-key map (kbd "S-") 'helm-ff-sort-alpha) + (define-key map (kbd "S-") 'helm-ff-sort-by-newest) + (define-key map (kbd "S-") 'helm-ff-sort-by-size) + (define-key map (kbd "S-") 'helm-ff-sort-by-ext) + (define-key map (kbd "RET") 'helm-ff-RET) + (helm-define-key-with-subkeys map (kbd "DEL") ?\d 'helm-ff-delete-char-backward + '((C-backspace . helm-ff-run-toggle-auto-update) + ([C-c DEL] . helm-ff-run-toggle-auto-update)) + nil 'helm-ff-delete-char-backward--exit-fn) + map) + "Keymap for `helm-read-file-name'.") + +;;; User variables +;; +(defgroup helm-files nil + "Files applications and libraries for Helm." + :group 'helm) + +(defcustom helm-tramp-verbose 0 + "Just like `tramp-verbose' but specific to Helm. +When set to 0 don't show tramp messages in Helm. +If you want to have the default tramp messages set it to 3." + :type 'integer) + +(defcustom helm-ff-auto-update-initial-value nil + "Auto update when only one candidate directory is matched. +Default value when starting `helm-find-files' is nil to not +confuse new users. +For a better experience with `helm-find-files' set this to +non-nil and use C- to toggle it." + :type 'boolean) + +(defcustom helm-ff-history-max-length 100 + "Number of elements shown in `helm-find-files' history." + :type 'integer) + +(defcustom helm-ff-fuzzy-matching t + "Enable fuzzy matching for `helm-find-files' when non--nil. +See `helm-ff--transform-pattern-for-completion' for more info." + :type 'boolean) + +(defcustom helm-ff-exif-data-program "exiftran" + "Program used to extract exif data of an image file." + :type 'string) + +(defcustom helm-ff-exif-data-program-args "-d" + "Arguments used for `helm-ff-exif-data-program'." + :type 'string) + +(defcustom helm-ff-newfile-prompt-p t + "Whether Prompt or not when creating new file. +This set `ffap-newfile-prompt'." + :type 'boolean) + +(defcustom helm-ff-avfs-directory "~/.avfs" + "The default avfs directory, usually \\='~/.avfs'. +When this is set you will be able to expand archive filenames +with `C-j' inside an avfs directory mounted with mountavfs. +See ." + :type 'string) + +(defcustom helm-ff-file-compressed-list '("gz" "bz2" "zip" "7z") + "Minimal list of compressed files extension." + :type '(repeat (choice string))) + +(defcustom helm-ff-printer-list nil + "A list of available printers on your system. +When non-nil let you choose a printer to print file. +Otherwise when nil the variable `printer-name' will be used. +On Unix based systems (lpstat command needed) you don't need to +set this, `helm-ff-find-printers' will find a list of available +printers for you." + :type '(repeat (choice string))) + +(defcustom helm-ff-transformer-show-only-basename t + "Show only basename of candidates in `helm-find-files'. +This can be toggled at anytime from `helm-find-files' with \ +\\\\[helm-ff-run-toggle-basename]." + :type 'boolean) + +(defcustom helm-ff-signal-error-on-dot-files t + "Signal error when file is `.' or `..' on file deletion when non-nil. +Default is non-nil. +WARNING: Setting this to nil is unsafe and can cause deletion of +a whole tree." + :type 'boolean) + +(defcustom helm-ff-search-library-in-sexp nil + "Search for library in `require' and `declare-function' sexp." + :type 'boolean) + +(defcustom helm-tooltip-hide-delay 25 + "Hide tooltips automatically after this many seconds." + :type 'integer) + +(defcustom helm-ff-file-name-history-use-recentf nil + "Use `recentf-list' instead of `file-name-history' in `helm-find-files'." + :type 'boolean) + +(defcustom helm-ff-skip-boring-files nil + "Non-nil to skip boring files. +I.e. the files matching regexps in `helm-boring-file-regexp-list'. +This takes effect in `helm-find-files' and file completion used by +`helm-mode' i.e. `helm-read-file-name'. +Note that when non-nil this will slow down slightly `helm-find-files'." + :type 'boolean) + +(defcustom helm-ff-skip-git-ignored-files nil + "Non-nil to skip git ignored files. +This take effect only in `helm-find-files'. +Check is not done on remote files. +Note that when non-nil this will slow down slightly +`helm-find-files'." + :type 'boolean) + +(defcustom helm-ff-candidate-number-limit 5000 + "The `helm-candidate-number-limit' for `helm-find-files' and friends. +Note that when going one level up with +`\\\\[helm-find-files-up-one-level]' the +length of directory will be used instead if it is higher than +this value. This is to avoid failing to preselect the previous +directory/file if this one is situated lower than +`helm-ff-candidate-number-limit' num candidate." + :type 'integer) + +(defcustom helm-ff-preselect-ignore-large-dirs nil + "Preselect directory belonging to current-buffer even if large." + :type 'boolean) + +(defcustom helm-ff-up-one-level-preselect t + "Always preselect previous directory when going one level up. + +When non-nil `candidate-number-limit' source value is modified +dynamically when going one level up if the position of previous +candidate in its directory is > to +`helm-ff-candidate-number-limit'. + +It can be helpful to disable this and reduce +`helm-ff-candidate-number-limit' if you often navigate across +very large directories." + :type 'boolean) + +(defcustom helm-files-save-history-extra-sources + '("Find" "Locate" "Recentf" + "Files from Current Directory" "File Cache") + "Extras source that save candidate to `file-name-history'." + :type '(repeat (choice string))) + +(defcustom helm-find-files-before-init-hook nil + "Hook that run before initialization of `helm-find-files'." + :type 'hook) + +(defcustom helm-find-files-after-init-hook nil + "Hook that run after initialization of `helm-find-files'." + :type 'hook) + +(defcustom helm-find-files-bookmark-prefix nil + "bookmark name prefix of `helm-find-files' sessions." + :type 'string) + +(defcustom helm-ff-guess-ffap-filenames nil + "Use ffap to guess local filenames at point in `helm-find-files'. +This doesn't disable url or mail at point, see +`helm-ff-guess-ffap-urls' for this." + :type 'boolean) + +(defcustom helm-ff-guess-ffap-urls t + "Use ffap to guess local urls at point in `helm-find-files'. +This doesn't disable guessing filenames at point, see +`helm-ff-guess-ffap-filenames' for this. +See also `ffap-url-unwrap-remote' that may override this +variable." + :type 'boolean) + +(defcustom helm-ff-no-preselect nil + "When non-nil `helm-find-files' starts at root of current directory." + :type 'boolean) + +(defcustom helm-ff-allow-non-existing-file-at-point nil + "Use non existing file-at-point as initial input in `helm-find-files'." + :type 'boolean) + +(defcustom helm-find-files-ignore-thing-at-point nil + "Use only `default-directory' as default input in `helm-find-files'. +I.e. text under cursor in `current-buffer' is ignored. +Note that when non-nil you will be unable to complete filename at +point in `current-buffer'." + :type 'boolean) + +(defcustom helm-substitute-in-filename-stay-on-remote nil + "Don't switch back to local filesystem when expanding pattern with / or ~/." + :type 'boolean) + +(defcustom helm-ff-goto-first-real-dired-exceptions '(dired-goto-file) + "Dired commands that are allowed moving to first real candidate." + :type '(repeat (choice symbol))) + +(defcustom helm-mounted-network-directories nil + "A list of directories used for mounting remotes filesystem. + +When nil `helm-file-on-mounted-network-p' always return nil +otherwise check if a file is in one of these directories. + +Remote filesystem are generally mounted with sshfs." + :type '(repeat string)) + +(defcustom helm-browse-project-default-find-files-fn + (cond ((or (executable-find "fd") + (executable-find "fdfind")) + #'helm-browse-project-fd-find-files) + ((executable-find "rg") + #'helm-browse-project-rg-find-files) + ((executable-find "ag") + #'helm-browse-project-ag-find-files) + (t #'helm-browse-project-walk-directory)) + "The default function to retrieve files in a non-vc directory. + +A function that takes a directory name as only arg." + :type 'function) + +(defcustom helm-ff-kill-or-find-buffer-fname-fn + #'helm-ff-kill-or-find-buffer-fname + "Default function used to expand non-directory filenames in `helm-find-files'. + +This variable will take effect only in `helm-find-files'. It +affects the behavior of persistent-action on filenames and +non-existing filenames. + +The default is to expand filename on first hit on +\\\\[helm-execute-persistent-action], pop buffer in +other window on second hit and finally kill this buffer on third +hit. This is very handy to create several new buffers, or when +navigating, show quickly the buffer of file to see its contents +briefly before killing it and continue navigating. + +However some users may not want this, so to disable this behaviour +just set this to `ignore' function. + +Of course you can also write your own function to do something +else." + :type 'function) + +(defcustom helm-modes-using-escaped-strings + '(eshell-mode shell-mode term-mode) + "Modes that requires string's insertion to be escaped." + :type '(repeat symbol)) + +(defcustom helm-ff-allow-recursive-deletes nil + "When \\='always don't prompt for recursive deletion of directories. +When nil, will ask for recursive deletion. +Note that when deleting multiple directories you can answer ! +when prompted to avoid being asked for next directories, so it +is probably better to not modify this variable." + :type '(choice + (const :tag "Delete non-empty directories" t) + (const :tag "Confirm for each directory" nil))) + +(defcustom helm-ff-delete-files-function #'helm-delete-marked-files + "The function to use by default to delete files. + +Default is to delete files synchronously, other choice is to +delete files asynchronously. + +BE AWARE that when deleting async you will not be warned about +recursive deletion of directories, IOW non-empty directories will +be deleted with no warnings in background!!! + +It is the function that will be used when using +`\\\\[helm-ff-run-delete-file]' from +`helm-find-files'." + :type '(choice (function :tag "Delete files synchronously." + helm-delete-marked-files) + (function :tag "Delete files asynchronously." + helm-delete-marked-files-async))) + +(defcustom helm-trash-remote-files nil + "Allow trashing remote files when non-nil. + +Trashing remote files with tramp doesn't work out of the box +unless the \\='trash-cli' package is installed. This is why trashing +remote files from Helm is disabled by default. + +Tramp is using external \\='trash' command in its `delete-file' and +`delete-directory' handlers when using +`delete-by-moving-to-trash', which is documented nowhere in +Emacs. + +If you want to enable this you will have to install the \\='trash' +command on remote (and/or locally if you want to trash as root). +On Ubuntu-based distributions it is \\='trash-cli'." + :type 'boolean) + +(defcustom helm-list-directory-function + (cl-case system-type + (gnu/linux #'helm-list-dir-external) + (berkeley-unix #'helm-list-dir-lisp) + (windows-nt #'helm-list-dir-lisp) + (t #'helm-list-dir-lisp)) + "The function used in `helm-find-files' to list remote directories. + +Actually Helm provides two functions to do this: +`helm-list-dir-lisp' and `helm-list-dir-external'. + +Using `helm-list-dir-external' will provide a similar display to +what is provided with local files i.e. colorized symlinks, +executables files etc., whereas using `helm-list-dir-lisp' will +allow colorizing only directories but it is more portable. + +NOTE: `helm-list-dir-external' needs ls and awk as dependencies. +Also the ls version installed on the remote side should support +the same arguments as the GNU/ls version, which are -A -1 -F -b +and -Q. So even if you are using a GNU/ls version locally and you +want to connect e.g. on a Freebsd server, you may have failures +due to the incompatible ls version installed on remote server. In +such case use `helm-list-dir-lisp' which works everywhere but is +slower and less featured (only directories colorized)." + :type 'function) + +(defcustom helm-ff-initial-sort-method nil + "Sort method to use when initially listing a directory. + +It is better to keep this nil globally and turn it on only when needed +otherwise it may be slightly slower specially with `ext' method which +BTW is not provided on remote files (helm will fallback on nil in such +case). +Note that this have no effect as soon as you start narrowing directory +i.e. filtering filenames inside directory." + :type '(choice + (const :tag "alphabetically" nil) + (const :tag "newest" newest) + (const :tag "size" size) + (const :tag "extensions" ext))) + +(defcustom helm-ff-rotate-image-program "exiftran" + "External program used to rotate images. +When nil and `helm-ff-display-image-native' is enabled, fallback to +`image-rotate' without modification of exif data i.e. rotation is not +persistent otherwise an error is returned when not using +`helm-ff-display-image-native' i.e. using image-dired." + :type '(choice + (const :tag "Mogrify" "mogrify") + (const :tag "Exiftran" "exiftran") + (const :tag "Jpegtran" "jpegtran"))) + +(defcustom helm-ff-rotate-image-switch '("-i") + "Options used with `helm-ff-rotate-image-program'. +If you are using Mogrify or Jpegtran mandatory option is +\"-rotate\", with Exiftran mandatory option is \"-i\"." + :type '(repeat string)) + +(defcustom helm-ff-preferred-shell-mode 'eshell-mode + "Shell to use to switch to a shell buffer from `helm-find-files'. +Possible values are `shell-mode', `eshell-mode' and `term-mode'. +This affects `\\\\[helm-ff-run-switch-to-shell]' keybinding." + :type '(choice + (const :tag "Use Eshell" eshell-mode) + (const :tag "Use Shell" shell-mode) + (const :tag "Use Shell" term-mode))) + +(defcustom helm-rsync-no-mode-line-update nil + "When non nil don't update mode-line when rsync is running. +This is useful if you display the progress bar somewhere else, +e.g. with minibuffer-line in minibuffer, in this case updating +mode-line may create flickering in other frame's mode-line." + :type 'boolean) + +(defcustom helm-rsync-switches '("-a" "-z" "-h" "-s" "--info=all2") + "Rsync options to use with HFF Rsync action. +Note: Using \"--info=all2\" allows having the name of the file +currently transfered in an help-echo in mode-line, if you use +\"--info=progress2\" you will not have this information." + :type '(repeat string)) + +(defcustom helm-rsync-percent-sign "%" + "Percentage unicode sign to use in Rsync reporter." + :type 'string) + +(defcustom helm-trash-default-directory nil + "The default trash directory. +You probably don't need to set this when using a Linux system using +standard settings. +Should be the directory file name i.e. don't add final slash. +When nil helm will compute a default value according to freedesktop +specs. +It is generally \"~/.local/share/Trash\"." + :type 'string) + +(defcustom helm-ff-lynx-style-map t + "Use arrow keys to navigate with `helm-find-files'. +Note that if you define this variable with `setq' your change +will have no effect, use customize instead." + :type 'boolean + :set (lambda (var val) + (set var val) + (if val + (progn + (define-key helm-find-files-map (kbd "") 'helm-execute-persistent-action) + (define-key helm-find-files-map (kbd "") 'helm-find-files-up-one-level) + (define-key helm-read-file-map (kbd "") 'helm-execute-persistent-action) + (define-key helm-read-file-map (kbd "") 'helm-find-files-up-one-level)) + (define-key helm-find-files-map (kbd "") nil) + (define-key helm-find-files-map (kbd "") nil) + (define-key helm-read-file-map (kbd "") nil) + (define-key helm-read-file-map (kbd "") nil)))) + +(defcustom helm-ff-DEL-up-one-level-maybe nil + "Use DEL to maybe go up one level when non nil. + +Going up one level works only when pattern is a directory endings +with \"/\", otherwise this command deletes char backward. + +When nil always delete char backward." + :type 'boolean) + +(defcustom helm-ff-display-image-native t + "Use native `image-mode' when non nil. + +You should use this only with Emacs>= 27 and `image-auto-resize' +enabled to have images resized properly. When this is enabled, +you have new commands to zoom in/out images. See +`image-transform-resize' and `image-auto-resize'. Otherwise, +when nil `image-dired' is used, using imagemagick as backend. +NOTE: On Emacs-29 `image-dired' is no more using external program +image-magick to display image, so this is used inconditionally even +when value is nil." + :type 'boolean) + +(defcustom helm-ff-reset-filters-on-update t + "Reset filter variables when changing directory. +When filtering directories/files only, switch back to a \"show all\" view +when moving out of directory when non nil." + :type 'boolean) + +(defcustom helm-ff-eshell-unwanted-aliases nil + "A list of eshell aliases to not display." + :type '(repeat string)) + +(defcustom helm-find-files-actions + (helm-make-actions + "Find File" 'helm-find-file-or-marked + "Find file in Dired" 'helm-point-file-in-dired + "View file" 'view-file + "Query replace fnames on marked `M-@'" 'helm-ff-query-replace-fnames-on-marked + "Marked files in dired `C-x C-q'" 'helm-ff-edit-marked-files + "Query replace contents on marked `M-%'" 'helm-ff-query-replace + "Query replace regexp contents on marked `C-M-%'" 'helm-ff-query-replace-regexp + "Attach file(s) to mail buffer `C-c C-a'" 'helm-ff-mail-attach-files + "Serial rename files" 'helm-ff-serial-rename + "Serial rename by symlinking files" 'helm-ff-serial-rename-by-symlink + "Serial rename by copying files" 'helm-ff-serial-rename-by-copying + "Open file with default tool" 'helm-open-file-with-default-tool + "Find file in hex dump" 'hexl-find-file + "Browse project `C-x C-d'" 'helm-ff-browse-project + "Complete at point `C-c i'" 'helm-insert-file-name-completion-at-point + "Insert as org link `C-c @'" 'helm-files-insert-as-org-link + "Find shell command `C-c /'" 'helm-ff-find-sh-command + "Fd shell command (C-/)" 'helm-ff-fd + "Find files in file" 'helm-find-files-in-file + "Add marked files to file-cache" 'helm-ff-cache-add-file + "Open file externally `C-c C-x, C-u to choose'" 'helm-open-file-externally + "Grep File(s) `C-s, C-u Recurse'" 'helm-find-files-grep + "Grep current directory with AG `M-g a, C-u select type'" 'helm-find-files-ag + "Git grep `M-g g, C-u from root'" 'helm-ff-git-grep + "Zgrep File(s) `M-g z, C-u Recurse'" 'helm-ff-zgrep + "Pdf Grep File(s)" 'helm-ff-pdfgrep + "Gid `M-g i'" 'helm-ff-gid + "Switch to Eshell `M-e'" 'helm-ff-switch-to-shell + "Etags `M-., C-u reload tag file'" 'helm-ff-etags-select + "Eshell command on file(s) `M-!, C-u take all marked as arguments.'" + 'helm-find-files-eshell-command-on-file + "Find file as root `C-c r'" 'helm-find-file-as-root + "Find alternate file `C-x C-v'" 'find-alternate-file + "Ediff File `C-c ='" 'helm-find-files-ediff-files + "Ediff Merge File `M-='" 'helm-find-files-ediff-merge-files + (lambda () (format "Delete File(s)%s `M-D' (C-u reverse trash)" + (if (eq helm-ff-delete-files-function + 'helm-delete-marked-files-async) + " async" ""))) + 'helm-ff-delete-files + "Touch File(s) `M-T'" 'helm-ff-touch-files + "Copy file(s) `M-C, C-u to follow'" 'helm-find-files-copy + (lambda () + (and (executable-find "rsync") + "Rsync file(s) `M-V' (C-u edit command)")) + 'helm-find-files-rsync + "Rename file(s) `M-R, C-u to follow'" 'helm-find-files-rename + "Backup files" 'helm-find-files-backup + "Copy file to dir(s) `C-M-c'" 'helm-ff-mcp + "Symlink files(s) `M-S, C-u to follow'" 'helm-find-files-symlink + "Relsymlink file(s) `M-Y, C-u to follow'" 'helm-find-files-relsymlink + "Hardlink file(s) `M-H, C-u to follow'" 'helm-find-files-hardlink + "Change mode on file(s) `M-M'" 'helm-ff-chmod + "Find file other window `C-c o'" 'helm-find-files-other-window + "Find file other frame `C-c C-o'" 'find-file-other-frame + (lambda () (and (fboundp 'tab-bar-mode) + "Find file other tab `C-c C-t'")) + 'find-file-other-tab + "Print File `C-c p, C-u to refresh'" 'helm-ff-print + "Locate `C-x C-f, C-u to specify locate db'" 'helm-ff-locate) + "Actions for `helm-find-files'." + :type '(alist :key-type string :value-type function)) + +(defcustom helm-dwim-target nil + "Default target directory for file actions. + +Define the directory where you want to start navigating for the +target directory when copying, renaming, etc.. You can use the +`default-directory' of `next-window', the visited directory, the +current `default-directory' or have completion on all the +directories belonging to each visible windows." + :type '(radio :tag "Define default target directory for file actions." + (const :tag "Directory belonging to next window" + next-window) + (const :tag "Completion on directories belonging to each window" + completion) + (const :tag "Use initial directory or `default-directory'" + default-directory) + (const :tag "Use visited directory" + nil))) + +(defcustom helm-ff-use-notify t + "Watch directories visited with `helm-find-files' when non nil. +If your system have no file notification package available turn this +to nil to avoid error messages when using `helm-find-files'." + :type 'boolean + :set (lambda (var val) + (set-default var val) + (unless (symbol-value var) + (cl-loop for dir being the hash-keys of helm-ff--file-notify-watchers + do (remhash dir helm-ff--list-directory-cache))))) + +(defcustom helm-ff-inotify-unsupported-methods '("adb") + "Tramp methods unsupported by file-notify." + :type '(repeat string)) + +(defcustom helm-ff-image-cache-max-len 5 + "The last seen image number to keep in cache." + :type 'integer) + +(defcustom helm-ff-image-cache-max-len 5 + "The last seen image number to keep in cache." + :type 'integer) + +(defcustom helm-ff-slideshow-default-delay 3 + "Delay in seconds between each image in slideshow." + :type 'integer) + +(defcustom helm-file-name-history-hide-deleted nil + "Hide deleted files in file-name-history when non nil. + +This can be toggled at any time from `helm-ff-file-name-history' with \ +\\\\[helm-file-name-history-show-or-hide-deleted]." + :type 'boolean) + +(defcustom helm-file-name-history-max-length 72 + "Max length of candidates in helm file name history before truncating." + :type 'integer) + +(defcustom helm-ff-follow-blacklist-file-exts '("gpg" "doc" "docx" "mp3" "ogg") + "File extensions we don't want to follow when helm-follow-mode is enabled. +Note that image files are always followed even if their extensions is +present in this list." + :type '(repeat string)) + +(defcustom helm-ff-nohighlight-matches t + "Highlight matches in `helm-find-files' when nil." + :type 'boolean + :initialize 'custom-initialize-changed + :set (lambda (var val) + (set var val) + (setq helm-source-find-files nil) + (when helm-ff-icon-mode + (helm-ff-icon-mode 1)))) + +(defcustom helm-ff-edit-marked-files-fn (if (< emacs-major-version 29) + #'helm-ff-wfnames + #'helm-marked-files-in-dired) + "A function to edit filenames in a special buffer." + :type '(choice (function :tag "Use Wfnames package to edit filenames." + helm-ff-wfnames) + (function :tag "Use Wdired package to edit filenames." + helm-marked-files-in-dired))) + +;;; Faces +;; +;; +(defgroup helm-files-faces nil + "Customize the appearance of helm-files." + :prefix "helm-" + :group 'helm-files + :group 'helm-faces) + +(defface helm-ff-prefix + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "yellow" :foreground "black")) + "Face used to prefix new file or url paths in `helm-find-files'." + :group 'helm-files-faces) + +(defface helm-ff-executable + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "green")) + "Face used for executable files in `helm-find-files'." + :group 'helm-files-faces) + +(defface helm-ff-suid + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "red" :foreground "white")) + "Face used for suid files in `helm-find-files'." + :group 'helm-files-faces) + +(defface helm-ff-directory + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "DarkRed" :background "LightGray")) + "Face used for directories in `helm-find-files'." + :group 'helm-files-faces) + +(defface helm-ff-dotted-directory + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "black" :background "DimGray")) + "Face used for dotted directories in `helm-find-files'." + :group 'helm-files-faces) + +(defface helm-ff-dotted-symlink-directory + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "DarkOrange" :background "DimGray")) + "Face used for dotted symlinked directories in `helm-find-files'." + :group 'helm-files-faces) + +(defface helm-ff-symlink + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :inherit font-lock-comment-face)) + "Face used for symlinks in `helm-find-files'." + :group 'helm-files-faces) + +(defface helm-ff-invalid-symlink + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "black" :background "red")) + "Face used for invalid symlinks in `helm-find-files'." + :group 'helm-files-faces) + +(defface helm-ff-denied + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "red" :background "black")) + "Face used for non accessible files in `helm-find-files'." + :group 'helm-files-faces) + +(defface helm-ff-file + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :inherit font-lock-builtin-face)) + "Face used for file names in `helm-find-files'." + :group 'helm-files-faces) + +(defface helm-ff-nofile + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :inherit helm-ff-file)) + "Face used for file names in `helm-find-files'." + :group 'helm-files-faces) + +(defface helm-ff-truename + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :inherit font-lock-string-face)) + "Face used for symlink truenames in `helm-find-files'." + :group 'helm-files-faces) + +(defface helm-ff-dirs + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :inherit font-lock-function-name-face)) + "Face used for file names in recursive dirs completion in `helm-find-files'." + :group 'helm-files-faces) + +(defface helm-ff-socket + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "DeepPink")) + "Face used for socket files in `helm-find-files'." + :group 'helm-files-faces) + +(defface helm-ff-pipe + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "yellow" :background "black")) + "Face used for named pipes and character device files in `helm-find-files'." + :group 'helm-files-faces) + +(defface helm-ff-file-extension + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "magenta")) + "Face used for file extensions in `helm-find-files'." + :group 'helm-files-faces) + +(defface helm-ff-backup-file + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "DimGray")) + "Face used for backup files in `helm-find-files'." + :group 'helm-files-faces) + +(defface helm-history-deleted + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :inherit helm-ff-invalid-symlink)) + "Face used for deleted files in `file-name-history'." + :group 'helm-files-faces) + +(defface helm-history-remote + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "Indianred1")) + "Face used for remote files in `file-name-history'." + :group 'helm-files-faces) + +(defface helm-delete-async-message + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "yellow")) + "Face used for mode-line message." + :group 'helm-files-faces) + +(defface helm-ff-rsync-progress + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :inherit font-lock-warning-face)) + "Face used for rsync mode-line indicator." + :group 'helm-files-faces) + + +;;; Helm-find-files +;; +;; +(defvar helm-source-find-files nil + "The main source to browse files. +Should not be used among other sources.") + +(defclass helm-source-ffiles (helm-source-sync) + ((header-name + :initform (lambda (name) + (concat name (substitute-command-keys + helm-find-files-doc-header)))) + (init + :initform (lambda () + (setq helm-ff-auto-update-flag + helm-ff-auto-update-initial-value) + (setq helm-ff--auto-update-state + helm-ff-auto-update-flag) + (helm-set-local-variable 'bookmark-make-record-function + #'helm-ff-make-bookmark-record) + (require 'helm-external))) + (candidates :initform 'helm-find-files-get-candidates) + (update :initform (lambda () + (remhash helm-ff-default-directory + helm-ff--list-directory-cache))) + (match-on-real :initform t) + (filtered-candidate-transformer + :initform '(helm-ff-fct + helm-ff-maybe-show-thumbnails + ;; These next two have to be called after + ;; `helm-ff-fct' as they use only cons cell candidates. + helm-ff-directories-only + helm-ff-files-only + helm-ff-sort-candidates)) + (persistent-action-if :initform 'helm-find-files-persistent-action-if) + (persistent-help :initform "Hit1 Expand Candidate, Hit2 or (C-u) Find file") + (help-message :initform 'helm-ff-help-message) + (mode-line :initform (list "File(s)" helm-mode-line-string)) + (volatile :initform t) + (cleanup :initform 'helm-find-files-cleanup) + (migemo :initform t) + (nohighlight :initform (progn helm-ff-nohighlight-matches)) + (keymap :initform 'helm-find-files-map) + (candidate-number-limit :initform 'helm-ff-candidate-number-limit) + (completing-file-name + :initarg :completing-file-name :initform t + :documentation "Flag to notify `helm-resume' we are completing filenames.") + (action-transformer + :initform 'helm-find-files-action-transformer) + (action :initform 'helm-find-files-actions) + (before-init-hook :initform 'helm-find-files-before-init-hook) + (after-init-hook :initform 'helm-find-files-after-init-hook) + (group :initform 'helm-files))) + +;; Bookmark handlers. +;; +(defun helm-ff-make-bookmark-record () + "The `bookmark-make-record-function' for `helm-find-files'." + (with-helm-buffer + `((filename . ,helm-ff-default-directory) + (presel . ,(helm-get-selection)) + (handler . helm-ff-bookmark-jump)))) + +(defun helm-ff-bookmark-jump (bookmark) + "bookmark handler for `helm-find-files'." + (let ((fname (bookmark-prop-get bookmark 'filename)) + (presel (bookmark-prop-get bookmark 'presel))) + ;; Force tramp connection with `file-directory-p' before lauching + ;; hff otherwise the directory name is inserted on top before + ;; tramp starts and display candidates. FNAME is here always a + ;; directory. + (when (file-directory-p fname) + (helm-find-files-1 fname + (format helm-ff-last-expanded-candidate-regexp + (if helm-ff-transformer-show-only-basename + (regexp-quote (helm-basename presel)) + (regexp-quote presel))))))) + +(defun helm-ff-bookmark-set () + "Record `helm-find-files' session in bookmarks." + (interactive) + (with-helm-alive-p + (with-helm-buffer + (bookmark-set + (concat helm-find-files-bookmark-prefix + (abbreviate-file-name helm-ff-default-directory)))) + (message "Helm find files session bookmarked! "))) +(put 'helm-ff-bookmark-set 'helm-only t) + +(defun helm-dwim-target-directory () + "Try to return a suitable directory according to `helm-dwim-target'." + (with-selected-window (or + ;; Try next-window if current-buffer has been + ;; killed during this session probably by C-d. + (get-buffer-window helm-current-buffer) + (next-window (helm-window) 1)) + (let ((wins (remove (get-buffer-window helm-marked-buffer-name) + (window-list)))) + (expand-file-name + (cond (;; Provide completion on all the directory belonging to + ;; visible windows if some. + (and (cdr wins) + (eq helm-dwim-target 'completion)) + (helm-comp-read "Browse target starting from: " + (append (list (or (car-safe helm-ff-history) + default-directory) + default-directory) + (cl-loop for w in wins collect + (with-selected-window w + default-directory))))) + ;; Use default-directory of next-window. + ((and (cdr wins) + (eq helm-dwim-target 'next-window)) + (with-selected-window (next-window) + default-directory)) + ;; Always use default-directory when only one window. + ((and (null (cdr wins)) + (eq helm-dwim-target 'default-directory)) + default-directory) + ;; Use the visited directory. + ((or (null (cdr wins)) + (null helm-dwim-target)) + ;; Using the car of *ff-history allow + ;; staying in the directory visited instead of + ;; current. + (or (car-safe helm-ff-history) default-directory))))))) + +(defsubst helm-ff--file-directory-p (file) + (if (file-remote-p file) + (get-text-property 1 'helm-ff-dir file) + (file-directory-p file))) + +(defun helm-ff--count-and-collect-dups (files) + (cl-loop with dups = (make-hash-table :test 'equal) + for f in files + for file = (if (helm-ff--file-directory-p f) + (concat (helm-basename f) "/") + (helm-basename f)) + for count = (gethash file dups) + if count do (puthash file (1+ count) dups) + else do (puthash file 1 dups) + finally return (cl-loop for k being the hash-keys in dups + using (hash-value v) + if (> v 1) + collect (format "%s(%s)" k v) + else + collect k))) + +(defun helm-find-files-do-action (action &optional target) + "Generic function for creating actions from `helm-source-find-files'. +ACTION can be `rsync' or any action supported by `helm-dired-action'." + (require 'dired-async) + (when (eq action 'rsync) + (cl-assert (executable-find "rsync") nil "No command named rsync")) + (let* ((rsync-switches + (when (and (eq action 'rsync) + helm-current-prefix-arg) + (cdr (split-string + (read-string "Run rsync like this: " + (mapconcat + 'identity + (cons "rsync" helm-rsync-switches) " ") + 'helm-rsync-command-history))))) + (ifiles (mapcar 'expand-file-name ; Allow modify '/foo/.' -> '/foo' + (helm-marked-candidates :with-wildcard t))) + (cand (unless (cdr ifiles) (helm-get-selection))) ; preselection. + (prefarg helm-current-prefix-arg) + (prompt (format "%s %s file(s) %s: " + (if (and (and (fboundp 'dired-async-mode) + dired-async-mode) + (not (eq action 'rsync)) + (null prefarg)) + (concat "Async " (symbol-name action)) + (capitalize (symbol-name action))) + (length ifiles) + (if (memq action '(symlink relsymlink hardlink)) + "from" "to"))) + helm-ff--move-to-first-real-candidate + helm-display-source-at-screen-top ; prevent setting window-start. + helm-ff-auto-update-initial-value + ;; It is not possible to rename a file to a boring name when + ;; helm-ff-skip-boring-files is enabled + helm-ff-skip-boring-files + ;; If HFF is using a frame use a frame as well. + (helm-actions-inherit-frame-settings t) + helm-use-frame-when-more-than-two-windows + (dest (or target + (with-helm-display-marked-candidates + helm-marked-buffer-name + (helm-ff--count-and-collect-dups ifiles) + (with-helm-current-buffer + (helm-read-file-name + prompt + :preselect (when cand + (format helm-ff-last-expanded-candidate-regexp + (regexp-quote + (if helm-ff-transformer-show-only-basename + (helm-basename cand) cand)))) + :initial-input (helm-dwim-target-directory) + :history (helm-find-files-history nil :comp-read nil)))))) + (dest-dir-p (file-directory-p dest)) + (dest-dir (helm-basedir dest))) + (unless (or dest-dir-p (file-directory-p dest-dir)) + (when (y-or-n-p (format "Create directory `%s'? " dest-dir)) + (make-directory dest-dir t))) + (if (eq action 'rsync) + (helm-rsync-copy-files ifiles dest rsync-switches) + (helm-dired-action + dest :files ifiles :action action :follow prefarg)))) + +;; Rsync +;; +(defun helm-rsync-remote2rsync (file) + (if (file-remote-p file) + (let ((localname (directory-file-name + (expand-file-name (file-remote-p file 'localname)))) + (user (file-remote-p file 'user)) + ;; Tramp name may contain port e.g. /ssh:host#2222:/foo. + (host (replace-regexp-in-string + "#[0-9]+" "" (file-remote-p file 'host)))) + (if user + (format "%s@%s:%s" user host (shell-quote-argument localname)) + (format "%s:%s" host (shell-quote-argument localname)))) + (shell-quote-argument + (directory-file-name + (expand-file-name file))))) + +(defun helm-rsync-format-mode-line-str (proc) + (helm-aif (and (process-live-p proc) + (assoc-default proc helm-rsync-progress-str-alist)) + (progn + ;; When rsync progress bar stop for some reason (e.g. rsync + ;; takes time to finalize writing file to disk), no output is + ;; coming from filter process, as a result the progress bar + ;; disapear for a while giving no information to user while + ;; the rsync process continues, so keep printing the last valid + ;; progress bar (stored in `helm-rsync--last-progress-bar-alist') + ;; instead of sending empty string. + (unless (equal it "") + (push (cons proc it) helm-rsync--last-progress-bar-alist)) + (format " [%s]" (propertize + (or (assoc-default proc helm-rsync--last-progress-bar-alist) + ;; Avoid (wrong-type-argument stringp + ;; nil) when process is not ready. + "") + 'face 'helm-ff-rsync-progress))))) + +(defun helm-rsync-mode-line (proc) + "Add Rsync progress to the mode line." + (or global-mode-string (setq global-mode-string '(""))) + (unless (member `(:eval (helm-rsync-format-mode-line-str ,proc)) + global-mode-string) + (setq global-mode-string + (append global-mode-string + `((:eval (helm-rsync-format-mode-line-str ,proc))))))) + +(defun helm-rsync-restore-mode-line (proc) + "Restore the mode line when Rsync finishes." + (setq global-mode-string + (remove `(:eval (helm-rsync-format-mode-line-str ,proc)) + global-mode-string)) + (setq helm-rsync--last-progress-bar-alist nil) + (force-mode-line-update)) + +(defun helm-rsync-copy-files (files dest &optional switches) + "Send FILES to DEST using Rsync with SWITCHES as arguments. + +DEST must be a directory. SWITCHES when unspecified default to +`helm-rsync-switches'." + (cl-assert (file-directory-p dest) t) + (setq files (cl-loop for f in files + collect (helm-rsync-remote2rsync f)) + dest (helm-rsync-remote2rsync dest)) + (let* ((buf (generate-new-buffer-name helm-rsync-process-buffer)) + (port (when (helm-aand (file-remote-p dest 'host) + (string-match "#\\([0-9]+\\)" it)) + (match-string 1))) + (proc (start-process-shell-command + "rsync" buf + (format "rsync %s" + (mapconcat + 'identity + (append (or switches helm-rsync-switches) + (and port + ;; Add automatically port + ;; specified in tramp name + ;; unless user already specified + ;; it himself with the -e option + ;; by editing command. + (and switches + (cl-loop for arg in switches never + (string-match-p + "\\`-e" arg))) + (list (format "-e 'ssh -p %s'" + port))) + files (list dest)) + " "))))) + (helm-rsync-mode-line proc) + (set-process-sentinel + proc `(lambda (process event) + (cond ((string= event "finished\n") + (message "%s copied %s files" + (capitalize (process-name process)) + ,(length files))) + (t (error "Process %s %s with code %s" + (process-name process) + (process-status process) + (process-exit-status process)))) + (setq helm-rsync-progress-str-alist + (delete (assoc process helm-rsync-progress-str-alist) + helm-rsync-progress-str-alist)) + (helm-rsync-restore-mode-line process) + (force-mode-line-update))) + (set-process-filter proc #'helm-rsync-process-filter))) + +(defun helm-rsync-process-filter (proc output) + "Filter process function used by `helm-rsync-copy-files'." + (let ((inhibit-read-only t) + fname progbar) + (with-current-buffer (process-buffer proc) + (when (string-match comint-password-prompt-regexp output) + ;; FIXME: Fully not tested and + ;; use an agent or auth-source + ;; or whatever to get password if + ;; available. + (process-send-string + proc (concat (read-passwd (match-string 0 output)) "\n"))) + ;; Extract the progress bar. + (with-temp-buffer + (insert output) + (when (re-search-backward "[[:cntrl:]]" nil t) + (setq progbar (buffer-substring-no-properties + (match-end 0) (point-max))))) + ;; Insert the text, advancing the process marker. + (save-excursion + (goto-char (process-mark proc)) + (insert output) + (set-marker (process-mark proc) (point))) + (goto-char (process-mark proc)) + ;; Extract the file name currently + ;; copied (Imply --info=all2 or all1). + (save-excursion + (when (re-search-backward "^[^[:cntrl:]]" nil t) + (setq fname (helm-basename + (buffer-substring-no-properties + (point) (point-at-eol)))))) + ;; Now format the string for the mode-line. + (let ((ml-str (mapconcat 'identity + (split-string + (replace-regexp-in-string + "%" helm-rsync-percent-sign + progbar) + " " t) + " "))) + (setq ml-str (propertize ml-str 'help-echo + (format "%s->%s" (process-name proc) fname))) + ;; Now associate the formatted + ;; progress-bar string with process. + (helm-aif (assoc proc helm-rsync-progress-str-alist) + (setcdr it ml-str) + (setq helm-rsync-progress-str-alist + (push (cons proc ml-str) helm-rsync-progress-str-alist))))) + ;; Finally update mode-line. + (unless helm-rsync-no-mode-line-update + (force-mode-line-update)))) + +(defun helm-ff-kill-rsync-process (process) + "Kill rsync process PROCESS. + +When called interactively prompt user with completion when more than +one process." + (interactive (list (get-process + (helm-comp-read + "Kill rsync process: " + (mapcar (lambda (x) + (process-name (car x))) + helm-rsync-progress-str-alist) + :exec-when-only-one t)))) + (with-current-buffer (process-buffer process) + (delete-process process) + (kill-buffer)) + (setq helm-rsync-progress-str-alist + (delete (assoc process helm-rsync-progress-str-alist) + helm-rsync-progress-str-alist))) + +(defun helm-find-files-rsync (_candidate) + "Rsync files from `helm-find-files'." + (helm-find-files-do-action 'rsync)) + +(defun helm-find-files-copy (_candidate) + "Copy files from `helm-find-files'." + (helm-find-files-do-action 'copy)) + +(defun helm-find-files-backup (_candidate) + "Backup files from `helm-find-files'. +This reproduce the behavior of \"cp --backup=numbered from to\"." + (cl-assert (and (fboundp 'dired-async-mode) dired-async-mode) nil + "Backup only available when `dired-async-mode' is enabled") + (helm-find-files-do-action 'backup)) + +(defun helm-find-files-rename (_candidate) + "Rename files from `helm-find-files'." + (helm-find-files-do-action 'rename)) + +(defun helm-find-files-symlink (_candidate) + "Symlink files from `helm-find-files'." + (helm-find-files-do-action 'symlink)) + +(defun helm-find-files-relsymlink (_candidate) + "Relsymlink files from `helm-find-files'." + (helm-find-files-do-action 'relsymlink)) + +(defun helm-find-files-hardlink (_candidate) + "Hardlink files from `helm-find-files'." + (helm-find-files-do-action 'hardlink)) + +(defun helm-ff-chmod (_candidate) + "Set file mode on marked files. +If no mode is specified in prompt, default mode will be the mode of +the car of marked files i.e. the first marked file." + (let* ((mkd (helm-marked-candidates)) + (model (car mkd)) + (default (helm-file-attributes model :octal t)) + (mode (read-file-modes nil model)) + (smode (file-modes-number-to-symbolic mode)) + (candidates (if (string= default (format "%o" mode)) + (cdr mkd) mkd))) + (with-helm-display-marked-candidates + helm-marked-buffer-name + (helm-ff--count-and-collect-dups candidates) + (when (y-or-n-p (format "Change file mode to `%s'? " smode)) + (dolist (f candidates) + (unless (file-symlink-p f) + ;; For now don't use the FLAG arg 'nofollow of `set-file-modes' for + ;; Emacs-26 compatibility. + (set-file-modes f mode))) + (message "Changed file mode to `%s' on %s file(s)" + smode (length candidates)))))) + +(defun helm-find-files-other-window (_candidate) + "Keep current-buffer and open files in separate windows. +When a prefix arg is detected files are opened in a vertical +windows layout." + (let* ((files (helm-marked-candidates)) + (buffers (mapcar 'find-file-noselect files))) + (helm-window-show-buffers buffers t))) + +(defun helm-find-files-byte-compile (_candidate) + "Byte compile elisp files from `helm-find-files'." + (let ((files (helm-marked-candidates :with-wildcard t)) + (parg helm-current-prefix-arg)) + (cl-loop for fname in files + do (condition-case _err + (with-no-warnings + (byte-compile-file fname parg)) + (wrong-number-of-arguments + ;; Emacs-28 accepts only one arg. + (byte-compile-file fname) + (when parg (load fname))))))) + +(defun helm-find-files-load-files (_candidate) + "Load elisp files from `helm-find-files'." + (let ((files (helm-marked-candidates :with-wildcard t))) + (cl-loop for fname in files + do (load fname)))) + +(defun helm-find-files-ediff-files-1 (candidate &optional merge) + "Generic function to ediff/merge files in `helm-find-files'." + (let* ((helm-dwim-target 'next-window) + (bname (helm-basename candidate)) + (marked (helm-marked-candidates :with-wildcard t)) + (prompt (if merge "Ediff Merge `%s' With File: " + "Ediff `%s' With File: ")) + (fun (if merge 'ediff-merge-files 'ediff-files)) + (input (helm-dwim-target-directory)) + (presel (if helm-ff-transformer-show-only-basename + (helm-basename candidate) + (expand-file-name + (helm-basename candidate) + input)))) + (if (= (length marked) 2) + (funcall fun (car marked) (cadr marked)) + (funcall fun candidate (helm-read-file-name + (format prompt bname) + :initial-input input + :preselect presel))))) + +(defun helm-find-files-ediff-files (candidate) + (helm-find-files-ediff-files-1 candidate)) + +(defun helm-find-files-ediff-merge-files (candidate) + (helm-find-files-ediff-files-1 candidate 'merge)) + +(defun helm-find-files-grep (_candidate) + "Default action to grep files from `helm-find-files'." + (helm-do-grep-1 (helm-marked-candidates :with-wildcard t) + helm-current-prefix-arg)) + +(defun helm-ff-git-grep (_candidate) + "Default action to git-grep `helm-ff-default-directory'." + (helm-grep-git-1 helm-ff-default-directory helm-current-prefix-arg)) + +(defun helm-find-files-ag (_candidate) + (helm-grep-ag helm-ff-default-directory + helm-current-prefix-arg)) + +(defun helm-ff-zgrep (_candidate) + "Default action to zgrep files from `helm-find-files'." + (helm-ff-zgrep-1 (helm-marked-candidates :with-wildcard t) helm-current-prefix-arg)) + +(defun helm-ff-pdfgrep (_candidate) + "Default action to pdfgrep files from `helm-find-files'." + (let* ((recurse nil) + (cands (cl-loop for file in (helm-marked-candidates :with-wildcard t) + for dir = (file-directory-p file) + when dir do (setq recurse t) + when (or dir + (string= (file-name-extension file) "pdf") + (string= (file-name-extension file) "PDF")) + collect file))) + (when cands + (helm-do-pdfgrep-1 cands recurse)))) + +(defun helm-ff-etags-select (candidate) + "Default action to jump to etags from `helm-find-files'." + (when (get-buffer helm-action-buffer) + (kill-buffer helm-action-buffer)) + (let* ((source-name (assoc-default 'name (helm-get-current-source))) + (default-directory (if (string= source-name "Find Files") + helm-ff-default-directory + (file-name-directory candidate)))) + (helm-etags-select helm-current-prefix-arg))) + +;;; Eshell command on file +;; +(defvar eshell-command-aliases-list nil) +(defvar helm-eshell-command-on-file-input-history nil) +(defvar helm-eshell-command-on-file-history nil) +(cl-defun helm-find-files-eshell-command-on-file-1 (&optional map) + "Run `eshell-command' on CANDIDATE or marked candidates. +This is done possibly with an Eshell alias. If no alias found, +you can type in an Eshell command. + +Only aliases accepting a file as argument at the end of command +line are collected, i.e. aliases ending with \"$1\" or \"$*\". + +Basename of CANDIDATE can be a wild-card. +E.g. you can do \"eshell-command command *.el\" +Where \"*.el\" is the CANDIDATE. + +It is possible to do eshell-command command like this: \"command %s some more args\". + +If MAP is given run `eshell-command' on all marked files at once, +Otherwise, run `eshell-command' on each marked files. +In other terms, with a prefix arg do on the three marked files +\"foo\" \"bar\" \"baz\": + +\"eshell-command command foo bar baz\" + +otherwise do + +\"eshell-command command foo\" +\"eshell-command command bar\" +\"eshell-command command baz\" + +Note: +You have to setup some aliases in Eshell with the `alias' command +or by editing yourself the file `eshell-aliases-file' to make +this working." + (require 'helm-adaptive) + (require 'em-alias) (eshell-read-aliases-list) + (unless (> emacs-major-version 27) + ;; This advice have been merged in emacs-28. + (advice-add 'eshell-eval-command :override #'helm--advice-eshell-eval-command)) + (when (or eshell-command-aliases-list + (y-or-n-p "No eshell aliases found, run eshell-command without alias anyway? ")) + (let* ((cand-list (helm-marked-candidates :with-wildcard t)) + (default-directory (or helm-ff-default-directory + ;; If candidate is an url *-ff-default-directory is nil + ;; so keep value of default-directory. + default-directory)) + helm-display-source-at-screen-top + (helm-actions-inherit-frame-settings t) + helm-use-frame-when-more-than-two-windows + (command + (with-helm-display-marked-candidates + helm-marked-buffer-name + (helm-ff--count-and-collect-dups + (mapcar 'helm-basename cand-list)) + (with-helm-current-buffer + (helm-comp-read + "Command: " + (cl-loop with len = 0 + with aliases = + (cl-loop for (a c) in (eshell-read-aliases-list) + for len-key = (length a) + when + (and (string-match + "\\(\\$1\\|\\$\\*\\)" + c) + (not (member a helm-ff-eshell-unwanted-aliases))) + do (when (> len-key len) (setq len len-key)) + and collect (list a c)) + for (a c) in aliases + collect (cons + (concat (propertize + a 'face 'font-lock-keyword-face) + (make-string (1+ (- len (length a))) ? ) + c) + a)) + :fc-transformer #'helm-adaptive-sort + :buffer "*helm eshell on file*" + :name "Eshell command" + :mode-line + '("Eshell alias" + "C-h m: Help, \\[universal-argument]: Insert output at point") + :help-message 'helm-esh-help-message + :history 'helm-eshell-command-on-file-history + :raw-history t + :input-history + 'helm-eshell-command-on-file-input-history)))) + (alias-value (car (assoc-default command eshell-command-aliases-list))) + cmd-line) + (if (or (equal helm-current-prefix-arg '(16)) + (equal map '(16))) + ;; Two time C-u from `helm-comp-read' mean print to current-buffer. + ;; i.e `eshell-command' will use this value. + (setq current-prefix-arg '(16)) + ;; Else reset the value of `current-prefix-arg' + ;; to avoid printing in current-buffer. + (setq current-prefix-arg nil)) + (if (and (or + ;; One prefix-arg have been passed before `helm-comp-read'. + ;; If map have been set with C-u C-u (value == '(16)) + ;; ignore it. + (and map (equal map '(4))) + ;; One C-u from `helm-comp-read'. + (equal helm-current-prefix-arg '(4)) + ;; An alias that finish with $* + (and alias-value + ;; If command is an alias be sure it accept + ;; more than one arg i.e $*. + (string-match "\\$\\*" alias-value))) + (cdr cand-list) + (and alias-value + ;; Command is an alias and accept only one arg. + (not (string-match "\\$1" alias-value)))) + + ;; Run eshell-command with ALL marked files as argument. + ;; This wont work on remote files, because tramp handlers depend + ;; on `default-directory' (limitation). + (let ((mapfiles (mapconcat 'shell-quote-argument cand-list " "))) + (if (string-match "%s" command) + (setq cmd-line (format command mapfiles)) ; See [1] + (setq cmd-line (format "%s %s" command mapfiles))) + (eshell-command cmd-line)) + + ;; Run eshell-command sequencially on EACH marked files. + ;; To work with tramp handler we have to call + ;; COMMAND on basename of each file, using + ;; its basedir as `default-directory'. + (unwind-protect + (progn + (cl-loop for f in cand-list + for n from 1 + for dir = (and (not (string-match helm--url-regexp f)) + (helm-basedir f)) + ;; We can use basename here as the command will run + ;; under default-directory. + ;; This allows running e.g. + ;; "tar czvf test.tar.gz %s/*" without creating + ;; an archive expanding from /home. + for file = (shell-quote-argument + (if (string-match helm--url-regexp f) + f (helm-basename f))) + ;; \@ => placeholder for file without extension. + ;; \# => placeholder for incremental number. + for fcmd = (helm-aand command + (replace-regexp-in-string + "\\\\#" (format "%03d" n) + it t t) + (replace-regexp-in-string + "\\\\@" + (regexp-quote + (file-name-sans-extension file)) + it t t)) + for com = (if (string-match "%s" fcmd) + ;; [1] This allows to enter other args AFTER filename + ;; i.e + (format fcmd file) + (format "%s %s" fcmd file)) + do (let ((default-directory (or dir default-directory))) + (eshell-command com)))) + ;; Async process continues running but doesn't need anymore + ;; the advice at this point (see the `eshell-eval-command' + ;; call in `eshell-command'). + (unless (> emacs-major-version 27) + (advice-remove 'eshell-eval-command #'helm--advice-eshell-eval-command))))))) + +(defun helm--advice-eshell-eval-command (command &optional input) + "Fix return value when command ends with \"&\"." + ;; Fix this emacs commit which is plain wrong as it returns + ;; either nil or an error (double because format spec doesn't + ;; always match specifier) whereas it should return either a + ;; single element (CAR DELIM) or DELIM itself if the car of + ;; DELIM is a process. + ;; This prevent running eshell-command async when needed i.e. when + ;; command ends with "&". + ;; + ;; UPDATE: This have now been merged in Emacs-28. + ;; + ;; 6b6f91b357f6fe2f1e0d72f046a1b8d8a2d6d8c3 + ;; Author: John Wiegley + ;; AuthorDate: Fri May 27 02:57:18 2005 +0000 + ;; Commit: John Wiegley + ;; CommitDate: Fri May 27 02:57:18 2005 +0000 + (if eshell-current-command + ;; we can just stick the new command at the end of the current + ;; one, and everything will happen as it should + (setcdr (last (cdr eshell-current-command)) + (list `(let ((here (and (eobp) (point)))) + ,(and input + `(insert-and-inherit ,(concat input "\n"))) + (if here + (eshell-update-markers here)) + (eshell-do-eval ',command)))) + (and eshell-debug-command + (with-current-buffer (get-buffer-create "*eshell last cmd*") + (erase-buffer) + (insert "command: \"" input "\"\n"))) + (setq eshell-current-command command) + (let* ((delim (catch 'eshell-incomplete + (eshell-resume-eval))) + (val (car-safe delim))) + ;; If the return value of `eshell-resume-eval' is wrapped in a + ;; list, it indicates that the command was run asynchronously. + ;; In that case, unwrap the value before checking the delimiter + ;; value. + (if (and val + (not (processp val)) + (not (eq val t))) + (error "Unmatched delimiter: %S" val) + ;; Eshell-command expect a list like () to know if the + ;; command should be async or not. + (or (and (processp val) delim) val))))) + +(defun helm-find-files-eshell-command-on-file (_candidate) + "Run `eshell-command' on CANDIDATE or marked candidates. +See `helm-find-files-eshell-command-on-file-1' for more info." + (helm-find-files-eshell-command-on-file-1 helm-current-prefix-arg)) + +(defun helm-ff--shell-interactive-buffer-p (buffer &optional mode) + (with-current-buffer buffer + (when (eq major-mode (or mode 'eshell-mode)) + (let ((next-prompt-fn (cl-case major-mode + (shell-mode #'comint-next-prompt) + (eshell-mode #'eshell-next-prompt) + (term-mode #'term-next-prompt)))) + (save-excursion + (goto-char (point-min)) + (funcall next-prompt-fn 1) + (null (eql (point) (point-min)))))))) + +(defun helm-ff-switch-to-shell (_candidate) + "Switch to a shell buffer and cd to `helm-ff-default-directory'. +Set your preferred shell mode in `helm-ff-preferred-shell-mode'. + +With a numeric prefix arg switch to numbered shell buffer, if no +prefix arg provided and more than one shell buffer exists, provide +completions on those buffers. If only one shell buffer exists, +switch to this one, if no shell buffer exists or if the numeric +prefix arg shell buffer doesn't exists, create it and switch to it." + ;; Reproduce the Emacs-25 behavior to be able to edit and send + ;; command in term buffer. + (let (term-char-mode-buffer-read-only ; Emacs-25 behavior. + term-char-mode-point-at-process-mark ; Emacs-25 behavior. + (cd-eshell (lambda () + (eshell/cd helm-ff-default-directory) + (eshell-reset))) + (cd-shell + (lambda () + (goto-char (point-max)) + (when (eq helm-ff-preferred-shell-mode 'shell-mode) + (comint-delete-input)) + (insert (format "cd %s" + (shell-quote-argument + (or (file-remote-p + helm-ff-default-directory 'localname) + helm-ff-default-directory)))) + (cl-case helm-ff-preferred-shell-mode + (shell-mode (comint-send-input)) + (term-mode (progn (term-char-mode) (term-send-input)))))) + (bufs (cl-loop for b in (mapcar 'buffer-name (buffer-list)) + when (helm-ff--shell-interactive-buffer-p + b helm-ff-preferred-shell-mode) + collect b))) + ;; Jump to a shell buffer or open a new session. + (helm-aif (and (not helm-current-prefix-arg) + (if (cdr bufs) + (helm-comp-read "Switch to shell buffer: " bufs + :must-match t) + (car bufs))) + ;; Display in same window by default to preserve the + ;; historical behaviour + (pop-to-buffer it '(display-buffer-same-window)) + (cl-case helm-ff-preferred-shell-mode + (eshell-mode + (eshell helm-current-prefix-arg)) + (shell-mode + (shell (helm-aif (and helm-current-prefix-arg + (prefix-numeric-value + helm-current-prefix-arg)) + (format "*shell<%s>*" it)))) + (term-mode + (progn + (ansi-term (getenv "SHELL") + (helm-aif (and helm-current-prefix-arg + (prefix-numeric-value + helm-current-prefix-arg)) + (format "*ansi-term<%s>*" it))) + (term-line-mode))))) + ;; Now cd into directory. + (helm-aif (and (memq major-mode '(shell-mode term-mode)) + (get-buffer-process (current-buffer))) + (accept-process-output it 0.1)) + (unless (helm-ff-shell-alive-p major-mode) + (funcall + (if (eq major-mode 'eshell-mode) cd-eshell cd-shell))))) + +(defun helm-ff-shell-alive-p (mode) + "Returns non nil when a process is running inside `shell-mode' buffer." + (cl-ecase mode + (shell-mode + (save-excursion + (comint-goto-process-mark) + (or (null comint-last-prompt) + (not (eql (point) + (marker-position (cdr comint-last-prompt))))))) + (eshell-mode + (get-buffer-process (current-buffer))) + (term-mode + (save-excursion + (goto-char (term-process-mark)) + (not (looking-back "\\$ " (- (point) 2))))))) + +(defun helm-ff-touch-files (_candidate) + "The touch files action for helm-find-files." + (let* ((files (helm-marked-candidates)) + (split (cl-loop for f in files + for spt = (unless helm-current-prefix-arg + (cons (helm-basedir f) + (split-string f ", ?"))) + if spt + append (cl-loop with dir = (car spt) + for ff in (cdr spt) + collect (expand-file-name ff dir)) + else collect f)) + (timestamp (helm-comp-read + "Timestamp (default Now): " + (cl-loop for f in split + for time = (file-attributes f) + for date = (and time + (format-time-string + "%Y-%m-%d %H:%M:%S" + (nth 5 time))) + when date + collect (cons (format "%s: %s" + (helm-basename f) date) + date)) + :default + (format-time-string "%Y-%m-%d %H:%M:%S" + (current-time)))) + (failures + (cl-loop with default-directory = helm-ff-default-directory + for f in split + for file = (or (file-remote-p f 'localname) f) + when (> (process-file + "touch" nil nil nil "-d" timestamp file) + 0) + collect f))) + (when failures + (message "Failed to touch *%s files:\n%s" + (length failures) + (mapconcat (lambda (f) (format "- %s\n" f)) failures ""))))) + +(helm-make-command-from-action helm-ff-run-touch-files + "Used to interactively run touch file action from keyboard." + 'helm-ff-touch-files) + +(defun helm-ff-sort-by-size () + (interactive) + (let ((helm-ff-initial-sort-method 'size)) + (helm-force-update + (concat (regexp-quote (helm-get-selection + nil helm-ff-transformer-show-only-basename)) + "$")) + (message "Sorting by size"))) +(put 'helm-ff-sort-by-size 'helm-only t) + +(defun helm-ff-sort-by-newest () + (interactive) + (let ((helm-ff-initial-sort-method 'newest)) + (helm-force-update + (concat (regexp-quote (helm-get-selection + nil helm-ff-transformer-show-only-basename)) + "$")) + (message "Sorting by newest"))) +(put 'helm-ff-sort-by-newest 'helm-only t) + +(defun helm-ff-sort-by-ext () + (interactive) + (let ((helm-ff-initial-sort-method 'ext)) + (helm-force-update + (concat (regexp-quote (helm-get-selection + nil helm-ff-transformer-show-only-basename)) + "$")) + (message "Sorting by extensions"))) +(put 'helm-ff-sort-by-ext 'no-helm-mx t) + +(defun helm-ff-sort-alpha () + (interactive) + (let ((helm-ff-initial-sort-method nil)) + (helm-force-update + (concat (regexp-quote (helm-get-selection + nil helm-ff-transformer-show-only-basename)) + "$")) + (message "Sorting alphabetically"))) +(put 'helm-ff-sort-alpha 'helm-only t) + +(defun helm-ff-directories-only (candidates _source) + (if helm-ff--show-directories-only + (cl-loop for (d . r) in candidates + when (file-directory-p r) + ;; We can use this as long as this filtering function + ;; is called after `helm-ff-fct' otherwise candidates + ;; may not be cons cell at first call [1]. + collect (cons d r)) + candidates)) + +(defun helm-ff-files-only (candidates _source) + (if helm-ff--show-files-only + (cl-loop for (d . r) in candidates + unless (file-directory-p r) + ;; Same comment as in [1] above. + collect (cons d r)) + candidates)) + +(defun helm-ff-toggle-dirs-only () + "Show only directories in helm-find-files." + (interactive) + (with-helm-alive-p + (setq helm-ff--show-directories-only (not helm-ff--show-directories-only)) + (setq helm-ff--show-files-only nil) + (helm-update (helm-get-selection nil t)))) +(put 'helm-ff-toggle-dirs-only 'helm-only t) + +(defun helm-ff-toggle-files-only () + "Show only files in helm-find-files." + (interactive) + (with-helm-alive-p + (setq helm-ff--show-files-only (not helm-ff--show-files-only)) + (setq helm-ff--show-directories-only nil) + (helm-update (helm-get-selection nil t)))) +(put 'helm-ff-toggle-files-only 'helm-only t) + +(defun helm-ff-after-persistent-show-all () + (when helm-ff-reset-filters-on-update + (setq helm-ff--show-directories-only nil + helm-ff--show-files-only nil))) + +(defun helm-ff-serial-rename-action (method) + "Rename all marked files in `helm-ff-default-directory' with METHOD. +See `helm-ff-serial-rename-1'." + (let* ((helm--reading-passwd-or-string t) + (cands (helm-marked-candidates :with-wildcard t)) + (def-name (car cands)) + (name (helm-read-string "NewName: " + (replace-regexp-in-string + "[0-9]+$" "" + (helm-basename + def-name + (file-name-extension def-name))))) + (start (read-number "StartAtNumber: ")) + (extension (helm-read-string "Extension: " + (file-name-extension (car cands)))) + (dir (expand-file-name + (helm-read-file-name + "Serial Rename to directory: " + :initial-input + (expand-file-name helm-ff-default-directory) + :test 'file-directory-p + :must-match t))) + done) + (with-helm-display-marked-candidates + helm-marked-buffer-name (helm-ff--count-and-collect-dups cands) + (if (y-or-n-p + (format "Rename %s file(s) to <%s> like this ?\n%s " + (length cands) dir (format "%s <-> %s%s.%s" + (helm-basename (car cands)) + name start extension))) + (progn + (helm-ff-serial-rename-1 + dir cands name start extension :method method) + (setq done t) + (message nil)))) + (if done + (with-helm-current-buffer (helm-find-files-1 dir)) + (message "Operation aborted")))) + +(defun helm-ff-member-directory-p (file directory) + (let ((dir-file (expand-file-name + (file-name-as-directory (file-name-directory file)))) + (cur-dir (expand-file-name (file-name-as-directory directory)))) + (string= dir-file cur-dir))) + +(cl-defun helm-ff-serial-rename-1 + (directory collection new-name start-at-num extension &key (method 'rename)) + "Rename files in COLLECTION to DIRECTORY with the prefix name NEW-NAME. +Rename start at number START-AT-NUM - ex: prefixname-01.jpg. +EXTENSION is the file extension to use. In empty prompt, reuse +the original extension of file. +METHOD can be one of rename, copy or symlink. +Files will be renamed if they are files of current directory, +otherwise they will be treated with METHOD. +Default METHOD is rename." + ;; Maybe remove directories selected by error in collection. + (setq collection (cl-remove-if 'file-directory-p collection)) + (let* ((tmp-dir (file-name-as-directory + (concat (file-name-as-directory directory) + (symbol-name (cl-gensym "tmp"))))) + (fn (cl-case method + (copy 'copy-file) + (symlink 'make-symbolic-link) + (rename 'rename-file) + (t (error "Error: Unknown method %s" method))))) + (make-directory tmp-dir) + (unwind-protect + (progn + ;; Rename all files to tmp-dir with new-name. + ;; If files are not from start directory, use method + ;; to move files to tmp-dir. + (cl-loop for i in collection + for count from start-at-num + for fnum = (if (< count 10) "0%s" "%s") + for nname = (concat tmp-dir new-name (format fnum count) + (if (not (string= extension "")) + (format ".%s" (replace-regexp-in-string + "[.]" "" extension)) + (file-name-extension i 'dot))) + do (if (helm-ff-member-directory-p i directory) + (rename-file i nname) + (funcall fn i nname))) + ;; Now move all from tmp-dir to destination. + (cl-loop with dirlist = (directory-files + tmp-dir t directory-files-no-dot-files-regexp) + for f in dirlist do + (if (file-symlink-p f) + (make-symbolic-link (file-truename f) + (concat (file-name-as-directory directory) + (helm-basename f))) + (rename-file f directory)))) + (delete-directory tmp-dir t)))) + +(defun helm-ff-serial-rename (_candidate) + "Serial rename all marked files to `helm-ff-default-directory'. +Rename only file of current directory, and symlink files coming from +other directories. +See `helm-ff-serial-rename-1'." + (helm-ff-serial-rename-action 'rename)) + +(defun helm-ff-serial-rename-by-symlink (_candidate) + "Serial rename all marked files to `helm-ff-default-directory'. +Rename only file of current directory, and symlink files coming +from other directories. +See `helm-ff-serial-rename-1'." + (helm-ff-serial-rename-action 'symlink)) + +(defun helm-ff-serial-rename-by-copying (_candidate) + "Serial rename all marked files to `helm-ff-default-directory'. +Rename only file of current directory, and copy files coming from +other directories. +See `helm-ff-serial-rename-1'." + (helm-ff-serial-rename-action 'copy)) + +(defvar helm-ff-query-replace-fnames-history-from nil) +(defvar helm-ff-query-replace-fnames-history-to nil) +(defun helm-ff-query-replace-on-filenames (candidates) + "Query replace on filenames of CANDIDATES. +This doesn't replace inside the files, only modify filenames." + (with-helm-display-marked-candidates + helm-marked-buffer-name + (mapcar 'helm-basename candidates) + (let* ((regexp (read-string "Replace regexp on filename(s): " + nil 'helm-ff-query-replace-history-from + (helm-basename (car candidates)))) + (rep (read-string (format "Replace regexp `%s' with: " regexp) + nil 'helm-ff-query-replace-history-to))) + (cl-loop with query = "y" + with count = 0 + for old in candidates + for new = (helm-ff--query-replace-in-fname-set-new-name + old regexp rep count) + ;; If `regexp' is not matched in `old' + ;; `replace-regexp-in-string' will + ;; return `old' unmodified. + unless (string= old new) + do (progn + (when (file-exists-p new) + (setq new (concat (file-name-sans-extension new) + (format "(%s)" count) + (file-name-extension new t)))) + (unless (string= query "!") + (setq query (helm-read-answer (format + "Replace `%s' by `%s' [!,y,n,q]" + (helm-basename old) + (helm-basename new)) + '("y" "n" "!" "q")))) + (when (string= query "q") + (cl-return (message "Operation aborted"))) + (unless (string= query "n") + (rename-file old new) + (cl-incf count))) + finally (message "%d Files renamed" count)))) + ;; This fix the emacs bug where "Emacs-Lisp:" is sent + ;; in minibuffer (not the echo area). + (sit-for 0.1) + (with-current-buffer (window-buffer (minibuffer-window)) + (delete-minibuffer-contents))) + +(defun helm-ff--query-replace-in-fname-set-new-name (old regexp rep count) + "Setup a new name for OLD replacing part matching REGEXP with REP. +COUNT is used for incrementing new name if needed." + (let (subexp target) + (concat (helm-basedir old) + (helm--replace-regexp-in-buffer-string + (save-match-data + (cond ((string= regexp "%.") + (setq subexp 1) + (helm-ff--prepare-str-with-regexp + (setq target (helm-basename old t)))) + ((string= regexp ".%") + (setq subexp 1) + (helm-ff--prepare-str-with-regexp + (setq target (file-name-extension old)))) + ((string= regexp "%") + (regexp-quote + (setq target (helm-basename old)))) + ((string-match "%:\\([0-9]+\\):\\([0-9]+\\)" regexp) + (setq subexp 1) + (let ((beg (match-string 1 regexp)) + (end (match-string 2 regexp)) + (str (helm-basename old))) + (setq target (substring str + (string-to-number beg) + (string-to-number end))) + (helm-ff--prepare-str-with-regexp str beg end))) + (t regexp))) + (save-match-data + (cond (;; Handle incremental + ;; replacement with \# in + ;; search and replace + ;; feature in placeholder \@. + (string-match + "\\\\@/\\(.*\\)/\\(\\(?99:.*\\)\\\\#\\)/" + rep) + (replace-regexp-in-string + (match-string 1 rep) + (concat (match-string 99 rep) + (format "%03d" (1+ count))) + target)) + ;; Incremental replacement + ;; before or after \@. + ((and (string-match-p "\\\\#" rep) + (string-match "\\\\@" rep)) + (replace-regexp-in-string + "\\\\#" (format "%03d" (1+ count)) + (replace-match target t t rep))) + ;; Simple incremental replacement. + ((string-match "\\\\#" rep) + (replace-match + (format "%03d" (1+ count)) t t rep)) + ;; Substring replacement in placeholder. + ((string-match + "\\\\@:\\([0-9]*\\):\\([0-9]*\\)" rep) + (replace-match (substring + target + (string-to-number + (match-string 1 rep)) + (pcase (match-string 2 rep) + ((pred (string= "")) + (length target)) + (res (string-to-number res)))) + t t rep)) + ;; Search and replace in + ;; placeholder. Doesn't + ;; handle incremental here. + ((string-match "\\\\@/\\(.*\\)/\\(.*\\)/" rep) + (replace-match (replace-regexp-in-string + (match-string 1 rep) + (match-string 2 rep) + target t) + t t rep)) + ;; Simple replacement by placeholder. + ((string-match "\\\\@" rep) + (replace-match target t t rep)) + ;; Replacement with + ;; upcase, downcase or + ;; capitalized text. + ((string= rep "%u") #'upcase) + ((string= rep "%d") #'downcase) + ((string= rep "%c") #'capitalize) + ;; Simple replacement with + ;; whole replacement regexp. + (t rep))) + (helm-basename old) t nil subexp)))) + +(defun helm-ff--prepare-str-with-regexp (str &optional rep1 rep2) + ;; This is used in `helm-ff-query-replace-on-filenames' to prepare + ;; STR when REGEXP is specified as substring e.g %:1:3 in this case + ;; substring from 1 to 3 in STR will be enclosed with parenthesis to + ;; match this substring as a subexp e.g %:1:3 on string "emacs" will + ;; be replaced by "e\\(ma\\)cs" using subexp 1 like this: + ;; (helm--replace-regexp-in-buffer-string "e\\(ma\\)cs" "fo" "emacs" nil t 1) + ;; => "efocs" + ;; ^^ + ;; Where "1" and "3" will be strings extracted with match-string + ;; from regexp and refered respectively in this function as REP1 and + ;; REP2. + (let* ((from (or (and rep1 (string-to-number rep1)) 0)) + (to (or (and rep2 (string-to-number rep2)) (length str))) + (subexp (concat "\\(" (regexp-quote (substring str from to)) "\\)")) + (before-str (unless (zerop from) + (regexp-quote (substring str 0 from)))) + (after-str (unless (= to (length str)) + (regexp-quote (substring str to (length str)))))) + (concat before-str subexp after-str))) + +;; The action. +(defun helm-ff-query-replace-fnames-on-marked (_candidate) + (let ((marked (helm-marked-candidates :with-wildcard t))) + (helm-ff-query-replace-on-filenames marked))) + +;; The command for `helm-find-files-map'. +(helm-make-command-from-action helm-ff-run-query-replace-fnames-on-marked + "Run query-replace on filenames from HFF." + 'helm-ff-query-replace-fnames-on-marked) + +(defun helm-ff-query-replace (_candidate) + (let ((bufs (cl-loop for f in (helm-marked-candidates :with-wildcard t) + collect (buffer-name (find-file-noselect f))))) + (helm-buffer-query-replace-1 nil bufs))) + +(helm-make-command-from-action helm-ff-run-query-replace + "Run query-replace from HFF." + 'helm-ff-query-replace) + +(defun helm-ff-query-replace-regexp (_candidate) + (let ((bufs (cl-loop for f in (helm-marked-candidates :with-wildcard t) + collect (buffer-name (find-file-noselect f))))) + (helm-buffer-query-replace-1 'regexp bufs))) + +(helm-make-command-from-action helm-ff-run-query-replace-regexp + "Run query-replace regexp from HFF." + 'helm-ff-query-replace-regexp) + +(defun helm-ff-toggle-auto-update () + (if helm-ff--deleting-char-backward + (progn + (message "[Auto expansion disabled]") + (sit-for 1) (message nil) + (setq helm-ff--auto-update-state nil)) + (setq helm-ff-auto-update-flag (not helm-ff-auto-update-flag)) + (setq helm-ff--auto-update-state helm-ff-auto-update-flag) + (message "[Auto expansion %s]" + (if helm-ff-auto-update-flag "enabled" "disabled")))) + +(defun helm-ff-run-toggle-auto-update () + (interactive) + (with-helm-alive-p + (helm-ff-toggle-auto-update))) +(put 'helm-ff-run-toggle-auto-update 'helm-only t) + +(defun helm-ff-delete-char-backward () + "Go up one level or disable HFF auto update and delete char backward. + +Going up one level works only when pattern is a directory endings +with \"/\", otherwise this command deletes char backward. + +Going up one level can be disabled if necessary by deleting \"/\" +at end of pattern using \\\\[backward-char] and +\\[helm-delete-minibuffer-contents]." + (interactive) + (with-helm-alive-p + (if (and helm-ff-DEL-up-one-level-maybe + (string-match "/\\'" helm-pattern) + (file-directory-p helm-pattern)) + (call-interactively 'helm-find-files-up-one-level) + (setq helm-ff-auto-update-flag nil) + (setq helm-ff--deleting-char-backward t) + (call-interactively + (lookup-key (current-global-map) + (read-kbd-macro "DEL"))) + (helm--update-header-line)))) +(put 'helm-ff-delete-char-backward 'helm-only t) + +(defun helm-ff-delete-char-backward--exit-fn () + (setq helm-ff-auto-update-flag helm-ff--auto-update-state) + (setq helm-ff--deleting-char-backward nil)) + +(defvar helm-ff--RET-disabled nil) +(defun helm-ff-RET-1 (&optional must-match) + "Used for RET action in `helm-find-files'. +See `helm-ff-RET' for details. +If MUST-MATCH is specified exit with +`helm-confirm-and-exit-minibuffer' which handle must-match mechanism." + (let ((sel (helm-get-selection)) + ;; Ensure `file-directory-p' works on remote files. + non-essential) + (cl-assert sel nil "Trying to exit with no candidates") + (if (and (or (file-directory-p sel) + (helm-ff--invalid-tramp-name-p sel)) + ;; Allows exiting with default action when a prefix arg + ;; is specified. + (null current-prefix-arg) + (null helm-ff--RET-disabled) + (or (and (file-remote-p sel) + (string= "." (helm-basename sel)) + (string-match-p "\\`[/].*:.*:\\'" + helm-pattern)) + (not (string= "." (helm-basename sel))))) + (helm-execute-persistent-action) + (if must-match + (helm-confirm-and-exit-minibuffer) + (helm-maybe-exit-minibuffer))))) + +(defun helm-ff-RET () + "Default action for RET in `helm-find-files'. + +Behave differently depending on `helm-selection': + +- candidate basename is \".\" => open it in dired. +- candidate is a directory => expand it. +- candidate is a file => open it." + (interactive) + (helm-ff-RET-1)) +(put 'helm-ff-RET 'helm-only t) + +(defun helm-ff-TAB-1 (&optional force-menu) + "Used for TAB action in `helm-find-files'." + (let ((sel (helm-get-selection))) + (if (and (null force-menu) + (file-directory-p sel) + (not (string= "." (helm-basename sel)))) + (helm-execute-persistent-action) + (helm-select-action)))) + +(defun helm-ff-TAB (arg) + "Default action for TAB in `helm-find-files'. + +Behave differently depending on `helm-selection': + +- candidate basename is \".\" => open the action menu. +- candidate is a directory => expand it. +- candidate is a file => open action menu. + +Called with a prefix arg open menu unconditionally." + (interactive "P") + (helm-ff-TAB-1 arg)) +(put 'helm-ff-TAB 'helm-only t) + +(defun helm-ff-RET-must-match () + "Same as `helm-ff-RET' but used in must-match map." + (interactive) + (helm-ff-RET-1 t)) + +(helm-make-command-from-action helm-ff-run-grep + "Run Grep action from `helm-source-find-files'." + 'helm-find-files-grep) + +(helm-make-command-from-action helm-ff-run-git-grep + "Run git-grep action from `helm-source-find-files'." + 'helm-ff-git-grep) + +(helm-make-command-from-action helm-ff-run-grep-ag + "Run grep AG action from `helm-source-find-files'." + 'helm-find-files-ag) + +(helm-make-command-from-action helm-ff-run-pdfgrep + "Run Pdfgrep action from `helm-source-find-files'." + 'helm-ff-pdfgrep) + +(helm-make-command-from-action helm-ff-run-zgrep + "Run Grep action from `helm-source-find-files'." + 'helm-ff-zgrep) + +(helm-make-command-from-action helm-ff-run-copy-file + "Run Copy file action from `helm-source-find-files'." + 'helm-find-files-copy) + +(helm-make-command-from-action helm-ff-run-rsync-file + "Run Rsync file action from `helm-source-find-files'." + 'helm-find-files-rsync) + +(helm-make-command-from-action helm-ff-run-rename-file + "Run Rename file action from `helm-source-find-files'." + 'helm-find-files-rename) + +(helm-make-command-from-action helm-ff-run-byte-compile-file + "Run Byte compile file action from `helm-source-find-files'." + 'helm-find-files-byte-compile) + +(helm-make-command-from-action helm-ff-run-load-file + "Run Load file action from `helm-source-find-files'." + 'helm-find-files-load-files) + +(helm-make-command-from-action helm-ff-run-eshell-command-on-file + "Run eshell command on file action from `helm-source-find-files'." + 'helm-find-files-eshell-command-on-file) + +(helm-make-command-from-action helm-ff-run-ediff-file + "Run Ediff file action from `helm-source-find-files'." + 'helm-find-files-ediff-files) + +(helm-make-command-from-action helm-ff-run-ediff-merge-file + "Run Ediff merge file action from `helm-source-find-files'." + 'helm-find-files-ediff-merge-files) + +(helm-make-command-from-action helm-ff-run-symlink-file + "Run Symlink file action from `helm-source-find-files'." + 'helm-find-files-symlink) + +(helm-make-command-from-action helm-ff-run-relsymlink-file + "Run Symlink file action from `helm-source-find-files'." + 'helm-find-files-relsymlink) + +(helm-make-command-from-action helm-ff-run-hardlink-file + "Run Hardlink file action from `helm-source-find-files'." + 'helm-find-files-hardlink) + +(helm-make-command-from-action helm-ff-run-chmod + "Run chmod action from `helm-source-find-files'." + 'helm-ff-chmod) + +(defun helm-ff-delete-files (candidate) + "Delete files default action." + (funcall helm-ff-delete-files-function candidate)) + +(helm-make-command-from-action helm-ff-run-delete-file + "Run Delete file action from `helm-source-find-files'." + 'helm-ff-delete-files) + +(helm-make-command-from-action helm-ff-run-complete-fn-at-point + "Run complete file name action from `helm-source-find-files'." + 'helm-insert-file-name-completion-at-point) + +(helm-make-command-from-action helm-ff-run-switch-to-shell + "Run switch to eshell action from `helm-source-find-files'." + 'helm-ff-switch-to-shell) + +(helm-make-command-from-action helm-ff-run-switch-other-window + "Run switch to other window action from `helm-source-find-files'. +When a prefix arg is provided, split is done vertically." + 'helm-find-files-other-window) + +(helm-make-command-from-action helm-ff-run-switch-other-frame + "Run switch to other frame action from `helm-source-find-files'." + 'find-file-other-frame) + +(helm-make-command-from-action helm-ff-run-open-file-externally + "Run open file externally command action from `helm-source-find-files'." + 'helm-open-file-externally) + +(helm-make-command-from-action helm-ff-run-open-file-with-default-tool + "Run open file externally command action from `helm-source-find-files'." + 'helm-open-file-with-default-tool) + +(defun helm-ff-locate (candidate) + "Locate action function for `helm-find-files'." + (helm-locate-set-command) + (let ((default (concat (helm-basename + (expand-file-name + candidate + helm-ff-default-directory)) + (unless (or + ;; "-b" is already added when fuzzy matching. + helm-locate-fuzzy-match + ;; The locate '-b' option doesn't exists + ;; in everything (es). + (and (eq system-type 'windows-nt) + (string-match "^es" helm-locate-command))) + " -b")))) + (helm-locate-1 helm-current-prefix-arg nil 'from-ff default))) + +(helm-make-command-from-action helm-ff-run-locate + "Run locate action from `helm-source-find-files'." + 'helm-ff-locate) + +(defun helm-files-insert-as-org-link (candidate) + (insert (format "[[%s][]]" candidate)) + (goto-char (- (point) 2))) + +(helm-make-command-from-action helm-ff-run-insert-org-link + "Run insert org link from HFF." + 'helm-files-insert-as-org-link) + +(helm-make-command-from-action helm-ff-run-find-file-as-root + "Run find file as root from HFF." + 'helm-find-file-as-root) + +(helm-make-command-from-action helm-ff-run-find-alternate-file + "Run `find-alternate-file' from HFF." + 'find-alternate-file) + +(helm-make-command-from-action helm-ff-run-mail-attach-files + "Run mail attach files command action from `helm-source-find-files'." + 'helm-ff-mail-attach-files) + +(helm-make-command-from-action helm-ff-run-etags + "Run Etags command action from `helm-source-find-files'." + 'helm-ff-etags-select) + +(defvar lpr-printer-switch) +(defun helm-ff-print (_candidate) + "Print marked files. + +You may to set in order variables `lpr-command',`lpr-switches' +and/or `printer-name', but with no settings Helm should detect +your printer(s) and print with the default `lpr' settings. + +NOTE: DO NOT set the \"-P\" flag in `lpr-switches'. If you really +have to modify this, do it in `lpr-printer-switch'. + +Same as `dired-do-print' but for Helm." + (require 'lpr) + (when (or helm-current-prefix-arg + (not helm-ff-printer-list)) + (setq helm-ff-printer-list + (helm-ff-find-printers))) + (let* ((file-list (helm-marked-candidates :with-wildcard t)) + (len (length file-list)) + (printer-name (if helm-ff-printer-list + (helm-comp-read + "Printer: " helm-ff-printer-list) + printer-name)) + (lpr-switches + (if (and (stringp printer-name) + (string< "" printer-name)) + (cons (concat lpr-printer-switch " " printer-name) + lpr-switches) + lpr-switches)) + (command (helm-read-string + (format "Print *%s File(s):\n%s with: " + len + (mapconcat + (lambda (f) (format "- %s\n" f)) + file-list "")) + (when (and lpr-command lpr-switches) + (mapconcat 'identity + (cons lpr-command + (if (stringp lpr-switches) + (list lpr-switches) + lpr-switches)) + " ")))) + (file-args (mapconcat #'shell-quote-argument + file-list " ")) + (cmd-line (concat command " " file-args))) + (if command + (start-process-shell-command "helm-print" nil cmd-line) + (error "Error: Please verify your printer settings in Emacs.")))) + +(helm-make-command-from-action helm-ff-run-print-file + "Run Print file action from `helm-source-find-files'." + 'helm-ff-print) + +(defun helm-ff-checksum (file) + "Calculate the checksum of FILE. +The checksum is copied to `kill-ring'. +Checksum is calculated with the md5sum, sha1sum, sha224sum, +sha256sum, sha384sum and sha512sum when available, otherwise the +Emacs function `secure-hash' is used but it is slow and may crash +Emacs and even the whole system as it eats all memory." + (cl-assert (file-regular-p file) + nil "`%s' is not a regular file" file) + (let* ((algo (intern (helm-comp-read + "Algorithm: " + '(md5 sha1 sha224 sha256 sha384 sha512)))) + (cmd (concat (symbol-name algo) "sum")) + (bn (helm-basename file)) + proc) + (message "Calculating %s checksum for %s..." algo bn) + (if (executable-find cmd) + (progn + (set-process-filter + (setq proc (start-file-process cmd nil cmd "-b" file)) + (lambda (_process output) + (when output (kill-new output)))) + (set-process-sentinel + proc + `(lambda (_process event) + (when (string= event "finished\n") + (message "Calculating %s checksum for `%s' done and copied to kill-ring" + ,(symbol-name algo) ,bn))))) + (async-let ((sum (with-temp-buffer + (insert-file-contents-literally file) + (secure-hash algo (current-buffer))))) + (kill-new sum) + (message "Calculating %s checksum for `%s' done and copied to kill-ring" + algo bn))))) + +(defun helm-ff-toggle-basename () + (with-helm-buffer + (setq helm-ff-transformer-show-only-basename + (not helm-ff-transformer-show-only-basename)) + (let* ((cand (helm-get-selection)) + (target (if helm-ff-transformer-show-only-basename + (helm-basename cand) cand))) + (helm-force-update + (format helm-ff-last-expanded-candidate-regexp + (regexp-quote target)))))) + +(defun helm-ff-run-toggle-basename () + (interactive) + (with-helm-alive-p + (unless (helm-empty-source-p) + (helm-ff-toggle-basename)))) +(put 'helm-ff-run-toggle-basename 'helm-only t) + +(defun helm-ff-mark-similar-files-1 () + "Mark similar files. +Files are considered similar if they have the same face and same +extension." + (with-helm-window + (let* ((src (helm-get-current-source)) + (file (helm-get-selection nil 'withprop src)) + (face (get-text-property (min 2 (length file)) 'face file)) + (ext (file-name-extension file))) + (helm-map-candidates-in-source src + (lambda (_cand) (helm-make-visible-mark)) + (lambda (cand) + (and (not (helm-this-visible-mark)) + (eq (get-text-property (min 2 (length cand)) 'face cand) face) + (equal ext (file-name-extension cand))))) + (helm-mark-current-line) + (helm-display-mode-line src t) + (when helm-marked-candidates + (message "%s candidates marked" (length helm-marked-candidates)) + (set-window-margins (selected-window) 1))))) + +(defun helm-ff-mark-similar-files () + "Mark all files similar to selection." + (interactive) + (with-helm-alive-p + (let ((marked (helm-marked-candidates))) + (if (and (>= (length marked) 1) + (with-helm-window helm-visible-mark-overlays)) + (helm-unmark-all) + (helm-ff-mark-similar-files-1))))) +(put 'helm-ff-mark-similar-files 'helm-only t) + +(defun helm-reduce-file-name-1 (fname level) + ;; This is the old version of helm-reduce-file-name, we still use it + ;; with ftp fnames as expand-file-name is not working as expected + ;; with ftp fnames (emacs bug). + (cl-loop with result + with iter = (helm-iter-reduce-fname (expand-file-name fname)) + repeat level do (setq result (helm-iter-next iter)) + finally return (or result (expand-file-name "/")))) + +(defun helm-reduce-file-name-2 (fname level) + ;; This version comes from Bug#2004 (UNC paths) and should fix + ;; it. It works with local files and remote files as well but not + ;; with ftp, see helm-reduce-file-name-1. + (while (> level 0) + (unless (or (string= fname "/") + (string= (file-remote-p fname 'localname) "/")) + (setq fname (expand-file-name + (concat (expand-file-name fname) "/../")))) + (setq level (1- level))) + fname) + +(defun helm-reduce-file-name (fname level) + "Reduce FNAME by number LEVEL from end." + (if (helm-aand (file-remote-p fname 'method) + (string= it "ftp")) + (helm-reduce-file-name-1 fname level) + (helm-reduce-file-name-2 fname level))) + +(defun helm-iter-reduce-fname (fname) + "Yield FNAME reduced by one level at each call." + (let ((split (split-string fname "/" t))) + (unless (or (null split) + (string-match "\\`\\(~\\|[[:alpha:]]:\\)" (car split))) + (setq split (cons "/" split))) + (lambda () + (when (and split (cdr split)) + (cl-loop for i in (setq split (butlast split)) + concat (if (string= i "/") i (concat i "/"))))))) + +(defvar helm-find-files--level-tree nil) +(defvar helm-find-files--level-tree-iterator nil) +(defun helm-find-files-up-one-level (arg) + "Go up one level like unix command `cd ..'. +If prefix numeric arg is given go ARG level up." + (interactive "p") + (with-helm-alive-p + (helm-ff-after-persistent-show-all) + (let ((src (helm-get-current-source))) + (when (and (helm-file-completion-source-p src) + (not (helm-ff--invalid-tramp-name-p))) + (with-helm-window + (when (helm-follow-mode-p) + (helm-follow-mode -1) (message nil))) + ;; When going up one level we want to be at the line + ;; corresponding to actual directory, so store this info + ;; in `helm-ff-last-expanded'. + (let ((cur-cand (helm-get-selection nil nil src)) + (new-pattern (helm-reduce-file-name helm-pattern arg))) + ;; Ensure visibility on all candidates for preselection. + (unless (helm-empty-source-p) + ;; We may have an empty source in read-file-name when a + ;; predicate is used e.g. images and the default is a non + ;; file image. + (helm-set-attr 'candidate-number-limit + (if helm-ff-up-one-level-preselect + (max (gethash new-pattern + helm-ff--directory-files-length + helm-ff-candidate-number-limit) + helm-ff-candidate-number-limit) + helm-ff-candidate-number-limit))) + (cond ((file-directory-p helm-pattern) + (setq helm-ff-last-expanded helm-ff-default-directory)) + ((file-exists-p helm-pattern) + (setq helm-ff-last-expanded helm-pattern)) + ((and cur-cand (file-exists-p cur-cand)) + (setq helm-ff-last-expanded cur-cand))) + (unless helm-find-files--level-tree + (setq helm-find-files--level-tree + (cons helm-ff-default-directory + helm-find-files--level-tree))) + (setq helm-find-files--level-tree-iterator nil) + (push new-pattern helm-find-files--level-tree) + (setq helm-ff--show-thumbnails + (member new-pattern helm-ff--thumbnailed-directories)) + (helm-set-pattern new-pattern helm-suspend-update-flag) + (with-helm-after-update-hook (helm-ff-retrieve-last-expanded))))))) +(put 'helm-find-files-up-one-level 'helm-only t) + +(defun helm-find-files-down-last-level () + "Retrieve previous paths reached by `C-l' in helm-find-files." + (interactive) + (with-helm-alive-p + (when (and (helm-file-completion-source-p) + (not (helm-ff--invalid-tramp-name-p))) + (unless helm-find-files--level-tree-iterator + (setq helm-find-files--level-tree-iterator + (helm-iter-list (cdr helm-find-files--level-tree)))) + (setq helm-find-files--level-tree nil) + (helm-aif (helm-iter-next helm-find-files--level-tree-iterator) + (progn + (setq helm-ff--show-thumbnails + (member it helm-ff--thumbnailed-directories)) + (helm-set-pattern it)) + (setq helm-find-files--level-tree-iterator nil))))) +(put 'helm-find-files-down-last-level 'helm-only t) + +(defun helm-find-files--reset-level-tree () + (setq helm-find-files--level-tree-iterator nil + helm-find-files--level-tree nil)) + +(add-hook 'helm-cleanup-hook 'helm-find-files--reset-level-tree) +(add-hook 'post-self-insert-hook 'helm-find-files--reset-level-tree) +(add-hook 'helm-after-persistent-action-hook 'helm-find-files--reset-level-tree) + +(defun helm-ff-retrieve-last-expanded () + "Move overlay to last visited directory `helm-ff-last-expanded'. +This happen after using `helm-find-files-up-one-level', or +hitting C-j on \"..\"." + (when helm-ff-last-expanded + (let ((presel (if helm-ff-transformer-show-only-basename + (helm-basename + (directory-file-name helm-ff-last-expanded)) + (directory-file-name helm-ff-last-expanded)))) + (with-helm-window + (when (re-search-forward + (format helm-ff-last-expanded-candidate-regexp + (regexp-quote presel)) + nil t) + (forward-line 0) + (helm-mark-current-line))) + (setq helm-ff-last-expanded nil)))) + +(defun helm-ff-move-to-first-real-candidate () + "When candidate is an incomplete file name move to first real candidate." + (let* ((src (helm-get-current-source)) + (name (assoc-default 'name src)) + ;; Ensure `helm-file-completion-source-p' returns nil on + ;; `helm-read-file-name' history. + minibuffer-completing-file-name) + (helm-aif (and (helm-file-completion-source-p src) + (not (helm-empty-source-p)) + ;; Prevent dired commands moving to first real + ;; (Bug#910). + (or (memq (intern-soft name) + helm-ff-goto-first-real-dired-exceptions) + (not (string-match "\\`[Dd]ired-" name))) + helm-ff--move-to-first-real-candidate + (helm-get-selection nil nil src)) + (unless (or (not (stringp it)) + (and (string-match helm-tramp-file-name-regexp it) + (not (file-remote-p it nil t))) + (string-match helm-ff-tramp-method-regexp it) + (file-exists-p it)) + (helm-next-line))))) + +(defun helm-ff-undo () + "Undo minibuffer in `helm-find-files'. +Ensure disabling `helm-ff-auto-update-flag' before undoing." + (interactive) + (let ((old--flag helm-ff-auto-update-flag)) + (setq helm-ff-auto-update-flag nil) + (setq helm-ff--auto-update-state nil) + (unwind-protect + (progn + (undo) + (helm-check-minibuffer-input)) + (setq helm-ff-auto-update-flag old--flag) + (setq helm-ff--auto-update-state helm-ff-auto-update-flag)))) + +;;; Auto-update - helm-find-files auto expansion of directories. +;; +;; +(defun helm-ff-update-when-only-one-matched () + "Expand to directory when sole completion. +When only one candidate is remaining and it is a directory, +expand to this directory. +This happen only when `helm-ff-auto-update-flag' is non-nil or +when `helm-pattern' is equal to \"~/\"." + (let ((src (helm-get-current-source))) + (when (and (helm-file-completion-source-p src) + (not (get-buffer-window helm-action-buffer 'visible)) + (not (helm-ff--invalid-tramp-name-p)) + (not (string-match-p "\\`[.]\\{2\\}[^/]+" + (helm-basename helm-pattern)))) + (with-helm-buffer + (let* ((history-p (string= (assoc-default 'name src) + "Read File Name History")) + (pat (helm-ff-set-pattern helm-pattern)) + ;; Try to shut up persistent tramp error with adb method when + ;; adding tilde to path. + (tramp-tolerate-tilde (equal (file-remote-p pat 'method) + tramp-adb-method)) + (completed-p (helm-aand (expand-file-name + (substitute-in-file-name pat)) + (string= (file-name-as-directory it) + helm-ff-default-directory))) + (candnum (helm-get-candidate-number)) + (lt2-p (and (<= candnum 2) + (>= (string-width (helm-basename helm-pattern)) 2))) + (cur-cand (prog2 + (unless (or completed-p + (file-exists-p pat) + history-p (null lt2-p)) + ;; Only one non--existing candidate + ;; and one directory candidate, move to it, + ;; but not when renaming, copying etc..., + ;; so for this use + ;; `helm-ff-move-to-first-real-candidate' + ;; instead of `helm-next-line' (Bug#910). + (helm-ff-move-to-first-real-candidate)) + (helm-get-selection nil nil src))) + expand-to) + (when (and (or (and helm-ff-auto-update-flag + (null helm-ff--deleting-char-backward) + ;; Bug#295 + ;; File predicates are returning t + ;; with paths like //home/foo. + ;; So check it is not the case by regexp + ;; to allow user to do C-a / to start e.g + ;; entering a tramp method e.g /sudo::. + (not (string-match "\\`//" helm-pattern)) + (not (eq last-command 'helm-yank-text-at-point))) + ;; Fix Bug#542. + (string= helm-pattern "~/") + ;; Only one remaining directory, expand it. + (and (= candnum 1) + helm-ff--auto-update-state + (file-accessible-directory-p pat) + (null helm-ff--deleting-char-backward))) + (or + ;; Only one candidate remaining + ;; and at least 2 char in basename. + lt2-p + ;; Already completed. + completed-p) + (not history-p) ; Don't try to auto complete in history. + (stringp cur-cand) + (file-accessible-directory-p cur-cand)) + (if (and (not (helm-ff-dot-file-p cur-cand)) ; [1] + ;; Maybe we are here because completed-p is true + ;; but check this again to be sure. (Windows fix) + (<= candnum 2)) ; [2] + ;; If after going to next line the candidate + ;; is not one of "." or ".." [1] + ;; and only one candidate is remaining [2], + ;; assume candidate is a new directory to expand, and do it. + (progn + (setq expand-to (file-name-as-directory + (substring-no-properties cur-cand))) + (setq helm-ff--show-thumbnails + (member expand-to helm-ff--thumbnailed-directories)) + (helm-set-pattern expand-to) + ;; Reset flags to show all when changing dir. + (helm-ff-after-persistent-show-all)) + ;; The candidate is one of "." or ".." + ;; that mean we have entered the last letter of the directory name + ;; in prompt, so expansion is already done, just add the "/" at end + ;; of name unless helm-pattern ends with "." + ;; (i.e we are writing something starting with ".") + (unless (string-match "\\`.*[.]\\{1\\}\\'" helm-pattern) + ;; Need to expand-file-name to avoid e.g /ssh:host:./ in prompt. + (setq expand-to (expand-file-name (file-name-as-directory helm-pattern))) + (setq helm-ff--show-thumbnails + (member expand-to helm-ff--thumbnailed-directories)) + (helm-set-pattern expand-to))) + ;; When typing pattern in minibuffer, helm + ;; expand very fast to a directory matching pattern and + ;; don't let undo the time to set a boundary, the result + ;; is when e.g. going to root with "//" and undoing, undo + ;; doesn't undo to previous input. One fix for this is to + ;; advice `undo-auto--boundary-ensure-timer' so that it is + ;; possible to modify its delay (use a value of 1s for + ;; helm), a second fix is to run directly here `undo-boundary' + ;; inside a timer. + (run-at-time helm-input-idle-delay nil #'undo-boundary) + (helm-check-minibuffer-input))))))) + +(cl-defun helm-ff-auto-expand-to-home-or-root (&optional (pattern helm-pattern spattern)) + "Allow expanding to $HOME or \"/\" or text yanked after pattern. + +Argument PATTERN default to `helm-pattern' and should _not_ be used for +other purpose than debugging the second cond clause of this function. +When PATTERN is specified, specific helm functions are not called to +avoid errors when called outside helm for debugging purpose." + (when (or spattern + (and (helm-file-completion-source-p) + (with-current-buffer (window-buffer (minibuffer-window)) (eolp)) + (not (string-match helm-ff-url-regexp pattern)))) + (cond ((and (not (file-remote-p pattern)) + (null (file-exists-p pattern)) + (string-match-p + "\\`\\([.]\\)\\{2\\}[^/]+" + (helm-basename pattern)) + (string-match-p "/\\'" pattern) + (null spattern)) + (helm-ff-recursive-dirs pattern) + (helm-ff--maybe-set-pattern-and-update)) + ((string-match + "\\(?:\\`~/\\)\\|/?\\$.*/\\|/\\./\\|/\\.\\./\\|/~.*/\\|//\\|\\(/[[:alpha:]]:/\\)" + pattern) + (let* ((match (match-string 0 pattern)) + (input (cond ((string= match "/./") + (expand-file-name default-directory)) + ((string= pattern "/../") "/") + ((string-match-p "\\`/\\$" match) + (let ((sub (substitute-in-file-name match))) + (if (file-directory-p sub) + sub (replace-regexp-in-string "/\\'" "" sub)))) + (t (helm-ff--expand-substitued-pattern pattern))))) + ;; `file-directory-p' returns t on "/home/me/." (Bug#1844). + (if (and (file-directory-p input) + (not (string-match-p "[^.]\\.\\'" input))) + (progn + (setq helm-ff-default-directory + (setq input (file-name-as-directory input))) + ;; When changing directory ensure to show all. + (helm-ff-after-persistent-show-all)) + (setq helm-ff-default-directory (file-name-as-directory + (file-name-directory input)))) + (if spattern input (helm-ff--maybe-set-pattern-and-update input)))) + ((and (string-match "\\`/\\(-\\):.*" pattern) (null spattern)) + (helm-ff--maybe-set-pattern-and-update + (replace-match tramp-default-method t t pattern 1)))))) + +(defun helm-ff--maybe-set-pattern-and-update (&optional str) + (with-helm-window + (when str (helm-set-pattern str)) + (helm-check-minibuffer-input))) + +(defun helm-ff--expand-file-name-no-dot (name &optional directory) + "Prevent expanding \"/home/user/.\" to \"/home/user\"." + ;; Bug#1844 - If user enter "~/." to type an hidden filename + ;; don't expand to /home/him e.g. + ;; (expand-file-name "~/.") =>"/home/thierry" + ;; (helm-ff--expand-substitued-pattern "~/.") =>"/home/thierry/." + (concat (expand-file-name name directory) + (and (string-match "[^.]\\.\\'" name) "/."))) + +(defun helm-ff--expand-substitued-pattern (pattern) + ;; [Windows] On UNC paths "/" expand to current machine, + ;; so use the root of current Drive. (i.e "C:/") + (let* ((directory (and (memq system-type '(windows-nt ms-dos)) + (getenv "SystemDrive"))) + (subst (helm-substitute-in-filename pattern)) + ;; On Windows use a simple call to `expand-file-name' to + ;; avoid Bug#2004. + (expand-fn (if directory + #'expand-file-name + #'helm-ff--expand-file-name-no-dot))) + ;; Fix Bug#2223 with tilde in directory names e.g. "~/tmp/~test/". + (funcall expand-fn (if (string-match-p "\\`~[^/]" subst) + pattern subst) + ;; directory is nil on Nix. + directory))) + +(defun helm-substitute-in-filename (fname) + "Substitute all parts of FNAME from start up to \"~/\" or \"/\". +On windows system substitute from start up to \"/[[:lower:]]:/\". +This function is needed for `helm-ff-auto-expand-to-home-or-root' +and should be used carefully elsewhere, or not at all, using +`substitute-in-file-name' instead." + (cond ((and helm--url-regexp + (string-match-p helm--url-regexp fname)) + fname) + ((and (file-remote-p fname) + helm-substitute-in-filename-stay-on-remote) + (let ((sub (substitute-in-file-name fname))) + (if (file-directory-p sub) + sub (replace-regexp-in-string "/\\'" "" sub)))) + (t + (with-temp-buffer + (insert fname) + (goto-char (point-min)) + (when (memq system-type '(windows-nt ms-dos)) + (skip-chars-forward "/")) ;; Avoid infloop in UNC paths Bug#424 + (if (re-search-forward "~.*/?\\|//\\|/[[:alpha:]]:/" nil t) + (let ((match (match-string 0))) + (goto-char (if (or (string= match "//") + (string-match-p "/[[:alpha:]]:/" match)) + (1+ (match-beginning 0)) + (match-beginning 0))) + (buffer-substring-no-properties (point) (point-at-eol))) + fname))))) + +(defun helm-point-file-in-dired (file) + "Put point on filename FILE in dired buffer." + (unless (and helm--url-regexp + (string-match-p helm--url-regexp file)) + (let ((target (expand-file-name (helm-substitute-in-filename file)))) + (dired (file-name-directory target)) + (dired-goto-file target)))) + +(defun helm-marked-files-in-dired (_candidate) + "Open a dired buffer with only marked files. + +With a prefix arg toggle dired buffer to wdired mode. + +Note: This function works only in Emacs-29+ because Wdired doesn't support +editing absolute fnames in previous Emacs versions." + (let* ((marked (helm-marked-candidates :with-wildcard t)) + (current (car marked))) + (unless (and helm--url-regexp + (string-match-p helm--url-regexp current)) + (let ((target (expand-file-name (helm-substitute-in-filename current)))) + (dired (cons helm-ff-default-directory marked)) + (dired-goto-file target) + (when (or helm-current-prefix-arg current-prefix-arg) + (call-interactively 'wdired-change-to-wdired-mode)))))) + +(defun helm-ff-wfnames (_candidate) + "Edit marked fnames with `Wfnames' package." + (cl-assert (require 'wfnames nil t) nil "Wfnames package not found") + (let ((marked (helm-marked-candidates :with-wildcard t))) + (wfnames-setup-buffer marked))) + +(defun helm-ff-edit-marked-files (candidate) + "Edit marked files with `helm-ff-edit-marked-files-fn' fn." + (funcall helm-ff-edit-marked-files-fn candidate)) + +(helm-make-command-from-action helm-ff-run-edit-marked-files + "Execute `helm-ff-edit-marked-files' interactively." + 'helm-ff-edit-marked-files) + +(defun helm-ff--create-tramp-name (fname) + "Build filename from `helm-pattern' like /su:: or /sudo::." + ;; `tramp-make-tramp-file-name' takes 7 args on emacs-26 whereas it + ;; takes only 5 args in emacs-24/25. + (apply #'tramp-make-tramp-file-name + ;; `tramp-dissect-file-name' returns a list in emacs-26 + ;; whereas in 24.5 it returns a vector, thus the car is a + ;; symbol (`tramp-file-name') which is not needed as argument + ;; for `tramp-make-tramp-file-name' so transform the cdr in + ;; vector, and for 24.5 use directly the returned value. + (cl-loop with v = (helm-ff--tramp-cons-or-vector + (tramp-dissect-file-name fname)) + for i across v collect i))) + +(defun helm-ff--tramp-cons-or-vector (vector-or-cons) + "Return VECTOR-OR-CONS as a vector." + (pcase vector-or-cons + (`(,_l . ,ll) (vconcat ll)) + ((and vec (pred vectorp)) vec))) + +(defun helm-ff--get-tramp-methods () + "Return a list of the car of `tramp-methods'." + (or helm-ff--tramp-methods + (setq helm-ff--tramp-methods (mapcar 'car tramp-methods)))) + +(defun helm-ff--previous-mh-tramp-method (str) + (save-match-data + (with-temp-buffer + (insert str) + (when (re-search-backward + (concat "\\([|]\\)\\(" + (mapconcat 'identity (helm-ff--get-tramp-methods) "\\|") + "\\):") + nil t) + (list + (buffer-substring-no-properties (point-at-bol) (match-beginning 2)) + (buffer-substring-no-properties (match-beginning 2) (match-end 2))))))) + +(defun helm-ff--get-host-from-tramp-invalid-fname (fname) + "Extract hostname from an incomplete tramp file name. +Return nil on valid file name remote or not." + ;; Check first if whole file is remote (file-remote-p is inefficient + ;; in this case) otherwise we are matching e.g. /home/you/ssh:foo/ + ;; which is not a remote name. + ;; FIXME this will not work with a directory or a file named like + ;; "ssh:foo" and located at root (/) but it seems there is no real + ;; solution apart disabling tramp-mode when a file/dir located at / + ;; is matching helm-tramp-file-name-regexp; This would prevent usage + ;; of tramp if one have such a directory at / (who would want to + ;; have such a dir at / ???) See emacs-bug#31489. + (when (string-match-p helm-tramp-file-name-regexp fname) + (let* ((bn (helm-basename fname)) + (bd (replace-regexp-in-string (regexp-quote bn) "" fname)) + (split (split-string bn ":" t)) + (meth (car (member (car split) + (helm-ff--get-tramp-methods))))) + (and meth (string= bd "/") (car (last split)))))) + +(cl-defun helm-ff--tramp-hostnames (&optional (pattern helm-pattern)) + "Get a list of hosts for tramp method found in `helm-pattern'. +Argument PATTERN default to `helm-pattern'. It is here only for +debugging purpose." + (when (string-match helm-tramp-file-name-regexp pattern) + (let* ((mh-method (helm-ff--previous-mh-tramp-method pattern)) + (method (or (cadr mh-method) (match-string 1 pattern)))) + (cl-loop with all-methods = (helm-ff--get-tramp-methods) + for (f . h) in (tramp-get-completion-function method) + append (cl-loop for e in (funcall f (car h)) + for host = (and (consp e) (cadr e)) + ;; On emacs-27 host may be + ;; ("root" t) in sudo method. + when (and (stringp host) + (not (member host all-methods))) + collect (helm-ff-filter-candidate-one-by-one + (concat (or (car mh-method) "/") + method ":" host))) + into comps + finally return + (helm-fast-remove-dups comps :test 'equal))))) + +(defun helm-ff-before-action-hook-fn () + "Exit Helm when user try to execute action on an invalid tramp fname." + (let* ((src (helm-get-current-source)) + (cand (helm-get-selection nil nil src))) + (when (and (helm-file-completion-source-p src) + (stringp cand) + (helm-ff--invalid-tramp-name-p cand) ; Check candidate. + (helm-ff--invalid-tramp-name-p)) ; check helm-pattern. + (error "Error: Unknown file or directory `%s'" cand)))) +(add-hook 'helm-before-action-hook 'helm-ff-before-action-hook-fn) + +(cl-defun helm-ff--invalid-tramp-name-p (&optional (pattern helm-pattern)) + "Return non-nil when PATTERN is an invalid tramp filename." + (or (string= (helm-ff-set-pattern pattern) + "@@TRAMP@@") + ;; Tramp methods completion. + (string-match helm-ff-tramp-method-regexp pattern))) + +(defun helm-ff--tramp-postfixed-p (str) + "Return non nil when tramp path STR is complete." + ;; E.g.: + ;; (helm-ff--tramp-postfixed-p "/ssh:foo") + ;; => nil + ;; (helm-ff--tramp-postfixed-p "/ssh:foo:") + ;; => 10 + ;; (helm-ff--tramp-postfixed-p "/ssh:foo|sudo:") + ;; => nil + ;; (helm-ff--tramp-postfixed-p "/ssh:foo|sudo::") + ;; => 16 + (let ((methods (helm-ff--get-tramp-methods)) + result) + (save-match-data + (with-temp-buffer + (save-excursion (insert str)) + (helm-awhile (search-forward ":" nil t) + (if (save-excursion + (forward-char -1) + (or (looking-back "[/|]" (1- (point))) + (looking-back + (mapconcat (lambda (m) (format "[/|]%s" m)) methods "\\|") + (point-at-bol)))) + (setq result nil) + (setq result it))))) + result)) + +(defun helm-ff--tramp-multihops-p (name) + (cl-loop for m in (helm-ff--get-tramp-methods) + thereis (string-match (format "\\`\\(/%s:.*[|]\\).*" m) name))) + +(defun helm-ff-complete-tramp-methods () + "Completion on tramp methods in a nested helm session." + (interactive) + (with-helm-alive-p + (let* (initial-input + (str helm-pattern) + (pattern (with-temp-buffer + (insert str) + (let ((end (point)) beg) + (when (re-search-backward "[/|]" nil t) + (setq beg (1+ (point))) + (unless (= beg end) + (setq initial-input + (buffer-substring beg end)) + (delete-region beg end)) + (buffer-string))))) + (collection (helm-ff--get-tramp-methods)) + (method (helm-comp-read + "Tramp methods: " + (sort collection #'string<) + :initial-input initial-input + :fc-transformer + (lambda (candidates _source) + (cl-loop for c in candidates + collect (propertize c 'face 'helm-ff-file))) + :allow-nest t + :must-match t))) + (helm-set-pattern (concat pattern method ":"))))) +(put 'helm-ff-complete-tramp-methods 'no-helm-mx t) + +(defun helm-ff-set-pattern (pattern) + "Handle tramp filenames in `helm-pattern'." + (let* ((methods (helm-ff--get-tramp-methods)) + ;; Returns the position of last ":" entered. + (postfixed (helm-ff--tramp-postfixed-p pattern)) + (reg "\\`/\\([^[/:]+\\|[^/]+]\\):.*:") + cur-method tramp-name) + (when (string-match "\\`/\\(-\\):" pattern) + (setq pattern (replace-match tramp-default-method t t pattern 1))) + ;; In some rare cases tramp can return a nil input, + ;; so be sure pattern is a string for safety (Bug#476). + (unless pattern (setq pattern "")) + (cond ((string-match helm-ff-url-regexp pattern) pattern) + ((string-match "\\`\\$" pattern) + (substitute-in-file-name pattern)) + ((string= pattern "") "") + ((string-match "\\`[.]\\{1,2\\}/\\'" pattern) + (expand-file-name pattern)) + ;; Directories ending by a dot (Bug#1940) + ((string-match "[^/][.]/\\'" pattern) + (expand-file-name pattern)) + ((string-match ".*\\(~?/?[.]\\{1\\}/\\)\\'" pattern) + (expand-file-name default-directory)) + ((string-match ".*\\(~//\\|//\\)\\'" pattern) + (expand-file-name "/")) ; Expand to "/" or "c:/" + ((string-match "\\`\\(~/\\|.*/~/\\)\\'" pattern) + (expand-file-name "~/")) + ((string-match "\\`~/" pattern) + (expand-file-name pattern)) + ((string-match helm-ff-tramp-method-regexp pattern) + pattern) + ;; Match "/method:maybe_hostname:~" + ((and (string-match (concat reg "~") pattern) + postfixed + (setq cur-method (match-string 1 pattern)) + (member cur-method methods)) + (setq tramp-name (expand-file-name + (helm-ff--create-tramp-name + (match-string 0 pattern)))) + (replace-match tramp-name nil t pattern)) + ;; Match "/method:maybe_hostname:" + ((and (string-match reg pattern) + postfixed + (setq cur-method (match-string 1 pattern)) + (member cur-method methods)) + (setq tramp-name (helm-ff--create-tramp-name + (match-string 0 pattern))) + (replace-match tramp-name nil t pattern)) + ;; Match "/hostname:" + ((and (string-match helm-tramp-file-name-regexp pattern) + postfixed + (setq cur-method (match-string 1 pattern)) + (and cur-method (not (member cur-method methods)))) + (setq tramp-name (helm-ff--create-tramp-name + (match-string 0 pattern))) + (replace-match tramp-name nil t pattern)) + ;; Match "/method:" in this case don't try to connect. + ((and (null postfixed) + (string-match helm-tramp-file-name-regexp pattern) + (member (match-string 1 pattern) methods)) + ;; A flag to notify tramp name is incomplete. + "@@TRAMP@@") + ;; Return PATTERN unchanged. + (t pattern)))) + +(defun helm-find-files-get-candidates (&optional require-match) + "Create candidate list for `helm-source-find-files'." + (let* ((path (helm-ff-set-pattern helm-pattern)) + (dir-p (file-accessible-directory-p path)) + basedir + invalid-basedir + non-essential + (tramp-verbose helm-tramp-verbose)) ; No tramp message when 0. + ;; Tramp check if path is valid without waiting a valid + ;; connection and may send a file-error. + (setq helm--ignore-errors (file-remote-p path)) + (set-text-properties 0 (length path) nil path) + ;; Bug#118 allow creation of newdir+newfile. + (unless (or + ;; A tramp file name not completed. + (string= path "@@TRAMP@@") + ;; An empty pattern + (string= path "") + (and (string-match-p ":\\'" path) + (helm-ff--tramp-postfixed-p path)) + ;; Check if base directory of PATH is valid. + (helm-aif (file-name-directory path) + ;; If PATH is a valid directory IT=PATH, + ;; else IT=basedir of PATH. + (file-directory-p it))) + ;; BASEDIR is invalid, that's mean user is starting + ;; to write a non--existing path in minibuffer + ;; probably to create a 'new_dir' or a 'new_dir+new_file'. + (setq invalid-basedir t)) + ;; Don't set now `helm-pattern' if `path' == "@@TRAMP@@" + ;; like that the actual value (e.g /ssh:) is passed to + ;; `helm-ff--tramp-hostnames'. + (unless (or (string= path "@@TRAMP@@") + invalid-basedir) ; Leave helm-pattern unchanged. + (setq helm-ff-auto-update-flag ; [1] + ;; Unless auto update is disabled start auto updating only + ;; at third char. + (unless (or (null helm-ff--auto-update-state) + ;; But don't enable auto update when + ;; deleting backward. + helm-ff--deleting-char-backward + (and dir-p (not (string-match-p "/\\'" path)))) + (or (>= (length (helm-basename path)) 3) dir-p))) + ;; At this point the tramp connection is triggered. + (helm-log + "helm-find-files-get-candidates" + "Pattern=%S" + (setq helm-pattern (if (string-match helm-ff-tramp-method-regexp path) + ;; A tramp method, don't modify pattern. + helm-pattern + (helm-ff--transform-pattern-for-completion path)))) + ;; This have to be set after [1] to allow deleting char backward. + (setq basedir (or (helm-aand + (if (and dir-p helm-ff-auto-update-flag) + ;; Add the final "/" to path + ;; when `helm-ff-auto-update-flag' is enabled. + (file-name-as-directory path) + (if (string= path "") + "/" (file-name-directory path))) + (expand-file-name it)) + default-directory)) + (setq helm-ff-default-directory + (if (string= helm-pattern "") + (expand-file-name "/") ; Expand to "/" or "c:/" + ;; If path is an url *default-directory have to be nil. + (unless (or (string-match helm-ff-url-regexp path) + (and helm--url-regexp + (string-match helm--url-regexp path))) + basedir)))) + (when (and (string-match ":\\'" path) + (file-remote-p basedir nil t)) + (setq helm-pattern basedir)) + (cond ((string-match helm-ff-tramp-method-regexp path) ; Tramp methods + (mapcar (lambda (method) + (helm-ff-filter-candidate-one-by-one + (concat "/" ":" method))) + (helm-ff--get-tramp-methods))) + ((string= path "@@TRAMP@@") + (helm-ff--tramp-hostnames)) ; Hostnames completion. + ((or (and (file-regular-p path) + (eq last-repeatable-command 'helm-execute-persistent-action)) + ;; `ffap-url-regexp' don't match until url is complete. + (string-match helm-ff-url-regexp path) + invalid-basedir + (and (not (file-exists-p path)) (string-match "/$" path)) + (and helm--url-regexp (string-match helm--url-regexp path))) + ;; Do NOT filter boring files here (Bug#2330). + (list (helm-ff-filter-candidate-one-by-one path nil t))) + ((string= path "") (helm-ff-directory-files "/")) + ;; Check here if directory is accessible (not working on Windows). + ((and (file-directory-p path) (not (file-readable-p path))) + ;; Prefix error message with @@@@ for safety + ;; (some files may match file-error See bug#2400) + (list (cons (format "@@@@file-error: Opening directory permission denied `%s'" path) + path))) + ;; A fast expansion of PATH is made only if `helm-ff-auto-update-flag' + ;; is enabled. + ((and dir-p helm-ff-auto-update-flag) + (helm-ff-directory-files path)) + (t (append (unless (or (eq require-match t) + ;; Check here if path is an existing + ;; file before adding it to + ;; candidates, it was previously done + ;; in the sort function but this + ;; create a bug with remote files + ;; when path is at the same time a + ;; pattern matching a candidate and a + ;; real candidate e.g. ack and + ;; ack-grep in /usr/bin. This is due + ;; presumably to a latency more + ;; important with remote files which + ;; lead to a confusion with the + ;; pattern matching one candidate and + ;; the real candidate which is same + ;; as pattern. + (file-exists-p path) + ;; When `helm-ff-auto-update-flag' has been + ;; disabled, whe don't want PATH to be added on top + ;; if it is a directory. + dir-p) + ;; Do NOT filter boring files here (Bug#2330). + (list (helm-ff-filter-candidate-one-by-one path nil t))) + (helm-ff-directory-files basedir)))))) + +(defun helm-list-directory (directory &optional sel) + "List directory DIRECTORY. + +If DIRECTORY is remote use `helm-list-directory-function', +otherwise use `directory-files'. +SEL argument is only here for debugging purpose, it default to +`helm-get-selection'." + (let* ((remote (file-remote-p directory 'method)) + (helm-list-directory-function + (cond ((and remote (string= remote "ftp")) + #'helm-list-dir-lisp) + ((and remote (string= remote "adb")) + #'helm-list-dir-adb) + (t helm-list-directory-function))) + (remote-fn-p (eq helm-list-directory-function + 'helm-list-dir-external)) + (sort-method (cl-case helm-ff-initial-sort-method + (newest (if (and remote remote-fn-p) + "-t" #'file-newer-than-file-p)) + (size (if (and remote remote-fn-p) + "-S" #'helm-ff-file-larger-that-file-p)) + (ext (unless (and remote remote-fn-p) + #'helm-group-candidates-by)) + (t nil)))) + (cond (remote + (ignore-errors + (funcall helm-list-directory-function directory sort-method))) + ((memq helm-ff-initial-sort-method '(newest size)) + (sort (directory-files + directory t directory-files-no-dot-files-regexp) + sort-method)) + ((eq helm-ff-initial-sort-method 'ext) + (funcall sort-method + (directory-files + directory t directory-files-no-dot-files-regexp) + #'file-name-extension + (or sel (helm-get-selection) ""))) + (t (directory-files + directory t directory-files-no-dot-files-regexp))))) + +(defsubst helm-ff-file-larger-that-file-p (f1 f2) + (let ((attr1 (file-attributes f1)) + (attr2 (file-attributes f2))) + (> (nth 7 attr1) (nth 7 attr2)))) + +(defun helm-list-dir-lisp (directory &optional sort-method) + "List DIRECTORY with `file-name-all-completions' as backend. + +Add a `helm-ff-dir' property on each fname ending with \"/\"." + ;; NOTE: `file-name-all-completions' and `directory-files' and most + ;; tramp file handlers don't handle cntrl characters in fnames, so + ;; the displayed files will be plain wrong in this case, even worst + ;; the filenames will be splitted in two or more filenames. + (cl-loop for f in (sort (file-name-all-completions "" directory) + (or sort-method 'string-lessp)) + unless (or (string= f "") + (member f '("./" "../" "." ".."))) + if (and (helm--dir-name-p f) + (helm--dir-file-name f directory)) + collect (propertize it 'helm-ff-dir t) + else collect (propertize (expand-file-name f directory) + 'helm-ff-file t))) + +(defun helm-file-name-all-completions-internal (directory) + (let ((switches "-1F")) + (with-temp-buffer + (insert-directory (format "%s*" + (file-name-as-directory directory)) + switches t) + (split-string + (buffer-substring-no-properties (point-min) (point-max)) + "\n" t)))) + +(defun helm-list-dir-adb (directory &optional sort-method) + "List DIRECTORY with `helm-file-name-all-completions-internal' as backend. + +This is used for tramp adb backend. + +Add a `helm-ff-dir' property on each fname ending with \"/\"." + (cl-loop with files = (helm-file-name-all-completions-internal directory) + for f in (sort files (or sort-method 'string-lessp)) + for split = (split-string f "->" t) + for fname = (replace-regexp-in-string " $" "" (car split)) + for truename = (cadr split) + collect (cond ((string-match "/\\'" fname) + (propertize (helm--dir-file-name fname directory) + 'helm-ff-dir t)) + (truename + (propertize (expand-file-name + (substring fname 0 (1- (length fname))) + directory) + 'helm-ff-sym truename)) + (t (propertize (expand-file-name fname directory) + 'helm-ff-file t))))) + +(defun helm-list-dir-external (dir &optional sort-method) + "List directory DIR with external shell command as backend. + +This function is fast enough to be used for remote files and save +the type of files at the same time in a property for using it +later in the transformer." + (let ((default-directory (file-name-as-directory + (expand-file-name dir)))) + (with-temp-buffer + (when (eq (process-file-shell-command + (format + ;; -A remove dot files, -F append [*=@|/>] at eof + ;; and -Q quote the real filename. If not using -Q, + ;; there is no way to distinguish if foo* is a real + ;; file or if it is foo the executable file so with + ;; -Q we have "foo"* for the executable file foo and + ;; "foo*" for the real file foo. The downside is + ;; that we need an extra step to remove the quotes + ;; at the end which impact performances. + "ls -A -1 -F -b -Q %s | awk -v dir=%s '{print dir $0}'" + (or sort-method "") + (shell-quote-argument default-directory)) + nil t nil) + 0) + (goto-char (point-min)) + (save-excursion + (while (re-search-forward "[*=@|/>]$" nil t) + ;; A line looks like /home/you/"foo"@ + (helm-acase (match-string 0) + ("*" (replace-match "") + (put-text-property + (point-at-bol) (point-at-eol) 'helm-ff-exe t)) + ("@" (replace-match "") + (put-text-property + (point-at-bol) (point-at-eol) 'helm-ff-sym t)) + ("/" (replace-match "") + (put-text-property + (point-at-bol) (point-at-eol) 'helm-ff-dir t)) + (("=" "|" ">") (replace-match ""))))) + (while (re-search-forward "[\"]" nil t) + (replace-match "")) + (add-text-properties (point-min) (point-max) '(helm-ff-file t)) + (split-string (buffer-string) "\n" t))))) + +;; This is to fix issue with file-notify.el no more following symlinks +;; on emacs-29 (regression) with inotify backend at least. Also it +;; seems inotify is not configured to follow symlinks on other systems +;; (MacOS) so this should fix as well this issue on such systems see +;; bug#2542. +;; Store here associations of (truename . symlink) when opening a +;; symlinked directory, then add the watch to the truename; When the +;; watcher ring on the truename remove the symlinked directory from cache. +(defvar helm-ff--list-directory-links nil) + +(defun helm-ff-directory-files (directory &optional force-update) + "List contents of DIRECTORY. +Argument FULL mean absolute path. +It is same as `directory-files' but always returns the dotted +filename \\='.' and \\='..' even on root directories in Windows +systems. +When FORCE-UPDATE is non nil recompute candidates even if DIRECTORY is +in cache." + (let* ((method (file-remote-p directory 'method)) + (dfn (directory-file-name directory)) + (truename (and (file-symlink-p dfn) (file-truename dfn)))) + (setq directory (file-name-as-directory + (expand-file-name directory))) + (when truename + (cl-pushnew (cons truename directory) + helm-ff--list-directory-links :test 'equal)) + (or (and (not force-update) + (gethash directory helm-ff--list-directory-cache)) + (let* (file-error + (ls (condition-case err + (helm-list-directory directory) + ;; Handle file-error from here for Windows + ;; because predicates like `file-readable-p' and friends + ;; seem broken on emacs for Windows systems (always returns t). + ;; This should never be called on GNU/Linux/Unix + ;; as the error is properly intercepted in + ;; `helm-find-files-get-candidates' by `file-readable-p'. + (file-error + (prog1 + ;; Prefix error message with @@@@ for safety + ;; (some files may match file-error See bug#2400) + (list (format "@@@@%s:%s" + (car err) + (mapconcat 'identity (cdr err) " "))) + (setq file-error t))))) + (dot (concat directory ".")) + (dot2 (concat directory "..")) + (candidates (append (and (not file-error) (list dot dot2)) ls)) + watcher) + (puthash directory (+ (length ls) 2) helm-ff--directory-files-length) + (prog1 + (puthash directory + (cl-loop for f in candidates + when (helm-ff-filter-candidate-one-by-one f) + collect it) + helm-ff--list-directory-cache) + ;; Put an inotify watcher to check directory modifications. + (unless (or (null helm-ff-use-notify) + (member method helm-ff-inotify-unsupported-methods) + (helm-aand (setq watcher (gethash + directory + helm-ff--file-notify-watchers)) + ;; [1] If watcher is invalid enter + ;; next and delete it. + (file-notify-valid-p it))) + (condition-case-unless-debug err + (let ((to-watch (or truename directory))) + (when watcher + ;; If watcher is still in cache and we are here, + ;; that's mean test [1] above fails and watcher + ;; is invalid, so delete it. + (file-notify-rm-watch watcher) + (remhash directory helm-ff--file-notify-watchers)) + ;; Keep adding DIRECTORY to + ;; helm-ff--file-notify-watchers but watch on the + ;; truename and not the symlink as before bug#2542. + (puthash directory + (file-notify-add-watch + to-watch + '(change attribute-change) + (helm-ff--inotify-make-callback to-watch)) + helm-ff--file-notify-watchers)) + (file-notify-error (user-error "Error: %S %S" (car err) (cdr err)))))))))) + +(defun helm-ff--inotify-make-callback (directory) + "Return a callback for `file-notify-add-watch'." + (lambda (event) + (let ((desc (cadr event)) + (target directory)) ; Either truename or directory. + (helm-log "Inotify callback" "Event %S called on %S" event directory) + ;; `attribute-changed' means permissions have changed, not + ;; file modifications like file changes, visit + ;; etc... AFAIU the desc for this is `changed' and for our + ;; use case we don't care of this. Elemnts of + ;; `helm-ff--list-directory-links' are of the form + ;; (truename . visited-symlink-directory) + (when (memq desc '(created deleted renamed attribute-changed)) + ;; Watched directory is the truename which is not in the + ;; cache, so remove its associated directory (the symlink) + ;; from the cache bug#2542. + (helm-aif (assoc directory helm-ff--list-directory-links) + (progn + (setq target (cdr it)) + (setq helm-ff--list-directory-links + (delete it helm-ff--list-directory-links)))) + ;; When TARGET is modified remove it from cache. + (helm-log "Inotify callback" + "Removing %S from `helm-ff--list-directory-cache'" target) + (remhash target helm-ff--list-directory-cache))))) + +(defun helm-ff-tramp-cleanup-hook (vec) + "Remove remote directories related to VEC in helm-ff* caches. +Remove as well all related file-notify watchers. + +This is meant to run in `tramp-cleanup-connection-hook'." + (cl-loop for key being the hash-keys in helm-ff--list-directory-cache + when (equal (file-remote-p key 'method) (cadr vec)) + do (remhash key helm-ff--list-directory-cache)) + (cl-loop for key being the hash-keys in helm-ff--file-notify-watchers + when (equal (file-remote-p key 'method) (cadr vec)) + do (progn + (file-notify-rm-watch + (gethash key helm-ff--file-notify-watchers)) + (remhash key helm-ff--file-notify-watchers)))) +(add-hook 'tramp-cleanup-connection-hook #'helm-ff-tramp-cleanup-hook) + +(defun helm-ff-handle-backslash (fname) + ;; Allow creation of filenames containing a backslash. + (cl-loop with bad = '((92 . "")) + for i across fname + if (assq i bad) concat (cdr it) + else concat (string i))) + +(defun helm-ff-fuzzy-matching-p () + (and helm-ff-fuzzy-matching + (not (memq helm-mm-matching-method '(multi1 multi3p))))) + +(defun helm-ff--transform-pattern-for-completion (pattern) + "Maybe return PATTERN with it's basename modified as a regexp. +This happens only when `helm-ff-fuzzy-matching' is enabled. +This provides a similar behavior as `ido-enable-flex-matching'. +See also `helm--mapconcat-pattern'. +If PATTERN is an url return it unmodified. +When PATTERN contains a space fallback to multi-match. +If basename contains one or more space fallback to multi-match. +If PATTERN is a valid directory name, return PATTERN unchanged." + ;; handle bad filenames containing a backslash (no more needed in + ;; emacs-26, also prevent regexp matching with e.g. "\|"). + ;; (setq pattern (helm-ff-handle-backslash pattern)) + (let ((bn (helm-basename pattern)) + (bd (or (helm-basedir pattern) "")) + ;; Trigger tramp connection with file-directory-p. + (dir-p (file-directory-p pattern)) + (tramp-p (cl-loop for (m . f) in tramp-methods + thereis (string-match m pattern)))) + ;; Always regexp-quote base directory name to handle + ;; crap dirnames such e.g bookmark+ + (cond + ((or (and dir-p tramp-p (string-match ":\\'" pattern)) + (string= pattern "") + (and dir-p (<= (length bn) 2)) + ;; Fix Bug#541 when BD have a subdir similar + ;; to BN, don't switch to match plugin + ;; which will match both. + (and dir-p (string-match (regexp-quote bn) bd))) + ;; Use full PATTERN on e.g "/ssh:host:". + (regexp-quote pattern)) + ;; Prefixing BN with a space call multi-match completion. + ;; This allow showing all files/dirs matching BN (Bug#518). + ;; FIXME: some multi-match methods may not work here. + (dir-p (concat (regexp-quote bd) " " (regexp-quote bn))) + ((or (not (helm-ff-fuzzy-matching-p)) + (string-match "[ !]" bn)) ; Fall back to multi-match. + (concat (regexp-quote bd) " " bn)) + ((or (string-match "[*][.]?.*" bn) ; Allow entering wildcard. + (string-match "/\\'" pattern) ; Allow mkdir. + (string-match helm-ff-url-regexp pattern) + (and (string= helm-ff-default-directory "/") tramp-p)) + ;; Don't treat wildcards ("*") as regexp char. + ;; (e.g ./foo/*.el => ./foo/\\*\\.el) or ./foo/*.[ch] => + ;; ./foo/\\*\\.\\[ch] + (concat (regexp-quote bd) + ;; We were previously using + ;; (replace-regexp-in-string "[*]" "[*]" bn) but this + ;; doesn't handle wilcards like *.[ch], so regexp-quote + ;; bn as well. + (regexp-quote bn))) + (t (concat (regexp-quote bd) + (if (>= (length bn) 2) ; wait 2nd char before concating. + (helm--mapconcat-pattern bn) + (concat ".*" (regexp-quote bn)))))))) + +(defalias 'helm-dir-is-dot 'helm-ff-dot-file-p) +(make-obsolete 'helm-dir-is-dot 'helm-ff-dot-file-p "3.8.8") + +(defun helm-ff-save-history () + "Store the last value of `helm-ff-default-directory' in `helm-ff-history'. +Note that only existing directories are saved here." + (when (and helm-ff-default-directory + (helm-file-completion-source-p) + (file-directory-p helm-ff-default-directory)) + (set-text-properties 0 (length helm-ff-default-directory) + nil helm-ff-default-directory) + (push helm-ff-default-directory helm-ff-history))) +(add-hook 'helm-cleanup-hook 'helm-ff-save-history) + +(defun helm-ff-valid-symlink-p (file &optional link) + "Returns the truename of FILE if it exists. +If we already know the truename of FILE we can pass it with LINK arg +to avoid an unnecessary call to `file-truename'." + (helm-aif (condition-case-unless-debug nil + ;; `file-truename' send error + ;; on cyclic symlinks (Bug#692). + (or link (file-truename file)) + (error nil)) + (and (file-exists-p it) it))) + +(defun helm-get-default-mode-for-file (filename) + "Return the default mode to open FILENAME." + (let ((mode (cl-loop for (r . m) in auto-mode-alist + thereis (and (string-match r filename) m)))) + (or (and (symbolp mode) mode) "Fundamental"))) + +(defun helm-ff-properties (candidate) + "Show file properties of CANDIDATE in a tooltip or message." + (require 'helm-external) ; For `helm-get-default-program-for-file'. + (helm-aif (helm-file-attributes candidate) + (let* ((dired-line (helm-file-attributes-dired-line it t)) + (type (cl-getf it :type)) + (mode-type (cl-getf it :mode-type)) + (owner (cl-getf it :uid)) + (owner-right (cl-getf it :user t)) + (group (cl-getf it :gid)) + (group-right (cl-getf it :group)) + (other-right (cl-getf it :other)) + (octal (cl-getf it :octal)) + (trash (and (helm-ff-trash-file-p candidate) + (helm-ff--get-dest-file-from-trash + (helm-ff-trash-list) + (replace-regexp-in-string + "\\.trashinfo\\'" "" candidate)))) + (size (helm-file-human-size (cl-getf it :size))) + (modif (cl-getf it :modif-time)) + (access (cl-getf it :access-time)) + (ext (helm-get-default-program-for-file candidate)) + (tooltip-hide-delay (or helm-tooltip-hide-delay tooltip-hide-delay))) + (if (and (display-graphic-p) tooltip-mode) + (tooltip-show + (concat + (helm-basename candidate) "\n" + dired-line "\n" + (format "Mode: %s\n" (helm-get-default-mode-for-file candidate)) + (format "Ext prog: %s\n" (or (and ext (replace-regexp-in-string + " %s" "" ext)) + "Not defined")) + (format "Type: %s: %s\n" type mode-type) + (when (string= type "symlink") + (format "True name: '%s'\n" + (cond ((string-match "^\\.#" (helm-basename candidate)) + "Autosave symlink") + ((helm-ff-valid-symlink-p candidate)) + (t "Invalid Symlink")))) + (format "Owner: %s: %s\n" owner owner-right) + (format "Group: %s: %s\n" group group-right) + (format "Others: %s\n" other-right) + (format "NumMode: %s\n" octal) + (format "Size: %s\n" size) + (when (string= type "directory") + (format "Size used in directory: %s\n" + (helm-directory-size + candidate current-prefix-arg t))) + (format "Modified: %s\n" modif) + (format "Accessed: %s\n" access) + (and (stringp trash) + (format "Trash: %s\n" + (abbreviate-file-name trash))))) + (message dired-line) (sit-for 5))) + (message "Permission denied, file not readable"))) + +(helm-make-persistent-command-from-action helm-ff-properties-persistent + "Show properties without quitting helm." + 'properties-action 'helm-ff-properties) + +(helm-make-persistent-command-from-action helm-ff-persistent-delete + "Delete current candidate without quitting." + 'quick-delete 'helm-ff-quick-delete) + +(defun helm-ff-kill-default-directory (_candidate) + (with-helm-window + (kill-new helm-ff-default-directory) + (message "`%s' copied to kill-ring" helm-ff-default-directory))) + +(helm-make-persistent-command-from-action helm-ff-run-kill-default-directory + "Kill `helm-ff-default-directory'." + 'kill-default-directory + 'helm-ff-kill-default-directory) + +(defun helm-ff-dot-file-p (file) + "Check if FILE is `.' or `..'." + (member (helm-basename file) '("." ".."))) + +(defun helm-ff-kill-buffer-fname (candidate) + (let* ((buf (get-file-buffer candidate)) + (buf-name (buffer-name buf))) + (cond ((and buf (eq buf (get-buffer helm-current-buffer))) + (user-error + "Can't kill `helm-current-buffer' without quitting session")) + (buf (kill-buffer buf) (message "Buffer `%s' killed" buf-name)) + (t (message "No buffer to kill"))))) + +(defun helm-ff-kill-or-find-buffer-fname (candidate) + "Find file CANDIDATE or kill its buffer if it is visible. +Never kill `helm-current-buffer'. +Never kill buffer modified. +This is called normally on third hit of \ +\\\\[helm-execute-persistent-action] +in `helm-find-files-persistent-action-if'." + (let* ((buf (get-file-buffer candidate)) + (buf-name (buffer-name buf)) + (win (get-buffer-window buf)) + (helm--reading-passwd-or-string t)) + (cond ((and buf win (eql buf (get-buffer helm-current-buffer))) + (user-error + "Can't kill `helm-current-buffer' without quitting session")) + ((and buf win (buffer-modified-p buf)) + (message "Can't kill modified buffer, please save it before")) + ((and buf win) + (kill-buffer buf) + (if (and helm-persistent-action-display-window + (window-dedicated-p (next-window win 1))) + (delete-window helm-persistent-action-display-window) + (set-window-buffer win helm-current-buffer)) + (message "Buffer `%s' killed" buf-name)) + (t (find-file candidate))))) + +(helm-make-persistent-command-from-action helm-ff-run-kill-buffer-persistent + "Execute `helm-ff-kill-buffer-fname' without quitting." + 'kill-buffer-fname 'helm-ff-kill-buffer-fname) + +;; Preview with external tool +(defun helm-ff-persistent-open-file-externally (file) + (require 'helm-external) + (if (helm-get-default-program-for-file file) + (helm-open-file-externally file) + (message "Please configure an external program for `*%s' file in `helm-external-programs-associations'" + (file-name-extension file t)))) + +(helm-make-persistent-command-from-action helm-ff-run-preview-file-externally + "Run open file externally without quitting helm." + 'open-file-externally 'helm-ff-persistent-open-file-externally) + +(defun helm-ff-prefix-filename (fname &optional file-or-symlinkp new-file) + "Add display property to FNAME. +Display property presents a string maybe prefixed with [?] or [@]. +If FILE-OR-SYMLINKP is non-nil this means we assume FNAME is an +existing filename or valid symlink and there is no need to test +it. +NEW-FILE when non-nil means FNAME is a non existing file and +return FNAME with display property prefixed with [?]." + (let* ((prefix-new (propertize + " " 'display + (propertize "[?]" 'face 'helm-ff-prefix))) + (prefix-url (propertize + " " 'display + (propertize "[@]" 'face 'helm-ff-prefix)))) + (cond (file-or-symlinkp fname) + ((or (string-match helm-ff-url-regexp fname) + (and helm--url-regexp (string-match helm--url-regexp fname))) + (concat prefix-url " " fname)) + (new-file (concat prefix-new " " fname))))) + +(defun helm-ff-score-candidate-for-pattern (real disp pattern) + (cond ((member real '("." "..")) 900000) + ((and (string-match-p "\\`\\s-\\{2\\}" disp) + (string= real (substring-no-properties disp 2))) + ;; Incomplete filenames are prefixed with two spaces, the + ;; first one beeing propertized with a 'display prop + ;; i.e. "[?] foo". + 900001) + (t (helm-score-candidate-for-pattern real pattern)))) + +(defun helm-ff-sort-candidates-1 (candidates input) + "Sort function for `helm-source-find-files'. +Return candidates prefixed with basename of INPUT first." + (if (or (and (file-directory-p input) + (string-match "/\\'" input)) + (string-match "\\`\\$" input) + (null candidates)) + candidates + (let* ((memo-src (make-hash-table :test 'equal)) + (all (sort candidates + (lambda (s1 s2) + (let* ((score (lambda (disp real) + (helm-ff-score-candidate-for-pattern + disp real (helm-basename input)))) + ;; Reals + (r1 (helm-basename (if (consp s1) (cdr s1) s1))) + (r2 (helm-basename (if (consp s2) (cdr s2) s2))) + ;; Displays + (d1 (helm-basename (if (consp s1) (car s1) s1))) + (d2 (helm-basename (if (consp s2) (car s2) s2))) + (sc1 (or (gethash r1 memo-src) + (puthash r1 (funcall score r1 d1) memo-src))) + (sc2 (or (gethash r2 memo-src) + (puthash r2 (funcall score r2 d2) memo-src)))) + (cond ((= sc1 sc2) + (< (string-width r1) + (string-width r2))) + ((> sc1 sc2)))))))) + all))) + +(defun helm-ff-sort-candidates (candidates _source) + "Sort function for `helm-source-find-files'. +Return candidates prefixed with basename of `helm-input' first." + (helm-ff-sort-candidates-1 candidates helm-input)) + +(defun helm-ff-boring-file-p (file) + "Returns non nil when FILE is matching boring regexps." + ;; Prevent user doing silly thing like + ;; adding the dotted files to boring regexps (#924). + (and helm-ff-skip-boring-files + (not (string-match "\\.$" file)) + (string-match helm-ff--boring-regexp file))) + +(defvar helm-ff--git-found-p nil) +(defun helm-ff-git-ignored-p (file) + "Returns non nil when FILE is matched in \".gitignore\" file." + (and helm-ff-skip-git-ignored-files + (not (file-remote-p file)) + (or helm-ff--git-found-p + (setq helm-ff--git-found-p (executable-find "git"))) + (zerop (call-process "git" nil nil nil "check-ignore" "-q" file)))) + +(defun helm-ff-fct (candidates _source) + "Filter in charge of displaying basename or full path in HFF. +Because CANDIDATES are directly stored as (basename . full_path), when +`helm-ff-transformer-show-only-basename' is non nil do nothing and +return directly CANDIDATES." + (if (null helm-ff-transformer-show-only-basename) + (cl-loop for (_disp . real) in candidates + for fc = (helm-ff-filter-candidate-one-by-one real 'reverse) + when fc collect fc) + candidates)) + +(defun helm-ff-filter-candidate-one-by-one (file &optional reverse skip-boring-check) + "Transform file in a cons cell like (DISPLAY . REAL). +DISPLAY is shown as basename of FILE and REAL as full path of FILE. +If REVERSE is non nil DISPLAY is shown as full path. +If SKIP-BORING-CHECK is non nil don't filter boring files." + (let* ((basename (helm-basename file)) + (dot (helm-ff-dot-file-p file)) + (urlp (string-match-p helm-ff-url-regexp file)) + (tramp-invalid-fname (helm-ff--get-host-from-tramp-invalid-fname file)) + (disp (or tramp-invalid-fname + ;; Filename with cntrl chars e.g. foo^J + (replace-regexp-in-string + "[[:cntrl:]]" "?" + (if (or reverse urlp) file basename)))) + (len (length disp)) + (backup (backup-file-name-p disp))) + (when (string-match "/\\'" file) + (setq disp (concat disp "/") + len (1+ len))) + ;; We want to filter boring files only on the files coming + ;; from the output of helm-ff-directory-files not on single + ;; candidate (Bug#2330). + (unless (and (not skip-boring-check) + (or (helm-ff-boring-file-p basename) + (helm-ff-git-ignored-p file))) + ;; Highlight extensions. + (helm-aif (and (not backup) + (not urlp) + (helm-file-name-extension disp)) + (when (condition-case _err + (string-match (format "\\.\\(%s\\)\\'" it) disp) + (invalid-regexp nil)) + (add-face-text-property + (match-beginning 1) (match-end 1) + 'helm-ff-file-extension t disp))) + ;; Handle tramp files with minimal highlighting. + (if (and (or (string-match-p helm-tramp-file-name-regexp helm-pattern) + (helm-file-on-mounted-network-p helm-pattern))) + (helm-acond (;; Dot directories . and .. + dot + (cons (propertize file 'face 'helm-ff-dotted-directory) file)) + ;; Directories. + ((get-text-property 1 'helm-ff-dir file) + (cons (propertize disp 'face 'helm-ff-directory) file)) + ;; Backup files. + (backup + (cons (propertize disp 'face 'helm-ff-backup-file) file)) + ;; Executable files. + ((get-text-property 1 'helm-ff-exe file) + (add-face-text-property 0 len 'helm-ff-executable t disp) + (cons disp file)) + ;; Symlinks. + ((get-text-property 1 'helm-ff-sym file) + (add-face-text-property 0 len 'helm-ff-symlink t disp) + (if (stringp it) ; adb method. + (progn + (add-face-text-property 0 (length it) 'helm-ff-truename nil it) + (cons (propertize disp 'display (concat disp " ->" it)) file)) + (cons disp file))) + ;; Regular files. + ((get-text-property 1 'helm-ff-file file) + (add-face-text-property 0 len 'helm-ff-file t disp) + (cons disp file)) + ;; Tramp methods. + ((string-match helm-ff-tramp-method-regexp file) + (let ((method (match-string 1 file)) + (mh (helm-ff--tramp-multihops-p helm-pattern))) + (cons (propertize (concat (if mh "" "/") method) 'face 'helm-ff-file) + (if mh + (concat (match-string 1 helm-pattern) ":" method) + (concat "/:" method))))) + ;; non existing files. + (t + (add-face-text-property 0 len 'helm-ff-file t disp) + (when tramp-invalid-fname + (add-text-properties 0 len `(host ,tramp-invalid-fname) disp)) + (cons (helm-ff-prefix-filename + disp + tramp-invalid-fname + (unless tramp-invalid-fname 'new-file)) + file))) + + ;; Highlight local files showing everything, symlinks, exe, + ;; dirs etc... + (let* ((attr (condition-case err + (file-attributes file) + (file-error + ;; Possible error not happening during listing + ;; but when calling file-attributes see error + ;; with sshfs bug#2405 + (message "%s:%s" (car err) (cdr err)) nil))) + (type (car attr)) + x-bit) + (cond (;; Not a file but the message error printed in + ;; helm-buffer. Such a message should not have a + ;; subdir so matching on bol should suffice, but to + ;; be sure use @@@@ as prefix in file-error message + ;; to be safe bug#2400. + (string-match "\\`@@@@file-error:" file) file) + (;; A dead symlink. + (and (stringp type) + (not (helm-ff-valid-symlink-p file)) + (not (string-match "^\\.#" basename))) + (add-face-text-property 0 len 'helm-ff-invalid-symlink t disp) + (cons disp file)) + ;; A dotted directory symlinked. + ((and dot (stringp type)) + (cons (propertize file 'face 'helm-ff-dotted-symlink-directory) file)) + ;; A dotted directory. + (dot + (cons (propertize file 'face 'helm-ff-dotted-directory) file)) + ;; Backup files. + (backup + (cons (propertize disp 'face 'helm-ff-backup-file) file)) + ;; A symlink. + ((stringp type) + (let* ((abbrev (abbreviate-file-name type)) + (len-abbrev (length abbrev))) + (helm-aif (helm-file-name-extension abbrev) + (when (string-match (format "\\.\\(%s\\)\\'" it) abbrev) + (add-face-text-property + (match-beginning 1) (match-end 1) + 'helm-ff-file-extension t abbrev))) + (add-face-text-property 0 len-abbrev 'helm-ff-truename t abbrev) + ;; Colorize extension only on truename. + (add-face-text-property 0 len 'helm-ff-symlink nil disp) + ;; As we use match-on-real we can use this safely, + ;; abbrev will not be matched. + (cons (concat disp " -> " abbrev) + file))) + ;; A directory. + ((eq t type) + (cons (propertize disp 'face 'helm-ff-directory) file)) + ;; A character device file. + ((and attr (string-match + "\\`[cp]" (setq x-bit (substring (nth 8 attr) 0 4)))) + (add-face-text-property 0 len 'helm-ff-pipe t disp) + (cons disp file)) + ;; A socket file. + ((and attr (string-match "\\`[s]" x-bit)) + (add-face-text-property 0 len 'helm-ff-socket t disp) + (cons disp file)) + ;; An executable file. + ((and attr (string-match "x\\'" x-bit)) + (add-face-text-property 0 len 'helm-ff-executable t disp) + (cons disp file)) + ;; An executable file with suid + ((and attr (string-match "s\\'" x-bit)) + (add-face-text-property 0 len 'helm-ff-suid t disp) + (cons disp file)) + ;; A file. + ((and attr (null type)) + (add-face-text-property 0 len 'helm-ff-file t disp) + (cons disp file)) + ;; A tramp method + ;; At this point no need to handle multi hops syntax + ;; which is considered remote and handled in first + ;; cond before. + ((string-match helm-ff-tramp-method-regexp file) + (cons (propertize (concat "/" (match-string 1 file)) + 'face 'helm-ff-nofile) + (concat "/:" (match-string 1 file)))) + ;; A non--existing file. + (t + (add-face-text-property 0 len 'helm-ff-nofile t disp) + (cons (helm-ff-prefix-filename + disp nil 'new-file) + file)))))))) + +(defun helm-ff-icons-transformer (candidates _source) + "Transformer for HFF that prefix candidates with icons." + (cl-loop for (disp . fname) in candidates + for icon = (helm-ff-get-icon disp fname) + collect (cons (concat icon disp) fname))) + +(defun helm-ff-get-icon (disp file) + "Get icon from all-the-icons for FILE. +Arg DISP is the display part of the candidate." + (let ((icon (helm-acond (;; Non symlink directories. + (helm-ff--is-dir-from-disp disp) + (all-the-icons-octicon "file-directory")) + (;; All files, symlinks may be symlink directories. + (helm-ff--is-file-from-disp disp) + ;; Detect symlink directories. We must call + ;; `file-directory-p' here but it is + ;; limited to symlinks, so it should not + ;; degrade too much performances. + (if (and (memq it '(helm-ff-symlink + helm-ff-dotted-symlink-directory)) + (file-directory-p file)) + (let* ((icon (all-the-icons-match-to-alist + (helm-basename file) + all-the-icons-dir-icon-alist)) + (args (cdr icon))) + (apply #'all-the-icons-octicon + "file-symlink-directory" (cdr args))) + (all-the-icons-icon-for-file file)))))) + (when icon (concat icon " ")))) + +(defun helm-ff--is-dir-from-disp (disp) + "Return the face used for candidate when candidate is a directory." + (cl-loop with faces = (helm-mklist (get-text-property 0 'face disp)) + for face in '(helm-ff-directory helm-ff-dotted-directory) + thereis (memq face faces))) + +(defun helm-ff--is-file-from-disp (disp) + "Return the face used for file's candidate or dotted-symlink dirs." + (cl-loop with faces = (helm-mklist (get-text-property 0 'face disp)) + for face in '(helm-ff-file + helm-ff-suid + helm-ff-executable + helm-ff-socket + helm-ff-pipe + helm-ff-symlink + helm-ff-dotted-symlink-directory + helm-ff-backup-file) + when (memq face faces) + return face)) + +;;;###autoload +(define-minor-mode helm-ff-icon-mode + "Display icons from `all-the-icons' package in HFF when enabled. + +NOTE: This mode is building `helm-source-find-files', so if you enable +it from your init file, ensure to call it _after_ your defmethod's +`helm-setup-user-source' definitions (if some) to ensure they are called." + :global t + :group 'helm-files + (if helm-ff-icon-mode + (progn + (require 'all-the-icons) + (unless helm-source-find-files + (setq helm-source-find-files + (helm-make-source + "Find Files" 'helm-source-ffiles))) + (let ((fct (helm-get-attr + 'filtered-candidate-transformer + helm-source-find-files))) + (unless (memq 'helm-ff-icons-transformer fct) + (helm-set-attr 'filtered-candidate-transformer + (append fct '(helm-ff-icons-transformer)) + helm-source-find-files)))) + (when helm-source-find-files + (helm-set-attr 'filtered-candidate-transformer + (remove 'helm-ff-icons-transformer + (helm-get-attr + 'filtered-candidate-transformer + helm-source-find-files)) + helm-source-find-files)))) + +(defun helm-find-files-action-transformer (actions candidate) + "Action transformer for `helm-source-find-files'." + (let ((str-at-point (with-helm-current-buffer + (buffer-substring-no-properties + (point-at-bol) (point-at-eol))))) + (when (file-regular-p candidate) + (setq actions (helm-append-at-nth + actions '(("Checksum File" . helm-ff-checksum)) 4))) + (cond ((and (file-exists-p candidate) + (string-match helm-ff--trash-directory-regexp + (helm-basedir (expand-file-name candidate))) + (not (member (helm-basename candidate) '("." ".."))) + (executable-find "trash")) + (helm-append-at-nth + actions + '(("Restore file(s) from trash" . helm-restore-file-from-trash) + ("Delete file(s) from trash" . helm-ff-trash-rm)) + 1)) + ((and helm--url-regexp + (not (string-match-p helm--url-regexp str-at-point)) + (not (with-helm-current-buffer (eq major-mode 'dired-mode))) + (string-match-p ":\\([0-9]+:?\\)" str-at-point)) + (append '(("Find file to line number" . helm-ff-goto-linum)) + actions)) + ((string-match (image-file-name-regexp) candidate) + (helm-append-at-nth + actions + '(("Rotate image right `M-r'" . helm-ff-rotate-image-right) + ("Rotate image left `M-l'" . helm-ff-rotate-image-left) + ("Start slideshow with marked" . helm-ff-start-slideshow-on-marked)) + 3)) + ((string-match "\\.el\\'" candidate) + (helm-append-at-nth + actions + '(("Byte compile lisp file(s) `M-B, C-u to load'" + . helm-find-files-byte-compile) + ("Load File(s) `M-L'" . helm-find-files-load-files)) + 2)) + ((string-match (concat (regexp-opt load-suffixes) "\\'") candidate) + (helm-append-at-nth + actions + '(("Load File(s) `M-L'" . helm-find-files-load-files)) + 2)) + ((and (string-match "\\.html?$" candidate) + (file-exists-p candidate)) + (helm-append-at-nth + actions '(("Browse url file" . browse-url-of-file)) 2)) + (t actions)))) + +;;; Trashing files +;; +(defun helm-ff-trash-action (fn names &rest args) + "Execute a trash action FN on marked files. + +Arg NAMES is a list of strings to pass to messages. +E.g. \\='(\"delete\" \"deleting\") + +ARGS are other arguments to be passed to FN." + (let ((mkd (helm-marked-candidates)) + errors aborted) + (with-helm-display-marked-candidates + helm-marked-buffer-name + (if (and args (string= (car names) "restore")) + (cl-loop for f in mkd + for bd = (helm-basename f) + for assoc = (assoc bd (car args)) + when assoc + collect (concat (truncate-string-to-width + (car assoc) 40 nil nil t) + " -> " + (truncate-string-to-width + (helm-basedir (cdr assoc)) 40 nil nil t))) + (helm-ff--count-and-collect-dups (mapcar 'helm-basename mkd))) + (if (y-or-n-p (format "%s %s files from trash? " + (capitalize (car names)) + (length mkd))) + (progn + (message "%s files from trash..." (capitalize (cadr names))) + (cl-loop for f in mkd do + (condition-case err + (apply fn f args) + (error (push (format "%s" (cadr err)) errors) + nil)))) + (message "%s files from trash aborted" (capitalize (cadr names))) + (setq aborted t))) + ;; Handle errors from outside the + ;; with-helm-display-marked-candidates block otherwise warning is + ;; never displayed. + (if errors + (progn + (display-warning 'helm + (with-temp-buffer + (insert (format-time-string "%Y-%m-%d %H:%M:%S\n" + (current-time))) + (insert (format + "Failed to %s %s/%s files from trash\n" + (car names) (length errors) (length mkd))) + (insert (mapconcat 'identity errors "\n") "\n ") + (buffer-string)) + :error + "*helm restore warnings*") + (message "%s files from trash aborted" (capitalize (cadr names)))) + (unless aborted + (message "%s %s files from trash done" + (capitalize (cadr names)) (length mkd)))))) + +(defun helm-ff-trash-rm (_candidate) + "Delete marked-files from a Trash directory. + +The Trash directory should be a directory compliant with + and each +file should have its \\='*.trashinfo' correspondent file in +Trash/info directory." + (helm-ff-trash-action 'helm-ff-trash-rm-1 '("delete" "deleting"))) + +(defun helm-ff-trash-rm-1 (file) + (let ((info-file (concat (helm-reduce-file-name file 2) + "info/" (helm-basename file "trashinfo") + ".trashinfo"))) + (cl-assert (file-exists-p file) + nil (format "No such file or directory `%s'" + file)) + (cl-assert (file-exists-p info-file) + nil (format "No such file or directory `%s'" + info-file)) + (if (file-directory-p file) + (delete-directory file t) + (delete-file file)) + (delete-file info-file))) + +(defun helm-restore-file-from-trash (_candidate) + "Restore marked-files from a Trash directory. + +The Trash directory should be a directory compliant with + and each +file should have its \\='*.trashinfo' corresponding file in +Trash/info directory." + (let* ((default-directory (file-name-as-directory + helm-ff-default-directory)) + (trashed-files (helm-ff-trash-list))) + (helm-ff-trash-action 'helm-restore-file-from-trash-1 + '("restore" "restoring") + trashed-files))) + +(defun helm-restore-file-from-trash-1 (file trashed-files) + "Restore FILE from a trash directory. +Arg TRASHED-FILES is an alist of (fname_in_trash . dest) obtained +with `helm-ff-trash-list'." + ;; Emacs trash duplicate files with a unique name + .trashinfo in + ;; the filename which is wrong, only files in info directory should + ;; end with .trashinfo, so fix the filename before looking for dest name. + (let* ((fname (replace-regexp-in-string "\\.trashinfo\\'" "" file)) + (info-file (concat (helm-reduce-file-name fname 2) + "info/" + (helm-basename fname) + ".trashinfo")) + (dest-file (helm-ff--get-dest-file-from-trash + trashed-files fname))) + (cl-assert (not (file-exists-p dest-file)) nil + (format "File `%s' already exists" dest-file)) + (cl-assert dest-file nil "No such file in trash") + (message "Restoring %s to %s..." (helm-basename file) (helm-basedir dest-file)) + (rename-file file dest-file) + (message "Restoring %s to %s done" (helm-basename file) (helm-basedir dest-file)) + (delete-file info-file))) + +(defun helm-ff-trash-file-p (file) + "Return t when FILE is a trashed file." + (and (file-exists-p file) + (string-match helm-ff--trash-directory-regexp (helm-basedir file)) + (not (member (helm-basename file) '("." ".."))))) + +(defun helm-ff--get-dest-file-from-trash (trashed-files file) + (assoc-default (helm-basename file) trashed-files)) + +(cl-defun helm-ff-trash-list (&optional (trash-dir nil strash-dir)) + "Return an alist of trashed files basename and dest name. +Assume the trash system in use is freedesktop compatible, see + +This function is intended to be used from a trash directory i.e. it +use `helm-ff-default-directory', but it may be used elsewhere by +specifying the trash directory with TRASH-DIR arg." + (unless (or (fboundp 'system-move-file-to-trash) + (and strash-dir (null trash-dir))) + ;; Files owned by root are trashed in /root/.local/share/Trash. + ;; Files owned by user and trashed by root are trashed in + ;; /home/.Trash. + ;; Files owned by user and trashed by user are trashed in + ;; ~/.local/share/Trash. + (cl-loop for f in (directory-files + (expand-file-name + ;; helm-ff-default-directory is actually the + ;; trash directory. + "info" (helm-basedir (directory-file-name + (or trash-dir helm-ff-default-directory)))) + t directory-files-no-dot-files-regexp) + collect (cons (helm-basename (replace-regexp-in-string "\\.trashinfo\\'" "" f)) + (with-temp-buffer + (save-excursion + (insert-file-contents f)) + (when (re-search-forward "^path=" nil t) + (let ((path (helm-url-unhex-string + (buffer-substring-no-properties + (point) (point-at-eol))))) + (if (string-match "\\`/" path) + ;; path is absolute + path + ;; When path is relative, assume the + ;; trash directory is located at + ;; /home/.Trash and path is the + ;; relative name of file from /home. + (expand-file-name path "/home"))))))))) + +(defun helm-ff-goto-linum (candidate) + "Find file CANDIDATE and maybe jump to line number found in fname at point. +Line number should be added at end of fname preceded with \":\". +E.g. \"foo:12\"." + (let ((linum (with-helm-current-buffer + (let ((str (buffer-substring-no-properties + (point-at-bol) (point-at-eol)))) + (when (string-match ":\\([0-9]+:?\\)" str) + (match-string 1 str)))))) + (find-file candidate) + (and linum (not (string= linum "")) + (helm-goto-line (string-to-number linum) t)))) + +(defun helm-ff-mail-attach-files (_candidate) + "Run `mml-attach-file' on `helm-marked-candidates'." + (require 'mml) + (let ((flist (helm-marked-candidates :with-wildcard t)) + (dest-buf (and (derived-mode-p 'message-mode 'mail-mode) + (current-buffer))) + bufs) + (unless dest-buf + (setq bufs (cl-loop for b in (buffer-list) + when (with-current-buffer b + (derived-mode-p 'message-mode 'mail-mode)) + collect (buffer-name b))) + (if (and bufs (y-or-n-p "Attach files to existing mail composition buffer? ")) + (setq dest-buf + (if (cdr bufs) + (helm-comp-read "Attach to buffer: " bufs :nomark t) + (car bufs))) + (compose-mail) + (setq dest-buf (current-buffer)))) + (switch-to-buffer dest-buf) + (save-restriction + (widen) + (save-excursion + (goto-char (point-max)) + (cl-loop for f in flist + do (mml-attach-file f (or (mm-default-file-encoding f) + "application/octet-stream"))))))) + +(defvar image-dired-display-image-buffer) +(defun helm-ff-rotate-current-image-1 (file angle) + "Rotate current image at ANGLE degrees." + (cl-assert (and (file-exists-p file) + (string-match (image-file-name-regexp) file)) + nil "Can't rotate non image file") + (setq file (file-truename file)) ; For symlinked images. + (let ((default-directory (file-name-directory file)) + (basename (helm-basename file)) + ;; convert ANGLE to a suitable value for exiftran. + (num-arg (if (string= helm-ff-rotate-image-program "exiftran") + (cl-case angle + (90 "-9") ; 90 clockwise + (270 "-2")) ; 270 clockwise == -90 + (number-to-string angle))) + rotation-failed) + ;; Try to rotate image with exiftran even with helm-ff-display-image-native. + (if (and helm-ff-rotate-image-program + (executable-find helm-ff-rotate-image-program)) + (apply #'process-file helm-ff-rotate-image-program nil nil nil + (append helm-ff-rotate-image-switch + (list num-arg basename))) + (setq rotation-failed t)) + ;; Display image in image-mode. + (if (helm-ff-display-image-native-p) + (if rotation-failed + ;; When rotation fails fallback to `image-rotate' with no + ;; transformation of file. + (with-selected-window (helm-persistent-action-display-window) + (condition-case _err + (with-no-warnings (image-rotate angle)) + (wrong-number-of-arguments (image-rotate)))) + (helm-ff--display-image-native file)) + ;; Use image-dired to display image. + (when rotation-failed + (error "%s not found" (or helm-ff-rotate-image-program + "`helm-ff-rotate-image-program'"))) + (when (buffer-live-p image-dired-display-image-buffer) + (kill-buffer image-dired-display-image-buffer)) + (image-dired-display-image basename) + (message nil) + (display-buffer (get-buffer image-dired-display-image-buffer))))) + +(defun helm-ff-rotate-image-left (candidate) + "Rotate image file CANDIDATE left. +This affects directly file CANDIDATE." + (helm-ff-rotate-current-image-1 candidate 270)) + +(defun helm-ff-rotate-image-right (candidate) + "Rotate image file CANDIDATE right. +This affects directly file CANDIDATE." + (helm-ff-rotate-current-image-1 candidate 90)) + +(defun helm-ff-rotate-left-persistent () + "Rotate image left without quitting helm." + (interactive) + (with-helm-alive-p + (helm-set-attr 'image-action1 'helm-ff-rotate-image-left) + (helm-execute-persistent-action 'image-action1))) +(put 'helm-ff-rotate-left-persistent 'helm-only t) + +(defun helm-ff-rotate-right-persistent () + "Rotate image right without quitting helm." + (interactive) + (with-helm-alive-p + (helm-set-attr 'image-action2 'helm-ff-rotate-image-right) + (helm-execute-persistent-action 'image-action2))) +(put 'helm-ff-rotate-right-persistent 'helm-only t) + +(defun helm-ff-resize-image-1 (arg) + ;; `image-decrease-size' and `image-increase-size' are not usable + ;; because they run directly `image--change-size' in a timer without + ;; taking care of the selected-window. + (cl-assert (and (fboundp 'image--change-size) + (helm-ff-display-image-native-p)) + nil "Resizing image not available") + (if (> arg 0) + (run-with-idle-timer + 0.3 nil + (lambda () + (with-selected-window (helm-persistent-action-display-window) + (image--change-size 1.2)))) + (run-with-idle-timer + 0.3 nil + (lambda () + (with-selected-window (helm-persistent-action-display-window) + (image--change-size 0.8)))))) + +(defun helm-ff-increase-image-size (_candidate) + (helm-ff-resize-image-1 1)) + +(defun helm-ff-decrease-image-size (_candidate) + (helm-ff-resize-image-1 -1)) + +(defun helm-ff-increase-image-size-persistent () + "Increase image size without quitting helm." + (interactive) + (with-helm-alive-p + (helm-set-attr 'image-action3 'helm-ff-increase-image-size) + (helm-execute-persistent-action 'image-action3))) +(put 'helm-ff-increase-image-size-persistent 'helm-only t) + +(defun helm-ff-decrease-image-size-persistent () + "Decrease image size without quitting helm." + (interactive) + (with-helm-alive-p + (helm-set-attr 'image-action4 'helm-ff-decrease-image-size) + (helm-execute-persistent-action 'image-action4))) +(put 'helm-ff-decrease-image-size-persistent 'helm-only t) + +(defun helm-ff-exif-data (candidate) + "Extract exif data from file CANDIDATE using `helm-ff-exif-data-program'." + (if (and helm-ff-exif-data-program + (executable-find helm-ff-exif-data-program)) + (shell-command-to-string (format "%s %s %s" + helm-ff-exif-data-program + helm-ff-exif-data-program-args + candidate)) + (format "No program %s found to extract exif" + helm-ff-exif-data-program))) + +(defvar helm-ff-image-native-buffer "*image-native-display*") + +(defvar helm-ff-sound-file-extensions '("wav" "au")) + +(defun helm-ff--maybe-follow (candidate) + (let ((file (file-regular-p candidate)) + (image (string-match-p (image-file-name-regexp) candidate)) + (ext (file-name-extension candidate))) + (and file + (or image (not (member ext helm-ff-follow-blacklist-file-exts)))))) + +(cl-defun helm-find-files-persistent-action-if (candidate) + "Open subtree CANDIDATE without quitting helm. +If CANDIDATE is not a directory expand CANDIDATE filename. +If CANDIDATE is alone, open file CANDIDATE filename. +That means: +First hit on C-j expands CANDIDATE, second hit opens file. +If a prefix arg is given or `helm-follow-mode' is on, then open +file." + (let* ((follow (or (helm-follow-mode-p) + helm--temp-follow-flag)) + (image-cand (string-match-p (image-file-name-regexp) candidate)) + (sound-cand (member (file-name-extension candidate) + helm-ff-sound-file-extensions)) + (selection (helm-get-selection)) + (insert-in-minibuffer (lambda (fname) + (with-selected-window (or (active-minibuffer-window) + (minibuffer-window)) + (unless follow + (delete-minibuffer-contents) + (set-text-properties 0 (length fname) + nil fname) + (insert fname)))))) + (helm-set-attr 'candidate-number-limit helm-ff-candidate-number-limit) + (unless (helm-ff--maybe-follow candidate) + (when follow + (helm-follow-mode -1) (message nil) + (cl-return-from helm-find-files-persistent-action-if + (prog1 + #'ignore + (user-error "Can't follow this kind of file"))))) + (cond (;; Tramp methods completion. + (string-match helm-ff-tramp-method-regexp candidate) + (let ((method (match-string 1 candidate))) + (cons (lambda (candidate) + (funcall insert-in-minibuffer + (if (helm-ff--tramp-multihops-p candidate) + (concat (match-string 1 candidate) method ":") + (concat "/" method ":")))) + 'never-split))) + ((and (helm-ff--invalid-tramp-name-p) + (string-match helm-tramp-file-name-regexp candidate)) + (cons (lambda (_candidate) + ;; First hit insert hostname and + ;; second hit insert ":" and expand. + (if (string= candidate helm-pattern) + (funcall insert-in-minibuffer (concat candidate ":")) + (funcall insert-in-minibuffer candidate))) + 'never-split)) + (;; A symlink directory, expand it but not to its truename + ;; unless a prefix arg is given. + (and (file-directory-p candidate) (file-symlink-p candidate)) + (cons (lambda (_candidate) + (helm-ff-after-persistent-show-all) + (let ((new-dir (file-name-as-directory + (if current-prefix-arg + (file-truename (expand-file-name candidate)) + (expand-file-name candidate))))) + (setq helm-ff--show-thumbnails + (member new-dir helm-ff--thumbnailed-directories)) + (funcall insert-in-minibuffer new-dir))) + 'never-split)) + ;; A directory, open it. + ((file-directory-p candidate) + (cons (lambda (_candidate) + (helm-ff-after-persistent-show-all) + (when (string= (helm-basename candidate) "..") + (setq helm-ff-last-expanded helm-ff-default-directory)) + (let ((new-dir (file-name-as-directory + (expand-file-name candidate)))) + (setq helm-ff--show-thumbnails + (member new-dir helm-ff--thumbnailed-directories)) + (funcall insert-in-minibuffer new-dir)) + (with-helm-after-update-hook (helm-ff-retrieve-last-expanded))) + 'never-split)) + ;; A symlink file, expand to it's true name. (first hit) + ((and (file-symlink-p candidate) (not current-prefix-arg) (not follow)) + (cons (lambda (_candidate) + (funcall insert-in-minibuffer (file-truename candidate)) + (helm-check-minibuffer-input)) ; Force update. + 'never-split)) + ;; A regular file, expand it, (first hit) + ((and (not (file-equal-p selection helm-pattern)) + (not current-prefix-arg) (not follow)) + (cons (lambda (_candidate) + (funcall insert-in-minibuffer selection) + (helm-check-minibuffer-input)) ; Force update. + 'never-split)) + (sound-cand (lambda (candidate) (play-sound-file candidate))) + ;; An image file and it is the second hit on C-j, display it. + (image-cand + (if (helm-ff-display-image-native-p) + #'helm-ff--display-or-kill-image-native + (lambda (_candidate) + (require 'image-dired) + (let* ((win (get-buffer-window + image-dired-display-image-buffer 'visible)) + (fname (and win + (with-selected-window win + (get-text-property (point-min) + 'original-file-name)))) + (remove-buf-only (and win + fname + (with-helm-buffer + (file-equal-p candidate fname))))) + (when remove-buf-only + (with-helm-window + (if (and helm-persistent-action-display-window + (window-dedicated-p (next-window win 1))) + (delete-window helm-persistent-action-display-window) + (set-window-buffer win helm-current-buffer)))) + (when (buffer-live-p (get-buffer image-dired-display-image-buffer)) + (kill-buffer image-dired-display-image-buffer)) + (unless remove-buf-only + ;; Fix emacs bug never fixed upstream. + (unless (file-directory-p image-dired-dir) + (make-directory image-dired-dir)) + (switch-to-buffer image-dired-display-image-buffer) + (message "Resizing image...") + (cl-letf (((symbol-function 'message) #'ignore)) + (image-dired-display-image candidate)) + (message "Resizing image done") + (with-current-buffer image-dired-display-image-buffer + (let ((exif-data (helm-ff-exif-data candidate))) + (setq default-directory helm-ff-default-directory) + (image-dired-update-property 'help-echo exif-data)))))))) + ;; Allow browsing archive on avfs fs. + ;; Assume volume is already mounted with mountavfs. + ((helm-aand helm-ff-avfs-directory + (file-name-directory candidate) + (string-match + (regexp-quote (expand-file-name helm-ff-avfs-directory)) + it) + (helm-ff-file-compressed-p candidate)) + (cons (lambda (_candidate) + (funcall insert-in-minibuffer (concat candidate "#/"))) + 'never-split)) + ;; File doesn't exists and basename starts with ".." or " ", + ;; Start a recursive search for directories. + ((and (not (file-exists-p candidate)) + (not (file-remote-p candidate)) + (string-match-p "\\`\\([.]\\|\\s-\\)\\{2\\}[^/]+" + (helm-basename candidate))) + ;; As soon as the final "/" is added the job is passed + ;; to `helm-ff-auto-expand-to-home-or-root'. + (cons (lambda (_candidate) + (funcall insert-in-minibuffer (concat candidate "/"))) + 'never-split)) + ;; File is not existing and have no basedir, typically when + ;; user hit C-k (minibuffer is empty) and then write foo and + ;; hit C-j. This make clear that when no basedir, helm will + ;; create the file in default-directory. + ((and (not (file-exists-p candidate)) + (not (helm-basedir candidate))) + (cons (lambda (_candidate) + (funcall insert-in-minibuffer + (expand-file-name candidate default-directory))) + 'never-split)) + ;; On second hit we open file. + ;; On Third hit we kill it's buffer maybe. + (t + (lambda (candidate) + (funcall helm-ff-kill-or-find-buffer-fname-fn candidate)))))) + +;; Native image display (with image-mode). +;; +(defvar helm-ff--image-cache nil) + +(defun helm-ff-display-image-native-p () + "Use `helm-ff-display-image-native' when returns `t'." + (or helm-ff-display-image-native + ;; Image-dired in emacs-29 uses image-mode but + ;; display is no more working with our old + ;; image-dired code, so force usage of + ;; helm-ff-display-image-native. + (fboundp 'image-dired-display-image-mode))) + +(defun helm-ff--display-or-kill-image-native (candidate) + ;; Display images in same buffer + ;; `helm-ff-image-native-buffer'. + (if (and (buffer-live-p (get-buffer helm-ff-image-native-buffer)) + (file-equal-p (buffer-file-name + (get-buffer helm-ff-image-native-buffer)) + candidate) + ;; Allow redisplaying + ;; `helm-ff-image-native-buffer' when it + ;; already exists and display same image as candidate. + (get-buffer-window helm-ff-image-native-buffer 'visible)) + (progn + (set-window-buffer + helm-persistent-action-display-window helm-current-buffer) + (kill-buffer helm-ff-image-native-buffer)) + (helm-ff--display-image-native candidate))) + +(defun helm-ff-clean-image-cache () + (when helm-ff--image-cache + (cl-loop for img in helm-ff--image-cache + do (clear-image-cache img) + finally do (setq helm-ff--image-cache nil)))) + +(defun helm-ff--display-image-native (candidate) + (when (buffer-live-p (get-buffer helm-ff-image-native-buffer)) + (kill-buffer helm-ff-image-native-buffer)) + ;; Avoid hight memory consumption see + ;; https://lists.gnu.org/archive/html/bug-gnu-emacs/2021-11/msg00879.html. + (when (> (length helm-ff--image-cache) + (* helm-ff-image-cache-max-len 2)) + ;; Only keep the last `helm-ff-image-cache-max-len' images in cache. + (cl-loop for img in (butlast helm-ff--image-cache + (1+ helm-ff-image-cache-max-len)) + do (clear-image-cache img) + (setq helm-ff--image-cache + (delete img helm-ff--image-cache)))) + (cl-letf* (((symbol-function 'message) #'ignore) + (buf (find-file-noselect candidate t))) + ;; When going back reuse the cached images. + (unless (member candidate helm-ff--image-cache) + (setq helm-ff--image-cache + (append helm-ff--image-cache + (list (expand-file-name candidate))))) + (with-current-buffer buf + (rename-buffer helm-ff-image-native-buffer)) + (display-buffer buf))) + +;;; Slideshow action +;; +(defvar helm-ff--slideshow-iterator nil) +(defvar helm-ff--slideshow-sequence nil) +(defvar helm-ff--slideshow-in-pause nil) +(defvar helm-ff-slideshow-helper + "Type `\\[helm-ff-slideshow-pause-or-restart]' to %s, \ +`\\[helm-ff-slideshow-next]' for next, `\\[helm-ff-slideshow-previous]' for previous, \ +`\\[helm-ff-slideshow-quit]' to quit") + +(defvar helm-slideshow-mode-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map image-mode-map) + (define-key map (kbd "SPC") 'helm-ff-slideshow-pause-or-restart) + (define-key map (kbd "q") 'helm-ff-slideshow-quit) + (define-key map (kbd "n") 'helm-ff-slideshow-next) + (define-key map (kbd "p") 'helm-ff-slideshow-previous) + map)) + +(define-derived-mode helm-slideshow-mode + image-mode "helm-image-mode" + "Mode to display images from helm-find-files. + +Special commands: +\\{helm-slideshow-mode-map} +") +(put 'helm-slideshow-mode 'no-helm-mx t) + +(defun helm-ff-start-slideshow-on-marked (_candidate) + "Start a slideshow on marked files." + (let ((marked (helm-marked-candidates :with-wildcard t))) + (cl-assert (cdr marked) nil "Can't start a slideshow on a single file") + (setq helm-ff--slideshow-sequence marked) + (setq helm-ff--slideshow-iterator (helm-iter-circular marked)) + (helm-ff--display-image-native (helm-iter-next helm-ff--slideshow-iterator)) + (delete-other-windows (get-buffer-window helm-ff-image-native-buffer)) + (cl-letf (((symbol-function 'message) #'ignore)) + (helm-slideshow-mode)) + (message (concat (format "(1/%s) " (length marked)) + (substitute-command-keys + (format helm-ff-slideshow-helper "pause")))) + (helm-ff-slideshow-loop helm-ff--slideshow-iterator))) + +(defun helm-ff-slideshow-state () + (format "(%s/%s) " + (1+ (cl-position + (buffer-file-name) helm-ff--slideshow-sequence + :test 'equal)) + (length helm-ff--slideshow-sequence))) + +(defun helm-ff-slideshow-sequence-from-current (&optional reverse) + (helm-reorganize-sequence-from-elm + helm-ff--slideshow-sequence (buffer-file-name) reverse)) + +(defun helm-ff-slideshow-loop (iterator) + (while (sit-for helm-ff-slideshow-default-delay) + (helm-ff--display-image-native (helm-iter-next iterator)) + (delete-other-windows (get-buffer-window helm-ff-image-native-buffer)) + (cl-letf (((symbol-function 'message) #'ignore)) + (helm-slideshow-mode)) + (message (concat (helm-ff-slideshow-state) + (substitute-command-keys + (format helm-ff-slideshow-helper "pause")))))) + +(defun helm-ff-slideshow-pause-or-restart () + (interactive) + (setq helm-ff--slideshow-in-pause (not helm-ff--slideshow-in-pause)) + (if helm-ff--slideshow-in-pause + (message (substitute-command-keys + (format helm-ff-slideshow-helper "restart"))) + (message "Helm Slideshow restarting...") + (setq helm-ff--slideshow-iterator + (helm-iter-circular (helm-ff-slideshow-sequence-from-current))) + (helm-ff-slideshow-loop helm-ff--slideshow-iterator))) +(put 'helm-ff-slideshow-pause-or-restart 'no-helm-mx t) + +(defun helm-ff-slideshow-next () + (interactive) + (setq helm-ff--slideshow-in-pause t) + (setq helm-ff--slideshow-iterator nil) + (helm-ff--display-image-native + (car (helm-ff-slideshow-sequence-from-current))) + (delete-other-windows (get-buffer-window helm-ff-image-native-buffer)) + (cl-letf (((symbol-function 'message) #'ignore)) + (helm-slideshow-mode)) + (message (concat (helm-ff-slideshow-state) + (substitute-command-keys + (format helm-ff-slideshow-helper "restart"))))) +(put 'helm-ff-slideshow-next 'no-helm-mx t) + +(defun helm-ff-slideshow-previous () + (interactive) + (setq helm-ff--slideshow-in-pause t) + (setq helm-ff--slideshow-iterator nil) + (helm-ff--display-image-native + (car (helm-ff-slideshow-sequence-from-current 'reverse))) + (delete-other-windows (get-buffer-window helm-ff-image-native-buffer)) + (cl-letf (((symbol-function 'message) #'ignore)) + (helm-slideshow-mode)) + (message (concat (helm-ff-slideshow-state) + (substitute-command-keys + (format helm-ff-slideshow-helper "restart"))))) +(put 'helm-ff-slideshow-previous 'no-helm-mx t) + +(defun helm-ff-slideshow-quit () + (interactive) + (setq helm-ff--slideshow-iterator nil) + (setq helm-ff--slideshow-in-pause nil) + (helm-ff-clean-image-cache) + (quit-window)) +(put 'helm-ff-slideshow-quit 'no-helm-mx t) + +;;; Thumbnails view +;; +(defun helm-ff-maybe-show-thumbnails (candidates _source) + (require 'image-dired) + (if (and helm-ff--show-thumbnails + (null (file-remote-p helm-ff-default-directory))) + (progn + (cl-pushnew helm-ff-default-directory + helm-ff--thumbnailed-directories :test 'equal) + (cl-loop for (disp . img) in candidates + for imgtype = (helm-acase (file-name-extension img) + ("png" 'png) + (("jpg" "jpeg") 'jpeg)) + for type = (if (and imgtype + (memq image-dired-thumbnail-storage + '(standard standard-large))) + 'png + imgtype) + if type collect + (let ((thumbnail (plist-get + (cdr (helm-ff--image-dired-get-thumbnail-image img)) + :file))) + (cons (concat (propertize " " + 'display `(image + :type ,type + :margin 5 + :file ,thumbnail) + 'rear-nonsticky '(display)) + disp) + img)) + else collect (cons disp img))) + candidates)) + +;; Same as `image-dired-get-thumbnail-image' but use +;; `helm-ff--image-dired-thumb-name' which cache thumbnails for further use. +(defun helm-ff--image-dired-get-thumbnail-image (file) + "Return the image descriptor for a thumbnail of image file FILE." + (unless (string-match-p (image-file-name-regexp) file) + (error "%s is not a valid image file" file)) + (let* ((thumb-file (helm-ff--image-dired-thumb-name file)) + (thumb-attr (file-attributes thumb-file))) + (when (or (not thumb-attr) + (time-less-p (file-attribute-modification-time thumb-attr) + (file-attribute-modification-time + (file-attributes file)))) + (image-dired-create-thumb file thumb-file)) + (create-image thumb-file))) + +(defvar helm-ff-image-dired-thumbnails-cache (make-hash-table :test 'equal) + "Store associations of image_file/thumbnail_file.") +(defun helm-ff--image-dired-thumb-name (file) + (or (gethash file helm-ff-image-dired-thumbnails-cache) + (let ((thumb-name (image-dired-thumb-name file))) + (puthash file thumb-name helm-ff-image-dired-thumbnails-cache) + thumb-name))) + +(defun helm-ff-toggle-thumbnails () + (interactive) + (cl-assert (null (file-remote-p helm-ff-default-directory)) + nil "Thumbnails show not supported on remote files") + (setq helm-ff--show-thumbnails (not helm-ff--show-thumbnails)) + (when (and (null helm-ff--show-thumbnails) + (member helm-ff-default-directory + helm-ff--thumbnailed-directories)) + (setq helm-ff--thumbnailed-directories + (delete helm-ff-default-directory helm-ff--thumbnailed-directories))) + (helm-update (regexp-quote (replace-regexp-in-string + "\\`[[:multibyte:] ]*" "" (helm-get-selection nil t))))) +(put 'helm-ff-toggle-thumbnails 'no-helm-mx t) + +;;;###autoload +(defun helm-ff-clear-image-dired-thumbnails-cache () + "Clear `helm-ff-image-dired-thumbnails-cache'. +You may want to do this after customizing +`image-dired-thumbnail-storage' which may change the place where +thumbnail files are stored." + (interactive) + (clrhash helm-ff-image-dired-thumbnails-cache)) + +;;;###autoload +(defun helm-ff-cleanup-image-dired-dir-and-cache () + "Cleanup `image-dired-dir' directory. +Delete all thumb files that are no more associated with an existing +image file in `helm-ff-image-dired-thumbnails-cache'." + (interactive) + (cl-loop for key being the hash-keys in helm-ff-image-dired-thumbnails-cache + using (hash-value val) + unless (file-exists-p key) do + (progn + (message "Deleting %s" val) + (delete-file val) + (remhash key helm-ff-image-dired-thumbnails-cache)))) + +;;; Recursive dirs completion +;; +(defun helm-find-files-recursive-dirs (directory &optional input) + (when (string-match "\\([.]\\)\\{2\\}" input) + (setq input (replace-match "" nil t input))) + (message "Recursively searching %s from %s ..." + input (abbreviate-file-name directory)) + ;; Ensure to not create a new frame + (let (helm-actions-inherit-frame-settings) + (helm :sources + (helm-make-source + "Recursive directories" 'helm-locate-subdirs-source + :basedir (if (string-match-p + "\\`es" helm-locate-recursive-dirs-command) + directory + (shell-quote-argument directory)) + :subdir (shell-quote-argument input) + :candidate-transformer + `((lambda (candidates) + (cl-loop for c in candidates + when (and (file-directory-p c) + (null (helm-boring-directory-p + c helm-boring-file-regexp-list)) + (string-match-p ,(regexp-quote input) + (helm-basename c))) + collect (propertize c 'face 'helm-ff-dirs))) + helm-w32-pathname-transformer + (lambda (candidates) + (helm-ff-sort-candidates-1 candidates ,input))) + :persistent-action 'ignore + :action (lambda (c) + (helm-set-pattern + (file-name-as-directory (expand-file-name c))))) + :candidate-number-limit 999999 + :allow-nest t + :resume 'noresume + :ff-transformer-show-only-basename nil + :buffer "*helm recursive dirs*"))) + +(defun helm-ff-recursive-dirs (_candidate) + "Launch a recursive search in `helm-ff-default-directory'." + (with-helm-default-directory helm-ff-default-directory + (helm-find-files-recursive-dirs + (helm-current-directory) + (helm-basename (helm-get-selection))))) + +(defun helm-ff-file-compressed-p (candidate) + "Whether CANDIDATE is a compressed file or not." + (member (file-name-extension candidate) + helm-ff-file-compressed-list)) + +(defun helm-ff--fname-at-point () + "Try to guess fname at point." + (let ((end (point)) + (limit (helm-aif (bounds-of-thing-at-point 'filename) + (car it) + (point)))) + (save-excursion + (while (re-search-backward "\\(~\\|/\\|[[:lower:][:upper:]]:/\\)" + limit t)) + (buffer-substring-no-properties (point) end)))) + +(defun helm-insert-file-name-completion-at-point (_candidate) + "Insert file name completion at point. + +When completing i.e. there is already something at point, insert +filename abbreviated, relative or full according to initial +input, whereas when inserting i.e. there is nothing at point, +insert filename full, abbreviated or relative according to prefix +arg, respectively no prefix arg, one prefix arg or two prefix +arg." + (with-helm-current-buffer + (if buffer-read-only + (error "Error: Buffer `%s' is read-only" (buffer-name)) + (let* ((mkds (helm-marked-candidates :with-wildcard t)) + (candidate (car mkds)) + (end (point)) + (tap (helm-ffap-guesser)) + (guess (and (stringp tap) + (substring-no-properties tap))) + (beg (helm-aif (and guess + (save-excursion + (when (re-search-backward + (regexp-quote guess) + (point-at-bol) t) + (point)))) + it (point))) + (full-path-p (and (stringp guess) + (or (string-match-p + (concat "^" (getenv "HOME")) + guess) + (string-match-p + "\\`\\(/\\|[[:lower:][:upper:]]:/\\)" + guess)))) + (escape-fn (if (memq major-mode + helm-modes-using-escaped-strings) + #'shell-quote-argument #'identity))) + (when (and beg end) + (delete-region beg end)) + (insert + (funcall + escape-fn + (helm-ff--format-fname-to-insert + candidate beg end full-path-p guess + helm-current-prefix-arg)) + (if (cdr mkds) " " "") + (mapconcat escape-fn + (cl-loop for f in (cdr mkds) + collect (helm-ff--format-fname-to-insert + f nil nil nil nil + helm-current-prefix-arg)) + " ")))))) + +(defun helm-ff--format-fname-to-insert (candidate + &optional beg end full-path guess prefarg) + (set-text-properties 0 (length candidate) nil candidate) + (if (and beg end guess (not (string= guess "")) + (null prefarg) + (or (string-match + "^\\(~/\\|/\\|[[:lower:][:upper:]]:/\\)" + guess) + (file-exists-p candidate))) + (cond (full-path + (expand-file-name candidate)) + ((string= (match-string 1 guess) "~/") + (abbreviate-file-name candidate)) + (t (file-relative-name candidate))) + (helm-acase prefarg + ('(4) (abbreviate-file-name candidate)) + ('(16) (file-relative-name candidate)) + ('(64) (helm-basename candidate)) + (t candidate)))) + +(cl-defun helm-find-files-history (arg &key (comp-read t)) + "The `helm-find-files' history. +Show the first `helm-ff-history-max-length' elements of +`helm-ff-history' in an `helm-comp-read'." + (interactive "p") + (let ((history (when helm-ff-history + (helm-fast-remove-dups helm-ff-history + :test 'equal)))) + (when history + (setq helm-ff-history + (if (>= (length history) helm-ff-history-max-length) + (helm-take history helm-ff-history-max-length) + history)) + (if comp-read + (let ((src (helm-build-sync-source "Helm Find Files History" + :candidates helm-ff-history + :fuzzy-match (helm-ff-fuzzy-matching-p) + :persistent-action 'ignore + :migemo t + :action (lambda (candidate) + (if arg + (helm-set-pattern + (expand-file-name candidate)) + (identity candidate)))))) + (helm :sources src + :resume 'noresume + :buffer helm-ff-history-buffer-name + :allow-nest t)) + helm-ff-history)))) +(put 'helm-find-files-history 'helm-only t) + +(defvar helm-ff-drag-mouse-1-default-action 'copy + "Default action when dragging files. +Possible values are `copy', `rsync' or `rename'.") + +(defvar helm-ff-drag-and-drop-default-directory nil + "Default directory where to drop files on a drag-and-drop action. +It is used when no suitable directory is found at drop place, +generally when dropping outside of an emacs frame. +You want generally to set this to your home desktop directory.") + +(defun helm-ff-drag-mouse-1-fn (event) + "Drag-and-drop function for `helm-find-files'. +Allows dropping marked files to another frame or window. +When dropping to another frame (i.e. not the selected one where helm +is running), you are asked for which directory you want to drop to when frame +displays more than one window. +When no suitable place to drop is found ask to drop to +`helm-ff-drag-and-drop-default-directory' if set." + (interactive "e") + (cl-assert (memq helm-ff-drag-mouse-1-default-action + '(copy rsync rename))) + (let* ((win-or-frame (posn-window (event-end event))) + (target-frame (when (framep win-or-frame) + (car (mouse-pixel-position)))) + (target (with-selected-window + (if target-frame + (frame-selected-window target-frame) + win-or-frame) + default-directory)) + (windows (and target-frame + (remove (helm-window) + (window-list target-frame 1))))) + (when windows + (setq target + (helm-acond ((cdr windows) + (x-popup-menu + t (list "Choose target" + (cons "" + (cl-loop for win in windows + for dir = (with-selected-window + win default-directory) + collect (cons dir dir)))))) + ((and (eql (window-buffer (car windows)) + helm-current-buffer) + helm-ff-drag-and-drop-default-directory) + (x-popup-menu + t (list "Choose target" + (cons "" + (list (cons it it)))))) + ((car windows) + (with-selected-window it default-directory))))) + (if (memq helm-ff-drag-mouse-1-default-action '(copy rsync)) + (helm-find-files-do-action + helm-ff-drag-mouse-1-default-action target) + (helm-run-after-exit + #'helm-find-files-do-action + helm-ff-drag-mouse-1-default-action target)))) + +(defun helm-find-files-1 (fname &optional preselect) + "Find FNAME filename with PRESELECT filename preselected. + +Use it for non-interactive calls of `helm-find-files'." + (require 'tramp) + (unless (featurep 'all-the-icons) + (helm-ff-icon-mode -1)) + ;; Resolve FNAME now outside of helm. + ;; [FIXME] When `helm-find-files-1' is used directly from lisp + ;; and FNAME is an abbreviated path, for some reasons + ;; `helm-update' is called many times before resolving + ;; the abbreviated path (Bug#1939) so be sure to pass a + ;; full path to helm-find-files-1. + (unless (string-match-p helm-ff-url-regexp fname) + (setq fname (expand-file-name (substitute-in-file-name fname)))) + (when (get-buffer helm-action-buffer) + (kill-buffer helm-action-buffer)) + (setq helm-find-files--toggle-bookmark nil) + (let* ( ;; Be sure we don't erase the precedent minibuffer if some. + (helm-ff-auto-update-initial-value + (and helm-ff-auto-update-initial-value + (not (minibuffer-window-active-p (minibuffer-window))))) + (tap (thing-at-point 'filename)) + (def (and tap (or (file-remote-p tap) + (expand-file-name tap)))) + ;; Ensure not being prompted for password each time we + ;; navigate to a directory. + (password-cache t) + (minibuffer-completing-file-name t)) + (helm-set-local-variable 'helm-follow-mode-persistent nil + 'helm-drag-mouse-1-fn 'helm-ff-drag-mouse-1-fn) + (unless helm-source-find-files + (setq helm-source-find-files (helm-make-source + "Find Files" 'helm-source-ffiles))) + (when (helm-get-attr 'follow helm-source-find-files) + (helm-set-attr 'follow -1 helm-source-find-files)) + ;; If preselected candidate is further than `helm-ff-candidate-number-limit' + ;; in the directory file list, we have to increase `candidate-number-limit' + ;; attr to have this candidate visible for preselection. NOTE: + ;; When HFF has yet not been launched in this directory the maximum length + ;; of this directory is unknown and candidate will NOT be selected until + ;; next time we call HFF on this same buffer. + (helm-aif (and preselect + (not helm-ff-preselect-ignore-large-dirs) + (gethash fname helm-ff--directory-files-length + helm-ff-candidate-number-limit)) + (helm-set-attr 'candidate-number-limit + (max it helm-ff-candidate-number-limit) + helm-source-find-files)) + (helm-ff-setup-update-hook) + (add-hook 'helm-resume-after-hook 'helm-ff--update-resume-after-hook) + (unwind-protect + (helm :sources 'helm-source-find-files + :input fname + :case-fold-search helm-file-name-case-fold-search + :preselect preselect + :ff-transformer-show-only-basename + helm-ff-transformer-show-only-basename + :default def + :prompt "Find files or url: " + :buffer "*helm find files*") + (helm-ff--update-resume-after-hook nil t) + (setq helm-ff-default-directory nil)))) + +(defun helm-ff--update-resume-after-hook (sources &optional nohook) + "Meant to be used in `helm-resume-after-hook'. +When NOHOOK is non-nil run inconditionally, otherwise only when +source is `helm-source-find-files'." + (when (or nohook (string= "Find Files" + (assoc-default 'name (car sources)))) + (helm-set-attr 'resume `(lambda () + (helm-ff-setup-update-hook) + (setq helm-ff-default-directory + ,helm-ff-default-directory + helm-ff-last-expanded + ,helm-ff-last-expanded)) + helm-source-find-files))) + +(defun helm-ff-clean-initial-input () + ;; When using hff in an external frame initial input is printed in + ;; the minibuffer of initial-frame, delete it. + (with-selected-frame helm-initial-frame + (helm-clean-up-minibuffer))) + +(defun helm-ff-setup-update-hook () + (dolist (hook '(helm-ff-clean-initial-input ; Add to be called first. + helm-ff-move-to-first-real-candidate + helm-ff-update-when-only-one-matched + helm-ff-auto-expand-to-home-or-root)) + (add-hook 'helm-after-update-hook hook))) + +(defun helm-find-files-cleanup () + (mapc (lambda (hook) + (remove-hook 'helm-after-update-hook hook)) + '(helm-ff-auto-expand-to-home-or-root + helm-ff-update-when-only-one-matched + helm-ff-move-to-first-real-candidate + helm-ff-clean-initial-input)) + (setq helm-ff--show-directories-only nil + helm-ff--show-files-only nil + helm-ff--show-thumbnails nil + helm-ff--thumbnailed-directories nil) + (helm-ff-clean-image-cache)) + +(defun helm-ff-bookmark () + (helm :sources 'helm-source-bookmark-helm-find-files + :buffer "*helm ff bookmarks*")) + +(defun helm-find-files-switch-to-bookmark () + "Switch to helm-bookmark for `helm-find-files' from `helm-find-files.'" + (interactive) + (require 'helm-bookmark) + (with-helm-alive-p + (helm-run-after-exit 'helm-ff-bookmark))) +(put 'helm-find-files-switch-to-bookmark 'helm-only t) + +(defun helm-find-files-initial-input (&optional input) + "Return INPUT if present, otherwise try to guess it." + (let ((guesser (helm-acase (helm-ffap-guesser) + ("" nil) + (t it)))) + (unless (eq major-mode 'image-mode) + (if input + (if (or (file-remote-p input) + (string-match helm-ff-url-regexp input)) + input + (expand-file-name input)) + (helm-find-files-input + (if (and helm-ff-allow-non-existing-file-at-point + guesser + (not (string-match ffap-url-regexp guesser))) + ;; Keep the ability of jumping to numbered lines even + ;; when allowing non existing filenames at point. + (helm-aand guesser + (thing-at-point 'filename) + (replace-regexp-in-string + ":[0-9]+\\'" "" it)) + guesser) + (thing-at-point 'filename)))))) + +(defun helm-ffap-guesser () + "Same as `ffap-guesser' but without gopher and machine support." + (require 'ffap) + ;; Avoid "Stack overflow in regexp matcher" error + ;; in evil `ffap-guesser' by removing crap `ffap-gopher-at-point' + ;; (bug fixed in emacs-26 http://debbugs.gnu.org/cgi/bugreport.cgi?bug=25391) . + ;; `ffap-machine-at-point' have been removed too as it was anyway + ;; disabled with `ffap-machine-p-known' bound to 'reject. + ;; `ffap-file-at-point' can be neutralized with + ;; `helm-ff-guess-ffap-filenames' and `ffap-url-at-point' with + ;; `helm-ff-guess-ffap-urls' + ;; Note also that `ffap-url-unwrap-remote' can override these + ;; variables. + (let ((ffap-alist (and helm-ff-guess-ffap-filenames ffap-alist)) + (ffap-url-regexp helm--url-regexp)) + (if (eq major-mode 'dired-mode) + (let ((beg (save-excursion (dired-move-to-filename))) + (end (save-excursion (dired-move-to-end-of-filename t)))) + (helm-aif (and beg end (member (buffer-substring beg end) + '("." ".."))) + (concat (file-name-as-directory + (expand-file-name dired-directory)) + (car it)) + (dired-get-filename 'no-dir t))) + (let* ((beg (and (use-region-p) (region-beginning))) + (end (and (use-region-p) (region-end))) + (str (and beg end (buffer-substring-no-properties beg end))) + (ffap (or (helm-aand helm-ff-guess-ffap-urls ffap-url-regexp + (ffap-url-at-point) + (ffap-fixup-url it) + (and (string-match ffap-url-regexp it) it)) + (ffap-file-at-point)))) + ;; Workaround emacs bugs: + ;; When the region is active and a file is detected + ;; `ffap-string-at-point' returns the region prefixed with + ;; "/", e.g. at a beginning of a patch (first bug) and make + ;; `file-remote-p' returning an error (second bug), so in such + ;; case returns the region itself instead of the region + ;; corrupted by ffap. + (if (and str ffap) str ffap))))) + +(defun helm-find-files-input (file-at-pt thing-at-pt) + "Try to guess a default input for `helm-find-files'." + (let* ((non-essential t) + (remp (or (and file-at-pt (file-remote-p file-at-pt)) + (and thing-at-pt (file-remote-p thing-at-pt)))) + (def-dir (helm-current-directory)) + (urlp (and file-at-pt helm--url-regexp + (string-match helm--url-regexp file-at-pt))) + (lib (when helm-ff-search-library-in-sexp + (helm-find-library-at-point))) + (hlink (helm-ff-find-url-at-point)) + (file-p (and file-at-pt + (not (string= file-at-pt "")) + (not remp) + (or (file-exists-p file-at-pt) + helm-ff-allow-non-existing-file-at-point) + (not urlp) + thing-at-pt + (not (string= thing-at-pt "")) + (file-exists-p + (file-name-directory + (expand-file-name thing-at-pt def-dir)))))) + (cond (lib) ; e.g we are inside a require sexp. + (hlink) ; String at point is an hyperlink. + (file-p ; a regular file + (and file-at-pt (if (not (member (helm-basename file-at-pt) + '("." ".."))) + (expand-file-name file-at-pt) + file-at-pt))) + (urlp (helm-html-decode-entities-string file-at-pt)) ; possibly an url or email. + ((and file-at-pt + (not remp) + (or helm-ff-allow-non-existing-file-at-point + (file-exists-p file-at-pt))) + (expand-file-name file-at-pt))))) + +(defun helm-ff-find-url-at-point () + "Try to find link to an url in text-property at point." + (let* ((he (get-text-property (point) 'help-echo)) + (ov (overlays-at (point))) + (ov-he (and ov (overlay-get + (car (overlays-at (point))) 'help-echo))) + (w3m-l (get-text-property (point) 'w3m-href-anchor)) + (nt-prop (get-text-property (point) 'nt-link))) + ;; Org link. + (when (and (stringp he) (string-match "^LINK: " he)) + (setq he (replace-match "" t t he))) + (cl-loop for i in (list he ov-he w3m-l nt-prop) + thereis (and (stringp i) helm--url-regexp (string-match helm--url-regexp i) i)))) + +(defun helm-find-library-at-point () + "Try to find library path at point. +Find inside `require' and `declare-function' sexp." + (require 'find-func) + (let* ((beg-sexp (save-excursion (search-backward "(" (point-at-bol) t))) + (end-sexp (save-excursion (ignore-errors (end-of-defun)) (point))) + (sexp (and beg-sexp end-sexp + (buffer-substring-no-properties + (1+ beg-sexp) (1- end-sexp))))) + (ignore-errors + (cond (;; Should work only when point is on the use-package line + ;; i.e. first line of sexp otherwise it prevents matching + ;; urls with helm-find-files (bug #2469). + (and sexp (string-match "use-package +\\([^ )\n]+\\)" sexp)) + (find-library-name (match-string 1 sexp))) + ((and sexp (string-match "require +[']\\([^ )]+\\)" sexp)) + ;; If require use third arg, ignore it, + ;; always use library path found in `load-path'. + (find-library-name (match-string 1 sexp))) + ;; Assume declare-function sexps are on one line. + ((and sexp (string-match "declare-function .+? \"\\(?:ext:\\)?\\([^ )]+\\)\"" sexp)) + (find-library-name (match-string 1 sexp))) + (t nil))))) + + +;;; Handle copy, rename, symlink, relsymlink and hardlink from helm. +;; +;; +(defun helm-ff--valid-default-directory () + (with-helm-current-buffer + (cl-loop for b in (buffer-list) + for cd = (with-current-buffer b default-directory) + when (eq (car (file-attributes cd)) t) + return cd))) + +(cl-defun helm-dired-action (destination + &key action follow (files (dired-get-marked-files))) + "Execute ACTION on FILES to DESTINATION. +Where ACTION is a symbol that can be one of: +\\='copy', \\='rename', \\='symlink', \\='relsymlink', \\='hardlink' or \\='backup'. +Argument FOLLOW when non-nil specifies to follow FILES to +DESTINATION for the actions copy and rename." + (require 'dired-async) + (require 'dired-x) ; For dired-keep-marker-relsymlink + (when (get-buffer dired-log-buffer) (kill-buffer dired-log-buffer)) + ;; When default-directory in current-buffer is an invalid directory, + ;; (e.g buffer-file directory have been renamed somewhere else) + ;; be sure to use a valid value to give to dired-create-file. + ;; i.e start-process is creating a process buffer based on default-directory. + (let ((default-directory (helm-ff--valid-default-directory)) + (fn (cl-case action + (copy 'dired-copy-file) + (rename 'dired-rename-file) + (symlink 'make-symbolic-link) + (relsymlink 'dired-make-relative-symlink) + (hardlink 'dired-hardlink) + (backup 'backup-file))) + (marker (cl-case action + ((copy rename backup) dired-keep-marker-copy) + (symlink dired-keep-marker-symlink) + (relsymlink dired-keep-marker-relsymlink) + (hardlink dired-keep-marker-hardlink))) + (dirflag (and (= (length files) 1) + (file-directory-p (car files)) + (not (file-directory-p destination)))) + (dired-async-state (if (and (boundp 'dired-async-mode) + dired-async-mode) + 1 -1))) + (and follow (fboundp 'dired-async-mode) (dired-async-mode -1)) + (when (and (cdr files) (not (file-directory-p destination))) + (error "%s: target `%s' is not a directory" action destination)) + (unwind-protect + (dired-create-files + fn (symbol-name action) files + (if (file-directory-p destination) + ;; When DESTINATION is a directory, build file-name in this directory. + ;; Else we use DESTINATION. + (lambda (from) + (expand-file-name (file-name-nondirectory from) destination)) + (lambda (_from) destination)) + marker) + (and (fboundp 'dired-async-mode) + (dired-async-mode dired-async-state))) + (push (file-name-as-directory + (if (file-directory-p destination) + (expand-file-name destination) + (file-name-directory destination))) + helm-ff-history) + ;; If follow is non--nil we should not be in async mode. + (when (and follow + (not (memq action '(symlink relsymlink hardlink))) + (not (get-buffer dired-log-buffer))) + (let ((target (directory-file-name destination)) + (cands-to-mark (helm-get-dest-fnames-from-list files destination dirflag))) + (with-helm-after-update-hook (helm-ff-maybe-mark-candidates cands-to-mark)) + ;; Wait for the notify callback ends before calling HFF. + (run-at-time + 0.1 nil + (lambda () + (if (and dirflag (eq action 'rename)) + (helm-find-files-1 (file-name-directory target) + (format helm-ff-last-expanded-candidate-regexp + (if helm-ff-transformer-show-only-basename + (helm-basename target) target))) + (helm-find-files-1 (if (file-directory-p destination) + (file-name-as-directory + (expand-file-name destination)) + (expand-file-name (helm-basedir destination))) + (format helm-ff-last-expanded-candidate-regexp + (if helm-ff-transformer-show-only-basename + (helm-basename (car files)) + (car files))))))))))) + +(defun helm-get-dest-fnames-from-list (flist dest-cand rename-dir-flag) + "Transform filenames of FLIST to abs of DEST-CAND. +If RENAME-DIR-FLAG is non-nil collect the `directory-file-name' +of transformed members of FLIST." + ;; At this point files have been renamed/copied at destination. + ;; That's mean DEST-CAND exists. + (cl-loop + with dest = (expand-file-name dest-cand) + for src in flist + for basename-src = (helm-basename src) + for fname = (cond (rename-dir-flag (directory-file-name dest)) + ((file-directory-p dest) + (concat (file-name-as-directory dest) basename-src)) + (t dest)) + when (file-exists-p fname) + collect fname into tmp-list + finally return (sort tmp-list 'string<))) + +(defun helm-ff-maybe-mark-candidates (seq) + "Add visible mark to all candidates in SEQ. +This is used when copying/renaming/symlinking etc. and following +files to destination." + (when (and (string= (assoc-default 'name (helm-get-current-source)) + (assoc-default 'name helm-source-find-files)) + seq) + (with-helm-window + (while seq + (if (string= (car seq) (helm-get-selection)) + (progn + (helm-make-visible-mark) + (helm-next-line) + (setq seq (cdr seq))) + (helm-next-line))) + (unless (helm-this-visible-mark) + (helm-prev-visible-mark))))) + + +;;; Delete and trash files +;; +;; +(defun helm-file-buffers (filename) + "Return a list of buffer names corresponding to FILENAME." + (cl-loop with name = (expand-file-name filename) + for buf in (buffer-list) + for bfn = (buffer-file-name buf) + when (and bfn (string= name bfn)) + collect (buffer-name buf))) + +(defun helm-ff--delete-by-moving-to-trash (file) + "Decide to trash or delete FILE. +Return non-nil when FILE needs to be trashed." + (let ((remote (file-remote-p file))) + (or + (and delete-by-moving-to-trash + (null helm-current-prefix-arg) + (null current-prefix-arg) + (or (and remote helm-trash-remote-files) + (null remote))) + (and (null delete-by-moving-to-trash) + (or helm-current-prefix-arg + current-prefix-arg) + (or (and remote helm-trash-remote-files) + (null remote)))))) + +(defun helm-trash-directory () + "Try to find a trash directory. +Return the \"files\" subdirectory of trash directory. +When `helm-trash-default-directory' is set use it as trash directory." + (let* ((xdg-data-dir + (or helm-trash-default-directory + (directory-file-name + (expand-file-name "Trash" + (or (getenv "XDG_DATA_HOME") + "~/.local/share"))))) + (trash-files-dir (expand-file-name "files" xdg-data-dir))) + ;; Just return nil if the Trash directory is not yet created. It will be + ;; created later by `delete-directory'. + (and (file-exists-p trash-files-dir) trash-files-dir))) + +(cl-defun helm-ff-file-already-trashed (file &optional (trash-alist nil strash-alist)) + "Return FILE when it is already in trash. + +Optional arg TRASH-ALIST should be an alist as what +`helm-ff-trash-list' returns." + (unless (or (fboundp 'system-move-file-to-trash) + (and strash-alist (null trash-alist))) + (let ((trash-files-dir (helm-trash-directory))) + (cl-loop for (_bn . fn) in (or trash-alist + (helm-ff-trash-list trash-files-dir)) + thereis (file-equal-p file fn))))) + +(defun helm-ff-quick-delete (_candidate) + "Delete file CANDIDATE without quitting. + +When a prefix arg is given, meaning of +`delete-by-moving-to-trash' is the opposite." + (with-helm-window + (let* ((marked (helm-marked-candidates)) + (trash (helm-ff--delete-by-moving-to-trash (car marked))) + (helm-ff--trashed-files + (and trash (helm-ff-trash-list (helm-trash-directory))))) + (unwind-protect + (cl-loop for c in marked do + (progn (helm-preselect + (format helm-ff-last-expanded-candidate-regexp + (regexp-quote + (if (and helm-ff-transformer-show-only-basename + (not (helm-ff-dot-file-p c))) + (helm-basename c) c)))) + (when (y-or-n-p + (format "Really %s file `%s'? " + (if trash "Trash" "Delete") + (abbreviate-file-name c))) + (helm-acase (helm-delete-file + c helm-ff-signal-error-on-dot-files 'synchro trash) + (skip + ;; This happens only when trying to + ;; trash a file already trashed. + (helm-delete-visible-mark (helm-this-visible-mark)) + (if (helm-end-of-source-p) + (helm-previous-line) + (helm-next-line))) + (t (helm-delete-current-selection))) + (message nil) + (helm--remove-marked-and-update-mode-line c)))) + (setq helm-marked-candidates nil + helm-visible-mark-overlays nil) + (helm-force-update + (let ((presel (helm-get-selection))) + (when presel + (format helm-ff-last-expanded-candidate-regexp + (regexp-quote (if (and helm-ff-transformer-show-only-basename + (not (helm-ff-dot-file-p presel))) + (helm-basename presel) presel)))))))))) + +(defun helm-delete-file (file &optional error-if-dot-file-p synchro trash) + "Delete FILE after querying the user. + +When a prefix arg is given, meaning of +`delete-by-moving-to-trash' is the opposite. + +Return error when ERROR-IF-DOT-FILE-P is non-nil and user tries +to delete a dotted file i.e. \".\" or \"..\". + +Ask user when directory are not empty to allow recursive deletion +unless `helm-ff-allow-recursive-deletes' is non nil. +When user is asked and reply with \"!\" don't ask for remaining +directories. + +Ask to kill buffers associated with that file, too. + +When TRASH is non nil, trash FILE even if `delete-by-moving-to-trash' +is nil." + (require 'dired) + (cl-block nil + (when (and error-if-dot-file-p + (helm-ff-dot-file-p file)) + (error "Error: Cannot operate on `.' or `..'")) + (let ((buffers (helm-file-buffers file)) + (helm--reading-passwd-or-string t) + (file-attrs (file-attributes file)) + (trash (or trash (helm-ff--delete-by-moving-to-trash file))) + (delete-by-moving-to-trash trash) + (already-trashed + (and trash (helm-ff-file-already-trashed + file helm-ff--trashed-files)))) + (cond (already-trashed + ;; We use message here to avoid exiting loop when + ;; deleting more than one file. + (message "User error: `%s' is already trashed" file) + (sit-for 1.5) + (cl-return 'skip)) + ((and (eq (nth 0 file-attrs) t) + (directory-files file t directory-files-no-dot-files-regexp)) + ;; Synchro means persistent deletion from HFF. + (if synchro + (when (or helm-ff-allow-recursive-deletes + trash + (y-or-n-p (format "Recursive delete of `%s'? " + (abbreviate-file-name file)))) + (delete-directory file 'recursive trash)) + ;; Avoid using dired-delete-file really annoying in + ;; emacs-26 but allows using ! (instead of all) to not + ;; confirm anymore for recursive deletion of + ;; directory. This is not persistent for all session + ;; like emacs-26 does with dired-delete-file (think it + ;; is a bug). + (if (or helm-ff-allow-recursive-deletes trash) + (delete-directory file 'recursive trash) + (helm-acase (helm-read-answer (format "Recursive delete of `%s'? [y,n,!,q]" + (abbreviate-file-name file)) + '("y" "n" "!" "q")) + ("y" (delete-directory file 'recursive trash)) + ("!" (setq helm-ff-allow-recursive-deletes t) + (delete-directory file 'recursive trash)) + ("n" (cl-return 'skip)) + ("q" (throw 'helm-abort-delete-file + (progn + (message "Abort file deletion") (sleep-for 1)))))))) + ((eq (nth 0 file-attrs) t) + (delete-directory file nil trash)) + (t (delete-file file trash))) + (when buffers + (dolist (buf buffers) + (when (y-or-n-p (format "Kill buffer %s, too? " buf)) + (kill-buffer buf))))))) + +(defun helm-delete-marked-files (_ignore) + "Delete marked files with `helm-delete-file'. + +When a prefix arg is given, meaning of +`delete-by-moving-to-trash' is the opposite." + (let* ((files (helm-marked-candidates :with-wildcard t)) + (len 0) + (trash (helm-ff--delete-by-moving-to-trash (car files))) + (helm-ff--trashed-files + (and trash (helm-ff-trash-list (helm-trash-directory)))) + (prmt (if trash "Trash" "Delete")) + (old--allow-recursive-deletes helm-ff-allow-recursive-deletes)) + (with-helm-display-marked-candidates + helm-marked-buffer-name + (helm-ff--count-and-collect-dups files) + (if (not (y-or-n-p (format "%s *%s File(s)" prmt (length files)))) + (message "(No deletions performed)") + (catch 'helm-abort-delete-file + (unwind-protect + (dolist (i files) + (set-text-properties 0 (length i) nil i) + (let ((res (helm-delete-file + i helm-ff-signal-error-on-dot-files nil trash))) + (if (eq res 'skip) + (progn (message "Directory is not empty, skipping") + (sleep-for 1)) + (cl-incf len)))) + (setq helm-ff-allow-recursive-deletes old--allow-recursive-deletes))) + (message "%s File(s) %s" len (if trash "trashed" "deleted")))))) + +;;; Delete files async +;; +;; +(defvar helm-ff-delete-log-file + (locate-user-emacs-file "helm-delete-file.log") + "The file use to communicate with Emacs child when deleting files async.") + +(defvar helm-ff--trash-flag nil) + +(define-minor-mode helm-ff--delete-async-modeline-mode + "Notify mode-line that an async process run." + :group 'dired-async + :global t + ;; FIXME: Handle jobs like in dired-async, needs first to allow + ;; naming properly processes in async, they are actually all named + ;; emacs and running `async-batch-invoke', so if one copy a file and + ;; delete another file at the same time it may clash. + :lighter (:eval (propertize (format " %s file(s) async ..." + (if helm-ff--trash-flag + "Trashing" "Deleting")) + 'face 'helm-delete-async-message)) + (unless helm-ff--delete-async-modeline-mode + (let ((visible-bell t)) (ding)) + (setq helm-ff--trash-flag nil))) + +(defun helm-delete-async-mode-line-message (text face &rest args) + "Notify end of async operation in mode-line." + (message nil) + (let ((mode-line-format (concat + " " (propertize + (if args + (apply #'format text args) + text) + 'face face)))) + (force-mode-line-update) + (sit-for 3) + (force-mode-line-update))) + +(defun helm-delete-async-kill-process () + "Kill async process created by helm delete files async." + (interactive) + (let* ((processes (dired-async-processes)) + (proc (car (last processes)))) + (and proc (delete-process proc)) + (unless (> (length processes) 1) + (helm-ff--delete-async-modeline-mode -1)))) + +(defun helm-delete-marked-files-async (_ignore) + "Same as `helm-delete-marked-files' but async. + +When a prefix arg is given, meaning of +`delete-by-moving-to-trash' is the opposite. + +This function is not using `helm-delete-file' and BTW not asking +user for recursive deletion of directory, be warned that +directories are always deleted with no warnings." + (let* ((files (helm-marked-candidates :with-wildcard t)) + (trash (helm-ff--delete-by-moving-to-trash (car files))) + (prmt (if trash "Trash" "Delete")) + buffers callback already-trashed + ;; Workaround emacs-26 bug with tramp see + ;; https://github.com/jwiegley/emacs-async/issues/80. + (async-quiet-switch "-q")) + (cl-loop with trash-alist = (and trash (helm-ff-trash-list (helm-trash-directory))) + for f in files + for buf = (helm-file-buffers f) + for trashed = (helm-ff-file-already-trashed f trash-alist) + for dot-file-p = (helm-ff-dot-file-p f) + when (and helm-ff-signal-error-on-dot-files + dot-file-p) + do (cl-return (error "Error: Cannot operate on `.' or `..'")) + when buf + do (setq buffers (nconc buf buffers)) + when trashed + do (push trashed already-trashed)) + (setq callback (lambda (result) + (helm-ff--delete-async-modeline-mode -1) + (when (file-exists-p helm-ff-delete-log-file) + (display-warning 'helm + (with-temp-buffer + (insert-file-contents + helm-ff-delete-log-file) + (buffer-string)) + :error + "*helm delete files*") + (fit-window-to-buffer (get-buffer-window + "*helm delete files*")) + (delete-file helm-ff-delete-log-file)) + (when buffers + (helm-read-answer-dolist-with-action + "Kill buffer `%s', too? " + buffers #'kill-buffer)) + (run-with-timer + 0.1 nil + (lambda () + (helm-delete-async-mode-line-message + "%s (%s/%s) file(s) async done" + 'helm-delete-async-message + (if trash "Trashing" "Deleting") + result (length files)))))) + (setq helm-ff--trash-flag trash) + (with-helm-display-marked-candidates + helm-marked-buffer-name + (helm-ff--count-and-collect-dups files) + (if (not (y-or-n-p (format "%s *%s File(s)" prmt (length files)))) + (message "(No deletions performed)") + (async-start + `(lambda () + (require 'cl-lib) + ;; `delete-by-moving-to-trash' have to be set globally, + ;; using the TRASH argument of delete-file or + ;; delete-directory is not enough. + (setq delete-by-moving-to-trash ,trash) + (let ((result 0)) + (dolist (file ',files result) + (condition-case err + (cond ((and ,trash + (cl-loop for f in ',already-trashed + thereis (file-equal-p f file))) + (error (format "`%s' is already trashed" file))) + ((eq (nth 0 (file-attributes file)) t) + (delete-directory file 'recursive ,trash) + (setq result (1+ result))) + (t (delete-file file ,trash) + (setq result (1+ result)))) + (error (with-temp-file ,helm-ff-delete-log-file + (insert (format-time-string "%x:%H:%M:%S\n")) + (insert (format "%s:%s\n " + (car err) + (mapconcat 'identity (cdr err) " "))))))))) + callback) + (helm-ff--delete-async-modeline-mode 1))))) + +(defun helm-find-file-or-marked (candidate) + "Open file CANDIDATE or open helm marked files in separate windows. +Called with one prefix arg open files in separate windows in a +vertical split. +Called with two prefix arg open files in background without +selecting them." + (let ((marked (helm-marked-candidates :with-wildcard t)) + (url-p (and helm--url-regexp ; we should have only one candidate. + (string-match helm--url-regexp candidate))) + (ffap-newfile-prompt helm-ff-newfile-prompt-p) + (find-file-wildcards nil) + (helm--reading-passwd-or-string t)) + (if (cdr marked) + (if (equal helm-current-prefix-arg '(16)) + (mapcar 'find-file-noselect marked) + ;; If helm-current-prefix-arg is detected split is done + ;; vertically. + (helm-window-show-buffers (mapcar 'find-file-noselect marked))) + (let ((dir (and (not url-p) (helm-basedir candidate)))) + (cond ((and dir (file-directory-p dir)) + (find-file (substitute-in-file-name candidate))) + (url-p (find-file-at-point candidate)) + ;; A a non--existing filename ending with / + ;; Create a directory and jump to it. + ((and (not (file-exists-p candidate)) + (string-match "/$" candidate)) + (helm-ff--mkdir candidate 'helm-ff)) + ;; A non--existing filename NOT ending with / or + ;; an existing filename, create or jump to it. + ;; If the basedir of candidate doesn't exists, + ;; ask for creating it. + (dir + (helm-ff--mkdir dir) + (find-file candidate)) + ;; Find file at `default-directory' when basedir is + ;; unspecified e.g user hit C-k foo RET. + (t (find-file candidate))))))) + +(helm-make-command-from-action helm-ff-find-file-other-tab + "Run find file in other tab action from `helm-source-buffers-list'." + 'find-file-other-tab + (cl-assert (fboundp 'tab-bar-mode) nil "Tab-bar-mode not available")) + +(defun helm-ff--new-dirs-to-update (path) + "Collect directories to update when creating new directory PATH." + (let ((result (list path))) + (helm-awhile (helm-reduce-file-name path 1) + (if (not (file-directory-p it)) + (progn (push it result) (setq path it)) + (push it result) + (cl-return))) + result)) + +(defun helm-ff--mkdir (dir &optional helm-ff) + (when (or (not confirm-nonexistent-file-or-buffer) + (y-or-n-p (format "Create directory `%s'? " + (abbreviate-file-name + (expand-file-name dir))))) + (let ((dirfname (directory-file-name dir)) + (to-update (and helm-ff (helm-ff--new-dirs-to-update dir)))) + (if (file-exists-p dirfname) + (error + "Mkdir: Unable to create directory `%s': file exists." + (helm-basename dirfname)) + (make-directory dir 'parent)) + (when helm-ff + ;; Refresh cache. + (mapc (lambda (x) (helm-ff-directory-files x t)) to-update) + ;; Allow having this new dir in history + ;; to be able to retrieve it immediately + ;; if we want to e.g copy a file from somewhere in it. + (setq helm-ff-default-directory + (file-name-as-directory (expand-file-name dir))) + (push helm-ff-default-directory helm-ff-history)) + (or (and helm-ff (helm-find-files-1 dir)) t)))) + +(defun helm-transform-file-load-el (actions candidate) + "Add action to load the file CANDIDATE if it is an Emacs Lisp +file. Else return ACTIONS unmodified." + (if (member (file-name-extension candidate) '("el" "elc")) + (append actions '(("Load Emacs Lisp File" . load-file))) + actions)) + +(defun helm-transform-file-browse-url (actions candidate) + "Add an action to browse the file CANDIDATE if it is a HTML file or URL. +Else return ACTIONS unmodified." + (let ((browse-action '("Browse with Browser" . browse-url))) + (cond ((string-match "^http\\|^ftp" candidate) + (cons browse-action actions)) + ((string-match "\\.html?$" candidate) + (append actions (list browse-action))) + (t actions)))) + +(defun helm-file-on-mounted-network-p (file) + "Return non-nil when FILE is part of a mounted remote directory. + +This function is checking `helm-mounted-network-directories' +list." + (when helm-mounted-network-directories + (cl-loop for dir in helm-mounted-network-directories + thereis (file-in-directory-p file dir)))) + +;; helm-find-files bindings for filecache +(defvar file-cache-alist) + +(defun helm-ff-cache-add-file (_candidate) + (require 'filecache) + (let ((mkd (helm-marked-candidates :with-wildcard t))) + (mapc 'file-cache-add-file mkd))) + +(defun helm-ff-file-cache-remove-file-1 (file) + "Remove FILE from `file-cache-alist'." + (let ((entry (assoc (helm-basename file) file-cache-alist)) + (dir (helm-basedir file)) + new-entry) + (setq new-entry (remove dir entry)) + (when (= (length entry) 1) + (setq new-entry nil)) + (setq file-cache-alist + (cons new-entry (remove entry file-cache-alist))))) + +(defun helm-ff-file-cache-remove-file (_file) + "Remove marked files from `file-cache-alist.'" + (let ((mkd (helm-marked-candidates))) + (mapc 'helm-ff-file-cache-remove-file-1 mkd))) + +;;; Find files in file +;; +;; +(defclass helm-find-files-in-file-class (helm-source-in-file helm-type-file) ()) +(cl-defmethod helm--setup-source ((source helm-find-files-in-file-class)) + (helm-aif (slot-value source 'candidate-transformer) + (setf (slot-value source 'candidate-transformer) + (append (helm-mklist it) + (list (lambda (candidates) + (cl-loop for c in candidates + when (and (not (string= c "")) + (file-exists-p c)) + collect c))))))) + +(defun helm-find-files-in-file-build-source (file) + (helm-make-source + (format "Find files in `%s'" (helm-basename file)) + 'helm-find-files-in-file-class + :candidates-file file)) + +(defun helm-find-files-in-file (_file) + "Helm action for listing filenames listed in marked files." + (require 'helm-for-files) + (let ((sources (cl-loop for f in (helm-marked-candidates) + collect (helm-find-files-in-file-build-source f)))) + (helm :sources sources + :quit-if-no-candidate (lambda () + (message "No files found in file(s)")) + :buffer "*helm find files in files*"))) + +(cl-defun helm-ff-mcp (_candidate) + "Copy the car of marked candidates to the remaining marked candidates. + +The car of marked should be a regular file and the rest of marked (cdr) should +be directories." + (let* ((mkd (helm-marked-candidates)) + (file (car mkd)) + (targets (cdr mkd)) + (skipped 0) + operations) + (cl-assert (file-regular-p file) nil (format "ERROR: Not a regular file `%s'" file)) + (cl-assert targets nil (format "ERROR: No destination specified for file `%s'" file)) + (cl-assert (cl-loop for f in targets always (file-directory-p f)) nil + "ERROR: Destinations must be directories") + (when targets + (cl-loop with yes-for-all + for dest in targets + for dest-file = (expand-file-name (helm-basename file) dest) + for dir-ok = (file-accessible-directory-p dest) + for exists = (and dir-ok + (file-exists-p + (expand-file-name + (helm-basename file) dest))) + for overwrite = (or (null exists) + yes-for-all + (pcase (helm-read-answer + (format + "File `%s' already-exists, overwrite (y,n,!,q) ? " + dest-file) + '("y" "n" "!" "q")) + ("y" t) + ("n" nil) + ("!" (prog1 t + (setq yes-for-all t))) + ("q" (cl-return-from helm-ff-mcp + (message "Operation aborted"))))) + if dir-ok + do (if overwrite + (push (list file (file-name-as-directory dest) overwrite) operations) + (cl-incf skipped)) + else do (cl-incf skipped)) + (when operations + (with-helm-display-marked-candidates + helm-marked-buffer-name + (mapcar #'abbreviate-file-name targets) + (if (y-or-n-p (format "Copy `%s' to directories?" (helm-basename file))) + (progn + (process-put + (async-start + `(lambda () + (require 'cl-lib) + (cl-loop with copies = 0 + with skipped = ,skipped + for (file dest overwrite) in ',operations + do (condition-case _err + (progn + (copy-file file dest overwrite) + (cl-incf copies)) + (file-error (cl-incf skipped))) + finally return (list file copies skipped))) + (lambda (result) + (let ((copied (nth 1 result))) + (dired-async--modeline-mode -1) + (run-with-idle-timer + 0.1 nil + (lambda () + (dired-async-mode-line-message + "Mcp done, %s %s of %s done, %s files skipped" + 'dired-async-message + copied + (if (> copied 1) + "copies" "copy") + (helm-basename (nth 0 result)) + (nth 2 result))))))) + 'dired-async-process t) + (dired-async--modeline-mode 1)) + (message "Operation aborted"))))))) + +(helm-make-command-from-action helm-ff-run-mcp + "Copy the car of marked candidates to the remaining marked candidates." + 'helm-ff-mcp) +;;; File name history +;; +;; +(defun helm-files-save-file-name-history (&optional force) + "Save marked files to `file-name-history'." + (let* ((src (helm-get-current-source)) + (src-name (assoc-default 'name src))) + (when (or force (helm-file-completion-source-p src) + (member src-name helm-files-save-history-extra-sources)) + (let ((mkd (helm-marked-candidates :with-wildcard t)) + (history-delete-duplicates t)) + (cl-loop for sel in mkd + when (and sel + (stringp sel) + ;; If file was one of HFF candidates assume it + ;; is an existing file, so no need to call + ;; file-exists-p which is costly on remote candidates. + ;; (file-exists-p sel) + (not (helm-ff--file-directory-p sel)) + ;; When creating a new directory previous test + ;; check for file-directory-p BEFORE its + ;; creation, so check for ending slash as + ;; well to know if it is a future directory. + (not (string-match "/\\'" sel))) + do + ;; we use `abbreviate-file-name' here because + ;; other parts of Emacs seems to, + ;; and we don't want to introduce duplicates. + (add-to-history 'file-name-history + (abbreviate-file-name sel))))))) +(add-hook 'helm-exit-minibuffer-hook 'helm-files-save-file-name-history) + +(defvar helm-source-file-name-history + (helm-build-sync-source "File Name History" + :candidates 'file-name-history + :persistent-action #'ignore + :filtered-candidate-transformer #'helm-file-name-history-transformer + :action 'helm-type-file-actions)) + +(defun helm-file-name-history-show-or-hide-deleted () + (interactive) + (setq helm-file-name-history-hide-deleted + (not helm-file-name-history-hide-deleted)) + (helm-update)) +(put 'helm-file-name-history-show-or-hide-deleted 'helm-only t) + +(defvar helm-file-name-history-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map helm-map) + (define-key map (kbd "C-c d") 'helm-file-name-history-show-or-hide-deleted) + (define-key map (kbd "C-x C-f") 'helm-ff-file-name-history-run-ff) + map)) + +(defun helm-file-name-history-transformer (candidates _source) + (cl-loop with lgst = helm-file-name-history-max-length + for elm in candidates + for c = (truncate-string-to-width + elm helm-file-name-history-max-length nil nil t) + for disp = (cond ((or (file-remote-p elm) + (and (fboundp 'tramp-archive-file-name-p) + (tramp-archive-file-name-p c))) + (propertize c 'face 'helm-history-remote)) + ((file-exists-p elm) + (let ((last-access (format-time-string "%d/%m/%Y %X" + (nth 4 (file-attributes elm))))) + (propertize + elm 'display + (concat (propertize c 'face 'helm-ff-file) + (make-string (1+ (- lgst (length c))) ? ) + last-access)))) + (t (unless helm-file-name-history-hide-deleted + (propertize c 'face 'helm-history-deleted)))) + when disp + collect (cons (if helm-ff-icon-mode + (concat (all-the-icons-icon-for-file c) " " disp) + disp) + c))) + +(defun helm-ff-file-name-history-ff (candidate) + (helm-set-pattern + (expand-file-name candidate))) + +(helm-make-command-from-action helm-ff-file-name-history-run-ff + "Switch back to current HFF session with selection as preselect." + 'helm-ff-file-name-history-ff) + +(defun helm-ff-file-name-history-delete-item (_candidate) + (let ((files (helm-marked-candidates))) + (with-helm-display-marked-candidates + helm-marked-buffer-name + (helm-ff--count-and-collect-dups files) + (when (y-or-n-p "Delete file(s) from history? ") + (cl-loop for f in files do + (setq file-name-history (delete f file-name-history)))) + (message nil)))) + +(defun helm-ff-file-name-history () + "Switch to `file-name-history' without quitting `helm-find-files'." + (interactive) + (let ((src (helm-build-sync-source "File name history" + :init (lambda () + (with-helm-alive-p + (when helm-ff-file-name-history-use-recentf + (require 'recentf) + (or recentf-mode (recentf-mode 1))))) + :candidate-number-limit (helm-aand (or (get 'file-name-history 'history-length) + history-length) + (and (numberp it) it)) + :candidates (lambda () + (if helm-ff-file-name-history-use-recentf + recentf-list + file-name-history)) + :help-message 'helm-file-name-history-help-message + :fuzzy-match t + :persistent-action 'ignore + :migemo t + :filtered-candidate-transformer 'helm-file-name-history-transformer + :action (helm-make-actions + "Find file" (lambda (candidate) + (helm-set-pattern + (expand-file-name candidate)) + (with-helm-after-update-hook (helm-exit-minibuffer))) + "Find file in helm" 'helm-ff-file-name-history-ff + "Delete candidate(s)" 'helm-ff-file-name-history-delete-item) + :keymap helm-file-name-history-map))) + (with-helm-alive-p + (helm :sources src + :buffer "*helm-file-name-history*" + :allow-nest t + :resume 'noresume)))) +(put 'helm-ff-file-name-history 'helm-only t) + +;;; Browse project +;; Need dependencies: +;; +;; +;; Only hg and git are supported for now. +(defvar helm--browse-project-cache (make-hash-table :test 'equal)) +(defvar helm-buffers-in-project-p) + +(defvar helm-browse-project-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map helm-generic-files-map) + (define-key map (kbd "M-g a") 'helm-browse-project-run-ag) + map)) + +(defun helm-browse-project-get-buffers (root-directory) + (cl-loop for b in (helm-buffer-list) + ;; FIXME: Why default-directory is root-directory + ;; for current-buffer when coming from helm-quit-and-find-file. + for cd = (with-current-buffer b default-directory) + for bn = (buffer-file-name (get-buffer b)) + if (or (and bn (file-in-directory-p bn root-directory)) + (and (null bn) + (not (file-remote-p cd)) + (file-in-directory-p cd root-directory))) + collect b)) + +(defun helm-browse-project-build-buffers-source (directory) + (helm-make-source "Buffers in project" 'helm-source-buffers + :header-name (lambda (name) + (format + "%s (%s)" + name (abbreviate-file-name directory))) + :buffer-list (lambda () (helm-browse-project-get-buffers directory)))) + +(defun helm-browse-project-walk-directory (directory) + "Default function for `helm-browse-project-default-find-files-fn'." + (helm-walk-directory + directory + :directories nil :path 'full :skip-subdirs t)) + +(defun helm-browse-project-find-files-1 (directory program) + "List files in DIRECTORY recursively with external PROGRAM." + (require 'helm-fd) + (let* ((fd-exe (or helm-fd-executable + (executable-find "fdfind") + (executable-find "fd"))) + (cmd (cl-ecase program + (ag "ag --hidden -g '.*' %s") + (rg "rg --files --hidden -g '*' %s") + (fd (concat fd-exe " --hidden --type f --glob '*' %s"))))) + (with-temp-buffer + (call-process-shell-command + (format cmd directory) + nil t nil) + (mapcar (lambda (f) (expand-file-name f directory)) + (split-string (buffer-string) "\n"))))) + +(defun helm-browse-project-ag-find-files (directory) + "A suitable function for `helm-browse-project-default-find-files-fn'. +Use AG as backend." + (helm-browse-project-find-files-1 directory 'ag)) + +(defun helm-browse-project-rg-find-files (directory) + "A suitable function for `helm-browse-project-default-find-files-fn'. +Use RG as backend." + (helm-browse-project-find-files-1 directory 'rg)) + +(defun helm-browse-project-fd-find-files (directory) + "A suitable function for `helm-browse-project-default-find-files-fn'. +Use FD as backend." + (helm-browse-project-find-files-1 directory 'fd)) + +(defun helm-browse-project-ag (_candidate) + "A `helm-grep' AG action for `helm-browse-project'." + (let ((dir (with-helm-buffer (helm-get-attr 'root-dir)))) + (helm-grep-ag dir helm-current-prefix-arg))) + +(helm-make-command-from-action helm-browse-project-run-ag + "Run `helm-grep' AG from `helm-browse-project'." + 'helm-browse-project-ag) + +(defclass helm-browse-project-override-inheritor (helm-type-file) ()) + +(defclass helm-browse-project-source (helm-source-in-buffer + helm-browse-project-override-inheritor) + ((root-dir :initarg :root-dir + :initform nil + :custom 'file) + (match-part :initform + (lambda (c) + (if (with-helm-buffer + helm-ff-transformer-show-only-basename) + (helm-basename c) c))) + (filter-one-by-one :initform + (lambda (c) + (if (with-helm-buffer + helm-ff-transformer-show-only-basename) + (cons (propertize (helm-basename c) + 'face 'helm-ff-file) + c) + (propertize c 'face 'helm-ff-file))))) + "Class to define a source in `helm-browse-project' handling non +VC handled directories.") + +(cl-defmethod helm--setup-source :after ((source helm-browse-project-override-inheritor)) + (let ((actions (slot-value source 'action))) + (setf (slot-value source 'action) + (helm-append-at-nth + (symbol-value actions) + '(("Grep project with AG `M-g a, C-u select type'" . helm-browse-project-ag)) + 7)) + (setf (slot-value source 'keymap) helm-browse-project-map))) + +(defun helm-browse-project-find-files (directory &optional refresh) + "Browse non VC handled directory DIRECTORY." + (when refresh (remhash directory helm--browse-project-cache)) + (unless (gethash directory helm--browse-project-cache) + (puthash directory (funcall helm-browse-project-default-find-files-fn + directory) + helm--browse-project-cache)) + (helm :sources `(,(helm-browse-project-build-buffers-source directory) + ,(helm-make-source "Browse project" + 'helm-browse-project-source + :root-dir directory + :data (gethash directory helm--browse-project-cache) + :header-name + (lambda (name) + (format + "%s (%s)" + name (abbreviate-file-name directory))))) + :ff-transformer-show-only-basename nil + :buffer "*helm browse project*")) + +(defvar helm-browse-project-history nil) + +;;;###autoload +(defun helm-projects-history (arg) + (interactive "P") + (helm :sources + (helm-build-sync-source "Project history" + :candidates helm-browse-project-history + :action (lambda (candidate) + (with-helm-default-directory candidate + (helm-browse-project + (or arg helm-current-prefix-arg))))) + :buffer "*helm browse project history*")) + +;;;###autoload +(defun helm-browse-project (arg) + "Preconfigured helm to browse projects. +Browse files and see status of project with its VCS. +Only HG and GIT are supported for now. +Fall back to `helm-browse-project-find-files' if current +directory is not under control of one of those VCS. +With a prefix ARG browse files recursively, with two prefix ARG +rebuild the cache. +If the current directory is found in the cache, start +`helm-browse-project-find-files' even with no prefix ARG. +NOTE: The prefix ARG have no effect on the VCS controlled +directories. + +Needed dependencies for VCS: + +and +." + (interactive "P") + (require 'helm-x-files) + (let ((helm-type-buffer-actions + (remove (assoc "Browse project from buffer" + helm-type-buffer-actions) + helm-type-buffer-actions)) + (helm-buffers-in-project-p t)) + (cl-flet ((push-to-hist (root) + (setq helm-browse-project-history + (cons root (delete root helm-browse-project-history))))) + (helm-acond ((and (require 'helm-ls-git nil t) + (fboundp 'helm-ls-git-root-dir) + (helm-ls-git-root-dir)) + (push-to-hist it) + (helm-ls-git)) + ((and (require 'helm-ls-hg nil t) + (fboundp 'helm-hg-root) + (helm-hg-root)) + (push-to-hist it) + (helm-hg-find-files-in-project)) + ((helm-browse-project-get--root-dir (helm-current-directory)) + (if (or arg (gethash it helm--browse-project-cache)) + (progn + (push-to-hist it) + (helm-browse-project-find-files it (equal arg '(16)))) + (helm :sources (helm-browse-project-build-buffers-source it) + :buffer "*helm browse project*"))))))) + +(defun helm-browse-project-get--root-dir (directory) + (cl-loop with dname = (file-name-as-directory directory) + while (and dname (not (gethash dname helm--browse-project-cache))) + if (file-remote-p dname) + do (setq dname nil) else + do (setq dname (helm-basedir (substring dname 0 (1- (length dname))))) + finally return (or dname (file-name-as-directory directory)))) + +(defun helm-ff-browse-project (_candidate) + "Browse project in current directory. +See `helm-browse-project'." + (with-helm-default-directory helm-ff-default-directory + (helm-browse-project helm-current-prefix-arg))) + +(helm-make-command-from-action helm-ff-run-browse-project + "Run browse project." + 'helm-ff-browse-project) + +;;; Actions calling helm and main interactive functions. +;; +;; +(defun helm-ff-gid (_candidate) + (with-helm-default-directory helm-ff-default-directory + (helm-gid))) + +(helm-make-command-from-action helm-ff-run-gid + "Run gid from HFF." + 'helm-ff-gid) + +;; helm-find bindings for helm-find-files. +(defun helm-ff-find-sh-command (_candidate) + "Run `helm-find' from `helm-find-files'." + (require 'helm-find) + (helm-find-1 helm-ff-default-directory)) + +(helm-make-command-from-action helm-ff-run-find-sh-command + "Run find shell command action with key from `helm-find-files'." + 'helm-ff-find-sh-command) + +;; helm-hd bindings for hff +(defun helm-ff-fd (_candidate) + "Run fd shell command from `helm-find-files'." + (require 'helm-fd) + (helm-fd-1 helm-ff-default-directory)) + +(helm-make-command-from-action helm-ff-run-fd + "Run fd shell command action with key from `helm-find-files'." + 'helm-ff-fd) + +;;;###autoload +(defun helm-find-files (arg) + "Preconfigured `helm' for helm implementation of `find-file'. +Called with a prefix arg show history if some. +Don't call it from programs, use `helm-find-files-1' instead. +This is the starting point for nearly all actions you can do on +files." + (interactive "P") + (let* (tramp-archive-enabled ; Disable tramp-archive which is + ; kicking in unexpectedly. + (hist (and arg helm-ff-history (helm-find-files-history nil))) + (smart-input (or hist (helm-find-files-initial-input))) + (default-input (expand-file-name (helm-current-directory))) + (input (cond ((and (null hist) + helm-find-files-ignore-thing-at-point) + default-input) + ((and (eq major-mode 'org-agenda-mode) + org-directory + (not smart-input)) + (file-name-as-directory + (expand-file-name org-directory))) + ((and (eq major-mode 'dired-mode) smart-input) + (file-name-directory smart-input)) + ((and (not (string= smart-input "")) + smart-input)) + (t default-input))) + (input-as-presel (null (file-directory-p input))) + (presel (helm-aif (or hist + (and input-as-presel input) + (buffer-file-name (current-buffer)) + (and (eq major-mode 'dired-mode) + smart-input)) + (if (and helm-ff-transformer-show-only-basename + (null hist) + (not (string-match-p "[.]\\{1,2\\}\\'" it))) + (helm-basename it) + it)))) + ;; Continue using the same display function as history which used + ;; probably itself the same display function as inner HFF call, + ;; i.e. if history was using frame use a frame otherwise use a window. + (when (and hist (buffer-live-p (get-buffer helm-ff-history-buffer-name))) + (helm-set-local-variable 'helm-display-function + (with-current-buffer helm-ff-history-buffer-name + helm-display-function) + 'helm--last-frame-parameters + (with-current-buffer helm-ff-history-buffer-name + helm--last-frame-parameters))) + (set-text-properties 0 (length input) nil input) + (setq current-prefix-arg nil) + ;; Allow next helm session to reuse helm--last-frame-parameters as + ;; resume would do. + (let ((helm--executing-helm-action (not (null hist)))) + (helm-find-files-1 input (and presel (null helm-ff-no-preselect) + (format helm-ff-last-expanded-candidate-regexp + (regexp-quote presel))))))) + + + +(provide 'helm-files) + +;;; helm-files.el ends here diff --git a/org/elpa/helm-20230406.839/helm-find.el b/org/elpa/helm-20230406.839/helm-find.el new file mode 100644 index 0000000..bdf6d8a --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-find.el @@ -0,0 +1,170 @@ +;;; helm-find.el --- helm interface for find command. -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2023 Thierry Volpiatto + +;; 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 . + +;;; Code: + +(require 'helm-files) +(require 'helm-external) + +(defcustom helm-findutils-skip-boring-files t + "Ignore boring files in find command results." + :group 'helm-files + :type 'boolean) + +(defcustom helm-findutils-search-full-path nil + "Search in full path with shell command find when non-nil. +I.e. use the -path/ipath arguments of find instead of +-name/iname." + :group 'helm-files + :type 'boolean) + +(defcustom helm-find-noerrors nil + "Prevent showing error messages in helm buffer when non nil." + :group 'helm-files + :type 'boolean) + +(defvar helm-find-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map helm-generic-files-map) + (define-key map (kbd "DEL") 'helm-delete-backward-no-update) + map)) + +(defvar helm-source-findutils + (helm-build-async-source "Find" + :header-name (lambda (name) + (concat name " in [" (helm-default-directory) "]")) + :candidates-process 'helm-find-shell-command-fn + :filtered-candidate-transformer 'helm-findutils-transformer + :action-transformer 'helm-transform-file-load-el + :persistent-action 'helm-ff-kill-or-find-buffer-fname + :action 'helm-type-file-actions + :help-message 'helm-generic-file-help-message + :keymap helm-find-map + :candidate-number-limit 9999 + :requires-pattern 3)) + +(defun helm-findutils-transformer (candidates _source) + (let (non-essential + (default-directory (helm-default-directory))) + (cl-loop for i in candidates + for abs = (expand-file-name + (helm-aif (file-remote-p default-directory) + (concat it i) i)) + for type = (car (file-attributes abs)) + for disp = (if (and helm-ff-transformer-show-only-basename + (not (string-match "[.]\\{1,2\\}$" i))) + (helm-basename abs) abs) + collect (cond ((eq t type) + (cons (propertize disp 'face 'helm-ff-directory) + abs)) + ((stringp type) + (cons (propertize disp 'face 'helm-ff-symlink) + abs)) + (t (cons (propertize disp 'face 'helm-ff-file) + abs)))))) + +(defun helm-find--build-cmd-line () + (require 'find-cmd) + (let* ((default-directory (or (file-remote-p default-directory 'localname) + default-directory)) + (patterns+options (split-string helm-pattern "\\(\\`\\| +\\)\\* +")) + (fold-case (helm-set-case-fold-search (car patterns+options))) + (patterns (split-string (car patterns+options))) + (additional-options (and (cdr patterns+options) + (list (concat (cadr patterns+options) " ")))) + (ignored-dirs ()) + (ignored-files (when helm-findutils-skip-boring-files + (cl-loop for f in completion-ignored-extensions + if (string-match "/$" f) + do (push (replace-match "" nil t f) + ignored-dirs) + else collect (concat "*" f)))) + (path-or-name (if helm-findutils-search-full-path + '(ipath path) '(iname name))) + (name-or-iname (if fold-case + (car path-or-name) (cadr path-or-name)))) + (find-cmd (and ignored-dirs + `(prune (name ,@ignored-dirs))) + (and ignored-files + `(not (name ,@ignored-files))) + `(and ,@(mapcar + (lambda (pattern) + `(,name-or-iname ,(concat "*" pattern "*"))) + patterns) + ,@additional-options)))) + +(defun helm-find-shell-command-fn () + "Asynchronously fetch candidates for `helm-find'. +Additional find options can be specified after a \"*\" +separator." + (let* (process-connection-type + non-essential + (cmd (concat (helm-find--build-cmd-line) + (if helm-find-noerrors "2> /dev/null" ""))) + (proc (start-file-process-shell-command "hfind" helm-buffer cmd))) + (helm-log "helm-find-shell-command-fn" "Find command:\n%s" cmd) + (prog1 proc + (set-process-sentinel + proc + (lambda (process event) + (helm-process-deferred-sentinel-hook + process event (helm-default-directory)) + (if (string= event "finished\n") + (helm-locate-update-mode-line "Find") + (helm-log "helm-find-shell-command-fn sentinel" "Error: Find %s" + (replace-regexp-in-string "\n" "" event)))))))) + +(defun helm-find-1 (dir) + (let ((default-directory (file-name-as-directory dir))) + (helm :sources 'helm-source-findutils + :buffer "*helm find*" + :ff-transformer-show-only-basename nil + :case-fold-search helm-file-name-case-fold-search))) + + +;;; Preconfigured commands +;; +;; +;;;###autoload +(defun helm-find (arg) + "Preconfigured `helm' for the find shell command. + +Recursively find files whose names are matched by all specified +globbing PATTERNs under the current directory using the external +program specified in `find-program' (usually \"find\"). Every +input PATTERN is silently wrapped into two stars: *PATTERN*. + +With prefix argument, prompt for a directory to search. + +When user option `helm-findutils-search-full-path' is non-nil, +match against complete paths, otherwise, against file names +without directory part. + +The (possibly empty) list of globbing PATTERNs can be followed by +the separator \"*\" plus any number of additional arguments that +are passed to \"find\" literally." + (interactive "P") + (let ((directory + (if arg + (file-name-as-directory + (read-directory-name "DefaultDirectory: ")) + default-directory))) + (helm-find-1 directory))) + +(provide 'helm-find) + +;;; helm-find.el ends here diff --git a/org/elpa/helm-20230406.839/helm-font.el b/org/elpa/helm-20230406.839/helm-font.el new file mode 100644 index 0000000..9d43ffa --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-font.el @@ -0,0 +1,344 @@ +;;; helm-font --- Font and ucs selection for Helm -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2023 Thierry Volpiatto + +;; 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 . + +;;; Code: + +(require 'cl-lib) +(require 'helm) +(require 'helm-help) + +;; No warnings in Emacs built --without-x +(declare-function x-list-fonts "xfaces.c") + +(declare-function helm-generic-sort-fn "helm-utils") + +(defgroup helm-font nil + "Related applications to display fonts in Helm." + :group 'helm) + +(defcustom helm-ucs-recent-size 10 + "Number of recent chars to keep." + :type 'integer + :group 'helm-font) + +(defcustom helm-ucs-actions + '(("Insert character" . helm-ucs-insert-char) + ("Insert character name" . helm-ucs-insert-name) + ("Insert character code in hex" . helm-ucs-insert-code) + ("Kill marked characters" . helm-ucs-kill-char) + ("Kill name" . helm-ucs-kill-name) + ("Kill code" . helm-ucs-kill-code) + ("Describe char" . helm-ucs-describe-char)) + "Actions for `helm-source-ucs'." + :group 'helm-font + :type '(alist :key-type string :value-type function)) + +(defvar helm-ucs-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map helm-map) + (define-key map (kbd "") 'helm-ucs-persistent-delete) + (define-key map (kbd "") 'helm-ucs-persistent-backward) + (define-key map (kbd "") 'helm-ucs-persistent-forward) + (define-key map (kbd "C-c SPC") 'helm-ucs-persistent-insert-space) + map) + "Keymap for `helm-ucs'.") + +(defface helm-ucs-char + `((((class color) (background dark)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "Gold")) + "Face used to display ucs characters." + :group 'helm-font) + +;;; Xfont selection +;; +;; +(defvar helm-xfonts-cache nil) +(defvar helm-previous-font nil) +(defvar helm-source-xfonts + (helm-build-sync-source "X Fonts" + :init (lambda () + (unless helm-xfonts-cache + (setq helm-xfonts-cache + (x-list-fonts "*"))) + ;; Save current font so it can be restored in cleanup + (setq helm-previous-font (cdr (assq 'font (frame-parameters))))) + :candidates 'helm-xfonts-cache + :action '(("Copy font to kill ring" . (lambda (elm) + (kill-new elm))) + ("Set font" . (lambda (elm) + (kill-new elm) + (set-frame-font elm 'keep-size) + (message "Font copied to kill ring")))) + :cleanup (lambda () + ;; Restore previous font + (set-frame-font helm-previous-font 'keep-size)) + :persistent-action (lambda (new-font) + (set-frame-font new-font 'keep-size) + (kill-new new-font)) + :persistent-help "Preview font and copy to kill-ring")) + + +;;; 𝕌𝕔𝕤 𝕊𝕪𝕞𝕓𝕠𝕝 𝕔𝕠𝕞𝕡𝕝𝕖𝕥𝕚𝕠𝕟 +;; +;; +(defvar helm-ucs--max-len nil) +(defvar helm-ucs--names nil) +(defvar helm-ucs-history nil) +(defvar helm-ucs-recent nil + "Ring of recent `helm-ucs' selections.") + +(defun helm-calculate-ucs-alist-max-len (names) + "Calculate the length of the longest NAMES list candidate." + (cl-loop for (_n . v) in names + maximize (length (format "#x%x:" v)) into code + maximize (max 1 (string-width (format "%c" v))) into char + finally return (cons code char))) + +(defun helm-calculate-ucs-hash-table-max-len (names) + "Calculate the length of the longest NAMES hash table candidate." + (cl-loop for _n being the hash-keys of names + using (hash-values v) + maximize (length (format "#x%x:" v)) into code + maximize (max 1 (string-width (format "%c" v))) into char + finally return (cons code char))) + +(defun helm-calculate-ucs-max-len () + "Calculate the length of the longest `ucs-names' candidate." + (let ((ucs-struct (ucs-names))) + (if (hash-table-p ucs-struct) + (helm-calculate-ucs-hash-table-max-len ucs-struct) + (helm-calculate-ucs-alist-max-len ucs-struct)))) + +(defun helm-ucs-collect-symbols-alist (names) + "Collect ucs symbols from the NAMES list." + (cl-loop with pr = (make-progress-reporter + "collecting ucs names" + 0 (length names)) + for (n . v) in names + for count from 1 + for xcode = (format "#x%x:" v) + for len = (length xcode) + for diff = (- (car helm-ucs--max-len) len) + for code = (format "(#x%x): " v) + for char = (propertize (format "%c" v) + 'face 'helm-ucs-char) + unless (or (string= "" n) + ;; `char-displayable-p' return a font object or + ;; t for some char that are displayable but have + ;; no special font (e.g 10) so filter out char + ;; with no font. + (not (fontp (char-displayable-p (read xcode))))) + collect + (concat code (make-string diff ? ) + char " " n) + and do (progress-reporter-update pr count))) + +(defun helm-ucs-collect-symbols-hash-table (names) + "Collect ucs symbols from the NAMES hash-table." + (cl-loop with pr = (make-progress-reporter + "collecting ucs names" + 0 (hash-table-count names)) + for n being the hash-keys of names + using (hash-values v) + for count from 1 + for xcode = (format "#x%x:" v) + for len = (length xcode) + for diff = (- (car helm-ucs--max-len) len) + for code = (format "(#x%x): " v) + for char = (propertize (format "%c" v) + 'face 'helm-ucs-char) + unless (or (string= "" n) + (not (fontp (char-displayable-p (read xcode))))) + collect + (concat code (make-string diff ? ) + char " " n) + and do (progress-reporter-update pr count))) + +(defun helm-ucs-collect-symbols (ucs-struct) + "Collect ucs symbols from UCS-STRUCT. + +Depending on the Emacs version, the variable `ucs-names' can +either be an alist or a hash-table." + (if (hash-table-p ucs-struct) + (helm-ucs-collect-symbols-hash-table ucs-struct) + (helm-ucs-collect-symbols-alist ucs-struct))) + +(defun helm-ucs-init () + "Initialize a Helm buffer with ucs symbols. +Only math* symbols are collected." + (unless helm-ucs--max-len + (setq helm-ucs--max-len + (helm-calculate-ucs-max-len))) + (or helm-ucs--names + (setq helm-ucs--names + (helm-ucs-collect-symbols (ucs-names))))) + +;; Actions (insertion) + +(defun helm-ucs-match (candidate n) + "Return the N part of an ucs CANDIDATE. +Where N=1 is the ucs code, N=2 the ucs char and N=3 the ucs +name." + (when (string-match + "^(\\(#x[a-f0-9]+\\)): *\\(.\\) *\\([^:]+\\)+" + candidate) + (match-string n candidate))) + +(defun helm-ucs-save-recentest (candidate) + (let ((lst (cons candidate (delete candidate helm-ucs-recent)))) + (setq helm-ucs-recent + (if (> (length lst) helm-ucs-recent-size) + (nbutlast lst 1) + lst)))) + +(defun helm-ucs-insert (candidate n) + "Insert the N part of CANDIDATE." + (with-helm-current-buffer + (helm-ucs-save-recentest candidate) + (insert (helm-ucs-match candidate n)))) + +(defun helm-ucs-insert-char (candidate) + "Insert ucs char part of CANDIDATE at point." + (helm-ucs-insert candidate 2)) + +(defun helm-ucs-insert-code (candidate) + "Insert ucs code part of CANDIDATE at point." + (helm-ucs-insert candidate 1)) + +(defun helm-ucs-insert-name (candidate) + "Insert ucs name part of CANDIDATE at point." + (helm-ucs-insert candidate 3)) + +;; Kill actions +(defun helm-ucs-kill-char (_candidate) + "Action that concatenate ucs marked chars." + (let ((marked (helm-marked-candidates))) + (cl-loop for candidate in marked + do (helm-ucs-save-recentest candidate)) + (kill-new (mapconcat (lambda (x) + (helm-ucs-match x 2)) + marked "")))) + +(defun helm-ucs-kill-code (candidate) + (helm-ucs-save-recentest candidate) + (kill-new (helm-ucs-match candidate 1))) + +(defun helm-ucs-kill-name (candidate) + (helm-ucs-save-recentest candidate) + (kill-new (helm-ucs-match candidate 3))) + +;; Describe char +(defun helm-ucs-describe-char (candidate) + "Describe char CANDIDATE." + (with-temp-buffer + (insert (helm-ucs-match candidate 2)) + (describe-char (point-min)))) + +;; Navigation in current-buffer (persistent) + +(defun helm-ucs-forward-char (_candidate) + (with-helm-current-buffer + (forward-char 1))) + +(defun helm-ucs-backward-char (_candidate) + (with-helm-current-buffer + (forward-char -1))) + +(defun helm-ucs-delete-backward (_candidate) + (with-helm-current-buffer + (delete-char -1))) + +(defun helm-ucs-insert-space (_candidate) + (with-helm-current-buffer + (insert " "))) + +(defun helm-ucs-persistent-forward () + (interactive) + (with-helm-alive-p + (helm-set-attr 'action-forward 'helm-ucs-forward-char) + (helm-execute-persistent-action 'action-forward))) +(put 'helm-ucs-persistent-forward 'helm-only t) + +(defun helm-ucs-persistent-backward () + (interactive) + (with-helm-alive-p + (helm-set-attr 'action-back 'helm-ucs-backward-char) + (helm-execute-persistent-action 'action-back))) +(put 'helm-ucs-persistent-backward 'helm-only t) + +(defun helm-ucs-persistent-delete () + (interactive) + (with-helm-alive-p + (helm-set-attr 'action-delete 'helm-ucs-delete-backward) + (helm-execute-persistent-action 'action-delete))) +(put 'helm-ucs-persistent-delete 'helm-only t) + +(defun helm-ucs-persistent-insert-space () + (interactive) + (with-helm-alive-p + (helm-set-attr 'action-insert-space 'helm-ucs-insert-space) + (helm-execute-persistent-action 'action-insert-space))) + +(defvar helm-source-ucs-recent + (helm-build-sync-source "Recent UCS" + :action 'helm-ucs-actions + :candidates (lambda () helm-ucs-recent) + :help-message helm-ucs-help-message + :keymap helm-ucs-map + :volatile t)) + +(defvar helm-source-ucs + (helm-build-in-buffer-source "UCS names" + :data #'helm-ucs-init + :get-line #'buffer-substring + :help-message 'helm-ucs-help-message + :filtered-candidate-transformer + (lambda (candidates _source) (sort candidates #'helm-generic-sort-fn)) + :action 'helm-ucs-actions + :persistent-action (lambda (candidate) + (helm-ucs-insert-char candidate) + (helm-force-update)) + :keymap helm-ucs-map) + "Source for collecting `ucs-names' math symbols.") + +;;;###autoload +(defun helm-select-xfont () + "Preconfigured `helm' to select Xfont." + (interactive) + (helm :sources 'helm-source-xfonts + :buffer "*helm select xfont*")) + +;;;###autoload +(defun helm-ucs (arg) + "Preconfigured `helm' for `ucs-names'. + +Called with a prefix arg force reloading cache." + (interactive "P") + (when arg + (setq helm-ucs--names nil + helm-ucs--max-len nil + ucs-names nil)) + (let ((char (helm-aif (char-after) (string it)))) + (helm :sources (list helm-source-ucs-recent helm-source-ucs) + :history 'helm-ucs-history + :input (and char (multibyte-string-p char) char) + :buffer "*helm ucs*"))) + +(provide 'helm-font) + +;;; helm-font.el ends here diff --git a/org/elpa/helm-20230406.839/helm-for-files.el b/org/elpa/helm-20230406.839/helm-for-files.el new file mode 100644 index 0000000..0d55db9 --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-for-files.el @@ -0,0 +1,310 @@ +;;; helm-for-files.el --- helm-for-files and related. -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2023 Thierry Volpiatto + +;; 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 . + +;;; Code: + +(require 'helm-files) +(require 'helm-external) +(require 'helm-bookmark) + +(defcustom helm-multi-files-toggle-locate-binding "C-c p" + "Default binding to switch back and forth locate in `helm-multi-files'." + :group 'helm-files + :type 'string) + +(defcustom helm-for-files-preferred-list + '(helm-source-buffers-list + helm-source-recentf + helm-source-bookmarks + helm-source-file-cache + helm-source-files-in-current-dir + helm-source-locate) + "Your preferred sources for `helm-for-files' and `helm-multi-files'. + +When adding a source here it is up to you to ensure the library +of this source is accessible and properly loaded." + :type '(repeat (choice symbol)) + :group 'helm-files) + +(defcustom helm-for-files-tramp-not-fancy t + "Colorize remote files when non nil. + +Be aware that a nil value will make tramp display very slow." + :group 'helm-files + :type 'boolean) + +;;; File Cache +;; +;; +(defvar file-cache-alist) + +(defclass helm-file-cache (helm-source-in-buffer helm-type-file) + ((init :initform (lambda () (require 'filecache))))) + +(defun helm-file-cache-get-candidates () + (cl-loop for item in file-cache-alist append + (cl-destructuring-bind (base &rest dirs) item + (cl-loop for dir in dirs collect + (concat dir base))))) + +(defvar helm-source-file-cache nil) + +(defcustom helm-file-cache-fuzzy-match nil + "Enable fuzzy matching in `helm-source-file-cache' when non--nil." + :group 'helm-files + :type 'boolean + :set (lambda (var val) + (set var val) + (setq helm-source-file-cache + (helm-make-source "File Cache" 'helm-file-cache + :fuzzy-match helm-file-cache-fuzzy-match + :data 'helm-file-cache-get-candidates)))) + +(cl-defun helm-file-cache-add-directory-recursively + (dir &optional match (ignore-dirs t)) + (require 'filecache) + (cl-loop for f in (helm-walk-directory + dir + :path 'full + :directories nil + :match match + :skip-subdirs ignore-dirs) + do (file-cache-add-file f))) + +(defun helm-transform-file-cache (actions _candidate) + (let ((source (helm-get-current-source))) + (if (string= (assoc-default 'name source) "File Cache") + (append actions + '(("Remove marked files from file-cache" + . helm-ff-file-cache-remove-file))) + actions))) + +;;; Recentf files +;; +;; +(defvar helm-recentf--basename-flag nil) + +(defun helm-recentf-pattern-transformer (pattern) + (let ((pattern-no-flag (replace-regexp-in-string " -b" "" pattern))) + (cond ((and (string-match " " pattern-no-flag) + (string-match " -b\\'" pattern)) + (setq helm-recentf--basename-flag t) + pattern-no-flag) + ((string-match "\\([^ ]*\\) -b\\'" pattern) + (prog1 (match-string 1 pattern) + (setq helm-recentf--basename-flag t))) + (t (setq helm-recentf--basename-flag nil) + pattern)))) + +(defcustom helm-turn-on-recentf t + "Automatically turn on `recentf-mode' when non-nil." + :group 'helm-files + :type 'boolean) + +(defclass helm-recentf-source (helm-source-sync helm-type-file) + ((init :initform (lambda () + (require 'recentf) + (when helm-turn-on-recentf (recentf-mode 1)))) + (candidates :initform (lambda () recentf-list)) + (pattern-transformer :initform 'helm-recentf-pattern-transformer) + (match-part :initform (lambda (candidate) + (if (or helm-ff-transformer-show-only-basename + helm-recentf--basename-flag) + (helm-basename candidate) candidate))) + (migemo :initform t) + (persistent-action :initform 'helm-ff-kill-or-find-buffer-fname))) + +(cl-defmethod helm--setup-source :after ((source helm-recentf-source)) + (setf (slot-value source 'action) + (append (symbol-value (helm-actions-from-type-file)) + '(("Delete file(s) from recentf" . + (lambda (_candidate) + (cl-loop for file in (helm-marked-candidates) + do (setq recentf-list (delete file recentf-list))))))))) + +(defvar helm-source-recentf nil + "See (info \"(emacs)File Conveniences\"). +Set `recentf-max-saved-items' to a bigger value if default is too +small.") + +(defcustom helm-recentf-fuzzy-match nil + "Enable fuzzy matching in `helm-source-recentf' when non-nil." + :group 'helm-files + :type 'boolean + :set (lambda (var val) + (set var val) + (let ((helm-fuzzy-sort-fn 'helm-fuzzy-matching-sort-fn-preserve-ties-order)) + (setq helm-source-recentf + (helm-make-source "Recentf" 'helm-recentf-source + :fuzzy-match val))))) + + +;;; Files in current dir +;; +;; +(defun helm-highlight-files (files _source) + "A basic transformer for helm files sources. +Colorize only symlinks, directories and files." + (cl-loop with mp-fn = (or (assoc-default + 'match-part (helm-get-current-source)) + 'identity) + for i in files + for disp = (if (and helm-ff-transformer-show-only-basename + (not (helm-ff-dot-file-p i)) + (not (and helm--url-regexp + (string-match helm--url-regexp i))) + (not (string-match helm-ff-url-regexp i))) + (helm-basename i) (abbreviate-file-name i)) + for isremote = (or (file-remote-p i) + (helm-file-on-mounted-network-p i)) + ;; Call file-attributes only if: + ;; - file is not remote + ;; - helm-for-files--tramp-not-fancy is nil and file is remote AND + ;; connected. (Bug#1679) + for type = (and (or (null isremote) + (and (null helm-for-files-tramp-not-fancy) + (file-remote-p i nil t))) + (car (file-attributes i))) + collect + (cond ((and (null type) isremote) (cons disp i)) + ((stringp type) + (cons (propertize disp + 'face 'helm-ff-symlink + 'match-part (funcall mp-fn disp) + 'help-echo (expand-file-name i)) + i)) + ((eq type t) + (cons (propertize disp + 'face 'helm-ff-directory + 'match-part (funcall mp-fn disp) + 'help-echo (expand-file-name i)) + i)) + (t (let* ((ext (helm-file-name-extension disp)) + (disp (propertize disp + 'face 'helm-ff-file + 'match-part (funcall mp-fn disp) + 'help-echo (expand-file-name i)))) + (when (condition-case _err + (string-match (format "\\.\\(%s\\)$" ext) disp) + (invalid-regexp nil)) + (add-face-text-property + (match-beginning 1) (match-end 1) + 'helm-ff-file-extension nil disp)) + (cons disp i)))))) + +(defclass helm-files-in-current-dir-source (helm-source-sync helm-type-file) + ((candidates :initform (lambda () + (with-helm-current-buffer + (let ((dir (helm-current-directory))) + (when (file-accessible-directory-p dir) + (directory-files dir t)))))) + (pattern-transformer :initform 'helm-recentf-pattern-transformer) + (match-part :initform (lambda (candidate) + (if (or helm-ff-transformer-show-only-basename + helm-recentf--basename-flag) + (helm-basename candidate) candidate))) + (fuzzy-match :initform t) + (migemo :initform t))) + +(defvar helm-source-files-in-current-dir + (helm-make-source "Files from Current Directory" + 'helm-files-in-current-dir-source)) + +;;;###autoload +(defun helm-for-files () + "Preconfigured `helm' for opening files. +Run all sources defined in `helm-for-files-preferred-list'." + (interactive) + (require 'helm-x-files) + (unless helm-source-buffers-list + (setq helm-source-buffers-list + (helm-make-source "Buffers" 'helm-source-buffers))) + (helm :sources helm-for-files-preferred-list + :ff-transformer-show-only-basename nil + :buffer "*helm for files*" + :truncate-lines helm-buffers-truncate-lines)) + +(defun helm-multi-files-toggle-to-locate () + (interactive) + (with-helm-alive-p + (with-helm-buffer + (if (setq helm-multi-files--toggle-locate + (not helm-multi-files--toggle-locate)) + (progn + (helm-set-sources (unless (memq 'helm-source-locate + helm-sources) + (cons 'helm-source-locate helm-sources))) + (helm-set-source-filter '(helm-source-locate))) + (helm-kill-async-processes) + (helm-set-sources (remove 'helm-source-locate + helm-for-files-preferred-list)) + (helm-set-source-filter nil))))) +(put 'helm-multi-files-toggle-to-locate 'helm-only t) + +;;;###autoload +(defun helm-multi-files () + "Preconfigured helm like `helm-for-files' but running locate only on demand. + +Allow toggling back and forth from locate to others sources with +`helm-multi-files-toggle-locate-binding' key. +This avoids launching locate needlessly when what you are +searching for is already found." + (interactive) + (require 'helm-x-files) + (unless helm-source-buffers-list + (setq helm-source-buffers-list + (helm-make-source "Buffers" 'helm-source-buffers))) + (setq helm-multi-files--toggle-locate nil) + (helm-locate-set-command) + (helm-set-local-variable 'helm-async-outer-limit-hook + (list (lambda () + (when (and helm-locate-fuzzy-match + (not (string-match-p + "\\s-" helm-pattern))) + (helm-redisplay-buffer))))) + (let ((sources (remove 'helm-source-locate helm-for-files-preferred-list)) + (helm-locate-command + (if helm-locate-fuzzy-match + (unless (string-match-p "\\`locate -b" helm-locate-command) + (replace-regexp-in-string + "\\`locate" "locate -b" helm-locate-command)) + helm-locate-command)) + (old-key (lookup-key + helm-map + (read-kbd-macro helm-multi-files-toggle-locate-binding)))) + (with-helm-temp-hook 'helm-after-initialize-hook + (define-key helm-map (kbd helm-multi-files-toggle-locate-binding) + 'helm-multi-files-toggle-to-locate)) + (unwind-protect + (helm :sources sources + :ff-transformer-show-only-basename nil + :buffer "*helm multi files*" + :truncate-lines helm-buffers-truncate-lines) + (define-key helm-map (kbd helm-multi-files-toggle-locate-binding) + old-key)))) + +;;;###autoload +(defun helm-recentf () + "Preconfigured `helm' for `recentf'." + (interactive) + (helm :sources 'helm-source-recentf + :ff-transformer-show-only-basename nil + :buffer "*helm recentf*")) + +(provide 'helm-for-files) + +;;; helm-for-files.el ends here diff --git a/org/elpa/helm-20230406.839/helm-global-bindings.el b/org/elpa/helm-20230406.839/helm-global-bindings.el new file mode 100644 index 0000000..5f4ff98 --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-global-bindings.el @@ -0,0 +1,104 @@ +;;; helm-global-bindings.el --- Bind global helm commands -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2023 Thierry Volpiatto + +;; 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 . + +;;; Code: + +(require 'helm-lib) ; For helm-aif (bug #2520). + + +;;; Command Keymap +;; +;; +(defgroup helm-global-bindings nil + "Global bindings for Helm." + :group 'helm) + +(defcustom helm-command-prefix-key + (helm-aif (car (where-is-internal 'Control-X-prefix (list global-map))) + (concat it [?c])) + "The key `helm-command-prefix' is bound to in the global map." + :type '(choice (string :tag "Key") (const :tag "no binding")) + :group 'helm-global-bindings + :set + (lambda (var key) + (when (and (boundp var) (symbol-value var)) + (define-key (current-global-map) + (read-kbd-macro (symbol-value var)) nil)) + (when key + (define-key (current-global-map) + (read-kbd-macro key) 'helm-command-prefix)) + (set var key))) + +(defvar helm-command-map + (let ((map (make-sparse-keymap))) + (define-key map (kbd "a") 'helm-apropos) + (define-key map (kbd "e") 'helm-etags-select) + (define-key map (kbd "l") 'helm-locate) + (define-key map (kbd "s") 'helm-surfraw) + (define-key map (kbd "r") 'helm-regexp) + (define-key map (kbd "m") 'helm-man-woman) + (define-key map (kbd "t") 'helm-top) + (define-key map (kbd "/") 'helm-find) + (define-key map (kbd "i") 'helm-imenu) + (define-key map (kbd "I") 'helm-imenu-in-all-buffers) + (define-key map (kbd "") 'helm-lisp-completion-at-point) + (define-key map (kbd "p") 'helm-list-emacs-process) + (define-key map (kbd "C-x r b") 'helm-filtered-bookmarks) + (define-key map (kbd "M-y") 'helm-show-kill-ring) + (define-key map (kbd "C-c ") 'helm-all-mark-rings) + (define-key map (kbd "C-x C-f") 'helm-find-files) + (define-key map (kbd "f") 'helm-multi-files) + (define-key map (kbd "C-:") 'helm-eval-expression-with-eldoc) + (define-key map (kbd "C-,") 'helm-calcul-expression) + (define-key map (kbd "M-x") 'helm-M-x) + (define-key map (kbd "M-s o") 'helm-occur) + (define-key map (kbd "M-g a") 'helm-do-grep-ag) + (define-key map (kbd "c") 'helm-colors) + (define-key map (kbd "F") 'helm-select-xfont) + (define-key map (kbd "8") 'helm-ucs) + (define-key map (kbd "C-c f") 'helm-recentf) + (define-key map (kbd "C-c g") 'helm-google-suggest) + (define-key map (kbd "h i") 'helm-info-at-point) + (define-key map (kbd "h r") 'helm-info-emacs) + (define-key map (kbd "h g") 'helm-info-gnus) + (define-key map (kbd "h h") 'helm-documentation) + (define-key map (kbd "C-x C-b") 'helm-buffers-list) + (define-key map (kbd "C-x r i") 'helm-register) + (define-key map (kbd "C-c C-x") 'helm-run-external-command) + (define-key map (kbd "b") 'helm-resume) + (define-key map (kbd "M-g i") 'helm-gid) + (define-key map (kbd "@") 'helm-list-elisp-packages) + map)) + +;; Don't override the keymap we just defined with an empty +;; keymap. This also protect bindings changed by the user. +(defvar helm-command-prefix) +(define-prefix-command 'helm-command-prefix) +(fset 'helm-command-prefix helm-command-map) +(setq helm-command-prefix helm-command-map) + + +;;; Menu + +(require 'helm-easymenu) + + +;;; Provide + +(provide 'helm-global-bindings) + +;;; helm-global-bindings.el ends here diff --git a/org/elpa/helm-20230406.839/helm-grep.el b/org/elpa/helm-20230406.839/helm-grep.el new file mode 100644 index 0000000..ef4c3b4 --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-grep.el @@ -0,0 +1,1800 @@ +;;; helm-grep.el --- Helm Incremental Grep. -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2023 Thierry Volpiatto + +;; 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 . + +;;; Code: +(require 'ansi-color) +(require 'cl-lib) +(require 'format-spec) +(require 'helm) +(require 'helm-help) +(require 'helm-regexp) + +;;; load wgrep proxy if it's available +(require 'wgrep-helm nil t) + +(declare-function helm-buffer-list "helm-buffers") +(declare-function View-quit "view") +(declare-function doc-view-goto-page "doc-view" (page)) +(declare-function pdf-view-goto-page "pdf-view" (page &optional window)) +(declare-function helm-mm-split-pattern "helm-multi-match") +(declare-function helm-comp-read "helm-mode") +(declare-function helm-occur "helm-occur") + +(defvar helm--ansi-color-regexp) +(defvar helm-ff-default-directory) +(defvar helm-tramp-verbose) +(defvar helm-grep-ack-types-cache) +(defvar helm-grep-git-grep-command) +(defvar helm-source-grep-git) +(defvar tramp-verbose) +(defvar helm-current-error) + +;;; Internals vars +;; +;; +(defvar helm-rzgrep-cache (make-hash-table :test 'equal)) +(defvar helm-grep-default-function 'helm-grep-init) +(defvar helm-zgrep-recurse-flag nil) +(defvar helm-grep-history nil) +(defvar helm-grep-ag-history nil) +(defvar helm-grep-last-targets nil) +(defvar helm-grep-include-files nil) +(defvar helm-grep-in-recurse nil) +(defvar helm-grep-use-zgrep nil) +(defvar helm-grep-default-directory-fn nil + "A function that should return a directory to expand candidate to. +It is intended to use as a let-bound variable, DON'T set this globaly.") +(defvar helm-pdfgrep-targets nil) +(defvar helm-grep-last-cmd-line nil) +(defvar helm-grep-split-line-regexp "^\\([[:lower:][:upper:]]?:?.*?\\):\\([0-9]+\\):\\(.*\\)") + + +;;; Keymaps +;; +;; +(defvar helm-grep-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map helm-map) + (define-key map (kbd "M-") 'helm-goto-next-file) + (define-key map (kbd "M-") 'helm-goto-precedent-file) + (define-key map (kbd "C-c o") 'helm-grep-run-other-window-action) + (define-key map (kbd "C-c C-o") 'helm-grep-run-other-frame-action) + (define-key map (kbd "C-x C-s") 'helm-grep-run-save-buffer) + (define-key map (kbd "DEL") 'helm-delete-backward-no-update) + map) + "Keymap used in Grep sources.") + +(defvar helm-pdfgrep-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map helm-map) + (define-key map (kbd "M-") 'helm-goto-next-file) + (define-key map (kbd "M-") 'helm-goto-precedent-file) + (define-key map (kbd "DEL") 'helm-delete-backward-no-update) + map) + "Keymap used in pdfgrep.") + +(defvar helm-grep-mode-map + (let ((map (make-sparse-keymap))) + (define-key map (kbd "RET") 'helm-grep-mode-jump) + (define-key map (kbd "C-o") 'helm-grep-mode-jump-other-window) + (define-key map (kbd "") 'helm-grep-mode-jump-other-window-forward) + (define-key map (kbd "") 'helm-grep-mode-jump-other-window-backward) + (define-key map (kbd "") 'helm-gm-next-file) + (define-key map (kbd "") 'helm-gm-precedent-file) + (define-key map (kbd "M-n") 'helm-grep-mode-jump-other-window-forward) + (define-key map (kbd "M-p") 'helm-grep-mode-jump-other-window-backward) + (define-key map (kbd "M-N") 'helm-gm-next-file) + (define-key map (kbd "M-P") 'helm-gm-precedent-file) + map)) + + +(defgroup helm-grep nil + "Grep related Applications and libraries for Helm." + :group 'helm) + +(defcustom helm-grep-default-command + "grep --color=always -a -d skip %e -n%cH -e %p %f" + "Default grep format command for `helm-do-grep-1'. +Where: +'%e' format spec is for --exclude or --include grep options or + ack-grep --type option. (Not mandatory) + +'%c' format spec is for case-fold-search, + whether to use the -i option of grep. (Not mandatory) + When you specify this spec, helm grep will use smartcase + that is when a upcase character is found in pattern case will + be respected and no \\='-i' option will be used, otherwise, when + no upcase character is found in pattern always use \\='-i'. + If you don't want this behavior, don't use this spec and + specify or not the \\='-i' option. + Note that with ack-grep this is not needed, just specify + the \\='--smart-case' option. + +'%p' format spec is for pattern. (Mandatory) + +'%f' format spec is for filenames. (Mandatory) + +If your grep version doesn't support the --exclude/include args +don't specify the \\='%e' format spec. + +Helm also support ack-grep and git-grep. The following is a +default command example for ack-grep: + +\(setq helm-grep-default-command + \"ack-grep -Hn --color --smart-case --no-group %e -- %p %f\" + helm-grep-default-recurse-command + \"ack-grep -H --color --smart-case --no-group %e -- %p %f\") + +You can ommit the %e spec if you don't want to be prompted for +types. + +NOTE: Helm for ack-grep support ANSI sequences, so you can remove +the \"--no-color\" option safely (recommended). +However you should specify --color to enable multi matches highlighting +because ack disable it when output is piped. + +Same for grep you can use safely the option \"--color=always\" (default). +You can customize the color of matches using GREP_COLORS env var. +e.g: (setenv \"GREP_COLORS\" + \"ms=30;43:mc=30;43:sl=01;37:cx=:fn=35:ln=32:bn=32:se=36\") + +To enable ANSI color in git-grep just add \"--color=always\". +To customize the ANSI color in git-grep, GREP_COLORS have no effect, +you will have to setup this in your .gitconfig: + + [color \"grep\"] + match = black yellow + +Where \"black\" is the foreground and \"yellow\" the background. +See the git documentation for more infos. + +`helm-grep-default-command' and +`helm-grep-default-recurse-command' are independent, so you can +enable `helm-grep-default-command' with ack-grep and +`helm-grep-default-recurse-command' with grep if you want to be +faster on recursive grep. + +NOTE: Remote grepping is not available with ack-grep, and badly + supported with grep because tramp handles badly repeated + remote processes in a short delay (< to 5s)." + :type 'string) + +(defcustom helm-grep-default-recurse-command + "grep --color=always -a -d recurse %e -n%cH -e %p %f" + "Default recursive grep format command for `helm-do-grep-1'. +See `helm-grep-default-command' for format specs and infos about +ack-grep." + :type 'string) + +(defcustom helm-default-zgrep-command + "zgrep --color=always -a -n%cH -e %p %f" + "Default command for Zgrep. +See `helm-grep-default-command' for infos on format specs. +Option --color=always is supported and can be used safely to +replace the Helm internal match highlighting. See +`helm-grep-default-command' for more infos." + :type 'string) + +(defcustom helm-pdfgrep-default-command + "pdfgrep --color always -niH %s %s" + "Default command for pdfgrep. +Option \"--color always\" is supported starting Helm version +1.7.8. When used matches will be highlighted according to +GREP_COLORS env var." + :type 'string) + +(defcustom helm-pdfgrep-default-recurse-command + "pdfgrep --color always -rniH %s %s" + "Default recurse command for pdfgrep. +Option \"--color always\" is supported starting Helm version +1.7.8. When used matches will be highlighted according to +GREP_COLORS env var." + :type 'string) + +(defcustom helm-pdfgrep-default-read-command nil + "Default command to read pdf files from pdfgrep. +Where \\='%f' format spec is filename and \\='%p' is page number. +E.g. In Ubuntu you can set it to: + + \"evince --page-label=%p \\='%f'\" + +If set to nil either `doc-view-mode' or `pdf-view-mode' will be +used instead of an external command." + :type 'string) + +(defcustom helm-grep-max-length-history 100 + "Max number of elements to save in `helm-grep-history'." + :type 'integer) + +(defcustom helm-zgrep-file-extension-regexp + ".*\\(\\.gz\\|\\.bz\\|\\.xz\\|\\.lzma\\)$" + "Default file extensions zgrep will search in." + :type 'string) + +(defcustom helm-grep-preferred-ext nil + "This file extension will be preselected for grep." + :type 'string) + +(defcustom helm-grep-save-buffer-name-no-confirm nil + "When *hgrep* already exists, auto append suffix." + :type 'boolean) + +(defcustom helm-grep-ignored-files + (cons ".#*" (delq nil (mapcar (lambda (s) + (unless (string-match-p "/\\'" s) + (concat "*" s))) + completion-ignored-extensions))) + "List of file names which `helm-grep' shall exclude." + :type '(repeat string)) + +(defcustom helm-grep-ignored-directories + helm-walk-ignore-directories + "List of names of sub-directories which `helm-grep' shall not recurse into." + :type '(repeat string)) + +(defcustom helm-grep-truncate-lines t + "When nil the grep line that appears will not be truncated." + :type 'boolean) + +(defcustom helm-grep-file-path-style 'basename + "File path display style when grep results are displayed. +Possible value are: + basename: displays only the filename, none of the directory path + absolute: displays absolute path + relative: displays relative path from root grep directory." + :type '(choice (const :tag "Basename" basename) + (const :tag "Absolute" absolute) + (const :tag "Relative" relative))) + +(defcustom helm-grep-actions + (helm-make-actions + "Find File" 'helm-grep-action + "Find file other frame" 'helm-grep-other-frame + "Save results in grep buffer" 'helm-grep-save-results + "Find file other window (C-u vertically)" 'helm-grep-other-window) + "Actions for helm grep." + :type '(alist :key-type string :value-type function)) + +(defcustom helm-grep-pipe-cmd-switches nil + "A list of additional parameters to pass to grep pipe command. +This will be used to pipe command for multiple pattern matching +for grep, zgrep ack-grep and git-grep backends. +If you add extra args for ack-grep, use ack-grep options, for +others (grep, zgrep and git-grep) use grep options. +Here are the commands where you may want to add switches: + + grep --color=always + ack-grep --smart-case --color + +You probably don't need to use this unless you know what you are +doing." + :type '(repeat string)) + +(defcustom helm-grep-ag-pipe-cmd-switches nil + "A list of additional parameters to pass to grep-ag pipe command. +Use parameters compatibles with the backend you are using +\(i.e. AG for AG, PT for PT or RG for RG) +Here are the commands where you may want to add switches: + + ag -S --color + rg -N -S --color=? + +For RG the value of --color= is computed according to the --color= +value used in `helm-grep-ag-command'. + +Note also that by default the \"--\" option is always used, you don't +need to add it here. + +You probably don't need to use this unless you know what you are +doing." + :type '(repeat string)) + +(defcustom helm-grep-input-idle-delay 0.1 + "Idle time before updating, specified in seconds. +A lower value (default) means Helm will display the results +faster. Increasing it to a higher value (e.g. 0.6) prevents the +buffer from flickering when updating." + :type 'float) + +(defcustom helm-grep-use-ioccur-style-keys t + "Use Arrow keys to jump to occurences. +Note that if you define this variable with `setq' your change +will have no effect, use customize instead." + :type 'boolean + :set (lambda (var val) + (set var val) + (if val + (progn + (define-key helm-grep-map (kbd "") 'helm-execute-persistent-action) + (define-key helm-grep-map (kbd "") 'helm-grep-run-default-action)) + (define-key helm-grep-map (kbd "") nil) + (define-key helm-grep-map (kbd "") nil)))) + +(defcustom helm-grep-ag-command + (cond ((executable-find "rg") + "rg --color=always --smart-case --search-zip --no-heading --line-number %s -- %s %s") + ((executable-find "ag") + "ag --line-numbers -S --color --nogroup %s -- %s %s")) + "The default command for RG or AG. + +Prefer RG by default if available. + +Update: PT is still mentionned in this documentation but it seems it +doesn't exists anymore, or at least it is no more maintained. + +Takes three format specs, the first for type(s), the second for +pattern and the third for directory. + +You can use safely \"--color\" (used by default) with AG RG and +PT. + +NOTE: Usage of \"--color=never\" is discouraged as it uses Elisp +to colorize matched items which is slower than using the native +colorization of backend, however it is still supported. + +For ripgrep here is the command line to use: + + rg --color=always --smart-case --no-heading --line-number %s -- %s %s + +And to customize colors (always for ripgrep) use something like this: + + rg --color=always --colors \\='match:bg:yellow' --colors \\='match:fg:black' +\--smart-case --no-heading --line-number %s -- %s %s + +This will change color for matched items from foreground red (the +default) to a yellow background with a black foreground. Note +that your color settings for RG will not work properly with +multiples pattern if you have configured colors in rg config file +instead of command line. For more enhanced settings of ansi +colors see https://github.com/emacs-helm/helm/issues/2313 + +You must use an output format that fit with helm grep, that is: + + \"filename:line-number:string\" + +The option \"--nogroup\" allow this. +The option \"--line-numbers\" is also mandatory except with +PT (not supported). +For RG the options \"--no-heading\" and \"--line-number\" are the +ones to use. + +When modifying the default colors of matches with e.g. +\"--color-match\" option of AG or \"--colors\" option of ripgrep +you may want to modify as well `helm-grep-ag-pipe-cmd-switches' +to have all matches colorized with the same color in multi +match. + +Of course you can use several other options, see the man page of the +backend you are using." + :type 'string) + +(defcustom helm-grep-git-grep-command + "git --no-pager grep -n%cH --color=always --full-name -e %p -- %f" + "The git grep default command line. +The option \"--color=always\" can be used safely. +The color of matched items can be customized in your .gitconfig +See `helm-grep-default-command' for more infos. + +The \"--exclude-standard\" and \"--no-index\" switches allow +skipping unwanted files specified in ~/.gitignore_global and +searching files not already staged (not enabled by default). + +You have also to enable this in global \".gitconfig\" with + \"git config --global core.excludesfile ~/.gitignore_global\"." + :type 'string) + + +;;; Faces +;; +;; +(defgroup helm-grep-faces nil + "Customize the appearance of helm-grep." + :prefix "helm-" + :group 'helm-grep + :group 'helm-faces) + +(defface helm-grep-match + `((((background light)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "#b00000") + (((background dark)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "gold1")) + "Face used to highlight grep matches. +Have no effect when grep backend use \"--color=\"." + :group 'helm-grep-faces) + +(defface helm-grep-file + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "BlueViolet" + :underline t)) + "Face used to highlight grep results filenames." + :group 'helm-grep-faces) + +(defface helm-grep-lineno + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "Darkorange1")) + "Face used to highlight grep number lines." + :group 'helm-grep-faces) + +(defface helm-grep-finish + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "Green")) + "Face used in mode line when grep is finish." + :group 'helm-grep-faces) + +(defface helm-grep-cmd-line + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :inherit font-lock-type-face)) + "Face used to highlight grep command line when no results." + :group 'helm-grep-faces) + + +;;; Init +;; +;; +(defun helm-grep-prepare-candidates (candidates in-directory) + "Prepare filenames and directories CANDIDATES for grep command line." + ;; If one or more candidate is a directory, search in all files + ;; of this candidate (e.g /home/user/directory/*). + ;; If r option is enabled search also in subdidrectories. + ;; We need here to expand wildcards to support crap windows filenames + ;; as grep doesn't accept quoted wildcards (e.g "dir/*.el"). + (if helm-zgrep-recurse-flag + (mapconcat 'shell-quote-argument candidates " ") + ;; When candidate is a directory, search in all its files. + ;; NOTE that `file-expand-wildcards' will return also + ;; directories, they will be ignored by grep but not + ;; by ack-grep that will grep all files of this directory + ;; without recursing in their subdirs though, see that as a one + ;; level recursion with ack-grep. + ;; So I leave it as it is, considering it is a feature. [1] + (cl-loop for i in candidates append + (cond ((string-match "^git" helm-grep-default-command) + (list i)) + ;; Candidate is a directory and we use recursion or ack. + ((and (file-directory-p i) + (or helm-grep-in-recurse + ;; ack-grep accept directory [1]. + (helm-grep-use-ack-p))) + (list (expand-file-name i))) + ;; Grep doesn't support directory only when not in recurse. + ((file-directory-p i) + (file-expand-wildcards + (concat (file-name-as-directory (expand-file-name i)) "*") t)) + ;; Candidate is a file or wildcard and we use recursion, use the + ;; current directory instead of candidate. + ((and (or (file-exists-p i) (string-match "[*]" i)) + helm-grep-in-recurse) + (list (expand-file-name + (directory-file-name ; Needed for windoze. + (file-name-directory (directory-file-name i)))))) + ;; Else should be one or more file/directory + ;; possibly marked. + ;; When real is a normal filename without wildcard + ;; file-expand-wildcards returns a list of one file. + ;; wildcards should have been already handled by + ;; helm-read-file-name or helm-find-files but do it from + ;; here too in case we are called from elsewhere. + (t (file-expand-wildcards i t))) into all-files ; [1] + finally return + (let ((files (if (file-remote-p in-directory) + ;; Grep don't understand tramp filenames + ;; use the local name. + (mapcar (lambda (x) + (file-remote-p x 'localname)) + all-files) + all-files))) + ;; When user mark files and use recursion with grep + ;; backend enabled, the loop collect on each marked + ;; candidate its `file-name-directory' and we endup with + ;; duplicates (Bug#1714). FIXME: For now as a quick fix + ;; I just remove dups here but I should handle this inside + ;; the cond above. + (setq files (helm-fast-remove-dups files :test 'equal)) + (if (string-match "^git" helm-grep-default-command) + (mapconcat 'identity files " ") + (mapconcat 'shell-quote-argument files " ")))))) + +(defun helm-grep-command (&optional recursive grep) + (let* ((com (if recursive + helm-grep-default-recurse-command + helm-grep-default-command)) + (exe (if grep + (symbol-name grep) + (and com (car (split-string com " ")))))) + (if (and exe (string= exe "git")) "git-grep" exe))) + +(cl-defun helm-grep-use-ack-p (&key where) + (let* ((rec-com (helm-grep-command t)) + (norm-com (helm-grep-command)) + (norm-com-ack-p (string-match "\\`ack" norm-com)) + (rec-com-ack-p (and rec-com (string-match "\\`ack" rec-com)))) + (cl-case where + (default (and norm-com norm-com-ack-p)) + (recursive (and rec-com rec-com-ack-p)) + (strict (and norm-com rec-com rec-com-ack-p norm-com-ack-p)) + (t (and (not (and norm-com (string= norm-com "git-grep"))) + (or (and norm-com norm-com-ack-p) + (and rec-com rec-com-ack-p))))))) + +(defun helm-grep--pipe-command-for-grep-command (smartcase pipe-switches &optional grep-cmd) + (pcase (or grep-cmd (helm-grep-command)) + ;; Use grep for GNU regexp based tools. + ((or "grep" "zgrep" "git-grep") + (format "grep --color=always%s %s" + (if smartcase " -i" "") + pipe-switches)) + ;; Use ack-grep for PCRE based tools. + ;; Sometimes ack-grep cmd is ack only. + ((and (pred (string-match-p "ack")) ack) + (format "%s --smart-case --color %s" ack pipe-switches)))) + +(defun helm-grep--prepare-cmd-line (only-files &optional include zgrep) + (let* ((default-directory (or helm-ff-default-directory + (helm-default-directory) + default-directory)) + (fnargs (helm-grep-prepare-candidates + only-files default-directory)) + (ignored-files (unless (helm-grep-use-ack-p) + (mapconcat + (lambda (x) + (concat "--exclude=" + (shell-quote-argument x))) + helm-grep-ignored-files " "))) + (ignored-dirs (unless (helm-grep-use-ack-p) + (mapconcat + ;; Need grep version >=2.5.4 + ;; of Gnuwin32 on windoze. + (lambda (x) + (concat "--exclude-dir=" + (shell-quote-argument x))) + helm-grep-ignored-directories " "))) + (exclude (unless (helm-grep-use-ack-p) + (let ((inc (and include + (concat include " "))) + (igfiles (and ignored-files + (concat ignored-files " "))) + (igdirs (and helm-grep-in-recurse + ignored-dirs))) + (concat inc igfiles igdirs)))) + (types (and (helm-grep-use-ack-p) + ;; When %e format spec is not specified + ;; in `helm-grep-default-command' + ;; we need to pass an empty string + ;; to types to avoid error. + (or include ""))) + (smartcase (if (helm-grep-use-ack-p) + "" + (unless (let ((case-fold-search nil)) + (string-match-p + "[[:upper:]]" helm-pattern)) + "i"))) + (helm-grep-default-command + (concat helm-grep-default-command " %m")) ; `%m' like multi. + (patterns (helm-mm-split-pattern helm-pattern t)) + (pipe-switches (mapconcat 'identity helm-grep-pipe-cmd-switches " ")) + (pipes + (helm-aif (cdr patterns) + (cl-loop with pipcom = (helm-grep--pipe-command-for-grep-command + smartcase pipe-switches) + for p in it concat + (format " | %s %s" pipcom (shell-quote-argument p))) + ""))) + (format-spec + helm-grep-default-command + (delq nil + (list (unless zgrep + (if types + (cons ?e types) + (cons ?e exclude))) + (cons ?c (or smartcase "")) + (cons ?p (shell-quote-argument (car patterns))) + (cons ?f fnargs) + (cons ?m pipes)))))) + +(defun helm-grep-init (cmd-line) + "Start an asynchronous grep process with CMD-LINE using ZGREP if non-nil." + (let* ((default-directory (or helm-ff-default-directory + (helm-default-directory) + default-directory)) + (zgrep (string-match "\\`zgrep" cmd-line)) + ;; Use pipe only with grep, zgrep or git-grep. + (process-connection-type (and (not zgrep) (helm-grep-use-ack-p))) + (tramp-verbose helm-tramp-verbose) + (start-time (float-time)) + (proc-name (if helm-grep-use-zgrep + "Zgrep" + (capitalize + (if helm-grep-in-recurse + (helm-grep-command t) + (helm-grep-command))))) + non-essential) + ;; Start grep process. + (helm-log "helm-grep-init" "Starting Grep process in directory `%s'" default-directory) + (helm-log "helm-grep-init" "Command line used was:\n\n%s" + (concat ">>> " (propertize cmd-line 'face 'helm-grep-cmd-line) "\n\n")) + (prog1 ; This function should return the process first. + (start-file-process-shell-command + proc-name helm-buffer cmd-line) + ;; Init sentinel. + (set-process-sentinel + (get-buffer-process helm-buffer) + (lambda (process event) + (let* ((err (process-exit-status process)) + (noresult (= err 1))) + (unless (and err (> err 0)) + (helm-process-deferred-sentinel-hook + process event (helm-default-directory))) + (cond ((and noresult + ;; This is a workaround for zgrep + ;; that exit with code 1 + ;; after a certain amount of results. + (with-helm-buffer (helm-empty-buffer-p))) + (with-helm-buffer + (insert (concat "* Exit with code 1, no result found," + " command line was:\n\n " + (propertize helm-grep-last-cmd-line + 'face 'helm-grep-cmd-line))) + (setq mode-line-format + `(" " mode-line-buffer-identification " " + (:eval (format "L%s" (helm-candidate-number-at-point))) " " + (:eval (propertize + (format + "[%s process finished - (no results)] " + ,proc-name) + 'face 'helm-grep-finish)))))) + ((or (string= event "finished\n") + (and noresult + ;; This is a workaround for zgrep + ;; that exit with code 1 + ;; after a certain amount of results. + (with-helm-buffer (not (helm-empty-buffer-p))))) + (helm-log "helm-grep-init" "%s process finished with %s results in %fs" + proc-name + (helm-get-candidate-number) + (- (float-time) start-time)) + (helm-maybe-show-help-echo) + (with-helm-window + (setq mode-line-format + `(" " mode-line-buffer-identification " " + (:eval (format "L%s" (helm-candidate-number-at-point))) " " + (:eval (propertize + (format + "[%s process finished in %.2fs - (%s results)] " + ,proc-name + ,(- (float-time) start-time) + (helm-get-candidate-number)) + 'face 'helm-grep-finish)))) + (force-mode-line-update) + (when (and helm-allow-mouse helm-selection-point) + (helm--bind-mouse-for-selection helm-selection-point)))) + ;; Catch error output in log. + (t (helm-log + "helm-grep-init" + "Error: %s %s" + proc-name + (replace-regexp-in-string "\n" "" event)))))))))) + +(defun helm-grep-collect-candidates () + (let ((cmd-line (helm-grep--prepare-cmd-line + helm-grep-last-targets + helm-grep-include-files + helm-grep-use-zgrep))) + (set (make-local-variable 'helm-grep-last-cmd-line) cmd-line) + (funcall helm-grep-default-function cmd-line))) + + +;;; Actions +;; +;; +(defun helm-grep-action (candidate &optional where) + "Define a default action for `helm-do-grep-1' on CANDIDATE. +WHERE can be `other-window' or `other-frame'." + (let* ((split (helm-grep-split-line candidate)) + (split-pat (helm-mm-split-pattern helm-input)) + (lineno (string-to-number (nth 1 split))) + (loc-fname (or (with-current-buffer + (if (eq major-mode 'helm-grep-mode) + (current-buffer) + helm-buffer) + (get-text-property (point-at-bol) + 'helm-grep-fname)) + (car split))) + (tramp-fname (file-remote-p (or helm-ff-default-directory + default-directory))) + (fname (if tramp-fname + (concat tramp-fname loc-fname) + loc-fname))) + (helm-log "helm-grep-action" "helm-grep-action fname: %s" fname ) + (cl-case where + (other-window (helm-window-show-buffers + (list (find-file-noselect fname)) t)) + (other-frame (find-file-other-frame fname)) + (grep (helm-grep-save-results-1)) + (pdf (if helm-pdfgrep-default-read-command + (helm-pdfgrep-action-1 split lineno (car split)) + (find-file (car split)) + (if (derived-mode-p 'pdf-view-mode) + (pdf-view-goto-page lineno) + (doc-view-goto-page lineno)))) + (t (find-file fname))) + (unless (or (eq where 'grep) (eq where 'pdf)) + (helm-goto-line lineno) + ;; Move point to the nearest matching regexp from bol. + (cl-loop for reg in split-pat + when (save-excursion + (condition-case _err + (if helm-migemo-mode + (helm-mm-migemo-forward reg (point-at-eol) t) + (re-search-forward reg (point-at-eol) t)) + (invalid-regexp nil))) + collect (match-beginning 0) into pos-ls + finally (when pos-ls (goto-char (apply #'min pos-ls)))) + ;; Save history + (unless (or helm-in-persistent-action + (eq major-mode 'helm-grep-mode) + (string= helm-pattern "")) + (setq helm-grep-history + (cons helm-pattern + (delete helm-pattern helm-grep-history))) + (when (> (length helm-grep-history) + helm-grep-max-length-history) + (setq helm-grep-history + (delete (car (last helm-grep-history)) + helm-grep-history))))))) + +(defun helm-grep-persistent-action (candidate) + "Persistent action for `helm-do-grep-1'. +With a prefix arg record CANDIDATE in `mark-ring'." + (helm-grep-action candidate) + (helm-highlight-current-line)) + +(defun helm-grep-other-window (candidate) + "Jump to result in other window from helm grep." + (helm-grep-action candidate 'other-window)) + +(defun helm-grep-other-frame (candidate) + "Jump to result in other frame from helm grep." + (helm-grep-action candidate 'other-frame)) + +(defun helm-goto-next-or-prec-file (n) + "Go to next or precedent candidate file in helm grep/etags buffers. +If N is positive go forward otherwise go backward." + (let* ((allow-mode (or (eq major-mode 'helm-grep-mode) + (eq major-mode 'helm-moccur-mode) + (eq major-mode 'helm-occur-mode))) + (sel (if allow-mode + (buffer-substring (point-at-bol) (point-at-eol)) + (helm-get-selection nil t))) + (current-line-list (helm-grep-split-line sel)) + (current-fname (nth 0 current-line-list)) + (bob-or-eof (if (eq n 1) 'eobp 'bobp)) + (mark-maybe (lambda () + (if allow-mode + (ignore) + (helm-mark-current-line))))) + (catch 'break + (while (not (funcall bob-or-eof)) + (forward-line n) ; Go forward or backward depending of n value. + ;; Exit when current-fname is not matched or in `helm-grep-mode' + ;; the line is not a grep line i.e 'fname:num:tag'. + (setq sel (buffer-substring (point-at-bol) (point-at-eol))) + (when helm-allow-mouse + (helm--mouse-reset-selection-help-echo)) + (unless (or (string= current-fname + (car (helm-grep-split-line sel))) + (and (eq major-mode 'helm-grep-mode) + (not (get-text-property (point-at-bol) 'helm-grep-fname)))) + (funcall mark-maybe) + (throw 'break nil)))) + (cond ((and (> n 0) (eobp)) + (re-search-backward ".") + (forward-line 0) + (funcall mark-maybe)) + ((and (< n 0) (bobp)) + (helm-aif (next-single-property-change (point-at-bol) 'helm-grep-fname) + (goto-char it) + (forward-line 1)) + (funcall mark-maybe))) + (unless allow-mode + (helm-follow-execute-persistent-action-maybe) + (helm-log-run-hook "helm-goto-next-or-prec-file" 'helm-move-selection-after-hook)))) + +;;;###autoload +(defun helm-goto-precedent-file () + "Go to previous file in Helm grep/etags buffers." + (interactive) + (with-helm-alive-p + (with-helm-window + (helm-goto-next-or-prec-file -1)))) +(put 'helm-goto-precedent-file 'helm-only t) + +;;;###autoload +(defun helm-goto-next-file () + "Go to previous file in Helm grep/etags buffers." + (interactive) + (with-helm-window + (helm-goto-next-or-prec-file 1))) + +(helm-make-command-from-action helm-grep-run-default-action + "Run grep default action from `helm-do-grep-1'." + 'helm-grep-action) + +(helm-make-command-from-action helm-grep-run-other-window-action + "Run grep goto other window action from `helm-do-grep-1'." + 'helm-grep-other-window) + +(helm-make-command-from-action helm-grep-run-other-frame-action + "Run grep goto other frame action from `helm-do-grep-1'." + 'helm-grep-other-frame) + +(helm-make-command-from-action helm-grep-run-save-buffer + "Run grep save results action from `helm-do-grep-1'." + 'helm-grep-save-results) + +(defun helm-grep-quit-an-find-file-fn (source) + (let* ((sel (helm-get-selection nil nil source)) + (grep-line (and (stringp sel) + (helm-grep-split-line sel)))) + (if (and grep-line (file-exists-p (car grep-line))) + (expand-file-name (car grep-line)) + default-directory))) + +;;; helm-grep-mode +;; +;; +(defun helm-grep-save-results (candidate) + (helm-grep-action candidate 'grep)) + +(defvar helm-grep-mode-use-pcre nil) +(defun helm-grep-save-results-1 () + "Save Helm grep result in a `helm-grep-mode' buffer." + (let* ((buf "*hgrep*") + new-buf + (pattern (with-helm-buffer helm-input-local)) + (src (helm-get-current-source)) + (src-name (assoc-default 'name src))) + (when (get-buffer buf) + (if helm-grep-save-buffer-name-no-confirm + (setq new-buf (format "*hgrep|%s|-%s" pattern + (format-time-string "%H-%M-%S*"))) + (setq new-buf (helm-read-string "GrepBufferName: " buf)) + (cl-loop for b in (helm-buffer-list) + when (and (string= new-buf b) + (not (y-or-n-p + (format "Buffer `%s' already exists overwrite? " + new-buf)))) + do (setq new-buf (helm-read-string "GrepBufferName: " "*hgrep ")))) + (setq buf new-buf)) + (with-current-buffer (get-buffer-create buf) + (setq default-directory (or helm-ff-default-directory + (helm-default-directory) + default-directory)) + (setq-local helm-grep-mode-use-pcre (helm-get-attr 'pcre src)) + (setq buffer-read-only t) + (let ((inhibit-read-only t) + (map (make-sparse-keymap))) + (erase-buffer) + (insert "-*- mode: helm-grep -*-\n\n" + (format "%s Results for `%s':\n\n" src-name pattern)) + (save-excursion + (insert (with-current-buffer helm-buffer + (goto-char (point-min)) (forward-line 1) + (buffer-substring (point) (point-max))))) + (save-excursion + (while (not (eobp)) + (add-text-properties (point-at-bol) (point-at-eol) + `(keymap ,map + help-echo ,(concat + (get-text-property + (point) 'helm-grep-fname) + "\nmouse-1: set point\nmouse-2: jump to selection") + mouse-face highlight)) + (define-key map [mouse-1] 'mouse-set-point) + (define-key map [mouse-2] 'helm-grep-mode-mouse-jump) + (define-key map [mouse-3] 'ignore) + (forward-line 1)))) + (helm-grep-mode)) + (pop-to-buffer buf) + (setq next-error-last-buffer (get-buffer buf)) + (message "Helm %s Results saved in `%s' buffer" src-name buf))) + +(defun helm-grep-mode-mouse-jump (event) + (interactive "e") + (let* ((window (posn-window (event-end event))) + (pos (posn-point (event-end event)))) + (with-selected-window window + (when (eq major-mode 'helm-grep-mode) + (goto-char pos) + (helm-grep-mode-jump))))) +(put 'helm-grep-mode-mouse-jump 'helm-only t) + +(defun helm-grep-next-error (&optional argp reset) + "Goto ARGP position from a `helm-grep-mode' buffer. +RESET non-nil means rewind to the first match. +This is the `next-error-function' for `helm-grep-mode'." + (interactive "p") + (goto-char (cond (reset (point-min)) + ((and (< argp 0) helm-current-error) + (line-beginning-position)) + ((and (> argp 0) helm-current-error) + (line-end-position)) + ((point)))) + (let ((fun (if (> argp 0) + #'next-single-property-change + #'previous-single-property-change))) + (helm-aif (funcall fun (point) 'helm-grep-fname) + (progn + (goto-char it) + ;; `helm-current-error' is set in + ;; `helm-grep-mode-jump'. + (helm-grep-mode-jump)) + (user-error "No more matches")))) +(put 'helm-grep-next-error 'helm-only t) + +;;;###autoload +(defun helm-revert-next-error-last-buffer () + "Revert last `next-error' buffer from `current-buffer'. + +Accept to revert only `helm-grep-mode' or `helm-occur-mode' buffers. +Use this when you want to revert the `next-error' buffer after +modifications in `current-buffer'." + (interactive) + (let ((buffer (next-error-find-buffer)) + (linum (line-number-at-pos)) + (bufname (buffer-name))) + (if buffer + (with-current-buffer buffer + (helm-aif (memq major-mode '(helm-grep-mode helm-occur-mode)) + (progn (revert-buffer) + ;; helm-occur-mode revert fn is synchronous so + ;; reajust from here (it is done with + ;; helm-grep-mode in its sentinel). + (when (eq (car it) 'helm-occur-mode) + (helm-grep-goto-closest-from-linum linum bufname))) + (error "No suitable buffer to revert found"))) + (error "No suitable buffer to revert found")))) + +(define-derived-mode helm-grep-mode + special-mode "helm-grep" + "Major mode to provide actions in helm grep saved buffer. + +Special commands: +\\{helm-grep-mode-map}" + (set (make-local-variable 'helm-grep-last-cmd-line) + (with-helm-buffer helm-grep-last-cmd-line)) + (set (make-local-variable 'revert-buffer-function) + #'helm-grep-mode--revert-buffer-function) + (set (make-local-variable 'next-error-function) + #'helm-grep-next-error) + (set (make-local-variable 'helm-current-error) nil)) +(put 'helm-grep-mode 'helm-only t) + +(defun helm-grep-mode--revert-buffer-function (&optional _ignore-auto _noconfirm) + (goto-char (point-min)) + (when (re-search-forward helm-grep-split-line-regexp nil t) (forward-line 0)) + (let ((inhibit-read-only t)) + (delete-region (point) (point-max))) + (message "Reverting buffer...") + (let ((process-connection-type + ;; Git needs a nil value otherwise it tries to use a pager. + (null (string-match-p "\\`git" helm-grep-last-cmd-line)))) + (set-process-sentinel + (start-file-process-shell-command + "hgrep" (generate-new-buffer "*hgrep revert*") helm-grep-last-cmd-line) + 'helm-grep-mode--sentinel))) + +(defun helm-grep-mode--sentinel (process event) + (when (string= event "finished\n") + (with-current-buffer (if (eq major-mode 'helm-grep-mode) + (current-buffer) + (next-error-find-buffer)) + (let ((inhibit-read-only t)) + (save-excursion + (cl-loop for l in (with-current-buffer (process-buffer process) + (prog1 (split-string (buffer-string) "\n") + (kill-buffer))) + for line = (if (string-match-p helm--ansi-color-regexp l) + (ansi-color-apply l) l) + when (string-match helm-grep-split-line-regexp line) + do (insert (propertize + (car (helm-grep-filter-one-by-one + line helm-grep-mode-use-pcre)) + ;; needed for wgrep. + 'helm-realvalue line) + "\n")))) + (when (fboundp 'wgrep-cleanup-overlays) + (wgrep-cleanup-overlays (point-min) (point-max)))) + (unless (eq major-mode 'helm-grep-mode) + (let ((bufname (buffer-name)) + (linum (line-number-at-pos))) + (with-current-buffer (next-error-find-buffer) + (helm-grep-goto-closest-from-linum linum bufname)))) + (message "Reverting buffer done") + (when executing-kbd-macro (sit-for 1)))) + +(defun helm-grep-goto-closest-from-linum (linum bufname) + (goto-char (point-min)) + (catch 'break + (while (re-search-forward (format "^%s:\\([0-9]+\\):" (regexp-quote bufname)) nil t) + (let ((numline (string-to-number (match-string 1)))) + (when (< (- linum numline) 0) + (forward-line -1) + (throw 'break nil)))))) + +(defun helm-gm-next-file () + (interactive) + (helm-goto-next-or-prec-file 1)) + +(defun helm-gm-precedent-file () + (interactive) + (helm-goto-next-or-prec-file -1)) + +(defun helm-grep-mode-jump () + (interactive) + (setq next-error-last-buffer (current-buffer)) + (setq-local helm-current-error (point-marker)) + (helm-grep-action + (buffer-substring (point-at-bol) (point-at-eol))) + (helm-match-line-cleanup-pulse)) + +(defun helm-grep-mode-jump-other-window-1 (arg) + (condition-case nil + (progn + (when (or (eq last-command 'helm-grep-mode-jump-other-window-forward) + (eq last-command 'helm-grep-mode-jump-other-window-backward)) + (forward-line arg)) + (save-selected-window + (helm-grep-action (buffer-substring (point-at-bol) (point-at-eol)) + 'other-window) + (helm-match-line-cleanup-pulse) + (recenter))) + (error nil))) + +(defun helm-grep-mode-jump-other-window-forward (arg) + (interactive "p") + (helm-grep-mode-jump-other-window-1 arg)) + +(defun helm-grep-mode-jump-other-window-backward (arg) + (interactive "p") + (helm-grep-mode-jump-other-window-1 (- arg))) + +(defun helm-grep-mode-jump-other-window () + (interactive) + (setq next-error-last-buffer (current-buffer)) + (setq-local helm-current-error (point-marker)) + (let ((candidate (buffer-substring (point-at-bol) (point-at-eol)))) + (condition-case nil + (progn (helm-grep-action candidate 'other-window) + (helm-match-line-cleanup-pulse)) + (error nil)))) + + +;;; ack-grep types +;; +;; +(defun helm-grep-hack-types () + "Return a list of known ack-grep types." + (with-temp-buffer + ;; "--help-types" works with both 1.96 and 2.1+, while + ;; "--help types" works only with 1.96 Bug#422. + ;; `helm-grep-command' should return the ack executable + ;; when this function is used in the right context + ;; i.e After checking is we are using ack-grep with + ;; `helm-grep-use-ack-p'. + (call-process (helm-grep-command t) nil t nil "--help-types") + (goto-char (point-min)) + (cl-loop while (re-search-forward "^ +\\([^. ]+\\) +\\(.*\\)" nil t) + collect (cons (concat (match-string 1) + " [" (match-string 2) "]") + (match-string 1)) + collect (cons (concat "no" (match-string 1) + " [" (match-string 2) "]") + (concat "no" (match-string 1)))))) + +(defun helm-grep-ack-types-transformer (candidates _source) + (cl-loop for i in candidates + if (stringp i) + collect (rassoc i helm-grep-ack-types-cache) + else + collect i)) + +(defvar helm-grep-ack-types-cache nil) +(defun helm-grep-read-ack-type () + "Select types for the \\='--type' argument of ack-grep." + (require 'helm-mode) + (require 'helm-adaptive) + (setq helm-grep-ack-types-cache (helm-grep-hack-types)) + (let ((types (helm-comp-read + "Types: " helm-grep-ack-types-cache + :name "*Ack-grep types*" + :marked-candidates t + :must-match t + :fc-transformer '(helm-adaptive-sort + helm-grep-ack-types-transformer) + :buffer "*helm ack-types*"))) + (mapconcat (lambda (type) (concat "--type=" type)) types " "))) + + +;;; grep extensions +;; +;; +(defun helm-grep-guess-extensions (files) + "Try to guess file extensions in FILES list when using grep recurse. +These extensions will be added to command line with --include arg +of grep." + (cl-loop with ext-list = (list helm-grep-preferred-ext "*") + with lst = (if (file-directory-p (car files)) + (directory-files + (car files) nil + directory-files-no-dot-files-regexp) + files) + for i in lst + for ext = (file-name-extension i 'dot) + for glob = (and ext (not (string= ext "")) + (concat "*" ext)) + unless (or (not glob) + (and glob-list (member glob glob-list)) + (and glob-list (member glob ext-list)) + (and glob-list (member glob helm-grep-ignored-files))) + collect glob into glob-list + finally return (delq nil (append ext-list glob-list)))) + +(defun helm-grep-get-file-extensions (files) + "Try to return a list of file extensions to pass to \\='--include' arg of grep." + (require 'helm-adaptive) + (let* ((all-exts (helm-grep-guess-extensions + (mapcar 'expand-file-name files))) + (extensions (helm-comp-read "Search Only in: " all-exts + :marked-candidates t + :fc-transformer 'helm-adaptive-sort + :buffer "*helm grep exts*" + :name "*helm grep extensions*"))) + (when (listp extensions) ; Otherwise it is empty string returned by C-RET. + ;; If extensions is a list of one string containing spaces, + ;; assume user entered more than one glob separated by space(s) and + ;; split this string to pass it later to mapconcat. + ;; e.g '("*.el *.py") + (cl-loop for i in extensions + append (split-string-and-unquote i " "))))) + + +;;; Set up source +;; +;; +(defvar helm-grep-before-init-hook nil + "Hook that runs before initialization of the Helm buffer.") + +(defvar helm-grep-after-init-hook nil + "Hook that runs after initialization of the Helm buffer.") + +(defclass helm-grep-class (helm-source-async) + ((candidates-process :initform 'helm-grep-collect-candidates) + (filtered-candidate-transformer :initform #'helm-grep-fc-transformer) + (keymap :initform 'helm-grep-map) + (pcre :initarg :pcre :initform nil + :documentation + " Backend is using pcre regexp engine when non-nil.") + (nohighlight :initform t) + (nomark :initform t) + (backend :initarg :backend + :initform nil + :documentation + " The grep backend that will be used. + It is actually used only as an internal flag + and doesn't set the backend by itself. + You probably don't want to modify this.") + (candidate-number-limit :initform 9999) + (help-message :initform 'helm-grep-help-message) + (history :initform 'helm-grep-history) + (action :initform 'helm-grep-actions) + (persistent-action :initform 'helm-grep-persistent-action) + (persistent-help :initform "Jump to line (`C-u' Record in mark ring)") + (requires-pattern :initform 2) + (before-init-hook :initform 'helm-grep-before-init-hook) + (after-init-hook :initform 'helm-grep-after-init-hook) + (find-file-target :initform #'helm-grep-quit-an-find-file-fn) + (group :initform 'helm-grep))) + +(defvar helm-source-grep nil) + +(cl-defmethod helm--setup-source ((source helm-grep-class)) + (cl-call-next-method) + (helm-aif (and helm-follow-mode-persistent + (if (eq (slot-value source 'backend) 'git) + helm-source-grep-git + helm-source-grep)) + (setf (slot-value source 'follow) + (assoc-default 'follow it)))) + +(cl-defun helm-do-grep-1 (targets &optional recurse backend exts + default-input input (source 'helm-source-grep)) + "Launch helm using backend BACKEND on a list of TARGETS files. + +When RECURSE is given and BACKEND is \\='grep' use -r option of +BACKEND and prompt user for EXTS to set the --include args of +BACKEND. +Interactively you can give more than one arg separated by space +at prompt. +E.g.: + $Pattern: *.el *.py *.tex + +From Lisp use the EXTS argument as a list of extensions as above. +If you are using ack-grep, you will be prompted for --type +instead and EXTS will be ignored. If prompt is empty +`helm-grep-ignored-files' are added to --exclude. + +Argument DEFAULT-INPUT is use as `default' arg of `helm' and +INPUT is used as `input' arg of `helm'. See `helm' docstring. + +Arg BACKEND when non-nil specifies which backend to use. +It is used actually to specify \\='zgrep' or \\='git'. +When BACKEND \\='zgrep' is used don't prompt for a choice in +recurse, and ignore EXTS, search being made recursively on files +matching `helm-zgrep-file-extension-regexp' only." + (let* (non-essential + (ack-rec-p (helm-grep-use-ack-p :where 'recursive)) + (exts (and recurse + ;; [FIXME] I could handle this from helm-walk-directory. + (not (eq backend 'zgrep)) ; zgrep doesn't handle -r opt. + (not ack-rec-p) + (or exts (helm-grep-get-file-extensions targets)))) + (include-files + (and exts + (mapconcat (lambda (x) + (concat "--include=" + (shell-quote-argument x))) + (if (> (length exts) 1) + (remove "*" exts) + exts) " "))) + (types (and (not include-files) + (not (eq backend 'zgrep)) + recurse + ack-rec-p + ;; When %e format spec is not specified + ;; ignore types and do not prompt for choice. + (string-match "%e" helm-grep-default-command) + (helm-grep-read-ack-type))) + (src-name (capitalize (helm-grep-command recurse backend))) + (com (cond ((eq backend 'zgrep) helm-default-zgrep-command) + ((eq backend 'git) helm-grep-git-grep-command) + (recurse helm-grep-default-recurse-command) + ;; When resuming, the local value of + ;; `helm-grep-default-command' is used, only git-grep + ;; should need this. + (t helm-grep-default-command)))) + ;; When called as action from an other source e.g *-find-files + ;; we have to kill action buffer. + (when (get-buffer helm-action-buffer) + (kill-buffer helm-action-buffer)) + ;; If `helm-find-files' haven't already started, + ;; give a default value to `helm-ff-default-directory' + ;; and set locally `default-directory' to this value . See below [1]. + (unless helm-ff-default-directory + (setq helm-ff-default-directory default-directory)) + ;; We need to store these vars locally + ;; to pass infos later to `helm-resume'. + (helm-set-local-variable + 'helm-zgrep-recurse-flag (and recurse (eq backend 'zgrep)) + 'helm-grep-last-targets targets + 'helm-grep-include-files (or include-files types) + 'helm-grep-in-recurse recurse + 'helm-grep-use-zgrep (eq backend 'zgrep) + 'helm-grep-default-command com + 'helm-input-idle-delay helm-grep-input-idle-delay + 'default-directory helm-ff-default-directory) ;; [1] + ;; Setup the source. + (set source (helm-make-source src-name 'helm-grep-class + :backend backend + :pcre (string-match-p "\\`ack" com))) + (helm + :sources source + :buffer (format "*helm %s*" (helm-grep-command recurse backend)) + :default default-input + :input input + :keymap helm-grep-map + :history 'helm-grep-history + :truncate-lines helm-grep-truncate-lines))) + + +;;; zgrep +;; +;; +(defun helm-ff-zgrep-1 (flist recursive) + (unwind-protect + (let* ((def-dir (or helm-ff-default-directory + default-directory)) + (only (if recursive + (or (gethash def-dir helm-rzgrep-cache) + (puthash + def-dir + (helm-walk-directory + def-dir + :directories nil + :path 'full + :match helm-zgrep-file-extension-regexp) + helm-rzgrep-cache)) + flist))) + (helm-do-grep-1 only recursive 'zgrep)) + (setq helm-zgrep-recurse-flag nil))) + + +;;; transformers +;; +;; +(defun helm-grep-split-line (line) + "Split a grep output line." + ;; The output of grep may send a truncated line in this chunk, + ;; so don't split until grep line is valid, that is + ;; once the second part of the line comes with next chunk + ;; send by process. + (when (string-match helm-grep-split-line-regexp line) + ;; Don't use split-string because buffer/file name or string + ;; may contain a ":". + (cl-loop for n from 1 to 3 collect (match-string n line)))) + +(defun helm-grep--filter-candidate-1 (candidate &optional dir pcre) + (let* ((root (or dir (and helm-grep-default-directory-fn + (funcall helm-grep-default-directory-fn)))) + (ansi-p (string-match-p helm--ansi-color-regexp candidate)) + (line (if ansi-p (ansi-color-apply candidate) candidate)) + (split (helm-grep-split-line line)) + (fname (if (and root split) + ;; Filename should always be provided as a local + ;; path, if the root directory is remote, the + ;; tramp prefix will be added before executing + ;; action, see `helm-grep-action' and Bug#2032. + (expand-file-name (car split) + (or (file-remote-p root 'localname) + root)) + (car-safe split))) + (lineno (nth 1 split)) + (str (nth 2 split)) + (display-fname (cl-ecase helm-grep-file-path-style + (basename (and fname (file-name-nondirectory fname))) + (absolute fname) + (relative (and fname root + (file-relative-name fname root)))))) + (if (and display-fname lineno str) + (cons (concat (propertize display-fname + 'face 'helm-grep-file + 'help-echo (abbreviate-file-name fname) + 'helm-grep-fname fname) + ":" + (propertize lineno 'face 'helm-grep-lineno) + ":" + (if ansi-p str (helm-grep-highlight-match str pcre))) + line) + ""))) + +(defun helm-grep-filter-one-by-one (candidate &optional pcre) + "`filter-one-by-one' transformer function for `helm-do-grep-1'." + (let ((helm-grep-default-directory-fn + (or helm-grep-default-directory-fn + (lambda () (or helm-ff-default-directory + (and helm-alive-p + (helm-default-directory)) + default-directory))))) + (if (consp candidate) + ;; Already computed do nothing (default as input). + candidate + (and (stringp candidate) + (helm-grep--filter-candidate-1 candidate nil pcre))))) + +(defun helm-grep-fc-transformer (candidates source) + (let ((helm-grep-default-directory-fn + (or helm-grep-default-directory-fn + (lambda () (or helm-ff-default-directory + (and (null (eq major-mode 'helm-grep-mode)) + (helm-default-directory)) + default-directory)))) + (pcre (helm-get-attr 'pcre source))) + (cl-loop for c in candidates + collect (helm-grep--filter-candidate-1 c nil pcre)))) + +(defun helm-grep-highlight-match (str &optional pcre) + "Highlight in string STR all occurences matching `helm-pattern'." + (let (beg end) + (condition-case-unless-debug nil + (with-temp-buffer + (insert (propertize str 'read-only nil)) ; Fix bug#1176 + (goto-char (point-min)) + (cl-loop for reg in + (cl-loop for r in (helm-mm-split-pattern + helm-input) + unless (string-match "\\`!" r) + collect + (helm-aif (and helm-migemo-mode + (assoc r helm-mm--previous-migemo-info)) + (cdr it) r)) + do + (while (and (re-search-forward + (if pcre + (helm--translate-pcre-to-elisp reg) + reg) + nil t) + (> (- (setq end (match-end 0)) + (setq beg (match-beginning 0))) + 0)) + (helm-add-face-text-properties beg end 'helm-grep-match)) + do (goto-char (point-min))) + (buffer-string)) + (error nil)))) + + +;;; Grep from buffer list +;; +;; +(defun helm-grep-buffers-1 (candidate &optional zgrep) + "Run grep on all file buffers or CANDIDATE if it is a file buffer. +If one of selected buffers is not a file buffer, it is ignored +and grep will run on all others file-buffers. +If only one candidate is selected and it is not a file buffer, +switch to this buffer and run `helm-occur'. +If a prefix arg is given run grep on all buffers ignoring +non-file buffers." + (let* ((prefarg (or current-prefix-arg helm-current-prefix-arg)) + (helm-ff-default-directory + (if (and helm-ff-default-directory + (file-remote-p helm-ff-default-directory)) + default-directory + helm-ff-default-directory)) + (cands (if prefarg + (buffer-list) + (helm-marked-candidates))) + (win-conf (current-window-configuration)) + ;; Non--fname and remote buffers are ignored. + (bufs (cl-loop for buf in cands + for fname = (buffer-file-name (get-buffer buf)) + when (and fname (not (file-remote-p fname))) + collect (expand-file-name fname)))) + (if bufs + (if zgrep + (helm-do-grep-1 bufs nil 'zgrep) + (helm-do-grep-1 bufs)) + ;; bufs is empty, thats mean we have only CANDIDATE + ;; and it is not a buffer-filename, fallback to occur. + (switch-to-buffer candidate) + (when (get-buffer helm-action-buffer) + (kill-buffer helm-action-buffer)) + (helm-occur) + (when (eq helm-exit-status 1) + (set-window-configuration win-conf))))) + +(defun helm-grep-buffers (candidate) + "Action to grep buffers." + (helm-grep-buffers-1 candidate)) + +(defun helm-zgrep-buffers (candidate) + "Action to zgrep buffers." + (helm-grep-buffers-1 candidate 'zgrep)) + + +;;; Helm interface for pdfgrep +;; pdfgrep program +;; and a pdf-reader (e.g xpdf) are needed. +;; +(defvar helm-pdfgrep-default-function 'helm-pdfgrep-init) +(defun helm-pdfgrep-init (only-files &optional recurse) + "Start an asynchronous pdfgrep process in ONLY-FILES list." + (let* ((default-directory (or helm-ff-default-directory + default-directory)) + (fnargs (helm-grep-prepare-candidates + (if (file-remote-p default-directory) + (mapcar (lambda (x) + (file-remote-p x 'localname)) + only-files) + only-files) + default-directory)) + (cmd-line (format (if recurse + helm-pdfgrep-default-recurse-command + helm-pdfgrep-default-command) + helm-pattern + fnargs)) + process-connection-type) + ;; Start pdf grep process. + (helm-log "helm-pdfgrep-init" "Starting Pdf Grep process in directory `%s'" default-directory) + (helm-log "helm-pdfgrep-init" "Command line used was:\n\n%s" + (concat ">>> " (propertize cmd-line 'face 'helm-grep-cmd-line) "\n\n")) + (prog1 + (start-file-process-shell-command + "pdfgrep" helm-buffer cmd-line) + (message nil) + (set-process-sentinel + (get-buffer-process helm-buffer) + (lambda (_process event) + (if (string= event "finished\n") + (with-helm-window + (setq mode-line-format + '(" " mode-line-buffer-identification " " + (:eval (format "L%s" (helm-candidate-number-at-point))) " " + (:eval (propertize + (format "[Pdfgrep Process Finish - %s result(s)] " + (max (1- (count-lines + (point-min) (point-max))) 0)) + 'face 'helm-grep-finish)))) + (force-mode-line-update) + (when helm-allow-mouse + (helm--bind-mouse-for-selection helm-selection-point))) + (helm-log "helm-pdfgrep-init" "Error: Pdf grep %s" + (replace-regexp-in-string "\n" "" event)))))))) + +(defun helm-do-pdfgrep-1 (only &optional recurse) + "Launch pdfgrep with a list of ONLY files." + (unless (executable-find "pdfgrep") + (error "Error: No such program `pdfgrep'.")) + (let (helm-grep-in-recurse) ; recursion is implemented differently in *pdfgrep. + ;; When called as action from an other source e.g *-find-files + ;; we have to kill action buffer. + (when (get-buffer helm-action-buffer) + (kill-buffer helm-action-buffer)) + (setq helm-pdfgrep-targets only) + (helm + :sources (helm-build-async-source "PdfGrep" + :init (lambda () + ;; If `helm-find-files' haven't already started, + ;; give a default value to `helm-ff-default-directory'. + (setq helm-ff-default-directory (or helm-ff-default-directory + default-directory))) + :candidates-process (lambda () + (funcall helm-pdfgrep-default-function + helm-pdfgrep-targets recurse)) + :nohighlight t + :nomark t + :filter-one-by-one #'helm-grep-filter-one-by-one + :candidate-number-limit 9999 + :history 'helm-grep-history + :keymap helm-pdfgrep-map + :help-message 'helm-pdfgrep-help-message + :action #'helm-pdfgrep-action + :persistent-help "Jump to PDF Page" + :requires-pattern 2) + :buffer "*helm pdfgrep*" + :history 'helm-grep-history))) + +(defun helm-pdfgrep-action (candidate) + (helm-grep-action candidate 'pdf)) + +(defun helm-pdfgrep-action-1 (_split pageno fname) + (save-selected-window + (start-file-process-shell-command + "pdf-reader" nil + (format-spec helm-pdfgrep-default-read-command + (list (cons ?f fname) (cons ?p pageno)))))) + +;;; AG - PT - RG +;; +;; https://github.com/ggreer/the_silver_searcher +;; https://github.com/monochromegane/the_platinum_searcher +;; https://github.com/BurntSushi/ripgrep + +(defun helm-grep--ag-command () + (car (helm-remove-if-match + "\\`[A-Z]*=" (split-string helm-grep-ag-command)))) + +(defun helm-grep-ag-get-types () + "Returns a list of AG types if available with AG version. +See AG option \"--list-file-types\" +Ripgrep (rg) types are also supported if this backend is used." + (with-temp-buffer + (let* ((com (helm-grep--ag-command)) + (ripgrep (string= com "rg")) + (regex (if ripgrep "^\\(.*\\):" "^ *\\(--[a-z]*\\)")) + (prefix (if ripgrep "-t " ""))) + (when (equal (call-process com + nil t nil + (if ripgrep + "--type-list" "--list-file-types")) 0) + (goto-char (point-min)) + (cl-loop while (re-search-forward regex nil t) + for type = (match-string 1) + collect (cons type (concat prefix type))))))) + +(defun helm-grep-ag-prepare-cmd-line (pattern directory &optional type) + "Prepare AG command line to search PATTERN in DIRECTORY. +When TYPE is specified it is one of what `helm-grep-ag-get-types' +returns if available with current AG version." + (let* ((patterns (helm-mm-split-pattern pattern t)) + (pipe-switches (mapconcat 'identity helm-grep-ag-pipe-cmd-switches " ")) + (pipe-cmd (helm-acase (helm-grep--ag-command) + (("ag" "pt") + (format "%s -S --color%s" it (concat " " pipe-switches))) + ("rg" (format "rg -N -S --color=%s%s" + (when (string-match "--color=\\([a-z]+\\) " + helm-grep-ag-command) + (match-string 1 helm-grep-ag-command)) + (concat " " pipe-switches))))) + (cmd (format helm-grep-ag-command + (mapconcat 'identity type " ") + (shell-quote-argument (car patterns)) + (shell-quote-argument directory)))) + (helm-aif (cdr patterns) + (concat cmd (cl-loop for p in it concat + (format " | %s -- %s" + pipe-cmd (shell-quote-argument p)))) + cmd))) + +(defun helm-grep-ag-init (directory &optional type) + "Start AG process in DIRECTORY maybe searching only files of type TYPE." + (let ((default-directory (or helm-ff-default-directory + (helm-default-directory) + default-directory)) + (cmd-line (helm-grep-ag-prepare-cmd-line + helm-pattern (or (file-remote-p directory 'localname) + directory) + type)) + (start-time (float-time)) + (proc-name (helm-grep--ag-command))) + (set (make-local-variable 'helm-grep-last-cmd-line) cmd-line) + (helm-log "helm-grep-ag-init" "Starting %s process in directory `%s'" + proc-name directory) + (helm-log "helm-grep-ag-init" "Command line used was:\n\n%s" + (concat ">>> " cmd-line "\n\n")) + (prog1 + (start-file-process-shell-command + proc-name helm-buffer cmd-line) + (set-process-sentinel + (get-buffer-process helm-buffer) + (lambda (process event) + (let* ((err (process-exit-status process)) + (noresult (= err 1))) + (cond (noresult + (with-helm-buffer + (insert (concat "* Exit with code 1, no result found," + " command line was:\n\n " + (propertize helm-grep-last-cmd-line + 'face 'helm-grep-cmd-line))) + (setq mode-line-format + `(" " mode-line-buffer-identification " " + (:eval (format "L%s" (helm-candidate-number-at-point))) " " + (:eval (propertize + (format + "[%s process finished - (no results)] " + ,(upcase proc-name)) + 'face 'helm-grep-finish)))))) + ((string= event "finished\n") + (helm-log "helm-grep-ag-init" "%s process finished with %s results in %fs" + proc-name + (helm-get-candidate-number) + (- (float-time) start-time)) + (helm-maybe-show-help-echo) + (with-helm-window + (setq mode-line-format + `(" " mode-line-buffer-identification " " + (:eval (format "L%s" (helm-candidate-number-at-point))) " " + (:eval (propertize + (format + "[%s process finished in %.2fs - (%s results)] " + ,(upcase proc-name) + ,(- (float-time) start-time) + (helm-get-candidate-number)) + 'face 'helm-grep-finish)))) + (force-mode-line-update) + (when helm-allow-mouse + (helm--bind-mouse-for-selection helm-selection-point)))) + (t (helm-log + "helm-grep-ag-init" + "Error: %s %s" + proc-name + (replace-regexp-in-string "\n" "" event)))))))))) + +(defclass helm-grep-ag-class (helm-source-async) + ((nohighlight :initform t) + (pcre :initarg :pcre :initform t + :documentation + " Backend is using pcre regexp engine when non--nil.") + (keymap :initform 'helm-grep-map) + (history :initform 'helm-grep-ag-history) + (help-message :initform 'helm-grep-help-message) + (filtered-candidate-transformer :initform #'helm-grep-fc-transformer) + (persistent-action :initform 'helm-grep-persistent-action) + (persistent-help :initform "Jump to line (`C-u' Record in mark ring)") + (candidate-number-limit :initform 99999) + (requires-pattern :initform 2) + (nomark :initform t) + (action :initform 'helm-grep-actions) + (find-file-target :initform #'helm-grep-quit-an-find-file-fn) + (group :initform 'helm-grep))) + +(defvar helm-source-grep-ag nil) + +(cl-defmethod helm--setup-source ((source helm-grep-ag-class)) + (cl-call-next-method) + (helm-aif (and helm-follow-mode-persistent + helm-source-grep-ag + (assoc-default 'follow helm-source-grep-ag)) + (setf (slot-value source 'follow) it))) + +(defun helm-grep-ag-1 (directory &optional type input) + "Start helm ag in DIRECTORY maybe searching in files of type TYPE. +If INPUT is provided, use it as the search string." + (setq helm-source-grep-ag + (helm-make-source (upcase (helm-grep--ag-command)) 'helm-grep-ag-class + :header-name (lambda (name) + (format "%s [%s]" + name (abbreviate-file-name directory))) + :candidates-process + (lambda () (helm-grep-ag-init directory type)))) + (helm-set-local-variable 'helm-input-idle-delay helm-grep-input-idle-delay) + (helm :sources 'helm-source-grep-ag + :keymap helm-grep-map + :history 'helm-grep-ag-history + :input input + :truncate-lines helm-grep-truncate-lines + :buffer (format "*helm %s*" (helm-grep--ag-command)))) + +(defun helm-grep-ag (directory with-types) + "Start grep AG in DIRECTORY. +When WITH-TYPES is non-nil provide completion on AG types." + (require 'helm-adaptive) + (let ((com (capitalize (helm-grep--ag-command)))) + (helm-grep-ag-1 directory + (helm-aif (and with-types + (helm-grep-ag-get-types)) + (helm-comp-read + (format "%s type: " com) it + :must-match t + :marked-candidates t + :fc-transformer 'helm-adaptive-sort + :buffer (format "*helm %s types*" com)))))) + +;;; Git grep +;; +;; +(defvar helm-source-grep-git nil) + +(defun helm-grep-git-1 (directory &optional all default input) + "Run git-grep on DIRECTORY. +If DIRECTORY is not inside or part of a git repo exit with error. +If optional arg ALL is non-nil grep the whole repo otherwise +start at DIRECTORY. +Arg DEFAULT is what you will have with `next-history-element', +arg INPUT is what you will have by default at prompt on startup." + (require 'vc) + (let* (helm-grep-default-recurse-command + ;; Expand filename of each candidate with the git root dir. + ;; The filename will be in the helm-grep-fname prop. + (helm-grep-default-directory-fn (lambda () + (vc-find-root directory ".git"))) + (helm-ff-default-directory (funcall helm-grep-default-directory-fn))) + (cl-assert helm-ff-default-directory nil "Not inside a Git repository") + (helm-do-grep-1 (if all '("") `(,(expand-file-name directory))) + nil 'git nil default input 'helm-source-grep-git))) + + +;;;###autoload +(defun helm-do-grep-ag (arg) + "Preconfigured `helm' for grepping with AG in `default-directory'. +With prefix arg prompt for type if available with your AG +version." + (interactive "P") + (require 'helm-files) + (helm-grep-ag (expand-file-name default-directory) arg)) + +;;;###autoload +(defun helm-grep-do-git-grep (arg) + "Preconfigured `helm' for git-grepping `default-directory'. +With a prefix arg ARG git-grep the whole repository." + (interactive "P") + (require 'helm-files) + (helm-grep-git-1 default-directory arg)) + + +(provide 'helm-grep) + +;;; helm-grep.el ends here diff --git a/org/elpa/helm-20230406.839/helm-help.el b/org/elpa/helm-20230406.839/helm-help.el new file mode 100644 index 0000000..0877176 --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-help.el @@ -0,0 +1,2571 @@ +;;; helm-help.el --- Help messages for Helm. -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2023 Thierry Volpiatto + +;; 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 . + +;;; Code: +(require 'helm) + + +(defgroup helm-help nil + "Embedded help for `helm'." + :group 'helm) + +(defface helm-helper + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :inherit helm-header)) + "Face for Helm help string in minibuffer." + :group 'helm-help) + +(defvar helm-help--string-list '(helm-help-message + helm-buffer-help-message + helm-ff-help-message + helm-read-file-name-help-message + helm-generic-file-help-message + helm-fd-help-message + helm-grep-help-message + helm-pdfgrep-help-message + helm-etags-help-message + helm-ucs-help-message + helm-bookmark-help-message + helm-esh-help-message + helm-buffers-ido-virtual-help-message + helm-moccur-help-message + helm-top-help-message + helm-el-package-help-message + helm-M-x-help-message + helm-imenu-help-message + helm-colors-help-message + helm-semantic-help-message + helm-kmacro-help-message + helm-kill-ring-help-message) + "A list of help messages (strings) used by `helm-documentation'.") + +(defvar helm-documentation-buffer-name "*helm documentation*") + +;;;###autoload +(defun helm-documentation () + "Preconfigured `helm' for Helm documentation. +With a prefix arg refresh the documentation. + +Find here the documentation of all documented sources." + (interactive) + (let ((buf (get-buffer-create helm-documentation-buffer-name))) + (switch-to-buffer buf) + (set-buffer buf) + (let ((inhibit-read-only t)) + (erase-buffer) + (save-excursion + (cl-loop for elm in helm-help--string-list + for str = (helm-interpret-value elm) + do (insert (substitute-command-keys str) "\n\n"))) + (org-mode)) + (setq buffer-read-only t) + (view-mode))) + + +;;; Local help messages. + +;;; `helm-buffer-list' help +;; +;; +(defvar helm-buffer-help-message + "* Helm Buffer + +** Tips + +*** Completion + +**** Major-mode + +You can enter a partial major-mode name (e.g. lisp, sh) to narrow down buffers. +To specify the major-mode, prefix it with \"*\" e.g. \"*lisp\". + +If you want to match all buffers but the ones with a specific major-mode +\(negation), prefix the major-mode with \"!\" e.g. \"*!lisp\". + +If you want to specify more than one major-mode, separate them with \",\", +e.g. \"*!lisp,!sh,!fun\" lists all buffers but the ones in lisp-mode, sh-mode +and fundamental-mode. + +Then enter a space followed by a pattern to narrow down to buffers matching this +pattern. + +**** Search inside buffers + +If you enter a space and a pattern prefixed by \"@\", Helm searches for text +matching this pattern *inside* the buffer (i.e. not in the name of the buffer). + +Negation are supported i.e. \"!\". + +When you specify more than one of such patterns, it will match +buffers with contents matching each of these patterns i.e. AND, +not OR. That means that if you specify \"@foo @bar\" the contents +of buffer will have to be matched by foo AND bar. If you specify +\"@foo @!bar\" it means the contents of the buffer have to be +matched by foo but NOT bar. + +If you enter a pattern prefixed with an escaped \"@\", Helm searches for a +buffer matching \"@pattern\" but does not search inside the buffer. + +**** Search by directory name + +If you prefix the pattern with \"/\", Helm matches over the directory names +of the buffers. + +This feature can be used to narrow down the search to one directory while +subsequent strings entered after a space match over the buffer name only. + +Note that negation is not supported for matching on buffer filename. + +Starting from Helm v1.6.8, you can specify more than one directory. + +**** Fuzzy matching + +`helm-buffers-fuzzy-matching' turns on fuzzy matching on buffer +names, but not on directory names or major modes. A pattern +starting with \"^\" disables fuzzy matching and matching is done +litteraly IOW do not use regexps (\"^\" or whatever special +regexp character) when you want to fuzzy match. + +**** Examples + +With the following pattern + + \"*lisp ^helm @moc\" + +Helm narrows down the list by selecting only the buffers that are in lisp mode, +start with \"helm\" and which content matches \"moc\". + +Without the \"@\" + + \"*lisp ^helm moc\" + +Helm looks for lisp mode buffers starting with \"helm\" and containing \"moc\" +in their name. + +With this other pattern + + \"*!lisp !helm\" + +Helm narrows down to buffers that are not in \"lisp\" mode and that do not match +\"helm\". + +With this last pattern + + /helm/ w3 + +Helm narrows down to buffers that are in any \"helm\" subdirectory and +matching \"w3\". + +*** Creating buffers + +When creating a new buffer, use `\\[universal-argument]' to choose a mode from a +list. This list is customizable, see `helm-buffers-favorite-modes'. + +*** Killing buffers + +You can kill buffers either one by one or all the marked buffers at once. + +One kill-buffer command leaves Helm while the other is persistent. Run the +persistent kill-buffer command either with the regular +`helm-execute-persistent-action' called with a prefix argument (`\\[universal-argument] \\\\[helm-execute-persistent-action]') +or with its specific command `helm-buffer-run-kill-persistent'. See the +bindings below. + +*** Switching to buffers + +To switch to a buffer, press RET, to switch to a buffer in another window, select this buffer +and press \\\\[helm-buffer-switch-other-window], when called with a prefix arg +the buffer will be displayed vertically in other window. +If you mark more than one buffer, the marked buffers will be displayed in different windows. + +*** Saving buffers + +If buffer is associated to a file and is modified, it is by default colorized in orange, +see [[Meaning of colors and prefixes for buffers][Meaning of colors and prefixes for buffers]]. +You can save these buffers with \\\\[helm-buffer-save-persistent]. +If you want to save all these buffers, you can mark them with \\[helm-buffers-mark-similar-buffers] +and save them with \\[helm-buffer-save-persistent]. You can also do this in one step with +\\[helm-buffer-run-save-some-buffers]. Note that you will not be asked for confirmation. + +*** Meaning of colors and prefixes for buffers + +Remote buffers are prefixed with '@'. +Red => Buffer's file was modified on disk by an external process. +Indianred2 => Buffer exists but its file has been deleted. +Orange => Buffer is modified and not saved to disk. +Italic => A non-file buffer. +Yellow => Tramp archive buffer. + +** Commands +\\ +|Keys|Description| +|-------------+----------| +|\\[helm-buffer-run-zgrep]|Grep Buffer(s) works as zgrep too (`\\[universal-argument]' to grep all buffers but non-file buffers). +|\\[helm-buffers-run-occur]|Multi-Occur buffer or marked buffers (`\\[universal-argument]' to toggle force-searching current-buffer). +|\\[helm-buffer-switch-other-window]|Switch to other window. +|\\[helm-buffer-switch-other-frame]|Switch to other frame. +|\\[helm-buffers-run-browse-project]|Browse project from buffer. +|\\[helm-buffer-run-query-replace-regexp]|Query-replace-regexp in marked buffers. +|\\[helm-buffer-run-query-replace]|Query-replace in marked buffers. +|\\[helm-buffer-run-ediff]|Ediff current buffer with candidate. With two marked buffers, ediff those buffers. +|\\[helm-buffer-run-ediff-merge]|Ediff-merge current buffer with candidate. With two marked buffers, ediff-merge those buffers. +|\\[helm-buffer-diff-persistent]|Toggle Diff-buffer with saved file without leaving Helm. +|\\[helm-buffer-revert-persistent]|Revert buffer without leaving Helm. +|\\[helm-buffer-save-persistent]|Save buffer without leaving Helm. +|\\[helm-buffer-run-save-some-buffers]|Save all unsaved buffers. +|\\[helm-buffer-run-kill-buffers]|Delete marked buffers and leave Helm. +|\\[helm-buffer-run-kill-persistent]|Delete buffer without leaving Helm. +|\\[helm-buffer-run-rename-buffer]|Rename buffer. +|\\[helm-toggle-all-marks]|Toggle all marks. +|\\[helm-mark-all]|Mark all. +|\\[helm-toggle-buffers-details]|Toggle details. +|\\[helm-buffers-toggle-show-hidden-buffers]|Show hidden buffers. +|\\[helm-buffers-mark-similar-buffers]|Mark all buffers of the same type (color) as current buffer.") + +;;; Find files help (`helm-find-files') +;; +;; +(defvar helm-ff-help-message + "* Helm Find Files + +** Tips + +*** Navigation summary + +For a better experience you can enable auto completion by setting +`helm-ff-auto-update-initial-value' to non-nil in your init file. It is not +enabled by default to not confuse new users. + +**** Navigate with arrow keys + +You can use and arrows to go down or up one level, to disable +this customize `helm-ff-lynx-style-map'. +Note that using `setq' will NOT work. + +**** Use `\\\\[helm-execute-persistent-action]' (persistent action) on a directory to go down one level + +On a symlinked directory a prefix argument expands to its true name. + +**** Use `\\\\[helm-find-files-up-one-level]' or `DEL' on a directory to go up one level + +***** `DEL' behavior + +`DEL' by default deletes char backward. + +But when `helm-ff-DEL-up-one-level-maybe' is non nil `DEL' behaves +differently depending on the contents of helm-pattern. It goes up one +level if the pattern is a directory ending with \"/\" or disables HFF +auto update and delete char backward if the pattern is a filename or +refers to a non existing path. Going up one level can be disabled +if necessary by deleting \"/\" at the end of the pattern using +\\\\[backward-char] and \\[helm-delete-minibuffer-contents]. + +Note that when deleting char backward, Helm takes care of +disabling update giving you the opportunity to edit your pattern for +e.g. renaming a file or creating a new file or directory. +When `helm-ff-auto-update-initial-value' is non nil you may want to +disable it temporarily, see [[Toggle auto-completion][Toggle auto-completion]] for this. + +**** Use `\\\\[helm-find-files-down-last-level]' to walk back the resulting tree of all the `\\\\[helm-find-files-up-one-level]' or DEL you did + +The tree is reinitialized each time you browse a new tree with +`\\\\[helm-execute-persistent-action]' or by entering some pattern in the prompt. + +**** `RET' behavior + +It behaves differently depending on `helm-selection' (current candidate in helm-buffer): + +- candidate basename is \".\" => Open it in dired. +- candidate is a directory => Expand it. +- candidate is a file => Open it. + +If you have marked candidates and you press RET on a directory, +Helm will navigate to this directory. If you want to exit with +RET with default action with these marked candidates, press RET a +second time while you are on the root of this directory e.g. +\"/home/you/dir/.\" or press RET on any file which is not a +directory. You can also exit with default action at any moment +with `f1'. + +Note that when copying, renaming, etc. from `helm-find-files' the +destination file is selected with `helm-read-file-name'. + +**** `TAB' behavior + +Normally `TAB' is bound to `helm-select-action' in helm-map which +display the action menu. + +You can change this behavior by setting in `helm-find-files-map' +a new command for `TAB': + + (define-key helm-find-files-map (kbd \"C-i\") 'helm-ff-TAB) + +It will then behave slighly differently depending of +`helm-selection': + +- candidate basename is \".\" => open the action menu. +- candidate is a directory => expand it (behave as \\\\[helm-execute-persistent-action]). +- candidate is a file => open action menu. + +Called with a prefix arg open menu unconditionally. + +*** Filter out files or directories + +You can show files or directories only with respectively +\\\\[helm-ff-toggle-dirs-only] and \\\\[helm-ff-toggle-files-only]. +These are toggle commands i.e. filter/show_all. +Changing directory disable filtering. + +*** Sort directory contents + +When listing a directory without narrowing its contents, i.e. when pattern ends with \"/\", +you can sort alphabetically, by newest or by size by using respectively +\\\\[helm-ff-sort-alpha], \\[helm-ff-sort-by-newest] or \\[helm-ff-sort-by-size]. +NOTE: +When starting back narrowing i.e. entering something in minibuffer after \"/\" sorting is done +again with fuzzy sorting and no more with sorting methods previously selected. + +You can use these sort functions only on files or directory, +see [[Filter out files or directories][Filter out files or directories]]. + +*** Find file at point + +Helm uses `ffap' partially or completely to find file at point depending on the +value of `helm-ff-guess-ffap-filenames': if non-nil, support is complete +\(annoying), if nil, support is partial. + +Note that when the variable +`helm-ff-allow-non-existing-file-at-point' is non nil Helm will +insert the filename at point even if file with this name doesn't +exists. If non existing file at point ends with numbers prefixed +with \":\" the \":\" and numbers are stripped. + +**** Find file at line number + +When text at point is in the form of + + ~/elisp/helm/helm.el:1234 + +Helm finds this file at the indicated line number, here 1234. + +**** Find URL at point + +When a URL is found at point, Helm expands to that URL only. +Pressing `RET' opens that URL using `browse-url-browser-function'. + +**** Find e-mail address at point + +When an e-mail address is found at point, Helm expands to this e-mail address +prefixed with \"mailto:\". Pressing `RET' opens a message buffer with that +e-mail address. + +*** Quick pattern expansion + +**** Enter `~/' at end of pattern to quickly reach home directory + +**** Enter `/' at end of pattern to quickly reach the file system root + +**** Enter `./' at end of pattern to quickly reach `default-directory' + +\(As per its value at the beginning of the session.) + +If you already are in the `default-directory' this will move the cursor to the top. + +**** Enter `../' at end of pattern will reach upper directory, moving cursor to the top + +This is different from using `\\\\[helm-find-files-up-one-level]' in that it moves +the cursor to the top instead of remaining on the previous subdir name. + +**** Enter `..name/' at end of pattern to start a recursive search + +It searches directories matching \"name\" under the current directory, +see the [[Recursive completion on subdirectories][Recursive completion on subdirectories]] section below for more details. + +**** Any environment variable (e.g. `$HOME') at end of pattern gets expanded + +**** Any valid filename yanked after pattern gets expanded + +**** Special case: URL at point + +The quick expansions do not take effect after end a URL, you must kill the +pattern first (`\\[helm-delete-minibuffer-contents]'). + +*** Helm-find-files supports fuzzy matching + +It starts from the third character of the pattern. + +For instance \"fob\" or \"fbr\" will complete \"foobar\" but \"fb\" needs a +third character in order to complete it. + +*** Watch briefly files contents while navigating + +You can use `\\[helm-execute-persistent-action]' on a filename for this, then: + +- First hit expands to that filename in the Helm buffer. +- Second hit displays the buffer filename. +- Third hit kills the buffer filename. + +Note: `\\[universal-argument] \\[helm-execute-persistent-action]' displays the buffer directly. + +*** Browse images directories with `helm-follow-mode' and navigate up/down + +Before Emacs-27 Helm was using image-dired that works with +external ImageMagick tools. From Emacs-27 Helm use native +display of images with image-mode by default for Emacs-27 (see `helm-ff-display-image-native'), +this allows automatic resize when changing window size, zooming with `\\[helm-ff-increase-image-size-persistent]' and `\\[helm-ff-decrease-image-size-persistent]' +and rotate images as before. + +You can also use `helm-follow-action-forward' and `helm-follow-action-backward' with +`\\[helm-follow-action-forward]' and `\\[helm-follow-action-backward]' respectively. +Note that these commands have different behavior when `helm-follow-mode' +is enabled (go to next/previous line only). + +Use `\\[universal-argument] \\[helm-execute-persistent-action]' to display an image or kill its buffer. + +TIP: Use `\\\\[helm-toggle-resplit-and-swap-windows]' and `\\[helm-enlarge-window]' to display Helm window vertically +and to enlarge it while viewing images. +Note this may not work with exotic Helm windows settings such as the ones in Spacemacs. + +**** Show thumbnails + +Helm use image-dired to show thumbnails on image files, you can +toggle the thumbnail view with \\`\\[helm-ff-toggle-thumbnails]'. + +**** Launch a slideshow from marked files + +Helm provides an action from `helm-find-files' that allows running a slideshow on marked files. +Just mark image files and launch slideshow from action menu, bindings are self documented. + +*** Open files externally + +- Open file with external program (`\\\\[helm-ff-run-open-file-externally]',`C-u' to choose). + +Helm is looking what is used by default to open file +externally (mailcap files) but have its own variable +`helm-external-programs-associations' to store external +applications. If you call the action or its binding without +prefix arg Helm will see if there is an application suitable in +`helm-external-programs-associations', otherwise it will look in +mailcap files. If you want to specify which external application +to use (and its options) use a prefix arg. + +If you have to pass arguments after filename use `%s' in your command e.g. \"foo %s -a -b\" +If you want to detach your program from Emacs, you can use e.g. \"(foo %s &)\" (only supported on Linux/Unix). +When using `%s' do not quote it (i.e. \"%s\"), helm is already quoting filename argument. + +Note: What you configure for Helm in `helm-external-programs-associations' +will take precedence on mailcap files. + +- Preview file with external program (`\\[helm-ff-run-preview-file-externally]'). + +Same as above but doesn't quit Helm session, it is apersistent action. + +- Open file externally with default tool (`\\[helm-ff-run-open-file-with-default-tool]'). + +Use `xdg-open' to open files. + +*** Toggle auto-completion + +It is useful when trying to create a new file or directory and you don't want +Helm to complete what you are writing. + +Note: On a terminal, the default binding `C-' may not work. +In this case use `C-c '. + +*** You can create a new directory and a new file at the same time + +Simply write the path in the prompt and press `RET', e.g. +\"~/new/newnew/newnewnew/my_newfile.txt\". + +*** To create a new directory, append a \"/\" to the new name and press `RET' + +*** To create a new file, enter a filename not ending with \"/\" + +Note that when you enter a new name, this one is prefixed with [?]. + +*** Recursive search from Helm-find-files + +**** You can use Helm-browse-project (see binding below) + +- With no prefix argument: +If the current directory is under version control with either git or hg and +helm-ls-git and/or helm-ls-hg are installed, it lists all the files under +version control. Otherwise it falls back to Helm-find-files. See +https://github.com/emacs-helm/helm-ls-git and +https://github.com/emacs-helm/helm-ls-hg. + +- With one prefix argument: +List all the files under this directory and other subdirectories +\(recursion) and this list of files will be cached. + +- With two prefix arguments: +Same but the cache is refreshed. + +**** You can start a recursive search with \"locate\", \"find\" or [[https://github.com/sharkdp/fd][Fd]] + +See \"Note\" in the [[Recursive completion on subdirectories][section on subdirectories]]. + +Using \"locate\", you can enable the local database with a prefix argument. If the +local database doesn't already exists, you will be prompted for its creation. +If it exists and you want to refresh it, give it two prefix args. + +When using locate the Helm buffer remains empty until you type something. +Regardless Helm uses the basename of the pattern entered in the helm-find-files +session by default. Hitting `\\[next-history-element]' should just kick in the +locate search with this pattern. If you want Helm to automatically do this, add +`helm-source-locate' to `helm-sources-using-default-as-input'. + +NOTE: On Windows use Everything with its command line ~es~ as a replacement of locate. +See [[https://github.com/emacs-helm/helm/wiki/Locate#windows][Locate on Windows]] + +**** Recursive completion on subdirectories + +Starting from the directory you are currently browsing, it is possible to have +completion of all directories underneath. Say you are at \"/home/you/foo/\" and +you want to go to \"/home/you/foo/bar/baz/somewhere/else\", simply type +\"/home/you/foo/..else\" and hit `\\[helm-execute-persistent-action]' or enter +the final \"/\". Helm will then list all possible directories under \"foo\" +matching \"else\". + +Note: Completion on subdirectories uses \"locate\" as backend, you can configure +the command with `helm-locate-recursive-dirs-command'. Because this completion +uses an index, the directory tree displayed may be out-of-date and not reflect +the latest change until you update the index (using \"updatedb\" for \"locate\"). + +If for some reason you cannot use an index, the \"find\" command from +\"findutils\" can be used instead. It will be slower though. You need to pass +the basedir as first argument of \"find\" and the subdir as the value for +'-(i)regex' or '-(i)name' with the two format specs that are mandatory in +`helm-locate-recursive-dirs-command'. + +Examples: +- \"find %s -type d -name '*%s*'\" +- \"find %s -type d -regex .*%s.*$\" + +[[https://github.com/sharkdp/fd][Fd]] command is now also +supported which is regexp based and very fast. Here is the command +line to use: + +- \"fd --hidden --type d .*%s.*$ %s\" + +You can use also a glob based search, in this case use the --glob option: + +- \"fd --hidden --type d --glob '*%s*' %s\" + +*** Insert filename at point or complete filename at point + +On insertion (i.e. there is nothing at point): + +- `\\[helm-ff-run-complete-fn-at-point]': insert absolute file name. +- `\\[universal-argument] \\[helm-ff-run-complete-fn-at-point]': insert abbreviated file name. +- `\\[universal-argument] \\[universal-argument] \\[helm-ff-run-complete-fn-at-point]': insert relative file name. +- `\\[universal-argument] \\[universal-argument] \\[universal-argument] \\[helm-ff-run-complete-fn-at-point]': insert basename. + +On completion (\\[helm-ff-run-complete-fn-at-point]): + +- Target starts with \"~/\": insert abbreviate file name. +- target starts with \"/\" or \"[a-z]:/\": insert full path. +- Otherwise: insert relative file name. + +*** Use the wildcard to select multiple files + +Use of wildcard is supported to run an action over a set of files. + +Example: You can copy all the files with \".el\" extension by using \"*.el\" and +then run copy action. + +Similarly, \"**.el\" (note the two stars) will recursively select all \".el\" +files under the current directory. + +Note that when recursively copying files, you may have files with same name +dispatched across different subdirectories, so when copying them in the same +directory they will get overwritten. To avoid this Helm has a special action +called \"backup files\" that has the same behavior as the command line \"cp -f +--backup=numbered\": it allows you to copy many files with the same name from +different subdirectories into one directory. Files with same name are renamed +as follows: \"foo.txt.~1~\". Like with the --force option of cp, it is possible +to backup files in current directory. + +This command is available only when `dired-async-mode' is active. + +When using an action that involves an external backend (e.g. grep), using \"**\" +is not recommended (even thought it works fine) because it will be slower to +select all the files. You are better off leaving the backend to do it, it will +be faster. However, if you know you have not many files it is reasonable to use +this, also using not recursive wildcard (e.g. \"*.el\") is perfectly fine for +this. + +The \"**\" feature is active by default in the option `helm-file-globstar'. It +is different from the Bash \"shopt globstar\" feature in that to list files with +a named extension recursively you would write \"**.el\" whereas in Bash it would +be \"**/*.el\". Directory selection with \"**/\" like Bash \"shopt globstar\" +option is not supported yet. + +Helm supports different styles of wildcards: + +- `sh' style, the ones supported by `file-expand-wildcards'. +e.g. \"*.el\", \"*.[ch]\" which match respectively all \".el\" +files or all \".c\" and \".h\" files. + +- `bash' style (partially) In addition to what allowed in `sh' +style you can specify file extensions that have more than one +character like this: \"*.{sh,py}\" which match \".sh\" and +\".py\" files. + +Of course in both styles you can specify one or two \"*\". + +*** Query replace regexp on filenames + +Replace different parts of a file basename with something else. + +When calling this action you will be prompted twice as with +`query-replace', first for the matching expression of the text to +replace and second for the replacement text. Several facilities, +however, are provided to make the two prompts more powerfull. + +**** Syntax of the first prompt + +In addition to simple regexps, these shortcuts are available: + +- Basename without extension => \"%.\" +- Only extension => \".%\" +- Substring => \"%::\" +- Whole basename => \"%\" + +**** Syntax of the second prompt + +In addition to a simple string to use as replacement, here is what you can use: + +- A placeholder refering to what you have selected in the first prompt: \"\\@\". + +After this placeholder you can use a search-and-replace syntax à-la sed: + + \"\\@/// + +You can select a substring from the string represented by the placeholder: + + \"\\@::\" + +- A special character representing a number which is incremented: \"\\#\". + +- Shortcuts for `upcase', `downcase' and `capitalize' +are available as`%u', `%d' and `%c' respectively. + +**** Examples + +***** Recursively rename all files with \".JPG\" extension to \".jpg\" + +Use the `helm-file-globstar' feature described in [[Use the wildcard to select multiple files][recursive globbing]] +by entering \"**.JPG\" at the end of the Helm-find-files pattern, then hit +\\\\[helm-ff-run-query-replace-fnames-on-marked] and enter \"JPG\" on first prompt, then \"jpg\" on second prompt and hit `RET'. + +Alternatively you can enter \".%\" at the first prompt, then \"jpg\" and hit +`RET'. Note that when using this instead of using \"JPG\" at the first prompt, +all extensions will be renamed to \"jpg\" even if the extension of one of the +files is, say, \"png\". If you want to keep the original extension you can use +\"%d\" at the second prompt (downcase). + +***** Batch-rename files from number 001 to 00x + +Use \"\\#\" inside the second prompt. + +Example 1: To rename the files + + foo.jpg + bar.jpg + baz.jpg + +to + + foo-001.jpg + foo-002.jpg + foo-003.jpg + +use \"%.\" as matching regexp and \"foo-\\#\" as replacement string. + +Example 2: To rename the files + + foo.jpg + bar.jpg + baz.jpg + +to + + foo-001.jpg + bar-002.jpg + baz-003.jpg + +use as matching regexp \"%.\" and as replacement string \"\\@-\\#\". + +***** Replace a substring + +Use \"%::\". + +Example: To rename files + + foo.jpg + bar.jpg + baz.jpg + +to + + fOo.jpg + bAr.jpg + bAz.jpg + +use as matching regexp \"%:1:2\" and as replacement string \"%u\" (upcase). + +Note that you \*cannot* use \"%.\" and \".%\" along with substring replacement. + +***** Modify the string from the placeholder (\\@) + +- By substring, i.e. only using the substring of the placeholder: \"\\@::\". +The length of placeholder is used for when unspecified. + +Example 1: \"\\@:0:2\" replaces from the beginning to the second char of the placeholder. + +Example 2: \\@:2: replaces from the second char of the placeholder to the end. + +- By search-and-replace: \"\\@///\". + +Incremental replacement is also handled in . + +Example 3: \"\\@/foo/bar/\" replaces \"foo\" by \"bar\" in the placeholder. + +Example 4: \"\\@/foo/-\\#/\" replaces \"foo\" in the placeholder by 001, 002, etc. + +***** Clash in replacements (avoid overwriting files) + +When performing any of these replacement operations you may end up with same +names as replacement. In such cases Helm numbers the file that would otherwise +overwritten. For instance, should you remove the \"-m\" part from the files +\"emacs-m1.txt\", \"emacs-m2.txt\" and \"emacs-m3.txt\" you would end up with +three files named \"emacs.txt\", the second renaming overwriting first file, and +the third renaming overwriting second file and so on. Instead Helm will +automatically rename the second and third files as \"emacs(1).txt\" and +\"emacs(2).txt\" respectively. + +***** Query-replace on filenames vs. serial-rename action + +Unlike the [[Serial renaming][serial rename]] actions, the files renamed with +the query-replace action stay in their initial directory and are not moved to +the current directory. As such, using \"\\#\" to serial-rename files only makes +sense for files inside the same directory. It even keeps renaming files +with an incremental number in the next directories. + +*** Serial renaming + +You can use the serial-rename actions to rename, copy or symlink marked files to +a specific directory or in the current directory with all the files numbered +incrementally. + +- Serial-rename by renaming: +Rename all marked files with incremental numbering to a specific directory. + +- Serial-rename by copying: +Copy all marked files with incremental numbering to a specific directory. + +- Serial-rename by symlinking: +Symlink all marked files with incremental numbering to a specific directory. + +*** Edit marked files in a dired buffer + +You can open a dired buffer containing only marked files with `\\\\[helm-ff-run-marked-files-in-dired]'. +With a prefix argument you can open this same dired buffer in wdired mode for +editing. Note that wildcards are supported as well, so you can use e.g. +\"*.txt\" to select all \".txt\" files in the current directory or \"**.txt\" to +select all files recursively from the current directory. +See [[Use the wildcard to select multiple files]] section above. + +*** Defining default target directory for copying, renaming, etc + +You can customize `helm-dwim-target' to behave differently depending on the +windows open in the current frame. Default is to provide completion on all +directories associated to each window. + +*** Copying/Renaming from or to remote directories + +Never use ssh tramp method to copy/rename large files, use +instead its scp method if you want to avoid out of memory +problems and crash Emacs or the whole system. Moreover when using +scp method, you will hit a bug when copying more than 3 files at +the time, see [[https://github.com/emacs-helm/helm/issues/1945][bug#1945]]. +The best way actually is using Rsync to copy files from or to +remote, see [[Use Rsync to copy files][Use Rsync to copy files]]. +Also if you often work on remote you may consider using SSHFS +instead of relying on tramp. + +*** Copying and renaming asynchronously + +If you have the async library installed (if you got Helm from MELPA you do), you +can use it for copying/renaming files by enabling `dired-async-mode'. + +Note that even when async is enabled, running a copy/rename action with a prefix +argument will execute action synchronously. Moreover it will follow the first +file of the marked files in its destination directory. + +When `dired-async-mode' is enabled, an additional action named \"Backup files\" +will be available. (Such command is not natively available in Emacs). +See [[Use the wildcard to select multiple files]] for details. + +*** Multiple copies of a file + +The command \\\\[helm-ff-run-mcp] allows +copying a single file to multiple directories. To use it, mark +the file you want to copy first and then mark the directories +where you want to copy file. For example if you run +\\[helm-ff-run-mcp] on the marked candidates '(\"foo.txt\" \"bar/\" \"baz\"), +\"foo.txt\" will be copied to directories \"bar/\" and \"baz/\". + +*** Use Rsync to copy files + +If Rsync is available, you can use it to copy/sync files or directories +with some restrictions though: + +- Copying from/to tramp sudo method may not work (permissions). +- Copying from remote to remote is not supported (rsync restriction) +however you can mount a remote with sshfs and copy to it (best), otherwise you have to modify +the command line with a prefix arg, see [[https://unix.stackexchange.com/questions/183504/how-to-rsync-files-between-two-remotes][how-to-rsync-files-between-two-remotes]] +for the command line to use. + +This command is mostly useful when copying large files as it is +fast, asynchronous and provide a progress bar in mode-line. Each +rsync process have its own progress bar, so you can run several +rsync jobs, they are independents. If rsync fails you can +consult the \"*helm-rsync*\" buffer to see rsync errors. An +help-echo (move mouse over progress bar) is provided to see which +file is in transfer. Note that when copying directories, no +trailing slashes are added to directory names, which mean that +directory is created on destination if it doesn't already exists, +see rsync documentation for more infos on rsync behavior. To +synchronize a directory, mark all in the directory and rsync all +marked to the destination directory or rsync the directory itself +to its parent, e.g. remote:/home/you/music => /home/you. + +The options are configurable through `helm-rsync-switches', but +you can modify them on the fly when needed by using a prefix arg, +in this case you will be prompted for modifications. + +NOTE: When selecting a remote file, if you use the tramp syntax +for specifying a port, i.e. host#2222, helm will add +automatically \"-e 'ssh -p 2222'\" to the rsync command line +unless you have specified yourself the \"-e\" option by editing +rsync command line with a prefix arg (see above). + +*** Access files on Android phones from Helm + +Since Android doesn't provide anymore mass storage for USB, it is +not simple to access files on Android, the best way to do this +actually seems to use Adb, here some hints to set this up, read +in addition the Tramp documentation. + +1) Install Adb, most distribution provide it. +2) Enable on your phone USB debug in System/dvlpmnt settings. +3) From helm-find-files use adb tramp method: + /adb::/ +From there you can navigate as usual, mark and copy files etc... + +*** Bookmark the `helm-find-files' session + +You can bookmark the `helm-find-files' session with `\\[helm-ff-bookmark-set]'. +You can later retrieve these bookmarks by calling `helm-filtered-bookmarks' +or, from the current `helm-find-files' session, by hitting `\\[helm-find-files-switch-to-bookmark]'. + +*** Grep files from `helm-find-files' + +You can grep individual files from `helm-find-files' by using +\`\\\\[helm-ff-run-grep]'. This same command can also +recursively grep files from the current directory when called with a prefix +argument. In this case you will be prompted for the file extensions to use +\(grep backend) or the types of files to use (ack-grep backend). See the +`helm-grep-default-command' documentation to set this up. For compressed files +or archives, use zgrep with \`\\\\[helm-ff-run-zgrep]'. + +Otherwise you can use recursive commands like \`\\\\[helm-ff-run-grep-ag]' or `\\\\[helm-ff-run-git-grep]' +that are much faster than using `\\\\[helm-ff-run-grep]' with a prefix argument. +See `helm-grep-ag-command' and `helm-grep-git-grep-command' to set this up. + +You can also use \"id-utils\"' GID with \`\\\\[helm-ff-run-gid]' +by creating an ID index file with the \"mkid\" shell command. + +All those grep commands use the symbol at point as the default pattern. +Note that default is different from input (nothing is added to the prompt until +you hit `\\[next-history-element]'). + +**** Grepping on remote files + +On remote files grep is not well supported by TRAMP unless you suspend updates before +entering the pattern and re-enable it once your pattern is ready. +To toggle suspend-update, use `\\\\[helm-toggle-suspend-update]'. + +*** Execute Eshell commands on files + +Setting up aliases in Eshell allows you to set up powerful customized commands. + +Your aliases for using eshell command on file should allow +specifying one or more files, use e.g. \"alias foo $1\" or +\"alias foo $*\", if you want your command to be asynchronous add +at end \"&\", e.g. \"alias foo $* &\". + +Adding Eshell aliases to your `eshell-aliases-file' or using the +`alias' command from Eshell allows you to create personalized +commands not available in `helm-find-files' actions and use them +from `\\\\[helm-ff-run-eshell-command-on-file]'. + +Example: You want a command to uncompress some \"*.tar.gz\" files from `helm-find-files': + +1) Create an Eshell alias named, say, \"untargz\" with the command +\"alias untargz tar zxvf $*\". + +2) Now from `helm-find-files' select the \"*.tar.gz\" file (you can also +mark files if needed) and hit `\\\\[helm-ff-run-eshell-command-on-file]'. + +Note: When using marked files with this, the meaning of the prefix argument is +quite subtle. Say you have \"foo\", \"bar\" and \"baz\" marked; when you run +the alias command `example' on these files with no prefix argument it will run +`example' sequentially on each file: + +$ example foo +$ example bar +$ example baz + +With a prefix argument however it will apply `example' on all files at once: + +$ example foo bar baz + +Of course the alias command should support this. + +NOTE: Helm assume that any alias command ending with '$*' or +'$*&' supports many files as arguments, so no need to give a +prefix arg for such alias, however if your command is not an +alias you have to specify a prefix arg if you want your command +to apply all files at once. + +If you add %s to the command line %s will be replaced with the candidate, this mean you can +add extra argument to your command e.g. command -extra-arg %s or command %s -extra-arg. +If you want to pass many files inside %s, don't forget to use a prefix arg. + +You can also use special placeholders in extra-args, +see the specific info page once you hit `\\\\[helm-ff-run-eshell-command-on-file]'. + +*** Using TRAMP with `helm-find-files' to read remote directories + +`helm-find-files' works fine with TRAMP despite some limitations. + +- Grepping files is not very well supported when used incrementally. +See [[Grepping on remote files]]. + +- Locate does not work on remote directories. + +**** A TRAMP syntax crash course + +Please refer to TRAMP's documentation for more details. + +- Connect to host 192.168.0.4 as user \"foo\": + +/scp:192.168.0.4@foo: + +- Connect to host 192.168.0.4 as user \"foo\" on port 2222: + +/scp:192.168.0.4@foo#2222: + +- Connect to host 192.168.0.4 as root using multihops syntax: + +/ssh:192.168.0.4@foo|sudo:192.168.0.4: + +Note: You can also use `tramp-default-proxies-alist' when connecting often to +the same hosts. + +As a rule of thumb, prefer the scp method unless using multihops (which only +works with the ssh method), especially when copying large files. + +IMPORTANT: +You need to hit `C-j' once on top of a directory on the first connection +to complete the pattern in the minibuffer. + +**** Display color for directories, symlinks etc... with tramp + +Starting at helm version 2.9.7 it is somewhat possible to +colorize fnames by listing files without loosing performances with +external commands (ls and awk) if your system is compatible. +For this you can use `helm-list-dir-external' as value +for `helm-list-directory-function'. + +See `helm-list-directory-function' documentation for more infos. + +**** Completing host + +As soon as you enter the first \":\" after method e.g =/scp:= you will +have some completion about previously used hosts or from your =~/.ssh/config= +file, hitting `\\[helm-execute-persistent-action]' or `right' on a candidate will insert this host in minibuffer +without addind the ending \":\", second hit insert the last \":\". +As soon the last \":\" is entered TRAMP will kick in and you should see the list +of candidates soon after. + +**** Completion on tramp methods + +If you enter \":\" directly after \"/\" or \"|\" you will have completion on tramp methods, +hitting `\\[helm-execute-persistent-action]' or `right' on a method will insert it in minibuffer. + +When connection fails, be sure to delete your TRAMP connection with M-x +`helm-delete-tramp-connection' before retrying. + +**** Editing local files as root + +Use the sudo method: + +\"/sudo:host:\" or simply \"/sudo::\". + +*** Attach files to a mail buffer (message-mode) + +If you are in a `message-mode' or `mail-mode' buffer, that action will appear +in action menu, otherwise it is available at any time with \\\\[helm-ff-run-mail-attach-files]. +It behaves as follows: + +- If you are in a (mail or message) buffer, files are attached there. + +- If you are not in a mail buffer but one or more mail buffers exist, you are +prompted to attach files to one of these mail buffers. + +- If you are not in a mail buffer and no mail buffer exists, +a new mail buffer is created with the attached files in it. + +*** Open files in separate windows + +When [[Marked candidates][marking]] multiple files or using [[Use the wildcard to select multiple files][wildcard]], helm allow opening all +this files in separate windows using an horizontal layout or a +vertical layout if you used a prefix arg, when no more windows can be +displayed in frame, next files are opened in background without being +displayed. When using \\\\[helm-ff-run-switch-other-window] the current +buffer is kept and files are displayed next to it with same behavior as above. +When using two prefix args, files are opened in background without beeing displayed. + +*** Expand archives as directories in a avfs directory + +If you have mounted your filesystem with 'mountavfs' command, +you can expand archives in the \"~/.avfs\" directory with \\\\[helm-execute-persistent-action]. + +To umount Avfs, use ~fusermount -u ~/.avfs~ + +NOTE: You need the package 'avfs', on debian like distros use ~apt-get install avfs~. + +*** Tramp archive support (emacs-27+ only) + +As Tramp archive often crash Helm and Emacs, Helm does its best +to disable it, however it is hard to do so as Tramp Archive is +enabled inconditionally in Emacs. Here I build my Emacs +without-dbus to ensure Tramp archive wont kickin unexpectedly. + +If you want to browse archives please use [[Expand archives as +directories in a avfs directory][Avfs]] which is much better and +stable. + +*** Touch files + +In the completion buffer, you can choose the default which is the current-time, it is +the first candidate or the timestamp of one of the selected files. +If you need to use something else, use \\\\[next-history-element] and edit +the date in minibuffer. +It is also a way to quickly create a new file without opening a buffer, saving it +and killing it. +To touch more than one new file, separate you filenames with a comma (\",\"). +If one wants to create (touch) a new file with comma inside the name use a prefix arg, +this will prevent splitting the name and create multiple files. + +*** Change mode on files (chmod) + +When running `\\\\[helm-ff-run-chmod]' on +marked files, you can enter the new mode in prompt but you can +also use the first marked file as model to use it as default. +For example you can mark a file with mode 777 and mark other +files with mode 664, press 'RET' and answer 'y', all marked files +will be changed to 777. + +NOTE: Another way to change modes on files in helm-find-files is +running `\\\\[helm-ff-run-switch-to-shell]' and use 'chmod' directly. + +*** Delete files + +You can delete files without quitting helm with +`\\\\[helm-ff-persistent-delete]' or delete files and quit helm with `\\[helm-ff-run-delete-file]'. + +In the second method you can choose to +make this command asynchronous by customizing +\`helm-ff-delete-files-function'. + +_WARNING_: When deleting files asynchronously you will NOT be +WARNED if directories are not empty, that's mean non empty directories will +be deleted recursively in background without asking. + +A good compromise is to trash your files +when using asynchronous method (see [[Trashing files][Trashing files]]). + +When choosing synchronous delete, you can allow recursive +deletion of directories with `helm-ff-allow-recursive-deletes'. +Note that when trashing (synchronous) you are not asked for recursive deletion. + +Note that `helm-ff-allow-recursive-deletes' have no effect when +deleting asynchronously. + +First method (persistent delete) is always synchronous. + +Note that when a prefix arg is given, trashing behavior is inversed. +See [[Trashing files][Trashing files]]. + +**** Trashing files + +If you want to trash your files instead of deleting them you can +set `delete-by-moving-to-trash' to non nil, like this your files +will be moved to trash instead of beeing deleted. + +You can reverse at any time the behavior of `delete-by-moving-to-trash' by using +a prefix arg with any of the delete files command. + +On GNULinux distributions, when navigating to a Trash directory you +can restore any file in ..Trash/files directory with the 'Restore +from trash' action you will find in action menu (needs the +trash-cli package installed for remote files, see [[Trashing remote files with tramp][Here]]). +You can as well delete files from Trash directories with the 'delete files from trash' +action. +If you want to know where a file will be restored, hit `M-i', you will find a trash info. + +Tip: Navigate to your Trash/files directories with `helm-find-files' and set a bookmark +there with \\\\[helm-ff-bookmark-set] for fast access to Trash. + +NOTE: Restoring files from trash is working only on system using +the +[[http://freedesktop.org/wiki/Specifications/trash-spec][freedesktop trash specifications]]. + +***** Trashing remote files with tramp + +Trashing remote files (or local files with sudo method) is disabled by default +because tramp is requiring the 'trash' command to be installed, if you want to +trash your remote files, customize `helm-trash-remote-files'. +The package on most GNU/Linux based distributions is trash-cli, it is available [[https://github.com/andreafrancia/trash-cli][here]]. + +NOTE: +When deleting your files with sudo method, your trashed files will not be listed +with trash-list command line until you log in as root. + +*** Checksum file + +Checksum is calculated with the md5sum, sha1sum, sha224sum, +sha256sum, sha384sum and sha512sum commands when available, otherwise the +Emacs function `secure-hash' is used but it is slow and may crash +Emacs and even the whole system as it eats all memory. So if +your system doesn't have the md5sum and sha*sum command line tools be +careful when checking sum of larges files e.g. isos. + +*** Ignored or boring files + +Helm-find-files can ignore files matching +`helm-boring-file-regexp-list' or files that are git ignored, you +can set this with `helm-ff-skip-boring-files' or +`helm-ff-skip-git-ignored-files'. +NOTE: This will slow down helm, be warned. + +*** Helm-find-files is using a cache + +Helm is caching each directory files list in a hash table for +faster search, when a directory is modified it is removed from cache +so that further visit in this directory refresh cache. +You may have in some rare cases to refresh directory manually with `\\\\[helm-refresh]' +for example when helm-find-files session is running and a file is modified/deleted +in current visited directory by an external command from outside Emacs. + +NOTE: Helm is using file-notify to watch visited directories, +nowaday most systems come with a notify package but if your +system doesn't support this, you can turn off file notifications +by customizing the variable `helm-ff-use-notify'. In this case +you will have to refresh manually directories when needed with `\\\\[helm-refresh]'. + +*** Prefix file candidates with icons + +If `all-the-icons' package is installed, turning on +`helm-ff-icon-mode' will show icons before files and directories. + +** Commands +\\ +|Keys|Description +|-----------+----------| +|\\[helm-ff-run-locate]|Run `locate' (`\\[universal-argument]' to specify locate database, `M-n' to insert basename of candidate). +|\\[helm-ff-run-browse-project]|Browse project (`\\[universal-argument]' to recurse, `\\[universal-argument] \\[universal-argument]' to recurse and refresh database). +|\\[helm-ff-run-find-sh-command]|Run `find' shell command from this directory. +|\\[helm-ff-run-grep]|Run Grep (`\\[universal-argument]' to recurse). +|\\[helm-ff-run-pdfgrep]|Run Pdfgrep on marked files. +|\\[helm-ff-run-zgrep]|Run zgrep (`\\[universal-argument]' to recurse). +|\\[helm-ff-run-grep-ag]|Run AG grep on current directory. +|\\[helm-ff-run-git-grep]|Run git-grep on current directory. +|\\[helm-ff-run-gid]|Run gid (id-utils). +|\\[helm-ff-run-etags]|Run Etags (`\\[universal-argument]' to use thing-at-point, `\\[universal-argument] \\[universal-argument]' to reload cache). +|\\[helm-ff-run-rename-file]|Rename Files (`\\[universal-argument]' to follow). +|\\[helm-ff-run-query-replace-fnames-on-marked]|Query replace on marked files. +|\\[helm-ff-run-copy-file]|Copy Files (`\\[universal-argument]' to follow). +|\\[helm-ff-run-mcp]|Copy car of marked to remaining directories. +|\\[helm-ff-run-rsync-file]|Rsync Files (`\\[universal-argument]' to edit command). +|\\[helm-ff-run-byte-compile-file]|Byte Compile Files (`\\[universal-argument]' to load). +|\\[helm-ff-run-load-file]|Load Files. +|\\[helm-ff-run-symlink-file]|Symlink Files. +|\\[helm-ff-run-hardlink-file]|Hardlink files. +|\\[helm-ff-run-relsymlink-file]|Relative symlink Files. +|\\[helm-ff-run-chmod]|Change mode on Files. +|\\[helm-ff-run-delete-file]|Delete Files. +|\\[helm-ff-run-touch-files]|Touch files. +|\\[helm-ff-run-kill-buffer-persistent]|Kill buffer candidate without leaving Helm. +|\\[helm-ff-persistent-delete]|Delete file without leaving Helm. +|\\[helm-ff-run-switch-to-shell]|Switch to prefered shell. +|\\[helm-ff-run-eshell-command-on-file]|Eshell command on file (`\\[universal-argument]' to apply on marked files, otherwise treat them sequentially). +|\\[helm-ff-run-ediff-file]|Ediff file. +|\\[helm-ff-run-ediff-merge-file]|Ediff merge file. +|\\[helm-ff-run-complete-fn-at-point]|Complete file name at point. +|\\[helm-ff-run-switch-other-window]|Switch to other window. +|\\[helm-ff-run-switch-other-frame]|Switch to other frame. +|\\[helm-ff-run-open-file-externally]|Open file with external program (`\\[universal-argument]' to choose). +|\\[helm-ff-run-preview-file-externally]|Preview file with external program. +|\\[helm-ff-run-open-file-with-default-tool]|Open file externally with default tool. +|\\[helm-ff-rotate-left-persistent]|Rotate image left. +|\\[helm-ff-rotate-right-persistent]|Rotate image right. +|\\[helm-ff-increase-image-size-persistent]|Zoom in image. +|\\[helm-ff-decrease-image-size-persistent]|Zoom out image. +|\\[helm-ff-toggle-thumbnails]|Show thumbnails on image files. +|\\[helm-find-files-up-one-level]|Go to parent directory. +|\\[helm-find-files-history]|Switch to the visited-directory history. +|\\[helm-ff-file-name-history]|Switch to file name history. +|\\[helm-ff-properties-persistent]|Show file properties in a tooltip. +|\\[helm-mark-all]|Mark all visible candidates. +|\\[helm-ff-run-toggle-auto-update]|Toggle auto-expansion of directories. +|\\[helm-unmark-all]|Unmark all candidates, visible and invisible ones. +|\\[helm-ff-run-mail-attach-files]|Attach files to message buffer. +|\\[helm-ff-run-print-file]|Print file, (`\\[universal-argument]' to refresh printer list). +|\\[helm-enlarge-window]|Enlarge Helm window. +|\\[helm-narrow-window]|Narrow Helm window. +|\\[helm-ff-run-toggle-basename]|Toggle basename/fullpath. +|\\[helm-ff-run-find-file-as-root]|Find file as root. +|\\[helm-ff-run-find-alternate-file]|Find alternate file. +|\\[helm-ff-run-insert-org-link]|Insert org link. +|\\[helm-ff-bookmark-set]|Set bookmark to current directory. +|\\[helm-find-files-switch-to-bookmark]|Jump to bookmark list. +|\\[helm-ff-sort-alpha]|Sort alphabetically. +|\\[helm-ff-sort-by-newest]|Sort by newest. +|\\[helm-ff-sort-by-size]|Sort by size. +|\\[helm-ff-toggle-dirs-only]|Show only directories. +|\\[helm-ff-toggle-files-only]|Show only files. +|\\[helm-ff-sort-by-ext]|Sort by extensions.") + +;;; Help for file-name-history +;; +;; +(defvar helm-file-name-history-help-message + "* Helm file name history + +** Tips +You can open directly the selected file and exit helm or preselect the file in helm-find-files, +see actions in action menu. + +You can toggle the view of deleted files, see commands below. + +** Commands +\\ +\\[helm-file-name-history-show-or-hide-deleted]|Toggle deleted files view.") + +;;; Help for `helm-read-file-name' +;; +;; +(defun helm-read-file-name-help-message () + (let ((name (if helm-alive-p + (assoc-default 'name (helm-get-current-source)) + "generic"))) + (format + "* Helm `%s' read file name completion + +This is `%s' read file name completion that have been \"helmized\" +because you have enabled [[Helm mode][helm-mode]]. +Don't confuse this with `helm-find-files' which is a native helm command, +see [[Helm functions vs helmized Emacs functions]]. + +** Tips + +*** Navigation + +**** Enter `~/' at end of pattern to quickly reach home directory + +**** Enter `/' at end of pattern to quickly reach the file system root + +**** Enter `./' at end of pattern to quickly reach `default-directory' + +\(As per its value at the beginning of the session.) + +If you already are in the `default-directory' this will move the cursor to the top. + +**** Enter `../' at end of pattern will reach upper directory, moving cursor on top + +This is different from using `\\[helm-find-files-up-one-level]' in that it moves +the cursor to the top instead of remaining on the previous subdir name. + +**** You can complete with partial basename + +It starts from the third character of the pattern. + +For instance \"fob\" or \"fbr\" will complete \"foobar\" but \"fb\" needs a +third character in order to complete it. + +*** Persistent actions + +By default `helm-read-file-name' uses the persistent actions of `helm-find-files'. + +**** Use `\\[universal-argument] \\\\[helm-execute-persistent-action]' to display an image + +**** `\\\\[helm-execute-persistent-action]' on a filename will expand to this filename in Helm-buffer + +Second hit displays the buffer filename. +Third hit kills the buffer filename. +Note: `\\[universal-argument] \\\\[helm-execute-persistent-action]' displays the buffer directly. + +**** Browse images directories with `helm-follow-mode' and navigate up/down + +*** Delete characters backward + +When you want to delete characters backward, e.g. to create a new file or directory, +auto-update may come in the way when it keeps updating to an existent directory. +In that case, type `C-' and then `'. +This should not be needed when copying/renaming files because autoupdate is disabled +by default in that case. + +Note: On a terminal, the default binding `C-' may not work. +In this case use `C-c '. + +*** Create new directories and files + +**** You can create a new directory and a new file at the same time + +Simply write the path in prompt and press `RET', e.g. +\"~/new/newnew/newnewnew/my_newfile.txt\". + +**** To create a new directory, append a \"/\" at to the new name and press `RET' + +**** To create a new file, enter a filename not ending with \"/\" + +File and directory creation works only with some commands (e.g. `find-file') +and it will not work with others where it is not intended to return a file or +a directory \(e.g `list-directory'). + +*** Exiting minibuffer with empty string + +You can exit minibuffer with empty string with \\\\[helm-cr-empty-string]. +It is useful when some commands are prompting continuously until you enter an empty prompt. + +** Commands +\\ +|Keys|Description +|-----------+----------| +|\\[helm-find-files-up-one-level]|Go to parent directory. +|\\[helm-ff-run-toggle-auto-update]|Toggle auto-expansion of directories. +|\\[helm-ff-run-toggle-basename]|Toggle basename. +|\\[helm-ff-file-name-history]|File name history. +|C/\\[helm-cr-empty-string]|Return empty string unless `must-match' is non-nil. +|\\[helm-next-source]|Go to next source. +|\\[helm-previous-source]|Go to previous source." + name name))) + +;;; FD help +;; +;; +(defvar helm-fd-help-message + "* Helm fd + +** Tips + +\[[https://github.com/sharkdp/fd][The Fd command line tool]] is very fast to search files recursively. +You may have to wait several seconds at first usage when your +hard drive cache is \"cold\", then once the cache is initialized +searchs are very fast. You can pass any [[https://github.com/sharkdp/fd#command-line-options][Fd options]] before pattern, e.g. \"-e py foo\". + +The [[https://github.com/sharkdp/fd][Fd]] command line can be customized with `helm-fd-switches' user variable. +Always use =--color always= as option otherwise you will have no colors. +To customize colors see [[https://github.com/sharkdp/fd#colorized-output][Fd colorized output]]. + +NOTE: +Starting from fd version 8.2.1, you have to provide the env var +LS_COLORS to Emacs to have a colorized output, the easiest way is +to add to your =~/.profile= file =eval $(dircolors)=. +Another way is using =setenv= in your init file. +This is not needed when running Emacs from a terminal either with =emacs -nw= +or =emacs= because emacs inherit the env vars of this terminal. +See [[https://github.com/sharkdp/fd/issues/725][fd bugref#725]] + +Search is (pcre) regexp based (see [[https://docs.rs/regex/1.0.0/regex/#syntax][Regexp syntax]]), multi patterns are _not_ supported. + +** Man page + +NAME + fd - find entries in the filesystem + +SYNOPSIS + fd [-HIEsiaLp0hV] [-d depth] [-t filetype] [-e ext] [-E exclude] [-c + when] [-j num] [-x cmd] [pattern] [path...] + +DESCRIPTION + fd is a simple, fast and user-friendly alternative to find(1). + +OPTIONS + -H, --hidden + Include hidden files and directories in the search results + (default: hidden files and directories are skipped). + + -I, --no-ignore + Show search results from files and directories that would other‐ + wise be ignored by .gitignore, .ignore, .fdignore, or the global + ignore file. + + -u, --unrestricted + Alias for '--no-ignore'. Can be repeated; '-uu' is an alias for + '--no-ignore --hidden'. + + --no-ignore-vcs + Show search results from files and directories that would other‐ + wise be ignored by .gitignore files. + + -s, --case-sensitive + Perform a case-sensitive search. By default, fd uses case-insen‐ + sitive searches, unless the pattern contains an uppercase char‐ + acter (smart case). + + -i, --ignore-case + Perform a case-insensitive search. By default, fd uses case- + insensitive searches, unless the pattern contains an uppercase + character (smart case). + + -g, --glob + Perform a glob-based search instead of a regular expression + search. + + --regex + Perform a regular-expression based seach (default). This can be + used to override --glob. + + -F, --fixed-strings + Treat the pattern as a literal string instead of a regular + expression. + + -a, --absolute-path + Shows the full path starting from the root as opposed to rela‐ + tive paths. + + -l, --list-details + Use a detailed listing format like 'ls -l'. This is basically an + alias for '--exec-batch ls -l' with some additional 'ls' + options. This can be used to see more metadata, to show symlink + targets and to achieve a deterministic sort order. + + -L, --follow + By default, fd does not descend into symlinked directories. + Using this flag, symbolic links are also traversed. + + -p, --full-path + By default, the search pattern is only matched against the file‐ + name (or directory name). Using this flag, the pattern is + matched against the full path. + + -0, --print0 + Separate search results by the null character (instead of new‐ + lines). Useful for piping results to xargs. + + --max-results count + Limit the number of search results to 'count' and quit immedi‐ + ately. + + -1 Limit the search to a single result and quit immediately. This + is an alias for '--max-results=1'. + + --show-errors + Enable the display of filesystem errors for situations such as + insufficient permissions or dead symlinks. + + --one-file-system, --mount, --xdev + By default, fd will traverse the file system tree as far as + other options dictate. With this flag, fd ensures that it does + not descend into a different file system than the one it started + in. Comparable to the -mount or -xdev filters of find(1). + + -h, --help + Print help information. + + -V, --version + Print version information. + + -d, --max-depth d + Limit directory traversal to at most d levels of depth. By + default, there is no limit on the search depth. + + --min-depth d + Only show search results starting at the given depth. See also: + '--max-depth' and '--exact-depth'. + + --exact-depth d + Only show search results at the exact given depth. This is an + alias for '--min-depth --max-depth '. + + -t, --type filetype + Filter search by type: + + f, file + regular files + + d, directory + directories + + l, symlink + symbolic links + + x, executable + executable (files) + + e, empty + empty files or directories + + s, socket + sockets + + p, pipe + named pipes (FIFOs) + + This option can be used repeatedly to allow for multiple file + types. + + -e, --extension ext + Filter search results by file extension ext. This option can be + used repeatedly to allow for multiple possible file extensions. + + -E, --exclude pattern + Exclude files/directories that match the given glob pattern. + This overrides any other ignore logic. Multiple exclude pat‐ + terns can be specified. + + --ignore-file path + Add a custom ignore-file in '.gitignore' format. These files + have a low precedence. + + -c, --color when + Declare when to colorize search results: + + auto Colorize output when standard output is connected to terminal (default). + + never Do not colorize output. + + always Always colorize output. + + -j, --threads num + Set number of threads to use for searching & executing (default: + number of available CPU cores). + + -S, --size size + Limit results based on the size of files using the format + <+-> + + '+' file size must be greater than or equal to this + + '-' file size must be less than or equal to this + + 'NUM' The numeric size (e.g. 500) + + 'UNIT' The units for NUM. They are not case-sensitive. Allowed + unit values: + + 'b' bytes + + 'k' kilobytes (base ten, 10^3 = 1000 bytes) + + 'm' megabytes + + 'g' gigabytes + + 't' terabytes + + 'ki' kibibytes (base two, 2^10 = 1024 bytes) + + 'mi' mebibytes + + 'gi' gibibytes + + 'ti' tebibytes + + --changed-within date|duration + Filter results based on the file modification time. The argument + can be provided as a specific point in time (YYYY-MM-DD + HH:MM:SS) or as a duration (10h, 1d, 35min). --change-newer- + than can be used as an alias. + + Examples: + --changed-within 2weeks + --change-newer-than \"2018-10-27 10:00:00\" + + --changed-before date|duration + Filter results based on the file modification time. The argument + can be provided as a specific point in time (YYYY-MM-DD + HH:MM:SS) or as a duration (10h, 1d, 35min). --change-older- + than can be used as an alias. + + Examples: + --changed-before \"2018-10-27 10:00:00\" + --change-older-than 2weeks + + -o, --owner [user][:group] + Filter files by their user and/or group. Format: + [(user|uid)][:(group|gid)]. Either side is optional. Precede + either side with a '!' to exclude files instead. + + Examples: + --owner john + --owner :students + --owner \"!john:students\" + + -x, --exec command + Execute command for each search result. The following placehold‐ + ers are substituted by a path derived from the current search + result: + + {} path + + {/} basename + + {//} parent directory + + {.} path without file extension + + {/.} basename without file extension + + -X, --exec-batch command + Execute command with all search results at once. A single + occurence of the following placeholders is authorized and + sub stituted by the paths derived from the search results before the + command is executed: + + {} path + + {/} basename + + {//} parent directory + + {.} path without file extension + + {/.} basename without file extension + +** Commands +\\ +|Keys|Description +|-----------+----------| +|\\[helm-ff-run-grep]|Run grep (`\\[universal-argument]' to recurse). +|\\[helm-ff-run-zgrep]|Run zgrep. +|\\[helm-ff-run-pdfgrep]|Run PDFgrep on marked files. +|\\[helm-ff-run-copy-file]|Copy file(s) +|\\[helm-ff-run-rename-file]|Rename file(s). +|\\[helm-ff-run-symlink-file]|Symlink file(s). +|\\[helm-ff-run-hardlink-file]|Hardlink file(s). +|\\[helm-ff-run-delete-file]|Delete file(s). +|\\[helm-ff-run-byte-compile-file]|Byte compile Elisp file(s) (`\\[universal-argument]' to load). +|\\[helm-ff-run-load-file]|Load Elisp file(s). +|\\[helm-ff-run-ediff-file]|Ediff file. +|\\[helm-ff-run-ediff-merge-file]|Ediff-merge file. +|\\[helm-ff-run-switch-other-window]|Switch to other window. +|\\[helm-ff-properties-persistent]|Show file properties. +|\\[helm-ff-run-open-file-externally]|Open file with external program (`\\[universal-argument]' to choose). +|\\[helm-ff-run-open-file-with-default-tool]|Open file externally with default tool. +|\\[helm-ff-run-insert-org-link]|Insert org link. +|\\[helm-fd-previous-directory]|Move to previous directory. +|\\[helm-fd-next-directory]|Move to next directory.") + +;;; Generic file help - Used by locate. +;; +;; +(defvar helm-generic-file-help-message + "* Helm Generic files + +** Tips + +*** Locate + +You can append to the search pattern any of the locate command line options, +e.g. -b, -e, -n , etc. See the locate(1) man page for more details. + +Some other sources (at the moment \"recentf\" and \"file in current directory\") +support the -b flag for compatibility with locate when they are used with it. + +When you enable fuzzy matching on locate with `helm-locate-fuzzy-match', the +search will be performed on basename only for efficiency (so don't add \"-b\" at +prompt). As soon as you separate the patterns with spaces, fuzzy matching will +be disabled and search will be done on the full filename. Note that in +multi-match, fuzzy is completely disabled, which means that each pattern is a +match regexp (i.e. \"helm\" will match \"helm\" but \"hlm\" will *not* match +\"helm\"). + +NOTE: On Windows use Everything with its command line ~es~ as a replacement of locate. +See [[https://github.com/emacs-helm/helm/wiki/Locate#windows][Locate on Windows]] + +*** Browse project + +When the current directory is not under version control, don't forget to refresh +the cache when files have been added/removed in the directory. + +*** Find command + +Recursively search files using the \"find\" shell command. + +Candidates are all filenames that match all given globbing patterns. This +respects the options `helm-case-fold-search' and +`helm-findutils-search-full-path'. + +You can pass arbitrary \"find\" options directly after a \"*\" separator. +For example, this would find all files matching \"book\" that are larger +than 1 megabyte: + + book * -size +1M + +** Commands +\\ +|Keys|Description +|-----------+----------| +|\\[helm-ff-run-toggle-basename]|Toggle basename. +|\\[helm-ff-run-grep]|Run grep (`\\[universal-argument]' to recurse). +|\\[helm-ff-run-zgrep]|Run zgrep. +|\\[helm-ff-run-pdfgrep]|Run PDFgrep on marked files. +|\\[helm-ff-run-copy-file]|Copy file(s) +|\\[helm-ff-run-rename-file]|Rename file(s). +|\\[helm-ff-run-symlink-file]|Symlink file(s). +|\\[helm-ff-run-hardlink-file]|Hardlink file(s). +|\\[helm-ff-run-delete-file]|Delete file(s). +|\\[helm-ff-run-byte-compile-file]|Byte compile Elisp file(s) (`\\[universal-argument]' to load). +|\\[helm-ff-run-load-file]|Load Elisp file(s). +|\\[helm-ff-run-ediff-file]|Ediff file. +|\\[helm-ff-run-ediff-merge-file]|Ediff-merge file. +|\\[helm-ff-run-switch-other-window]|Switch to other window. +|\\[helm-ff-properties-persistent]|Show file properties. +|\\[helm-ff-run-open-file-externally]|Open file with external program (`\\[universal-argument]' to choose). +|\\[helm-ff-run-open-file-with-default-tool]|Open file externally with default tool. +|\\[helm-ff-run-insert-org-link]|Insert org link.") + +;;; Grep help +;; +;; +(defvar helm-grep-help-message + "* Helm Grep + +** Tips + +With Helm supporting Git-grep and AG/RG, you are better off using +one of them for recursive searches, keeping grep or ack-grep to +grep individual or marked files. See [[Helm AG][Helm AG]]. + +*** Meaning of the prefix argument +**** With grep or ack-grep + +Grep recursively, in this case you are +prompted for types (ack-grep) or for wild cards (grep). + +**** With AG or RG + +the prefix arg allows you to specify a type of file to search in. + +*** You can use wild cards when selecting files (e.g. \"*.el\") + +Note that a way to grep specific files recursively is to use +e.g. \"**.el\" to select files, the variable `helm-file-globstar' +controls this (it is non nil by default), however it is much +slower than using grep recusively (see helm-find-files +documentation about this feature). + +*** Grep hidden files + +You may want to customize your command line for grepping hidden +files, for AG/RG use \"--hidden\", see man page +of your backend for more infos. + +*** You can grep in different directories by marking files or using wild cards + +*** You can save the result in a `helm-grep-mode' buffer + +See [[Commands][commands]] below. + +Once in that buffer you can use [[https://github.com/mhayashi1120/Emacs-wgrep][emacs-wgrep]] (external package not bundled with Helm) +to edit your changes, for Helm the package name is `wgrep-helm', it is hightly recommended. + +Type `g' to update (revert) the buffer (after saving your buffer's changes to file). + +NOTE: `next-error' is available from this `helm-grep-mode' buffer. + +When you are running `next-error' from elsewhere, you can update +the buffer with `helm-revert-next-error-last-buffer' (up to you +to bind it to a convenient key). + +*** Helm-grep supports multi-matching + +\(Starting from version 1.9.4.) + +Simply add a space between each pattern as for most Helm commands. + +NOTE: Depending the regexp you use it may match as well the +filename, this because we pipe the first grep command which send +the filename in output. + +*** See full path of selected candidate + +Add (helm-popup-tip-mode 1) in your init file or enable it +interactively with M-x helm-popup-tip-mode, however it is +generally enough to just put your mouse cursor over candidate. + +*** Open file in other window + +The command \\\\[helm-grep-run-other-window-action] allow you to open file +in other window horizontally or vertically if a prefix arg is supplied. + +*** Performance over TRAMP + +Grepping works but it is badly supported as TRAMP doesn't support multiple +processes running in a short delay (less than 5s) among other things. + +Helm uses a special hook to suspend the process automatically while you are +typing. Even if Helm handles this automatically by delaying each process by 5s, +you are adviced to this manually by hitting `\\\\[helm-toggle-suspend-update]' (suspend process) before +typing, and hit again `\\\\[helm-toggle-suspend-update]' when the regexp is ready to send to the remote +process. For simple regexps, there should be no need for this. + +Another solution is to not use TRAMP at all and mount your remote file system via +SSHFS. + +* Helm GID + +Still supported, but mostly deprecated, using AG/RG or Git-grep +is much more efficient, also `id-utils' seems no more maintained. + +** Tips + +Helm-GID reads the database created with the `mkid' command from id-utils. +The name of the database file can be customized with `helm-gid-db-file-name', it +is usually \"ID\". + +Helm-GID use the symbol at point as default-input. This command is also +accessible from `helm-find-files' which allow you to navigate to another +directory to consult its database. + +Note: Helm-GID supports multi-matches but only the last pattern entered will be +highlighted since there is no ~--color~-like option in GID itself. + +* Helm AG + +** Tips + +Helm-AG is different from grep or ack-grep in that it works on a +directory recursively and not on a list of files. It is called +helm-AG but it support several backend, namely AG, RG and PT. +Nowaday the best backend is Ripgrep aka RG, it is the fastest and +is actively maintained, see `helm-grep-ag-command' and +`helm-grep-ag-pipe-cmd-switches' to configure it. + +You can ignore files and directories with a \".agignore\" or +\".rgignore\" file, local to a directory or global when placed in +the home directory. (See the AG/RG man pages for more details.) +Note that `helm-grep-ignored-files'and +`helm-grep-ignored-directories' have no effect in helm-AG/RG. + +As always you can access Helm AG from `helm-find-files'. + +Starting with version 0.30, AG accepts one or more TYPE arguments on its command +line. Helm provides completion on these TYPE arguments when available with your +AG version. Use a prefix argument when starting a Helm-AG session to enable this +completion. See RG and AG man pages on how to add new types. + + +Note: You can mark several types to match in the AG query. The first AG +versions providing this feature allowed only one type, so in this case only the +last mark will be used. + +* Helm git-grep + +Helm-git-grep searches the current directory, i.e. the default directory or the +directory in Helm-find-files. If this current directory is a subdirectory of a +project and you want to also match parent directories (i.e the whole project), +use a prefix argument. + +** Commands +\\ +|Keys|Description +|-----------+----------| +|\\[helm-goto-next-file]|Next File. +|\\[helm-goto-precedent-file]|Previous File. +|\\[helm-yank-text-at-point]|Yank text at point in minibuffer. +|\\[helm-grep-run-other-window-action]|Jump to other window. +|\\[helm-grep-run-other-frame-action]|Jump to other frame. +|\\[helm-grep-run-default-action]|Run default action (same as `RET'). +|\\[helm-grep-run-save-buffer]|Save to a `helm-grep-mode' enabled buffer.") + +;;; PDF grep help +;; +;; +(defvar helm-pdfgrep-help-message + "* Helm PDFgrep Map + +** Commands +\\ +|Keys|Description +|-----------+----------| +|\\[helm-goto-next-file]|Next file. +|\\[helm-goto-precedent-file]|Previous file. +|\\[helm-yank-text-at-point]|Yank text at point in minibuffer.") + +;;; Etags help +;; +;; +(defvar helm-etags-help-message + "* Helm Etags Map + +** Commands +\\ +|Keys|Description +|-----------+----------| +|\\[helm-goto-next-file]|Next file. +|\\[helm-goto-precedent-file]|Previous file. +|\\[helm-yank-text-at-point]|Yank text at point in minibuffer.") + +;;; UCS help +;; +;; +(defvar helm-ucs-help-message + "* Helm UCS + +** Tips + +Use commands below to insert unicode characters in current buffer without +leaving Helm. + +** Commands +\\ +|Keys|Description +|-----------+----------| +|\\[helm-ucs-persistent-insert]|Insert character. +|\\[helm-ucs-persistent-forward]|Forward character. +|\\[helm-ucs-persistent-backward]|Backward character. +|\\[helm-ucs-persistent-delete]|Delete character backward. +|\\[helm-ucs-persistent-insert-space]|Insert space.") + +;;; Bookmark help +;; +;; +(defvar helm-bookmark-help-message + "* Helm bookmark name + +When `helm-bookmark-use-icon' is non nil and `all-the-icons' +package is installed icons before candidates will be displayed. + +** Commands +\\ +|Keys|Description +|-----------+----------| +|\\[helm-bookmark-run-jump-other-window]|Jump other window. +|\\[helm-bookmark-run-delete]|Delete bookmark. +|\\[helm-bookmark-run-edit]|Edit bookmark. +|\\[helm-bookmark-toggle-filename]|Toggle bookmark location visibility.") + +;;; Eshell command on file help +;; +;; +(defvar helm-esh-help-message + "* Helm Eshell on file + +** Tips + +*** Pass extra arguments after filename + +Normally the command or alias will be called with file as argument. For instance + + candidate_file + +But you can also pass an argument or more after \"candidate_file\" like this: + + %s [extra_args] + +\"candidate_file\" will be added at \"%s\" and the command will look at this: + + candidate_file [extra_args] + +**** Use placeholders in extra arguments + +placeholder for file without extension: \\@ +placeholder for incremental number: \\# + +\"candidate_file\" will be added at \"%s\" and \\@ but without extension. + + + +\"candidate_file\" will be added at \"%s\" and \\# will be replaced by an incremental number. + + %s \\# + +Here examples: + +Say you want to use the =convert= command to convert all your .png files in a directory to .jpg. + +This will convert all your files to jpg keeping the same basename. + + convert %s \\@.jpg + +This will convert all your files to foo-001.jpg, foo-002.jpg etc... + + convert %s foo-\\#.jpg + +You can of course combine both placeholders if needed. + + convert %s \\@-\\#.jpg + +*** Specify marked files as arguments + +When you have marked files and your command support only one file +as arg, helm will execute command sequencially on each file like +this: + +Example: + + file1 + file2 + ...etc + +When you have marked files and your command accept many files at +once helm will run your command with all files at once like this: + +Example: + + file1 file2 etc... + +The two use case above are applied automatically by Helm +depending if your command is an eshell alias which value ends by +'$1' or '$*'. If your command is not an alias, i.e. you entered +an arbitrary command on prompt with '%s' to specify filenames, +you will have to pass one prefix argument from the command +selection buffer. + +Note: This does not work on remote files. + +With two prefix-args the output is printed to the +`current-buffer', the command being executed in the same +conditions as described above. +NOTE: If your command is not an alias, you can't pass all files at once and print in current buffer at the same time. +Also note that running multiple files at once is not supported with remote files. + +*** Run eshell commands asynchronously + +You can run your commands asynchronously by adding \"&\" at end +of any commands, e.g. \"foo %s &\". You can also directly setup +your alias in the eshell alias file with e.g. \"alias foo $1 &\". + +** Commands +\\") + +;;; Ido virtual buffer help +;; +;; +(defvar helm-buffers-ido-virtual-help-message + "* Helm Ido virtual buffers + +** Commands +\\ +|Keys|Description +|-----------+----------| +|\\[helm-ff-run-switch-other-window]|Switch to other window. +|\\[helm-ff-run-switch-other-frame]|Switch to other frame. +|\\[helm-ff-run-grep]|Grep file. +|\\[helm-ff-run-zgrep]|Zgrep file. +|\\[helm-ff-run-delete-file]|Delete file. +|\\[helm-ff-run-open-file-externally]|Open file externally.") + +;;; helm-occur help +;; +;; +(defvar helm-moccur-help-message + "* Helm Moccur + +** Tips + +*** Searching in many buffers + +Start from `helm-buffers-list' or `helm-mini', mark some buffers and hit \\\\[helm-execute-persistent-action]' (persistent-action), to do it repeatedly +you can use `\\\\[helm-follow-action-forward]' and `\\\\[helm-follow-action-backward]' or enable `helm-follow-mode' with `\\\\[helm-follow-mode]'. +Follow mode is enabled by default in helm-occur. + +*** Switch to buffer in other window + +The command \\\\[helm-moccur-run-goto-line-ow] allow you to switch to buffer +in other window horizontally or vertically if a prefix arg is supplied. + +*** Save the results + +Similarly to Helm-grep, you can save the results with `\\\\[helm-occur-run-save-buffer]'. +Once in the saved buffer, you can edit it, see [[Edit a saved buffer][below]]. + +Of course if you don't save the results, you can resume the Helm session with +`helm-resume'. + +*** Refresh the resumed session + +When the buffer(s) where you ran helm-(m)occur get(s) modified, the Helm buffer +will flash red as a warning. You can refresh the buffer by running `\\\\[helm-refresh]'. +This can be done automatically by customizing `helm-moccur-auto-update-on-resume'. + +*** Refresh a saved buffer + +Type `g' to update (revert) the buffer. + +When you are running `next-error' from elsewhere, you can update +the buffer with `helm-revert-next-error-last-buffer' (up to you +to bind it to a convenient key). + +*** Edit a saved buffer + +First, install wgrep (https://github.com/mhayashi1120/Emacs-wgrep) and then: + +1) `C-c C-p' (`wgrep-change-to-wgrep-mode') to edit the buffer(s). +2) `C-x C-s' to save your changes. + +Tip: Use the excellent iedit (https://github.com/victorhge/iedit) to modify all +occurences at once in the buffer. + +NOTE: `next-error' is available from this `helm-occur-mode' buffer. + +*** Search in region + +When searching in current-buffer with `helm-occur', if a region +is found helm will search in this region only. If you marked +this region with `mark-defun' the symbol that was at point before +marking defun will be used when `helm-source-occur' is member of +`helm-sources-using-default-as-input'. + +*** Switch to next or previous source + +See [[Moving in `helm-buffer'][Moving in `helm-buffer']]. + +** Commands +\\ +|Keys|Description +|-----------+----------| +|\\[helm-occur-run-goto-line-ow]|Go to line in other window. +|\\[helm-occur-run-goto-line-of]|Go to line in new frame. +|\\[helm-occur-run-save-buffer]|Save results in new buffer.") +;;; Helm Top +;; +;; +(defvar helm-top-help-message + "* Helm Top + +** Commands +\\ +|Keys|Description +|-----------+----------| +|\\[helm-top-run-sort-by-com]|Sort by commands. +|\\[helm-top-run-sort-by-cpu]|Sort by CPU usage. +|\\[helm-top-run-sort-by-user]|Sort alphabetically by user. +|\\[helm-top-run-sort-by-mem]|Sort by memory.") + +;;; Helm Elisp package +;; +;; +(defvar helm-el-package-help-message + "* Helm Elisp package + +** Tips + +*** Compile all your packages asynchronously + +If you use async (if you have installed Helm from MELPA you do), only \"helm\", +\"helm-core\", and \"magit\" are compiled asynchronously. If you want all your +packages compiled asynchronously, add this to your init file: + + (setq async-bytecomp-allowed-packages '(all)) + +*** Upgrade Elisp packages + +On initialization (when Emacs is fetching packages on remote), if Helm finds +packages to upgrade, it will start in the upgradable packages view showing the packages +available for upgrade. + +On subsequent runs, you will have to refresh the list with `C-c \\[universal-argument]'. If Helm +finds upgrades you can switch to upgrade view (see below) to see what packages +are available for upgrade or simply hit `C-c U' to upgrade them all. + +To see upgradable packages hit `M-U'. + +Then you can install all upgradable packages with the \"upgrade all\" action +\(`C-c \\[universal-argument]'), or upgrade only specific packages by marking them and running the +\"upgrade\" action (visible only when there are upgradable packages). Of course +you can upgrade a single package by just running the \"upgrade\" action without +marking it (`C-c u' or `RET') . + +\*Warning:* You are strongly advised to \*restart* Emacs after \*upgrading* packages. + +*** Meaning of flags prefixing packages + +\(Emacs ≥25) + +- The flag \"S\" that prefixes package names means that the packages belong to `package-selected-packages'. + +- The flag \"U\" that prefix package names mean that this package is no more needed. + +** Commands +\\ +|Keys|Description +|-----------+----------| +|\\[helm-el-package-show-all]|Show all packages. +|\\[helm-el-package-show-installed]|Show installed packages only. +|\\[helm-el-package-show-uninstalled]|Show non-installed packages only. +|\\[helm-el-package-show-upgrade]|Show upgradable packages only. +|\\[helm-el-package-show-built-in]|Show built-in packages only. +|\\[helm-el-run-package-install]|Install package(s). +|\\[helm-el-run-package-reinstall]|Reinstall package(s). +|\\[helm-el-run-package-uninstall]|Uninstall package(s). +|\\[helm-el-run-package-upgrade]|Upgrade package(s). +|\\[helm-el-run-package-upgrade-all]|Upgrade all packages. +|\\[helm-el-run-visit-homepage]|Visit package homepage.") + +;;; Helm M-x +;; +;; +(defvar helm-M-x-help-message + "* Helm M-x + +** Tips + +*** Display docstring without quitting session (persistent action) + +You can get help on any command with persistent action (\\\\[helm-execute-persistent-action]) + +*** Display short docstring in helm buffer + +You can toggle short docstring description with \\\\[helm-M-x-toggle-short-doc]. +if you want this at startup you can configure `helm-M-x-show-short-doc'. + +NOTE: helm-M-x will be slower with this enabled. + +*** History source + +Helm-M-x is displaying two sources, one for the commands +themselves and one for the command history, more exactly +`extended-command-history', by default the history source is +displayed in first position, however you can put it in second +position if you don't like that by customizing +`helm-M-x-reverse-history'. + +**** Duplicate entries in helm-M-x history + +helm-M-x history obey to history variables, if you have +duplicates in your helm-M-x history set `history-delete-duplicates' to non nil. + +**** Number of entries in history + +The number of entries saved is controlled by `history-length' +global value, however if you want a different value for +`extended-command-history' e.g. 50 you can add to your config: + + (put 'extended-command-history 'history-length 50) + +*** Enabled modes are highlighted in helm-M-x + +*** Prefix arguments + +You can pass prefix arguments *after* starting `helm-M-x'. A mode-line +counter will display the number of given prefix arguments. + +If you pass prefix arguments before running `helm-M-x', it will +be displayed in the prompt. +The first `\\\\[universal-argument]' after `helm-M-x' clears those prefix arguments. + +NOTE: When you specify prefix arguments once `helm-M-x' is +started, the prefix argument apply on the next command, so if you +hit RET, it will apply on the selected command, but if you type a +new character at prompt to narrow down further candidates, the +prefix arg will apply to `self-insert-command' (e.g. if you type +`C-u e' \"eeee\" will be inserted in prompt) so select the +command you want to execute before specifying prefix arg. + +** Commands +\\ +|Keys|Description +|-----------+------------| +|\\[helm-M-x-universal-argument]|Universal argument for selected command +|\\[helm-M-x-toggle-short-doc]|Toggle details on commands") + + +;;; Helm imenu +;; +;; +(defvar helm-imenu-help-message + "* Helm Imenu + +** Commands +\\ +|Keys|Description +|-----------+----------| +|\\[helm-imenu-next-section]|Go to next section. +|\\[helm-imenu-previous-section]|Go to previous section.") + +;;; Helm colors +;; +;; +(defvar helm-colors-help-message + "* Helm colors + +** Commands +\\ +|Keys|Description +|-----------+----------| +|\\[helm-color-run-insert-name]|Insert the entry name. +|\\[helm-color-run-kill-name]|Kill the entry name. +|\\[helm-color-run-insert-rgb]|Insert entry in RGB format. +|\\[helm-color-run-kill-rgb]|Kill entry in RGB format.") + +;;; Helm Semantic +;; +;; +(defvar helm-semantic-help-message + "* Helm Semantic + +** Commands +\\") + +;;; Helm kmacro +;; +;; +(defvar helm-kmacro-help-message + "* Helm kmacro + +** Tips + +- Start recording a kmacro with `f3'. +- End the kmacro recording with `f4'. +- Run `helm-execute-kmacro' to list all your kmacros. + +Use persistent action to run your kmacro as many times as needed. +You can browse the kmacros with `helm-next-line' and `helm-previous-line'. + +Note: You can't record keys running Helm commands except `helm-M-x', under the +condition that you don't choose a command using Helm completion. + +** Commands +\\") + +;;; Kill ring +;; +;; +(defvar helm-kill-ring-help-message + "* Helm kill ring + +** Tips + +Every Helm session lets you save a candidate to the kill-ring / clipboard / +primary-selection with `\\\\[helm-kill-selection-and-quit]'. + +To save space, Helm-kill-ring truncates the candidates longer than +`helm-kill-ring-max-offset'. +`\\\\[helm-kill-ring-kill-selection]' then saves the whole +text and not the truncated value. The view of truncated candidates can be +toggled; see the command list below. + +As opposed to `yank', numeric prefix arguments are ignored with +`helm-show-kill-ring': there is no need for them since selection happens within +Helm. Moreover Helm has [[Shortcuts for executing the default action on the n-th candidate][Shortcuts for executing the default action on the n-th candidate]]. + +It is recommended to globally bind `M-y' to `helm-show-kill-ring'. Once in the +Helm-kill-ring session you can navigate to next/previous line with `M-y' and +`M-u' for convenience. Of course `\\[helm-next-line]' and `\\[helm-previous-line]' are still available. + +It is possible to delete candidates from the kill ring with `\\\\[helm-kill-ring-delete]' +but also persistently with `\\\\[helm-kill-ring-run-persistent-delete]'. + +You can concatenate marked candidates and yank them in the current +buffer, thus creating a new entry in the kill ring. Candidates are +concatenated with `helm-kill-ring-separator' as default but you can +change interactively the separator while yanking by using two prefix +args. When you have something else than \"\\n\" as default value for +`helm-kill-ring-separator' and you want to use \"\\n\" from prompt, use +`C-q C-j' to enter a newline in prompt. + +To not push a new entry in the kill ring, use `\\\\[helm-copy-to-buffer]' instead of RET +\(note that you can't change separator with this). + +When inserting candidates with the default action (`RET'), `point' is placed at +the end of the candidate and `mark' at the beginning. You can revert this behavior +by using a prefix argument, i.e. `C-u RET', like the regular `yank' command does. + +** Commands +\\ +|Keys|Description +|-----------+----------| +|\\[helm-next-line]|Next line. +|\\[helm-previous-line]|Previous line. +|\\[helm-kill-ring-delete]|Delete entry. +|\\[helm-kill-ring-toggle-truncated]|Toggle truncated view of candidate. +|\\[helm-kill-ring-kill-selection]|Kill non-truncated of selection.") + +;;; Completing-read +;; +(defun helm-comp-read-help-message () + (let ((com (assoc-default 'name (helm-get-current-source)))) + (format + "* Helm completing-read completion for `%s' + +Command `%s' is using a `completing-read' for completion on your input, +this completion have been \"helmized\" because you have enabled [[Helm mode][helm-mode]]'. + +** Tips + +*** Disabling or use something else than helm for completion of some commands + +You can disable helm completion or use something else for specific commands of your choice, +for this customize variable `helm-completing-read-handlers-alist'. + +*** Exiting minibuffer with empty string + +You can exit minibuffer with empty string with \\\\[helm-cr-empty-string]. +It is useful when some commands are prompting continuously until you enter an empty prompt. + +** Commands +\\ +|Keys|Description +|-----------+----------| +|\\[helm-cr-empty-string]|Exit minibuffer with empty string." + com com))) + + +;;; Mode line strings +;; +;; +;;;###autoload +(defvar helm-comp-read-mode-line "\ +\\\ +C/\\[helm-cr-empty-string]:Empty \ +\\\ +\\[helm-help]:Help \ +\\[helm-select-action]:Act \ +\\[helm-maybe-exit-minibuffer]/\ +f1/f2/f-n:NthAct \ +\\[helm-toggle-suspend-update]:Tog.suspend \ +\\[helm-customize-group]:Conf") + +;;;###autoload +(defvar helm-read-file-name-mode-line-string "\ +\\\ +\\[helm-help]:Help \ +C/\\[helm-cr-empty-string]:Empty \ +\\\ +\\[helm-select-action]:Act \ +\\[helm-maybe-exit-minibuffer]/\ +f1/f2/f-n:NthAct \ +\\[helm-toggle-suspend-update]:Tog.suspend \ +\\[helm-customize-group]:Conf" + "String displayed in mode-line in `helm-source-find-files'.") + +;;;###autoload +(defvar helm-top-mode-line "\ +\\\ +\\[helm-help]:Help \ +\\\ +\\[helm-select-action]:Act \ +\\[helm-maybe-exit-minibuffer]/\ +f1/f2/f-n:NthAct \ +\\[helm-toggle-suspend-update]:Tog.suspend \ +\\[helm-customize-group]:Conf") + + +(provide 'helm-help) + +;;; helm-help.el ends here diff --git a/org/elpa/helm-20230406.839/helm-id-utils.el b/org/elpa/helm-20230406.839/helm-id-utils.el new file mode 100644 index 0000000..215092b --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-id-utils.el @@ -0,0 +1,125 @@ +;;; helm-id-utils.el --- Helm interface for id-utils. -*- lexical-binding: t -*- + +;; Copyright (C) 2015 ~ 2020 Thierry Volpiatto + +;; 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 . + +;;; Code: + +(require 'helm-grep) +(require 'helm-help) + +(defgroup helm-id-utils nil + "ID-Utils related Applications and libraries for Helm." + :group 'helm) + +(defcustom helm-gid-program "gid" + "Name of gid command (usually `gid'). +For Mac OS X users, if you install GNU coreutils, the name `gid' +might be occupied by `id' from GNU coreutils, and you should set +it to correct name (or absolute path). For example, if using +MacPorts to install id-utils, it should be `gid32'." + :group 'helm-id-utils + :type 'file) + +(defcustom helm-gid-db-file-name "ID" + "Name of a database file created by `mkid' command from `ID-utils'." + :group 'helm-id-utils + :type 'string) + +(defun helm-gid-candidates-process () + (let* ((patterns (helm-mm-split-pattern helm-pattern)) + (default-com (format "%s -r %s" helm-gid-program + (shell-quote-argument (car patterns)))) + (cmd (helm-aif (cdr patterns) + (concat default-com + (cl-loop for p in it + concat (format " | grep --color=always %s" + (shell-quote-argument p)))) + default-com)) + (proc (start-process-shell-command + "gid" helm-buffer cmd))) + (set (make-local-variable 'helm-grep-last-cmd-line) cmd) + (prog1 proc + (set-process-sentinel + proc (lambda (_process event) + (when (string= event "finished\n") + (helm-maybe-show-help-echo) + (with-helm-window + (setq mode-line-format + '(" " mode-line-buffer-identification " " + (:eval (format "L%s" (helm-candidate-number-at-point))) " " + (:eval (propertize + (format "[Helm Gid process finished - (%s results)]" + (max (1- (count-lines + (point-min) (point-max))) + 0)) + 'face 'helm-locate-finish)))) + (force-mode-line-update)) + (helm-log "helm-gid-candidates-process" "Error: Gid %s" + (replace-regexp-in-string "\n" "" event)))))))) + +(defun helm-gid-filtered-candidate-transformer (candidates _source) + ;; "gid -r" may add dups in some rare cases. + (cl-loop for c in (helm-fast-remove-dups candidates :test 'equal) + collect (helm-grep--filter-candidate-1 c))) + +(defclass helm-gid-source (helm-source-async) + ((header-name + :initform + (lambda (name) + (concat name " [" (helm-get-attr 'db-dir) "]"))) + (db-dir :initarg :db-dir + :initform nil + :custom string + :documentation " Location of ID file.") + (candidates-process :initform #'helm-gid-candidates-process) + (filtered-candidate-transformer + :initform #'helm-gid-filtered-candidate-transformer) + (candidate-number-limit :initform 99999) + (action :initform (helm-make-actions + "Find File" 'helm-grep-action + "Find file other frame" 'helm-grep-other-frame + "Save results in grep buffer" 'helm-grep-save-results + "Find file other window" 'helm-grep-other-window)) + (persistent-action :initform 'helm-grep-persistent-action) + (history :initform 'helm-grep-history) + (nohighlight :initform t) + (help-message :initform 'helm-grep-help-message) + (requires-pattern :initform 2))) + +;;;###autoload +(defun helm-gid () + "Preconfigured `helm' for `gid' command line of `ID-Utils'. +Need A database created with the command `mkid' above +`default-directory'. +Need id-utils as dependency which provide `mkid', `gid' etc.. +See ." + (interactive) + (let* ((db (locate-dominating-file + default-directory + helm-gid-db-file-name)) + (helm-grep-default-directory-fn + (lambda () default-directory)) + (helm-maybe-use-default-as-input t)) + (cl-assert db nil "No DataBase found, create one with `mkid'") + (helm :sources (helm-make-source "Gid" 'helm-gid-source + :db-dir db) + :buffer "*helm gid*" + :keymap helm-grep-map + :truncate-lines helm-grep-truncate-lines))) + +(provide 'helm-id-utils) + +;;; helm-id-utils ends here diff --git a/org/elpa/helm-20230406.839/helm-imenu.el b/org/elpa/helm-20230406.839/helm-imenu.el new file mode 100644 index 0000000..b615a7f --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-imenu.el @@ -0,0 +1,534 @@ +;;; helm-imenu.el --- Helm interface for Imenu -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2023 Thierry Volpiatto + +;; 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 . + +;;; Code: + +(require 'cl-lib) +(require 'helm) +(require 'helm-lib) +(require 'imenu) +(require 'helm-utils) +(require 'helm-help) + +(defvar all-the-icons-default-adjust) +(defvar all-the-icons-scale-factor) + +(declare-function which-function "which-func") +(declare-function all-the-icons-material "ext:all-the-icons.el") +(declare-function all-the-icons-octicon "ext:all-the-icons.el") +(declare-function all-the-icons-faicon "ext:all-the-icons.el") +(declare-function all-the-icons-wicon "ext:all-the-icons.el") + + +(defgroup helm-imenu nil + "Imenu related libraries and applications for Helm." + :group 'helm) + +(defcustom helm-imenu-delimiter " / " + "Delimit types of candidates and their value in `helm-buffer'." + :group 'helm-imenu + :type 'string) + +(defcustom helm-imenu-execute-action-at-once-if-one + #'helm-imenu--execute-action-at-once-p + "Goto the candidate when only one is remaining." + :group 'helm-imenu + :type 'function) + +(defcustom helm-imenu-all-buffer-assoc nil + "Major mode association alist for `helm-imenu-in-all-buffers'. +Allow `helm-imenu-in-all-buffers' searching in these associated +buffers even if they are not derived from each other. The alist +is bidirectional, i.e. no need to add \\='((foo . bar) (bar . foo)), +only \\='((foo . bar)) is needed." + :type '(alist :key-type symbol :value-type symbol) + :group 'helm-imenu) + +(defcustom helm-imenu-in-all-buffers-separate-sources t + "Display imenu index of each buffer in its own source when non-nil. + +When nil all candidates are displayed in a single source. + +NOTE: Each source will have as name \"Imenu \". +`helm-source-imenu-all' will not be set, however it will continue +to be used as a flag for using default as input. If you do not +want this behavior, remove it from +`helm-sources-using-default-as-input' even if not using a single +source to display imenu in all buffers." + :type 'boolean + :group 'helm-imenu) + +(defcustom helm-imenu-type-faces + '(("^Variables$" . font-lock-variable-name-face) + ("^\\(Function\\|Functions\\|Defuns\\)$" . font-lock-function-name-face) + ("^\\(Types\\|Provides\\|Requires\\|Classes\\|Class\\|Includes\\|Imports\\|Misc\\|Code\\)$" . font-lock-type-face)) + "Faces for showing type in helm-imenu. +This is a list of cons cells. The cdr of each cell is a face to +be used, and it can also just be like \\='(:foreground +\"yellow\"). Each car is a regexp match pattern of the imenu type +string." + :group 'helm-faces + :type '(repeat + (cons + (regexp :tag "Imenu type regexp pattern") + (sexp :tag "Face")))) + +(defcustom helm-imenu-extra-modes nil + "Extra modes where `helm-imenu-in-all-buffers' should look into." + :group 'helm-imenu + :type '(repeat symbol)) + +(defcustom helm-imenu-hide-item-type-name nil + "Hide display name of imenu item type along with the icon when non nil. + +This value can be toggled with \\\\[helm-imenu-toggle-type-view]." + :group 'helm-imenu + :type 'boolean) + +(defcustom helm-imenu-use-icon nil + "Display an icon from all-the-icons package when non nil." + :group 'helm-imenu + :type 'boolean) + +(defcustom helm-imenu-icon-type-alist + '(("Array" . (all-the-icons-material "crop" :face font-lock-builtin-face)) + ("Array" . (all-the-icons-material "crop" :face font-lock-builtin-face)) + ("Boolean" . (all-the-icons-material "crop" :face font-lock-builtin-face)) + ("Boolean" . (all-the-icons-material "crop" :face font-lock-builtin-face)) + ("Class" . (all-the-icons-octicon "package" :face font-lock-type-face)) + ("Class" . (all-the-icons-octicon "package" :face font-lock-type-face)) + ("Color" . (all-the-icons-material "color_lens" :face font-lock-builtin-face)) + ("Colors" . (all-the-icons-material "color_lens" :face font-lock-builtin-face)) + ("Constant" . (all-the-icons-material "crop" :face font-lock-builtin-face)) + ("Constants" . (all-the-icons-material "crop" :face font-lock-builtin-face)) + ("Constructor" . (all-the-icons-faicon "cube" :face font-lock-function-name-face)) + ("Constructors" . (all-the-icons-faicon "cube" :face font-lock-function-name-face)) + ("Enum Member" . (all-the-icons-octicon "three-bars" :face font-lock-type-face)) + ("Enum Members" . (all-the-icons-octicon "three-bars" :face font-lock-type-face)) + ("Enum" . (all-the-icons-faicon "cog" :face font-lock-type-face)) + ("Enums" . (all-the-icons-faicon "cog" :face font-lock-type-face)) + ("Event" . (all-the-icons-wicon "lightning" :face font-lock-builtin-face)) + ("Events" . (all-the-icons-wicon "lightning" :face font-lock-builtin-face)) + ("Field" . (all-the-icons-octicon "three-bars" :face font-lock-type-face)) + ("Fields" . (all-the-icons-octicon "three-bars" :face font-lock-type-face)) + ("File" . (all-the-icons-faicon "file" :face font-lock-variable-name-face)) + ("Files" . (all-the-icons-faicon "file" :face font-lock-variable-name-face)) + ("Folder" . (all-the-icons-faicon "folder" :face font-lock-variable-name-face)) + ("Folders" . (all-the-icons-faicon "folder" :face font-lock-variable-name-face)) + ("Interface" . (all-the-icons-octicon "package" :face font-lock-builtin-face)) + ("Interfaces" . (all-the-icons-octicon "package" :face font-lock-builtin-face)) + ("Keyword" . (all-the-icons-octicon "key" :face font-lock-builtin-face)) + ("Keywords" . (all-the-icons-octicon "key" :face font-lock-builtin-face)) + ("Method" . (all-the-icons-faicon "cube" :face font-lock-function-name-face)) + ("Methods" . (all-the-icons-faicon "cube" :face font-lock-function-name-face)) + ("Defun" . (all-the-icons-faicon "cube" :face font-lock-function-name-face)) + ("Defuns" . (all-the-icons-faicon "cube" :face font-lock-function-name-face)) + ("Fn" . (all-the-icons-faicon "cube" :face font-lock-function-name-face)) + ("Fns" . (all-the-icons-faicon "cube" :face font-lock-function-name-face)) + ("Function" . (all-the-icons-faicon "cube" :face font-lock-function-name-face)) + ("Functions" . (all-the-icons-faicon "cube" :face font-lock-function-name-face)) + ("Misc" . (all-the-icons-faicon "globe" :face font-lock-function-name-face)) + ("Miscs" . (all-the-icons-faicon "globe" :face font-lock-function-name-face)) + ("Module" . (all-the-icons-faicon "angle-double-right" :face font-lock-builtin-face)) + ("Modules" . (all-the-icons-faicon "angle-double-right" :face font-lock-builtin-face)) + ("Numeric" . (all-the-icons-material "crop" :face font-lock-builtin-face)) + ("Numeric" . (all-the-icons-material "crop" :face font-lock-builtin-face)) + ("Object" . (all-the-icons-faicon "angle-double-right" :face font-lock-builtin-face)) + ("Objects" . (all-the-icons-faicon "angle-double-right" :face font-lock-builtin-face)) + ("Operator" . (all-the-icons-faicon "calculator" :face font-lock-builtin-face)) + ("Operators" . (all-the-icons-faicon "calculator" :face font-lock-builtin-face)) + ("Property" . (all-the-icons-octicon "book" :face font-lock-variable-name-face)) + ("Properties" . (all-the-icons-octicon "book" :face font-lock-variable-name-face)) + ("Reference" . (all-the-icons-octicon "book" :face font-lock-variable-name-face)) + ("References" . (all-the-icons-octicon "book" :face font-lock-variable-name-face)) + ("Snippet" . (all-the-icons-material "border_style" :face font-lock-variable-name-face)) + ("Snippet" . (all-the-icons-material "border_style" :face font-lock-variable-name-face)) + ("String" . (all-the-icons-material "text_fields" :face font-lock-variable-name-face)) + ("Strings" . (all-the-icons-material "text_fields" :face font-lock-variable-name-face)) + ("Struct" . (all-the-icons-faicon "cog" :face font-lock-type-face)) + ("Structs" . (all-the-icons-faicon "cog" :face font-lock-type-face)) + ("Text" . (all-the-icons-material "text_fields" :face font-lock-variable-name-face)) + ("Texts" . (all-the-icons-material "text_fields" :face font-lock-variable-name-face)) + ("Top level" . (all-the-icons-faicon "globe" :face font-lock-function-name-face)) + ("Trait" . (all-the-icons-octicon "package" :face font-lock-builtin-face)) + ("Traits" . (all-the-icons-octicon "package" :face font-lock-builtin-face)) + ("Type" . (all-the-icons-faicon "cog" :face font-lock-type-face)) + ("Types" . (all-the-icons-faicon "cog" :face font-lock-type-face)) + ("Type Parameter" . (all-the-icons-material "code" :face font-lock-type-face)) + ("Type Parameters" . (all-the-icons-material "code" :face font-lock-type-face)) + ("Unit" . (all-the-icons-faicon "bar-chart" :face font-lock-builtin-face)) + ("Units" . (all-the-icons-faicon "bar-chart" :face font-lock-builtin-face)) + ("Value" . (all-the-icons-faicon "cog" :face font-lock-type-face)) + ("Values" . (all-the-icons-faicon "cog" :face font-lock-type-face)) + ("Variable" . (all-the-icons-octicon "book" :face font-lock-variable-name-face)) + ("Variables" . (all-the-icons-octicon "book":face font-lock-variable-name-face))) + "An alist of types associated with a sexp returning an icon. +The sexp should be an `all-the-icons' function with its args." + :type '(alist :key-type string :value-type sexp) + :group 'helm-imenu) + +(defcustom helm-imenu-default-type-sexp + '(all-the-icons-faicon "globe" :face font-lock-function-name-face) + "Default sexp to use when no type for an object is found." + :type 'sexp + :group 'helm-imenu) + +;;; keymap +(defvar helm-imenu-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map helm-map) + (define-key map (kbd "M-") 'helm-imenu-next-section) + (define-key map (kbd "M-") 'helm-imenu-previous-section) + (define-key map (kbd "C-]") 'helm-imenu-toggle-type-view) + map)) + +(defun helm-imenu-toggle-type-view () + "Toggle candidate type view." + (interactive) + (with-helm-window + (setq helm-imenu-hide-item-type-name (not helm-imenu-hide-item-type-name)) + (let* ((sel (substring (helm-get-selection nil 'withprop) + (if helm-imenu-use-icon 2 0))) + (type (get-text-property 1 'type-name sel))) + (setq sel (substring-no-properties sel)) + (helm-force-update (if helm-imenu-hide-item-type-name + (format "^[ ]*%s$" + (car (last (split-string + sel helm-imenu-delimiter t)))) + (format "^[ ]*%s / %s$" + type sel)))))) +(put 'helm-imenu-toggle-type-view 'no-helm-mx t) + +(defcustom helm-imenu-lynx-style-map nil + "Use Arrow keys to jump to occurences." + :group 'helm-imenu + :type 'boolean + :set (lambda (var val) + (set var val) + (if val + (progn + (define-key helm-imenu-map (kbd "") 'helm-execute-persistent-action) + (define-key helm-imenu-map (kbd "") 'helm-maybe-exit-minibuffer)) + (define-key helm-imenu-map (kbd "") nil) + (define-key helm-imenu-map (kbd "") nil)))) + +(defun helm-imenu-next-or-previous-section (n) + (with-helm-window + (let* ((fn (lambda () + (let ((str (buffer-substring + (point-at-bol) (point-at-eol)))) + (if helm-imenu-hide-item-type-name + (get-text-property 1 'type-name str) + (car (split-string str helm-imenu-delimiter)))))) + (curtype (funcall fn)) + (stop-fn (if (> n 0) + #'helm-end-of-source-p + #'helm-beginning-of-source-p))) + (while (and (not (funcall stop-fn)) + (string= curtype (funcall fn))) + (forward-line n)) + (helm-mark-current-line) + (helm-follow-execute-persistent-action-maybe)))) + +(defun helm-imenu-next-section () + (interactive) + (helm-imenu-next-or-previous-section 1)) + +(defun helm-imenu-previous-section () + (interactive) + (helm-imenu-next-or-previous-section -1)) + + +;;; Internals +(defvar helm-cached-imenu-alist nil) +(make-variable-buffer-local 'helm-cached-imenu-alist) + +(defvar helm-cached-imenu-candidates nil) +(make-variable-buffer-local 'helm-cached-imenu-candidates) + +(defvar helm-cached-imenu-tick nil) +(make-variable-buffer-local 'helm-cached-imenu-tick) + +(defvar helm-imenu--in-all-buffers-cache nil) + + +(defvar helm-source-imenu nil "See (info \"(emacs)Imenu\")") +(defvar helm-source-imenu-all nil) + +(defclass helm-imenu-source (helm-source-sync) + ((candidates :initform 'helm-imenu-candidates) + (candidate-transformer :initform 'helm-imenu-transformer) + (persistent-action :initform 'helm-imenu-persistent-action) + (persistent-help :initform "Show this entry") + (nomark :initform t) + (keymap :initform 'helm-imenu-map) + (help-message :initform 'helm-imenu-help-message) + (action :initform 'helm-imenu-action) + (find-file-target :initform #'helm-imenu-quit-and-find-file-fn) + (group :initform 'helm-imenu))) + +(defcustom helm-imenu-fuzzy-match nil + "Enable fuzzy matching in `helm-source-imenu'." + :group 'helm-imenu + :type 'boolean + :set (lambda (var val) + (set var val) + (setq helm-source-imenu + (helm-make-source "Imenu" 'helm-imenu-source + :fuzzy-match helm-imenu-fuzzy-match)))) + +(defun helm-imenu--maybe-switch-to-buffer (candidate) + (let ((cand (cdr candidate))) + (helm-aif (and (markerp cand) (marker-buffer cand)) + (switch-to-buffer it)))) + +(defun helm-imenu--execute-action-at-once-p () + (let ((cur (helm-get-selection)) + (mb (with-helm-current-buffer + (save-excursion + (goto-char (point-at-bol)) + (point-marker))))) + ;; Happen when cursor is on the line where a definition is. This + ;; prevent jumping to the definition where we are already, instead + ;; display helm with all definitions and preselection to the place + ;; we already are. + (if (equal (cdr cur) mb) + (prog1 nil + (helm-set-pattern "") + (helm-force-update)) + t))) + +(defun helm-imenu-quit-and-find-file-fn (source) + (let ((sel (helm-get-selection nil nil source))) + (when (and (consp sel) (markerp (cdr sel))) + (buffer-file-name (marker-buffer (cdr sel)))))) + +(defun helm-imenu-action (candidate) + "Default action for `helm-source-imenu'." + (helm-log-run-hook "helm-imenu-action" 'helm-goto-line-before-hook) + (helm-imenu--maybe-switch-to-buffer candidate) + (imenu candidate) + ;; If semantic is supported in this buffer + ;; imenu used `semantic-imenu-goto-function' + ;; and position have been highlighted, + ;; no need to highlight again. + (unless (eq imenu-default-goto-function + 'semantic-imenu-goto-function) + (helm-highlight-current-line))) + +(defun helm-imenu-persistent-action (candidate) + "Default persistent action for `helm-source-imenu'." + (helm-imenu--maybe-switch-to-buffer candidate) + (imenu candidate) + (helm-highlight-current-line)) + +(defun helm-imenu-candidates (&optional buffer) + (with-current-buffer (or buffer helm-current-buffer) + (let ((tick (buffer-modified-tick))) + (if (eq helm-cached-imenu-tick tick) + helm-cached-imenu-candidates + (setq imenu--index-alist nil) + (prog1 (setq helm-cached-imenu-candidates + (let ((index (imenu--make-index-alist t))) + (helm-imenu--candidates-1 + (delete (assoc "*Rescan*" index) index)))) + (setq helm-cached-imenu-tick tick)))))) + +(defun helm-imenu-candidates-in-all-buffers (&optional build-sources) + (let* ((lst (buffer-list)) + (progress-reporter (make-progress-reporter + "Imenu indexing buffers..." 1 (length lst)))) + (prog1 + (cl-loop with cur-buf = (if build-sources + (current-buffer) helm-current-buffer) + for b in lst + for count from 1 + when (with-current-buffer b + (and (or (member major-mode helm-imenu-extra-modes) + (derived-mode-p 'prog-mode)) + (helm-same-major-mode-p + cur-buf helm-imenu-all-buffer-assoc))) + if build-sources + collect (helm-make-source + (format "Imenu in %s" (buffer-name b)) + 'helm-imenu-source + :candidates (with-current-buffer b + (helm-imenu-candidates b)) + :fuzzy-match helm-imenu-fuzzy-match) + else + append (with-current-buffer b + (helm-imenu-candidates b)) + do (progress-reporter-update progress-reporter count)) + (progress-reporter-done progress-reporter)))) + +(defun helm-imenu--candidates-1 (alist) + (cl-loop for elm in alist + nconc (cond + ((imenu--subalist-p elm) + (helm-imenu--candidates-1 + (cl-loop for (e . v) in (cdr elm) collect + (cons (propertize + e 'helm-imenu-type (car elm)) + ;; If value is an integer, convert it + ;; to a marker, otherwise it is a cons cell + ;; and it will be converted on next recursions. + ;; (Bug#1060) [1]. + (if (integerp v) (copy-marker v) v))))) + ((listp (cdr elm)) + (and elm (list elm))) + (t + ;; bug in imenu, should not be needed. + (and (cdr elm) + ;; Semantic uses overlays whereas imenu uses + ;; markers (Bug#1706). + (setcdr elm (pcase (cdr elm) ; Same as [1]. + ((and ov (pred overlayp)) + (copy-overlay ov)) + ((and mk (or (pred markerp) + (pred integerp))) + (copy-marker mk)))) + (list elm)))))) + +(defun helm-imenu--get-prop (item) + ;; property value of ITEM can have itself + ;; a property value which have itself a property value + ;; ...and so on; Return a list of all these + ;; properties values starting at ITEM. + (let* ((prop (get-text-property 0 'helm-imenu-type item)) + (lst (list prop item))) + (when prop + (while prop + (setq prop (get-text-property 0 'helm-imenu-type prop)) + (and prop (push prop lst))) + lst))) + +(defun helm-imenu-icon-for-type (type) + "Return an icon for type TYPE. +The icon is found in `helm-imenu-icon-type-alist', if not +`helm-imenu-default-type-sexp' is evaled to provide a default icon." + (require 'all-the-icons) + (let ((all-the-icons-scale-factor 1.0) + (all-the-icons-default-adjust 0.0)) + (or (helm-aand (assoc-default + type helm-imenu-icon-type-alist) + (apply (car it) (cdr it))) + (apply (car helm-imenu-default-type-sexp) + (cdr helm-imenu-default-type-sexp))))) + +(defun helm-imenu-transformer (candidates) + (cl-loop for (k . v) in candidates + ;; (k . v) == (symbol-name . marker) + for bufname = (buffer-name + (pcase v + ((pred overlayp) (overlay-buffer v)) + ((or (pred markerp) (pred integerp)) + (marker-buffer v)))) + for types = (or (helm-imenu--get-prop k) + (list (if (with-current-buffer bufname + (derived-mode-p 'prog-mode)) + "Function" + "Top level") + k)) + for type-icon = (and helm-imenu-use-icon + (helm-imenu-icon-for-type (car types))) + for type-name = (propertize + (car types) 'face + (cl-loop for (p . f) in helm-imenu-type-faces + when (string-match p (car types)) + return f + finally return 'default)) + for disp1 = (mapconcat 'identity + (cdr types) + (propertize helm-imenu-delimiter + 'face 'shadow)) + for disp = (concat (if helm-imenu-use-icon + (concat (propertize " " 'display type-icon) " ") + "") + (if helm-imenu-hide-item-type-name + "" + (concat type-name + (propertize helm-imenu-delimiter + 'face 'shadow))) + (propertize disp1 'help-echo bufname 'types types)) + collect + (cons (propertize disp 'type-name type-name) (cons k v)))) + + +;;;###autoload +(defun helm-imenu () + "Preconfigured `helm' for `imenu'." + (interactive) + (require 'which-func) + (unless helm-source-imenu + (setq helm-source-imenu + (helm-make-source "Imenu" 'helm-imenu-source + :fuzzy-match helm-imenu-fuzzy-match))) + (let* ((imenu-auto-rescan t) + (helm-highlight-matches-around-point-max-lines 'never) + (str (thing-at-point 'symbol)) + (init-reg (and str (concat "\\_<" (regexp-quote str) "\\_>"))) + (helm-execute-action-at-once-if-one + helm-imenu-execute-action-at-once-if-one)) + (helm :sources 'helm-source-imenu + :default (and str (list init-reg str)) + :preselect (helm-aif (which-function) + (concat "\\_<" (regexp-quote it) "\\_>") + init-reg) + :buffer "*helm imenu*"))) + +;;;###autoload +(defun helm-imenu-in-all-buffers () + "Fetch Imenu entries in all buffers with similar mode as current. +A mode is similar as current if it is the same, it is derived +i.e. `derived-mode-p' or it have an association in +`helm-imenu-all-buffer-assoc'." + (interactive) + (require 'which-func) + (unless helm-imenu-in-all-buffers-separate-sources + (unless helm-source-imenu-all + (setq helm-source-imenu-all + (helm-make-source "Imenu in all buffers" 'helm-imenu-source + :init (lambda () + ;; Use a cache to avoid repeatedly sending + ;; progress-reporter message when updating + ;; (Bug#1704). + (setq helm-imenu--in-all-buffers-cache + (helm-imenu-candidates-in-all-buffers))) + :candidates 'helm-imenu--in-all-buffers-cache + :fuzzy-match helm-imenu-fuzzy-match)))) + (let* ((imenu-auto-rescan t) + (helm-highlight-matches-around-point-max-lines 'never) + (str (thing-at-point 'symbol)) + (init-reg (and str (concat "\\_<" (regexp-quote str) "\\_>"))) + (helm-execute-action-at-once-if-one + helm-imenu-execute-action-at-once-if-one) + (helm-maybe-use-default-as-input + (not (null (memq 'helm-source-imenu-all + helm-sources-using-default-as-input)))) + (sources (if helm-imenu-in-all-buffers-separate-sources + (helm-imenu-candidates-in-all-buffers 'build-sources) + '(helm-source-imenu-all)))) + (helm :sources sources + :default (and str (list init-reg str)) + :preselect (helm-aif (which-function) + (concat "\\_<" (regexp-quote it) "\\_>") + init-reg) + :buffer "*helm imenu all*"))) + +(provide 'helm-imenu) + +;;; helm-imenu.el ends here diff --git a/org/elpa/helm-20230406.839/helm-info.el b/org/elpa/helm-20230406.839/helm-info.el new file mode 100644 index 0000000..54023bf --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-info.el @@ -0,0 +1,308 @@ +;;; helm-info.el --- Browse info index with helm -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2023 Thierry Volpiatto + +;; 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 . + +;;; Code: + +(require 'cl-lib) +(require 'helm) +(require 'helm-lib) +(require 'helm-utils) +(require 'info) + +(declare-function Info-index-nodes "info" (&optional file)) +(declare-function Info-goto-node "info" (&optional fork)) +(declare-function Info-find-node "info" (filename nodename &optional no-going-back)) +(declare-function ring-insert "ring") +(declare-function ring-empty-p "ring") +(declare-function ring-ref "ring") +(defvar Info-history) +(defvar Info-directory-list) +;; `Info-minibuf-history' is not declared in Emacs, see emacs bug/58786. +(when (and (> emacs-major-version 28) + (not (boundp 'Info-minibuf-history))) + (defvar Info-minibuf-history nil)) + + +;;; Customize + +(defgroup helm-info nil + "Info-related applications and libraries for Helm." + :group 'helm) + +(defcustom helm-info-default-sources + '(helm-source-info-elisp + helm-source-info-cl + helm-source-info-eieio + helm-source-info-pages) + "Default sources to use for looking up symbols at point in Info +files with `helm-info-at-point'." + :group 'helm-info + :type '(repeat (choice symbol))) + +;;; Build info-index sources with `helm-info-source' class. + +(cl-defun helm-info-init (&optional (file (helm-get-attr 'info-file))) + "Initialize candidates for info FILE. +If FILE have nodes, loop through all nodes and accumulate candidates +found in each node, otherwise scan only the current info buffer." + ;; Allow reinit candidate buffer when using edebug. + (helm-aif (and debug-on-error + (helm-candidate-buffer)) + (kill-buffer it)) + (unless (helm-candidate-buffer) + (save-selected-window + (info file " *helm info temp buffer*") + (let ((tobuf (helm-candidate-buffer 'global)) + Info-history) + (helm-aif (Info-index-nodes) + (dolist (node it) + (Info-goto-node node) + (helm-info-scan-current-buffer tobuf)) + (helm-info-scan-current-buffer tobuf)) + (bury-buffer))))) + +(defun helm-info-scan-current-buffer (tobuf) + "Scan current info buffer and print lines to TOBUF. +Argument TOBUF is the `helm-candidate-buffer'." + (let (start end line) + (goto-char (point-min)) + (while (search-forward "\n* " nil t) + (unless (search-forward "Menu:\n" (1+ (point-at-eol)) t) + (setq start (point-at-bol) + ;; Fix Bug#1503 by getting the invisible + ;; info displayed on next line in long strings. + ;; e.g "* Foo.\n (line 12)" instead of + ;; "* Foo.(line 12)" + end (or (save-excursion + (goto-char (point-at-bol)) + (re-search-forward "(line +[0-9]+)" nil t)) + (point-at-eol)) + ;; Long string have a new line inserted before the + ;; invisible spec, remove it. + line (replace-regexp-in-string + "\n" "" (buffer-substring start end))) + (with-current-buffer tobuf + (insert line) + (insert "\n")))))) + +(defun helm-info-goto (node-line) + "The helm-info action to jump to NODE-LINE." + (let ((alive (buffer-live-p (get-buffer "*info*")))) + (Info-goto-node (car node-line)) + (when alive (revert-buffer nil t)) + (helm-goto-line (cdr node-line)))) + +(defvar helm-info--node-regexp + "^\\* +\\(.+\\):[[:space:]]+\\(.*\\)\\(?:[[:space:]]*\\)(line +\\([0-9]+\\))" + "A regexp that should match file name, node name and line number in +a line like this: + +\* bind: Bash Builtins. (line 21).") + +(defun helm-info-display-to-real (line) + "Transform LINE to an acceptable argument for `info'. +If line have a node use the node, otherwise use directly first name found." + (let ((info-file (helm-get-attr 'info-file)) + nodename linum) + (when (string-match helm-info--node-regexp line) + (setq nodename (match-string 2 line) + linum (match-string 3 line))) + (if nodename + (cons (format "(%s)%s" + info-file + (replace-regexp-in-string ":\\'" "" nodename)) + (string-to-number (or linum "1"))) + (cons (format "(%s)%s" + info-file + (helm-aand (replace-regexp-in-string "^* " "" line) + (replace-regexp-in-string "::?.*\\'" "" it))) + 1)))) + +(defclass helm-info-source (helm-source-in-buffer) + ((info-file :initarg :info-file + :initform nil + :custom 'string) + (init :initform #'helm-info-init) + (display-to-real :initform #'helm-info-display-to-real) + (get-line :initform #'buffer-substring) + (action :initform '(("Goto node" . helm-info-goto))))) + +(defmacro helm-build-info-source (fname &rest args) + `(helm-make-source (concat "Info Index: " ,fname) 'helm-info-source + :info-file ,fname ,@args)) + +(defun helm-build-info-index-command (name doc source buffer) + "Define a Helm command NAME with documentation DOC. +Arg SOURCE will be an existing helm source named +`helm-source-info-' and BUFFER a string buffer name." + (defalias (intern (concat "helm-info-" name)) + (lambda () + (interactive) + (helm :sources source + :buffer buffer + :candidate-number-limit 1000)) + doc)) + +(defun helm-define-info-index-sources (var-value &optional commands) + "Define Helm sources named helm-source-info-. +Sources are generated for all entries of +`helm-default-info-index-list'. +If COMMANDS arg is non-nil, also build commands named +`helm-info-'. +Where NAME is an element of `helm-default-info-index-list'." + (cl-loop for str in var-value + for sym = (intern (concat "helm-source-info-" str)) + do (set sym (helm-build-info-source str)) + when commands + do (helm-build-info-index-command + str (format "Predefined helm for %s info." str) + sym (format "*helm info %s*" str)))) + +(defun helm-info-index-set (var value) + (set var value) + (helm-define-info-index-sources value t)) + +;;; Search Info files + +;; `helm-info' is the main entry point here. It prompts the user for an Info +;; file, then a term in the file's index to jump to. + +(defvar helm-info-searched (make-ring 32) + "Ring of previously searched Info files.") + +(defun helm-get-info-files () + "Return list of Info files to use for `helm-info'. + +Elements of the list are strings of Info file names without +extensions (e.g., \"emacs\" for file \"emacs.info.gz\"). Info +files are found by searching directories in +`Info-directory-list'." + (info-initialize) ; Build Info-directory-list from INFOPATH (Bug#2118) + (let ((files (cl-loop for d in (or Info-directory-list + Info-default-directory-list) + when (file-directory-p d) + append (directory-files d nil "\\.info")))) + (helm-fast-remove-dups + (cl-loop for f in files collect + (helm-file-name-sans-extension f)) + :test 'equal))) + +(defcustom helm-default-info-index-list + (helm-get-info-files) + "Info files to search in with `helm-info'." + :group 'helm-info + :type '(repeat (choice string)) + :set 'helm-info-index-set) + +(defun helm-info-search-index (candidate) + "Search the index of CANDIDATE's Info file using the function +helm-info-." + (let ((helm-info-function + (intern-soft (concat "helm-info-" candidate)))) + (when (fboundp helm-info-function) + (funcall helm-info-function) + (ring-insert helm-info-searched candidate)))) + +(defun helm-def-source--info-files () + "Return a Helm source for Info files." + (helm-build-sync-source "Helm Info" + :candidates + (lambda () (copy-sequence helm-default-info-index-list)) + :candidate-number-limit 999 + :candidate-transformer + (lambda (candidates) + (sort candidates #'string-lessp)) + :nomark t + :action '(("Search index" . helm-info-search-index)))) + +;;;###autoload +(defun helm-info (&optional refresh) + "Preconfigured `helm' for searching Info files' indices. + +With a prefix argument \\[universal-argument], set REFRESH to +non-nil. + +Optional parameter REFRESH, when non-nil, re-evaluates +`helm-default-info-index-list'. If the variable has been +customized, set it to its saved value. If not, set it to its +standard value. See `custom-reevaluate-setting' for more. + +REFRESH is useful when new Info files are installed. If +`helm-default-info-index-list' has not been customized, the new +Info files are made available." + (interactive "P") + (let ((default (unless (ring-empty-p helm-info-searched) + (ring-ref helm-info-searched 0)))) + (when refresh + (custom-reevaluate-setting 'helm-default-info-index-list)) + (helm :sources (helm-def-source--info-files) + :buffer "*helm Info*" + :preselect (and default + (concat "\\_<" (regexp-quote default) "\\_>"))))) + +;;;; Info at point + +;; `helm-info-at-point' is the main entry point here. It searches for the +;; symbol at point through the Info sources defined in +;; `helm-info-default-sources' and jumps to it. + +(defvar helm-info--pages-cache nil + "Cache for all Info pages on the system.") + +(defvar helm-source-info-pages + (helm-build-sync-source "Info Pages" + :init #'helm-info-pages-init + :candidates (lambda () helm-info--pages-cache) + :action '(("Show with Info" . + (lambda (node-str) + (info (replace-regexp-in-string + "^[^:]+: " "" node-str))))) + :requires-pattern 2) + "Helm source for Info pages.") + +(defun helm-info-pages-init () + "Collect candidates for initial Info node Top." + (or helm-info--pages-cache + (let ((info-topic-regexp "\\* +\\([^:]+: ([^)]+)[^.]*\\)\\.")) + (save-selected-window + (info "dir" " *helm info temp buffer*") + (Info-find-node "dir" "top") + (goto-char (point-min)) + (while (re-search-forward info-topic-regexp nil t) + (push (match-string-no-properties 1) + helm-info--pages-cache)) + (kill-buffer))))) + +;;;###autoload +(defun helm-info-at-point () + "Preconfigured `helm' for searching info at point." + (interactive) + ;; Symbol at point is used as default as long as one of the sources + ;; in `helm-info-default-sources' is member of + ;; `helm-sources-using-default-as-input'. + (cl-loop for src in helm-info-default-sources + for name = (if (symbolp src) + (assoc 'name (symbol-value src)) + (assoc 'name src)) + unless name + do (warn "Couldn't build source `%S' without its info file" src)) + (helm :sources helm-info-default-sources + :buffer "*helm info*")) + +(provide 'helm-info) + +;;; helm-info.el ends here diff --git a/org/elpa/helm-20230406.839/helm-locate.el b/org/elpa/helm-20230406.839/helm-locate.el new file mode 100644 index 0000000..11c66c7 --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-locate.el @@ -0,0 +1,482 @@ +;;; helm-locate.el --- helm interface for locate. -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2023 Thierry Volpiatto + +;; 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 . + +;; NOTE for WINDOZE users: +;; You have to install Everything with his command line interface here: +;; http://www.voidtools.com/download.php + +;;; Code: + +(require 'cl-lib) +(require 'helm) +(require 'helm-types) +(require 'helm-help) + +(defvar helm-ff-default-directory) +(declare-function helm-read-file-name "helm-mode") + + +(defgroup helm-locate nil + "Locate related Applications and libraries for Helm." + :group 'helm) + +(defcustom helm-locate-db-file-regexp "m?locate\\.db$" + "Default regexp to match locate database. +If nil Search in all files." + :type 'string) + +(defcustom helm-ff-locate-db-filename "locate.db" + "The basename of the locatedb file you use locally in your directories. +When this is set and Helm finds such a file in the directory from +where you launch locate, it will use this file and will not +prompt you for a db file. +Note that this happen only when locate is launched with a prefix +arg." + :type 'string) + +(defcustom helm-locate-command nil + "A list of arguments for locate program. + +Helm will calculate a default value for your system on startup +unless `helm-locate-command' is non-nil. + +Here are the default values it will use according to your system: + +Gnu/linux: \"locate %s -e -A --regex %s\" +berkeley-unix: \"locate %s %s\" +windows-nt: \"es %s %s\" +Others: \"locate %s %s\" + +This string will be passed to format so it should end with `%s'. +The first format spec is used for the \"-i\" value of locate/es, +so don't set it directly but use `helm-locate-case-fold-search' +for this. + +The last option must be the one preceding pattern i.e \"-r\" or +\"--regex\". + +You will be able to pass other options such as \"-b\" or \"l\" +during Helm invocation after entering pattern only when multi +matching, not when fuzzy matching. + +Note that the \"-b\" option is added automatically by Helm when +var `helm-locate-fuzzy-match' is non-nil and switching back from +multimatch to fuzzy matching (this is done automatically when a +space is detected in pattern)." + :type 'string) + +(defcustom helm-locate-create-db-command + "updatedb -l 0 -o '%s' -U '%s'" + "Command used to create a locale locate db file." + :type 'string) + +(defcustom helm-locate-case-fold-search helm-case-fold-search + "It have the same meaning as `helm-case-fold-search'. +The -i option of locate will be used depending of value of +`helm-pattern' when this is set to \\='smart. +When nil \"-i\" will not be used at all and when non-nil it will +always be used. +NOTE: the -i option of the \"es\" command used on windows does +the opposite of \"locate\" command." + :type 'symbol) + +(defcustom helm-locate-fuzzy-match nil + "Enable fuzzy matching in `helm-locate'. +Note that when this is enabled searching is done on basename." + :type 'boolean) + +(defcustom helm-locate-fuzzy-sort-fn + #'helm-locate-default-fuzzy-sort-fn + "Default fuzzy matching sort function for locate." + :type 'boolean) + +(defcustom helm-locate-project-list nil + "A list of directories, your projects. +When set, allow browsing recursively files in all directories of +this list with `helm-projects-find-files'." + :type '(repeat string)) + +(defcustom helm-locate-recursive-dirs-command "locate -i -e -A --regex '^%s' '%s.*$'" + "Command used for recursive directories completion in `helm-find-files'. + +For Windows and `es' use something like \"es -r ^%s.*%s.*$\" + +The two format specs are mandatory. + +If for some reasons you can't use locate because your filesystem +doesn't have a database, you can use find command from findutils +but be aware that it will be much slower. See `helm-find-files' +embedded help for more infos." + :type 'string + :group 'helm-files) + + +(defvar helm-locate-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map helm-generic-files-map) + (define-key map (kbd "DEL") 'helm-delete-backward-no-update) + map)) + +(defface helm-locate-finish + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "Green")) + "Face used in mode line when locate process is finish." + :group 'helm-locate) + + +(defun helm-ff-find-locatedb (&optional from-ff) + "Try to find if a local locatedb file is available. +The search is done in `helm-ff-default-directory' or falls back to +`default-directory' if FROM-FF is nil." + (helm-aif (and helm-ff-locate-db-filename + (locate-dominating-file + (or (and from-ff + helm-ff-default-directory) + default-directory) + helm-ff-locate-db-filename)) + (expand-file-name helm-ff-locate-db-filename it))) + +(defun helm-locate-create-db-default-function (db-name directory) + "Default function used to create a locale locate db file. +Argument DB-NAME name of the db file. +Argument DIRECTORY root of file system subtree to scan." + (format helm-locate-create-db-command + db-name (expand-file-name directory))) + +(defvar helm-locate-create-db-function + #'helm-locate-create-db-default-function + "Function used to create a locale locate db file. +It should receive the same arguments as +`helm-locate-create-db-default-function'.") + +(defun helm-locate-1 (&optional localdb init from-ff default) + "Generic function to run Locate. +Prefix arg LOCALDB when (4) search and use a local locate db file +when it exists or create it, when (16) force update of existing +db file even if exists. +It has no effect when locate command is \\='es'. INIT is a string +to use as initial input in prompt. +See `helm-locate-with-db' and `helm-locate'." + (require 'helm-mode) + (helm-locate-set-command) + (let ((pfn (lambda (candidate) + (if (file-directory-p candidate) + (message "Error: The locate Db should be a file") + (if (= (shell-command + (funcall helm-locate-create-db-function + candidate + helm-ff-default-directory)) + 0) + (message "New locatedb file `%s' created" candidate) + (error "Failed to create locatedb file `%s'" candidate))))) + (locdb (and localdb + (not (string-match "^es" helm-locate-command)) + (or (and (equal '(4) localdb) + (helm-ff-find-locatedb from-ff)) + (helm-read-file-name + "Create Locate Db file: " + :initial-input (expand-file-name "locate.db" + (or helm-ff-default-directory + default-directory)) + :preselect helm-locate-db-file-regexp + :test (lambda (x) + (if helm-locate-db-file-regexp + ;; Select only locate db files and directories + ;; to allow navigation. + (or (string-match + helm-locate-db-file-regexp x) + (file-directory-p x)) + x))))))) + (when (and locdb (or (equal localdb '(16)) + (not (file-exists-p locdb)))) + (funcall pfn locdb)) + (helm-locate-with-db (and localdb locdb) init default))) + +(defun helm-locate-set-command () + "Setup `helm-locate-command' if not already defined." + (unless helm-locate-command + (setq helm-locate-command + (cl-case system-type + (gnu/linux "locate %s -e -A --regex %s") + (berkeley-unix "locate %s %s") + (windows-nt "es %s %s") + (t "locate %s %s"))))) + +(defun helm-locate-initial-setup () + (require 'helm-for-files) + (helm-locate-set-command)) + +(defvar helm-file-name-history nil) +(defun helm-locate-with-db (&optional db initial-input default) + "Run locate -d DB. +If DB is not given or nil use locate without -d option. +Argument DB can be given as a string or list of db files. +Argument INITIAL-INPUT is a string to use as initial-input. +See also `helm-locate'." + (require 'helm-files) + (when (and db (stringp db)) (setq db (list db))) + (helm-locate-set-command) + (let ((helm-locate-command + (if db + (replace-regexp-in-string + "locate" + (format (if helm-locate-fuzzy-match + "locate -b -d '%s'" "locate -d '%s'") + (mapconcat 'identity + ;; Remove eventually + ;; marked directories by error. + (cl-loop for i in db + unless (file-directory-p i) + ;; expand-file-name to resolve + ;; abbreviated fnames not + ;; expanding inside single + ;; quotes i.e. '%s'. + collect (expand-file-name i)) + ":")) + helm-locate-command) + (if (and helm-locate-fuzzy-match + (not (string-match-p "\\`locate -b" helm-locate-command))) + (replace-regexp-in-string + "\\`locate" "locate -b" helm-locate-command) + helm-locate-command)))) + (setq helm-file-name-history (mapcar 'helm-basename file-name-history)) + (helm :sources 'helm-source-locate + :buffer "*helm locate*" + :ff-transformer-show-only-basename nil + :input initial-input + :default default + :history 'helm-file-name-history))) + +(defun helm-locate-update-mode-line (process-name) + "Update mode-line with PROCESS-NAME status information." + (with-helm-window + (setq mode-line-format + `(" " mode-line-buffer-identification " " + (:eval (format "L%s" (helm-candidate-number-at-point))) " " + (:eval (propertize + (format "[%s process finished - (%s results)]" + (max (1- (count-lines + (point-min) (point-max))) + 0) + ,process-name) + 'face 'helm-locate-finish)))) + (force-mode-line-update))) + +(defun helm-locate--default-process-coding-system () + "Fix `default-process-coding-system' in locate for Windows systems." + ;; This is an attempt to fix issue #1322. + (if (and (eq system-type 'windows-nt) + (boundp 'w32-ansi-code-page)) + (let ((code-page-eol + (intern (format "cp%s-%s" w32-ansi-code-page "dos")))) + (if (ignore-errors (check-coding-system code-page-eol)) + (cons code-page-eol code-page-eol) + default-process-coding-system)) + default-process-coding-system)) + +(defun helm-locate-init () + "Initialize async locate process for `helm-source-locate'." + (let* ((default-process-coding-system + (helm-locate--default-process-coding-system)) + (locate-is-es (string-match "\\`es" helm-locate-command)) + (real-locate (string-match "\\`locate" helm-locate-command)) + (case-sensitive-flag (if locate-is-es "-i" "")) + (ignore-case-flag (if (or locate-is-es + (not real-locate)) "" "-i")) + (args (helm-mm-split-pattern helm-pattern)) + (cmd (format helm-locate-command + (cl-case helm-locate-case-fold-search + (smart (let ((case-fold-search nil)) + (if (string-match "[[:upper:]]" helm-pattern) + case-sensitive-flag + ignore-case-flag))) + (t (if helm-locate-case-fold-search + ignore-case-flag + case-sensitive-flag))) + (helm-aif (cdr args) + (concat + ;; The pattern itself. + (shell-quote-argument (car args)) " " + ;; Possible locate args added + ;; after pattern, don't quote them. + (mapconcat 'identity it " ")) + (shell-quote-argument (car args))))) + (default-directory (if (file-directory-p default-directory) + default-directory "/"))) + (helm-log "helm-locat-init" "Starting helm-locate process") + (helm-log "helm-locat-init" "Command line used was:\n\n%s" + (concat ">>> " (propertize cmd 'face 'font-lock-comment-face) "\n\n")) + (prog1 + (start-process-shell-command + "locate-process" helm-buffer + cmd) + (set-process-sentinel + (get-buffer-process helm-buffer) + (lambda (process event) + (let* ((err (process-exit-status process)) + (noresult (= err 1))) + (cond (noresult + (with-helm-buffer + (unless (cdr helm-sources) + (insert (concat "* Exit with code 1, no result found," + " command line was:\n\n " + cmd))))) + ((string= event "finished\n") + (when (and helm-locate-fuzzy-match + (not (string-match-p "\\s-" helm-pattern))) + (helm-redisplay-buffer)) + (helm-locate-update-mode-line "Locate")) + (t + (helm-log "helm-locat-init" "Error: Locate %s" + (replace-regexp-in-string "\n" "" event)))))))))) + +(defun helm-locate-default-fuzzy-sort-fn (candidates) + "Default sort function for files in fuzzy matching. +Sort is done on basename of CANDIDATES." + (helm-fuzzy-matching-default-sort-fn-1 candidates nil t)) + +(defclass helm-locate-override-inheritor (helm-type-file) ()) + +(defclass helm-locate-source (helm-source-async helm-locate-override-inheritor) + ((init :initform 'helm-locate-initial-setup) + (candidates-process :initform 'helm-locate-init) + (requires-pattern :initform 3) + (history :initform 'helm-file-name-history) + (persistent-action :initform 'helm-ff-kill-or-find-buffer-fname) + (candidate-number-limit :initform 9999) + (redisplay :initform (progn helm-locate-fuzzy-sort-fn)))) + +;; Override helm-type-file class keymap. +(cl-defmethod helm--setup-source :after ((source helm-locate-override-inheritor)) + (setf (slot-value source 'keymap) helm-locate-map) + (setf (slot-value source 'group) 'helm-locate)) + +(defvar helm-source-locate + (helm-make-source "Locate" 'helm-locate-source + :pattern-transformer 'helm-locate-pattern-transformer + ;; :match-part is only used here to tell helm which part + ;; of candidate to highlight. + :match-part (lambda (candidate) + (if (or (string-match-p " -b\\'" helm-pattern) + (and helm-locate-fuzzy-match + (not (string-match "\\s-" helm-pattern)))) + (helm-basename candidate) + candidate)))) + +(defun helm-locate-pattern-transformer (pattern) + (if helm-locate-fuzzy-match + ;; When fuzzy is enabled helm add "-b" option on startup. + (cond ((string-match-p " " pattern) + (when (string-match "\\`locate -b" helm-locate-command) + (setq helm-locate-command + (replace-match "locate" t t helm-locate-command))) + pattern) + (t + (unless (string-match-p "\\`locate -b" helm-locate-command) + (setq helm-locate-command + (replace-regexp-in-string + "\\`locate" "locate -b" helm-locate-command))) + (helm--mapconcat-pattern pattern))) + pattern)) + +(defun helm-locate-find-dbs-in-projects (&optional update) + (let* ((pfn (lambda (candidate directory) + (unless (= (shell-command + (funcall helm-locate-create-db-function + candidate + directory)) + 0) + (error "Failed to create locatedb file `%s'" candidate))))) + (cl-loop for p in helm-locate-project-list + for db = (expand-file-name + helm-ff-locate-db-filename + (file-name-as-directory p)) + if (and (null update) (file-exists-p db)) + collect db + else do (funcall pfn db p) + and collect db))) + +;;; Directory completion for hff. +;; +(defclass helm-locate-subdirs-source (helm-source-in-buffer) + ((basedir :initarg :basedir + :initform nil + :custom string) + (subdir :initarg :subdir + :initform nil + :custom 'string) + (data :initform #'helm-locate-init-subdirs) + (group :initform 'helm-locate))) + +(defun helm-locate-init-subdirs () + (with-temp-buffer + (call-process-shell-command + (if (string-match-p "\\`fd" helm-locate-recursive-dirs-command) + (format helm-locate-recursive-dirs-command + ;; fd pass path at end. + (helm-get-attr 'subdir) (helm-get-attr 'basedir)) + (format helm-locate-recursive-dirs-command + (if (string-match-p "\\`es" helm-locate-recursive-dirs-command) + ;; Fix W32 paths. + (replace-regexp-in-string + "/" "\\\\\\\\" (helm-get-attr 'basedir)) + (helm-get-attr 'basedir)) + (helm-get-attr 'subdir))) + nil t nil) + (buffer-string))) + +;;;###autoload +(defun helm-projects-find-files (update) + "Find files with locate in `helm-locate-project-list'. +With a prefix arg refresh the database in each project." + (interactive "P") + (helm-locate-set-command) + (cl-assert (and (string-match-p "\\`locate" helm-locate-command) + (executable-find "updatedb")) + nil "Unsupported locate version") + (let ((dbs (helm-locate-find-dbs-in-projects update))) + (if dbs + (helm-locate-with-db dbs) + (user-error "No projects found, please setup `helm-locate-project-list'")))) + +;;;###autoload +(defun helm-locate (arg) + "Preconfigured `helm' for Locate. +Note: you can add locate options after entering pattern. +See \\='man locate' for valid options and also `helm-locate-command'. + +You can specify a local database with prefix argument ARG. +With two prefix arg, refresh the current local db or create it if +it doesn't exists. + +To create a user specific db, use +\"updatedb -l 0 -o db_path -U directory\". +Where db_path is a filename matched by +`helm-locate-db-file-regexp'." + (interactive "P") + (helm-set-local-variable 'helm-async-outer-limit-hook + (list (lambda () + (when (and helm-locate-fuzzy-match + (not (string-match-p + "\\s-" helm-pattern))) + (helm-redisplay-buffer))))) + (setq helm-ff-default-directory default-directory) + (helm-locate-1 arg nil nil (thing-at-point 'filename))) + +(provide 'helm-locate) + +;;; helm-locate.el ends here diff --git a/org/elpa/helm-20230406.839/helm-man.el b/org/elpa/helm-20230406.839/helm-man.el new file mode 100644 index 0000000..3217051 --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-man.el @@ -0,0 +1,114 @@ +;;; helm-man.el --- Man and woman UI -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2023 Thierry Volpiatto + +;; 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 . + +;;; Code: + +(require 'cl-lib) +(require 'helm) +(require 'helm-help) + +(defvar woman-topic-all-completions) +(defvar woman-manpath) +(defvar woman-path) +(defvar woman-expanded-directory-path) +(declare-function woman-file-name "woman.el" (topic &optional re-cache)) +(declare-function woman-file-name-all-completions "woman.el" (topic)) +(declare-function Man-getpage-in-background "man.el" (topic)) +(declare-function woman-expand-directory-path "woman.el" (path-dirs path-regexps)) +(declare-function woman-topic-all-completions "woman.el" (path)) +(declare-function helm-generic-sort-fn "helm-utils.el" (S1 S2)) +(declare-function helm-comp-read "helm-mode") + +(defgroup helm-man nil + "Man and Woman applications for Helm." + :group 'helm) + +(defcustom helm-man-or-woman-function 'Man-getpage-in-background + "Default command to display a man page." + :group 'helm-man + :type '(radio :tag "Preferred command to display a man page" + (const :tag "Man" Man-getpage-in-background) + (const :tag "Woman" woman))) + +(defcustom helm-man-format-switches (cl-case system-type + ((darwin macos) "%s") + (t "-l %s")) + "Arguments to pass to the `manual-entry' function. +Arguments are passed to `manual-entry' with `format.'" + :group 'helm-man + :type 'string) + +;; Internal +(defvar helm-man--pages nil + "All man pages on system. +Will be calculated the first time you invoke Helm with this +source.") + +(defun helm-man-default-action (candidate) + "Default action for jumping to a woman or man page from Helm." + (let ((wfiles (mapcar #'car (woman-file-name-all-completions candidate)))) + (condition-case nil + (let ((file (if (cdr wfiles) + (helm-comp-read "ManFile: " wfiles :must-match t) + (car wfiles)))) + (if (eq helm-man-or-woman-function 'Man-getpage-in-background) + (manual-entry (format helm-man-format-switches file)) + (condition-case nil + (woman-find-file file) + ;; If woman is unable to format correctly + ;; try Man instead. + (error (kill-buffer) + (manual-entry (format helm-man-format-switches file)))))) + ;; If even Man failed with file as argument, try again with Man + ;; but using Topic candidate instead of the file calculated by + ;; woman. + (error (kill-buffer) + (Man-getpage-in-background candidate))))) + +(defun helm-man--init () + (require 'woman) + (require 'helm-utils) + (unless helm-man--pages + (setq woman-expanded-directory-path + (woman-expand-directory-path woman-manpath woman-path)) + (setq woman-topic-all-completions + (woman-topic-all-completions woman-expanded-directory-path)) + (setq helm-man--pages (mapcar 'car woman-topic-all-completions))) + (helm-init-candidates-in-buffer 'global helm-man--pages)) + +(defvar helm-source-man-pages + (helm-build-in-buffer-source "Manual Pages" + :init #'helm-man--init + :persistent-action #'ignore + :filtered-candidate-transformer + (lambda (candidates _source) + (sort candidates #'helm-generic-sort-fn)) + :action '(("Display Man page" . helm-man-default-action)) + :group 'helm-man)) + +;;;###autoload +(defun helm-man-woman (arg) + "Preconfigured `helm' for Man and Woman pages. +With a prefix arg reinitialize the cache." + (interactive "P") + (when arg (setq helm-man--pages nil)) + (helm :sources 'helm-source-man-pages + :buffer "*helm man woman*")) + +(provide 'helm-man) + +;;; helm-man.el ends here diff --git a/org/elpa/helm-20230406.839/helm-misc.el b/org/elpa/helm-20230406.839/helm-misc.el new file mode 100644 index 0000000..104c9e4 --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-misc.el @@ -0,0 +1,393 @@ +;;; helm-misc.el --- Various functions for helm -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2023 Thierry Volpiatto + +;; 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 . + +;;; Code: +(require 'cl-lib) +(require 'helm) +(require 'helm-help) +(require 'helm-types) + +(declare-function display-time-world-display "time.el") +(defvar display-time-world-list) +(declare-function LaTeX-math-mode "ext:latex.el") +(declare-function jabber-chat-with "ext:jabber.el") +(declare-function jabber-read-account "ext:jabber.el") +(declare-function helm-comp-read "helm-mode") + + +(defgroup helm-misc nil + "Various Applications and libraries for Helm." + :group 'helm) + +(defcustom helm-time-zone-home-location "Paris" + "The time zone of your home." + :group 'helm-misc + :type 'string) + +(defcustom helm-timezone-actions + '(("Set timezone env (TZ)" . (lambda (candidate) + (setenv "TZ" candidate)))) + "Actions for helm-timezone." + :group 'helm-misc + :type '(alist :key-type string :value-type function)) + +(defface helm-time-zone-current + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "green")) + "Face used to colorize current time in `helm-world-time'." + :group 'helm-misc) + +(defface helm-time-zone-home + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "red")) + "Face used to colorize home time in `helm-world-time'." + :group 'helm-misc) + + + +;;; Latex completion +;; +;; Test +;; (setq LaTeX-math-menu '("Math" +;; ["foo" val0 t] +;; ("bar" +;; ["baz" val1 t]) +;; ("aze" +;; ["zer" val2 t]) +;; ("AMS" +;; ("rec" +;; ["fer" val3 t]) +;; ("rty" +;; ["der" val4 t])) +;; ("ABC" +;; ("xcv" +;; ["sdf" val5 t]) +;; ("dfg" +;; ["fgh" val6 t])))) +;; (helm-latex-math-candidates) +;; => +;; (("foo" . val0) +;; ("baz" . val1) +;; ("zer" . val2) +;; ("fer" . val3) +;; ("der" . val4) +;; ("sdf" . val5) +;; ("fgh" . val6)) + +(defvar LaTeX-math-menu) +(defun helm-latex-math-candidates () + (cl-labels ((helm-latex--math-collect (L) + (cond ((vectorp L) + (list (cons (aref L 0) (aref L 1)))) + ((listp L) + (cl-loop for a in L nconc + (helm-latex--math-collect a)))))) + (helm-latex--math-collect LaTeX-math-menu))) + +(defvar helm-source-latex-math + (helm-build-sync-source "Latex Math Menu" + :init (lambda () + (with-helm-current-buffer + (LaTeX-math-mode 1))) + :candidate-number-limit 9999 + :candidates 'helm-latex-math-candidates + :action (lambda (candidate) + (call-interactively candidate)))) + + +;;; Jabber Contacts (jabber.el) +(defun helm-jabber-online-contacts () + "List online Jabber contacts." + (with-no-warnings + (cl-loop for item in (jabber-concat-rosters) + when (get item 'connected) + collect + (if (get item 'name) + (cons (get item 'name) item) + (cons (symbol-name item) item))))) + +(defvar helm-source-jabber-contacts + (helm-build-sync-source "Jabber Contacts" + :init (lambda () (require 'jabber)) + :candidates (lambda () (mapcar 'car (helm-jabber-online-contacts))) + :action (lambda (x) + (jabber-chat-with + (jabber-read-account) + (symbol-name + (cdr (assoc x (helm-jabber-online-contacts)))))))) + +;;; World time +;; +(defvar zoneinfo-style-world-list) +(defvar legacy-style-world-list) + +(defun helm-time-zone-transformer (candidates _source) + (cl-loop for i in candidates + for (z . p) in display-time-world-list + collect + (cons + (cond ((string-match (format-time-string "%H:%M" (current-time)) i) + (propertize i 'face 'helm-time-zone-current)) + ((string-match helm-time-zone-home-location i) + (propertize i 'face 'helm-time-zone-home)) + (t i)) + z))) + +(defvar helm-source-time-world + (helm-build-in-buffer-source "Time World List" + :init (lambda () + (require 'time) + (unless (and display-time-world-list + (listp display-time-world-list)) + ;; adapted from `time--display-world-list' from + ;; emacs-27 for compatibility as + ;; `display-time-world-list' is set by default to t. + (setq display-time-world-list + ;; Determine if zoneinfo style timezones are + ;; supported by testing that America/New York and + ;; Europe/London return different timezones. + (let ((nyt (format-time-string "%z" nil "America/New_York")) + (gmt (format-time-string "%z" nil "Europe/London"))) + (if (string-equal nyt gmt) + legacy-style-world-list + zoneinfo-style-world-list))))) + :data (lambda () + (with-temp-buffer + (display-time-world-display display-time-world-list) + (buffer-string))) + :action 'helm-timezone-actions + :filtered-candidate-transformer 'helm-time-zone-transformer)) + +;;; Commands +;; +(defun helm-call-interactively (cmd-or-name) + "Execute CMD-OR-NAME as Emacs command. +It is added to `extended-command-history'. +`helm-current-prefix-arg' is used as the command's prefix argument." + (setq extended-command-history + (cons (helm-stringify cmd-or-name) + (delete (helm-stringify cmd-or-name) extended-command-history))) + (let ((current-prefix-arg helm-current-prefix-arg) + (cmd (helm-symbolify cmd-or-name))) + (if (stringp (symbol-function cmd)) + (execute-kbd-macro (symbol-function cmd)) + (setq this-command cmd) + (call-interactively cmd)))) + +;;; Minibuffer History +;; +;; +(defvar helm-minibuffer-history-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map helm-map) + (define-key map [remap helm-minibuffer-history] 'undefined) + map)) + +(defcustom helm-minibuffer-history-must-match t + "Allow inserting non matching elements when nil or \\='confirm." + :group 'helm-misc + :type '(choice + (const :tag "Must match" t) + (const :tag "Confirm" confirm) + (const :tag "Always allow" nil))) + +(defcustom helm-minibuffer-history-key "C-r" + "The key `helm-minibuffer-history' is bound to in minibuffer local maps." + :type '(choice (string :tag "Key") (const :tag "no binding")) + :group 'helm-mode) + +(defconst helm-minibuffer-history-old-key + (cl-loop for map in '(minibuffer-local-completion-map + minibuffer-local-filename-completion-map + minibuffer-local-filename-must-match-map ; Emacs 23.1.+ + minibuffer-local-isearch-map + minibuffer-local-map + minibuffer-local-must-match-filename-map ; Older Emacsen + minibuffer-local-must-match-map + minibuffer-local-ns-map) + when (and (boundp map) (symbol-value map)) + collect (cons map (lookup-key (symbol-value map) "\C-r")))) + +;;;###autoload +(define-minor-mode helm-minibuffer-history-mode + "Bind `helm-minibuffer-history-key' in al minibuffer maps. +This mode is enabled by `helm-mode', so there is no need to enable it directly." + :group 'helm-misc + :global t + (if helm-minibuffer-history-mode + (let ((key helm-minibuffer-history-key)) + (dolist (map '(minibuffer-local-completion-map + minibuffer-local-filename-completion-map + minibuffer-local-filename-must-match-map ; Emacs 23.1.+ + minibuffer-local-isearch-map + minibuffer-local-map + minibuffer-local-must-match-filename-map ; Older Emacsen + minibuffer-local-must-match-map + minibuffer-local-ns-map)) + (let ((vmap (and (boundp map) (symbol-value map)))) + (when (keymapp vmap) + (let ((val (and (boundp 'helm-minibuffer-history-key) + (symbol-value 'helm-minibuffer-history-key)))) + (when val + (define-key vmap + (if (stringp val) (read-kbd-macro val) val) + nil))) + (when key + (define-key (symbol-value map) + (if (stringp key) (read-kbd-macro key) key) + 'helm-minibuffer-history)))))) + (dolist (map '(minibuffer-local-completion-map + minibuffer-local-filename-completion-map + minibuffer-local-filename-must-match-map + minibuffer-local-isearch-map + minibuffer-local-map + minibuffer-local-must-match-filename-map + minibuffer-local-must-match-map + minibuffer-local-ns-map)) + (let ((vmap (and (boundp map) (symbol-value map)))) + (when (keymapp vmap) + (let ((val (and (boundp 'helm-minibuffer-history-key) + (symbol-value 'helm-minibuffer-history-key)))) + (when val + (define-key vmap + (if (stringp val) (read-kbd-macro val) val) + (assoc-default map helm-minibuffer-history-old-key))))))))) + + +;;; Helm ratpoison UI +;; +;; +(defvar helm-source-ratpoison-commands + (helm-build-in-buffer-source "Ratpoison Commands" + :init 'helm-ratpoison-commands-init + :action (helm-make-actions + "Execute the command" 'helm-ratpoison-commands-execute) + :display-to-real 'helm-ratpoison-commands-display-to-real + :candidate-number-limit 999999)) + +(defun helm-ratpoison-commands-init () + (unless (helm-candidate-buffer) + (with-current-buffer (helm-candidate-buffer 'global) + ;; with ratpoison prefix key + (save-excursion + (call-process "ratpoison" nil (current-buffer) nil "-c" "help")) + (while (re-search-forward "^\\([^ ]+\\) \\(.+\\)$" nil t) + (replace-match " \\1: \\2")) + (goto-char (point-max)) + ;; direct binding + (save-excursion + (call-process "ratpoison" nil (current-buffer) nil "-c" "help top")) + (while (re-search-forward "^\\([^ ]+\\) \\(.+\\)$" nil t) + (replace-match "\\1: \\2"))))) + +(defun helm-ratpoison-commands-display-to-real (display) + (and (string-match ": " display) + (substring display (match-end 0)))) + +(defun helm-ratpoison-commands-execute (candidate) + (call-process "ratpoison" nil nil nil "-ic" candidate)) + +;;; Helm stumpwm UI +;; +;; +(defvar helm-source-stumpwm-commands + (helm-build-in-buffer-source "Stumpwm Commands" + :init 'helm-stumpwm-commands-init + :action (helm-make-actions + "Execute the command" 'helm-stumpwm-commands-execute) + :candidate-number-limit 999999)) + +(defun helm-stumpwm-commands-init () + (with-current-buffer (helm-candidate-buffer 'global) + (save-excursion + (call-process "stumpish" nil (current-buffer) nil "commands")) + (while (re-search-forward "[ ]*\\([^ ]+\\)[ ]*\n?" nil t) + (replace-match "\n\\1\n")) + (delete-blank-lines) + (sort-lines nil (point-min) (point-max)) + (goto-char (point-max)))) + +(defun helm-stumpwm-commands-execute (candidate) + (call-process "stumpish" nil nil nil candidate)) + +;;;###autoload +(defun helm-world-time () + "Preconfigured `helm' to show world time. +Default action change TZ environment variable locally to emacs." + (interactive) + (helm-other-buffer 'helm-source-time-world "*helm world time*")) + +;;;###autoload +(defun helm-insert-latex-math () + "Preconfigured helm for latex math symbols completion." + (interactive) + (helm-other-buffer 'helm-source-latex-math "*helm latex*")) + +;;;###autoload +(defun helm-ratpoison-commands () + "Preconfigured `helm' to execute ratpoison commands." + (interactive) + (helm-other-buffer 'helm-source-ratpoison-commands + "*helm ratpoison commands*")) + +;;;###autoload +(defun helm-stumpwm-commands() + "Preconfigured helm for stumpwm commands." + (interactive) + (helm-other-buffer 'helm-source-stumpwm-commands + "*helm stumpwm commands*")) + +;;;###autoload +(defun helm-minibuffer-history () + "Preconfigured `helm' for `minibuffer-history'." + (interactive) + (cl-assert (minibuffer-window-active-p (selected-window)) nil + "Error: Attempt to use minibuffer history outside a minibuffer") + (let* ((enable-recursive-minibuffers t) + (query-replace-p (or (eq last-command 'query-replace) + (eq last-command 'query-replace-regexp))) + (elm (helm-comp-read "Next element matching (regexp): " + (cl-loop for i in + (symbol-value minibuffer-history-variable) + unless (equal "" i) collect i into history + finally return + (if (consp (car history)) + (mapcar 'prin1-to-string history) + history)) + :header-name + (lambda (name) + (format "%s (%s)" name minibuffer-history-variable)) + :buffer "*helm minibuffer-history*" + :must-match helm-minibuffer-history-must-match + :multiline t + :keymap helm-minibuffer-history-map + :allow-nest t))) + ;; Fix Bug#1667 with emacs-25+ `query-replace-from-to-separator'. + (when (and (boundp 'query-replace-from-to-separator) query-replace-p) + (let ((pos (string-match "\0" elm))) + (and pos + (add-text-properties + pos (1+ pos) + `(display ,query-replace-from-to-separator separator t) + elm)))) + (delete-minibuffer-contents) + (insert elm))) + + +(provide 'helm-misc) + +;;; helm-misc.el ends here diff --git a/org/elpa/helm-20230406.839/helm-mode.el b/org/elpa/helm-20230406.839/helm-mode.el new file mode 100644 index 0000000..3697fb4 --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-mode.el @@ -0,0 +1,2276 @@ +;;; helm-mode.el --- Enable helm completion everywhere. -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2023 Thierry Volpiatto + +;; 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 . + +;;; Code: + +(require 'cl-lib) +(require 'helm) +(require 'helm-lib) +(require 'helm-files) +(require 'helm-misc) + +(defvar crm-separator) +(defvar ido-everywhere) +(defvar completion-flex-nospace) +(defvar helm-completion--sorting-done) +(defvar helm-mode) +(defvar password-cache) + +;; No warnings in Emacs built --without-x +(declare-function x-file-dialog "xfns.c") + +(declare-function ido-mode "ido.el") +(declare-function helm-apropos-init "helm-elisp") +(declare-function helm-lisp-completion-persistent-action "helm-elisp") +(declare-function helm-lisp-completion-persistent-help "helm-elisp") +(declare-function help--symbol-class "help-fns.el") +(declare-function helm-get-first-line-documentation "helm-elisp") + +(defgroup helm-mode nil + "Enable helm completion." + :group 'helm) + +(defcustom helm-completing-read-handlers-alist + '((find-tag . helm-completing-read-default-find-tag) + (xref-find-definitions . helm-completing-read-default-find-tag) + (xref-find-references . helm-completing-read-default-find-tag) + (ggtags-find-tag-dwim . helm-completing-read-default-find-tag) + (tmm-menubar . nil) + (find-file . nil) + (execute-extended-command . nil) + (dired-do-rename . helm-read-file-name-handler-1) + (dired-do-copy . helm-read-file-name-handler-1) + (dired-do-symlink . helm-read-file-name-handler-1) + (dired-do-relsymlink . helm-read-file-name-handler-1) + (dired-do-hardlink . helm-read-file-name-handler-1) + (basic-save-buffer . helm-read-file-name-handler-1) + (write-file . (default helm-read-file-name-handler-1)) + (write-region . (default helm-read-file-name-handler-1))) + "Completing read functions for specific Emacs commands. + +By default `helm-mode' use `helm-completing-read-default-handler' to +provide helm completion in each `completing-read' or `read-file-name' +found, but other functions can be specified here for specific +commands. This also allows disabling helm completion for some commands +when needed. + +Each entry is a cons cell like (EMACS_COMMAND . COMPLETING-READ_HANDLER) +where key and value are symbols. +However if a command is using in its definition both a `completing-read' AND +a `read-file-name' we may want to specify a handler for both of them, +this can be done by specifying value as a list of two symbols instead of +a single symbol where the 1st element of the list specify the handler for the +`completing-read' and the second the handler for the `read-file-name'. +Special symbol \\='default' means use the default helm handler for either +`completing-read' or `read-file-name'. +e.g. (write-region . (default helm-read-file-name-handler-1)) +means helm will use `helm-completing-read-default-handler' when +`write-region' calls `completing-read' and +`helm-read-file-name-handler-1' when it calls `read-file-name'. + +Each key is an Emacs command that use originaly `completing-read' +or/and `read-file-name'. + +Each value maybe a helm function that takes same arguments as +`completing-read' plus NAME and BUFFER, where NAME is the name of the new +helm source and BUFFER the name of the buffer we will use, but it can +be also a function not using helm, in this case the function should +take the same args as `completing-read' and not be prefixed by \"helm-\". + +`helm' will use the name of the command calling `completing-read' as +NAME and BUFFER will be computed as well with NAME but prefixed with +\"*helm-mode-\". + +This function prefix name must start by \"helm-\" when it uses helm, +otherwise `helm' assumes the function is not a helm function and +expects the same args as `completing-read', this allows you to define a +handler not using helm completion. + +Example: + + (defun foo/test () + (interactive) + (message \"%S\" (completing-read \"test: \" \\='(a b c d e)))) + + (defun helm-foo/test-completing-read-handler (prompt collection + predicate require-match + initial-input hist def + inherit-input-method + name buffer) + (helm-comp-read prompt collection :marked-candidates t + :name name + :buffer buffer)) + + (add-to-list \\='helm-completing-read-handlers-alist + \\='(foo/test . helm-foo/test-completing-read-handler)) + + +We want here to make the regular `completing-read' in `foo/test' +return a list of candidate(s) instead of a single candidate. + +Note that this function will be reused for ALL the `completing-read' +of this command, so it should handle all cases. E.g., +if first `completing-read' completes against symbols and +second `completing-read' should handle only buffer, +your specialized function should handle both. + +If the value of an entry is nil completion will fall back to +Emacs vanilla behaviour. +Example: + +If you want to disable helm completion for `describe-function', use: + + (describe-function . nil) + +Ido is also supported, you can use `ido-completing-read' and +`ido-read-file-name' as value of an entry or just \\='ido. +Example: +Enable ido completion for `find-file': + + (find-file . ido) + +same as + + (find-file . ido-read-file-name) + +Note that you don't need to enable `ido-mode' for this to work, see +`helm-mode' documentation." + :group 'helm-mode + :type '(alist :key-type symbol :value-type symbol)) + +(defcustom helm-comp-read-case-fold-search helm-case-fold-search + "Default Local setting of `helm-case-fold-search' for `helm-comp-read'. +See `helm-case-fold-search' for more info." + :group 'helm-mode + :type 'symbol) + +(defcustom helm-mode-handle-completion-in-region t + "Whether to replace or not `completion-in-region-function'. +This enables support for `completing-read-multiple' and `completion-at-point' +when non--nil." + :group 'helm-mode + :type 'boolean) + +(defcustom helm-mode-no-completion-in-region-in-modes nil + "A list of modes that do not want helm for `completion-in-region'." + :group 'helm-mode + :type 'boolean) + +(defcustom helm-mode-reverse-history t + "Display history source after current source when non nil. + +Apply only in `helm-mode' handled commands." + :group 'helm-mode + :type 'boolean) + +(defcustom helm-completion-in-region-default-sort-fn + 'helm-completion-in-region-sort-fn + "The default sort function to sort candidates in completion-in-region. + +When nil no sorting is done. +The function is a `filtered-candidate-transformer' function which takes +two args CANDIDATES and SOURCE. +The function must use the flag `helm-completion--sorting-done' and +return CANDIDATES unchanged when the flag is nil. +See default function `helm-completion-in-region-sort-fn' as example. +It will be used only when `helm-completion-style' is either Emacs or +helm, otherwise when helm-fuzzy style is used, the fuzzy sort function +will be used." + :group 'helm-mode + :type 'function) + +(defcustom helm-mode-ignore-diacritics nil + "Ignore diacritics in completing-read." + :group 'helm-mode + :type 'boolean) + +(defcustom helm-completion-mark-suffix t + "Push mark at end of suffix when non nil." + :group 'helm-mode + :type 'boolean) + +(defcustom helm-read-file-name-use-default-arg-behavior nil + "Use emacs vanilla `read-file-name' behavior for default arg. + +The behavior of default arg in `read-file-name' and friends is using +the default arg as default value when initial input is not modified, +even if this initial input is a valid value i.e. an existing file. +We expect generally a default arg to be used if nothing is specified +in the prompt or if what is specified is invalid, but the emacs behavior +here is really weird, so we use this variable to disable this +behavior, letting user specify default if needed with `M-n'. +However we keep the emacs default for `read-file-name' and derived +fns, this variable affecting only `helm-read-file-name'." + :type 'boolean + :group 'helm-mode) + +(defvar helm-mode-minibuffer-setup-hook-black-list '(minibuffer-completion-help) + "Incompatible `minibuffer-setup-hook' functions go here. +A list of symbols. `helm-mode' is rejecting all lambda's, byte-code fns +and all functions belonging in this list from `minibuffer-setup-hook'. +This is mainly needed to prevent \"*Completions*\" buffers to popup.") + +(defface helm-mode-prefix + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + (:background "red" :foreground "black"))) + "Face used for prefix completion." + :group 'helm-mode) + +(defvar helm-comp-read-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map helm-map) + (define-key map (kbd "") 'helm-cr-empty-string) + (define-key map (kbd "M-RET") 'helm-cr-empty-string) + map) + "Keymap for `helm-comp-read'.") + +(defun helm-mode-delete-char-backward-1 () + (interactive) + (condition-case err + (call-interactively 'delete-backward-char) + (text-read-only + (if (with-selected-window (minibuffer-window) + (not (string= (minibuffer-contents) ""))) + (message "Trying to delete prefix completion, next hit will quit") + (user-error "%s" (car err)))))) +(put 'helm-mode-delete-char-backward-1 'helm-only t) + +(defun helm-mode-delete-char-backward-2 () + (interactive) + (condition-case _err + (call-interactively 'delete-backward-char) + (text-read-only + (unless (with-selected-window (minibuffer-window) + (string= (minibuffer-contents) "")) + (with-helm-current-buffer + (run-with-timer 0.1 nil (lambda () + (call-interactively 'delete-backward-char)))) + (helm-keyboard-quit))))) +(put 'helm-mode-delete-char-backward-2 'helm-only t) + +(helm-multi-key-defun helm-mode-delete-char-backward-maybe + "Delete char backward when text is not the prefix helm is completing against. +First call warns user about deleting prefix completion. +Second call deletes backward char in current-buffer and quits helm completion, +letting the user start a new completion with a new prefix." + '(helm-mode-delete-char-backward-1 helm-mode-delete-char-backward-2) 1) + +(defcustom helm-completion-style 'helm + "Style of completion to use in `completion-in-region'. + +This affects only `completion-at-point' and friends, and +the `completing-read' using the default handler +i.e. `helm-completing-read-default-handler'. + +NB: This has nothing to do with `completion-styles', it is independent from +helm, but when using \\='emacs as helm-completion-style helm +will use the `completion-styles' for its completions. +Up to the user to configure `completion-styles'. + +There are three possible values to use: + +- helm, use multi match regular helm completion. + +- helm-fuzzy, use fuzzy matching. Note that as usual when + entering a space helm switches to multi matching mode. + +- emacs, use regular Emacs completion according to + `completion-styles'. Note that even in this style, helm allows using + multi match. Emacs-27 provides a style called `flex' that can be used + aside `helm' style (see `completion-styles-alist'). When `flex' style + is not available (Emacs<27) helm provides `helm-flex' style which is + similar to `flex' and helm fuzzy matching. + +For a better experience with emacs style, if you don't know what to use, set +`completion-styles' to \\='(flex) if you are using emacs-27 or to +\\='(helm-flex) if you are using emacs-26 and keep \\='emacs as default +value for `helm-completion-style'. Advanced users can also have a +look to `completion-category-overrides' to set styles according to category. +You can as well use `helm-completion-styles-alist' to override +`helm-completion-style' in specific modes. + +Of course when using `helm' or `helm-fuzzy' as `helm-completion-style' +emacs `completion-styles' have no effect. + +Please use custom interface or `customize-set-variable' to set this, +NOT `setq'." + :group 'helm-mode + :type '(choice (const :tag "Emacs" emacs) + (const :tag "Helm" helm) + (const :tag "Helm-fuzzy" helm-fuzzy)) + :set (lambda (var val) + (set var val) + (if (memq val '(helm helm-fuzzy)) + (define-key helm-comp-read-map (kbd "DEL") 'helm-mode-delete-char-backward-maybe) + (define-key helm-comp-read-map (kbd "DEL") 'delete-backward-char)))) + +(defconst helm-completion--all-styles + (let ((flex (if (assq 'flex completion-styles-alist) + 'flex 'helm-flex))) + (helm-fast-remove-dups + (append (list 'helm flex) + (mapcar 'car completion-styles-alist))))) + +(defconst helm-completion--styles-type + `(repeat :tag "with other completion styles" + (choice ,@(mapcar (lambda (x) (list 'const x)) + helm-completion--all-styles)))) + +(defcustom helm-completion-styles-alist '((gud-mode . helm) + ;; See https://github.com/djcb/mu/issues/2181. + (mu4e-compose-mode . emacs)) + "Allow configuring `helm-completion-style' per mode or command. + +NOTE: Use a mode for a completion that will be used in a buffer +i.e. completion-in-region, whereas you have to specify instead a command to +affect the completing-read trigerred by this command. + +Each entry is a cons cell like (mode . style) where style must be a +suitable value for `helm-completion-style'. +When specifying emacs as style for a mode or a command, `completion-styles' can be +specified by using a cons cell specifying completion-styles to use +with helm emacs style, e.g. (foo-mode . (emacs helm flex)) will set +`completion-styles' to \\='(helm flex) for foo-mode." + :group 'helm-mode + :type + `(alist :key-type (symbol :tag "Major Mode") + :value-type + (choice :tag "Use helm style or completion styles" + (radio :tag "Helm Style" + (const helm) + (const helm-fuzzy) + (const emacs)) + (cons :tag "Completion Styles" + (const :tag "Using Helm `emacs' style" emacs) + ,helm-completion--styles-type)))) + +;;; helm-comp-read +;; +;; +(defvar helm-comp-read-use-marked nil + "[INTERNAL] When non nil `helm-comp-read' will return marked candidates. + +Use this ONLY in `let', NOT globally, this allows third party packages +to use a list as return value when `helm-mode' is enabled, e.g. + + (let ((helm-comp-read-use-marked t)) + (completing-read \"test: \" \\='(a b c d e f g))) + +") + +(defun helm-cr-empty-string () + "Return empty string." + (interactive) + (with-helm-alive-p + (helm-exit-and-execute-action + (lambda (_candidate) + (identity ""))))) +(put 'helm-cr-empty-string 'helm-only t) + +(defun helm-mode--keyboard-quit () + ;; Use this instead of `keyboard-quit' + ;; to avoid deactivating mark in current-buffer. + (let ((debug-on-quit nil)) + (signal 'quit nil))) + +(cl-defun helm-comp-read-get-candidates (collection &optional + test sort-fn alistp + (input helm-pattern)) + "Convert COLLECTION to list removing elements that don't match TEST. +See `helm-comp-read' about supported COLLECTION arguments. + +SORT-FN is a predicate to sort COLLECTION. + +ALISTP when non--nil will not use `all-completions' to collect +candidates because it doesn't handle alists correctly for helm. +i.e In `all-completions' the car of each pair is used as value. +In helm we want to use the cdr instead like (display . real), +so we return the alist as it is with no transformation by +`all-completions'. + +e.g + +\(setq A \\='((a . 1) (b . 2) (c . 3))) +==>((a . 1) (b . 2) (c . 3)) +\(helm-comp-read \"test: \" A :alistp nil + :exec-when-only-one t + :initial-input \"a\") +==>\"a\" Which is not what we expect. + +\(helm-comp-read \"test: \" A :alistp t + :exec-when-only-one t + :initial-input \"1\") +==>\"1\" + +See docstring of `all-completions' for more info. + +INPUT is the string you want to complete against, defaulting to +`helm-pattern' which is the value of what you enter in minibuffer. +Note that when using a function as COLLECTION this value will be +available with the input argument of the function only when using a +sync source from `helm-comp-read', i.e. not using +`:candidates-in-buffer', otherwise the function is called only once +with an empty string as value for `helm-pattern' because +`helm-pattern' is not yet computed, which is what we want otherwise +data would not be fully collected at init time. + +If COLLECTION is an `obarray', a TEST should be needed. See `obarray'." + ;; Ensure COLLECTION is computed from `helm-current-buffer' + ;; because some functions used as COLLECTION work + ;; only in the context of current-buffer (Bug#1030) . + (with-helm-current-buffer + (let ((cands + (cond ((and alistp (hash-table-p collection)) + (cl-loop for k being the hash-keys of collection + using (hash-values v) + collect (cons k v))) + ((vectorp collection) + (all-completions input collection test)) + ((and (symbolp collection) (boundp collection) + ;; Bug#324 history is let-bounded and given + ;; quoted as hist argument of completing-read. + ;; See example in `rcirc-browse-url'. + (symbolp (symbol-value collection))) + nil) + ;; When collection is a symbol, most of the time + ;; it should be a symbol used as a minibuffer-history. + ;; The value of this symbol in this case return a list + ;; of string which maybe are converted later as symbol + ;; in special cases. + ;; we treat here commandp as a special case as it return t + ;; also with a string unless its last arg is provided. + ;; Also, the history collections generally collect their + ;; elements as string, so intern them to call predicate. + ((and (symbolp collection) (boundp collection) test) + (let ((predicate (lambda (elm) + (condition-case _err + (if (eq test 'commandp) + (funcall test (intern elm)) + (funcall test elm)) + (wrong-type-argument + (funcall test (intern elm))))))) + (all-completions input (symbol-value collection) predicate))) + ((and (symbolp collection) (boundp collection)) + (all-completions input (symbol-value collection))) + ;; Normally file completion should not be handled here, + ;; but special cases like `find-file-at-point' do it. + ;; Handle here specially such cases. + ((and (functionp collection) (not (string= input "")) + (or minibuffer-completing-file-name + (eq (completion-metadata-get + (completion-metadata input collection test) + 'category) + 'file))) + (cl-loop for f in (funcall collection input test t) + unless (member f '("./" "../")) + if (string-match helm--url-regexp input) + collect f + else + collect (concat (file-name-as-directory + (helm-basedir input)) + f))) + ((functionp collection) + (funcall collection input test t)) + ((and alistp (null test)) collection) + ;; Next test ensure circular objects are removed + ;; with `all-completions' (Bug#1530). + (t (all-completions input collection test))))) + (if sort-fn (sort cands sort-fn) cands)))) + +(cl-defun helm-cr--pattern-in-candidates-p (candidates &optional (pattern helm-pattern)) + (or (assoc pattern candidates) + (assq (intern pattern) candidates) + (member pattern candidates) + (member (downcase pattern) candidates) + (member (upcase pattern) candidates))) + +(defun helm-cr-default-transformer (candidates source) + "Default filter candidate function for `helm-comp-read'." + (let ((must-match (helm-get-attr 'must-match source)) + (annotation (plist-get completion-extra-properties + :annotation-function)) + (affixation (plist-get completion-extra-properties + :affixation-function))) + ;; Annotation and affixation are already handled in completion-in-region and + ;; in helm-completing-read-default-2 when emacs style is in use. + (cl-loop for c in (if (and (or annotation affixation) + (not helm--completing-region) + (memq helm-completion-style '(helm helm-fuzzy))) + (helm-completion-in-region--initial-filter + ;; Ensure we use the display part of candidates (if some). + (all-completions "" candidates) + annotation nil nil) + candidates) + for cand = (let ((elm (if (stringp c) + (replace-regexp-in-string "\\s\\" "" c) + c))) + (cond ((and (stringp elm) + (string-match "\n" elm)) + (cons (replace-regexp-in-string "\n" "->" elm) c)) + (t c))) + collect cand into lst + finally return + ;; Unquote helm-pattern when it is added as candidate + ;; (Bug#2015). + (let ((pat (replace-regexp-in-string "\\s\\" "" helm-pattern))) + (if (or (string= pat "") + (eq must-match t) + (helm-cr--pattern-in-candidates-p lst pat)) + lst + (append (list (cons (concat (propertize + " " 'display + (propertize "[?]" + 'face 'helm-ff-prefix + 'unknown t)) + pat) + pat)) + lst)))))) + +(defun helm-comp-read--move-to-first-real-candidate () + (helm-aif (helm-get-selection nil 'withprop) + ;; Avoid error with candidates with an image as display (Bug#2296). + (when (equal (get-text-property 0 'display it) "[?]") + (helm-next-line)))) + +(defun helm-cr-default (default cands) + (delq nil + (cond ((and (consp default) (string= helm-pattern "")) + (append (cl-loop for d in default + ;; Don't convert + ;; nil to "nil" (i.e the string) + ;; it will be delq'ed on top. + for str = (if (null d) d (helm-stringify d)) + when (member str cands) + do (setq cands (delete d cands)) + when str collect str) + cands)) + ((and (not (equal default "")) + (string= helm-pattern "")) + (cons default (delete (helm-stringify default) + cands))) + (t cands)))) + +;;;###autoload +(cl-defun helm-comp-read (prompt collection + &key + test + initial-input + default + preselect + (buffer "*Helm Completions*") + must-match + fuzzy + reverse-history + (requires-pattern 0) + (history nil shistory) + raw-history + input-history + (case-fold helm-comp-read-case-fold-search) + (persistent-action nil) + (persistent-help "DoNothing") + (mode-line helm-comp-read-mode-line) + help-message + (keymap helm-comp-read-map) + (name "Helm Completions") + header-name + candidates-in-buffer + diacritics + match-part + match-dynamic + exec-when-only-one + quit-when-no-cand + (volatile t) + sort + fc-transformer + hist-fc-transformer + (marked-candidates helm-comp-read-use-marked) + nomark + (alistp t) + (candidate-number-limit helm-candidate-number-limit) + multiline + allow-nest + coerce + (group 'helm)) + "Read a string in the minibuffer, with helm completion. + +It is helm `completing-read' equivalent. + +- PROMPT is the prompt name to use. + +- COLLECTION can be a list, alist, vector, obarray or hash-table. + For alists and hash-tables their car are use as real value of + candidate unless ALISTP is non-nil. + It can be also a function that receives three arguments: + the values string, predicate and t. See `all-completions' for more details. + +Keys description: + +- TEST: A predicate called with one arg i.e candidate. + +- INITIAL-INPUT: Same as input arg in `helm'. + +- PRESELECT: See preselect arg of `helm'. + +- DEFAULT: This option is used only for compatibility with regular + Emacs `completing-read' (Same as DEFAULT arg of `completing-read'). + +- BUFFER: Name of helm-buffer. + +- MUST-MATCH: Candidate selected must be one of COLLECTION. + +- FUZZY: Enable fuzzy matching. + +- REVERSE-HISTORY: When non--nil display history source after current + source completion. + +- REQUIRES-PATTERN: Same as helm attribute, default is 0. + +- HISTORY: A symbol where each result will be saved. + If not specified as a symbol an error will popup. + When specified, all elements of HISTORY are displayed in + a special source before or after COLLECTION according to REVERSE-HISTORY. + The main difference with INPUT-HISTORY is that the result of the + completion is saved whereas in INPUT-HISTORY it is the minibuffer + contents which is saved when you exit. + Don't use the same symbol for INPUT-HISTORY and HISTORY. + NOTE: As mentionned above this has nothing to do with + `minibuffer-history-variable', therefore if you want to save this + history persistently, you will have to add this variable to the + relevant variable of your favorite tool for persistent emacs session + i.e. psession, desktop etc... + +- RAW-HISTORY: When non-nil do not remove backslashs if some in + HISTORY candidates. + +- INPUT-HISTORY: A symbol. The minibuffer input history will be + stored there, if nil or not provided, `minibuffer-history' + will be used instead. You can navigate in this history with + `M-p' and `M-n'. + Don't use the same symbol for INPUT-HISTORY and HISTORY. + +- CASE-FOLD: Same as `helm-case-fold-search'. + +- PERSISTENT-ACTION: A function called with one arg i.e candidate. + +- PERSISTENT-HELP: A string to document PERSISTENT-ACTION. + +- MODE-LINE: A string or list to display in mode line. + Default is `helm-comp-read-mode-line'. + +- KEYMAP: A keymap to use in this `helm-comp-read'. + (the keymap will be shared with history source) + +- NAME: The name related to this local source. + +- HEADER-NAME: A function to alter NAME, see `helm'. + +- EXEC-WHEN-ONLY-ONE: Bound `helm-execute-action-at-once-if-one' + to non--nil. (possibles values are t or nil). + +- VOLATILE: Use volatile attribute. + +- SORT: A predicate to give to `sort' e.g `string-lessp' + Use this only on small data as it is inefficient. + If you want to sort faster add a sort function to + FC-TRANSFORMER. + Note that FUZZY when enabled is already providing a sort function. + +- FC-TRANSFORMER: A `filtered-candidate-transformer' function + or a list of functions. + +- HIST-FC-TRANSFORMER: A `filtered-candidate-transformer' + function for the history source. + +- MARKED-CANDIDATES: If non-nil return candidate or marked candidates as a list. + +- NOMARK: When non--nil don't allow marking candidates. + +- ALISTP: + When non-nil (default) pass the value of (DISPLAY . REAL) + candidate in COLLECTION to action when COLLECTION is an alist or a + hash-table, otherwise DISPLAY is always returned as result on exit, + which is the default when using `completing-read'. + See `helm-comp-read-get-candidates'. + +- CANDIDATES-IN-BUFFER: when non--nil use a source build with + `helm-source-in-buffer' which is much faster. + Argument VOLATILE have no effect when CANDIDATES-IN-BUFFER is non--nil. + +- MATCH-PART: Allow matching only one part of candidate. + See match-part documentation in `helm-source'. + +- MATCH-DYNAMIC: See match-dynamic in `helm-source-sync' + It has no effect when used with CANDIDATES-IN-BUFFER. + +- ALLOW-NEST: Allow nesting this `helm-comp-read' in a helm session. + See `helm'. + +- MULTILINE: See multiline in `helm-source'. + +- COERCE: See coerce in `helm-source'. + +- GROUP: See group in `helm-source'. + +Any prefix args passed during `helm-comp-read' invocation will be recorded +in `helm-current-prefix-arg', otherwise if prefix args were given before +`helm-comp-read' invocation, the value of `current-prefix-arg' will be used. +That means you can pass prefix args before or after calling a command +that use `helm-comp-read'. See `helm-M-x' for example." + ;; Handle error with HISTORY: + ;; + ;; Should show helm with one source at first run and save result on + ;; exit, should show the history source along candidates source on + ;; next run as soon as `test-hist' value is feeded. + ;; (setq test-hist nil) + ;; (helm-comp-read "test: " '(a b c d e) + ;; :history 'test-hist) + ;; + ;; Should run normally as long as `test-hist' is bound and nil. As + ;; soon `test-hist' becomes non-nil throw an error. + ;; (helm-comp-read "test: " '(a b c d e) + ;; :history test-hist) + ;; + ;; Should run normally. + ;; (completing-read "test: " '(a b c d e)) + (cl-assert (if shistory + (or (null history) + (and history (symbolp history))) + t) + nil "Error: History should be specified as a symbol") + (when (get-buffer helm-action-buffer) + (kill-buffer helm-action-buffer)) + (unless (memq must-match '(confirm confirm-after-completion t nil)) + ;; Fix completing-read's using something else than `t' e.g. 1 or + ;; whatever (bug #2527). + (setq must-match t)) + (let ((action-fn `(("Sole action (Identity)" + . (lambda (candidate) + (if ,marked-candidates + (helm-marked-candidates) + (identity candidate))))))) + (let* ((minibuffer-completion-predicate test) + (minibuffer-completion-table + (or minibuffer-completion-table collection)) + (helm-read-file-name-mode-line-string + (replace-regexp-in-string "helm-maybe-exit-minibuffer" + "helm-confirm-and-exit-minibuffer" + helm-read-file-name-mode-line-string)) + (get-candidates + (lambda () + (let ((cands (helm-comp-read-get-candidates + ;; If `helm-pattern' is passed as INPUT + ;; and :alistp is nil INPUT is passed to + ;; `all-completions' which defeat helm + ;; matching functions (multi match, fuzzy + ;; etc...) Bug#2134. + collection test sort alistp + (if (and match-dynamic (null candidates-in-buffer)) + helm-pattern "")))) + (helm-cr-default default cands)))) + (history-get-candidates + (lambda () + (let ((cands (helm-comp-read-get-candidates + history test nil alistp))) + (when cands + (delete "" (helm-cr-default default cands)))))) + (src-hist (helm-build-sync-source (format "%s History" name) + :candidates history-get-candidates + :fuzzy-match fuzzy + :multiline multiline + :match-part match-part + :filtered-candidate-transformer + (append `((lambda (candidates _source) + (if ,raw-history + candidates + (cl-loop for i in candidates + ;; Input is added to history in completing-read's + ;; and may be regexp-quoted, so unquote it + ;; but check if cand is a string (it may be at this stage + ;; a symbol or nil) Bug#1553. + when (stringp i) + collect (replace-regexp-in-string "\\s\\" "" i))))) + (and hist-fc-transformer (helm-mklist hist-fc-transformer))) + :persistent-action persistent-action + :persistent-help persistent-help + :keymap keymap + :must-match must-match + :group group + :coerce coerce + :mode-line mode-line + :help-message help-message + :action action-fn)) + (src (helm-build-sync-source name + :candidates get-candidates + :match-part match-part + :multiline multiline + :header-name header-name + :filtered-candidate-transformer + (let ((transformers (helm-mklist fc-transformer))) + (append transformers + (unless (member 'helm-cr-default-transformer transformers) + '(helm-cr-default-transformer)))) + :requires-pattern requires-pattern + :persistent-action persistent-action + :persistent-help persistent-help + :fuzzy-match fuzzy + :diacritics diacritics + :keymap keymap + :must-match must-match + :group group + :coerce coerce + :mode-line mode-line + :match-dynamic match-dynamic + :help-message help-message + :action action-fn + :volatile volatile)) + (src-1 (helm-build-in-buffer-source name + :data get-candidates + :match-part match-part + :multiline multiline + :header-name header-name + :filtered-candidate-transformer + (append (helm-mklist fc-transformer) + '(helm-cr-default-transformer)) + :requires-pattern requires-pattern + :persistent-action persistent-action + :fuzzy-match fuzzy + :diacritics diacritics + :keymap keymap + :must-match must-match + :group group + :coerce coerce + :persistent-help persistent-help + :mode-line mode-line + :help-message help-message + :action action-fn)) + (src-list (list src-hist + (if candidates-in-buffer + src-1 src))) + (helm-execute-action-at-once-if-one exec-when-only-one) + (helm-quit-if-no-candidate quit-when-no-cand) + result) + (when nomark + (setq src-list (cl-loop for src in src-list + collect (cons '(nomark) src)))) + (when reverse-history (setq src-list (nreverse src-list))) + (add-hook 'helm-after-update-hook 'helm-comp-read--move-to-first-real-candidate) + (unwind-protect + (setq result (helm + :sources src-list + :input initial-input + :default default + :preselect preselect + :prompt prompt + :resume 'noresume + :keymap keymap ;; Needed with empty collection. + :allow-nest allow-nest + :candidate-number-limit candidate-number-limit + :case-fold-search case-fold + :history (and (symbolp input-history) input-history) + :buffer buffer)) + (remove-hook 'helm-after-update-hook 'helm-comp-read--move-to-first-real-candidate)) + ;; If `history' is a symbol save it, except when it is t. + (when (and result history (symbolp history) (not (eq history t))) + (set history + ;; RESULT may be a a string or a list of strings bug #2461. + (delete-dups (append (mapcar #'substring-no-properties (helm-mklist result)) + (symbol-value history))))) + (or result (helm-mode--keyboard-quit))))) + + +;; Generic completing-read +;; +;; Support also function as collection. +;; e.g M-x man is supported. +;; Support hash-table and vectors as collection. +;; NOTE: +;; Some crap emacs functions may not be supported +;; like ffap-alternate-file (bad use of completing-read) +;; and maybe others. +;; Provide a mode `helm-mode' which turn on +;; helm in all `completing-read' and `read-file-name' in Emacs. +;; +(defvar helm-completion-mode-string " Helm") + +(defvar helm-completion-mode-quit-message + "Helm completion disabled") + +(defvar helm-completion-mode-start-message + "Helm completion enabled") + +;;; Specialized handlers +;; +;; +(defun helm-completing-read-symbols + (prompt _collection test _require-match init + hist default _inherit-input-method name buffer) + "Specialized function for fast symbols completion in `helm-mode'." + (require 'helm-elisp) + (or + (helm + :sources (helm-build-in-buffer-source name + :init (lambda () + (helm-apropos-init (lambda (x) + (and (funcall test x) + (not (keywordp x)))) + (or (car-safe default) default))) + :filtered-candidate-transformer 'helm-apropos-default-sort-fn + :help-message #'helm-comp-read-help-message + :fuzzy-match (eq helm-completion-style 'helm-fuzzy) + :persistent-action + (lambda (candidate) + (helm-lisp-completion-persistent-action + candidate name)) + :persistent-help (helm-lisp-completion-persistent-help)) + :prompt prompt + :buffer buffer + :input init + :history hist + :resume 'noresume + :default (or default "")) + (helm-mode--keyboard-quit))) + + +;;; Generic completing read +;; +;; +(defun helm-completing-read-default-1 + (prompt collection test require-match + init hist default _inherit-input-method + name buffer &optional cands-in-buffer exec-when-only-one) + "Call `helm-comp-read' with same args as `completing-read'. +Extra optional arg CANDS-IN-BUFFER means use `candidates-in-buffer' +method which is faster. +It should be used when candidate list doesn't need to be rebuilt dynamically." + (let ((history (or (car-safe hist) hist)) + (initial-input (helm-aif (pcase init + ((pred (stringp)) init) + ;; INIT is a cons cell. + (`(,l . ,_ll) l)) + it)) + (minibuffer-completion-table collection)) + (helm-comp-read + prompt collection + :test test + :history history + :reverse-history helm-mode-reverse-history + :input-history history + :must-match require-match + :alistp nil + :diacritics helm-mode-ignore-diacritics + :help-message #'helm-comp-read-help-message + :name name + :requires-pattern (if (and (stringp default) + (string= default "") + (or (eq require-match 'confirm) + (eq require-match + 'confirm-after-completion))) + 1 0) + :quit-when-no-cand (eq require-match t) + :nomark (null helm-comp-read-use-marked) + :candidates-in-buffer cands-in-buffer + :exec-when-only-one exec-when-only-one + :fuzzy (eq helm-completion-style 'helm-fuzzy) + :buffer buffer + ;; If DEF is not provided, fallback to empty string + ;; to avoid `thing-at-point' to be appended on top of list + :default (or default "") + ;; Fail with special characters (e.g in gnus "nnimap+gmail:") + ;; if regexp-quote is not used. + ;; when init is added to history, it will be unquoted by + ;; helm-comp-read. + :initial-input initial-input))) + +(defun helm-completing-read-default-2 + (prompt collection predicate require-match + init hist default _inherit-input-method + name buffer &optional _cands-in-buffer exec-when-only-one) + "Call `helm-comp-read' with same args as `completing-read'. + +This handler uses dynamic matching which allows honouring `completion-styles'." + (let* ((history (or (car-safe hist) hist)) + (input (pcase init + ((pred (stringp)) init) + ;; INIT is a cons cell. + (`(,l . ,_ll) l))) + (completion-flex-nospace t) + (minibuffer-completion-table collection) + ;; (completion-styles + ;; (helm--prepare-completion-styles 'nomode)) + (metadata (or (completion-metadata (or input "") collection predicate) + '(metadata))) + (afun (or (plist-get completion-extra-properties :annotation-function) + (completion-metadata-get metadata 'annotation-function))) + (afix (or (plist-get completion-extra-properties :affixation-function) + (completion-metadata-get metadata 'affixation-function))) + (file-comp-p (eq (completion-metadata-get metadata 'category) 'file)) + (compfn (lambda (str _predicate _action) + (let* ((completion-ignore-case (helm-set-case-fold-search)) + (comps + (completion-all-completions + str ; This is helm-pattern + collection + predicate + (length str) + metadata)) + (last-data (last comps)) + ;; Helm syle sort fn is added to + ;; metadata only in emacs-27, so in + ;; emacs-26 use helm-generic-sort-fn + ;; which handle both helm and + ;; helm-flex styles. When + ;; helm-completion-style is helm or + ;; helm-fuzzy, sorting will be done + ;; later in FCT. + (sort-fn + (and (eq helm-completion-style 'emacs) + (or + ;; Emacs-27 + (completion-metadata-get + metadata 'display-sort-function) + ;; Emacs-26 + (lambda (candidates) + (sort candidates #'helm-generic-sort-fn))))) + all) + (when (cdr last-data) + ;; Remove the last element of + ;; comps by side-effect. + (setcdr last-data nil)) + (setq helm-completion--sorting-done (and sort-fn t)) + (setq all (copy-sequence comps)) + ;; Default is passed here only with helm + ;; h-c-styles, otherwise with emacs style it is + ;; passed with the :default arg of helm-comp-read + ;; and computed in its get-candidates function. + (append (and default + (memq helm-completion-style '(helm helm-fuzzy)) + (list default)) + (helm-completion-in-region--initial-filter + (let ((lst (if (and sort-fn (> (length str) 0)) + (funcall sort-fn all) + all))) + (if (and default afix) + (prog1 (append (list default) + (delete default lst)) + (setq default nil)) + lst)) + afun afix file-comp-p))))) + (data (if (memq helm-completion-style '(helm helm-fuzzy)) + (funcall compfn (or input "") nil nil) + compfn)) + (helm-completion-in-region-default-sort-fn + (lambda (candidates _source) + (if (or helm-completion--sorting-done + (string= helm-pattern "")) + candidates + (sort candidates 'helm-generic-sort-fn))))) + (unwind-protect + (helm-comp-read + ;; Completion-at-point and friends have no prompt. + prompt + data + :name name + :initial-input input + :buffer buffer + :history history + :nomark (null helm-comp-read-use-marked) + :reverse-history helm-mode-reverse-history + ;; In helm h-c-styles default is passed directly in + ;; candidates. + :default (and (eq helm-completion-style 'emacs) (null afix) default) + :fc-transformer + ;; Ensure sort fn is at the end. + (append '(helm-cr-default-transformer) + (and helm-completion-in-region-default-sort-fn + (list helm-completion-in-region-default-sort-fn))) + :match-dynamic (eq helm-completion-style 'emacs) + :diacritics helm-mode-ignore-diacritics + :fuzzy (eq helm-completion-style 'helm-fuzzy) + :exec-when-only-one exec-when-only-one + :quit-when-no-cand (eq require-match t) + :must-match require-match) + (setq helm-completion--sorting-done nil)))) + +(defun helm-completing-read-default-find-tag + (prompt collection test require-match + init hist default inherit-input-method + name buffer) + "Specialized `helm-mode' handler for `find-tag'." + ;; Some commands like find-tag may use `read-file-name' from inside + ;; the calculation of collection. in this case it clash with + ;; candidates-in-buffer that reuse precedent data (files) which is wrong. + ;; So (re)calculate collection outside of main helm-session. + (let* ((cands (helm-comp-read-get-candidates + collection test nil nil))) + (helm-completing-read-default-1 prompt cands test require-match + init hist default inherit-input-method + name buffer t))) + +(defun helm-completing-read-sync-default-handler + (prompt collection test require-match + init hist default inherit-input-method + name buffer) + "`helm-mode' handler using sync source as backend." + (helm-completing-read-default-1 prompt collection test require-match + init hist default inherit-input-method + name buffer)) + +(defun helm-completing-read-inbuffer-default-handler + (prompt collection test require-match + init hist default inherit-input-method + name buffer) + "`helm-mode' handler using inbuffer source as backend." + (helm-completing-read-default-1 prompt collection test require-match + init hist default inherit-input-method + name buffer t)) + +(defun helm-completing-read-default-handler + (prompt collection test require-match + init hist default inherit-input-method + name buffer) + "Default `helm-mode' handler for all `completing-read'." + (let* (;; Standard will be used as CANDS-IN-BUFFER arg. + (standard (and (memq helm-completion-style '(helm helm-fuzzy)) t)) + (fn (if standard + #'helm-completing-read-default-1 + #'helm-completing-read-default-2))) + (funcall fn + prompt collection test require-match + init hist default inherit-input-method name buffer + ;; CANDS-IN-BUFFER + standard))) + +(defun helm-mode--read-buffer-to-switch (prompt) + "[INTERNAL] This is used to advice `read-buffer-to-switch'. +Don't use it directly." + ;; `read-buffer-to-switch' is passing `minibuffer-completion-table' + ;; to `read-buffer' through `minibuffer-setup-hook' which is too + ;; late to be known by `read-buffer-function', in our case + ;; `helm--generic-read-buffer'. It should let bind it to allow us + ;; using it. + (let ((minibuffer-completion-table (internal-complete-buffer-except))) + (read-buffer prompt (other-buffer (current-buffer)) + (confirm-nonexistent-file-or-buffer)))) + +(defun helm--generic-read-buffer (prompt &optional default require-match predicate) + "The `read-buffer-function' for `helm-mode'. +Affects `switch-to-buffer' `kill-buffer' and related." + ;; `read-buffer' is using internally `Vbuffer_alist' which is an + ;; alist with elements like (BUF-NAME . BUF-OBJ), therefore some + ;; predicates in Emacs are working only on such cons cells. + ;; However, helm is transforming COLLECTION in a list of strings and + ;; such predicates are failing because they expect cons cells (see + ;; bug#2506 with `project-switch-to-buffer'), even if they should + ;; handle strings as well according to `read-buffer' + ;; documentation. + (let ((pred (when predicate + (lambda (buffer) + (let ((buf (cons buffer (get-buffer buffer)))) + (condition-case _err + (funcall predicate buffer) + (wrong-type-argument + (funcall predicate buf)))))))) + (helm--completing-read-default + prompt (or minibuffer-completion-table + (internal-complete-buffer "" nil t)) + pred require-match nil nil default))) + +(defun helm-mode--get-default-handler-for (comp-or-file entry) + ;; Use 'comp for completing-read and 'file for 'read-file-name as + ;; COMP-OR-FILE value. + (let ((val (cdr-safe entry)) + (reading-file (eq comp-or-file 'file))) + (if (consp val) + (helm-acase (if reading-file (cadr val) (car val)) + (default (if reading-file + #'helm-read-file-name + #'helm-completing-read-default-handler)) + (t it)) + val))) + +(defun helm-mode--apply-helm-handler (handler arg-list) + "Ensure `minibuffer-complete' is disabled when running HANDLER. +ARG-LIST is a list of arguments to pass to HANDLER." + ;; Some functions are calling `minibuffer-complete' + ;; within `minibuffer-setup-hook' when calling their + ;; `completing-read', like `woman-file-name' (bug #2527). + ;; This defeat Helm which is already + ;; completing minibuffer, so deactivate + ;; minibuffer-complete one time for all [1]. + (cl-letf (((symbol-function 'minibuffer-complete) #'ignore)) + (apply handler arg-list))) + +(cl-defun helm--completing-read-default + (prompt collection &optional + predicate require-match + initial-input hist def + inherit-input-method) + "An helm replacement of `completing-read'. +This function should be used only as a `completing-read-function'. + +Don't use it directly, use instead `helm-comp-read' in your programs. + +See documentation of `completing-read' and `all-completions' for details." + (let* ((current-command (or (helm-this-command) this-command)) + (str-command (if current-command + (helm-symbol-name current-command) + "completing-read")) + (buf-name (format "*helm-mode-%s*" str-command)) + (entry (assq current-command + helm-completing-read-handlers-alist)) + (def-com (helm-mode--get-default-handler-for 'comp entry)) + (str-defcom (and def-com (helm-symbol-name def-com))) + (def-args (list prompt collection predicate require-match + initial-input hist def inherit-input-method)) + ;; Append the two extra args needed to set the buffer and source name + ;; in helm specialized functions. + (others-args (append def-args (list str-command buf-name))) + helm-completion-mode-start-message ; Be quiet + helm-completion-mode-quit-message + ;; Be sure this pesty *completion* buffer doesn't popup. + ;; Note: `minibuffer-with-setup-hook' may setup a lambda + ;; calling `minibuffer-completion-help' or other minibuffer + ;; functions we DONT WANT here, in these cases removing the hook + ;; (a symbol) have no effect. Bug#448. + ;; Because `minibuffer-completion-table' and + ;; `minibuffer-completion-predicate' are not bound + ;; anymore here, these functions should have no effect now, + ;; except in some rare cases like in `woman-file-name', + ;; so remove all incompatible functions + ;; from `minibuffer-setup-hook' (Bug#1205, Bug#1240). + ;; otherwise helm have not the time to close its initial session. + (minibuffer-setup-hook + (cl-loop for h in minibuffer-setup-hook + unless (or (consp h) ; a lambda. + (byte-code-function-p h) + (helm-subr-native-elisp-p h) + (memq h helm-mode-minibuffer-setup-hook-black-list)) + collect h)) + ;; Disable hack that could be used before `completing-read'. + ;; i.e (push ?\t unread-command-events). + unread-command-events + ;; Let-bounding here helm-completion-style according to + ;; helm-completion-styles-alist allow using helm style per commands. + (helm-completion-style (helm-aif (cdr (assq current-command helm-completion-styles-alist)) + (if (cdr-safe it) (car it) it) + (default-value 'helm-completion-style))) + (completion-styles + (helm--prepare-completion-styles current-command)) + (default-handler + ;; If nothing is found in + ;; helm-completing-read-handlers-alist use default + ;; handler which will itself use `helm-completion-style'. + #'helm-completing-read-default-handler)) + (when (eq def-com 'ido) (setq def-com 'ido-completing-read)) + (unless (or (not entry) def-com) + ;; An entry in *read-handlers-alist exists but have + ;; a nil value, so we exit from here, disable `helm-mode' + ;; and run the command again with it original behavior. + ;; `helm-mode' will be restored on exit. + (cl-return-from helm--completing-read-default + (unwind-protect + (progn + (helm-mode -1) + (apply completing-read-function def-args)) + (helm-mode 1)))) + ;; If we use now `completing-read' we MUST turn off `helm-mode' + ;; to avoid infinite recursion and CRASH. It will be reenabled on exit. + (when (or (eq def-com 'completing-read) + ;; All specialized functions are prefixed by "helm" + (and (stringp str-defcom) + (not (string-match "^helm" str-defcom)))) + (helm-mode -1)) + (unwind-protect + (cond (;; An helm specialized function exists, run it. + (and def-com helm-mode) + ;; Disable `minibuffer-complete' for handlers using + ;; helm (bug #2533). + (helm-mode--apply-helm-handler + def-com others-args)) + (;; Try to handle `ido-completing-read' everywhere. + (and def-com (eq def-com 'ido-completing-read)) + (setcar (memq collection def-args) + (all-completions "" collection predicate)) + (apply def-com def-args)) + (;; A non helm function specified in + ;; `helm-completing-read-handlers-alist' use it with + ;; exactly the same args as in `completing-read'. If + ;; we are here `helm-mode' is now disabled. + def-com + (apply def-com def-args)) + (;; Use by default a in-buffer handler unless + ;; COLLECTION is a function. + t + ;; Disable `minibuffer-complete' for handlers using + ;; helm (bug #2533). + (helm-mode--apply-helm-handler + default-handler others-args))) + (helm-mode 1) + ;; When exiting minibuffer, `this-command' is set to + ;; `helm-exit-minibuffer', which is unwanted when starting + ;; on another `completing-read', so restore `this-command' to + ;; initial value when exiting. + (setq this-command current-command)))) + +;;; Generic read-file-name +;; +;; +;;;###autoload +(cl-defun helm-read-file-name + (prompt + &key + (name "Read File Name") + initial-input + (buffer "*Helm file completions*") + test + noret + (case-fold helm-file-name-case-fold-search) + preselect + history + must-match + (fuzzy t) + default + marked-candidates + (candidate-number-limit helm-ff-candidate-number-limit) + nomark + (alistp t) + (persistent-action-if 'helm-find-files-persistent-action-if) + (persistent-help "Hit1 Expand Candidate, Hit2 or (C-u) Find file") + (mode-line helm-read-file-name-mode-line-string)) + "Read a file name with helm completion. + +It is helm `read-file-name' emulation. + +Argument PROMPT is the default prompt to use. + +Keys description: + +- NAME: Source name, default to \"Read File Name\". + +- INITIAL-INPUT: Where to start reading file name, + default to `default-directory' or $HOME. + +- BUFFER: `helm-buffer' name, defaults to \"*Helm Completions*\". + +- TEST: A predicate called with one arg \\='candidate'. + +- NORET: Allow disabling helm-ff-RET (have no effect if helm-ff-RET + isn't bound to RET). + +- CASE-FOLD: Same as `helm-case-fold-search'. + +- PRESELECT: helm preselection. + +- HISTORY: Display HISTORY in a special source. + +- MUST-MATCH: Can be \\='confirm, nil, or t. + +- FUZZY: Enable fuzzy matching when non-nil (Enabled by default). + +- MARKED-CANDIDATES: When non--nil return a list of marked candidates. + +- NOMARK: When non--nil don't allow marking candidates. + +- ALISTP: Don't use `all-completions' in history + (take effect only on history). + +- PERSISTENT-ACTION-IF: a persistent if action function. + +- PERSISTENT-HELP: persistent help message. + +- MODE-LINE: A mode line message, default is + `helm-read-file-name-mode-line-string'." + (require 'tramp) + (unless initial-input + (setq initial-input (or default-directory (getenv "HOME")))) + (when (get-buffer helm-action-buffer) + (kill-buffer helm-action-buffer)) + (mapc (lambda (hook) + (add-hook 'helm-after-update-hook hook)) + '(helm-ff-move-to-first-real-candidate + helm-ff-update-when-only-one-matched + helm-ff-auto-expand-to-home-or-root)) + (let* ((action-fn `(("Sole action (Identity)" + . (lambda (candidate) + (if ,marked-candidates + (helm-marked-candidates :with-wildcard t) + (identity candidate)))))) + ;; Be sure we don't erase the underlying minibuffer if some. + (helm-ff-auto-update-initial-value + (and helm-ff-auto-update-initial-value + (not (minibuffer-window-active-p (minibuffer-window))))) + helm-follow-mode-persistent + (helm-ff-fuzzy-matching + (and fuzzy + (not (memq helm-mm-matching-method '(multi1 multi3p))))) + (hist (and history (helm-comp-read-get-candidates + history nil nil alistp))) + (helm-ff--RET-disabled noret) + (minibuffer-completion-predicate test) + (minibuffer-completing-file-name t) + ;; Ensure not being prompted for password each time we + ;; navigate to a directory. + (password-cache t) + (helm--completing-file-name t) + (helm-read-file-name-mode-line-string + (replace-regexp-in-string "helm-maybe-exit-minibuffer" + "helm-confirm-and-exit-minibuffer" + helm-read-file-name-mode-line-string)) + (src-list + (list + ;; History source. + (helm-build-sync-source (format "%s History" name) + :header-name (lambda (name) + (concat name (substitute-command-keys + helm-find-files-doc-header))) + :mode-line mode-line + :candidates hist + :nohighlight t + :fuzzy-match fuzzy + :persistent-action-if persistent-action-if + :persistent-help persistent-help + :keymap helm-read-file-map + :must-match must-match + :nomark nomark + :action action-fn) + ;; Other source. + (helm-build-sync-source name + :header-name (lambda (name) + (concat name (substitute-command-keys + helm-find-files-doc-header))) + :init (lambda () + (setq helm-ff-auto-update-flag + helm-ff-auto-update-initial-value) + (setq helm-ff--auto-update-state + helm-ff-auto-update-flag)) + :mode-line mode-line + :help-message 'helm-read-file-name-help-message + :nohighlight helm-ff-nohighlight-matches + :candidate-number-limit 'helm-ff-candidate-number-limit + :candidates + (lambda () + (if test + (append (and (not (file-exists-p helm-pattern)) + (not (helm-ff--invalid-tramp-name-p helm-pattern)) + (list (helm-ff-filter-candidate-one-by-one + helm-pattern nil t))) + (cl-loop with hn = (helm-ff--tramp-hostnames) + ;; helm-find-files-get-candidates is + ;; returning a list of cons cells. + for (d . r) in (helm-find-files-get-candidates + must-match) + when (or (member r hn) ; A tramp host + (funcall test r)) ; Test ok + collect (cons d r))) + (helm-find-files-get-candidates must-match))) + :update (lambda () + (remhash helm-ff-default-directory + helm-ff--list-directory-cache)) + :match-on-real t + :filtered-candidate-transformer (delq nil `(helm-ff-fct + helm-ff-maybe-show-thumbnails + helm-ff-sort-candidates + ,(and helm-ff-icon-mode + (featurep 'all-the-icons) + 'helm-ff-icons-transformer))) + :persistent-action-if persistent-action-if + :persistent-help persistent-help + :volatile t + :keymap helm-read-file-map + :must-match must-match + :cleanup 'helm-find-files-cleanup + :nomark nomark + :action action-fn))) + ;; Helm result. + (result (helm + :sources (if helm-mode-reverse-history + (reverse src-list) src-list) + :input (if (string-match helm-ff-url-regexp initial-input) + initial-input + (expand-file-name initial-input)) + :prompt prompt + :candidate-number-limit candidate-number-limit + :resume 'noresume + :case-fold-search case-fold + :default default + :buffer buffer + :full-frame nil + :preselect preselect))) + (or + (cond ((and result (stringp result) + (string= result "") "")) + ((and result + (stringp result) + (file-equal-p result initial-input) + helm-read-file-name-use-default-arg-behavior + default) + (if (listp default) (car default) default)) + ((and result (listp result)) + (mapcar #'expand-file-name result)) + ((and result (file-directory-p result)) + (file-name-as-directory (expand-file-name result))) + (result (expand-file-name result))) + (helm-mode--keyboard-quit)))) + +(defun helm-mode--default-filename (fname dir initial) + (unless dir (setq dir default-directory)) + (unless (file-name-absolute-p dir) + (setq dir (expand-file-name dir))) + (unless (or fname (consp fname)) + (setq fname (expand-file-name + (or initial buffer-file-name dir) + dir))) + (if (and fname (consp fname)) + (setq fname (cl-loop for f in fname + collect (expand-file-name f dir))) + (if (file-name-absolute-p fname) + fname (expand-file-name fname dir)))) + +(cl-defun helm--generic-read-file-name + (prompt &optional dir default-filename mustmatch initial predicate) + "Generic helm replacement of `read-file-name'. +Don't use it directly, use instead `helm-read-file-name' in your programs." + (let* ((init (or initial dir default-directory)) + (helm-read-file-name-use-default-arg-behavior t) + (current-command (or (helm-this-command) this-command)) + (str-command (if current-command + (helm-symbol-name current-command) + "read-file-name")) + (helm--file-completion-sources + (cons str-command + (remove str-command helm--file-completion-sources))) + (buf-name (format "*helm-mode-%s*" str-command)) + (entry (assq current-command + helm-completing-read-handlers-alist)) + (def-com (helm-mode--get-default-handler-for 'file entry)) + (str-defcom (and def-com (helm-symbol-name def-com))) + ;; Don't modify the original args list for emacs generic functions. + (def-args (list prompt dir default-filename mustmatch initial predicate)) + ;; Append the two extra args needed to set the buffer and source name + ;; in helm specialized functions. + (others-args (append def-args (list str-command buf-name))) + (reading-directory (eq predicate 'file-directory-p)) + (use-dialog (and (next-read-file-uses-dialog-p) + ;; Graphical file dialogs can't handle + ;; remote files. + (not (file-remote-p init)) + use-file-dialog)) + helm-completion-mode-start-message ; Be quiet + helm-completion-mode-quit-message ; Same here + add-to-history fname) + ;; Build `default-filename' with `dir'+`initial' when + ;; `default-filename' is not specified. + ;; See `read-file-name' docstring for more infos. + (setq default-filename (helm-mode--default-filename + default-filename dir initial)) + ;; Some functions that normally call `completing-read' can switch + ;; brutally to `read-file-name' (e.g find-tag), in this case + ;; the helm specialized function will fail because it is build + ;; for `completing-read', so set it to 'incompatible to be sure + ;; we switch to `helm-read-file-name' and don't try to call it + ;; with wrong number of args. + (when (eq def-com 'ido) + (setq def-com 'ido-read-file-name)) + (when (and def-com (> (length (help-function-arglist def-com)) 8)) + (setq def-com 'incompatible)) + (unless (or (not entry) def-com) + (cl-return-from helm--generic-read-file-name + (unwind-protect + (progn + (helm-mode -1) + (apply read-file-name-function def-args)) + (helm-mode 1)))) + ;; If we use now `read-file-name' or dialog we MUST turn off `helm-mode' + ;; to avoid infinite recursion and CRASH. It will be reenabled on exit. + (when (or (memq def-com '(read-file-name ido-read-file-name)) + use-dialog + (and (stringp str-defcom) + (not (string-match "^helm" str-defcom)))) + (helm-mode -1)) + (unwind-protect + (setq fname + (cond (use-dialog + (let ((dialog-mustmatch + (not (memq mustmatch + '(nil confirm confirm-after-completion))))) + ;; Dialogs don't support a list of default fnames. + (when (and default-filename (consp default-filename)) + (setq default-filename + (expand-file-name (car default-filename) init))) + (setq add-to-history t) + (x-file-dialog prompt init default-filename + dialog-mustmatch + reading-directory))) + ;; A specialized function exists, run it + ;; with the two extra args specific to helm. + ;; Note that the helm handler should ensure + ;; :initial-input is not nil i.e. Use init + ;; which fallback to default-directory instead + ;; of INITIAL. + ((and def-com helm-mode + (not (eq def-com 'ido-read-file-name)) + (not (eq def-com 'incompatible)) + ;; The entry in + ;; `helm-completing-read-handlers-alist' is + ;; a cons cell specifying a completing-read + ;; and a read-file-name handler default + ;; e.g. (foo (default default)). + (not (eq def-com 'helm-read-file-name))) + (apply def-com others-args)) + (;; Def-com value is `ido-read-file-name' + ;; run it with default args. + (and def-com (eq def-com 'ido-read-file-name)) + (ido-mode 1) + (apply def-com def-args)) + (;; Def-com value is `read-file-name' + ;; run it with default args. + (eq def-com 'read-file-name) + (apply def-com def-args)) + (t ; Fall back to classic `helm-read-file-name'. + (helm-read-file-name + prompt + :name str-command + :buffer buf-name + :default default-filename + ;; Helm handlers should always have a non nil INITIAL arg. + :initial-input (if (string-match helm-ff-url-regexp init) + init + (expand-file-name init dir)) + :alistp nil + :nomark (null helm-comp-read-use-marked) + :marked-candidates helm-comp-read-use-marked + :must-match mustmatch + :test predicate + :noret reading-directory)))) + (and ido-mode (ido-mode -1)) + (helm-mode 1) + ;; Same comment as in `helm--completing-read-default'. + (setq this-command current-command)) + (when add-to-history + (add-to-history 'file-name-history + (minibuffer-maybe-quote-filename fname))) + (if (and + ;; Using `read-directory-name'. + reading-directory + ;; `file-name-as-directory' return "./" when FNAME is + ;; empty string. + (not (string= fname ""))) + (file-name-as-directory fname) + fname))) + +;; Read file name handler with history (Bug#1652) +(defun helm-read-file-name-handler-1 (prompt dir default-filename + mustmatch initial predicate + name buffer) + "A `read-file-name' handler with history. +Can be added to `helm-completing-read-handlers-alist' for functions +that need a `read-file-name' function with directory history. +The `helm-find-files' history `helm-ff-history' is used here." + (let ((helm-always-two-windows t) + (helm-split-window-default-side + (if (eq helm-split-window-default-side 'same) + 'below helm-split-window-default-side)) + helm-reuse-last-window-split-state + ;; Helm handlers should always have a non nil INITIAL arg. + (init (or initial dir default-directory))) + (helm-read-file-name + prompt + :name name + :history helm-ff-history + :buffer buffer + :default default-filename + :initial-input (expand-file-name init dir) + :alistp nil + :must-match mustmatch + :test predicate))) + + +;;; Completion in region and Helm style +;; +(defun helm-mode--advice-lisp--local-variables (old--fn &rest args) + (ignore-errors + (apply old--fn args))) + +(defvar helm-completion--sorting-done nil + "Flag that notifies the FCT if sorting has been done in completion function.") +(defun helm-completion-in-region-sort-fn (candidates _source) + "Default sort function for completion-in-region." + (if helm-completion--sorting-done + candidates + (sort candidates 'helm-generic-sort-fn))) + +(defun helm-mode--completion-in-region-initial-input (str) + "Highlight prefix in helm and helm-fuzzy `helm-completion-styles'." + (if (memq helm-completion-style '(helm helm-fuzzy)) + (propertize str 'read-only t 'face 'helm-mode-prefix 'rear-nonsticky t) + str)) + +(defun helm--symbol-completion-table-affixation (completions) + "Same as `help--symbol-completion-table-affixation' but for helm. + +Return a list of cons cells of the form (disp . real)." + (mapcar (lambda (c) + (let* ((s (intern c)) + (doc (ignore-errors + (helm-get-first-line-documentation s)))) + (cons (concat (propertize + (format "%-4s" (help--symbol-class s)) + 'face 'completions-annotations) + c + (if doc + (propertize (format " -- %s" doc) + 'face 'completions-annotations) + "")) + c))) + completions)) + +(defun helm-completion-in-region--initial-filter (comps afun afix file-comp-p) + "Compute COMPS with function AFUN or AFIX unless FILE-COMP-P non nil. + +If both AFUN and AFIX are provided only AFIX is used. +When FILE-COMP-P is provided only filter out dot files." + (if file-comp-p + ;; Filter out dot files in file completion. + (cl-loop for f in comps unless + (string-match "\\`\\.\\{1,2\\}/\\'" f) + collect f) + (cond (afix (helm--symbol-completion-table-affixation comps)) + (afun + ;; Add annotation at end of + ;; candidate if needed, e.g. foo, this happen when + ;; completing against a quoted symbol. + (mapcar (lambda (s) + (let ((ann (funcall afun s))) + (if ann + (cons + (concat + s + (propertize + " " 'display + (propertize + ann + 'face 'completions-annotations))) + s) + s))) + comps)) + (t comps)))) + +;; Helm multi matching style + +(defun helm-completion-try-completion (string table pred point) + "The try completion function for `completing-styles-alist'. +Actually does nothing." + ;; AFAIU the try-completions style functions + ;; are here to check if what is at point is suitable for TABLE but + ;; there is no way to pass a multiple pattern from what is at point + ;; apart sending STRING in a minibuffer like helm does. Perhaps + ;; minibuffer-complete should benefit of this but for now just do + ;; nothing as this is used nowhere. It is anyway not clear what the + ;; try-completions functions do in emacs so just do nothing for now. + (ignore string table pred point)) + +(defun helm-completion-all-completions (string table pred point) + "The all completions function for `completing-styles-alist'." + ;; FIXME: No need to bind all these value. + ;; (cl-multiple-value-bind (all _pattern prefix _suffix _carbounds) + (pcase-let ((`(,all ,_pattern ,prefix ,_suffix ,_carbounds) + (helm-completion--multi-all-completions string table pred point))) + (when all (nconc all (length prefix))))) + +(defun helm-completion--multi-all-completions-1 (string collection &optional predicate) + "Allow `all-completions' multi matching on its candidates." + ;; Doing an initial call of all-completions on the first element of + ;; STRING speedup completion and fix file completion when CAPF + ;; returns relative paths to initial pattern (eshell and shell). + (let* ((split (helm-mm-split-pattern string)) + (fpat (or (car split) "")) + (file-comp-p (or minibuffer-completing-file-name + (eq + (completion-metadata-get + (completion-metadata string collection predicate) + 'category) + 'file))) + (all (and file-comp-p + (or (cdr split) + (and (not (cdr split)) + ;; Kickin when STRING is a simple string. + ;; Handle as well "foo " (space at end). + (not (string= fpat ""))) + (string= string "")) + (not (string-match "\\`!" fpat)) + ;; all-completions should return nil if FPAT is a + ;; regexp, it is what we expect. + (all-completions fpat collection + (lambda (x &optional _y) + (let ((elm (if (listp x) (car x) x))) + (funcall (or predicate #'identity) elm)))))) + (pattern (helm-aand all (string-match " " string) + ;; Returns the part of STRING after space + ;; e.g. "foo bar baz" => "bar baz". + (substring string (1+ it))))) + (if (or (and all (not (cdr split))) + (equal pattern "")) ; e.g. STRING == "foo ". + all + (all-completions "" (or all collection) + (lambda (x &optional _y) + ;; Second arg _y is needed when + ;; COLLECTION is a hash-table (Bug#2231) + ;; (C-x 8 RET). + ;; Elements of COLLECTION may be + ;; lists or alists, in this case consider the + ;; car of element (Bug#2219 org-refile). + (let ((elm (if (listp x) (car x) x))) + ;; PREDICATE have been already called in + ;; initial all-completions, no need to call + ;; it a second time, thus ALL is now a list + ;; of strings maybe not supported by + ;; PREDICATE (e.g. symbols vs strings). + (if (and predicate (null all)) + (and (funcall predicate elm) + ;; ALL is nil so use whole STRING + ;; against COLLECTION. + (helm-mm-match (helm-stringify elm) string)) + (helm-mm-match (helm-stringify elm) + (or (and all pattern) string))))))))) + +(defun helm-completion--multi-all-completions (string table pred point) + "Collect completions from TABLE for helm completion style." + (let* ((beforepoint (substring string 0 point)) + (afterpoint (substring string point)) + (bounds (completion-boundaries beforepoint table pred afterpoint)) + (prefix (substring beforepoint 0 (car bounds))) + (suffix (substring afterpoint (cdr bounds))) + (all (helm-completion--multi-all-completions-1 + ;; Using `regexp-quote' on STRING fixes bug#2355 but + ;; breaks regexp matching in multi match, actually with + ;; Helm-3.7.1 and emacs-27+ it seems using plain STRING + ;; works for both so use it. + ;;(regexp-quote string) + string table pred))) + (list all string prefix suffix point))) + +;; The adjust-metadata functions run only in emacs-27, they are NOT +;; used otherwise. +(defun helm-completion--adjust-metadata (metadata) + (if (memq helm-completion-style '(helm helm-fuzzy)) + metadata + (let ((compose-helm-sort-fn + (lambda (candidates) + (sort candidates #'helm-generic-sort-fn)))) + `(metadata + (display-sort-function + . ,compose-helm-sort-fn) + (cycle-sort-function + . ,compose-helm-sort-fn) + ,@(cdr metadata))))) +(put 'helm 'completion--adjust-metadata 'helm-completion--adjust-metadata) + +;; Helm-flex style. +;; This is more or less the same as emacs-27 flex style. +(defun helm-flex-completion-try-completion (string table pred point) + "The try completion function for `completing-styles-alist'." + ;; It is needed here to make minibuffer-complete work in emacs-26, + ;; e.g. with regular M-x. + (unless (string-match-p " " string) + (pcase-let ((`(,all ,pattern ,prefix ,suffix ,_carbounds) + (helm-completion--flex-all-completions string table pred point))) + (when minibuffer-completing-file-name + (setq all (completion-pcm--filename-try-filter all))) + (completion-pcm--merge-try pattern all prefix suffix)))) + +(defun helm-flex-completion-all-completions (string table pred point) + "The all completions function for `completing-styles-alist'." + ;; FIXME: No need to bind all these value. + (unless (string-match-p " " string) + (pcase-let ((`(,all ,pattern ,prefix ,_suffix ,_carbounds) + (helm-completion--flex-all-completions + string table pred point + #'helm-completion--flex-transform-pattern))) + (let ((regexp (completion-pcm--pattern->regex pattern 'group))) + (when all (nconc (helm-flex-add-score-as-prop all regexp) + (length prefix))))))) + +;; Same as emacs-27 completion-substring--all-completions. +(defun helm-completion--flex-all-completions + (string table pred point &optional transform-pattern-fn) + "Match the presumed substring STRING to the entries in TABLE. +Respect PRED and POINT. The pattern used is a PCM-style substring +pattern, but it will be massaged by TRANSFORM-PATTERN-FN, if that +is non-nil." + (let* ((beforepoint (substring string 0 point)) + (afterpoint (substring string point)) + (bounds (completion-boundaries beforepoint table pred afterpoint)) + (suffix (substring afterpoint (cdr bounds))) + (prefix (substring beforepoint 0 (car bounds))) + (basic-pattern (completion-basic--pattern + beforepoint afterpoint bounds)) + (pattern (if (not (stringp (car basic-pattern))) + basic-pattern + (cons 'prefix basic-pattern))) + (pattern (if transform-pattern-fn + (funcall transform-pattern-fn pattern) + pattern)) + (all (completion-pcm--all-completions prefix pattern table pred))) + (list all pattern prefix suffix (car bounds)))) + +(defun helm-completion-in-region--selection () + (with-helm-buffer + (setq helm-saved-selection (helm-get-selection nil 'withprop)))) + +;; Completion-in-region-function + +(defvar helm--completing-region nil + "[INTERNAL] flag let-bounded to nil when completing in region.") + +(defun helm--completion-in-region (origfun start end collection &optional predicate) + "Helm replacement of `completion--in-region'. + +Can be used for `completion-in-region-function' by advicing it with an +:around advice to allow passing the old +`completion-in-region-function' value in ORIGFUN." + (cl-declare (special require-match prompt)) + (if (memq major-mode helm-mode-no-completion-in-region-in-modes) + (funcall origfun start end collection predicate) + (advice-add + 'lisp--local-variables + :around #'helm-mode--advice-lisp--local-variables) + (let ((old--helm-completion-style helm-completion-style) + (exit-fun (plist-get completion-extra-properties :exit-function)) + ;; Always start with prefix to allow completing without + ;; the need of inserting a space after cursor or + ;; relaying on crap old completion-styles emacs22 which + ;; add suffix after prefix. e.g. def|else. + (initial-input (buffer-substring-no-properties start (point))) + string) + (helm-aif (cdr (assq major-mode helm-completion-styles-alist)) + (customize-set-variable 'helm-completion-style + (if (cdr-safe it) (car it) it))) + ;; This hook force usage of the display part of candidate with + ;; its properties, this is needed for lsp-mode in its + ;; :exit-function see Bug#2265. + (add-hook 'helm-before-action-hook 'helm-completion-in-region--selection) + (unwind-protect + (let* ((enable-recursive-minibuffers t) + (completion-flex-nospace t) + (helm--completing-region t) + (completion-styles (helm--prepare-completion-styles)) + (input (buffer-substring-no-properties start end)) + (prefix (and (eq helm-completion-style 'emacs) initial-input)) + (point (point)) + (current-command (or (helm-this-command) + this-command + ;; Some backends are async and + ;; use a callback, in those + ;; cases, we can't retrieve from + ;; frames the last interactive + ;; command, so fallback to + ;; `last-command' which may be + ;; the one that called the callback. + last-command)) + (crm (eq current-command 'crm-complete)) + (str-command (helm-symbol-name current-command)) + (buf-name (format "*helm-mode-%s*" str-command)) + (require-match (or (and (boundp 'require-match) require-match) + minibuffer-completion-confirm + ;; If prompt have not been propagated here, that's + ;; probably mean we have no prompt and we are in + ;; completion-at-point or friend, so use a non--nil + ;; value for require-match. + (not (boundp 'prompt)))) + (metadata (completion-metadata input collection predicate)) + ;; `completion-extra-properties' is let-bounded in `completion-at-point'. + ;; `afun' is a closure to call against each string in `data'. + ;; it provide the annotation info for each string. + ;; e.g "foo" => "foo " where foo is a function. + ;; See Bug#407. + (afun (or (plist-get completion-extra-properties :annotation-function) + (completion-metadata-get metadata 'annotation-function))) + ;; Not sure if affixations are provided in + ;; completion-in-region, try anyway never know. + (afix (or (plist-get completion-extra-properties :affixation-function) + (completion-metadata-get metadata 'affixation-function))) + (init-space-suffix (unless (or (memq helm-completion-style '(helm-fuzzy emacs)) + (string-suffix-p " " input) + (string= input "")) + " ")) + (file-comp-p (or (eq (completion-metadata-get metadata 'category) 'file) + (helm-guess-filename-at-point) + ;; Assume that when `afun' and `predicate' are null + ;; we are in filename completion. + (and (null afun) (null predicate)))) + ;; `completion-all-completions' store the base-size in the last `cdr', + ;; so data looks like this: '(a b c d . 0) and (last data) == (d . 0). + base-size + (compfn (lambda (str _predicate _action) + (let* ((completion-ignore-case (helm-set-case-fold-search)) + (comps + (completion-all-completions + str ; This is helm-pattern + collection + predicate + ;; Use prefix length at first call to + ;; allow styles matching + ;; "prefix*suffix" to kick in. + (length (or prefix str)) + metadata)) + (last-data (last comps)) + (bs (helm-aif (cdr last-data) + (prog1 it + ;; Remove the last element of + ;; comps by side-effect. + (setcdr last-data nil)) + 0)) + ;; Helm syle sort fn is added to + ;; metadata only in emacs-27, so in + ;; emacs-26 use helm-generic-sort-fn + ;; which handle both helm and + ;; helm-flex styles. When + ;; helm-completion-style is helm or + ;; helm-fuzzy, sorting will be done + ;; later in FCT. + (sort-fn + (and (eq helm-completion-style 'emacs) + (or + ;; Emacs-27 + (completion-metadata-get + metadata 'display-sort-function) + ;; Emacs-26 + (lambda (candidates) + (sort candidates #'helm-generic-sort-fn))))) + all) + ;; Reset prefix to allow using length of + ;; helm-pattern on next calls (this avoid + ;; args-out-of-range error). + (and prefix (setq prefix nil)) + ;; base-size needs to be set only once at + ;; first call. + (unless base-size (setq base-size bs)) + (setq helm-completion--sorting-done (and sort-fn t)) + (setq all (copy-sequence comps)) + (helm-completion-in-region--initial-filter + (if (and sort-fn (> (length str) 0)) + (funcall sort-fn all) + all) + afun afix file-comp-p)))) + (data (if (memq helm-completion-style '(helm helm-fuzzy)) + (funcall compfn input nil nil) + compfn)) + (result (if (stringp data) + data + (helm-comp-read + ;; Completion-at-point and friends have no prompt. + (or (and (boundp 'prompt) prompt) "Pattern: ") + data + :name str-command + :nomark (null crm) + :marked-candidates crm + :initial-input + (cond ((and file-comp-p + (not (string-match "/\\'" initial-input))) + (concat (helm-mode--completion-in-region-initial-input + (if (memq helm-completion-style '(helm helm-fuzzy)) + (helm-basename initial-input) + initial-input)) + init-space-suffix)) + ((string-match "/\\'" initial-input) + (and (eq helm-completion-style 'emacs) initial-input)) + ((or (null require-match) + (stringp require-match)) + (helm-mode--completion-in-region-initial-input initial-input)) + (t (concat (helm-mode--completion-in-region-initial-input initial-input) + init-space-suffix))) + :buffer buf-name + :fc-transformer + ;; Ensure sort fn is at the end. + (append '(helm-cr-default-transformer) + (and helm-completion-in-region-default-sort-fn + (list helm-completion-in-region-default-sort-fn))) + :match-dynamic (eq helm-completion-style 'emacs) + :fuzzy (eq helm-completion-style 'helm-fuzzy) + :exec-when-only-one t + :quit-when-no-cand + (lambda () + ;; Delay message to overwrite "Quit". + (run-with-timer + 0.01 nil + (lambda () + (message "[No matches]"))) + t) ; exit minibuffer immediately. + :must-match require-match)))) + ;; `helm-completion-in-region--insert-result' is stripping + ;; out properties on RESULT by side-effect (perhaps + ;; `choose-completion-string'?) so make a copy of STRING + ;; to not loose props. + (setq string (copy-sequence result)) + (helm-completion-in-region--insert-result + result start point end base-size)) + ;; Allow running extra property `:exit-function' (Bug#2265, + ;; Bug#2356). Function is called with 'exact if for a unique + ;; match which is exact, the return value of `try-completion' + ;; is t or a string ending with "/" i.e. possibly a directory + ;; (Bug#2274), + ;; otherwise it is called with 'finished. + (when (and (stringp string) exit-fun) + (let ((tcomp (try-completion initial-input collection))) + (funcall exit-fun string + (if (or (eq tcomp t) ; Unique. + (and (stringp tcomp) + (string-match "/\\'" tcomp))) ; A directory. + 'exact 'finished)))) + (remove-hook 'helm-before-action-hook 'helm-completion-in-region--selection) + (customize-set-variable 'helm-completion-style old--helm-completion-style) + (setq helm-completion--sorting-done nil) + (advice-remove 'lisp--local-variables + #'helm-mode--advice-lisp--local-variables))))) + +(defvar helm-crm-default-separator "," + "Default separator for `completing-read-multiple'. + +`crm-separator' will take precedence on this when it is a string composed +of a single character. +If used globally, it is a string composed of a single character, +if let-bounded, it can be also nil or a symbol which mean no +separator. Don't set this to a string composed of more than one +character. +Be sure to know what you are doing when modifying this.") +(defun helm-completion-in-region--insert-result (result start point end base-size) + (cond ((stringp result) + ;; When RESULT have annotation, annotation is displayed + ;; in it with a display property attached to a space + ;; added at end of string, take care of removing this + ;; space (Bug#2360). However keep RESULT intact to + ;; pass it to `:exit-function' i.e. Don't store the + ;; modified string in STRING. + (choose-completion-string + (replace-regexp-in-string " \\'" "" result) + (current-buffer) + (list (+ start base-size) point) + completion-list-insert-choice-function) + (when helm-completion-mark-suffix + (run-with-idle-timer 0.01 nil + (lambda () + (helm-aand + (+ (- (point) point) end) + (and (> it (point)) it) + (push-mark it t t)))))) + ((consp result) ; crm. + (let ((beg (+ start base-size)) + (sep (or (and + ;; If `crm-separator' is a string of length 1 + ;; assume it can be used as separator (Bug#2298), + ;; otherwise it is a regexp and use the value + ;; it matches or default to "," if no match. + (eq (length crm-separator) 1) + crm-separator) + helm-crm-default-separator))) + ;; Try to find a default separator. If `crm-separator' is a + ;; regexp use the string the regexp is matching. + ;; If SEP is not a string, it have been probably bound to a + ;; symbol or nil through `helm-crm-default-separator' that serve + ;; as a flag to say "Please no separator" (Bug#2353 with + ;; `magit-completing-read-multiple'). + (if (stringp sep) + (save-excursion + (goto-char beg) + (when (looking-back crm-separator (1- (point))) + (setq sep (match-string 0)))) + (setq sep nil)) + (funcall completion-list-insert-choice-function + beg end (mapconcat 'identity (append result '("")) sep)))) + (t nil))) + +(defun helm-mode--disable-ido-maybe (&optional from-hook) + (when (and (boundp 'ido-everywhere) ido-everywhere) + (remove-function read-file-name-function #'ido-read-file-name) + (remove-function read-buffer-function #'ido-read-buffer) + (setq ido-everywhere nil) + (if from-hook + (user-error "Unable to turn on Ido-everywhere while Helm-mode is enabled") + (user-error "Helm-mode enabled (Ido-everywhere is incompatible with Helm-mode, disabling it)")))) + +(defun helm-mode--ido-everywhere-hook () + ;; Called only when user calls directly ido-everywhere + ;; and helm-mode is enabled. + (when helm-mode + (helm-mode--disable-ido-maybe t))) + +;;;###autoload +(define-minor-mode helm-mode + "Toggle generic helm completion. + +All functions in Emacs that use `completing-read', +`read-file-name', `completion-in-region' and friends will use helm +interface when this mode is turned on. + +However you can modify this behavior for functions of your choice +with `helm-completing-read-handlers-alist'. + +Called with a positive arg, turn on unconditionally, with a +negative arg turn off. +You can toggle it with M-x `helm-mode'. + +About `ido-mode': +DO NOT enable `ido-everywhere' when using `helm-mode'. Instead of +using `ido-mode', add the commands where you want to use ido to +`helm-completing-read-handlers-alist' with `ido' as value. + +Note: This mode is incompatible with Emacs23." + :group 'helm-mode + :global t + :lighter helm-completion-mode-string + (cl-assert (boundp 'completing-read-function) nil + "`helm-mode' not available, upgrade to Emacs-24") + (if helm-mode + (progn + (add-function :override completing-read-function + #'helm--completing-read-default) + (add-function :override read-file-name-function + #'helm--generic-read-file-name) + (add-function :override read-buffer-function + #'helm--generic-read-buffer) + (when helm-mode-handle-completion-in-region + (add-function :around completion-in-region-function + #'helm--completion-in-region)) + ;; If user have enabled ido-everywhere BEFORE enabling + ;; helm-mode disable it and warn user about its + ;; incompatibility with helm-mode (Bug#2085). + (helm-mode--disable-ido-maybe) + ;; If ido-everywhere is not enabled yet anticipate and + ;; disable it if user attempt to enable it while helm-mode + ;; is running (Bug#2085). + (add-hook 'ido-everywhere-hook #'helm-mode--ido-everywhere-hook) + (when (fboundp 'ffap-read-file-or-url-internal) + ;; `ffap-read-file-or-url-internal' have been removed in + ;; emacs-27 and `ffap-read-file-or-url' is fixed, so no need + ;; to advice it. + (advice-add 'ffap-read-file-or-url :override #'helm-advice--ffap-read-file-or-url)) + (advice-add 'read-buffer-to-switch :override #'helm-mode--read-buffer-to-switch) + (helm-minibuffer-history-mode 1)) + (progn + (remove-function completing-read-function #'helm--completing-read-default) + (remove-function read-file-name-function #'helm--generic-read-file-name) + (remove-function read-buffer-function #'helm--generic-read-buffer) + (remove-function completion-in-region-function #'helm--completion-in-region) + (remove-hook 'ido-everywhere-hook #'helm-mode--ido-everywhere-hook) + (when (fboundp 'ffap-read-file-or-url-internal) + (advice-remove 'ffap-read-file-or-url #'helm-advice--ffap-read-file-or-url)) + (advice-remove 'read-buffer-to-switch #'helm-mode--read-buffer-to-switch) + (helm-minibuffer-history-mode -1)))) + +(provide 'helm-mode) + +;;; helm-mode.el ends here diff --git a/org/elpa/helm-20230406.839/helm-net.el b/org/elpa/helm-20230406.839/helm-net.el new file mode 100644 index 0000000..a0ad9c8 --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-net.el @@ -0,0 +1,436 @@ +;;; helm-net.el --- helm browse url and search web. -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2023 Thierry Volpiatto + +;; 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 . + +;;; Code: + +(require 'cl-lib) +(require 'helm) +(require 'helm-help) +(require 'url) +(require 'xml) +(require 'browse-url) + +(declare-function helm-comp-read "helm-mode") + + +(defgroup helm-net nil + "Net related applications and libraries for Helm." + :group 'helm) + +(defcustom helm-google-suggest-default-browser-function nil + "The browse url function you prefer to use with Google suggest. +When nil, use the first browser function available +See `helm-browse-url-default-browser-alist'." + :group 'helm-net + :type 'symbol) + +(defcustom helm-home-url "https://www.google.com" + "Default url to use as home url." + :group 'helm-net + :type 'string) + +(defcustom helm-surfraw-default-browser-function nil + "The browse url function you prefer to use with surfraw. +When nil, fallback to `browse-url-browser-function'." + :group 'helm-net + :type 'symbol) + +(defcustom helm-google-suggest-url + "https://encrypted.google.com/complete/search?output=toolbar&q=%s" + "URL used for looking up Google suggestions. +This is a format string, don't forget the `%s'." + :type 'string + :group 'helm-net) + +(defcustom helm-google-suggest-search-url + "https://encrypted.google.com/search?ie=utf-8&oe=utf-8&q=%s" + "URL used for Google searching. +This is a format string, don't forget the `%s'." + :type 'string + :group 'helm-net) + +(defvaralias 'helm-google-suggest-use-curl-p 'helm-net-prefer-curl) +(make-obsolete-variable 'helm-google-suggest-use-curl-p 'helm-net-prefer-curl "1.7.7") + +(defcustom helm-net-prefer-curl nil + "When non--nil use CURL external program to fetch data. +Otherwise `url-retrieve-synchronously' is used." + :type 'boolean + :group 'helm-net) + +(defcustom helm-surfraw-duckduckgo-url + "https://duckduckgo.com/lite/?q=%s&kp=1" + "The Duckduckgo url. +This is a format string, don't forget the `%s'. +If you have personal settings saved on duckduckgo you should have +a personal url, see your settings on duckduckgo." + :type 'string + :group 'helm-net) + +(defcustom helm-search-suggest-action-wikipedia-url + "https://en.wikipedia.org/wiki/Special:Search?search=%s" + "The Wikipedia search url. +This is a format string, don't forget the `%s'." + :type 'string + :group 'helm-net) + +(defcustom helm-search-suggest-action-youtube-url + "https://www.youtube.com/results?aq=f&search_query=%s" + "The Youtube search url. +This is a format string, don't forget the `%s'." + :type 'string + :group 'helm-net) + +(defcustom helm-search-suggest-action-imdb-url + "http://www.imdb.com/find?s=all&q=%s" + "The IMDb search url. +This is a format string, don't forget the `%s'." + :type 'string + :group 'helm-net) + +(defcustom helm-search-suggest-action-google-maps-url + "https://maps.google.com/maps?f=q&source=s_q&q=%s" + "The Google Maps search url. +This is a format string, don't forget the `%s'." + :type 'string + :group 'helm-net) + +(defcustom helm-search-suggest-action-google-news-url + "https://www.google.com/search?safe=off&prmd=nvlifd&source=lnms&tbs=nws:1&q=%s" + "The Google News search url. +This is a format string, don't forget the `%s'." + :type 'string + :group 'helm-net) + +(defcustom helm-google-suggest-actions + '(("Google Search" . helm-google-suggest-action) + ("Wikipedia" . (lambda (candidate) + (helm-search-suggest-perform-additional-action + helm-search-suggest-action-wikipedia-url + candidate))) + ("Youtube" . (lambda (candidate) + (helm-search-suggest-perform-additional-action + helm-search-suggest-action-youtube-url + candidate))) + ("IMDb" . (lambda (candidate) + (helm-search-suggest-perform-additional-action + helm-search-suggest-action-imdb-url + candidate))) + ("Google Maps" . (lambda (candidate) + (helm-search-suggest-perform-additional-action + helm-search-suggest-action-google-maps-url + candidate))) + ("Google News" . (lambda (candidate) + (helm-search-suggest-perform-additional-action + helm-search-suggest-action-google-news-url + candidate)))) + "List of actions for google suggest sources." + :group 'helm-net + :type '(alist :key-type string :value-type function)) + +(defcustom helm-browse-url-firefox-new-window "--new-tab" + "Allow choosing to browse url in new window or new tab. +Can be \"--new-tab\" (default), \"--new-window\" or \"--private-window\"." + :group 'helm-net + :type '(radio + (const :tag "New tab" "--new-tab") + (const :tag "New window" "--new-window") + (const :tag "New private window" "--private-window"))) + +(defcustom helm-net-curl-switches '("-s" "-L") + "Arguments list passed to curl when using `helm-net-prefer-curl'." + :group 'helm-net + :type '(repeat string)) + +;;; Additional actions for search suggestions +;; +;; +;; Internal +(defvar helm-net-curl-log-file (expand-file-name "helm-curl.log" user-emacs-directory)) +(defun helm-search-suggest-perform-additional-action (url query) + "Perform the search via URL using QUERY as input." + (browse-url (format url (url-hexify-string query)))) + +(defun helm-net--url-retrieve-sync (request parser) + (if helm-net-prefer-curl + (with-temp-buffer + (apply #'call-process "curl" + nil `(t ,helm-net-curl-log-file) nil request helm-net-curl-switches) + (funcall parser)) + (with-current-buffer (url-retrieve-synchronously request) + (funcall parser)))) + + +;;; Google Suggestions +;; +;; +(defun helm-google-suggest-parser () + (cl-loop + with result-alist = (xml-get-children + (car (xml-parse-region + (point-min) (point-max))) + 'CompleteSuggestion) + for i in result-alist collect + (cdr (cl-caadr (assq 'suggestion i))))) + +(defun helm-google-suggest-fetch (input) + "Fetch suggestions for INPUT from XML buffer." + (let ((request (format helm-google-suggest-url + (url-hexify-string input)))) + (helm-net--url-retrieve-sync + request #'helm-google-suggest-parser))) + +(defun helm-google-suggest-set-candidates (&optional request-prefix) + "Set candidates with result and number of Google results found." + (let ((suggestions (helm-google-suggest-fetch + (or (and request-prefix + (concat request-prefix + " " helm-pattern)) + helm-pattern)))) + (if (member helm-pattern suggestions) + suggestions + ;; if there is no suggestion exactly matching the input then + ;; prepend a Search on Google item to the list + (append + suggestions + (list (cons (format "Search for '%s' on Google" helm-input) + helm-input)))))) + +(defun helm-ggs-set-number-result (num) + (if num + (progn + (and (numberp num) (setq num (number-to-string num))) + (cl-loop for i in (reverse (split-string num "" t)) + for count from 1 + append (list i) into C + when (= count 3) + append (list ",") into C + and do (setq count 0) + finally return + (replace-regexp-in-string + "^," "" (mapconcat 'identity (reverse C) "")))) + "?")) + +(defun helm-google-suggest-action (candidate) + "Default action to jump to a Google suggested candidate." + (let ((arg (format helm-google-suggest-search-url + (url-hexify-string candidate)))) + (helm-aif helm-google-suggest-default-browser-function + (funcall it arg) + (helm-browse-url arg)))) + +(defvar helm-google-suggest-default-function + 'helm-google-suggest-set-candidates + "Default function to use in `helm-google-suggest'.") + +(defvar helm-source-google-suggest + (helm-build-sync-source "Google Suggest" + :candidates (lambda () + (funcall helm-google-suggest-default-function)) + :action 'helm-google-suggest-actions + :match-dynamic t + :keymap helm-map + :requires-pattern 3)) + +(defun helm-google-suggest-emacs-lisp () + "Try to emacs lisp complete with Google suggestions." + (helm-google-suggest-set-candidates "emacs lisp")) + + +;;; Web browser functions. +;; +;; +;; If default setting of `w3m-command' is not +;; what you want and you modify it, you will have to reeval +;; also `helm-browse-url-default-browser-alist'. + +(defvar helm-browse-url-chromium-program "chromium-browser") +(defvar helm-browse-url-uzbl-program "uzbl-browser") +(defvar helm-browse-url-nyxt-program "nyxt") +(defvar helm-browse-url-conkeror-program "conkeror") +(defvar helm-browse-url-opera-program "opera") +(defvar helm-browse-url-w3m-program (or (and (boundp 'w3m-command) w3m-command) + (executable-find "w3m"))) +(defvar helm-browse-url-default-browser-alist + '((helm-browse-url-w3m-program . w3m-browse-url) + (browse-url-firefox-program . browse-url-firefox) + (helm-browse-url-chromium-program . helm-browse-url-chromium) + (helm-browse-url-conkeror-program . helm-browse-url-conkeror) + (helm-browse-url-opera-program . helm-browse-url-opera) + (helm-browse-url-uzbl-program . helm-browse-url-uzbl) + (helm-browse-url-nyxt-program . helm-browse-url-nyxt) + (browse-url-kde-program . browse-url-kde) + (browse-url-gnome-moz-program . browse-url-gnome-moz) + (browse-url-mozilla-program . browse-url-mozilla) + (browse-url-galeon-program . browse-url-galeon) + (browse-url-netscape-program . browse-url-netscape) + (browse-url-xterm-program . browse-url-text-xterm) + ("emacs" . eww-browse-url)) + "Alist of (browse_url_variable . function) to try to find a suitable url browser.") + +(cl-defun helm-generic-browser (url cmd-name &rest args) + "Browse URL with NAME browser." + (let ((proc (concat cmd-name " " url))) + (message "Starting %s..." cmd-name) + (apply 'start-process proc nil cmd-name + (append args (list url))) + (set-process-sentinel + (get-process proc) + (lambda (process event) + (when (string= event "finished\n") + (message "%s process %s" process event)))))) + +;;;###autoload +(defun helm-browse-url-firefox (url &optional _ignore) + "Same as `browse-url-firefox' but detach from Emacs. + +So when you quit Emacs you can keep your Firefox session open and +not be prompted to kill the Firefox process. + +NOTE: Probably not supported on some systems (e.g., Windows)." + (interactive (list (read-string "URL: " (browse-url-url-at-point)) + nil)) + (setq url (browse-url-encode-url url)) + (let ((process-environment (browse-url-process-environment))) + (call-process-shell-command + (format "(%s %s %s &)" + browse-url-firefox-program + helm-browse-url-firefox-new-window + (shell-quote-argument url))))) + +;;;###autoload +(defun helm-browse-url-opera (url &optional _ignore) + "Browse URL with Opera browser and detach from Emacs. + +So when you quit Emacs you can keep your Opera session open and +not be prompted to kill the Opera process. + +NOTE: Probably not supported on some systems (e.g., Windows)." + (interactive (list (read-string "URL: " (browse-url-url-at-point)) + nil)) + (setq url (browse-url-encode-url url)) + (let ((process-environment (browse-url-process-environment))) + (call-process-shell-command + (format "(%s %s &)" + helm-browse-url-opera-program (shell-quote-argument url))))) + +;;;###autoload +(defun helm-browse-url-chromium (url &optional _ignore) + "Browse URL with Google Chrome browser." + (interactive "sURL: ") + (helm-generic-browser + url helm-browse-url-chromium-program)) + +;;;###autoload +(defun helm-browse-url-uzbl (url &optional _ignore) + "Browse URL with uzbl browser." + (interactive "sURL: ") + (helm-generic-browser url helm-browse-url-uzbl-program "-u")) + +;;;###autoload +(defun helm-browse-url-conkeror (url &optional _ignore) + "Browse URL with conkeror browser." + (interactive "sURL: ") + (helm-generic-browser url helm-browse-url-conkeror-program)) + +;;;###autoload +(defun helm-browse-url-nyxt (url &optional _ignore) + "Browse URL with nyxt browser." + (interactive "sURL: ") + (helm-generic-browser url helm-browse-url-nyxt-program)) + +(defun helm-browse-url-default-browser (url &rest args) + "Find the first available browser and ask it to load URL." + (let ((default-browser-fn + (cl-loop for (var . fn) in helm-browse-url-default-browser-alist + for exe = (if (stringp var) + var + (and (boundp var) (symbol-value var))) + thereis (and exe (executable-find exe) (fboundp fn) fn)))) + (if default-browser-fn + (apply default-browser-fn url args) + (error "No usable browser found")))) + +(defun helm-browse-url (url &rest args) + "Default command to browse URL." + (if browse-url-browser-function + (browse-url url args) + (helm-browse-url-default-browser url args))) + + +;;; Surfraw +;; +;; Need external program surfraw. +;; + +;; Internal +(defvar helm-surfraw-engines-history nil) +(defvar helm-surfraw-input-history nil) +(defvar helm-surfraw--elvi-cache nil) + +(defun helm-build-elvi-list () + "Return list of all engines and descriptions handled by surfraw." + (or helm-surfraw--elvi-cache + (setq helm-surfraw--elvi-cache + (cdr (with-temp-buffer + (call-process "surfraw" nil t nil "-elvi") + (split-string (buffer-string) "\n")))))) + +;;;###autoload +(defun helm-surfraw (pattern engine) + "Preconfigured `helm' to search PATTERN with search ENGINE." + (interactive + (list + (let* ((default (if (use-region-p) + (buffer-substring-no-properties + (region-beginning) (region-end)) + (thing-at-point 'symbol))) + (prompt (if default + (format "SearchFor (default %s): " default) + "SearchFor: "))) + (read-string prompt nil 'helm-surfraw-input-history default)) + (helm-comp-read + "Engine: " + (helm-build-elvi-list) + :must-match t + :name "Surfraw Search Engines" + :history 'helm-surfraw-engines-history))) + (let* ((engine-nodesc (car (split-string engine))) + (url (if (string= engine-nodesc "duckduckgo") + ;; "sr duckduckgo -p foo" is broken, workaround. + (format helm-surfraw-duckduckgo-url + (url-hexify-string pattern)) + (with-temp-buffer + (apply 'call-process "surfraw" nil t nil + (append (list engine-nodesc "-p") (split-string pattern))) + (replace-regexp-in-string + "\n" "" (buffer-string))))) + (browse-url-browser-function (or helm-surfraw-default-browser-function + browse-url-browser-function))) + (if (string= engine-nodesc "W") + (helm-browse-url helm-home-url) + (helm-browse-url url)))) + +;;;###autoload +(defun helm-google-suggest () + "Preconfigured `helm' for Google search with Google suggest." + (interactive) + (helm-other-buffer 'helm-source-google-suggest "*helm google*")) + +(provide 'helm-net) + +;;; helm-net.el ends here diff --git a/org/elpa/helm-20230406.839/helm-occur.el b/org/elpa/helm-20230406.839/helm-occur.el new file mode 100644 index 0000000..0adc09f --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-occur.el @@ -0,0 +1,885 @@ +;;; helm-occur.el --- Incremental Occur for Helm. -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2023 Thierry Volpiatto + +;; 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 . + + +;;; Code: + +(require 'cl-lib) +(require 'helm) +(require 'helm-help) +(require 'helm-utils) + +(declare-function helm-buffers-get-visible-buffers "helm-buffers") +(declare-function helm-buffer-list "helm-buffers") +(declare-function helm-grep-split-line "helm-grep") +(declare-function helm-grep-highlight-match "helm-grep") +(declare-function helm-comp-read "helm-mode") + +(defvar helm-current-error) + +;;; Internals +;; +(defvar helm-source-occur nil + "This will be the name of the source related to `current-buffer'. +Don't use it as it value changes always.") +(defvar helm-source-moccur nil + "This is just a flag to add to `helm-sources-using-default-as-input'. +Don't set it to any value, it will have no effect.") +(defvar helm-occur--buffer-list nil) +(defvar helm-occur--buffer-tick nil) +(defvar helm-occur-history nil) +(defvar helm-occur--search-buffer-regexp "\\`\\([0-9]*\\)\\s-\\{1\\}\\(.*\\)\\'" + "The regexp matching candidates in helm-occur candidate buffer.") +(defvar helm-occur-mode--last-pattern nil) +(defvar helm-occur--initial-pos 0) + +(defvar helm-occur-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map helm-map) + (define-key map (kbd "C-c o") 'helm-occur-run-goto-line-ow) + (define-key map (kbd "C-c C-o") 'helm-occur-run-goto-line-of) + (define-key map (kbd "C-x C-s") 'helm-occur-run-save-buffer) + map) + "Keymap used in occur source.") + +(defgroup helm-occur nil + "Regexp related Applications and libraries for Helm." + :group 'helm) + +(defcustom helm-occur-actions + '(("Go to Line" . helm-occur-goto-line) + ("Goto line other window (C-u vertically)" . helm-occur-goto-line-ow) + ("Goto line new frame" . helm-occur-goto-line-of) + ("Save buffer" . helm-occur-save-results) + ) + "Actions for helm-occur." + :type '(alist :key-type string :value-type function)) + +(defcustom helm-occur-use-ioccur-style-keys nil + "Similar to `helm-grep-use-ioccur-style-keys' but for multi occur. + +Note that if you define this variable with `setq' your change will +have no effect, use customize instead." + :type 'boolean + :set (lambda (var val) + (set var val) + (if val + (progn + (define-key helm-occur-map (kbd "") 'helm-occur-right) + (define-key helm-occur-map (kbd "") 'helm-occur-run-default-action)) + (define-key helm-occur-map (kbd "") nil) + (define-key helm-occur-map (kbd "") nil)))) + +(defcustom helm-occur-always-search-in-current nil + "Helm multi occur always search in current buffer when non--nil." + :type 'boolean) + +(defcustom helm-occur-truncate-lines t + "Truncate lines in occur buffer when non nil." + :type 'boolean) + +(defcustom helm-occur-auto-update-on-resume nil + "Allow auto updating helm-occur buffer when outdated. +noask => Always update without asking +nil => Don't update but signal buffer needs update +never => Never update and do not signal buffer needs update +Any other non--nil value update after confirmation." + :type '(radio :tag "Allow auto updating helm-occur buffer when outdated." + (const :tag "Always update without asking" noask) + (const :tag "Never update and do not signal buffer needs update" never) + (const :tag "Don't update but signal buffer needs update" nil) + (const :tag "Update after confirmation" t))) + +(defcustom helm-occur-candidate-number-limit 99999 + "Value of `helm-candidate-number-limit' for helm-occur." + :type 'integer) + +(defcustom helm-occur-buffer-substring-fn-for-modes + '((mu4e-headers-mode . buffer-substring)) + "Function used to display buffer contents per major-mode. + +Use this to display lines with their text properties in helm-occur +buffer. Can be one of `buffer-substring' or `buffer-substring-no-properties'. +See `helm-occur-buffer-substring-default-mode' to setup this globally. + +Note that when using `buffer-substring' initialization will be slower." + :type '(alist :key-type (symbol :tag "Mode") + :value-type (radio (const :tag "With text properties" + buffer-substring) + (const :tag "Without text properties" + buffer-substring-no-properties)))) + +(defcustom helm-occur-buffer-substring-default-mode + 'buffer-substring-no-properties + "Function used to display buffer contents in helm-occur buffer. + +Default mode for major modes not defined in +`helm-occur-buffer-substring-fn-for-modes'. +Can be one of `buffer-substring' or `buffer-substring-no-properties'. + +Note that when using `buffer-substring' initialization will be +slower. If buffer-substring, all buffers with the modes not +defined in helm-occur-buffer-substring-fn-for-modes will be +displayed with colors and properties in the helm-occur buffer" + :type '(radio + (const :tag "With text properties" buffer-substring) + (const :tag "Without text properties" buffer-substring-no-properties))) + +(defcustom helm-occur-keep-closest-position t + "When non nil select closest candidate from point after update. +This happen only in `helm-source-occur' which is always related to +`current-buffer'." + :type 'boolean) + +(defcustom helm-occur-ignore-diacritics nil + "When non nil helm-occur will ignore diacritics in patterns." + :type 'boolean) + +(defcustom helm-occur-match-shorthands nil + "Transform pattern according to `read-symbol-shorthands' when non nil." + :type 'boolean) + +(defface helm-moccur-buffer + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "DarkTurquoise" :underline t)) + "Face used to highlight occur buffer names.") + +(defface helm-resume-need-update + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "red")) + "Face used to flash occur buffer when it needs update.") + + +(defun helm-occur--select-closest-candidate () + ;; Prevent error with `with-helm-window' when switching to help. + (unless (or (not (get-buffer-window helm-buffer 'visible)) + (string-equal helm-pattern "")) + (with-helm-window + (let ((lst '()) + (name (helm-get-attr 'name helm-source-occur)) + closest beg end) + (while-no-input + (goto-char (point-min)) + (if (string= name "Helm occur") + (setq beg (point) + end (point-max)) + (helm-awhile (helm-get-next-header-pos) + (when (string= name (buffer-substring-no-properties + (point-at-bol) (point-at-eol))) + (forward-line 1) + (setq beg (point) + end (or (helm-get-next-header-pos) (point-max))) + (cl-return)))) + (save-excursion + (when (and beg end) + (goto-char beg) + (while (re-search-forward "^[0-9]+" end t) + (push (string-to-number (match-string 0)) lst)) + (setq closest (helm-closest-number-in-list + helm-occur--initial-pos lst)))) + (when (and closest (re-search-forward (format "^%s" closest) end t)) + (helm-mark-current-line) + (goto-char (overlay-start + helm-selection-overlay)))))))) + +;;;###autoload +(defun helm-occur () + "Preconfigured helm for searching lines matching pattern in `current-buffer'. + +When `helm-source-occur' is member of +`helm-sources-using-default-as-input' which is the default, +symbol at point is searched at startup. + +When a region is marked search only in this region by narrowing. + +To search in multiples buffers start from one of the commands listing +buffers (i.e. a helm command using `helm-source-buffers-list' like +`helm-mini') and use the multi occur buffers action. + +This is the helm implementation that collect lines matching pattern +like vanilla Emacs `occur' but have nothing to do with it, the search +engine beeing completely different and also much faster." + (interactive) + (setq helm-source-occur + (car (helm-occur-build-sources (list (current-buffer)) "Helm occur"))) + (helm-set-local-variable 'helm-occur--buffer-list (list (current-buffer)) + 'helm-occur--buffer-tick + (list (buffer-chars-modified-tick (current-buffer)))) + (helm-set-attr 'header-name (lambda (_name) + (format "HO [%s]" + (buffer-name helm-current-buffer))) + helm-source-occur) + (when helm-occur-keep-closest-position + (setq helm-occur--initial-pos (line-number-at-pos)) + (add-hook 'helm-after-update-hook 'helm-occur--select-closest-candidate)) + (save-restriction + (let ((helm-sources-using-default-as-input + (unless (> (buffer-size) 2000000) + helm-sources-using-default-as-input)) + def pos) + (when (use-region-p) + ;; When user mark defun with `mark-defun' with intention of + ;; using helm-occur on this region, it is relevant to use the + ;; thing-at-point located at previous position which have been + ;; pushed to `mark-ring', if it's within the active region. + (let ((beg (region-beginning)) + (end (region-end)) + (prev-pos (car mark-ring))) + (when (and prev-pos (>= prev-pos beg) (< prev-pos end)) + (setq def (save-excursion + (goto-char (setq pos prev-pos)) + (helm-aif (thing-at-point 'symbol) (regexp-quote it))))) + (narrow-to-region beg end))) + (unwind-protect + (helm :sources 'helm-source-occur + :buffer "*helm occur*" + :history 'helm-occur-history + :default (or def (helm-aif (thing-at-point 'symbol) + (regexp-quote it))) + :preselect (and (memq 'helm-source-occur + helm-sources-using-default-as-input) + (format "^%d:" (line-number-at-pos + (or pos (point))))) + :truncate-lines helm-occur-truncate-lines) + (deactivate-mark t) + (remove-hook 'helm-after-update-hook 'helm-occur--select-closest-candidate))))) + +;;;###autoload +(defun helm-occur-visible-buffers () + "Run helm-occur on all visible buffers in frame." + (interactive) + (require 'helm-buffers) + (if (or (one-window-p) (region-active-p)) + (call-interactively #'helm-occur) + (let ((buffers (helm-buffers-get-visible-buffers))) + (helm-multi-occur-1 (mapcar 'get-buffer buffers))))) + +(defun helm-occur-transformer (candidates source) + "Return CANDIDATES prefixed with line number." + (cl-loop with buf = (helm-get-attr 'buffer-name source) + for c in candidates + for disp-linum = (when (string-match helm-occur--search-buffer-regexp c) + (let ((linum (match-string 1 c)) + (disp (match-string 2 c))) + (list + linum + (format "%s:%s" + (propertize + linum 'face 'helm-grep-lineno + 'help-echo (buffer-file-name + (get-buffer buf))) + disp)))) + for linum = (car disp-linum) + for disp = (cadr disp-linum) + when (and disp (not (string= disp ""))) + collect (cons disp (string-to-number linum)))) + +(defvar helm-occur--gshorthands nil) +(defun helm-occur-symbol-shorthands-pattern-transformer (pattern buffer gshorthands) + "Maybe transform PATTERN to its `read-symbol-shorthands' counterpart in BUFFER. + +GSHORTHANDS is the concatenation of all `read-symbol-shorthands' value found in +all buffers i.e. `buffer-list'. +When GSHORTHANDS is nil use PATTERN unmodified." + (if gshorthands + (let* ((lshorthands (buffer-local-value 'read-symbol-shorthands buffer)) + (prefix (cl-loop for (k . v) in gshorthands + if (string-match (concat "\\`" k) pattern) + return k + else + if (string-match (concat "\\`" v) pattern) + return v)) + (lgstr (cdr (or (assoc prefix gshorthands) + (rassoc prefix gshorthands))))) + (if (and lgstr lshorthands) + (concat (car (rassoc lgstr lshorthands)) + (replace-regexp-in-string prefix "" pattern)) + pattern)) + pattern)) + +(defclass helm-moccur-class (helm-source-in-buffer) + ((buffer-name :initarg :buffer-name + :initform nil) + (moccur-buffers :initarg :moccur-buffers + :initform nil) + (find-file-target :initform #'helm-occur-quit-an-find-file-fn))) + +(defun helm-occur-build-sources (buffers &optional source-name) + "Build sources for `helm-occur' for each buffer in BUFFERS list." + (setq helm-occur--gshorthands nil) + (and helm-occur-match-shorthands + (setq helm-occur--gshorthands + (cl-loop for b in (buffer-list) + for rss = (buffer-local-value + 'read-symbol-shorthands + b) + when rss append rss))) + (let (sources) + (dolist (buf buffers) + (let ((bname (buffer-name buf))) + (push (helm-make-source (or source-name bname) + 'helm-moccur-class + :header-name (lambda (name) + (format "HO [%s]" (if (string= name "Helm occur") + bname name))) + :buffer-name bname + :match-part + (lambda (candidate) + ;; The regexp should match what is in candidate buffer, + ;; not what is displayed in helm-buffer e.g. "12 foo" + ;; and not "12:foo". + (when (string-match helm-occur--search-buffer-regexp + candidate) + (match-string 2 candidate))) + :diacritics helm-occur-ignore-diacritics + :search (lambda (pattern) + (when (string-match "\\`\\^\\([^ ]*\\)" pattern) + (setq pattern (concat "^[0-9]* \\{1\\}" (match-string 1 pattern)))) + (condition-case _err + (re-search-forward pattern nil t) + (invalid-regexp nil))) + :pattern-transformer (lambda (pattern) + (helm-occur-symbol-shorthands-pattern-transformer + pattern buf helm-occur--gshorthands)) + :init (lambda () + (with-current-buffer buf + (let* ((bsfn (or (cdr (assq + major-mode + helm-occur-buffer-substring-fn-for-modes)) + helm-occur-buffer-substring-default-mode)) + (contents (funcall bsfn (point-min) (point-max)))) + (helm-set-attr 'get-line bsfn) + (with-current-buffer (helm-candidate-buffer 'global) + (insert contents) + (goto-char (point-min)) + (let ((linum 1)) + (insert (format "%s " linum)) + (while (re-search-forward "\n" nil t) + (cl-incf linum) + (insert (format "%s " linum)))))))) + :filtered-candidate-transformer 'helm-occur-transformer + :help-message 'helm-moccur-help-message + :nomark t + :migemo t + ;; Needed for resume. + :history 'helm-occur-history + :candidate-number-limit helm-occur-candidate-number-limit + :action 'helm-occur-actions + :requires-pattern 2 + :follow 1 + :group 'helm-occur + :keymap helm-occur-map + :resume 'helm-occur-resume-fn + :moccur-buffers buffers) + sources))) + (nreverse sources))) + +(defun helm-multi-occur-1 (buffers &optional input) + "Run `helm-occur' on a list of buffers. +Each buffer's result is displayed in a separated source." + (let* ((curbuf (current-buffer)) + (bufs (if helm-occur-always-search-in-current + (cons curbuf (remove curbuf buffers)) + buffers)) + (helm-sources-using-default-as-input + (unless (cl-loop with total_size = 0 + for b in bufs + do (setq total_size (buffer-size b)) + finally return (> total_size 2000000)) + helm-sources-using-default-as-input)) + (sources (helm-occur-build-sources bufs (and (eql curbuf (car bufs)) + (not (cdr bufs)) + "Helm occur"))) + (helm-maybe-use-default-as-input + (not (null (memq 'helm-source-moccur + helm-sources-using-default-as-input))))) + (helm-set-local-variable 'helm-occur--buffer-list bufs + 'helm-occur--buffer-tick + (cl-loop for b in bufs collect + (buffer-chars-modified-tick + (get-buffer b)))) + (when (and helm-occur-always-search-in-current + helm-occur-keep-closest-position) + (setq helm-source-occur + (cl-loop for s in sources + when (eql helm-current-buffer + (get-buffer (helm-get-attr 'buffer-name s))) + return s)) + (setq helm-occur--initial-pos (line-number-at-pos)) + (add-hook 'helm-after-update-hook 'helm-occur--select-closest-candidate)) + (unwind-protect + (helm :sources sources + :buffer "*helm moccur*" + :history 'helm-occur-history + :default (helm-aif (thing-at-point 'symbol) + (regexp-quote it)) + :input input + :truncate-lines helm-occur-truncate-lines) + (remove-hook 'helm-after-update-hook 'helm-occur--select-closest-candidate)))) + +;;; Actions +;; +(cl-defun helm-occur-action (lineno + &optional (method (quote buffer))) + "Jump to line number LINENO with METHOD. +METHOD can be one of buffer, buffer-other-window, buffer-other-frame." + (require 'helm-grep) + (let ((buf (if (eq major-mode 'helm-occur-mode) + (get-text-property (point) 'buffer-name) + (helm-get-attr 'buffer-name))) + (split-pat (helm-mm-split-pattern helm-input))) + (cl-case method + (buffer (switch-to-buffer buf)) + (buffer-other-window (helm-window-show-buffers (list buf) t)) + (buffer-other-frame (switch-to-buffer-other-frame buf))) + (with-current-buffer buf + (helm-goto-line lineno) + ;; Move point to the nearest matching regexp from bol. + (cl-loop for str in split-pat + for reg = (helm-occur-symbol-shorthands-pattern-transformer + str (get-buffer buf) helm-occur--gshorthands) + when (save-excursion + (condition-case _err + (if helm-migemo-mode + (helm-mm-migemo-forward reg (point-at-eol) t) + (re-search-forward reg (point-at-eol) t)) + (invalid-regexp nil))) + collect (match-beginning 0) into pos-ls + finally (when pos-ls (goto-char (apply #'min pos-ls))))))) + +(defun helm-occur-goto-line (candidate) + "From multi occur, switch to buffer and CANDIDATE line." + (helm-occur-action + candidate 'buffer)) + +(defun helm-occur-goto-line-ow (candidate) + "Go to CANDIDATE line in other window. +Same as `helm-occur-goto-line' but go in other window." + (helm-occur-action + candidate 'buffer-other-window)) + +(defun helm-occur-goto-line-of (candidate) + "Go to CANDIDATE line in new frame. +Same as `helm-occur-goto-line' but go in new frame." + (helm-occur-action + candidate 'buffer-other-frame)) + +(helm-make-command-from-action helm-occur-run-goto-line-ow + "Run goto line other window action from `helm-occur'." + 'helm-occur-goto-line-ow) + +(helm-make-command-from-action helm-occur-run-goto-line-of + "Run goto line new frame action from `helm-occur'." + 'helm-occur-goto-line-of) + +(helm-make-command-from-action helm-occur-run-default-action + "Goto matching line from helm-occur buffer." + 'helm-occur-goto-line) + +(helm-make-command-from-action helm-occur-run-save-buffer + "Run moccur save results action from `helm-moccur'." + 'helm-occur-save-results) + +(defun helm-occur-right () + "`helm-occur' action for right arrow. +This is used when `helm-occur-use-ioccur-style-keys' is enabled. +If follow is enabled (default) go to next source, otherwise execute +persistent action." + (interactive) + (if (helm-aand (helm-get-attr 'follow) (> it 0)) + (helm-next-source) + (helm-execute-persistent-action))) +(put 'helm-occur-right 'helm-only t) + +(defun helm-occur-quit-an-find-file-fn (source) + (let* ((sel (helm-get-selection nil nil source)) + (occur-fname (helm-aand (numberp sel) + (helm-get-attr 'buffer-name) + (buffer-file-name (get-buffer it))))) + (when (and occur-fname (file-exists-p occur-fname)) + (expand-file-name occur-fname)))) + +;;; helm-occur-mode +;; +;; +(defvar helm-occur-mode-map + (let ((map (make-sparse-keymap))) + (define-key map (kbd "RET") 'helm-occur-mode-goto-line) + (define-key map (kbd "C-o") 'helm-occur-mode-goto-line-ow) + (define-key map (kbd "") 'helm-occur-mode-goto-line-ow-forward) + (define-key map (kbd "") 'helm-occur-mode-goto-line-ow-backward) + (define-key map (kbd "") 'helm-gm-next-file) + (define-key map (kbd "") 'helm-gm-precedent-file) + (define-key map (kbd "M-n") 'helm-occur-mode-goto-line-ow-forward) + (define-key map (kbd "M-p") 'helm-occur-mode-goto-line-ow-backward) + (define-key map (kbd "M-N") 'helm-gm-next-file) + (define-key map (kbd "M-P") 'helm-gm-precedent-file) + (define-key map (kbd "C-c b") 'helm-occur-mode-resume-session) + map)) + +(defun helm-occur-mode-goto-line () + (interactive) + (setq next-error-last-buffer (current-buffer)) + (setq-local helm-current-error (point-marker)) + (helm-aif (get-text-property (point) 'helm-realvalue) + (progn (helm-occur-goto-line it) (helm-match-line-cleanup-pulse)))) + +(defun helm-occur-mode-goto-line-ow () + (interactive) + (setq next-error-last-buffer (current-buffer)) + (setq-local helm-current-error (point-marker)) + (helm-aif (get-text-property (point) 'helm-realvalue) + (progn (helm-occur-goto-line-ow it) (helm-match-line-cleanup-pulse)))) + +(defun helm-occur-mode-goto-line-ow-forward-1 (arg) + (condition-case nil + (progn + (when (or (eq last-command 'helm-occur-mode-goto-line-ow-forward) + (eq last-command 'helm-occur-mode-goto-line-ow-backward)) + (forward-line arg)) + (save-selected-window + (helm-occur-mode-goto-line-ow) + (recenter))) + (error nil))) + +(defun helm-occur-mode-goto-line-ow-forward (arg) + (interactive "p") + (helm-occur-mode-goto-line-ow-forward-1 arg)) + +(defun helm-occur-mode-goto-line-ow-backward (arg) + (interactive "p") + (helm-occur-mode-goto-line-ow-forward-1 (- arg))) + +(defun helm-occur-save-results (_candidate) + "Save helm moccur results in a `helm-moccur-mode' buffer." + (let ((buf "*hmoccur*") + new-buf) + (when (get-buffer buf) + (setq new-buf (helm-read-string "OccurBufferName: " buf)) + (cl-loop for b in (helm-buffer-list) + when (and (string= new-buf b) + (not (y-or-n-p + (format "Buffer `%s' already exists overwrite? " + new-buf)))) + do (setq new-buf (helm-read-string + "OccurBufferName: " "*hmoccur "))) + (setq buf new-buf)) + (with-current-buffer (get-buffer-create buf) + (kill-all-local-variables) + (setq buffer-read-only t) + (buffer-disable-undo) + (let ((inhibit-read-only t) + (map (make-sparse-keymap)) + buf-name) + (erase-buffer) + (insert "-*- mode: helm-occur -*-\n\n" + (format "Occur Results for `%s':\n\n" helm-input)) + (save-excursion + (insert (with-current-buffer helm-buffer + (goto-char (point-min)) + (forward-line 1) + (buffer-substring (point) (point-max))))) + (save-excursion + (forward-line -2) + (while (not (eobp)) + (if (helm-pos-header-line-p) + (let ((beg (point-at-bol)) + (end (point-at-eol))) + (set-text-properties beg (1+ end) nil) + (delete-region (1- beg) end)) + (helm-aif (setq buf-name (assoc-default + 'buffer-name + (get-text-property (point) 'helm-cur-source))) + (progn + (insert (propertize (concat it ":") + 'face 'helm-moccur-buffer + 'helm-realvalue (get-text-property (point) 'helm-realvalue))) + (add-text-properties + (point-at-bol) (point-at-eol) + `(buffer-name ,buf-name)) + (add-text-properties + (point-at-bol) (point-at-eol) + `(keymap ,map + help-echo ,(concat + (buffer-file-name + (get-buffer buf-name)) + "\nmouse-1: set point\nmouse-2: jump to selection") + mouse-face highlight + invisible nil)) + (define-key map [mouse-1] 'mouse-set-point) + (define-key map [mouse-2] 'helm-occur-mode-mouse-goto-line) + (define-key map [mouse-3] 'ignore)))) + (forward-line 1)))) + (buffer-enable-undo) + (helm-occur-mode)) + (pop-to-buffer buf) + (setq next-error-last-buffer (get-buffer buf)) + (message "Helm occur Results saved in `%s' buffer" buf))) + +(defun helm-occur-mode-mouse-goto-line (event) + (interactive "e") + (let* ((window (posn-window (event-end event))) + (pos (posn-point (event-end event)))) + (with-selected-window window + (when (eq major-mode 'helm-occur-mode) + (goto-char pos) + (helm-occur-mode-goto-line))))) +(put 'helm-moccur-mode-mouse-goto-line 'helm-only t) + +(defun helm-occur-mode-resume-session () + (interactive) + (cl-assert (eq major-mode 'helm-occur-mode) nil "Helm command called in wrong context") + (helm-multi-occur-1 helm-occur--buffer-list helm-occur-mode--last-pattern)) + +(defun helm-occur-buffer-substring-with-linums () + "Return current-buffer contents as a string with all lines +numbered. The property \\='buffer-name is added to the whole string." + (let ((bufstr (buffer-substring-no-properties (point-min) (point-max))) + (bufname (buffer-name))) + (with-temp-buffer + (save-excursion + (insert bufstr)) + (let ((linum 1)) + (insert (format "%s " linum)) + (while (re-search-forward "\n" nil t) + (cl-incf linum) + (insert (format "%s " linum))) + (add-text-properties (point-min) (point-max) `(buffer-name ,bufname))) + (buffer-string)))) + +(defun helm-occur-mode--revert-buffer-function (&optional _ignore-auto _noconfirm) + "The `revert-buffer-function' for `helm-occur-mode'." + (goto-char (point-min)) + (let (pattern) + (when (re-search-forward "^Occur Results for `\\(.*\\)'" nil t) + (setq pattern (match-string 1)) + (forward-line 0) + (when (re-search-forward "^$" nil t) + (forward-line 1)) + (let ((inhibit-read-only t) + (buffer (current-buffer)) + (buflst helm-occur--buffer-list)) + (delete-region (point) (point-max)) + (message "Reverting buffer...") + (save-excursion + (with-temp-buffer + (insert + "\n" + (cl-loop for buf in buflst + for bufstr = (or (and (buffer-live-p (get-buffer buf)) + (with-current-buffer buf + (helm-occur-buffer-substring-with-linums))) + "") + concat bufstr) + "\n") + (goto-char (point-min)) + (cl-loop with linum + with mpart + ;; Bind helm-pattern used by `helm-grep-split-line'. + with helm-pattern = pattern + while (helm-mm-search pattern) ; point is at eol. + ;; Calculate line number (linum) and extract real + ;; part of line (mpart). + do (when (save-excursion + ;; `helm-mm-search' puts point at eol. + (forward-line 0) + (re-search-forward "^\\([0-9]*\\)\\s-\\{1\\}\\(.*\\)$" + (point-at-eol) t)) + (setq linum (string-to-number (match-string 1)) + mpart (match-string 2))) + ;; Match part after line number. + when (and mpart (helm-mm-match mpart pattern)) + for line = (format "%s:%d:%s" + (get-text-property (point) 'buffer-name) + linum + mpart) + when line + do (with-current-buffer buffer + (insert + (propertize + (car (helm-occur-filter-one-by-one line)) + 'helm-realvalue linum) + "\n")))) + (when (fboundp 'wgrep-cleanup-overlays) + (wgrep-cleanup-overlays (point-min) (point-max))) + (message "Reverting buffer done") + (when executing-kbd-macro (sit-for 1))))))) + +(defun helm-occur-filter-one-by-one (candidate) + "`filter-one-by-one' function for `helm-source-moccur'." + (require 'helm-grep) + (let* ((split (helm-grep-split-line candidate)) + (buf (car split)) + (lineno (nth 1 split)) + (str (nth 2 split))) + (cons (concat (propertize + buf + 'face 'helm-moccur-buffer + 'help-echo (buffer-file-name + (get-buffer buf)) + 'buffer-name buf) + ":" + (propertize lineno 'face 'helm-grep-lineno) + ":" + (helm-grep-highlight-match str)) + candidate))) + +(define-derived-mode helm-occur-mode + special-mode "helm-moccur" + "Major mode to provide actions in helm moccur saved buffer. + +Special commands: +\\{helm-occur-mode-map}" + (set (make-local-variable 'helm-occur--buffer-list) + (with-helm-buffer helm-occur--buffer-list)) + (set (make-local-variable 'revert-buffer-function) + #'helm-occur-mode--revert-buffer-function) + (set (make-local-variable 'helm-occur-mode--last-pattern) + helm-input) + (set (make-local-variable 'next-error-function) + #'helm-occur-next-error) + (set (make-local-variable 'helm-current-error) nil)) +(put 'helm-moccur-mode 'helm-only t) + +(defun helm-occur-next-error (&optional argp reset) + "Goto ARGP position from a `helm-occur-mode' buffer. +RESET non-nil means rewind to the first match. +This is the `next-error-function' for `helm-occur-mode'." + (interactive "p") + (goto-char (cond (reset (point-min)) + ((and (< argp 0) helm-current-error) + (line-beginning-position)) + ((and (> argp 0) helm-current-error) + (line-end-position)) + ((point)))) + (let ((fun (if (> argp 0) + #'next-single-property-change + #'previous-single-property-change))) + (helm-aif (funcall fun (point) 'buffer-name) + (progn + (goto-char it) + (forward-line 0) + ;; `helm-current-error' is set in + ;; `helm-occur-mode-goto-line'. + (helm-occur-mode-goto-line)) + (user-error "No more matches")))) + +;;; Resume +;; +(defun helm-occur-resume-fn () + (with-helm-buffer + (let (new-tick-ls buffer-is-modified) + (set (make-local-variable 'helm-occur--buffer-list) + (cl-loop for b in helm-occur--buffer-list + when (buffer-live-p (get-buffer b)) + collect b)) + (setq buffer-is-modified (/= (length helm-occur--buffer-list) + (length (helm-get-attr 'moccur-buffers)))) + (helm-set-attr 'moccur-buffers helm-occur--buffer-list) + (setq new-tick-ls (cl-loop for b in helm-occur--buffer-list + collect (buffer-chars-modified-tick + (get-buffer b)))) + (when buffer-is-modified + (setq helm-occur--buffer-tick new-tick-ls)) + (cl-assert (> (length helm-occur--buffer-list) 0) nil + "helm-resume error: helm-(m)occur buffer list is empty") + (unless (eq helm-occur-auto-update-on-resume 'never) + (when (or buffer-is-modified + (cl-loop for b in helm-occur--buffer-list + for new-tick = (buffer-chars-modified-tick + (get-buffer b)) + for tick in helm-occur--buffer-tick + thereis (/= tick new-tick))) + (helm-aif helm-occur-auto-update-on-resume + (when (or (eq it 'noask) + (y-or-n-p "Helm (m)occur Buffer outdated, update? ")) + (run-with-idle-timer + 0.1 nil (lambda () + (with-helm-buffer + (helm-force-update) + (message "Helm (m)occur Buffer have been udated") + (sit-for 1) (message nil)))) + (unless buffer-is-modified (setq helm-occur--buffer-tick + new-tick-ls))) + (run-with-idle-timer + 0.1 nil + (lambda () + (with-helm-buffer + (let ((ov (make-overlay (save-excursion + (goto-char (point-min)) + (forward-line 1) + (point)) + (point-max)))) + (overlay-put ov 'face 'helm-resume-need-update) + (sit-for 0) + (delete-overlay ov) + (message "[Helm occur Buffer outdated (C-c C-u to update)]"))))) + (unless buffer-is-modified + (with-helm-after-update-hook + (setq helm-occur--buffer-tick new-tick-ls) + (message "Helm (m)occur Buffer have been udated"))))))))) + +;;; Helm occur from isearch +;; +;;;###autoload +(defun helm-occur-from-isearch () + "Invoke `helm-occur' from isearch. + +To use this bind it to a key in `isearch-mode-map'." + (interactive) + (let ((input (if isearch-regexp + isearch-string + (regexp-quote isearch-string))) + (bufs (list (current-buffer))) + ;; Use `helm-occur-always-search-in-current' as a flag for + ;; `helm-occur--select-closest-candidate'. + (helm-occur-always-search-in-current t)) + (isearch-exit) + (helm-multi-occur-1 bufs input))) + +;;;###autoload +(defun helm-multi-occur-from-isearch () + "Invoke `helm-multi-occur' from isearch. + +With a prefix arg, reverse the behavior of +`helm-moccur-always-search-in-current'. +The prefix arg can be set before calling +`helm-multi-occur-from-isearch' or during the buffer selection. + +To use this bind it to a key in `isearch-mode-map'." + (interactive) + (let (buf-list + helm-moccur-always-search-in-current + (input (if isearch-regexp + isearch-string + (regexp-quote isearch-string)))) + (isearch-exit) + (setq buf-list (mapcar 'get-buffer + (helm-comp-read "Buffers: " + (helm-buffer-list) + :name "Occur in buffer(s)" + :marked-candidates t))) + (setq helm-moccur-always-search-in-current + (if (or current-prefix-arg + helm-current-prefix-arg) + (not helm-moccur-always-search-in-current) + helm-moccur-always-search-in-current)) + (helm-multi-occur-1 buf-list input))) + +(provide 'helm-occur) + +;;; helm-occur.el ends here diff --git a/org/elpa/helm-20230406.839/helm-pkg.el b/org/elpa/helm-20230406.839/helm-pkg.el new file mode 100644 index 0000000..bc0fd39 --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-pkg.el @@ -0,0 +1,11 @@ +(define-package "helm" "20230406.839" "Helm is an Emacs incremental and narrowing framework" + '((helm-core "3.9.0") + (popup "0.5.3")) + :commit "5c9d28da67d3f42fd27c7f7fcf0701b899fbaa8a" :authors + '(("Thierry Volpiatto" . "thievol@posteo.net")) + :maintainer + '("Thierry Volpiatto" . "thievol@posteo.net") + :url "https://emacs-helm.github.io/helm/") +;; Local Variables: +;; no-byte-compile: t +;; End: diff --git a/org/elpa/helm-20230406.839/helm-regexp.el b/org/elpa/helm-20230406.839/helm-regexp.el new file mode 100644 index 0000000..73f0021 --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-regexp.el @@ -0,0 +1,132 @@ +;;; helm-regexp.el --- In buffer regexp searching and replacement for helm. -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2023 Thierry Volpiatto + +;; 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 . + +;;; Code: + +(require 'cl-lib) +(require 'helm) +(require 'helm-help) +(require 'helm-utils) + +(declare-function helm-mm-split-pattern "helm-multi-match") + + +(defgroup helm-regexp nil + "Regexp related Applications and libraries for Helm." + :group 'helm) + + + +;; History vars +(defvar helm-build-regexp-history nil) + +(defun helm-query-replace-regexp (_candidate) + "Query replace regexp from `helm-regexp'. +With a prefix arg replace only matches surrounded by word boundaries, +i.e. don't replace inside a word, regexp is surrounded with \\bregexp\\b." + (let ((regexp helm-input)) + (apply 'query-replace-regexp + (helm-query-replace-args regexp)))) + +(defun helm-kill-regexp-as-sexp (_candidate) + "Kill regexp in a format usable in lisp code." + (helm-regexp-kill-new + (prin1-to-string helm-input))) + +(defun helm-kill-regexp (_candidate) + "Kill regexp as it is in `helm-pattern'." + (helm-regexp-kill-new helm-input)) + +(defun helm-query-replace-args (regexp) + "Create arguments of `query-replace-regexp' action in `helm-regexp'." + (let ((region-only (helm-region-active-p))) + (list + regexp + (query-replace-read-to regexp + (format "Query replace %sregexp %s" + (if helm-current-prefix-arg "word " "") + (if region-only "in region " "")) + t) + helm-current-prefix-arg + (when region-only (region-beginning)) + (when region-only (region-end))))) + +(defvar helm-source-regexp + (helm-build-in-buffer-source "Regexp Builder" + :init (lambda () + (helm-init-candidates-in-buffer + 'global (with-temp-buffer + (insert-buffer-substring helm-current-buffer) + (buffer-string)))) + :get-line #'helm-regexp-get-line + :persistent-action #'helm-regexp-persistent-action + :persistent-help "Show this line" + :multiline t + :multimatch nil + :requires-pattern 2 + :group 'helm-regexp + :mode-line "Press TAB to select action." + :action '(("Kill Regexp as sexp" . helm-kill-regexp-as-sexp) + ("Query Replace Regexp (C-u Not inside word.)" + . helm-query-replace-regexp) + ("Kill Regexp" . helm-kill-regexp)))) + +(defun helm-regexp-get-line (s e) + (let ((matches (match-data)) + (line (buffer-substring s e))) + (propertize + (cl-loop with ln = (format "%5d: %s" (1- (line-number-at-pos s)) line) + for i from 0 to (1- (/ (length matches) 2)) + if (match-string i) + concat (format "\n%s%s'%s'" + (make-string 10 ? ) (format "Group %d: " i) it) + into ln1 + finally return (concat ln ln1)) + 'helm-realvalue s))) + +(defun helm-regexp-persistent-action (pt) + (helm-goto-char pt) + (helm-highlight-current-line)) + +(defun helm-regexp-kill-new (input) + (kill-new (substring-no-properties input)) + (message "Killed: %s" input)) + + +;;; Predefined commands +;; +;; + +;;;###autoload +(defun helm-regexp () + "Preconfigured helm to build regexps. +`query-replace-regexp' can be run from there against found regexp." + (interactive) + (save-restriction + (when (and (helm-region-active-p) + ;; Don't narrow to region if buffer is already narrowed. + (not (helm-current-buffer-narrowed-p (current-buffer)))) + (narrow-to-region (region-beginning) (region-end))) + (helm :sources helm-source-regexp + :buffer "*helm regexp*" + :prompt "Regexp: " + :history 'helm-build-regexp-history))) + + +(provide 'helm-regexp) + +;;; helm-regexp.el ends here diff --git a/org/elpa/helm-20230406.839/helm-ring.el b/org/elpa/helm-20230406.839/helm-ring.el new file mode 100644 index 0000000..1d3a130 --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-ring.el @@ -0,0 +1,593 @@ +;;; helm-ring.el --- kill-ring, mark-ring, and register browsers for helm. -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2023 Thierry Volpiatto + +;; 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 . + +;;; Code: + +(require 'cl-lib) +(require 'helm) +(require 'helm-utils) +(require 'helm-help) +(require 'helm-elisp) + +(declare-function undo-tree-restore-state-from-register "ext:undo-tree.el" (register)) + + +(defgroup helm-ring nil + "Ring related Applications and libraries for Helm." + :group 'helm) + +(defcustom helm-kill-ring-threshold 3 + "Minimum length of a candidate to be listed by `helm-source-kill-ring'." + :type 'integer + :group 'helm-ring) + +(defcustom helm-kill-ring-max-offset 400 + "Max number of chars displayed per candidate in kill-ring browser. +When `t', don't truncate candidate, show all. +By default it is approximatively the number of bits contained in five lines +of 80 chars each, i.e. 80*5. +Note that if you set this to nil multiline will be disabled, i.e. you +will not have separators between candidates any more." + :type '(choice (const :tag "Disabled" t) + (integer :tag "Max candidate offset")) + :group 'helm-ring) + +(defcustom helm-kill-ring-actions + '(("Yank marked" . helm-kill-ring-action-yank) + ("Delete marked" . helm-kill-ring-action-delete) + ("Search from candidate" . helm-kill-ring-search-from-string)) + "List of actions for kill ring source." + :group 'helm-ring + :type '(alist :key-type string :value-type function)) + +(defcustom helm-kill-ring-separator "\n" + "The separator used to separate marked candidates when yanking." + :group 'helm-ring + :type 'string) + +(defcustom helm-register-max-offset 160 + "Max size of string register entries before truncating." + :group 'helm-ring + :type 'integer) + +;;; Kill ring +;; +;; +(defvar helm-kill-ring-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map helm-map) + (define-key map (kbd "M-y") 'helm-next-line) + (define-key map (kbd "M-u") 'helm-previous-line) + (define-key map (kbd "M-D") 'helm-kill-ring-delete) + (define-key map (kbd "C-s") 'helm-kill-ring-run-search-from-string) + (define-key map (kbd "C-]") 'helm-kill-ring-toggle-truncated) + (define-key map (kbd "C-c C-k") 'helm-kill-ring-kill-selection) + (define-key map (kbd "C-c d") 'helm-kill-ring-run-persistent-delete) + map) + "Keymap for `helm-show-kill-ring'.") + +(defvar helm-source-kill-ring + (helm-build-sync-source "Kill Ring" + :init (lambda () + (helm-set-attr 'last-command last-command) + (helm-set-attr 'multiline helm-kill-ring-max-offset)) + :candidates #'helm-kill-ring-candidates + :filtered-candidate-transformer #'helm-kill-ring-transformer + :action 'helm-kill-ring-actions + :persistent-action 'ignore + :help-message 'helm-kill-ring-help-message + :persistent-help "DoNothing" + :keymap helm-kill-ring-map + :migemo t + :multiline 'helm-kill-ring-max-offset + :group 'helm-ring) + "Source for browse and insert contents of kill-ring.") + +(defun helm-kill-ring-candidates () + (cl-loop with cands = (helm-fast-remove-dups kill-ring :test 'equal) + for kill in (if (eq (helm-get-attr 'last-command) 'yank) + (cdr cands) + cands) + unless (or (< (length kill) helm-kill-ring-threshold) + (string-match "\\`[\n[:blank:]]+\\'" kill)) + collect kill)) + +(defun helm-kill-ring-transformer (candidates _source) + "Ensure CANDIDATES are not read-only." + (cl-loop for i in candidates + when (get-text-property 0 'read-only i) + do (set-text-properties 0 (length i) '(read-only nil) i) + collect i)) + +(defvar helm-kill-ring--truncated-flag nil) +(defun helm-kill-ring-toggle-truncated () + "Toggle truncated view of candidates in helm kill-ring browser." + (interactive) + (with-helm-alive-p + (setq helm-kill-ring--truncated-flag (not helm-kill-ring--truncated-flag)) + (let* ((cur-cand (helm-get-selection)) + (presel-fn (lambda () + (helm-kill-ring--preselect-fn cur-cand)))) + (helm-set-attr 'multiline + (if helm-kill-ring--truncated-flag + 15000000 + helm-kill-ring-max-offset)) + (helm-update presel-fn)))) +(put 'helm-kill-ring-toggle-truncated 'helm-only t) + +(defun helm-kill-ring-kill-selection () + "Store the real value of candidate in kill-ring. +Same as `helm-kill-selection-and-quit' called with a prefix arg." + (interactive) + (helm-kill-selection-and-quit t)) +(put 'helm-kill-ring-kill-selection 'helm-only t) + +(defun helm-kill-ring--preselect-fn (candidate) + "Internal, used to preselect CANDIDATE when toggling truncated view." + ;; Preselection by regexp may not work if candidate is huge, so walk + ;; the helm buffer until selection is on CANDIDATE. + (helm-awhile (condition-case-unless-debug nil + (and (not (helm-pos-header-line-p)) + (helm-get-selection)) + (error nil)) + (if (string= it candidate) + (cl-return) + (helm-next-line)))) + +(defun helm-kill-ring-action-yank (_str) + "Insert concatenated marked candidates in current-buffer. + +When two prefix args are given prompt to choose separator, otherwise +use `helm-kill-ring-separator' as default." + (let ((marked (helm-marked-candidates)) + (sep (if (equal helm-current-prefix-arg '(16)) + (read-string "Separator: ") + helm-kill-ring-separator))) + (helm-kill-ring-action-yank-1 + (cl-loop for c in (butlast marked) + concat (concat c sep) into str + finally return (concat str (car (last marked))))))) + +(defun helm-kill-ring-action-yank-1 (str) + "Insert STR in `kill-ring' and set STR to the head. + +When called with a prefix arg, point and mark are exchanged +without activating region. +If this action is executed just after `yank', replace with STR as +yanked string." + (let ((yank-fn (lambda (&optional before yank-pop) + (insert-for-yank str) + ;; Set the window start back where it was in + ;; the yank command, if possible. + (when yank-pop + (set-window-start (selected-window) yank-window-start t)) + (when (or (equal helm-current-prefix-arg '(4)) before) + ;; Same as exchange-point-and-mark but without + ;; activating region. + (goto-char (prog1 (mark t) + (set-marker (mark-marker) + (point) + helm-current-buffer))))))) + ;; Prevent inserting and saving highlighted items. + (set-text-properties 0 (length str) nil str) + (with-helm-current-buffer + (unwind-protect + (progn + (setq kill-ring (delete str kill-ring)) + ;; Adding a `delete-selection' property + ;; to `helm-kill-ring-action' is not working + ;; because `this-command' will be `helm-maybe-exit-minibuffer', + ;; so use this workaround (Bug#1520). + (when (and (region-active-p) delete-selection-mode) + (delete-region (region-beginning) (region-end))) + (if (not (eq (helm-get-attr 'last-command helm-source-kill-ring) 'yank)) + (progn + ;; Ensure mark is at beginning of inserted text. + (push-mark) + ;; When yanking in a helm minibuffer we need a small + ;; delay to detect the mark in previous minibuffer. [1] + (run-with-timer 0.01 nil yank-fn)) + ;; from `yank-pop' + (let ((inhibit-read-only t) + (before (< (point) (mark t)))) + (if before + (funcall (or yank-undo-function 'delete-region) (point) (mark t)) + (funcall (or yank-undo-function 'delete-region) (mark t) (point))) + (setq yank-undo-function nil) + (set-marker (mark-marker) (point) helm-current-buffer) + ;; Same as [1] but use the same mark and point as in + ;; the initial yank according to BEFORE even if no + ;; prefix arg is given. + (run-with-timer 0.01 nil yank-fn before 'pop)))) + (kill-new str))))) +(define-obsolete-function-alias 'helm-kill-ring-action 'helm-kill-ring-action-yank "2.4.0") + +(defun helm-kill-ring-search-from-string (candidate) + (let ((str (car (split-string candidate "\n")))) + (helm-multi-occur-1 + (list (current-buffer)) + (regexp-quote (substring-no-properties str))))) + +(helm-make-command-from-action helm-kill-ring-run-search-from-string + "Run helm-occur from kill ring." + 'helm-kill-ring-search-from-string) + +(defun helm-kill-ring-action-delete (_candidate) + "Delete marked candidates from `kill-ring'." + (cl-loop for c in (helm-marked-candidates) + do (setq kill-ring + (delete c kill-ring)))) + +(defun helm-kill-ring-persistent-delete (_candidate) + (unwind-protect + (cl-loop for c in (helm-marked-candidates) + do (progn + (helm-preselect (format "^%s" (regexp-quote c))) + (setq kill-ring (delete c kill-ring)) + (helm-delete-current-selection) + (helm--remove-marked-and-update-mode-line c))) + (with-helm-buffer + (setq helm-marked-candidates nil + helm-visible-mark-overlays nil)) + (helm-force-update (helm-aif (helm-get-selection nil t) (regexp-quote it))))) + +(helm-make-persistent-command-from-action helm-kill-ring-run-persistent-delete + "Delete current candidate without quitting." + 'quick-delete 'helm-kill-ring-persistent-delete) + +(helm-make-command-from-action helm-kill-ring-delete + "Delete marked candidates from `kill-ring'." + 'helm-kill-ring-action-delete) + + +;;;; +;; DO NOT use these sources with other sources use +;; the commands `helm-mark-ring', `helm-global-mark-ring' or +;; `helm-all-mark-rings' instead. + +(defun helm-mark-ring-line-string-at-pos (pos) + "Return line string at position POS." + (save-excursion + (goto-char pos) + (forward-line 0) + (let ((line (car (split-string (thing-at-point 'line) "[\n\r]")))) + (remove-text-properties 0 (length line) '(read-only) line) + (if (string= "" line) + "" + line)))) + +(defun helm-mark-ring-get-candidates () + (with-helm-current-buffer + (cl-loop with marks = (if (mark t) + (cons (mark-marker) mark-ring) + mark-ring) + for marker in marks + with max-line-number = (line-number-at-pos (point-max)) + with width = (length (number-to-string max-line-number)) + for m = (format (concat "%" (number-to-string width) "d: %s") + (line-number-at-pos marker) + (helm-mark-ring-line-string-at-pos marker)) + unless (and recip (assoc m recip)) + collect (cons m marker) into recip + finally return recip))) + +(defun helm-mark-ring-default-action (candidate) + (let ((target (copy-marker candidate))) + (helm-aif (marker-buffer candidate) + (progn + (switch-to-buffer it) + (helm-log-run-hook "helm-mark-ring-default-action" 'helm-goto-line-before-hook) + (helm-match-line-cleanup) + (with-helm-current-buffer + (unless helm-yank-point (setq helm-yank-point (point)))) + (helm-goto-char target) + (helm-highlight-current-line)) + ;; marker points to no buffer, no need to dereference it, just + ;; delete it. + (setq mark-ring (delete target mark-ring)) + (error "Marker points to no buffer")))) + +(defvar helm-source-mark-ring + (helm-build-sync-source "mark-ring" + :candidates #'helm-mark-ring-get-candidates + :action '(("Goto line" . helm-mark-ring-default-action)) + :persistent-help "Show this line" + :group 'helm-ring)) + +;;; Global-mark-ring +(defvar helm-source-global-mark-ring + (helm-build-sync-source "global-mark-ring" + :candidates #'helm-global-mark-ring-get-candidates + :action '(("Goto line" . helm-mark-ring-default-action)) + :persistent-help "Show this line" + :group 'helm-ring)) + +(defun helm-global-mark-ring-format-buffer (marker) + (with-current-buffer (marker-buffer marker) + (goto-char marker) + (forward-line 0) + (let ((line (pcase (thing-at-point 'line) + ((and line (pred stringp) + (guard (not (string-match-p "\\`\n?\\'" line)))) + (car (split-string line "[\n\r]"))) + (_ "")))) + (remove-text-properties 0 (length line) '(read-only) line) + (format "%7d:%s: %s" + (line-number-at-pos) (marker-buffer marker) line)))) + +(defun helm-global-mark-ring-get-candidates () + (let ((marks global-mark-ring)) + (when marks + (cl-loop for marker in marks + for mb = (marker-buffer marker) + for gm = (unless (or (string-match "^ " (format "%s" mb)) + (null mb)) + (helm-global-mark-ring-format-buffer marker)) + when (and gm (not (assoc gm recip))) + collect (cons gm marker) into recip + finally return recip)))) + +;;;; +;;; Insert from register +(defvar helm-source-register + (helm-build-sync-source "Registers" + :candidates #'helm-register-candidates + :action-transformer #'helm-register-action-transformer + :persistent-help "" + :multiline t + :action '(("Delete Register(s)" . + (lambda (_candidate) + (cl-loop for candidate in (helm-marked-candidates) + for register = (car candidate) + do (setq register-alist + (delq (assoc register register-alist) + register-alist)))))) + :group 'helm-ring) + "See (info \"(emacs)Registers\")") + +(defun helm-register-candidates () + "Collecting register contents and appropriate commands." + (cl-loop for (char . rval) in register-alist + for key = (single-key-description char) + for e27 = (registerv-p rval) + for val = (if e27 ; emacs-27 + (registerv-data rval) + rval) + for string-actions = + (cond + ((numberp val) + (list (int-to-string val) + 'insert-register + 'increment-register)) + ((markerp val) + (let ((buf (marker-buffer val))) + (if (null buf) + (list "a marker in no buffer") + (list (concat + "a buffer position:" + (buffer-name buf) + ", position " + (int-to-string (marker-position val))) + 'jump-to-register + 'insert-register)))) + ((and (consp val) (window-configuration-p (car val))) + (list "window configuration." + 'jump-to-register)) + ((and (vectorp val) + (fboundp 'undo-tree-register-data-p) + (undo-tree-register-data-p (if e27 val (elt val 1)))) + (list + "Undo-tree entry." + 'undo-tree-restore-state-from-register)) + ((or (and (vectorp val) (eq 'registerv (aref val 0))) + (and (consp val) (frame-configuration-p (car val)))) + (list "frame configuration." + 'jump-to-register)) + ((and (consp val) (eq (car val) 'file)) + (list (concat "file:" + (prin1-to-string (cdr val)) + ".") + 'jump-to-register)) + ((and (consp val) (eq (car val) 'file-query)) + (list (concat "file:a file-query reference: file " + (car (cdr val)) + ", position " + (int-to-string (car (cdr (cdr val)))) + ".") + 'jump-to-register)) + ((consp val) + (let ((lines (format "%4d" (length val)))) + (list (format "%s: %s\n" lines + (truncate-string-to-width + (mapconcat 'identity (list (car val)) + "^J") + (- (window-width) 15))) + 'insert-register))) + ((stringp val) + (list + (concat (substring-no-properties + val 0 (min (length val) helm-register-max-offset)) + (if (> (length val) helm-register-max-offset) + "[...]" "")) + 'insert-register + 'kill-new + 'append-to-register + 'prepend-to-register))) + unless (null string-actions) ; Fix Bug#1107. + collect (cons (format "Register %3s:\n %s" key (car string-actions)) + (cons char (cdr string-actions))))) + +(defun helm-register-action-transformer (actions register-and-functions) + "Decide actions by the contents of register." + (cl-loop with func-actions = + '((insert-register + "Insert Register" . + (lambda (c) (insert-register (car c)))) + (kill-new + "Kill Register" . + (lambda (c) (with-temp-buffer + (insert-register (car c)) + (kill-new (buffer-string))))) + (jump-to-register + "Jump to Register" . + (lambda (c) (jump-to-register (car c)))) + (append-to-register + "Append Region to Register" . + (lambda (c) (append-to-register + (car c) (region-beginning) (region-end)))) + (prepend-to-register + "Prepend Region to Register" . + (lambda (c) (prepend-to-register + (car c) (region-beginning) (region-end)))) + (increment-register + "Increment Prefix Arg to Register" . + (lambda (c) (increment-register + helm-current-prefix-arg (car c)))) + (undo-tree-restore-state-from-register + "Restore Undo-tree register" . + (lambda (c) (and (fboundp 'undo-tree-restore-state-from-register) + (undo-tree-restore-state-from-register (car c)))))) + for func in (cdr register-and-functions) + when (assq func func-actions) + collect (cdr it) into transformer-actions + finally return (append transformer-actions actions))) + +;;;###autoload +(defun helm-mark-ring () + "Preconfigured `helm' for `helm-source-mark-ring'." + (interactive) + (helm :sources 'helm-source-mark-ring + :resume 'noresume + :buffer "*helm mark*")) + +;;;###autoload +(defun helm-global-mark-ring () + "Preconfigured `helm' for `helm-source-global-mark-ring'." + (interactive) + (helm :sources 'helm-source-global-mark-ring + :resume 'noresume + :buffer "*helm global mark*")) + +;;;###autoload +(defun helm-all-mark-rings () + "Preconfigured `helm' for mark rings. +Source used are `helm-source-global-mark-ring' and +`helm-source-mark-ring'." + (interactive) + (helm :sources '(helm-source-mark-ring + helm-source-global-mark-ring) + :resume 'noresume + :buffer "*helm mark ring*")) + +;;;###autoload +(defun helm-register () + "Preconfigured `helm' for Emacs registers." + (interactive) + (helm :sources 'helm-source-register + :resume 'noresume + :buffer "*helm register*")) + +;;;###autoload +(defun helm-show-kill-ring () + "Preconfigured `helm' for `kill-ring'. +It is drop-in replacement of `yank-pop'. + +First call open the kill-ring browser, next calls move to next line." + (interactive) + (setq helm-kill-ring--truncated-flag nil) + (let ((enable-recursive-minibuffers t)) + (helm :sources helm-source-kill-ring + :buffer "*helm kill ring*" + :resume 'noresume + :allow-nest t))) + +;;;###autoload +(defun helm-execute-kmacro () + "Preconfigured helm for keyboard macros. +Define your macros with `f3' and `f4'. +See (info \"(emacs) Keyboard Macros\") for detailed infos. +This command is useful when used with persistent action." + (interactive) + (let ((helm-quit-if-no-candidate + (lambda () (message "No kbd macro has been defined")))) + (helm :sources + (helm-build-sync-source "Kmacro" + :candidates (lambda () + (helm-fast-remove-dups + (cons (kmacro-ring-head) + kmacro-ring) + :test 'equal)) + :multiline t + :candidate-transformer + (lambda (candidates) + (cl-loop for c in candidates collect + (propertize (help-key-description (car c) nil) + 'helm-realvalue c))) + :persistent-help "Execute kmacro" + :help-message 'helm-kmacro-help-message + :action + (helm-make-actions + "Execute kmacro (`C-u ' to execute times)" + 'helm-kbd-macro-execute + "Concat marked macros" + 'helm-kbd-macro-concat-macros + "Delete marked macros" + 'helm-kbd-macro-delete-macro + "Edit marked macro" + 'helm-kbd-macro-edit-macro) + :group 'helm-ring) + :buffer "*helm kmacro*"))) + +(defun helm-kbd-macro-execute (candidate) + ;; Move candidate on top of list for next use. + (setq kmacro-ring (delete candidate kmacro-ring)) + (kmacro-push-ring) + (kmacro-split-ring-element candidate) + (kmacro-exec-ring-item + candidate helm-current-prefix-arg)) + +(defun helm-kbd-macro-concat-macros (_candidate) + (let ((mkd (helm-marked-candidates))) + (when (cdr mkd) + (kmacro-push-ring) + (setq last-kbd-macro + (mapconcat 'identity + (cl-loop for km in mkd + if (vectorp km) + append (cl-loop for k across km collect + (key-description (vector k))) + into result + else collect (car km) into result + finally return result) + ""))))) + +(defun helm-kbd-macro-delete-macro (_candidate) + (let ((mkd (helm-marked-candidates))) + (kmacro-push-ring) + (cl-loop for km in mkd + do (setq kmacro-ring (delete km kmacro-ring))) + (kmacro-pop-ring1))) + +(defun helm-kbd-macro-edit-macro (candidate) + (kmacro-push-ring) + (setq kmacro-ring (delete candidate kmacro-ring)) + (kmacro-split-ring-element candidate) + (kmacro-edit-macro)) + +(provide 'helm-ring) + +;;; helm-ring.el ends here diff --git a/org/elpa/helm-20230406.839/helm-semantic.el b/org/elpa/helm-20230406.839/helm-semantic.el new file mode 100644 index 0000000..d06a7db --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-semantic.el @@ -0,0 +1,233 @@ +;;; helm-semantic.el --- Helm interface for Semantic -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2017 Daniel Hackney +;; 2012 ~ 2023 Thierry Volpiatto + +;; Author: Daniel Hackney + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; Uses `candidates-in-buffer' for speed. + +;;; Code: + +(require 'cl-lib) +(require 'semantic) +(require 'helm-help) +(require 'helm-imenu) + +(declare-function pulse-momentary-highlight-one-line "pulse.el" (point &optional face)) + +(defgroup helm-semantic nil + "Semantic tags related libraries and applications for helm." + :group 'helm) + +(defcustom helm-semantic-display-style + '((python-mode . semantic-format-tag-summarize) + (c-mode . semantic-format-tag-concise-prototype-c-mode) + (emacs-lisp-mode . semantic-format-tag-abbreviate-emacs-lisp-mode)) + "Function to present a semantic tag according to `major-mode'. + +It is an alist where the `car' of each element is a `major-mode' and +the `cdr' a `semantic-format-tag-*' function. + +If no function is found for current `major-mode', fall back to +`semantic-format-tag-summarize' default function. + +You can have more or less informations depending of the `semantic-format-tag-*' +function you choose. + +All the supported functions are prefixed with \"semantic-format-tag-\", +you have completion on these functions with `C-M i' in the customize interface." + :group 'helm-semantic + :type '(alist :key-type symbol :value-type symbol)) + +;;; keymap +(defvar helm-semantic-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map helm-map) + map)) + +(defcustom helm-semantic-lynx-style-map nil + "Use Arrow keys to jump to occurences." + :group 'helm-semantic + :type 'boolean + :set (lambda (var val) + (set var val) + (if val + (progn + (define-key helm-semantic-map (kbd "") 'helm-execute-persistent-action) + (define-key helm-semantic-map (kbd "") 'helm-maybe-exit-minibuffer)) + (define-key helm-semantic-map (kbd "") nil) + (define-key helm-semantic-map (kbd "") nil)))) + +;; Internals vars +(defvar helm-semantic--tags-cache nil) + +(defun helm-semantic--fetch-candidates (tags depth &optional class) + "Write the contents of TAGS to the current buffer." + (let ((class class) cur-type + (stylefn (or (with-helm-current-buffer + (assoc-default major-mode helm-semantic-display-style)) + #'semantic-format-tag-summarize))) + (dolist (tag tags) + (when (listp tag) + (cl-case (setq cur-type (semantic-tag-class tag)) + ((function variable type) + (let ((spaces (make-string (* depth 2) ?\s)) + (type-p (eq cur-type 'type))) + (unless (and (> depth 0) (not type-p)) + (setq class nil)) + (insert + (if (and class (not type-p)) + (format "%s%s(%s) " + spaces (if (< depth 2) "" "├►") class) + spaces) + ;; Save the tag for later + (propertize (funcall stylefn tag nil t) + 'semantic-tag tag) + "\n") + (and type-p (setq class (car tag))) + ;; Recurse to children + (unless (eq cur-type 'function) + (helm-semantic--fetch-candidates + (semantic-tag-components tag) (1+ depth) class)))) + + ;; Don't do anything with packages or includes for now + ((package include) + (insert + (propertize (funcall stylefn tag nil t) + 'semantic-tag tag) + "\n") + ) + ;; Catch-all + (t)))))) + +(defun helm-semantic-default-action (_candidate &optional persistent) + ;; By default, helm doesn't pass on the text properties of the selection. + ;; Fix this. + (helm-log-run-hook "helm-semantic-default-action" + 'helm-goto-line-before-hook) + (with-current-buffer helm-buffer + (when (looking-at " ") + (goto-char (next-single-property-change + (point-at-bol) 'semantic-tag nil (point-at-eol)))) + (let ((tag (get-text-property (point) 'semantic-tag))) + (semantic-go-to-tag tag) + (unless persistent + (pulse-momentary-highlight-one-line (point)))))) + +(defun helm-semantic--maybe-set-needs-update () + (with-helm-current-buffer + (when (semantic-parse-tree-needs-update-p) + (semantic-parse-tree-set-needs-update)))) + +(defvar helm-source-semantic nil) + +(defclass helm-semantic-source (helm-source-in-buffer) + ((init :initform (lambda () + (helm-semantic--maybe-set-needs-update) + (setq helm-semantic--tags-cache (semantic-fetch-tags)) + (with-current-buffer (helm-candidate-buffer 'global) + (let ((major-mode (with-helm-current-buffer major-mode))) + (helm-semantic--fetch-candidates helm-semantic--tags-cache 0))))) + (get-line :initform 'buffer-substring) + (persistent-help :initform "Show this entry") + (keymap :initform 'helm-semantic-map) + (help-message :initform 'helm-semantic-help-message) + (persistent-action :initform (lambda (elm) + (helm-semantic-default-action elm t) + (helm-highlight-current-line))) + (action :initform 'helm-semantic-default-action))) + +(defcustom helm-semantic-fuzzy-match nil + "Enable fuzzy matching in `helm-source-semantic'." + :group 'helm-semantic + :type 'boolean + :set (lambda (var val) + (set var val) + (setq helm-source-semantic + (helm-make-source "Semantic Tags" 'helm-semantic-source + :fuzzy-match helm-semantic-fuzzy-match)))) + +;;;###autoload +(defun helm-semantic (arg) + "Preconfigured `helm' for `semantic'. +If ARG is supplied, pre-select symbol at point instead of current." + (interactive "P") + (let ((tag (helm-aif (car (semantic-current-tag-parent)) + (let ((curtag (car (semantic-current-tag)))) + (if (string= it curtag) + (format "\\_<%s\\_>" curtag) + (cons (format "\\_<%s\\_>" it) + (format "\\_<%s\\_>" curtag)))) + (format "\\_<%s\\_>" (car (semantic-current-tag))))) + (helm-highlight-matches-around-point-max-lines 'never)) + (unless helm-source-semantic + (setq helm-source-semantic + (helm-make-source "Semantic Tags" 'helm-semantic-source + :fuzzy-match helm-semantic-fuzzy-match))) + (helm :sources 'helm-source-semantic + :candidate-number-limit 9999 + :preselect (if arg + (thing-at-point 'symbol) + tag) + :buffer "*helm semantic*"))) + +;;;###autoload +(defun helm-semantic-or-imenu (arg) + "Preconfigured helm for `semantic' or `imenu'. +If ARG is supplied, pre-select symbol at point instead of current +semantic tag in scope. + +If `semantic-mode' is active in the current buffer, then use +semantic for generating tags, otherwise fall back to `imenu'. +Fill in the symbol at point by default." + (interactive "P") + (unless helm-source-semantic + (setq helm-source-semantic + (helm-make-source "Semantic Tags" 'helm-semantic-source + :fuzzy-match helm-semantic-fuzzy-match))) + (unless helm-source-imenu + (setq helm-source-imenu + (helm-make-source "Imenu" 'helm-imenu-source + :fuzzy-match helm-imenu-fuzzy-match))) + (let* ((source (if (semantic-active-p) + 'helm-source-semantic + 'helm-source-imenu)) + (helm-highlight-matches-around-point-max-lines 'never) + (imenu-p (eq source 'helm-source-imenu)) + (imenu-auto-rescan imenu-p) + (str (thing-at-point 'symbol)) + (helm-execute-action-at-once-if-one + (and imenu-p + helm-imenu-execute-action-at-once-if-one)) + (tag (helm-aif (car (semantic-current-tag-parent)) + (let ((curtag (car (semantic-current-tag)))) + (if (string= it curtag) + (format "\\_<%s\\_>" curtag) + (cons (format "\\_<%s\\_>" it) + (format "\\_<%s\\_>" curtag)))) + (format "\\_<%s\\_>" (car (semantic-current-tag)))))) + (helm :sources source + :candidate-number-limit 9999 + :default (and imenu-p (list (concat "\\_<" (and str (regexp-quote str)) "\\_>") str)) + :preselect (if (or arg imenu-p) str tag) + :buffer "*helm semantic/imenu*"))) + +(provide 'helm-semantic) + +;;; helm-semantic.el ends here diff --git a/org/elpa/helm-20230406.839/helm-shell.el b/org/elpa/helm-20230406.839/helm-shell.el new file mode 100644 index 0000000..ce70751 --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-shell.el @@ -0,0 +1,38 @@ +;;; helm-shell.el --- Shell prompt navigation for helm. -*- lexical-binding: t -*- + +;; Copyright (C) 2020 Pierre Neidhardt + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; +;; This is superseded by helm-comint.el. + +;;; Code: +(require 'cl-lib) +(require 'helm) +(require 'helm-lib) +(require 'helm-help) +(require 'helm-elisp) +(require 'helm-comint) + +;;;###autoload +(defalias 'helm-shell-prompts 'helm-comint-prompts) + +;;;###autoload +(defalias 'helm-shell-prompts-all 'helm-comint-prompts-all) + +(provide 'helm-shell) + +;;; helm-shell ends here diff --git a/org/elpa/helm-20230406.839/helm-sys.el b/org/elpa/helm-20230406.839/helm-sys.el new file mode 100644 index 0000000..03bd4ed --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-sys.el @@ -0,0 +1,472 @@ +;;; helm-sys.el --- System related functions for helm. -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2023 Thierry Volpiatto + +;; 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 . + +;;; Code: + +(require 'cl-lib) +(require 'helm) +(require 'helm-help) +(require 'helm-utils) + + +(defgroup helm-sys nil + "System related helm library." + :group 'helm) + +(defface helm-top-columns + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :inherit helm-header)) + "Face for helm help string in minibuffer." + :group 'helm-sys) + + +(defcustom helm-top-command + (cl-case system-type + (darwin "env COLUMNS=%s ps -axo pid,user,pri,nice,ucomm,tty,start_time,vsz,%%cpu,%%mem,etime,command") + (t "env COLUMNS=%s top -b -n 1")) + "Top command used to display output of top. +A format string where %s will be replaced with `frame-width'. + +To use 'top' command, a version supporting batch mode (-b option) +is needed. On Mac OSX 'top' command doesn't support this, so the +'ps' command is used instead by default. + +Normally 'top' command output have 12 columns, but in some +versions you may have less than this, so you can either customize +'top' to use 12 columns with the interactives 'f' and 'W' commands +of 'top', or modify `helm-top-sort-columns-alist' to fit with the +number of columns your 'top' command is using. + +If you modify 'ps' command be sure that 'pid' comes in first and +\"env COLUMNS=%s\" is specified at beginning of command. Ensure +also that no elements contain spaces (e.g., use start_time and +not start). Same as for 'top': you can customize +`helm-top-sort-columns-alist' to make sort commands working +properly according to your settings." + :group 'helm-sys + :type 'string) + +(defcustom helm-top-sort-columns-alist '((com . 11) + (mem . 9) + (cpu . 8) + (user . 1)) + "Allow defining which column to use when sorting output of top/ps command. +Only com, mem, cpu and user are sorted, so no need to put something +else there,it will have no effect. +Note that column numbers are counted from zero, i.e. column 1 is the +nth 0 column." + :group 'helm-sys + :type '(alist :key-type symbol :value-type (integer :tag "Column number"))) + +(defcustom helm-top-poll-delay 1.5 + "Helm top poll after this delay when `helm-top-poll-mode' is enabled. +The minimal delay allowed is 1.5, if less than this helm-top will use 1.5." + :group 'helm-sys + :type 'float) + +(defcustom helm-top-poll-delay-post-command 1.0 + "Helm top stop polling during this delay. +This delay is added to `helm-top-poll-delay' after Emacs stops +being idle." + :group 'helm-sys + :type 'float) + +(defcustom helm-top-poll-preselection 'linum + "Stay on same line or follow candidate when `helm-top-poll' updates display. +Possible values are \\='candidate or \\='linum. +This affects also sorting functions in the same way." + :group'helm-sys + :type '(radio :tag "Preferred preselection action for helm-top" + (const :tag "Follow candidate" candidate) + (const :tag "Stay on same line" linum))) + +;;; Top (process) +;; +;; +(defvar helm-top-sort-fn nil) +(defvar helm-top-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map helm-map) + (define-key map (kbd "M-P") 'helm-top-run-sort-by-cpu) + (define-key map (kbd "M-C") 'helm-top-run-sort-by-com) + (define-key map (kbd "M-M") 'helm-top-run-sort-by-mem) + (define-key map (kbd "M-U") 'helm-top-run-sort-by-user) + map)) + +(defvar helm-top-after-init-hook nil + "Local hook for helm-top.") + +(defvar helm-top--poll-timer nil) + +(defun helm-top-poll (&optional no-update delay) + (when helm-top--poll-timer + (cancel-timer helm-top--poll-timer)) + (condition-case nil + (progn + (when (and (helm--alive-p) (null no-update)) + ;; Fix quitting while process is running + ;; by binding `with-local-quit' in init function + ;; Bug#1521. + (helm-force-update + (cl-ecase helm-top-poll-preselection + (candidate (replace-regexp-in-string + "[0-9]+" "[0-9]+" + (regexp-quote (helm-get-selection nil t)))) + (linum `(lambda () + (goto-char (point-min)) + (forward-line ,(helm-candidate-number-at-point))))))) + (setq helm-top--poll-timer + (run-with-idle-timer + (helm-aif (current-idle-time) + (time-add it (seconds-to-time + (or delay (helm-top--poll-delay)))) + (or delay (helm-top--poll-delay))) + nil + 'helm-top-poll))) + (quit (cancel-timer helm-top--poll-timer)))) + +(defun helm-top--poll-delay () + (max 1.5 helm-top-poll-delay)) + +(defun helm-top-poll-no-update () + (helm-top-poll t (+ (helm-top--poll-delay) + helm-top-poll-delay-post-command))) + +(defun helm-top-initialize-poll-hooks () + ;; When Emacs is idle during say 20s + ;; the idle timer will run in 20+1.5 s. + ;; This is fine when Emacs stays idle, because the next timer + ;; will run at 21.5+1.5 etc... so the display will be updated + ;; at every 1.5 seconds. + ;; But as soon as emacs looses its idleness, the next update + ;; will occur at say 21+1.5 s, so we have to reinitialize + ;; the timer at 0+1.5. + (add-hook 'post-command-hook 'helm-top-poll-no-update) + (add-hook 'focus-in-hook 'helm-top-poll-no-update)) + +;;;###autoload +(define-minor-mode helm-top-poll-mode + "Refresh automatically helm top buffer once enabled." + :group 'helm-top + :global t + (if helm-top-poll-mode + (progn + (add-hook 'helm-top-after-init-hook 'helm-top-poll-no-update) + (add-hook 'helm-top-after-init-hook 'helm-top-initialize-poll-hooks)) + (remove-hook 'helm-top-after-init-hook 'helm-top-poll-no-update) + (remove-hook 'helm-top-after-init-hook 'helm-top-initialize-poll-hooks))) + +(defvar helm-source-top + (helm-build-in-buffer-source "Top" + :header-name (lambda (name) + (concat name (if helm-top-poll-mode + " (auto updating)" + " (Press C-c C-u to refresh)"))) + :init #'helm-top-init + :after-init-hook 'helm-top-after-init-hook + :cleanup (lambda () + (when helm-top--poll-timer + (cancel-timer helm-top--poll-timer)) + (remove-hook 'post-command-hook 'helm-top-poll-no-update) + (remove-hook 'focus-in-hook 'helm-top-poll-no-update)) + :display-to-real #'helm-top-display-to-real + :persistent-action '(helm-top-sh-persistent-action . never-split) + :persistent-help "SIGTERM" + :help-message 'helm-top-help-message + :mode-line 'helm-top-mode-line + :follow 'never + :keymap helm-top-map + :filtered-candidate-transformer #'helm-top-sort-transformer + :action-transformer #'helm-top-action-transformer + :group 'helm-sys)) + +(defvar helm-top--line nil) +(defun helm-top-transformer (candidates _source) + "Transformer for `helm-top'. +Return empty string for non--valid candidates." + (cl-loop for disp in candidates collect + (cond ((string-match "^ *[0-9]+" disp) disp) + ((string-match "^ *PID" disp) + (setq helm-top--line (cons (propertize disp 'face 'helm-top-columns) ""))) + (t (cons disp ""))) + into lst + finally return (or (member helm-top--line lst) + (cons helm-top--line lst)))) + +(defun helm-top--skip-top-line () + (let* ((src (helm-get-current-source)) + (src-name (assoc-default 'name src))) + (helm-aif (and (stringp src-name) + (string= src-name "Top") + (helm-get-selection nil t src)) + (when (string-match-p "^ *PID" it) + (helm-next-line))))) + +(defun helm-top-action-transformer (actions _candidate) + "Action transformer for `top'. +Show actions only on line starting by a PID." + (let ((disp (helm-get-selection nil t))) + (cond ((string-match "\\` *[0-9]+" disp) + (list '("kill (SIGTERM)" . (lambda (_pid) + (helm-top-sh "TERM" (helm-top--marked-pids)))) + '("kill (SIGKILL)" . (lambda (_pid) + (helm-top-sh "KILL" (helm-top--marked-pids)))) + '("kill (SIGINT)" . (lambda (_pid) + (helm-top-sh "INT" (helm-top--marked-pids)))) + '("kill (Choose signal)" + . (lambda (_pid) + (let ((pids (helm-top--marked-pids))) + (helm-top-sh + (helm-comp-read (format "Kill %d pids with signal: " + (length pids)) + '("ALRM" "HUP" "INT" "KILL" "PIPE" "POLL" + "PROF" "TERM" "USR1" "USR2" "VTALRM" + "STKFLT" "PWR" "WINCH" "CHLD" "URG" + "TSTP" "TTIN" "TTOU" "STOP" "CONT" + "ABRT" "FPE" "ILL" "QUIT" "SEGV" + "TRAP" "SYS" "EMT" "BUS" "XCPU" "XFSZ") + :must-match t) + pids)))))) + (t actions)))) + +(defun helm-top--marked-pids () + (helm-remove-if-not-match "\\`[0-9]+\\'" (helm-marked-candidates))) + +(defun helm-top-sh (sig pids) + "Run kill shell command with signal SIG on PIDS for `helm-top'." + (message "kill -%s %s exited with status %s" + sig (mapconcat 'identity pids " ") + (apply #'call-process + "kill" nil nil nil (format "-%s" sig) pids))) + +(defun helm-top-sh-persistent-action (pid) + (helm-top-sh "TERM" (list pid)) + (helm-delete-current-selection)) + +(defun helm-top-init () + "Insert output of top command in candidate buffer." + (with-local-quit + (unless helm-top-sort-fn (helm-top-set-mode-line "CPU")) + (with-current-buffer (helm-candidate-buffer 'global) + (call-process-shell-command + (format helm-top-command (frame-width)) + nil (current-buffer))))) + +(defun helm-top-display-to-real (line) + "Return pid only from LINE." + (car (split-string line))) + +;; Sort top command + +(defun helm-top-set-mode-line (str) + (if (string-match "Sort:\\[\\(.*\\)\\] " helm-top-mode-line) + (setq helm-top-mode-line (replace-match str nil nil helm-top-mode-line 1)) + (setq helm-top-mode-line (concat (format "Sort:[%s] " str) helm-top-mode-line)))) + +(defun helm-top-sort-transformer (candidates source) + (helm-top-transformer + (if helm-top-sort-fn + (cl-loop for c in candidates + if (string-match "^ *[0-9]+" c) + collect c into pid-cands + else collect c into header-cands + finally return (append + header-cands + (sort pid-cands helm-top-sort-fn))) + candidates) + source)) + +(defun helm-top-sort-by-com (s1 s2) + (let* ((split-1 (split-string s1)) + (split-2 (split-string s2)) + (col (cdr (assq 'com helm-top-sort-columns-alist))) + (com-1 (nth col split-1)) + (com-2 (nth col split-2))) + (string< com-1 com-2))) + +(defun helm-top-sort-by-mem (s1 s2) + (let* ((split-1 (split-string s1)) + (split-2 (split-string s2)) + (col (cdr (assq 'mem helm-top-sort-columns-alist))) + (mem-1 (string-to-number (nth col split-1))) + (mem-2 (string-to-number (nth col split-2)))) + (> mem-1 mem-2))) + +(defun helm-top-sort-by-cpu (s1 s2) + (let* ((split-1 (split-string s1)) + (split-2 (split-string s2)) + (col (cdr (assq 'cpu helm-top-sort-columns-alist))) + (cpu-1 (string-to-number (nth col split-1))) + (cpu-2 (string-to-number (nth col split-2)))) + (> cpu-1 cpu-2))) + +(defun helm-top-sort-by-user (s1 s2) + (let* ((split-1 (split-string s1)) + (split-2 (split-string s2)) + (col (cdr (assq 'user helm-top-sort-columns-alist))) + (user-1 (nth col split-1)) + (user-2 (nth col split-2))) + (string< user-1 user-2))) + +(defun helm-top--preselect-fn () + (if (eq helm-top-poll-preselection 'linum) + `(lambda () + (goto-char (point-min)) + (forward-line ,(helm-candidate-number-at-point))) + (replace-regexp-in-string + "[0-9]+" "[0-9]+" + (regexp-quote (helm-get-selection nil t))))) + +(defun helm-top-run-sort-by-com () + (interactive) + (helm-top-set-mode-line "COM") + (setq helm-top-sort-fn 'helm-top-sort-by-com) + (helm-update (helm-top--preselect-fn))) + +(defun helm-top-run-sort-by-cpu () + (interactive) + (helm-top-set-mode-line "CPU") + ;; Force sorting by CPU even if some versions of top are using by + ;; default CPU sorting (Bug#1908). + (setq helm-top-sort-fn 'helm-top-sort-by-cpu) + (helm-update (helm-top--preselect-fn))) + +(defun helm-top-run-sort-by-mem () + (interactive) + (helm-top-set-mode-line "MEM") + (setq helm-top-sort-fn 'helm-top-sort-by-mem) + (helm-update (helm-top--preselect-fn))) + +(defun helm-top-run-sort-by-user () + (interactive) + (helm-top-set-mode-line "USER") + (setq helm-top-sort-fn 'helm-top-sort-by-user) + (helm-update (helm-top--preselect-fn))) + + +;;; X RandR resolution change +;; +;; +;;; FIXME I do not care multi-display. + +(defun helm-xrandr-info () + "Return a pair with current X screen number and current X display name." + (with-temp-buffer + (call-process "xrandr" nil (current-buffer) nil + "--current") + (let (screen output) + (goto-char (point-min)) + (save-excursion + (when (re-search-forward "\\(^Screen \\)\\([0-9]\\):" nil t) + (setq screen (match-string 2)))) + (when (re-search-forward "^\\(.*\\) connected" nil t) + (setq output (match-string 1))) + (list screen output)))) + +(defun helm-xrandr-screen () + "Return current X screen number." + (car (helm-xrandr-info))) + +(defun helm-xrandr-output () + "Return current X display name." + (cadr (helm-xrandr-info))) + +(defvar helm-source-xrandr-change-resolution + (helm-build-sync-source "Change Resolution" + :candidates + (lambda () + (with-temp-buffer + (call-process "xrandr" nil (current-buffer) nil + "--screen" (helm-xrandr-screen) "-q") + (goto-char 1) + (cl-loop while (re-search-forward " \\([0-9]+x[0-9]+\\)" nil t) + for mode = (match-string 1) + unless (member mode modes) + collect mode into modes + finally return modes))) + :action + (helm-make-actions "Change Resolution" + (lambda (mode) + (call-process "xrandr" nil nil nil + "--screen" (helm-xrandr-screen) + "--output" (helm-xrandr-output) + "--mode" mode))))) + + +;;; Emacs process +;; +;; +(defvar helm-source-emacs-process + (helm-build-sync-source "Emacs Process" + :init (lambda () + (let (tabulated-list-use-header-line) + (list-processes--refresh))) + :candidates (lambda () (mapcar #'process-name (process-list))) + :candidate-transformer + (lambda (candidates) + (cl-loop for c in candidates + for command = (mapconcat + 'identity + (process-command (get-process c)) " ") + if (and command (not (string= command ""))) collect + (cons (concat c " --> " + (mapconcat 'identity + (process-command (get-process c)) " ")) + c) + else collect c)) + :multiline t + :persistent-action (lambda (elm) + (delete-process (get-process elm)) + (helm-delete-current-selection)) + :persistent-help "Kill Process" + :action (helm-make-actions "Kill Process" + (lambda (_elm) + (cl-loop for p in (helm-marked-candidates) + do (delete-process (get-process p))))))) + + +;;;###autoload +(defun helm-top () + "Preconfigured `helm' for top command." + (interactive) + (add-hook 'helm-after-update-hook 'helm-top--skip-top-line) + (unwind-protect + (helm :sources 'helm-source-top + :buffer "*helm top*" :full-frame t + :candidate-number-limit 9999 + :preselect "^\\s-*[0-9]+" + :truncate-lines helm-show-action-window-other-window) + (remove-hook 'helm-after-update-hook 'helm-top--skip-top-line))) + +;;;###autoload +(defun helm-list-emacs-process () + "Preconfigured `helm' for Emacs process." + (interactive) + (helm :sources 'helm-source-emacs-process + :truncate-lines t + :buffer "*helm process*")) + +;;;###autoload +(defun helm-xrandr-set () + "Preconfigured helm for xrandr." + (interactive) + (helm :sources 'helm-source-xrandr-change-resolution + :buffer "*helm xrandr*")) + +(provide 'helm-sys) + +;;; helm-sys.el ends here diff --git a/org/elpa/helm-20230406.839/helm-tags.el b/org/elpa/helm-20230406.839/helm-tags.el new file mode 100644 index 0000000..efbd9ce --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-tags.el @@ -0,0 +1,337 @@ +;;; helm-tags.el --- Helm for Etags. -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2023 Thierry Volpiatto + +;; 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 . + +;;; Code: + +(require 'cl-lib) +(require 'helm) +(require 'helm-help) +(require 'helm-utils) +(require 'helm-grep) + +(defvar helm-etags-fuzzy-match) +(declare-function xref-push-marker-stack "xref") + + +(defgroup helm-tags nil + "Tags related Applications and libraries for Helm." + :group 'helm) + +(defcustom helm-etags-tag-file-name "TAGS" + "Etags tag file name." + :type 'string) + +(defcustom helm-etags-tag-file-search-limit 10 + "The limit level of directory to search tag file. +Don't search tag file deeply if outside this value." + :type 'number) + +(defcustom helm-etags-match-part-only 'tag + "Allow choosing the tag part of CANDIDATE in `helm-source-etags-select'. +A tag looks like this: + filename: (defun foo +You can choose matching against the tag part (i.e \"(defun foo\"), +or against the whole candidate (i.e \"(filename:5:(defun foo\")." + :type '(choice + (const :tag "Match only tag" tag) + (const :tag "Match all file+tag" all))) + +(defcustom helm-etags-execute-action-at-once-if-one t + "Whether to jump straight to the selected tag if there's only +one match." + :type 'boolean) + + +(defgroup helm-tags-faces nil + "Customize the appearance of helm-tags faces." + :prefix "helm-" + :group 'helm-tags + :group 'helm-faces) + +(defface helm-etags-file + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "Lightgoldenrod4" + :underline t)) + "Face used to highlight etags filenames." + :group 'helm-tags-faces) + + +;;; Etags +;; +;; +(defun helm-etags-find-file (candidate) + "Find file CANDIDATE from helm etags buffer." + (helm-etags-action-goto 'find-file candidate)) + +(defun helm-etags-find-file-other-window (candidate) + "Find file other window from helm etags buffer." + (helm-etags-action-goto 'find-file-other-window candidate)) + +(defun helm-etags-find-file-other-frame (candidate) + "Find file other frame from helm etags buffer." + (helm-etags-action-goto 'find-file-other-frame candidate)) + +(helm-make-command-from-action helm-etags-run-switch-other-window + "Run switch to other window action from `helm-source-etags-select'." + 'helm-etags-find-file-other-window) + +(helm-make-command-from-action helm-etags-run-switch-other-frame + "Run switch to other frame action from `helm-source-etags-select'." + 'helm-etags-find-file-other-frame) + +(defvar helm-etags-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map helm-map) + (define-key map (kbd "M-") 'helm-goto-next-file) + (define-key map (kbd "M-") 'helm-goto-precedent-file) + (define-key map (kbd "C-c o") 'helm-etags-run-switch-other-window) + (define-key map (kbd "C-c C-o") 'helm-etags-run-switch-other-frame) + map) + "Keymap used in Etags.") + +(defvar helm-etags-mtime-alist nil + "Store the last modification time of etags files here.") +(defvar helm-etags-cache (make-hash-table :test 'equal) + "Cache content of etags files used here for faster access.") + +(defun helm-etags-get-tag-file (&optional directory) + "Return the path of etags file if found in DIRECTORY. +Look recursively in parents directorys for a +`helm-etags-tag-file-name' file." + ;; Get tag file from `default-directory' or upper directory. + (let ((current-dir (helm-etags-find-tag-file-directory + (or directory default-directory)))) + ;; Return nil if not find tag file. + (when current-dir + (expand-file-name helm-etags-tag-file-name current-dir)))) + +(defun helm-etags-all-tag-files () + "Find Etags files. +Return files from the following sources: + 1) An automatically located file in the parent directories, + by `helm-etags-get-tag-file'. + 2) `tags-file-name', which is commonly set by `find-tag' command. + 3) `tags-table-list' which is commonly set by `visit-tags-table' command." + (helm-fast-remove-dups + (delq nil + (append (list (helm-etags-get-tag-file) + tags-file-name) + tags-table-list)) + :test 'equal)) + +(defun helm-etags-find-tag-file-directory (current-dir) + "Try to find the directory containing tag file. +If not found in CURRENT-DIR search in upper directory." + (let ((file-exists? (lambda (dir) + (let ((tag-path (expand-file-name + helm-etags-tag-file-name dir))) + (and (stringp tag-path) + (file-regular-p tag-path) + (file-readable-p tag-path)))))) + (cl-loop with count = 0 + until (funcall file-exists? current-dir) + ;; Return nil if outside the value of + ;; `helm-etags-tag-file-search-limit'. + if (= count helm-etags-tag-file-search-limit) + do (cl-return nil) + ;; Or search upper directories. + else + do (cl-incf count) + (setq current-dir (expand-file-name (concat current-dir "../"))) + finally return current-dir))) + +(defun helm-etags-get-header-name (_x) + "Create header name for this helm etags session." + (concat "Etags in " + (with-helm-current-buffer + (helm-etags-get-tag-file)))) + +(defun helm-etags-create-buffer (file) + "Create the `helm-buffer' based on contents of etags tag FILE." + (let* (max + (split (with-temp-buffer + (insert-file-contents file) + (prog1 + (split-string (buffer-string) "\n" 'omit-nulls) + (setq max (line-number-at-pos (point-max)))))) + (progress-reporter (make-progress-reporter "Loading tag file..." 0 max))) + (cl-loop + with fname + with cand + for i in split for count from 0 + for elm = (unless (string-match "^\x0c" i) ;; "^L" + (helm-aif (string-match "\177" i) ;; "^?" + (substring i 0 it) + i)) + for linum = (when (string-match "[0-9]+,?[0-9]*$" i) + (car (split-string (match-string 0 i) ","))) + do (cond ((and elm (string-match "^\\([^,]+\\),[0-9]+$" elm)) + (setq fname (propertize (match-string 1 elm) + 'face 'helm-etags-file))) + (elm (setq cand (format "%s:%s:%s" fname linum elm))) + (t (setq cand nil))) + when cand do (progn + (insert (propertize (concat cand "\n") 'linum linum)) + (progress-reporter-update progress-reporter count))))) + +(defun helm-etags-init () + "Feed `helm-buffer' using `helm-etags-cache' or tag file. +If there is no entry in cache, create one." + (let ((tagfiles (helm-etags-all-tag-files))) + (when tagfiles + (with-current-buffer (helm-candidate-buffer 'global) + (dolist (f tagfiles) + (helm-aif (gethash f helm-etags-cache) + ;; An entry is present in cache, insert it. + (insert it) + ;; No entry, create a new buffer using content of tag file (slower). + (helm-etags-create-buffer f) + ;; Store content of buffer in cache. + (puthash f (buffer-string) helm-etags-cache) + ;; Store or set the last modification of tag file. + (helm-aif (assoc f helm-etags-mtime-alist) + ;; If an entry exists modify it. + (setcdr it (helm-etags-mtime f)) + ;; No entry create a new one. + (cl-pushnew (cons f (helm-etags-mtime f)) + helm-etags-mtime-alist + :test 'equal)))))))) + +(defvar helm-source-etags-select nil + "Helm source for Etags.") + +(defun helm-etags-build-source () + (helm-build-in-buffer-source "Etags" + :header-name 'helm-etags-get-header-name + :init 'helm-etags-init + :get-line 'buffer-substring + :match-part (lambda (candidate) + ;; Match only the tag part of CANDIDATE + ;; and not the filename. + (cl-case helm-etags-match-part-only + (tag (cl-caddr (helm-grep-split-line candidate))) + (t candidate))) + :fuzzy-match helm-etags-fuzzy-match + :help-message 'helm-etags-help-message + :keymap helm-etags-map + :action '(("Go to tag" . helm-etags-find-file) + ("Go to tag in other window" . helm-etags-find-file-other-window) + ("Go to tag in other frame" . helm-etags-find-file-other-frame)) + :group 'helm-tags + :persistent-help "Go to line" + :persistent-action (lambda (candidate) + (helm-etags-action-goto 'find-file candidate) + (helm-highlight-current-line)))) + +(defcustom helm-etags-fuzzy-match nil + "Use fuzzy matching in `helm-etags-select'." + :group 'helm-tags + :type 'boolean + :set (lambda (var val) + (set var val) + (setq helm-source-etags-select + (helm-etags-build-source)))) + +(defsubst helm-etags--file-from-tag (fname) + (cl-loop for ext in + (cons "" (remove "" tags-compression-info-list)) + for file = (concat fname ext) + when (file-exists-p file) + return file)) + +(defun helm-etags-action-goto (switcher candidate) + "Helm default action to jump to an etags entry in other window." + (require 'etags) + (deactivate-mark t) + (helm-log-run-hook "helm-etags-action-goto " 'helm-goto-line-before-hook) + (let* ((split (helm-grep-split-line candidate)) + (fname (cl-loop for tagf being the hash-keys of helm-etags-cache + for f = (expand-file-name + (car split) (file-name-directory tagf)) + ;; Try to find an existing file, possibly compressed. + when (helm-etags--file-from-tag f) + return it)) + (elm (cl-caddr split)) + (linum (string-to-number (cadr split)))) + (if (null fname) + (error "file %s not found" fname) + (xref-push-marker-stack) + (funcall switcher fname) + (helm-goto-line linum t) + (when (search-forward elm nil t) + (goto-char (match-beginning 0)))))) + +(defun helm-etags-mtime (file) + "Last modification time of etags tag FILE." + (cadr (nth 5 (file-attributes file)))) + +(defun helm-etags-file-modified-p (file) + "Check if tag FILE have been modified in this session. +If FILE is nil return nil." + (let ((last-modif (and file + (assoc-default file helm-etags-mtime-alist)))) + (and last-modif + (/= last-modif (helm-etags-mtime file))))) + +;;;###autoload +(defun helm-etags-select (reinit) + "Preconfigured helm for etags. +If called with a prefix argument REINIT +or if any of the tag files have been modified, reinitialize cache. + +This function aggregates three sources of tag files: + + 1) An automatically located file in the parent directories, + by `helm-etags-get-tag-file'. + 2) `tags-file-name', which is commonly set by `find-tag' command. + 3) `tags-table-list' which is commonly set by `visit-tags-table' command." + (interactive "P") + (let ((tag-files (helm-etags-all-tag-files)) + (helm-execute-action-at-once-if-one + helm-etags-execute-action-at-once-if-one) + (str (if (region-active-p) + (buffer-substring-no-properties + (region-beginning) (region-end)) + (thing-at-point 'symbol)))) + (if (cl-notany 'file-exists-p tag-files) + (message "Error: No tag file found.\ +Create with etags shell command, or visit with `find-tag' or `visit-tags-table'.") + (cl-loop for k being the hash-keys of helm-etags-cache + unless (member k tag-files) + do (remhash k helm-etags-cache)) + (mapc (lambda (f) + (when (or (equal reinit '(4)) + (and helm-etags-mtime-alist + (helm-etags-file-modified-p f))) + (remhash f helm-etags-cache))) + tag-files) + (unless helm-source-etags-select + (setq helm-source-etags-select + (helm-etags-build-source))) + (helm :sources 'helm-source-etags-select + :keymap helm-etags-map + :default (and (stringp str) + (if (or helm-etags-fuzzy-match + (and (eq major-mode 'haskell-mode) + (string-match "[']\\'" str))) + str + (list (concat "\\_<" str "\\_>") str))) + :buffer "*helm etags*")))) + +(provide 'helm-tags) + +;;; helm-tags.el ends here diff --git a/org/elpa/helm-20230406.839/helm-types.el b/org/elpa/helm-20230406.839/helm-types.el new file mode 100644 index 0000000..65280ff --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-types.el @@ -0,0 +1,337 @@ +;;; helm-types.el --- Helm types classes and methods. -*- lexical-binding: t -*- + +;; Copyright (C) 2015 ~ 2020 Thierry Volpiatto + +;; Author: Thierry Volpiatto +;; URL: http://github.com/emacs-helm/helm + +;; 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 . + + +;;; Code: + +(require 'cl-lib) +(require 'eieio) +(eval-when-compile (require 'helm-source)) + +(defvar helm-map) +(defvar helm-mode-line-string) +(defvar helm-bookmark-map) +(declare-function helm-make-actions "helm-lib") +(declare-function helm-ediff-marked-buffers "helm-buffers") +(declare-function helm-make-type "helm-source") + + +;; Files +(defclass helm-type-file (helm-source) () + "A class to define helm type file.") + +(cl-defmethod helm-source-get-action-from-type ((object helm-type-file)) + (slot-value object 'action)) + +(defun helm-actions-from-type-file () + (let ((source (make-instance 'helm-type-file))) + (helm--setup-source source) + (helm-source-get-action-from-type source))) + +(defvar helm-generic-files-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map helm-map) + (define-key map (kbd "C-]") 'helm-ff-run-toggle-basename) + (define-key map (kbd "C-s") 'helm-ff-run-grep) + (define-key map (kbd "M-g s") 'helm-ff-run-grep) + (define-key map (kbd "M-g z") 'helm-ff-run-zgrep) + (define-key map (kbd "M-g p") 'helm-ff-run-pdfgrep) + (define-key map (kbd "M-R") 'helm-ff-run-rename-file) + (define-key map (kbd "M-C") 'helm-ff-run-copy-file) + (define-key map (kbd "M-B") 'helm-ff-run-byte-compile-file) + (define-key map (kbd "M-L") 'helm-ff-run-load-file) + (define-key map (kbd "M-S") 'helm-ff-run-symlink-file) + (define-key map (kbd "M-H") 'helm-ff-run-hardlink-file) + (define-key map (kbd "M-D") 'helm-ff-run-delete-file) + (define-key map (kbd "C-=") 'helm-ff-run-ediff-file) + (define-key map (kbd "C-c =") 'helm-ff-run-ediff-merge-file) + (define-key map (kbd "C-c o") 'helm-ff-run-switch-other-window) + (define-key map (kbd "C-c r") 'helm-ff-run-find-file-as-root) + (define-key map (kbd "C-c C-o") 'helm-ff-run-switch-other-frame) + (define-key map (kbd "M-i") 'helm-ff-properties-persistent) + (define-key map (kbd "C-c C-x") 'helm-ff-run-open-file-externally) + (define-key map (kbd "C-c X") 'helm-ff-run-open-file-with-default-tool) + (define-key map (kbd "C-c @") 'helm-ff-run-insert-org-link) + (define-key map (kbd "C-x C-q") 'helm-ff-run-marked-files-in-dired) + (define-key map (kbd "C-c C-a") 'helm-ff-run-mail-attach-files) + map) + "Generic Keymap for files.") + +(defcustom helm-type-file-actions + (helm-make-actions + "Find file" 'helm-find-file-or-marked + "Find file as root" 'helm-find-file-as-root + "Find file other window" 'helm-find-files-other-window + "Find file other frame" 'find-file-other-frame + "Open dired in file's directory" 'helm-open-dired + "Attach file(s) to mail buffer `C-c C-a'" 'helm-ff-mail-attach-files + "Marked files in dired" 'helm-marked-files-in-dired + "Grep File(s) `C-u recurse'" 'helm-find-files-grep + "Zgrep File(s) `C-u Recurse'" 'helm-ff-zgrep + "Pdfgrep File(s)" 'helm-ff-pdfgrep + "Insert as org link" 'helm-files-insert-as-org-link + "Checksum File" 'helm-ff-checksum + "Ediff File" 'helm-find-files-ediff-files + "Ediff Merge File" 'helm-find-files-ediff-merge-files + "View file" 'view-file + "Insert file" 'insert-file + "Add marked files to file-cache" 'helm-ff-cache-add-file + "Delete file(s)" 'helm-ff-delete-files + "Copy file(s) `M-C, C-u to follow'" 'helm-find-files-copy + "Rename file(s) `M-R, C-u to follow'" 'helm-find-files-rename + "Symlink files(s) `M-S, C-u to follow'" 'helm-find-files-symlink + "Relsymlink file(s) `C-u to follow'" 'helm-find-files-relsymlink + "Hardlink file(s) `M-H, C-u to follow'" 'helm-find-files-hardlink + "Open file externally (C-u to choose)" 'helm-open-file-externally + "Open file with default tool" 'helm-open-file-with-default-tool + "Find file in hex dump" 'hexl-find-file) + "Default actions for type files." + :group 'helm-files + :type '(alist :key-type string :value-type function)) + +(cl-defmethod helm--setup-source ((_source helm-type-file))) + +(cl-defmethod helm--setup-source :before ((source helm-type-file)) + (setf (slot-value source 'action) 'helm-type-file-actions) + (setf (slot-value source 'persistent-help) "Show this file") + (setf (slot-value source 'action-transformer) + '(helm-transform-file-load-el + helm-transform-file-browse-url + helm-transform-file-cache)) + (setf (slot-value source 'candidate-transformer) + '(helm-skip-boring-files + helm-w32-pathname-transformer)) + (setf (slot-value source 'filtered-candidate-transformer) + 'helm-highlight-files) + (setf (slot-value source 'help-message) 'helm-generic-file-help-message) + (setf (slot-value source 'mode-line) (list "File(s)" helm-mode-line-string)) + (setf (slot-value source 'keymap) helm-generic-files-map) + (setf (slot-value source 'group) 'helm-files)) + + +;; Bookmarks +(defclass helm-type-bookmark (helm-source) () + "A class to define type bookmarks.") + +(defcustom helm-type-bookmark-actions + (helm-make-actions + "Jump to bookmark" 'helm-bookmark-jump + "Jump to BM other window" 'helm-bookmark-jump-other-window + "Jump to BM other frame" 'helm-bookmark-jump-other-frame + "Jump to BM other tab" 'helm-bookmark-jump-other-tab + "Bookmark edit annotation" 'bookmark-edit-annotation + "Bookmark show annotation" 'bookmark-show-annotation + "Delete bookmark(s)" 'helm-delete-marked-bookmarks + "Edit Bookmark" 'helm-bookmark-edit-bookmark + "Rename bookmark" 'helm-bookmark-rename + "Relocate bookmark" 'bookmark-relocate) + "Default actions for type bookmarks." + :group 'helm-bookmark + :type '(alist :key-type string + :value-type function)) + +(cl-defmethod helm-source-get-action-from-type ((object helm-type-bookmark)) + (slot-value object 'action)) + +(cl-defmethod helm--setup-source ((_source helm-type-bookmark))) + +(cl-defmethod helm--setup-source :before ((source helm-type-bookmark)) + (setf (slot-value source 'action) 'helm-type-bookmark-actions) + (setf (slot-value source 'keymap) helm-bookmark-map) + (setf (slot-value source 'mode-line) (list "Bookmark(s)" helm-mode-line-string)) + (setf (slot-value source 'help-message) 'helm-bookmark-help-message) + (setf (slot-value source 'migemo) t) + (setf (slot-value source 'follow) 'never) + (setf (slot-value source 'group) 'helm-bookmark)) + + +;; Buffers +(defclass helm-type-buffer (helm-source) () + "A class to define type buffer.") + +(defcustom helm-type-buffer-actions + (helm-make-actions + "Switch to buffer(s)" 'helm-buffer-switch-buffers + "Switch to buffer(s) other window `C-c o'" + 'helm-buffer-switch-buffers-other-window + "Switch to buffer(s) other frame `C-c C-o'" + 'helm-buffer-switch-to-buffer-other-frame + "Raise buffer frame maybe" + 'helm-buffers-maybe-raise-buffer-frame + (lambda () (and (fboundp 'tab-bar-mode) + "Switch to buffer(s) other tab `C-c C-t'")) + 'helm-buffers-switch-to-buffer-other-tab + "Switch to buffer at line number" + 'helm-switch-to-buffer-at-linum + "Browse project `C-x C-d'" + 'helm-buffers-browse-project + "Switch to shell" + 'helm-buffer-switch-to-shell + "Query replace regexp `C-M-%'" + 'helm-buffer-query-replace-regexp + "Query replace `M-%'" 'helm-buffer-query-replace + "View buffer" 'view-buffer + "Display buffer" 'display-buffer + "Rename buffer `M-R'" 'helm-buffers-rename-buffer + "Grep buffer(s) `M-g s' (C-u grep all buffers)" + 'helm-zgrep-buffers + "Multi occur buffer(s) `C-s (C-u search also in current)'" + 'helm-multi-occur-as-action + "Revert buffer(s) `M-G'" 'helm-revert-marked-buffers + "Insert buffer" 'insert-buffer + "Kill buffer(s) `M-D'" 'helm-kill-marked-buffers + "Diff with file `C-='" 'diff-buffer-with-file + "Ediff Marked buffers `C-c ='" 'helm-ediff-marked-buffers + "Ediff Merge marked buffers `M-='" + (lambda (candidate) + (helm-ediff-marked-buffers candidate t))) + "Default actions for type buffers." + :group 'helm-buffers + :type '(alist :key-type string :value-type function)) + +(cl-defmethod helm-source-get-action-from-type ((object helm-type-buffer)) + (slot-value object 'action)) + +(cl-defmethod helm--setup-source ((_source helm-type-buffer))) + +(cl-defmethod helm--setup-source :before ((source helm-type-buffer)) + (setf (slot-value source 'action) 'helm-type-buffer-actions) + (setf (slot-value source 'persistent-help) "Show this buffer") + (setf (slot-value source 'mode-line) + ;; Use default-value of `helm-mode-line-string' in case user + ;; starts with a helm buffer as current-buffer otherwise the + ;; local value of this helm buffer is used (bug#1517, bug#2377). + (list "Buffer(s)" (default-value 'helm-mode-line-string))) + (setf (slot-value source 'filtered-candidate-transformer) + '(helm-skip-boring-buffers + helm-buffers-sort-transformer + helm-highlight-buffers)) + (setf (slot-value source 'group) 'helm-buffers)) + +;; Functions +(defclass helm-type-function (helm-source) () + "A class to define helm type function.") + +(defcustom helm-type-function-actions + (helm-make-actions + "Describe function" 'helm-describe-function + "Find function" 'helm-find-function + "Info lookup" 'helm-info-lookup-symbol + "Debug on entry" 'debug-on-entry + "Cancel debug on entry" 'cancel-debug-on-entry + "Trace function" 'trace-function + "Trace function (background)" 'trace-function-background + "Untrace function" 'untrace-function) + "Default actions for type functions." + :group 'helm-elisp + ;; Use symbol as value type because some functions may not be + ;; autoloaded (like untrace-function). + :type '(alist :key-type string :value-type symbol)) + +(cl-defmethod helm-source-get-action-from-type ((object helm-type-function)) + (slot-value object 'action)) + +(defun helm-actions-from-type-function () + (let ((source (make-instance 'helm-type-function))) + (helm--setup-source source) + (helm-source-get-action-from-type source))) + +(cl-defmethod helm--setup-source ((_source helm-type-function))) + +(cl-defmethod helm--setup-source :before ((source helm-type-function)) + (setf (slot-value source 'action) 'helm-type-function-actions) + (setf (slot-value source 'action-transformer) + 'helm-transform-function-call-interactively) + (setf (slot-value source 'candidate-transformer) + 'helm-mark-interactive-functions) + (setf (slot-value source 'coerce) 'helm-symbolify)) + + +;; Commands +(defclass helm-type-command (helm-source) () + "A class to define helm type command.") + +(defun helm-actions-from-type-command () + (let ((source (make-instance 'helm-type-command))) + (helm--setup-source source) + (helm-source-get-action-from-type source))) + +(defcustom helm-type-command-actions + (append (helm-make-actions + "Execute command" 'helm-M-x-execute-command) + (symbol-value + (helm-actions-from-type-function))) + "Default actions for type command." + :group 'helm-command + :type '(alist :key-type string :value-type symbol)) + +(cl-defmethod helm--setup-source ((_source helm-type-command))) + +(cl-defmethod helm--setup-source :before ((source helm-type-command)) + (setf (slot-value source 'action) 'helm-type-command-actions) + (setf (slot-value source 'coerce) 'helm-symbolify) + (setf (slot-value source 'persistent-action) 'helm-M-x-persistent-action) + (setf (slot-value source 'persistent-help) "Describe this command") + (setf (slot-value source 'group) 'helm-command)) + +;; Timers +(defclass helm-type-timers (helm-source) () + "A class to define helm type timers.") + +(defcustom helm-type-timers-actions + '(("Cancel Timer" . (lambda (_timer) + (let ((mkd (helm-marked-candidates))) + (cl-loop for timer in mkd + do (cancel-timer timer))))) + ("Describe Function" . (lambda (tm) + (describe-function (timer--function tm)))) + ("Find Function" . (lambda (tm) + (helm-aif (timer--function tm) + (if (or (byte-code-function-p it) + (helm-subr-native-elisp-p it)) + (message "Can't find anonymous function `%s'" it) + (find-function it)))))) + "Default actions for type timers." + :group 'helm-elisp + :type '(alist :key-type string :value-type function)) + +(cl-defmethod helm--setup-source ((_source helm-type-timers))) + +(cl-defmethod helm--setup-source :before ((source helm-type-timers)) + (setf (slot-value source 'action) 'helm-type-timers-actions) + (setf (slot-value source 'persistent-action) + (lambda (tm) + (describe-function (timer--function tm)))) + (setf (slot-value source 'persistent-help) "Describe Function") + (setf (slot-value source 'group) 'helm-elisp)) + +;; Builders. +(defun helm-build-type-file () + (helm-make-type 'helm-type-file)) + +(defun helm-build-type-function () + (helm-make-type 'helm-type-function)) + +(defun helm-build-type-command () + (helm-make-type 'helm-type-command)) + +(provide 'helm-types) + +;;; helm-types.el ends here diff --git a/org/elpa/helm-20230406.839/helm-utils.el b/org/elpa/helm-20230406.839/helm-utils.el new file mode 100644 index 0000000..92c8ab0 --- /dev/null +++ b/org/elpa/helm-20230406.839/helm-utils.el @@ -0,0 +1,1142 @@ +;;; helm-utils.el --- Utilities Functions for helm. -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2023 Thierry Volpiatto + +;; 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 . + +;;; Code: + +(require 'cl-lib) +(require 'helm) +(require 'helm-help) + +(declare-function helm-find-files-1 "helm-files" (fname &optional preselect)) +(declare-function helm-grep-split-line "helm-grep" (line)) +(declare-function popup-tip "ext:popup") +(declare-function markdown-show-entry "ext:markdown-mode.el") +(declare-function outline-show-subtree "outline") +(declare-function org-reveal "org") +(declare-function hs-show-block "hideshow.el") +(declare-function tab-bar-tabs "tab-bar") +(declare-function tab-bar-select-tab "tab-bar") +(declare-function dired-goto-file "dired") +(declare-function bookmark-get-filename "bookmark") +(declare-function package-installed-p "package") +(declare-function package-desc-dir "package") + +(defvar hs-minor-mode) +(defvar hs-show-hook) +(defvar org-directory) +(defvar winner-boring-buffers) +(defvar bookmark-alist) +(defvar dired-buffers) +(defvar helm-show-completion-overlay) +(defvar helm-buffers-maybe-switch-to-tab) +(defvar helm-ff-transformer-show-only-basename) +(defvar helm-popup-tip-mode) +(defvar helm-ff-last-expanded-candidate-regexp) + + +(defgroup helm-utils nil + "Utilities routines for Helm." + :group 'helm) + +(defcustom helm-su-or-sudo "sudo" + "What command to use for root access." + :type 'string + :group 'helm-utils) + +(defcustom helm-default-kbsize 1024.0 + "Default Kbsize to use for showing files size. +It is a float, usually 1024.0 but could be 1000.0 on some systems." + :group 'helm-utils + :type 'float) + +(define-obsolete-variable-alias + 'helm-highlight-number-lines-around-point + 'helm-highlight-matches-around-point-max-lines + "20160119") + +(defcustom helm-highlight-matches-around-point-max-lines '(15 . 15) + "Number of lines around point where matched items are highlighted. + +Possible value are: +- A cons cell (x . y) + Match x lines before point and y lines after point. +- An integer + Positive means this number lines after point. + Negative means this number lines before point. + A zero value means highlight only inside matched lines. +- The symbol never + Means do not highlight matched items. " + :group 'helm-utils + :type '(choice (cons (integer :tag "Match before") + (integer :tag "Match after")) + (const :tag "Match in line only" 0) + (integer :tag "Match after or before (+/-)") + (const :tag "Never match" never))) + +(defcustom helm-highlight-only-all-matches nil + "Highlight only when all items match on the line when non nil. +See `helm-highlight-current-line'." + :group 'helm-utils + :type 'boolean) + +(defcustom helm-buffers-to-resize-on-pa nil + "A list of helm buffers where the helm-window should be reduced on PA. +Where PA means persistent action." + :group 'helm-utils + :type '(repeat (choice string))) + +(defcustom helm-resize-on-pa-text-height 12 + "The size of the helm-window when resizing on persistent action." + :group 'helm-utils + :type 'integer) + +(defcustom helm-sources-using-help-echo-popup '("Ack-Grep" "AG" "RG" "Gid" "Git-Grep") + "Show the buffer name or the filename in a popup at selection." + :group 'helm-utils + :type '(repeat (choice string))) + +(defcustom helm-html-decode-entities-function #'helm-html-decode-entities-string + "Function used to decode HTML entities in HTML bookmarks. +Helm comes by default with `helm-html-decode-entities-string', if +you need something more sophisticated you can use +`w3m-decode-entities-string' if available. + +In Emacs itself org-entities seem broken and `xml-substitute-numeric-entities' +supports only numeric entities." + :group 'helm-utils + :type 'function) + + +(defvar helm-goto-line-before-hook '(helm-save-current-pos-to-mark-ring) + "Run before jumping to line. +This hook runs when jumping from `helm-goto-line', `helm-etags-default-action', +and `helm-imenu-default-action'. +This allows you to retrieve a previous position after using the different helm +tools for searching (etags, grep, gid, (m)occur etc...). +By default positions are added to `mark-ring'. +You can also add to register by using (or adding) +`helm-save-pos-to-register-before-jump' instead. In this case +last position is added to the register `helm-save-pos-before-jump-register'.") + +(defvar helm-save-pos-before-jump-register ?_ + "The register where `helm-save-pos-to-register-before-jump' saves position.") + +(defconst helm-html-entities-alist + '((""" . 34) ;; " + (">" . 62) ;; > + ("<" . 60) ;; < + ("&" . 38) ;; & + ("€" . 8364) ;; € + ("Ÿ" . 89) ;; Y + ("¡" . 161) ;; ¡ + ("¢" . 162) ;; ¢ + ("£" . 163) ;; £ + ("¤" . 164) ;; ¤ + ("¥" . 165) ;; ¥ + ("¦" . 166) ;; ¦ + ("§" . 167) ;; § + ("¨" . 32) ;; SPC + (" " . 160) ;;   (non breaking space) + ("©" . 169) ;; © + ("ª" . 97) ;; a + ("«" . 171) ;; « + ("¬" . 172) ;; ¬ + ("&masr;" . 174) ;; ® + ("°" . 176) ;; ° + ("±" . 177) ;; ± + ("²" . 50) ;; 2 + ("³" . 51) ;; 3 + ("´" . 39) ;; ' + ("µ" . 956) ;; μ + ("¶" . 182) ;; ¶ + ("·" . 183) ;; · + ("¸" . 32) ;; SPC + ("¹" . 49) ;; 1 + ("º" . 111) ;; o + ("»" . 187) ;; » + ("¼" . 49) ;; 1 + ("½" . 49) ;; 1 + ("¾" . 51) ;; 3 + ("¿" . 191) ;; ¿ + ("À" . 192) ;; À + ("Á" . 193) ;; Á + ("Â" . 194) ;; Â + ("Ã" . 195) ;; Ã + ("Ä" . 196) ;; Ä + ("Å" . 197) ;; Å + ("&Aelig" . 198) ;; Æ + ("Ç" . 199) ;; Ç + ("È" . 200) ;; È + ("É" . 201) ;; É + ("Ê" . 202) ;; Ê + ("Ë" . 203) ;; Ë + ("Ì" . 204) ;; Ì + ("Í" . 205) ;; Í + ("Î" . 206) ;; Î + ("Ï" . 207) ;; Ï + ("ð" . 208) ;; Ð + ("Ñ" . 209) ;; Ñ + ("Ò" . 210) ;; Ò + ("Ó" . 211) ;; Ó + ("Ô" . 212) ;; Ô + ("Õ" . 213) ;; Õ + ("Ö" . 214) ;; Ö + ("×" . 215) ;; × + ("Ø" . 216) ;; Ø + ("Ù" . 217) ;; Ù + ("Ú" . 218) ;; Ú + ("Û" . 219) ;; Û + ("Ü" . 220) ;; Ü + ("Ý" . 221) ;; Ý + ("þ" . 222) ;; Þ + ("ß" . 223) ;; ß + ("à" . 224) ;; à + ("á" . 225) ;; á + ("â" . 226) ;; â + ("ã" . 227) ;; ã + ("ä" . 228) ;; ä + ("å" . 229) ;; å + ("æ" . 230) ;; æ + ("ç" . 231) ;; ç + ("è" . 232) ;; è + ("é" . 233) ;; é + ("ê" . 234) ;; ê + ("ë" . 235) ;; ë + ("ì" . 236) ;; ì + ("í" . 237) ;; í + ("î" . 238) ;; î + ("ï" . 239) ;; ï + ("ð" . 240) ;; ð + ("ñ" . 241) ;; ñ + ("ò" . 242) ;; ò + ("ó" . 243) ;; ó + ("ô" . 244) ;; ô + ("õ" . 245) ;; õ + ("ö" . 246) ;; ö + ("÷" . 247) ;; ÷ + ("ø" . 248) ;; ø + ("ù" . 249) ;; ù + ("ú" . 250) ;; ú + ("û" . 251) ;; û + ("ü" . 252) ;; ü + ("ý" . 253) ;; ý + ("þ" . 254) ;; þ + ("ÿ" . 255) ;; ÿ + ("®" . 174) ;; ® + ("­" . 173)) ;; ­ + + "Table of html character entities and values. +See https://www.freeformatter.com/html-entities.html") + +(defvar helm-find-many-files-after-hook nil + "Hook that runs at end of `helm-find-many-files'.") + +;;; Faces. +;; +(defface helm-selection-line + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :inherit highlight :distant-foreground "black")) + "Face used in the `helm-current-buffer' when jumping to a candidate." + :group 'helm-faces) + +(defface helm-match-item + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :inherit isearch)) + "Face used to highlight the item matched in a selected line." + :group 'helm-faces) + + +;;; Utils functions +;; +;; +(defcustom helm-window-prefer-horizontal-split nil + "Maybe switch to other window vertically when non nil. + +Possible values are t, nil and `decide'. + +When t switch vertically. +When nil switch horizontally. +When `decide' try to guess if it is possible to switch vertically +according to the setting of `split-width-threshold' and the size of +the window from where splitting is done. + +Note that when using `decide' and `split-width-threshold' is nil, the +behavior is the same as with a nil value." + :group 'helm-utils + :type '(choice + (const :tag "Split window vertically" t) + (const :tag "Split window horizontally" nil) + (symbol :tag "Guess how to split window" 'decide))) + +(defcustom helm-window-show-buffers-function #'helm-window-default-split-fn + "The default function to use when opening several buffers at once. +It is typically used to rearrange windows." + :group 'helm-utils + :type '(choice + (function :tag "Split windows vertically or horizontally" + helm-window-default-split-fn) + (function :tag "Split in alternate windows" + helm-window-alternate-split-fn) + (function :tag "Split windows in mosaic" + helm-window-mosaic-fn))) + +(defun helm-window-show-buffers (buffers &optional other-window) + "Show BUFFERS. + +With more than one buffer marked switch to these buffers in separate windows. +If OTHER-WINDOW is non-nil, keep current buffer and switch to other buffers +in separate windows. +If a prefix arg is given split windows vertically." + (let ((initial-ow-fn (if (cdr (window-list)) + #'switch-to-buffer-other-window + #'helm-window-other-window))) + (if (cdr buffers) + (funcall helm-window-show-buffers-function buffers + (and other-window initial-ow-fn)) + (if other-window + (funcall initial-ow-fn (car buffers)) + (helm-buffers-switch-to-buffer-or-tab (car buffers)))))) + +(defvar tab-bar-tab-name-function) +(declare-function tab-bar-switch-to-tab "tab-bar.el") +(declare-function tab-bar-tab-name-all "tab-bar.el") + +(defun helm-buffers-switch-to-buffer-or-tab (buffer) + "Switch to BUFFER in its tab if some." + (if (and (fboundp 'tab-bar-mode) + helm-buffers-maybe-switch-to-tab) + (let* ((tab-bar-tab-name-function #'tab-bar-tab-name-all) + (tabs (tab-bar-tabs)) + (tab-names (mapcar (lambda (tab) + (cdr (assq 'name tab))) + tabs)) + (bname (buffer-name (get-buffer buffer))) + (tab (helm-buffers--get-tab-from-name bname tabs))) + (if (helm-buffers--buffer-in-tab-p bname tab-names) + (progn + (tab-bar-switch-to-tab (alist-get 'name tab)) + (select-window (get-buffer-window bname))) + (switch-to-buffer buffer))) + (switch-to-buffer buffer))) + +(defun helm-buffers--get-tab-from-name (tab-name tabs) + "Return tab from TABS when it contains TAB-NAME." + (cl-loop for tab in tabs + when (member tab-name (split-string (cdr (assq 'name tab)) ", " t)) + return tab)) + +(defun helm-buffers--buffer-in-tab-p (buffer-name tab-names) + "Check if BUFFER-NAME is in TAB-NAMES list." + (cl-loop for name in tab-names + ;; Buf names are separated with "," in TAB-NAMES + ;; e.g. '("tab-bar.el" "*scratch*, helm-buffers.el"). + thereis (member buffer-name (split-string name ", " t)))) + +(defun helm-window-default-split-fn (candidates &optional other-window-fn) + "Split windows in one direction and balance them. + +Direction can be controlled via `helm-window-prefer-horizontal-split'. +If a prefix arg is given split windows the other direction. +This function is suitable for `helm-window-show-buffers-function'." + (if other-window-fn + (funcall other-window-fn (car candidates)) + (switch-to-buffer (car candidates))) + (save-selected-window + (cl-loop with nosplit + for b in (cdr candidates) + when nosplit return + (message "Too many buffers to visit simultaneously") + do (condition-case _err + (helm-window-other-window b 'balance) + (error (setq nosplit t) nil))))) + +(defun helm-window-alternate-split-fn (candidates &optional other-window-fn) + "Split windows horizontally and vertically in alternate fashion. + +Direction can be controlled via `helm-window-prefer-horizontal-split'. +If a prefix arg is given split windows the other direction. +This function is suitable for `helm-window-show-buffers-function'." + (if other-window-fn + (funcall other-window-fn (car candidates)) + (switch-to-buffer (car candidates))) + (let (right-side) + (save-selected-window + (cl-loop with nosplit + for b in (cdr candidates) + when nosplit return + (message "Too many buffers to visit simultaneously") + do (condition-case _err + (let ((helm-current-prefix-arg right-side)) + (helm-window-other-window b) + (setq right-side (not right-side))) + (error (setq nosplit t) nil)))))) + +(defun helm-window-mosaic-fn (candidates &optional other-window-fn) + "Make an as-square-as-possible window mosaic of the CANDIDATES buffers. + +If rectangular, the long side is in the direction given by +`helm-window-prefer-horizontal-split': if non-nil, it is horizontal, vertical +otherwise. +If OTHER-WINDOW-FN is non-nil, current windows are included in the mosaic. +This function is suitable for `helm-window-show-buffers-function'." + (when other-window-fn + (setq candidates (append (mapcar 'window-buffer (window-list)) candidates))) + (delete-other-windows) + (let* ((helm-window-prefer-horizontal-split + (if (eq helm-window-prefer-horizontal-split 'decide) + (and (numberp split-width-threshold) + (>= (window-width (selected-window)) + split-width-threshold)) + helm-window-prefer-horizontal-split)) + mosaic-length-tile-count + mosaic-width-tile-count + mosaic-length-tile-size + mosaic-width-tile-size + next-window) + ;; If 4 tiles, make 2x2 mosaic. + ;; If 5-6 tiles, make 2x3 mosaic with direction depending on `helm-window-prefer-horizontal-split'. + ;; If 7-9 tiles, make 3x3 mosaic. And so on. + (setq mosaic-length-tile-count (ceiling (sqrt (length candidates)))) + (setq mosaic-width-tile-count + (if (<= (length candidates) (* mosaic-length-tile-count (1- mosaic-length-tile-count))) + (1- mosaic-length-tile-count) + mosaic-length-tile-count)) + ;; We lower-bound the tile size, otherwise the function would + ;; fail during the first inner split. + ;; There is consequently no need to check for errors when + ;; splitting. + (let ((frame-mosaic-length-direction-size (frame-height)) + (frame-mosaic-width-direction-size (frame-width)) + (window-mosaic-length-direction-min-size window-min-height) + (window-mosaic-width-direction-min-size window-min-width)) + (if helm-window-prefer-horizontal-split + (setq frame-mosaic-length-direction-size (frame-width) + frame-mosaic-width-direction-size (frame-height) + window-mosaic-length-direction-min-size window-min-width + window-mosaic-width-direction-min-size window-min-height)) + (setq mosaic-length-tile-size (max + (/ frame-mosaic-length-direction-size mosaic-length-tile-count) + window-mosaic-length-direction-min-size) + mosaic-width-tile-size (max + (/ frame-mosaic-width-direction-size mosaic-width-tile-count) + window-mosaic-width-direction-min-size)) + ;; Shorten `candidates' to `max-tiles' elements. + (let ((max-tiles (* (/ frame-mosaic-length-direction-size mosaic-length-tile-size) + (/ frame-mosaic-width-direction-size mosaic-width-tile-size)))) + (when (> (length candidates) max-tiles) + (message "Too many buffers to visit simultaneously") + (setcdr (nthcdr (- max-tiles 1) candidates) nil)))) + ;; Make the mosaic. + (while candidates + (when (> (length candidates) mosaic-length-tile-count) + (setq next-window (split-window nil + mosaic-width-tile-size + (not helm-window-prefer-horizontal-split)))) + (switch-to-buffer (pop candidates)) + (dotimes (_ (min (1- mosaic-length-tile-count) (length candidates))) + (select-window (split-window nil + mosaic-length-tile-size + helm-window-prefer-horizontal-split)) + (switch-to-buffer (pop candidates))) + (when next-window + (select-window next-window))))) + +(defun helm-window-other-window (buffer-or-name &optional balance) + "Switch to BUFFER-OR-NAME in other window. +Direction can be controlled via `helm-window-prefer-horizontal-split'. +If a prefix arg is given split windows the other direction. +When argument BALANCE is provided `balance-windows'." + (let* ((helm-window-prefer-horizontal-split + (if (eq helm-window-prefer-horizontal-split 'decide) + (and (numberp split-width-threshold) + (>= (window-width (selected-window)) + split-width-threshold)) + helm-window-prefer-horizontal-split)) + (right-side (if helm-window-prefer-horizontal-split + (not helm-current-prefix-arg) + helm-current-prefix-arg))) + (select-window (split-window nil nil right-side)) + (and balance (balance-windows)) + (switch-to-buffer buffer-or-name))) + +(cl-defun helm-current-buffer-narrowed-p (&optional + (buffer helm-current-buffer)) + "Check if BUFFER is narrowed. +Default is `helm-current-buffer'." + (with-current-buffer buffer + (let ((beg (point-min)) + (end (point-max)) + (total (buffer-size))) + (or (/= beg 1) (/= end (1+ total)))))) + +(defun helm-goto-char (loc) + "Go to char, revealing if necessary." + (goto-char loc) + (let ((fn (cond ((eq major-mode 'org-mode) + ;; On some old Emacs versions org may not be loaded. + (require 'org) + #'org-reveal) + ((and (boundp 'outline-minor-mode) + outline-minor-mode) + #'outline-show-subtree) + ((and (boundp 'hs-minor-mode) + hs-minor-mode) + #'hs-show-block) + ((and (boundp 'markdown-mode-map) + (derived-mode-p 'markdown-mode)) + #'markdown-show-entry))) + (hs-show-hook (list (lambda () (goto-char loc))))) + ;; outline may fail in some conditions e.g. with markdown enabled + ;; (Bug#1919). + (condition-case-unless-debug nil + (and fn (funcall fn)) + (error nil)))) + +(defun helm-goto-line (lineno &optional noanim) + "Goto LINENO opening only outline headline if needed. +Animation is used unless NOANIM is non--nil." + (helm-log-run-hook "helm-goto-line" + 'helm-goto-line-before-hook) + (helm-match-line-cleanup) + (unless helm-alive-p + (with-helm-current-buffer + (unless helm-yank-point (setq helm-yank-point (point))))) + (goto-char (point-min)) + (helm-goto-char (point-at-bol lineno)) + (unless noanim + (helm-highlight-current-line))) + +(defun helm-save-pos-to-register-before-jump () + "Save current buffer position to `helm-save-pos-before-jump-register'. +To use this add it to `helm-goto-line-before-hook'." + (with-helm-current-buffer + (unless helm-in-persistent-action + (point-to-register helm-save-pos-before-jump-register)))) + +(defun helm-save-current-pos-to-mark-ring () + "Save current buffer position to mark ring. +To use this add it to `helm-goto-line-before-hook'." + (with-helm-current-buffer + (unless helm-in-persistent-action + (set-marker (mark-marker) (point)) + (push-mark (point) 'nomsg)))) + +(defun helm-displaying-source-names () + "Return the list of sources name for this helm session." + (with-current-buffer helm-buffer + (goto-char (point-min)) + (cl-loop with pos + while (setq pos (next-single-property-change (point) 'helm-header)) + do (goto-char pos) + collect (buffer-substring-no-properties (point-at-bol)(point-at-eol)) + do (forward-line 1)))) + +(defun helm-handle-winner-boring-buffers () + "Add `helm-buffer' to `winner-boring-buffers' when quitting/exiting helm. +Add this function to `helm-cleanup-hook' when you don't want to see helm buffers +after running winner-undo/redo." + (require 'winner) + (cl-pushnew helm-buffer winner-boring-buffers :test 'equal)) +(add-hook 'helm-cleanup-hook #'helm-handle-winner-boring-buffers) + +(defun helm-quit-and-find-file () + "Drop into `helm-find-files' from `helm'. +If current selection is a buffer or a file, `helm-find-files' +from its directory." + (interactive) + (with-helm-alive-p + (require 'helm-grep) + (require 'helm-elisp) + (require 'bookmark) ; For bookmark-alist + (let ((src (helm-get-current-source))) + (helm-run-after-exit + (lambda (f) + ;; Ensure specifics `helm-execute-action-at-once-if-one' + ;; fns don't run here. + (let (helm-execute-action-at-once-if-one + helm-actions-inherit-frame-settings) ; use this-command + (if (file-exists-p f) + (helm-find-files-1 (file-name-directory f) + (format + helm-ff-last-expanded-candidate-regexp + (regexp-quote + (if helm-ff-transformer-show-only-basename + (helm-basename f) f)))) + (helm-find-files-1 f)))) + (helm--quit-and-find-file-default-file src))))) +(put 'helm-quit-and-find-file 'helm-only t) + +(defun helm--quit-and-find-file-default-file (source) + (let ((target-fn (helm-get-attr 'find-file-target))) + ;; target-fn function may return nil, in this case fallback to default. + (helm-aif (and target-fn (funcall target-fn source)) + it + (let* ((sel (helm-get-selection nil nil source)) + (default-preselection (or (helm-default-directory) + (buffer-file-name helm-current-buffer) + default-directory))) + (cond + ((and (stringp sel) (or (file-remote-p sel) + (file-exists-p sel))) + (expand-file-name sel)) + ;; Url. + ((and (stringp sel) + helm--url-regexp + (string-match helm--url-regexp sel)) + sel) + ;; Exit brutally from a `with-helm-show-completion' + ((and helm-show-completion-overlay + (overlayp helm-show-completion-overlay)) + (delete-overlay helm-show-completion-overlay) + (remove-hook 'helm-move-selection-after-hook 'helm-show-completion) + (expand-file-name default-preselection)) + ;; Default. + (t (expand-file-name default-preselection))))))) + +(defun helm-generic-sort-fn (s1 s2) + "Sort predicate function for helm candidates. +Args S1 and S2 can be single or (display . real) candidates, +that is sorting is done against real value of candidate." + (let* ((qpattern (regexp-quote helm-pattern)) + (reg1 (concat "\\_<" qpattern "\\_>")) + (reg2 (concat "\\_<" qpattern)) + (reg3 helm-pattern) + (split (helm-remove-if-match + "\\`!" (helm-mm-split-pattern helm-pattern))) + (str1 (if (consp s1) (cdr s1) s1)) + (str2 (if (consp s2) (cdr s2) s2)) + (score (lambda (str r1 r2 r3 lst) + (+ (if (string-match (concat "\\`" qpattern) str) 1 0) + (cond ((string-match r1 str) 5) + ((and (string-match " " qpattern) + (string-match + (concat "\\_<" (regexp-quote (car lst))) str) + (cl-loop for r in (cdr lst) + always (string-match r str))) + 4) + ((and (string-match " " qpattern) + (cl-loop for r in lst + always (string-match r str))) + 3) + ((string-match r2 str) 2) + ((string-match r3 str) 1) + (t 0))))) + (sc1 (get-text-property 0 'completion-score str1)) + (sc2 (get-text-property 0 'completion-score str2)) + (sc3 (if sc1 0 (funcall score str1 reg1 reg2 reg3 split))) + (sc4 (if sc2 0 (funcall score str2 reg1 reg2 reg3 split)))) + (cond ((and sc1 sc2) ; helm-flex style. + (> sc1 sc2)) + ((or (zerop (string-width qpattern)) + (and (zerop sc3) (zerop sc4))) + (string-lessp str1 str2)) + ((= sc3 sc4) + (< (length str1) (length str2))) + (t (> sc3 sc4))))) + +(cl-defun helm-file-human-size (size &optional (kbsize helm-default-kbsize)) + "Return a string showing SIZE of a file in human readable form. +SIZE can be an integer or a float depending on it's value. +`file-attributes' will take care of that to avoid overflow error. +KBSIZE is a floating point number, defaulting to `helm-default-kbsize'." + (cl-loop with result = (cons "B" size) + for i in '("k" "M" "G" "T" "P" "E" "Z" "Y") + while (>= (cdr result) kbsize) + do (setq result (cons i (/ (cdr result) kbsize))) + finally return + (helm-acase (car result) + ("B" (format "%s" size)) + (t (format "%.1f%s" (cdr result) it))))) + +(defun helm-directory-size (directory &optional recursive human) + "Return the resulting size of the sum of all files in DIRECTORY. + +If RECURSIVE is non nil return the size of all files in DIRECTORY and +its subdirectories. With arg HUMAN format the size in a human +readable format,see `helm-file-human-size'." + (cl-loop with files = (if recursive + (helm-walk-directory + directory + :path 'full + :directories t) + (directory-files directory t)) + for file in files + sum (nth 7 (file-attributes file)) into total + finally return (if human + (helm-file-human-size total) + total))) + +(cl-defun helm-file-attributes + (file &key type links uid gid access-time modif-time + status size mode gid-change inode device-num dired human-size + mode-type mode-owner mode-group mode-other octal (string t)) + "Return `file-attributes' elements of FILE separately according to key value. +Availables keys are: +- TYPE: Same as nth 0 `files-attributes' if STRING is nil + otherwise return either symlink, directory or file (default). +- LINKS: See nth 1 `files-attributes'. +- UID: See nth 2 `files-attributes'. +- GID: See nth 3 `files-attributes'. +- ACCESS-TIME: See nth 4 `files-attributes', however format time + when STRING is non--nil (the default). +- MODIF-TIME: See nth 5 `files-attributes', same as above. +- STATUS: See nth 6 `files-attributes', same as above. +- SIZE: See nth 7 `files-attributes'. +- MODE: See nth 8 `files-attributes'. +- GID-CHANGE: See nth 9 `files-attributes'. +- INODE: See nth 10 `files-attributes'. +- DEVICE-NUM: See nth 11 `files-attributes'. +- DIRED: A line similar to what \\='ls -l' return. +- HUMAN-SIZE: The size in human form, see `helm-file-human-size'. +- MODE-TYPE, mode-owner,mode-group, mode-other: Split what + nth 8 `files-attributes' return in four categories. +- OCTAL: The octal value of MODE-OWNER+MODE-GROUP+MODE-OTHER. +- STRING: When non--nil (default) `helm-file-attributes' return + more friendly values. +If you want the same behavior as `files-attributes' , +\(but with return values in proplist) use a nil value for STRING. +However when STRING is non--nil, time and type value are different from what +you have in `file-attributes'." + (helm-aif (file-attributes file string) + (let* ((all (cl-destructuring-bind + (type links uid gid access-time modif-time + status size mode gid-change inode device-num) + it + (list :type (if string + (cond ((stringp type) "symlink") ; fname + (type "directory") ; t + (t "file")) ; nil + type) + :links links + :uid uid + :gid gid + :access-time (if string + (format-time-string + "%Y-%m-%d %R" access-time) + access-time) + :modif-time (if string + (format-time-string + "%Y-%m-%d %R" modif-time) + modif-time) + :status (if string + (format-time-string + "%Y-%m-%d %R" status) + status) + :size size + :mode mode + :gid-change gid-change + :inode inode + :device-num device-num))) + (perms (cl-getf all :mode)) + (modes (helm-split-mode-file-attributes perms))) + (cond (type (cl-getf all :type)) + (links (cl-getf all :links)) + (uid (cl-getf all :uid)) + (gid (cl-getf all :gid)) + (access-time (cl-getf all :access-time)) + (modif-time (cl-getf all :modif-time)) + (status (cl-getf all :status)) + (size (cl-getf all :size)) + (mode perms) + (gid-change (cl-getf all :gid-change)) + (inode (cl-getf all :inode)) + (device-num (cl-getf all :device-num)) + (dired (helm-file-attributes-dired-line all human-size)) + (human-size (helm-file-human-size (cl-getf all :size))) + (mode-type (cl-getf modes :mode-type)) + (mode-owner (cl-getf modes :user)) + (mode-group (cl-getf modes :group)) + (mode-other (cl-getf modes :other)) + (octal (cl-getf modes :octal)) + (t (append all modes)))))) + +(defun helm-file-attributes-dired-line (all &optional human-size) + (format "%s %s %s:%s %s %s" + (helm-split-mode-file-attributes + (cl-getf all :mode) t) + (number-to-string (cl-getf all :links)) + (cl-getf all :uid) + (cl-getf all :gid) + (if human-size + (helm-file-human-size (cl-getf all :size)) + (int-to-string (cl-getf all :size))) + (cl-getf all :modif-time))) + +(defun helm-split-mode-file-attributes (modes &optional string) + "Split MODES in a list of modes. +MODES is same as what (nth 8 (file-attributes \"foo\")) would return." + (if (string-match "\\`\\(.\\)\\(...\\)\\(...\\)\\(...\\)\\'" modes) + (let* ((type (match-string 1 modes)) + (user (match-string 2 modes)) + (group (match-string 3 modes)) + (other (match-string 4 modes)) + (octal (helm-ff-numeric-permissions (list user group other)))) + (if string + (mapconcat 'identity (list type user group other octal) " ") + (list :mode-type type :user user + :group group :other other + :octal octal))) + (error "Wrong modes specification for %s" modes))) + +(defun helm-ff-numeric-permissions (perms) + "Return the numeric representation of PERMS. +PERMS is the list of permissions for owner, group and others." + ;; `file-modes-symbolic-to-number' interpret its MODES argument as what would + ;; result when calling such mode on a file with chmod, BTW we have to remove + ;; all "-" like read-file-modes does. + (helm-aand (listp perms) + (apply 'format "u=%s,g=%s,o=%s" perms) + (replace-regexp-in-string "-" "" it) + (format "%o" (file-modes-symbolic-to-number it)))) + +(defun helm-format-columns-of-files (files) + "Same as `dired-format-columns-of-files'. +Inlined here for compatibility." + (let ((beg (point))) + (completion--insert-strings files) + (put-text-property beg (point) 'mouse-face nil))) + +(defmacro with-helm-display-marked-candidates (buffer-or-name candidates &rest body) + (declare (indent 0) (debug t)) + (helm-with-gensyms (buffer window winconf) + `(let* ((,buffer (temp-buffer-window-setup ,buffer-or-name)) + (,winconf helm-last-frame-or-window-configuration) + (helm-always-two-windows t) + (helm-split-window-default-side + (if (eq helm-split-window-default-side 'same) + 'below helm-split-window-default-side)) + helm-split-window-inside-p + helm-reuse-last-window-split-state + ,window) + (with-current-buffer ,buffer + (helm-format-columns-of-files ,candidates)) + (unwind-protect + (with-selected-window + (setq ,window (temp-buffer-window-show + ,buffer + '(display-buffer-below-selected + (window-height . fit-window-to-buffer)))) + (progn ,@body)) + (quit-window 'kill ,window) + (and ,winconf (set-window-configuration ,winconf)))))) + +;;; Persistent Action Helpers +;; +;; +;; Internal +(defvar helm-match-line-overlay nil) +(defvar helm--match-item-overlays nil) + +(cl-defun helm-highlight-current-line (&optional start end buf face) + "Highlight current line and all matching items around it. + +The number of lines around matched line where the matching items are +highlighted are defined by `helm-highlight-matches-around-point-max-lines'. +When the variable `helm-highlight-only-all-matches' is non nil only +the lines containing all matches (in case of multi match) are highlighted. + +Optional arguments START, END and FACE are only here for debugging purpose." + (let* ((start (or start (line-beginning-position))) + (end (or end (1+ (line-end-position)))) + start-match end-match + (args (list start end buf)) + (case-fold-search (if helm-alive-p + (helm-set-case-fold-search) + case-fold-search))) + ;; Highlight the current line. + (if (not helm-match-line-overlay) + (setq helm-match-line-overlay (apply 'make-overlay args)) + (apply 'move-overlay helm-match-line-overlay args)) + (overlay-put helm-match-line-overlay + 'face (or face 'helm-selection-line)) + ;; Now highlight matches only if we are in helm session, we are + ;; maybe coming from helm-grep-mode or helm-moccur-mode buffers. + (when helm-alive-p + (cond (;; These 2 clauses have to be the first otherwise + ;; `helm-highlight-matches-around-point-max-lines' is + ;; compared as a number by other clauses and return an error. + (eq helm-highlight-matches-around-point-max-lines 'never) + (cl-return-from helm-highlight-current-line)) + ((consp helm-highlight-matches-around-point-max-lines) + (setq start-match + (save-excursion + (forward-line + (- (car helm-highlight-matches-around-point-max-lines))) + (point-at-bol)) + end-match + (save-excursion + (forward-line + (cdr helm-highlight-matches-around-point-max-lines)) + (point-at-bol)))) + ((or (null helm-highlight-matches-around-point-max-lines) + (zerop helm-highlight-matches-around-point-max-lines)) + (setq start-match start + end-match end)) + ((< helm-highlight-matches-around-point-max-lines 0) + (setq start-match + (save-excursion + (forward-line + helm-highlight-matches-around-point-max-lines) + (point-at-bol)) + end-match start)) + ((> helm-highlight-matches-around-point-max-lines 0) + (setq start-match start + end-match + (save-excursion + (forward-line + helm-highlight-matches-around-point-max-lines) + (point-at-bol))))) + (catch 'empty-line + (let* ((regex-list (helm-remove-if-match + "\\`!" (helm-mm-split-pattern + (if (with-helm-buffer + ;; Needed for highlighting AG matches. + (assq 'pcre (helm-get-current-source))) + (helm--translate-pcre-to-elisp helm-input) + helm-input)))) + (num-regex (length regex-list))) + (save-excursion + (goto-char start-match) + (while (< (point) end-match) + (let* ((start-line (line-beginning-position)) + (end-line (line-end-position)) + all-matches) + (dolist (r regex-list) + (let ((match-list '())) + (save-excursion + (goto-char start-line) + (while (condition-case _err + (and (not (= start-line end-line)) + (if helm-migemo-mode + (helm-mm-migemo-forward r end-line t) + (re-search-forward r end-line t))) + (invalid-regexp nil)) + (let ((s (match-beginning 0)) + (e (match-end 0))) + (if (= s e) + (throw 'empty-line nil) + (push (cons s e) match-list))))) + (when match-list + (push match-list all-matches)))) + (when (and all-matches + (or (not helm-highlight-only-all-matches) + (eql (length all-matches) num-regex))) + (cl-loop for ml in all-matches + do (cl-loop for (s . e) in ml + for ov = (make-overlay s e) + do (progn + (push ov helm--match-item-overlays) + (overlay-put ov 'face 'helm-match-item) + (overlay-put ov 'priority 1)))))) + (forward-line 1)))))) + (recenter))) + +(defun helm--translate-pcre-to-elisp (regexp) + "Should translate pcre REGEXP to elisp regexp. +Assume regexp is a pcre based regexp." + (with-temp-buffer + (insert " " regexp " ") + (goto-char (point-min)) + (save-excursion + ;; match (){}| unquoted + (helm-awhile (and (re-search-forward "\\([(){}|]\\)" nil t) + (match-string 1)) + (let ((pos (match-beginning 1))) + (if (eql (char-before pos) ?\\) + (delete-region pos (1- pos)) + (replace-match (concat "\\" it) t t nil 1))))) + ;; match \s or \S + (helm-awhile (and (re-search-forward "\\S\\?\\(\\s\\[sS]\\)[^-]" nil t) + (match-string 1)) + (replace-match (concat it "-") t t nil 1)) + (buffer-substring (1+ (point-min)) (1- (point-max))))) + +(defun helm-match-line-cleanup () + (when helm-match-line-overlay + (delete-overlay helm-match-line-overlay) + (setq helm-match-line-overlay nil)) + (when helm--match-item-overlays + (mapc 'delete-overlay helm--match-item-overlays))) + +(defun helm-match-line-cleanup-maybe () + (when (helm-empty-buffer-p) + (helm-match-line-cleanup))) + +(defun helm-match-line-update () + (when helm--match-item-overlays + (mapc 'delete-overlay helm--match-item-overlays)) + (when helm-match-line-overlay + (delete-overlay helm-match-line-overlay) + (helm-highlight-current-line))) + +(defun helm-persistent-autoresize-hook () + (when (and helm-buffers-to-resize-on-pa + (member helm-buffer helm-buffers-to-resize-on-pa) + (eq helm-split-window-state 'vertical)) + (set-window-text-height (helm-window) helm-resize-on-pa-text-height))) + +(defun helm-match-line-cleanup-pulse () + (run-with-timer 0.3 nil #'helm-match-line-cleanup)) + +(add-hook 'helm-after-update-hook 'helm-match-line-cleanup-maybe) +(add-hook 'helm-after-persistent-action-hook 'helm-persistent-autoresize-hook) +(add-hook 'helm-cleanup-hook 'helm-match-line-cleanup) +(add-hook 'helm-after-action-hook 'helm-match-line-cleanup-pulse) +(add-hook 'helm-after-persistent-action-hook 'helm-match-line-update) + +;;; Popup buffer-name or filename in grep/moccur/imenu-all. +;; +(defvar helm--show-help-echo-timer nil) + +(defun helm-cancel-help-echo-timer () + (when helm--show-help-echo-timer + (cancel-timer helm--show-help-echo-timer) + (setq helm--show-help-echo-timer nil))) + +(defun helm-maybe-show-help-echo () + (when helm--show-help-echo-timer + (cancel-timer helm--show-help-echo-timer) + (setq helm--show-help-echo-timer nil)) + (when (and helm-alive-p + helm-popup-tip-mode + (member (assoc-default 'name (helm-get-current-source)) + helm-sources-using-help-echo-popup)) + (setq helm--show-help-echo-timer + (run-with-timer + 1 nil + (lambda () + (save-selected-window + (with-helm-window + (helm-aif (get-text-property (point-at-bol) 'help-echo) + (popup-tip (concat " " (abbreviate-file-name + (replace-regexp-in-string "\n.*" "" it))) + :around nil + :point (save-excursion + (end-of-visual-line) (point))))))))))) + +;;;###autoload +(define-minor-mode helm-popup-tip-mode + "Show help-echo informations in a popup tip at end of line." + :global t + (require 'popup) + (if helm-popup-tip-mode + (progn + (add-hook 'helm-move-selection-after-hook 'helm-maybe-show-help-echo) + (add-hook 'helm-cleanup-hook 'helm-cancel-help-echo-timer)) + (remove-hook 'helm-move-selection-after-hook 'helm-maybe-show-help-echo) + (remove-hook 'helm-cleanup-hook 'helm-cancel-help-echo-timer))) + +(defun helm-open-file-with-default-tool (file) + "Open FILE with the default tool on this platform." + (let (process-connection-type) + (if (eq system-type 'windows-nt) + (helm-w32-shell-execute-open-file file) + (start-process "helm-open-file-with-default-tool" + nil + (cond ((eq system-type 'gnu/linux) + "xdg-open") + ((or (eq system-type 'darwin) ;; Mac OS X + (eq system-type 'macos)) ;; Mac OS 9 + "open")) + file)))) + +(defun helm-open-dired (file) + "Open a dired buffer in FILE's directory. +If FILE is a directory, open this directory." + (require 'dired) + (if (file-directory-p file) + (dired file) + (dired (file-name-directory file)) + (dired-goto-file file))) + +(defun helm-find-file-as-root (candidate) + (let* ((buf (helm-basename candidate)) + (host (file-remote-p candidate 'host)) + (remote-path (format "/%s:%s:%s" + helm-su-or-sudo + (or host "") + (expand-file-name + (if host + (file-remote-p candidate 'localname) + candidate)))) + non-essential) + (if (buffer-live-p (get-buffer buf)) + (progn + (set-buffer buf) + (find-alternate-file remote-path)) + (find-file remote-path)))) + +(defun helm-find-many-files (_ignore) + "Simple action that run `find-file' on marked candidates. +Run `helm-find-many-files-after-hook' at end." + (let ((helm--reading-passwd-or-string t)) + (mapc 'find-file (helm-marked-candidates)) + (helm-log-run-hook "helm-find-many-files" + 'helm-find-many-files-after-hook))) + +(defun helm-read-repeat-string (prompt &optional count) + "Prompt as many time PROMPT is not empty. +If COUNT is non--nil add a number after each prompt." + (cl-loop with elm + while (not (string= elm "")) + for n from 1 + do (when count + (setq prompt (concat prompt (int-to-string n) ": "))) + collect (setq elm (helm-read-string prompt)) into lis + finally return (remove "" lis))) + +(defun helm-html-bookmarks-to-alist (file url-regexp bmk-regexp) + "Parse HTML bookmark FILE and return an alist with (title . url) as elements." + (let (bookmarks-alist url title) + (with-temp-buffer + (insert-file-contents file) + (goto-char (point-min)) + (while (re-search-forward "href=\\|^ *
. + +;;; Commentary: + +;;; Code: + +(require 'helm-for-files) + + +;;; List of files gleaned from every dired buffer +;; +;; +(defvar dired-buffers) +(defvar directory-files-no-dot-files-regexp) +(defun helm-files-in-all-dired-candidates () + "Return a list of files from live `dired' buffers." + (save-excursion + (cl-loop for (f . b) in dired-buffers + when (buffer-live-p b) + append (let ((dir (with-current-buffer b dired-directory))) + (if (listp dir) (cdr dir) + (directory-files f t directory-files-no-dot-files-regexp)))))) + +;; (dired '("~/" "~/.emacs.d/.emacs-custom.el" "~/.emacs.d/.emacs.bmk")) + +(defclass helm-files-dired-source (helm-source-sync helm-type-file) + ((candidates :initform #'helm-files-in-all-dired-candidates))) + +(defvar helm-source-files-in-all-dired + (helm-make-source "Files in all dired buffer." 'helm-files-dired-source)) + +;;; session.el files +;; +;; session (http://emacs-session.sourceforge.net/) is an alternative to +;; recentf that saves recent file history and much more. +(defvar session-file-alist) +(defclass helm-source-session-class (helm-source-sync) + ((candidates :initform (lambda () + (cl-delete-if-not + (lambda (f) + (or (string-match helm-tramp-file-name-regexp f) + (file-exists-p f))) + (mapcar 'car session-file-alist)))) + (keymap :initform 'helm-generic-files-map) + (help-message :initform 'helm-generic-file-help-message) + (action :initform 'helm-type-file-actions))) + +(defvar helm-source-session nil + "File list from emacs-session.") + +(defcustom helm-session-fuzzy-match nil + "Enable fuzzy matching in `helm-source-session' when non--nil." + :group 'helm-files + :type 'boolean + :set (lambda (var val) + (set var val) + (setq helm-source-session + (helm-make-source "Session" 'helm-source-session-class + :fuzzy-match val)))) + + +;;; External searching file tools. +;; +;; Tracker desktop search + +(defun helm-source-tracker-transformer (candidates _source) + "Return file names from tracker CANDIDATES." + ;; loop through tracker candidates selecting out file:// lines + ;; then select part after file:// and url decode to get straight filenames + (cl-loop for cand in candidates + when (and (stringp cand) + (string-match "\\`[[:space:]]*file://\\(.*\\)" cand)) + collect (url-unhex-string (match-string 1 cand)))) + +(defvar helm-source-tracker-search + (helm-build-async-source "Tracker Search" + :candidates-process + (lambda () + ;; the tracker-search command has been deprecated, now invoke via tracker + ;; also, disable the contextual snippets which we don't currently use + (start-process "tracker-search-process" nil + "tracker" "search" + "--disable-snippets" + "--disable-color" + "--limit=512" + helm-pattern)) + ;; new simplified transformer of tracker search results + :filtered-candidate-transformer #'helm-source-tracker-transformer + ;;(multiline) ; https://github.com/emacs-helm/helm/issues/529 + :keymap helm-generic-files-map + :action 'helm-type-file-actions + :action-transformer '(helm-transform-file-load-el + helm-transform-file-browse-url) + :requires-pattern 3) + "Source for the Tracker desktop search engine.") + +;; Spotlight (MacOS X desktop search) +(defclass helm-mac-spotlight-source (helm-source-async helm-type-file) + ((candidates-process :initform + (lambda () + (start-process + "mdfind-process" nil "mdfind" helm-pattern))) + (requires-pattern :initform 3))) + +(defvar helm-source-mac-spotlight + (helm-make-source "mdfind" 'helm-mac-spotlight-source) + "Source for retrieving files via Spotlight's command line utility mdfind.") + +(provide 'helm-x-files) + +;;; helm-x-files.el ends here diff --git a/org/elpa/helm-20230406.839/helm.el b/org/elpa/helm-20230406.839/helm.el new file mode 100644 index 0000000..0140bdf --- /dev/null +++ b/org/elpa/helm-20230406.839/helm.el @@ -0,0 +1,43 @@ +;;; helm.el --- Helm is an Emacs incremental and narrowing framework -*- lexical-binding: t -*- + +;; Copyright (C) 2007 Tamas Patrovics +;; 2008 ~ 2011 rubikitch +;; 2011 ~ 2023 Thierry Volpiatto + +;; This is a fork of anything.el wrote by Tamas Patrovics. + +;; Authors of anything.el: Tamas Patrovics +;; rubikitch +;; Thierry Volpiatto + +;; Author: Thierry Volpiatto +;; Version: 3.9.0 +;; URL: https://emacs-helm.github.io/helm/ +;; Package-Requires: ((helm-core "3.9.0") (popup "0.5.3")) + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; This is just a wrapper for helm-core.el and a place holder we +;; currently use only to hold the package's metadata in the header. + +;;; Code: + +(require 'helm-core) +(require 'helm-global-bindings) + +(provide 'helm) + +;;; helm.el ends here diff --git a/org/elpa/helm-core-20230317.1729/helm-core-autoloads.el b/org/elpa/helm-core-20230317.1729/helm-core-autoloads.el new file mode 100644 index 0000000..7a2f97c --- /dev/null +++ b/org/elpa/helm-core-20230317.1729/helm-core-autoloads.el @@ -0,0 +1,264 @@ +;;; helm-core-autoloads.el --- automatically extracted autoloads -*- lexical-binding: t -*- +;; +;;; Code: + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + + +;;;### (autoloads nil "helm-core" "helm-core.el" (0 0 0 0)) +;;; Generated autoloads from helm-core.el + +(autoload 'helm-define-multi-key "helm-core" "\ +In KEYMAP, define key sequence KEY for function list FUNCTIONS. +Each function runs sequentially for each KEY press. +If DELAY is specified, switch back to initial function of FUNCTIONS list +after DELAY seconds. +The functions in FUNCTIONS list take no args. +E.g. + (defun foo () + (interactive) + (message \"Run foo\")) + (defun bar () + (interactive) + (message \"Run bar\")) + (defun baz () + (interactive) + (message \"Run baz\")) + +\(helm-define-multi-key global-map (kbd \" q\") \\='(foo bar baz) 2) + +Each time \" q\" is pressed, the next function is executed. +Waiting more than 2 seconds between key presses switches back to +executing the first function on the next hit. + +\(fn KEYMAP KEY FUNCTIONS &optional DELAY)" nil nil) + +(autoload 'helm-multi-key-defun "helm-core" "\ +Define NAME as a multi-key command running FUNS. +After DELAY seconds, the FUNS list is reinitialized. +See `helm-define-multi-key'. + +\(fn NAME DOCSTRING FUNS &optional DELAY)" nil t) + +(function-put 'helm-multi-key-defun 'lisp-indent-function '2) + +(autoload 'helm-define-key-with-subkeys "helm-core" "\ +Define in MAP a KEY and SUBKEY to COMMAND. + +This allows typing KEY to call COMMAND the first time and +type only SUBKEY on subsequent calls. + +Arg MAP is the keymap to use, SUBKEY is the initial short +key binding to call COMMAND. + +Arg OTHER-SUBKEYS is an alist specifying other short key bindings +to use once started, e.g.: + + (helm-define-key-with-subkeys global-map + (kbd \"C-x v n\") ?n \\='git-gutter:next-hunk + \\='((?p . git-gutter:previous-hunk))) + +In this example, `C-x v n' will run `git-gutter:next-hunk' +subsequent \"n\" will run this command again and subsequent \"p\" +will run `git-gutter:previous-hunk'. + +If specified PROMPT can be displayed in minibuffer to describe +SUBKEY and OTHER-SUBKEYS. Arg EXIT-FN specifies a function to run +on exit. + +For any other key pressed, run their assigned command as defined +in MAP and then exit the loop running EXIT-FN, if specified. + +If DELAY an integer is specified exit after DELAY seconds. + +NOTE: SUBKEY and OTHER-SUBKEYS bindings support only char syntax +and vectors, so don't use strings to define them. While defining +or executing a kbd macro no SUBKEY or OTHER-SUBKEYS are provided, +i.e. the loop is not entered after running COMMAND. + +\(fn MAP KEY SUBKEY COMMAND &optional OTHER-SUBKEYS PROMPT EXIT-FN DELAY DOCSTRING)" nil nil) + +(function-put 'helm-define-key-with-subkeys 'lisp-indent-function '1) + +(autoload 'helm-configuration "helm-core" "\ +Customize Helm." t nil) + +(autoload 'helm-debug-open-last-log "helm-core" "\ +Open Helm log file or buffer of last Helm session." t nil) + +(autoload 'helm "helm-core" "\ +Main function to execute helm sources. + +PLIST is a list like + +\(:key1 val1 :key2 val2 ...) + + or + +\(&optional sources input prompt resume preselect + buffer keymap default history allow-nest). + +** Keywords + +Keywords supported: + +- :sources +- :input +- :prompt +- :resume +- :preselect +- :buffer +- :keymap +- :default +- :history +- :allow-nest + +Extra LOCAL-VARS keywords are supported, see the \"** Other +keywords\" section below. + +Basic keywords are the following: + +*** :sources + +One of the following: + +- List of sources +- Symbol whose value is a list of sources +- Alist representing a Helm source. + - In this case the source has no name and is referenced in + `helm-sources' as a whole alist. + +*** :input + +Initial input of minibuffer (temporary value of `helm-pattern') + +*** :prompt + +Minibuffer prompt. Default value is `helm--prompt'. + +*** :resume + +If t, allow resumption of the previous session of this Helm +command, skipping initialization. + +If \\='noresume, this instance of `helm' cannot be resumed. + +*** :preselect + +Initially selected candidate (string or regexp). + +*** :buffer + +Buffer name for this Helm session. `helm-buffer' will take this value. + +*** :keymap + +\[Obsolete] + +Keymap used at the start of this Helm session. + +It is overridden by keymaps specified in sources, and is kept +only for backward compatibility. + +Keymaps should be specified in sources using the :keymap slot +instead. See `helm-source'. + +This keymap is not restored by `helm-resume'. + +*** :default + +Default value inserted into the minibuffer with +\\\\[next-history-element]. + +It can be a string or a list of strings, in this case +\\\\[next-history-element] cycles through +the list items, starting with the first. + +If nil, `thing-at-point' is used. + +If `helm-maybe-use-default-as-input' is non-nil, display is +updated using this value if this value matches, otherwise it is +ignored. If :input is specified, it takes precedence on :default. + +*** :history + +Minibuffer input, by default, is pushed to `minibuffer-history'. + +When an argument HISTORY is provided, input is pushed to +HISTORY. HISTORY should be a valid symbol. + +*** :allow-nest + +Allow running this Helm command in a running Helm session. + +** Other keywords + +Other keywords are interpreted as local variables of this Helm +session. The `helm-' prefix can be omitted. For example, + +\(helm :sources \\='helm-source-buffers-list + :buffer \"*helm buffers*\" + :candidate-number-limit 10) + +Starts a Helm session with the variable +`helm-candidate-number-limit' set to 10. + +** Backward compatibility + +For backward compatibility, positional parameters are +supported: + +\(helm sources input prompt resume preselect + buffer keymap default history allow-nest) + +However, the use of non-keyword args is deprecated. + +\(fn &key SOURCES INPUT PROMPT RESUME PRESELECT BUFFER KEYMAP DEFAULT HISTORY ALLOW-NEST OTHER-LOCAL-VARS)" nil nil) + +(autoload 'helm-cycle-resume "helm-core" "\ +Cycle in `helm-buffers' list and resume when waiting more than 1.2s." t nil) + +(autoload 'helm-other-buffer "helm-core" "\ +Simplified Helm interface with other `helm-buffer'. +Call `helm' only with SOURCES and BUFFER as args. + +\(fn SOURCES BUFFER)" nil nil) + +(register-definition-prefixes "helm-core" '("helm-" "with-helm-")) + +;;;*** + +;;;### (autoloads nil "helm-lib" "helm-lib.el" (0 0 0 0)) +;;; Generated autoloads from helm-lib.el + +(register-definition-prefixes "helm-lib" '("helm-" "with-helm-")) + +;;;*** + +;;;### (autoloads nil "helm-multi-match" "helm-multi-match.el" (0 +;;;;;; 0 0 0)) +;;; Generated autoloads from helm-multi-match.el + +(register-definition-prefixes "helm-multi-match" '("helm-m")) + +;;;*** + +;;;### (autoloads nil "helm-source" "helm-source.el" (0 0 0 0)) +;;; Generated autoloads from helm-source.el + +(register-definition-prefixes "helm-source" '("helm-")) + +;;;*** + +;;;### (autoloads nil nil ("helm-core-pkg.el") (0 0 0 0)) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; coding: utf-8 +;; End: +;;; helm-core-autoloads.el ends here diff --git a/org/elpa/helm-core-20230317.1729/helm-core-pkg.el b/org/elpa/helm-core-20230317.1729/helm-core-pkg.el new file mode 100644 index 0000000..8260c57 --- /dev/null +++ b/org/elpa/helm-core-20230317.1729/helm-core-pkg.el @@ -0,0 +1,11 @@ +(define-package "helm-core" "20230317.1729" "Development files for Helm" + '((emacs "25.1") + (async "1.9.7")) + :commit "e15fd87d85ebb0df9cdd9115257292488c94549f" :authors + '(("Thierry Volpiatto" . "thievol@posteo.net")) + :maintainer + '("Thierry Volpiatto" . "thievol@posteo.net") + :url "https://emacs-helm.github.io/helm/") +;; Local Variables: +;; no-byte-compile: t +;; End: diff --git a/org/elpa/helm-core-20230317.1729/helm-core.el b/org/elpa/helm-core-20230317.1729/helm-core.el new file mode 100644 index 0000000..f1f182a --- /dev/null +++ b/org/elpa/helm-core-20230317.1729/helm-core.el @@ -0,0 +1,7833 @@ +;;; helm-core.el --- Development files for Helm -*- lexical-binding: t; -*- + +;; Copyright (C) 2022 ~ 2023 Thierry Volpiatto + +;; Author: Thierry Volpiatto +;; URL: https://emacs-helm.github.io/helm/ +;; Version: 3.9.0 +;; Package-Requires: ((emacs "25.1") (async "1.9.7")) + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; Contains the main code for Helm. +;; As a package helm-core provides the files helm-core.el, helm-lib.el, +;; helm-source.el and helm-multi-match.el. + +;;; Code: + +(require 'cl-lib) +(require 'async) +(require 'helm-lib) +(require 'helm-multi-match) +(require 'helm-source) + +;; Ensure async-bytecomp is used even with helm-core package. +(declare-function async-bytecomp-package-mode "ext:async-bytecomp.el") +(when (require 'async-bytecomp nil t) + (and (fboundp 'async-bytecomp-package-mode) + (async-bytecomp-package-mode 1))) + +;; Setup completion styles for helm-mode +(helm--setup-completion-styles-alist) + +(declare-function helm-comp-read "helm-mode.el") +(declare-function custom-unlispify-tag-name "cus-edit.el") +(declare-function helm-quit-and-find-file "helm-utils.el") + +(defvar helm-marked-buffer-name) + + +;;; Internal Variables +;; +;; +(defvar helm-source-filter nil + "A list of source names to be displayed. +Other sources won't appear in the search results. +If nil, no filtering is done. +Don't set this directly, use `helm-set-source-filter' during a +Helm session to modify it.") +(defvar helm-saved-action nil + "Saved value of the currently selected action by key.") +(defvar helm-saved-current-source nil + "Value of the current source when the action list is shown.") +(defvar helm-in-persistent-action nil + "Flag whether in persistent-action or not.") +(defvar helm-last-buffer nil + "`helm-buffer' of a previous Helm session.") +(defvar helm-saved-selection nil + "Value of the currently selected object when the action list is shown.") +(defvar helm-sources nil + "[INTERNAL] Value of current sources in use, a list of alists. +The list of sources (symbols or alists) is normalized to alists +in `helm-initialize'.") +(defvar helm-buffer-file-name nil + "Variable `buffer-file-name' when Helm is invoked.") +(defvar helm-candidate-cache (make-hash-table :test 'equal) + "Holds the available candidate within a single Helm invocation.") +(defvar helm--candidate-buffer-alist nil) +(defvar helm-input "" + "The input typed in the candidates panel.") +(defvar helm-input-local nil + "Internal, store locally `helm-pattern' value for later use in `helm-resume'.") +(defvar helm--source-name nil) +(defvar helm-current-source nil) +(defvar helm-issued-errors nil) +(defvar helm--last-log-file nil + "The name of the log file of the last Helm session.") +(defvar helm--local-variables nil) +(defvar helm-split-window-state nil) +(defvar helm--window-side-state nil) +(defvar helm-selection-point nil + "The value of point at selection.") +(defvar helm-alive-p nil) +(defvar helm-visible-mark-overlays nil) +(defvar helm-update-blacklist-regexps '("^" "^ *" "$" "!" " " "\\b" + "\\<" "\\>" "\\_<" "\\_>" ".*" + "??" "?*" "*?" "?")) +(defvar helm--force-updating-p nil + "[INTERNAL] Don't use this in your programs.") +(defvar helm-exit-status 0 + "Flag to inform if Helm did exit or quit. +0 means Helm did exit when executing an action. +1 means Helm did quit with \\[keyboard-quit] +Knowing this exit-status could help restore a window config when +Helm aborts in some special circumstances. See +`helm-exit-minibuffer' and `helm-keyboard-quit'.") +(defvar helm-minibuffer-confirm-state nil) +(defvar helm--quit nil) +(defvar helm-buffers nil + "Helm buffers listed in order of most recently used.") +(defvar helm-current-position nil + "Cons of (point . window-start) when Helm is invoked. +`helm-current-buffer' uses this to restore position after +`helm-keyboard-quit'") +(defvar helm-last-frame-or-window-configuration nil + "Used to store window or frame configuration at Helm start.") +(defvar helm-onewindow-p nil) +(defvar helm-types nil) +(defvar helm--mode-line-string-real nil) ; The string to display in mode-line. +(defvar helm-persistent-action-display-window nil) +(defvar helm-marked-candidates nil + "Marked candidates. List of (source . real) pair.") +(defvar helm--mode-line-display-prefarg nil) +(defvar helm--temp-follow-flag nil + "[INTERNAL] A simple flag to notify persistent action we are following.") +(defvar helm--reading-passwd-or-string nil) +(defvar helm--in-update nil) +(defvar helm--in-fuzzy nil) +(defvar helm-maybe-use-default-as-input nil + "Flag to notify the use of use-default-as-input. +Use only in let-bindings. +Use :default arg of `helm' as input to update display. +Note that if also :input is specified as `helm' arg, it will take +precedence on :default.") +(defvar helm--temp-hooks nil + "Store temporary hooks added by `with-helm-temp-hook'.") +(defvar helm--prompt nil) +(defvar helm--file-completion-sources + '("Find Files" "Read File Name") + "Sources that use the *find-files mechanism can be added here. +Sources generated by `helm-mode' don't need to be added here +because they are automatically added. + +You should not modify this yourself unless you know what you are +doing.") +(defvar helm--completing-file-name nil + "Non nil when `helm-read-file-name' is running. +Used for `helm-file-completion-source-p'.") +;; Same as `ffap-url-regexp' but keep it here to ensure `ffap-url-regexp' is not nil. +(defvar helm--url-regexp "\\`\\(news\\(post\\)?:\\|mailto:\\|file:\\|\\(ftp\\|https?\\|telnet\\|gopher\\|www\\|wais\\)://\\)") +(defvar helm--ignore-errors nil + "Flag to prevent Helm popping up errors in candidates functions. +Should be set in candidates functions if needed, and will be +restored at end of session.") +(defvar helm--action-prompt "Select action: ") +(defvar helm--cycle-resume-iterator nil) +(defvar helm--buffer-in-new-frame-p nil) +(defvar helm-initial-frame nil + "[INTERNAL] The selected frame before starting Helm. +Helm use this internally to know in which frame it started, don't +modify this yourself.") +(defvar helm-popup-frame nil + "The frame where Helm is displayed. + +This is only used when Helm is using +`helm-display-buffer-in-own-frame' as `helm-display-function' and +`helm-display-buffer-reuse-frame' is non nil.") +(defvar helm--nested nil) +(defconst helm--frame-default-attributes + '(width height tool-bar-lines left top + title undecorated vertical-scroll-bars + visibility fullscreen menu-bar-lines undecorated + alpha foreground-color background-color) + "Frame parameters to save in `helm--last-frame-parameters'.") +(defvar helm--last-frame-parameters nil + "Frame parameters to save for later resuming. +Local to `helm-buffer'.") +(defvar helm--executing-helm-action nil + "Non nil when action is triggering a new helm-session. +This may be let bounded in other places to notify the display +function to reuse the same frame parameters as the previous Helm +session just like resume would do.") +(defvar helm--current-buffer-narrowed nil) +(defvar helm--suspend-update-interactive-flag nil) +(defvar helm-persistent-action-window-buffer nil + "[INTERNAL] Store the buffer where helm is started. +It is generally `helm-current-buffer', but when this one is displayed +in a dedicated buffer, helm can't start in this window and use another +window handling a buffer, it is this one we store.") +(defvar helm--tramp-archive-maybe-loaded nil) +(defvar helm--original-dedicated-windows-alist nil + "[INTERNAL] Store all dedicated windows with their dedicated state on startup") + +;;; Multi keys +;; +;; +;;;###autoload +(defun helm-define-multi-key (keymap key functions &optional delay) + "In KEYMAP, define key sequence KEY for function list FUNCTIONS. +Each function runs sequentially for each KEY press. +If DELAY is specified, switch back to initial function of FUNCTIONS list +after DELAY seconds. +The functions in FUNCTIONS list take no args. +E.g. + (defun foo () + (interactive) + (message \"Run foo\")) + (defun bar () + (interactive) + (message \"Run bar\")) + (defun baz () + (interactive) + (message \"Run baz\")) + +\(helm-define-multi-key global-map (kbd \" q\") \\='(foo bar baz) 2) + +Each time \" q\" is pressed, the next function is executed. +Waiting more than 2 seconds between key presses switches back to +executing the first function on the next hit." + (define-key keymap key (helm-make-multi-command functions delay))) + +;;;###autoload +(defmacro helm-multi-key-defun (name docstring funs &optional delay) + "Define NAME as a multi-key command running FUNS. +After DELAY seconds, the FUNS list is reinitialized. +See `helm-define-multi-key'." + (declare (indent 2)) + (setq docstring (if docstring (concat docstring "\n\n") + "This is a helm-ish multi-key command.")) + `(defalias (quote ,name) (helm-make-multi-command ,funs ,delay) ,docstring)) + +(defun helm-make-multi-command (functions &optional delay) + "Return an anonymous multi-key command running FUNCTIONS. +Run each function in the FUNCTIONS list in turn when called within +DELAY seconds." + (declare (indent 1)) + (let ((funs functions) + (iter (list nil)) + (timeout delay)) + (lambda () + (interactive) + (helm-run-multi-key-command funs iter timeout)))) + +(defun helm-run-multi-key-command (functions iterator delay) + (let ((fn (lambda () + (cl-loop for count from 1 to (length functions) + collect count))) + next) + (unless (and (car iterator) + ;; Reset iterator when another key is pressed. + (eq this-command real-last-command)) + (setcar iterator (helm-iter-circular (funcall fn)))) + (setq next (helm-iter-next (car iterator))) + (and next (car iterator) + (call-interactively (nth (1- next) functions))) + (when delay (run-with-idle-timer + delay nil (lambda () + (setcar iterator nil)))))) + +(helm-multi-key-defun helm-toggle-resplit-and-swap-windows + "Multi key command to re-split and swap Helm window. +First call runs `helm-toggle-resplit-window', +and second call within 1s runs `helm-swap-windows'." + '(helm-toggle-resplit-window helm-swap-windows) 1) +(put 'helm-toggle-resplit-and-swap-windows 'helm-only t) + +(defun helm-command-with-subkeys (map subkey command + &optional other-subkeys prompt exit-fn delay) + "Return an anonymous interactive command to use with `helm-define-key-with-subkeys'." + (lambda () + (interactive) + (let (timer) + (call-interactively command) + (unless (or defining-kbd-macro executing-kbd-macro) + (unwind-protect + (progn + (when delay + (setq timer (run-with-idle-timer + delay nil (lambda () (keyboard-quit))))) + (while (let ((input (read-key prompt)) other kb com) + (setq last-command-event input) + (cond + ((eq input subkey) + (call-interactively command) + (setq last-command command) + t) + ((setq other (assoc input other-subkeys)) + (call-interactively (cdr other)) + (setq last-command (cdr other)) + t) + (t + (setq kb (vector last-command-event)) + (setq com (lookup-key map kb)) + (if (commandp com) + (call-interactively com) + (setq unread-command-events + (nconc (mapcar #'identity kb) + unread-command-events))) + nil))))) + (when timer (cancel-timer timer)) + (and exit-fn (funcall exit-fn))))))) + +;;;###autoload +(defun helm-define-key-with-subkeys (map key subkey command + &optional other-subkeys + prompt exit-fn delay + docstring) + "Define in MAP a KEY and SUBKEY to COMMAND. + +This allows typing KEY to call COMMAND the first time and +type only SUBKEY on subsequent calls. + +Arg MAP is the keymap to use, SUBKEY is the initial short +key binding to call COMMAND. + +Arg OTHER-SUBKEYS is an alist specifying other short key bindings +to use once started, e.g.: + + (helm-define-key-with-subkeys global-map + (kbd \"C-x v n\") ?n \\='git-gutter:next-hunk + \\='((?p . git-gutter:previous-hunk))) + +In this example, `C-x v n' will run `git-gutter:next-hunk' +subsequent \"n\" will run this command again and subsequent \"p\" +will run `git-gutter:previous-hunk'. + +If specified PROMPT can be displayed in minibuffer to describe +SUBKEY and OTHER-SUBKEYS. Arg EXIT-FN specifies a function to run +on exit. + +For any other key pressed, run their assigned command as defined +in MAP and then exit the loop running EXIT-FN, if specified. + +If DELAY an integer is specified exit after DELAY seconds. + +NOTE: SUBKEY and OTHER-SUBKEYS bindings support only char syntax +and vectors, so don't use strings to define them. While defining +or executing a kbd macro no SUBKEY or OTHER-SUBKEYS are provided, +i.e. the loop is not entered after running COMMAND." + (declare (indent 1)) + (let ((fn (helm-command-with-subkeys + map subkey command other-subkeys prompt exit-fn delay)) + (com (intern (format "helm-%s-with-subkeys" + (symbol-name command))))) + (defalias com fn + (or docstring + ;; When no DOCSTRING, generate a basic one specifying + ;; COMMAND, SUBKEY and OTHER-SUBKEYS. + (concat + (format "Run `%s' and bound it to `%s' for subsequent calls." + command (if (numberp subkey) (single-key-description subkey) subkey)) + (if other-subkeys + (helm-basic-docstring-from-alist other-subkeys) + "")))) + (define-key map key com))) + +(defun helm-basic-docstring-from-alist (alist) + (let* ((len (length alist)) + (osk (cl-loop for (k . v) in alist + for count from 1 + for sep = (cond ((and (= count len) (> len 1)) + " and ") + ((> count 1) ",") + (t "")) + for key = (if (numberp k) (single-key-description k) k) + concat (format "%s`%s'" sep key) into ks + concat (format "%s`%s'" sep v) into kv + finally return (list ks kv)))) + (format "\nBound as well %s to %s%s." + (car osk) (if (> len 1) "respectively " "") (cadr osk)))) + +;;; Keymap +;; +;; +(defvar helm-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map minibuffer-local-map) + (define-key map (kbd "") #'helm-next-line) + (define-key map (kbd "") #'helm-previous-line) + (define-key map (kbd "C-n") #'helm-next-line) + (define-key map (kbd "C-p") #'helm-previous-line) + (define-key map (kbd "") #'helm-follow-action-forward) + (define-key map (kbd "") #'helm-follow-action-backward) + (define-key map (kbd "") #'helm-previous-page) + (define-key map (kbd "") #'helm-next-page) + (define-key map (kbd "M-v") #'helm-scroll-up) + (define-key map (kbd "C-v") #'helm-scroll-down) + (define-key map (kbd "M-<") #'helm-beginning-of-buffer) + (define-key map (kbd "M->") #'helm-end-of-buffer) + (define-key map (kbd "C-g") #'helm-keyboard-quit) + (define-key map (kbd "") #'helm-maybe-exit-minibuffer) + (define-key map (kbd "C-i") #'helm-select-action) + (define-key map (kbd "C-j") #'helm-execute-persistent-action) + (define-key map (kbd "C-o") #'helm-next-source) + (define-key map (kbd "M-o") #'helm-previous-source) + (define-key map (kbd "") #'helm-next-source) + (define-key map (kbd "") #'helm-previous-source) + (define-key map (kbd "C-l") #'helm-recenter-top-bottom-other-window) + (define-key map (kbd "M-C-l") #'helm-reposition-window-other-window) + (define-key map (kbd "C-M-v") #'helm-scroll-other-window) + (define-key map (kbd "M-") #'helm-scroll-other-window) + (define-key map (kbd "C-M-y") #'helm-scroll-other-window-down) + (define-key map (kbd "C-M-S-v") #'helm-scroll-other-window-down) + (define-key map (kbd "M-") #'helm-scroll-other-window-down) + (define-key map (kbd "") #'helm-scroll-other-window) + (define-key map (kbd "") #'helm-scroll-other-window-down) + (define-key map (kbd "C-@") #'helm-toggle-visible-mark) + (define-key map (kbd "C-SPC") #'helm-toggle-visible-mark-forward) + (define-key map (kbd "M-SPC") #'helm-toggle-visible-mark-backward) + (define-key map (kbd "M-[") nil) + (define-key map (kbd "M-(") #'helm-prev-visible-mark) + (define-key map (kbd "M-)") #'helm-next-visible-mark) + (define-key map (kbd "C-k") #'helm-delete-minibuffer-contents) + (define-key map (kbd "C-x C-f") #'helm-quit-and-find-file) + (define-key map (kbd "M-m") #'helm-toggle-all-marks) + (define-key map (kbd "M-a") #'helm-mark-all) + (define-key map (kbd "M-U") #'helm-unmark-all) + (define-key map (kbd "C-M-a") #'helm-show-all-candidates-in-source) + (define-key map (kbd "C-M-e") #'helm-display-all-sources) + (define-key map (kbd "C-s") #'undefined) + (define-key map (kbd "M-s") #'undefined) + (define-key map (kbd "C-}") #'helm-narrow-window) + (define-key map (kbd "C-{") #'helm-enlarge-window) + (define-key map (kbd "C-c -") #'helm-swap-windows) + (define-key map (kbd "C-c _") #'helm-toggle-full-frame) + (define-key map (kbd "C-c %") #'helm-exchange-minibuffer-and-header-line) + (define-key map (kbd "C-c C-y") #'helm-yank-selection) + (define-key map (kbd "C-c C-k") #'helm-kill-selection-and-quit) + (define-key map (kbd "C-c C-i") #'helm-insert-or-copy) + (define-key map (kbd "C-c C-f") #'helm-follow-mode) + (define-key map (kbd "C-c C-u") #'helm-refresh) + (define-key map (kbd "C-c >") #'helm-toggle-truncate-line) + (define-key map (kbd "C-c l") #'helm-display-line-numbers-mode) + (define-key map (kbd "M-p") #'previous-history-element) + (define-key map (kbd "M-n") #'next-history-element) + (define-key map (kbd "C-!") #'helm-toggle-suspend-update) + (define-key map (kbd "C-x b") #'helm-resume-previous-session-after-quit) + (define-key map (kbd "C-x C-b") #'helm-resume-list-buffers-after-quit) + (helm-define-key-with-subkeys map (kbd "C-c n") ?n #'helm-run-cycle-resume) + ;; Disable `file-cache-minibuffer-complete'. + (define-key map (kbd "") #'undefined) + ;; Multi keys + (define-key map (kbd "C-t") #'helm-toggle-resplit-and-swap-windows) + ;; Debugging command + (define-key map (kbd "C-h C-d") #'helm-enable-or-switch-to-debug) + (define-key map (kbd "C-h c") #'helm-customize-group) + ;; Allow to eval keymap without errors. + (define-key map [f1] nil) + (define-key map (kbd "C-h C-h") #'undefined) + (define-key map (kbd "C-h h") #'undefined) + (helm-define-key-with-subkeys map + (kbd "C-w") ?\C-w #'helm-yank-text-at-point + '((?\C-_ . helm-undo-yank-text-at-point))) + ;; Use `describe-mode' key in `global-map'. + (dolist (k (where-is-internal #'describe-mode global-map)) + (define-key map k #'helm-help)) + ;; Bind all actions from f1 to f12, `helm-select-nth-action' + ;; counts from 0, i.e. (helm-select-nth-action 0) = action 1. + (dotimes (n 12) + (define-key map (kbd (format "" (1+ n))) + (lambda () + (interactive) + (helm-select-nth-action n)))) + map) + "Keymap for helm.") + +(defun helm-customize-group-1 (group) + (require 'cus-edit) + (let ((name (format "*Customize Group: %s*" + (custom-unlispify-tag-name group)))) + (if (buffer-live-p (get-buffer name)) + (switch-to-buffer name) + (custom-buffer-create + (list (list group 'custom-group)) + name + (concat " for group " + (custom-unlispify-tag-name group)))))) + +(defun helm-customize-group () + "Jump to customization group of current source. + +Default to Helm group when group is not defined in source." + (interactive) + (let ((source (or (helm-get-current-source) + (helm-comp-read + "Customize variables for: " + (cl-loop for src in (with-helm-buffer helm-sources) + collect `(,(assoc-default 'name src) . + ,src)) + :allow-nest t + :exec-when-only-one t)))) + (helm-run-after-exit 'helm-customize-group-1 (helm-get-attr 'group source)))) +(put 'helm-customize-group 'helm-only t) + +(defun helm--action-at-nth-set-fn-1 (value &optional negative) + (dotimes (n 9) + (let ((key (format value (1+ n))) + (fn (lambda () + (interactive) + (helm-execute-selection-action-at-nth + (if negative (- (1+ n)) (1+ n)))))) + (define-key helm-map (kbd key) nil) + (define-key helm-map (kbd key) fn)))) + +(defun helm--action-at-nth-set-fn- (var val) + (set var val) + (helm--action-at-nth-set-fn-1 val 'negative)) + +(defun helm--action-at-nth-set-fn+ (var val) + (set var val) + (helm--action-at-nth-set-fn-1 val)) + +(defcustom helm-action-at-nth-negative-prefix-key "C-x %d" + "The prefix key to execute default action on nth <-n> candidate. + +This is a format spec where %d will be replaced by the candidate +number. + +NOTE: `setq' have no effect until you restart Emacs, use +customize for immediate effect." + :group 'helm + :type 'string + :set #'helm--action-at-nth-set-fn-) + +(defcustom helm-action-at-nth-positive-prefix-key "C-c %d" + "The prefix key to execute default action on nth <+n> candidate. + +This is a format spec where %d will be replaced by the candidate +number. + +NOTE: `setq' have no effect until you restart Emacs, use +customize for immediate effect." + :group 'helm + :type 'string + :set #'helm--action-at-nth-set-fn+) + + +(defgroup helm nil + "Open Helm." + :prefix "helm-" :group 'convenience) + +;; Easy access to customize +;;;###autoload +(defun helm-configuration () + "Customize Helm." + (interactive) + (customize-group "helm")) + +(defcustom helm-completion-window-scroll-margin 5 + "`scroll-margin' to use for Helm completion window. +Set to 0 to disable. +NOTE: This has no effect when `helm-display-source-at-screen-top' +id is non-nil." + :group 'helm + :type 'integer) + +(defcustom helm-left-margin-width 0 + "`left-margin-width' value for the `helm-buffer'." + :group 'helm + :type 'integer) + +(defcustom helm-display-source-at-screen-top t + "Display candidates at the top of screen. +This happens with `helm-next-source' and `helm-previous-source'. +NOTE: When non-nil (default), disable +`helm-completion-window-scroll-margin'." + :group 'helm + :type 'boolean) + +(defcustom helm-candidate-number-limit 50 + "Global limit for number of candidates displayed. +When the pattern is empty, the number of candidates shown will be +as set here instead of the entire list, which may be hundreds or +thousands. Since narrowing and filtering rapidly reduces +available candidates, having a small list will keep the interface +responsive. + +Set this value to nil for no limit." + :group 'helm + :type '(choice (const :tag "Disabled" nil) integer)) + +(defcustom helm-input-idle-delay 0.01 + "Idle time before updating, specified in seconds." + :group 'helm + :type 'float) + +(defcustom helm-exit-idle-delay 0 + "Idle time before exiting minibuffer while Helm is updating. +Has no affect when helm-buffer is up to date (i.e. exit without +delay in this condition)." + :group 'helm + :type 'float) + +(defvaralias 'helm-samewindow 'helm-full-frame) +(make-obsolete-variable 'helm-samewindow 'helm-full-frame "1.4.8.1") +(defcustom helm-full-frame nil + "Use current window for showing candidates. +If t, then Helm does not pop-up a new window." + :group 'helm + :type 'boolean) + +(defcustom helm-candidate-separator + (if (fontp (char-displayable-p (read "#x2015"))) + "――――――――――――――――――――――――――――――――――――――" + "--------------------------------------") + "Candidates separator of `multiline' source." + :group 'helm + :type 'string) + +(defcustom helm-save-configuration-functions + '(set-window-configuration . current-window-configuration) + "Functions used to restore or save configurations for frames and windows. +Specified as a pair of functions, where car is the restore +function and cdr is the save function. + +To save and restore frame configuration, set this variable to +\\='(set-frame-configuration . current-frame-configuration) + +NOTE: This may not work properly with own-frame minibuffer +settings. Older versions saves/restores frame configuration, but +the default has changed now to avoid flickering." + :group 'helm + :type 'sexp) + +(defcustom helm-display-function 'helm-default-display-buffer + "Function used to display `helm-buffer'. + +Local value in `helm-buffer' will take precedence on this default +value. Commands that are in `helm-commands-using-frame' will have +`helm-buffer' displayed in frame, `helm-display-function' being +ignored. +If no local value is found and current command is not one of +`helm-commands-using-frame' use this default value. +The function in charge of deciding which value use is +`helm-resolve-display-function'. + +To set it locally to `helm-buffer' in Helm sources use +`helm-set-local-variable' in init function or use +:display-function slot in `helm' call." + :group 'helm + :type 'symbol) + +(defcustom helm-case-fold-search 'smart + "Adds \\='smart' option to `case-fold-search'. +Smart option ignores case for searches as long as there are no +upper case characters in the pattern. + +Use nil or t to turn off smart behavior and use +`case-fold-search' behavior. + +Default is smart. + +NOTE: Case fold search has no effect when searching asynchronous +sources, which relies on customized features implemented directly +into their execution process. See helm-grep.el for an example." + :group 'helm + :type '(choice (const :tag "Ignore case" t) + (const :tag "Respect case" nil) + (other :tag "Smart" smart))) + +(defcustom helm-file-name-case-fold-search + (if (memq system-type + '(cygwin windows-nt ms-dos darwin)) + t + helm-case-fold-search) + "Local setting of `helm-case-fold-search' for reading filenames. + +See `helm-case-fold-search' for more info." + :group 'helm + :type 'symbol) + +(defcustom helm-reuse-last-window-split-state nil + "Use the same state of window split, vertical or horizontal. +`helm-toggle-resplit-window' for the next helm session will use +the same window scheme as the previous session unless +`helm-split-window-default-side' is \\='same or \\='other." + :group 'helm + :type 'boolean) + +(defcustom helm-split-width-threshold nil + "The value of `split-width-threshold' for helm windows. +This affect the behavior of `helm-split-window-default-fn'. +When the value is an integer, `split-window-sensibly' is used inconditionally +and all the helm variables that affect window splitting are ignored." + :group 'helm + :type '(choice + (const :tag "Maybe use `split-window-sensibly'" nil) + (integer :tag "Inconditionally use `split-window-sensibly'"))) + +(defcustom helm-split-window-preferred-function 'helm-split-window-default-fn + "Default function used for splitting window." + :group 'helm + :type 'function) + +(defcustom helm-split-window-default-side 'below + "The default side to display `helm-buffer'. +Must be one acceptable arg for `split-window' SIDE, +that is `below', `above', `left' or `right'. + +Other acceptable values are `same' which always displays +`helm-buffer' in current window and `other' that displays +`helm-buffer' below if only one window or in +`other-window-for-scrolling' when available. + +A nil value has same effect as `below'. If `helm-full-frame' is +non-nil, it take precedence over this setting. + +See also `helm-split-window-inside-p' and +`helm-always-two-windows' that take precedence over this. + +NOTE: this has no effect if +`helm-split-window-preferred-function' is not +`helm-split-window-default-fn' unless this new function can +handle this." + :group 'helm + :type 'symbol) + +(defcustom helm-split-window-other-side-when-one-window 'below + "The default side to display `helm-buffer' when (1) +`helm-split-window-default-side' is \\='other and (2) +the current frame only has one window. Possible values +are acceptable args for `split-window' SIDE, that is `below', +`above', `left' or `right'. + +If `helm-full-frame' is non-nil, it takes precedence over this +setting. + +See also `helm-split-window-inside-p' and `helm-always-two-windows' that +takes precedence over this. + +NOTE: this has no effect if +`helm-split-window-preferred-function' is not +`helm-split-window-default-fn' unless this new function can +handle this." + :group 'helm + :type 'symbol) + +(defcustom helm-display-buffer-default-height nil + "Initial height of `helm-buffer', specified as an integer or a function. + +The function should take one arg and be responsible for re-sizing +the window; function's return value is ignored. Note that this +has no effect when the split is vertical. See `display-buffer' +for more info." + :group 'helm + :type '(choice integer function)) + +(defcustom helm-display-buffer-default-width nil + "Initial width of `helm-buffer', specified as an integer or a function. + +The function should take one arg and be responsible for re-sizing +the window; function's return value is ignored. Note that this +have no effect when the split is horizontal. See `display-buffer' +for more info." + :group 'helm + :type '(choice integer function)) + +(defvaralias 'helm-split-window-in-side-p 'helm-split-window-inside-p) +(make-obsolete-variable 'helm-split-window-in-side-p 'helm-split-window-inside-p "2.8.6") +(defcustom helm-split-window-inside-p nil + "Force split inside selected window when non-nil. +See also `helm-split-window-default-side'. + +NOTE: this has no effect if +`helm-split-window-preferred-function' is not +`helm-split-window-default-fn' unless this new function can +handle this." + :group 'helm + :type 'boolean) + +(defcustom helm-always-two-windows nil + "When non-nil Helm uses two windows in this frame. + +I.e. `helm-buffer' in one window and `helm-current-buffer' +in the other. + +Note: this has no effect when `helm-split-window-inside-p' is +non-nil, or when `helm-split-window-default-side' is set to +\\='same. + +When `helm-autoresize-mode' is enabled, setting this to nil +will have no effect. + +Also when non-nil it overrides the effect of +`helm-split-window-default-side' set to `other'." + :group 'helm + :type 'boolean) + +(defcustom helm-display-buffer-width 72 + "Frame width when displaying helm-buffer in own frame." + :group 'helm + :type 'integer) + +(defcustom helm-display-buffer-height 20 + "Frame height when displaying helm-buffer in own frame." + :group 'helm + :type 'integer) + +(defcustom helm-default-display-buffer-functions nil + "Action functions to pass to `display-buffer'. +See (info \"(elisp) Buffer Display Action Functions\"). + +It has no effect when `helm-always-two-windows' is non-nil and +may override other settings like `helm-split-window-inside-p'." + :group 'helm + :type '(repeat symbol)) + +(defcustom helm-default-display-buffer-alist nil + "Additional alist to pass to `display-buffer' action. +See (info \"(elisp) Action Alists for Buffer Display\"). + +It has no effect when `helm-always-two-windows' is non-nil and +may override other settings like `helm-split-window-inside-p'. +Note that window-height and window-width have to be configured in +`helm-display-buffer-height' and `helm-display-buffer-width'." + :group 'helm + :type '(alist :key-type symbol :value-type sexp)) + +(defcustom helm-sources-using-default-as-input '(helm-source-imenu + helm-source-imenu-all + helm-source-info-elisp + helm-source-etags-select + helm-source-man-pages + helm-source-occur + helm-source-moccur + helm-source-grep-ag + helm-source-grep-git + helm-source-grep) + "List of Helm sources that need to use `helm-maybe-use-default-as-input'. +When a source is a member of this list, default `thing-at-point' +will be used as input." + :group 'helm + :type '(repeat (choice symbol))) + +(defcustom helm-delete-minibuffer-contents-from-point t + "When non-nil, `helm-delete-minibuffer-contents' deletes region from `point'. +Otherwise it deletes `minibuffer-contents'. +See documentation for `helm-delete-minibuffer-contents'." + :group 'helm + :type 'boolean) + +(defcustom helm-follow-mode-persistent nil + "When non-nil, save last state of `helm-follow-mode' for the next Emacs sessions. + +Each time you turn on or off `helm-follow-mode', the current +source name will be stored or removed from +`helm-source-names-using-follow'. + +Note that this may be disabled in some places where it is unsafe +to use because persistent action is changing according to +context." + :group 'helm + :type 'boolean) + +(defcustom helm-source-names-using-follow nil + "A list of source names to have follow enabled. +This list of source names will be used only +when `helm-follow-mode-persistent' is non-nil. + +You don't have to customize this yourself unless you really want +and know what you are doing, instead just set +`helm-follow-mode-persistent' to non-nil and as soon as you turn +on or off `helm-follow-mode' (C-c C-f) in a source, Helm will +save or remove source name in this variable." + :group 'helm + :type '(repeat (choice string))) + +(defcustom helm-prevent-escaping-from-minibuffer t + "Prevent escaping from minibuffer with `other-window' during the Helm session." + :group 'helm + :type 'boolean) + +(defcustom helm-allow-mouse nil + "Allow mouse usage during the Helm session when non-nil. + +Note that this also allows moving out of minibuffer when clicking +outside of `helm-buffer', so it is up to you to get back to Helm +by clicking back in `helm-buffer' or minibuffer." + :group 'helm + :type 'boolean) + +(defcustom helm-move-to-line-cycle-in-source nil + "Cycle to the beginning or end of the list after reaching the bottom or top. +This applies when using `helm-next/previous-line'." + :group 'helm + :type 'boolean) + +(defcustom helm-fuzzy-match-fn 'helm-fuzzy-match + "The function for fuzzy matching in `helm-source-sync' based sources." + :group 'helm + :type 'function) + +(defcustom helm-fuzzy-search-fn 'helm-fuzzy-search + "The function for fuzzy matching in `helm-source-in-buffer' based sources." + :group 'helm + :type 'function) + +(defcustom helm-fuzzy-sort-fn 'helm-fuzzy-matching-default-sort-fn + "The sort transformer function used in fuzzy matching." + :group 'helm + :type 'function) + +(defcustom helm-fuzzy-matching-highlight-fn #'helm-fuzzy-default-highlight-match + "The function to highlight fuzzy matches. +The function must have the same signature as +`helm-fuzzy-default-highlight-match' which is the default." + :group 'helm + :type 'function) + +(defcustom helm-autoresize-max-height 40 + "Specify maximum height and defaults to percent of Helm window's frame height. + +See `fit-window-to-buffer' for more infos." + :group 'helm + :type 'integer) + +(defcustom helm-autoresize-min-height 10 + "Specify minimum height and defaults to percent of Helm window's frame height. + +If nil, `window-min-height' is used. +See `fit-window-to-buffer' for details." + :group 'helm + :type 'integer) + +(defcustom helm-input-method-verbose-flag nil + "The default value for `input-method-verbose-flag' used in Helm minibuffer. +It is nil by default, which does not turn off input method. Helm +updates and exits without interruption -- necessary for complex +methods. + +If set to any other value as per `input-method-verbose-flag', +then use `C-\\' to disable the `current-input-method' to exit or +update Helm." + :group 'helm + :type '(radio :tag "A flag to control extra guidance for input methods in helm." + (const :tag "Never provide guidance" nil) + (const :tag "Always provide guidance" t) + (const :tag "Provide guidance only for complex methods" complex-only))) + +(defcustom helm-display-header-line t + "Display header-line when non nil. +It has to be non nil when you want to display minibuffer contents in there with +`helm-echo-input-in-header-line'." + :group 'helm + :type 'boolean) + +(defcustom helm-inherit-input-method t + "Inherit `current-input-method' from `current-buffer' when non-nil. +The default is to enable this by default and then toggle +`toggle-input-method'." + :group 'helm + :type 'boolean) + +(defcustom helm-echo-input-in-header-line nil + "Send current input to header-line when non-nil. +Note that `helm-display-header-line' has to be non nil as well for this to take +effect." + :group 'helm + :type 'boolean) + +(defcustom helm-header-line-space-before-prompt 'left-fringe + "Specify the space before prompt in header-line. + +This will be used when `helm-echo-input-in-header-line' is +non-nil. + +Value can be one of the symbols \\='left-fringe or \\='left-margin or +an integer specifying the number of spaces before prompt. Note +that on input longer that `window-width' the continuation string +will be shown on left side of window without taking care of +this." + :group 'helm + :type '(choice + (symbol + (const :tag "Fringe" left-fringe) + (const :tag "Margin" left-margin)) + integer)) + +(defcustom helm-tramp-connection-min-time-diff 5 + "Value of `tramp-connection-min-time-diff' for Helm remote processes. +If set to zero Helm remote processes are not delayed. + +Setting this to a value less than 5 or disabling it with a zero +value is risky, however on Emacs versions starting at 24.5 it +seems it is now possible to disable it. + +Anyway at any time in Helm you can suspend your processes while +typing by hitting \\ `\\[helm-toggle-suspend-update]'. + +Only async sources than use a sentinel calling +`helm-process-deferred-sentinel-hook' are affected by this." + :type 'integer + :group 'helm) + +(defcustom helm-show-action-window-other-window nil + "Show action buffer beside `helm-buffer' when non-nil. + +If nil don't split and replace helm-buffer by the action buffer +in same window. +If left display the action buffer at the left of helm-buffer. +If right or any other value, split at right. + +Note that this may not fit well with some Helm window +configurations, so it have only effect when +`helm-always-two-windows' is non-nil." + :group 'helm + :type '(choice + (const :tag "Split at left" left) + (const :tag "Don't split" nil) + (other :tag "Split at right" right))) + +(defcustom helm-cycle-resume-delay 1.0 + "Delay used before resuming in `helm-run-cycle-resume'." + :type 'float + :group 'helm) + +(defcustom helm-display-buffer-reuse-frame nil + "When non nil Helm frame is not deleted and reused in next sessions. + +This was used to workaround a bug in Emacs where frames where +popping up slowly, now that the bug have been fixed upstream +\(emacs-27) probably you don't want to use this any more. On +emacs-26 set `x-wait-for-event-timeout' to nil to have your +frames popping up fast." + :group 'helm + :type 'boolean) + +(defcustom helm-commands-using-frame nil + "A list of commands where `helm-buffer' is displayed in a frame." + :group 'helm + :type '(repeat symbol)) + +(defcustom helm-actions-inherit-frame-settings t + "Actions inherit Helm frame settings of initial command when non nil." + :group 'helm + :type 'boolean) + +(defcustom helm-use-undecorated-frame-option t + "Display Helm frame undecorated when non nil. + +This option has no effect with Emacs versions lower than 26." + :group 'helm + :type 'boolean) + +(defcustom helm-frame-background-color nil + "Background color for Helm frames, a string. +Fallback to default face background when nil." + :group 'helm + :type 'string) + +(defcustom helm-frame-foreground-color nil + "Foreground color for Helm frames, a string. +Fallback to default face foreground when nil" + :group 'helm + :type 'string) + +(defcustom helm-frame-alpha nil + "Alpha parameter for Helm frames, an integer. +Fallback to 100 when nil." + :group 'helm + :type 'integer) + +(defcustom helm-use-frame-when-more-than-two-windows nil + "Display Helm buffer in frame when more than two windows." + :group 'helm + :type 'boolean) + +(defvaralias 'helm-use-frame-when-dedicated-window + 'helm-use-frame-when-no-suitable-window) + +(defcustom helm-use-frame-when-no-suitable-window nil + "Display Helm buffer in frame when Helm is started from a dedicated window." + :group 'helm + :type 'boolean) +(make-obsolete-variable 'helm-use-frame-when-dedicated-window + 'helm-use-frame-when-no-suitable-window + "3.8.1") + +(defcustom helm-default-prompt-display-function + #'helm-set-default-prompt-display + "The function to use to set face of fake cursor in header-line." + :group 'helm + :type 'function) + +(defcustom helm-truncate-lines nil + "The value of `truncate-lines' when Helm starts. +You can toggle later `truncate-lines' with +\\\\[helm-toggle-truncate-line]." + :group 'helm + :type 'boolean) + +(defcustom helm-visible-mark-prefix "*" + "Prefix used in margin for marked candidates. +Set this to an empty string if you don't want prefix in margin when marking." + :group 'helm + :type 'string) + +;;; Faces +;; +;; +(defgroup helm-faces nil + "Customize the appearance of Helm." + :prefix "helm-" + :group 'faces + :group 'helm) + +(defface helm-source-header + `((((background dark)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "#22083397778B" + :foreground "white" + :weight bold :height 1.3 :family "Sans Serif") + (((background light)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "#abd7f0" + :foreground "black" + :weight bold :height 1.3 :family "Sans Serif")) + "Face for source header in the Helm buffer." + :group 'helm-faces) + +(defface helm-visible-mark + `((((min-colors 88) (background dark)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "green1" + :foreground "black") + (((background dark)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "green" + :foreground "black") + (((background light)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "#d1f5ea") + (((min-colors 88)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "green1") + (t ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "green")) + "Face for visible mark." + :group 'helm-faces) + +(defface helm-header + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :inherit header-line)) + "Face for header lines in the Helm buffer." + :group 'helm-faces) + +(defface helm-candidate-number + `((((background dark)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "Yellow" :foreground "black") + (((background light)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "#faffb5" :foreground "black")) + "Face for candidate number in mode-line." + :group 'helm-faces) + +(defface helm-candidate-number-suspended + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :inherit helm-candidate-number :inverse-video t)) + "Face for candidate number in mode-line when Helm is suspended." + :group 'helm-faces) + +(defface helm-selection + `((((background dark)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "ForestGreen" + :distant-foreground "black") + (((background light)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :background "#b5ffd1" + :distant-foreground "black")) + "Face for currently selected item in the Helm buffer." + :group 'helm-faces) + +(defface helm-separator + `((((background dark)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "red") + (((background light)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "#ffbfb5")) + "Face for multiline source separator." + :group 'helm-faces) + +(defface helm-action + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :underline t)) + "Face for action lines in the Helm action buffer." + :group 'helm-faces) + +(defface helm-prefarg + `((((background dark)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "green") + (((background light)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "red")) + "Face for showing prefix arg in mode-line." + :group 'helm-faces) + +(defface helm-match + `((((background light)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "#b00000") + (((background dark)) + ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "gold1")) + "Face used to highlight matches." + :group 'helm-faces) + +(defface helm-header-line-left-margin + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :foreground "black" :background "yellow")) + "Face used to highlight helm-header sign in left-margin." + :group 'helm-faces) + +(defface helm-minibuffer-prompt + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :inherit minibuffer-prompt)) + "Face used for the minibuffer/headline prompt (such as Pattern:) in Helm." + :group 'helm-faces) + +(defface helm-eob-line + `((t ,@(and (>= emacs-major-version 27) '(:extend t)) + :inherit default)) + "Face for empty line at end of sources in the Helm buffer. +Allow specifying the height of this line." + :group 'helm-faces) + +(defface helm-mark-prefix + `((t :inherit default)) + "Face for string `helm-visible-mark-prefix'." + :group 'helm-faces) + +;;; Variables. +;; +;; +(defvar helm-selection-overlay nil + "Overlay used to highlight the currently selected item.") + +(defvar helm-async-processes nil + "List of information about asynchronous processes managed by Helm.") + +(defvar helm-before-initialize-hook nil + "Runs before Helm initialization. +This hook runs before init functions in `helm-sources', which is +before creation of `helm-buffer'. Set local variables for +`helm-buffer' that need a value from `current-buffer' with +`helm-set-local-variable'.") + +(defvar helm-after-initialize-hook nil + "Runs after Helm initialization. +This hook runs after `helm-buffer' is created but not from +`helm-buffer'. The hook needs to specify in which buffer to +run.") + +(defvaralias 'helm-update-hook 'helm-after-update-hook) +(make-obsolete-variable 'helm-update-hook 'helm-after-update-hook "1.9.9") + +(defvar helm-after-update-hook nil + "Runs after updating the Helm buffer with the new input pattern.") + +(defvar helm-before-update-hook nil + "Runs before updating the Helm buffer with the new input pattern.") + +(defvar helm-cleanup-hook nil + "Runs after exiting the minibuffer and before performing an +action. + +This hook runs even if Helm exits the minibuffer abnormally (e.g. +via `helm-keyboard-quit').") + +(defvar helm-select-action-hook nil + "Runs when opening the action buffer.") + +(defvar helm-before-action-hook nil + "Runs before executing action. +Unlike `helm-cleanup-hook', this hook runs before Helm closes the +minibuffer and also before performing an action.") + +(defvar helm-after-action-hook nil + "Runs after executing action.") + +(defvar helm-exit-minibuffer-hook nil + "Runs just before exiting the minibuffer. + +This hook runs when Helm exits the minibuffer normally (e.g., via +candidate selection), but does NOT run if Helm exits the +minibuffer abnormally (e.g. via `helm-keyboard-quit').") + +(defvar helm-after-persistent-action-hook nil + "Runs after executing persistent action.") + +(defvar helm-move-selection-before-hook nil + "Runs before moving selection in `helm-buffer'.") + +(defvar helm-move-selection-after-hook nil + "Runs after moving selection in `helm-buffer'.") + +(defvar helm-after-preselection-hook nil + "Runs after pre-selection in `helm-buffer'.") + +(defvar helm-window-configuration-hook nil + "Runs when switching to and from the action buffer. +Should run also at end of `helm-display-function'.") + +(defvar helm-execute-action-at-once-if-one nil + "When non-nil execute the default action and then exit if only one candidate. +If symbol \\='current-source is given as value exit if only one +candidate in current source. This variable accepts a function +with no args that should returns a boolean value or \\='current-source.") + +(defvar helm-quit-if-no-candidate nil + "When non-nil, quit if there are no candidates. +This variable accepts a function.") + +(defvar helm-debug-variables nil + "A list of Helm variables that `helm-debug-output' displays. +If nil, `helm-debug-output' includes only variables with `helm-' +prefixes.") + +(defvar helm-debug-buffer "*Debug Helm Log*") + +(defvar helm-debug nil + "If non-nil, write log message to `helm-debug-buffer'. +Default is nil, which disables writing log messages because the +size of `helm-debug-buffer' grows quickly.") + +(defvar helm-mode-line-string "\ +\\\ +\\[helm-help]:Help \ +\\[helm-select-action]:Act \ +\\[helm-maybe-exit-minibuffer]/\ +f1..f12:NthAct \ +\\[helm-toggle-suspend-update]:Tog.suspend \ +\\[helm-customize-group]:Conf" + "Help string displayed by Helm in the mode-line. +It is either a string or a list of two string arguments where the +first string is the name and the second string is displayed in +the mode-line. When nil, it defaults to `mode-line-format'.") + +(defvar helm-minibuffer-set-up-hook '(helm-hide-minibuffer-maybe) + "Hook that runs at minibuffer initialization. +A hook useful for modifying minibuffer settings in Helm. + +Uses `helm-hide-minibuffer-maybe' by default which hide minibuffer contents with +header-line contents when `helm-echo-input-in-header-line' is non nil.") + +(defvar helm-help-message + "* Helm Generic Help +** Basics + +To navigate in this Help buffer see [[Helm help][here]]. + +Helm narrows down the list of candidates as you type a filter +pattern. See [[Matching in Helm][Matching in Helm]]. + +Helm accepts multiple space-separated patterns, each pattern can +be negated with \"!\". + +Helm also supports fuzzy matching in some places when specified, +you will find several variables to enable fuzzy matching in +diverse [[Helm sources][sources]], see [[https://github.com/emacs-helm/helm/wiki/Fuzzy-matching][fuzzy-matching]] in helm-wiki for more infos. + +Helm generally uses familiar Emacs keys to navigate the list. +Here follow some of the less obvious bindings: + +- `\\\\[helm-maybe-exit-minibuffer]' selects the +candidate from the list, executes the default action upon exiting +the Helm session. + +- `\\\\[helm-execute-persistent-action]' executes the +default action but without exiting the Helm session. Not all +sources support this. + +- `\\\\[helm-select-action]' displays a list of actions +available on current candidate or all marked candidates. The +default binding is ordinarily used for completion, but that +would be redundant since Helm completes upon every character +entered in the prompt. See [[https://github.com/emacs-helm/helm/wiki#helm-completion-vs-emacs-completion][Helm wiki]]. + +Note: In addition to the default actions list, additional actions +appear depending on the type of the selected candidate(s). They +are called filtered actions. + +** Helm sources + +Helm uses what's called sources to provide different kinds of +completions. Each Helm session can handle one or more source. A +source is an alist object which is build from various classes, +see [[Writing your own Helm sources][here]] and [[https://github.com/emacs-helm/helm/wiki/Developing#creating-a-source][Helm wiki]] for more infos. + +*** Configure sources + +You will find in Helm sources already built and bound to a +variable called generally `helm-source-'. In this case +it is an alist and you can change the attributes (keys) values +using `helm-set-attr' function in your configuration. Of course +you have to ensure before calling `helm-set-attr' that the file +containing source is loaded, e.g. with `with-eval-after-load'. Of +course you can also completely redefine the source but this is +generally not elegant as it duplicate for its most part code +already defined in Helm. + +You will find also sources that are not built and even not bound +to any variables because they are rebuilded at each start of a +Helm session. In this case you can add a defmethod called +`helm-setup-user-source' to your config: + +#+begin_src elisp + + (cl-defmethod helm-setup-user-source ((source helm-moccur-class)) + (setf (slot-value source 'follow) -1)) + +#+end_src + +See +[[https://github.com/emacs-helm/helm/wiki/FAQ#why-is-a-customizable-helm-source-nil][here]] +for more infos, and for more complex examples of configuration +[[https://github.com/thierryvolpiatto/emacs-tv-config/blob/master/init-helm.el#L340][here]]. + +** Modify keybindings in Helm + +Helm main keymap is `helm-map', all keys bound in this map apply +to all Helm sources. However, most sources have their own keymap, +with each binding overriding its counterpart in `helm-map', you +can see all bindings in effect in the [[Commands][Commands]] +section (available only if the source has its own keymap and +documentation of course). + +** Matching in Helm + +All that you write in minibuffer is interpreted as a regexp or +multiple regexps if separated by a space. This is true for most +sources unless the developer of the source has disabled it or +have choosen to use fuzzy matching. Even if a source has fuzzy +matching enabled, Helm will switch to multi match as soon as it +detects a space in the pattern. It may also switch to multi match +as well if pattern starts with a \"^\" beginning of line sign. In +those cases each pattern separated with space should be a regexp +and not a fuzzy pattern. When using multi match patterns, each +pattern starting with \"!\" is interpreted as a negation i.e. +match everything but this. + +*** Completion-styles + +UPDATE: At version 3.8.0 Helm default is now to NOT use +`completion-styles' i.e. now `helm-completion-style' default to +'helm and no more to 'emacs. + +If you want to use `completion-styles' in Helm customize +`helm-completion-style' to 'emacs. + +Helm generally fetches its candidates with the :candidates +function up to `helm-candidate-number-limit' and then applies +match functions to these candidates according to `helm-pattern'. +But Helm allows matching candidates directly from the :candidates +function using its own `completion-styles'. +Helm provides 'helm completion style but also 'helm-flex +completion style for Emacs<27 that don't have 'flex completion +style, otherwise (emacs-27) 'flex completion style is used to +provide fuzzy aka flex completion. + +When using helm-fuzzy as `helm-completion-style' helm use its own +fuzzy implementation which have nothing to do with emacs `flex' +style. + +Any Helm sources can use `completion-styles' +by using :match-dynamic slot and building their :candidates +function with `helm-dynamic-completion'. + +Example: + +#+begin_src elisp + + (helm :sources (helm-build-sync-source \"test\" + :candidates (helm-dynamic-completion + '(foo bar baz foab) + 'symbolp) + :match-dynamic t) + :buffer \"*helm test*\") + +#+end_src + +By default Helm sets up `completion-styles' and always adds 'helm +to it. However the flex completion styles are not added. This is +up to the user if she wants to have such completion to enable +this. +As specified above use 'flex for emacs-27 and 'helm-flex for +emacs-26. Anyway, 'helm-flex is not provided in +`completion-styles-alist' if 'flex is present. + +Finally Helm provides two user variables to control +`completion-styles' usage: `helm-completion-style' and +`helm-completion-styles-alist'. Both variables are customizable. +The former allows retrieving previous Helm behavior if needed, by +setting it to `helm' or `helm-fuzzy', default being `emacs' which +allows dynamic completion and usage of `completion-styles'. The +second allows setting `helm-completion-style' per mode and also +specifying `completion-styles' per mode (see its docstring). Note +that these two variables take effect only in helm-mode i.e. in +all that uses `completion-read' or `completion-in-region', IOW all +helmized commands. File completion in `read-file-name' family +doesn't obey completion-styles and has its own file completion +implementation. Native Helm commands using `completion-styles' +doesn't obey `helm-completion-style' and +`helm-completion-styles-alist' (e.g., helm-M-x). + +Also for a better control of styles in native Helm sources (not +helmized by helm-mode) using :match-dynamic, +`helm-dynamic-completion' provides a STYLES argument that allows +specifying explicitely styles for this source. + +NOTE: Some old completion styles are not working fine with Helm +and are disabled by default in +`helm-blacklist-completion-styles'. They are anyway not useful in +Helm because 'helm style supersedes these styles. + +** Helm mode + +`helm-mode' toggles Helm completion in native Emacs functions, so +when you turn `helm-mode' on, commands like `switch-to-buffer' +will use Helm completion instead of the usual Emacs completion +buffer. + +*** What gets or does not get \"helmized\" when `helm-mode' is enabled? + +Helm provides generic completion on all Emacs functions using +`completing-read', `completion-in-region' and their derivatives, +e.g. `read-file-name'. Helm exposes a user variable to control +which function to use for a specific Emacs command: +`helm-completing-read-handlers-alist'. If the function for a +specific command is nil, it turns off Helm completion. See the +variable documentation for more infos. + +*** Helm functions vs helmized Emacs functions + +While there are Helm functions that perform the same completion +as other helmized Emacs functions, e.g. `switch-to-buffer' and +`helm-buffers-list', the native Helm functions like +`helm-buffers-list' can receive new features that allow marking +candidates, have several actions, etc. Whereas the helmized Emacs +functions only have Helm completion, Emacs can provide no more +than one action for this function. This is the intended behavior. + +Generally you are better off using the native Helm command than +the helmized Emacs equivalent. + +*** Completion behavior with Helm and completion-at-point + +Helm is NOT completing dynamically. That means that when you are +completing some text at point, completion is done against this +text and subsequent characters you add AFTER this text. This +allows you to use matching methods provided by Helm, that is multi +matching or fuzzy matching (see [[Matching in Helm][Matching in +Helm]]). + +Completion is not done dynamically (against `helm-pattern') +because backend functions (i.e. `completion-at-point-functions') +are not aware of Helm matching methods. + +By behaving like this, the benefit is that you can fully use Helm +matching methods but you can't start a full completion against a +prefix different than the initial text you have at point. Helm +warns you against this by colorizing the initial input and sends +a user-error message when trying to delete backward text beyond +this limit at first hit on DEL. A second hit on DEL within a +short delay (1s) quits Helm and delete-backward char in +current-buffer. + +** Helm help + +\\[helm-documentation]: Show all Helm documentations concatenated +in one org file. + +From a Helm session, just hit \\\\[helm-help] to have +the documentation for the current source followed by the global +Helm documentation. + +While in the help buffer, most of the Emacs regular key bindings +are available; the most important ones are shown in minibuffer. +However, due to implementation restrictions, no regular Emacs +keymap is used (it runs in a loop when reading the help buffer). +Only simple bindings are available and they are defined in +`helm-help-hkmap', which is a simple alist of (key . function). +You can define or redefine bindings in help with +`helm-help-define-key' or by adding/removing entries directly in +`helm-help-hkmap'. +See `helm-help-hkmap' for restrictions on bindings and functions. + +The documentation of default bindings are: + +| Key | Alternative keys | Command | +|-----------+------------------+---------------------| +| C-v | Space next | Scroll up | +| M-v | b prior | Scroll down | +| C-s | | Isearch forward | +| C-r | | Isearch backward | +| C-a | | Beginning of line | +| C-e | | End of line | +| C-f | right | Forward char | +| C-b | left | Backward char | +| C-n | down | Next line | +| C-p | up | Previous line | +| M-a | | Backward sentence | +| M-e | | Forward sentence | +| M-f | | Forward word | +| M-b | | Backward word | +| M-> | | End of buffer | +| M-< | | Beginning of buffer | +| C- | | Toggle mark | +| C-M-SPACE | | Mark sexp | +| RET | | Follow org link | +| C-% | | Push org mark | +| C-& | | Goto org mark-ring | +| TAB | | Org cycle | +| M- | | Toggle visibility | +| M-w | | Copy region | +| q | | Quit | + +** Customize Helm + +Helm provides a lot of user variables for extensive customization. +From any Helm session, type \\\\[helm-customize-group] +to jump to the current source `custom' group. Helm also has a +special group for faces you can access via `M-x customize-group +RET helm-faces'. + +Note: Some sources may not have their group set and default to +the `helm' group. + +** Display Helm in windows and frames + +You can display the Helm completion buffer in many different +window configurations, see the custom interface to discover the +different windows configurations available (See [[Customize Helm][Customize Helm]] to jump to custom interface). +When using Emacs in a graphic display (i.e. not in a terminal) you can as +well display your Helm buffers in separated frames globally for +all Helm commands or separately for specific Helm commands. +See `helm-display-function' and `helm-commands-using-frame'. +See also [[https://github.com/emacs-helm/helm/wiki/frame][helm wiki]] for more infos. + +There is a variable to allow reusing frame instead of deleting +and creating a new one at each session, see `helm-display-buffer-reuse-frame'. +Normally you don't have to use this, it have been made to workaround +slow frame popup in Emacs-26, to workaround this slowness in Emacs-26 use instead + +#+begin_src elisp + (when (= emacs-major-version 26) + (setq x-wait-for-event-timeout nil)) +#+end_src + +WARNING: +There is a package called Posframe and also one called Helm-posframe, +you DO NOT need these packages to display helm buffers in frames. +Thus Posframe package use child frames which have no minibuffers +and are by the way not compatible with Helm. + +** Helm's basic operations and default key bindings + +| Key| Command| +|----+--------| +| | +| \\[helm-previous-line]| Previous line | +| \\[helm-next-line]| Next line | +| \\[helm-scroll-up]| Scroll up | +| \\[helm-scroll-down]| Scroll down | +| \\[helm-scroll-other-window]| Scroll up other-window | +| \\[helm-scroll-other-window-down]| Scroll down other-window | +| \\[helm-maybe-exit-minibuffer]| Execute first (default) action / Select [1] | +| \\[helm-beginning-of-buffer]| Goto beginning of buffer | +| \\[helm-end-of-buffer]| Goto end of buffer | +| \\[helm-select-action]| Show actions menu | +| \\[helm-previous-source]| Previous source | +| \\[helm-next-source]| Next source | +| \\[helm-delete-minibuffer-contents]| Delete pattern (with prefix arg delete from point to end or all [2]) | +| \\[helm-execute-persistent-action]| Persistent action (Execute and keep Helm session) | +|\\[helm-toggle-resplit-and-swap-windows]|Rotate or swap windows. | +|\\[helm-exchange-minibuffer-and-header-line]|Exchange minibuffer and header-line. | +|\\[helm-quit-and-find-file]|Drop into `helm-find-files'. | +|\\[helm-kill-selection-and-quit]|Kill display value of candidate and quit (with prefix arg, kill the real value). | +|\\[helm-yank-selection]|Yank current selection into pattern. | +|\\[helm-insert-or-copy]|Insert or copy marked candidates (C-u) . | +|\\[helm-follow-mode]|Toggle automatic execution of persistent action. | +|\\[helm-follow-action-forward]|Run persistent action then select next line. | +|\\[helm-follow-action-backward]|Run persistent action then select previous line. | +|\\[helm-refresh]|Recalculate and redisplay candidates. | +|\\[helm-toggle-suspend-update]|Toggle candidate updates. | + +\[1] Behavior may change depending context in some source e.g. `helm-find-files'. + +\[2] Delete from point to end or all depending on the value of +`helm-delete-minibuffer-contents-from-point'. + +NOTE: Any of these bindings are from `helm-map' and may be +overriten by the map specific to the current source in use (each +source can have its own keymap). + +** The actions menu + +You can display the action menu in the same window +as helm candidates (default) or in a side window according to +`helm-show-action-window-other-window' value. + +When the action menu popup, the helm prompt is used to narrow +down this menu, no more candidates. + +When `helm-allow-mouse' is non nil, you can use as well +mouse-3 (right click) in the candidate zone to select actions +with the mouse once your candidate is selected. + +** Action transformers + +You may be surprized to see your actions list changing depending +on the context. This happen when a source has an action +transformer function which checks the current selected candidate +and adds specific actions for this candidate. + +** Shortcuts for n-th first actions + +f1-f12: Execute n-th action where n is 1 to 12. + +** Shortcuts for executing the default action on the n-th candidate + +Helm does not display line numbers by default, with Emacs-26+ you +can enable it permanently in all helm buffers with: + + (add-hook 'helm-after-initialize-hook 'helm-init-relative-display-line-numbers) + +You can also toggle line numbers with +\\\\[helm-display-line-numbers-mode] in current Helm +buffer. + +Of course when enabling `global-display-line-numbers-mode' Helm +buffers will have line numbers as well. \(Don't forget to +customize `display-line-numbers-type' to relative). + +In Emacs versions < to 26 you will have to use +[[https://github.com/coldnew/linum-relative][linum-relative]] +package and `helm-linum-relative-mode'. + +Then when line numbers are enabled with one of the methods above +the following keys are available([1]): + +C-x : Execute default action on the n-th candidate before +currently selected candidate. + +C-c : Execute default action on the n-th candidate after +current selected candidate. + +\"n\" is limited to 1-9. For larger jumps use other navigation +keys. + +\[1] Note that the key bindings are always available even if line +numbers are not displayed. They are just useless in this case. + +** Mouse control in Helm + +A basic support for the mouse is provided when the user sets +`helm-allow-mouse' to non-nil. + +- mouse-1 selects the candidate. +- mouse-2 executes the default action on selected candidate. +- mouse-3 pops up the action menu. + +Note: When mouse control is enabled in Helm, it also lets you +click around and lose the minibuffer focus: you'll have to click +on the Helm buffer or the minibuffer to retrieve control of your +Helm session. + +** Marked candidates + +You can mark candidates to execute an action on all of them +instead of the current selected candidate only. (See bindings +below.) Most Helm actions operate on marked candidates unless +candidate-marking is explicitely forbidden for a specific source. + +- To mark/unmark a candidate, use +\\[helm-toggle-visible-mark]. (See bindings below.) With a +numeric prefix arg mark ARG candidates forward, if ARG is +negative mark ARG candidates backward. + +- To mark all visible unmarked candidates at once in current +source use \\[helm-mark-all]. With a prefix argument, mark all +candidates in all sources. + +- To unmark all visible marked candidates at once use + \\[helm-unmark-all]. + +- To mark/unmark all candidates at once use +\\[helm-toggle-all-marks]. With a prefix argument, mark/unmark +all candidates in all sources. + +Note: When multiple candidates are selected across different +sources, only the candidates of the current source will be used +when executing most actions (as different sources can have +different actions). Some actions support multi-source marking +however. + +** Follow candidates + +When `helm-follow-mode' is on (\\\\[helm-follow-mode] +to toggle it), moving up and down Helm session or updating the +list of candidates will automatically execute the +persistent-action as specified for the current source. + +If `helm-follow-mode-persistent' is non-nil, the state of the +mode will be restored for the following Helm sessions. + +If you just want to follow candidates occasionally without +enabling `helm-follow-mode', you can use +\\\\[helm-follow-action-forward] or +\\[helm-follow-action-backward] instead. Conversely, when +`helm-follow-mode' is enabled, those commands go to previous/next +line without executing the persistent action. + +** Special yes, no or yes for all answers + +You may be prompted in the minibuffer to answer by [y,n,!,q] in +some places for confirmation. + +- y mean yes +- no mean no +- ! mean yes for all +- q mean quit or abort current operation. + +When using ! you will not be prompted for the same thing in +current operation any more, e.g. file deletion, file copy etc... + +** Moving in `helm-buffer' + +You can move in `helm-buffer' with the usual commands used in +Emacs: \(\\\\[helm-next-line], +\\\\[helm-previous-line], etc. See above basic +commands. When `helm-buffer' contains more than one source, +change source with \\\\[helm-next-source] and +\\[helm-previous-source]. + +Note: When reaching the end of a source, +\\\\[helm-next-line] will *not* go to the next source +when variable `helm-move-to-line-cycle-in-source' is non-nil, so +you will have to use \\\\[helm-next-source] and +\\[helm-previous-source]. + +** Resume previous session from current Helm session + +You can use `C-c n' (`helm-run-cycle-resume') to cycle in +resumables sources. `C-c n' is a special key set with +`helm-define-key-with-subkeys' which, after pressing it, allows +you to keep cycling with further `n'. + +Tip: You can bound the same key in `global-map' to + `helm-cycle-resume' with `helm-define-key-with-subkeys' to + let you transparently cycle sessions, Helm fired up or not. + You can also bind the cycling commands to single key + presses (e.g., `S-') this time with a simple + `define-key'. (Note that `S-' is not available in + terminals.) + +Note: `helm-define-key-with-subkeys' is available only once Helm +is loaded. + +You can also use +\\\\[helm-resume-previous-session-after-quit] to resume +the previous session, or +\\\\[helm-resume-list-buffers-after-quit] to have +completion on all resumable buffers. + +** Global commands + +*** Resume Helm session from outside Helm + +\\\\[helm-resume] revives the last Helm session. +Binding a key to this command will greatly improve Helm +interactivity, e.g. when quitting Helm accidentally. + +You can call \\\\[helm-resume] with a prefix argument +to choose \(with completion!) which session you'd like to resume. +You can also cycle in these sources with `helm-cycle-resume' (see +above). + +** Debugging Helm + +Helm exposes the special variable `helm-debug': setting it to +non-nil will enable Helm logging in a special outline-mode +buffer. Helm resets the variable to nil at the end of each +session. + +For convenience, \\\\[helm-enable-or-switch-to-debug] +allows you to turn on debugging for this session only. To avoid +accumulating log entries while you are typing patterns, you can +use \\\\[helm-toggle-suspend-update] to turn off +updating. When you are ready turn it on again to resume logging. + +Once you exit your Helm session you can access the debug buffer +with `helm-debug-open-last-log'. + +Note: Be aware that Helm log buffers grow really fast, so use +`helm-debug' only when needed. + +** Writing your own Helm sources + +Writing simple sources for your own usage is easy. When calling +the `helm' function, the sources are added the :sources slot +which can be a symbol or a list of sources. Sources can be built +with different EIEIO classes depending on what you want to do. To +simplify this, several `helm-build-*' macros are provided. Below +there are simple examples to start with. + +We will not go further here, see +[[https://github.com/emacs-helm/helm/wiki/Developing][Helm wiki]] +and the source code for more information and more complex +examples. + +#+begin_src elisp + + ;; Candidates are stored in a list. + (helm :sources (helm-build-sync-source \"test\" + ;; A function can be used as well + ;; to provide candidates. + :candidates '(\"foo\" \"bar\" \"baz\")) + :buffer \"*helm test*\") + + ;; Candidates are stored in a buffer. + ;; Generally faster but doesn't allow a dynamic updating + ;; of the candidates list i.e the list is fixed on start. + (helm :sources (helm-build-in-buffer-source \"test\" + :data '(\"foo\" \"bar\" \"baz\")) + :buffer \"*helm test*\") + +#+end_src + +** Helm Map +\\{helm-map}" + "Message string containing detailed help for `helm'. +It also accepts function or variable symbol.") + +(defvar helm-autoresize-mode) ;; Undefined in `helm-default-display-buffer'. + +(defvar helm-async-outer-limit-hook nil + "Run in async sources when process output is out of `candidate-number-limit'. +Should be set locally to `helm-buffer' with `helm-set-local-variable'.") + +(defvar helm-quit-hook nil + "A hook that runs when quitting Helm.") + +(defvar helm-resume-after-hook nil + "A hook that runs after resuming a Helm session. +The hook should takes one arg SOURCES.") + +(defvar helm-help-buffer-name "*Helm Help*" + "The name of helm help buffer.") + +;; See bug#2503. +(defvar helm-process-output-split-string-separator "\n" + "Separator to use when splitting helm async output.") + +(defvar helm-last-query "" + "The value of `helm-pattern' is stored here exit or quit.") + +;; Utility: logging +(defun helm-log (from format-string &rest args) + "Log message if `helm-debug' is non-nil. +Messages are written to the `helm-debug-buffer' buffer. + +FROM is the place from where it is called. +Argument FORMAT-STRING is a string to use with `format'. +Use optional arguments ARGS like in `format'." + (when helm-debug + (with-current-buffer (get-buffer-create helm-debug-buffer) + (outline-mode) + (buffer-disable-undo) + (let ((inhibit-read-only t)) + (goto-char (point-max)) + (insert (let ((tm (current-time))) + (format (concat (if (string-match "Start session" format-string) + "* " "** ") + "%s.%06d (%s)\n %s\n") + (format-time-string "%H:%M:%S" tm) + (nth 2 tm) + from + (apply #'format (cons format-string args))))))))) + +(defun helm-log-run-hook (from hook) + "Run HOOK like `run-hooks' and log these actions to Helm log buffer. +FROM is the place from where it is called." + (helm-log from "Executing %s with value = %S" hook (symbol-value hook)) + (helm-log from "Executing %s with global value = %S" hook (default-value hook)) + (run-hooks hook) + (helm-log from "executed %s" hook)) + +(defun helm-log-error (from &rest args) + "Accumulate error messages into `helm-issued-errors'. +FROM is the place from where it is called. +ARGS are args given to `format'. +E.g. (helm-log-error \"Error %s: %s\" (car err) (cdr err))." + (apply 'helm-log from (concat "ERROR: " (car args)) (cdr args)) + (let ((msg (apply 'format args))) + (unless (member msg helm-issued-errors) + (cl-pushnew msg helm-issued-errors :test 'equal)))) + +;;;###autoload +(defun helm-debug-open-last-log () + "Open Helm log file or buffer of last Helm session." + (interactive) + (if helm--last-log-file + (progn + (find-file helm--last-log-file) + (outline-mode) (view-mode 1) (visual-line-mode 1)) + (switch-to-buffer helm-debug-buffer) + (view-mode 1) (visual-line-mode 1))) + +(defun helm-print-error-messages () + "Print error messages in `helm-issued-errors'." + (and helm-issued-errors + (message "Helm issued errors: %s" + (mapconcat 'identity (reverse helm-issued-errors) "\n")))) + + +;; Test tools +(defmacro with-helm-time-after-update (&rest body) + (helm-with-gensyms (start-time time-elapsed) + `(let ((,start-time (float-time)) ,time-elapsed) + (add-hook 'helm-after-update-hook + (lambda () + (setq ,time-elapsed (- (float-time) ,start-time)) + (keyboard-quit))) + (unwind-protect ,@body + (remove-hook 'helm-after-update-hook + (lambda () + (setq ,time-elapsed (- (float-time) ,start-time)) + (keyboard-quit)))) + ,time-elapsed))) + + +;; Helm API +(defmacro with-helm-default-directory (directory &rest body) + (declare (indent 1) (debug t)) + `(let ((default-directory (or (and ,directory + (file-name-as-directory ,directory)) + default-directory))) + ,@body)) + +(defun helm-default-directory () + "Return the local value of `default-directory' in `helm-buffer'." + (buffer-local-value 'default-directory (get-buffer helm-buffer))) + +(defmacro with-helm-temp-hook (hook &rest body) + "Execute temporarily BODY as a function for HOOK." + (declare (indent 1) (debug t)) + `(letrec ((helm--hook (lambda () + (unwind-protect + (progn ,@body) + (remove-hook ,hook helm--hook))))) + (push (cons helm--hook ,hook) helm--temp-hooks) + (add-hook ,hook helm--hook))) + +(defmacro with-helm-after-update-hook (&rest body) + "Execute BODY at end of `helm-update'." + (declare (indent 0) (debug t)) + `(with-helm-temp-hook 'helm-after-update-hook ,@body)) + +(defmacro with-helm-alive-p (&rest body) + "Return error when BODY run outside Helm context." + (declare (indent 0) (debug t)) + `(progn + (if helm-alive-p + (progn ,@body) + (error "Running helm command outside of context")))) + +(defmacro with-helm-in-frame (&rest body) + "Execute Helm function in BODY displaying `helm-buffer' in separate frame." + (declare (debug t) (indent 0)) + `(progn + (helm-set-local-variable + 'helm-display-function 'helm-display-buffer-in-own-frame) + ,@body)) + +(defmacro helm-make-command-from-action (symbol doc action &rest body) + "Make a command SYMBOL from ACTION with docstring DOC. +The command SYMBOL will quit helm before execute. +Argument ACTION should be an existing helm action. +BODY form will run before calling action. + +Example: + + (helm-make-command-from-action foo-command + \"Docstring\" + \\='foo-action + (run body)) + +will produce a command like this: + + (defun foo-command () + \"docstring\" + (interactive) + (with-helm-alive-p + (run body) + (helm-exit-and-execute-action \\='foo-action))) + +And automatically put the symbol \\='helm-only on SYMBOL." + (declare (indent defun) (debug t)) + `(progn + (defun ,symbol () + ,doc + (interactive) + (with-helm-alive-p + (progn ,@body) + (helm-exit-and-execute-action ,action))) + (put ',symbol 'helm-only t))) + +(defmacro helm-make-persistent-command-from-action (symbol doc psymbol action) + "Make a persistent command SYMBOL bound to PSYMBOL from ACTION." + (declare (indent defun) (debug t)) + `(progn + (defun ,symbol () + ,doc + (interactive) + (with-helm-alive-p + (helm-set-attr ,psymbol (cons ,action 'never-split)) + (helm-execute-persistent-action ,psymbol))) + (put ',symbol 'helm-only t))) + + +;;; helm-attributes +;; +(defun helm-get-attr (attribute-name &optional source compute) + "Get the value of ATTRIBUTE-NAME of SRC. + +If SRC is omitted, use current source. + +If COMPUTE is non-`nil' compute value of ATTRIBUTE-NAME with +`helm-interpret-value'. COMPUTE can have also \\='ignorefn as value, +in this case `helm-interpret-value' will return a function as +value unchanged, but will eval a symbol which is bound. + +You can use `setf' to modify value of ATTRIBUTE-NAME unless +COMPUTE is specified, if attribute ATTRIBUTE-NAME is not found in +SOURCE `setf' will create new attribute ATTRIBUTE-NAME with +specified value. You can also use `helm-set-attr' to modify +ATTRIBUTE-NAME." + (declare (gv-setter + (lambda (val) + `(let* ((src (or ,source (helm-get-current-source))) + (attr (assq ,attribute-name src))) + (cl-assert (null ,compute) nil + "`setf' can't set the computed value of attribute `%s'" + ,attribute-name) + (if attr + (setcdr attr ,val) + (and (setcdr src (cons (cons ,attribute-name ,val) + (cdr src))) + ,val)))))) + (let ((src (or source (helm-get-current-source)))) + (helm-aif (assq attribute-name src) + (if compute + (helm-interpret-value (cdr it) src compute) + (cdr it))))) + +(defalias 'helm-attr 'helm-get-attr) +(make-obsolete 'helm-attr 'helm-get-attr "3.7.0") + +(cl-defun helm-set-attr (attribute-name value + &optional + (src (helm-get-current-source))) + "Set the value of ATTRIBUTE-NAME of source SRC to VALUE. + +If ATTRIBUTE-NAME doesn't exists in source it is created with +value VALUE. If SRC is omitted, use current source. If operation +succeed, return value, otherwise nil. + +Using this function is same as using `setf' on `helm-get-attr'." + (setf (helm-get-attr attribute-name src) value)) + +(defalias 'helm-attrset 'helm-set-attr) +(make-obsolete 'helm-attrset 'helm-set-attr "3.7.0") + +(defun helm-add-action-to-source (name fn source &optional index) + "Add new action NAME linked to function FN to SOURCE. +Function FN should be a valid function that takes one arg i.e. +candidate, argument NAME is a string that will appear in action +menu and SOURCE should be an existing helm source already loaded. +If INDEX is specified, action is added to the action list at INDEX, +otherwise added at end. +This allows users to add specific actions to an existing source +without modifying source code." + (let ((actions (helm-get-attr 'action source 'ignorefn)) + (new-action (list (cons name fn)))) + (when (functionp actions) + (setq actions (list (cons "Default action" actions)))) + (helm-set-attr 'action + (if index + (helm-append-at-nth actions new-action index) + (append actions new-action)) + source))) + +(defun helm-delete-action-from-source (action-or-name source) + "Delete ACTION-OR-NAME from SOURCE. +ACTION-OR-NAME can either be the name of action or the symbol +function associated to name." + (let* ((actions (helm-get-attr 'action source 'ignorefn)) + (del-action (if (symbolp action-or-name) + (rassoc action-or-name actions) + (assoc action-or-name actions)))) + (helm-set-attr 'action (delete del-action actions) source))) + +(cl-defun helm-add-action-to-source-if (name fn source predicate + &optional (index 4) test-only) + "Add new action NAME linked to function FN to SOURCE. +Action NAME will be available when the current candidate matches +PREDICATE. +This function adds an entry in the `action-transformer' attribute +of SOURCE (or creates one if not found). +Function PREDICATE must take one candidate as arg. +Function FN should be a valid function that takes one arg i.e. +candidate, argument NAME is a string that will appear in action +menu and SOURCE should be an existing Helm source already loaded. +If INDEX is specified, action is added in action list at INDEX. +Value of INDEX should be always >=1, default to 4. This allows +user to add a specific `action-transformer' to an existing source +without modifying source code. + +E.g. + +Add the action \"Byte compile file async\" linked to function +`async-byte-compile-file' to source `helm-source-find-files' only +when predicate helm-ff-candidates-lisp-p returns non-nil: + +\(helm-add-action-to-source-if \"Byte compile file async\" + \\='async-byte-compile-file + helm-source-find-files + \\='helm-ff-candidates-lisp-p)." + (let* ((actions (helm-get-attr 'action source 'ignorefn)) + (action-transformers (helm-get-attr 'action-transformer source)) + (new-action (list (cons name fn))) + (transformer (lambda (actions _candidate) + (let ((candidate (car (helm-marked-candidates)))) + (cond ((funcall predicate candidate) + (helm-append-at-nth + actions new-action index)) + (t actions)))))) + (when (functionp actions) + (helm-set-attr 'action (list (cons "Default action" actions)) source)) + (when (or (symbolp action-transformers) (functionp action-transformers)) + (setq action-transformers (list action-transformers))) + (if test-only ; debug + (delq nil (append (list transformer) action-transformers)) + (helm-set-attr 'action-transformer + (helm-fast-remove-dups + (delq nil (append (list transformer) action-transformers)) + :test 'equal) + source)))) + + +;;; Source filter +;; +(defun helm-set-source-filter (sources) + "Set the value of `helm-source-filter' to SOURCES and update. + +This function sets a filter for Helm sources and it may be called +while Helm is running. It can be used to toggle displaying of +sources dynamically. For example, additional keys can be bound +into `helm-map' to display only the file-related results if there +are too many matches from other sources and you're after files +only: + +Shift+F shows only file results from some sources: + +\(define-key helm-map \"F\" \\='helm-my-show-files-only) + +\(defun helm-my-show-files-only () + (interactive) + (helm-set-source-filter \\='(\"File Name History\" + \"Files from Current Directory\"))) + +Shift+A shows all results: + +\(define-key helm-map \"A\" \\='helm-my-show-all) + +\(defun helm-my-show-all () + (interactive) + (helm-set-source-filter nil)) + +The -my- part is added to avoid collisions with +existing Helm function names." + (with-helm-buffer + (let ((cur-disp-sel (helm-get-selection nil t))) + (set (make-local-variable 'helm-source-filter) + (helm--normalize-filter-sources sources)) + (helm-log "helm-set-source-filter" "helm-source-filter = %S" helm-source-filter) + ;; Use force-update to run init/update functions. + (helm-update (and (stringp cur-disp-sel) + (regexp-quote cur-disp-sel)))))) + +(defun helm--normalize-filter-sources (sources) + (cl-loop for s in sources collect + (cl-typecase s + (symbol (assoc-default 'name (symbol-value s))) + (list (assoc-default 'name s)) + (string s)))) + +(defun helm-set-sources (sources &optional no-init no-update) + "Set SOURCES during `helm' invocation. +If NO-INIT is non-nil, skip executing init functions of SOURCES. +If NO-UPDATE is non-nil, skip executing `helm-update'." + (with-current-buffer helm-buffer + (setq helm-sources (helm-get-sources sources)) + (helm-log "helm-set-sources" "helm-sources = %S" helm-sources)) + (unless no-init (helm-compute-attr-in-sources 'init)) + (unless no-update (helm-update))) + +(defun helm-show-all-candidates-in-source (arg) + "Toggle all or only candidate-number-limit cands in current source. +With a numeric prefix arg show only the ARG number of candidates. +The prefix arg has no effect when toggling to only +candidate-number-limit." + (interactive "p") + (with-helm-alive-p + (with-helm-buffer + (if helm-source-filter + (progn + (setq-local helm-candidate-number-limit + (default-value 'helm-candidate-number-limit)) + (helm-set-source-filter nil)) + (with-helm-default-directory (helm-default-directory) + (setq-local helm-candidate-number-limit (and (> arg 1) arg)) + (helm-set-source-filter + (list (helm-get-current-source)))))))) +(put 'helm-show-all-candidates-in-source 'helm-only t) + +(defun helm-display-all-sources () + "Display all sources previously hidden by `helm-set-source-filter'." + (interactive) + (with-helm-alive-p + (helm-set-source-filter nil))) +(put 'helm-display-all-sources 'helm-only t) + + +;;; Source infos fns. +;; +(defun helm-get-selection (&optional buffer force-display-part source) + "Return the currently selected candidate from BUFFER. + +If BUFFER is nil or unspecified, use `helm-buffer' as default value. + +If FORCE-DISPLAY-PART is non-nil, return the display part of candidate. + +If FORCE-DISPLAY-PART value is `withprop' the display part of +candidate is returned with its properties. + +When FORCE-DISPLAY-PART is nil the real part of candidate is returned. + +SOURCE default to current-source when unspecified but it is better to +specify SOURCE when it is already available to avoid to call +`helm-get-current-source' uselessly. + +Note that FORCE-DISPLAY-PART when specified takes precedence over +`display-to-real' attribute, that's mean don't use FORCE-DISPLAY-PART +when you want the `display-to-real' function(s) to be applied." + (with-current-buffer (or buffer helm-buffer) + (unless (or (helm-empty-buffer-p (current-buffer)) + (helm-pos-header-line-p)) + (let* ((beg (overlay-start helm-selection-overlay)) + (end (overlay-end helm-selection-overlay)) + (disp-fn (if (eq force-display-part 'withprop) + 'buffer-substring + 'buffer-substring-no-properties)) + ;; If there is no selection at point, the + ;; overlay is at its initial pos, (point-min) + ;; (point-min), that's mean the helm-buffer + ;; is not empty but have no selection yet, + ;; this happen with grep sentinel sending an + ;; error message in helm-buffer when no matches. + (disp (unless (= beg end) (funcall disp-fn beg (1- end)))) + (src (or source (helm-get-current-source))) + (selection (helm-acond (force-display-part disp) + ;; helm-realvalue always takes precedence + ;; over display-to-real. + ((get-text-property beg 'helm-realvalue) it) + ((assoc-default 'display-to-real src) + (helm-apply-functions-from-source source it disp)) + (t disp)))) + (unless (equal selection "") + (helm-log "helm-get-selection" "selection = %S" selection) + selection))))) + +(defun helm-get-actions-from-current-source (&optional source) + "Return the associated action for the selected candidate. +It is a function symbol (sole action) or list +of (action-display . function)." + (unless (helm-empty-buffer-p (helm-buffer-get)) + (let* ((src (or source (helm-get-current-source))) + (marked (helm-marked-candidates)) + (action-transformer (helm-get-attr 'action-transformer src)) + (actions (helm-get-attr 'action src 'ignorefn))) + (if action-transformer + (helm-apply-functions-from-source + src action-transformer actions + ;; When there is marked candidates assume the set of + ;; candidates user selected contains candidates of the same + ;; type so that the actions added by transformer fit with + ;; all marked (previously we were looping on each marked + ;; but it is too costly for the benefit it brings). + (car marked)) + actions)))) + +(defun helm-get-current-source () + "Return the source for the current selection. +Return nil when `helm-buffer' is empty." + (or helm-current-source + (with-helm-buffer + (or (get-text-property (point) 'helm-cur-source) + (progn + ;; This is needed to not loose selection. + (goto-char (overlay-start helm-selection-overlay)) + (let ((header-pos (or (helm-get-previous-header-pos) + (helm-get-next-header-pos)))) + ;; Return nil when no--candidates. + (when header-pos + (cl-loop with source-name = (save-excursion + (goto-char header-pos) + (helm-current-line-contents)) + for source in helm-sources thereis + (and (equal (assoc-default 'name source) source-name) + source))))))))) + +(defun helm-run-after-exit (function &rest args) + "Execute FUNCTION with ARGS after exiting Helm. +The action is to call FUNCTION with arguments ARGS. +Unlike `helm-exit-and-execute-action', this can be used +to call non-actions functions with any ARGS or no ARGS at all. + +Use this on commands invoked from key bindings, but not on action +functions invoked as action from the action menu, i.e. functions +called with RET." + (helm-kill-async-processes) + (helm-log "helm-run-after-exit" "function = %S" function) + (helm-log "helm-run-after-exit" "args = %S" args) + (helm-exit-and-execute-action + (lambda (_candidate) + (apply function args)))) + +(defun helm-exit-and-execute-action (action) + "Exit current Helm session and execute ACTION. +Argument ACTION is a function called with one arg (candidate) and +part of the actions of current source. + +Use this on commands invoked from key bindings, but not +on action functions invoked as action from the action menu, +i.e. functions called with RET." + ;; If ACTION is not an action available in source 'action attribute, + ;; return an error. This allow to remove unneeded actions from + ;; source that inherit actions from type, note that ACTION have to + ;; be bound to a symbol and not to be an anonymous action + ;; i.e. lambda or byte-code. + (helm-log "helm-exit-and-execute-action" "Start executing action") + (let ((actions (helm-get-actions-from-current-source))) + (when actions + (cl-assert (or (eq action actions) + ;; Compiled lambdas + (byte-code-function-p action) + ;; Natively compiled (libgccjit) + (helm-subr-native-elisp-p action) + ;; Lambdas + (and (listp action) (functionp action)) + ;; One of current actions. + (rassq action actions)) + nil "No such action `%s' for this source" action))) + (setq helm-saved-action action) + (setq helm-saved-selection (or (helm-get-selection) "")) + (setq helm--executing-helm-action t) + ;; When toggling minibuffer and header-line, we want next action + ;; inherit this setting. + (helm-set-local-variable 'helm-echo-input-in-header-line + (with-helm-buffer helm-echo-input-in-header-line)) + ;; Ensure next action use same display function as initial helm-buffer when + ;; helm-actions-inherit-frame-settings is non nil. + (when (and helm-actions-inherit-frame-settings + helm--buffer-in-new-frame-p) + (helm-set-local-variable 'helm-display-function + (with-helm-buffer helm-display-function) + 'helm--last-frame-parameters + (with-helm-buffer + (helm--get-frame-parameters))) + ;; The helm-buffer keeps `helm-display-function' and + ;; `helm--get-frame-parameters' values during 0.5 seconds, just + ;; the time to execute the possible helm action with those values. + ;; If no helm based action run within 0.5 seconds, the next helm + ;; session will have to resolve again those variable values. + (run-with-idle-timer 0.5 nil + (lambda () (helm-set-local-variable 'helm-display-function nil + 'helm--last-frame-parameters nil)))) + (helm-exit-minibuffer)) + +(defun helm--get-frame-parameters (&optional frame) + (cl-loop with params = (frame-parameters frame) + for p in helm--frame-default-attributes + when (assq p params) collect it)) + +(defalias 'helm-run-after-quit 'helm-run-after-exit) +(make-obsolete 'helm-run-after-quit 'helm-run-after-exit "1.7.7") +(defalias 'helm-quit-and-execute-action 'helm-exit-and-execute-action) +(make-obsolete 'helm-quit-and-execute-action 'helm-exit-and-execute-action "1.7.7") + +(defun helm-interpret-value (value &optional source compute) + "Interpret VALUE as variable, function or literal and return it. +If VALUE is a function, call it with no arguments and return the value +unless COMPUTE value is \\='ignorefn. +If SOURCE compute VALUE for this source. +If VALUE is a variable, return the value. +If VALUE is a symbol, but it is not a function or a variable, cause an error. +Otherwise, return VALUE itself." + (cond ((and source (functionp value) (not (eq compute 'ignorefn))) + (helm-apply-functions-from-source source value)) + ((and (functionp value) (not (eq compute 'ignorefn))) + (funcall value)) + ((and (symbolp value) (boundp value)) + (symbol-value value)) + ((and (symbolp value) (not (functionp value))) + (error + "helm-interpret-value: Symbol must be a function or a variable")) + (t + value))) + +(defun helm-set-local-variable (&rest args) + "Bind each pair in ARGS locally to `helm-buffer'. + +Use this to set local vars before calling helm. + +When used from an init or update function +\(i.e. when `helm-force-update' is running) the variables are set +using `make-local-variable' within the `helm-buffer'. + +Usage: helm-set-local-variable ([VAR VALUE]...) +Just like `setq' except that the vars are not set sequentially. +IOW Don't use VALUE of previous VAR to set the VALUE of next VAR. + +\(fn VAR VALUE ...)" + (if helm--force-updating-p + (with-helm-buffer + (cl-loop for i on args by #'cddr + do (set (make-local-variable (car i)) (cadr i)))) + (setq helm--local-variables + (append (cl-loop for i on args by #'cddr + collect (cons (car i) (cadr i))) + helm--local-variables)))) + +(defun helm--set-local-variables-internal () + (cl-loop for (var . val) in helm--local-variables + ;; If `helm-set-local-variable' is called twice or more + ;; on same variable use the last value entered which is + ;; the first on stack e.g. + ;; (helm-set-local-variable 'helm-foo 1) + ;; (helm-set-local-variable 'helm-foo 2) + ;; helm--local-variables => + ;; '((helm-foo . 2) (helm-foo. 1)) + ;; (helm-foo . 2) is retained and (helm-foo . 1) + ;; ignored. + unless (memq var computed) + do (set (make-local-variable var) val) + collect var into computed + finally (setq helm--local-variables nil))) + + +;; API helper +(cl-defun helm-empty-buffer-p (&optional (buffer helm-buffer)) + "Check if BUFFER have candidates. +Default value for BUFFER is `helm-buffer'." + (zerop (buffer-size (and buffer (get-buffer buffer))))) + +(defun helm-empty-source-p () + "Check if current source contains candidates. +This could happen when for example the last element of a source +was deleted and the candidates list not updated." + (when (helm-window) + (with-helm-window + (or (helm-empty-buffer-p) + (and (helm-end-of-source-p) + (eq (point-at-bol) (point-at-eol)) + (or + (save-excursion + (forward-line -1) + (helm-pos-header-line-p)) + (bobp))))))) + + +;; Tools +;; +(defun helm-apply-functions-from-source (source functions &rest args) + "From SOURCE apply FUNCTIONS on ARGS. + +This function is used to process filter functions. When filter is +a `filtered-candidate-transformer', we pass to ARGS +candidates+source whereas when the filter is +`candidate-transformer' we pass to ARGS candidates only. +This function is also used to process functions called with no +args, e.g. init functions. In this case it is called without +ARGS. +See `helm-process-filtered-candidate-transformer' + `helm-compute-attr-in-sources' + `helm-process-candidate-transformer'. + +Arg FUNCTIONS is either a symbol or a list of functions, each +function being applied on ARGS and called on the result of the +precedent function. Return the result of last function call." + (let ((helm--source-name (assoc-default 'name source)) + (helm-current-source source) + (funs (if (functionp functions) (list functions) functions))) + (cl-loop with result + for fn in funs + ;; In filter functions, ARGS is a list of one or two elements where + ;; the first element is the list of candidates and the second + ;; a list containing the source. + do (setq result (apply fn args)) + when (and args (cdr funs)) + ;; When more than one fn, set the candidates list to what returns + ;; this fn to compute the modified candidates with the next fn + ;; and so on. + do (setcar args result) + finally return result))) + +(defalias 'helm-funcall-with-source 'helm-apply-functions-from-source) +(make-obsolete 'helm-funcall-with-source 'helm-apply-functions-from-source "2.9.7") + +(defun helm-compute-attr-in-sources (attr &optional sources) + "Call the associated function(s) to ATTR for each source if any." + (let ((sources (or (helm-get-sources sources) + ;; Fix error no buffer named *helm... by checking + ;; if helm-buffer exists. + (and (buffer-live-p (get-buffer (helm-buffer-get))) + ;; `helm-sources' are local to helm-buffer. + (with-helm-buffer helm-sources))))) + (when sources + (dolist (source sources) + (helm-aif (assoc-default attr source) + (helm-apply-functions-from-source source it)))))) + +(defalias 'helm-funcall-foreach 'helm-compute-attr-in-sources) +(make-obsolete 'helm-funcall-foreach 'helm-compute-attr-in-sources "2.9.7") + +(defun helm-normalize-sources (sources) + "If SOURCES is only one source, make a list of one element." + (if (or (and sources (symbolp sources)) + (and (listp sources) (assq 'name sources))) + (list sources) + sources)) + +(defun helm-get-candidate-number (&optional in-current-source) + "Return candidates number in `helm-buffer'. +If IN-CURRENT-SOURCE is provided return the number of candidates +of current source only." + (with-helm-buffer + (if (or (helm-empty-buffer-p) + (helm-empty-source-p)) + 0 + (save-excursion + (helm-aif (and in-current-source (helm-get-previous-header-pos)) + (goto-char it) + (goto-char (point-min))) + (forward-line 1) + (if (helm-pos-multiline-p) + (cl-loop with count-multi = 1 + while (and (not (if in-current-source + (save-excursion + (forward-line 2) + (or (helm-pos-header-line-p) (eobp))) + (eobp))) + (search-forward helm-candidate-separator nil t)) + do (cl-incf count-multi) + finally return count-multi) + (cl-loop with ln = 0 + while (not (if in-current-source + (or (helm-pos-header-line-p) (eobp)) + (eobp))) + ;; Don't count empty lines maybe added by popup (bug#1370). + unless (or (eq (point-at-bol) (point-at-eol)) + (helm-pos-header-line-p)) + do (cl-incf ln) + do (forward-line 1) finally return ln)))))) + +;; Entry point +;; `:allow-nest' is not in this list because it is treated before. +(defconst helm-argument-keys + '(:sources :input :prompt :resume + :preselect :buffer :keymap :default :history)) + +;;;###autoload +(defun helm (&rest plist) + "Main function to execute helm sources. + +PLIST is a list like + +\(:key1 val1 :key2 val2 ...) + + or + +\(&optional sources input prompt resume preselect + buffer keymap default history allow-nest). + +** Keywords + +Keywords supported: + +- :sources +- :input +- :prompt +- :resume +- :preselect +- :buffer +- :keymap +- :default +- :history +- :allow-nest + +Extra LOCAL-VARS keywords are supported, see the \"** Other +keywords\" section below. + +Basic keywords are the following: + +*** :sources + +One of the following: + +- List of sources +- Symbol whose value is a list of sources +- Alist representing a Helm source. + - In this case the source has no name and is referenced in + `helm-sources' as a whole alist. + +*** :input + +Initial input of minibuffer (temporary value of `helm-pattern') + +*** :prompt + +Minibuffer prompt. Default value is `helm--prompt'. + +*** :resume + +If t, allow resumption of the previous session of this Helm +command, skipping initialization. + +If \\='noresume, this instance of `helm' cannot be resumed. + +*** :preselect + +Initially selected candidate (string or regexp). + +*** :buffer + +Buffer name for this Helm session. `helm-buffer' will take this value. + +*** :keymap + +\[Obsolete] + +Keymap used at the start of this Helm session. + +It is overridden by keymaps specified in sources, and is kept +only for backward compatibility. + +Keymaps should be specified in sources using the :keymap slot +instead. See `helm-source'. + +This keymap is not restored by `helm-resume'. + +*** :default + +Default value inserted into the minibuffer \ with +\\\\[next-history-element]. + +It can be a string or a list of strings, in this case +\\\\[next-history-element] cycles through +the list items, starting with the first. + +If nil, `thing-at-point' is used. + +If `helm-maybe-use-default-as-input' is non-nil, display is +updated using this value if this value matches, otherwise it is +ignored. If :input is specified, it takes precedence on :default. + +*** :history + +Minibuffer input, by default, is pushed to `minibuffer-history'. + +When an argument HISTORY is provided, input is pushed to +HISTORY. HISTORY should be a valid symbol. + +*** :allow-nest + +Allow running this Helm command in a running Helm session. + +** Other keywords + +Other keywords are interpreted as local variables of this Helm +session. The `helm-' prefix can be omitted. For example, + +\(helm :sources \\='helm-source-buffers-list + :buffer \"*helm buffers*\" + :candidate-number-limit 10) + +Starts a Helm session with the variable +`helm-candidate-number-limit' set to 10. + +** Backward compatibility + +For backward compatibility, positional parameters are +supported: + +\(helm sources input prompt resume preselect + buffer keymap default history allow-nest) + +However, the use of non-keyword args is deprecated. + +\(fn &key SOURCES INPUT PROMPT RESUME PRESELECT BUFFER KEYMAP DEFAULT HISTORY ALLOW-NEST OTHER-LOCAL-VARS)" + (let ((fn (cond ((or (and helm-alive-p (plist-get plist :allow-nest)) + (and helm-alive-p (memq 'allow-nest plist))) + #'helm--nest) + ((keywordp (car plist)) + #'helm) + (t #'helm-internal)))) + (if (and helm-alive-p (eq fn #'helm)) + (if (helm--alive-p) + ;; A helm session is normally running. + (error "Error: Trying to run helm within a running helm session") + ;; A helm session is already running and user jump somewhere else + ;; without deactivating it. + (with-helm-buffer + (prog1 + (message "Aborting an helm session running in background") + ;; `helm-alive-p' will be reset in unwind-protect forms. + (helm-keyboard-quit)))) + (if (keywordp (car plist)) + ;; Parse `plist' and move not regular `helm-argument-keys' + ;; to `helm--local-variables', then calling helm on itself + ;; with normal arguments (the non--arguments-keys removed) + ;; will end up in [1]. + (progn + (setq helm--local-variables + (append helm--local-variables + ;; Vars passed by keyword on helm call + ;; take precedence on same vars + ;; that may have been passed before helm call. + (helm-parse-keys plist))) + (apply fn (mapcar (lambda (key) (plist-get plist key)) + helm-argument-keys))) + (apply fn plist))))) ; [1] fn == helm-internal. + +(defun helm--alive-p () + "[INTERNAL] Check if `helm' is alive. +An Helm session is considered alive if `helm-alive-p' value is +non-nil, the `helm-buffer' is visible, and cursor is in the +minibuffer." + (and helm-alive-p + (get-buffer-window (helm-buffer-get) 'visible) + (minibuffer-window-active-p (minibuffer-window)) + (minibufferp (current-buffer)))) + +(defun helm-parse-keys (keys) + "Parse the KEYS arguments of `helm'. +Return only those keys not in `helm-argument-keys', prefix them +with \"helm\", and then convert them to an alist. This allows +adding arguments that are not part of `helm-argument-keys', but +are valid helm variables nevertheless. For example, +:candidate-number-limit is bound to `helm-candidate-number-limit' +in the source. + + (helm-parse-keys \\='(:sources ((name . \"test\") + (candidates . (a b c))) + :buffer \"toto\" + :candidate-number-limit 4)) + ==> ((helm-candidate-number-limit . 4))." + + (cl-loop for (key value) on keys by #'cddr + for symname = (substring (symbol-name key) 1) + for sym = (intern (if (string-match "^helm-" symname) + symname + (concat "helm-" symname))) + unless (memq key helm-argument-keys) + collect (cons sym value))) + +(defun helm--maybe-load-tramp-archive () + ;; Should fix bug#2393 and bug#2394. `while-no-input-ignore-events' + ;; is also let-bounded in `helm--maybe-use-while-no-input'. + (let ((while-no-input-ignore-events + (and (boundp 'while-no-input-ignore-events) + (cons 'dbus-event while-no-input-ignore-events)))) + (unless helm--tramp-archive-maybe-loaded + ;; This for Emacs-27 not requiring tramp-archive. + (and (boundp 'tramp-archive-enabled) + (require 'tramp-archive nil t)) + (setq helm--tramp-archive-maybe-loaded t)))) + +;;; Entry point helper +(defun helm-internal (&optional + sources input + prompt resume + preselect buffer + keymap default history) + "The internal Helm function called by `helm'. +For SOURCES INPUT PROMPT RESUME PRESELECT BUFFER KEYMAP DEFAULT and +HISTORY args see `helm'." + (cl-assert (or (stringp input) + (null input)) + nil "Error in %S buffer: Initial input should be a string or nil" + buffer) + ;; Set all windows NON dedicated to avoid headaches with PA and + ;; helm-window (bug#2443) + (cl-loop for win in (window-list nil 1) + for state = (window-dedicated-p win) + when state + do (progn (set-window-dedicated-p win nil) + (push `(,win . ,state) helm--original-dedicated-windows-alist))) + (unless helm--nested (setq helm-initial-frame (selected-frame))) + ;; Launch tramp-archive with dbus-event in `while-no-input-ignore-events'. + (helm--maybe-load-tramp-archive) + ;; Activate the advices. + ;; Advices will be available only in >=emacs-24.4, but + ;; allow compiling without errors on lower emacs. + (when (fboundp 'advice-add) + (advice-add 'tramp-read-passwd :around #'helm--suspend-read-passwd) + (advice-add 'ange-ftp-get-passwd :around #'helm--suspend-read-passwd) + (advice-add 'epa-passphrase-callback-function + :around #'helm--suspend-read-passwd) + ;; Ensure linum-mode is disabled in Helm buffers to preserve + ;; performances (Bug#1894). + (advice-add 'linum-on :override #'helm--advice-linum-on '((depth . 100)))) + (helm-log "helm-internal" (concat "[Start session] " (make-string 41 ?+))) + (helm-log "helm-internal" "prompt = %S" prompt) + (helm-log "helm-internal" "preselect = %S" preselect) + (helm-log "helm-internal" "buffer = %S" buffer) + (helm-log "helm-internal" "keymap = %S" keymap) + (helm-log "helm-internal" "default = %S" default) + (helm-log "helm-internal" "history = %S" history) + (setq helm--prompt (or prompt "pattern: ")) + (let ((non-essential t) + ;; Prevent mouse jumping to the upper-right + ;; hand corner of the frame (bug#1538). + mouse-autoselect-window + focus-follows-mouse + mode-line-in-non-selected-windows + minibuffer-completion-confirm + (ori--minibuffer-follows-selected-frame + (and (boundp 'minibuffer-follows-selected-frame) + (default-toplevel-value 'minibuffer-follows-selected-frame))) + (input-method-verbose-flag helm-input-method-verbose-flag) + (helm-maybe-use-default-as-input + (and (null input) + (or helm-maybe-use-default-as-input ; it is let-bounded so use it. + (cl-loop for s in (helm-normalize-sources sources) + thereis (memq s helm-sources-using-default-as-input)))))) + (unwind-protect + (condition-case-unless-debug _v + (let ( ;; `helm--source-name' is non-`nil' + ;; when `helm' is invoked by action, reset it. + helm--source-name + helm-current-source + helm-in-persistent-action + helm--quit + (helm-buffer (or buffer helm-buffer))) + (helm-initialize + resume input default sources) + ;; This allows giving the focus to a nested helm session which use + ;; a frame, like completion in + ;; `helm-eval-expression'. Unfortunately + ;; `minibuffer-follows-selected-frame' is available only in + ;; emacs-28+ (bug#2536). + ;; When non-nil (the default) the current active + ;; minibuffer is used in new frame, which is not what we + ;; want in helm when starting from an active minibuffer, + ;; either a helm minibuffer or something line M-:. + (and ori--minibuffer-follows-selected-frame + (setq minibuffer-follows-selected-frame + (unless (or helm--nested + ;; Allow keeping initial minibuffer visible + ;; e.g. completion-at-point from M-:. + (minibufferp helm-current-buffer)) + t))) + ;; We don't display helm-buffer here to avoid popping + ;; up a window or a frame when exiting immediately when + ;; only one candidate (this avoid having the helm frame + ;; flashing), lets first compute candidates and if more + ;; than one display helm-buffer (this is done later in + ;; helm-read-from-minibuffer). + (unless helm-execute-action-at-once-if-one + (helm-display-buffer helm-buffer resume) + (select-window (helm-window)) + (when (and resume helm-visible-mark-overlays) + (set-window-margins (selected-window) + (+ (string-width helm-visible-mark-prefix) + helm-left-margin-width)))) + ;; We are now in helm-buffer. + (unless helm-allow-mouse + (helm--remap-mouse-mode 1)) ; Disable mouse bindings. + (add-hook 'post-command-hook 'helm--maybe-update-keymap) + ;; Add also to update hook otherwise keymap is not updated + ;; until a key is hitted (Bug#1670). + (add-hook 'helm-after-update-hook 'helm--maybe-update-keymap) + (add-hook 'post-command-hook 'helm--update-header-line) + (helm-log "helm-internal" "show prompt") + (unwind-protect + (helm-read-from-minibuffer + prompt input preselect + resume keymap default history) + (helm-cleanup)) + (prog1 + (unless helm--quit (helm-execute-selection-action)) + (helm-log "helm-internal" (concat "[End session] " (make-string 41 ?-))))) + (quit + (helm-restore-position-on-quit) + (helm-log-run-hook "helm-internal" 'helm-quit-hook) + (helm-log "helm-internal" (concat "[End session (quit)] " (make-string 34 ?-))) + nil)) + (when (fboundp 'advice-remove) + (advice-remove 'tramp-read-passwd #'helm--suspend-read-passwd) + (advice-remove 'ange-ftp-get-passwd #'helm--suspend-read-passwd) + (advice-remove 'epa-passphrase-callback-function #'helm--suspend-read-passwd) + (advice-remove 'linum-on #'helm--advice-linum-on)) + (helm-log "helm-internal" "helm-alive-p = %S" (setq helm-alive-p nil)) + (helm--remap-mouse-mode -1) ; Reenable mouse bindings. + (setq helm-alive-p nil) + (and ori--minibuffer-follows-selected-frame + (set-default-toplevel-value 'minibuffer-follows-selected-frame + ori--minibuffer-follows-selected-frame)) + ;; Prevent error "No buffer named *helm*" triggered by + ;; `helm-set-local-variable'. + (setq helm--force-updating-p nil) + (setq helm--buffer-in-new-frame-p nil) + ;; Reset helm-pattern so that lambda's using it + ;; before running helm will not start with its old value. + (setq helm-pattern "") + (setq helm--ignore-errors nil + helm-debug nil)))) + +(defun helm--advice-linum-on () + (unless (or (minibufferp) + (string-match "\\`\\*helm" (buffer-name)) + (and (daemonp) (null (frame-parameter nil 'client)))) + (linum-mode 1))) + +;;; Helm resume +;; +;; +(defun helm-resume (arg) + "Resume a previous Helm session. +Call with a prefix arg to choose among existing Helm +buffers (sessions). When calling from Lisp, specify a +`buffer-name' as a string with ARG." + (interactive "P") + (let (buffer + cur-dir + narrow-pos + (helm-full-frame (default-value 'helm-full-frame)) + sources) + (if arg + (if (and (stringp arg) (bufferp (get-buffer arg))) + (setq buffer arg) + (setq buffer (helm-resume-select-buffer))) + (setq buffer helm-last-buffer)) + (cl-assert buffer nil + "helm-resume: No helm buffers found to resume") + (setq sources (buffer-local-value + 'helm-sources (get-buffer buffer))) + ;; Reset `cursor-type' to nil as it have been set to t + ;; when quitting previous session. + (with-current-buffer buffer (setq cursor-type nil)) + (setq helm-full-frame (buffer-local-value + 'helm-full-frame (get-buffer buffer))) + (setq cur-dir (buffer-local-value + 'default-directory (get-buffer buffer))) + (setq helm-saved-selection nil + helm-saved-action nil) + (unless (buffer-live-p helm-current-buffer) + ;; `helm-current-buffer' may have been killed. + (setq helm-current-buffer (current-buffer))) + (helm-aif (with-current-buffer buffer + helm--current-buffer-narrowed) + (progn + (set-buffer (car it)) + (setq narrow-pos (cdr it)))) + ;; This happen when calling C-x b within helm. + (helm-aif (get-buffer-window helm-marked-buffer-name 'visible) + (progn (delete-window it) (kill-buffer helm-marked-buffer-name))) + (save-restriction + (when narrow-pos (apply #'narrow-to-region narrow-pos)) + ;; Restart with same `default-directory' value this session + ;; was initially started with. + (with-helm-default-directory cur-dir + (unwind-protect + (helm + :sources sources + :input (buffer-local-value 'helm-input-local (get-buffer buffer)) + :prompt (buffer-local-value 'helm--prompt (get-buffer buffer)) + :resume t + :buffer buffer) + (run-hook-with-args 'helm-resume-after-hook sources)))))) + +(defun helm-resume-previous-session-after-quit () + "Resume previous Helm session within a running Helm." + (interactive) + (with-helm-alive-p + (let ((arg (if (null (member helm-buffer helm-buffers)) 0 1))) + (if (> (length helm-buffers) arg) + (helm-run-after-exit (lambda () (helm-resume (nth arg helm-buffers)))) + (message "No previous helm sessions available for resuming!"))))) +(put 'helm-resume-previous-session-after-quit 'helm-only t) + +(defun helm-resume-list-buffers-after-quit () + "List Helm buffers that can be resumed within a running Helm." + (interactive) + (with-helm-alive-p + (if (> (length helm-buffers) 0) + (helm-run-after-exit (lambda () (helm-resume t))) + (message "No previous helm sessions available for resuming!")))) +(put 'helm-resume-list-buffers-after-quit 'helm-only t) + +(defun helm-resume-p (resume) + "Whether current Helm session is resumed or not." + (eq resume t)) + +(defun helm-resume-select-buffer () + "Select an `helm-buffer' in `helm-buffers' list to resume a helm session. +Return nil if no `helm-buffer' found." + (when helm-buffers + (or (helm :sources (helm-build-sync-source "Resume helm buffer" + :candidates helm-buffers) + :resume 'noresume + :buffer "*helm resume*") + (keyboard-quit)))) + +;;;###autoload +(defun helm-cycle-resume () + "Cycle in `helm-buffers' list and resume when waiting more than 1.2s." + (interactive) + (cl-assert (and helm-buffers helm-last-buffer) + nil "No helm buffers to resume") + ;; Setup a new iterator only on first hit on + ;; `helm-run-cycle-resume', subsequents hits should reuse same + ;; iterator. + (unless (and (eq last-command 'helm-cycle-resume) + helm--cycle-resume-iterator) + (setq helm--cycle-resume-iterator + (helm-iter-sub-next-circular + helm-buffers helm-last-buffer :test 'equal))) + (helm--resume-or-iter)) + +(defun helm--resume-or-iter (&optional from-helm) + (message "Resuming helm buffer `%s'" helm-last-buffer) + (if (sit-for helm-cycle-resume-delay) + ;; Delay expire, run helm-resume. + (if from-helm + (helm-run-after-exit (lambda () (helm-resume helm-last-buffer))) + (helm-resume helm-last-buffer)) + ;; key pressed before delay, cycle. + (unless from-helm ; cycling to next item already done. + (message "Resuming helm buffer `%s'" + (setq helm-last-buffer + (helm-iter-next helm--cycle-resume-iterator)))))) + +(defun helm-run-cycle-resume () + "Same as `helm-cycle-resume' but intended to be called only from Helm." + (interactive) + (when (cdr helm-buffers) ; only one session registered. + ;; Setup a new iterator only on first hit on + ;; `helm-run-cycle-resume', subsequents hits should reuse same + ;; iterator. + (unless (and (eq last-command 'helm-run-cycle-resume) + helm--cycle-resume-iterator) + (setq helm--cycle-resume-iterator + (helm-iter-sub-next-circular + helm-buffers helm-last-buffer :test 'equal))) + ;; start at next buffer as we already are at `helm-last-buffer'. + (setq helm-last-buffer + (helm-iter-next helm--cycle-resume-iterator)) + (helm--resume-or-iter 'from-helm))) +(put 'helm-run-cycle-resume 'helm-only t) + + +;;; Nested sessions +;; +;; +(defun helm--nest (&rest same-as-helm) + "[INTERNAL] Allow calling `helm' within a running Helm session. + +Arguments SAME-AS-HELM are the same as `helm'. + +Don't use this directly, use instead `helm' with the keyword +:allow-nest. + +\(fn &key SOURCES INPUT PROMPT RESUME PRESELECT BUFFER KEYMAP DEFAULT HISTORY OTHER-LOCAL-VARS)" + (with-helm-window + (let ((orig-helm-current-buffer helm-current-buffer) + (orig-helm-buffer helm-buffer) + (orig-helm--prompt helm--prompt) + (orig-helm-sources helm-sources) + (orig-helm--in-fuzzy helm--in-fuzzy) + (orig-helm--display-frame helm--buffer-in-new-frame-p) + (orig-helm-last-frame-or-window-configuration + helm-last-frame-or-window-configuration) + (orig-one-window-p helm-onewindow-p) + (helm--nested (if helm--buffer-in-new-frame-p 'share t))) + ;; FIXME Using helm-full-frame here allow showing the new + ;; helm-buffer in the same window as old helm-buffer, why? + (helm-set-local-variable 'helm-full-frame t) + (unwind-protect + (let (helm-current-position + helm-current-buffer + helm-pattern + (helm-buffer (or (cl-getf same-as-helm :buffer) + (nth 5 same-as-helm) + "*Helm*")) + (enable-recursive-minibuffers t)) + (setq helm-sources nil) + (apply #'helm same-as-helm)) + (with-current-buffer orig-helm-buffer + (setq helm-sources orig-helm-sources) + (setq helm--nested nil) + (setq helm--buffer-in-new-frame-p orig-helm--display-frame) + (setq helm-alive-p t) ; Nested session set this to nil on exit. + (setq helm-buffer orig-helm-buffer) + (setq helm-full-frame nil) + (setq helm--prompt orig-helm--prompt) + (setq helm--in-fuzzy orig-helm--in-fuzzy) + (helm-initialize-overlays helm-buffer) + (unless (helm-empty-buffer-p) (helm-mark-current-line t)) + (setq helm-last-frame-or-window-configuration + orig-helm-last-frame-or-window-configuration) + (setq cursor-type nil) + (setq helm-current-buffer orig-helm-current-buffer) + (setq helm-onewindow-p orig-one-window-p) + ;; Be sure advices, hooks, and local modes keep running. + (advice-add 'tramp-read-passwd + :around #'helm--suspend-read-passwd) + (advice-add 'ange-ftp-get-passwd + :around #'helm--suspend-read-passwd) + (advice-add 'epa-passphrase-callback-function + :around #'helm--suspend-read-passwd) + (unless helm-allow-mouse + (helm--remap-mouse-mode 1)) + (unless (cl-loop for h in post-command-hook + thereis (memq h '(helm--maybe-update-keymap + helm--update-header-line))) + (add-hook 'post-command-hook 'helm--maybe-update-keymap) + (add-hook 'post-command-hook 'helm--update-header-line)) + (helm-display-mode-line (helm-get-current-source))))))) + + +;;; Windows and frames +;; +;; + +(defun helm-frame-or-window-configuration (save-or-restore) + "Save or restore last frame or window configuration. +Argument SAVE-OR-RESTORE is either save or restore of window or +frame configuration as per `helm-save-configuration-functions'." + (helm-log "helm-frame-or-window-configuration" "helm-save-configuration-functions = %S" + helm-save-configuration-functions) + (let ((window-persistent-parameters (append '((no-other-window . t)) + window-persistent-parameters))) + (cl-case save-or-restore + (save (setq helm-last-frame-or-window-configuration + (funcall (cdr helm-save-configuration-functions)))) + (restore (funcall (car helm-save-configuration-functions) + helm-last-frame-or-window-configuration) + ;; Restore dedicated windows (bug#2443). + (when helm--original-dedicated-windows-alist + (cl-loop for (win . state) in helm--original-dedicated-windows-alist + when (window-live-p win) + do (set-window-dedicated-p win state)) + (setq helm--original-dedicated-windows-alist nil)) + ;; Restore frame focus. + ;; This is needed for minibuffer own-frame config + ;; when recursive minibuffers are in use. + ;; e.g M-: + helm-minibuffer-history. + (cl-letf ((frame (if (minibufferp helm-current-buffer) + (selected-frame) + (last-nonminibuffer-frame))) + ;; This is a workaround, because the i3 window + ;; manager developers are refusing to fix their + ;; broken timestamp and event handling. + ;; + ;; We basically just disable the part of + ;; select-frame-set-input-focus that would call + ;; XSetInputFocus in Xlib (x-focus-frame), that + ;; resets a timestamp in the xserver which the i3 + ;; developers fail to notice. + ;; + ;; Since they don't know about the new timestamp, + ;; their keyboard handling can break after a helm + ;; user quits emacs, as reported in bug#1641. + ;; + ;; Fortunately for us, we really don't need this + ;; XSetInputFocus call, since we already have focus + ;; for Emacs, the user is just using helm! We call + ;; select-frame-set-input-focus for the other + ;; side-effects, not for x-focus-frame. + ((symbol-function 'x-focus-frame) #'ignore)) + (select-frame-set-input-focus frame)))))) + +(defun helm-split-window-default-fn (window) + "Default function to split windows before displaying `helm-buffer'. + +It is used as default value for +`helm-split-window-preferred-function' which is then the +let-bounded value of `split-window-preferred-function' in +`helm-display-buffer'. When `helm-display-function' which default +to `helm-default-display-buffer' is called from +`helm-display-buffer' the value of +`split-window-preferred-function' will be used by +`display-buffer'." + (let* ((split-width-threshold (and (integerp helm-split-width-threshold) + helm-split-width-threshold)) + (win (if (and (fboundp 'window-in-direction) + ;; Don't try to split when starting in a minibuffer + ;; e.g M-: and try to use helm-show-kill-ring. + (not (minibufferp helm-current-buffer)) + (null helm-split-width-threshold)) + (if (or (one-window-p t) + helm-split-window-inside-p) + (split-window + (selected-window) nil + (if (eq helm-split-window-default-side 'other) + helm-split-window-other-side-when-one-window + helm-split-window-default-side)) + ;; If more than one window reuse one of them. + (cl-case helm-split-window-default-side + (left (or (helm-window-in-direction 'left) + (helm-window-in-direction 'above) + (selected-window))) + (above (or (helm-window-in-direction 'above) + (helm-window-in-direction 'left) + (selected-window))) + (right (or (helm-window-in-direction 'right) + (helm-window-in-direction 'below) + (selected-window))) + (below (or (helm-window-in-direction 'below) + (helm-window-in-direction 'right) + (selected-window))) + (same (selected-window)) + (other (or (helm-other-window-for-scrolling) + (selected-window))) + (t (or (window-next-sibling) (selected-window))))) + (split-window-sensibly window)))) + (setq helm-persistent-action-window-buffer (window-buffer win)) + win)) + +(defun helm-window-in-direction (direction) + "Same as `window-in-direction' but check if window is dedicated. +Return nil when window is dedicated." + (helm-aif (window-in-direction direction) + (and (not (window-dedicated-p it)) it))) + +(defun helm-other-window-for-scrolling () + "Same as `other-window-for-scrolling' but check if window is dedicated. +Returns nil when window is dedicated." + (helm-aif (other-window-for-scrolling) + (and (not (window-dedicated-p it)) it))) + +(defun helm-resolve-display-function (com) + "Decide which display function to use according to `helm-commands-using-frame'. + +The `helm-display-function' buffer local value takes precedence +on `helm-commands-using-frame'. +If `helm-initial-frame' has no minibuffer, use +`helm-display-buffer-in-own-frame' function. +Fallback to global value of `helm-display-function' when no local +value found and current command is not in +`helm-commands-using-frame'." + (let ((win (get-buffer-window helm-current-buffer))) + (or (with-helm-buffer helm-display-function) + (and (or (memq com helm-commands-using-frame) + (and helm-use-frame-when-no-suitable-window + (or (window-dedicated-p win) + (window-parameter win 'window-side))) + (and helm-use-frame-when-more-than-two-windows + (null helm--nested) + (> (length (window-list)) 2)) + ;; Frame parameter is unreliable for minibuffer on emacs-26. + (null (member helm-initial-frame (minibuffer-frame-list)))) + #'helm-display-buffer-in-own-frame) + (default-value 'helm-display-function)))) + +(defun helm-display-buffer (buffer &optional resume) + "Display BUFFER. + +The function used to display `helm-buffer' by calling +`helm-display-function' which splits window with +`helm-split-window-preferred-function'." + (let ((split-window-preferred-function + helm-split-window-preferred-function) + (helm-split-window-default-side + (if (and (not helm-full-frame) + helm-reuse-last-window-split-state) + (cond ((eq helm-split-window-default-side 'same) 'same) + ((eq helm-split-window-default-side 'other) 'other) + (helm--window-side-state) + (t helm-split-window-default-side)) + helm-split-window-default-side)) + (disp-fn (with-current-buffer buffer + (helm-resolve-display-function + (if helm-actions-inherit-frame-settings + (helm-this-command) this-command))))) + (prog1 + (funcall disp-fn buffer (or (helm-resume-p resume) + (and helm-actions-inherit-frame-settings + helm--executing-helm-action))) + (with-helm-buffer (setq-local helm-display-function disp-fn)) + (setq helm-onewindow-p (one-window-p t)) + ;; Don't allow other-window and friends switching out of minibuffer. + (when helm-prevent-escaping-from-minibuffer + (helm-prevent-switching-other-window))))) + +(cl-defun helm-prevent-switching-other-window (&key (enabled t)) + "Allow setting `no-other-window' parameter for all windows. +Arg ENABLE is the value of `no-other-window' window property." + (walk-windows + (lambda (w) + (unless (window-dedicated-p w) + (set-window-parameter w 'no-other-window enabled))) + 0)) + +(defun helm-default-display-buffer (buffer &optional _resume) + "Default function to display `helm-buffer' BUFFER. + +It is the default value of `helm-display-function'. +It uses `switch-to-buffer' or `display-buffer' depending on the +value of `helm-full-frame' or `helm-split-window-default-side'." + (let (pop-up-frames + (curwin (get-buffer-window helm-current-buffer))) + (if (or (buffer-local-value 'helm-full-frame (get-buffer buffer)) + (and (eq helm-split-window-default-side 'same) + (one-window-p t))) + (progn (and (not (minibufferp helm-current-buffer)) + ;; side-windows can't be the only window in frame, + ;; emacs refuse to delete other windows when + ;; current is a side-window [1]. + (not (window-parameter curwin 'window-side)) + (delete-other-windows)) + (switch-to-buffer buffer)) + (when (and (or helm-always-two-windows helm-autoresize-mode) + (not (eq helm-split-window-default-side 'same)) + (not (minibufferp helm-current-buffer)) + (not helm-split-window-inside-p) + ;; Same comment as in [1]. + (not (window-parameter curwin 'window-side))) + (delete-other-windows)) + (display-buffer + buffer `(,helm-default-display-buffer-functions + . ,(append helm-default-display-buffer-alist + `((window-height . ,helm-display-buffer-default-height) + (window-width . ,helm-display-buffer-default-width))))) + (helm-log-run-hook "helm-default-display-buffer" 'helm-window-configuration-hook)))) + +;; Shut up byte-compiler in emacs-26 +(defvar tab-bar-mode) +;; No warnings in Emacs built --without-x +(defvar x-display-name) + +(defun helm-display-buffer-in-own-frame (buffer &optional resume) + "Display Helm buffer BUFFER in a separate frame. + +Function suitable for `helm-display-function', +`helm-completion-in-region-display-function' and/or +`helm-show-completion-default-display-function'. + +See `helm-display-buffer-height' and `helm-display-buffer-width' +to configure frame size. + +Note that this feature is available only with emacs-25+. +Note also it is not working properly in helm nested session with emacs +version < emacs-28." + (cl-assert (and (fboundp 'window-absolute-pixel-edges) + (fboundp 'frame-geometry)) + nil "Helm buffer in own frame is only available starting at emacs-25+") + (if (not (display-graphic-p)) + ;; Fallback to default when frames are not usable. + (helm-default-display-buffer buffer) + (setq helm--buffer-in-new-frame-p t) + (let* ((pos (window-absolute-pixel-position)) + (half-screen-size (/ (display-pixel-height x-display-name) 2)) + (frame-info (frame-geometry)) + (prmt-size (length helm--prompt)) + (line-height (frame-char-height)) + tab-bar-mode + (new-frame-alist + (if resume + (buffer-local-value 'helm--last-frame-parameters + (get-buffer buffer)) + `((width . ,helm-display-buffer-width) + (height . ,helm-display-buffer-height) + (tool-bar-lines . 0) + (left . ,(- (car pos) + (* (frame-char-width) + (if (< (- (point) (point-at-bol)) prmt-size) + (- (point) (point-at-bol)) + prmt-size)))) + ;; Try to put frame at the best possible place. + ;; Frame should be below point if enough + ;; place, otherwise above point and + ;; current line should not be hidden + ;; by helm frame. + (top . ,(if (> (cdr pos) half-screen-size) + ;; Above point + (- (cdr pos) + ;; add 2 lines to make sure there is always a gap + (* (+ helm-display-buffer-height 2) line-height) + ;; account for title bar height too + (cddr (assq 'title-bar-size frame-info))) + ;; Below point + (+ (cdr pos) line-height))) + (title . "Helm") + (undecorated . ,helm-use-undecorated-frame-option) + (background-color . ,(or helm-frame-background-color + (face-attribute 'default :background))) + (foreground-color . ,(or helm-frame-foreground-color + (face-attribute 'default :foreground))) + (alpha . ,(or helm-frame-alpha 100)) + (font . ,(assoc-default 'font (frame-parameters))) + (vertical-scroll-bars . nil) + (menu-bar-lines . 0) + (fullscreen . nil) + (visibility . ,(null helm-display-buffer-reuse-frame)) + (minibuffer . t)))) + display-buffer-alist) + ;; Display minibuffer above or below only in initial session, + ;; not on a session triggered by action, this way if user have + ;; toggled minibuffer and header-line manually she keeps this + ;; setting in next action. + (unless (or helm--executing-helm-action resume) + ;; Add the hook inconditionally, if + ;; helm-echo-input-in-header-line is nil helm-hide-minibuffer-maybe + ;; will have anyway no effect so no need to remove the hook. + (add-hook 'helm-minibuffer-set-up-hook 'helm-hide-minibuffer-maybe) + (with-helm-buffer + (setq-local helm-echo-input-in-header-line + (not (> (cdr pos) half-screen-size))))) + (helm-display-buffer-popup-frame buffer new-frame-alist) + ;; When frame size have been modified manually by user restore + ;; it to default value unless resuming or not using + ;; `helm-display-buffer-reuse-frame'. + ;; This have to be done AFTER raising the frame otherwise + ;; minibuffer visibility is lost until next session. + (unless (or resume (not helm-display-buffer-reuse-frame)) + (set-frame-size helm-popup-frame + helm-display-buffer-width + helm-display-buffer-height))) + (helm-log-run-hook "helm-display-buffer-in-own-frame" 'helm-window-configuration-hook))) + +(defun helm-display-buffer-popup-frame (buffer frame-alist) + (if helm-display-buffer-reuse-frame + (let* ((x (cdr (assoc 'left frame-alist))) + (y (cdr (assoc 'top frame-alist))) + (width (cdr (assoc 'width frame-alist))) + (height (cdr (assoc 'height frame-alist)))) + (unless (and helm-popup-frame + (frame-live-p helm-popup-frame)) + (setq helm-popup-frame (make-frame frame-alist))) + (select-frame helm-popup-frame) + (set-frame-position helm-popup-frame x y) + (set-frame-width helm-popup-frame width) + (set-frame-height helm-popup-frame height) + (switch-to-buffer buffer) + (select-frame-set-input-focus helm-popup-frame t)) + ;; If user have changed `helm-display-buffer-reuse-frame' to nil + ;; maybe kill the frame. + (when (and helm-popup-frame + (frame-live-p helm-popup-frame)) + (delete-frame helm-popup-frame)) + (display-buffer + buffer `(display-buffer-pop-up-frame + . ((pop-up-frame-parameters . ,frame-alist)))))) + +;; Ensure to quit helm when user delete helm frame manually. +;; If user deletes another frame keep session running. +(defun helm--delete-frame-function (frame) + (when (and helm-alive-p + ;; FRAME is handling helm-buffer + (get-buffer-window helm-buffer frame)) + (helm-keyboard-quit))) +(add-hook 'delete-frame-functions 'helm--delete-frame-function) + +;;; Initialize +;; +(defun helm-get-sources (sources) + "Transform each element of SOURCES in alist. +Return the resulting list." + (when sources + (mapcar (lambda (source) + (if (listp source) + source (symbol-value source))) + (helm-normalize-sources sources)))) + +(defun helm-initialize (resume input default sources) + "Start initialization of Helm session. +For RESUME INPUT DEFAULT and SOURCES see `helm'." + (helm-log "helm-initialize" "start initialization: resume=%S input=%S" + resume input) + (helm-frame-or-window-configuration 'save) + (let ((sources-list (helm-get-sources sources))) + (setq helm--in-fuzzy + (cl-loop for s in sources-list + for matchfns = (helm-match-functions s) + for searchfns = (helm-search-functions s) + when (or (memq 'helm-fuzzy-match matchfns) + (memq 'helm-fuzzy-search searchfns)) + return t)) + (helm-log "helm-initialize" "sources-list = %S" sources-list) + (helm-set-local-variable 'helm-sources sources-list) + ;; Once `helm-buffer' is created `helm-sources' will be a local + ;; variable which value is a list of alists. + (helm-current-position 'save) + (if (helm-resume-p resume) + (helm-initialize-overlays (helm-buffer-get)) + (helm-initial-setup input default sources-list)) + (setq helm-alive-p t) + (unless (eq resume 'noresume) + (helm--push-and-remove-dups helm-buffer 'helm-buffers) + (setq helm-last-buffer helm-buffer)) + ;; If a `resume' attribute is present `helm-compute-attr-in-sources' + ;; will run its function. + (when (helm-resume-p resume) + (helm-compute-attr-in-sources 'resume)) + (helm-log "helm-initialize" "end initialization"))) + +(defun helm-current-position (save-or-restore) + "Save or restore current position in `helm-current-buffer'. +Argument SAVE-OR-RESTORE is either save or restore." + (cl-case save-or-restore + (save + (helm-log "helm-current-position" "Save position at %S" (cons (point) (window-start))) + (setq helm-current-position (cons (point) (window-start)))) + (restore + ;; Maybe `helm-current-buffer' have been deleted + ;; during helm session so check if it is here + ;; otherwise position in underlying buffer will be lost. + (when (get-buffer-window helm-current-buffer 'visible) + (helm-log "helm-current-position" "Restore position at %S in buffer %s" + helm-current-position + (buffer-name (current-buffer))) + (goto-char (car helm-current-position)) + ;; Fix this position with the NOFORCE arg of `set-window-start' + ;; otherwise, if there is some other buffer than `helm-current-buffer' + ;; one, position will be lost. + (set-window-start (selected-window) (cdr helm-current-position) t))))) + +(defun helm-initialize-overlays (buffer) + "Initialize Helm overlays in BUFFER." + (helm-log "helm-initialize-overlays" "overlay setup") + (if helm-selection-overlay + ;; make sure the overlay belongs to the helm buffer if + ;; it's newly created + (move-overlay helm-selection-overlay (point-min) (point-min) + (get-buffer buffer)) + + (setq helm-selection-overlay + (make-overlay (point-min) (point-min) (get-buffer buffer))) + (overlay-put helm-selection-overlay 'face 'helm-selection) + (overlay-put helm-selection-overlay 'priority 1))) + +(defun helm-initial-setup (input default sources) + "Initialize Helm settings and set up the Helm buffer." + ;; Run global hook. + (helm-log-run-hook "helm-initial-setup" 'helm-before-initialize-hook) + ;; Run local source hook. + (helm--run-init-hooks 'before-init-hook sources) + ;; For initialization of helm locals vars that need + ;; a value from current buffer, it is here. + (helm-set-local-variable 'current-input-method current-input-method) + (setq helm-current-prefix-arg nil + helm-saved-action nil + helm-saved-selection nil + helm-suspend-update-flag nil + ;; Ensure this is called BEFORE selecting helm-window. + helm-current-buffer (helm--current-buffer) + helm-buffer-file-name buffer-file-name + helm-issued-errors nil + helm-saved-current-source nil + helm--suspend-update-interactive-flag nil) + (when (and (with-helm-current-buffer + (and (buffer-narrowed-p) + (use-region-p))) + (not helm--nested)) + (helm-set-local-variable 'helm--current-buffer-narrowed + (list (current-buffer) + (region-beginning) (region-end)))) + (unless (and (or helm-split-window-state + helm--window-side-state) + helm-reuse-last-window-split-state) + (setq helm-split-window-state + (if (or (null split-width-threshold) + (and (integerp split-width-threshold) + (>= split-width-threshold (+ (frame-width) 4)))) + 'vertical 'horizontal)) + (setq helm--window-side-state + (or helm-split-window-default-side 'below))) + ;; Some sources like helm-mu are using input to init their + ;; candidates in init function, so setup initial helm-pattern here. + ;; See bug#2530 and https://github.com/emacs-helm/helm-mu/issues/54. + ;; Input should have precedence on default. + (cond (input + (setq helm-input input + helm-pattern input)) + ((and default helm-maybe-use-default-as-input) + (setq helm-pattern (if (listp default) + (car default) + default) + ;; Even if helm-pattern is set we want the + ;; prompt to be empty when using default as input, why + ;; helm-input is initialized to "". + helm-input "")) + (helm-maybe-use-default-as-input + (setq helm-pattern (or (with-helm-current-buffer + (thing-at-point 'symbol)) + "") + helm-input "")) + (t + (setq helm-pattern "" + helm-input ""))) + (helm--fuzzy-match-maybe-set-pattern) + ;; Call the init function for sources where appropriate + (helm-compute-attr-in-sources 'init sources) + (clrhash helm-candidate-cache) + (helm-create-helm-buffer) + (helm-clear-visible-mark) + ;; Run global hook. + (helm-log-run-hook "helm-initial-setup" 'helm-after-initialize-hook) + ;; Run local source hook. + (helm--run-init-hooks 'after-init-hook sources)) + +(defun helm--run-init-hooks (hook sources) + "Run after and before init hooks local to source. +See :after-init-hook and :before-init-hook in `helm-source'." + (cl-loop for s in sources + for hv = (assoc-default hook s) + when hv + do (pcase hv + ((and (pred (functionp)) + (guard (not (symbolp hv)))) + (funcall hv)) + ((and hook (pred (listp))) + (dolist (h hook) (funcall h))) + (_ (helm-log-run-hook "helm--run-init-hooks" hv))))) + +(defun helm-restore-position-on-quit () + "Restore position in `helm-current-buffer' when quitting." + (helm-current-position 'restore)) + +(defun helm--push-and-remove-dups (elm sym) + "Move ELM of SYM value on top and set SYM to this new value." + (set sym (cons elm (delete elm (symbol-value sym))))) + +(defun helm--current-buffer () + "[INTERNAL] Return `current-buffer' BEFORE `helm-buffer' is initialized. +Note that it returns the minibuffer in use after Helm has started +and is intended for `helm-initial-setup'. To get the buffer where +Helm was started, use `helm-current-buffer' instead." + (if (minibuffer-window-active-p (minibuffer-window)) + ;; If minibuffer is active be sure to use it's buffer + ;; as `helm-current-buffer', this allow to use helm + ;; from an already active minibuffer (M-: etc...) + (window-buffer (active-minibuffer-window)) + ;; Fix Bug#456 + ;; Use this instead of `current-buffer' to ensure + ;; helm session started in helm-mode from a completing-read + ;; Use really the buffer where we started and not the one + ;; where the completing-read is wrapped. i.e + ;; (with-current-buffer SOME-OTHER-BUFFER (completing-read [...]) + (window-buffer (with-selected-window (minibuffer-window) + (minibuffer-selected-window))))) + +(define-derived-mode helm-major-mode + fundamental-mode "Hmm" + "[INTERNAL] Provide major-mode name in Helm buffers. +Unuseful when used outside Helm, don't use it.") +(put 'helm-major-mode 'mode-class 'special) +(put 'helm-major-mode 'helm-only t) + +(defun helm-create-helm-buffer () + "Create and setup `helm-buffer'." + (let ((root-dir default-directory) + (inhibit-read-only t)) + (with-current-buffer (get-buffer-create helm-buffer) + (helm-log "helm-create-helm-buffer" "Enabling major-mode %S" major-mode) + (helm-log "helm-create-helm-buffer" "kill local variables: %S" (buffer-local-variables)) + (kill-all-local-variables) + (helm-major-mode) + (set (make-local-variable 'buffer-read-only) nil) + (buffer-disable-undo) + (erase-buffer) + ;; Use this instead of setting helm-map local ensure we have all + ;; our keys when helm loose minibuffer focus. And the map is + ;; made local as well AFAIU. + (use-local-map helm-map) + (set (make-local-variable 'helm-source-filter) nil) + (make-local-variable 'helm-sources) + (set (make-local-variable 'helm-display-function) nil) + (set (make-local-variable 'helm-selection-point) nil) + (set (make-local-variable 'scroll-margin) + (if helm-display-source-at-screen-top + 0 helm-completion-window-scroll-margin)) + (set (make-local-variable 'default-directory) root-dir) + (set (make-local-variable 'helm-marked-candidates) nil) + (set (make-local-variable 'helm--prompt) helm--prompt) + (helm-initialize-persistent-action) + (helm-log "helm-create-helm-buffer" "helm-display-function = %S" helm-display-function) + (helm-log "helm-create-helm-buffer" "helm--local-variables = %S" helm--local-variables) + (helm--set-local-variables-internal) + (setq truncate-lines helm-truncate-lines) ; already local. + (setq left-margin-width helm-left-margin-width) + (setq cursor-type nil)) + (helm-initialize-overlays helm-buffer) + (get-buffer helm-buffer))) + +(define-minor-mode helm--minor-mode + "[INTERNAL] Enable keymap in Helm minibuffer. +Since this mode has no effect when run outside of Helm context, +please don't use it outside of Helm. + +\\{helm-map}" + :group 'helm + :keymap (and helm-alive-p helm-map) + (unless helm-alive-p (setq helm--minor-mode nil))) +(put 'helm--minor-mode 'helm-only t) + +(defun helm--reset-default-pattern () + (setq helm-pattern "") + (setq helm-maybe-use-default-as-input nil)) + +(defun helm-read-from-minibuffer (prompt + input preselect resume + keymap default history) + "Read pattern with prompt PROMPT and initial input INPUT. +For PRESELECT RESUME KEYMAP DEFAULT HISTORY, see `helm'." + (with-helm-buffer + (if (and (helm-resume-p resume) + ;; When no source, helm-buffer is empty + ;; or contain non--candidate lines (e.g grep exit status) + (helm-get-current-source)) + (helm-mark-current-line t) + (helm-update preselect)) + (let* ((src (helm-get-current-source)) + (src-keymap (assoc-default 'keymap src)) + (hist (or (and history (symbolp history) history) + ;; Needed for resuming. + (assoc-default 'history src))) + (timer nil) + blink-matching-paren + (resize-mini-windows (and (null helm-echo-input-in-header-line) + resize-mini-windows)) + (first-src (car helm-sources)) + (source-process-p (or (assq 'candidates-process src) + (assq 'candidates-process first-src))) + ;; As we are using `helm-keyboard-quit' for `C-g' we have + ;; to prevent emacs command loop redefining `C-g' during + ;; helm-session. This happen only on async source with + ;; large output after a certain delay. The effect is that + ;; the minibuffer is exited but the helm async process + ;; continue running, and because minibuffer is lost `C-g' + ;; have no more effect. By binding `inhibit-quit' here we + ;; prevent this and allow `C-g' (the helm one aka + ;; `helm-keyboard-quit') to quit immediately. + (inhibit-quit source-process-p)) + (helm-log "helm-read-from-minibuffer" "helm-get-candidate-number => %S" + (helm-get-candidate-number)) + (helm-log "helm-read-from-minibuffer" "helm-execute-action-at-once-if-one = %S" + helm-execute-action-at-once-if-one) + (helm-log "helm-read-from-minibuffer" + "helm-quit-if-no-candidate = %S" helm-quit-if-no-candidate) + (when (and src (helm-resume-p resume)) + (helm-display-mode-line src) + (setq helm-pattern input)) + ;; Reset `helm-pattern' and update + ;; display if no result found with precedent value of `helm-pattern' + ;; unless `helm-quit-if-no-candidate' is non-`nil', in this case + ;; Don't force update with an empty pattern. + ;; Reset also `helm-maybe-use-default-as-input' as this checking + ;; happen only on startup. + (when helm-maybe-use-default-as-input + ;; Store value of `default' temporarily here waiting next update + ;; to allow actions like helm-moccur-action matching pattern + ;; at the place it jump to. + (setq helm-input helm-pattern) + (if source-process-p + ;; Reset pattern to next update. + (with-helm-after-update-hook + (helm--reset-default-pattern)) + ;; Reset pattern right now. + (helm--reset-default-pattern)) + ;; Ensure force-update when no candidates + ;; when we start with an empty pattern. + (and (helm-empty-buffer-p) + (null helm-quit-if-no-candidate) + (helm-force-update preselect))) + ;; Handle `helm-execute-action-at-once-if-one' and + ;; `helm-quit-if-no-candidate' now. + (cond ((and (if (functionp helm-execute-action-at-once-if-one) + (funcall helm-execute-action-at-once-if-one) + helm-execute-action-at-once-if-one) + (= (helm-get-candidate-number + (eq helm-execute-action-at-once-if-one 'current-source)) + 1)) + (ignore)) ; Don't enter the minibuffer loop. + ((and helm-quit-if-no-candidate + (= (helm-get-candidate-number) 0)) + (setq helm--quit t) + (and (functionp helm-quit-if-no-candidate) + (funcall helm-quit-if-no-candidate))) + (t ; Enter now minibuffer and wait for input. + (let ((tap (or default + (with-helm-current-buffer + (thing-at-point 'symbol))))) + (when helm-execute-action-at-once-if-one + (helm-display-buffer helm-buffer resume) + (select-window (helm-window))) + (unwind-protect + (minibuffer-with-setup-hook + (lambda () + ;; Start minor-mode with global value of helm-map. + (helm--minor-mode 1) + ;; Now override the global value of `helm-map' with + ;; the local one which is in this order: + ;; - The keymap of current source. + ;; - The value passed in KEYMAP + ;; - Or fallback to the global value of helm-map. + (helm--maybe-update-keymap + (or src-keymap keymap helm-map)) + (helm-log-run-hook "helm-read-from-minibuffer" + 'helm-minibuffer-set-up-hook) + (setq timer + (run-with-idle-timer + (max (with-helm-buffer helm-input-idle-delay) + 0.001) + 'repeat + (lambda () + ;; Stop updating in persistent action + ;; or when `helm-suspend-update-flag' + ;; is non-`nil'. + (unless (or helm-in-persistent-action + helm-suspend-update-flag) + (save-selected-window + (helm-check-minibuffer-input) + (helm-print-error-messages)))))) + ;; minibuffer has already been filled here. + (helm--update-header-line)) + (read-from-minibuffer (propertize (or prompt "pattern: ") + 'face 'helm-minibuffer-prompt) + input helm-map + nil hist tap + helm-inherit-input-method)) + (when timer (cancel-timer timer) (setq timer nil))))))))) + +(defun helm-toggle-suspend-update () + "Enable or disable display update in helm. +This can be useful for example for quietly writing a complex +regexp without Helm constantly updating." + (interactive) + (helm-suspend-update (not helm-suspend-update-flag) t) + (setq helm--suspend-update-interactive-flag + (not helm--suspend-update-interactive-flag))) +(put 'helm-toggle-suspend-update 'helm-only t) + +(defun helm-suspend-update (arg &optional verbose) + "Enable or disable display update in helm. +If ARG is 1 or non nil suspend update, if it is -1 or nil reenable +updating. When VERBOSE is specified display a message." + (with-helm-buffer + (when (setq helm-suspend-update-flag + (helm-acase arg + (1 t) + (-1 nil) + (t it))) + (helm-kill-async-processes) + (setq helm-pattern "")) + (when verbose + (message (if helm-suspend-update-flag + "Helm update suspended!" + "Helm update re-enabled!"))) + (helm-aif (helm-get-current-source) + (helm-display-mode-line it t)))) + +(defun helm-delete-backward-no-update (arg) + "Disable update and delete ARG chars backward. +Update is reenabled when idle 1s." + (interactive "p") + (with-helm-alive-p + (unless helm--suspend-update-interactive-flag + (helm-suspend-update 1)) + (backward-delete-char arg) + (run-with-idle-timer + 1 nil + (lambda () + (unless helm--suspend-update-interactive-flag + (helm-suspend-update -1) + (helm-check-minibuffer-input) + (helm-force-update)))))) +(put 'helm-delete-backward-no-update 'helm-only t) + +(defun helm--suspend-read-passwd (old--fn &rest args) + "Suspend Helm while reading password. +This is used to advice `tramp-read-passwd', `ange-ftp-get-passwd' +and `epa-passphrase-callback-function'." + ;; Suspend update when prompting for a tramp password. + (setq helm-suspend-update-flag t) + (setq overriding-terminal-local-map nil) + (setq helm--reading-passwd-or-string t) + (unwind-protect + ;; No need to suspend timer in emacs-24.4 + ;; it is fixed upstream. + (apply old--fn args) + (setq helm--reading-passwd-or-string nil) + (setq helm-suspend-update-flag nil))) + +(defun helm--maybe-update-keymap (&optional map) + "Handle different keymaps in multiples sources. + +Overrides `helm-map' with the local map of current source. If no +map is found in current source, does nothing (keeps previous +map)." + (with-helm-buffer + (helm-aif (or map (assoc-default 'keymap (helm-get-current-source))) + ;; We used a timer in the past to leave + ;; enough time to helm to setup its keymap + ;; when changing source from a recursive minibuffer. + ;; e.g C-x C-f M-y C-g + ;; => *find-files have now the bindings of *kill-ring. + ;; It is no more true now we are using `minor-mode-overriding-map-alist' + ;; and `helm--minor-mode' thus it fix Bug#1076 for emacs-24.3 + ;; where concurrent timers are not supported. + ;; i.e update keymap+check input. + (with-current-buffer (window-buffer (minibuffer-window)) + (setq minor-mode-overriding-map-alist `((helm--minor-mode . ,it))))))) + +;;; Prevent loosing focus when using mouse. +;; +(defvar helm--remap-mouse-mode-map + (let ((map (make-sparse-keymap))) + (cl-loop for k in '([mouse-1] [mouse-2] [mouse-3] + [down-mouse-1] [down-mouse-2] [down-mouse-3] + [drag-mouse-1] [drag-mouse-2] [drag-mouse-3] + [double-mouse-1] [double-mouse-2] [double-mouse-3] + [triple-mouse-1] [triple-mouse-2] [triple-mouse-3]) + do (define-key map k 'ignore)) + map)) + +(define-minor-mode helm--remap-mouse-mode + "[INTERNAL] Prevent escaping helm minibuffer with mouse clicks. +Do nothing when used outside of helm context. + +WARNING: Do not use this mode yourself, it is internal to Helm." + :group 'helm + :global t + :keymap helm--remap-mouse-mode-map + (unless helm-alive-p + (setq helm--remap-mouse-mode-map nil))) +(put 'helm--remap-mouse-mode 'helm-only t) + +;; Clean up + +(defun helm-cleanup () + "Clean up the mess when Helm exit or quit." + (helm-log "helm-cleanup" "start cleanup") + (with-selected-window + ;; When exiting with `helm-execute-action-at-once-if-one', + ;; `helm-window' may not be created and we endup with an error + ;; e.g. in eshell completion when only one candidate to complete + ;; so fallback to selected-window in such cases. + (or (get-buffer-window helm-buffer) + (selected-window)) + (let ((frame (selected-frame))) + (setq cursor-type (default-value 'cursor-type)) + ;; Ensure restoring default-value of mode-line to allow user + ;; using the mouse when helm is inactive (Bug#1517,Bug#2377). + (setq mode-line-format (default-value 'mode-line-format)) + (remove-hook 'post-command-hook 'helm--maybe-update-keymap) + (remove-hook 'post-command-hook 'helm--update-header-line) + ;; Be sure we call cleanup functions from helm-buffer. + (helm-compute-attr-in-sources 'cleanup) + ;; Delete or make invisible helm frame. + (if (and helm--buffer-in-new-frame-p + ;; a helm session running in a frame that runs a nested + ;; session share the same frame for both sessions so + ;; don't delete the common frame. + ;; i.e. helm--nested == t => delete + ;; helm--nested == nil => delete + ;; helm--nested == share => don't delete + (not (eq helm--nested 'share))) + (progn + (setq-local helm--last-frame-parameters + (helm--get-frame-parameters)) + (bury-buffer) + (if helm-display-buffer-reuse-frame + (make-frame-invisible frame) (delete-frame frame))) + ;; bury-buffer from this window [1]. + ;; Do it at end to make sure buffer is still current. + (bury-buffer)))) + (helm-kill-async-processes) + ;; Remove the temporary hooks added + ;; by `with-helm-temp-hook' that + ;; may not have been consumed. + (when helm--temp-hooks + (cl-loop for (fn . hook) in helm--temp-hooks + do (remove-hook hook fn)) + (setq helm--temp-hooks nil)) + ;; When running helm from a dedicated frame + ;; with no minibuffer, helm will run in the main frame + ;; which have a minibuffer, so be sure to disable + ;; the `no-other-window' prop there. + (helm-prevent-switching-other-window :enabled nil) + (helm-log-run-hook "helm-cleanup" 'helm-cleanup-hook) + (helm-frame-or-window-configuration 'restore) + ;; [1] now bury-buffer from underlying windows otherwise, + ;; if this window is killed the underlying buffer will + ;; be a helm buffer. + (replace-buffer-in-windows helm-buffer) + (setq helm-alive-p nil) + ;; Prevent error "No buffer named *helm*" triggered by + ;; `helm-set-local-variable'. + (setq helm--force-updating-p nil) + (setq helm--buffer-in-new-frame-p nil) + ;; No need to reinitialize helm-pattern here now it is done only + ;; once in init function bug#2530. + (setq helm-last-query helm-pattern) + ;; This is needed in some cases where last input + ;; is yielded infinitely in minibuffer after helm session. + (helm-clean-up-minibuffer)) + +(defun helm-clean-up-minibuffer () + "Remove contents of minibuffer." + (let ((miniwin (minibuffer-window))) + ;; Clean only current minibuffer used by helm. + ;; i.e The precedent one is active. + (unless (minibuffer-window-active-p miniwin) + (with-current-buffer (window-buffer miniwin) + (delete-minibuffer-contents))))) + + +;;; Input handling +;; +;; +(defun helm-check-minibuffer-input () + "Check minibuffer content." + (with-selected-window (or (active-minibuffer-window) + (minibuffer-window)) + (helm-check-new-input (minibuffer-contents)))) + +(defun helm-check-new-input (input) + "Check INPUT string and update the helm buffer if necessary." + (unless (equal input helm-pattern) + (setq helm-pattern input) + (unless (helm-action-window) + (setq helm-input helm-pattern)) + (helm-log "helm-check-new-input" "helm-pattern = %S" helm-pattern) + (helm-log "helm-check-new-input" "helm-input = %S" helm-input) + (helm-log-run-hook "helm-check-new-input" 'helm-before-update-hook) + (setq helm--in-update t) + (helm-update))) + +(defun helm--reset-update-flag () + (run-with-idle-timer + helm-exit-idle-delay nil + (lambda () (setq helm--in-update nil)))) + +;; (add-hook 'helm-after-update-hook #'helm--reset-update-flag) + + +;; All candidates + +(defun helm-get-candidates (source) + "Retrieve and return the list of candidates from SOURCE." + (let* ((candidate-fn (assoc-default 'candidates source)) + (candidate-proc (assoc-default 'candidates-process source)) + ;; See comment in helm-get-cached-candidates (Bug#2113). + (inhibit-quit candidate-proc) + cfn-error + (notify-error + (lambda (&optional e) + (error + "In `%s' source: `%s' %s %s" + (assoc-default 'name source) + (or candidate-fn candidate-proc) + (if e "\n" "must be a list, a symbol bound to a list, or a function returning a list") + (if e (prin1-to-string e) "")))) + (candidates (condition-case-unless-debug err + ;; Process candidates-(process) function + ;; It may return a process or a list of candidates. + (if candidate-proc + ;; Calling `helm-interpret-value' with no + ;; SOURCE arg force the use of `funcall' + ;; and not `helm-apply-functions-from-source'. + (helm-interpret-value candidate-proc) + (helm-interpret-value candidate-fn source)) + (error (helm-log "helm-get-candidates" + "Error: %S" (setq cfn-error err)) + nil)))) + (cond ((and (processp candidates) (not candidate-proc)) + (warn "Candidates function `%s' should be called in a `candidates-process' attribute" + candidate-fn)) + ((and candidate-proc (not (processp candidates))) + (error "Candidates function `%s' should run a process" candidate-proc))) + (cond ((processp candidates) + ;; Candidates will be filtered later in process filter. + candidates) + ;; An error occured in candidates function. + (cfn-error (unless helm--ignore-errors + (funcall notify-error cfn-error))) + ;; Candidates function returns no candidates. + ((or (null candidates) + ;; Can happen when the output of a process + ;; is empty, and the candidates function call + ;; something like (split-string (buffer-string) "\n") + ;; which result in a list of one empty string (Bug#938). + ;; e.g (completing-read "test: " '("")) + (equal candidates '(""))) + nil) + ((listp candidates) + ;; Transform candidates with `candidate-transformer' functions or + ;; `real-to-display' functions if those are found, + ;; otherwise return candidates unmodified. + ;; `filtered-candidate-transformer' is NOT called here. + (helm-transform-candidates candidates source)) + (t (funcall notify-error))))) + +(defun helm-get-cached-candidates (source) + "Return the cached value of candidates for SOURCE. +Cache the candidates if there is no cached value yet." + (let* ((name (assoc-default 'name source)) + (candidate-cache (gethash name helm-candidate-cache)) + ;; Bind inhibit-quit to ensure function terminate in case of + ;; quit from `helm-while-no-input' and processes are added to + ;; helm-async-processes for further deletion (Bug#2113). + ;; FIXME: Is this still needed now `helm-while-no-input' + ;; handles quit-flag? + (inhibit-quit (assoc-default 'candidates-process source))) + (helm-aif candidate-cache + (prog1 it (helm-log "helm-get-cached-candidates" + "Use cached candidates")) + (helm-log "helm-get-cached-candidates" + "No cached candidates, calculate candidates") + (let ((candidates (helm-get-candidates source))) + (cond ((processp candidates) + (push (cons candidates + (append source + (list (cons 'item-count 0) + (cons 'incomplete-line "")))) + helm-async-processes) + (set-process-filter candidates 'helm-output-filter) + (setq candidates nil)) + ((not (assq 'volatile source)) + (puthash name candidates helm-candidate-cache))) + candidates)))) + + +;;; Candidate transformers + +(defun helm-process-candidate-transformer (candidates source) + "Execute `candidate-transformer' function(s) on CANDIDATES in SOURCE." + (helm-aif (assoc-default 'candidate-transformer source) + (helm-apply-functions-from-source source it candidates) + candidates)) + +(defun helm-process-filtered-candidate-transformer (candidates source) + "Execute `filtered-candidate-transformer' function(s) on CANDIDATES in SOURCE." + (helm-aif (assoc-default 'filtered-candidate-transformer source) + (helm-apply-functions-from-source source it candidates source) + candidates)) + +(defmacro helm--maybe-process-filter-one-by-one-candidate (candidate source) + "Execute `filter-one-by-one' function(s) on real value of CANDIDATE in SOURCE." + `(helm-aif (assoc-default 'filter-one-by-one ,source) + (let ((real (if (consp ,candidate) + (cdr ,candidate) + ,candidate))) + (if (and (listp it) + (not (functionp it))) ;; Don't treat lambda's as list. + (cl-loop for f in it + do (setq ,candidate (funcall f real)) + finally return ,candidate) + (setq ,candidate (funcall it real)))) + ,candidate)) + +(defun helm--initialize-one-by-one-candidates (candidates source) + "Process CANDIDATES with the `filter-one-by-one' function in SOURCE. +Return CANDIDATES unchanged when pattern is not empty." + (helm-aif (and (string= helm-pattern "") + (assoc-default 'filter-one-by-one source)) + (cl-loop for cand in candidates collect + (helm--maybe-process-filter-one-by-one-candidate cand source)) + candidates)) + +(defun helm-process-filtered-candidate-transformer-maybe + (candidates source process-p) + "Execute `filtered-candidate-transformer' function(s) on CANDIDATES in SOURCE. +When PROCESS-P is non-nil execute +`filtered-candidate-transformer' functions if some, otherwise +return CANDIDATES." + (if process-p + ;; When no filter return CANDIDATES unmodified. + (helm-process-filtered-candidate-transformer candidates source) + candidates)) + +(defun helm-process-real-to-display (candidates source) + "Execute real-to-display function on all CANDIDATES of SOURCE." + (helm-aif (assoc-default 'real-to-display source) + (setq candidates (helm-apply-functions-from-source + source 'mapcar + (lambda (cand) + (if (consp cand) + ;; override DISPLAY from candidate-transformer + (cons (funcall it (cdr cand)) (cdr cand)) + (cons (funcall it cand) cand))) + candidates)) + candidates)) + +(defun helm-transform-candidates (candidates source &optional process-p) + "Transform CANDIDATES from SOURCE according to candidate transformers. + +When PROCESS-P is non-nil executes the +`filtered-candidate-transformer' functions, otherwise processes +`candidate-transformer' functions only, +`filtered-candidate-transformer' functions being processed later, +after the candidates have been narrowed by +`helm-candidate-number-limit', see `helm-compute-matches'. When +`real-to-display' attribute is present, execute its functions on all +maybe filtered CANDIDATES." + (helm-process-real-to-display + (helm-process-filtered-candidate-transformer-maybe + (helm-process-candidate-transformer + candidates source) + source process-p) + source)) + + +;; Narrowing candidates +(defun helm-candidate-number-limit (source) + "Apply candidate-number-limit attribute value. +This overrides `helm-candidate-number-limit' variable. + +E.g.: +If (candidate-number-limit) is in SOURCE, show all candidates in SOURCE. +If (candidate-number-limit . 123) is in SOURCE limit candidate to 123." + (helm-aif (assq 'candidate-number-limit source) + ;; When assoc value is nil use by default 99999999 otherwise use + ;; the assoc value, when it is a symbol interpret its value (bug#1831). + (or (helm-aand (cdr it) (helm-interpret-value it)) 99999999) + (or helm-candidate-number-limit 99999999))) + +(defun helm-candidate-get-display (candidate) + "Get searched display part from CANDIDATE. +CANDIDATE is either a string, a symbol, or a (DISPLAY . REAL) +cons cell." + (cond ((car-safe candidate)) + ((symbolp candidate) + (symbol-name candidate)) + ((numberp candidate) + (number-to-string candidate)) + (t candidate))) + +(defun helm-process-pattern-transformer (pattern source) + "Execute pattern-transformer attribute function(s) on PATTERN in SOURCE." + (helm-aif (assoc-default 'pattern-transformer source) + (helm-apply-functions-from-source source it pattern) + pattern)) + +(defun helm-default-match-function (candidate) + "Check if `helm-pattern' match CANDIDATE. +Default function to match candidates according to `helm-pattern'." + (string-match helm-pattern candidate)) + + +;;; Fuzzy matching +;; +;; +(defvar helm--fuzzy-regexp-cache (make-hash-table :test 'eq)) +(defun helm--fuzzy-match-maybe-set-pattern () + ;; Computing helm-pattern with helm--mapconcat-pattern + ;; is costly, so cache it once time for all and reuse it + ;; until pattern change. + (when helm--in-fuzzy + (let ((fun (if (string-match "\\`\\^" helm-pattern) + #'identity + #'helm--mapconcat-pattern))) + (clrhash helm--fuzzy-regexp-cache) + ;; FIXME: Splitted part are not handled here, + ;; I must compute them in `helm-search-match-part' + ;; when negation and in-buffer are used. + (if (string-match "\\`!" helm-pattern) + (puthash 'helm-pattern + (if (> (length helm-pattern) 1) + (list (regexp-quote (substring helm-pattern 1 2)) + (funcall fun (substring helm-pattern 1))) + '("" "")) + helm--fuzzy-regexp-cache) + (puthash 'helm-pattern + (if (> (length helm-pattern) 0) + (list (regexp-quote (substring helm-pattern 0 1)) + (funcall fun helm-pattern)) + '("" "")) + helm--fuzzy-regexp-cache))))) + +(defun helm-fuzzy-match (candidate) + "Check if `helm-pattern' fuzzy matches CANDIDATE. +This function is used with sources built with `helm-source-sync'." + (unless (string-match " " helm-pattern) + ;; When pattern have one or more spaces, let + ;; multi-match doing the job with no fuzzy matching.[1] + (let ((regexp (cadr (gethash 'helm-pattern helm--fuzzy-regexp-cache)))) + (if (string-match "\\`!" helm-pattern) + (not (string-match regexp candidate)) + (string-match regexp candidate))))) + +(defun helm-fuzzy-search (pattern) + "Same as `helm-fuzzy-match' but for sources built with +`helm-source-in-buffer'." + (unless (string-match " " helm-pattern) + ;; Same as in `helm-fuzzy-match' ref[1]. + (let* ((regexps (gethash 'helm-pattern helm--fuzzy-regexp-cache)) + (partial-regexp (car regexps)) + (regexp (cadr regexps))) + (if (string-match "\\`!" pattern) + ;; Don't try to search here, just return + ;; the position of line and go ahead, + ;; letting `helm-search-match-part' checking if + ;; pattern match against this line. + (prog1 (list (point-at-bol) (point-at-eol)) + (forward-line 1)) + ;; We could use here directly `re-search-forward' + ;; on the regexp produced by `helm--mapconcat-pattern', + ;; but it is very slow because emacs have to do an incredible + ;; amount of loops to match e.g "[^f]*f[^o]*o..." in the whole buffer, + ;; more the regexp is long more the amount of loops grow. + ;; (Probably leading to a max-lisp-eval-depth error if both + ;; regexp and buffer are too big) + ;; So just search the first bit of pattern e.g "[^f]*f", and + ;; then search the corresponding line with the whole regexp, + ;; which increase dramatically the speed of the search. + (cl-loop while (re-search-forward partial-regexp nil t) + for bol = (point-at-bol) + for eol = (point-at-eol) + if (progn (goto-char bol) + (re-search-forward regexp eol t)) + do (goto-char eol) and return t + else do (goto-char eol) + finally return nil))))) + +(defvar helm-fuzzy-default-score-fn #'helm-fuzzy-flex-style-score) +(defun helm-score-candidate-for-pattern (candidate pattern) + "Assign score to CANDIDATE according to PATTERN." + ;; Unknown candidates always go on top. + (if (equal (get-text-property 0 'display candidate) "[?]") + 200.00 + (funcall helm-fuzzy-default-score-fn candidate pattern))) + +;; The flex scoring needs a regexp whereas the fuzzy scoring works +;; directly with helm-pattern, so cache the needed regexp for flex +;; scoring to not (re)compute it at each candidate. We could reuse +;; the regexp cached in `helm--fuzzy-regexp-cache' but it is not +;; exactly the same as the one needed for flex and also it is always +;; computed against the whole helm-pattern which is not usable for +;; e.g. file completion. +(defvar helm--fuzzy-flex-regexp-cache (make-hash-table :test 'equal)) +(defun helm-fuzzy-flex-style-score (candidate pattern) + "Give a score to CANDIDATE according to PATTERN. +A regexp is generated from PATTERN to calculate score. +Score is calculated with the emacs-27 flex algorithm using +`helm-flex--style-score'." + (let ((regexp (helm-aif (gethash pattern helm--fuzzy-flex-regexp-cache) + it + (clrhash helm--fuzzy-flex-regexp-cache) + (puthash pattern (helm--fuzzy-flex-pattern-to-regexp pattern) + helm--fuzzy-flex-regexp-cache)))) + (helm-flex--style-score candidate regexp t))) + +(defun helm--fuzzy-flex-pattern-to-regexp (pattern) + "Return a regexp from PATTERN compatible with emacs-27 flex algorithm." + (completion-pcm--pattern->regex + (helm-completion--flex-transform-pattern (list pattern)) 'group)) + +(defun helm-flex-add-score-as-prop (candidates regexp) + (cl-loop with case-fold-search = (helm-set-case-fold-search) + for cand in candidates + collect (helm-flex--style-score cand regexp))) + +(defun helm-completion--flex-transform-pattern (pattern) + ;; "fob" => '(prefix "f" any "o" any "b" any point) + (cl-loop for p in pattern + if (stringp p) nconc + (cl-loop for str across p + nconc (list (string str) 'any)) + else nconc (list p))) + +(defun helm-fuzzy-helm-style-score (candidate pattern) + "Give a score to CANDIDATE according to PATTERN. +Score is calculated for contiguous matches found with PATTERN. +Score is 100 (maximum) if PATTERN is fully matched in CANDIDATE. +One point bonus is added to score when PATTERN prefix matches +CANDIDATE. Contiguous matches get a coefficient of 2." + (let* ((cand (if (stringp candidate) + candidate (helm-stringify candidate))) + (pat-lookup (helm--collect-pairs-in-string pattern)) + (str-lookup (helm--collect-pairs-in-string cand)) + (inter (cl-nintersection pat-lookup str-lookup :test 'equal)) + ;; Prefix + (bonus (cond ((or (equal (car pat-lookup) (car str-lookup)) + (equal (caar pat-lookup) (caar str-lookup))) + 2) + ((and (null pat-lookup) ; length = 1 + (string= pattern (substring cand 0 1))) + 150) + (t 0))) + ;; Exact match e.g. foo -> foo == 200 + (bonus1 (and (string= cand pattern) 200)) + ;; Partial match e.g. foo -> aafooaa == 100 + ;; or foo -> fooaaa + (bonus2 (and (or (string-match + (concat "\\`" (regexp-quote pattern)) + cand) + (string-match + (concat "\\<" (regexp-quote pattern) "\\>") + cand)) + 100))) + (+ bonus + (or bonus1 bonus2 + ;; Give a coefficient of 2 for contiguous matches. + ;; That's mean that "wiaaaki" will not take precedence + ;; on "aaawiki" when matching on "wiki" even if "wiaaaki" + ;; starts by "wi". + (* (length inter) 2))))) + +(defun helm-fuzzy-matching-default-sort-fn-1 (candidates &optional use-real basename preserve-tie-order) + "The transformer for sorting candidates in fuzzy matching. +It sorts on the display part by default. + +It sorts CANDIDATES by their scores as calculated by +`helm-score-candidate-for-pattern'. Set USE-REAL to non-nil to +sort on the real part. If BASENAME is non-nil assume we are +completing filenames and sort on basename of candidates. If +PRESERVE-TIE-ORDER is nil, ties in scores are sorted by length of +the candidates." + (if (string= helm-pattern "") + candidates + (let ((table-scr (make-hash-table :test 'equal))) + (sort candidates + (lambda (s1 s2) + ;; Score and measure the length on real or display part of candidate + ;; according to `use-real'. + (let* ((real-or-disp-fn (if use-real #'cdr #'car)) + (cand1 (cond ((and basename (consp s1)) + (helm-basename (funcall real-or-disp-fn s1))) + ((consp s1) (funcall real-or-disp-fn s1)) + (basename (helm-basename s1)) + (t s1))) + (cand2 (cond ((and basename (consp s2)) + (helm-basename (funcall real-or-disp-fn s2))) + ((consp s2) (funcall real-or-disp-fn s2)) + (basename (helm-basename s2)) + (t s2))) + (data1 (or (gethash cand1 table-scr) + (puthash cand1 + (list (helm-score-candidate-for-pattern + cand1 helm-pattern) + (length (helm-stringify cand1))) + table-scr))) + (data2 (or (gethash cand2 table-scr) + (puthash cand2 + (list (helm-score-candidate-for-pattern + cand2 helm-pattern) + (length (helm-stringify cand2))) + table-scr))) + (len1 (cadr data1)) + (len2 (cadr data2)) + (scr1 (car data1)) + (scr2 (car data2))) + (cond ((= scr1 scr2) + (unless preserve-tie-order + (< len1 len2))) + ((> scr1 scr2))))))))) + +(defun helm-fuzzy-matching-default-sort-fn (candidates _source) + "Default `filtered-candidate-transformer' to sort in fuzzy matching." + (helm-fuzzy-matching-default-sort-fn-1 candidates)) + +(defun helm-fuzzy-matching-sort-fn-preserve-ties-order (candidates _source) + "Same as `helm-fuzzy-matching-default-sort-fn' but preserving order of ties. +The default function, `helm-fuzzy-matching-default-sort-fn', +sorts ties by length, shortest first. This function may be more +useful when the order of the candidates is meaningful, e.g. with +`recentf-list'." + (helm-fuzzy-matching-default-sort-fn-1 candidates nil nil t)) + +(defun helm--maybe-get-migemo-pattern (pattern &optional diacritics) + (or (and helm-migemo-mode + (assoc-default pattern helm-mm--previous-migemo-info)) + (if diacritics + (char-fold-to-regexp pattern) + pattern))) + +(defun helm-fuzzy-default-highlight-match-1 (candidate &optional pattern diacritics file-comp) + (let* ((pair (and (consp candidate) candidate)) + (display (helm-stringify (if pair (car pair) candidate))) + (real (cdr pair)) + (host (and file-comp (get-text-property + (max 0 (1- (length display))) 'host display))) + (regex (helm--maybe-get-migemo-pattern pattern diacritics)) + (mpart (get-text-property 0 'match-part display)) + (mp (cond ((and mpart (string= display mpart)) nil) + (mpart) + ;; FIXME: This may be wrong when match-on-real + ;; is nil, so we should flag match-on-real on + ;; top and use it. + (file-comp (file-name-nondirectory + (or host (and (stringp real) real) display))))) + (count 0) + beg-str end-str) + (when host (setq pattern (cadr (split-string pattern ":")))) + ;; Extract all parts of display keeping original properties. + (when (and mp (ignore-errors + ;; Avoid error when candidate is a huge line. + (string-match (regexp-quote mp) display))) + (setq beg-str (substring display 0 (match-beginning 0)) + end-str (substring display (match-end 0) (length display)) + mp (substring display (match-beginning 0) (match-end 0)))) + (with-temp-buffer + ;; Insert the whole display part and remove non--match-part + ;; to keep their original face properties. + (insert (propertize (or mp display) 'read-only nil)) ; Fix (bug#1176) + (goto-char (point-min)) + (condition-case nil + (progn + ;; Try first matching against whole pattern. + (unless (string= pattern "") + (while (re-search-forward regex nil t) + (cl-incf count) + (helm-add-face-text-properties + (match-beginning 0) (match-end 0) 'helm-match))) + ;; If no matches start matching against multiples or fuzzy matches. + (when (zerop count) + (cl-loop with multi-match = (string-match-p " " pattern) + with patterns = (if multi-match + (cl-loop for pat in (helm-mm-split-pattern + pattern) + collect + (helm--maybe-get-migemo-pattern + pat diacritics)) + (split-string pattern "" t)) + for p in patterns + ;; Multi matches (regexps patterns). + if multi-match do + (progn + (while (re-search-forward p nil t) + (helm-add-face-text-properties + (match-beginning 0) (match-end 0) + 'helm-match)) + (goto-char (point-min))) + ;; Fuzzy matches (literal patterns). + else do + (when (search-forward p nil t) + (helm-add-face-text-properties + (match-beginning 0) (match-end 0) + 'helm-match))))) + (invalid-regexp nil)) + ;; Now replace the original match-part with the part + ;; with face properties added. + (setq display (if mp (concat beg-str (buffer-string) end-str) (buffer-string)))) + (if real (cons display real) display))) + +(cl-defun helm-fuzzy-default-highlight-match (candidate + &optional (pattern helm-pattern) diacritics file-comp) + "The default function to highlight matches in fuzzy matching. +Highlight elements in CANDIDATE matching PATTERN according +to the matching method in use. When DIACRITICS is specified, ignore +diacritics, see `char-fold-to-regexp' for more infos." + (if (string= pattern "") + ;; Empty pattern, do nothing. This is needed when this function + ;; is used outside of helm-fuzzy-highlight-matches like in *buffers-list. + candidate + ;; Else start highlighting. + (helm-fuzzy-default-highlight-match-1 candidate pattern diacritics file-comp))) + +(defun helm-fuzzy-highlight-matches (candidates source) + "Highlight matches in CANDIDATES for SOURCE. +The filtered-candidate-transformer function to highlight fuzzy matches. +See `helm-fuzzy-default-highlight-match'." + (cl-assert helm-fuzzy-matching-highlight-fn nil "Wrong type argument functionp: nil") + (cl-loop with diac = (helm-get-attr 'diacritics source) + with file-comp-p = (and (not (helm-action-window)) + (or minibuffer-completing-file-name + (helm-get-attr 'completing-file-name source) + (helm-guess-filename-at-point))) + ;; helm-pattern may have been modified (fuzzy) so ensure to + ;; use helm-input which is the raw pattern. + with pattern = (if file-comp-p + (file-name-nondirectory helm-input) + helm-pattern) + when (string= pattern "") return candidates + for c in candidates + collect (funcall helm-fuzzy-matching-highlight-fn c pattern diac file-comp-p))) + + +;;; helm-flex style +;; +;; Provide the emacs-27 flex style for emacs<27. +;; Reuse the flex scoring algorithm of flex style in emacs-27. +(defun helm-flex--style-score (str regexp &optional score) + "Score STR candidate according to REGEXP. + +REGEXP should be generated from a pattern which is a list like +\\='(point \"f\" any \"o\" any \"b\" any) for \"fob\" as pattern. +Such pattern may be build with +`helm-completion--flex-transform-pattern' function, and the regexp +with `completion-pcm--pattern->regex'. For commodity, +`helm--fuzzy-flex-pattern-to-regexp' is used to build such regexp. + +Function extracted from `completion-pcm--hilit-commonality' in +emacs-27 to provide such scoring in emacs<27." + ;; Don't modify the string itself. + (setq str (copy-sequence str)) + (if (string-match regexp str) + (let* ((md (match-data)) + (start (pop md)) + (len (length str)) + (score-numerator 0) + (score-denominator 0) + (last-b 0) + (update-score + (lambda (a b) + "Update score variables given match range (A B)." + (setq score-numerator (+ score-numerator (- b a))) + (unless (or (= a last-b) + (zerop last-b) + (= a (length str))) + (setq score-denominator (+ score-denominator + 1 + (expt (- a last-b 1) + (/ 1.0 3))))) + (setq last-b b))) + result) + (funcall update-score start start) + (setq md (cdr md)) + (while md + (funcall update-score start (pop md)) + (setq start (pop md))) + (funcall update-score len len) + (unless (zerop (length str)) + (setq result (/ score-numerator (* len (1+ score-denominator)) 1.0)) + (put-text-property 0 1 'completion-score result str)) + (if (and score result) result str)) + (put-text-property 0 1 'completion-score 0.0 str) + (if score 0.0 str))) + + +;;; Matching candidates +;; +;; +(defun helm-match-functions (source) + (let ((matchfns (or (assoc-default 'match source) + (assoc-default 'match-strict source) + #'helm-default-match-function))) + (if (and (listp matchfns) (not (functionp matchfns))) + matchfns (list matchfns)))) + +(defun helm-search-functions (source) + (let ((searchfns (assoc-default 'search source))) + (if (and (listp searchfns) (not (functionp searchfns))) + searchfns (list searchfns)))) + +(defun helm-match-from-candidates (cands matchfns match-part-fn limit source) + (when cands ; nil in async sources. + (condition-case-unless-debug err + (cl-loop with hash = (make-hash-table :test 'equal) + with allow-dups = (assq 'allow-dups source) + with case-fold-search = (helm-set-case-fold-search) + with count = 0 + for iter from 1 + for fn in matchfns + when (< count limit) nconc + (cl-loop for c in cands + for dup = (gethash c hash) + for disp = (helm-candidate-get-display c) + while (< count limit) + for target = (if (helm-get-attr 'match-on-real source) + ;; Let's fails on error in + ;; case next block returns nil. + (or (cdr-safe c) + (get-text-property 0 'helm-realvalue disp)) + disp) + for prop-part = (get-text-property 0 'match-part target) + for part = (and match-part-fn + (or prop-part + (funcall match-part-fn target))) + ;; When allowing dups check if DUP + ;; have been already found in previous loop + ;; by comparing its value with ITER. + when (and (or (and allow-dups dup (= dup iter)) + (null dup)) + (condition-case nil + (funcall fn (or part target)) + (invalid-regexp nil))) + do + (progn + ;; Give as value the iteration number of + ;; inner loop to be able to check if + ;; the duplicate have not been found in previous loop. + (puthash c iter hash) + (helm--maybe-process-filter-one-by-one-candidate c source) + (cl-incf count)) + ;; Filter out nil candidates maybe returned by + ;; `helm--maybe-process-filter-one-by-one-candidate'. + and when c collect + (if (and part (not prop-part)) + (if (consp c) + (cons (propertize target 'match-part part) (cdr c)) + (propertize c 'match-part part)) + c))) + (error (unless (eq (car err) 'invalid-regexp) ; Always ignore regexps errors. + (helm-log-error "helm-match-from-candidates" + "helm-match-from-candidates in source `%s': %s %s" + (assoc-default 'name source) (car err) (cdr err))) + nil)))) + +(defun helm-compute-matches (source) + "Start computing candidates in SOURCE." + (save-current-buffer + (let ((matchfns (helm-match-functions source)) + (matchpartfn (assoc-default 'match-part source)) + (helm--source-name (assoc-default 'name source)) + (helm-current-source source) + (limit (helm-candidate-number-limit source)) + (helm-pattern (helm-process-pattern-transformer + helm-pattern source))) + (helm--fuzzy-match-maybe-set-pattern) + ;; If source have a `filtered-candidate-transformer' attr + ;; Filter candidates with this func, otherwise just compute + ;; candidates. + ;; NOTE that this next block of code is returning nil on async sources, + ;; the candidates being processed directly in `helm-output-filter' + ;; process-filter. + (helm-process-filtered-candidate-transformer + ;; When using in-buffer method or helm-pattern is empty or + ;; using dynamic completion always compute all candidates. + (if (or (equal helm-pattern "") + (assq 'match-dynamic source) + (helm--candidates-in-buffer-p source)) + ;; Compute all candidates up to LIMIT. + ;; one-by-one are computed here only for sources that + ;; display a list of candidates even with an empty + ;; pattern. + (helm--initialize-one-by-one-candidates + (helm-take (helm-get-cached-candidates source) limit) + source) + ;; Compute candidates according to pattern with their match + ;; fns. + ;; one-by-one filtered candidates are computed during the + ;; execution of next loop in `helm-match-from-candidates'. + (helm-match-from-candidates + (helm-get-cached-candidates source) matchfns matchpartfn limit source)) + source)))) + +(defun helm--candidates-in-buffer-p (source) + (assq 'search source)) + +(defun helm-render-source (source matches) + "Display MATCHES from SOURCE according to its settings." + (helm-log "helm-render-source" "Source = %S" (remove (assq 'keymap source) source)) + (when matches + (helm-insert-header-from-source source) + (cl-loop with separate = nil + with start = (point) + with singleline = (null (assq 'multiline source)) + for m in matches + for count from 1 + if singleline + do (helm-insert-match m 'insert count source) + else + do (progn + (if separate + (helm-insert-candidate-separator) + (setq separate t)) + (helm-insert-match m 'insert count source)) + finally (and (null singleline) + (put-text-property start (point) + 'helm-multiline t))))) + +(defmacro helm-while-no-input (&rest body) + "Same as `while-no-input' but returns either BODY or nil. +Unlike `while-no-input' this macro ensure to not returns `t'." + (declare (debug t) (indent 0)) + (let ((catch-sym (make-symbol "input"))) + `(with-local-quit + (catch ',catch-sym + (let ((throw-on-input ',catch-sym) + val) + (setq val (progn ,@body)) + ;; See comments in `while-no-input' about resetting + ;; quit-flag. + (cond ((eq quit-flag throw-on-input) + (setq quit-flag nil)) + (quit-flag nil) + (t val))))))) + +(defmacro helm--maybe-use-while-no-input (&rest body) + "Wrap BODY in `helm-while-no-input' unless initializing a remote connection." + `(progn + (if (and (file-remote-p helm-pattern) + (not (file-remote-p helm-pattern nil t))) + ;; Tramp will ask for passwd, don't use `helm-while-no-input'. + ,@body + (helm-log "helm--maybe-use-while-no-input" + "Using here `helm-while-no-input'") + ;; Emacs bug , unexpected + ;; dbus-event is triggered on dbus init. + ;; Ignoring the dbus-event work on emacs28+; for emacs27 or older + ;; version, require tramp-archive can workaround the issue. + (let ((while-no-input-ignore-events + (and (boundp 'while-no-input-ignore-events) + (cons 'dbus-event while-no-input-ignore-events)))) + (helm-while-no-input ,@body))))) + +(defun helm--collect-matches (src-list) + "Return a list of matches for each source in SRC-LIST. + +The resulting value is a list of lists, e.g. ((a b c) (c d) (e +f)) or (nil nil nil) for three sources when no matches found, +however this function can be interrupted by new input and in this +case returns a plain nil i.e. not (nil), in this case +`helm-update' is not rendering the source, keeping previous +candidates in display." + (let ((matches (helm--maybe-use-while-no-input + (cl-loop for src in src-list + collect (helm-compute-matches src))))) + (unless (eq matches t) matches))) + + +;;; Case fold search +;; +;; +(cl-defun helm-set-case-fold-search (&optional (pattern helm-pattern)) + "Used to set the value of `case-fold-search' in Helm. +Return t or nil depending on the value of `helm-case-fold-search' +and `helm-pattern'." + (if helm-alive-p + (let ((helm-case-fold-search + (helm-aif (assq 'case-fold-search (helm-get-current-source)) + (cdr it) + helm-case-fold-search)) + ;; Only parse basename for filenames + ;; to avoid setting case sensitivity + ;; when expanded directories contains upcase + ;; characters. + (bn-or-pattern (if (string-match "[~/]*" pattern) + (helm-basename pattern) + pattern))) + (helm-set-case-fold-search-1 bn-or-pattern)) + case-fold-search)) + +(defun helm-set-case-fold-search-1 (pattern) + (cl-case helm-case-fold-search + (smart (let ((case-fold-search nil)) + (if (string-match "[[:upper:]]" pattern) nil t))) + (t helm-case-fold-search))) + + +;;; Helm update +;; +(defun helm-update (&optional preselect source candidates) + "Update candidates list in `helm-buffer' based on `helm-pattern'. +Argument PRESELECT is a string or regexp used to move selection +to a particular place after finishing update. +When SOURCE is provided update mode-line for this source, otherwise +the current source will be used. +Argument CANDIDATES when provided is used to redisplay these candidates +without recomputing them, it should be a list of lists." + (helm-log "helm-update" "Start updating") + (helm-kill-async-processes) + ;; When persistent action have been called + ;; we have two windows even with `helm-full-frame'. + ;; So go back to one window when updating if `helm-full-frame' + ;; is non-`nil'. + (when (with-helm-buffer + (and helm-onewindow-p + ;; We are not displaying helm-buffer in a frame and + ;; helm-window is already displayed. + (not helm--buffer-in-new-frame-p) + (helm-window) + (not (helm-action-window)))) + (with-helm-window (delete-other-windows))) + (with-current-buffer (helm-buffer-get) + (set (make-local-variable 'helm-input-local) helm-pattern) + (unwind-protect + (let (sources matches) + ;; Collect sources ready to be updated. + (setq sources + (cl-loop for src in helm-sources + when (helm-update-source-p src) + collect src)) + ;; When no sources to update erase buffer + ;; to avoid duplication of header and candidates + ;; when next chunk of update will arrive, + ;; otherwise the buffer is erased AFTER [1] the results + ;; are computed. + (unless sources (erase-buffer)) + ;; Compute matches without rendering the sources. + ;; This prevent the helm-buffer flickering when constantly + ;; updating. + (helm-log "helm-update" "Matches: %S" + (setq matches (or candidates (helm--collect-matches sources)))) + ;; If computing matches finished and is not interrupted + ;; erase the helm-buffer and render results (Fix #1157). + (when matches ;; nil only when interrupted by while-no-input. + (erase-buffer) ; [1] + (cl-loop for src in sources + for mtc in matches + do (helm-render-source src mtc)) + ;; Move to first line only when there is matches + ;; to avoid cursor moving upside down (Bug#1703). + (helm--update-move-first-line))) + ;; When there is only one async source, update mode-line and run + ;; `helm-after-update-hook' in `helm-output-filter--post-process', + ;; when there is more than one source, update mode-line and run + ;; `helm-after-update-hook' now even if an async source is + ;; present and running in BG. + (let ((src (or source (helm-get-current-source)))) + (unless (assq 'candidates-process src) + (helm-display-mode-line src 'force) + (helm-log-run-hook "helm-update" 'helm-after-update-hook))) + (when preselect + (helm-log "helm-update" "Update preselect candidate %s" preselect) + (if (helm-window) + (with-helm-window (helm-preselect preselect source)) + (helm-preselect preselect source))) + (setq helm--force-updating-p nil) + (helm--reset-update-flag)) + (helm-log "helm-update" "end update"))) + +(defun helm-update-source-p (source) + "Whether SOURCE needs updating or not." + (let ((len (string-width + (if (assq 'multimatch source) + ;; Don't count spaces entered when using + ;; multi-match. + (replace-regexp-in-string " " "" helm-pattern) + helm-pattern)))) + (and (or (not helm-source-filter) + (member (assoc-default 'name source) helm-source-filter)) + (>= len + (helm-aif (assq 'requires-pattern source) (or (cdr it) 1) 0)) + ;; Entering repeatedly these strings (*, ?) takes 100% CPU + ;; and hang emacs on MacOs preventing deleting backward those + ;; characters (Bug#1802). Update: it seems it is no more true, + ;; thus this affect bug#2423, so let's remove this for now. + ;; (not (string-match-p "\\`[*]+\\'" helm-pattern)) + ;; These incomplete regexps hang helm forever + ;; so defer update. Maybe replace spaces quoted when using + ;; multi-match. + (not (member (replace-regexp-in-string "\\s\\ " " " helm-pattern) + helm-update-blacklist-regexps))))) + +(defun helm--update-move-first-line () + "Goto first line of `helm-buffer'." + (goto-char (point-min)) + (if (helm-window) + (helm-move-selection-common :where 'line + :direction 'next + :follow t) + (forward-line 1) + (helm-mark-current-line) + (helm-follow-execute-persistent-action-maybe))) + +(cl-defun helm-force-update (&optional preselect (recenter t)) + "Force recalculation and update of candidates. + +Unlike `helm-update', this function re-evaluates `init' and +`update' attributes when present; also `helm-candidate-cache' is +not reinitialized, meaning candidates are not recomputed unless +pattern has changed. + +Selection is preserved to current candidate if it still exists after +update or moved to PRESELECT, if specified. +The helm-window is re-centered at the end when RECENTER is t which +is the default. RECENTER can be also a number in this case it is +passed as argument to `recenter'." + (with-helm-buffer + (let* ((source (helm-get-current-source)) + (selection (helm-aif (helm-get-selection nil t source) + (regexp-quote it)))) + (setq helm--force-updating-p t) + (mapc 'helm-force-update--reinit helm-sources) + (helm-update (or preselect selection) source) + (when (and (helm-window) recenter) + (with-helm-window + (recenter (and (numberp recenter) recenter))))))) + +(defun helm-refresh () + "Force recalculation and update of candidates." + (interactive) + (with-helm-alive-p + (helm-force-update))) +(put 'helm-refresh 'helm-only t) + +(defun helm-force-update--reinit (source) + "Reinit SOURCE by calling its update and init functions." + ;; When using a specific buffer as cache, don't kill it. + (helm-aif (and (null (bufferp (assoc-default + (helm-get-attr 'name source) + helm--candidate-buffer-alist))) + (helm-apply-functions-from-source + source 'helm-candidate-buffer)) + (kill-buffer it)) + (dolist (attr '(update init)) + (helm-aif (assoc-default attr source) + (helm-apply-functions-from-source source it))) + (helm-remove-candidate-cache source)) + +(defun helm-redisplay-buffer () + "Redisplay candidates in `helm-buffer'. + +Candidates are not recomputed, only redisplayed after modifying +the whole list of candidates in each source with functions found +in `redisplay' attribute of current source. Note that candidates +are redisplayed with their display part with all properties +included only. This function is used in async sources to +transform the whole list of candidates from the sentinel +functions (i.e. when all candidates have been computed) because +other filters like `candidate-transformer' are modifying only +each chunk of candidates from `process-filter' as they come in +and not the whole list. Use this for e.g. sorting the whole list +of async candidates once computed. + +Note: To ensure redisplay is done in async sources after Helm +reached `candidate-number-limit' you will have also to redisplay +your candidates from `helm-async-outer-limit-hook'." + (with-helm-buffer + (let ((get-cands (lambda (source) + (let ((fns (assoc-default 'redisplay source)) + candidates + helm-move-to-line-cycle-in-source + helm-allow-mouse) + (helm-goto-source source) + (helm-next-line) + (helm-awhile (condition-case-unless-debug nil + (and (not (helm-pos-header-line-p)) + (helm-get-selection + nil 'withprop source)) + (error nil)) + (push it candidates) + (when (save-excursion + (forward-line 1) (helm-end-of-source-p t)) + (cl-return nil)) + (helm-next-line)) + (helm-apply-functions-from-source + source fns (nreverse candidates))))) + (get-sources (lambda () + (let (sources helm-move-to-line-cycle-in-source) + (helm-awhile (helm-get-current-source) + (push it sources) + (when (save-excursion + (helm-move--end-of-source) + (forward-line 1) (eobp)) + (cl-return nil)) + (helm-next-source)) + (nreverse sources))))) + (goto-char (point-min)) + (helm-update nil (helm-get-current-source) + (cl-loop with sources = (funcall get-sources) + for s in helm-sources + for name = (assoc-default 'name s) collect + (when (cl-loop for src in sources thereis + (string= name + (assoc-default 'name src))) + (funcall get-cands s))))))) + +(defun helm-remove-candidate-cache (source) + "Remove SOURCE from `helm-candidate-cache'." + (remhash (assoc-default 'name source) helm-candidate-cache)) + +(defvar helm-drag-mouse-1-fn 'ignore) +(defun helm-insert-match (match insert-function &optional num source) + "Insert MATCH into `helm-buffer' with INSERT-FUNCTION. +If MATCH is a cons cell then insert the car as display with the +cdr stored as real value in a `helm-realvalue' text property. +Args NUM and SOURCE are also stored as text property when +specified as respectively `helm-cand-num' and `helm-cur-source'." + (let ((start (point-at-bol (point))) + (dispvalue (helm-candidate-get-display match)) + (realvalue (cdr-safe match)) + (map (when helm-allow-mouse (make-sparse-keymap))) + (inhibit-read-only t) + end) + (when (and (stringp dispvalue) + (not (zerop (length dispvalue)))) + (funcall insert-function dispvalue) + (setq end (point-at-eol)) + ;; Some strings may handle another keymap prop. + (remove-text-properties start end '(keymap nil)) + (put-text-property start end 'read-only nil) + ;; Some sources with candidates-in-buffer have already added + ;; 'helm-realvalue property when creating candidate buffer. + (unless (get-text-property start 'helm-realvalue) + (and realvalue + (put-text-property start end + 'helm-realvalue realvalue))) + (when map + (define-key map [drag-mouse-1] 'ignore) + (define-key map [mouse-1] 'helm-mouse-select-candidate) + (define-key map [mouse-2] 'ignore) + (define-key map [mouse-3] 'helm-menu-select-action) + (add-text-properties + start end + `(mouse-face highlight + keymap ,map + help-echo ,(pcase (get-text-property start 'help-echo) + ((and it (pred stringp)) + (concat it "\nmouse-1: select candidate\nmouse-3: menu actions")) + (_ "mouse-1: select candidate\nmouse-3: menu actions"))))) + (when num + (put-text-property start end 'helm-cand-num num)) + (when source + (put-text-property start end 'helm-cur-source source)) + (funcall insert-function "\n")))) + +(defun helm--mouse-reset-selection-help-echo () + (let* ((inhibit-read-only t) + (start (overlay-start helm-selection-overlay)) + (end (overlay-end helm-selection-overlay)) + (help-echo (get-text-property start 'help-echo))) + (when (and (stringp help-echo) + (string-match "mouse-2: execute action" help-echo)) + (put-text-property + start end + 'help-echo (replace-match "mouse-1: select candidate" + t t help-echo))))) + +(defun helm--bind-mouse-for-selection (pos) + (let ((inhibit-read-only t) + (map (get-text-property pos 'keymap))) + (when map + (define-key map [drag-mouse-1] helm-drag-mouse-1-fn) + (define-key map [mouse-2] 'helm-maybe-exit-minibuffer) + (put-text-property + helm-selection-point + (overlay-end helm-selection-overlay) + 'help-echo (helm-aif (get-text-property pos 'help-echo) + (if (and (stringp it) + (string-match "mouse-1: select candidate" it)) + (replace-match "mouse-2: execute action" t t it) + "mouse-2: execute action\nmouse-3: menu actions") + "mouse-2: execute action\nmouse-3: menu actions"))))) + +(defun helm-mouse-select-candidate (event) + (interactive "e") + (let* ((window (posn-window (event-end event))) + (pos (posn-point (event-end event)))) + (unwind-protect + (with-current-buffer (window-buffer window) + (if (and (helm-action-window) + (eql window (get-buffer-window helm-buffer))) + (user-error "selection in helm-window not available while selecting action") + (helm--mouse-reset-selection-help-echo) + (goto-char pos) + (when (helm-pos-multiline-p) + (goto-char (or (helm-get-previous-candidate-separator-pos) + (helm-get-previous-header-pos))) + (forward-line 1))) + (helm-mark-current-line) + (helm-follow-execute-persistent-action-maybe)) + (select-window (minibuffer-window)) + (set-buffer (window-buffer window))))) +(put 'helm-mouse-select-candidate 'helm-only t) + +(defun helm-insert-header-from-source (source) + "Insert SOURCE name in `helm-buffer' header. +Maybe insert, by overlay, additional info after the source name +if SOURCE has header-name attribute." + (let ((name (assoc-default 'name source))) + (helm-insert-header + name + (helm-aif (assoc-default 'header-name source) + (helm-apply-functions-from-source source it name))))) + +(defun helm-insert-header (name &optional display-string) + "Insert header of source NAME into the helm buffer. +If DISPLAY-STRING is non-nil and a string value then display this +additional info after the source name by overlay." + (unless (bobp) + (let ((start (point))) + (insert (propertize "\n" 'face 'helm-eob-line)) + (put-text-property start (point) 'helm-header-separator t))) + (let ((start (point))) + (insert name) + (put-text-property (point-at-bol) + (point-at-eol) 'helm-header t) + (when display-string + (overlay-put (make-overlay (point-at-bol) (point-at-eol)) + 'display display-string)) + (insert "\n") + (add-text-properties start (point) '(face helm-source-header + ;; Disable line numbers on + ;; source headers. + display-line-numbers-disable t)))) + +(defun helm-insert-candidate-separator () + "Insert separator of candidates into the Helm buffer." + (insert (propertize helm-candidate-separator 'face 'helm-separator)) + (put-text-property (point-at-bol) + (point-at-eol) 'helm-candidate-separator t) + (insert "\n")) + +(defun helm-init-relative-display-line-numbers () + "Enable `display-line-numbers' for Helm buffers. +This is intended to be added to `helm-after-initialize-hook'. +This will work only in Emacs-26+, i.e. Emacs versions that have +`display-line-numbers-mode'." + (when (boundp 'display-line-numbers) + (with-helm-buffer + (setq display-line-numbers 'relative)))) + +(define-minor-mode helm-display-line-numbers-mode + "Toggle display of line numbers in current Helm buffer." + :group 'helm + (with-helm-alive-p + (cl-assert (boundp 'display-line-numbers) nil + "`display-line-numbers' not available") + (if helm-display-line-numbers-mode + (with-helm-buffer + (setq display-line-numbers 'relative)) + (with-helm-buffer + (setq display-line-numbers nil))))) +(put 'helm-display-line-numbers-mode 'helm-only t) + + + +;;; Async process +;; +(defun helm-output-filter (process output-string) + "The `process-filter' function for Helm async sources." + (with-local-quit + (helm-output-filter-1 (assoc process helm-async-processes) output-string))) + +(defun helm-output-filter-1 (process-assoc output-string) + (helm-log "helm-output-filter-1" "output-string = %S" output-string) + (with-current-buffer helm-buffer + (let ((source (cdr process-assoc))) + (save-excursion + (helm-aif (assoc-default 'insertion-marker source) + (goto-char it) + (goto-char (point-max)) + (helm-insert-header-from-source source) + (setcdr process-assoc + (append source `((insertion-marker . ,(point-marker)))))) + (helm-output-filter--process-source + (car process-assoc) output-string source + (helm-candidate-number-limit source)))) + (helm-output-filter--post-process))) + +(defun helm-output-filter--process-source (process output-string source limit) + (cl-dolist (candidate (helm-transform-candidates + (helm-output-filter--collect-candidates + (split-string output-string + helm-process-output-split-string-separator) + (assq 'incomplete-line source)) + source t)) + (setq candidate + (helm--maybe-process-filter-one-by-one-candidate candidate source)) + (if (assq 'multiline source) + (let ((start (point))) + (helm-insert-candidate-separator) + (helm-insert-match candidate 'insert-before-markers + (1+ (cdr (assq 'item-count source))) + source) + (put-text-property start (point) 'helm-multiline t)) + (helm-insert-match candidate 'insert-before-markers + (1+ (cdr (assq 'item-count source))) + source)) + (cl-incf (cdr (assq 'item-count source))) + (when (>= (assoc-default 'item-count source) limit) + (helm-kill-async-process process) + (helm-log-run-hook "helm-output-filter--process-source" + 'helm-async-outer-limit-hook) + (cl-return)))) + +(defun helm-output-filter--collect-candidates (lines incomplete-line-info) + "Collect LINES maybe completing the truncated first and last lines." + ;; The output of process may come in chunks of any size, so the last + ;; line of LINES could be truncated, this truncated line is stored + ;; in INCOMPLETE-LINE-INFO to be concatenated with the first + ;; incomplete line of the next arriving chunk. INCOMPLETE-LINE-INFO + ;; is an attribute of source; it is created with an empty string + ;; when the source is computed => (incomplete-line . "") + (helm-log "helm-output-filter--collect-candidates" + "incomplete-line-info = %S" (cdr incomplete-line-info)) + (butlast + (cl-loop for line in lines + ;; On start `incomplete-line-info' value is empty string. + for newline = (helm-aif (cdr incomplete-line-info) + (prog1 + (concat it line) + (setcdr incomplete-line-info nil)) + line) + collect newline + ;; Store last incomplete line (last chunk truncated) until + ;; new output arrives. Previously storing 'line' in + ;; incomplete-line-info assumed output was truncated in + ;; only two chunks. But output could be large and + ;; truncated in more than two chunks. Therefore store + ;; 'newline' to contain the previous chunks (Bug#1187). + finally do (setcdr incomplete-line-info newline)))) + +(defun helm-output-filter--post-process () + (helm-aif (get-buffer-window helm-buffer 'visible) + (with-selected-window it + (helm-skip-noncandidate-line 'next) + (helm-mark-current-line nil 'nomouse) + ;; FIXME Don't hardcode follow delay. + (helm-follow-execute-persistent-action-maybe 0.5) + (helm-display-mode-line (helm-get-current-source)) + (helm-log-run-hook "helm-output-filter--post-process" + 'helm-after-update-hook) + (helm--reset-update-flag)))) + +(defun helm-process-deferred-sentinel-hook (process event file) + "Defer remote processes in sentinels. +Meant to be called at the beginning of a sentinel process +function." + (when (and (not (zerop helm-tramp-connection-min-time-diff)) + (string= event "finished\n") + (or (file-remote-p file) + ;; `helm-suspend-update-flag' + ;; is non-`nil' here only during a + ;; running process, this will never be called + ;; when user set it explicitly with `C-!'. + helm-suspend-update-flag)) + (setq helm-suspend-update-flag t) + ;; Kill the process but don't delete entry in + ;; `helm-async-processes'. + (helm-kill-async-process process) + ;; When tramp opens the same connection twice in less than 5 + ;; seconds, it throws 'suppress, which calls the real-handler on + ;; the main "Emacs". To avoid this [1] helm waits for 5 seconds + ;; before updates yet allows user input during this delay. [1] In + ;; recent Emacs versions, this has been fixed so tramp returns nil + ;; in such conditions. Note: `tramp-connection-min-time-diff' cannot + ;; have values less than 5 seconds otherwise the process dies. + (run-at-time helm-tramp-connection-min-time-diff + nil (lambda () + (when helm-alive-p ; Don't run timer fn after quit. + (setq helm-suspend-update-flag nil) + (helm-check-minibuffer-input)))))) + +(defun helm-kill-async-processes () + "Kill all asynchronous processes registered in `helm-async-processes'." + (while helm-async-processes + (helm-kill-async-process (caar helm-async-processes)) + (setq helm-async-processes (cdr helm-async-processes)))) + +(defun helm-kill-async-process (process) + "Stop output from `helm-output-filter' and kill associated PROCESS." + (set-process-filter process nil) + (delete-process process)) + + +;;; Actions +;; +(defun helm-execute-selection-action () + "Execute current action." + (helm-log-run-hook "helm-execute-selection-action" + 'helm-before-action-hook) + ;; Position can be change when `helm-current-buffer' + ;; is split, so jump to this position before executing action. + (helm-current-position 'restore) + (unwind-protect + (prog1 (helm-execute-selection-action-1) + (helm-log-run-hook "helm-execute-selection-action" + 'helm-after-action-hook)) + (setq helm--executing-helm-action nil))) + +(defun helm-execute-selection-action-1 (&optional + selection action + preserve-saved-action) + "Execute ACTION on current SELECTION. +If PRESERVE-SAVED-ACTION is non-nil, then save the action." + (helm-log "helm-execute-selection-action-1" "executing action") + (setq action (helm-get-default-action + (or action + helm-saved-action + (if (get-buffer helm-action-buffer) + (helm-get-selection helm-action-buffer) + (helm-get-actions-from-current-source))))) + (helm-aif (and (not helm-in-persistent-action) + (get-buffer helm-action-buffer)) + (kill-buffer it)) + (let ((source (or helm-saved-current-source + (helm-get-current-source))) + non-essential) + (setq selection (helm-coerce-selection + (or selection + helm-saved-selection + (helm-get-selection nil nil source) + (and (assq 'accept-empty source) "")) + source)) + (unless preserve-saved-action (setq helm-saved-action nil)) + (when (and selection action) (funcall action selection)))) + +(defun helm-coerce-selection (selection source) + "Apply coerce attribute function to SELECTION in SOURCE. +Coerce source with coerce function." + (helm-aif (assoc-default 'coerce source) + (helm-apply-functions-from-source source it selection) + selection)) + +(defun helm-get-default-action (action) + "Get the first ACTION value of action list in source." + (if (and (listp action) (not (functionp action))) + (cdar action) + action)) + +(defun helm--show-action-window-other-window-p () + (and helm-show-action-window-other-window + (or helm-always-two-windows + helm--buffer-in-new-frame-p) + (eq helm-split-window-state 'vertical))) + +(defun helm-select-action () + "Select an action for the currently selected candidate. +If action buffer is selected, back to the Helm buffer." + (interactive) + (with-helm-alive-p + (let ((src (helm-get-current-source))) + (helm-log-run-hook "helm-select-action" 'helm-select-action-hook) + (setq helm-saved-selection (helm-get-selection nil nil src)) + (with-selected-frame (with-helm-window (selected-frame)) + (prog1 + (helm-acond ((get-buffer-window helm-action-buffer 'visible) + (set-window-buffer it helm-buffer) + (helm--set-action-prompt 'restore) + (when (helm--show-action-window-other-window-p) + (delete-window it)) + (kill-buffer helm-action-buffer) + (setq helm-saved-selection nil) + (helm-set-pattern helm-input 'noupdate)) + (helm-saved-selection + (setq helm-saved-current-source src) + (let ((actions (helm-get-actions-from-current-source src)) + helm-onewindow-p) + (if (functionp actions) + (message "Sole action: %s" + (if (or (consp actions) + (byte-code-function-p actions) + (helm-subr-native-elisp-p actions)) + "Anonymous" actions)) + (helm-show-action-buffer actions) + ;; Be sure the minibuffer is entirely deleted (bug#907). + (helm--delete-minibuffer-contents-from "") + (helm--set-action-prompt) + (helm-check-minibuffer-input)))) + (t (message "No Actions available"))) + (helm-display-mode-line (helm-get-current-source)) + (run-hooks 'helm-window-configuration-hook)))))) +(put 'helm-select-action 'helm-only t) + +(defun helm-menu-select-action (_event) + "Popup action menu from mouse-3." + (interactive "e") + (if (get-buffer-window helm-action-buffer 'visible) + (helm-select-action) + (let ((src (helm-get-current-source))) + (helm-aif (helm-get-actions-from-current-source src) + (progn + (setq helm-saved-current-source src) + (if (functionp it) + (message "Sole action: %s" + (if (or (consp it) + (byte-code-function-p it) + (helm-subr-native-elisp-p it)) + "Anonymous" it)) + (setq helm-saved-action + (x-popup-menu + t (list "Available Actions" + (cons "" it)))) + (helm-maybe-exit-minibuffer)) + (message "No Actions available")))))) +(put 'helm-menu-select-action 'helm-only t) + +(defun helm--set-action-prompt (&optional restore) + (with-selected-window (minibuffer-window) + (let ((inhibit-read-only t) + (props '(face minibuffer-prompt + field t + read-only t + rear-nonsticky t + front-sticky t)) + (prt (if restore helm--prompt helm--action-prompt))) + (erase-buffer) + (insert (apply #'propertize prt props))))) + +(defun helm-show-action-buffer (actions) + (with-current-buffer (get-buffer-create helm-action-buffer) + (erase-buffer) + (buffer-disable-undo) + (setq cursor-type nil) + (set-window-buffer (if (helm--show-action-window-other-window-p) + (split-window (get-buffer-window helm-buffer) + nil helm-show-action-window-other-window) + (get-buffer-window helm-buffer)) + helm-action-buffer) + (set (make-local-variable 'helm-sources) + (list + (helm-build-sync-source "Actions" + :volatile t + :nomark t + :persistent-action #'ignore + :persistent-help "DoNothing" + :keymap 'helm-map + :candidates actions + :mode-line '("Action(s)" "\\\\[helm-select-action]:BackToCands RET/f1/f2/fn:NthAct") + :candidate-transformer + (lambda (candidates) + (cl-loop for (i . j) in candidates + for count from 1 + collect + (cons (concat (cond ((> count 12) + " ") + ((< count 10) + (format "[f%s] " count)) + (t (format "[f%s] " count))) + (propertize i 'face 'helm-action)) + j))) + :candidate-number-limit nil))) + (set (make-local-variable 'helm-source-filter) nil) + (set (make-local-variable 'helm-selection-overlay) nil) + (helm-initialize-overlays helm-action-buffer))) + + +;; Selection of candidates + +(defun helm-display-source-at-screen-top-maybe (unit) + "Display source at the top of screen when UNIT value is \\='source. +Return nil for any other value of UNIT." + (when (and helm-display-source-at-screen-top (eq unit 'source)) + (set-window-start (selected-window) + (save-excursion (forward-line -1) (point))))) + +(defun helm-skip-noncandidate-line (direction) + "Skip source header or candidates separator when going in DIRECTION. +DIRECTION is either \\='next or \\='previous. +Same as `helm-skip-header-and-separator-line' but ensure point is +moved to the right place when at bob or eob." + (helm-skip-header-and-separator-line direction) + (and (bobp) (forward-line 1)) ; Skip first header. + (and (eobp) (forward-line -1))) ; Avoid last empty line. + +(defun helm-skip-header-and-separator-line (direction) + "Skip source header or candidate separator when going to next/previous line. +DIRECTION is either \\='next or \\='previous." + (let ((fn (cl-ecase direction + (next 'eobp) + (previous 'bobp)))) + (while (and (not (funcall fn)) + (or (helm-pos-header-line-p) + (helm-pos-candidate-separator-p))) + (forward-line (if (and (eq direction 'previous) + (not (eq (point-at-bol) (point-min)))) + -1 1))))) + +(defun helm-display-mode-line (source &optional force) + "Set up mode-line and header-line for `helm-buffer'. + +SOURCE is a Helm source object. + +Optional argument FORCE forces redisplay of the Helm buffer's +mode and header lines." + (set (make-local-variable 'helm-mode-line-string) + (helm-interpret-value (or (and (listp source) ; Check if source is empty. + (assoc-default 'mode-line source)) + (default-value 'helm-mode-line-string)) + source)) + (let ((follow (and (or (helm-follow-mode-p source) + (and helm-follow-mode-persistent + (member (assoc-default 'name source) + helm-source-names-using-follow))) + " (HF)")) + (marked (and helm-marked-candidates + (cl-loop with cur-name = (assoc-default 'name source) + for c in helm-marked-candidates + for name = (assoc-default 'name (car c)) + when (string= name cur-name) + collect c)))) + ;; Setup mode-line. + (if helm-mode-line-string + (setq mode-line-format + `(:propertize + (" " mode-line-buffer-identification " " + (:eval (format "L%-3d" (helm-candidate-number-at-point))) + ,follow + " " + (:eval ,(and marked + (propertize + (format "M%d" (length marked)) + 'face 'helm-visible-mark))) + (:eval (when ,helm--mode-line-display-prefarg + (let ((arg (prefix-numeric-value + (or prefix-arg current-prefix-arg)))) + (unless (= arg 1) + (propertize (format " [prefarg:%s]" arg) + 'face 'helm-prefarg))))) + " " + (:eval (with-helm-buffer + (helm-show-candidate-number + (car-safe helm-mode-line-string)))) + " " helm--mode-line-string-real " " + (:eval (make-string (window-width) ? ))) + keymap (keymap (mode-line keymap + (mouse-1 . ignore) + (down-mouse-1 . ignore) + (drag-mouse-1 . ignore) + (mouse-2 . ignore) + (down-mouse-2 . ignore) + (drag-mouse-2 . ignore) + (mouse-3 . ignore) + (down-mouse-3 . ignore) + (drag-mouse-3 . ignore)))) + helm--mode-line-string-real + (substitute-command-keys (if (listp helm-mode-line-string) + (cadr helm-mode-line-string) + helm-mode-line-string))) + (setq mode-line-format (default-value 'mode-line-format))) + ;; Setup header-line. + (cond (helm-echo-input-in-header-line + (setq force t) + (helm--set-header-line)) + (helm-display-header-line + (let ((hlstr (helm-interpret-value + (and (listp source) + (assoc-default 'header-line source)) + source)) + (endstr (make-string (window-width) ? ))) + (setq header-line-format + (propertize (concat " " hlstr endstr) + 'face 'helm-header)))))) + (when force (force-mode-line-update))) + +(defun helm--set-header-line (&optional update) + (with-selected-window (minibuffer-window) + (when helm-display-header-line + ;; Prevent cursor movement over the overlay displaying + ;; persistent-help in minibuffer (Bug#2108). + (setq-local disable-point-adjustment t)) + (let* ((beg (save-excursion (vertical-motion 0 (helm-window)) (point))) + (end (save-excursion (end-of-visual-line) (point))) + ;; The visual line where the cursor is. + (cont (buffer-substring beg end)) + (pref (propertize + " " + 'display (if (string-match-p (regexp-opt `(,helm--prompt + ,helm--action-prompt)) + cont) + `(space :width ,helm-header-line-space-before-prompt) + (propertize + "->" + 'face 'helm-header-line-left-margin)))) + (pos (- (point) beg))) + ;; Increment pos each time we find a "%" up to current-pos (bug#1648). + (cl-loop for c across (buffer-substring-no-properties beg (point)) + when (eql c ?%) do (cl-incf pos)) + ;; Increment pos when cursor is on a "%" to make it visible in header-line + ;; i.e "%%|" and not "%|%" (bug#1649). + (when (eql (char-after) ?%) (setq pos (1+ pos))) + (setq cont (replace-regexp-in-string "%" "%%" cont)) + (with-helm-buffer + (setq header-line-format (concat pref cont " ")) + (funcall helm-default-prompt-display-function pos) + (when update (force-mode-line-update)))))) + +(defun helm-set-default-prompt-display (pos) + (put-text-property + ;; Increment pos to handle the space before prompt (i.e `pref'). + (+ 1 pos) (+ 2 pos) + 'face + ;; Don't just use cursor face, this can hide the current character. + (list :inverse-video t + :foreground (face-background 'cursor) + :background (face-background 'default)) + header-line-format)) + +(defun helm-exchange-minibuffer-and-header-line () + "Display minibuffer in header-line and vice versa for current Helm session. + +This is a toggle command." + (interactive) + (with-helm-window + (add-hook 'helm-minibuffer-set-up-hook 'helm-hide-minibuffer-maybe) + (setq-local helm-echo-input-in-header-line + (not helm-echo-input-in-header-line)) + (with-selected-window (minibuffer-window) + (if (with-helm-buffer helm-echo-input-in-header-line) + (helm-hide-minibuffer-maybe) + (remove-overlays) + (setq cursor-type t))) + (helm-display-mode-line (helm-get-current-source) t))) +(put 'helm-exchange-minibuffer-and-header-line 'helm-only t) + +(defun helm--update-header-line () + ;; This should be used in `post-command-hook', + ;; nowhere else. + (when (with-helm-buffer helm-echo-input-in-header-line) + (helm--set-header-line t))) + +(defun helm-hide-minibuffer-maybe () + "Hide minibuffer contents in a Helm session. +This function should normally go to `helm-minibuffer-set-up-hook'. +It has no effect if `helm-echo-input-in-header-line' is nil." + (when (with-helm-buffer helm-echo-input-in-header-line) + (let ((ov (make-overlay (point-min) (point-max) nil nil t))) + (overlay-put ov 'window (selected-window)) + (helm-aif (and helm-display-header-line + (helm-get-attr 'persistent-help)) + (progn + (overlay-put ov 'display + (truncate-string-to-width + (substitute-command-keys + (concat "\\\\[helm-execute-persistent-action]: " + (format "%s (keeping session)" it))) + (- (window-width) 1))) + (overlay-put ov 'face 'helm-header)) + (overlay-put ov 'face (let ((bg-color (face-background 'default nil))) + `(:background ,bg-color :foreground ,bg-color)))) + + (setq cursor-type nil)))) + +(defun helm-show-candidate-number (&optional name) + "Used to display candidate number in mode-line. +You can specify NAME of candidates e.g. \"Buffers\" otherwise it +is \"Candidate(s)\" by default." + (when helm-alive-p + (unless (helm-empty-source-p) + ;; Build a fixed width string when candidate-number < 1000 + (let* ((cand-name (or name "Candidate(s)")) + (width (length (format "[999 %s]" cand-name)))) + (propertize + (format (concat "%-" (number-to-string width) "s") + (format "[%s %s]" + (helm-get-candidate-number 'in-current-source) + cand-name)) + 'face (if helm-suspend-update-flag + 'helm-candidate-number-suspended + 'helm-candidate-number)))))) + +(cl-defun helm-move-selection-common (&key where direction (follow t)) + "Move the selection marker to a new position. +Position is determined by WHERE and DIRECTION. +Key arg WHERE can be one of: + - line + - page + - edge + - source +Key arg DIRECTION can be one of: + - previous + - next + - A source or a source name when used with :WHERE \\='source." + (let ((move-func (cl-case where + (line (cl-ecase direction + (previous 'helm-move--previous-line-fn) + (next 'helm-move--next-line-fn))) + (page (cl-ecase direction + (previous 'helm-move--previous-page-fn) + (next 'helm-move--next-page-fn))) + (edge (cl-ecase direction + (previous 'helm-move--beginning-of-buffer-fn) + (next 'helm-move--end-of-buffer-fn))) + (source (cl-case direction + (previous 'helm-move--previous-source-fn) + (next 'helm-move--next-source-fn) + (t (lambda () ; A source is passed as DIRECTION arg. + (helm-move--goto-source-fn direction))))))) + source) + (unless (or (helm-empty-buffer-p (helm-buffer-get)) + (not (helm-window))) + (with-helm-window + (when helm-allow-mouse + (helm--mouse-reset-selection-help-echo)) + (helm-log-run-hook "helm-move-selection-common" + 'helm-move-selection-before-hook) + (funcall move-func) + (and (memq direction '(next previous)) + (helm-skip-noncandidate-line direction)) + (when (helm-pos-multiline-p) + (helm-move--beginning-of-multiline-candidate)) + (helm-display-source-at-screen-top-maybe where) + (helm-mark-current-line) + (when follow + (helm-follow-execute-persistent-action-maybe)) + (helm-display-mode-line (setq source (helm-get-current-source))) + (helm-log-run-hook "helm-move-selection-common" + 'helm-move-selection-after-hook) + (helm--set-minibuffer-completion-confirm source))))) + +(defun helm-move--beginning-of-multiline-candidate () + (let ((header-pos (helm-get-previous-header-pos)) + (separator-pos (helm-get-previous-candidate-separator-pos))) + (when header-pos + (goto-char (if (or (null separator-pos) + (< separator-pos header-pos)) + header-pos + separator-pos)) + (forward-line 1)))) + +(defun helm-move--previous-multi-line-fn () + (forward-line -1) + (unless (helm-pos-header-line-p) + (helm-skip-header-and-separator-line 'previous) + (helm-move--beginning-of-multiline-candidate))) + +(defun helm-move--previous-line-fn () + (if (not (helm-pos-multiline-p)) + (forward-line -1) + (helm-move--previous-multi-line-fn)) + (when (and helm-move-to-line-cycle-in-source + (helm-pos-header-line-p)) + (forward-line 1) + (helm-move--end-of-source) + ;; We are at end of helm-buffer + ;; check if last candidate is a multiline candidate + ;; and jump to it + (when (and (eobp) + (save-excursion (forward-line -1) (helm-pos-multiline-p))) + (helm-move--previous-multi-line-fn)))) + +(defun helm-move--next-multi-line-fn () + (let ((header-pos (helm-get-next-header-pos)) + (separator-pos (helm-get-next-candidate-separator-pos))) + (cond ((and separator-pos + (or (null header-pos) (< separator-pos header-pos))) + (goto-char separator-pos)) + (header-pos + (goto-char header-pos))))) + +(defun helm-move--next-line-fn () + (if (not (helm-pos-multiline-p)) + (forward-line 1) + (helm-move--next-multi-line-fn)) + (when (and helm-move-to-line-cycle-in-source + (or (save-excursion (and (helm-pos-multiline-p) + (goto-char (overlay-end + helm-selection-overlay)) + (helm-end-of-source-p t))) + (helm-end-of-source-p t))) + (helm-move--beginning-of-source) + (helm-display-source-at-screen-top-maybe 'source))) + +(defun helm-move--previous-page-fn () + (condition-case nil + (scroll-down helm-scroll-amount) + (beginning-of-buffer (goto-char (point-min))))) + +(defun helm-move--next-page-fn () + (condition-case nil + (scroll-up helm-scroll-amount) + (end-of-buffer (goto-char (point-max))))) + +(defun helm-move--beginning-of-buffer-fn () + (goto-char (point-min))) + +(defun helm-move--end-of-buffer-fn () + (goto-char (point-max))) + +(defun helm-move--end-of-source () + (helm-aif (helm-get-next-header-pos) + (progn (goto-char it) (forward-line -2)) + (goto-char (point-max)))) + +(defun helm-move--beginning-of-source () + (helm-aif (helm-get-previous-header-pos) + (progn (goto-char it) + (forward-line 1)) + (goto-char (point-min)))) + +(defun helm-move--previous-source-fn () + (forward-line -1) + (if (bobp) + (goto-char (point-max)) + (helm-skip-header-and-separator-line 'previous)) + (goto-char (helm-get-previous-header-pos)) + (forward-line 1)) + +(defun helm-move--next-source-fn () + (goto-char (or (and (not (save-excursion + (forward-line 1) (eobp))) + ;; Empty source at eob are just + ;; not displayed unless they are dummy. + ;; Bug#1117. + (helm-get-next-header-pos)) + (point-min)))) + +(defun helm-move--goto-source-fn (source-or-name) + (goto-char (point-min)) + (let ((name (if (stringp source-or-name) + source-or-name + (assoc-default 'name source-or-name)))) + (if (or (null name) (string= name "")) + (forward-line 1) + (condition-case err + (while (not (string= name (helm-current-line-contents))) + (goto-char (helm-get-next-header-pos))) + (error (helm-log "helm-move--goto-source-fn" "%S" err)))))) + +(defun helm-candidate-number-at-point () + (if helm-alive-p + (with-helm-buffer + (or (get-text-property (point) 'helm-cand-num) 1)) + (or (get-text-property (point) 'helm-cand-num) 1))) + +(defun helm--next-or-previous-line (direction &optional arg) + ;; Be sure to not use this in non--interactives calls. + (let ((helm-move-to-line-cycle-in-source + (and helm-move-to-line-cycle-in-source arg))) + (if (and arg (> arg 1)) + (cl-loop with pos = (helm-candidate-number-at-point) + with cand-num = (helm-get-candidate-number t) + with iter = (min arg (if (eq direction 'next) + (- cand-num pos) + (min arg (1- pos)))) + for count from 1 + while (<= count iter) + do + (helm-move-selection-common :where 'line :direction direction)) + (helm-move-selection-common :where 'line :direction direction)))) + +(defun helm-previous-line (&optional arg) + "Move selection to the ARG previous line(s). +Same behavior as `helm-next-line' when called with a numeric +prefix arg." + (interactive "p") + (with-helm-alive-p + (helm--next-or-previous-line 'previous arg))) +(put 'helm-previous-line 'helm-only t) + +(defun helm-next-line (&optional arg) + "Move selection to the next ARG line(s). +When numeric prefix arg is > than the number of candidates, then +move to the last candidate of current source (i.e. don't move to +next source)." + (interactive "p") + (with-helm-alive-p + (helm--next-or-previous-line 'next arg))) +(put 'helm-next-line 'helm-only t) + +(defun helm-scroll-up () + "Scroll up helm-buffer by `helm-scroll-amount' lines." + (interactive) + (with-helm-alive-p + (helm-move-selection-common :where 'page :direction 'previous))) +(put 'helm-scroll-up 'helm-only t) + +(defun helm-previous-page () + "Move selection back with a pageful." + (interactive) + (with-helm-alive-p + (let (helm-scroll-amount) + (helm-move-selection-common :where 'page :direction 'previous)))) +(put 'helm-previous-page 'helm-only t) + +(defun helm-scroll-down () + "Scroll down helm-buffer by `helm-scroll-amount' lines." + (interactive) + (with-helm-alive-p + (helm-move-selection-common :where 'page :direction 'next))) +(put 'helm-scroll-down 'helm-only t) + +(defun helm-next-page () + "Move selection forward with a pageful." + (interactive) + (with-helm-alive-p + (let (helm-scroll-amount) + (helm-move-selection-common :where 'page :direction 'next)))) +(put 'helm-next-page 'helm-only t) + +(defun helm-beginning-of-buffer () + "Move selection at the top." + (interactive) + (with-helm-alive-p + (helm-move-selection-common :where 'edge :direction 'previous))) +(put 'helm-beginning-of-buffer 'helm-only t) + +(defun helm-end-of-buffer () + "Move selection at the bottom." + (interactive) + (with-helm-alive-p + (helm-move-selection-common :where 'edge :direction 'next))) +(put 'helm-end-of-buffer 'helm-only t) + +(defun helm-previous-source () + "Move selection to the previous source." + (interactive) + (with-helm-alive-p + (helm-move-selection-common :where 'source :direction 'previous))) +(put 'helm-previous-source 'helm-only t) + +(defun helm-next-source () + "Move selection to the next source." + (interactive) + (with-helm-alive-p + (helm-move-selection-common :where 'source :direction 'next))) +(put 'helm-next-source 'helm-only t) + +(defun helm-goto-source (&optional source-or-name) + "Move the selection to the source named SOURCE-OR-NAME. + +If SOURCE-OR-NAME is empty string or nil go to the first +candidate of first source." + (helm-move-selection-common :where 'source :direction source-or-name)) + +(defvar helm-follow-action-white-list-commands + '(helm-ff-decrease-image-size-persistent + helm-ff-increase-image-size-persistent + helm-ff-rotate-left-persistent + helm-ff-rotate-right-persistent) + "Allow `helm-follow-action-forward/backward' switching to next file +when one of these commands is the `last-command'. + +For example when browsing files with `C-` and rotate the current file, +hitting `C-` again will not switch to next file but kill its buffer.") + +(defun helm--follow-action (arg) + (let ((helm--temp-follow-flag t) ; Needed in HFF. + (in-follow-mode (helm-follow-mode-p))) + ;; When follow-mode is already enabled, just go to next or + ;; previous line. + (when (or (eq last-command 'helm-follow-action-forward) + (eq last-command 'helm-follow-action-backward) + (eq last-command 'helm-execute-persistent-action) + (memq last-command helm-follow-action-white-list-commands) + in-follow-mode) + (if (> arg 0) + (helm-move-selection-common :where 'line + :direction 'next + :follow nil) + (helm-move-selection-common :where 'line + :direction 'previous + :follow nil))) + (unless in-follow-mode + (helm-execute-persistent-action)))) + +(defun helm-follow-action-forward () + "Go to next line and execute persistent action." + (interactive) + (with-helm-alive-p (helm--follow-action 1))) +(put 'helm-follow-action-forward 'helm-only t) + +(defun helm-follow-action-backward () + "Go to previous line and execute persistent action." + (interactive) + (with-helm-alive-p (helm--follow-action -1))) +(put 'helm-follow-action-backward 'helm-only t) + +(defun helm-mark-current-line (&optional resumep nomouse) + "Move `helm-selection-overlay' to current line. +When RESUMEP is non nil move overlay to `helm-selection-point'. +When NOMOUSE is specified do not set mouse bindings. + +Note that selection is unrelated to visible marks used for +marking candidates." + (with-helm-buffer + (when resumep + (goto-char helm-selection-point)) + (move-overlay + helm-selection-overlay (point-at-bol) + (if (helm-pos-multiline-p) + (let ((header-pos (helm-get-next-header-pos)) + (separator-pos (helm-get-next-candidate-separator-pos))) + (or (and (null header-pos) separator-pos) + (and header-pos separator-pos + (< separator-pos header-pos) + separator-pos) + header-pos + (point-max))) + (1+ (point-at-eol)))) + (setq helm-selection-point (overlay-start helm-selection-overlay)) + (when (and helm-allow-mouse (null nomouse)) + (helm--bind-mouse-for-selection helm-selection-point)))) + +(defun helm-confirm-and-exit-minibuffer () + "Maybe ask for confirmation when exiting helm. +It is similar to `minibuffer-complete-and-exit' adapted to Helm. +If `minibuffer-completion-confirm' value is \\='confirm, send +minibuffer confirm message and exit on next hit. If +`minibuffer-completion-confirm' value is t, don't exit and send +message \\='no match'." + (interactive) + (with-helm-alive-p + (if (and (helm--updating-p) + (null helm--reading-passwd-or-string)) + (progn (message "[Display not ready]") + (sit-for 0.5) (message nil) + (helm-update)) + (let* ((src (helm-get-current-source)) + (empty-buffer-p (with-current-buffer helm-buffer + (eq (point-min) (point-max)))) + (unknown (and (not empty-buffer-p) + (helm-aif (get-text-property + 0 'display + (helm-get-selection nil 'withprop src)) + (when (stringp it) + (string-match-p "\\`\\[\\?\\]" it)))))) + (cond ((and (or empty-buffer-p unknown) + (memq minibuffer-completion-confirm + '(confirm confirm-after-completion))) + (setq helm-minibuffer-confirm-state + 'confirm) + (setq minibuffer-completion-confirm nil) + (minibuffer-message " [confirm]")) + ;; When require-match is strict (i.e. `t'), buffer + ;; should be either empty or in read-file-name have an + ;; unknown candidate ([?] prefix), if it's not the case + ;; fix it in helm-mode but not here. + ((and (or empty-buffer-p unknown) + (eq minibuffer-completion-confirm t)) + (minibuffer-message " [No match]")) + (empty-buffer-p + ;; This is used when helm-buffer is totally empty, + ;; i.e. the [?] have not been added because must-match + ;; is used from outside helm-comp-read i.e. from a helm + ;; source built with :must-match. + (setq helm-saved-selection helm-pattern + helm-saved-action (helm-get-default-action + (assoc-default + 'action + (car (with-helm-buffer helm-sources)))) + helm-minibuffer-confirm-state nil) + (helm-exit-minibuffer)) + (t + (setq helm-minibuffer-confirm-state nil) + (helm-exit-minibuffer))))))) +(put 'helm-confirm-and-exit-minibuffer 'helm-only t) + +(defun helm-confirm-and-exit-hook () + "Restore `minibuffer-completion-confirm' when helm update." + (unless (or (eq minibuffer-completion-confirm t) + (not helm-minibuffer-confirm-state)) + (setq minibuffer-completion-confirm + helm-minibuffer-confirm-state))) +(add-hook 'helm-after-update-hook 'helm-confirm-and-exit-hook) + +(defun helm--set-minibuffer-completion-confirm (src) + (with-helm-buffer + (helm-aif (helm-get-attr 'must-match src) + (setq minibuffer-completion-confirm it)))) + +(defun helm-read-string (prompt &optional initial-input history + default-value inherit-input-method) + "Same as `read-string' but for reading string from a helm session." + (let ((helm--reading-passwd-or-string t)) + (read-string + prompt initial-input history default-value inherit-input-method))) + +(defun helm--updating-p () + ;; helm timer is between two cycles. + ;; IOW `helm-check-minibuffer-input' haven't yet compared input + ;; and `helm-pattern'. + (or (not (equal (minibuffer-contents) helm-pattern)) + ;; `helm-check-minibuffer-input' have launched `helm-update'. + helm--in-update)) + +(defun helm-maybe-exit-minibuffer () + (interactive) + (with-helm-alive-p + (if (and (helm--updating-p) + (null helm--reading-passwd-or-string)) + (progn + (message "[Display not ready]") + (sit-for 0.5) (message nil) + (helm-update)) + (helm-exit-minibuffer)))) +(put 'helm-maybe-exit-minibuffer 'helm-only t) + +(defun helm-exit-minibuffer () + "Select the current candidate by exiting the minibuffer." + (unless helm-current-prefix-arg + (setq helm-current-prefix-arg current-prefix-arg)) + (setq helm-exit-status 0) + (helm-log-run-hook "helm-exit-minibuffer" + 'helm-exit-minibuffer-hook) + (exit-minibuffer)) + +(defun helm-keyboard-quit () + "Quit minibuffer in helm. +If action buffer is displayed, kill it." + (interactive) + (with-helm-alive-p + (when (get-buffer-window helm-action-buffer 'visible) + (kill-buffer helm-action-buffer)) + (setq helm-exit-status 1) + (abort-recursive-edit))) +(put 'helm-keyboard-quit 'helm-only t) + +(defun helm-get-next-header-pos () + "Return the position of the next header from point." + (next-single-property-change (point) 'helm-header)) + +(defun helm-get-previous-header-pos () + "Return the position of the previous header from point." + (previous-single-property-change (point) 'helm-header)) + +(defun helm-pos-multiline-p () + "Return non-`nil' if the current position is in the multiline source region." + (get-text-property (point) 'helm-multiline)) + +(defun helm-get-next-candidate-separator-pos () + "Return the position of the next candidate separator from point." + (let ((hp (helm-get-next-header-pos))) + (helm-aif (next-single-property-change (point) 'helm-candidate-separator) + (or + ;; Be sure we don't catch + ;; the separator of next source. + (and hp (< it hp) it) + ;; The separator found is in next source + ;; we are at last cand, so use the header pos. + (and hp (< hp it) hp) + ;; A single source, just try next separator. + it)))) + +(defun helm-get-previous-candidate-separator-pos () + "Return the position of the previous candidate separator from point." + (previous-single-property-change (point) 'helm-candidate-separator)) + +(defun helm-pos-header-line-p () + "Return t if the current line is a header line." + (or (get-text-property (point-at-bol) 'helm-header) + (get-text-property (point-at-bol) 'helm-header-separator))) + +(defun helm-pos-candidate-separator-p () + "Return t if the current line is a candidate separator." + (get-text-property (point-at-bol) 'helm-candidate-separator)) + + +;;; Debugging +;; +;; +(defun helm-debug-output () + "Show all Helm-related variables at this time." + (interactive) + (with-helm-alive-p + (helm-help-internal " *Helm Debug*" 'helm-debug-output-function))) +(put 'helm-debug-output 'helm-only t) + +(defun helm-debug-output-function (&optional vars) + (message "Calculating all helm-related values...") + (insert "If you debug some variables or forms, set `helm-debug-variables' +to a list of forms.\n\n") + (dolist (v (or vars + helm-debug-variables + (apropos-internal "^helm-" 'boundp))) + (insert "** " + (pp-to-string v) "\n" + (pp-to-string (with-current-buffer helm-buffer (eval v))) "\n")) + (message "Calculating all helm-related values...Done")) + +(defun helm-enable-or-switch-to-debug () + "First hit enable helm debugging, second hit switch to debug buffer." + (interactive) + (with-helm-alive-p + (if helm-debug + (helm-run-after-exit + #'helm-debug-open-last-log) + (setq helm-debug t) + (with-helm-buffer (setq truncate-lines nil)) + (message "Debugging enabled")))) +(put 'helm-enable-or-switch-to-debug 'helm-only t) + + +;; Misc + +(defun helm-preselect (candidate-or-regexp &optional source) + "Move selection to CANDIDATE-OR-REGEXP on Helm start. + +CANDIDATE-OR-REGEXP can be a: + +- String +- Cons cell of two strings +- Nullary function, which moves to a candidate + +When CANDIDATE-OR-REGEXP is a cons cell, tries moving to first +element of the cons cell, then the second, and so on. This allows +selection of duplicate candidates after the first. + +Optional argument SOURCE is a Helm source object." + (with-helm-buffer + (when candidate-or-regexp + (if source + (helm-goto-source source) + (goto-char (point-min)) + (forward-line 1)) + (if (functionp candidate-or-regexp) + (funcall candidate-or-regexp) + (let ((start (point)) mp) + (helm-awhile (if (consp candidate-or-regexp) + (and (re-search-forward (car candidate-or-regexp) nil t) + (re-search-forward (cdr candidate-or-regexp) nil t)) + (re-search-forward candidate-or-regexp nil t)) + ;; If search fall on an header line continue loop + ;; until it match or fail (Bug#1509). + (unless (helm-pos-header-line-p) (cl-return (setq mp it)))) + (goto-char (or mp start))))) + (forward-line 0) ; Avoid scrolling right on long lines. + (when (helm-pos-multiline-p) + (helm-move--beginning-of-multiline-candidate)) + (when (helm-pos-header-line-p) (forward-line 1)) + (when helm-allow-mouse + (helm--mouse-reset-selection-help-echo)) + (helm-mark-current-line) + (helm-display-mode-line (or source (helm-get-current-source))) + (helm-log-run-hook "helm-preselect" 'helm-after-preselection-hook))) + +(defun helm-delete-current-selection () + "Delete the currently selected item." + (with-helm-window + (cond ((helm-pos-multiline-p) + (helm-aif (helm-get-next-candidate-separator-pos) + (delete-region (point-at-bol) + (1+ (progn (goto-char it) (point-at-eol)))) + ;; last candidate + (goto-char (helm-get-previous-candidate-separator-pos)) + (delete-region (point-at-bol) (point-max))) + (when (helm-end-of-source-p) + (goto-char (or (helm-get-previous-candidate-separator-pos) + (point-min))) + (forward-line 1))) + (t + (delete-region (point-at-bol) (1+ (point-at-eol))) + (when (helm-end-of-source-p t) + (let ((headp (save-excursion + (forward-line -1) + (not (helm-pos-header-line-p))))) + (and headp (forward-line -1)))))) + (unless (helm-end-of-source-p t) + (helm-mark-current-line)))) + +(defun helm-end-of-source-1 (n at-point) + (save-excursion + (if (and (helm-pos-multiline-p) (null at-point)) + (null (helm-get-next-candidate-separator-pos)) + (forward-line (if at-point 0 n)) + (or (eq (point-at-bol) (point-at-eol)) + (helm-pos-header-line-p) + (if (< n 0) (bobp) (eobp)))))) + +(defun helm-end-of-source-p (&optional at-point) + "Return non-nil if we are at EOB or end of source." + (helm-end-of-source-1 1 at-point)) + +(defun helm-beginning-of-source-p (&optional at-point) + "Return non-nil if we are at BOB or beginning of source." + (helm-end-of-source-1 -1 at-point)) + +(defun helm--edit-current-selection-internal (func) + (with-helm-window + (forward-line 0) + (let ((realvalue (get-text-property (point) 'helm-realvalue)) + (multiline (get-text-property (point) 'helm-multiline))) + (funcall func) + (forward-line 0) + (and realvalue + (put-text-property (point) (point-at-eol) + 'helm-realvalue realvalue)) + (and multiline + (put-text-property (point) + (or (helm-get-next-candidate-separator-pos) + (point-max)) + 'helm-multiline multiline)) + (helm-mark-current-line)))) + +(defmacro helm-edit-current-selection (&rest forms) + "Evaluate FORMS at current selection in the helm buffer. +Used generally to modify current selection." + (declare (indent 0) (debug t)) + `(helm--edit-current-selection-internal + (lambda () ,@forms))) + +(defun helm--delete-minibuffer-contents-from (from-str) + ;; Giving an empty string value to FROM-STR delete all. + (let ((input (minibuffer-contents))) + (helm-reset-yank-point) + (if (> (length input) 0) + ;; minibuffer is not empty, delete contents from end + ;; of FROM-STR and update. + (helm-set-pattern from-str) + ;; minibuffer is already empty, force update. + (helm-force-update)))) + +(defun helm-delete-minibuffer-contents (&optional arg) + "Delete minibuffer contents. +When `helm-delete-minibuffer-contents-from-point' is non-nil, +delete minibuffer contents from point instead of deleting all. +With a prefix arg reverse this behaviour. When at the end of +minibuffer, delete all." + (interactive "P") + (with-helm-alive-p + (let ((str (if helm-delete-minibuffer-contents-from-point + (if (or arg (eobp)) + "" (helm-minibuffer-completion-contents)) + (if (and arg (not (eobp))) + (helm-minibuffer-completion-contents) "")))) + (helm--delete-minibuffer-contents-from str)))) +(put 'helm-delete-minibuffer-contents 'no-helm-mx t) + + +;;; helm-source-in-buffer. +;; +(defun helm-candidates-in-buffer (&optional source) + "The top level function used to store candidates with `helm-source-in-buffer'. + +Candidates are stored in a buffer generated internally by +`helm-candidate-buffer' function. Each candidate must be placed +in one line. + +The buffer is created and fed in the init attribute function of +Helm. + +E.g.: + + (helm-build-in-buffer-source \"test\" + :init (lambda () + (helm-init-candidates-in-buffer + \\='global \\='(foo foa fob bar baz)))) + +A shortcut can be used to simplify: + + (helm-build-in-buffer-source \"test\" + :data \\='(foo foa fob bar baz)) + +By default, Helm makes candidates by evaluating the candidates +function, then narrows them by `string-match' for each candidate. + +But this is slow for large number of candidates. The new way is +to store all candidates in a buffer and then narrow with +`re-search-forward'. Search function is customizable by search +attribute. The important point is that buffer processing is MUCH +FASTER than string list processing and is the Emacs way. + +The init function writes all candidates to a newly-created +candidate buffer. The candidates buffer is created or specified +by `helm-candidate-buffer'. Candidates are stored in a line. + +The candidates function narrows all candidates, IOW creates a +subset of candidates dynamically. + +Class `helm-source-in-buffer' is implemented with three attributes: + + (candidates . helm-candidates-in-buffer) + (volatile) + (match identity) + +The volatile attribute is needed because +`helm-candidates-in-buffer' creates candidates dynamically and +need to be called every time `helm-pattern' changes. + +Because `helm-candidates-in-buffer' plays the role of `match' +attribute function, specifying `(match identity)' makes the +source slightly faster. + +However if source contains `match-part' attribute, match is +computed only on part of candidate returned by the call of +function provided by this attribute. The function should have one +arg, candidate, and return only a specific part of candidate. + +To customize `helm-candidates-in-buffer' behaviour, use `search', +`get-line' and `match-part' attributes." + (let ((src (or source (helm-get-current-source)))) + (helm-candidates-in-buffer-1 + (helm-candidate-buffer) + helm-pattern + (or (assoc-default 'get-line src) + #'buffer-substring-no-properties) + (or (assoc-default 'search src) + '(helm-candidates-in-buffer-search-default-fn)) + (helm-candidate-number-limit src) + (helm-get-attr 'match-part) + src))) + +(defun helm-candidates-in-buffer-search-default-fn (pattern) + "Search PATTERN with `re-search-forward' with bound and noerror args." + (condition-case _err + (re-search-forward pattern nil t) + (invalid-regexp nil))) + +(defun helm-candidates-in-buffer-1 (buffer pattern get-line-fn + search-fns limit + match-part-fn source) + "Return the list of candidates inserted in BUFFER matching PATTERN." + ;; buffer == nil when candidates buffer does not exist. + (when buffer + (with-current-buffer buffer + (let ((inhibit-point-motion-hooks t) + (start-point (1- (point-min)))) + (goto-char start-point) + (if (string= pattern "") + (helm-initial-candidates-from-candidate-buffer + get-line-fn limit) + (helm-search-from-candidate-buffer + pattern get-line-fn search-fns limit + start-point match-part-fn source)))))) + + +(defun helm-search-from-candidate-buffer (pattern get-line-fn search-fns + limit start-point match-part-fn source) + (let ((inhibit-read-only t) + (diacritics (assoc-default 'diacritics source))) + (helm--search-from-candidate-buffer-1 + (lambda () + (cl-loop with hash = (make-hash-table :test 'equal) + with allow-dups = (assq 'allow-dups source) + with case-fold-search = (helm-set-case-fold-search) + with count = 0 + for iter from 1 + for searcher in search-fns + do (progn + (goto-char start-point) + ;; The character at start-point is a newline, + ;; if pattern match it that's mean we are + ;; searching for newline in buffer, in this + ;; case skip this false line. + ;; See comment >>>[1] in + ;; `helm--search-from-candidate-buffer-1'. + (and (condition-case nil + (looking-at pattern) + (invalid-regexp nil)) + (forward-line 1))) + nconc + (cl-loop with pos-lst + ;; POS-LST is used as a flag to decide if we + ;; run `helm-search-match-part' even if + ;; MATCH-PART isn't specified on source. This + ;; happen when fuzzy matching or using a + ;; negation (!) in one of the patterns, in + ;; these case the searcher returns a list + ;; '(BEG END) instead of an integer like + ;; `re-search-forward'. + while (and (setq pos-lst (funcall searcher pattern)) + (not (eobp)) + (< count limit)) + for cand = (apply get-line-fn + (if (and pos-lst (listp pos-lst)) + pos-lst + (list (point-at-bol) (point-at-eol)))) + when (and match-part-fn + (not (get-text-property 0 'match-part cand))) + do (setq cand + (propertize cand 'match-part (funcall match-part-fn cand))) + for dup = (gethash cand hash) + when (and (or (and allow-dups dup (= dup iter)) + (null dup)) + (or + ;; Always collect when cand is matched + ;; by searcher funcs and match-part attr + ;; is not present. + (and (not match-part-fn) + (not (consp pos-lst))) + ;; If match-part attr is present, or if SEARCHER fn + ;; returns a cons cell, collect PATTERN only if it + ;; match the part of CAND specified by + ;; the match-part func. + (helm-search-match-part cand pattern diacritics))) + do (progn + (puthash cand iter hash) + (helm--maybe-process-filter-one-by-one-candidate cand source) + (cl-incf count)) + and collect cand)))))) + +(defun helm-search-match-part (candidate pattern diacritics) + "Match PATTERN only on match-part property value of CANDIDATE. + +Because `helm-search-match-part' may be called even if +unspecified in source (negation or fuzzy), the part to match +falls back to the whole candidate even if match-part hasn't been +computed by match-part-fn and stored in the match-part property." + (let ((part (or (get-text-property 0 'match-part candidate) + candidate)) + (fuzzy-regexp (cadr (gethash 'helm-pattern helm--fuzzy-regexp-cache))) + (matchfn (cond (helm-migemo-mode 'helm-mm-migemo-string-match) + (diacritics 'helm-mm-diacritics-string-match) + (t 'string-match)))) + (condition-case _err + (if (string-match " " pattern) + (cl-loop for i in (helm-mm-split-pattern pattern) always + (if (string-match "\\`!" i) + (not (funcall matchfn (substring i 1) part)) + (funcall matchfn i part))) + (if (string-match "\\`!" pattern) + (if helm--in-fuzzy + ;; Fuzzy regexp have already been + ;; computed with substring 1. + (not (string-match fuzzy-regexp part)) + (not (funcall matchfn (substring pattern 1) part))) + (funcall matchfn (if helm--in-fuzzy fuzzy-regexp pattern) part))) + (invalid-regexp nil)))) + +(defun helm-initial-candidates-from-candidate-buffer (get-line-fn limit) + (cl-loop repeat limit + until (eobp) + for line = (funcall get-line-fn (point-at-bol) (point-at-eol)) + when line collect line + do (forward-line 1))) + +(defun helm--search-from-candidate-buffer-1 (search-fn) + ;; We are adding a newline at bob and at eol + ;; and removing these newlines afterward. + ;; This is a bad hack that should be removed. + ;; To avoid matching the empty line at first line + ;; when searching with e.g occur and "^$" just + ;; forward-line before searching (See >>>[1] above). + (goto-char (point-min)) + (insert "\n") + (goto-char (point-max)) + (insert "\n") + (unwind-protect + (funcall search-fn) + (goto-char (point-min)) + (delete-char 1) + (goto-char (1- (point-max))) + (delete-char 1) + (set-buffer-modified-p nil))) + +(defun helm-candidate-buffer (&optional buffer-spec) + "Register and return a buffer storing candidates of current source. + +This is used to initialize a buffer for storing candidates for a +candidates-in-buffer source, candidates will be searched in this +buffer and displayed in `helm-buffer'. This should be used only +in init functions, don't relay on this in other places unless you +know what you are doing. + +This function is still in public API only for backward +compatibility, you should use instead +`helm-init-candidates-in-buffer' for initializing your sources. + +Internally, this function is called without argument and returns +the buffer corresponding to current source i.e. +`helm--source-name' which is available in only some places. + +Acceptable values of BUFFER-SPEC: + +- global (a symbol) + Create a new global candidates buffer, + named \" *helm candidates:SOURCE*\". + This is used by `helm-init-candidates-in-buffer' and it is + the most common usage of BUFFER-SPEC. + The buffer will be killed and recreated at each new + helm-session. + +- local (a symbol) + Create a new local candidates buffer, + named \" *helm candidates:SOURCE*HELM-CURRENT-BUFFER\". + You may want to use this when you want to have a different + buffer each time source is used from a different + `helm-current-buffer'. + The buffer is erased and refilled at each new session but not + killed. You probably don't want to use this value for + BUFFER-SPEC. + +- nil (omit) + Only return the candidates buffer of current source if found. + +- A buffer + Register a buffer as a candidates buffer. + The buffer needs to exists, it is not created. + This allow you to use the buffer as a cache, it is faster + because the buffer is already drawn, but be careful when using + this as you may mangle your buffer depending on what you write + in your init(s) function, IOW don't modify the contents of the + buffer in init(s) function but in a transformer. + The buffer is not erased nor deleted. + Generally it is safer to use a copy of buffer inserted + in a global or local buffer. + +If for some reasons a global buffer and a local buffer exist and +are belonging to the same source, the local buffer takes +precedence on the global one and is used instead. + +When forcing update only the global and local buffers are killed +before running again the init function." + (let ((global-bname (format " *helm candidates:%s*" + helm--source-name)) + (local-bname (format " *helm candidates:%s*%s" + helm--source-name + (buffer-name helm-current-buffer)))) + (when buffer-spec + ;; Register buffer in `helm--candidate-buffer-alist'. + ;; This is used only to retrieve buffer associated to current source + ;; when using named buffer as value of BUFFER-SPEC. + (setq helm--candidate-buffer-alist + (cons (cons helm--source-name buffer-spec) + (delete (assoc helm--source-name + helm--candidate-buffer-alist) + helm--candidate-buffer-alist))) + ;; When using global or local as value of BUFFER-SPEC + ;; create the buffer global-bname or local-bname, otherwise + ;; reuse the buffer named BUFFER-SPEC. + (unless (bufferp buffer-spec) + ;; Global buffers are killed and recreated. + (and (eq buffer-spec 'global) + (buffer-live-p (get-buffer global-bname)) + (kill-buffer global-bname)) + ;; Create global or local buffer. + ;; Local buffer, once created are reused and a new one + ;; is created when `helm-current-buffer' change across sessions. + (with-current-buffer (get-buffer-create + (helm-acase buffer-spec + (global global-bname) + (local local-bname) + (t (and (stringp buffer-spec) + buffer-spec)))) + ;; We need a buffer not read-only to perhaps insert later + ;; text coming from read-only buffers (Bug#1176). + (set (make-local-variable 'buffer-read-only) nil) + ;; Undo is automatically disabled in buffer names starting + ;; with a space, so no need to disable it. + (erase-buffer) + (font-lock-mode -1)))) + ;; Finally return the candidates buffer. + (helm-acond ((get-buffer local-bname)) + ((get-buffer global-bname)) + ((assoc-default helm--source-name helm--candidate-buffer-alist) + (and (or (stringp it) (bufferp it)) + (buffer-live-p (get-buffer it)) + it))))) + +(defvar helm-candidate-buffer-longest-len 0 + "May store the longest length of candidates in a in-buffer source. +It is a local variable set from `helm-init-candidates-in-buffer' in +`helm-candidate-buffer'. +Allow getting the longest length of initial candidates in transformers +without looping again through the whole list.") + +(defun helm-init-candidates-in-buffer (buffer-spec data) + "Register BUFFER-SPEC with DATA for a helm candidates-in-buffer session. + +Arg BUFFER-SPEC can be a `buffer-name' (stringp), a buffer-spec +object (bufferp), or a symbol, either \\='local or \\='global which is +passed to `helm-candidate-buffer'. +The most common usage of BUFFER-SPEC is \\='global. + +Arg DATA can be either a list or a plain string. +Returns the resulting buffer. + +Use this in your init function to register a buffer for a +`helm-source-in-buffer' session and feed it with DATA. You +probably don't want to bother with this and use the :data slot +when initializing a source with `helm-source-in-buffer' class." + (declare (indent 1)) + (let ((caching (and (or (stringp buffer-spec) + (bufferp buffer-spec)) + (buffer-live-p (get-buffer buffer-spec)))) + (buf (helm-candidate-buffer buffer-spec))) + (unless caching + (with-current-buffer buf + (erase-buffer) + (cond ((listp data) + (insert (mapconcat (lambda (i) + (let ((cand (cond ((symbolp i) (symbol-name i)) + ((numberp i) (number-to-string i)) + (t i)))) + (setq-local helm-candidate-buffer-longest-len + (max helm-candidate-buffer-longest-len + (length cand))) + cand)) + data "\n"))) + ((stringp data) (insert data)))) + buf))) + + +;;; Resplit helm window +;; +;; +(defun helm-toggle-resplit-window () + "Toggle resplit helm window, vertically or horizontally." + (interactive) + (with-helm-alive-p + (if (and (= (length (window-list nil 1)) 2) + (not (window-dedicated-p + (get-buffer-window helm-current-buffer)))) + (progn + (when helm-prevent-escaping-from-minibuffer + (helm-prevent-switching-other-window :enabled nil)) + (unwind-protect + (with-helm-window + (cond ((or helm-full-frame (one-window-p t)) + (user-error "Attempt to resplit a single window")) + ((helm-action-window) + (user-error "Can't resplit while selecting actions")) + (t + (let ((before-height (window-height))) + (delete-window) + (set-window-buffer + (select-window + (if (= (window-height) before-height) ; initial split was horizontal. + ;; Split window vertically with `helm-buffer' placed + ;; on the good side according to actual value of + ;; `helm-split-window-default-side'. + (prog1 + (cond ((or (eq helm-split-window-default-side 'above) + (eq helm-split-window-default-side 'left)) + (split-window + (selected-window) nil 'above)) + (t (split-window-vertically))) + (setq helm-split-window-state 'vertical)) + ;; Split window vertically, same comment as above. + (setq helm-split-window-state 'horizontal) + (cond ((or (eq helm-split-window-default-side 'left) + (eq helm-split-window-default-side 'above)) + (split-window (selected-window) nil 'left)) + (t (split-window-horizontally))))) + helm-buffer)))) + (setq helm--window-side-state (helm--get-window-side-state))) + (when helm-prevent-escaping-from-minibuffer + (helm-prevent-switching-other-window :enabled t)))) + (error "current window configuration not suitable for splitting")))) +(put 'helm-toggle-resplit-window 'helm-only t) + +;; Utility: Resize helm window. +(defun helm-enlarge-window-1 (n) + "Enlarge or narrow helm window. +If N is positive enlarge, if negative narrow." + (unless helm-full-frame + (let ((horizontal-p (eq helm-split-window-state 'horizontal))) + (with-helm-window + (enlarge-window n horizontal-p))))) + +(defun helm-narrow-window () + "Narrow helm window." + (interactive) + (with-helm-alive-p + (helm-enlarge-window-1 -1))) +(put 'helm-narrow-window 'helm-only t) + +(defun helm-enlarge-window () + "Enlarge helm window." + (interactive) + (with-helm-alive-p + (helm-enlarge-window-1 1))) +(put 'helm-enlarge-window 'helm-only t) + +(defun helm-toggle-full-frame (&optional arg) + "Toggle `helm-buffer' full-frame view." + (interactive "p") + (cl-assert (null (helm-action-window)) + nil "Unable to toggle full frame from action window") + (when arg ; Called interactively + (cl-assert (null helm--buffer-in-new-frame-p) + nil "Can't toggle full frame when using helm own frame")) + (if (or helm-onewindow-p + (buffer-local-value 'helm-full-frame (get-buffer helm-buffer))) + (with-helm-window + (setq-local helm-full-frame nil) + (setq helm-onewindow-p nil) + (let ((split-window-preferred-function + helm-split-window-preferred-function)) + (switch-to-buffer helm-current-buffer) + (helm-display-buffer helm-buffer) + (select-window (minibuffer-window)))) + (with-helm-window + (delete-other-windows) + (setq-local helm-full-frame t) + (setq helm-onewindow-p t)))) +(put 'helm-toggle-full-frame 'helm-only t) + +(defun helm-swap-windows () + "Swap window holding `helm-buffer' with other window." + (interactive) + (with-helm-alive-p + (if (= (length (window-list nil 1)) 2) + (cond ((and helm-full-frame (one-window-p t)) + (user-error "Can't swap windows in a single window")) + ((helm-action-window) + (user-error "Can't resplit while selecting actions")) + (t + (let* ((w1 (helm-window)) + (split-state (eq helm-split-window-state 'horizontal)) + (w1size (window-total-size w1 split-state)) + (b1 (window-buffer w1)) ; helm-buffer + (s1 (window-start w1)) + (cur-frame (window-frame w1)) + (w2 (with-selected-window (helm-window) + ;; Don't try to display helm-buffer + ;; in a dedicated window. + (get-window-with-predicate + (lambda (w) (not (window-dedicated-p w))) + 1 cur-frame))) + (w2size (window-total-size w2 split-state)) + (b2 (window-buffer w2)) ; probably helm-current-buffer + (s2 (window-start w2)) + resize) + (with-selected-frame (window-frame w1) + (helm-replace-buffer-in-window w1 b1 b2) + (helm-replace-buffer-in-window w2 b2 b1) + (setq resize + (cond ( ;; helm-window is smaller than other window. + (< w1size w2size) + (- (- (max w2size w1size) + (min w2size w1size)))) + ( ;; helm-window is larger than other window. + (> w1size w2size) + (- (max w2size w1size) + (min w2size w1size))) + ( ;; windows have probably same size. + t nil))) + ;; Maybe resize the window holding helm-buffer. + (and resize (window-resize w2 resize split-state)) + (set-window-start w1 s2 t) + (set-window-start w2 s1 t)) + (setq helm--window-side-state (helm--get-window-side-state))))) + (error "current window configuration not suitable for splitting")))) +(put 'helm-swap-windows 'helm-only t) + +(defun helm--get-window-side-state () + "Return the position of `helm-window' from `helm-current-buffer'. +Possible values are \\='left \\='right \\='below or \\='above." + (let ((side-list '(left right below above))) + (cl-loop for side in side-list + thereis (and (equal (helm-window) + (window-in-direction + side (get-buffer-window helm-current-buffer t) + t)) + side)))) + +(defun helm-replace-buffer-in-window (window buffer1 buffer2) + "Replace BUFFER1 by BUFFER2 in WINDOW registering BUFFER1." + (when (get-buffer-window buffer1) + (unrecord-window-buffer window buffer1) + (set-window-buffer window buffer2))) + +;; Utility: select another action by key +(defun helm-select-nth-action (n) + "Select the N nth action for the currently selected candidate." + (let ((src (helm-get-current-source))) + (setq helm-saved-selection (helm-get-selection nil nil src)) + (unless helm-saved-selection + (error "Nothing is selected")) + (setq helm-saved-action + (helm-get-nth-action + n + (if (get-buffer-window helm-action-buffer 'visible) + (assoc-default 'candidates src) + (helm-get-actions-from-current-source src)))) + (helm-maybe-exit-minibuffer))) + +(defun helm-get-nth-action (n action) + (cond ((and (zerop n) (functionp action)) + action) + ((listp action) + (or (cdr (elt action n)) + (error "No such action"))) + ((and (functionp action) (< 0 n)) + (error "Sole action")) + (t + (error "Error in `helm-select-nth-action'")))) + +(defun helm-execute-selection-action-at-nth (linum) + "Execute default action on candidate at LINUM lines from selection." + (let ((prefarg current-prefix-arg)) + (if (>= linum 0) + (helm-next-line linum) + (helm-previous-line (lognot (1- linum)))) + (setq current-prefix-arg prefarg) + (helm-exit-minibuffer))) + +;;; Persistent Action +;; +(defun helm-initialize-persistent-action () + (set (make-local-variable 'helm-persistent-action-display-window) nil)) + +(cl-defun helm-execute-persistent-action (&optional attr split) + "Perform the associated action ATTR without quitting helm. + +Arg ATTR default will be `persistent-action' or +`persistent-action-if' if unspecified depending on what's found +in source, but it can be anything else. +In this case you have to add this new attribute to your source. +See `persistent-action' and `persistent-action-if' slot +documentation in `helm-source'. + +When `helm-full-frame' is non-nil, and `helm-buffer' is displayed +in only one window, the helm window is split to display +`helm-select-persistent-action-window' in other window to +maintain visibility. The argument SPLIT can be used to force +splitting inconditionally, it is unused actually." + (interactive) + (with-helm-alive-p + (let ((source (helm-get-current-source))) + (unless attr + (setq attr (or (car (assq 'persistent-action source)) + (car (assq 'persistent-action-if source))))) + (helm-log "helm-execute-persistent-action" "executing persistent-action") + (let* ((selection (and source (helm-get-selection nil nil source))) + (attr-val (if (eq attr 'persistent-action-if) + (funcall (assoc-default attr source) selection) + (assoc-default attr source))) + ;; If attr value is a cons, use its car as persistent function. + (fn (if (and (consp attr-val) + ;; maybe a lambda. + (not (functionp attr-val))) + (car attr-val) attr-val)) + ;; And its cdr to decide if helm window should be splitted. + (no-split (and (consp attr-val) + (not (functionp attr-val)) + (cdr attr-val))) + ;; Is next-window (from helm-window) a suitable window for PA? + (no-suitable-win + (helm-aand (not helm--buffer-in-new-frame-p) + (get-buffer-window helm-current-buffer) + (or (window-dedicated-p it) + (window-parameter it 'window-side)))) + (cursor-in-echo-area t) + mode-line-in-non-selected-windows) + (progn + (when (and helm-onewindow-p (null no-split) + (null helm--buffer-in-new-frame-p)) + (helm-toggle-full-frame)) + (when (eq fn 'ignore) + (cl-return-from helm-execute-persistent-action nil)) + (when source + (with-helm-window + (save-selected-window + ;; FIXME: Simplify SPLIT behavior, it is a mess actually. + (if no-split + (helm-select-persistent-action-window :split 'never) + (helm-select-persistent-action-window + :split (or split helm-onewindow-p no-suitable-win))) + (helm-log "helm-execute-persistent-action" + "current-buffer = %S" (current-buffer)) + (let ((helm-in-persistent-action t) + (display-buffer-alist '((".*" (display-buffer-same-window)))) + display-buffer-function pop-up-windows pop-up-frames + special-display-regexps special-display-buffer-names) + (helm-execute-selection-action-1 + selection (or fn (helm-get-actions-from-current-source source)) t) + (unless (helm-action-window) + (helm-log-run-hook "helm-execute-persistent-action" + 'helm-after-persistent-action-hook))) + ;; A typical case is when a persistent action delete + ;; the buffer already displayed in + ;; `helm-persistent-action-display-window' and `helm-full-frame' + ;; is enabled, we end up with the `helm-buffer' + ;; displayed in two windows. + (when (and helm-onewindow-p + (> (length (window-list)) 1) + (equal (buffer-name + (window-buffer + helm-persistent-action-display-window)) + (helm-buffer-get))) + (delete-other-windows)))))))))) +(put 'helm-execute-persistent-action 'helm-only t) + +(cl-defun helm-persistent-action-display-window (&key split) + "Return the window that will be used for persistent action. +If SPLIT is t window is split in persistent action, if it has the +special symbol `never' don't split, if it is nil don't split either. +The symbol `never' is kept for backward compatibility." + (with-helm-window + (setq helm-persistent-action-display-window + (cond ((and (window-live-p helm-persistent-action-display-window) + (not (member helm-persistent-action-display-window + (get-buffer-window-list helm-buffer)))) + helm-persistent-action-display-window) + ((and helm--buffer-in-new-frame-p helm-initial-frame) + (with-selected-frame helm-initial-frame + (let ((win (selected-window))) + (if (or (window-dedicated-p win) + (window-parameter win 'window-side)) + (next-window win 1) + win)))) + ((and split (not (eq split 'never))) + (split-window)) + ((get-buffer-window helm-current-buffer)) + (t (previous-window (selected-window) 1)))))) + +(cl-defun helm-select-persistent-action-window (&key split) + "Select the window that will be used for persistent action. +See `helm-persistent-action-display-window' for how to use SPLIT." + (select-window (get-buffer-window (helm-buffer-get))) + (prog1 + (select-window + (setq minibuffer-scroll-window + (helm-persistent-action-display-window :split split))) + (helm-log "helm-select-persistent-action-window" + "Selected window is %S" minibuffer-scroll-window))) + +;;; Scrolling - recentering +;; +;; +(defun helm-other-window-base (command &optional arg) + (let ((minibuffer-scroll-window + (helm-persistent-action-display-window))) + (funcall command (or arg helm-scroll-amount)))) + +(defun helm-scroll-other-window (&optional arg) + "Scroll other window upward ARG many lines. +When arg is not provided scroll `helm-scroll-amount' lines. +See `scroll-other-window'." + (interactive "P") + (with-helm-alive-p (helm-other-window-base 'scroll-other-window arg))) +(put 'helm-scroll-other-window 'helm-only t) + +(defun helm-scroll-other-window-down (&optional arg) + "Scroll other window downward ARG many lines. +When arg is not provided scroll `helm-scroll-amount' lines. +See `scroll-other-window-down'." + (interactive "P") + (with-helm-alive-p (helm-other-window-base 'scroll-other-window-down arg))) +(put 'helm-scroll-other-window-down 'helm-only t) + +(defun helm-recenter-top-bottom-other-window (&optional arg) + "Run `recenter-top-bottom' in other window. +Meaning of prefix ARG is the same as in `recenter-top-bottom'." + (interactive "P") + (with-helm-alive-p + (with-helm-window + (with-selected-window (helm-persistent-action-display-window) + (recenter-top-bottom arg))))) +(put 'helm-recenter-top-bottom-other-window 'helm-only t) + +(defun helm-reposition-window-other-window (&optional arg) + "Run `reposition-window' in other window. +Meaning of prefix ARG is the same as in `reposition-window'." + (interactive "P") + (with-helm-alive-p + (with-helm-window + (with-selected-window (helm-persistent-action-display-window) + (reposition-window arg))))) +(put 'helm-reposition-window-other-window 'helm-only t) + + +;; Utility: Visible Mark + +(defun helm-clear-visible-mark () + (with-current-buffer (helm-buffer-get) + (mapc 'delete-overlay helm-visible-mark-overlays) + (set (make-local-variable 'helm-visible-mark-overlays) nil))) + +(defun helm-this-visible-mark () + (cl-loop for o in (overlays-at (point)) + when (overlay-get o 'visible-mark) + return o)) + +(defun helm-delete-visible-mark (overlay) + (let ((src (helm-get-current-source))) + (setq helm-marked-candidates + (remove + (cons src (helm-get-selection nil nil src)) + helm-marked-candidates)) + (delete-overlay overlay) + (setq helm-visible-mark-overlays + (delq overlay helm-visible-mark-overlays)))) + +(defun helm-make-visible-mark (&optional src selection) + (let* ((source (or src (helm-get-current-source))) + (sel (or selection (helm-get-selection + nil (helm-get-attr 'marked-with-props source) + source))) + (selection-end (if (helm-pos-multiline-p) + ;; Stays within source + (or (helm-get-next-candidate-separator-pos) + (helm-get-next-header-pos) + (point-max)) + ;; Not multiline + (1+ (point-at-eol)))) + (o (make-overlay (point-at-bol) selection-end))) + (overlay-put o 'priority 0) + (overlay-put o 'face 'helm-visible-mark) + (overlay-put o 'source source) + (overlay-put o 'string (buffer-substring (overlay-start o) (overlay-end o))) + (overlay-put o 'real sel) + (overlay-put o 'before-string (propertize " " 'display + `((margin left-margin) + ,(propertize + helm-visible-mark-prefix + 'face 'helm-mark-prefix)))) + (overlay-put o 'visible-mark t) + (overlay-put o 'evaporate t) + (cl-pushnew o helm-visible-mark-overlays) + (push (cons source sel) helm-marked-candidates))) + +(defun helm-toggle-visible-mark (arg) + "Toggle Helm visible mark at point ARG times. +If ARG is negative toggle backward." + (interactive "p") + (with-helm-alive-p + (with-helm-window + (let ((nomark (assq 'nomark (helm-get-current-source))) + (next-fns (if (< arg 0) + '(helm-beginning-of-source-p . helm-previous-line) + '(helm-end-of-source-p . helm-next-line)))) + (if nomark + (message "Marking not allowed in this source") + (cl-loop with n = (if (< arg 0) (* arg -1) arg) + repeat n do + (progn + (helm-aif (helm-this-visible-mark) + (helm-delete-visible-mark it) + (helm-make-visible-mark)) + (if (funcall (car next-fns)) + (progn + (helm-display-mode-line (helm-get-current-source)) + (cl-return nil)) + (funcall (cdr next-fns))))) + (set-window-margins (selected-window) + (if helm-visible-mark-overlays + (+ (string-width helm-visible-mark-prefix) + helm-left-margin-width) + helm-left-margin-width))))))) +(put 'helm-toggle-visible-mark 'helm-only t) + +(defun helm-toggle-visible-mark-forward () + (interactive) + (helm-toggle-visible-mark 1)) + +(defun helm-toggle-visible-mark-backward () + (interactive) + (helm-toggle-visible-mark -1)) + +(defun helm-file-completion-source-p (&optional source) + "Return non-nil if current source is a file completion source." + (or helm--completing-file-name ; helm-read-file-name + (let ((cur-source (cdr (assq 'name + (or source (helm-get-current-source)))))) + (cl-loop for i in helm--file-completion-sources + thereis (string= cur-source i))))) + +(defun helm-mark-all (&optional all) + "Mark all visible unmarked candidates in current source. + +With a prefix arg mark all visible unmarked candidates in all +sources." + (interactive "P") + (with-helm-alive-p + (with-helm-window ; Using `with-helm-buffer' for some unknow + ; reasons infloop. + (set-window-margins (selected-window) + (+ (string-width helm-visible-mark-prefix) + helm-left-margin-width)) + (if (null all) + (helm-mark-all-1 t) + (let ((pos (point))) + (goto-char (point-min)) + (helm-awhile (helm-get-next-header-pos) + (goto-char it) + (forward-line 1) + (helm-mark-current-line) + (helm-mark-all-1)) + ;; `save-excursion' seems confused if used in addition of + ;; the one used in `helm-mark-all-1', so save POS and back + ;; to it when loop is finished. + (goto-char pos) + (helm-mark-current-line) + (helm-display-mode-line (helm-get-current-source) t)))))) +(put 'helm-mark-all 'helm-only t) + +(defun helm-mark-all-1 (&optional ensure-beg-of-source) + "Mark all visible unmarked candidates in current source. +Need to be wrapped in `with-helm-window'. +Arg ENSURE-BEG-OF-SOURCE ensure we are at beginning of source +when starting to mark candidates, if handled elsewhere before +starting it is not needed." + (let* ((src (helm-get-current-source)) + (follow (if (helm-follow-mode-p src) 1 -1)) + (nomark (assq 'nomark src)) + (src-name (assoc-default 'name src)) + (filecomp-p (or (helm-file-completion-source-p src) + (string= src-name "Files from Current Directory")))) + ;; Note that `cl-letf' prevents edebug working properly. + (cl-letf (((symbol-function 'message) #'ignore)) + (helm-follow-mode -1) + (unwind-protect + (if nomark + (user-error "Marking not allowed in this source") + (save-excursion + (when ensure-beg-of-source + (goto-char (helm-get-previous-header-pos)) + (forward-line 1)) + (let* ((next-head (helm-get-next-header-pos)) + (end (and next-head + (save-excursion + (goto-char next-head) + (forward-line -1) + (point)))) + (maxpoint (or end (point-max)))) + (while (< (point) maxpoint) + (helm-mark-current-line) + (let* ((prefix (get-text-property (point-at-bol) 'display)) + (cand (helm-get-selection + nil (helm-get-attr 'marked-with-props src) + src)) + (bn (and filecomp-p (helm-basename cand)))) + ;; Don't mark possibles directories ending with . or .. + ;; autosave files/links and non--existent files. + (unless + (or (helm-this-visible-mark) + ;; Non existing files in HFF and + ;; RFN. Display may be an image. See + ;; https://github.com/yyoncho/helm-treemacs-icons/issues/5 + ;; and also Bug#2296. + (equal prefix "[?]") + (and filecomp-p + (or + ;; autosave files + (string-match-p "\\`[.]?#.*#?\\'" bn) + ;; dot files + (member bn '("." ".."))))) + (helm-make-visible-mark src cand))) + (when (helm-pos-multiline-p) + (goto-char + (or (helm-get-next-candidate-separator-pos) + (point-max)))) + (forward-line 1)))) + (helm-mark-current-line)) + (helm-follow-mode follow))))) + +(defun helm-unmark-all () + "Unmark all candidates in all sources of current helm session." + (interactive) + (with-helm-alive-p + (with-helm-window + (save-excursion + (helm-clear-visible-mark)) + (setq helm-marked-candidates nil) + (helm-mark-current-line) + (helm-display-mode-line (helm-get-current-source)) + (set-window-margins (selected-window) helm-left-margin-width)))) +(put 'helm-unmark-all 'helm-only t) + +(defun helm-toggle-all-marks (&optional all) + "Toggle all marks. + +Mark all visible candidates of current source or unmark all +candidates visible or invisible in all sources of current Helm +session. + +With a prefix argument mark all candidates in all sources." + (interactive "P") + (with-helm-alive-p + (let ((marked (helm-marked-candidates))) + (if (and (>= (length marked) 1) + (with-helm-window helm-visible-mark-overlays)) + (helm-unmark-all) + (helm-mark-all all))))) +(put 'helm-toggle-all-marks 'helm-only t) + +(defun helm--compute-marked (real source &optional wildcard) + (let* ((coerced (helm-coerce-selection real source)) + (wilds (and wildcard + (condition-case nil + (helm-file-expand-wildcards + coerced t) + (error nil))))) + ;; Avoid returning a not expanded wildcard fname. + ;; e.g assuming "/tmp" doesn't contain "*.el" + ;; return nil when coerced is "/tmp/*.el". + (unless (or wilds (null wildcard) + (string-match-p helm--url-regexp coerced) + (file-exists-p coerced) + (and (stringp coerced) + (null (string-match-p "[[*?]" coerced)))) + (setq coerced nil)) + (or wilds (and coerced (list coerced))))) + +(cl-defun helm-marked-candidates (&key with-wildcard all-sources) + "Return marked candidates of current source, if any. + +Otherwise return one element list consisting of the current +selection. When key WITH-WILDCARD is specified, expand it. When +ALL-SOURCES key value is non-nil returns marked candidates of all +sources." + (with-current-buffer helm-buffer + (let* ((current-src (helm-get-current-source)) + (candidates + (cl-loop for (source . real) in (reverse helm-marked-candidates) + for use-wc = (and with-wildcard + (string-match-p "\\*" real) + (null (file-exists-p real))) + when (or all-sources + (equal (assq 'name source) + (assq 'name current-src))) + append (helm--compute-marked real source use-wc))) + sel) + (unless candidates + (setq sel (helm-get-selection + nil (helm-get-attr 'marked-with-props + current-src) + current-src)) + (setq candidates + (helm--compute-marked + sel current-src + (and with-wildcard (null (file-exists-p sel)))))) + (helm-log "helm-marked-candidates" + "Marked candidates = %S" candidates) + candidates))) + +(defun helm--remove-marked-and-update-mode-line (elm) + (with-helm-buffer + (setq helm-marked-candidates + (delete (rassoc elm helm-marked-candidates) + helm-marked-candidates)) + (helm-display-mode-line (helm-get-current-source)))) + +(defun helm-current-source-name= (name) + (save-excursion + (goto-char (helm-get-previous-header-pos)) + (equal name (helm-current-line-contents)))) + +(defun helm-revive-visible-mark () + "Restore marked candidates when helm updates display." + (with-current-buffer helm-buffer + (save-excursion + (dolist (o helm-visible-mark-overlays) + (let* ((source (overlay-get o 'source)) + (ov-src-name (assoc-default 'name source)) + (ov-str (overlay-get o 'string)) + (ov-real (overlay-get o 'real)) + (ov-ml-str (helm-aif (helm-get-attr 'multiline source) + (if (numberp it) + ;; Assume display have been computed + ;; against real e.g. kill-ring. + (helm--multiline-get-truncated-candidate + ov-real it) + ov-str) + ov-str)) + beg end) + ;; Move point to end of source header line. + (goto-char (point-min)) + (search-forward ov-src-name nil t) + (while (and (search-forward ov-ml-str nil t) + (cl-loop for ov in (overlays-at (point-at-bol 0)) + never (overlay-get ov 'visible-mark)) + (helm-current-source-name= ov-src-name)) + (setq beg (match-beginning 0) + end (if (string= ov-ml-str ov-str) + (match-end 0) (1+ (match-end 0)))) + ;; Calculate real value of candidate. + ;; It can be nil if candidate have only a display value. + (let ((real (get-text-property (point-at-bol 0) 'helm-realvalue))) + (if real + ;; Check if real value of current candidate is the same + ;; than the one stored in overlay. + ;; This is needed when some cands have same display names. + ;; Using equal allow testing any type of value for real cand. + ;; bug#706. + (and (equal ov-real real) + (move-overlay o beg end)) + (and (equal ov-str (buffer-substring beg end)) + (move-overlay o beg end)))))))))) +(add-hook 'helm-after-update-hook 'helm-revive-visible-mark) + +(defun helm-next-point-in-list (curpos points &optional prev) + (cond + ;; rule out special cases. + ((null points) curpos) + ((and prev (<= curpos (car points))) + (nth (1- (length points)) points)) + ((< (car (last points)) curpos) + (if prev (car (last points)) (nth 0 points))) + ((and (not prev) (>= curpos (car (last points)))) + (nth 0 points)) + (t + (nth (if prev + (cl-loop for pt in points + for i from 0 + if (<= curpos pt) return (1- i)) + (cl-loop for pt in points + for i from 0 + if (< curpos pt) return i)) + points)))) + +(defun helm-next-visible-mark (&optional prev) + "Move next Helm visible mark. +If PREV is non-nil move to precedent." + (interactive) + (with-helm-alive-p + (with-helm-window + (ignore-errors + (goto-char (helm-next-point-in-list + (point) + (sort (mapcar 'overlay-start helm-visible-mark-overlays) '<) + prev))) + (helm-mark-current-line)))) +(put 'helm-next-visible-mark 'helm-only t) + +(defun helm-prev-visible-mark () + "Move previous helm visible mark." + (interactive) + (with-helm-alive-p + (helm-next-visible-mark t))) +(put 'helm-prev-visible-mark 'helm-only t) + +;;; Utility: Selection Paste +;; +(defun helm-yank-selection (arg) + "Set minibuffer contents to current display selection. +With a prefix arg set to real value of current selection." + (interactive "P") + (with-helm-alive-p + (let ((str (format "%s" (helm-get-selection nil (not arg))))) + (kill-new str) + (helm-set-pattern str)))) +(put 'helm-yank-selection 'helm-only t) + +(defun helm-kill-selection-and-quit (arg) + "Store display value of current selection to kill ring. +With a prefix arg use real value of current selection. +Display value is shown in `helm-buffer' and real value is used to +perform actions." + (interactive "P") + (with-helm-alive-p + (helm-run-after-exit + (lambda (sel) + (kill-new sel) + ;; Return nil to force `helm-mode--keyboard-quit' + ;; in `helm-comp-read' otherwise the value "Saved to kill-ring: foo" + ;; is used as exit value for `helm-comp-read'. + (prog1 nil (message "Saved to kill-ring: %s" sel) (sit-for 1))) + (format "%s" (helm-get-selection nil (not arg)))))) +(put 'helm-kill-selection-and-quit 'helm-only t) + +(defun helm-insert-or-copy (&optional arg) + "Insert selection or marked candidates in current buffer. + +With a prefix arg copy marked candidates to kill-ring. +The real value of each candidate is used." + (interactive "P") + (with-helm-alive-p + (helm-run-after-exit + (lambda (cands) + (with-helm-current-buffer + (let ((sels (mapconcat (lambda (c) + (format "%s" c)) + cands "\n"))) + (if arg (kill-new sels) (insert sels))))) + (helm-marked-candidates)))) +(put 'helm-insert-or-copy 'helm-only t) + + +;;; Follow-mode: Automatic execution of persistent-action +;; +;; +(defvar helm-follow-input-idle-delay nil + "`helm-follow-mode' will execute its persistent action after this delay. +Note that if the `follow-delay' attr is present in source, it +will take precedence over this.") + +(defun helm-follow-mode (&optional arg) + "Execute persistent action every time the cursor is moved. + +This mode is source local, i.e. It applies on current source only. +\\ +This mode can be enabled or disabled interactively at anytime during +a helm session with \\[helm-follow-mode]. + +When enabling interactively `helm-follow-mode' in a source, you +can keep it enabled for next Emacs sessions by setting +`helm-follow-mode-persistent' to a non-nil value. + +When `helm-follow-mode' is called with a prefix arg and +`helm-follow-mode-persistent' is non-nil `helm-follow-mode' will +be persistent only for this Emacs session, but not for the next +Emacs sessions, i.e. the current source will not be saved to +`helm-source-names-using-follow'. + +A prefix arg with `helm-follow-mode' already enabled will have no +effect. + +Note that you can use instead of this mode the commands +`helm-follow-action-forward' and `helm-follow-action-backward' at +anytime in all Helm sessions. + +They are bound by default to \\[helm-follow-action-forward] and +\\[helm-follow-action-backward]." + (interactive (list (helm-aif (and current-prefix-arg + (prefix-numeric-value current-prefix-arg)) + (unless (helm-follow-mode-p) it)))) + (with-helm-alive-p + (with-current-buffer helm-buffer + (let* ((src (helm-get-current-source)) + (name (assoc-default 'name src)) + (fol-attr (assq 'follow src)) + (enabled (or (helm-follow-mode-p src) + (and helm-follow-mode-persistent + (member (assoc-default 'name src) + helm-source-names-using-follow))))) + (if src + (progn + (if (eq (cdr fol-attr) 'never) + (message "helm-follow-mode not allowed in this source") + ;; Make follow attr persistent for this emacs session. + (helm-follow-mode-set-source + (if (or enabled (and (numberp arg) (< arg 0))) -1 1) + src) + ;; When arg is nil assume the call is interactive. + ;; However if user call helm-follow-mode with a prefix arg, + ;; the call will be considered non--interactive and + ;; src-name will NOT be saved to helm-source-names-using-follow. + ;; When called from lisp (non--interactive) src-name + ;; will never be saved. + (when (and helm-follow-mode-persistent (null arg)) + (if (null enabled) + (unless (member name helm-source-names-using-follow) + (push name helm-source-names-using-follow) + (customize-save-variable 'helm-source-names-using-follow + helm-source-names-using-follow)) + (when (member name helm-source-names-using-follow) + (setq helm-source-names-using-follow + (delete name helm-source-names-using-follow)) + (customize-save-variable 'helm-source-names-using-follow + helm-source-names-using-follow)))) + (message "helm-follow-mode is %s" + (if (helm-follow-mode-p src) + "enabled" "disabled")) + (helm-display-mode-line src t))) + (message "Not enough candidates for helm-follow-mode")))))) +(put 'helm-follow-mode 'helm-only t) + +(defun helm-follow-execute-persistent-action-maybe (&optional delay) + "Execute persistent action in mode `helm-follow-mode'. + +This happen after: DELAY or the \\='follow-attr value of current +source or `helm-follow-input-idle-delay' or +`helm-input-idle-delay' secs." + (let* ((src (helm-get-current-source)) + (at (or delay + (assoc-default 'follow-delay src) + helm-follow-input-idle-delay + (or (and helm-input-idle-delay + (max helm-input-idle-delay 0.01)) + 0.01)))) + (when (and (not (get-buffer-window helm-action-buffer 'visible)) + (not (helm-pos-header-line-p)) + (or (helm-follow-mode-p src) + (and helm-follow-mode-persistent + (member (assoc-default 'name src) + helm-source-names-using-follow))) + (null (eq (assoc-default 'follow src) 'never)) + (helm-get-selection nil nil src)) + (helm-follow-mode-set-source 1 src) + (run-with-idle-timer at nil (lambda () + (when helm-alive-p + (helm-execute-persistent-action))))))) + +(defun helm-follow-mode-p (&optional source) + (with-helm-buffer + (eq (helm-get-attr 'follow (or source (helm-get-current-source))) 1))) + +(defun helm-follow-mode-set-source (value &optional source) + (with-helm-buffer + (helm-set-attr 'follow value (or source (helm-get-current-source))))) + +;;; Auto-resize mode +;; +(defun helm--autoresize-hook (&optional max-height min-height) + (when (helm-window) + (with-helm-window + (fit-window-to-buffer nil + (/ (* (frame-height) + (or max-height helm-autoresize-max-height)) + 100) + (/ (* (frame-height) + (or min-height helm-autoresize-min-height)) + 100))))) + +(define-minor-mode helm-autoresize-mode + "Auto resize helm window when enabled. +Helm window is re-sized according to `helm-autoresize-max-height' +and `helm-autoresize-min-height'. Note that when this mode is +enabled, Helm behaves as if `helm-always-two-windows' is enabled. + +See `fit-window-to-buffer' for more infos." + :group 'helm + :global t + (if helm-autoresize-mode + (progn (add-hook 'helm-after-update-hook 'helm--autoresize-hook) + (add-hook 'helm-window-configuration-hook 'helm--autoresize-hook)) + (remove-hook 'helm-after-update-hook 'helm--autoresize-hook) + (remove-hook 'helm-window-configuration-hook 'helm--autoresize-hook))) + +(defun helm-help () + "Generate Helm's help according to `help-message' attribute. + +If `helm-buffer' is empty, provide completions on `helm-sources' +to choose its local documentation. +If source doesn't have any `help-message' attribute, a generic +message explaining this is added instead. +The global `helm-help-message' is always added after this local +help." + (interactive) + (require 'helm-mode) ; for helm-comp-read. + (with-helm-alive-p + (let ((source (or (helm-get-current-source) + (helm-comp-read + "Help for: " + (cl-loop for src in (with-helm-buffer helm-sources) + collect `(,(assoc-default 'name src) . + ,src)) + :allow-nest t + :exec-when-only-one t)))) + (save-selected-window + (helm-help-internal + helm-help-buffer-name + (lambda () + (helm-aif (assoc-default 'help-message source) + (insert (substitute-command-keys + (helm-interpret-value it))) + (insert "* No specific help for this source available.")) + (insert "\n\n" + (substitute-command-keys + (helm-interpret-value helm-help-message))))))))) +(put 'helm-help 'helm-only t) + +(defun helm-toggle-truncate-line () + "Toggle `truncate-lines' value in `helm-buffer'" + (interactive) + (with-helm-alive-p + (with-helm-buffer + (setq truncate-lines (not truncate-lines)) + (when (helm-get-previous-header-pos) + (helm-update (regexp-quote (helm-get-selection nil t)))) + (message "%sisplaying continuation lines" + (if truncate-lines "Not D" "D"))))) +(put 'helm-toggle-truncate-line 'helm-only t) + +;;;###autoload +(defun helm-other-buffer (sources buffer) + "Simplified Helm interface with other `helm-buffer'. +Call `helm' only with SOURCES and BUFFER as args." + (helm :sources sources :buffer buffer)) + + +(provide 'helm-core) +;;; helm-core.el ends here diff --git a/org/elpa/helm-core-20230317.1729/helm-lib.el b/org/elpa/helm-core-20230317.1729/helm-lib.el new file mode 100644 index 0000000..9fc1ed7 --- /dev/null +++ b/org/elpa/helm-core-20230317.1729/helm-lib.el @@ -0,0 +1,1908 @@ +;;; helm-lib.el --- Helm routines. -*- lexical-binding: t -*- + +;; Copyright (C) 2015 ~ 2020 Thierry Volpiatto + +;; Author: Thierry Volpiatto +;; URL: http://github.com/emacs-helm/helm + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; All helm functions that don't require specific helm code should go here. + +;;; Code: + +(require 'cl-lib) + +(declare-function ansi-color--find-face "ansi-color.el") +(declare-function ansi-color-apply-sequence "ansi-color.el") +(declare-function dired-current-directory "dired.el") +(declare-function ffap-file-remote-p "ffap.el") +(declare-function ffap-url-p "ffap.el") +(declare-function helm-get-attr "helm-core.el") +(declare-function helm-set-attr "helm-core.el") +(declare-function helm-follow-mode-p "helm-core.el") +(declare-function helm-get-current-source "helm-core.el") +(declare-function helm-get-selection "helm-core.el") +(declare-function helm-get-sources "helm-core.el") +(declare-function helm-interpret-value "helm-core.el") +(declare-function helm-log-run-hook "helm-core.el") +(declare-function helm-marked-candidates "helm-core.el") +(declare-function helm-set-case-fold-search "helm-core.el") +(declare-function helm-source--cl--print-table "helm-source.el") +(declare-function helm-update "helm-core.el") +(declare-function org-content "org.el") +(declare-function org-mark-ring-goto "org.el") +(declare-function org-mark-ring-push "org.el") +(declare-function org-table-p "org-compat.el") +(declare-function org-table-align "org-table.el") +(declare-function org-table-end "org-table.el") +(declare-function org-open-at-point "org.el") +(declare-function helm-read-file-name "helm-mode.el") +(declare-function find-function-library "find-func.el") +(declare-function find-library-name "find-func.el") + +(defvar helm-sources) +(defvar helm-initial-frame) +(defvar helm-current-position) +(defvar helm-persistent-action-display-window) +(defvar helm--buffer-in-new-frame-p) +(defvar helm-completion-style) +(defvar helm-completion-styles-alist) +(defvar helm-persistent-action-window-buffer) +(defvar completion-flex-nospace) +(defvar find-function-source-path) +(defvar ffap-machine-p-unknown) +(defvar ffap-machine-p-local) +(defvar ffap-machine-p-known) + + +;;; User vars. +;; +(defcustom helm-file-globstar t + "Same as globstar bash shopt option. +When non-nil a pattern beginning with two stars will expand +recursively. +Directories expansion is not supported yet." + :group 'helm + :type 'boolean) + +(defcustom helm-yank-text-at-point-function nil + "The function used to forward point with `helm-yank-text-at-point'. +With a nil value, fallback to default `forward-word'. +The function should take one arg, an integer like `forward-word'. +NOTE: Using `forward-symbol' here is not very useful as it is +already provided by \\\\[next-history-element]." + :type 'function + :group 'helm) + +(defcustom helm-scroll-amount nil + "Scroll amount when scrolling helm window or other window in a helm session. +It is used by `helm-scroll-other-window', `helm-scroll-up', `helm-scroll-down' +and `helm-scroll-other-window-down'. + +If you prefer scrolling line by line, set this value to 1." + :group 'helm + :type 'integer) + +(defcustom helm-help-full-frame t + "Display help window in full frame when non nil. + +Even when nil probably the same result (full frame) can be +reached by tweaking `display-buffer-alist', but it is much more +convenient to use a simple boolean value here." + :type 'boolean + :group 'helm-help) + +(defvar helm-ff--boring-regexp nil) +(defun helm-ff--setup-boring-regex (var val) + (set var val) + (setq helm-ff--boring-regexp + (cl-loop with last = (car (last val)) + for r in (butlast val) + if (string-match "\\$\\'" r) + concat (concat r "\\|") into result + else concat (concat r "$\\|") into result + finally return + (concat result last + (if (string-match "\\$\\'" last) "" "$"))))) + +(defcustom helm-boring-file-regexp-list + (mapcar (lambda (f) + (let ((rgx (regexp-quote f))) + (if (string-match-p "[^/]$" f) + ;; files: e.g .o => \\.o$ + (concat rgx "$") + ;; directories: e.g .git/ => \.git\\(/\\|$\\) + (concat (substring rgx 0 -1) "\\(/\\|$\\)")))) + completion-ignored-extensions) + "A list of regexps matching boring files. + +This list is build by default on `completion-ignored-extensions'. +The directory names should end with \"/?\" e.g. \"\\.git/?\" and +the file names should end with \"$\" e.g. \"\\.o$\". + +These regexps may be used to match the entire path, not just the +file name, so for example to ignore files with a prefix +\".bak.\", use \"\\.bak\\..*$\" as the regexp. + +NOTE: When modifying this, be sure to use customize interface or +the customize functions e.g. `customize-set-variable' and NOT +`setq'." + :group 'helm-files + :type '(repeat (choice regexp)) + :set 'helm-ff--setup-boring-regex) + +(defcustom helm-describe-function-function 'describe-function + "Function used to describe functions in Helm." + :group 'helm-elisp + :type 'function) + +(defcustom helm-describe-variable-function 'describe-variable + "Function used to describe variables in Helm." + :group 'helm-elisp + :type 'function) + + +;;; Internal vars +;; +(defvar helm-yank-point nil) +(defvar helm-pattern "" + "The input pattern used to update the helm buffer.") +(defvar helm-buffer "*helm*" + "Buffer showing completions.") +(defvar helm-current-buffer nil + "Current buffer when `helm' is invoked.") +(defvar helm-suspend-update-flag nil) +(defvar helm-action-buffer "*helm action*" + "Buffer showing actions.") +(defvar helm-current-prefix-arg nil + "Record `current-prefix-arg' when exiting minibuffer.") +(defvar helm-current-error nil + "Same as `compilation-current-error' but for helm-occur and helm-grep.") + +;;; Compatibility +;; +(defun helm-add-face-text-properties (beg end face &optional append object) + "Add the face property to the text from START to END. +It is a compatibility function which behaves exactly like +`add-face-text-property' if available, otherwise like +`add-text-properties'. When only `add-text-properties' is +available APPEND is ignored." + (if (fboundp 'add-face-text-property) + (add-face-text-property beg end face append object) + (add-text-properties beg end `(face ,face) object))) + +;;; Override `push-mark' +;; +;; Fix duplicates in `mark-ring' and `global-mark-ring' and update +;; buffers in `global-mark-ring' to recentest mark. +(defun helm--advice-push-mark (&optional location nomsg activate) + (unless (null (mark t)) + (let ((marker (copy-marker (mark-marker)))) + (setq mark-ring (cons marker (delete marker mark-ring)))) + (when (> (length mark-ring) mark-ring-max) + ;; Move marker to nowhere. + (set-marker (car (nthcdr mark-ring-max mark-ring)) nil) + (setcdr (nthcdr (1- mark-ring-max) mark-ring) nil))) + (set-marker (mark-marker) (or location (point)) (current-buffer)) + ;; Now push the mark on the global mark ring. + (setq global-mark-ring (cons (copy-marker (mark-marker)) + ;; Avoid having multiple entries + ;; for same buffer in `global-mark-ring'. + (cl-loop with mb = (current-buffer) + for m in global-mark-ring + for nmb = (marker-buffer m) + unless (eq mb nmb) + collect m))) + (when (> (length global-mark-ring) global-mark-ring-max) + (set-marker (car (nthcdr global-mark-ring-max global-mark-ring)) nil) + (setcdr (nthcdr (1- global-mark-ring-max) global-mark-ring) nil)) + (or nomsg executing-kbd-macro (> (minibuffer-depth) 0) + (message "Mark set")) + (when (or activate (not transient-mark-mode)) + (set-mark (mark t))) + nil) + +(defcustom helm-advice-push-mark t + "Override `push-mark' with a version avoiding duplicates when non-nil." + :group 'helm + :type 'boolean + :set (lambda (var val) + (set var val) + (if val + (advice-add 'push-mark :override #'helm--advice-push-mark '((depth . 100))) + (advice-remove 'push-mark #'helm--advice-push-mark)))) + +;; This the version of Emacs-27 written by Stefan +(defun helm-advice--ffap-read-file-or-url (prompt guess) + (or guess (setq guess default-directory)) + (if (ffap-url-p guess) + (read-string prompt guess nil nil t) + (unless (ffap-file-remote-p guess) + (setq guess (abbreviate-file-name (expand-file-name guess)))) + (read-file-name prompt (file-name-directory guess) nil nil + (file-name-nondirectory guess)))) + +;; The native-comp branch of emacs "is a modified Emacs capable of compiling +;; and running Emacs Lisp as native code in form of re-loadable elf files." +;; (https://akrl.sdf.org/gccemacs.html). The function subr-native-elisp-p is a +;; native function available only in this branch and evaluates to true if the +;; argument supplied is a natively compiled lisp function. Use this function +;; if it's available, otherwise return nil. Helm needs to distinguish compiled +;; functions from other symbols in a various places. +(defun helm-subr-native-elisp-p (object) + (when (fboundp 'subr-native-elisp-p) + (subr-native-elisp-p object))) + +;; Available only in Emacs-28+ +(unless (fboundp 'file-modes-number-to-symbolic) + (defun file-modes-number-to-symbolic (mode &optional filetype) + "Return a string describing a file's MODE. +For instance, if MODE is #o700, then it produces `-rwx------'. +FILETYPE if provided should be a character denoting the type of file, +such as `?d' for a directory, or `?l' for a symbolic link and will override +the leading `-' char." + (string + (or filetype + (pcase (lsh mode -12) + ;; POSIX specifies that the file type is included in st_mode + ;; and provides names for the file types but values only for + ;; the permissions (e.g., S_IWOTH=2). + + ;; (#o017 ??) ;; #define S_IFMT 00170000 + (#o014 ?s) ;; #define S_IFSOCK 0140000 + (#o012 ?l) ;; #define S_IFLNK 0120000 + ;; (8 ??) ;; #define S_IFREG 0100000 + (#o006 ?b) ;; #define S_IFBLK 0060000 + (#o004 ?d) ;; #define S_IFDIR 0040000 + (#o002 ?c) ;; #define S_IFCHR 0020000 + (#o001 ?p) ;; #define S_IFIFO 0010000 + (_ ?-))) + (if (zerop (logand 256 mode)) ?- ?r) + (if (zerop (logand 128 mode)) ?- ?w) + (if (zerop (logand 64 mode)) + (if (zerop (logand 2048 mode)) ?- ?S) + (if (zerop (logand 2048 mode)) ?x ?s)) + (if (zerop (logand 32 mode)) ?- ?r) + (if (zerop (logand 16 mode)) ?- ?w) + (if (zerop (logand 8 mode)) + (if (zerop (logand 1024 mode)) ?- ?S) + (if (zerop (logand 1024 mode)) ?x ?s)) + (if (zerop (logand 4 mode)) ?- ?r) + (if (zerop (logand 2 mode)) ?- ?w) + (if (zerop (logand 512 mode)) + (if (zerop (logand 1 mode)) ?- ?x) + (if (zerop (logand 1 mode)) ?T ?t))))) + +;;; Macros helper. +;; +(defmacro helm-with-gensyms (symbols &rest body) + "Bind the SYMBOLS to fresh uninterned symbols and eval BODY." + (declare (indent 1)) + `(let ,(mapcar (lambda (s) + ;; Use cl-gensym here instead of make-symbol + ;; to ensure a symbol that have a live that go + ;; beyond the live of its macro have different name. + ;; i.e symbols created with `with-helm-temp-hook' + ;; should have random names. + `(,s (cl-gensym (symbol-name ',s)))) + symbols) + ,@body)) + +;;; Command loop helper +;; +(defconst helm-this-command-black-list + '(helm-maybe-exit-minibuffer + helm-confirm-and-exit-minibuffer + helm-exit-minibuffer + exit-minibuffer + helm-M-x)) + +(defun helm-this-command () + "Return the actual command in action. +Like `this-command' but return the real command, and not +`exit-minibuffer' or other unwanted functions." + (cl-loop for count from 1 to 50 + for btf = (backtrace-frame count) + for fn = (cl-second btf) + if (and + ;; In some case we may have in the way an + ;; advice compiled resulting in byte-code, + ;; ignore it (Bug#691). + (symbolp fn) + (commandp fn) + (not (memq fn helm-this-command-black-list))) + return fn + else + if (and (eq fn 'call-interactively) + (> (length btf) 2)) + return (cadr (cdr btf)))) + + +;;; Iterators +;; +(cl-defmacro helm-position (item seq &key test all) + "A simple and faster replacement of CL `position'. + +Returns ITEM first occurence position found in SEQ. +When SEQ is a string, ITEM have to be specified as a char. +Argument TEST when unspecified default to `eq'. +When argument ALL is non-nil return a list of all ITEM positions +found in SEQ." + (let ((key (if (stringp seq) 'across 'in))) + `(cl-loop with deftest = 'eq + for c ,key ,seq + for index from 0 + when (funcall (or ,test deftest) c ,item) + if ,all collect index into ls + else return index + finally return ls))) + +(defun helm-iter-list (seq &optional cycle) + "Return an iterator object from SEQ. +The iterator die and return nil when it reach end of SEQ. +When CYCLE is specified the iterator never ends." + (let ((lis seq)) + (lambda () + (let ((elm (car lis))) + (setq lis (if cycle + (or (cdr lis) seq) + (cdr lis))) + elm)))) + +(defun helm-iter-circular (seq) + "Infinite iteration on SEQ." + (helm-iter-list seq 'cycle)) + +(cl-defun helm-iter-sub-next-circular (seq elm &key (test 'eq)) + "Infinite iteration of SEQ starting at ELM." + (let* ((pos (1+ (helm-position elm seq :test test))) + (sub (append (nthcdr pos seq) (helm-take seq pos))) + (iterator (helm-iter-circular sub))) + (lambda () + (helm-iter-next iterator)))) + +(defun helm-iter-next (iterator) + "Return next elm of ITERATOR." + (and iterator (funcall iterator))) + + +;;; Anaphoric macros. +;; +(defmacro helm-aif (test-form then-form &rest else-forms) + "Anaphoric version of `if'. +Like `if' but set the result of TEST-FORM in a temporary variable +called `it'. THEN-FORM and ELSE-FORMS are then executed just like +in `if'." + (declare (indent 2) (debug t)) + `(let ((it ,test-form)) + (if it ,then-form ,@else-forms))) + +(defmacro helm-awhile (sexp &rest body) + "Anaphoric version of `while'. +Same usage as `while' except that SEXP is bound to a temporary +variable called `it' at each turn. +An implicit nil block is bound to the loop so usage of +`cl-return' is possible to exit the loop." + (declare (indent 1) (debug t)) + (helm-with-gensyms (flag) + `(let ((,flag t)) + (cl-block nil + (while ,flag + (helm-aif ,sexp + (progn ,@body) + (setq ,flag nil))))))) + +(defmacro helm-acond (&rest clauses) + "Anaphoric version of `cond'. +In each clause of CLAUSES, the result of the car of clause is +stored in a temporary variable called `it' and usable in the cdr +of this same clause. Each `it' variable is independent of its +clause. The usage is the same as `cond'." + (declare (debug cond)) + (unless (null clauses) + (helm-with-gensyms (sym) + (let ((clause1 (car clauses))) + `(let ((,sym ,(car clause1))) + (helm-aif ,sym + (if (cdr ',clause1) + (progn ,@(cdr clause1)) + it) + (helm-acond ,@(cdr clauses)))))))) + +(defmacro helm-aand (&rest conditions) + "Anaphoric version of `and'. +Each condition is bound to a temporary variable called `it' which +is usable in next condition." + (declare (debug (&rest form))) + (cond ((null conditions) t) + ((null (cdr conditions)) (car conditions)) + (t `(helm-aif ,(car conditions) + (helm-aand ,@(cdr conditions)))))) + +(defmacro helm-acase (expr &rest clauses) + "A simple anaphoric `cl-case' implementation handling strings. +EXPR is bound to a temporary variable called `it' which is usable +in CLAUSES to refer to EXPR. +NOTE: Duplicate keys in CLAUSES are deliberately not handled. + +\(fn EXPR (KEYLIST BODY...)...)" + (declare (indent 1) (debug (form &rest (sexp body)))) + (unless (null clauses) + (let ((clause1 (car clauses))) + `(let ((key ',(car clause1)) + (it ,expr)) + (if (or (equal it key) + (and (listp key) (member it key)) + (eq key t)) + (progn ,@(cdr clause1)) + (helm-acase it ,@(cdr clauses))))))) + +;;; Fuzzy matching routines +;; +(defsubst helm--mapconcat-pattern (pattern) + "Transform string PATTERN in regexp for further fuzzy matching. +E.g.: helm.el$ + => \"[^h]*?h[^e]*?e[^l]*?l[^m]*?m[^.]*?[.][^e]*?e[^l]*?l$\" + ^helm.el$ + => \"helm[.]el$\"." + (let ((ls (split-string-and-unquote pattern ""))) + (if (string= "^" (car ls)) + ;; Exact match. + (mapconcat (lambda (c) + (if (and (string= c "$") + (string-match "$\\'" pattern)) + c (regexp-quote c))) + (cdr ls) "") + ;; Fuzzy match. + (mapconcat (lambda (c) + (if (and (string= c "$") + (string-match "$\\'" pattern)) + c (format "[^%s]*?%s" c (regexp-quote c)))) + ls "")))) + +(defsubst helm--collect-pairs-in-string (string) + (cl-loop for str on (split-string string "" t) by 'cdr + when (cdr str) + collect (list (car str) (cadr str)))) + +;;; Help routines. +;; +(defvar helm-help--iter-org-state nil) + +(defvar helm-help-mode-before-hook nil + "A hook that runs before helm-help starts.") + +(defvar helm-help-mode-after-hook nil + "A hook that runs when helm-help exits.") + +(defcustom helm-help-default-prompt + "[SPC,C-v,next:ScrollUp b,M-v,prior:ScrollDown TAB:Cycle M-TAB:All C-s/r:Isearch q:Quit]" + "The prompt used in `helm-help'." + :type 'string + :group 'helm) + +(defcustom helm-help-hkmap + '(("C-v" . helm-help-scroll-up) + ("SPC" . helm-help-scroll-up) + ("" . helm-help-scroll-up) + ("M-v" . helm-help-scroll-down) + ("b" . helm-help-scroll-down) + ("" . helm-help-scroll-down) + ("C-s" . isearch-forward) + ("C-r" . isearch-backward) + ("C-a" . move-beginning-of-line) + ("C-e" . move-end-of-line) + ("C-f" . forward-char) + ("" . forward-char) + ("C-b" . backward-char) + ("" . backward-char) + ("C-n" . helm-help-next-line) + ("C-p" . helm-help-previous-line) + ("" . helm-help-next-line) + ("" . helm-help-previous-line) + ("M-a" . backward-sentence) + ("M-e" . forward-sentence) + ("M-f" . forward-word) + ("M-b" . backward-word) + ("M->" . end-of-buffer) + ("M-<" . beginning-of-buffer) + ("C-SPC" . helm-help-toggle-mark) + ("C-M-SPC" . mark-sexp) + ("TAB" . org-cycle) + ("C-m" . helm-help-org-open-at-point) + ("C-&" . helm-help-org-mark-ring-goto) + ("C-%" . org-mark-ring-push) + ("M-TAB" . helm-help-org-cycle) + ("M-w" . helm-help-copy-region-as-kill) + ("q" . helm-help-quit)) + "Alist of (KEY . FUNCTION) for `helm-help'. + +This is not a standard keymap, just an alist where it is possible to +define a simple KEY (a string with no spaces) associated with a +FUNCTION. More complex key like \"C-x C-x\" are not supported. +Interactive functions will be called interactively whereas other +functions will be called with funcall except commands that are in +`helm-help-not-interactive-command'. +For convenience you can add bindings here with `helm-help-define-key'." + :type '(alist :key-type string :key-value symbol) + :group 'helm) + +(defvar helm-help-not-interactive-command '(isearch-forward isearch-backward) + "Commands that we don't want to call interactively in `helm-help'.") + +(defun helm-help-internal (bufname insert-content-fn) + "Show long message during Helm session in BUFNAME. +INSERT-CONTENT-FN is the function that inserts text to be +displayed in BUFNAME." + (let ((winconf (current-frame-configuration)) + (hframe (selected-frame))) + (helm-log-run-hook "helm-help-internal" 'helm-help-mode-before-hook) + (with-selected-frame helm-initial-frame + (select-frame-set-input-focus helm-initial-frame) + (unwind-protect + (progn + (setq helm-suspend-update-flag t) + (set-buffer (get-buffer-create bufname)) + (switch-to-buffer bufname) + (when helm-help-full-frame (delete-other-windows)) + (delete-region (point-min) (point-max)) + (org-mode) + (save-excursion + (funcall insert-content-fn) + (goto-char (point-min)) + (while (re-search-forward "^[|]" nil t) + (when (org-table-p t) + (org-table-align) + (goto-char (org-table-end))))) + (org-mark-ring-push) ; Put mark at bob + (buffer-disable-undo) + (helm-help-event-loop)) + (raise-frame hframe) + (helm-log-run-hook "helm-help-internal" 'helm-help-mode-after-hook) + (setq helm-suspend-update-flag nil) + (set-frame-configuration winconf))))) + +(cl-defun helm-help-scroll-up (&optional (amount helm-scroll-amount)) + "Scroll up in `helm-help'." + (condition-case _err + (scroll-up-command amount) + (beginning-of-buffer nil) + (end-of-buffer nil))) + +(cl-defun helm-help-scroll-down (&optional (amount helm-scroll-amount)) + "Scroll down in `helm-help'." + (condition-case _err + (scroll-down-command amount) + (beginning-of-buffer nil) + (end-of-buffer nil))) + +(defun helm-help-next-line () + "Next line function for `helm-help'." + (condition-case _err + (call-interactively #'next-line) + (beginning-of-buffer nil) + (end-of-buffer nil))) + +(defun helm-help-previous-line () + "Previous line function for `helm-help'." + (condition-case _err + (call-interactively #'previous-line) + (beginning-of-buffer nil) + (end-of-buffer nil))) + +(defun helm-help-toggle-mark () + "Toggle mark in `helm-help'." + (if (region-active-p) + (deactivate-mark) + (push-mark nil nil t))) + +(defun helm-help-org-cycle () + "Runs `org-cycle' in `helm-help'." + (pcase (helm-iter-next helm-help--iter-org-state) + ((pred numberp) (org-content)) + ((and state) (org-cycle state)))) + +(defun helm-help-copy-region-as-kill () + "Copy region function for `helm-help'" + (copy-region-as-kill + (region-beginning) (region-end)) + (deactivate-mark)) + +(defun helm-help-quit () + "Quit `helm-help'." + (if (get-buffer-window helm-help-buffer-name 'visible) + (throw 'helm-help-quit nil) + (quit-window))) + +(defun helm-help-org-open-at-point () + "Calls `org-open-at-point' ignoring errors." + (ignore-errors + (org-open-at-point))) + +(defun helm-help-org-mark-ring-goto () + "Calls `org-mark-ring-goto' ignoring errors." + (ignore-errors + (org-mark-ring-goto))) + +(defun helm-help-event-loop () + "The loop in charge of scanning keybindings in `helm-help'." + (let ((prompt (propertize + helm-help-default-prompt + 'face 'helm-helper)) + scroll-error-top-bottom + (helm-help--iter-org-state (helm-iter-circular '(1 (16) (64))))) + (catch 'helm-help-quit + (helm-awhile (read-key prompt) + (let ((fun (cl-loop for (k . v) in helm-help-hkmap + when (eql (aref (kbd k) 0) it) + return v))) + (when fun + (if (and (commandp fun) + (not (memq fun helm-help-not-interactive-command))) + ;; For movement of cursor in help buffer we need to + ;; call interactively commands for impaired people + ;; using a synthetizer (Bug#1347). + (call-interactively fun) + (funcall fun)))))))) + +(defun helm-help-define-key (key function &optional override) + "Add KEY bound to fUNCTION in `helm-help-hkmap'. + +If OVERRIDE is non nil, all bindings associated with FUNCTION are +removed and only (KEY . FUNCTION) is kept. +If FUNCTION is nil (KEY . FUNCTION) is not added and removed from +alist if already present. +See `helm-help-hkmap' for supported keys and functions." + (cl-assert (not (cdr (split-string key))) nil + (format "Error: Unsuported key `%s'" key)) + (when override + (helm-awhile (rassoc function helm-help-hkmap) + (setq helm-help-hkmap (delete it helm-help-hkmap)))) + (helm-aif (and (null function) (assoc key helm-help-hkmap)) + (setq helm-help-hkmap (delete it helm-help-hkmap)) + (and function (add-to-list 'helm-help-hkmap `(,key . ,function))))) + +;;; Multiline transformer +;; +(defun helm-multiline-transformer (candidates _source) + (cl-loop with offset = (helm-interpret-value + (assoc-default 'multiline (helm-get-current-source))) + for cand in candidates + for disp = (or (car-safe cand) cand) + for real = (or (cdr-safe cand) cand) + if (numberp offset) + collect (cons (helm--multiline-get-truncated-candidate disp offset) + real) + else collect (cons disp real))) + +(defun helm--multiline-get-truncated-candidate (candidate offset) + "Truncate CANDIDATE when its length is > than OFFSET." + (with-temp-buffer + (insert candidate) + (goto-char (point-min)) + (if (and offset + (> (buffer-size) offset)) + (let ((end-str "[...]")) + (concat + (buffer-substring + (point) + (save-excursion + (forward-char offset) + (setq end-str (if (looking-at "\n") + end-str (concat "\n" end-str))) + (point))) + end-str)) + (buffer-string)))) + +;;; List processing +;; +(defun helm-flatten-list (seq) + "Return a list of all single elements of sublists in SEQ. + + Example: + (helm-flatten-list \\='(1 (2 . 3) nil (4 5 (6) 7) 8 (9 . 10))) + => (1 2 3 4 5 6 7 8 9 10)" + (let (result) + (cl-labels ((flatten + (seq) + (cl-loop for elm in seq + if (consp elm) + do (flatten + (if (atom (cdr elm)) + (list (car elm) (cdr elm)) + elm)) + else do (and elm (push elm result))))) + (flatten seq)) + (nreverse result))) + +(defun helm-mklist (obj) + "Return OBJ as a list. +Otherwise make a list with one element OBJ." + (if (and (listp obj) (not (functionp obj))) + obj + (list obj))) + +(cl-defun helm-fast-remove-dups (seq &key (test 'eq)) + "Remove duplicates elements in list SEQ. + +This is same as `remove-duplicates' but with memoisation. +It is much faster, especially in large lists. +A test function can be provided with TEST argument key. +Default is `eq'. +NOTE: Comparison of special Elisp objects (e.g., markers etc.) +fails because their printed representations which are stored in +hash-table can't be compared with with the real object in SEQ. +This is a bug in `puthash' which store the printable +representation of object instead of storing the object itself, +this to provide at the end a printable representation of +hashtable itself." + (cl-loop with cont = (make-hash-table :test test) + for elm in seq + unless (gethash elm cont) + collect (puthash elm elm cont))) + +(defsubst helm--string-join (strings &optional separator) + "Join all STRINGS using SEPARATOR." + (mapconcat 'identity strings separator)) + +(defun helm--concat-regexps (regexp-list) + "Return a regexp which matches any of the regexps in REGEXP-LIST." + (if regexp-list + (concat "\\(?:" (helm--string-join regexp-list "\\)\\|\\(?:") "\\)") + "\\`\\'")) ; Match nothing + +(defun helm-skip-entries (seq black-regexp-list &optional white-regexp-list) + "Remove entries which match one of REGEXP-LIST from SEQ." + (let ((black-regexp (helm--concat-regexps black-regexp-list)) + (white-regexp (helm--concat-regexps white-regexp-list))) + (cl-loop for i in seq + unless (and (stringp i) + (string-match-p black-regexp i) + (null + (string-match-p white-regexp i))) + collect i))) + +(defun helm-boring-directory-p (directory black-list) + "Check if one regexp in BLACK-LIST matches DIRECTORY." + (helm-awhile (helm-basedir (directory-file-name + (expand-file-name directory))) + ;; Break at root to avoid infloop, root is / or on Windows + ;; C:/ i.e. :/ (Bug#2308). + (when (string-match-p "\\`[A-Za-z]?:?/\\'" it) + (cl-return nil)) + (when (cl-loop for r in black-list + thereis (string-match-p + r (directory-file-name directory))) + (cl-return t)) + (setq directory it))) + +(defun helm-shadow-entries (seq regexp-list) + "Put shadow property on entries in SEQ matching a regexp in REGEXP-LIST." + (let ((face 'italic)) + (cl-loop for i in seq + if (cl-loop for regexp in regexp-list + thereis (and (stringp i) + (string-match regexp i))) + collect (propertize i 'face face) + else collect i))) + +(defun helm-remove-if-not-match (regexp seq) + "Remove all elements of SEQ that don't match REGEXP." + (cl-loop for s in seq + for str = (cond ((symbolp s) + (symbol-name s)) + ((consp s) + (car s)) + (t s)) + when (string-match-p regexp str) + collect s)) + +(defun helm-remove-if-match (regexp seq) + "Remove all elements of SEQ that match REGEXP." + (cl-loop for s in seq + for str = (cond ((symbolp s) + (symbol-name s)) + ((consp s) + (car s)) + (t s)) + unless (string-match-p regexp str) + collect s)) + +(defun helm-transform-mapcar (fn seq) + "Apply function FN on all elements of list SEQ. +When SEQ is a list of cons cells apply FN on the cdr of each element, +keeping their car unmodified. + +Examples: + + (helm-transform-mapcar \\='upcase \\='(\"foo\" \"bar\")) + => (\"FOO\" \"BAR\") + (helm-transform-mapcar \\='upcase \\='((\"1st\" . \"foo\") (\"2nd\" . \"bar\"))) + => ((\"1st\" . \"FOO\") (\"2nd\" . \"BAR\")) +" + (cl-loop for elm in seq + if (consp elm) + collect (cons (car elm) (funcall fn (cdr elm))) + else + collect (funcall fn elm))) + +(defun helm-append-at-nth (seq elm index) + "Append ELM at INDEX in SEQ. +When INDEX is > to the SEQ length ELM is added at end of SEQ. +When INDEX is 0 or negative, ELM is added at beginning of SEQ. + +Examples: + + (helm-append-at-nth \\='(a b c d) \\='(z) 2) + =>(a b z c d) + + (helm-append-at-nth \\='(a b c d) \\='((x . 1) (y . 2)) 2) + =>(a b (x . 1) (y . 2) c d) + + But this is not working: + (helm-append-at-nth \\='(a b c d) \\='(x . 1) 2) + =>Wrong type argument: listp, 1 + +NOTE: This function uses `append' internally, so ELM is expected +to be a list to be appended to SEQ, even if for convenience an +atom is supported as ELM value." + (setq index (min (max index 0) (length seq)) + elm (helm-mklist elm)) + (if (zerop index) + (append elm seq) + (let* ((end-part (nthcdr index seq)) + (len (length end-part)) + (beg-part (butlast seq len))) + (append beg-part elm end-part)))) + +(cl-defgeneric helm-take (seq n) + "Return the first N elements of SEQ if SEQ is longer than N. +It is used for narrowing list of candidates to the +`helm-candidate-number-limit'." + (if (> (length seq) n) (cl-subseq seq 0 n) seq)) + +(cl-defmethod helm-take ((seq list) n) + "`helm-take' optimized for lists." + (let ((store '())) + (if (> n (length seq)) + seq + (while (> (1+ (cl-decf n)) 0) + (push (pop seq) store)) + (nreverse store)))) + +(defalias 'helm-take-first-elements 'helm-take) +(make-obsolete 'helm-take-first-elements 'helm-take "3.9.1") + +(defun helm-source-by-name (name &optional sources) + "Get a Helm source in SOURCES by NAME. + +Optional argument SOURCES is a list of Helm sources which default +to `helm-sources'." + (cl-loop with src-list = (if sources + (cl-loop for src in sources + collect (if (listp src) + src + (symbol-value src))) + helm-sources) + for source in src-list + thereis (and (string= name (assoc-default 'name source)) source))) + +(defun helm-make-actions (&rest args) + "Build an alist with (NAME . ACTION) elements with each pairs in ARGS. +Where NAME is a string or a function returning a string or nil +and ACTION a function. +If NAME returns nil the pair is skipped. + +\(fn NAME ACTION ...)" + (cl-loop for (name fn) on args by #'cddr + when (functionp name) + do (setq name (funcall name)) + when name + collect (cons name fn))) + +(defun helm-closest-number-in-list (num list) + "Return closest number to NUM found in LIST. +LIST is a list of numbers and NUM a number." + (cl-loop for i in list + for diff = (if (> num i) (- num i) (- i num)) + collect (cons diff i) into res + minimize diff into min + finally return (cdr (assq min res)))) + +(defun helm-group-candidates-by (candidates function &optional selection separate) + "Group similar items in CANDIDATES according to FUNCTION. +Items not matching FUNCTION are grouped as well in a separate group. + +Example: + + (setq B \\='(1 2 3 4 5 6 7 8 9)) + + (helm-group-candidates-by B #'cl-oddp 2 \\='separate) + => ((2 4 6 8) (1 3 5 7 9)) + +SELECTION specify where to start in CANDIDATES. +Similar candidates to SELECTION will be listed on top. + +If SEPARATE is non-nil returns a list of groups i.e. a list of lists, +otherwise a plain list is returned." + (cl-loop with sel = (or selection (helm-get-selection) "") + with lst = (copy-sequence candidates) + while lst + for group = (cl-loop for c in lst + when (equal (funcall function c) + (funcall function sel)) + collect c into grp + and do (setq lst (delete c lst)) + finally return (prog1 grp + (setq sel (car lst)))) + if separate collect group + else append group)) + +(defun helm-reorganize-sequence-from-elm (sequence elm &optional reverse) + "Reorganize SEQUENCE from ELM. + +Examples: + + (helm-reorganize-sequence-from-elm \\='(a b c d e f g h i j k l) \\='e) + => (f g h i j k l a b c d e) + (helm-reorganize-sequence-from-elm \\='(a b c d e f g h i j k l) \\='e t) + => (d c b a l k j i h g f e) +" + (let* ((new-seq (if reverse + (reverse sequence) + sequence)) + (pos (1+ (cl-position elm new-seq :test 'equal)))) + (append (nthcdr pos new-seq) (helm-take new-seq pos)))) + +;;; Strings processing. +;; +(defun helm-stringify (elm) + "Return the representation of ELM as a string. +ELM can be a string, a number or a symbol." + (pcase elm + ((pred stringp) elm) + ((pred numberp) (number-to-string elm)) + ((pred symbolp) (symbol-name elm)))) + +(defun helm-substring (str width) + "Return the substring of string STR from 0 to WIDTH. +Handle multibyte characters by moving by columns." + (with-temp-buffer + (save-excursion + (insert str)) + (move-to-column width) + (buffer-substring (point-at-bol) (point)))) + +(defun helm-substring-by-width (str width &optional endstr) + "Truncate string STR to end at column WIDTH. +Similar to `truncate-string-to-width'. +Add ENDSTR at end of truncated STR. +Add spaces at end if needed to reach WIDTH when STR is shorter +than WIDTH." + (cl-loop for ini-str = str + then (substring ini-str 0 (1- (length ini-str))) + for sw = (string-width ini-str) + when (<= sw width) return + (concat ini-str endstr (make-string (- width sw) ? )))) + +(defun helm-string-multibyte-p (str) + "Check if string STR contains multibyte characters." + (cl-loop for c across str + thereis (> (char-width c) 1))) + +(defun helm-get-pid-from-process-name (process-name) + "Get pid from running process PROCESS-NAME." + ;; Protect system processes calls (Issue #2497) + ;; Ensure `list-system-processes' and `process-attributes' don't run + ;; on remote (only Emacs-28/29+). + (cl-loop with default-directory = temporary-file-directory + with process-list = (list-system-processes) + for pid in process-list + for process = (assoc-default 'comm (process-attributes pid)) + when (and process (string-match process-name process)) + return pid)) + +(defun helm-ff-find-printers () + "Return a list of available printers on Unix systems." + (when (executable-find "lpstat") + (let ((printer-list (with-temp-buffer + (call-process "lpstat" nil t nil "-a") + (split-string (buffer-string) "\n")))) + (cl-loop for p in printer-list + for printer = (car (split-string p)) + when printer + collect printer)))) + +(defun helm-region-active-p () + (and transient-mark-mode mark-active (/= (mark) (point)))) + +(defun helm-quote-whitespace (candidate) + "Quote whitespace, if some, in string CANDIDATE." + (replace-regexp-in-string " " "\\\\ " candidate)) + +(defun helm-current-line-contents () + "Current line string without properties." + (buffer-substring-no-properties (point-at-bol) (point-at-eol))) + +(defun helm--replace-regexp-in-buffer-string (regexp rep str &optional fixedcase literal subexp start) + "Replace REGEXP by REP in string STR. + +Same as `replace-regexp-in-string' but handle properly REP as +function with SUBEXP specified. + +E.g.: + + (helm--replace-regexp-in-buffer-string + \"e\\\\(m\\\\)acs\" \\='upcase \"emacs\" t nil 1) + => \"eMacs\" + + (replace-regexp-in-string + \"e\\\\(m\\\\)acs\" \\='upcase \"emacs\" t nil 1) + => \"eEMACSacs\" + +Also START argument behaves as expected unlike +`replace-regexp-in-string'. + +E.g.: + + (helm--replace-regexp-in-buffer-string \"f\" \"r\" \"foofoo\" t nil nil 3) + => \"fooroo\" + + (replace-regexp-in-string \"f\" \"r\" \"foofoo\" t nil nil 3) + => \"roo\" + +Unlike `replace-regexp-in-string' this function is buffer-based +implemented i.e. replacement is computed inside a temp buffer, so +REGEXP should be used differently than with +`replace-regexp-in-string'. + +NOTE: This function is used internally for +`helm-ff-query-replace-on-filenames' and builded for this. +You should use `replace-regexp-in-string' instead unless the +behaviour of this function is really needed." + (with-temp-buffer + (insert str) + (goto-char (or start (point-min))) + (while (re-search-forward regexp nil t) + (replace-match (cond ((and (functionp rep) subexp) + (funcall rep (match-string subexp))) + ((functionp rep) + (funcall rep str)) + (t rep)) + fixedcase literal nil subexp)) + (buffer-string))) + +(defun helm-url-unhex-string (str) + "Same as `url-unhex-string' but ensure STR is completely decoded." + (setq str (or str "")) + (with-temp-buffer + (save-excursion (insert str)) + (while (re-search-forward "%[A-Za-z0-9]\\{2\\}" nil t) + (replace-match (byte-to-string (string-to-number + (substring (match-string 0) 1) + 16)) + t t) + ;; Restart from beginning until string is completely decoded. + (goto-char (point-min))) + (decode-coding-string (buffer-string) 'utf-8))) + +(defun helm-read-answer (prompt answer-list) + "Prompt user for an answer. +Arg PROMPT is the prompt to present user the different possible +answers, ANSWER-LIST is a list of strings. +If user enters an answer which is one of ANSWER-LIST return this +answer, otherwise keep prompting for a valid answer. +Note that answer should be a single char, only short answer are +accepted. + +Example: + + (pcase (helm-read-answer + \"answer [y,n,!,q]: \" + \\='(\"y\" \"n\" \"!\" \"q\")) + (\"y\" \"yes\") + (\"n\" \"no\") + (\"!\" \"all\") + (\"q\" \"quit\")) + +" + (helm-awhile (read-key (propertize prompt 'face 'minibuffer-prompt)) + (let ((str (and (characterp it) (string it)))) + (if (and str (member str answer-list)) + (cl-return str) + (message "Please answer by %s" (mapconcat 'identity answer-list ", ")) + (sit-for 1))))) + +(defun helm-read-answer-dolist-with-action (prompt list action) + "Read answer with PROMPT and execute ACTION on each element of LIST. + +Argument PROMPT is a format spec string e.g. \"Do this on %s?\" +which take each elements of LIST as argument, no need to provide +the help part i.e. [y,n,!,q] it will be already added. + +While looping through LIST, ACTION is executed on each elements +differently depending of answer: + +- y Execute ACTION on element. +- n Skip element. +- ! Don't ask anymore and execute ACTION on remaining elements. +- q Skip all remaining elements." + (let (dont-ask) + (catch 'break + (dolist (elm list) + (if dont-ask + (funcall action elm) + (pcase (helm-read-answer + (format (concat prompt "[y,n,!,q]") elm) + '("y" "n" "!" "q")) + ("y" (funcall action elm)) + ("n" (ignore)) + ("!" (prog1 + (funcall action elm) + (setq dont-ask t))) + ("q" (throw 'break nil)))))))) + +(defsubst helm-string-numberp (str) + "Return non nil if string STR represent a number." + (cl-assert (stringp str) t) + (or (cl-loop for c across str always (char-equal c ?0)) + (not (zerop (string-to-number str))))) + +;;; Symbols routines +;; +(defun helm-symbolify (str-or-sym) + "Get symbol of STR-OR-SYM." + (cond ((symbolp str-or-sym) + str-or-sym) + ((equal str-or-sym "") nil) + (t (intern str-or-sym)))) + +(defun helm-symbol-name (obj) + (if (or (and (consp obj) (functionp obj)) + (byte-code-function-p obj) + (helm-subr-native-elisp-p obj)) + "Anonymous" + (symbol-name obj))) + +(defun helm-describe-class (class) + "Display documentation of Eieio CLASS, a symbol or a string." + (advice-add 'cl--print-table :override #'helm-source--cl--print-table '((depth . 100))) + (unwind-protect + (let ((helm-describe-function-function 'describe-function)) + (helm-describe-function class)) + (advice-remove 'cl--print-table #'helm-source--cl--print-table))) + +(defun helm-describe-function (func) + "Display documentation of FUNC, a symbol or string." + (cl-letf (((symbol-function 'message) #'ignore)) + (funcall helm-describe-function-function (helm-symbolify func)))) + +(defun helm-describe-variable (var) + "Display documentation of VAR, a symbol or a string." + (cl-letf (((symbol-function 'message) #'ignore)) + (funcall helm-describe-variable-function (helm-symbolify var)))) + +(defun helm-describe-face (face) + "Display documentation of FACE, a symbol or a string." + (let ((faces (helm-marked-candidates))) + (cl-letf (((symbol-function 'message) #'ignore)) + (describe-face (if (cdr faces) + (mapcar 'helm-symbolify faces) + (helm-symbolify face)))))) + +(defun helm-elisp--persistent-help (candidate fun &optional name) + "Used to build persistent actions describing CANDIDATE with FUN. +Argument NAME is used internally to know which command to use +when symbol CANDIDATE refers at the same time to a variable and a +function. +See `helm-elisp-show-help'." + (let ((hbuf (get-buffer (help-buffer)))) + (cond ((helm-follow-mode-p) + (if name + (funcall fun candidate name) + (funcall fun candidate))) + ((or (and (helm-get-attr 'help-running-p) + (string= candidate (helm-get-attr 'help-current-symbol)))) + (progn + ;; When started from a help buffer, + ;; Don't kill this buffer as it is helm-current-buffer. + (unless (equal hbuf helm-current-buffer) + (kill-buffer hbuf) + (set-window-buffer (get-buffer-window hbuf) + ;; It is generally + ;; helm-current-buffer but it may + ;; be another buffer when helm have + ;; been started from a dedicated window. + (if helm--buffer-in-new-frame-p + helm-current-buffer + helm-persistent-action-window-buffer))) + (helm-set-attr 'help-running-p nil)) + ;; Force running update hook to may be delete + ;; helm-persistent-action-display-window, this is done in + ;; helm-persistent-action-display-window (the function). + (unless helm--buffer-in-new-frame-p + (helm-update (regexp-quote (helm-get-selection))))) + (t + (if name + (funcall fun candidate name) + (funcall fun candidate)) + (helm-set-attr 'help-running-p t))) + (helm-set-attr 'help-current-symbol candidate))) + +(defcustom helm-find-function-default-project nil + "Default directories to search symbols definitions from `helm-apropos'. +A list of directories or a single directory name. +Helm will allow you selecting one of those directories with `M-n' when +using a prefix arg with the `find-function' action in `helm-apropos'. +This is a good idea to add the directory names of the projects you are +working on to quickly jump to the definitions in the project source +files instead of jumping to the loaded files located in `load-path'." + :type '(choice (repeat string) + string) + :group 'helm-elisp) + +(defun helm-find-function-noselect (func &optional root-dir type) + "Find FUNC definition without selecting buffer. +FUNC can be a symbol or a string. +Instead of looking in LOAD-PATH to find library, this function +search in all subdirs of ROOT-DIR, if ROOT-DIR is unspecified ask for +it with completion. +TYPE when nil specify function, for other values see +`find-function-regexp-alist'." + (require 'find-func) + (let* ((sym (helm-symbolify func)) + (dir (or root-dir (helm-read-file-name + "Project directory: " + :test 'file-directory-p + :default (helm-mklist helm-find-function-default-project) + :must-match t))) + (find-function-source-path + (cons dir (helm-walk-directory dir + :directories 'only + :path 'full))) + (symbol-lib (helm-acase type + ((defvar defface) + (or (symbol-file sym it) + (help-C-file-name sym 'var))) + (t (cdr (find-function-library sym))))) + (library (find-library-name + (helm-basename symbol-lib t)))) + (find-function-search-for-symbol sym type library))) + +(defun helm-find-function (func) + "Try to jump to FUNC definition. +With a prefix arg ask for the project directory to search in instead of +using LOAD-PATH." + (if (not helm-current-prefix-arg) + (find-function (helm-symbolify func)) + (let ((place (helm-find-function-noselect func))) + (when place + (switch-to-buffer (car place)) (goto-char (cdr place)))))) + +(defun helm-find-variable (var) + "Try to jump to VAR definition. +With a prefix arg ask for the project directory to search in instead of +using LOAD-PATH." + (if (not helm-current-prefix-arg) + (find-variable (helm-symbolify var)) + (let ((place (helm-find-function-noselect var nil 'defvar))) + (when place + (switch-to-buffer (car place)) (goto-char (cdr place)))))) + +(defun helm-find-face-definition (face) + "Try to jump to FACE definition. +With a prefix arg ask for the project directory to search in instead of +using LOAD-PATH." + (if (not helm-current-prefix-arg) + (find-face-definition (helm-symbolify face)) + (let ((place (helm-find-function-noselect face nil 'defface))) + (when place + (switch-to-buffer (car place)) (goto-char (cdr place)))))) + +(defun helm-kill-new (candidate &optional replace) + "CANDIDATE is symbol or string. +See `kill-new' for argument REPLACE." + (kill-new (helm-stringify candidate) replace)) + + +;;; Modes +;; +(defun helm-same-major-mode-p (start-buffer alist) + "Decide if current-buffer is related to START-BUFFER. +Argument ALIST is an alist of associated major modes." + ;; START-BUFFER is the current-buffer where we start searching. + ;; Determine the major-mode of START-BUFFER as `cur-maj-mode'. + ;; Each time the loop go in another buffer we try from this buffer + ;; to determine if its `major-mode' is: + ;; - same as the `cur-maj-mode' + ;; - derived from `cur-maj-mode' and from + ;; START-BUFFER if its mode is derived from the one in START-BUFFER. + ;; - have an assoc entry (major-mode . cur-maj-mode) + ;; - have an rassoc entry (cur-maj-mode . major-mode) + ;; - check if one of these entries inherit from another one in + ;; `alist'. + (let* ((cur-maj-mode (with-current-buffer start-buffer major-mode)) + (maj-mode major-mode) + (c-assoc-mode (assq cur-maj-mode alist)) + (c-rassoc-mode (rassq cur-maj-mode alist)) + (o-assoc-mode (assq major-mode alist)) + (o-rassoc-mode (rassq major-mode alist)) + (cdr-c-assoc-mode (cdr c-assoc-mode)) + (cdr-o-assoc-mode (cdr o-assoc-mode))) + (or (eq major-mode cur-maj-mode) + (derived-mode-p cur-maj-mode) + (with-current-buffer start-buffer + (derived-mode-p maj-mode)) + (or (eq cdr-c-assoc-mode major-mode) + (eq (car c-rassoc-mode) major-mode) + (eq (cdr (assq cdr-c-assoc-mode alist)) + major-mode) + (eq (car (rassq cdr-c-assoc-mode alist)) + major-mode)) + (or (eq cdr-o-assoc-mode cur-maj-mode) + (eq (car o-rassoc-mode) cur-maj-mode) + (eq (cdr (assq cdr-o-assoc-mode alist)) + cur-maj-mode) + (eq (car (rassq cdr-o-assoc-mode alist)) + cur-maj-mode))))) + +;;; Source processing +;; +(defun helm-map-candidates-in-source (src fn pred) + "Map over all candidates in SRC and execute FN if PRED returns non nil. +Arg FN and PRED are functions called with current display part of +candidate as arg." + (declare (indent 1)) + (save-excursion + (goto-char (helm-get-previous-header-pos)) + (helm-next-line) + (let* ((next-head (helm-get-next-header-pos)) + (end (and next-head + (save-excursion + (goto-char next-head) + (forward-line -1) + (point)))) + (maxpoint (or end (point-max)))) + (while (< (point) maxpoint) + (helm-mark-current-line) + (let ((cand (helm-get-selection nil 'withprop src))) + (when (funcall pred cand) + (funcall fn cand))) + (forward-line 1) (end-of-line))))) + +;;; Files routines +;; +(defun helm-file-name-sans-extension (filename) + "Same as `file-name-sans-extension' but remove all extensions." + (helm-aif (file-name-sans-extension filename) + ;; Start searching at index 1 for files beginning with a dot + ;; (bug#1335). + (if (string-match "\\." (helm-basename it) 1) + (helm-file-name-sans-extension it) + it))) + +(defsubst helm-file-name-extension (file) + "Returns FILE extension if it is not a number." + (helm-aif (file-name-extension file) + (and (not (helm-string-numberp it)) it))) + +(defun helm-basename (fname &optional ext) + "Print FNAME with any leading directory components removed. +If specified, also remove filename extension EXT. +Arg EXT can be specified as a string with or without dot, in this +case it should match `file-name-extension'. +It can also be non-nil (t) in this case no checking of +`file-name-extension' is done and the extension is removed +unconditionally." + (let ((non-essential t)) + (if (and ext (or (string= (file-name-extension fname) ext) + (string= (file-name-extension fname t) ext) + (eq ext t)) + (not (file-directory-p fname))) + (file-name-sans-extension (file-name-nondirectory fname)) + (file-name-nondirectory (directory-file-name fname))))) + +(defun helm-basedir (fname &optional parent) + "Return the base directory of filename ending by a slash. +If PARENT is specified and FNAME is a directory return the parent +directory of FNAME." + (helm-aif (and fname + (or (and (string= fname "~") "~") + (file-name-directory + (if parent + (directory-file-name fname) + fname)))) + (file-name-as-directory it))) + +(defun helm-current-directory () + "Return current-directory name at point. +Useful in dired buffers when there is inserted subdirs." + (expand-file-name + (if (eq major-mode 'dired-mode) + (dired-current-directory) + default-directory))) + +(defun helm-shadow-boring-files (files) + "Files matching `helm-boring-file-regexp' will be +displayed with the `file-name-shadow' face if available." + (helm-shadow-entries files helm-boring-file-regexp-list)) + +(defun helm-skip-boring-files (files) + "Files matching `helm-boring-file-regexp' will be skipped." + (helm-skip-entries files helm-boring-file-regexp-list)) + +(defun helm-skip-current-file (files) + "Current file will be skipped." + (remove (buffer-file-name helm-current-buffer) files)) + +(defun helm-w32-pathname-transformer (args) + "Change undesirable features of windows pathnames to ones more acceptable to +other candidate transformers." + (if (eq system-type 'windows-nt) + (helm-transform-mapcar + (lambda (x) + (replace-regexp-in-string + "/cygdrive/\\(.\\)" "\\1:" + (replace-regexp-in-string "\\\\" "/" x))) + args) + args)) + +(defun helm-w32-prepare-filename (file) + "Convert filename FILE to something usable by external w32 executables." + (replace-regexp-in-string ; For UNC paths + "/" "\\" + (replace-regexp-in-string ; Strip cygdrive paths + "/cygdrive/\\(.\\)" "\\1:" + file nil nil) nil t)) + +(defun helm-w32-shell-execute-open-file (file) + (with-no-warnings + (w32-shell-execute "open" (helm-w32-prepare-filename file)))) + +;; Same as `vc-directory-exclusion-list'. +(defvar helm-walk-ignore-directories + '("SCCS/" "RCS/" "CVS/" "MCVS/" ".svn/" ".git/" ".hg/" ".bzr/" + "_MTN/" "_darcs/" "{arch}/" ".gvfs/")) + +(defsubst helm--dir-file-name (file dir) + (expand-file-name + (substring file 0 (1- (length file))) dir)) + +(defsubst helm--dir-name-p (str) + (char-equal (aref str (1- (length str))) ?/)) + +(cl-defun helm-walk-directory (directory &key (path 'basename) + directories + match skip-subdirs + noerror) + "Walk through DIRECTORY tree. + +Argument PATH can be one of basename, relative, full, or a +function called on file name, default to basename. + +Argument DIRECTORIES when t return also directories names, +otherwise skip directories names, with a value of `only' returns +only subdirectories, i.e. files are skipped. + +Argument MATCH is a regexp matching files or directories. + +Argument SKIP-SUBDIRS when t will skip +`helm-walk-ignore-directories', otherwise if it is given as a +list of directories, this list will be used instead of +`helm-walk-ignore-directories'. + +Argument NOERROR when t will skip directories which are not +accessible." + (let ((fn (cl-case path + (basename 'file-name-nondirectory) + (relative 'file-relative-name) + (full 'identity) + (t path)))) ; A function. + (setq skip-subdirs (if (listp skip-subdirs) + skip-subdirs + helm-walk-ignore-directories)) + (cl-labels ((ls-rec (dir) + (unless (file-symlink-p dir) + (cl-loop for f in (sort (file-name-all-completions "" dir) + 'string-lessp) + unless (member f '("./" "../")) + ;; A directory. + ;; Use `helm--dir-file-name' to remove the final slash. + ;; Needed to avoid infloop on directory symlinks. + if (and (helm--dir-name-p f) + (helm--dir-file-name f dir)) + nconc + (unless (or (member f skip-subdirs) + (and noerror + (not (file-accessible-directory-p it)))) + (if (and directories + (or (null match) + (string-match match f))) + (nconc (list (concat (funcall fn it) "/")) + (ls-rec it)) + (ls-rec it))) + ;; A regular file. + else nconc + (when (and (null (eq directories 'only)) + (or (null match) (string-match match f))) + (list (funcall fn (expand-file-name f dir)))))))) + (ls-rec directory)))) + +(defun helm-file-expand-wildcards (pattern &optional full) + "Same as `file-expand-wildcards' but allow recursion. +Recursion happens when PATTERN starts with two stars. +Directories expansion is not supported." + (let ((bn (helm-basename pattern)) + (case-fold-search nil)) + (if (and helm-file-globstar + (string-match "\\`\\*\\{2\\}\\(.*\\)" bn)) + (helm-walk-directory (helm-basedir pattern) + :path (cl-case full + (full 'full) + (relative 'relative) + ((basename nil) 'basename) + (t 'full)) + :directories nil + :match (or (helm-wildcard-to-regexp bn) + (wildcard-to-regexp bn)) + :skip-subdirs t) + (helm-aif (helm-wildcard-to-regexp bn) + (directory-files (helm-basedir pattern) full it) + ;; `file-expand-wildcards' fails to expand weird directories + ;; like "[ foo.zz ] bar.*.avi", fallback to `directory-files' + ;; in such cases. + (or (file-expand-wildcards pattern full) + (directory-files (helm-basedir pattern) + full (wildcard-to-regexp bn))))))) + +(defun helm-wildcard-to-regexp (wc) + "Transform wilcard WC like \"**.{jpg,jpeg}\" in REGEXP." + (when (string-match ".*\\(\\*\\{1,2\\}\\)\\.[{]\\(.*\\)[}]\\'" wc) + (format ".*\\.\\(%s\\)$" + (replace-regexp-in-string + "," "\\\\|" (match-string 2 wc))))) + +;;; helm internals +;; +(defun helm-set-pattern (pattern &optional noupdate) + "Set minibuffer contents to PATTERN. +If optional NOUPDATE is non-nil, the Helm buffer is not changed." + (with-selected-window (or (active-minibuffer-window) (minibuffer-window)) + (delete-minibuffer-contents) + (insert pattern)) + (when noupdate + (setq helm-pattern pattern))) + +(defun helm-minibuffer-completion-contents () + "Return the user input in a minibuffer before point as a string. +That is what completion commands operate on." + (buffer-substring (field-beginning) (point))) + +(defmacro with-helm-buffer (&rest body) + "Eval BODY inside `helm-buffer'." + (declare (indent 0) (debug t)) + `(with-current-buffer (helm-buffer-get) + ,@body)) + +(defmacro with-helm-current-buffer (&rest body) + "Eval BODY inside `helm-current-buffer'." + (declare (indent 0) (debug t)) + `(with-current-buffer (or (and (buffer-live-p helm-current-buffer) + helm-current-buffer) + (setq helm-current-buffer + (current-buffer))) + ,@body)) + +(defun helm-buffer-get () + "Return `helm-action-buffer' if shown otherwise `helm-buffer'." + (if (helm-action-window) + helm-action-buffer + helm-buffer)) + +(defun helm-window () + "Window of `helm-buffer'." + (get-buffer-window (helm-buffer-get) 0)) + +(defun helm-action-window () + "Window of `helm-action-buffer'." + (get-buffer-window helm-action-buffer 'visible)) + +(defmacro with-helm-window (&rest body) + "Be sure BODY is excuted in the helm window." + (declare (indent 0) (debug t)) + `(with-selected-window (helm-window) + ,@body)) + +(defmacro helm-without-follow (&rest body) + "Ensure BODY runs without following. +I.e. when using `helm-next-line' and friends in BODY." + (declare (indent 0) (debug t)) + `(cl-letf (((symbol-function 'helm-follow-mode-p) + (lambda (&optional _) nil))) + (let (helm-follow-mode-persistent) + (progn ,@body)))) + +;; Completion styles related functions +;; +(defun helm--setup-completion-styles-alist () + (cl-pushnew '(helm helm-completion-try-completion + helm-completion-all-completions + "helm multi completion style.") + completion-styles-alist + :test 'equal) + (unless (assq 'flex completion-styles-alist) + ;; Add helm-fuzzy style only if flex is not available. + (cl-pushnew '(helm-flex helm-flex-completion-try-completion + helm-flex-completion-all-completions + "helm flex completion style.\nProvide flex matching for emacs-26.") + completion-styles-alist + :test 'equal))) + +(defvar helm-blacklist-completion-styles '(emacs21 emacs22)) +(defun helm--prepare-completion-styles (&optional com-or-mode styles) + "Return a suitable list of styles for `completion-styles'. + +When `helm-completion-style' is not `emacs' the Emacs vanilla +default `completion-styles' is used except for +`helm-dynamic-completion' which uses inconditionally `emacs' as +value for `helm-completion-style'. + +If styles are specified in `helm-completion-styles-alist' for a +particular mode, use these styles for the corresponding mode. +If COM-OR-MODE (a mode or a command) is specified it is used to find the +corresponding styles in `helm-completion-styles-alist'. + +If STYLES is specified as a list of styles suitable for +`completion-styles' these styles are used in the given order. +Otherwise helm style is added to `completion-styles' always after +flex or helm-flex completion style if present." + ;; For `helm-completion-style' and `helm-completion-styles-alist'. + (require 'helm-mode) + (let ((from (if com-or-mode com-or-mode major-mode))) + (if (memq helm-completion-style '(helm helm-fuzzy)) + ;; Keep default settings, but probably nil is fine as well. + '(basic partial-completion emacs22) + (or + styles + (pcase (cdr (assq from helm-completion-styles-alist)) + (`(,_l . ,ll) ll)) + ;; We need to have flex always behind helm, otherwise + ;; when matching against e.g. '(foo foobar foao frogo bar + ;; baz) with pattern "foo" helm style if before flex will + ;; return foo and foobar only defeating flex that would + ;; return foo foobar foao and frogo. + (let* ((wflex (car (or (assq 'flex completion-styles-alist) + (assq 'helm-flex completion-styles-alist)))) + (styles (append (and (memq wflex completion-styles) + (list wflex)) + (cl-loop for s in completion-styles + unless (or (memq s helm-blacklist-completion-styles) + (memq wflex completion-styles)) + collect s)))) + (helm-append-at-nth + styles '(helm) + (if (memq wflex completion-styles) + 1 0))))))) + +(defun helm-dynamic-completion (collection predicate &optional point metadata nomode styles) + "Build a completion function for `helm-pattern' in COLLECTION. + +Only the elements of COLLECTION that satisfy PREDICATE are considered. + +Argument POINT is the same as in `completion-all-completions' and +is meaningful only when using some kind of `completion-at-point'. + +The return value is a list of completions that may be sorted by +the sort function provided by the completion-style in +use (emacs-27 only), otherwise (emacs-26) the sort function has +to be provided if needed either with an FCT function in source or +by passing the sort function with METADATA +E.g.: (metadata (display-sort-function . foo)). + +If you don't want the sort fn provided by style to kick +in (emacs-27) you can use as metadata value the symbol `nosort'. + +Example: + + (helm :sources (helm-build-sync-source \"test\" + :candidates (helm-dynamic-completion + \\='(foo bar baz foab) + \\='symbolp) + :match-dynamic t) + :buffer \"*helm test*\") + +When argument NOMODE is non nil don't use `completion-styles' as +specified in `helm-completion-styles-alist' for specific modes. + +When STYLES is specified use these `completion-styles', see +`helm--prepare-completion-styles'. + +Also `helm-completion-style' settings have no effect here, +`emacs' being used inconditionally as value." + (lambda () + (let* (;; Force usage of emacs style otherwise + ;; helm--prepare-completion-styles will reset + ;; completion-styles to default value i.e. (basic partial + ;; emacs22). + (helm-completion-style 'emacs) + (completion-styles + (with-helm-current-buffer + (helm--prepare-completion-styles nomode styles))) + (completion-flex-nospace t) + (nosort (eq metadata 'nosort)) + (compsfn (lambda (str pred _action) + (let* ((completion-ignore-case (helm-set-case-fold-search)) + (comps (completion-all-completions + str + (if (functionp collection) + (funcall collection str pred t) + collection) + pred + (or point 0) + (or (and (listp metadata) metadata) + (setq metadata '(metadata))))) + (last-data (last comps)) + (sort-fn (unless nosort + (completion-metadata-get + metadata 'display-sort-function))) + all) + (when (cdr last-data) + (setcdr last-data nil)) + (setq all (copy-sequence comps)) + (if (and sort-fn (> (length str) 0)) + (funcall sort-fn all) + all))))) + ;; Ensure circular objects are removed. + (complete-with-action t compsfn helm-pattern predicate)))) + +(defun helm-guess-filename-at-point () + (with-helm-current-buffer + ;; Ensure to disable the evil `ffap-machine-at-point' which may run here as + ;; `file-name-at-point-functions' contains by default + ;; `ffap-guess-file-name-at-point' See bug#2574. + ;; Use same value as in Emacs-29 for next 3 vars to ensure `ffap-machine-p' + ;; never ping. + (let ((ffap-machine-p-known 'accept) + (ffap-machine-p-local 'reject) + (ffap-machine-p-unknown 'reject)) + (run-hook-with-args-until-success 'file-name-at-point-functions)))) + +;; Yank text at point. +;; +;; +(defun helm-yank-text-at-point (arg) + "Yank text at point in `helm-current-buffer' into minibuffer." + (interactive "p") + (with-helm-current-buffer + (let ((fwd-fn (or helm-yank-text-at-point-function #'forward-word)) + diff) + ;; Start to initial point if C-w have never been hit. + (unless helm-yank-point + (setq helm-yank-point (car helm-current-position))) + (save-excursion + (goto-char helm-yank-point) + (helm-set-pattern + (if (< arg 0) + (with-temp-buffer + (insert helm-pattern) + (let ((end (point-max))) + (goto-char end) + (funcall fwd-fn -1) + (setq diff (- end (point))) + (delete-region (point) end) + (buffer-string))) + (funcall fwd-fn arg) + (concat + ;; Allow yankink beyond eol allow inserting e.g long + ;; urls in mail buffers. + helm-pattern (replace-regexp-in-string + "\\`\n" "" + (buffer-substring-no-properties + helm-yank-point (point)))))) + (setq helm-yank-point (if diff (- (point) diff) (point))))))) +(put 'helm-yank-text-at-point 'helm-only t) + +(defun helm-undo-yank-text-at-point () + "Undo last entry added by `helm-yank-text-at-point'." + (interactive) + (helm-yank-text-at-point -1)) +(put 'helm-undo-yank-text-at-point 'helm-only t) + +(defun helm-reset-yank-point () + (setq helm-yank-point nil)) + +(add-hook 'helm-cleanup-hook 'helm-reset-yank-point) +(add-hook 'helm-after-initialize-hook 'helm-reset-yank-point) + +;;; Ansi +;; +;; +(defvar helm--ansi-color-regexp + "\033\\[\\(K\\|[0-9;]*m\\)") +(defvar helm--ansi-color-drop-regexp + "\033\\[\\([ABCDsuK]\\|[12][JK]\\|=[0-9]+[hI]\\|[0-9;]*[Hf]\\)") +(defun helm--ansi-color-apply (string) + "A version of `ansi-color-apply' immune to upstream changes. + +Similar to the emacs-24.5 version without support to +`ansi-color-context' which is buggy in Emacs. + +Modify also `ansi-color-regexp' by using own variable +`helm--ansi-color-regexp' that matches whole STRING. + +This is needed to provide compatibility for both emacs-25 and +emacs-24.5 as emacs-25 version of `ansi-color-apply' is partially +broken." + (require 'ansi-color) + (let ((start 0) + codes end escape-sequence + result colorized-substring) + ;; Find the next escape sequence. + (while (setq end (string-match helm--ansi-color-regexp string start)) + (setq escape-sequence (match-string 1 string)) + ;; Colorize the old block from start to end using old face. + (when codes + (put-text-property + start end 'font-lock-face (ansi-color--find-face codes) string)) + (setq colorized-substring (substring string start end) + start (match-end 0)) + ;; Eliminate unrecognized ANSI sequences. + (while (string-match helm--ansi-color-drop-regexp colorized-substring) + (setq colorized-substring + (replace-match "" nil nil colorized-substring))) + (push colorized-substring result) + ;; Create new face, by applying escape sequence parameters. + (setq codes (ansi-color-apply-sequence escape-sequence codes))) + ;; If the rest of the string should have a face, put it there. + (when codes + (put-text-property + start (length string) + 'font-lock-face (ansi-color--find-face codes) string)) + ;; Save the remainder of the string to the result. + (if (string-match "\033" string start) + (push (substring string start (match-beginning 0)) result) + (push (substring string start) result)) + (apply 'concat (nreverse result)))) + +(when (< emacs-major-version 26) + (advice-add 'ansi-color-apply :override #'helm--ansi-color-apply)) + + +;;; Fontlock +(dolist (mode '(emacs-lisp-mode lisp-interaction-mode)) + (font-lock-add-keywords + mode + '(("(\\<\\(with-helm-after-update-hook\\)\\>" 1 font-lock-keyword-face) + ("(\\<\\(with-helm-temp-hook\\)\\>" 1 font-lock-keyword-face) + ("(\\<\\(with-helm-window\\)\\>" 1 font-lock-keyword-face) + ("(\\<\\(with-helm-current-buffer\\)\\>" 1 font-lock-keyword-face) + ("(\\<\\(with-helm-buffer\\)\\>" 1 font-lock-keyword-face) + ("(\\<\\(with-helm-show-completion\\)\\>" 1 font-lock-keyword-face) + ("(\\<\\(with-helm-default-directory\\)\\>" 1 font-lock-keyword-face) + ("(\\<\\(with-helm-restore-variables\\)\\>" 1 font-lock-keyword-face) + ("(\\<\\(helm-multi-key-defun\\)\\>" 1 font-lock-keyword-face) + ("(\\<\\(helm-while-no-input\\)\\>" 1 font-lock-keyword-face) + ("(\\<\\(helm-aif\\)\\>" 1 font-lock-keyword-face) + ("(\\<\\(helm-awhile\\)\\>" 1 font-lock-keyword-face) + ("(\\<\\(helm-acond\\)\\>" 1 font-lock-keyword-face) + ("(\\<\\(helm-aand\\)\\>" 1 font-lock-keyword-face) + ("(\\<\\(helm-with-gensyms\\)\\>" 1 font-lock-keyword-face) + ("(\\<\\(helm-read-answer-dolist-with-action\\)\\>" 1 font-lock-keyword-face) + ("(\\<\\(helm-read-answer\\)\\>" 1 font-lock-keyword-face)))) + +(provide 'helm-lib) + +;;; helm-lib ends here diff --git a/org/elpa/helm-core-20230317.1729/helm-multi-match.el b/org/elpa/helm-core-20230317.1729/helm-multi-match.el new file mode 100644 index 0000000..594709b --- /dev/null +++ b/org/elpa/helm-core-20230317.1729/helm-multi-match.el @@ -0,0 +1,409 @@ +;;; helm-multi-match.el --- Multiple regexp matching methods for helm -*- lexical-binding: t -*- + +;; Original Author: rubikitch + +;; Copyright (C) 2008 ~ 2011 rubikitch +;; Copyright (C) 2011 ~ 2020 Thierry Volpiatto + +;; Author: Thierry Volpiatto +;; URL: http://github.com/emacs-helm/helm + +;; 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 . + +;;; Code: + +(require 'cl-lib) +(require 'helm-lib) + + +(defgroup helm-multi-match nil + "Helm multi match." + :group 'helm) + +(defcustom helm-mm-matching-method 'multi3 + "Matching method for helm match plugin. +You can set here different methods to match candidates in helm. +Here are the possible value of this symbol and their meaning: +- multi1: Respect order, prefix of pattern must match. +- multi2: Same but with partial match. +- multi3: The best, multiple regexp match, allow negation. +- multi3p: Same but prefix must match. + +Default is multi3, you should keep this for a better experience. + +Note that multi1 and multi3p are incompatible with fuzzy matching +in file completion and by the way fuzzy matching will be disabled there +when these options are used." + :type '(radio :tag "Matching methods for helm" + (const :tag "Multiple regexp 1 ordered with prefix match" multi1) + (const :tag "Multiple regexp 2 ordered with partial match" multi2) + (const :tag "Multiple regexp 3 matching no order, partial, best." multi3) + (const :tag "Multiple regexp 3p matching with prefix match" multi3p)) + :group 'helm-multi-match) + + +;; Internal +(defvar helm-mm-default-match-functions + '(helm-mm-exact-match helm-mm-match)) +(defvar helm-mm-default-search-functions + '(helm-mm-exact-search helm-mm-search)) + + +;;; Build regexps +;; +;; +(defconst helm-mm-space-regexp "\\s\\\\s-" + "Regexp to represent space itself in multiple regexp match.") + +(defun helm-mm-split-pattern (pattern &optional grep-space) + "Split PATTERN if it contains spaces and return resulting list. +If spaces in PATTERN are escaped, don't split at this place. +i.e \"foo bar baz\"=> (\"foo\" \"bar\" \"baz\") +but \"foo\\ bar baz\"=> (\"foo\\s-bar\" \"baz\"). +If GREP-SPACE is used translate escaped space to \"\\s\" instead of \"\\s-\"." + (split-string + ;; Match spaces litteraly because candidate buffer syntax-table + ;; doesn't understand "\s-" properly. + (replace-regexp-in-string + helm-mm-space-regexp + (if grep-space "\\s" "\\s-") pattern nil t))) + +(defun helm-mm-1-make-regexp (pattern) + "Replace spaces in PATTERN with \".*\"." + (mapconcat 'identity (helm-mm-split-pattern pattern) ".*")) + + +;;; Exact match. +;; +;; +;; Internal. +(defvar helm-mm-exact-pattern-str nil) +(defvar helm-mm-exact-pattern-real nil) + +(defun helm-mm-exact-get-pattern (pattern) + (unless (equal pattern helm-mm-exact-pattern-str) + (setq helm-mm-exact-pattern-str pattern + helm-mm-exact-pattern-real (concat "\n" pattern "\n"))) + helm-mm-exact-pattern-real) + + +(cl-defun helm-mm-exact-match (candidate &optional (pattern helm-pattern)) + (if case-fold-search + (progn + (setq candidate (downcase candidate) + pattern (downcase pattern)) + (string= candidate pattern)) + (string= candidate pattern))) + +(defun helm-mm-exact-search (pattern &rest _ignore) + (and (search-forward (helm-mm-exact-get-pattern pattern) nil t) + (forward-line -1))) + + +;;; Prefix match +;; +;; +;; Internal +(defvar helm-mm-prefix-pattern-str nil) +(defvar helm-mm-prefix-pattern-real nil) + +(defun helm-mm-prefix-get-pattern (pattern) + (unless (equal pattern helm-mm-prefix-pattern-str) + (setq helm-mm-prefix-pattern-str pattern + helm-mm-prefix-pattern-real (concat "\n" pattern))) + helm-mm-prefix-pattern-real) + +(defun helm-mm-prefix-match (candidate &optional pattern) + ;; In filename completion basename and basedir may be + ;; quoted, unquote them for string comparison (Bug#1283). + (setq pattern (replace-regexp-in-string + "\\\\" "" (or pattern helm-pattern))) + (let ((len (length pattern))) + (and (<= len (length candidate)) + (string= (substring candidate 0 len) pattern )))) + +(defun helm-mm-prefix-search (pattern &rest _ignore) + (search-forward (helm-mm-prefix-get-pattern pattern) nil t)) + + +;;; Multiple regexp patterns 1 (order is preserved / prefix). +;; +;; +;; Internal +(defvar helm-mm-1-pattern-str nil) +(defvar helm-mm-1-pattern-real nil) + +(defun helm-mm-1-get-pattern (pattern) + (unless (equal pattern helm-mm-1-pattern-str) + (setq helm-mm-1-pattern-str pattern + helm-mm-1-pattern-real + (concat "^" (helm-mm-1-make-regexp pattern)))) + helm-mm-1-pattern-real) + +(cl-defun helm-mm-1-match (candidate &optional (pattern helm-pattern)) + (string-match (helm-mm-1-get-pattern pattern) candidate)) + +(defun helm-mm-1-search (pattern &rest _ignore) + (re-search-forward (helm-mm-1-get-pattern pattern) nil t)) + + +;;; Multiple regexp patterns 2 (order is preserved / partial). +;; +;; +;; Internal +(defvar helm-mm-2-pattern-str nil) +(defvar helm-mm-2-pattern-real nil) + +(defun helm-mm-2-get-pattern (pattern) + (unless (equal pattern helm-mm-2-pattern-str) + (setq helm-mm-2-pattern-str pattern + helm-mm-2-pattern-real + (concat "^.*" (helm-mm-1-make-regexp pattern)))) + helm-mm-2-pattern-real) + +(cl-defun helm-mm-2-match (candidate &optional (pattern helm-pattern)) + (string-match (helm-mm-2-get-pattern pattern) candidate)) + +(defun helm-mm-2-search (pattern &rest _ignore) + (re-search-forward (helm-mm-2-get-pattern pattern) nil t)) + + +;;; Multiple regexp patterns 3 (permutation). +;; +;; +;; Internal +(defvar helm-mm--3-pattern-str nil) +(defvar helm-mm--3-pattern-list nil) + +(defun helm-mm-3-get-patterns (pattern) + "Return a list of predicate/regexp cons cells. +E.g., ((identity . \"foo\") (not . \"bar\")). +If PATTERN is unchanged, don't recompute PATTERN and return the +previous value stored in `helm-mm--3-pattern-list'." + (unless (equal pattern helm-mm--3-pattern-str) + (setq helm-mm--3-pattern-str pattern + helm-mm--3-pattern-list + (helm-mm-3-get-patterns-internal pattern))) + helm-mm--3-pattern-list) + +(defun helm-mm-3-get-patterns-internal (pattern) + "Return a list of predicate/regexp cons cells. +E.g., ((identity . \"foo\") (not . \"bar\"))." + (unless (string= pattern "") + (cl-loop for pat in (helm-mm-split-pattern pattern) + collect (if (char-equal ?! (aref pat 0)) + (cons 'not (substring pat 1)) + (cons 'identity pat))))) + +(defun helm-mm-regexp-p (string) + (string-match-p "[][*+^$.?]" string)) + +(defvar helm-mm--match-on-diacritics nil) + +(cl-defun helm-mm-3-match (candidate &optional (pattern helm-pattern)) + "Check if PATTERN match CANDIDATE. +When PATTERN contains a space, it is splitted and matching is +done with the several resulting regexps against CANDIDATE. +E.g., \"bar foo\" will match \"foobar\" and \"barfoo\". +Argument PATTERN, a string, is transformed in a list of cons cell +with `helm-mm-3-get-patterns' if it contains a space. +E.g., \"foo bar\"=>((identity . \"foo\") (identity . \"bar\")). +Then each predicate of cons cell(s) is called with the regexp of +the same cons cell against CANDIDATE. +I.e. (identity (string-match \"foo\" \"foo bar\")) => t." + (let ((pat (helm-mm-3-get-patterns pattern))) + (cl-loop for (predicate . regexp) in pat + for re = (if (and helm-mm--match-on-diacritics + (not (helm-mm-regexp-p regexp))) + (char-fold-to-regexp regexp) + regexp) + always (funcall predicate + (condition-case _err + ;; FIXME: Probably do nothing when + ;; using fuzzy leaving the job + ;; to the fuzzy fn. + (string-match re candidate) + (invalid-regexp nil)))))) + +(defun helm-mm-3-search-base (pattern searchfn1 searchfn2) + "Try to find PATTERN in `helm-buffer' with SEARCHFN1 and SEARCHFN2. +This is the search function for `candidates-in-buffer' enabled sources. +Use the same method as `helm-mm-3-match' except it search in buffer +instead of matching on a string. +i.e (identity (re-search-forward \"foo\" (point-at-eol) t)) => t." + (cl-loop with pat = (if (stringp pattern) + (helm-mm-3-get-patterns pattern) + pattern) + with regex = (cdar pat) + with regex1 = (if (and regex + helm-mm--match-on-diacritics + (not (helm-mm-regexp-p regex))) + (char-fold-to-regexp regex) + regex) + when (eq (caar pat) 'not) return + ;; Pass the job to `helm-search-match-part'. + (prog1 (list (point-at-bol) (point-at-eol)) + (forward-line 1)) + while (condition-case _err + (funcall searchfn1 (or regex1 "") nil t) + (invalid-regexp nil)) + for bol = (point-at-bol) + for eol = (point-at-eol) + if (cl-loop for (pred . str) in (cdr pat) + for regexp = (if (and helm-mm--match-on-diacritics + (not (helm-mm-regexp-p str))) + (char-fold-to-regexp str) + str) + always + (progn (goto-char bol) + (funcall pred (condition-case _err + (funcall searchfn2 regexp eol t) + (invalid-regexp nil))))) + do (goto-char eol) and return t + else do (goto-char eol) + finally return nil)) + +(defun helm-mm-3-search (pattern &rest _ignore) + (helm-mm-3-search-base + pattern 're-search-forward 're-search-forward)) + +(defun helm-mm-3-search-on-diacritics (pattern &rest _ignore) + (let ((helm-mm--match-on-diacritics t)) + (helm-mm-3-search pattern))) + +;;; mp-3 with migemo +;; Needs https://github.com/emacs-jp/migemo +;; +(defvar helm-mm--previous-migemo-info nil + "[Internal] Cache previous migemo query.") +(make-local-variable 'helm-mm--previous-migemo-info) + +(declare-function migemo-get-pattern "ext:migemo.el") +(declare-function migemo-search-pattern-get "ext:migemo.el") + +(define-minor-mode helm-migemo-mode + "Enable migemo in helm. +It will be available in the sources handling it, +i.e. the sources which have the slot :migemo with non--nil value." + :lighter " Hmio" + :group 'helm + :global t + (cl-assert (featurep 'migemo) + nil "No feature called migemo found, install migemo.el.")) + +(defun helm-mm-migemo-get-pattern (pattern) + (let ((regex (migemo-get-pattern pattern))) + (if (ignore-errors (string-match regex "") t) + (concat regex "\\|" pattern) pattern))) + +(defun helm-mm-migemo-search-pattern-get (pattern) + (let ((regex (migemo-search-pattern-get pattern))) + (if (ignore-errors (string-match regex "") t) + (concat regex "\\|" pattern) pattern))) + +(defun helm-mm-migemo-string-match (pattern str) + "Migemo version of `string-match'." + (unless (assoc pattern helm-mm--previous-migemo-info) + (with-helm-buffer + (setq helm-mm--previous-migemo-info + (push (cons pattern (helm-mm-migemo-get-pattern pattern)) + helm-mm--previous-migemo-info)))) + (string-match (assoc-default pattern helm-mm--previous-migemo-info) str)) + +(defun helm-mm-diacritics-string-match (pattern str) + "Check if PATTERN match STR ignoring diacritics. + +If PATTERN is a regexp (i.e. `helm-mm-regexp-p') use PATTERN +unmodified, otherwise transform PATTERN with `char-fold-to-regexp'. + +This function is used to search match-part of candidate in in-buffer +sources." + (string-match (if (helm-mm-regexp-p pattern) + pattern + (char-fold-to-regexp pattern)) + str)) + +(cl-defun helm-mm-3-migemo-match (candidate &optional (pattern helm-pattern)) + (and helm-migemo-mode + (cl-loop for (pred . re) in (helm-mm-3-get-patterns pattern) + always (funcall pred (helm-mm-migemo-string-match re candidate))))) + +(defun helm-mm-migemo-forward (word &optional bound noerror count) + (with-helm-buffer + (unless (assoc word helm-mm--previous-migemo-info) + (setq helm-mm--previous-migemo-info + (push (cons word (if (delq 'ascii (find-charset-string word)) + word + (helm-mm-migemo-search-pattern-get word))) + helm-mm--previous-migemo-info)))) + (re-search-forward + (assoc-default word helm-mm--previous-migemo-info) bound noerror count)) + +(defun helm-mm-3-migemo-search (pattern &rest _ignore) + (and helm-migemo-mode + (helm-mm-3-search-base + pattern 'helm-mm-migemo-forward 'helm-mm-migemo-forward))) + + +;;; mp-3p- (multiple regexp pattern 3 with prefix search) +;; +;; +(defun helm-mm-3p-match (candidate &optional pattern) + "Check if PATTERN match CANDIDATE. +Same as `helm-mm-3-match' but only for the cdr of patterns, the car of +patterns must always match CANDIDATE prefix. +E.g. \"bar foo baz\" will match \"barfoobaz\" or \"barbazfoo\" but not +\"foobarbaz\" whereas `helm-mm-3-match' would match all." + (let* ((pat (helm-mm-3-get-patterns (or pattern helm-pattern))) + (first (car pat))) + (and (funcall (car first) (helm-mm-prefix-match candidate (cdr first))) + (cl-loop for (predicate . regexp) in (cdr pat) + always (funcall predicate (string-match regexp candidate)))))) + +(defun helm-mm-3p-search (pattern &rest _ignore) + (helm-mm-3-search-base + pattern 'helm-mm-prefix-search 're-search-forward)) + + +;;; Generic multi-match/search functions +;; +;; +(cl-defun helm-mm-match (candidate &optional (pattern helm-pattern)) + "Call `helm-mm-matching-method' function against CANDIDATE." + (let ((fun (cl-ecase helm-mm-matching-method + (multi1 #'helm-mm-1-match) + (multi2 #'helm-mm-2-match) + (multi3 #'helm-mm-3-match) + (multi3p #'helm-mm-3p-match)))) + (funcall fun candidate pattern))) + +(cl-defun helm-mm-3-match-on-diacritics (candidate &optional (pattern helm-pattern)) + "Same as `helm-mm-3-match' but match on diacritics if possible." + (let ((helm-mm--match-on-diacritics t)) + (helm-mm-match candidate pattern))) + +(defun helm-mm-search (pattern &rest _ignore) + "Search for PATTERN with `helm-mm-matching-method' function." + (let ((fun (cl-ecase helm-mm-matching-method + (multi1 #'helm-mm-1-search) + (multi2 #'helm-mm-2-search) + (multi3 #'helm-mm-3-search) + (multi3p #'helm-mm-3p-search)))) + (funcall fun pattern))) + + +(provide 'helm-multi-match) + + +;;; helm-multi-match.el ends here diff --git a/org/elpa/helm-core-20230317.1729/helm-source.el b/org/elpa/helm-core-20230317.1729/helm-source.el new file mode 100644 index 0000000..2ca2ac1 --- /dev/null +++ b/org/elpa/helm-core-20230317.1729/helm-source.el @@ -0,0 +1,1309 @@ +;;; helm-source.el --- Helm source creation. -*- lexical-binding: t -*- + +;; Copyright (C) 2015 ~ 2020 Thierry Volpiatto + +;; Author: Thierry Volpiatto +;; URL: http://github.com/emacs-helm/helm + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; Interface to create helm sources easily. +;; Actually the eieo objects are transformed in alist for compatibility. +;; In the future this package should allow creating source as eieo objects +;; without conversion to alist, teaching helm to read such a structure. +;; The compatibility with alists would be kept. + +;;; Code: + +(require 'cl-lib) +(require 'eieio) +(require 'helm-lib) + +(defvar helm-fuzzy-sort-fn) +(defvar helm-fuzzy-match-fn) +(defvar helm-fuzzy-search-fn) + +(declare-function helm-init-candidates-in-buffer "helm-core.el") +(declare-function helm-interpret-value "helm-core.el") +(declare-function helm-fuzzy-highlight-matches "helm-core.el") + +;;; Advice Emacs fn +;; Make Classes's docstrings more readable by removing al the +;; unnecessary crap. + +(defun helm-source--cl--print-table (&rest args) + "Advice for `cl--print-table' to make readable class slots docstrings." + (cl-flet ((print-rows (rows) + (let ((format "%s\n\n Initform=%s\n\n%s")) + (dolist (row rows) + (setcar row (propertize (car row) 'face 'bold)) + (setcdr row (nthcdr 1 (cdr row))) + (insert "\n* " (apply #'format format row) "\n"))))) + (print-rows (cadr args)))) + +(cl-defgeneric helm--setup-source (source) + "Prepare slots and handle slot errors before creating a helm source.") + +(cl-defgeneric helm-setup-user-source (source) + "Allow users modifying slots in SOURCE just before creation.") + + +;;; Classes for sources +;; +;; +(defclass helm-source () + ((name + :initarg :name + :initform nil + :custom string + :documentation + " The name of the source. + A string which is also the heading which appears + above the list of matches from the source. Must be unique.") + + (header-name + :initarg :header-name + :initform nil + :custom function + :documentation + " A function returning the display string of the header. + Its argument is the name of the source. This attribute is useful to + add an additional information with the source name. + It doesn't modify the name of the source.") + + (init + :initarg :init + :initform nil + :custom function + :documentation + " Function called with no parameters when helm is started. + It is useful for collecting current state information which can be + used to create the list of candidates later. + Initialization of `candidates-in-buffer' is done here + with `helm-init-candidates-in-buffer'.") + + (candidates + :initarg :candidates + :initform nil + :custom (choice function list) + :documentation + " Specifies how to retrieve candidates from the source. + It can either be a variable name, a function called with no parameters + or the actual list of candidates. + + Do NOT use this for asynchronous sources, use `candidates-process' + instead. + + The list must be a list whose members are strings, symbols + or (DISPLAY . REAL) pairs. + + In case of (DISPLAY . REAL) pairs, the DISPLAY string is shown + in the Helm buffer, but the REAL one is used as action + argument when the candidate is selected. This allows a more + readable presentation for candidates which would otherwise be, + for example, too long or have a common part shared with other + candidates which can be safely replaced with an abbreviated + string for display purposes. + + Note that if the (DISPLAY . REAL) form is used then pattern + matching is done on the displayed string, not on the real + value. + + This function, generally should not compute candidates according to + `helm-pattern' which defeat all the Helm's matching mechanism + i.e. multiple pattern matching and/or fuzzy matching. + If you want to do so, use :match-dynamic slot to be sure matching + occur only in :candidates function and there is no conflict with + other match functions.") + + (update + :initarg :update + :initform nil + :custom function + :documentation + " Function called with no parameters at before \"init\" function + when `helm-force-update' is called.") + + (cleanup + :initarg :cleanup + :initform nil + :custom function + :documentation + " Function called with no parameters when *helm* buffer is + closed. It is useful for killing unneeded candidates buffer. + + Note that the function is executed BEFORE performing action.") + + (keymap + :initarg :keymap + :initform 'helm-map + :custom sexp + :documentation + " Specific keymap for this source. + default value is `helm-map'.") + + (action + :initarg :action + :initform 'identity + :custom (alist :key-type string + :value-type function) + :documentation + " An alist of (DISPLAY . FUNCTION) pairs, a variable name or a function. + FUNCTION is called with one parameter: the selected candidate. + + An action other than the default can be chosen from this list + of actions for the currently selected candidate (by default + with TAB). The DISPLAY string is shown in the completions + buffer and the FUNCTION is invoked when an action is + selected. The first action of the list is the default. + + You should use `helm-make-actions' to build this alist easily.") + + (persistent-action + :initarg :persistent-action + :initform nil + :custom function + :documentation + " Can be a either a Function called with one parameter (the + selected candidate) or a cons cell where first element is this + same function and second element a symbol (e.g never-split) + that inform `helm-execute-persistent-action' to not split his + window to execute this persistent action. + Example: + + (defun foo-persistent-action (candidate) + (do-something candidate)) + + :persistent-action \\='(foo-persistent-action . never-split) ; Don't split + or + :persistent-action \\='foo-persistent-action ; Split + + When specifying :persistent-action by slot directly, foo-persistent-action + will be executed without quitting helm when hitting `C-j'. + + Note that other persistent actions can be defined using other + bindings than `C-j' by simply defining an interactive function bound + to a key in the keymap source. + The function should create a new attribute in source before calling + `helm-execute-persistent-action' on this attribute. + Example: + + (defun helm-ff-persistent-delete () + \"Delete current candidate without quitting.\" + (interactive) + (with-helm-alive-p + (helm-set-attr \\='quick-delete \\='(helm-ff-quick-delete . never-split)) + (helm-execute-persistent-action \\='quick-delete))) + + This function is then bound in `helm-find-files-map'.") + + (persistent-action-if + :initarg :persistent-action-if + :initform nil + :custom function + :documentation + " Similar from persistent action but it is a function that should + return an object suitable for persistent action when called , i.e. a + function or a cons cell. + Example: + + (defun foo-persistent-action (candidate) + (cond (something + ;; Don't split helm-window. + (cons (lambda (_ignore) + (do-something candidate)) + \\='no-split)) + ;; Split helm-window. + (something-else + (lambda (_ignore) + (do-something-else candidate))))) + + :persistent-action-if \\='foo-persistent-action + + Here when hitting `C-j' one of the lambda's will be executed + depending on something or something-else condition, splitting or not + splitting as needed. + See `helm-find-files-persistent-action-if' definition as another example.") + + (persistent-help + :initarg :persistent-help + :initform nil + :custom string + :documentation + " A string to explain persistent-action of this source. + It is a facility to display what persistent action does in + header-line, once your source is loaded don't use it directly, it will + have no effect, use instead `header-line' attribute. + It also accepts a function or a variable name. + It will be displayed in `header-line' or in `minibuffer' depending + of value of `helm-echo-input-in-header-line' and `helm-display-header-line'.") + + (help-message + :initarg :help-message + :initform nil + :custom (choice string function) + :documentation + " Help message for this source. + If not present, `helm-help-message' value will be used.") + + (multiline + :initarg :multiline + :initform nil + :custom (choice boolean integer) + :documentation + " Allow multiline candidates. + When non-nil candidates will be separated by `helm-candidate-separator'. + You can customize the color of this separator with `helm-separator' face. + Value of multiline can be an integer which specify the maximum size of the + multiline string to display, if multiline string is longer than this value + it will be truncated.") + + (requires-pattern + :initarg :requires-pattern + :initform 0 + :custom integer + :documentation + " If present matches from the source are shown only if the + pattern is not empty. Optionally, it can have an integer + parameter specifying the required length of input which is + useful in case of sources with lots of candidates.") + + (candidate-transformer + :initarg :candidate-transformer + :initform nil + :custom (choice function list) + :documentation + " It's a function or a list of functions called with one argument + when the completion list from the source is built. The argument + is the list of candidates retrieved from the source. The + function should return a transformed list of candidates which + will be used for the actual completion. If it is a list of + functions, it calls each function sequentially. + + This can be used to transform or remove items from the list of + candidates. + + Note that `candidates' is run already, so the given transformer + function should also be able to handle candidates with (DISPLAY + . REAL) format.") + + (filtered-candidate-transformer + :initarg :filtered-candidate-transformer + :initform nil + :custom (choice function list) + :documentation + " It has the same format as `candidate-transformer', except the + function is called with two parameters: the candidate list and + the source. + + This transformer is run on the candidate list which is already + filtered by the current pattern. While `candidate-transformer' + is run only once, it is run every time the input pattern is + changed. + + It can be used to transform the candidate list dynamically, for + example, based on the current pattern. + + In some cases it may also be more efficent to perform candidate + transformation here, instead of with `candidate-transformer' + even if this transformation is done every time the pattern is + changed. For example, if a candidate set is very large then + `candidate-transformer' transforms every candidate while only + some of them will actually be displayed due to the limit + imposed by `helm-candidate-number-limit'. + + Note that `candidates' and `candidate-transformer' is run + already, so the given transformer function should also be able + to handle candidates with (DISPLAY . REAL) format.") + + (filter-one-by-one + :initarg :filter-one-by-one + :initform nil + :custom (choice function list) + :documentation + " A transformer function that treat candidates one by one. + It is called with one arg the candidate. + It is faster than `filtered-candidate-transformer' or + `candidate-transformer', but should be used only in sources + that recompute constantly their candidates, e.g `helm-source-find-files'. + Filtering happen early and candidates are treated + one by one instead of re-looping on the whole list. + If used with `filtered-candidate-transformer' or `candidate-transformer' + these functions should treat the candidates transformed by the + `filter-one-by-one' function in consequence.") + + (display-to-real + :initarg :display-to-real + :initform nil + :custom function + :documentation + " Transform the selected candidate when passing it to action. + + Function called with one parameter, the selected candidate. + + Avoid recomputing all candidates with candidate-transformer + or filtered-candidate-transformer to give a new value to REAL, + instead the selected candidate is transformed only when passing it + to action. This works (and make sense) only with plain string + candidates, it will NOT work when candidate is a cons cell, in this + case the real value of candidate will be used. + Example: + + (helm :sources (helm-build-sync-source \"test\" + :candidates \\='(a b c d e) + :display-to-real (lambda (c) (concat c \":modified by d-t-r\"))) + :buffer \"*helm test*\") + + Note that this is NOT a transformer, + so the display will not be modified by this function.") + + (real-to-display + :initarg :real-to-display + :initform nil + :custom function + :documentation + " Recompute all candidates computed previously with other transformers. + + Function called with one parameter, the selected candidate. + + The real value of candidates will be shown in display and of course + be used by action. + Example: + + (helm :sources (helm-build-sync-source \"test\" + :candidates \\='((\"foo\" . 1) (\"bar\" . 2) (\"baz\". 3)) + :real-to-display (lambda (c) (format \"%s\" (1+ c)))) + :buffer \"*helm test*\") + + Mostly deprecated, kept only for backward compatibility.") + + (marked-with-props + :initarg :marked-with-props + :initform nil + :custom (choice boolean symbol) + :documentation + " Get candidates with their properties in `helm-marked-candidates'. + Allow using the FORCE-DISPLAY-PART of `helm-get-selection' in marked + candidates, use t or \\='withprop to pass it to `helm-get-selection'.") + + (action-transformer + :initarg :action-transformer + :initform nil + :custom (choice function list) + :documentation + " It's a function or a list of functions called with two + arguments when the action list from the source is + assembled. The first argument is the list of actions, the + second is the current selection. If it is a list of functions, + it calls each function sequentially. + + The function should return a transformed action list. + + This can be used to customize the list of actions based on the + currently selected candidate.") + + (pattern-transformer + :initarg :pattern-transformer + :initform nil + :custom (choice function list) + :documentation + " It's a function or a list of functions called with one argument + before computing matches. Its argument is `helm-pattern'. + Functions should return transformed `helm-pattern'. + + It is useful to change interpretation of `helm-pattern'.") + + (candidate-number-limit + :initarg :candidate-number-limit + :initform nil + :custom integer + :documentation + " Override `helm-candidate-number-limit' only for this source.") + + (volatile + :initarg :volatile + :initform nil + :custom boolean + :documentation + " Indicates the source assembles the candidate list dynamically, + so it shouldn't be cached within a single Helm + invocation. It is only applicable to synchronous sources, + because asynchronous sources are not cached.") + + (match + :initarg :match + :initform nil + :custom (choice function list) + :documentation + " List of functions called with one parameter: a candidate. The + function should return non-nil if the candidate matches the + current pattern (see variable `helm-pattern'). + + When using `candidates-in-buffer' its default value is `identity' and + don't have to be changed, use the `search' slot instead. + + This attribute allows the source to override the default + pattern matching based on `string-match'. It can be used, for + example, to implement a source for file names and do the + pattern matching on the basename of files, since it's more + likely one is typing part of the basename when searching for a + file, instead of some string anywhere else in its path. + + If the list contains more than one function then the list of + matching candidates from the source is constructed by appending + the results after invoking the first function on all the + potential candidates, then the next function, and so on. The + matching candidates supplied by the first function appear first + in the list of results and then results from the other + functions, respectively. + + This attribute has no effect for asynchronous sources (see + attribute `candidates'), and sources using `match-dynamic' + since they perform pattern matching themselves. + + Note that FUZZY-MATCH slot will overhide value of this slot.") + + (diacritics + :initarg :diacritics + :initform nil + :custom boolean + :documentation + " Ignore diacritics when searching.") + + (match-on-real + :initarg :match-on-real + :initform nil + :custom boolean + :documentation + " Match the real value of candidates when non nil.") + + (fuzzy-match + :initarg :fuzzy-match + :initform nil + :custom boolean + :documentation + " Enable fuzzy matching in this source. + This will overwrite settings in MATCH slot, and for + sources built with child class `helm-source-in-buffer' the SEARCH slot. + This also add a `filtered-candidate-transformer' function to sort candidates + (see `helm-fuzzy-sort-fn') according to the score of each candidate which is + computed with `helm-fuzzy-default-score-fn'. + This is an easy way of enabling fuzzy matching, but you can use the MATCH + or SEARCH slots yourself if you want something more elaborated, mixing + different type of match (See `helm-source-buffers' class for example), you + will have in this case to provide as well a sort fn + in `filtered-candidate-transformer' yourself. + + This attribute is not supported for asynchronous sources + since they perform pattern matching themselves.") + + (redisplay + :initarg :redisplay + :initform 'identity + :custom (choice list function) + :documentation + " A function or a list of functions to apply to current list + of candidates when redisplaying buffer with `helm-redisplay-buffer'. + This is only interesting for modifying and redisplaying the whole list + of candidates in async sources. + It uses `identity' by default for when async sources are mixed with + normal sources, in this case these normal sources are not modified and + redisplayed as they are.") + + (nomark + :initarg :nomark + :initform nil + :custom boolean + :documentation + " Don't allow marking candidates when this attribute is present.") + + (nohighlight + :initarg :nohighlight + :initform nil + :custom boolean + :documentation + " Disable highlighting matches in this source. + This will disable generic highlighting of matches, + but some specialized highlighting can be done from elsewhere, + i.e from `filtered-candidate-transformer' or `filter-one-by-one' slots. + So use this to either disable completely highlighting in your source, + or to disable highlighting and use a specialized highlighting matches + function for this source. + Remember that this function should run AFTER all filter functions if those + filter functions are modifying face properties, though it is possible to + avoid this by using new `add-face-text-property' in your filter functions.") + + (allow-dups + :initarg :allow-dups + :initform nil + :custom boolean + :documentation + " Allow helm collecting duplicates candidates.") + + (history + :initarg :history + :initform nil + :custom symbol + :documentation + " Allow passing history variable to helm from source. + It should be a quoted symbol. + Passing the history variable here have no effect + so add it also in the `helm' call with the :history keyword. + The main point of adding the variable here + is to make it available when resuming.") + + (coerce + :initarg :coerce + :initform nil + :custom function + :documentation + " It's a function called with one argument: the selected candidate. + This function is intended for type convertion. In normal case, + the selected candidate (string) is passed to action + function. If coerce function is specified, it is called just + before action function. + + Example: converting string to symbol + (coerce . intern)") + + (mode-line + :initarg :mode-line + :initform nil + :custom (choice string sexp) + :documentation + " Source local `helm-mode-line-string' (included in + `mode-line-format'). It accepts also variable/function name.") + + (header-line + :initarg :header-line + :initform nil + :custom (choice string function) + :documentation + " Source local `header-line-format'. + It will be displayed in `header-line' or in `minibuffer' depending + of value of `helm-echo-input-in-header-line' and `helm-display-header-line'. + It accepts also variable/function name.") + + (resume + :initarg :resume + :initform nil + :custom function + :documentation + " Function called with no parameters at end of initialization + when `helm-resume' is started. + If this function try to do something against `helm-buffer', (e.g updating, + searching etc...) probably you should run it in a timer to ensure + `helm-buffer' is ready.") + + (follow + :initarg :follow + :initform nil + :custom integer + :documentation + " Enable `helm-follow-mode' for this source only. + With a value of 1 enable, a value of -1 or nil disable the mode. + See `helm-follow-mode' for more infos.") + + (follow-delay + :initarg :follow-delay + :initform nil + :custom integer + :documentation + " `helm-follow-mode' will execute persistent-action after this delay. + Otherwise value of `helm-follow-input-idle-delay' is used if non--nil, + If none of these are found fallback to `helm-input-idle-delay'.") + + (multimatch + :initarg :multimatch + :initform t + :custom boolean + :documentation + " Use the multi-match algorithm when non-nil. + I.e Allow specifying multiple patterns separated by spaces. + When a pattern is prefixed by \"!\" the negation of this pattern is used, + i.e match anything but this pattern. + It is the standard way of matching in helm and is enabled by default. + It can be used with fuzzy-matching enabled, but as soon helm detect a space, + each pattern will match by regexp and will not be fuzzy.") + + (match-part + :initarg :match-part + :initform nil + :custom function + :documentation + " Allow matching only one part of candidate. + If source contain match-part attribute, match is computed only + on part of candidate returned by the call of function provided + by this attribute. The function should have one arg, candidate, + and return only a specific part of candidate. + On async sources, as matching is done by the backend, this have + no effect apart for highlighting matches.") + + (before-init-hook + :initarg :before-init-hook + :initform nil + :custom symbol + :documentation + " A local hook that run at beginning of initilization of this source. + i.e Before the creation of `helm-buffer'. + + Should be a variable (a symbol) bound to a list of + functions or a single function (see `run-hooks' documentation). + Even better is to use `add-hook' to feed this variable. + Usage of an anonymous function, or a list of functions is still + supported but not recommended.") + + (after-init-hook + :initarg :after-init-hook + :initform nil + :custom symbol + :documentation + " A local hook that run at end of initilization of this source. + i.e After the creation of `helm-buffer'. + + Should be a variable (a symbol) bound to a list of + functions or a single function (see `run-hooks' documentation). + Even better is to use `add-hook' to feed this variable. + Usage of an anonymous function, or a list of functions is still + supported but not recommended.") + + (delayed + :initarg :delayed + :initform nil + :custom (choice null integer) + :documentation + " This slot have no more effect and is just kept for backward compatibility. + Please don't use it.") + + (must-match + :initarg :must-match + :initform nil + :custom symbol + :documentation + " Same as `completing-read' require-match arg. + Possible values are: + - `t' which prevent exiting with an empty helm-buffer i.e. no matches. + - `confirm' which ask for confirmation i.e. need to press a second + time RET. + - `nil' is the default and is doing nothing i.e. returns nil when + pressing RET with an empty helm-buffer. + - Any other non nil values e.g. `ignore' allow exiting with + minibuffer contents as candidate value (in this case helm-buffer + is empty).") + + (find-file-target + :initarg :find-file-target + :initform nil + :custom function + :documentation + " Determine the target file when running `helm-quit-and-find-file'. + It is a function called with one arg SOURCE.") + + (group + :initarg :group + :initform 'helm + :custom symbol + :documentation + " The current source group, default to `helm' when not specified.")) + + "Main interface to define helm sources." + :abstract t) + +(defclass helm-source-sync (helm-source) + ((candidates + :initform '("ERROR: You must specify the `candidates' slot, either with a list or a function")) + + (migemo + :initarg :migemo + :initform nil + :custom boolean + :documentation + " Enable migemo. + When multimatch is disabled, you can give the symbol \\='nomultimatch as value + to force not using generic migemo matching function. + In this case you have to provide your own migemo matching funtion + that kick in when `helm-migemo-mode' is enabled. + Otherwise it will be available for this source once `helm-migemo-mode' + is enabled when non-nil.") + + (match-strict + :initarg :match-strict + :initform nil + :custom function + :documentation + " When specifying a match function within a source and + helm-multi-match is enabled, the result of all matching + functions will be concatened, which in some cases is not what + is wanted. When using `match-strict' only this or these + functions will be used. You can specify those functions as a + list of functions or a single symbol function. + + NOTE: This have the same effect as using :MULTIMATCH nil.") + + (match-dynamic + :initarg :match-dynamic + :initform nil + :custom boolean + :documentation + " Disable all helm matching functions when non nil. + The :candidates function in this case is in charge of fetching + candidates dynamically according to `helm-pattern'. + If you want to make your :candidates function working with `completion-styles' + use the function `helm-dynamic-completion'. + Note that :volatile is automatically enabled when using this, so no + need to specify it.")) + + "Use this class to make helm sources using a list of candidates. +This list should be given as a normal list, a variable handling a list +or a function returning a list. +Matching is done basically with `string-match' against each candidate.") + +(defclass helm-source-async (helm-source) + ((candidates-process + :initarg :candidates-process + :initform nil + :custom function + :documentation + " This attribute is used to define a process as candidate. + The function called with no arguments must return a process + i.e. `processp', it use typically `start-process' or `make-process', + see (info \"(elisp) Asynchronous Processes\"). + + + NOTE: + When building the source at runtime you can give directly a process + as value, otherwise wrap the process call into a function. + The process buffer should be nil, otherwise, if you use + `helm-buffer' give to the process a sentinel.") + + (multimatch :initform nil)) + + "Use this class to define a helm source calling an external process. +The external process is called typically in a `start-process' call to be +asynchronous. + +Note that using multiples asynchronous sources is not fully working, +expect weird behavior if you try this. + +The :candidates slot is not allowed even if described because this class +inherit from `helm-source'.") + +(defclass helm-source-in-buffer (helm-source) + ((init + :initform 'helm-default-init-source-in-buffer-function) + + (data + :initarg :data + :initform nil + :custom (choice list string) + :documentation + " A string, a list or a buffer that will be used to feed the `helm-candidates-buffer'. + This data will be passed in a function added to the init slot and + the buffer will be build with `helm-init-candidates-in-buffer' or directly + with `helm-candidates-buffer' if data is a buffer. + This is an easy and fast method to build a `candidates-in-buffer' source.") + + (migemo + :initarg :migemo + :initform nil + :custom boolean + :documentation + " Enable migemo. + When multimatch is disabled, you can give the symbol \\='nomultimatch as value + to force not using generic migemo matching function. + In this case you have to provide your own migemo matching funtion + that kick in when `helm-migemo-mode' is enabled. + Otherwise it will be available for this source once `helm-migemo-mode' + is enabled when non-nil.") + + (candidates + :initform 'helm-candidates-in-buffer) + + (volatile + :initform t) + + (match + :initform '(identity)) + + (get-line + :initarg :get-line + :initform 'buffer-substring-no-properties + :custom function + :documentation + " A function like `buffer-substring-no-properties' or `buffer-substring'. + This function converts region from point at line-beginning and point + at line-end in the `helm-candidate-buffer' to a string which will be displayed + in the `helm-buffer', it takes two args BEG and END. + By default, `helm-candidates-in-buffer' uses + `buffer-substring-no-properties' which does no conversion and doesn't carry + text properties.") + + (search + :initarg :search + :initform '(helm-candidates-in-buffer-search-default-fn) + :custom (choice function list) + :documentation + " List of functions like `re-search-forward' or `search-forward'. + Buffer search function used by `helm-candidates-in-buffer'. + By default, `helm-candidates-in-buffer' uses `re-search-forward'. + The function should take one arg PATTERN. + If your search function needs to handle negation like multimatch, + this function should returns in such case a cons cell of two integers defining + the beg and end positions to match in the line previously matched by + `re-search-forward' or similar, and move point to next line + (See how the `helm-mm-3-search-base' and `helm-fuzzy-search' functions are working). + + NOTE: FUZZY-MATCH slot will overhide value of this slot.") + + (search-strict + :initarg :search-strict + :initform nil + :custom function + :documentation + " When specifying a search function within a source and + helm-multi-match is enabled, the result of all searching + functions will be concatened, which in some cases is not what + is wanted. When using `search-strict' only this or these + functions will be used. You can specify those functions as a + list of functions or a single symbol function. + + NOTE: This have the same effect as using a nil value for + :MULTIMATCH slot.")) + + "Use this source to make helm sources storing candidates inside a buffer. + +The buffer storing candidates is generated by `helm-candidate-buffer' function +and all search are done in this buffer, results are transfered to the `helm-buffer' +when done. +Contrarily to `helm-source-sync' candidates are matched using a function +like `re-search-forward' (see below documentation of `:search' slot) which makes +the search much faster than matching candidates one by one. +If you want to add search functions to your sources, don't use `:match' which +will raise an error, but `:search'. +See `helm-candidates-in-buffer' for more infos.") + +(defclass helm-source-dummy (helm-source) + ((candidates + :initform '("dummy")) + + (filtered-candidate-transformer + :initform (lambda (_candidates _source) (list helm-pattern))) + + (multimatch + :initform nil) + + (accept-empty + :initarg :accept-empty + :initform t + :custom boolean + :documentation + " Allow exiting with an empty string. + You should keep the default value.") + + (match + :initform 'identity) + + (volatile + :initform t))) + +(defclass helm-source-in-file (helm-source-in-buffer) + ((init :initform (lambda () + (let ((file (helm-get-attr 'candidates-file)) + (count 1)) + (with-current-buffer (helm-candidate-buffer 'global) + (insert-file-contents file) + (goto-char (point-min)) + (when (helm-get-attr 'linum) + (while (not (eobp)) + (add-text-properties + (point-at-bol) (point-at-eol) + `(helm-linum ,count)) + (cl-incf count) + (forward-line 1))))))) + (get-line :initform #'buffer-substring) + (candidates-file + :initarg :candidates-file + :initform nil + :custom string + :documentation + " The file used to fetch candidates.") + (linum + :initarg :linum + :initform nil + :documentation + " Store line number in each candidate when non nil. + Line number is stored in `helm-linum' text property.")) + + "The contents of the FILE will be used as candidates in buffer.") + + +;;; Error functions +;; +;; +(defun helm-default-init-source-in-buffer-function () + (helm-init-candidates-in-buffer 'global + '("ERROR: No buffer handling your data, use either the `init' slot or the `data' slot."))) + + +;;; Internal Builder functions. +;; +;; +(defun helm--create-source (object) + "[INTERNAL] Build a helm source from OBJECT. +Where OBJECT is an instance of an eieio class." + (cl-loop for sd in (eieio-class-slots (eieio-object-class object)) + for s = (eieio-slot-descriptor-name sd) + for slot-val = (slot-value object s) + when slot-val + collect (cons s slot-val))) + +(defun helm-make-source (name class &rest args) + "Build a `helm' source named NAME with ARGS for CLASS. +Argument NAME is a string which define the source name, so no need to use +the keyword :name in your source, NAME will be used instead. +Argument CLASS is an eieio class object. +Arguments ARGS are keyword value pairs as defined in CLASS." + (declare (indent 2)) + (let ((source (apply #'make-instance class name args))) + (setf (slot-value source 'name) name) + (helm--setup-source source) + (helm-setup-user-source source) + (helm--create-source source))) + +(defun helm-make-type (class &rest args) + (let ((source (apply #'make-instance class args))) + (setf (slot-value source 'name) nil) + (helm--setup-source source) + (helm--create-source source))) + +(defvar helm-mm-default-search-functions) +(defvar helm-mm-default-match-functions) + +(defun helm-source-mm-get-search-or-match-fns (source method) + "Prepare match or search functions for class SOURCE. +Argument METHOD is the matching method used by SOURCE either `match' +or `search'." + (let* ((diacritics (slot-value source 'diacritics)) + (defmatch (helm-aif (slot-value source 'match) + (helm-mklist it))) + (defmatch-strict (helm-aif (and (eq method 'match) + (slot-value source 'match-strict)) + (helm-mklist it))) + (defsearch (helm-aif (and (eq method 'search) + (slot-value source 'search)) + (helm-mklist it))) + (defsearch-strict (helm-aif (and (eq method 'search-strict) + (slot-value source 'search-strict)) + (helm-mklist it))) + (migemo (slot-value source 'migemo))) + (cl-case method + (match (cond (defmatch-strict) + ((and migemo diacritics) + (append (list 'helm-mm-exact-match + 'helm-mm-3-match-on-diacritics) + defmatch '(helm-mm-3-migemo-match))) + (migemo + (append helm-mm-default-match-functions + defmatch '(helm-mm-3-migemo-match))) + (diacritics + (delq nil + `(helm-mm-exact-match + ,@defmatch helm-mm-3-match-on-diacritics))) + (defmatch + (append helm-mm-default-match-functions defmatch)) + (t helm-mm-default-match-functions))) + (search (cond (defsearch-strict) + ((and migemo diacritics) + (append '(helm-mm-exact-search) + defsearch + '(helm-mm-3-migemo-search + helm-mm-3-search-on-diacritics))) + (migemo + (append helm-mm-default-search-functions + defsearch '(helm-mm-3-migemo-search))) + (diacritics + (delq nil + `(helm-mm-exact-search + ,@defsearch helm-mm-3-search-on-diacritics))) + (defsearch + (append helm-mm-default-search-functions defsearch)) + (t helm-mm-default-search-functions)))))) + + +;;; Modifiers +;; +(cl-defun helm-source-add-action-to-source-if (name fn source predicate + &optional (index 4)) + "Same as `helm-add-action-to-source-if' but for SOURCE defined as eieio object. +You can use this inside a `helm--setup-source' method for a SOURCE defined as +an eieio class." + (let* ((actions (slot-value source 'action)) + (action-transformers (slot-value source 'action-transformer)) + (new-action (list (cons name fn))) + (transformer (lambda (actions _candidate) + (let ((candidate (car (helm-marked-candidates)))) + (cond ((funcall predicate candidate) + (helm-append-at-nth + actions new-action index)) + (t actions)))))) + (cond ((functionp actions) + (setf (slot-value source 'action) (list (cons "Default action" actions)))) + ((listp actions) + (setf (slot-value source 'action) (helm-interpret-value actions source)))) + (when (or (symbolp action-transformers) (functionp action-transformers)) + (setq action-transformers (list action-transformers))) + (setf (slot-value source 'action-transformer) + (delq nil (append (list transformer) action-transformers))))) + + +;;; Methods to build sources. +;; +;; +(defun helm-source--persistent-help-string (value source) + "Format `persistent-help' VALUE in SOURCE. +Argument VALUE can be a string, a variable or a function." + (substitute-command-keys + (format "\\\\[helm-execute-persistent-action]: %s (keeping session)" + (helm-aif value + (helm-interpret-value value source) + (slot-value source 'header-line))))) + +(defun helm-source--header-line (source) + "Compute a default header line for SOURCE. + +The header line is based on one of `persistent-action-if', +`persistent-action', or `action' (in this order of precedence)." + (substitute-command-keys + (concat "\\\\[helm-execute-persistent-action]: " + (helm-acond + ((slot-value source 'persistent-action-if) + (helm-symbol-name it)) + ((or (slot-value source 'persistent-action) + (slot-value source 'action)) + (cond ((and (symbolp it) + (functionp it) + (eq it 'identity)) + "Do Nothing") + ((and (symbolp it) + (boundp it) + (listp (symbol-value it)) + (stringp (caar (symbol-value it)))) + (caar (symbol-value it))) + ((or (symbolp it) (functionp it)) + (helm-symbol-name it)) + ((listp it) + (let ((action (car it))) + ;; It comes from :action ("foo" . function). + (if (stringp (car action)) + (car action) + ;; It comes from :persistent-action + ;; (function . 'nosplit) Fix Bug#788. + (if (or (symbolp action) + (functionp action)) + (helm-symbol-name action))))) + (t ""))) + (t "")) + " (keeping session)"))) + +(cl-defmethod helm--setup-source ((_source helm-source))) + +(cl-defmethod helm--setup-source :before ((source helm-source)) + (unless (slot-value source 'group) + (setf (slot-value source 'group) 'helm)) + (when (slot-value source 'delayed) + (warn "Deprecated usage of helm `delayed' slot in `%s'" + (slot-value source 'name))) + (helm-aif (slot-value source 'keymap) + (let* ((map (if (symbolp it) + (symbol-value it) + it)) + (must-match-map (when (slot-value source 'must-match) + (let ((map (make-sparse-keymap))) + (define-key map (kbd "RET") + 'helm-confirm-and-exit-minibuffer) + map))) + (loc-map (if must-match-map + (make-composed-keymap + must-match-map map) + map))) + (setf (slot-value source 'keymap) loc-map))) + (helm-aif (slot-value source 'persistent-help) + (setf (slot-value source 'header-line) + (helm-source--persistent-help-string it source)) + (setf (slot-value source 'header-line) (helm-source--header-line source))) + (when (slot-value source 'fuzzy-match) + (cl-assert helm-fuzzy-sort-fn nil "Wrong type argument functionp: nil") + (setf (slot-value source 'filtered-candidate-transformer) + (helm-aif (slot-value source 'filtered-candidate-transformer) + (append (helm-mklist it) + (list helm-fuzzy-sort-fn)) + (list helm-fuzzy-sort-fn)))) + (unless (slot-value source 'nohighlight) + (setf (slot-value source 'filtered-candidate-transformer) + (helm-aif (slot-value source 'filtered-candidate-transformer) + (append (helm-mklist it) + (list #'helm-fuzzy-highlight-matches)) + (list #'helm-fuzzy-highlight-matches)))) + (when (numberp (helm-interpret-value (slot-value source 'multiline))) + (setf (slot-value source 'filtered-candidate-transformer) + (helm-aif (slot-value source 'filtered-candidate-transformer) + (append (helm-mklist it) + (list #'helm-multiline-transformer)) + (list #'helm-multiline-transformer)))) + (helm-aif (slot-value source 'requires-pattern) + (let ((val (if (symbolp it) + (symbol-value it) + it))) + (setf (slot-value source 'requires-pattern) val))) + (let ((sname (slot-value source 'name))) + (pcase (slot-value source 'before-init-hook) + ((or (and val (pred (functionp)) (guard (not (symbolp val)))) + (pred (consp))) + (warn "Helm source `%s': before-init-hook Should be defined as a symbol" sname))) + (pcase (slot-value source 'after-init-hook) + ((or (and val (pred (functionp)) (guard (not (symbolp val)))) + (pred (consp))) + (warn "Helm source `%s': after-init-hook Should be defined as a symbol" sname))))) + +(cl-defmethod helm-setup-user-source ((_source helm-source))) + +(cl-defmethod helm--setup-source ((source helm-source-sync)) + (when (slot-value source 'fuzzy-match) + (helm-aif (slot-value source 'match) + (setf (slot-value source 'match) + (append (helm-mklist it) + (list helm-fuzzy-match-fn))) + (setf (slot-value source 'match) helm-fuzzy-match-fn))) + (when (slot-value source 'multimatch) + (setf (slot-value source 'match) + (helm-source-mm-get-search-or-match-fns source 'match))) + (helm-aif (and (null (slot-value source 'multimatch)) + (slot-value source 'migemo)) + (unless (eq it 'nomultimatch) ; Use own migemo fn. + (setf (slot-value source 'match) + (append (helm-mklist (slot-value source 'match)) + '(helm-mm-3-migemo-match))))) + (when (slot-value source 'match-dynamic) + (setf (slot-value source 'match) 'identity) + (setf (slot-value source 'match-part) nil) + (setf (slot-value source 'multimatch) nil) + (setf (slot-value source 'fuzzy-match) nil) + (setf (slot-value source 'volatile) t))) + +(cl-defmethod helm--setup-source ((source helm-source-in-buffer)) + (cl-assert (eq (slot-value source 'candidates) 'helm-candidates-in-buffer) + nil + (format "Wrong usage of `candidates' attr in `%s' use `data' or `init' instead" + (slot-value source 'name))) + (let ((cur-init (slot-value source 'init))) + (helm-aif (slot-value source 'data) + (setf (slot-value source 'init) + (delq + nil + (list + (and (null (eq 'helm-default-init-source-in-buffer-function + cur-init)) + cur-init) + (lambda () + (helm-init-candidates-in-buffer + 'global + (cond ((functionp it) (funcall it)) + ((and (bufferp it) (buffer-live-p it)) + (with-current-buffer it (buffer-string))) + (t it))))))))) + (when (slot-value source 'fuzzy-match) + (helm-aif (slot-value source 'search) + (setf (slot-value source 'search) + (append (helm-mklist it) + (list helm-fuzzy-search-fn))) + (setf (slot-value source 'search) (list helm-fuzzy-search-fn)))) + (when (slot-value source 'multimatch) + (setf (slot-value source 'search) + (helm-source-mm-get-search-or-match-fns source 'search))) + (helm-aif (and (null (slot-value source 'multimatch)) + (slot-value source 'migemo)) + (unless (eq it 'nomultimatch) + (setf (slot-value source 'search) + (append (helm-mklist (slot-value source 'search)) + '(helm-mm-3-migemo-search))))) + (let ((mtc (slot-value source 'match))) + (cl-assert (or (equal '(identity) mtc) + (eq 'identity mtc)) + nil "Invalid slot value for `match'") + (cl-assert (eq (slot-value source 'volatile) t) + nil "Invalid slot value for `volatile'"))) + +(cl-defmethod helm--setup-source ((source helm-source-async)) + (cl-assert (null (slot-value source 'candidates)) + nil "Incorrect use of `candidates' use `candidates-process' instead") + (cl-assert (null (slot-value source 'multimatch)) + nil "`multimatch' not allowed in async sources.") + (cl-assert (null (slot-value source 'fuzzy-match)) + nil "`fuzzy-match' not supported in async sources.")) + +(cl-defmethod helm--setup-source ((source helm-source-dummy)) + (let ((mtc (slot-value source 'match))) + (cl-assert (or (equal '(identity) mtc) + (eq 'identity mtc)) + nil "Invalid slot value for `match'") + (cl-assert (eq (slot-value source 'volatile) t) + nil "Invalid slot value for `volatile'") + (cl-assert (equal (slot-value source 'candidates) '("dummy")) + nil "Invalid slot value for `candidates'") + (cl-assert (eq (slot-value source 'accept-empty) t) + nil "Invalid slot value for `accept-empty'"))) + + +;;; User functions +;; +;; Sources +(defmacro helm-build-sync-source (name &rest args) + "Build a synchronous helm source with name NAME. +Args ARGS are keywords provided by `helm-source-sync'." + (declare (indent 1)) + `(helm-make-source ,name 'helm-source-sync ,@args)) + +(defmacro helm-build-async-source (name &rest args) + "Build a asynchronous helm source with name NAME. +Args ARGS are keywords provided by `helm-source-async'." + (declare (indent 1)) + `(helm-make-source ,name 'helm-source-async ,@args)) + +(defmacro helm-build-in-buffer-source (name &rest args) + "Build a helm source with name NAME using `candidates-in-buffer' method. +Args ARGS are keywords provided by `helm-source-in-buffer'." + (declare (indent 1)) + `(helm-make-source ,name 'helm-source-in-buffer ,@args)) + +(defmacro helm-build-dummy-source (name &rest args) + "Build a helm source with name NAME using `dummy' method. +Args ARGS are keywords provided by `helm-source-dummy'." + (declare (indent 1)) + `(helm-make-source ,name 'helm-source-dummy ,@args)) + +(defmacro helm-build-in-file-source (name file &rest args) + "Build a helm source with NAME name using `candidates-in-files' method. +Arg FILE is a filename, the contents of this file will be +used as candidates in buffer. +Args ARGS are keywords provided by `helm-source-in-file'." + (declare (indent 2)) + `(helm-make-source ,name 'helm-source-in-file + :candidates-file ,file ,@args)) + + +(provide 'helm-source) + +;;; helm-source ends here diff --git a/code/elpa/helm-ls-git-20221118.503/helm-ls-git-autoloads.el b/org/elpa/helm-ls-git-20230405.957/helm-ls-git-autoloads.el similarity index 100% rename from code/elpa/helm-ls-git-20221118.503/helm-ls-git-autoloads.el rename to org/elpa/helm-ls-git-20230405.957/helm-ls-git-autoloads.el diff --git a/org/elpa/helm-ls-git-20230405.957/helm-ls-git-pkg.el b/org/elpa/helm-ls-git-20230405.957/helm-ls-git-pkg.el new file mode 100644 index 0000000..37bc4c1 --- /dev/null +++ b/org/elpa/helm-ls-git-20230405.957/helm-ls-git-pkg.el @@ -0,0 +1,2 @@ +;;; Generated package description from helm-ls-git.el -*- no-byte-compile: t -*- +(define-package "helm-ls-git" "20230405.957" "list git files." '((helm "1.7.8")) :commit "356e7f0c2725fc4ab6d2eb5bb4752ac1a8133039") diff --git a/code/elpa/helm-ls-git-20221007.1113/helm-ls-git.el b/org/elpa/helm-ls-git-20230405.957/helm-ls-git.el similarity index 98% rename from code/elpa/helm-ls-git-20221007.1113/helm-ls-git.el rename to org/elpa/helm-ls-git-20230405.957/helm-ls-git.el index f70dd10..d095489 100644 --- a/code/elpa/helm-ls-git-20221007.1113/helm-ls-git.el +++ b/org/elpa/helm-ls-git-20230405.957/helm-ls-git.el @@ -3,8 +3,8 @@ ;; Copyright (C) 2012 ~ 2022 Thierry Volpiatto ;; Package-Requires: ((helm "1.7.8")) -;; Package-Version: 20221007.1113 -;; Package-Commit: dbee5c668c49e5b77907f1d9887e2a44f7b196a3 +;; Package-Version: 20230405.957 +;; Package-Commit: 356e7f0c2725fc4ab6d2eb5bb4752ac1a8133039 ;; 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 @@ -537,6 +537,7 @@ See docstring of `helm-ls-git-ls-switches'. (lambda (_candidate) (funcall helm-ls-git-status-command (helm-default-directory))) + "Git Log" 'helm-ls-git-show-log-for-file "Switch to shell" 'helm-ls-git-switch-to-shell "Git grep files (`C-u' only current directory)" 'helm-ls-git-grep @@ -655,7 +656,7 @@ See docstring of `helm-ls-git-ls-switches'. (setq unread-command-events nil)) (helm-force-update)))))) -(defun helm-ls-git-log (&optional branch num) +(defun helm-ls-git-log (&optional branch num file) "Run git log branch -n num and return the resulting string." (when (and branch (string-match "->" branch)) (setq branch (car (last (split-string branch "->"))))) @@ -676,6 +677,7 @@ See docstring of `helm-ls-git-ls-switches'. helm-ls-git-log--last-number-commits) ,(or branch ""))) output) + (when file (setq switches (append switches `("--follow" ,file)))) (unless helm-ls-git-log--is-full (setq helm-ls-git-log--last-number-commits (number-to-string @@ -702,7 +704,10 @@ See docstring of `helm-ls-git-ls-switches'. branch helm-ls-git-log--last-number-commits)) helm-ls-git-log--last-log)) -(defun helm-ls-git-show-log (branch) +(defun helm-ls-git-show-log-for-file (file) + (helm-ls-git-show-log (helm-ls-git--branch) file)) + +(defun helm-ls-git-show-log (branch &optional file) (let ((name (if (helm-ls-git-detached-state-p) (helm-ls-git--branch) (replace-regexp-in-string "[ *]" "" branch))) @@ -715,10 +720,12 @@ See docstring of `helm-ls-git-ls-switches'. :header-name (lambda (sname) (format "%s (%s)" sname name)) :init (lambda () (helm-init-candidates-in-buffer 'global - (helm-ls-git-log name (helm-aif (or prefarg - ;; for force-update. - current-prefix-arg) - (prefix-numeric-value it)))) + (helm-ls-git-log + name (helm-aif (or prefarg + ;; for force-update. + current-prefix-arg) + (prefix-numeric-value it)) + file)) (setq prefarg nil)) :get-line 'buffer-substring :marked-with-props 'withprop @@ -1853,27 +1860,26 @@ Commands: map) "Keymap used in `helm-ls-git-rebase-todo-mode' buffers.") -(defun helm-ls-git-rebase-todo-move-down () - "Move commit line one line down." - (interactive) +(defun helm-ls-git-rebase-todo-move-1 (arg) + "Move commit line one line down or up according to ARG. +ARG can be 1 for down or -1 for up." (beginning-of-line) (let* ((next (+ 1 (line-end-position))) (line (buffer-substring (point) next))) (delete-region (point) next) - (forward-line 1) + (forward-line arg) (insert line) (forward-line -1))) +(defun helm-ls-git-rebase-todo-move-down () + "Move commit line one line down." + (interactive) + (helm-ls-git-rebase-todo-move-1 1)) + (defun helm-ls-git-rebase-todo-move-up () "Move commit line on line up." (interactive) - (beginning-of-line) - (let* ((next (+ 1 (line-end-position))) - (line (buffer-substring (point) next))) - (delete-region (point) next) - (forward-line -1) - (insert line) - (forward-line -1))) + (helm-ls-git-rebase-todo-move-1 -1)) (defun helm-ls-git-rebase-action (action) "Replace the current rebase command at bol by ACTION. diff --git a/code/elpa/helpful-20221209.1743/helpful-autoloads.el b/org/elpa/helpful-20230323.414/helpful-autoloads.el similarity index 100% rename from code/elpa/helpful-20221209.1743/helpful-autoloads.el rename to org/elpa/helpful-20230323.414/helpful-autoloads.el diff --git a/org/elpa/helpful-20230323.414/helpful-pkg.el b/org/elpa/helpful-20230323.414/helpful-pkg.el new file mode 100644 index 0000000..2026e0d --- /dev/null +++ b/org/elpa/helpful-20230323.414/helpful-pkg.el @@ -0,0 +1,2 @@ +;;; Generated package description from helpful.el -*- no-byte-compile: t -*- +(define-package "helpful" "20230323.414" "A better *help* buffer" '((emacs "25") (dash "2.18.0") (s "1.11.0") (f "0.20.0") (elisp-refs "1.2")) :commit "e9ec6fc2ae10db2b9b59ed656021845d11881a0a" :authors '(("Wilfred Hughes" . "me@wilfred.me.uk")) :maintainer '("Wilfred Hughes" . "me@wilfred.me.uk") :keywords '("help" "lisp") :url "https://github.com/Wilfred/helpful") diff --git a/code/elpa/helpful-20221024.134/helpful.el b/org/elpa/helpful-20230323.414/helpful.el similarity index 97% rename from code/elpa/helpful-20221024.134/helpful.el rename to org/elpa/helpful-20230323.414/helpful.el index 2a6f6db..edc7a62 100644 --- a/code/elpa/helpful-20221024.134/helpful.el +++ b/org/elpa/helpful-20230323.414/helpful.el @@ -4,8 +4,8 @@ ;; Author: Wilfred Hughes ;; URL: https://github.com/Wilfred/helpful -;; Package-Version: 20221024.134 -;; Package-Commit: 60c1cd49f72e930b8796e5644bd222e8fc466740 +;; Package-Version: 20230323.414 +;; Package-Commit: e9ec6fc2ae10db2b9b59ed656021845d11881a0a ;; Keywords: help, lisp ;; Version: 0.20 ;; Package-Requires: ((emacs "25") (dash "2.18.0") (s "1.11.0") (f "0.20.0") (elisp-refs "1.2")) @@ -982,7 +982,8 @@ vector suitable for `key-description', and COMMAND is a smbol." ;; Text of the form \\[foo-command] (rx "\\[" (group (+ (not (in "]")))) "]") (lambda (it) - (let* ((symbol-name (match-string 1 it)) + (let* ((button-face (if (>= emacs-major-version 28) 'help-key-binding 'button)) + (symbol-name (match-string 1 it)) (symbol (intern symbol-name)) (key (where-is-internal symbol keymap t)) (key-description @@ -993,7 +994,8 @@ vector suitable for `key-description', and COMMAND is a smbol." key-description 'helpful-describe-exactly-button 'symbol symbol - 'callable-p t))) + 'callable-p t + 'face button-face))) str t t)) @@ -1634,7 +1636,9 @@ Includes keybindings for aliases, unlike (push (format "%s %s" (propertize map 'face 'font-lock-variable-name-face) - key) + (if (>= emacs-major-version 28) + (propertize key 'face 'help-key-binding) + key)) (if (eq map 'global-map) global-lines mode-lines))))) (setq global-lines (-sort #'string< global-lines)) (setq mode-lines (-sort #'string< mode-lines)) @@ -1762,7 +1766,7 @@ POSITION-HEADS takes the form ((123 (defun foo)) (456 (defun bar)))." (with-temp-buffer (declare-function cl--generic-describe "cl-generic" (function)) (cl--generic-describe func) - (setf (point) (point-min)) + (goto-char (point-min)) (when (re-search-forward "^Implementations:$" nil t) (setq content (buffer-substring (point) (point-max))))) (when content @@ -2946,6 +2950,10 @@ See also `helpful-max-buffers'." (defvar helpful-mode-map (let* ((map (make-sparse-keymap))) (define-key map (kbd "g") #'helpful-update) + (define-key map [remap revert-buffer] #'helpful-update) + (when (fboundp 'revert-buffer-quick) + (define-key map [remap revert-buffer-quick] #'helpful-update)) + (define-key map (kbd "RET") #'helpful-visit-reference) (define-key map (kbd "TAB") #'forward-button) @@ -2964,6 +2972,39 @@ See also `helpful-max-buffers'." ;; TODO: find a cleaner solution. (defvar bookmark-make-record-function) +(defun helpful--add-support-for-org-links () + "Improve support for org \"help\" links through helpful." + (helpful--support-storing-org-links) + (helpful--prefer-helpful-when-following-org-link)) + +(defun helpful--support-storing-org-links () + "Make `org-store-link' in a helpful buffer return a \"help\" link." + (when (and (fboundp 'org-link-set-parameters) + (not (-contains-p (org-link-types) "helpful"))) + (org-link-set-parameters "helpful" + :store #'helpful--org-link-store))) + +(defun helpful--org-link-store () + "Store \"help\" type link when in a helpful buffer." + (when (derived-mode-p 'helpful-mode) + ;; Create a "help" link instead of a dedicated "helpful" link: the + ;; author of the Org document uses helful, but this is not + ;; necessarily the case of the reader of the document. + (org-link-store-props :type "help" + :link (format "help:%s" helpful--sym) + :description nil))) + +(defun helpful--prefer-helpful-when-following-org-link () + "Prefer helpful when using `org-open-at-point' on a \"help\" link." + (when (fboundp 'org-link-set-parameters) + (let ((follow-function (org-link-get-parameter "help" :follow))) + (when (not (equal follow-function #'helpful--org-link-follow)) + (org-link-set-parameters "help" + :follow #'helpful--org-link-follow))))) + +(defun helpful--org-link-follow (link _) + (helpful-symbol (intern link))) + (define-derived-mode helpful-mode special-mode "Helpful" "Major mode for *Helpful* buffers." (add-hook 'xref-backend-functions #'elisp--xref-backend nil t) @@ -2974,7 +3015,13 @@ See also `helpful-max-buffers'." ;; Enable users to bookmark helpful buffers. (set (make-local-variable 'bookmark-make-record-function) - #'helpful--bookmark-make-record)) + #'helpful--bookmark-make-record) + + ;; This function should normally only be called once after Org and + ;; helpful are loaded. To avoid using `eval-after-load' (which is + ;; only recommended in user init files), the function is called each + ;; time the major mode is used. + (helpful--add-support-for-org-links)) (provide 'helpful) ;;; helpful.el ends here diff --git a/org/elpa/markdown-mode-20230331.913/markdown-mode-autoloads.el b/org/elpa/markdown-mode-20230331.913/markdown-mode-autoloads.el new file mode 100644 index 0000000..9e93ad2 --- /dev/null +++ b/org/elpa/markdown-mode-20230331.913/markdown-mode-autoloads.el @@ -0,0 +1,64 @@ +;;; markdown-mode-autoloads.el --- automatically extracted autoloads -*- lexical-binding: t -*- +;; +;;; Code: + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + + +;;;### (autoloads nil "markdown-mode" "markdown-mode.el" (0 0 0 0)) +;;; Generated autoloads from markdown-mode.el + +(autoload 'markdown-mode "markdown-mode" "\ +Major mode for editing Markdown files. + +\(fn)" t nil) + +(add-to-list 'auto-mode-alist '("\\.\\(?:md\\|markdown\\|mkd\\|mdown\\|mkdn\\|mdwn\\)\\'" . markdown-mode)) + +(autoload 'gfm-mode "markdown-mode" "\ +Major mode for editing GitHub Flavored Markdown files. + +\(fn)" t nil) + +(autoload 'markdown-view-mode "markdown-mode" "\ +Major mode for viewing Markdown content. + +\(fn)" t nil) + +(autoload 'gfm-view-mode "markdown-mode" "\ +Major mode for viewing GitHub Flavored Markdown content. + +\(fn)" t nil) + +(autoload 'markdown-live-preview-mode "markdown-mode" "\ +Toggle native previewing on save for a specific markdown file. + +This is a minor mode. If called interactively, toggle the +`Markdown-Live-Preview mode' mode. If the prefix argument is +positive, enable the mode, and if it is zero or negative, disable +the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `markdown-live-preview-mode'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +\(fn &optional ARG)" t nil) + +(register-definition-prefixes "markdown-mode" '("defun-markdown-" "gfm-" "markdown")) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; coding: utf-8 +;; End: +;;; markdown-mode-autoloads.el ends here diff --git a/org/elpa/markdown-mode-20230331.913/markdown-mode-pkg.el b/org/elpa/markdown-mode-20230331.913/markdown-mode-pkg.el new file mode 100644 index 0000000..4aa41ef --- /dev/null +++ b/org/elpa/markdown-mode-20230331.913/markdown-mode-pkg.el @@ -0,0 +1,2 @@ +;;; Generated package description from markdown-mode.el -*- no-byte-compile: t -*- +(define-package "markdown-mode" "20230331.913" "Major mode for Markdown-formatted text" '((emacs "26.1")) :commit "ad3a816f7be97deb83fc0a7fa41305c79009bac5" :authors '(("Jason R. Blevins" . "jblevins@xbeta.org")) :maintainer '("Jason R. Blevins" . "jblevins@xbeta.org") :keywords '("markdown" "github flavored markdown" "itex") :url "https://jblevins.org/projects/markdown-mode/") diff --git a/org/elpa/markdown-mode-20230331.913/markdown-mode.el b/org/elpa/markdown-mode-20230331.913/markdown-mode.el new file mode 100644 index 0000000..fff9113 --- /dev/null +++ b/org/elpa/markdown-mode-20230331.913/markdown-mode.el @@ -0,0 +1,10016 @@ +;;; markdown-mode.el --- Major mode for Markdown-formatted text -*- lexical-binding: t; -*- + +;; Copyright (C) 2007-2022 Jason R. Blevins and markdown-mode +;; contributors (see the commit log for details). + +;; Author: Jason R. Blevins +;; Maintainer: Jason R. Blevins +;; Created: May 24, 2007 +;; Version: 2.6-alpha +;; Package-Version: 20230331.913 +;; Package-Commit: ad3a816f7be97deb83fc0a7fa41305c79009bac5 +;; Package-Requires: ((emacs "26.1")) +;; Keywords: Markdown, GitHub Flavored Markdown, itex +;; URL: https://jblevins.org/projects/markdown-mode/ + +;; This file is not part of GNU Emacs. + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; See the README.md file for details. + + +;;; Code: + +(require 'easymenu) +(require 'outline) +(require 'thingatpt) +(require 'cl-lib) +(require 'url-parse) +(require 'button) +(require 'color) +(require 'rx) +(require 'subr-x) + +(defvar jit-lock-start) +(defvar jit-lock-end) +(defvar flyspell-generic-check-word-predicate) +(defvar electric-pair-pairs) +(defvar sh-ancestor-alist) + +(declare-function project-roots "project") +(declare-function sh-set-shell "sh-script") + + +;;; Constants ================================================================= + +(defconst markdown-mode-version "2.6-alpha" + "Markdown mode version number.") + +(defconst markdown-output-buffer-name "*markdown-output*" + "Name of temporary buffer for markdown command output.") + + +;;; Global Variables ========================================================== + +(defvar markdown-reference-label-history nil + "History of used reference labels.") + +(defvar markdown-live-preview-mode nil + "Sentinel variable for command `markdown-live-preview-mode'.") + +(defvar markdown-gfm-language-history nil + "History list of languages used in the current buffer in GFM code blocks.") + + +;;; Customizable Variables ==================================================== + +(defvar markdown-mode-hook nil + "Hook run when entering Markdown mode.") + +(defvar markdown-before-export-hook nil + "Hook run before running Markdown to export XHTML output. +The hook may modify the buffer, which will be restored to it's +original state after exporting is complete.") + +(defvar markdown-after-export-hook nil + "Hook run after XHTML output has been saved. +Any changes to the output buffer made by this hook will be saved.") + +(defgroup markdown nil + "Major mode for editing text files in Markdown format." + :prefix "markdown-" + :group 'text + :link '(url-link "https://jblevins.org/projects/markdown-mode/")) + +(defcustom markdown-command (let ((command (cl-loop for cmd in '("markdown" "pandoc" "markdown_py") + when (executable-find cmd) + return (file-name-nondirectory it)))) + (or command "markdown")) + "Command to run markdown." + :group 'markdown + :type '(choice (string :tag "Shell command") (repeat (string)) function)) + +(defcustom markdown-command-needs-filename nil + "Set to non-nil if `markdown-command' does not accept input from stdin. +Instead, it will be passed a filename as the final command line +option. As a result, you will only be able to run Markdown from +buffers which are visiting a file." + :group 'markdown + :type 'boolean) + +(defcustom markdown-open-command nil + "Command used for opening Markdown files directly. +For example, a standalone Markdown previewer. This command will +be called with a single argument: the filename of the current +buffer. It can also be a function, which will be called without +arguments." + :group 'markdown + :type '(choice file function (const :tag "None" nil))) + +(defcustom markdown-open-image-command nil + "Command used for opening image files directly. +This is used at `markdown-follow-link-at-point'." + :group 'markdown + :type '(choice file function (const :tag "None" nil))) + +(defcustom markdown-hr-strings + '("-------------------------------------------------------------------------------" + "* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *" + "---------------------------------------" + "* * * * * * * * * * * * * * * * * * * *" + "---------" + "* * * * *") + "Strings to use when inserting horizontal rules. +The first string in the list will be the default when inserting a +horizontal rule. Strings should be listed in decreasing order of +prominence (as in headings from level one to six) for use with +promotion and demotion functions." + :group 'markdown + :type '(repeat string)) + +(defcustom markdown-bold-underscore nil + "Use two underscores when inserting bold text instead of two asterisks." + :group 'markdown + :type 'boolean) + +(defcustom markdown-italic-underscore nil + "Use underscores when inserting italic text instead of asterisks." + :group 'markdown + :type 'boolean) + +(defcustom markdown-marginalize-headers nil + "When non-nil, put opening atx header markup in a left margin. + +This setting goes well with `markdown-asymmetric-header'. But +sadly it conflicts with `linum-mode' since they both use the +same margin." + :group 'markdown + :type 'boolean + :safe 'booleanp + :package-version '(markdown-mode . "2.4")) + +(defcustom markdown-marginalize-headers-margin-width 6 + "Character width of margin used for marginalized headers. +The default value is based on there being six heading levels +defined by Markdown and HTML. Increasing this produces extra +whitespace on the left. Decreasing it may be preferred when +fewer than six nested heading levels are used." + :group 'markdown + :type 'natnump + :safe 'natnump + :package-version '(markdown-mode . "2.4")) + +(defcustom markdown-asymmetric-header nil + "Determines if atx header style will be asymmetric. +Set to a non-nil value to use asymmetric header styling, placing +header markup only at the beginning of the line. By default, +balanced markup will be inserted at the beginning and end of the +line around the header title." + :group 'markdown + :type 'boolean) + +(defcustom markdown-indent-function 'markdown-indent-line + "Function to use to indent." + :group 'markdown + :type 'function) + +(defcustom markdown-indent-on-enter t + "Determines indentation behavior when pressing \\[newline]. +Possible settings are nil, t, and \\='indent-and-new-item. + +When non-nil, pressing \\[newline] will call `newline-and-indent' +to indent the following line according to the context using +`markdown-indent-function'. In this case, note that +\\[electric-newline-and-maybe-indent] can still be used to insert +a newline without indentation. + +When set to \\='indent-and-new-item and the point is in a list item +when \\[newline] is pressed, the list will be continued on the next +line, where a new item will be inserted. + +When set to nil, simply call `newline' as usual. In this case, +you can still indent lines using \\[markdown-cycle] and continue +lists with \\[markdown-insert-list-item]. + +Note that this assumes the variable `electric-indent-mode' is +non-nil (enabled). When it is *disabled*, the behavior of +\\[newline] and `\\[electric-newline-and-maybe-indent]' are +reversed." + :group 'markdown + :type '(choice (const :tag "Don't automatically indent" nil) + (const :tag "Automatically indent" t) + (const :tag "Automatically indent and insert new list items" indent-and-new-item))) + +(defcustom markdown-enable-wiki-links nil + "Syntax highlighting for wiki links. +Set this to a non-nil value to turn on wiki link support by default. +Support can be toggled later using the `markdown-toggle-wiki-links' +function or \\[markdown-toggle-wiki-links]." + :group 'markdown + :type 'boolean + :safe 'booleanp + :package-version '(markdown-mode . "2.2")) + +(defcustom markdown-wiki-link-alias-first t + "When non-nil, treat aliased wiki links like [[alias text|PageName]]. +Otherwise, they will be treated as [[PageName|alias text]]." + :group 'markdown + :type 'boolean + :safe 'booleanp) + +(defcustom markdown-wiki-link-search-subdirectories nil + "When non-nil, search for wiki link targets in subdirectories. +This is the default search behavior for GitHub and is +automatically set to t in `gfm-mode'." + :group 'markdown + :type 'boolean + :safe 'booleanp + :package-version '(markdown-mode . "2.2")) + +(defcustom markdown-wiki-link-search-parent-directories nil + "When non-nil, search for wiki link targets in parent directories. +This is the default search behavior of Ikiwiki." + :group 'markdown + :type 'boolean + :safe 'booleanp + :package-version '(markdown-mode . "2.2")) + +(defcustom markdown-wiki-link-search-type nil + "Searching type for markdown wiki link. + +sub-directories: search for wiki link targets in sub directories +parent-directories: search for wiki link targets in parent directories +project: search for wiki link targets under project root" + :group 'markdown + :type '(set + (const :tag "search wiki link from subdirectories" sub-directories) + (const :tag "search wiki link from parent directories" parent-directories) + (const :tag "search wiki link under project root" project)) + :package-version '(markdown-mode . "2.5")) + +(make-obsolete-variable 'markdown-wiki-link-search-subdirectories 'markdown-wiki-link-search-type "2.5") +(make-obsolete-variable 'markdown-wiki-link-search-parent-directories 'markdown-wiki-link-search-type "2.5") + +(defcustom markdown-wiki-link-fontify-missing nil + "When non-nil, change wiki link face according to existence of target files. +This is expensive because it requires checking for the file each time the buffer +changes or the user switches windows. It is disabled by default because it may +cause lag when typing on slower machines." + :group 'markdown + :type 'boolean + :safe 'booleanp + :package-version '(markdown-mode . "2.2")) + +(defcustom markdown-uri-types + '("acap" "cid" "data" "dav" "fax" "file" "ftp" + "geo" "gopher" "http" "https" "imap" "ldap" "mailto" + "mid" "message" "modem" "news" "nfs" "nntp" + "pop" "prospero" "rtsp" "service" "sip" "tel" + "telnet" "tip" "urn" "vemmi" "wais") + "Link types for syntax highlighting of URIs." + :group 'markdown + :type '(repeat (string :tag "URI scheme"))) + +(defcustom markdown-url-compose-char + '(?∞ ?… ?⋯ ?# ?★ ?⚓) + "Placeholder character for hidden URLs. +This may be a single character or a list of characters. In case +of a list, the first one that satisfies `char-displayable-p' will +be used." + :type '(choice + (character :tag "Single URL replacement character") + (repeat :tag "List of possible URL replacement characters" + character)) + :package-version '(markdown-mode . "2.3")) + +(defcustom markdown-blockquote-display-char + '("▌" "┃" ">") + "String to display when hiding blockquote markup. +This may be a single string or a list of string. In case of a +list, the first one that satisfies `char-displayable-p' will be +used." + :type 'string + :type '(choice + (string :tag "Single blockquote display string") + (repeat :tag "List of possible blockquote display strings" string)) + :package-version '(markdown-mode . "2.3")) + +(defcustom markdown-hr-display-char + '(?─ ?━ ?-) + "Character for hiding horizontal rule markup. +This may be a single character or a list of characters. In case +of a list, the first one that satisfies `char-displayable-p' will +be used." + :group 'markdown + :type '(choice + (character :tag "Single HR display character") + (repeat :tag "List of possible HR display characters" character)) + :package-version '(markdown-mode . "2.3")) + +(defcustom markdown-definition-display-char + '(?⁘ ?⁙ ?≡ ?⌑ ?◊ ?:) + "Character for replacing definition list markup. +This may be a single character or a list of characters. In case +of a list, the first one that satisfies `char-displayable-p' will +be used." + :type '(choice + (character :tag "Single definition list character") + (repeat :tag "List of possible definition list characters" character)) + :package-version '(markdown-mode . "2.3")) + +(defcustom markdown-enable-math nil + "Syntax highlighting for inline LaTeX and itex expressions. +Set this to a non-nil value to turn on math support by default. +Math support can be enabled, disabled, or toggled later using +`markdown-toggle-math' or \\[markdown-toggle-math]." + :group 'markdown + :type 'boolean + :safe 'booleanp) +(make-variable-buffer-local 'markdown-enable-math) + +(defcustom markdown-enable-html t + "Enable font-lock support for HTML tags and attributes." + :group 'markdown + :type 'boolean + :safe 'booleanp + :package-version '(markdown-mode . "2.4")) + +(defcustom markdown-enable-highlighting-syntax nil + "Enable highlighting syntax." + :group 'markdown + :type 'boolean + :safe 'booleanp + :package-version '(markdown-mode . "2.5")) + +(defcustom markdown-css-paths nil + "List of URLs of CSS files to link to in the output XHTML." + :group 'markdown + :type '(repeat (string :tag "CSS File Path"))) + +(defcustom markdown-content-type "text/html" + "Content type string for the http-equiv header in XHTML output. +When set to an empty string, this attribute is omitted. Defaults to +`text/html'." + :group 'markdown + :type 'string) + +(defcustom markdown-coding-system nil + "Character set string for the http-equiv header in XHTML output. +Defaults to `buffer-file-coding-system' (and falling back to +`utf-8' when not available). Common settings are `iso-8859-1' +and `iso-latin-1'. Use `list-coding-systems' for more choices." + :group 'markdown + :type 'coding-system) + +(defcustom markdown-export-kill-buffer t + "Kill output buffer after HTML export. +When non-nil, kill the HTML output buffer after +exporting with `markdown-export'." + :group 'markdown + :type 'boolean + :safe 'booleanp + :package-version '(markdown-mode . "2.4")) + +(defcustom markdown-xhtml-header-content "" + "Additional content to include in the XHTML block." + :group 'markdown + :type 'string) + +(defcustom markdown-xhtml-body-preamble "" + "Content to include in the XHTML block, before the output." + :group 'markdown + :type 'string + :safe 'stringp + :package-version '(markdown-mode . "2.4")) + +(defcustom markdown-xhtml-body-epilogue "" + "Content to include in the XHTML block, after the output." + :group 'markdown + :type 'string + :safe 'stringp + :package-version '(markdown-mode . "2.4")) + +(defcustom markdown-xhtml-standalone-regexp + "^\\(<\\?xml\\| Links & Images menu." + :group 'markdown + :type 'boolean + :safe 'booleanp + :package-version '(markdown-mode . "2.3")) +(make-variable-buffer-local 'markdown-hide-urls) + +(defcustom markdown-translate-filename-function #'identity + "Function to use to translate filenames when following links. +\\\\[markdown-follow-thing-at-point] and \\[markdown-follow-link-at-point] +call this function with the filename as only argument whenever +they encounter a filename (instead of a URL) to be visited and +use its return value instead of the filename in the link. For +example, if absolute filenames are actually relative to a server +root directory, you can set +`markdown-translate-filename-function' to a function that +prepends the root directory to the given filename." + :group 'markdown + :type 'function + :risky t + :package-version '(markdown-mode . "2.4")) + +(defcustom markdown-max-image-size nil + "Maximum width and height for displayed inline images. +This variable may be nil or a cons cell (MAX-WIDTH . MAX-HEIGHT). +When nil, use the actual size. Otherwise, use ImageMagick to +resize larger images to be of the given maximum dimensions. This +requires Emacs to be built with ImageMagick support." + :group 'markdown + :package-version '(markdown-mode . "2.4") + :type '(choice + (const :tag "Use actual image width" nil) + (cons (choice (sexp :tag "Maximum width in pixels") + (const :tag "No maximum width" nil)) + (choice (sexp :tag "Maximum height in pixels") + (const :tag "No maximum height" nil))))) + +(defcustom markdown-mouse-follow-link t + "Non-nil means mouse on a link will follow the link. +This variable must be set before loading markdown-mode." + :group 'markdown + :type 'boolean + :safe 'booleanp + :package-version '(markdown-mode . "2.5")) + +(defcustom markdown-table-align-p t + "Non-nil means that table is aligned after table operation." + :group 'markdown + :type 'boolean + :safe 'booleanp + :package-version '(markdown-mode . "2.5")) + +(defcustom markdown-fontify-whole-heading-line nil + "Non-nil means fontify the whole line for headings. +This is useful when setting a background color for the +markdown-header-face-* faces." + :group 'markdown + :type 'boolean + :safe 'booleanp + :package-version '(markdown-mode . "2.5")) + + +;;; Markdown-Specific `rx' Macro ============================================== + +;; Based on python-rx from python.el. +(eval-and-compile + (defconst markdown-rx-constituents + `((newline . ,(rx "\n")) + ;; Note: #405 not consider markdown-list-indent-width however this is never used + (indent . ,(rx (or (repeat 4 " ") "\t"))) + (block-end . ,(rx (and (or (one-or-more (zero-or-more blank) "\n") line-end)))) + (numeral . ,(rx (and (one-or-more (any "0-9#")) "."))) + (bullet . ,(rx (any "*+:-"))) + (list-marker . ,(rx (or (and (one-or-more (any "0-9#")) ".") + (any "*+:-")))) + (checkbox . ,(rx "[" (any " xX") "]"))) + "Markdown-specific sexps for `markdown-rx'") + + (defun markdown-rx-to-string (form &optional no-group) + "Markdown mode specialized `rx-to-string' function. +This variant supports named Markdown expressions in FORM. +NO-GROUP non-nil means don't put shy groups around the result." + (let ((rx-constituents (append markdown-rx-constituents rx-constituents))) + (rx-to-string form no-group))) + + (defmacro markdown-rx (&rest regexps) + "Markdown mode specialized rx macro. +This variant of `rx' supports common Markdown named REGEXPS." + (cond ((null regexps) + (error "No regexp")) + ((cdr regexps) + (markdown-rx-to-string `(and ,@regexps) t)) + (t + (markdown-rx-to-string (car regexps) t))))) + + +;;; Regular Expressions ======================================================= + +(defconst markdown-regex-comment-start + "") + (setq-local comment-start-skip "=0) { + printf("%s Next display skipped. Reset display switcher.\n",node->class_->scanner->display_prompt); + } + } else { + SYNCTEX_MSG_SEND(node, display); + } + } +} +static char * _synctex_node_abstract(synctex_node_p node) { + SYNCTEX_PARAMETER_ASSERT(node || node->class_); + return (node && node->class_->abstract)? node->class_->abstract(node):"none"; +} + +SYNCTEX_INLINE static void _synctex_display_child(synctex_node_p node) { + synctex_node_p N = _synctex_tree_child(node); + if (N) { + _synctex_scanner_display_prompt_down(N->class_->scanner); + synctex_node_display(N); + _synctex_scanner_display_prompt_up(N->class_->scanner); + } +} + +SYNCTEX_INLINE static void _synctex_display_sibling(synctex_node_p node) { + synctex_node_display(__synctex_tree_sibling(node)); +} +#define SYNCTEX_ABSTRACT_MAX 128 +static char * _synctex_abstract_input(synctex_node_p node) { + static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; + if (node) { + snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"Input:%i:%s(%i)" SYNCTEX_PRINT_CHARINDEX_FMT, + _synctex_data_tag(node), + _synctex_data_name(node), + _synctex_data_line(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + } + return abstract; +} + +static void _synctex_display_input(synctex_node_p node) { + if (node) { + printf("Input:%i:%s(%i)" + SYNCTEX_PRINT_CHARINDEX_FMT + "\n", + _synctex_data_tag(node), + _synctex_data_name(node), + _synctex_data_line(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + synctex_node_display(__synctex_tree_sibling(node)); + } +} + +static char * _synctex_abstract_sheet(synctex_node_p node) { + static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; + if (node) { + snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"{%i...}" SYNCTEX_PRINT_CHARINDEX_FMT, + _synctex_data_page(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + } + return abstract; +} + +static void _synctex_display_sheet(synctex_node_p node) { + if (node) { + printf("%s{%i" + SYNCTEX_PRINT_CHARINDEX_FMT + "\n", + node->class_->scanner->display_prompt, + _synctex_data_page(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + _synctex_display_child(node); + printf("%s}\n",node->class_->scanner->display_prompt); + _synctex_display_sibling(node); + } +} + +static char * _synctex_abstract_form(synctex_node_p node) { + static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; + if (node) { + snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"<%i...>" SYNCTEX_PRINT_CHARINDEX_FMT, + _synctex_data_tag(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + SYNCTEX_PRINT_CHARINDEX; + } + return abstract; +} + +static void _synctex_display_form(synctex_node_p node) { + if (node) { + printf("%s<%i" + SYNCTEX_PRINT_CHARINDEX_FMT + "\n", + node->class_->scanner->display_prompt, + _synctex_data_tag(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + _synctex_display_child(node); + printf("%s>\n",node->class_->scanner->display_prompt); + _synctex_display_sibling(node); + } +} + +static char * _synctex_abstract_vbox(synctex_node_p node) { + static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; + if (node) { + snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"[%i,%i:%i,%i:%i,%i,%i...]" + SYNCTEX_PRINT_CHARINDEX_FMT, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_h(node), + _synctex_data_v(node), + _synctex_data_width(node), + _synctex_data_height(node), + _synctex_data_depth(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + } + return abstract; +} + +static void _synctex_display_vbox(synctex_node_p node) { + if (node) { + printf("%s[%i,%i:%i,%i:%i,%i,%i" + SYNCTEX_PRINT_CHARINDEX_FMT + "\n", + node->class_->scanner->display_prompt, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_h(node), + _synctex_data_v(node), + _synctex_data_width(node), + _synctex_data_height(node), + _synctex_data_depth(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + _synctex_display_child(node); + printf("%s]\n%slast:%s\n", + node->class_->scanner->display_prompt, + node->class_->scanner->display_prompt, + _synctex_node_abstract(_synctex_tree_last(node))); + _synctex_display_sibling(node); + } +} + +static char * _synctex_abstract_hbox(synctex_node_p node) { + static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; + if (node) { + snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"(%i,%i~%i*%i:%i,%i:%i,%i,%i...)" + SYNCTEX_PRINT_CHARINDEX_FMT, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_mean_line(node), + _synctex_data_weight(node), + _synctex_data_h(node), + _synctex_data_v(node), + _synctex_data_width(node), + _synctex_data_height(node), + _synctex_data_depth(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + } + return abstract; +} + +static void _synctex_display_hbox(synctex_node_p node) { + if (node) { + printf("%s(%i,%i~%i*%i:%i,%i:%i,%i,%i" + SYNCTEX_PRINT_CHARINDEX_FMT + "\n", + node->class_->scanner->display_prompt, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_mean_line(node), + _synctex_data_weight(node), + _synctex_data_h(node), + _synctex_data_v(node), + _synctex_data_width(node), + _synctex_data_height(node), + _synctex_data_depth(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + _synctex_display_child(node); + printf("%s)\n%slast:%s\n", + node->class_->scanner->display_prompt, + node->class_->scanner->display_prompt, + _synctex_node_abstract(_synctex_tree_last(node))); + _synctex_display_sibling(node); + } +} + +static char * _synctex_abstract_void_vbox(synctex_node_p node) { + static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; + if (node) { + snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"v%i,%i;%i,%i:%i,%i,%i" + SYNCTEX_PRINT_CHARINDEX_FMT + "\n", + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_h(node), + _synctex_data_v(node), + _synctex_data_width(node), + _synctex_data_height(node), + _synctex_data_depth(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + } + return abstract; +} + +static void _synctex_display_void_vbox(synctex_node_p node) { + if (node) { + printf("%sv%i,%i;%i,%i:%i,%i,%i" + SYNCTEX_PRINT_CHARINDEX_FMT + "\n", + node->class_->scanner->display_prompt, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_h(node), + _synctex_data_v(node), + _synctex_data_width(node), + _synctex_data_height(node), + _synctex_data_depth(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + _synctex_display_sibling(node); + } +} + +static char * _synctex_abstract_void_hbox(synctex_node_p node) { + static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; + if (node) { + snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"h%i,%i:%i,%i:%i,%i,%i" + SYNCTEX_PRINT_CHARINDEX_FMT, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_h(node), + _synctex_data_v(node), + _synctex_data_width(node), + _synctex_data_height(node), + _synctex_data_depth(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + } + return abstract; +} + +static void _synctex_display_void_hbox(synctex_node_p node) { + if (node) { + printf("%sh%i,%i:%i,%i:%i,%i,%i" + SYNCTEX_PRINT_CHARINDEX_FMT + "\n", + node->class_->scanner->display_prompt, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_h(node), + _synctex_data_v(node), + _synctex_data_width(node), + _synctex_data_height(node), + _synctex_data_depth(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + _synctex_display_sibling(node); + } +} + +static char * _synctex_abstract_glue(synctex_node_p node) { + static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; + if (node) { + snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"glue:%i,%i:%i,%i" + SYNCTEX_PRINT_CHARINDEX_FMT, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_h(node), + _synctex_data_v(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + } + return abstract; +} + +static void _synctex_display_glue(synctex_node_p node) { + if (node) { + printf("%sglue:%i,%i:%i,%i" + SYNCTEX_PRINT_CHARINDEX_FMT + "\n", + node->class_->scanner->display_prompt, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_h(node), + _synctex_data_v(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + _synctex_display_sibling(node); + } +} + +static char * _synctex_abstract_rule(synctex_node_p node) { + static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; + if (node) { + snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"rule:%i,%i:%i,%i:%i,%i,%i" + SYNCTEX_PRINT_CHARINDEX_FMT, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_h(node), + _synctex_data_v(node), + _synctex_data_width(node), + _synctex_data_height(node), + _synctex_data_depth(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + } + return abstract; +} + +static void _synctex_display_rule(synctex_node_p node) { + if (node) { + printf("%srule:%i,%i:%i,%i:%i,%i,%i" + SYNCTEX_PRINT_CHARINDEX_FMT + "\n", + node->class_->scanner->display_prompt, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_h(node), + _synctex_data_v(node), + _synctex_data_width(node), + _synctex_data_height(node), + _synctex_data_depth(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + _synctex_display_sibling(node); + } +} + +static char * _synctex_abstract_math(synctex_node_p node) { + static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; + if (node) { + snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"math:%i,%i:%i,%i" + SYNCTEX_PRINT_CHARINDEX_FMT, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_h(node), + _synctex_data_v(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + } + return abstract; +} + +static void _synctex_display_math(synctex_node_p node) { + if (node) { + printf("%smath:%i,%i:%i,%i" + SYNCTEX_PRINT_CHARINDEX_FMT + "\n", + node->class_->scanner->display_prompt, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_h(node), + _synctex_data_v(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + _synctex_display_sibling(node); + } +} + +static char * _synctex_abstract_kern(synctex_node_p node) { + static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; + if (node) { + snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"kern:%i,%i:%i,%i:%i" + SYNCTEX_PRINT_CHARINDEX_FMT, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_h(node), + _synctex_data_v(node), + _synctex_data_width(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + } + return abstract; +} + +static void _synctex_display_kern(synctex_node_p node) { + if (node) { + printf("%skern:%i,%i:%i,%i:%i" + SYNCTEX_PRINT_CHARINDEX_FMT + "\n", + node->class_->scanner->display_prompt, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_h(node), + _synctex_data_v(node), + _synctex_data_width(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + _synctex_display_sibling(node); + } +} + +static char * _synctex_abstract_boundary(synctex_node_p node) { + static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; + if (node) { + snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"boundary:%i,%i:%i,%i" + SYNCTEX_PRINT_CHARINDEX_FMT, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_h(node), + _synctex_data_v(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + } + return abstract; +} + +static void _synctex_display_boundary(synctex_node_p node) { + if (node) { + printf("%sboundary:%i,%i:%i,%i" + SYNCTEX_PRINT_CHARINDEX_FMT + "\n", + node->class_->scanner->display_prompt, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_h(node), + _synctex_data_v(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + _synctex_display_sibling(node); + } +} + +static char * _synctex_abstract_box_bdry(synctex_node_p node) { + static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; + if (node) { + snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"box bdry:%i,%i:%i,%i" SYNCTEX_PRINT_CHARINDEX_FMT, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_h(node), + _synctex_data_v(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + } + return abstract; +} + +static void _synctex_display_box_bdry(synctex_node_p node) { + if (node) { + printf("%sbox bdry:%i,%i:%i,%i", + node->class_->scanner->display_prompt, + _synctex_data_tag(node), + _synctex_data_line(node), + _synctex_data_h(node), + _synctex_data_v(node)); + SYNCTEX_PRINT_CHARINDEX_NL; + _synctex_display_sibling(node); + } +} + +static char * _synctex_abstract_ref(synctex_node_p node) { + static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; + if (node) { + snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"form ref:%i:%i,%i" SYNCTEX_PRINT_CHARINDEX_FMT, + _synctex_data_tag(node), + _synctex_data_h(node), + _synctex_data_v(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + } + return abstract; +} + +static void _synctex_display_ref(synctex_node_p node) { + if (node) { + printf("%sform ref:%i:%i,%i", + node->class_->scanner->display_prompt, + _synctex_data_tag(node), + _synctex_data_h(node), + _synctex_data_v(node)); + SYNCTEX_PRINT_CHARINDEX_NL; + _synctex_display_sibling(node); + } +} +static char * _synctex_abstract_proxy(synctex_node_p node) { + static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; + if (node) { + synctex_node_p N = _synctex_tree_target(node); + snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"%s:%i,%i:%i,%i/%p%s", + synctex_node_isa(node), + synctex_node_tag(node), + synctex_node_line(node), + _synctex_data_h(node), + _synctex_data_v(node), + node, + _synctex_node_abstract(N)); + } + return abstract; +} +static void _synctex_display_proxy(synctex_node_p node) { + if (node) { + synctex_node_p N = _synctex_tree_target(node); + printf("%s%s:%i,%i:%i,%i", + node->class_->scanner->display_prompt, + synctex_node_isa(node), + synctex_node_tag(node), + synctex_node_line(node), + _synctex_data_h(node), + _synctex_data_v(node)); + if (N) { + printf("=%i,%i:%i,%i,%i->%s", + synctex_node_h(node), + synctex_node_v(node), + synctex_node_width(node), + synctex_node_height(node), + synctex_node_depth(node), + _synctex_node_abstract(N)); + } + printf("\n"); + _synctex_display_child(node); + _synctex_display_sibling(node); + } +} +static char * _synctex_abstract_proxy_vbox(synctex_node_p node) { + static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; + if (node) { + snprintf(abstract,SYNCTEX_ABSTRACT_MAX, + "[*%i,%i:%i,%i:%i,%i,%i...*]" + SYNCTEX_PRINT_CHARINDEX_FMT, + synctex_node_tag(node), + synctex_node_line(node), + synctex_node_h(node), + synctex_node_v(node), + synctex_node_width(node), + synctex_node_height(node), + synctex_node_depth(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + } + return abstract; +} + +static void _synctex_display_proxy_vbox(synctex_node_p node) { + if (node) { + printf("%s[*%i,%i:%i,%i:%i,%i,%i" + SYNCTEX_PRINT_CHARINDEX_FMT + "\n", + node->class_->scanner->display_prompt, + synctex_node_tag(node), + synctex_node_line(node), + synctex_node_h(node), + synctex_node_v(node), + synctex_node_width(node), + synctex_node_height(node), + synctex_node_depth(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + _synctex_display_child(node); + printf("%s*]\n%slast:%s\n", + node->class_->scanner->display_prompt, + node->class_->scanner->display_prompt, + _synctex_node_abstract(_synctex_tree_last(node))); + _synctex_display_sibling(node); + } +} + +static char * _synctex_abstract_proxy_hbox(synctex_node_p node) { + static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; + if (node) { + snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"(*%i,%i~%i*%i:%i,%i:%i,%i,%i...*)/%p" + SYNCTEX_PRINT_CHARINDEX_FMT, + synctex_node_tag(node), + synctex_node_line(node), + synctex_node_mean_line(node), + synctex_node_weight(node), + synctex_node_h(node), + synctex_node_v(node), + synctex_node_width(node), + synctex_node_height(node), + synctex_node_depth(node), + node + SYNCTEX_PRINT_CHARINDEX_WHAT); + } + return abstract; +} + +static void _synctex_display_proxy_hbox(synctex_node_p node) { + if (node) { + printf("%s(*%i,%i~%i*%i:%i,%i:%i,%i,%i" + SYNCTEX_PRINT_CHARINDEX_FMT + "\n", + node->class_->scanner->display_prompt, + synctex_node_tag(node), + synctex_node_line(node), + synctex_node_mean_line(node), + synctex_node_weight(node), + synctex_node_h(node), + synctex_node_v(node), + synctex_node_width(node), + synctex_node_height(node), + synctex_node_depth(node) + SYNCTEX_PRINT_CHARINDEX_WHAT); + _synctex_display_child(node); + printf("%s*)\n%slast:%s\n", + node->class_->scanner->display_prompt, + node->class_->scanner->display_prompt, + _synctex_node_abstract(_synctex_tree_last(node))); + _synctex_display_sibling(node); + } +} + +static char * _synctex_abstract_handle(synctex_node_p node) { + static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; + if (node) { + synctex_node_p N = _synctex_tree_target(node); + if (N && !N->class_) { + exit(1); + } + snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"%s:%s", + synctex_node_isa(node), + (N?_synctex_node_abstract(N):"")); + } + return abstract; +} +static void _synctex_display_handle(synctex_node_p node) { + if (node) { + synctex_node_p N = _synctex_tree_target(node); + printf("%s%s(%i):->%s\n", + node->class_->scanner->display_prompt, + synctex_node_isa(node), + _synctex_data_weight(N), + _synctex_node_abstract(N)); + _synctex_display_child(node); + _synctex_display_sibling(node); + } +} +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark STATUS +# endif + +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark Prototypes +# endif +typedef struct { + size_t size; + synctex_status_t status; +} synctex_zs_s; +static synctex_zs_s _synctex_buffer_get_available_size(synctex_scanner_p scanner, size_t size); +static synctex_status_t _synctex_next_line(synctex_scanner_p scanner); +static synctex_status_t _synctex_match_string(synctex_scanner_p scanner, const char * the_string); + +typedef struct synctex_ns_t { + synctex_node_p node; + synctex_status_t status; +} synctex_ns_s; +static synctex_ns_s __synctex_parse_new_input(synctex_scanner_p scanner); +static synctex_status_t _synctex_scan_preamble(synctex_scanner_p scanner); +typedef struct { + float value; + synctex_status_t status; +} synctex_fs_s; +static synctex_fs_s _synctex_scan_float_and_dimension(synctex_scanner_p scanner); +static synctex_status_t _synctex_scan_post_scriptum(synctex_scanner_p scanner); +static synctex_status_t _synctex_scan_postamble(synctex_scanner_p scanner); +static synctex_status_t _synctex_setup_visible_hbox(synctex_node_p box); +static synctex_status_t _synctex_scan_content(synctex_scanner_p scanner); +int synctex_scanner_pre_x_offset(synctex_scanner_p scanner); +int synctex_scanner_pre_y_offset(synctex_scanner_p scanner); +const char * synctex_scanner_get_output_fmt(synctex_scanner_p scanner); + +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark SCANNER UTILITIES +# endif + +# define SYNCTEX_FILE (scanner->reader->file) + +/** + * Try to ensure that the buffer contains at least size bytes. + * Passing a huge size argument means the whole buffer length. + * Passing a 0 size argument means return the available buffer length, without reading the file. + * In that case, the return status is always SYNCTEX_STATUS_OK unless the given scanner is NULL. + * The size_t value returned is the number of bytes now available in the buffer. This is a nonnegative integer, it may take the value 0. + * It is the responsibility of the caller to test whether this size is conforming to its needs. + * Negative values may return in case of error, actually + * when there was an error reading the synctex file. + * - parameter scanner: The owning scanner. When NULL, returns SYNCTEX_STATUS_BAD_ARGUMENT. + * - parameter expected: expected number of bytes. + * - returns: a size and a status. + */ +static synctex_zs_s _synctex_buffer_get_available_size(synctex_scanner_p scanner, size_t expected) { + size_t size = 0; + if (NULL == scanner) { + return (synctex_zs_s){0,SYNCTEX_STATUS_BAD_ARGUMENT}; + } + if (expected>scanner->reader->size){ + expected = scanner->reader->size; + } + size = SYNCTEX_END - SYNCTEX_CUR; /* available is the number of unparsed chars in the buffer */ + if (expected<=size) { + /* There are already sufficiently many characters in the buffer */ + return (synctex_zs_s){size,SYNCTEX_STATUS_OK}; + } + if (SYNCTEX_FILE) { + /* Copy the remaining part of the buffer to the beginning, + * then read the next part of the file */ + int already_read = 0; +# if defined(SYNCTEX_USE_CHARINDEX) + scanner->reader->charindex_offset += SYNCTEX_CUR - SYNCTEX_START; +# endif + if (size) { + memmove(SYNCTEX_START, SYNCTEX_CUR, size); + } + SYNCTEX_CUR = SYNCTEX_START + size; /* the next character after the move, will change. */ + /* Fill the buffer up to its end */ + already_read = gzread(SYNCTEX_FILE,(void *)SYNCTEX_CUR,(int)(SYNCTEX_BUFFER_SIZE - size)); + if (already_read>0) { + /* We assume that 0already_read) { + /* There is a possible error in reading the file */ + int errnum = 0; + const char * error_string = gzerror(SYNCTEX_FILE, &errnum); + if (Z_ERRNO == errnum) { + /* There is an error in zlib caused by the file system */ + _synctex_error("gzread error from the file system (%i)",errno); + return (synctex_zs_s){0,SYNCTEX_STATUS_ERROR}; + } else if (errnum) { + _synctex_error("gzread error (%i:%i,%s)",already_read,errnum,error_string); + return (synctex_zs_s){0,SYNCTEX_STATUS_ERROR}; + } + } + /* Nothing was read, we are at the end of the file. */ + gzclose(SYNCTEX_FILE); + SYNCTEX_FILE = NULL; + SYNCTEX_END = SYNCTEX_CUR; + SYNCTEX_CUR = SYNCTEX_START; + * SYNCTEX_END = '\0';/* Terminate the string properly.*/ + /* there might be a bit of text left */ + return (synctex_zs_s){SYNCTEX_END - SYNCTEX_CUR,SYNCTEX_STATUS_EOF}; + } + /* We cannot enlarge the buffer because the end of the file was reached. */ + return (synctex_zs_s){size,SYNCTEX_STATUS_EOF}; +} + +/* Used when parsing the synctex file. + * Advance to the next character starting a line. + * Actually, only '\n' is recognized as end of line marker. + * On normal completion, the returned value is the number of unparsed characters available in the buffer. + * In general, it is a positive value, 0 meaning that the end of file was reached. + * -1 is returned in case of error, actually because there was an error while feeding the buffer. + * When the function returns with no error, SYNCTEX_CUR points to the first character of the next line, if any. + * J. Laurens: Sat May 10 07:52:31 UTC 2008 + */ +static synctex_status_t _synctex_next_line(synctex_scanner_p scanner) { + synctex_status_t status = SYNCTEX_STATUS_OK; + if (NULL == scanner) { + return SYNCTEX_STATUS_BAD_ARGUMENT; + } +infinite_loop: + while(SYNCTEX_CURreader->line_number; + return _synctex_buffer_get_available_size(scanner, 1).status; + } + ++SYNCTEX_CUR; + } + /* Here, we have SYNCTEX_CUR == SYNCTEX_END, such that the next call to _synctex_buffer_get_available_size + * will read another bunch of synctex file. Little by little, we advance to the end of the file. */ + status = _synctex_buffer_get_available_size(scanner, 1).status; + if (status<=SYNCTEX_STATUS_EOF) { + return status; + } + goto infinite_loop; +} + +/* Scan the given string. + * Both scanner and the_string must not be NULL, and the_string must not be 0 length. + * SYNCTEX_STATUS_OK is returned if the string is found, + * SYNCTEX_STATUS_EOF is returned when the EOF is reached, + * SYNCTEX_STATUS_NOT_OK is returned is the string is not found, + * an error status is returned otherwise. + * This is a critical method because buffering renders things more difficult. + * The given string might be as long as the maximum size_t value. + * As side effect, the buffer state may have changed if the given argument string can't fit into the buffer. + */ +static synctex_status_t _synctex_match_string(synctex_scanner_p scanner, const char * the_string) { + size_t tested_len = 0; /* the number of characters at the beginning of the_string that match */ + size_t remaining_len = 0; /* the number of remaining characters of the_string that should match */ + size_t available = 0; + synctex_zs_s zs = {0,0}; + if (NULL == scanner || NULL == the_string) { + return SYNCTEX_STATUS_BAD_ARGUMENT; + } + remaining_len = strlen(the_string); /* All the_string should match */ + if (0 == remaining_len) { + return SYNCTEX_STATUS_BAD_ARGUMENT; + } + /* How many characters available in the buffer? */ + zs = _synctex_buffer_get_available_size(scanner,remaining_len); + if (zs.status=remaining_len) { + /* The buffer is sufficiently big to hold the expected number of characters. */ + if (strncmp((char *)SYNCTEX_CUR,the_string,remaining_len)) { + return SYNCTEX_STATUS_NOT_OK; + } + return_OK: + /* Advance SYNCTEX_CUR to the next character after the_string. */ + SYNCTEX_CUR += remaining_len; + return SYNCTEX_STATUS_OK; + } else if (strncmp((char *)SYNCTEX_CUR,the_string,zs.size)) { + /* No need to go further, this is not the expected string in the buffer. */ + return SYNCTEX_STATUS_NOT_OK; + } else if (SYNCTEX_FILE) { + /* The buffer was too small to contain remaining_len characters. + * We have to cut the string into pieces. */ + z_off_t offset = 0L; + /* the first part of the string is found, advance the_string to the next untested character. */ + the_string += zs.size; + /* update the remaining length and the parsed length. */ + remaining_len -= zs.size; + tested_len += zs.size; + SYNCTEX_CUR += zs.size; /* We validate the tested characters. */ + if (0 == remaining_len) { + /* Nothing left to test, we have found the given string. */ + return SYNCTEX_STATUS_OK; + } + /* We also have to record the current state of the file cursor because + * if the_string does not match, all this should be a totally blank operation, + * for which the file and buffer states should not be modified at all. + * In fact, the states of the buffer before and after this function are in general different + * but they are totally equivalent as long as the values of the buffer before SYNCTEX_CUR + * can be safely discarded. */ + offset = gztell(SYNCTEX_FILE); + /* offset now corresponds to the first character of the file that was not buffered. */ + /* SYNCTEX_CUR - SYNCTEX_START is the number of chars that where already buffered and + * that match the head of the_string. If in fine the_string does not match, all these chars must be recovered + * because the whole buffer contents is replaced in _synctex_buffer_get_available_size. + * They were buffered from offset-len location in the file. */ + offset -= SYNCTEX_CUR - SYNCTEX_START; + more_characters: + /* There is still some work to be done, so read another bunch of file. + * This is the second call to _synctex_buffer_get_available_size, + * which means that the actual contents of the buffer will be discarded. + * We will definitely have to recover the previous state in case we do not find the expected string. */ + zs = _synctex_buffer_get_available_size(scanner,remaining_len); + if (zs.statusptr) { + SYNCTEX_CUR = end; + return (synctex_is_s){result,SYNCTEX_STATUS_OK}; + } + return (synctex_is_s){result,SYNCTEX_STATUS_NOT_OK}; +} +static synctex_is_s _synctex_decode_int_opt(synctex_scanner_p scanner, int default_value) { + char * ptr = NULL; + char * end = NULL; + synctex_zs_s zs = {0, 0}; + if (NULL == scanner) { + return (synctex_is_s){default_value, SYNCTEX_STATUS_BAD_ARGUMENT}; + } + zs = _synctex_buffer_get_available_size(scanner, SYNCTEX_BUFFER_MIN_SIZE); + if (zs.statusptr) { + SYNCTEX_CUR = end; + return (synctex_is_s){result,SYNCTEX_STATUS_OK}; + } + return (synctex_is_s){default_value,SYNCTEX_STATUS_NOT_OK}; + } + return (synctex_is_s){default_value,SYNCTEX_STATUS_OK}; +} +/* Used when parsing the synctex file. + * Decode an integer for a v field. + * Try the _synctex_decode_int version and set the last v field scanned. + * If it does not succeed, tries to match an '=' sign, + * which is a shortcut for the last v field scanned. + */ +# define SYNCTEX_INPUT_COMEQUALS ",=" +static synctex_is_s _synctex_decode_int_v(synctex_scanner_p scanner) { + synctex_is_s is = _synctex_decode_int(scanner); + if (SYNCTEX_STATUS_OK == is.status) { + scanner->reader->lastv = is.integer; + return is; + } + is.status = _synctex_match_string(scanner,SYNCTEX_INPUT_COMEQUALS); + if (is.statusreader->lastv; + return is; +} + +/* The purpose of this function is to read a string. + * A string is an array of characters from the current parser location + * and before the next '\n' character. + * If a string was properly decoded, it is returned in value_ref and + * the cursor points to the new line marker. + * The returned string was allocated on the heap, the caller is the owner and + * is responsible to free it in due time, + * unless it transfers the ownership to another object. + * If no string is parsed, * value_ref is undefined. + * The maximum length of a string that a scanner can decode is platform dependent, namely UINT_MAX. + * If you just want to blindly parse the file up to the end of the current line, + * use _synctex_next_line instead. + * On return, the scanner cursor is unchanged if a string could not be scanned or + * points to the terminating '\n' character otherwise. As a consequence, + * _synctex_next_line is necessary after. + * If either scanner or value_ref is NULL, it is considered as an error and + * SYNCTEX_STATUS_BAD_ARGUMENT is returned. + */ +static synctex_ss_s _synctex_decode_string(synctex_scanner_p scanner) { + char * end = NULL; + size_t len = 0;/* The number of bytes to copy */ + size_t already_len = 0; + synctex_zs_s zs = {0,0}; + char * string = NULL; + if (NULL == scanner) { + return (synctex_ss_s){NULL,SYNCTEX_STATUS_BAD_ARGUMENT}; + } + /* The buffer must at least contain one character: the '\n' end of line marker */ + if (SYNCTEX_CUR>=SYNCTEX_END) { +more_characters: + zs = _synctex_buffer_get_available_size(scanner,1); + if (zs.status < SYNCTEX_STATUS_EOF) { + return (synctex_ss_s){NULL,zs.status}; + } else if (0 == zs.size) { + return (synctex_ss_s){NULL,SYNCTEX_STATUS_EOF}; + } + } + /* Now we are sure that there is at least one available character, either because + * SYNCTEX_CUR was already < SYNCTEX_END, or because the buffer has been properly filled. */ + /* end will point to the next unparsed '\n' character in the file, when mapped to the buffer. */ + end = SYNCTEX_CUR; + /* We scan all the characters up to the next '\n' */ + while (end0) { + already_len = len--; + if (string[len]!=' ') { + break; + } + } + string[already_len] = '\0'; + return (synctex_ss_s){string,SYNCTEX_STATUS_OK}; + } + free(string); + _synctex_error("could not copy memory (1)."); + return (synctex_ss_s){NULL,SYNCTEX_STATUS_ERROR}; + } + } + _synctex_error("could not (re)allocate memory (1)."); + return (synctex_ss_s){NULL,SYNCTEX_STATUS_ERROR}; +} + +/* Used when parsing the synctex file. + * Read an Input record. + * - parameter scanner: non NULL scanner + * - returns SYNCTEX_STATUS_OK on successful completions, others values otherwise. + */ +static synctex_ns_s __synctex_parse_new_input(synctex_scanner_p scanner) { + synctex_node_p input = NULL; + synctex_status_t status = SYNCTEX_STATUS_BAD_ARGUMENT; + synctex_zs_s zs = {0,0}; + if (NULL == scanner) { + return (synctex_ns_s){NULL,status}; + } + if ((status=_synctex_match_string(scanner,SYNCTEX_INPUT_MARK))input);/* input has no parent */ + scanner->input = input; +# if SYNCTEX_VERBOSE + synctex_node_log(input); +# endif + return (synctex_ns_s){input,_synctex_next_line(scanner)};/* read the line termination character, if any */ +} + +typedef synctex_is_s (*synctex_decoder_t)(synctex_scanner_p); + +/* Used when parsing the synctex file. + * Read one of the settings. + * On normal completion, returns SYNCTEX_STATUS_OK. + * On error, returns SYNCTEX_STATUS_ERROR. + * Both arguments must not be NULL. + * On return, the scanner points to the next character after the decoded object whatever it is. + * It is the responsibility of the caller to prepare the scanner for the next line. + */ +static synctex_status_t _synctex_scan_named(synctex_scanner_p scanner,const char * name) { + synctex_status_t status = 0; + if (NULL == scanner || NULL == name) { + return SYNCTEX_STATUS_BAD_ARGUMENT; + } +not_found: + status = _synctex_match_string(scanner,name); + if (statusversion = is.integer; + /* Read all the input records */ + do { + status = __synctex_parse_new_input(scanner).status; + if (statusoutput_fmt = ss.string; + if ((status=_synctex_scan_named(scanner,"Magnification:"))pre_magnification = is.integer; + if ((status=_synctex_scan_named(scanner,"Unit:"))pre_unit = is.integer; + if ((status=_synctex_scan_named(scanner,"X Offset:"))pre_x_offset = is.integer; + if ((status=_synctex_scan_named(scanner,"Y Offset:"))pre_y_offset = is.integer; + return SYNCTEX_STATUS_OK; +} + +/* parse a float with a dimension */ +static synctex_fs_s _synctex_scan_float_and_dimension(synctex_scanner_p scanner) { + synctex_fs_s fs = {0,0}; + synctex_zs_s zs = {0,0}; + char * endptr = NULL; +#ifdef HAVE_SETLOCALE + char * loc = setlocale(LC_NUMERIC, NULL); +#endif + if (NULL == scanner) { + return (synctex_fs_s){0,SYNCTEX_STATUS_BAD_ARGUMENT}; + } + zs = _synctex_buffer_get_available_size(scanner, SYNCTEX_BUFFER_MIN_SIZE); + if (zs.status= SYNCTEX_STATUS_OK) { + fs.value *= 72.27f*65536; + } else if (fs.status= SYNCTEX_STATUS_OK) { + fs.value *= 72.27f*65536/2.54f; + } else if (fs.status= SYNCTEX_STATUS_OK) { + fs.value *= 72.27f*65536/25.4f; + } else if (fs.status= SYNCTEX_STATUS_OK) { + fs.value *= 65536.0f; + } else if (fs.status= SYNCTEX_STATUS_OK) { + fs.value *= 72.27f/72*65536.0f; + } else if (fs.status= SYNCTEX_STATUS_OK) { + fs.value *= 12.0*65536.0f; + } else if (fs.status= SYNCTEX_STATUS_OK) { + fs.value *= 1.0f; + } else if (fs.status= SYNCTEX_STATUS_OK) { + fs.value *= 1238.0f/1157*65536.0f; + } else if (fs.status= SYNCTEX_STATUS_OK) { + fs.value *= 14856.0f/1157*65536; + } else if (fs.status= SYNCTEX_STATUS_OK) { + fs.value *= 685.0f/642*65536; + } else if (fs.status= SYNCTEX_STATUS_OK) { + fs.value *= 1370.0f/107*65536; + } else if (fs.statusunit = strtod(SYNCTEX_CUR,&endptr); +#ifdef HAVE_SETLOCALE + setlocale(LC_NUMERIC, loc); +#endif + if (endptr == SYNCTEX_CUR) { + _synctex_error("bad magnification in the post scriptum, a float was expected."); + return SYNCTEX_STATUS_ERROR; + } + if (scanner->unit<=0) { + _synctex_error("bad magnification in the post scriptum, a positive float was expected."); + return SYNCTEX_STATUS_ERROR; + } + SYNCTEX_CUR = endptr; + goto next_line; + } + if (statusx_offset = fs.value; + goto next_line; + } else if (statusx_offset = fs.value; + goto next_line; + } else if (statusflags.postamble && (status=_synctex_match_string(scanner,"Postamble:"))count = is.integer; + /* Now we scan the last part of the SyncTeX file: the Post Scriptum section. */ + return _synctex_scan_post_scriptum(scanner); +} + +/* Horizontal boxes also have visible size. + * Visible size are bigger than real size. + * For example 0 width boxes may contain text. + * At creation time, the visible size is set to the values of the real size. + */ +static synctex_status_t _synctex_setup_visible_hbox(synctex_node_p box) { + if (box) { + switch(synctex_node_type(box)) { + case synctex_node_type_hbox: + _synctex_data_set_h_V(box,_synctex_data_h(box)); + _synctex_data_set_v_V(box,_synctex_data_v(box)); + _synctex_data_set_width_V(box,_synctex_data_width(box)); + _synctex_data_set_height_V(box,_synctex_data_height(box)); + _synctex_data_set_depth_V(box,_synctex_data_depth(box)); + return SYNCTEX_STATUS_OK; + default: + break; + } + } + return SYNCTEX_STATUS_BAD_ARGUMENT; +} + +/* This method is sent to an horizontal box to setup the visible size + * Some box have 0 width but do contain text material. + * With this method, one can enlarge the box to contain the given point (h,v). + */ +static synctex_status_t _synctex_make_hbox_contain_point(synctex_node_p node,synctex_point_s point) { + int min, max, n; + if (NULL == node || synctex_node_type(node) != synctex_node_type_hbox) { + return SYNCTEX_STATUS_BAD_ARGUMENT; + } + if ((n = _synctex_data_width_V(node))<0) { + max = _synctex_data_h_V(node); + min = max+n; + if (point.hmax) { + _synctex_data_set_h_V(node,point.h); + _synctex_data_set_width_V(node,min-point.h); + } + } else { + min = _synctex_data_h_V(node); + max = min+n; + if (point.hmax) { + _synctex_data_set_width_V(node,point.h - min); + } + } + n = _synctex_data_v_V(node); + min = n - _synctex_data_height_V(node); + max = n + _synctex_data_depth_V(node); + if (point.vmax) { + _synctex_data_set_depth_V(node,point.v-n); + } + return SYNCTEX_STATUS_OK; +} +static synctex_status_t _synctex_make_hbox_contain_box(synctex_node_p node,synctex_box_s box) { + int min, max, n; + if (NULL == node || synctex_node_type(node) != synctex_node_type_hbox) { + return SYNCTEX_STATUS_BAD_ARGUMENT; + } + if ((n = _synctex_data_width_V(node))<0) { + max = _synctex_data_h_V(node); + min = max+n; + if (box.min.h max) { + _synctex_data_set_h_V(node,box.max.h); + _synctex_data_set_width_V(node,min-box.max.h); + } + } else { + min = _synctex_data_h_V(node); + max = min+n; + if (box.min.hmax) { + _synctex_data_set_width_V(node,box.max.h - min); + } + } + n = _synctex_data_v_V(node); + min = n - _synctex_data_height_V(node); + max = n + _synctex_data_depth_V(node); + if (box.min.vmax) { + _synctex_data_set_depth_V(node,box.max.v-n); + } + return SYNCTEX_STATUS_OK; +} +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark SPECIAL CHARACTERS +# endif + + +/* Here are the control characters that start each line of the synctex output file. + * Their values define the meaning of the line. + */ +# define SYNCTEX_CHAR_BEGIN_SHEET '{' +# define SYNCTEX_CHAR_END_SHEET '}' +# define SYNCTEX_CHAR_BEGIN_FORM '<' +# define SYNCTEX_CHAR_END_FORM '>' +# define SYNCTEX_CHAR_BEGIN_VBOX '[' +# define SYNCTEX_CHAR_END_VBOX ']' +# define SYNCTEX_CHAR_BEGIN_HBOX '(' +# define SYNCTEX_CHAR_END_HBOX ')' +# define SYNCTEX_CHAR_ANCHOR '!' +# define SYNCTEX_CHAR_VOID_VBOX 'v' +# define SYNCTEX_CHAR_VOID_HBOX 'h' +# define SYNCTEX_CHAR_KERN 'k' +# define SYNCTEX_CHAR_GLUE 'g' +# define SYNCTEX_CHAR_RULE 'r' +# define SYNCTEX_CHAR_MATH '$' +# define SYNCTEX_CHAR_FORM_REF 'f' +# define SYNCTEX_CHAR_BOUNDARY 'x' +# define SYNCTEX_CHAR_CHARACTER 'c' +# define SYNCTEX_CHAR_COMMENT '%' + +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark SCANNERS & PARSERS +# endif + +# define SYNCTEX_DECODE_FAILED(NODE,WHAT) \ +(_synctex_data_decode_##WHAT(NODE)sheet) { + synctex_node_p last_sheet = scanner->sheet; + synctex_node_p next_sheet = NULL; + while ((next_sheet = __synctex_tree_sibling(last_sheet))) { + last_sheet = next_sheet; + } + /* sheets have no parent */ + __synctex_tree_set_sibling(last_sheet,node); + } else { + scanner->sheet = node; + } + return (synctex_ns_s){node,SYNCTEX_STATUS_OK}; + } + _synctex_free_node(node); + } + return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR}; +} +/** + * - requirement: scanner != NULL + */ +static synctex_ns_s _synctex_parse_new_form(synctex_scanner_p scanner) { + synctex_node_p node; + if ((node = _synctex_new_form(scanner))) { + if ( + SYNCTEX_DECODE_FAILED(node,tag)) { + _synctex_error("Bad sheet record."); + } else if (_synctex_next_line(scanner)form) { + synctex_node_p last_form = scanner->form; + synctex_node_p next_form = NULL; + while ((next_form = __synctex_tree_sibling(last_form))) { + last_form = next_form; + } + __synctex_tree_set_sibling(last_form,node); + } else { + scanner->form = node; + } + return (synctex_ns_s){node,SYNCTEX_STATUS_OK}; + } + _synctex_free_node(node); + } + return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR}; +} +# define SYNCTEX_SHOULD_DECODE_FAILED(NODE,WHAT) \ +(_synctex_data_has_##WHAT(NODE) &&(_synctex_data_decode_##WHAT(NODE)class_->scanner,_synctex_data_tag(node)); + } + if (_synctex_data_line(node)>_synctex_data_line(input)) { + _synctex_data_set_line(input,_synctex_data_line(node)); + } + return input; +} +/** + * Free node and its siblings and return its detached child. + */ +SYNCTEX_INLINE static synctex_node_p _synctex_handle_pop_child(synctex_node_p handle) { + synctex_node_p child = _synctex_tree_reset_child(handle); + synctex_node_free(handle); + return child; +} +/** + * Set the tlc of all the x nodes that are targets of + * x_handle and its sibling. + * Reset the target of x_handle and deletes its siblings. + * child is a node that has just been parsed and is not a boundary node. + */ +SYNCTEX_INLINE static void _synctex_handle_set_tlc(synctex_node_p x_handle, synctex_node_p child, synctex_bool_t make_friend) { + if (x_handle) { + synctex_node_p sibling = x_handle; + if (child) { + synctex_node_p target; + while ((target = synctex_node_target(sibling))) { + _synctex_data_set_tlc(target,child); + if (make_friend) { + _synctex_node_make_friend_tlc(target); + } + if ((sibling = __synctex_tree_sibling(sibling))) { + continue; + } else { + break; + } + } + } + _synctex_tree_reset_target(x_handle); + sibling = __synctex_tree_reset_sibling(x_handle); + synctex_node_free(sibling); + } +} +/** + * When we have parsed a box, we must register + * all the contained heading boundary nodes + * that have not yet been registered. + * Those handles will be deleted when popping. + */ +SYNCTEX_INLINE static void _synctex_handle_make_friend_tlc(synctex_node_p node) { + while (node) { + synctex_node_p target = _synctex_tree_reset_target(node); + _synctex_node_make_friend_tlc(target); + node = __synctex_tree_sibling(node); + } +} +/** + * Scan sheets, forms and input records. + * - parameter scanner: owning scanner + * - returns: status + */ +static synctex_status_t __synctex_parse_sfi(synctex_scanner_p scanner) { + synctex_status_t status = SYNCTEX_STATUS_OK; + synctex_zs_s zs = {0,0}; + synctex_ns_s input = SYNCTEX_NS_NULL; + synctex_node_p sheet = NULL; + synctex_node_p form = NULL; + synctex_node_p parent = NULL; + synctex_node_p child = NULL; + /* + * Experimentations lead to the forthcoming conclusion: + * Sometimes, the first nodes of a box have the wrong line number. + * These are only boundary (x) nodes. + * We observed that boundary nodes do have the proper line number + * if they follow a node with a different type. + * We keep track of these leading x nodes in a handle tree. + */ + synctex_node_p x_handle = NULL; +# define SYNCTEX_RETURN(STATUS) \ + synctex_node_free(x_handle);\ + return STATUS + synctex_node_p last_k = NULL; + synctex_node_p last_g = NULL; + synctex_ns_s ns = SYNCTEX_NS_NULL; + int form_depth = 0; + int ignored_form_depth = 0; + synctex_bool_t try_input = synctex_YES; + if (!(x_handle = _synctex_new_handle(scanner))) { + SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR); + } +# ifdef SYNCTEX_NOTHING +# pragma mark MAIN LOOP +# endif +main_loop: + status = SYNCTEX_STATUS_OK; + sheet = form = parent = child = NULL; +# define SYNCTEX_START_SCAN(WHAT)\ +(*SYNCTEX_CUR == SYNCTEX_CHAR_##WHAT) + if (SYNCTEX_CURflags.postamble = 1; + SYNCTEX_RETURN(status); + } + status = _synctex_next_line(scanner); + if (status" at top level. + * - in a box, the unique possibility is '<', '[', '(' or ">". + * We still keep the '(' for a sheet, because that dos not cost too much. + * We must also consider void boxes as children. + */ + /* forms are everywhere */ + ns = SYNCTEX_NS_NULL; +#if SYNCTEX_VERBOSE + synctex_scanner_set_display_switcher(scanner,-1); + printf("NEW CONTENT LOOP\n"); +#if SYNCTEX_DEBUG>500 + synctex_node_display(sheet); +#endif +#endif + if (SYNCTEX_CURreader->charindex_offset+SYNCTEX_CUR-SYNCTEX_START); + synctex_lineindex_t line_index = scanner->reader->line_number; +# endif + ns = _synctex_parse_new_hbox(scanner); + if (ns.status == SYNCTEX_STATUS_OK) { + x_handle = _synctex_new_handle_with_child(x_handle); + if (child) { + _synctex_node_set_sibling(child,ns.node); + } else { + _synctex_node_set_child(parent,ns.node); + } + parent = ns.node; + /* add a box boundary node at the start */ + if ((child = _synctex_new_box_bdry(scanner))) { +# if defined(SYNCTEX_USE_CHARINDEX) + child->line_index=line_index; + child->char_index=char_index; +# endif + _synctex_node_set_child(parent,child); + _synctex_data_set_tlchv(child,parent); + if (!form) { + __synctex_node_make_friend_tlc(child); + } + } else { + _synctex_error("Can't create box bdry record."); + } +# if SYNCTEX_VERBOSE + synctex_node_log(parent); +# endif + input.node = _synctex_input_register_line(input.node,parent); + last_k = last_g = NULL; + goto content_loop; + } + } else if (SYNCTEX_START_SCAN(END_HBOX)) { + if (synctex_node_type(parent) == synctex_node_type_hbox) { +# ifdef SYNCTEX_NOTHING +# pragma mark + SCAN XOBH +# endif + ++SYNCTEX_CUR; + /* setting the next horizontal box at the end ensures + * that a child is recorded before any of its ancestors. + */ + if (form == NULL /* && sheet != NULL*/ ) { + _synctex_tree_set_next_hbox(parent,_synctex_tree_next_hbox(sheet)); + _synctex_tree_set_next_hbox(sheet,parent); + } + { + /* Update the mean line number */ + synctex_node_p node = _synctex_tree_child(parent); + synctex_node_p sibling = NULL; + /* Ignore the first node (a box_bdry) */ + if (node && (sibling = __synctex_tree_sibling(node))) { + unsigned int node_weight = 0; + unsigned int cumulated_line_numbers = 0; + _synctex_data_set_line(node, _synctex_data_line(sibling)); + node = sibling; + do { + if (synctex_node_type(node)==synctex_node_type_hbox) { + if (_synctex_data_weight(node)) { + node_weight += _synctex_data_weight(node); + cumulated_line_numbers += _synctex_data_mean_line(node)*_synctex_data_weight(node); + } else { + ++node_weight; + cumulated_line_numbers += _synctex_data_mean_line(node); + } + } else { + ++node_weight; + cumulated_line_numbers += synctex_node_line(node); + } + } while ((node = __synctex_tree_sibling(node))); + _synctex_data_set_mean_line(parent,(cumulated_line_numbers + node_weight/2)/node_weight); + _synctex_data_set_weight(parent,node_weight); + } else { + _synctex_data_set_mean_line(parent,_synctex_data_line(parent)); + _synctex_data_set_weight(parent,1); + } + if ((sibling = _synctex_new_box_bdry(scanner))) { +# if defined(SYNCTEX_USE_CHARINDEX) + sibling->line_index=child->line_index; + sibling->char_index=child->char_index; +# endif + _synctex_node_set_sibling(child,sibling); + { + synctex_node_p N = child; + while (synctex_node_type(N) == synctex_node_type_ref) { + N = _synctex_tree_arg_sibling(N); + } + _synctex_data_set_tlc(sibling,N); + } + _synctex_data_set_h(sibling,_synctex_data_h_V(parent)+_synctex_data_width_V(parent)); + _synctex_data_set_v(sibling,_synctex_data_v_V(parent)); + child = sibling; + } else { + _synctex_error("Can't create box bdry record."); + } + sibling = _synctex_tree_child(parent); + _synctex_data_set_point(sibling,_synctex_data_point_V(parent)); + if (last_k && last_g && (child = synctex_node_child(parent))) { + /* Find the node preceding last_k */ + synctex_node_p next; + while ((next = __synctex_tree_sibling(child))) { + if (next == last_k) { + _synctex_data_set_tlc(last_k,child); + _synctex_data_set_tlc(last_g,child); + break; + } + child = next; + } + } + child = parent; + parent = _synctex_tree_parent(child); + if (!form) { + _synctex_handle_make_friend_tlc(x_handle); + } + x_handle = _synctex_handle_pop_child(x_handle); + _synctex_handle_set_tlc(x_handle,child,!form); + _synctex_make_hbox_contain_box(parent, _synctex_data_box_V(child)); +# if SYNCTEX_VERBOSE + synctex_node_log(child); +# endif + } + if (_synctex_next_line(scanner)500 + synctex_node_display(parent); + synctex_node_display(child); +#endif + ns = _synctex_parse_new_ref(scanner); + if (ns.status == SYNCTEX_STATUS_OK) { + if (child) { + _synctex_node_set_sibling(child,ns.node); + } else { + _synctex_node_set_child(parent,ns.node); + } + child = ns.node; + if (form) { + if (scanner->ref_in_form) { + synctex_tree_set_friend(child,scanner->ref_in_form); + } + scanner->ref_in_form = child; + } else { + if (scanner->ref_in_sheet) { + synctex_tree_set_friend(child,scanner->ref_in_sheet); + } + scanner->ref_in_sheet = child; + } +# if SYNCTEX_VERBOSE + synctex_node_log(child); +# endif + last_k = last_g = NULL; + goto content_loop; + } + } else if (SYNCTEX_START_SCAN(BOUNDARY)) { +# ifdef SYNCTEX_NOTHING +# pragma mark + SCAN BOUNDARY +# endif + ns = _synctex_parse_new_boundary(scanner); + if (ns.status == SYNCTEX_STATUS_OK) { + if (child) { + _synctex_node_set_sibling(child,ns.node); + } else { + _synctex_node_set_child(parent,ns.node); + } + if (synctex_node_type(child)==synctex_node_type_box_bdry + || _synctex_tree_target(x_handle)) { + child = _synctex_tree_reset_child(x_handle); + child = _synctex_new_handle_with_child(child); + __synctex_tree_set_sibling(child, x_handle); + x_handle = child; + _synctex_tree_set_target(x_handle,ns.node); + } else if (!form) { + __synctex_node_make_friend_tlc(ns.node); + } + child = ns.node; + _synctex_make_hbox_contain_point(parent,_synctex_data_point(child)); +# if SYNCTEX_VERBOSE + synctex_node_log(child); +# endif + input.node = _synctex_input_register_line(input.node,child); + last_k = last_g = NULL; + goto content_loop; + } + } else if (SYNCTEX_START_SCAN(CHARACTER)) { +# ifdef SYNCTEX_NOTHING +# pragma mark + SCAN CHARACTER +# endif + ++SYNCTEX_CUR; + if (_synctex_next_line(scanner) 0) { +# ifdef SYNCTEX_NOTHING +# pragma mark + SCAN MROF +# endif + ++SYNCTEX_CUR; + --form_depth; + if (_synctex_next_line(scanner)(line %i)\n",SYNCTEX_CUR, scanner->reader->line_number+1); + if (_synctex_next_line(scanner)class_->scanner, _synctex_data_tag(ref)); + /* The target is a single node (box) + * with children and no siblings. */ + if ((ns.node = __synctex_new_proxy_from_ref_to(ref, target))) { + /* Insert this proxy instead of ref. */ + _synctex_node_set_sibling(arg_sibling,ns.node); + /* Then append the original sibling of ref. */ + _synctex_node_set_sibling(ns.node,sibling); +# if defined(SYNCTEX_USE_CHARINDEX) + if (synctex_node_type(sibling) == synctex_node_type_box_bdry) { + /* The sibling is the last box boundary + * which may have a less accurate information */ + sibling->char_index = arg_sibling->char_index; + sibling->line_index = arg_sibling->line_index; + } +#endif +#if SYNCTEX_DEBUG>500 + printf("! Ref replacement:\n"); + synctex_node_log(ref); + synctex_node_display(synctex_node_sibling(ref)); +#endif + } else /* simply remove ref */ { + _synctex_tree_set_sibling(arg_sibling,sibling); + } + __synctex_tree_reset_parent(ref); + } else { + _synctex_error("! Missing parent in __synctex_replace_ref. " + "Please report."); + ns.status = SYNCTEX_STATUS_BAD_ARGUMENT; + } + return ns; +} +/** + * - argument ref: is the starting point of a linked list + * of refs. The link is made through the friend field. + * - returns: the status and the list of all the proxies + * created. The link is made through the friend field. + * - note: All refs are freed + */ +SYNCTEX_INLINE static synctex_ns_s _synctex_post_process_ref(synctex_node_p ref) { + synctex_ns_s ns = {NULL, SYNCTEX_STATUS_OK}; + while (ref) { + synctex_node_p next_ref = _synctex_tree_reset_friend(ref); + synctex_ns_s sub_ns = __synctex_replace_ref(ref); + if (sub_ns.status < ns.status) { + ns.status = sub_ns.status; + } else { + /* Insert all the created proxies in the list + * sub_ns.node is the last friend, + */ + synctex_tree_set_friend(sub_ns.node,ns.node); + ns.node = sub_ns.node; + } + synctex_node_free(ref); + ref = next_ref; + } + return ns; +} +typedef synctex_node_p (* synctex_processor_f)(synctex_node_p node); +/** + * Apply the processor f to the tree hierarchy rooted at proxy. + * proxy has replaced a form ref, no children yet. + * As a side effect all the hierarchy of nodes will be created. + */ +SYNCTEX_INLINE static synctex_status_t _synctex_post_process_proxy(synctex_node_p proxy, synctex_processor_f f) { + while(proxy) { + synctex_node_p next_proxy = _synctex_tree_friend(proxy); + synctex_node_p halt = __synctex_tree_sibling(proxy); + /* if proxy is the last sibling, halt is NULL. + * Find what should be a next node, + * without creating new nodes. */ + if (!halt) { + synctex_node_p parent = _synctex_tree_parent(proxy); + halt = __synctex_tree_sibling(parent); + while (!halt && parent) { + parent = _synctex_tree_parent(parent); + halt = __synctex_tree_sibling(parent); + } + } + do { +#if SYNCTEX_DEBUG>500 + printf("POST PROCESSING %s\n",_synctex_node_abstract(proxy)); + { + int i,j = 0; + for (i=0;iclass_->scanner->number_of_lists;++i) { + synctex_node_p N = proxy->class_->scanner->lists_of_friends[i]; + do { + if (N==proxy) { + ++j; + printf("%s",_synctex_node_abstract(N)); + } + } while ((N = _synctex_tree_friend(N))); + } + if (j) { + printf("\nBeforehand %i match\n",j); + } + } +#endif + f(proxy); +#if SYNCTEX_DEBUG>500 + { + int i,j = 0; + for (i=0;iclass_->scanner->number_of_lists;++i) { + synctex_node_p N = proxy->class_->scanner->lists_of_friends[i]; + do { + if (N==proxy) { + ++j; + printf("%s",_synctex_node_abstract(N)); + } + } while ((N = _synctex_tree_friend(N))); + } + if (j) { + printf("\n%i match\n",j); + } + } +#endif + /* Side effect: create the hierarchy on the fly */ + proxy = synctex_node_next(proxy); /* Change is here */ +#if SYNCTEX_DEBUG>500 + if (proxy) { + int i,j = 0; + for (i=0;iclass_->scanner->number_of_lists;++i) { + synctex_node_p N = proxy->class_->scanner->lists_of_friends[i]; + do { + if (N==proxy) { + ++j; + printf("%s",_synctex_node_abstract(N)); + } + } while ((N = _synctex_tree_friend(N))); + } + if (j) { + printf("\nnext %i match\n",j); + } + } +#endif + } while (proxy && proxy != halt); + proxy = next_proxy; + } + return SYNCTEX_STATUS_OK; +} +/** + * Replace all the form refs by root box proxies. + * Create the node hierarchy and update the friends. + * On entry, the refs are collected as a friend list + * in either a form or a sheet + * - parameter: the owning scanner + */ +SYNCTEX_INLINE static synctex_status_t _synctex_post_process(synctex_scanner_p scanner) { + synctex_status_t status = SYNCTEX_STATUS_OK; + synctex_ns_s ns = {NULL,SYNCTEX_STATUS_NOT_OK}; +#if SYNCTEX_DEBUG>500 + printf("! entering _synctex_post_process.\n"); + synctex_node_display(scanner->sheet); + synctex_node_display(scanner->form); +#endif + /* replace form refs inside forms by box proxies */ + ns = _synctex_post_process_ref(scanner->ref_in_form); + scanner->ref_in_form = NULL;/* it was just released */ + if (ns.status500 + printf("! ref replaced in form _synctex_post_process.\n"); + synctex_node_display(scanner->form); +#endif + /* Create all the form proxy nodes on the fly. + * ns.node is the root of the list of + * newly created proxies. + * There might be a problem with cascading proxies. + * In order to be properly managed, the data must + * be organized in the right way. + * The inserted form must be defined before + * the inserting one. *TeX will take care of that. */ + ns.status = _synctex_post_process_proxy(ns.node,&_synctex_tree_reset_friend); + if (ns.statusref_in_sheet); + if (ns.statusref_in_sheet = NULL; +#if SYNCTEX_DEBUG>500 + printf("! ref replaced in sheet _synctex_post_process.\n"); + synctex_node_display(scanner->sheet); +#endif +#if 0 + { + int i; + for (i=0;inumber_of_lists;++i) { + synctex_node_p P = ns.node; + do { + synctex_node_p N = scanner->lists_of_friends[i]; + do { + if (P == N) { + printf("Already registered.\n"); + synctex_node_display(N); + break; + } + } while ((N = _synctex_tree_friend(N))); + } while((P = _synctex_tree_friend(P))); + } + } +#endif +#if SYNCTEX_DEBUG>10000 + { + int i; + for (i=0;inumber_of_lists;++i) { + synctex_node_p P = scanner->lists_of_friends[i]; + int j = 0; + while (P) { + ++j; + synctex_node_log(P); + P = _synctex_tree_friend(P); + } + if (j) { + printf("friends %i -> # %i\n",i,j); + } + } + } +#endif + ns.status = _synctex_post_process_proxy(ns.node,&__synctex_proxy_make_friend_and_next_hbox); + if (ns.status500 + printf("! exiting _synctex_post_process.\n"); + synctex_node_display(scanner->sheet); + synctex_node_display(scanner->form); + printf("! display all.\n"); + synctex_node_display(scanner->sheet); + synctex_node_display(scanner->form); +#endif + return status; +} +/* Used when parsing the synctex file + */ +static synctex_status_t _synctex_scan_content(synctex_scanner_p scanner) { + scanner->reader->lastv = -1; + synctex_status_t status = 0; + if (NULL == scanner) { + return SYNCTEX_STATUS_BAD_ARGUMENT; + } + /* Find where this section starts */ +content_not_found: + status = _synctex_match_string(scanner,"Content:"); + if (statusreader = _synctex_malloc(sizeof(synctex_reader_s)))) { + _synctex_free(scanner); + return NULL; + } +# ifdef SYNCTEX_NOTHING +# pragma mark - +# endif +# define DEFINE_synctex_scanner_class(NAME)\ + scanner->class_[synctex_node_type_##NAME] = synctex_class_##NAME;\ +(scanner->class_[synctex_node_type_##NAME]).scanner = scanner + DEFINE_synctex_scanner_class(input); + DEFINE_synctex_scanner_class(sheet); + DEFINE_synctex_scanner_class(form); + DEFINE_synctex_scanner_class(hbox); + DEFINE_synctex_scanner_class(void_hbox); + DEFINE_synctex_scanner_class(vbox); + DEFINE_synctex_scanner_class(void_vbox); + DEFINE_synctex_scanner_class(kern); + DEFINE_synctex_scanner_class(glue); + DEFINE_synctex_scanner_class(rule); + DEFINE_synctex_scanner_class(math); + DEFINE_synctex_scanner_class(boundary); + DEFINE_synctex_scanner_class(box_bdry); + DEFINE_synctex_scanner_class(ref); + DEFINE_synctex_scanner_class(proxy_hbox); + DEFINE_synctex_scanner_class(proxy_vbox); + DEFINE_synctex_scanner_class(proxy); + DEFINE_synctex_scanner_class(proxy_last); + DEFINE_synctex_scanner_class(handle); + /* set up the lists of friends */ + scanner->number_of_lists = 1024; + scanner->lists_of_friends = (synctex_node_r)_synctex_malloc(scanner->number_of_lists*sizeof(synctex_node_p)); + if (NULL == scanner->lists_of_friends) { + synctex_scanner_free(scanner); + _synctex_error("malloc:2"); + return NULL; + } + scanner->display_switcher = 100; + scanner->display_prompt = (char *)_synctex_display_prompt+strlen(_synctex_display_prompt)-1; + } + return scanner; +} +/* Where the synctex scanner is created. */ +synctex_scanner_p synctex_scanner_new_with_output_file(const char * output, const char * build_directory, int parse) { + synctex_scanner_p scanner = synctex_scanner_new(); + if (NULL == scanner) { + _synctex_error("malloc problem"); + return NULL; + } + if ((scanner->reader = synctex_reader_init_with_output_file(scanner->reader, output, build_directory))) { + return parse? synctex_scanner_parse(scanner):scanner; + } + _synctex_error("No file?"); + return NULL; +} + +/* The scanner destructor + */ +int synctex_scanner_free(synctex_scanner_p scanner) { + int node_count = 0; + if (scanner) { + if (SYNCTEX_FILE) { + gzclose(SYNCTEX_FILE); + SYNCTEX_FILE = NULL; + } + synctex_node_free(scanner->sheet); + synctex_node_free(scanner->form); + synctex_node_free(scanner->input); + synctex_reader_free(scanner->reader); + SYNCTEX_SCANNER_FREE_HANDLE(scanner); + synctex_iterator_free(scanner->iterator); + free(scanner->output_fmt); + free(scanner->lists_of_friends); +#if SYNCTEX_USE_NODE_COUNT>0 + node_count = scanner->node_count; +#endif + free(scanner); + } + return node_count; +} + +/* Where the synctex scanner parses the contents of the file. */ +synctex_scanner_p synctex_scanner_parse(synctex_scanner_p scanner) { + synctex_status_t status = 0; + if (!scanner || scanner->flags.has_parsed) { + return scanner; + } + scanner->flags.has_parsed=1; + scanner->pre_magnification = 1000; + scanner->pre_unit = 8192; + scanner->pre_x_offset = scanner->pre_y_offset = 578; + /* initialize the offset with a fake unprobable value, + * If there is a post scriptum section, this value will be overridden by the real life value */ + scanner->x_offset = scanner->y_offset = 6.027e23f; + scanner->reader->line_number = 1; + + SYNCTEX_START = (char *)malloc(SYNCTEX_BUFFER_SIZE+1); /* one more character for null termination */ + if (NULL == SYNCTEX_START) { + _synctex_error("! malloc error in synctex_scanner_parse."); + bailey: +#ifdef SYNCTEX_DEBUG + return scanner; +#else + synctex_scanner_free(scanner); + return NULL; +#endif + } + synctex_scanner_set_display_switcher(scanner, 1000); + SYNCTEX_END = SYNCTEX_START+SYNCTEX_BUFFER_SIZE; + /* SYNCTEX_END always points to a null terminating character. + * Maybe there is another null terminating character between SYNCTEX_CUR and SYNCTEX_END-1. + * At least, we are sure that SYNCTEX_CUR points to a string covering a valid part of the memory. */ + *SYNCTEX_END = '\0'; + SYNCTEX_CUR = SYNCTEX_END; +# if defined(SYNCTEX_USE_CHARINDEX) + scanner->reader->charindex_offset = -SYNCTEX_BUFFER_SIZE; +# endif + status = _synctex_scan_preamble(scanner); + if (status500 + synctex_scanner_set_display_switcher(scanner, 100); + synctex_node_display(scanner->sheet); + synctex_node_display(scanner->form); +#endif + synctex_scanner_set_display_switcher(scanner, 1000); + /* Everything is finished, free the buffer, close the file */ + free((void *)SYNCTEX_START); + SYNCTEX_START = SYNCTEX_CUR = SYNCTEX_END = NULL; + gzclose(SYNCTEX_FILE); + SYNCTEX_FILE = NULL; + /* Final tuning: set the default values for various parameters */ + /* 1 pre_unit = (scanner->pre_unit)/65536 pt = (scanner->pre_unit)/65781.76 bp + * 1 pt = 65536 sp */ + if (scanner->pre_unit<=0) { + scanner->pre_unit = 8192; + } + if (scanner->pre_magnification<=0) { + scanner->pre_magnification = 1000; + } + if (scanner->unit <= 0) { + /* no post magnification */ + scanner->unit = scanner->pre_unit / 65781.76;/* 65781.76 or 65536.0*/ + } else { + /* post magnification */ + scanner->unit *= scanner->pre_unit / 65781.76; + } + scanner->unit *= scanner->pre_magnification / 1000.0; + if (scanner->x_offset > 6e23) { + /* no post offset */ + scanner->x_offset = scanner->pre_x_offset * (scanner->pre_unit / 65781.76); + scanner->y_offset = scanner->pre_y_offset * (scanner->pre_unit / 65781.76); + } else { + /* post offset */ + scanner->x_offset /= 65781.76f; + scanner->y_offset /= 65781.76f; + } + return scanner; +#undef SYNCTEX_FILE +} + +/* Scanner accessors. + */ +int synctex_scanner_pre_x_offset(synctex_scanner_p scanner){ + return scanner?scanner->pre_x_offset:0; +} +int synctex_scanner_pre_y_offset(synctex_scanner_p scanner){ + return scanner?scanner->pre_y_offset:0; +} +int synctex_scanner_x_offset(synctex_scanner_p scanner){ + return scanner?scanner->x_offset:0; +} +int synctex_scanner_y_offset(synctex_scanner_p scanner){ + return scanner?scanner->y_offset:0; +} +float synctex_scanner_magnification(synctex_scanner_p scanner){ + return scanner?scanner->unit:1; +} +void synctex_scanner_display(synctex_scanner_p scanner) { + if (NULL == scanner) { + return; + } + printf("The scanner:\noutput:%s\noutput_fmt:%s\nversion:%i\n",scanner->reader->output,scanner->output_fmt,scanner->version); + printf("pre_unit:%i\nx_offset:%i\ny_offset:%i\n",scanner->pre_unit,scanner->pre_x_offset,scanner->pre_y_offset); + printf("count:%i\npost_magnification:%f\npost_x_offset:%f\npost_y_offset:%f\n", + scanner->count,scanner->unit,scanner->x_offset,scanner->y_offset); + printf("The input:\n"); + synctex_node_display(scanner->input); + if (scanner->count<1000) { + printf("The sheets:\n"); + synctex_node_display(scanner->sheet); + printf("The friends:\n"); + if (scanner->lists_of_friends) { + int i = scanner->number_of_lists; + synctex_node_p node; + while(i--) { + printf("Friend index:%i\n",i); + node = (scanner->lists_of_friends)[i]; + while(node) { + printf("%s:%i,%i\n", + synctex_node_isa(node), + _synctex_data_tag(node), + _synctex_data_line(node) + ); + node = _synctex_tree_friend(node); + } + } + } + } else { + printf("SyncTeX Warning: Too many objects\n"); + } +} +/* Public */ +const char * synctex_scanner_get_name(synctex_scanner_p scanner,int tag) { + synctex_node_p input = NULL; + if (NULL == scanner) { + return NULL; + } + if ((input = scanner->input)) {; + do { + if (tag == _synctex_data_tag(input)) { + return (_synctex_data_name(input)); + } + } while((input = __synctex_tree_sibling(input))); + } + return NULL; +} +const char * synctex_node_get_name(synctex_node_p node) { + if (node) { + return synctex_scanner_get_name(node->class_->scanner,_synctex_data_tag(node)); + } + return NULL; +} + +static int _synctex_scanner_get_tag(synctex_scanner_p scanner,const char * name); +static int _synctex_scanner_get_tag(synctex_scanner_p scanner,const char * name) { + synctex_node_p input = NULL; + if (NULL == scanner) { + return 0; + } + if ((input = scanner->input)) { + do { + if (_synctex_is_equivalent_file_name(name,(_synctex_data_name(input)))) { + return _synctex_data_tag(input); + } + } while((input = __synctex_tree_sibling(input))); + } + // 2011 version + name = _synctex_base_name(name); + if ((input = scanner->input)) { + do { + if (_synctex_is_equivalent_file_name(name,_synctex_base_name(_synctex_data_name(input)))) { + synctex_node_p other_input = input; + while((other_input = __synctex_tree_sibling(other_input))) { + if (_synctex_is_equivalent_file_name(name,_synctex_base_name(_synctex_data_name(other_input))) + && (strlen(_synctex_data_name(input))!=strlen(_synctex_data_name(other_input)) + || strncmp(_synctex_data_name(other_input),_synctex_data_name(input),strlen(_synctex_data_name(input))))) { + // There is a second possible candidate + return 0; + } + } + return _synctex_data_tag(input); + } + } while((input = __synctex_tree_sibling(input))); + } + return 0; +} + +int synctex_scanner_get_tag(synctex_scanner_p scanner,const char * name) { + size_t char_index = strlen(name); + if ((scanner = synctex_scanner_parse(scanner)) && (0 < char_index)) { + /* the name is not void */ + char_index -= 1; + if (!SYNCTEX_IS_PATH_SEPARATOR(name[char_index])) { + /* the last character of name is not a path separator */ + int result = _synctex_scanner_get_tag(scanner,name); + if (result) { + return result; + } else { + /* the given name was not the one known by TeX + * try a name relative to the enclosing directory of the scanner->output file */ + const char * relative = name; + const char * ptr = scanner->reader->output; + while((strlen(relative) > 0) && (strlen(ptr) > 0) && (*relative == *ptr)) + { + relative += 1; + ptr += 1; + } + /* Find the last path separator before relative */ + while(relative > name) { + if (SYNCTEX_IS_PATH_SEPARATOR(*(relative-1))) { + break; + } + relative -= 1; + } + if ((relative > name) && (result = _synctex_scanner_get_tag(scanner,relative))) { + return result; + } + if (SYNCTEX_IS_PATH_SEPARATOR(name[0])) { + /* No tag found for the given absolute name, + * Try each relative path starting from the shortest one */ + while(0input:NULL; +} +synctex_node_p synctex_scanner_input_with_tag(synctex_scanner_p scanner, int tag) { + synctex_node_p input = scanner?scanner->input:NULL; + while (_synctex_data_tag(input)!=tag) { + if ((input = __synctex_tree_sibling(input))) { + continue; + } + break; + } + return input; +} +const char * synctex_scanner_get_output_fmt(synctex_scanner_p scanner) { + return NULL != scanner && scanner->output_fmt?scanner->output_fmt:""; +} +const char * synctex_scanner_get_output(synctex_scanner_p scanner) { + return NULL != scanner && scanner->reader->output?scanner->reader->output:""; +} +const char * synctex_scanner_get_synctex(synctex_scanner_p scanner) { + return NULL != scanner && scanner->reader->synctex?scanner->reader->synctex:""; +} +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark Public node attributes +# endif + +# define SYNCTEX_DEFINE_NODE_HVWHD(WHAT) \ +int synctex_node_##WHAT(synctex_node_p node) { \ + return (node && node->class_->inspector->WHAT)? \ + node->class_->inspector->WHAT(node): 0; \ +} +# define SYNCTEX_DEFINE_PROXY_HV(WHAT) \ +static int _synctex_proxy_##WHAT(synctex_proxy_p proxy) { \ + synctex_node_p target = _synctex_tree_target(proxy); \ + if (target) { \ + return _synctex_data_##WHAT(proxy)+synctex_node_##WHAT(target); \ + } else { \ + return proxy? _synctex_data_##WHAT(proxy): 0; \ + } \ +} +#define SYNCTEX_DEFINE_PROXY_TLCWVD(WHAT) \ +static int _synctex_proxy_##WHAT(synctex_proxy_p proxy) { \ + synctex_node_p target = _synctex_tree_target(proxy); \ + return target? synctex_node_##WHAT(target): 0; \ +} + +/** + * The horizontal location of the node. + * Idem for v, width, height and depth. + * - parameter node: a node with geometrical information. + * - returns: an integer. + * - requires: every proxy node has a target. + * - note: recursive call if the parameter has a proxy. + * - author: JL + */ +SYNCTEX_DEFINE_NODE_HVWHD(h) +SYNCTEX_DEFINE_NODE_HVWHD(v) +SYNCTEX_DEFINE_NODE_HVWHD(width) +SYNCTEX_DEFINE_NODE_HVWHD(height) +SYNCTEX_DEFINE_NODE_HVWHD(depth) +SYNCTEX_DEFINE_PROXY_TLCWVD(tag) +SYNCTEX_DEFINE_PROXY_TLCWVD(line) +SYNCTEX_DEFINE_PROXY_TLCWVD(column) +SYNCTEX_DEFINE_PROXY_HV(h) +SYNCTEX_DEFINE_PROXY_HV(v) +SYNCTEX_DEFINE_PROXY_TLCWVD(width) +SYNCTEX_DEFINE_PROXY_TLCWVD(height) +SYNCTEX_DEFINE_PROXY_TLCWVD(depth) + +/** + * Whether the argument is a box, + * either vertical or horizontal, + * either void or not, + * or a proxy to such a box. + * - parameter NODE: of type synctex_node_p + * - returns: yorn + */ + +SYNCTEX_INLINE static synctex_bool_t _synctex_node_is_box(synctex_node_p node) { + return node && + (node->class_->type == synctex_node_type_hbox + || node->class_->type == synctex_node_type_void_hbox + || node->class_->type == synctex_node_type_vbox + || node->class_->type == synctex_node_type_void_vbox + || _synctex_node_is_box(_synctex_tree_target(node))); +} + +/** + * Whether the argument is a handle. + * Handles are similar to proxies because they have a target. + * They are used for query results. + * - parameter NODE: of type synctex_node_p + * - returns: yorn + */ + +SYNCTEX_INLINE static synctex_bool_t _synctex_node_is_handle(synctex_node_p node) { + return node && + (node->class_->type == synctex_node_type_handle); +} + +/** + * Resolves handle indirection. + * - parameter node: of type synctex_node_p + * - returns: node if it is not a handle, + * its target otherwise. + */ + +SYNCTEX_INLINE static synctex_node_p _synctex_node_or_handle_target(synctex_node_p node) { + return _synctex_node_is_handle(node)? + _synctex_tree_target(node):node; +} + +/** + * Whether the argument is an hbox. + * - parameter NODE: of type synctex_node_p + * - returns: yorn + */ + +SYNCTEX_INLINE static synctex_bool_t _synctex_node_is_hbox(synctex_node_p node) { + return node && + (node->class_->type == synctex_node_type_hbox + || node->class_->type == synctex_node_type_void_hbox + || _synctex_node_is_hbox(_synctex_tree_target(node))); +} + +/** + * The horizontal location of the first box enclosing node. + * - parameter node: a node with geometrical information. + * - returns: an integer. + * - author: JL + */ +int synctex_node_box_h(synctex_node_p node) { + if (_synctex_node_is_box(node) || (node = _synctex_tree_parent(node))) { + return synctex_node_h(node); + } + return 0; +} +/** + * The vertical location of the first box enclosing node. + * - parameter node: a node with geometrical information. + * - returns: an integer. + * - author: JL + */ +int synctex_node_box_v(synctex_node_p node) { + if (_synctex_node_is_box(node) || (node = _synctex_tree_parent(node))) { + return synctex_node_v(node); + } + return 0; +} +/** + * The width of the first box enclosing node. + * - parameter node: a node with geometrical information. + * - returns: an integer. + * - author: JL + */ +int synctex_node_box_width(synctex_node_p node) { + if (_synctex_node_is_box(node) || (node = _synctex_tree_parent(node))) { + return synctex_node_width(node); + } + return 0; +} +/** + * The height of the first box enclosing node. + * - parameter node: a node with geometrical information. + * - returns: an integer. + * - author: JL + */ +int synctex_node_box_height(synctex_node_p node) { + if (_synctex_node_is_box(node) || (node = _synctex_tree_parent(node))) { + return synctex_node_height(node); + } + return 0; +} +/** + * The depth of the first box enclosing node. + * - parameter node: a node with geometrical information. + * - returns: an integer. + * - author: JL + */ +int synctex_node_box_depth(synctex_node_p node) { + if (_synctex_node_is_box(node) || (node = _synctex_tree_parent(node))) { + return synctex_node_depth(node); + } + return 0; +} +/** + * The horizontal location of an hbox, corrected with contents. + * - parameter node: an hbox node. + * - returns: an integer, 0 if node is not an hbox or an hbox proxy. + * - note: recursive call when node is an hbox proxy. + * - author: JL + */ +int synctex_node_hbox_h(synctex_node_p node) { + switch(synctex_node_type(node)) { + case synctex_node_type_hbox: + return _synctex_data_h_V(node); + case synctex_node_type_proxy_hbox: + return _synctex_data_h(node)+synctex_node_hbox_h(_synctex_tree_target(node)); + default: + return 0; + } +} +/** + * The vertical location of an hbox, corrected with contents. + * - parameter node: an hbox node. + * - returns: an integer, 0 if node is not an hbox or an hbox proxy. + * - note: recursive call when node is an hbox proxy. + * - author: JL + */ +int synctex_node_hbox_v(synctex_node_p node) { + switch(synctex_node_type(node)) { + case synctex_node_type_hbox: + return _synctex_data_v_V(node); + case synctex_node_type_proxy_hbox: + return _synctex_data_v(node)+synctex_node_hbox_v(_synctex_tree_target(node)); + default: + return 0; + } +} +/** + * The width of an hbox, corrected with contents. + * - parameter node: an hbox node, 0 if node is not an hbox or an hbox proxy. + * - returns: an integer. + * - author: JL + */ +int synctex_node_hbox_width(synctex_node_p node) { + synctex_node_p target = _synctex_tree_target(node); + if (target) { + node = target; + } + return synctex_node_type(node) == synctex_node_type_hbox? + _synctex_data_width_V(node): 0; +} +/** + * The height of an hbox, corrected with contents. + * - parameter node: an hbox node. + * - returns: an integer, 0 if node is not an hbox or an hbox proxy. + * - author: JL + */ +int synctex_node_hbox_height(synctex_node_p node) { + synctex_node_p target = _synctex_tree_target(node); + if (target) { + node = target; + } + return synctex_node_type(node) == synctex_node_type_hbox? + _synctex_data_height_V(node): 0; +} +/** + * The depth of an hbox, corrected with contents. + * - parameter node: an hbox node. + * - returns: an integer, 0 if node is not an hbox or an hbox proxy. + * - note: recursive call when node is an hbox proxy. + * - author: JL + */ +int synctex_node_hbox_depth(synctex_node_p node) { + synctex_node_p target = _synctex_tree_target(node); + if (target) { + node = target; + } + return synctex_node_type(node) == synctex_node_type_hbox? + _synctex_data_depth_V(node): 0; +} +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark Public node visible attributes +# endif + +#define SYNCTEX_VISIBLE_SIZE(node,s) \ +(s)*node->class_->scanner->unit +#define SYNCTEX_VISIBLE_DISTANCE_h(node,d) \ +((d)*node->class_->scanner->unit+node->class_->scanner->x_offset) +#define SYNCTEX_VISIBLE_DISTANCE_v(node,d) \ +((d)*node->class_->scanner->unit+node->class_->scanner->y_offset) +static float __synctex_node_visible_h(synctex_node_p node) { + return SYNCTEX_VISIBLE_DISTANCE_h(node,synctex_node_h(node)); +} +static float __synctex_node_visible_v(synctex_node_p node) { + return SYNCTEX_VISIBLE_DISTANCE_v(node,synctex_node_v(node)); +} +static float __synctex_node_visible_width(synctex_node_p node) { + return SYNCTEX_VISIBLE_SIZE(node,synctex_node_width(node)); +} +static float __synctex_node_visible_height(synctex_node_p node) { + return SYNCTEX_VISIBLE_SIZE(node,synctex_node_height(node)); +} +static float __synctex_node_visible_depth(synctex_node_p node) { + return SYNCTEX_VISIBLE_SIZE(node,synctex_node_depth(node)); +} +static float __synctex_proxy_visible_h(synctex_node_p node) { + return SYNCTEX_VISIBLE_DISTANCE_h(node,synctex_node_h(node)); +} +static float __synctex_proxy_visible_v(synctex_node_p node) { + return SYNCTEX_VISIBLE_DISTANCE_v(node,synctex_node_v(node)); +} +static float __synctex_proxy_visible_width(synctex_node_p node) { + synctex_node_p target = _synctex_tree_target(node); + return __synctex_node_visible_width(target); +} +static float __synctex_proxy_visible_height(synctex_node_p node) { + synctex_node_p target = _synctex_tree_target(node); + return __synctex_node_visible_height(target); +} +static float __synctex_proxy_visible_depth(synctex_node_p node) { + synctex_node_p target = _synctex_tree_target(node); + return __synctex_node_visible_depth(target); +} +static float __synctex_kern_visible_h(synctex_noxy_p noxy) { + int h = _synctex_data_h(noxy); + int width = _synctex_data_width(noxy); + return SYNCTEX_VISIBLE_DISTANCE_h(noxy, width>0?h-width:h); +} +static float __synctex_kern_visible_width(synctex_noxy_p noxy) { + int width = _synctex_data_width(noxy); + return SYNCTEX_VISIBLE_SIZE(noxy, width>0?width:-width); +} +static float __synctex_rule_visible_h(synctex_noxy_p noxy) { + int h = _synctex_data_h(noxy); + int width = _synctex_data_width(noxy); + return SYNCTEX_VISIBLE_DISTANCE_h(noxy, width>0?h:h-width); +} +static float __synctex_rule_visible_width(synctex_noxy_p noxy) { + int width = _synctex_data_width(noxy); + return SYNCTEX_VISIBLE_SIZE(noxy, width>0?width:-width); +} +static float __synctex_rule_visible_v(synctex_noxy_p noxy) { + return __synctex_node_visible_v(noxy); +} +static float __synctex_rule_visible_height(synctex_noxy_p noxy) { + return __synctex_node_visible_height(noxy); +} +static float __synctex_rule_visible_depth(synctex_noxy_p noxy) { + return __synctex_node_visible_depth(noxy); +} + +/** + * The horizontal location of node, in page coordinates. + * - parameter node: a node. + * - returns: a float. + * - author: JL + */ +float synctex_node_visible_h(synctex_node_p node){ + return node? node->class_->vispector->h(node): 0; +} +/** + * The vertical location of node, in page coordinates. + * - parameter node: a node. + * - returns: a float. + * - author: JL + */ +float synctex_node_visible_v(synctex_node_p node){ + return node? node->class_->vispector->v(node): 0; +} +/** + * The width of node, in page coordinates. + * - parameter node: a node. + * - returns: a float. + * - author: JL + */ +float synctex_node_visible_width(synctex_node_p node){ + return node? node->class_->vispector->width(node): 0; +} +/** + * The height of node, in page coordinates. + * - parameter node: a node. + * - returns: a float. + * - author: JL + */ +float synctex_node_visible_height(synctex_node_p node){ + return node? node->class_->vispector->height(node): 0; +} +/** + * The depth of node, in page coordinates. + * - parameter node: a node. + * - returns: a float. + * - author: JL + */ +float synctex_node_visible_depth(synctex_node_p node){ + return node? node->class_->vispector->depth(node): 0; +} + +/** + * The V variant of geometrical information. + * - parameter node: a node. + * - returns: an integer. + * - author: JL + */ +#define SYNCTEX_DEFINE_V(WHAT)\ +SYNCTEX_INLINE static int _synctex_node_##WHAT##_V(synctex_node_p node) { \ + synctex_node_p target = _synctex_tree_target(node); \ + if (target) { \ + return _synctex_data_##WHAT(node)+_synctex_node_##WHAT##_V(target); \ + } else if (_synctex_data_has_##WHAT##_V(node)) { \ + return _synctex_data_##WHAT##_V(node); \ + } else { \ + return _synctex_data_##WHAT(node); \ + } \ +} +SYNCTEX_DEFINE_V(h) +SYNCTEX_DEFINE_V(v) +SYNCTEX_DEFINE_V(width) +SYNCTEX_DEFINE_V(height) +SYNCTEX_DEFINE_V(depth) + +SYNCTEX_INLINE static synctex_point_s _synctex_data_point(synctex_node_p node) { + return (synctex_point_s){synctex_node_h(node),synctex_node_v(node)}; +} +SYNCTEX_INLINE static synctex_point_s _synctex_data_point_V(synctex_node_p node) { + return (synctex_point_s){_synctex_node_h_V(node),_synctex_node_v_V(node)}; +} +SYNCTEX_INLINE static synctex_point_s _synctex_data_set_point(synctex_node_p node, synctex_point_s point) { + synctex_point_s old = _synctex_data_point(node); + _synctex_data_set_h(node,point.h); + _synctex_data_set_v(node,point.v); + return old; +} +SYNCTEX_INLINE static synctex_box_s _synctex_data_box(synctex_node_p node) { + synctex_box_s box = {{0,0},{0,0}}; + int n; + n = synctex_node_width(node); + if (n<0) { + box.max.h = synctex_node_h(node); + box.min.h = box.max.h + n; + } else { + box.min.h = synctex_node_h(node); + box.max.h = box.min.h + n; + } + n = synctex_node_v(node); + box.min.v = n - synctex_node_height(node); + box.max.v = n + synctex_node_depth(node); + return box; +} +SYNCTEX_INLINE static synctex_box_s _synctex_data_xob(synctex_node_p node) { + synctex_box_s box = {{0,0},{0,0}}; + int n; + n = synctex_node_width(node); + if (n>0) { + box.max.h = synctex_node_h(node); + box.min.h = box.max.h - n; + } else { + box.min.h = synctex_node_h(node); + box.max.h = box.min.h - n; + } + n = synctex_node_v(node); + box.min.v = n - synctex_node_height(node); + box.max.v = n + synctex_node_depth(node); + return box; +} +SYNCTEX_INLINE static synctex_box_s _synctex_data_box_V(synctex_node_p node) { + synctex_box_s box = {{0,0},{0,0}}; + int n; + n = _synctex_node_width_V(node); + if (n<0) { + box.max.h = _synctex_node_h_V(node); + box.min.h = box.max.h + n; + } else { + box.min.h = _synctex_node_h_V(node); + box.max.h = box.min.h + n; + } + n = _synctex_node_v_V(node); + box.min.v = n - _synctex_node_height_V(node); + box.max.v = n + _synctex_node_depth_V(node); + return box; +} + +/** + * The higher box node in the parent hierarchy which + * mean line number is the one of node ±1. + * This enclosing box is computed as follows + * 1) get the first hbox in the parent linked list + * starting at node. + * If there is none, simply return the parent of node. + * 2) compute the mean line number + * 3) scans up the tree for the higher hbox with + * the same mean line number, ±1 eventually +* - parameter node: a node. + * - returns: a (proxy to a) box node. + * - author: JL + */ +static synctex_node_p _synctex_node_box_visible(synctex_node_p node) { + if ((node = _synctex_node_or_handle_target(node))) { + int mean = 0; + int bound = 1500000/(node->class_->scanner->pre_magnification/1000.0); + synctex_node_p parent = NULL; + /* get the first enclosing parent + * then get the highest enclosing parent with the same mean line ±1 */ + node = _synctex_node_or_handle_target(node); + if (!_synctex_node_is_box(node)) { + if ((parent = _synctex_tree_parent(node))) { + node = parent; + } else if ((node = _synctex_tree_target(node))) { + if (!_synctex_node_is_box(node)) { + if ((parent = _synctex_tree_parent(node))) { + node = parent; + } else { + return NULL; + } + } + } + } + parent = node; + mean = synctex_node_mean_line(node); + while ((parent = _synctex_tree_parent(parent))) { + if (_synctex_node_is_hbox(parent)) { + if (_synctex_abs(mean-synctex_node_mean_line(parent))>1) { + return node; + } else if (synctex_node_width(parent)>bound) { + return parent; + } else if (synctex_node_height(parent)+synctex_node_depth(parent)>bound) { + return parent; + } + node = parent; + } + } + } + return node; +} +/** + * The horizontal location of the first box enclosing node, in page coordinates. + * - parameter node: a node. + * - returns: a float. + * - author: JL + */ +float synctex_node_box_visible_h(synctex_node_p node) { + return SYNCTEX_VISIBLE_DISTANCE_h(node,_synctex_node_h_V(_synctex_node_box_visible(node))); +} +/** + * The vertical location of the first box enclosing node, in page coordinates. + * - parameter node: a node. + * - returns: a float. + * - author: JL + */ +float synctex_node_box_visible_v(synctex_node_p node) { + return SYNCTEX_VISIBLE_DISTANCE_v(node,_synctex_node_v_V(_synctex_node_box_visible(node))); +} +/** + * The width of the first box enclosing node, in page coordinates. + * - parameter node: a node. + * - returns: a float. + * - author: JL + */ +float synctex_node_box_visible_width(synctex_node_p node) { + return SYNCTEX_VISIBLE_SIZE(node,_synctex_node_width_V(_synctex_node_box_visible(node))); +} +/** + * The height of the first box enclosing node, in page coordinates. + * - parameter node: a node. + * - returns: a float. + * - author: JL + */ +float synctex_node_box_visible_height(synctex_node_p node) { + return SYNCTEX_VISIBLE_SIZE(node,_synctex_node_height_V(_synctex_node_box_visible(node))); +} +/** + * The depth of the first box enclosing node, in page coordinates. + * - parameter node: a node. + * - returns: a float. + * - author: JL + */ +float synctex_node_box_visible_depth(synctex_node_p node) { + return SYNCTEX_VISIBLE_SIZE(node,_synctex_node_depth_V(_synctex_node_box_visible(node))); +} +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark Other public node attributes +# endif + +/** + * The page number of the sheet enclosing node. + * - parameter node: a node. + * - returns: the page number or -1 if node does not belong to a sheet tree. + * - note: a proxy target does not belong to a sheet + * but a form, its page number is always -1. + * - note: a handles does not belong to a sheet not a form. + * its page number is -1. + * - author: JL + */ +int synctex_node_page(synctex_node_p node){ + synctex_node_p parent = NULL; + while((parent = _synctex_tree_parent(node))) { + node = parent; + } + if (synctex_node_type(node) == synctex_node_type_sheet) { + return _synctex_data_page(node); + } + return -1; +} +/** + * The page number of the target. + * - author: JL + */ +SYNCTEX_INLINE static int _synctex_node_target_page(synctex_node_p node){ + return synctex_node_page(_synctex_tree_target(node)); +} + +#if defined (SYNCTEX_USE_CHARINDEX) +synctex_charindex_t synctex_node_charindex(synctex_node_p node) { + synctex_node_p target = _synctex_tree_target(node); + return target? SYNCTEX_CHARINDEX(target):(node?SYNCTEX_CHARINDEX(node):0); +} +#endif + +/** + * The tag of the node. + * - parameter node: a node. + * - returns: the tag or -1 if node is NULL. + * - author: JL + */ +int synctex_node_tag(synctex_node_p node) { + return node? node->class_->tlcpector->tag(node): -1; +} +/** + * The line of the node. + * - parameter node: a node. + * - returns: the line or -1 if node is NULL. + * - author: JL + */ +int synctex_node_line(synctex_node_p node) { + return node? node->class_->tlcpector->line(node): -1; +} +/** + * The column of the node. + * - parameter node: a node. + * - returns: the column or -1 if node is NULL. + * - author: JL + */ +int synctex_node_column(synctex_node_p node) { + return node? node->class_->tlcpector->column(node): -1; +} +/** + * The mean line number of the node. + * - parameter node: a node. + * - returns: the mean line or -1 if node is NULL. + * - author: JL + */ +int synctex_node_mean_line(synctex_node_p node) { + synctex_node_p other = _synctex_tree_target(node); + if (other) { + node = other; + } + if (_synctex_data_has_mean_line(node)) { + return _synctex_data_mean_line(node); + } + if ((other = synctex_node_parent(node))) { + if (_synctex_data_has_mean_line(other)) { + return _synctex_data_mean_line(other); + } + } + return synctex_node_line(node); +} +/** + * The weight of the node. + * - parameter node: a node. + * - returns: the weight or -1 if node is NULL. + * - author: JL + */ +int synctex_node_weight(synctex_node_p node) { + synctex_node_p target = _synctex_tree_target(node); + if (target) { + node = target; + } + return node?(synctex_node_type(node)==synctex_node_type_hbox?_synctex_data_weight(node):0):-1; +} +/** + * The number of children of the node. + * - parameter node: a node. + * - returns: the count or -1 if node is NULL. + * - author: JL + */ +int synctex_node_child_count(synctex_node_p node) { + synctex_node_p target = _synctex_tree_target(node); + if (target) { + node = target; + } + return node?(synctex_node_type(node)==synctex_node_type_hbox?_synctex_data_weight(node):0):-1; +} +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark Sheet & Form +# endif + +/** + * The sheet of the scanner with a given page number. + * - parameter scanner: a scanner. + * - parameter page: a 1 based page number. + * If page == 0, returns the first sheet. + * - returns: a sheet or NULL. + * - author: JL + */ +synctex_node_p synctex_sheet(synctex_scanner_p scanner,int page) { + if (scanner) { + synctex_node_p sheet = scanner->sheet; + while(sheet) { + if (page == _synctex_data_page(sheet)) { + return sheet; + } + sheet = __synctex_tree_sibling(sheet); + } + if (page == 0) { + return scanner->sheet; + } + } + return NULL; +} +/** + * The form of the scanner with a given tag. + * - parameter scanner: a scanner. + * - parameter tag: an integer identifier. + * If tag == 0, returns the first form. + * - returns: a form. + * - author: JL + */ +synctex_node_p synctex_form(synctex_scanner_p scanner,int tag) { + if (scanner) { + synctex_node_p form = scanner->form; + while(form) { + if (tag == _synctex_data_tag(form)) { + return form; + } + form = __synctex_tree_sibling(form); + } + if (tag == 0) { + return scanner->form; + } + } + return NULL; +} + +/** + * The content of the sheet with given page number. + * - parameter scanner: a scanner. + * - parameter page: a 1 based page number. + * - returns: a (vertical) box node. + * - author: JL + */ +synctex_node_p synctex_sheet_content(synctex_scanner_p scanner,int page) { + if (scanner) { + return _synctex_tree_child(synctex_sheet(scanner,page)); + } + return NULL; +} + +/** + * The content of the sheet with given page number. + * - parameter scanner: a scanner. + * - parameter tag: an integer identifier. + * - returns: a box node. + * - author: JL + */ +synctex_node_p synctex_form_content(synctex_scanner_p scanner,int tag) { + if (scanner) { + return _synctex_tree_child(synctex_form(scanner,tag)); + } + return NULL; +} + +SYNCTEX_INLINE static synctex_node_p _synctex_scanner_friend(synctex_scanner_p scanner,int i) { + if (i>=0) { + i = _synctex_abs(i)%(scanner->number_of_lists); + return (scanner->lists_of_friends)[i]; + } + return NULL; +} +SYNCTEX_INLINE static synctex_bool_t _synctex_nodes_are_friend(synctex_node_p left, synctex_node_p right) { + return synctex_node_tag(left) == synctex_node_tag(right) && synctex_node_line(left) == synctex_node_line(right); +} +/** + * The sibling argument is a parent/child list of nodes of the same page. + */ +typedef struct { + int count; + synctex_node_p node; +} synctex_counted_node_s; + +SYNCTEX_INLINE static synctex_counted_node_s _synctex_vertically_sorted_v2(synctex_node_p sibling) { + /* Clean the weights of the parents */ + synctex_counted_node_s result = {0, NULL}; + synctex_node_p h = NULL; + synctex_node_p next_h = NULL; + synctex_node_p parent = NULL; + int weight = 0; + synctex_node_p N = NULL; + h = sibling; + do { + N = _synctex_tree_target(h); + parent = _synctex_tree_parent(N); + _synctex_data_set_weight(parent, 0); + } while((h = _synctex_tree_child(h))); + /* Compute the weights of the nodes */ + h = sibling; + do { + N = _synctex_tree_target(h); + parent = _synctex_tree_parent(N); + weight = _synctex_data_weight(parent); + if (weight==0) { + N = _synctex_tree_child(parent); + do { + if (_synctex_nodes_are_friend(N,sibling)) { + ++ weight; + } + } while ((N = __synctex_tree_sibling(N))); + _synctex_data_set_weight(h,weight); + _synctex_data_set_weight(parent,weight); + } + } while((h = _synctex_tree_child(h))); + /* Order handle nodes according to the weight */ + h = _synctex_tree_reset_child(sibling); + result.node = sibling; + weight = 0; + while((h)) { + N = result.node; + if (_synctex_data_weight(h)>_synctex_data_weight(N)) { + next_h = _synctex_tree_set_child(h,N); + result.node = h; + } else if (_synctex_data_weight(h) == 0) { + ++ weight; + next_h = _synctex_tree_reset_child(h); + synctex_node_free(h); + } else { + synctex_node_p next_N = NULL; + while((next_N = _synctex_tree_child(N))) { + N = next_N; + if (_synctex_data_weight(h)<_synctex_data_weight(next_N)) { + continue; + } + break; + } + next_h = _synctex_tree_set_child(h,_synctex_tree_set_child(N,h)); + } + h = next_h; + }; + h = result.node; + weight = 0; + do { + ++weight; + } while((h = _synctex_tree_child(h))); + result.count = 1; + h = result.node; + while((next_h = _synctex_tree_child(h))) { + if (_synctex_data_weight(next_h)==0) { + _synctex_tree_reset_child(h); + weight = 1; + h = next_h; + while((h = _synctex_tree_child(h))) { + ++weight; + } + synctex_node_free(next_h); + break; + } + ++result.count; + h = next_h; + } + return result; +} + +SYNCTEX_INLINE static synctex_bool_t _synctex_point_in_box_v2(synctex_point_p hitP, synctex_node_p node); + +/* This struct records distances, the left one is non negative and the right one is non positive. + * When comparing the locations of 2 different graphical objects on the page, we will have to also record the + * horizontal distance as signed to keep track of the typesetting order.*/ + +typedef struct { + synctex_node_p node; + int distance; +} synctex_nd_s; + +#define SYNCTEX_ND_0 (synctex_nd_s){NULL,INT_MAX} + +typedef synctex_nd_s * synctex_nd_p; + +typedef struct { + synctex_nd_s l; + synctex_nd_s r; +} synctex_nd_lr_s; + +/* The best container is the deeper box that contains the hit point (H,V). + * _synctex_eq_deepest_container_v2 starts with node whereas + * _synctex_box_child_deepest starts with node's children, if any + * if node is not a box, or a void box, NULL is returned. + * We traverse the node tree in a deep first manner and stop as soon as a result is found. */ +static synctex_node_p _synctex_eq_deepest_container_v2(synctex_point_p hitP, synctex_node_p node); + +SYNCTEX_INLINE static synctex_nd_lr_s _synctex_eq_get_closest_children_in_box_v2(synctex_point_p hitP, synctex_node_p node); + +/* Closest child, recursive. */ +static synctex_nd_s __synctex_closest_deep_child_v2(synctex_point_p hitP, synctex_node_p node); + +/* The smallest container between two has the smallest width or height. + * This comparison is used when there are 2 overlapping boxes that contain the hit point. + * For ConTeXt, the problem appears at each page. + * The chosen box is the one with the smallest height, then the smallest width. */ +SYNCTEX_INLINE static synctex_node_p _synctex_smallest_container_v2(synctex_node_p node, synctex_node_p other_node); + +/* Returns the distance between the hit point hit point=(H,V) and the given node. */ + +static int _synctex_point_node_distance_v2(synctex_point_p hitP, synctex_node_p node); + +/* The closest container is the box that is the one closest to the given point. + * The "visible" version takes into account the visible dimensions instead of the real ones given by TeX. */ +static synctex_nd_s _synctex_eq_closest_child_v2(synctex_point_p hitP, synctex_node_p node); + +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark Queries +# endif + +/** + * iterator for a deep first tree traversal. + */ +struct synctex_iterator_t { + synctex_node_p seed; + synctex_node_p top; + synctex_node_p next; + int count0; + int count; +}; + +SYNCTEX_INLINE static synctex_iterator_p _synctex_iterator_new(synctex_node_p result, int count) { + synctex_iterator_p iterator; + if ((iterator = _synctex_malloc(sizeof(synctex_iterator_s)))) { + iterator->seed = iterator->top = iterator->next = result; + iterator->count0 = iterator->count = count; + } + return iterator; +}; + +void synctex_iterator_free(synctex_iterator_p iterator) { + if (iterator) { + synctex_node_free(iterator->seed); + _synctex_free(iterator); + } +} +synctex_bool_t synctex_iterator_has_next(synctex_iterator_p iterator) { + return iterator?iterator->count>0:0; +} +int synctex_iterator_count(synctex_iterator_p iterator) { + return iterator? iterator->count: 0; +} + +/** + * The next result of the iterator. + * Internally, the iterator stores handles to nodes. + * Externally, it returns the targets, + * such that the caller only sees nodes. + */ +synctex_node_p synctex_iterator_next_result(synctex_iterator_p iterator) { + if (iterator && iterator->count>0) { + synctex_node_p N = iterator->next; + if(!(iterator->next = _synctex_tree_child(N))) { + iterator->next = iterator->top = __synctex_tree_sibling(iterator->top); + } + --iterator->count; + return _synctex_tree_target(N); + } + return NULL; +} +int synctex_iterator_reset(synctex_iterator_p iterator) { + if (iterator) { + iterator->next = iterator->top = iterator->seed; + return iterator->count = iterator->count0; + } + return 0; +} + +synctex_iterator_p synctex_iterator_new_edit(synctex_scanner_p scanner,int page,float h,float v){ + if (scanner) { + synctex_node_p sheet = NULL; + synctex_point_s hit; + synctex_node_p node = NULL; + synctex_nd_lr_s nds = {{NULL,0},{NULL,0}}; + if (NULL == (scanner = synctex_scanner_parse(scanner)) || 0 >= scanner->unit) {/* scanner->unit must be >0 */ + return NULL; + } + /* Find the proper sheet */ + sheet = synctex_sheet(scanner,page); + if (NULL == sheet) { + return NULL; + } + /* Now sheet points to the sheet node with proper page number. */ + /* Now that scanner has been initialized, we can convert + * the given point to scanner integer coordinates */ + hit = (synctex_point_s) + {(h-scanner->x_offset)/scanner->unit, + (v-scanner->y_offset)/scanner->unit}; + /* At first, we browse all the horizontal boxes of the sheet + * until we find one containing the hit point. */ + if ((node = _synctex_tree_next_hbox(sheet))) { + do { + if (_synctex_point_in_box_v2(&hit,node)) { + /* Maybe the hit point belongs to a contained vertical box. + * This is the most likely situation. + */ + synctex_node_p next = node; +#if defined(SYNCTEX_DEBUG) + printf("--- We are lucky\n"); +#endif + /* This trick is for catching overlapping boxes */ + while ((next = _synctex_tree_next_hbox(next))) { + if (_synctex_point_in_box_v2(&hit,next)) { + node = _synctex_smallest_container_v2(next,node); + } + } + /* node is the smallest horizontal box that contains hit, + * unless there is no hbox at all. + */ + node = _synctex_eq_deepest_container_v2(&hit, node); + nds = _synctex_eq_get_closest_children_in_box_v2(&hit, node); + end: + if (nds.r.node && nds.l.node) { + if ((_synctex_data_tag(nds.r.node)!=_synctex_data_tag(nds.l.node)) + || (_synctex_data_line(nds.r.node)!=_synctex_data_line(nds.l.node)) + || (_synctex_data_column(nds.r.node)!=_synctex_data_column(nds.l.node))) { + if (_synctex_data_line(nds.r.node)<_synctex_data_line(nds.l.node)) { + node = nds.r.node; + nds.r.node = nds.l.node; + nds.l.node = node; + } else if (_synctex_data_line(nds.r.node)==_synctex_data_line(nds.l.node)) { + if (nds.l.distance>nds.r.distance) { + node = nds.r.node; + nds.r.node = nds.l.node; + nds.l.node = node; + } + } + if((node = _synctex_new_handle_with_target(nds.l.node))) { + synctex_node_p other_handle; + if((other_handle = _synctex_new_handle_with_target(nds.r.node))) { + _synctex_tree_set_sibling(node,other_handle); + return _synctex_iterator_new(node,2); + } + return _synctex_iterator_new(node,1); + } + return NULL; + } + /* both nodes have the same input coordinates + * We choose the one closest to the hit point */ + if (nds.l.distance>nds.r.distance) { + nds.l.node = nds.r.node; + } + nds.r.node = NULL; + } else if (nds.r.node) { + nds.l = nds.r; + } else if (!nds.l.node) { + nds.l.node = node; + } + if((node = _synctex_new_handle_with_target(nds.l.node))) { + return _synctex_iterator_new(node,1); + } + return 0; + } + } while ((node = _synctex_tree_next_hbox(node))); + /* All the horizontal boxes have been tested, + * None of them contains the hit point. + */ + } + /* We are not lucky, + * we test absolutely all the node + * to find the closest... */ + if ((node = _synctex_tree_child(sheet))) { +#if defined(SYNCTEX_DEBUG) + printf("--- We are not lucky\n"); +#endif + nds.l = __synctex_closest_deep_child_v2(&hit, node); +#if defined(SYNCTEX_DEBUG) + printf("Edit query best: %i\n", nds.l.distance); +#endif + goto end; + } + } + return NULL; +} + +/** + * Loop the candidate friendly list to find the ones with the proper + * tag and line. + * Returns a tree of results targeting the found candidates. + * At the top level each sibling has its own page number. + * All the results with the same page number are linked by child/parent entry. + * - parameter candidate: a friendly list of candidates + */ +static synctex_node_p _synctex_display_query_v2(synctex_node_p target, int tag, int line, synctex_bool_t exclude_box) { + synctex_node_p first_handle = NULL; + /* Search the first match */ + if (target == NULL) { + return first_handle; + } + do { + int page; + if ((exclude_box + && _synctex_node_is_box(target)) + || (tag != synctex_node_tag(target)) + || (line != synctex_node_line(target))) { + continue; + } + /* We found a first match, create + * a result handle targeting that candidate. */ + first_handle = _synctex_new_handle_with_target(target); + if (first_handle == NULL) { + return first_handle; + } + /* target is either a node, + * or a proxy to some node, in which case, + * the target's target belongs to a form, + * not a sheet. */ + page = synctex_node_page(target); + /* Now create all the other results */ + while ((target = _synctex_tree_friend(target))) { + synctex_node_p result = NULL; + if ((exclude_box + && _synctex_node_is_box(target)) + || (tag != synctex_node_tag(target)) + || (line != synctex_node_line(target))) { + continue; + } + /* Another match, same page number ? */ + result = _synctex_new_handle_with_target(target); + if (NULL == result ) { + return first_handle; + } + /* is it the same page number ? */ + if (synctex_node_page(target) == page) { + __synctex_tree_set_child(result, first_handle); + first_handle = result; + } else { + /* We have 2 page numbers involved */ + __synctex_tree_set_sibling(first_handle, result); + while ((target = _synctex_tree_friend(target))) { + synctex_node_p same_page_node; + if ((exclude_box + && _synctex_node_is_box(target)) + || (tag != synctex_node_tag(target)) + || (line != synctex_node_line(target))) { + continue; + } + /* New match found, which page? */ + result = _synctex_new_handle_with_target(target); + if (NULL == result) { + return first_handle; + } + same_page_node = first_handle; + page = synctex_node_page(target); + /* Find a result with the same page number */; + do { + if (_synctex_node_target_page(same_page_node) == page) { + /* Insert result between same_page_node and its child */ + _synctex_tree_set_child(result,_synctex_tree_set_child(same_page_node,result)); + } else if ((same_page_node = __synctex_tree_sibling(same_page_node))) { + continue; + } else { + /* This is a new page number */ + __synctex_tree_set_sibling(result,first_handle); + first_handle = result; + } + break; + } while (synctex_YES); + } + return first_handle; + } + } + } while ((target = _synctex_tree_friend(target))); + return first_handle; +} +synctex_iterator_p synctex_iterator_new_display(synctex_scanner_p scanner,const char * name,int line,int column, int page_hint) { + SYNCTEX_UNUSED(column) + if (scanner) { + int tag = synctex_scanner_get_tag(scanner,name);/* parse if necessary */ + int max_line = 0; + int line_offset = 1; + int try_count = 100; + synctex_node_p node = NULL; + synctex_node_p result = NULL; + if (tag == 0) { + printf("SyncTeX Warning: No tag for %s\n",name); + return NULL; + } + node = synctex_scanner_input_with_tag(scanner, tag); + max_line = _synctex_data_line(node); + /* node = NULL; */ + if (line>max_line) { + line = max_line; + } + while(try_count--) { + if (line<=max_line) { + /* This loop will only be performed once for advanced viewers */ + synctex_node_p friend = _synctex_scanner_friend(scanner,tag+line); + if ((node = friend)) { + result = _synctex_display_query_v2(node,tag,line,synctex_YES); + if (!result) { + /* We did not find any matching boundary, retry including boxes */ + node = friend;/* no need to test it again, already done */ + result = _synctex_display_query_v2(node,tag,line,synctex_NO); + } + /* Now reverse the order to have nodes in display order, and then keep just a few nodes. + * Order first the best node. */ + /* The result is a tree. At the root level, all nodes + * correspond to different page numbers. + * Each node has a child which corresponds to the same + * page number if relevant. + * Then reorder the nodes to put first the one which fits best. + * The idea is to count the number of nodes + * with the same tag and line number in the parents + * and choose the ones with the biggest count. + */ + if (result) { + /* navigate through siblings, then children */ + synctex_node_p next_sibling = __synctex_tree_reset_sibling(result); + int best_match = abs(page_hint-_synctex_node_target_page(result)); + synctex_node_p sibling; + int match; + synctex_counted_node_s cn = _synctex_vertically_sorted_v2(result); + int count = cn.count; + result = cn.node; + while((sibling = next_sibling)) { + /* What is next? Do not miss that step! */ + next_sibling = __synctex_tree_reset_sibling(sibling); + cn = _synctex_vertically_sorted_v2(sibling); + count += cn.count; + sibling = cn.node; + match = abs(page_hint-_synctex_node_target_page(sibling)); + if (match=best_match)*/ { + __synctex_tree_set_sibling(sibling,__synctex_tree_sibling(result)); + __synctex_tree_set_sibling(result,sibling); + } + } + return _synctex_iterator_new(result,count); + } + } +# if defined(__SYNCTEX_STRONG_DISPLAY_QUERY__) + break; +# else + line += line_offset; + line_offset=line_offset<0?-(line_offset-1):-(line_offset+1); + if (line <= 0) { + line += line_offset; + line_offset=line_offset<0?-(line_offset-1):-(line_offset+1); + } +# endif + } + } + } + return NULL; +} +synctex_status_t synctex_display_query(synctex_scanner_p scanner,const char * name,int line,int column, int page_hint) { + if (scanner) { + synctex_iterator_free(scanner->iterator); + scanner->iterator = synctex_iterator_new_display(scanner, name,line,column, page_hint); + return synctex_iterator_count(scanner->iterator); + } + return SYNCTEX_STATUS_ERROR; +} +synctex_status_t synctex_edit_query(synctex_scanner_p scanner,int page,float h,float v) { + if (scanner) { + synctex_iterator_free(scanner->iterator); + scanner->iterator = synctex_iterator_new_edit(scanner, page, h, v); + return synctex_iterator_count(scanner->iterator); + } + return SYNCTEX_STATUS_ERROR; +} +/** + * The next result of a query. + */ +synctex_node_p synctex_scanner_next_result(synctex_scanner_p scanner) { + return scanner? synctex_iterator_next_result(scanner->iterator): NULL; +} +synctex_status_t synctex_scanner_reset_result(synctex_scanner_p scanner) { + return scanner? synctex_iterator_reset(scanner->iterator): SYNCTEX_STATUS_ERROR; +} + +synctex_node_p synctex_node_target(synctex_node_p node) { + return _synctex_tree_target(node); +} + +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark Geometric utilities +# endif + +/** Roughly speaking, this is: + * node's h coordinate - hit point's h coordinate. + * If node is to the right of the hit point, then this distance is positive, + * if node is to the left of the hit point, this distance is negative. + * If the argument is a pdf form reference, then the child is used and returned instead. + * Last Revision: Mon Apr 24 07:05:27 UTC 2017 + */ +static synctex_nd_s _synctex_point_h_ordered_distance_v2 +(synctex_point_p hit, synctex_node_p node) { + synctex_nd_s nd = {node,INT_MAX}; + if (node) { + int min,med,max,width; + switch(synctex_node_type(node)) { + /* The distance between a point and a box is special. + * It is not the euclidean distance, nor something similar. + * We have to take into account the particular layout, + * and the box hierarchy. + * Given a box, there are 9 regions delimited by the lines of the edges of the box. + * The origin being at the top left corner of the page, + * we also give names to the vertices of the box. + * + * 1 | 2 | 3 + * ---A---B---> + * 4 | 5 | 6 + * ---C---D---> + * 7 | 8 | 9 + * v v + */ + case synctex_node_type_vbox: + case synctex_node_type_void_vbox: + case synctex_node_type_void_hbox: + /* getting the box bounds, taking into account negative width, height and depth. */ + width = _synctex_data_width(node); + min = _synctex_data_h(node); + max = min + (width>0?width:-width); + /* We always have min <= max */ + if (hit->hh; /* regions 1+4+7, result is > 0 */ + } else if (hit->h>max) { + nd.distance = max - hit->h; /* regions 3+6+9, result is < 0 */ + } else { + nd.distance = 0; /* regions 2+5+8, inside the box, except for vertical coordinates */ + } + break; + case synctex_node_type_proxy_vbox: + /* getting the box bounds, taking into account negative width, height and depth. */ + width = synctex_node_width(node); + min = synctex_node_h(node); + max = min + (width>0?width:-width); + /* We always have min <= max */ + if (hit->hh; /* regions 1+4+7, result is > 0 */ + } else if (hit->h>max) { + nd.distance = max - hit->h; /* regions 3+6+9, result is < 0 */ + } else { + nd.distance = 0; /* regions 2+5+8, inside the box, except for vertical coordinates */ + } + break; + case synctex_node_type_hbox: + case synctex_node_type_proxy_hbox: + /* getting the box bounds, taking into account negative width, height and depth. */ + width = synctex_node_hbox_width(node); + min = synctex_node_hbox_h(node); + max = min + (width>0?width:-width); + /* We always have min <= max */ + if (hit->hh; /* regions 1+4+7, result is > 0 */ + } else if (hit->h>max) { + nd.distance = max - hit->h; /* regions 3+6+9, result is < 0 */ + } else { + nd.distance = 0; /* regions 2+5+8, inside the box, except for vertical coordinates */ + } + break; + case synctex_node_type_kern: + /* IMPORTANT NOTICE: the location of the kern is recorded AFTER the move. + * The distance to the kern is very special, + * in general, there is no text material in the kern, + * this is why we compute the offset relative to the closest edge of the kern.*/ + max = _synctex_data_width(node); + if (max<0) { + min = _synctex_data_h(node); + max = min - max; + } else { + min = -max; + max = _synctex_data_h(node); + min += max; + } + med = (min+max)/2; + /* positive kern: '.' means text, '>' means kern offset + * ............. + * min>>>>med>>>>max + * ............... + * negative kern: '.' means text, '<' means kern offset + * ............................ + * min<<<hh + 1; /* penalty to ensure other nodes are chosen first in case of overlapping ones */ + } else if (hit->h>max) { + nd.distance = max - hit->h - 1; /* same kind of penalty */ + } else if (hit->h>med) { + /* do things like if the node had 0 width and was placed at the max edge + 1*/ + nd.distance = max - hit->h + 1; /* positive, the kern is to the right of the hit point */ + } else { + nd.distance = min - hit->h - 1; /* negative, the kern is to the left of the hit point */ + } + break; + case synctex_node_type_rule:/* to do: special management */ + case synctex_node_type_glue: + case synctex_node_type_math: + case synctex_node_type_boundary: + case synctex_node_type_box_bdry: + nd.distance = _synctex_data_h(node) - hit->h; + break; + case synctex_node_type_ref: + nd.node = synctex_node_child(node); + nd = _synctex_point_h_ordered_distance_v2(hit,nd.node); + break; + case synctex_node_type_proxy: + case synctex_node_type_proxy_last: + { + /* shift the hit point to be relative to the proxy origin, + * then compute the distance to the target + */ + synctex_point_s otherHit = *hit; + otherHit.h -= _synctex_data_h(node); + otherHit.v -= _synctex_data_v(node); + nd.node = _synctex_tree_target(node); + nd = _synctex_point_h_ordered_distance_v2(&otherHit,nd.node); + nd.node = node; + } + default: + break; + } + } + return nd; +} +/** Roughly speaking, this is: + * node's v coordinate - hit point's v coordinate. + * If node is at the top of the hit point, then this distance is positive, + * if node is at the bottom of the hit point, this distance is negative. + */ +static synctex_nd_s _synctex_point_v_ordered_distance_v2 +(synctex_point_p hit, synctex_node_p node) { + synctex_nd_s nd = {node, INT_MAX}; + int min,max,depth,height; + switch(synctex_node_type(node)) { + /* The distance between a point and a box is special. + * It is not the euclidean distance, nor something similar. + * We have to take into account the particular layout, + * and the box hierarchy. + * Given a box, there are 9 regions delimited by the lines of the edges of the box. + * The origin being at the top left corner of the page, + * we also give names to the vertices of the box. + * + * 1 | 2 | 3 + * ---A---B---> + * 4 | 5 | 6 + * ---C---D---> + * 7 | 8 | 9 + * v v + */ + case synctex_node_type_vbox: + case synctex_node_type_void_vbox: + case synctex_node_type_void_hbox: + /* getting the box bounds, taking into account negative width, height and depth. */ + min = synctex_node_v(node); + max = min + _synctex_abs(_synctex_data_depth(node)); + min -= _synctex_abs(_synctex_data_height(node)); + /* We always have min <= max */ + if (hit->vv; /* regions 1+2+3, result is > 0 */ + } else if (hit->v>max) { + nd.distance = max - hit->v; /* regions 7+8+9, result is < 0 */ + } else { + nd.distance = 0; /* regions 4.5.6, inside the box, except for horizontal coordinates */ + } + break; + case synctex_node_type_proxy_vbox: + /* getting the box bounds, taking into account negative width, height and depth. */ + min = synctex_node_v(node); + max = min + _synctex_abs(synctex_node_depth(node)); + min -= _synctex_abs(synctex_node_height(node)); + /* We always have min <= max */ + if (hit->vv; /* regions 1+2+3, result is > 0 */ + } else if (hit->v>max) { + nd.distance = max - hit->v; /* regions 7+8+9, result is < 0 */ + } else { + nd.distance = 0; /* regions 4.5.6, inside the box, except for horizontal coordinates */ + } + break; + case synctex_node_type_hbox: + case synctex_node_type_proxy_hbox: + /* getting the box bounds, taking into account negative height and depth. */ + min = synctex_node_hbox_v(node); + depth = synctex_node_hbox_depth(node); + max = min + (depth>0?depth:-depth); + height = synctex_node_hbox_height(node); + min -= (height>0?height:-height); + /* We always have min <= max */ + if (hit->vv; /* regions 1+2+3, result is > 0 */ + } else if (hit->v>max) { + nd.distance = max - hit->v; /* regions 7+8+9, result is < 0 */ + } else { + nd.distance = 0; /* regions 4.5.6, inside the box, except for horizontal coordinates */ + } + break; + case synctex_node_type_rule:/* to do: special management */ + case synctex_node_type_kern: + case synctex_node_type_glue: + case synctex_node_type_math: + min = _synctex_data_v(node); + max = min + _synctex_abs(_synctex_data_depth(_synctex_tree_parent(node))); + min -= _synctex_abs(_synctex_data_height(_synctex_tree_parent(node))); + /* We always have min <= max */ + if (hit->vv; /* regions 1+2+3, result is > 0 */ + } else if (hit->v>max) { + nd.distance = max - hit->v; /* regions 7+8+9, result is < 0 */ + } else { + nd.distance = 0; /* regions 4.5.6, inside the box, except for horizontal coordinates */ + } + break; + case synctex_node_type_ref: + nd.node = synctex_node_child(node); + nd = _synctex_point_v_ordered_distance_v2(hit,nd.node); + break; + case synctex_node_type_proxy: + case synctex_node_type_proxy_last: + { + synctex_point_s otherHit = *hit; + otherHit.h -= _synctex_data_h(node); + otherHit.v -= _synctex_data_v(node); + nd.node = _synctex_tree_target(node); + nd = _synctex_point_v_ordered_distance_v2(&otherHit,nd.node); + nd.node = node; + } + default: break; + } + return nd; +} +/** + * The best is the one with the smallest area. + * The area is width*height where width and height may be big. + * So there is a real risk of overflow if we stick with ints. + */ +SYNCTEX_INLINE static synctex_node_p _synctex_smallest_container_v2(synctex_node_p node, synctex_node_p other_node) { + long total_height, other_total_height; + unsigned long area, other_area; + long width = synctex_node_hbox_width(node); + long other_width = synctex_node_hbox_width(other_node); + if (width<0) { + width = -width; + } + if (other_width<0) { + other_width = -other_width; + } + total_height = _synctex_abs(synctex_node_hbox_depth(node)) + _synctex_abs(synctex_node_hbox_height(node)); + other_total_height = _synctex_abs(synctex_node_hbox_depth(other_node)) + _synctex_abs(synctex_node_hbox_height(other_node)); + area = total_height*width; + other_area = other_total_height*other_width; + if (areaother_area) { + return other_node; + } + if (_synctex_abs(_synctex_data_width(node))>_synctex_abs(_synctex_data_width(other_node))) { + return node; + } + if (_synctex_abs(_synctex_data_width(node))<_synctex_abs(_synctex_data_width(other_node))) { + return other_node; + } + if (total_heightother_total_height) { + return other_node; + } + return node; +} + +SYNCTEX_INLINE static synctex_bool_t _synctex_point_in_box_v2(synctex_point_p hit, synctex_node_p node) { + if (node) { + if (0 == _synctex_point_h_ordered_distance_v2(hit,node).distance + && 0 == _synctex_point_v_ordered_distance_v2(hit,node).distance) { + return synctex_YES; + } + } + return synctex_NO; +} + +static int _synctex_distance_to_box_v2(synctex_point_p hit,synctex_box_p box) { + /* The distance between a point and a box is special. + * It is not the euclidean distance, nor something similar. + * We have to take into account the particular layout, + * and the box hierarchy. + * Given a box, there are 9 regions delimited by the lines of the edges of the box. + * The origin being at the top left corner of the page, + * we also give names to the vertices of the box. + * + * 1 | 2 | 3 + * ---A---B---> + * 4 | 5 | 6 + * ---C---D---> + * 7 | 8 | 9 + * v v + * In each region, there is a different formula. + * In the end we have a continuous distance which may not be a mathematical distance but who cares. */ + if (hit->vmin.v) { + /* Regions 1, 2 or 3 */ + if (hit->hmin.h) { + /* This is region 1. The distance to the box is the L1 distance PA. */ + return box->min.v - hit->v + box->min.h - hit->h;/* Integer overflow? probability epsilon */ + } else if (hit->h<=box->max.h) { + /* This is region 2. The distance to the box is the geometrical distance to the top edge. */ + return box->min.v - hit->v; + } else { + /* This is region 3. The distance to the box is the L1 distance PB. */ + return box->min.v - hit->v + hit->h - box->max.h; + } + } else if (hit->v<=box->max.v) { + /* Regions 4, 5 or 6 */ + if (hit->hmin.h) { + /* This is region 4. The distance to the box is the geometrical distance to the left edge. */ + return box->min.h - hit->h; + } else if (hit->h<=box->max.h) { + /* This is region 5. We are inside the box. */ + return 0; + } else { + /* This is region 6. The distance to the box is the geometrical distance to the right edge. */ + return hit->h - box->max.h; + } + } else { + /* Regions 7, 8 or 9 */ + if (hit->hmin.h) { + /* This is region 7. The distance to the box is the L1 distance PC. */ + return hit->v - box->max.v + box->min.h - hit->h; + } else if (hit->h<=box->max.h) { + /* This is region 8. The distance to the box is the geometrical distance to the top edge. */ + return hit->v - box->max.v; + } else { + /* This is region 9. The distance to the box is the L1 distance PD. */ + return hit->v - box->max.v + hit->h - box->max.h; + } + } +} + +/** + * The distance from the hit point to the node. + */ +static int _synctex_point_node_distance_v2(synctex_point_p hit, synctex_node_p node) { + int d = INT_MAX; + if (node) { + synctex_box_s box = {{0,0},{0,0}}; + int dd = INT_MAX; + switch(synctex_node_type(node)) { + case synctex_node_type_vbox: + box.min.h = _synctex_data_h(node); + box.max.h = box.min.h + _synctex_abs(_synctex_data_width(node)); + box.min.v = synctex_node_v(node); + box.max.v = box.min.v + _synctex_abs(_synctex_data_depth(node)); + box.min.v -= _synctex_abs(_synctex_data_height(node)); + return _synctex_distance_to_box_v2(hit,&box); + case synctex_node_type_proxy_vbox: + box.min.h = synctex_node_h(node); + box.max.h = box.min.h + _synctex_abs(synctex_node_width(node)); + box.min.v = synctex_node_v(node); + box.max.v = box.min.v + _synctex_abs(synctex_node_depth(node)); + box.min.v -= _synctex_abs(synctex_node_height(node)); + return _synctex_distance_to_box_v2(hit,&box); + case synctex_node_type_hbox: + case synctex_node_type_proxy_hbox: + box.min.h = synctex_node_hbox_h(node); + box.max.h = box.min.h + _synctex_abs(synctex_node_hbox_width(node)); + box.min.v = synctex_node_hbox_v(node); + box.max.v = box.min.v + _synctex_abs(synctex_node_hbox_depth(node)); + box.min.v -= _synctex_abs(synctex_node_hbox_height(node)); + return _synctex_distance_to_box_v2(hit,&box); + case synctex_node_type_void_vbox: + case synctex_node_type_void_hbox: + /* best of distances from the left edge and right edge*/ + box.min.h = _synctex_data_h(node); + box.max.h = box.min.h; + box.min.v = _synctex_data_v(node); + box.max.v = box.min.v + _synctex_abs(_synctex_data_depth(node)); + box.min.v -= _synctex_abs(_synctex_data_height(node)); + d = _synctex_distance_to_box_v2(hit,&box); + box.min.h = box.min.h + _synctex_abs(_synctex_data_width(node)); + box.max.h = box.min.h; + dd = _synctex_distance_to_box_v2(hit,&box); + return d
*/ + return deep; + } + } while((child = synctex_node_sibling(child))); + /* For vboxes we try to use some node inside. + * Walk through the list of siblings until we find the closest one. + * Only consider siblings with children inside. */ + if (synctex_node_type(node) == synctex_node_type_vbox + || synctex_node_type(node) == synctex_node_type_proxy_vbox) { + if ((child = synctex_node_child(node))) { + synctex_nd_s best = SYNCTEX_ND_0; + do { + if (synctex_node_child(child)) { + int d = _synctex_point_node_distance_v2(hit,child); + if (d < best.distance) { + best = (synctex_nd_s){child,d}; + } + } + } while((child = synctex_node_sibling(child))); + if (best.node) { + return best; + } + } + } + /* is the hit point inside the box? */ + if (_synctex_point_in_box_v2(hit,node)) { + return (synctex_nd_s){node, 0}; + } + } + } + return SYNCTEX_ND_0; +} + +/* Compares the locations of the hit point with the locations of + * the various nodes contained in the box. + * As it is an horizontal box, we only compare horizontal coordinates. + */ +SYNCTEX_INLINE static synctex_nd_lr_s __synctex_eq_get_closest_children_in_hbox_v2(synctex_point_p hitP, synctex_node_p node) { + synctex_nd_s childd = SYNCTEX_ND_0; + synctex_nd_lr_s nds = {SYNCTEX_ND_0,SYNCTEX_ND_0}; + if ((childd.node = synctex_node_child(node))) { + synctex_nd_s nd = SYNCTEX_ND_0; + do { + childd = _synctex_point_h_ordered_distance_v2(hitP,childd.node); + if (childd.distance > 0) { + /* node is to the right of the hit point. + * We compare node and the previously recorded one, through the recorded distance. + * If the nodes have the same tag, prefer the one with the smallest line number, + * if the nodes also have the same line number, prefer the one with the smallest column. */ + if (nds.r.distance > childd.distance) { + nds.r = childd; + } else if (nds.r.distance == childd.distance && nds.r.node) { + if (_synctex_data_tag(nds.r.node) == _synctex_data_tag(childd.node) + && (_synctex_data_line(nds.r.node) > _synctex_data_line(childd.node) + || (_synctex_data_line(nds.r.node) == _synctex_data_line(childd.node) + && _synctex_data_column(nds.r.node) > _synctex_data_column(childd.node)))) { + nds.r = childd; + } + } + } else if (childd.distance == 0) { + /* hit point is inside node. */ + if (_synctex_tree_child(childd.node)) { + return _synctex_eq_get_closest_children_in_box_v2(hitP, childd.node); + } + nds.l = childd; + } else { /* here childd.distance < 0, the hit point is to the right of node */ + childd.distance = -childd.distance; + if (nds.l.distance > childd.distance) { + nds.l = childd; + } else if (nds.l.distance == childd.distance && nds.l.node) { + if (_synctex_data_tag(nds.l.node) == _synctex_data_tag(childd.node) + && (_synctex_data_line(nds.l.node) > _synctex_data_line(childd.node) + || (_synctex_data_line(nds.l.node) == _synctex_data_line(childd.node) + && _synctex_data_column(nds.l.node) > _synctex_data_column(childd.node)))) { + nds.l = childd; + } + } + } + } while((childd.node = synctex_node_sibling(childd.node))); + if (nds.l.node) { + /* the left node is new, try to narrow the result */ + if ((nd = _synctex_eq_deepest_container_v3(hitP,nds.l.node)).node) { + nds.l = nd; + } + if((nd = __synctex_closest_deep_child_v2(hitP,nds.l.node)).node) { + nds.l.node = nd.node; + } + } + if (nds.r.node) { + /* the right node is new, try to narrow the result */ + if ((nd = _synctex_eq_deepest_container_v3(hitP,nds.r.node)).node) { + nds.r = nd; + } + if((nd = __synctex_closest_deep_child_v2(hitP,nds.r.node)).node) { + nds.r.node = nd.node; + } + } + } + return nds; +} + +#if 0 +SYNCTEX_INLINE static synctex_nd_lr_s __synctex_eq_get_closest_children_in_hbox_v3(synctex_point_p hitP, synctex_node_p nodeP) { + synctex_nd_s nd = SYNCTEX_ND_0; + synctex_nd_lr_s nds = {SYNCTEX_ND_0,SYNCTEX_ND_0}; + if ((nd.node = _synctex_tree_child(nodeP))) { + do { + nd = _synctex_point_h_ordered_distance_v2(hitP,nd.node); + if (nd.distance > 0) { + /* node is to the right of the hit point. + * We compare node and the previously recorded one, through the recorded distance. + * If the nodes have the same tag, prefer the one with the smallest line number, + * if the nodes also have the same line number, prefer the one with the smallest column. */ + if (nds.r.distance > nd.distance) { + nds.r = nd; + } else if (nds.r.distance == nd.distance && nds.r.node) { + if (_synctex_data_tag(nds.r.node) == _synctex_data_tag(nd.node) + && (_synctex_data_line(nds.r.node) > _synctex_data_line(nd.node) + || (_synctex_data_line(nds.r.node) == _synctex_data_line(nd.node) + && _synctex_data_column(nds.r.node) > _synctex_data_column(nd.node)))) { + nds.r = nd; + } + } + } else if (nd.distance == 0) { + /* hit point is inside node. */ + nds.l = nd; + } else { /* here nd.d < 0, the hit point is to the right of node */ + nd.distance = -nd.distance; + if (nds.l.distance > nd.distance) { + nds.l = nd; + } else if (nds.l.distance == nd.distance && nds.l.node) { + if (_synctex_data_tag(nds.l.node) == _synctex_data_tag(nd.node) + && (_synctex_data_line(nds.l.node) > _synctex_data_line(nd.node) + || (_synctex_data_line(nds.l.node) == _synctex_data_line(nd.node) + && _synctex_data_column(nds.l.node) > _synctex_data_column(nd.node)))) { + nds.l = nd; + } + } + } + } while((nd.node = __synctex_tree_sibling(nd.node))); + if (nds.l.node) { + /* the left node is new, try to narrow the result */ + if ((nd.node = _synctex_eq_deepest_container_v2(hitP,nds.l.node))) { + nds.l.node = nd.node; + } + if((nd = _synctex_eq_closest_child_v2(hitP,nds.l.node)).node) { + nds.l.node = nd.node; + } + } + if (nds.r.node) { + /* the right node is new, try to narrow the result */ + if ((nd.node = _synctex_eq_deepest_container_v2(hitP,nds.r.node))) { + nds.r.node = nd.node; + } + if((nd = _synctex_eq_closest_child_v2(hitP,nds.r.node)).node) { + nds.r.node = nd.node; + } + } + } + return nds; +} +#endif +SYNCTEX_INLINE static synctex_nd_lr_s __synctex_eq_get_closest_children_in_vbox_v2(synctex_point_p hitP, synctex_node_p nodeP) { + SYNCTEX_UNUSED(nodeP) + synctex_nd_lr_s nds = {SYNCTEX_ND_0,SYNCTEX_ND_0}; + synctex_nd_s nd = SYNCTEX_ND_0; + if ((nd.node = synctex_node_child(nd.node))) { + do { + nd = _synctex_point_v_ordered_distance_v2(hitP,nd.node); + /* this is what makes the difference with the h version above */ + if (nd.distance > 0) { + /* node is to the top of the hit point (below because TeX is oriented from top to bottom. + * We compare node and the previously recorded one, through the recorded distance. + * If the nodes have the same tag, prefer the one with the smallest line number, + * if the nodes also have the same line number, prefer the one with the smallest column. */ + if (nds.r.distance > nd.distance) { + nds.r = nd; + } else if (nds.r.distance == nd.distance && nds.r.node) { + if (_synctex_data_tag(nds.r.node) == _synctex_data_tag(nd.node) + && (_synctex_data_line(nds.r.node) > _synctex_data_line(nd.node) + || (_synctex_data_line(nds.r.node) == _synctex_data_line(nd.node) + && _synctex_data_column(nds.r.node) > _synctex_data_column(nd.node)))) { + nds.r = nd; + } + } + } else if (nd.distance == 0) { + nds.l = nd; + } else { /* here nd < 0 */ + nd.distance = -nd.distance; + if (nds.l.distance > nd.distance) { + nds.l = nd; + } else if (nds.l.distance == nd.distance && nds.l.node) { + if (_synctex_data_tag(nds.l.node) == _synctex_data_tag(nd.node) + && (_synctex_data_line(nds.l.node) > _synctex_data_line(nd.node) + || (_synctex_data_line(nds.l.node) == _synctex_data_line(nd.node) + && _synctex_data_column(nds.l.node) > _synctex_data_column(nd.node)))) { + nds.l = nd; + } + } + } + } while((nd.node = synctex_node_sibling(nd.node))); + if (nds.l.node) { + if ((nd.node = _synctex_eq_deepest_container_v2(hitP,nds.l.node))) { + nds.l.node = nd.node; + } + if((nd = _synctex_eq_closest_child_v2(hitP,nds.l.node)).node) { + nds.l.node = nd.node; + } + } + if (nds.r.node) { + if ((nd.node = _synctex_eq_deepest_container_v2(hitP,nds.r.node))) { + nds.r.node = nd.node; + } + if((nd = _synctex_eq_closest_child_v2(hitP,nds.r.node)).node) { + nds.r.node = nd.node; + } + } + } + return nds; +} + +/** + * Get the child closest to the hit point. + * - parameter: hit point + * - parameter: containing node + * - returns: the child and the distance to the hit point. + * SYNCTEX_ND_0 if the parameter node has no children. + * - note: recursive call. + */ +static synctex_nd_s __synctex_closest_deep_child_v2(synctex_point_p hitP, synctex_node_p node) { + synctex_nd_s best = SYNCTEX_ND_0; + synctex_node_p child = NULL; + if ((child = synctex_node_child(node))) { +#if defined(SYNCTEX_DEBUG) + printf("Closest deep child on box at line %i\n", + SYNCTEX_LINEINDEX(node)); +#endif + do { +#if SYNCTEX_DEBUG>500 + synctex_node_display(child); +#endif + synctex_nd_s nd = SYNCTEX_ND_0; + if (_synctex_node_is_box(child)) { + nd = __synctex_closest_deep_child_v2(hitP,child); + } else { + nd = (synctex_nd_s) {child, _synctex_point_node_distance_v2(hitP,child)}; + } + if (nd.distance < best.distance ||(nd.distance == best.distance + && synctex_node_type(nd.node) != synctex_node_type_kern)) { +#if defined(SYNCTEX_DEBUG) + if(nd.node) { + printf("New best %i<=%i line %i\n",nd.distance, + best.distance,SYNCTEX_LINEINDEX(nd.node)); + } +#endif + best = nd; + } + } while((child = synctex_node_sibling(child))); +#if defined(SYNCTEX_DEBUG) + if(best.node) { + printf("Found new best %i line %i\n",best.distance,SYNCTEX_LINEINDEX(best.node)); + } +#endif + } + return best; +} + +/** + * Return the closest child. + * - parameter: a pointer to the hit point, + * - parameter: the container + * - return: SYNCTEX_ND_0 if node has no child, + * the __synctex_closest_deep_child_v2 otherwise. + */ +static synctex_nd_s _synctex_eq_closest_child_v2(synctex_point_p hitP, synctex_node_p node) { + synctex_nd_s nd = SYNCTEX_ND_0; + if (_synctex_node_is_box(node)) { + nd = __synctex_closest_deep_child_v2(hitP, node); + if (_synctex_node_is_box(nd.node)) { + synctex_node_p child = NULL; + if ((child = synctex_node_child(nd.node))) { + synctex_nd_s best = {child,_synctex_point_node_distance_v2(hitP,child)}; + while((child = synctex_node_sibling(child))) { + int d = _synctex_point_node_distance_v2(hitP,child); + if (d < best.distance) { + best = (synctex_nd_s){child,d}; + } else if (d == best.distance && synctex_node_type(child) != synctex_node_type_kern) { + best.node = child; + } + } + return best; + } + } + return nd; + } + return SYNCTEX_ND_0; +} +SYNCTEX_INLINE static synctex_nd_lr_s _synctex_eq_get_closest_children_in_box_v2(synctex_point_p hitP, synctex_node_p node) { + synctex_nd_lr_s nds = {SYNCTEX_ND_0,SYNCTEX_ND_0}; + if(_synctex_tree_has_child(node)) { /* node != NULL */ + if (node->class_->type==synctex_node_type_hbox || + node->class_->type==synctex_node_type_proxy_hbox) { + return __synctex_eq_get_closest_children_in_hbox_v2(hitP,node); + } else { + return __synctex_eq_get_closest_children_in_vbox_v2(hitP,node); + } + } + return nds; +} + +#ifndef SYNCTEX_NO_UPDATER + +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark Updater +# endif + +typedef int (*synctex_print_f)(synctex_updater_p, const char * , ...); /* print formatted to either FILE * or gzFile */ +typedef void (*synctex_close_f)(synctex_updater_p); /* close FILE * or gzFile */ + +# define SYNCTEX_BITS_PER_BYTE 8 + +typedef union { + gzFile as_gzFile; + FILE * as_FILE_p; + void * as_ptr; +} syncex_file_u; + +struct synctex_updater_t { + syncex_file_u file; + synctex_print_f print; + synctex_close_f close; + int length; /* the number of chars appended */ +}; + +static int _synctex_updater_print(synctex_updater_p updater, const char * format, ...) { + int result = 0; + if (updater) { + va_list va; + va_start(va, format); + result = vfprintf(updater->file.as_FILE_p, + format, + va); + va_end(va); + } + return result; +} +#if defined(_MSC_VER) +#include +#include +#include + +static int vasprintf(char **ret, + const char *format, + va_list ap) +{ + int len; + len = _vsnprintf(NULL, 0, format, ap); + if (len < 0) return -1; + *ret = malloc(len + 1); + if (!*ret) return -1; + _vsnprintf(*ret, len+1, format, ap); + (*ret)[len] = '\0'; + return len; +} + +#endif + +/** + * gzvprintf is not available until OSX 10.10 + */ +static int _synctex_updater_print_gz(synctex_updater_p updater, const char * format, ...) { + int result = 0; + if (updater) { + char * buffer; + va_list va; + va_start(va, format); + if (vasprintf(&buffer, format, va) < 0) { + _synctex_error("Out of memory..."); + } else if ((result = (int)strlen(buffer))) { + result = gzwrite(updater->file.as_gzFile, buffer, (unsigned)result); + } + va_end(va); + free(buffer); + } + return result; +} + +static void _synctex_updater_close(synctex_updater_p updater) { + if (updater) { + fclose(updater->file.as_FILE_p); + } +} + +static void _synctex_updater_close_gz(synctex_updater_p updater) { + if (updater) { + gzclose(updater->file.as_gzFile); + } +} + +synctex_updater_p synctex_updater_new_with_output_file(const char * output, const char * build_directory) { + synctex_updater_p updater = NULL; + const char * mode = NULL; + synctex_open_s open; + /* prepare the updater, the memory is the only one dynamically allocated */ + updater = (synctex_updater_p)_synctex_malloc(sizeof(synctex_updater_s)); + if (NULL == updater) { + _synctex_error("! synctex_updater_new_with_file: malloc problem"); + return NULL; + } + open = _synctex_open_v2(output,build_directory,0,synctex_ADD_QUOTES); + if (open.status < SYNCTEX_STATUS_OK) { + open = _synctex_open_v2(output,build_directory,0,synctex_DONT_ADD_QUOTES); + if (open.status < SYNCTEX_STATUS_OK) { + return_on_error: + _synctex_free(updater); + return updater = NULL; + } + } + /* OK, the file exists, we close it and reopen it with the correct mode. + * The receiver is now the owner of the "synctex" variable. */ + gzclose(open.file); + updater->file.as_ptr = NULL; + mode = _synctex_get_io_mode_name(open.io_mode|synctex_io_append_mask);/* either "a" or "ab", depending on the file extension */ + if (open.io_mode&synctex_io_gz_mask) { + if (NULL == (updater->file.as_FILE_p = fopen(open.synctex,mode))) { + no_write_error: + _synctex_error("! synctex_updater_new_with_file: Can't append to %s",open.synctex); + free(open.synctex); + goto return_on_error; + } + updater->print = &_synctex_updater_print; + updater->close = &_synctex_updater_close; + } else { + if (NULL == (updater->file.as_gzFile = gzopen(open.synctex,mode))) { + goto no_write_error; + } + updater->print = &_synctex_updater_print_gz; + updater->close = &_synctex_updater_close_gz; + } + printf("SyncTeX: updating %s...",open.synctex); + _synctex_free(open.synctex); + return updater; +} + +void synctex_updater_append_magnification(synctex_updater_p updater, char * magnification){ + if (NULL==updater) { + return; + } + if (magnification && strlen(magnification)) { + updater->length += + updater->print(updater,"Magnification:%s\n",magnification); + } +} + +void synctex_updater_append_x_offset(synctex_updater_p updater, char * x_offset){ + if (NULL==updater) { + return; + } + if (x_offset && strlen(x_offset)) { + updater->length += updater->print(updater,"X Offset:%s\n",x_offset); + } +} + +void synctex_updater_append_y_offset(synctex_updater_p updater, char * y_offset){ + if (NULL==updater) { + return; + } + if (y_offset && strlen(y_offset)) { + updater->length += updater->print(updater,"Y Offset:%s\n",y_offset); + } +} + +void synctex_updater_free(synctex_updater_p updater){ + if (NULL==updater) { + return; + } + if (updater->length>0) { + updater->print(updater,"!%i\n",updater->length); + } + updater->close(updater); + _synctex_free(updater); + printf("... done.\n"); + return; +} +#endif + +#if defined(SYNCTEX_TESTING) +# ifdef SYNCTEX_NOTHING +# pragma mark - +# pragma mark Testers +# endif +static int _synctex_input_copy_name(synctex_node_p input, char * name) { + char * copy = _synctex_malloc(strlen(name)+1); + memcpy(copy,name,strlen(name)+1); + _synctex_data_set_name(input,copy); + return 0; +} +int synctex_test_setup_scanner_sheets_421(synctex_scanner_p scanner) { + int TC = 0; + synctex_node_p sheet = synctex_node_new(scanner,synctex_node_type_sheet); + _synctex_data_set_page(sheet,4); + SYNCTEX_TEST_BODY(TC, _synctex_data_page(sheet)==4,""); + synctex_node_free(scanner->sheet); + scanner->sheet = sheet; + sheet = synctex_node_new(scanner,synctex_node_type_sheet); + _synctex_data_set_page(sheet,2); + SYNCTEX_TEST_BODY(TC, _synctex_data_page(sheet)==2,""); + __synctex_tree_set_sibling(sheet, scanner->sheet); + scanner->sheet = sheet; + sheet = synctex_node_new(scanner,synctex_node_type_sheet); + _synctex_data_set_page(sheet,1); + SYNCTEX_TEST_BODY(TC, _synctex_data_page(sheet)==1,""); + __synctex_tree_set_sibling(sheet, scanner->sheet); + scanner->sheet = sheet; + return TC; +} +int synctex_test_input(synctex_scanner_p scanner) { + int TC = 0; + synctex_node_p input = synctex_node_new(scanner,synctex_node_type_input); + _synctex_data_set_tag(input,421); + SYNCTEX_TEST_BODY(TC, _synctex_data_tag(input)==421,""); + _synctex_data_set_tag(input,124); + SYNCTEX_TEST_BODY(TC, _synctex_data_tag(input)==124,""); + _synctex_data_set_line(input,421); + SYNCTEX_TEST_BODY(TC, _synctex_data_line(input)==421,""); + _synctex_data_set_line(input,214); + SYNCTEX_TEST_BODY(TC, _synctex_data_line(input)==214,""); + _synctex_data_set_line(input,214); + SYNCTEX_TEST_BODY(TC, _synctex_data_line(input)==214,""); + _synctex_input_copy_name(input,"214"); + SYNCTEX_TEST_BODY(TC, 0==memcmp(_synctex_data_name(input),"214",4),""); + _synctex_input_copy_name(input,"421421"); + + SYNCTEX_TEST_BODY(TC, + 0==memcmp(_synctex_data_name(input), + "421421", + 4), + ""); + synctex_node_free(input); + return TC; +} +int synctex_test_proxy(synctex_scanner_p scanner) { + int TC = 0; + synctex_node_p proxy = synctex_node_new(scanner,synctex_node_type_proxy); + synctex_node_p target = synctex_node_new(scanner,synctex_node_type_rule); + _synctex_tree_set_target(proxy,target); + _synctex_data_set_tag(target,421); + SYNCTEX_TEST_BODY(TC, _synctex_data_tag(target)==421,""); + SYNCTEX_TEST_BODY(TC, synctex_node_tag(target)==421,""); + SYNCTEX_TEST_BODY(TC, synctex_node_tag(proxy)==421,""); + synctex_node_free(proxy); + synctex_node_free(target); + return TC; +} +int synctex_test_handle(synctex_scanner_p scanner) { + int TC = 0; + synctex_node_p handle = synctex_node_new(scanner,synctex_node_type_handle); + synctex_node_p proxy = synctex_node_new(scanner, synctex_node_type_proxy); + synctex_node_p target = synctex_node_new(scanner,synctex_node_type_rule); + _synctex_tree_set_target(handle,target); + _synctex_data_set_tag(target,421); + SYNCTEX_TEST_BODY(TC, _synctex_data_tag(target)==421,""); + SYNCTEX_TEST_BODY(TC, synctex_node_tag(target)==421,""); + SYNCTEX_TEST_BODY(TC, synctex_node_tag(handle)==421,""); + _synctex_data_set_line(target,214); + SYNCTEX_TEST_BODY(TC, _synctex_data_line(target)==214,""); + SYNCTEX_TEST_BODY(TC, synctex_node_line(target)==214,""); + SYNCTEX_TEST_BODY(TC, synctex_node_line(handle)==214,""); + _synctex_data_set_column(target,142); + SYNCTEX_TEST_BODY(TC, _synctex_data_column(target)==142,""); + SYNCTEX_TEST_BODY(TC, synctex_node_column(target)==142,""); + SYNCTEX_TEST_BODY(TC, synctex_node_column(handle)==142,""); + _synctex_tree_set_target(proxy,target); + _synctex_tree_set_target(handle,proxy); + _synctex_data_set_tag(target,412); + SYNCTEX_TEST_BODY(TC, _synctex_data_tag(target)==412,""); + SYNCTEX_TEST_BODY(TC, synctex_node_tag(target)==412,""); + SYNCTEX_TEST_BODY(TC, synctex_node_tag(handle)==412,""); + _synctex_data_set_line(target,124); + SYNCTEX_TEST_BODY(TC, _synctex_data_line(target)==124,""); + SYNCTEX_TEST_BODY(TC, synctex_node_line(target)==124,""); + SYNCTEX_TEST_BODY(TC, synctex_node_line(handle)==124,""); + _synctex_data_set_column(target,241); + SYNCTEX_TEST_BODY(TC, _synctex_data_column(target)==241,""); + SYNCTEX_TEST_BODY(TC, synctex_node_column(target)==241,""); + SYNCTEX_TEST_BODY(TC, synctex_node_column(handle)==241,""); + synctex_node_free(handle); + synctex_node_free(proxy); + synctex_node_free(target); + return TC; +} +int synctex_test_setup_scanner_input(synctex_scanner_p scanner) { + int TC = 0; + synctex_node_p input = synctex_node_new(scanner,synctex_node_type_input); + _synctex_data_set_tag(input,4); + _synctex_input_copy_name(input,"21"); + _synctex_data_set_line(input,421); + synctex_node_free(scanner->input); + scanner->input = input; + SYNCTEX_TEST_BODY(TC, _synctex_data_tag(input)==4,""); + SYNCTEX_TEST_BODY(TC, strcmp(_synctex_data_name(input),"21")==0,""); + SYNCTEX_TEST_BODY(TC, _synctex_data_line(input)==421,""); + return TC; +} +int synctex_test_setup_nodes(synctex_scanner_p scanner, synctex_node_r nodes) { + int TC = 0; + int n; + for (n=0;nsheet; + synctex_node_p node = synctex_node_new(scanner,synctex_node_type_rule); + _synctex_data_set_tag(node,4); + _synctex_data_set_line(node,21); + synctex_node_free(_synctex_node_set_child(sheet,node)); + SYNCTEX_TEST_BODY(TC, synctex_node_page(node)==synctex_node_page(sheet),""); + return TC; +} +int synctex_test_display_query(synctex_scanner_p scanner) { + int TC = synctex_test_setup_scanner_sheets_421(scanner); + synctex_node_p sheet = scanner->sheet; + synctex_node_p node = synctex_node_new(scanner,synctex_node_type_rule); + _synctex_data_set_tag(node,4); + _synctex_data_set_line(node,21); + synctex_node_free(_synctex_node_set_child(sheet,node)); + SYNCTEX_TEST_BODY(TC, node==synctex_node_child(sheet),""); + __synctex_node_make_friend_tlc(node); + SYNCTEX_TEST_BODY(TC, _synctex_scanner_friend(scanner, 25)==node,""); + sheet = __synctex_tree_sibling(sheet); + node = synctex_node_new(scanner,synctex_node_type_rule); + _synctex_data_set_tag(node,4); + _synctex_data_set_line(node,21); + synctex_node_free(_synctex_node_set_child(sheet,node)); + SYNCTEX_TEST_BODY(TC, node==synctex_node_child(sheet),""); + __synctex_node_make_friend_tlc(node); + SYNCTEX_TEST_BODY(TC, _synctex_scanner_friend(scanner, 25)==node,""); + sheet = __synctex_tree_sibling(sheet); + node = synctex_node_new(scanner,synctex_node_type_rule); + _synctex_data_set_tag(node,4); + _synctex_data_set_line(node,21); + synctex_node_free(_synctex_node_set_child(sheet,node)); + SYNCTEX_TEST_BODY(TC, node==synctex_node_child(sheet),""); + __synctex_node_make_friend_tlc(node); + SYNCTEX_TEST_BODY(TC, (_synctex_scanner_friend(scanner, 25)==node),""); + synctex_test_setup_scanner_input(scanner); + scanner->flags.has_parsed = synctex_YES; +#if 1 + SYNCTEX_TEST_BODY(TC, (synctex_display_query(scanner,"21",21,4,-1)==3),""); +#endif + return TC; +} +typedef struct { + int s; /* status */ + char n[25]; /* name */ +} synctex_test_sn_s; + +synctex_test_sn_s synctex_test_tmp_sn(char * content) { + synctex_test_sn_s sn = {0, "/tmp/test.XXXXXX.synctex"}; + FILE *sfp; + int fd = mkstemps(sn.n,8); + if (fd < 0) { + fprintf(stderr, "%s: %s\n", sn.n, strerror(errno)); + sn.s = -1; + return sn; + } + if ((sfp = fdopen(fd, "w+")) == NULL) { + unlink(sn.n); + close(fd); + fprintf(stderr, "%s: %s\n", sn.n, strerror(errno)); + sn.s = -2; + return sn; + } + sn.s = fputs(content,sfp); + printf("temp:%s\n%i\n",sn.n,sn.s); + fclose(sfp); + if (sn.s==0) { + sn.s = -2; + unlink(sn.n); + } + return sn; +} +int synctex_test_sheet_1() { + int TC = 0; + char * content = + "SyncTeX Version:1 \n" /*00-19*/ + "Input:1:./1.tex \n" /*20-39*/ + "Output:pdf \n" /*40-59*/ + "Magnification:100000000 \n" /*60-89*/ + "Unit:1 \n" /*90-99*/ + "X Offset:0 \n" /*00-19*/ + "Y Offset:0 \n" /*20-39*/ + "Content: \n" /*40-49*/ + "{1 \n" /*50-59*/ + "[1,10:20,350:330,330,0 \n" /*60-89*/ + "] \n" /*90-99*/ + "} \n" /*00-09*/ + "Postamble:\n"; + synctex_test_sn_s sn = synctex_test_tmp_sn(content); + if (sn.s>0) { + synctex_scanner_p scanner = synctex_scanner_new_with_output_file(sn.n, NULL, synctex_YES); + synctex_node_p node = synctex_scanner_handle(scanner); + printf("Created nodes:\n"); + while (node) { + printf("%s\n",_synctex_node_abstract(node)); + node = synctex_node_next(node); + } + synctex_scanner_free(scanner); + unlink(sn.n); + } else { + ++TC; + } + return TC; +} +int synctex_test_sheet_2() { + int TC = 0; + char * content = + "SyncTeX Version:1 \n" /*00-19*/ + "Input:1:./1.tex \n" /*20-39*/ + "Output:pdf \n" /*40-59*/ + "Magnification:100000000 \n" /*60-89*/ + "Unit:1 \n" /*90-99*/ + "X Offset:0 \n" /*00-19*/ + "Y Offset:0 \n" /*20-39*/ + "Content: \n" /*40-49*/ + "{1 \n" /*50-59*/ + "(1,10:20,350:330,330,0 \n" /*60-89*/ + ") \n" /*90-99*/ + "} \n" /*00-09*/ + "Postamble:\n"; + synctex_test_sn_s sn = synctex_test_tmp_sn(content); + if (sn.s>0) { + synctex_scanner_p scanner = synctex_scanner_new_with_output_file(sn.n, NULL, synctex_YES); + synctex_node_p node = synctex_scanner_handle(scanner); + printf("Created nodes:\n"); + while (node) { + printf("%s\n",_synctex_node_abstract(node)); + node = _synctex_node_next(node); + } + TC += synctex_scanner_free(scanner); + unlink(sn.n); + } else { + ++TC; + } + return TC; +} +int synctex_test_charindex() { + int TC = 0; + char * content = + "SyncTeX Version:1 \n" /*00-19*/ + "Input:1:./1.tex \n" /*20-39*/ + "Output:pdf \n" /*40-59*/ + "Magnification:100000000 \n" /*60-89*/ + "Unit:1 \n" /*90-99*/ + "X Offset:0 \n" /*00-19*/ + "Y Offset:0 \n" /*20-39*/ + "Content: \n" /*40-49*/ + "{1 \n" /*50-59*/ + "[1,10:20,350:330,330,0 \n" /*60-89*/ + "(1,58:20,100:250,10,5 \n" /*90-119*/ + "f1000:50,100 \n" /*20-39*/ + ") \n" /*40-49*/ + "] \n" /*50-59*/ + "} \n" /*60-69*/ + "Postamble:\n"; + synctex_test_sn_s sn = synctex_test_tmp_sn(content); + if (sn.s>0) { + synctex_scanner_p scanner = synctex_scanner_new_with_output_file(sn.n, NULL, synctex_YES); + synctex_node_p node = synctex_scanner_handle(scanner); + printf("Created nodes:\n"); + while (node) { + printf("%s\n",_synctex_node_abstract(node)); + node = synctex_node_next(node); + } + TC += synctex_scanner_free(scanner); + unlink(sn.n); + } else { + ++TC; + } + return TC; +} +int synctex_test_form() { + int TC = 0; + char * content = + "SyncTeX Version:1 \n" /*00-19*/ + "Input:1:./1.tex \n" /*20-39*/ + "Output:pdf \n" /*40-59*/ + "Magnification:100000000 \n" /*60-89*/ + "Unit:1 \n" /*90-99*/ + "X Offset:0 \n" /*00-19*/ + "Y Offset:0 \n" /*20-39*/ + "Content: \n" /*40-49*/ + "{1 \n" /*50-59*/ + "[1,10:20,350:330,330,0 \n" /*60-89*/ + "(1,58:20,100:250,10,5 \n" /*90-119*/ + "f1000:50,100 \n" /*20-39*/ + ") \n" /*40-49*/ + "] \n" /*50-59*/ + "} \n" /*60-69*/ + "<1000 \n" /*70-79*/ + "(1,63:0,0:100,8,3 \n" /*80-99*/ + ") \n" /*00-09*/ + "> \n" /*10-19*/ + "Postamble:\n"; + synctex_test_sn_s sn = synctex_test_tmp_sn(content); + if (sn.s>0) { + synctex_scanner_p scanner = synctex_scanner_new_with_output_file(sn.n, NULL, synctex_YES); + synctex_node_p node = synctex_scanner_handle(scanner); + while (node) { + printf("%s\n",_synctex_node_abstract(node)); + node = _synctex_node_next(node); + } + TC += synctex_scanner_free(scanner); + unlink(sn.n); + } else { + ++TC; + } + return TC; +} +#endif diff --git a/org/elpa/pdf-tools-20230404.327/build/server/synctex_parser.h b/org/elpa/pdf-tools-20230404.327/build/server/synctex_parser.h new file mode 100644 index 0000000..9e0a00e --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/build/server/synctex_parser.h @@ -0,0 +1,429 @@ +/* + Copyright (c) 2008-2017 jerome DOT laurens AT u-bourgogne DOT fr + + This file is part of the __SyncTeX__ package. + + [//]: # (Latest Revision: Fri Jul 14 16:20:41 UTC 2017) + [//]: # (Version: 1.21) + + See `synctex_parser_readme.md` for more details + + ## License + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE + + Except as contained in this notice, the name of the copyright holder + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization from the copyright holder. + + ## Acknowledgments: + + The author received useful remarks from the __pdfTeX__ developers, especially Hahn The Thanh, + and significant help from __XeTeX__ developer Jonathan Kew. + + ## Nota Bene: + + If you include or use a significant part of the __SyncTeX__ package into a software, + I would appreciate to be listed as contributor and see "__SyncTeX__" highlighted. +*/ + +#ifndef __SYNCTEX_PARSER__ +# define __SYNCTEX_PARSER__ + +#include "synctex_version.h" + +#ifdef __cplusplus +extern "C" { +#endif + + /* The main synctex object is a scanner. + * Its implementation is considered private. + * The basic workflow is + * - create a "synctex scanner" with the contents of a file + * - perform actions on that scanner like + synctex_display_query or synctex_edit_query below. + * - perform actions on nodes returned by the scanner + * - free the scanner when the work is done + */ + typedef struct synctex_scanner_t synctex_scanner_s; + typedef synctex_scanner_s * synctex_scanner_p; + + /** + * This is the designated method to create + * a new synctex scanner object. + * - argument output: the pdf/dvi/xdv file associated + * to the synctex file. + * If necessary, it can be the tex file that + * originated the synctex file but this might cause + * problems if the \jobname has a custom value. + * Despite this method can accept a relative path + * in practice, you should only pass full paths. + * The path should be encoded by the underlying + * file system, assuming that it is based on + * 8 bits characters, including UTF8, + * not 16 bits nor 32 bits. + * The last file extension is removed and + * replaced by the proper extension, + * either synctex or synctex.gz. + * - argument build_directory: It is the directory where + * all the auxiliary stuff is created. + * If no synctex file is found in the same directory + * as the output file, then we try to find one in + * this build directory. + * It is the directory where all the auxiliary + * stuff is created. Sometimes, the synctex output + * file and the pdf, dvi or xdv files are not + * created in the same location. See MikTeX. + * This directory path can be NULL, + * it will be ignored then. + * It can be either absolute or relative to the + * directory of the output pdf (dvi or xdv) file. + * Please note that this new argument is provided + * as a convenience but should not be used. + * Available since version 1.5. + * - argument parse: In general, use 1. + * Use 0 only if you do not want to parse the + * content but just check for existence. + * Available since version 1.5 + * - return: a scanner. NULL is returned in case + * of an error or non existent file. + */ + synctex_scanner_p synctex_scanner_new_with_output_file(const char * output, const char * build_directory, int parse); + + /** + * Designated method to delete a synctex scanner object, + * including all its internal resources. + * Frees all the memory, you must call it when you are finished with the scanner. + * - argument scanner: a scanner. + * - returns: an integer used for testing purposes. + */ + int synctex_scanner_free(synctex_scanner_p scanner); + + /** + * Send this message to force the scanner to + * parse the contents of the synctex output file. + * Nothing is performed if the file was already parsed. + * In each query below, this message is sent, + * but if you need to access information more directly, + * you must ensure that the parsing did occur. + * Usage: + * if((my_scanner = synctex_scanner_parse(my_scanner))) { + * continue with my_scanner... + * } else { + * there was a problem + * } + * - returns: the argument on success. + * On failure, frees scanner and returns NULL. + */ + synctex_scanner_p synctex_scanner_parse(synctex_scanner_p scanner); + + /* synctex_node_p is the type for all synctex nodes. + * Its implementation is considered private. + * The synctex file is parsed into a tree of nodes, either sheet, form, boxes, math nodes... */ + + typedef struct synctex_node_t synctex_node_s; + typedef synctex_node_s * synctex_node_p; + + /* The main entry points. + * Given the file name, a line and a column number, synctex_display_query returns the number of nodes + * satisfying the contrain. Use code like + * + * if(synctex_display_query(scanner,name,line,column,page_hint)>0) { + * synctex_node_p node; + * while((node = synctex_scanner_next_result(scanner))) { + * // do something with node + * ... + * } + * } + * + * Please notice that since version 1.19, + * there is a new argument page_hint. + * The results in pages closer to page_hint are given first. + * For example, one can + * - highlight each resulting node in the output, using synctex_node_visible_h and synctex_node_visible_v + * - highlight all the rectangles enclosing those nodes, using synctex_node_box_visible_... functions + * - highlight just the character using that information + * + * Given the page and the position in the page, synctex_edit_query returns the number of nodes + * satisfying the contrain. Use code like + * + * if(synctex_edit_query(scanner,page,h,v)>0) { + * synctex_node_p node; + * while(node = synctex_scanner_next_result(scanner)) { + * // do something with node + * ... + * } + * } + * + * For example, one can + * - highlight each resulting line in the input, + * - highlight just the character using that information + * + * page is 1 based + * h and v are coordinates in 72 dpi unit, relative to the top left corner of the page. + * If you make a new query, the result of the previous one is discarded. If you need to make more than one query + * in parallel, use the iterator API exposed in + * the synctex_parser_private.h header. + * If one of this function returns a negative integer, + * it means that an error occurred. + * + * Both methods are conservative, in the sense that matching is weak. + * If the exact column number is not found, there will be an answer with the whole line. + * + * Sumatra-PDF, Skim, iTeXMac2, TeXShop and Texworks are examples of open source software that use this library. + * You can browse their code for a concrete implementation. + */ + typedef long synctex_status_t; + /* The page_hint argument is used to resolve ambiguities. + * Whenever, different matches occur, the ones closest + * to the page will be given first. Pass a negative number + * when in doubt. Using pdf forms may lead to ambiguities. + */ + synctex_status_t synctex_display_query(synctex_scanner_p scanner,const char * name,int line,int column, int page_hint); + synctex_status_t synctex_edit_query(synctex_scanner_p scanner,int page,float h,float v); + synctex_node_p synctex_scanner_next_result(synctex_scanner_p scanner); + synctex_status_t synctex_scanner_reset_result(synctex_scanner_p scanner); + + /** + * The horizontal and vertical location, + * the width, height and depth of a box enclosing node. + * All dimensions are given in page coordinates + * as opposite to TeX coordinates. + * The origin is at the top left corner of the page. + * Code example for Qt5: + * (from TeXworks source TWSynchronize.cpp) + * QRectF nodeRect(synctex_node_box_visible_h(node), + * synctex_node_box_visible_v(node) - + * synctex_node_box_visible_height(node), + * synctex_node_box_visible_width(node), + * synctex_node_box_visible_height(node) + + * synctex_node_box_visible_depth(node)); + * Code example for Cocoa: + * NSRect bounds = [pdfPage + * boundsForBox:kPDFDisplayBoxMediaBox]; + * NSRect nodeRect = NSMakeRect( + * synctex_node_box_visible_h(node), + * NSMaxY(bounds)-synctex_node_box_visible_v(node) + + * synctex_node_box_visible_height(node), + * synctex_node_box_visible_width(node), + * synctex_node_box_visible_height(node) + + * synctex_node_box_visible_depth(node) + * ); + * The visible dimensions are bigger than real ones + * to compensate 0 width boxes or nodes intentionnaly + * put outside the box (using \kern for example). + * - parameter node: a node. + * - returns: a float. + * - author: JL + */ + float synctex_node_box_visible_h(synctex_node_p node); + float synctex_node_box_visible_v(synctex_node_p node); + float synctex_node_box_visible_width(synctex_node_p node); + float synctex_node_box_visible_height(synctex_node_p node); + float synctex_node_box_visible_depth(synctex_node_p node); + + /** + * For quite all nodes, horizontal and vertical coordinates, and width. + * All dimensions are given in page coordinates + * as opposite to TeX coordinates. + * The origin is at the top left corner of the page. + * The visible dimensions are bigger than real ones + * to compensate 0 width boxes or nodes intentionnaly + * put outside the box (using \kern for example). + * All nodes have coordinates, but all nodes don't + * have non null size. For example, math nodes + * have no width according to TeX, and in that case + * synctex_node_visible_width simply returns 0. + * The same holds for kern nodes that do not have + * height nor depth, etc... + */ + float synctex_node_visible_h(synctex_node_p node); + float synctex_node_visible_v(synctex_node_p node); + float synctex_node_visible_width(synctex_node_p node); + float synctex_node_visible_height(synctex_node_p node); + float synctex_node_visible_depth(synctex_node_p node); + + /** + * Given a node, access to its tag, line and column. + * The line and column numbers are 1 based. + * The latter is not yet fully supported in TeX, + * the default implementation returns 0 + * which means the whole line. + * synctex_node_get_name returns the path of the + * TeX source file that was used to create the node. + * When the tag is known, the scanner of the node + * will also give that same file name, see + * synctex_scanner_get_name below. + * For an hbox node, the mean line is the mean + * of all the lines of the child nodes. + * Sometimes, when synchronization form pdf to source + * fails with the line, one should try with the + * mean line. + */ + int synctex_node_tag(synctex_node_p node); + int synctex_node_line(synctex_node_p node); + int synctex_node_mean_line(synctex_node_p node); + int synctex_node_column(synctex_node_p node); + const char * synctex_node_get_name(synctex_node_p node); + + /** + This is the page where the node appears. + * This is a 1 based index as given by TeX. + */ + int synctex_node_page(synctex_node_p node); + + /** + * Display all the information contained in the scanner. + * If the records are too numerous, only the first ones are displayed. + * This is mainly for informational purpose to help developers. + */ + void synctex_scanner_display(synctex_scanner_p scanner); + + /* Managing the input file names. + * Given a tag, synctex_scanner_get_name will return the corresponding file name. + * Conversely, given a file name, synctex_scanner_get_tag will return, the corresponding tag. + * The file name must be the very same as understood by TeX. + * For example, if you \input myDir/foo.tex, the file name is myDir/foo.tex. + * No automatic path expansion is performed. + * Finally, synctex_scanner_input is the first input node of the scanner. + * To browse all the input node, use a loop like + * ... + * synctex_node_p = input_node; + * ... + * if((input_node = synctex_scanner_input(scanner))) { + * do { + * blah + * } while((input_node=synctex_node_sibling(input_node))); + * } + * + * The output is the name that was used to create the scanner. + * The synctex is the real name of the synctex file, + * it was obtained from output by setting the proper file extension. + */ + const char * synctex_scanner_get_name(synctex_scanner_p scanner,int tag); + + int synctex_scanner_get_tag(synctex_scanner_p scanner,const char * name); + + synctex_node_p synctex_scanner_input(synctex_scanner_p scanner); + synctex_node_p synctex_scanner_input_with_tag(synctex_scanner_p scanner,int tag); + const char * synctex_scanner_get_output(synctex_scanner_p scanner); + const char * synctex_scanner_get_synctex(synctex_scanner_p scanner); + + /* The x and y offset of the origin in TeX coordinates. The magnification + These are used by pdf viewers that want to display the real box size. + For example, getting the horizontal coordinates of a node would require + synctex_node_box_h(node)*synctex_scanner_magnification(scanner)+synctex_scanner_x_offset(scanner) + Getting its TeX width would simply require + synctex_node_box_width(node)*synctex_scanner_magnification(scanner) + but direct methods are available for that below. + */ + int synctex_scanner_x_offset(synctex_scanner_p scanner); + int synctex_scanner_y_offset(synctex_scanner_p scanner); + float synctex_scanner_magnification(synctex_scanner_p scanner); + + /** + * ## Browsing the nodes + * parent, child and sibling are standard names for tree nodes. + * The parent is one level higher, + * the child is one level deeper, + * and the sibling is at the same level. + * A node and its sibling have the same parent. + * A node is the parent of its children. + * A node is either the child of its parent, + * or belongs to the sibling chain of its parent's child. + * The sheet or form of a node is the topmost ancestor, + * it is of type sheet or form. + * The next node is either the child, the sibling or the parent's sibling, + * unless the parent is a sheet, a form or NULL. + * This allows to navigate through all the nodes of a given sheet node: + * + * synctex_node_p node = sheet; + * while((node = synctex_node_next(node))) { + * // do something with node + * } + * + * With synctex_sheet_content and synctex_form_content, + * you can retrieve the sheet node given the page + * or form tag. + * The page is 1 based, according to TeX standards. + * Conversely synctex_node_parent_sheet or + * synctex_node_parent_form allows to retrieve + * the sheet or the form containing a given node. + * Notice that a node is not contained in a sheet + * and a form at the same time. + * Some nodes are not contained in either (handles). + */ + + synctex_node_p synctex_node_parent(synctex_node_p node); + synctex_node_p synctex_node_parent_sheet(synctex_node_p node); + synctex_node_p synctex_node_parent_form(synctex_node_p node); + synctex_node_p synctex_node_child(synctex_node_p node); + synctex_node_p synctex_node_last_child(synctex_node_p node); + synctex_node_p synctex_node_sibling(synctex_node_p node); + synctex_node_p synctex_node_last_sibling(synctex_node_p node); + synctex_node_p synctex_node_arg_sibling(synctex_node_p node); + synctex_node_p synctex_node_next(synctex_node_p node); + + /** + * Top level entry points. + * The scanner owns a list of sheet siblings and + * a list of form siblings. + * Sheets or forms have one child which is a box: + * theie contents. + * - argument page: 1 based sheet page number. + * - argument tag: 1 based form tag number. + */ + synctex_node_p synctex_sheet(synctex_scanner_p scanner,int page); + synctex_node_p synctex_sheet_content(synctex_scanner_p scanner,int page); + synctex_node_p synctex_form(synctex_scanner_p scanner,int tag); + synctex_node_p synctex_form_content(synctex_scanner_p scanner,int tag); + + /* This is primarily used for debugging purpose. + * The second one logs information for the node and recursively displays information for its next node */ + void synctex_node_log(synctex_node_p node); + void synctex_node_display(synctex_node_p node); + + /* For quite all nodes, horizontal, vertical coordinates, and width. + * These are expressed in TeX small points coordinates, with origin at the top left corner. + */ + int synctex_node_h(synctex_node_p node); + int synctex_node_v(synctex_node_p node); + int synctex_node_width(synctex_node_p node); + int synctex_node_height(synctex_node_p node); + int synctex_node_depth(synctex_node_p node); + + /* For all nodes, dimensions of the enclosing box. + * These are expressed in TeX small points coordinates, with origin at the top left corner. + * A box is enclosing itself. + */ + int synctex_node_box_h(synctex_node_p node); + int synctex_node_box_v(synctex_node_p node); + int synctex_node_box_width(synctex_node_p node); + int synctex_node_box_height(synctex_node_p node); + int synctex_node_box_depth(synctex_node_p node); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/org/elpa/pdf-tools-20230404.327/build/server/synctex_parser_advanced.h b/org/elpa/pdf-tools-20230404.327/build/server/synctex_parser_advanced.h new file mode 100644 index 0000000..95c2ac1 --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/build/server/synctex_parser_advanced.h @@ -0,0 +1,554 @@ +/* + Copyright (c) 2008-2017 jerome DOT laurens AT u-bourgogne DOT fr + + This file is part of the __SyncTeX__ package. + + [//]: # (Latest Revision: Sun Oct 15 15:09:55 UTC 2017) + [//]: # (Version: 1.21) + + See `synctex_parser_readme.md` for more details + + ## License + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE + + Except as contained in this notice, the name of the copyright holder + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization from the copyright holder. + */ + +#include "synctex_parser.h" +#include "synctex_parser_utils.h" + +#ifndef __SYNCTEX_PARSER_PRIVATE__ +# define __SYNCTEX_PARSER_PRIVATE__ + +#ifdef __cplusplus +extern "C" { +#endif + /* Reminder that the argument must not be NULL */ + typedef synctex_node_p synctex_non_null_node_p; + + /* Each node of the tree, except the scanner itself belongs to a class. + * The class object is just a struct declaring the owning scanner + * This is a pointer to the scanner as root of the tree. + * The type is used to identify the kind of node. + * The class declares pointers to a creator and a destructor method. + * The log and display fields are used to log and display the node. + * display will also display the child, sibling and parent sibling. + * parent, child and sibling are used to navigate the tree, + * from TeX box hierarchy point of view. + * The friend field points to a method which allows to navigate from friend to friend. + * A friend is a node with very close tag and line numbers. + * Finally, the info field point to a method giving the private node info offset. + */ + + /** + * These are the masks for the synctex node types. + * int's are 32 bits at least. + */ + enum { + synctex_shift_root, + synctex_shift_no_root, + synctex_shift_void, + synctex_shift_no_void, + synctex_shift_box, + synctex_shift_no_box, + synctex_shift_proxy, + synctex_shift_no_proxy, + synctex_shift_h, + synctex_shift_v + }; + enum { + synctex_mask_root = 1, + synctex_mask_no_root = synctex_mask_root<<1, + synctex_mask_void = synctex_mask_no_root<<1, + synctex_mask_no_void = synctex_mask_void<<1, + synctex_mask_box = synctex_mask_no_void<<1, + synctex_mask_no_box = synctex_mask_box<<1, + synctex_mask_proxy = synctex_mask_no_box<<1, + synctex_mask_no_proxy = synctex_mask_proxy<<1, + synctex_mask_h = synctex_mask_no_proxy<<1, + synctex_mask_v = synctex_mask_h<<1, + }; + enum { + synctex_mask_non_void_hbox = synctex_mask_no_void + | synctex_mask_box + | synctex_mask_h, + synctex_mask_non_void_vbox = synctex_mask_no_void + | synctex_mask_box + | synctex_mask_v + }; + typedef enum { + synctex_node_mask_sf = + synctex_mask_root + |synctex_mask_no_void + |synctex_mask_no_box + |synctex_mask_no_proxy, + synctex_node_mask_vbox = + synctex_mask_no_root + |synctex_mask_no_void + |synctex_mask_box + |synctex_mask_no_proxy + |synctex_mask_v, + synctex_node_mask_hbox = + synctex_mask_no_root + |synctex_mask_no_void + |synctex_mask_box + |synctex_mask_no_proxy + |synctex_mask_h, + synctex_node_mask_void_vbox = + synctex_mask_no_root + |synctex_mask_void + |synctex_mask_box + |synctex_mask_no_proxy + |synctex_mask_v, + synctex_node_mask_void_hbox = + synctex_mask_no_root + |synctex_mask_void + |synctex_mask_box + |synctex_mask_no_proxy + |synctex_mask_h, + synctex_node_mask_vbox_proxy = + synctex_mask_no_root + |synctex_mask_no_void + |synctex_mask_box + |synctex_mask_proxy + |synctex_mask_v, + synctex_node_mask_hbox_proxy = + synctex_mask_no_root + |synctex_mask_no_void + |synctex_mask_box + |synctex_mask_proxy + |synctex_mask_h, + synctex_node_mask_nvnn = + synctex_mask_no_root + |synctex_mask_void + |synctex_mask_no_box + |synctex_mask_no_proxy, + synctex_node_mask_input = + synctex_mask_root + |synctex_mask_void + |synctex_mask_no_box + |synctex_mask_no_proxy, + synctex_node_mask_proxy = + synctex_mask_no_root + |synctex_mask_void + |synctex_mask_no_box + |synctex_mask_proxy + } synctex_node_mask_t; + + enum { + /* input */ + synctex_tree_sibling_idx = 0, + synctex_tree_s_input_max = 1, + /* All */ + synctex_tree_s_parent_idx = 1, + synctex_tree_sp_child_idx = 2, + synctex_tree_spc_friend_idx = 3, + synctex_tree_spcf_last_idx = 4, + synctex_tree_spcfl_vbox_max = 5, + /* hbox supplement */ + synctex_tree_spcfl_next_hbox_idx = 5, + synctex_tree_spcfln_hbox_max = 6, + /* hbox proxy supplement */ + synctex_tree_spcfln_target_idx = 6, + synctex_tree_spcflnt_proxy_hbox_max = 7, + /* vbox proxy supplement */ + synctex_tree_spcfl_target_idx = 5, + synctex_tree_spcflt_proxy_vbox_max = 6, + /* spf supplement*/ + synctex_tree_sp_friend_idx = 2, + synctex_tree_spf_max = 3, + /* box boundary supplement */ + synctex_tree_spf_arg_sibling_idx = 3, + synctex_tree_spfa_max = 4, + /* proxy supplement */ + synctex_tree_spf_target_idx = 3, + synctex_tree_spft_proxy_max = 4, + /* last proxy supplement */ + synctex_tree_spfa_target_idx = 4, + synctex_tree_spfat_proxy_last_max = 5, + /* sheet supplement */ + synctex_tree_s_child_idx = 1, + synctex_tree_sc_next_hbox_idx = 2, + synctex_tree_scn_sheet_max = 3, + /* form supplement */ + synctex_tree_sc_target_idx = 2, + synctex_tree_sct_form_max = 3, + /* spct */ + synctex_tree_spc_target_idx = 3, + synctex_tree_spct_handle_max = 4, + }; + + enum { + /* input */ + synctex_data_input_tag_idx = 0, + synctex_data_input_line_idx = 1, + synctex_data_input_name_idx = 2, + synctex_data_input_tln_max = 3, + /* sheet */ + synctex_data_sheet_page_idx = 0, + synctex_data_p_sheet_max = 1, + /* form */ + synctex_data_form_tag_idx = 0, + synctex_data_t_form_max = 1, + /* tlchv */ + synctex_data_tag_idx = 0, + synctex_data_line_idx = 1, + synctex_data_column_idx = 2, + synctex_data_h_idx = 3, + synctex_data_v_idx = 4, + synctex_data_tlchv_max = 5, + /* tlchvw */ + synctex_data_width_idx = 5, + synctex_data_tlchvw_max = 6, + /* box */ + synctex_data_height_idx = 6, + synctex_data_depth_idx = 7, + synctex_data_box_max = 8, + /* hbox supplement */ + synctex_data_mean_line_idx = 8, + synctex_data_weight_idx = 9, + synctex_data_h_V_idx = 10, + synctex_data_v_V_idx = 11, + synctex_data_width_V_idx = 12, + synctex_data_height_V_idx = 13, + synctex_data_depth_V_idx = 14, + synctex_data_hbox_max = 15, + /* ref */ + synctex_data_ref_tag_idx = 0, + synctex_data_ref_h_idx = 1, + synctex_data_ref_v_idx = 2, + synctex_data_ref_thv_max = 3, + /* proxy */ + synctex_data_proxy_h_idx = 0, + synctex_data_proxy_v_idx = 1, + synctex_data_proxy_hv_max = 2, + /* handle */ + synctex_data_handle_w_idx = 0, + synctex_data_handle_w_max = 1, + }; + + /* each synctex node has a class */ + typedef struct synctex_class_t synctex_class_s; + typedef synctex_class_s * synctex_class_p; + + + /* synctex_node_p is a pointer to a node + * synctex_node_s is the target of the synctex_node_p pointer + * It is a pseudo object oriented program. + * class is a pointer to the class object the node belongs to. + * implementation is meant to contain the private data of the node + * basically, there are 2 kinds of information: navigation information and + * synctex information. Both will depend on the type of the node, + * thus different nodes will have different private data. + * There is no inheritancy overhead. + */ + typedef union { + synctex_node_p as_node; + int as_integer; + char * as_string; + void * as_pointer; + } synctex_data_u; + typedef synctex_data_u * synctex_data_p; + +# if defined(SYNCTEX_USE_CHARINDEX) + typedef unsigned int synctex_charindex_t; + synctex_charindex_t synctex_node_charindex(synctex_node_p node); + typedef synctex_charindex_t synctex_lineindex_t; + synctex_lineindex_t synctex_node_lineindex(synctex_node_p node); + synctex_node_p synctex_scanner_handle(synctex_scanner_p scanner); +# define SYNCTEX_DECLARE_CHARINDEX \ + synctex_charindex_t char_index;\ + synctex_lineindex_t line_index; +# define SYNCTEX_DECLARE_CHAR_OFFSET \ + synctex_charindex_t charindex_offset; +# else +# define SYNCTEX_DECLARE_CHARINDEX +# define SYNCTEX_DECLARE_CHAR_OFFSET +# endif + struct synctex_node_t { + SYNCTEX_DECLARE_CHARINDEX + synctex_class_p class_; +#ifdef DEBUG + synctex_data_u data[22]; +#else + synctex_data_u data[1]; +#endif + }; + + typedef synctex_node_p * synctex_node_r; + + typedef struct { + int h; + int v; + } synctex_point_s; + + typedef synctex_point_s * synctex_point_p; + + typedef struct { + synctex_point_s min; /* top left */ + synctex_point_s max; /* bottom right */ + } synctex_box_s; + + typedef synctex_box_s * synctex_box_p; + /** + * These are the types of the synctex nodes. + * No need to use them but the compiler needs them here. + * There are 3 kinds of nodes. + * - primary nodes + * - proxies + * - handles + * Primary nodes are created at parse time + * of the synctex file. + * Proxies are used to support pdf forms. + * The ref primary nodes are replaced by a tree + * of proxy nodes which duplicate the tree of primary + * nodes available in the referred form. + * Roughly speaking, the primary nodes of the form + * know what to display, the proxy nodes know where. + * Handles are used in queries. They point to either + * primary nodes or proxies. + */ + typedef enum { + synctex_node_type_none = 0, + synctex_node_type_input, + synctex_node_type_sheet, + synctex_node_type_form, + synctex_node_type_ref, + synctex_node_type_vbox, + synctex_node_type_void_vbox, + synctex_node_type_hbox, + synctex_node_type_void_hbox, + synctex_node_type_kern, + synctex_node_type_glue, + synctex_node_type_rule, + synctex_node_type_math, + synctex_node_type_boundary, + synctex_node_type_box_bdry, + synctex_node_type_proxy, + synctex_node_type_proxy_last, + synctex_node_type_proxy_vbox, + synctex_node_type_proxy_hbox, + synctex_node_type_handle, + synctex_node_number_of_types + } synctex_node_type_t; + /* synctex_node_type gives the type of a given node, + * synctex_node_isa gives the same information as a human readable text. */ + synctex_node_type_t synctex_node_type(synctex_node_p node); + const char * synctex_node_isa(synctex_node_p node); + + synctex_node_type_t synctex_node_target_type(synctex_node_p node); + + synctex_node_type_t synctex_node_type(synctex_node_p node); + const char * synctex_node_isa(synctex_node_p node); + + void synctex_node_log(synctex_node_p node); + void synctex_node_display(synctex_node_p node); + + /* Given a node, access to the location in the synctex file where it is defined. + */ + + int synctex_node_form_tag(synctex_node_p node); + + int synctex_node_weight(synctex_node_p node); + int synctex_node_child_count(synctex_node_p node); + + int synctex_node_h(synctex_node_p node); + int synctex_node_v(synctex_node_p node); + int synctex_node_width(synctex_node_p node); + + int synctex_node_box_h(synctex_node_p node); + int synctex_node_box_v(synctex_node_p node); + int synctex_node_box_width(synctex_node_p node); + int synctex_node_box_height(synctex_node_p node); + int synctex_node_box_depth(synctex_node_p node); + + int synctex_node_hbox_h(synctex_node_p node); + int synctex_node_hbox_v(synctex_node_p node); + int synctex_node_hbox_width(synctex_node_p node); + int synctex_node_hbox_height(synctex_node_p node); + int synctex_node_hbox_depth(synctex_node_p node); + + synctex_scanner_p synctex_scanner_new(void); + synctex_node_p synctex_node_new(synctex_scanner_p scanner,synctex_node_type_t type); + + /** + * Scanner display switcher getter. + * If the switcher is 0, synctex_node_display is disabled. + * If the switcher is <0, synctex_node_display has no limit. + * If the switcher is >0, only the first switcher (as number) nodes are displayed. + * - parameter: a scanner + * - returns: an integer + */ + int synctex_scanner_display_switcher(synctex_scanner_p scanR); + void synctex_scanner_set_display_switcher(synctex_scanner_p scanR, int switcher); + + /** + * Iterator is the structure used to traverse + * the answer to client queries. + * First answers are the best matches, according + * to criteria explained below. + * Next answers are not ordered. + * Objects are handles to nodes in the synctex node tree starting at scanner. + */ + typedef struct synctex_iterator_t synctex_iterator_s; + typedef synctex_iterator_s * synctex_iterator_p; + + /** + * Designated creator for a display query, id est, + * forward navigation from source to output. + * Returns NULL if the query has no answer. + * Code example: + * synctex_iterator_p iterator = NULL; + * if ((iterator = synctex_iterator_new_display(...)) { + * synctex_node_p node = NULL; + * while((node = synctex_iterator_next_result(iterator))) { + * do something with node... + * } + */ + synctex_iterator_p synctex_iterator_new_display(synctex_scanner_p scanner,const char * name,int line,int column, int page_hint); + /** + * Designated creator for an edit query, id est, + * backward navigation from output to source. + * Code example: + * synctex_iterator_p iterator = NULL; + * if ((iterator = synctex_iterator_new_edit(...)) { + * synctex_node_p node = NULL; + * while((node = synctex_iterator_next_result(iterator))) { + * do something with node... + * } + */ + synctex_iterator_p synctex_iterator_new_edit(synctex_scanner_p scanner,int page,float h,float v); + /** + * Free all the resources. + * - argument iterator: the object to free... + * You should free the iterator before the scanner + * owning the nodes it iterates with. + */ + void synctex_iterator_free(synctex_iterator_p iterator); + /** + * Whether the iterator actually points to an object. + * - argument iterator: the object to iterate on... + */ + synctex_bool_t synctex_iterator_has_next(synctex_iterator_p iterator); + /** + * Returns the pointed object and advance the cursor + * to the next object. Returns NULL and does nothing + * if the end has already been reached. + * - argument iterator: the object to iterate on... + */ + synctex_node_p synctex_iterator_next_result(synctex_iterator_p iterator); + /** + * Reset the cursor position to the first result. + * - argument iterator: the object to iterate on... + */ + int synctex_iterator_reset(synctex_iterator_p iterator); + /** + * The number of objects left for traversal. + * - argument iterator: the object to iterate on... + */ + int synctex_iterator_count(synctex_iterator_p iterator); + + /** + * The target of the node, either a handle or a proxy. + */ + synctex_node_p synctex_node_target(synctex_node_p node); + +#ifndef SYNCTEX_NO_UPDATER + /* The main synctex updater object. + * This object is used to append information to the synctex file. + * Its implementation is considered private. + * It is used by the synctex command line tool to take into account modifications + * that could occur while postprocessing files by dvipdf like filters. + */ + typedef struct synctex_updater_t synctex_updater_s; + typedef synctex_updater_s * synctex_updater_p; + + /* Designated initializer. + * Once you are done with your whole job, + * free the updater */ + synctex_updater_p synctex_updater_new_with_output_file(const char * output, const char * directory); + + /* Use the next functions to append records to the synctex file, + * no consistency tests made on the arguments */ + void synctex_updater_append_magnification(synctex_updater_p updater, char * magnification); + void synctex_updater_append_x_offset(synctex_updater_p updater, char * x_offset); + void synctex_updater_append_y_offset(synctex_updater_p updater, char * y_offset); + + /* You MUST free the updater, once everything is properly appended */ + void synctex_updater_free(synctex_updater_p updater); +#endif + +#if defined(SYNCTEX_DEBUG) +# include "assert.h" +# define SYNCTEX_ASSERT assert +#else +# define SYNCTEX_ASSERT(UNUSED) +#endif + +#if defined(SYNCTEX_TESTING) +#warning TESTING IS PROHIBITED +#if __clang__ +#define __PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS \ +_Pragma("clang diagnostic push") \ +_Pragma("clang diagnostic ignored \"-Wformat-extra-args\"") + +#define __PRAGMA_POP_NO_EXTRA_ARG_WARNINGS _Pragma("clang diagnostic pop") +#else +#define __PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS +#define __PRAGMA_POP_NO_EXTRA_ARG_WARNINGS +#endif + +# define SYNCTEX_TEST_BODY(counter, condition, desc, ...) \ + do { \ + __PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS \ + if (!(condition)) { \ + ++counter; \ + printf("**** Test failed: %s\nfile %s\nfunction %s\nline %i\n",#condition,__FILE__,__FUNCTION__,__LINE__); \ + printf((desc), ##__VA_ARGS__); \ + } \ + __PRAGMA_POP_NO_EXTRA_ARG_WARNINGS \ + } while(0) + +# define SYNCTEX_TEST_PARAMETER(counter, condition) SYNCTEX_TEST_BODY(counter, (condition), "Invalid parameter not satisfying: %s", #condition) + + int synctex_test_input(synctex_scanner_p scanner); + int synctex_test_proxy(synctex_scanner_p scanner); + int synctex_test_tree(synctex_scanner_p scanner); + int synctex_test_page(synctex_scanner_p scanner); + int synctex_test_handle(synctex_scanner_p scanner); + int synctex_test_display_query(synctex_scanner_p scanner); + int synctex_test_charindex(); + int synctex_test_sheet_1(); + int synctex_test_sheet_2(); + int synctex_test_sheet_3(); + int synctex_test_form(); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/org/elpa/pdf-tools-20230404.327/build/server/synctex_parser_local.h b/org/elpa/pdf-tools-20230404.327/build/server/synctex_parser_local.h new file mode 100644 index 0000000..b53439f --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/build/server/synctex_parser_local.h @@ -0,0 +1,3 @@ +#include +#define printf(fmt, args...) (fprintf (stderr, (fmt), ## args)) +#define SYNCTEX_INLINE diff --git a/org/elpa/pdf-tools-20230404.327/build/server/synctex_parser_readme.txt b/org/elpa/pdf-tools-20230404.327/build/server/synctex_parser_readme.txt new file mode 100644 index 0000000..4a25b58 --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/build/server/synctex_parser_readme.txt @@ -0,0 +1,204 @@ +This file is part of the SyncTeX package. + +Please refer to synctex_parser_readme.md + +The Synchronization TeXnology named SyncTeX is a new feature +of recent TeX engines designed by Jerome Laurens. +It allows to synchronize between input and output, which means to +navigate from the source document to the typeset material and vice versa. +More information on http://itexmac2.sourceforge.net/SyncTeX.html + +This package is mainly for developers, it mainly contains the following files: + +synctex_parser_readme.txt +synctex_parser_version.txt +synctex_parser_utils.c +synctex_parser_utils.h +synctex_parser_local.h +synctex_parser_private.h +synctex_parser.h +synctex_parser.c + +The file you are reading contains more information about the SyncTeX parser history. + +In order to support SyncTeX in a viewer, it is sufficient to include +in the source the files synctex_parser.h and synctex_parser.c. +The synctex parser usage is described in synctex_parser.h header file. + +The other files are used by tex engines or by the synctex command line utility: + +ChangeLog +README.txt +am +man1 +man5 +synctex-common.h +synctex-convert.sh +synctex-e-mem.ch0 +synctex-e-mem.ch1 +synctex-e-rec.ch0 +synctex-e-rec.ch1 +synctex-etex.h +synctex-mem.ch0 +synctex-mem.ch1 +synctex-mem.ch2 +synctex-pdf-rec.ch2 +synctex-pdftex.h +synctex-rec.ch0 +synctex-rec.ch1 +synctex-rec.ch2 +synctex-tex.h +synctex-xe-mem.ch2 +synctex-xe-rec.ch2 +synctex-xe-rec.ch3 +synctex-xetex.h +synctex.c +synctex.defines +synctex.h +synctex_main.c +tests + + +Version: +-------- +This is version 1, which refers to the synctex output file format. +The files are identified by a build number. +In order to help developers to automatically manage the version and build numbers +and download the parser only when necessary, the synctex_parser.version +is an ASCII text file just containing the current version and build numbers. + +History: +-------- +1.1: Thu Jul 17 09:28:13 UTC 2008 +- First official version available in TeXLive 2008 DVD. + Unfortunately, the backwards synchronization is not working properly mainly for ConTeXt users, see below. +1.2: Tue Sep 2 10:28:32 UTC 2008 +- Correction for ConTeXt support in the edit query. + The previous method was assuming that TeX boxes do not overlap, + which is reasonable for LaTeX but not for ConTeXt. + This assumption is no longer considered. +1.3: Fri Sep 5 09:39:57 UTC 2008 +- Local variable "read" renamed to "already_read" to avoid conflicts. +- "inline" compiler directive renamed to "SYNCTEX_INLINE" for code support and maintenance +- _synctex_error cannot be inlined due to variable arguments (thanks Christiaan Hofman) +- Correction in the display query, extra boundary nodes are used for a more precise forwards synchronization +1.4: Fri Sep 12 08:12:34 UTC 2008 +- For an unknown reason, the previous version was not the real 1.3 (as used in iTeXMac2 build 747). + As a consequence, a crash was observed. +- Some typos are fixed. +1.6: Mon Nov 3 20:20:02 UTC 2008 +- The bug that prevented synchronization with compressed files on windows has been fixed. +- New interface to allow system specific customization. +- Note that some APIs have changed. +1.8: Mer 8 jul 2009 11:32:38 UTC +Note that version 1.7 was delivered privately. +- bug fix: synctex was causing a memory leak in pdftex and xetex, thus some processing speed degradation +- bug fix: the synctex command line tool was broken when updating a .synctex file +- enhancement: better accuracy of the synchronization process +- enhancement: the pdf output file and the associated .synctex file no longer need to live in the same directory. + The new -d option of the synctex command line tool manages this situation. + This is handy when using something like tex -output-directory=DIR ... +1.9: Wed Nov 4 11:52:35 UTC 2009 +- Various typo fixed +- OutputDebugString replaced by OutputDebugStringA to deliberately disable unicode preprocessing +- New conditional created because OutputDebugStringA is only available since Windows 2K professional +1.10: Sun Jan 10 10:12:32 UTC 2010 +- Bug fix in synctex_parser.c to solve a synchronization problem with amsmath's gather environment. + Concerns the synctex tool. +1.11: Sun Jan 17 09:12:31 UTC 2010 +- Bug fix in synctex_parser.c, function synctex_node_box_visible_v: 'x' replaced by 'y'. + Only 3rd party tools are concerned. +1.12: Mon Jul 19 21:52:10 UTC 2010 +- Bug fix in synctex_parser.c, function __synctex_open: the io_mode was modified even in case of a non zero return, +causing a void .synctex.gz file to be created even if it was not expected. Reported by Marek Kasik concerning a bug on evince. +1.13: Fri Mar 11 07:39:12 UTC 2011 +- Bug fix in synctex_parser.c, better synchronization as suggested by Jan Sundermeyer (near line 3388). +- Stronger code design in synctex_parser_utils.c, function _synctex_get_name (really neutral behavior). + Only 3rd party tools are concerned. +1.14: Fri Apr 15 19:10:57 UTC 2011 +- taking output_directory into account +- Replaced FOPEN_WBIN_MODE by FOPEN_W_MODE when opening the text version of the .synctex file. +- Merging with LuaTeX's version of synctex.c +1.15: Fri Jun 10 14:10:17 UTC 2011 +This concerns the synctex command line tool and 3rd party developers. +TeX and friends are not concerned by these changes. +- Bug fixed in _synctex_get_io_mode_name, sometimes the wrong mode was returned +- Support for LuaTeX convention of './' file prefixing +1.16: Tue Jun 14 08:23:30 UTC 2011 +This concerns the synctex command line tool and 3rd party developers. +TeX and friends are not concerned by these changes. +- Better forward search (thanks Jose Alliste) +- Support for LuaTeX convention of './' file prefixing now for everyone, not only for Windows +1.17: Fri Oct 14 08:15:16 UTC 2011 +This concerns the synctex command line tool and 3rd party developers. +TeX and friends are not concerned by these changes. +- synctex_parser.c: cosmetic changes to enhance code readability +- Better forward synchronization. + The problem occurs for example with LaTeX \item command. + The fact is that this command creates nodes at parse time but these nodes are used only + after the text material of the \item is displayed on the page. The consequence is that sometimes, + forward synchronization spots an irrelevant point from the point of view of the editing process. + This was due to some very basic filtering policy, where a somehow arbitrary choice was made when + many different possibilities where offered for synchronisation. + Now, forward synchronization prefers nodes inside an hbox with as many acceptable spots as possible. + This is achieved with the notion of mean line and node weight. +- Adding support for the new file naming convention with './' + + function synctex_ignore_leading_dot_slash_in_path replaces synctex_ignore_leading_dot_slash + + function _synctex_is_equivalent_file_name is more permissive + Previously, the function synctex_scanner_get_tag would give an answer only when + the given file name was EXACTLY one of the file names listed in the synctex file. + The we added some changes accepting for example 'foo.tex' instead of './foo.tex'. + Now we have an even looser policy for dealing with file names. + If the given file name does not match exactly one the file names of the synctex file, + then we try to match the base names. If there is only one match of the base names, + then it is taken as a match for the whole names. + The base name is defined as following: + ./foo => foo + /my///.////foo => foo + /foo => /foo + /my//.foo => /my//.foo +1.17: Tue Mar 13 10:10:03 UTC 2012 +- minor changes, no version changes +- syntax man pages are fixed as suggested by M. Shimata + see mail to tex-live@tug.org titled "syntax.5 has many warnings from groff" and "syntax.1 use invalid macro for mdoc" +1.17: Tue Jan 14 09:55:00 UTC 2014 +- fixed a segfault, from Sebastian Ramacher +1.17: Mon Aug 04 +- fixed a memory leak +1.18: Thu Jun 25 11:36:05 UTC 2015 +- nested sheets now fully supported (does it make sense in TeX) +- cosmetic changes: uniform indentation +- suppression of warnings, mainly long/int ones. In short, zlib likes ints when size_t likes longs. +- CLI synctex tool can build out of TeXLive (modulo appropriate options passed to the compiler) +1.19: Thu Mar 9 21:26:27 UTC 2017 +- the nested sheets patch was not a good solution. + It has been moved from the parser to the engine. + See the synctex.c source file for detailed explanations. +- there is a new synctex format specification. + We can see that a .synctex file can contain many times + the same vertical position because many objects belong + to the same line. When the options read -synctex=±2 or more, + a very basic compression algorithm is used: + if synctex is about write the same number then it writes + an = sign instead. This saves approximately 10% of the + synctex output file, either compressed or not. + The new synctex parser has been updated accordingly. + Actual tex frontend won't see any difference with the + TeX engines that include this new feature. + Frontends with the new parser won't see any difference + with the older TeX engines. + Frontends with the new parser will only see a difference + with new TeX engines if -synctex=±2 or more is used. + +Acknowledgments: +---------------- +The author received useful remarks from the pdfTeX developers, especially Hahn The Thanh, +and significant help from XeTeX developer Jonathan Kew + +Nota Bene: +---------- +If you include or use a significant part of the synctex package into a software, +I would appreciate to be listed as contributor and see "SyncTeX" highlighted. + +Copyright (c) 2008-2014 jerome DOT laurens AT u-bourgogne DOT fr + diff --git a/org/elpa/pdf-tools-20230404.327/build/server/synctex_parser_utils.c b/org/elpa/pdf-tools-20230404.327/build/server/synctex_parser_utils.c new file mode 100644 index 0000000..5be3d09 --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/build/server/synctex_parser_utils.c @@ -0,0 +1,570 @@ +/* + Copyright (c) 2008-2017 jerome DOT laurens AT u-bourgogne DOT fr + + This file is part of the __SyncTeX__ package. + + [//]: # (Latest Revision: Fri Jul 14 16:20:41 UTC 2017) + [//]: # (Version: 1.21) + + See `synctex_parser_readme.md` for more details + + ## License + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE + + Except as contained in this notice, the name of the copyright holder + shall not be used in advertising or otherwise to promote the sale, + use or other dealings in this Software without prior written + authorization from the copyright holder. + +*/ + +/* In this file, we find all the functions that may depend on the operating system. */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#if defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) || defined(__WINDOWS__) +#define SYNCTEX_WINDOWS 1 +#endif + +#if defined(__OS2__) +#define SYNCTEX_OS2 1 +#endif + +#if defined(_WIN32) +#define SYNCTEX_RECENT_WINDOWS 1 +#endif + +#ifdef SYNCTEX_WINDOWS +#include +#include /* Use shlwapi.lib */ +#endif + +void *_synctex_malloc(size_t size) { + void * ptr = malloc(size); + if(ptr) { + memset(ptr,0, size);/* ensures null termination of strings */ + } + return (void *)ptr; +} + +void _synctex_free(void * ptr) { + if (ptr) { + free(ptr); + } +} + +#if !defined(_WIN32) +# include +#endif + +int _synctex_log(int level, const char * prompt, const char * reason,va_list arg) { + int result; +# ifdef SYNCTEX_RECENT_WINDOWS + {/* This code is contributed by William Blum. + As it does not work on some older computers, + the _WIN32 conditional here is replaced with a SYNCTEX_RECENT_WINDOWS one. + According to http://msdn.microsoft.com/en-us/library/aa363362(VS.85).aspx + Minimum supported client Windows 2000 Professional + Minimum supported server Windows 2000 Server + People running Windows 2K standard edition will not have OutputDebugStringA. + JL.*/ + char *buff; + size_t len; + OutputDebugStringA(prompt); + len = _vscprintf(reason, arg) + 1; + buff = (char*)malloc( len * sizeof(char) ); + result = vsprintf(buff, reason, arg) +strlen(prompt); + OutputDebugStringA(buff); + OutputDebugStringA("\n"); + free(buff); + } +# elif SYNCTEX_USE_SYSLOG + char * buffer1 = NULL; + char * buffer2 = NULL; + openlog ("SyncTeX", LOG_CONS | LOG_PID | LOG_PERROR | LOG_NDELAY, LOG_LOCAL0); + if (vasprintf(&buffer1,reason,arg)>=0 + && asprintf(&buffer2,"%s%s",prompt, buffer1)>=0) { + syslog (level, "%s", buffer2); + result = (int)strlen(buffer2); + } else { + syslog (level, "%s",prompt); + vsyslog(level,reason,arg); + result = (int)strlen(prompt); + } + free(buffer1); + free(buffer2); + closelog(); +# else + FILE * where = level == LOG_ERR? stderr: stdout; + result = fputs(prompt,where); + result += vfprintf(where, reason, arg); + result += fprintf(where,"\n"); +# endif + return result; +} + +int _synctex_error(const char * reason,...) { + va_list arg; + int result; + va_start (arg, reason); +#if defined(SYNCTEX_RECENT_WINDOWS) /* LOG_ERR is not used */ + result = _synctex_log(0, "! SyncTeX Error : ", reason, arg); +#else + result = _synctex_log(LOG_ERR, "! SyncTeX Error : ", reason, arg); +#endif + va_end (arg); + return result; +} + +int _synctex_debug(const char * reason,...) { + va_list arg; + int result; + va_start (arg, reason); +#if defined(SYNCTEX_RECENT_WINDOWS) /* LOG_DEBUG is not used */ + result = _synctex_log(0, "! SyncTeX Error : ", reason, arg); +#else + result = _synctex_log(LOG_DEBUG, "! SyncTeX Error : ", reason, arg); +#endif + va_end (arg); + return result; +} + +/* strip the last extension of the given string, this string is modified! */ +void _synctex_strip_last_path_extension(char * string) { + if(NULL != string){ + char * last_component = NULL; + char * last_extension = NULL; +# if defined(SYNCTEX_WINDOWS) + last_component = PathFindFileName(string); + last_extension = PathFindExtension(string); + if(last_extension == NULL)return; + if(last_component == NULL)last_component = string; + if(last_extension>last_component){/* filter out paths like "my/dir/.hidden" */ + last_extension[0] = '\0'; + } +# else + char * next = NULL; + /* first we find the last path component */ + if(NULL == (last_component = strstr(string,"/"))){ + last_component = string; + } else { + ++last_component; + while((next = strstr(last_component,"/"))){ + last_component = next+1; + } + } +# if defined(SYNCTEX_OS2) + /* On OS2, the '\' is also a path separator. */ + while((next = strstr(last_component,"\\"))){ + last_component = next+1; + } +# endif /* SYNCTEX_OS2 */ + /* then we find the last path extension */ + if((last_extension = strstr(last_component,"."))){ + ++last_extension; + while((next = strstr(last_extension,"."))){ + last_extension = next+1; + } + --last_extension;/* back to the "." */ + if(last_extension>last_component){/* filter out paths like ....my/dir/.hidden"*/ + last_extension[0] = '\0'; + } + } +# endif /* SYNCTEX_WINDOWS */ + } +} + +synctex_bool_t synctex_ignore_leading_dot_slash_in_path(const char ** name_ref) +{ + if (SYNCTEX_IS_DOT((*name_ref)[0]) && SYNCTEX_IS_PATH_SEPARATOR((*name_ref)[1])) { + do { + (*name_ref) += 2; + while (SYNCTEX_IS_PATH_SEPARATOR((*name_ref)[0])) { + ++(*name_ref); + } + } while(SYNCTEX_IS_DOT((*name_ref)[0]) && SYNCTEX_IS_PATH_SEPARATOR((*name_ref)[1])); + return synctex_YES; + } + return synctex_NO; +} + +/* The base name is necessary to deal with the 2011 file naming convention... + * path is a '\0' terminated string + * The return value is the trailing part of the argument, + * just following the first occurrence of the regexp pattern "[^|/|\].[\|/]+".*/ +const char * _synctex_base_name(const char *path) { + const char * ptr = path; + do { + if (synctex_ignore_leading_dot_slash_in_path(&ptr)) { + return ptr; + } + do { + if (!*(++ptr)) { + return path; + } + } while (!SYNCTEX_IS_PATH_SEPARATOR(*ptr)); + } while (*(++ptr)); + return path; +} + +/* Compare two file names, windows is sometimes case insensitive... */ +synctex_bool_t _synctex_is_equivalent_file_name(const char *lhs, const char *rhs) { + /* Remove the leading regex '(\./+)*' in both rhs and lhs */ + synctex_ignore_leading_dot_slash_in_path(&lhs); + synctex_ignore_leading_dot_slash_in_path(&rhs); +next_character: + if (SYNCTEX_IS_PATH_SEPARATOR(*lhs)) {/* lhs points to a path separator */ + if (!SYNCTEX_IS_PATH_SEPARATOR(*rhs)) {/* but not rhs */ + return synctex_NO; + } + ++lhs; + ++rhs; + synctex_ignore_leading_dot_slash_in_path(&lhs); + synctex_ignore_leading_dot_slash_in_path(&rhs); + goto next_character; + } else if (SYNCTEX_IS_PATH_SEPARATOR(*rhs)) {/* rhs points to a path separator but not lhs */ + return synctex_NO; + } else if (SYNCTEX_ARE_PATH_CHARACTERS_EQUAL(*lhs,*rhs)){/* uppercase do not match */ + return synctex_NO; + } else if (!*lhs) {/* lhs is at the end of the string */ + return *rhs ? synctex_NO : synctex_YES; + } else if(!*rhs) {/* rhs is at the end of the string but not lhs */ + return synctex_NO; + } + ++lhs; + ++rhs; + goto next_character; +} + +synctex_bool_t _synctex_path_is_absolute(const char * name) { + if(!strlen(name)) { + return synctex_NO; + } +# if defined(SYNCTEX_WINDOWS) || defined(SYNCTEX_OS2) + if(strlen(name)>2) { + return (name[1]==':' && SYNCTEX_IS_PATH_SEPARATOR(name[2]))?synctex_YES:synctex_NO; + } + return synctex_NO; +# else + return SYNCTEX_IS_PATH_SEPARATOR(name[0])?synctex_YES:synctex_NO; +# endif +} + +/* We do not take care of UTF-8 */ +const char * _synctex_last_path_component(const char * name) { + const char * c = name+strlen(name); + if(c>name) { + if(!SYNCTEX_IS_PATH_SEPARATOR(*c)) { + do { + --c; + if(SYNCTEX_IS_PATH_SEPARATOR(*c)) { + return c+1; + } + } while(c>name); + } + return c;/* the last path component is the void string*/ + } + return c; +} + +int _synctex_copy_with_quoting_last_path_component(const char * src, char ** dest_ref, size_t size) { + if(src && dest_ref) { + const char * lpc; +# define dest (*dest_ref) + dest = NULL; /* Default behavior: no change and success. */ + lpc = _synctex_last_path_component(src); + if(strlen(lpc)) { + if(strchr(lpc,' ') && lpc[0]!='"' && lpc[strlen(lpc)-1]!='"') { + /* We are in the situation where adding the quotes is allowed. */ + /* Time to add the quotes. */ + /* Consistency test: we must have dest+size>dest+strlen(dest)+2 + * or equivalently: strlen(dest)+20) { + char * result = NULL; + ++size; + /* Create the memory storage */ + if(NULL!=(result = (char *)malloc(size))) { + char * dest = result; + va_start (arg, first); + temp = first; + do { + if((size = strlen(temp))>0) { + /* There is something to merge */ + if(dest != strncpy(dest,temp,size)) { + _synctex_error("! _synctex_merge_strings: Copy problem"); + free(result); + result = NULL; + return NULL; + } + dest += size; + } + } while( (temp = va_arg(arg, const char *)) != NULL); + va_end(arg); + dest[0]='\0';/* Terminate the merged string */ + return result; + } + _synctex_error("! _synctex_merge_strings: Memory problem"); + return NULL; + } + return NULL; +} + +/* The purpose of _synctex_get_name is to find the name of the synctex file. + * There is a list of possible filenames from which we return the most recent one and try to remove all the others. + * With two runs of pdftex or xetex we are sure the the synctex file is really the most appropriate. + */ +int _synctex_get_name(const char * output, const char * build_directory, char ** synctex_name_ref, synctex_io_mode_t * io_mode_ref) +{ + if(output && synctex_name_ref && io_mode_ref) { + /* If output is already absolute, we just have to manage the quotes and the compress mode */ + size_t size = 0; + char * synctex_name = NULL; + synctex_io_mode_t io_mode = *io_mode_ref; + const char * base_name = _synctex_last_path_component(output); /* do not free, output is the owner. base name of output*/ + /* Do we have a real base name ? */ + if(strlen(base_name)>0) { + /* Yes, we do. */ + const char * temp = NULL; + char * core_name = NULL; /* base name of output without path extension. */ + char * dir_name = NULL; /* dir name of output */ + char * quoted_core_name = NULL; + char * basic_name = NULL; + char * gz_name = NULL; + char * quoted_name = NULL; + char * quoted_gz_name = NULL; + char * build_name = NULL; + char * build_gz_name = NULL; + char * build_quoted_name = NULL; + char * build_quoted_gz_name = NULL; + struct stat buf; + time_t the_time = 0; + /* Create core_name: let temp point to the dot before the path extension of base_name; + * We start form the \0 terminating character and scan the string upward until we find a dot. + * The leading dot is not accepted. */ + if((temp = strrchr(base_name,'.')) && (size = temp - base_name)>0) { + /* There is a dot and it is not at the leading position */ + if(NULL == (core_name = (char *)malloc(size+1))) { + _synctex_error("! _synctex_get_name: Memory problem 1"); + return -1; + } + if(core_name != strncpy(core_name,base_name,size)) { + _synctex_error("! _synctex_get_name: Copy problem 1"); + free(core_name); + dir_name = NULL; + return -2; + } + core_name[size] = '\0'; + } else { + /* There is no path extension, + * Just make a copy of base_name */ + core_name = _synctex_merge_strings(base_name); + } + /* core_name is properly set up, owned by "self". */ + /* creating dir_name. */ + size = strlen(output)-strlen(base_name); + if(size>0) { + /* output contains more than one path component */ + if(NULL == (dir_name = (char *)malloc(size+1))) { + _synctex_error("! _synctex_get_name: Memory problem"); + free(core_name); + return -1; + } + if(dir_name != strncpy(dir_name,output,size)) { + _synctex_error("! _synctex_get_name: Copy problem"); + free(dir_name); + dir_name = NULL; + free(core_name); + dir_name = NULL; + return -2; + } + dir_name[size] = '\0'; + } + /* dir_name is properly set up. It ends with a path separator, if non void. */ + /* creating quoted_core_name. */ + if(strchr(core_name,' ')) { + quoted_core_name = _synctex_merge_strings("\"",core_name,"\""); + } + /* quoted_core_name is properly set up. */ + if(dir_name &&strlen(dir_name)>0) { + basic_name = _synctex_merge_strings(dir_name,core_name,synctex_suffix,NULL); + if(quoted_core_name && strlen(quoted_core_name)>0) { + quoted_name = _synctex_merge_strings(dir_name,quoted_core_name,synctex_suffix,NULL); + } + } else { + basic_name = _synctex_merge_strings(core_name,synctex_suffix,NULL); + if(quoted_core_name && strlen(quoted_core_name)>0) { + quoted_name = _synctex_merge_strings(quoted_core_name,synctex_suffix,NULL); + } + } + if(!_synctex_path_is_absolute(output) && build_directory && (size = strlen(build_directory))) { + temp = build_directory + size - 1; + if(_synctex_path_is_absolute(temp)) { + build_name = _synctex_merge_strings(build_directory,basic_name,NULL); + if(quoted_core_name && strlen(quoted_core_name)>0) { + build_quoted_name = _synctex_merge_strings(build_directory,quoted_name,NULL); + } + } else { + build_name = _synctex_merge_strings(build_directory,"/",basic_name,NULL); + if(quoted_core_name && strlen(quoted_core_name)>0) { + build_quoted_name = _synctex_merge_strings(build_directory,"/",quoted_name,NULL); + } + } + } + if(basic_name) { + gz_name = _synctex_merge_strings(basic_name,synctex_suffix_gz,NULL); + } + if(quoted_name) { + quoted_gz_name = _synctex_merge_strings(quoted_name,synctex_suffix_gz,NULL); + } + if(build_name) { + build_gz_name = _synctex_merge_strings(build_name,synctex_suffix_gz,NULL); + } + if(build_quoted_name) { + build_quoted_gz_name = _synctex_merge_strings(build_quoted_name,synctex_suffix_gz,NULL); + } + /* All the others names are properly set up... */ + /* retain the most recently modified file */ +# define TEST(FILENAME,COMPRESS_MODE) \ + if(FILENAME) {\ + if (stat(FILENAME, &buf)) { \ + free(FILENAME);\ + FILENAME = NULL;\ + } else if (buf.st_mtime>the_time) { \ + the_time=buf.st_mtime; \ + synctex_name = FILENAME; \ + if (COMPRESS_MODE) { \ + io_mode |= synctex_io_gz_mask; \ + } else { \ + io_mode &= ~synctex_io_gz_mask; \ + } \ + } \ + } + TEST(basic_name,synctex_DONT_COMPRESS); + TEST(gz_name,synctex_COMPRESS); + TEST(quoted_name,synctex_DONT_COMPRESS); + TEST(quoted_gz_name,synctex_COMPRESS); + TEST(build_name,synctex_DONT_COMPRESS); + TEST(build_gz_name,synctex_COMPRESS); + TEST(build_quoted_name,synctex_DONT_COMPRESS); + TEST(build_quoted_gz_name,synctex_COMPRESS); +# undef TEST + /* Free all the intermediate filenames, except the one that will be used as returned value. */ +# define CLEAN_AND_REMOVE(FILENAME) \ + if(FILENAME && (FILENAME!=synctex_name)) {\ + remove(FILENAME);\ + printf("synctex tool info: %s removed\n",FILENAME);\ + free(FILENAME);\ + FILENAME = NULL;\ + } + CLEAN_AND_REMOVE(basic_name); + CLEAN_AND_REMOVE(gz_name); + CLEAN_AND_REMOVE(quoted_name); + CLEAN_AND_REMOVE(quoted_gz_name); + CLEAN_AND_REMOVE(build_name); + CLEAN_AND_REMOVE(build_gz_name); + CLEAN_AND_REMOVE(build_quoted_name); + CLEAN_AND_REMOVE(build_quoted_gz_name); +# undef CLEAN_AND_REMOVE + /* set up the returned values */ + * synctex_name_ref = synctex_name; + /* synctex_name won't always end in .gz, even when compressed. */ + FILE * F = fopen(synctex_name, "r"); + if (F != NULL) { + if (!feof(F) + && 31 == fgetc(F) + && !feof(F) + && 139 == fgetc(F)) { + io_mode = synctex_compress_mode_gz; + } + fclose(F); + } + * io_mode_ref = io_mode; + return 0; + } + return -1;/* bad argument */ + } + return -2; +} + +const char * _synctex_get_io_mode_name(synctex_io_mode_t io_mode) { + static const char * synctex_io_modes[4] = {"r","rb","a","ab"}; + unsigned index = ((io_mode & synctex_io_gz_mask)?1:0) + ((io_mode & synctex_io_append_mask)?2:0);// bug pointed out by Jose Alliste + return synctex_io_modes[index]; +} diff --git a/org/elpa/pdf-tools-20230404.327/build/server/synctex_parser_utils.h b/org/elpa/pdf-tools-20230404.327/build/server/synctex_parser_utils.h new file mode 100644 index 0000000..4dd4e17 --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/build/server/synctex_parser_utils.h @@ -0,0 +1,163 @@ +/* + Copyright (c) 2008-2017 jerome DOT laurens AT u-bourgogne DOT fr + + This file is part of the __SyncTeX__ package. + + [//]: # (Latest Revision: Fri Jul 14 16:20:41 UTC 2017) + [//]: # (Version: 1.21) + + See `synctex_parser_readme.md` for more details + + ## License + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE + +Except as contained in this notice, the name of the copyright holder +shall not be used in advertising or otherwise to promote the sale, +use or other dealings in this Software without prior written +authorization from the copyright holder. + +*/ + +#ifndef SYNCTEX_PARSER_UTILS_H +#define SYNCTEX_PARSER_UTILS_H + +/* The utilities declared here are subject to conditional implementation. + * All the operating system special stuff goes here. + * The problem mainly comes from file name management: path separator, encoding... + */ + +#include "synctex_version.h" + +typedef int synctex_bool_t; +# define synctex_YES (0==0) +# define synctex_NO (0==1) + +# define synctex_ADD_QUOTES -1 +# define synctex_COMPRESS -1 +# define synctex_DONT_ADD_QUOTES 0 +# define synctex_DONT_COMPRESS 0 + +#ifndef __SYNCTEX_PARSER_UTILS__ +# define __SYNCTEX_PARSER_UTILS__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +# if defined(_WIN32) || defined(__OS2__) +# define SYNCTEX_CASE_SENSITIVE_PATH 0 +# define SYNCTEX_IS_PATH_SEPARATOR(c) ('/' == c || '\\' == c) +# else +# define SYNCTEX_CASE_SENSITIVE_PATH 1 +# define SYNCTEX_IS_PATH_SEPARATOR(c) ('/' == c) +# endif + +# if defined(_WIN32) || defined(__OS2__) +# define SYNCTEX_IS_DOT(c) ('.' == c) +# else +# define SYNCTEX_IS_DOT(c) ('.' == c) +# endif + +# if SYNCTEX_CASE_SENSITIVE_PATH +# define SYNCTEX_ARE_PATH_CHARACTERS_EQUAL(left,right) (left != right) +# else +# define SYNCTEX_ARE_PATH_CHARACTERS_EQUAL(left,right) (toupper(left) != toupper(right)) +# endif + +/* This custom malloc functions initializes to 0 the newly allocated memory. + * There is no bzero function on windows. */ +void *_synctex_malloc(size_t size); + +/* To balance _synctex_malloc. + * ptr might be NULL. */ +void _synctex_free(void * ptr); + +/* This is used to log some informational message to the standard error stream. + * On Windows, the stderr stream is not exposed and another method is used. + * The return value is the number of characters printed. */ + int _synctex_error(const char * reason,...); + int _synctex_debug(const char * reason,...); + +/* strip the last extension of the given string, this string is modified! + * This function depends on the OS because the path separator may differ. + * This should be discussed more precisely. */ +void _synctex_strip_last_path_extension(char * string); + +/* Compare two file names, windows is sometimes case insensitive... + * The given strings may differ stricto sensu, but represent the same file name. + * It might not be the real way of doing things. + * The return value is an undefined non 0 value when the two file names are equivalent. + * It is 0 otherwise. */ +synctex_bool_t _synctex_is_equivalent_file_name(const char *lhs, const char *rhs); + +/* Description forthcoming.*/ +synctex_bool_t _synctex_path_is_absolute(const char * name); + +/* Description forthcoming...*/ +const char * _synctex_last_path_component(const char * name); + +/* Description forthcoming...*/ +const char * _synctex_base_name(const char *path); + +/* If the core of the last path component of src is not already enclosed with double quotes ('"') + * and contains a space character (' '), then a new buffer is created, the src is copied and quotes are added. + * In all other cases, no destination buffer is created and the src is not copied. + * 0 on success, which means no error, something non 0 means error, mainly due to memory allocation failure, or bad parameter. + * This is used to fix a bug in the first version of pdftex with synctex (1.40.9) for which names with spaces + * were not managed in a standard way. + * On success, the caller owns the buffer pointed to by dest_ref (is any) and + * is responsible of freeing the memory when done. + * The size argument is the size of the src buffer. On return the dest_ref points to a buffer sized size+2.*/ +int _synctex_copy_with_quoting_last_path_component(const char * src, char ** dest_ref, size_t size); + +/* These are the possible extensions of the synctex file */ +extern const char * synctex_suffix; +extern const char * synctex_suffix_gz; + +typedef unsigned int synctex_io_mode_t; + +typedef enum { + synctex_io_append_mask = 1, + synctex_io_gz_mask = synctex_io_append_mask<<1 +} synctex_io_mode_masks_t; + +typedef enum { + synctex_compress_mode_none = 0, + synctex_compress_mode_gz = 1 +} synctex_compress_mode_t; + +int _synctex_get_name(const char * output, const char * build_directory, char ** synctex_name_ref, synctex_io_mode_t * io_mode_ref); + +/* returns the correct mode required by fopen and gzopen from the given io_mode */ +const char * _synctex_get_io_mode_name(synctex_io_mode_t io_mode); + +synctex_bool_t synctex_ignore_leading_dot_slash_in_path(const char ** name); + +#ifdef __cplusplus +} +#endif + +#endif +#endif /* SYNCTEX_PARSER_UTILS_H */ diff --git a/org/elpa/pdf-tools-20230404.327/build/server/synctex_parser_version.txt b/org/elpa/pdf-tools-20230404.327/build/server/synctex_parser_version.txt new file mode 100644 index 0000000..d2ab029 --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/build/server/synctex_parser_version.txt @@ -0,0 +1 @@ +1.21 diff --git a/org/elpa/pdf-tools-20230404.327/build/server/synctex_version.h b/org/elpa/pdf-tools-20230404.327/build/server/synctex_version.h new file mode 100644 index 0000000..5665ccb --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/build/server/synctex_version.h @@ -0,0 +1,59 @@ +/* +Copyright (c) 2008-2017 jerome DOT laurens AT u-bourgogne DOT fr + +This file is part of the __SyncTeX__ package. + +[//]: # (Latest Revision: Fri Jul 14 16:20:41 UTC 2017) +[//]: # (Version: 1.21) + +See `synctex_parser_readme.md` for more details + +## License + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE + +Except as contained in this notice, the name of the copyright holder +shall not be used in advertising or otherwise to promote the sale, +use or other dealings in this Software without prior written +authorization from the copyright holder. + +## Acknowledgments: + +The author received useful remarks from the __pdfTeX__ developers, especially Hahn The Thanh, +and significant help from __XeTeX__ developer Jonathan Kew. + +## Nota Bene: + +If you include or use a significant part of the __SyncTeX__ package into a software, +I would appreciate to be listed as contributor and see "__SyncTeX__" highlighted. +*/ + +#ifndef __SYNCTEX_VERSION__ +# define __SYNCTEX_VERSION__ + +# define SYNCTEX_VERSION_MAJOR 1 + +# define SYNCTEX_VERSION_STRING "1.21" + +# define SYNCTEX_CLI_VERSION_STRING "1.5" + +#endif diff --git a/org/elpa/pdf-tools-20230404.327/build/server/test/.gitignore b/org/elpa/pdf-tools-20230404.327/build/server/test/.gitignore new file mode 100644 index 0000000..aaedb1f --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/build/server/test/.gitignore @@ -0,0 +1 @@ +.start-vm diff --git a/org/elpa/pdf-tools-20230404.327/build/server/test/docker/.gitignore b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/.gitignore new file mode 100644 index 0000000..d7dc318 --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/.gitignore @@ -0,0 +1,3 @@ +*.Dockerfile +*.build +*.container diff --git a/org/elpa/pdf-tools-20230404.327/build/server/test/docker/lib/run-tests b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/lib/run-tests new file mode 100644 index 0000000..31887bf --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/lib/run-tests @@ -0,0 +1,24 @@ +#!/bin/sh + +PATH="$(dirname "$0")":$PATH + +run_tests_exit_success() +{ + echo "===============================" + echo " Elisp Tests succeeded. :O) " + echo "===============================" + exit 0 +} + +set -e +# Check that install completes successfully +yes-or-enter | ./server/autobuild -i /bin +# Check that re-install skips package installation +yes-or-enter | ./server/autobuild -i /usr/bin | \ + grep -q "Skipping package installation (already installed)" +# Check that lisp tests run correctly, if emacs is installed and available on PATH +echo +if which emacs > /dev/null 2> /dev/null; then + echo "Emacs found installed! Running elisp tests" + make test && run_tests_exit_success +fi diff --git a/org/elpa/pdf-tools-20230404.327/build/server/test/docker/lib/yes-or-enter b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/lib/yes-or-enter new file mode 100644 index 0000000..b19cc5a --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/lib/yes-or-enter @@ -0,0 +1,9 @@ +#!/bin/bash + +# Step over prompts from the package-manager. +if [ -f /etc/arch-release ]; then + yes '' +else + yes +fi + diff --git a/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/Dockerfile.common.in b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/Dockerfile.common.in new file mode 100644 index 0000000..142f062 --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/Dockerfile.common.in @@ -0,0 +1,4 @@ +COPY . /pdf-tools +WORKDIR /pdf-tools +RUN make -s distclean || true +CMD ["sh", "./server/test/docker/lib/run-tests"] diff --git a/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/arch.Dockerfile.in.FAILING b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/arch.Dockerfile.in.FAILING new file mode 100644 index 0000000..a85762b --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/arch.Dockerfile.in.FAILING @@ -0,0 +1,4 @@ +# -*- dockerfile -*- +FROM archlinux:latest +RUN pacman -Syu --noconfirm --noprogressbar +# @TODO: The official Archlinux image does not seem to have any form of shell. Marking this as FAILING. diff --git a/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/centos.Dockerfile.in.FAILING b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/centos.Dockerfile.in.FAILING new file mode 100644 index 0000000..1da2ab8 --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/centos.Dockerfile.in.FAILING @@ -0,0 +1,6 @@ +# -*- dockerfile -*- +FROM centos:centos7 +RUN sed -i -e "s|mirrorlist=|#mirrorlist=|g" /etc/yum.repos.d/CentOS-* +RUN sed -i -e "s|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g" /etc/yum.repos.d/CentOS-* +RUN yum update -y +# @TODO: Since CentOS is no more, do I even want to try and fix this? diff --git a/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/debian-10.Dockerfile.in b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/debian-10.Dockerfile.in new file mode 100644 index 0000000..a2ad6bb --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/debian-10.Dockerfile.in @@ -0,0 +1,6 @@ +# -*- dockerfile -*- +# Debian 10 is known as buster +FROM debian:10 +ARG DEBIAN_FRONTEND=noninteractive +# Need to install make, tzdata here to avoid stupid prompts when running package install via autobuild +RUN apt-get update -y && apt-get install -y make tzdata diff --git a/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/debian-11.Dockerfile.in b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/debian-11.Dockerfile.in new file mode 100644 index 0000000..dae6b6c --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/debian-11.Dockerfile.in @@ -0,0 +1,6 @@ +# -*- dockerfile -*- +# Debian 11 is known as bullseye +FROM debian:11 +ARG DEBIAN_FRONTEND=noninteractive +# Need to install make, tzdata here to avoid stupid prompts when running package install via autobuild +RUN apt-get update -y && apt-get install -y make tzdata diff --git a/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/debian-9.Dockerfile.in b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/debian-9.Dockerfile.in new file mode 100644 index 0000000..b558ade --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/debian-9.Dockerfile.in @@ -0,0 +1,6 @@ +# -*- dockerfile -*- +# Debian 9 is known as stretch +FROM debian:9 +ARG DEBIAN_FRONTEND=noninteractive +# Need to install make, tzdata here to avoid stupid prompts when running package install via autobuild +RUN apt-get update -y && apt-get install -y make tzdata diff --git a/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/emacs-26.Dockerfile.in b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/emacs-26.Dockerfile.in new file mode 100644 index 0000000..088a991 --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/emacs-26.Dockerfile.in @@ -0,0 +1,5 @@ +# -*- dockerfile -*- +FROM silex/emacs:26-ci-cask +ARG DEBIAN_FRONTEND=noninteractive +# Need to install make, tzdata here to avoid stupid prompts when running package install via autobuild +RUN apt-get update -y && apt-get install -y make tzdata diff --git a/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/emacs-27.Dockerfile.in b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/emacs-27.Dockerfile.in new file mode 100644 index 0000000..50cd820 --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/emacs-27.Dockerfile.in @@ -0,0 +1,5 @@ +# -*- dockerfile -*- +FROM silex/emacs:27-ci-cask +ARG DEBIAN_FRONTEND=noninteractive +# Need to install make, tzdata here to avoid stupid prompts when running package install via autobuild +RUN apt-get update -y && apt-get install -y make tzdata diff --git a/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/emacs-28.Dockerfile.in b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/emacs-28.Dockerfile.in new file mode 100644 index 0000000..c6895ac --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/emacs-28.Dockerfile.in @@ -0,0 +1,5 @@ +# -*- dockerfile -*- +FROM silex/emacs:28-ci-cask +ARG DEBIAN_FRONTEND=noninteractive +# Need to install make, tzdata here to avoid stupid prompts when running package install via autobuild +RUN apt-get update -y && apt-get install -y make tzdata diff --git a/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/emacs-29.Dockerfile.in b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/emacs-29.Dockerfile.in new file mode 100644 index 0000000..edbf764 --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/emacs-29.Dockerfile.in @@ -0,0 +1,5 @@ +# -*- dockerfile -*- +FROM silex/emacs:master-ci-cask +ARG DEBIAN_FRONTEND=noninteractive +# Need to install make, tzdata here to avoid stupid prompts when running package install via autobuild +RUN apt-get update -y && apt-get install -y make tzdata diff --git a/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/fedora-34.Dockerfile.in b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/fedora-34.Dockerfile.in new file mode 100644 index 0000000..dbb736e --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/fedora-34.Dockerfile.in @@ -0,0 +1,4 @@ +# -*- dockerfile -*- +FROM fedora:34 +# Need to install make, tzdata here to avoid stupid prompts when running package install via autobuild +RUN dnf update -y && dnf install -y make tzdata diff --git a/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/fedora-35.Dockerfile.in b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/fedora-35.Dockerfile.in new file mode 100644 index 0000000..915cac4 --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/fedora-35.Dockerfile.in @@ -0,0 +1,4 @@ +# -*- dockerfile -*- +FROM fedora:35 +# Need to install make, tzdata here to avoid stupid prompts when running package install via autobuild +RUN dnf update -y && dnf install -y make tzdata diff --git a/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/fedora-36.Dockerfile.in b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/fedora-36.Dockerfile.in new file mode 100644 index 0000000..c36a716 --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/fedora-36.Dockerfile.in @@ -0,0 +1,4 @@ +# -*- dockerfile -*- +FROM fedora:36 +# Need to install make, tzdata here to avoid stupid prompts when running package install via autobuild +RUN dnf update -y && dnf install -y make tzdata diff --git a/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/freebsd.Dockerfile.in.FAILING b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/freebsd.Dockerfile.in.FAILING new file mode 100644 index 0000000..e69de29 diff --git a/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/gentoo.Dockerfile.in.FAILING b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/gentoo.Dockerfile.in.FAILING new file mode 100644 index 0000000..7e1d520 --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/gentoo.Dockerfile.in.FAILING @@ -0,0 +1,6 @@ +# -*- dockerfile -*- +FROM gentoo/stage3 +RUN emerge --sync +# IF you see this error, just ignore it: !!! It seems /run is not mounted. Process management may malfunction. +# Note that gentoo takes a **long** time to build and run, that's okay. +# @TODO: Currently, running this errors out because it cannot find glib-2.0, needs fixing. diff --git a/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/macos.Dockerfile.in.FAILING b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/macos.Dockerfile.in.FAILING new file mode 100644 index 0000000..e69de29 diff --git a/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/msys2.Dockerfile.in.FAILING b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/msys2.Dockerfile.in.FAILING new file mode 100644 index 0000000..e69de29 diff --git a/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/nixos.Dockerfile.in.FAILING b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/nixos.Dockerfile.in.FAILING new file mode 100644 index 0000000..e69de29 diff --git a/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/openbsd.Dockerfile.in.FAILING b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/openbsd.Dockerfile.in.FAILING new file mode 100644 index 0000000..e69de29 diff --git a/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/opensuse.Dockerfile.in.FAILING b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/opensuse.Dockerfile.in.FAILING new file mode 100644 index 0000000..e69de29 diff --git a/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/ubuntu-18.Dockerfile.in b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/ubuntu-18.Dockerfile.in new file mode 100644 index 0000000..b139c84 --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/ubuntu-18.Dockerfile.in @@ -0,0 +1,5 @@ +# -*- dockerfile -*- +FROM ubuntu:bionic +ARG DEBIAN_FRONTEND=noninteractive +# Need to install make, tzdata here to avoid stupid prompts when running package install via autobuild +RUN apt-get update --fix-missing -y && apt-get install -y make tzdata diff --git a/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/ubuntu-20.Dockerfile.in b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/ubuntu-20.Dockerfile.in new file mode 100644 index 0000000..f650856 --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/ubuntu-20.Dockerfile.in @@ -0,0 +1,5 @@ +# -*- dockerfile -*- +FROM ubuntu:focal +ARG DEBIAN_FRONTEND=noninteractive +# Need to install make, tzdata here to avoid stupid prompts when running package install via autobuild +RUN apt-get update --fix-missing -y && apt-get install -y make tzdata diff --git a/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/ubuntu-22.Dockerfile.in b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/ubuntu-22.Dockerfile.in new file mode 100644 index 0000000..2ac7127 --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/ubuntu-22.Dockerfile.in @@ -0,0 +1,5 @@ +# -*- dockerfile -*- +FROM ubuntu:jammy +ARG DEBIAN_FRONTEND=noninteractive +# Need to install make, tzdata here to avoid stupid prompts when running package install via autobuild +RUN apt-get update --fix-missing -y && apt-get install -y make tzdata diff --git a/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/void.Dockerfile.in.FAILING b/org/elpa/pdf-tools-20230404.327/build/server/test/docker/templates/void.Dockerfile.in.FAILING new file mode 100644 index 0000000..e69de29 diff --git a/org/elpa/pdf-tools-20230404.327/pdf-annot.el b/org/elpa/pdf-tools-20230404.327/pdf-annot.el new file mode 100644 index 0000000..3b63593 --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/pdf-annot.el @@ -0,0 +1,1879 @@ +;;; pdf-annot.el --- Annotation support for PDF files. -*- lexical-binding: t -*- + +;; Copyright (C) 2013, 2014 Andreas Politz + +;; Author: Andreas Politz +;; Keywords: + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; + + +(require 'pdf-view) +(require 'pdf-info) +(require 'pdf-cache) +(require 'pdf-misc) +(require 'facemenu) ;; list-colors-duplicates +(require 'faces) ;; color-values +(require 'org) ;; org-create-formula-image +(require 'tablist) +(require 'cl-lib) + + +;; * ================================================================== * +;; * Customizations +;; * ================================================================== * + +;;; Code: + +(defgroup pdf-annot nil + "Annotation support for PDF documents." + :group 'pdf-tools) + +(defcustom pdf-annot-activate-handler-functions nil + "A list of functions to activate a annotation. + +The functions on this hook will be called when some annotation is +activated, usually by a mouse-click. Each one is called with the +annotation as a single argument and it should return a non-nil +value if it has `handled' it. If no such function exists, the +default handler `pdf-annot-default-activate-handler' will be +called. + +This hook is meant to allow for custom annotations. FIXME: +Implement and describe basic org example." + :type 'hook) + +(defcustom pdf-annot-default-text-annotation-properties nil + "Alist of initial properties for new text annotations." + :type '(alist :key-type symbol :value-type sexp)) + +(defcustom pdf-annot-default-markup-annotation-properties nil + "Alist of initial properties for new markup annotations." + :type '(alist :key-type symbol :value-type sexp)) + +(make-obsolete-variable 'pdf-annot-default-text-annotation-properties + 'pdf-annot-default-annotation-properties + "0.90") + +(make-obsolete-variable 'pdf-annot-default-markup-annotation-properties + 'pdf-annot-default-annotation-properties + "0.90") + +(defcustom pdf-annot-default-annotation-properties + `((t (label . ,user-full-name)) + (text (icon . "Note") + (color . "#ff0000")) + (highlight (color . "yellow")) + (squiggly (color . "orange")) + (strike-out(color . "red")) + (underline (color . "blue"))) + "An alist of initial properties for new annotations. + +The alist contains a sub-alist for each of the currently available +annotation types, i.e. text, highlight, squiggly, strike-out and +underline. Additionally a sub-alist with a key of t acts as a default +entry. + +Each of these sub-alists contain default property-values of newly +added annotations of its respective type. + +Some of the most important properties and their types are label +\(a string\), contents \(a string\), color \(a color\) and, for +text-annotations only, icon \(one of the standard icon-types, see +`pdf-annot-standard-text-icons'\). + +For example a value of + + \(\(t \(color . \"red\"\) + \(label . \"Joe\"\) + \(highlight \(color . \"green\"\)\) + +would use a green color for highlight and a red one for other +annotations. Additionally the label for all annotations is set +to \"Joe\"." + + :type (let* ((label '(cons :tag "Label" (const label) string)) + (contents '(cons :tag "Contents" (const contents) string)) + (color '(cons :tag "Color" (const color) color)) + (icon `(cons :tag "Icon" + (const icon) + (choice + ,@(mapcar (lambda (icon) + `(const ,icon)) + '("Note" "Comment" "Key" "Help" "NewParagraph" + "Paragraph" "Insert" "Cross" "Circle"))))) + (other '(repeat + :tag "Other properties" + (cons :tag "Property" + (symbol :tag "Key ") + (sexp :tag "Value")))) + (text-properties + `(set ,label ,contents ,color ,icon ,other)) + (markup-properties + `(set ,label ,contents ,color)) + (all-properties + `(set ,label ,contents ,color ,icon ,other))) + `(set + (cons :tag "All Annotations" (const t) ,all-properties) + (cons :tag "Text Annotations" (const text) ,text-properties) + (cons :tag "Highlight Annotations" (const highlight) ,markup-properties) + (cons :tag "Underline Annotations" (const underline) ,markup-properties) + (cons :tag "Squiggly Annotations" (const squiggly) ,markup-properties) + (cons :tag "Strike-out Annotations" (const strike-out) ,markup-properties)))) + +(defcustom pdf-annot-print-annotation-functions + '(pdf-annot-print-annotation-latex-maybe) + "A alist of functions for printing annotations, e.g. for the tooltip. + +The functions receive the annotation as single argument and +should return either a string or nil. The first string returned +will be used. + +If all of them return nil, the default function +`pdf-annot-print-annotation-default' is used." + :type 'hook) + +(defcustom pdf-annot-latex-string-predicate + (lambda (str) + (and str (string-match "\\`[[:space:]\n]*[$\\]" str))) + "A predicate for recognizing LaTeX fragments. + +It receives a string and should return non-nil, if string is a +LaTeX fragment." + :type 'function) + +(defcustom pdf-annot-latex-header + (concat org-format-latex-header + "\n\\setlength{\\textwidth}{12cm}") + "Header used when latex compiling annotations. +The default value is `org-format-latex-header' + +\"\\n\\\\setlength{\\\\textwidth}{12cm}\"." + :type 'string) + +(defcustom pdf-annot-tweak-tooltips t + "Whether this package should tweak some settings regarding tooltips. + +If this variable has a non-nil value, + +`x-gtk-use-system-tooltips' is set to nil if appropriate, in +order to display text properties; + +`tooltip-hide-delay' is set to infinity, in order to not being +annoyed while reading the annotations." + :type 'boolean) + +(defcustom pdf-annot-activate-created-annotations nil + "Whether to activate (i.e. edit) created annotations." + :type 'boolean) + +(defcustom pdf-annot-attachment-display-buffer-action nil + "The display action used when displaying attachments." + :type display-buffer--action-custom-type) + +(defconst pdf-annot-annotation-types + '(3d caret circle file + free-text highlight ink line link movie poly-line polygon popup + printer-mark screen sound square squiggly stamp strike-out text + trap-net underline unknown watermark widget) + "Complete list of annotation types.") + +(defcustom pdf-annot-list-listed-types + (if (pdf-info-markup-annotations-p) + (list 'text 'file 'squiggly 'highlight 'underline 'strike-out) + (list 'text 'file)) + "A list of annotation types displayed in the list buffer." + :type `(set ,@(mapcar (lambda (type) + (list 'const type)) + pdf-annot-annotation-types))) + + +;; * ================================================================== * +;; * Variables and Macros +;; * ================================================================== * + +(defvar pdf-annot-color-history nil + "A list of recently used colors for annotations.") + +(defvar-local pdf-annot-modified-functions nil + "Functions to call, when an annotation was modified. + +A function on this hook should accept one argument: A CLOSURE +containing inserted, changed and deleted annotations. + +It may access these annotations by calling CLOSURE with one of +these arguments: + +`:inserted' The list of recently added annotations. + +`:deleted' The list of recently deleted annotations. + +`:changed' The list of recently changed annotations. + +t The union of recently added, deleted or changed annotations. + +nil Just returns nil. + +Any other argument signals an error.") + +(defconst pdf-annot-text-annotation-size '(24 . 24) + "The Size of text and file annotations in PDF points. + +These values are hard-coded in poppler. And while the size of +these annotations may be changed, i.e. the edges property, it has +no effect on the rendering.") + +(defconst pdf-annot-markup-annotation-types + '(text link free-text line square + circle polygon poly-line highlight underline squiggly + strike-out stamp caret ink file sound) + "List of defined markup annotation types.") + +(defconst pdf-annot-standard-text-icons + '("Note" "Comment" "Key" "Help" "NewParagraph" + "Paragraph" "Insert" "Cross" "Circle") + "A list of standard icon properties for text annotations.") + +(defvar pdf-annot-inhibit-modification-hooks nil + "Controls the behavior of `pdf-annot-modified-functions'. + +If non-nil, `pdf-annot-modified-functions' are not run on any +annotation change.") + +(defvar-local pdf-annot-delayed-modified-annotations nil + "A plist of not yet propagated modifications. + +It contains three entries :change, :delete and :insert. Each one +having a list of annotations as value.") + +(defvar-local pdf-annot--attachment-file-alist nil + "Alist mapping attachment ids to unique relative filenames.") + +(defmacro pdf-annot-with-atomic-modifications (&rest body) + "Execute BODY joining multiple modifications. + +The effect is, that `pdf-annot-modified-functions' will be called +only once at the end of BODY. + +BODY should not modify annotations in a different then the +current buffer, because that won't run the hooks properly." + (declare (indent 0) (debug t)) + `(unwind-protect + (save-current-buffer + (let ((pdf-annot-inhibit-modification-hooks t)) + (progn ,@body))) + (pdf-annot-run-modified-hooks))) + + +;; * ================================================================== * +;; * Minor mode +;; * ================================================================== * + +(defcustom pdf-annot-minor-mode-map-prefix (kbd "C-c C-a") + "The prefix to use for `pdf-annot-minor-mode-map'. + +Setting this after the package was loaded has no effect." + :type 'key-sequence) + +(defvar pdf-annot-minor-mode-map + (let ((kmap (make-sparse-keymap)) + (smap (make-sparse-keymap))) + (define-key kmap pdf-annot-minor-mode-map-prefix smap) + (define-key smap "l" #'pdf-annot-list-annotations) + (define-key smap "a" #'pdf-annot-attachment-dired) + (when (pdf-info-writable-annotations-p) + (define-key smap "D" #'pdf-annot-delete) + (define-key smap "t" #'pdf-annot-add-text-annotation) + (when (pdf-info-markup-annotations-p) + (define-key smap "m" #'pdf-annot-add-markup-annotation) + (define-key smap "s" #'pdf-annot-add-squiggly-markup-annotation) + (define-key smap "u" #'pdf-annot-add-underline-markup-annotation) + (define-key smap "o" #'pdf-annot-add-strikeout-markup-annotation) + (define-key smap "h" #'pdf-annot-add-highlight-markup-annotation))) + kmap) + "Keymap used for `pdf-annot-minor-mode'.") + +(defvar savehist-minibuffer-history-variables) + +;;;###autoload +(define-minor-mode pdf-annot-minor-mode + "Support for PDF Annotations. + +\\{pdf-annot-minor-mode-map}" + :group 'pdf-annot + (cond + (pdf-annot-minor-mode + (when pdf-annot-tweak-tooltips + (when (boundp 'x-gtk-use-system-tooltips) + (setq x-gtk-use-system-tooltips nil)) + (setq tooltip-hide-delay 3600)) + (pdf-view-add-hotspot-function 'pdf-annot-hotspot-function 9) + (add-hook 'pdf-info-close-document-hook + #'pdf-annot-attachment-delete-base-directory nil t) + (when (featurep 'savehist) + (add-to-list 'savehist-minibuffer-history-variables + 'pdf-annot-color-history))) + (t + (pdf-view-remove-hotspot-function 'pdf-annot-hotspot-function) + (remove-hook 'pdf-info-close-document-hook + #'pdf-annot-attachment-delete-base-directory t))) + (pdf-view-redisplay t)) + +(defun pdf-annot-create-context-menu (a) + "Create a appropriate context menu for annotation A." + (let ((menu (make-sparse-keymap))) + ;; (when (and (bound-and-true-p pdf-misc-menu-bar-minor-mode) + ;; (bound-and-true-p pdf-misc-install-popup-menu)) + ;; (set-keymap-parent menu + ;; (lookup-key pdf-misc-menu-bar-minor-mode-map + ;; [menu-bar pdf-tools])) + ;; (define-key menu [sep-99] menu-bar-separator)) + (when (pdf-info-writable-annotations-p) + (define-key menu [delete-annotation] + `(menu-item "Delete annotation" + ,(lambda () + (interactive) + (pdf-annot-delete a) + (message "Annotation deleted")) + :help + "Delete this annotation."))) + (define-key menu [goto-annotation] + `(menu-item "List annotation" + ,(lambda () + (interactive) + (pdf-annot-show-annotation a t) + (pdf-annot-list-annotations) + (pdf-annot-list-goto-annotation a)) + :help "Find this annotation in the list buffer.")) + (when (pdf-annot-text-annotation-p a) + (define-key menu [change-text-icon] + `(menu-item "Change icon" + ,(pdf-annot-create-icon-submenu a) + :help "Change the appearance of this annotation."))) + (define-key menu [change-color] + `(menu-item "Change color" + ,(pdf-annot-create-color-submenu a) + :help "Change the appearance of this annotation.")) + (define-key menu [activate-annotation] + `(menu-item "Activate" + ,(lambda () + (interactive) + (pdf-annot-activate-annotation a)) + :help "Activate this annotation.")) + menu)) + +(defun pdf-annot-create-color-submenu (a) + "Show the user a color menu for their annotation A." + (let ((menu (make-sparse-keymap))) + (define-key menu [color-chooser] + `(menu-item "Choose ..." + ,(lambda () + (interactive) + (list-colors-display + nil "*Choose annotation color*" + ;; list-colors-print does not like closures. + (let ((callback (make-symbol "xcallback"))) + (fset callback + (lambda (color) + (pdf-annot-put a 'color color) + (setq pdf-annot-color-history + (cons color + (remove color pdf-annot-color-history))) + (quit-window t))) + (list 'function callback)))))) + (dolist (color (butlast (reverse pdf-annot-color-history) + (max 0 (- (length pdf-annot-color-history) + 12)))) + (define-key menu (vector (intern (format "color-%s" color))) + `(menu-item ,color + ,(lambda nil + (interactive) + (pdf-annot-put a 'color color))))) + menu)) + +(defun pdf-annot-create-icon-submenu (a) + "Show the user an icon menu for the annotation A." + (let ((menu (make-sparse-keymap))) + (dolist (icon (reverse pdf-annot-standard-text-icons)) + (define-key menu (vector (intern (format "icon-%s" icon))) + `(menu-item ,icon + ,(lambda nil + (interactive) + (pdf-annot-put a 'icon icon))))) + menu)) + +;; * ================================================================== * +;; * Annotation Basics +;; * ================================================================== * + +(defun pdf-annot-create (alist &optional buffer) + "Create a annotation from ALIST in BUFFER. + +ALIST should be a property list as returned by +`pdf-cache-getannots'. BUFFER should be the buffer of the +corresponding PDF document. It defaults to the current buffer." + + (cons `(buffer . ,(or buffer (current-buffer))) + alist)) + +(defun pdf-annot-getannots (&optional pages types buffer) + "Return a list of annotations on PAGES of TYPES in BUFFER. + +See `pdf-info-normalize-pages' for valid values of PAGES. TYPES +may be a symbol or list of symbols denoting annotation types. + +PAGES defaults to all pages, TYPES to all types and BUFFER to the +current buffer." + + (pdf-util-assert-pdf-buffer buffer) + (unless buffer + (setq buffer (current-buffer))) + (unless (listp types) + (setq types (list types))) + (with-current-buffer buffer + (let (result) + (dolist (a (pdf-info-getannots pages)) + (when (or (null types) + (memq (pdf-annot-get a 'type) types)) + (push (pdf-annot-create a) result))) + result))) + +(defun pdf-annot-getannot (id &optional buffer) + "Return the annotation object for annotation ID. + +Optionally take the BUFFER name of the PDF buffer. When none is +provided, the `current-buffer' is picked up." + (pdf-annot-create + (pdf-info-getannot id buffer) + buffer)) + +(defun pdf-annot-get (a property &optional default) + "Get annotation A's value of PROPERTY. + +Return DEFAULT, if value is nil." + (or (cdr (assq property a)) default)) + +(defun pdf-annot-put (a property value) + "Set annotation A's PROPERTY to VALUE. + +Unless VALUE is `equal' to the current value, sets A's buffer's +modified flag and runs the hook `pdf-annot-modified-functions'. + +Signals an error, if PROPERTY is not modifiable. + +Returns the modified annotation." + + (declare (indent 2)) + (unless (equal value (pdf-annot-get a property)) + (unless (pdf-annot-property-modifiable-p a property) + (error "Property `%s' is read-only for this annotation" + property)) + (with-current-buffer (pdf-annot-get-buffer a) + (setq a (pdf-annot-create + (pdf-info-editannot + (pdf-annot-get-id a) + `((,property . ,value))))) + (set-buffer-modified-p t) + (pdf-annot-run-modified-hooks :change a))) + a) + +(defun pdf-annot-run-modified-hooks (&optional operation &rest annotations) + "Run `pdf-annot-modified-functions' using OPERATION on ANNOTATIONS. + +OPERATION should be one of nil, :change, :insert or :delete. If +nil, annotations should be empty. + +Redisplay modified pages. + +If `pdf-annot-inhibit-modification-hooks' in non-nil, this just +saves ANNOTATIONS and does not call the hooks until later, when +the variable is nil and this function is called again." + + (unless (memq operation '(nil :insert :change :delete)) + (error "Invalid operation: %s" operation)) + (when (and (null operation) annotations) + (error "Missing operation argument")) + + (when operation + (let ((list (plist-get pdf-annot-delayed-modified-annotations operation))) + (dolist (a annotations) + (cl-pushnew a list :test 'pdf-annot-equal)) + (setq pdf-annot-delayed-modified-annotations + (plist-put pdf-annot-delayed-modified-annotations + operation list)))) + (unless pdf-annot-inhibit-modification-hooks + (let* ((changed (plist-get pdf-annot-delayed-modified-annotations :change)) + (inserted (mapcar (lambda (a) + (or (car (cl-member a changed :test 'pdf-annot-equal)) + a)) + (plist-get pdf-annot-delayed-modified-annotations :insert))) + (deleted (plist-get pdf-annot-delayed-modified-annotations :delete)) + (union (cl-union (cl-union changed inserted :test 'pdf-annot-equal) + deleted :test 'pdf-annot-equal)) + (closure (lambda (arg) + (when arg + (cl-case arg + (:inserted (copy-sequence inserted)) + (:changed (copy-sequence changed)) + (:deleted (copy-sequence deleted)) + (t (copy-sequence union)))))) + (pages (mapcar (lambda (a) (pdf-annot-get a 'page)) union))) + (when union + (unwind-protect + (run-hook-with-args + 'pdf-annot-modified-functions closure) + (setq pdf-annot-delayed-modified-annotations nil) + (apply #'pdf-view-redisplay-pages pages)))))) + +(defun pdf-annot-equal (a1 a2) + "Return non-nil, if annotations A1 and A2 are equal. + +Two annotations are equal, if they belong to the same buffer and +have identical id properties." + (and (eq (pdf-annot-get-buffer a1) + (pdf-annot-get-buffer a2)) + (eq (pdf-annot-get-id a1) + (pdf-annot-get-id a2)))) + +(defun pdf-annot-get-buffer (a) + "Return annotation A's buffer." + (pdf-annot-get a 'buffer)) + +(defun pdf-annot-get-id (a) + "Return id property of annotation A." + (pdf-annot-get a 'id)) + +(defun pdf-annot-get-type (a) + "Return type property of annotation A." + (pdf-annot-get a 'type)) + +(defun pdf-annot-get-display-edges (a) + "Return a list of EDGES used for display for annotation A. + +This returns a list of \(LEFT TOP RIGHT BOT\) demarking the +rectangles of the page where A is rendered." + + (or (pdf-annot-get a 'markup-edges) + (list (pdf-annot-get a 'edges)))) + +(defun pdf-annot-delete (a) + "Delete annotation A. + +Sets A's buffer's modified flag and runs the hook +`pdf-annot-modified-functions'. + +This function always returns nil." + (interactive + (list (pdf-annot-read-annotation + "Click on the annotation you wish to delete"))) + (with-current-buffer (pdf-annot-get-buffer a) + (pdf-info-delannot + (pdf-annot-get-id a)) + (set-buffer-modified-p t) + (pdf-annot-run-modified-hooks :delete a)) + (when (called-interactively-p 'any) + (message "Annotation deleted")) + nil) + +(defun pdf-annot-text-annotation-p (a) + "Return non-nil if annotation A is of type text." + (eq 'text (pdf-annot-get a 'type))) + +(defun pdf-annot-markup-annotation-p (a) + "Return non-nil if annotation A is a known markup type. + +Annotation types are defined in `pdf-annot-markup-annotation-types'." + (not (null + (memq (pdf-annot-get a 'type) + pdf-annot-markup-annotation-types)))) + +(defun pdf-annot-property-modifiable-p (a property) + "Return non-nil if PROPERTY for annotation A is editable." + (or (memq property '(edges color flags contents)) + (and (pdf-annot-markup-annotation-p a) + (memq property '(label opacity popup popup-is-open))) + (and (pdf-annot-text-annotation-p a) + (memq property '(icon is-open))))) + +(defun pdf-annot-activate-annotation (a) + "Run handler functions on A to activate the annotation. + +Activation functions are defined in `pdf-annot-activate-handler-functions'." + (or (run-hook-with-args-until-success + 'pdf-annot-activate-handler-functions + a) + (pdf-annot-default-activate-handler a))) + +(defun pdf-annot-default-activate-handler (a) + "The default activation function to run on annotation A. + +Activation functions are defined in `pdf-annot-activate-handler-functions'." + (cond + ((pdf-annot-has-attachment-p a) + (pdf-annot-pop-to-attachment a)) + (t (pdf-annot-edit-contents a)))) + + +;; * ================================================================== * +;; * Handling attachments +;; * ================================================================== * + +(defun pdf-annot-has-attachment-p (a) + "Return non-nil if annotation A's has data attached." + (eq 'file (pdf-annot-get a 'type))) + +(defun pdf-annot-get-attachment (a &optional do-save) + "Retrieve annotation A's attachment. + +The DO-SAVE argument is given to +`pdf-info-getattachment-from-annot', which see." + (unless (pdf-annot-has-attachment-p a) + (error "Annotation has no data attached: %s" a)) + (pdf-info-getattachment-from-annot + (pdf-annot-get-id a) + do-save + (pdf-annot-get-buffer a))) + +(defun pdf-annot-attachment-base-directory () + "Return the base directory for saving attachments." + (let ((dir (pdf-util-expand-file-name "attachments"))) + (unless (file-exists-p dir) + (make-directory dir)) + dir)) + +(defun pdf-annot-attachment-delete-base-directory () + "Delete all saved attachment files of the current buffer." + (setq pdf-annot--attachment-file-alist nil) + (delete-directory (pdf-annot-attachment-base-directory) t)) + +(defun pdf-annot-attachment-unique-filename (attachment) + "Return a unique absolute filename for ATTACHMENT." + (let* ((filename (or (cdr (assq 'filename attachment)) + "attachment")) + (id (cdr (assq 'id attachment))) + (unique + (or (cdr (assoc id pdf-annot--attachment-file-alist)) + (let* ((sans-ext + (expand-file-name + (concat (file-name-as-directory ".") + (file-name-sans-extension filename)) + (pdf-annot-attachment-base-directory))) + (ext (file-name-extension filename)) + (newname (concat sans-ext "." ext)) + (i 0)) + (while (rassoc newname pdf-annot--attachment-file-alist) + (setq newname (format "%s-%d.%s" sans-ext (cl-incf i) ext))) + (push (cons id newname) pdf-annot--attachment-file-alist) + newname))) + (directory (file-name-directory unique))) + (unless (file-exists-p directory) + (make-directory directory t)) + unique)) + + +(defun pdf-annot-attachment-save (attachment &optional regenerate-p) + "Save ATTACHMENT's data to a unique filename and return its name. + +If REGENERATE-P is non-nil, copy attachment's file even if the +copy already exists. + +Signal an error, if ATTACHMENT has no, or a non-existing, `file' +property, i.e. it was retrieved with an unset do-save argument. +See `pdf-info-getattachments'" + + (let ((datafile (cdr (assq 'file attachment)))) + (unless (and datafile + (file-exists-p datafile)) + (error "Attachment's file property is invalid")) + (let* ((filename + (pdf-annot-attachment-unique-filename attachment))) + (when (or regenerate-p + (not (file-exists-p filename))) + (copy-file datafile filename nil nil t t)) + filename))) + +(defun pdf-annot-find-attachment-noselect (a) + "Find annotation A's attachment in a buffer, without selecting it. + +Signals an error, if A has no data attached." + (let ((attachment (pdf-annot-get-attachment a t))) + (unwind-protect + (find-file-noselect + (pdf-annot-attachment-save attachment)) + (let ((tmpfile (cdr (assq 'file attachment)))) + (when (and tmpfile + (file-exists-p tmpfile)) + (delete-file tmpfile)))))) + +(defun pdf-annot-attachment-dired (&optional regenerate-p) + "List all attachments in a Dired buffer. + +If REGENERATE-P is non-nil, create attachment's files even if +they already exist. Interactively REGENERATE-P is non-nil if a +prefix argument was given. + +Return the Dired buffer." + (interactive (list current-prefix-arg)) + (let ((attachments (pdf-info-getattachments t))) + (unwind-protect + (progn + (dolist (a (pdf-annot-getannots nil 'file)) + (push (pdf-annot-get-attachment a t) + attachments )) + (dolist (att attachments) + (pdf-annot-attachment-save att regenerate-p)) + (unless attachments + (error "Document has no data attached")) + (dired (pdf-annot-attachment-base-directory))) + (dolist (att attachments) + (let ((tmpfile (cdr (assq 'file att)))) + (when (and tmpfile (file-exists-p tmpfile)) + (delete-file tmpfile))))))) + +(defun pdf-annot-display-attachment (a &optional display-action select-window-p) + "Display file annotation A's data in a buffer. + +DISPLAY-ACTION should be a valid `display-buffer' action. If +nil, `pdf-annot-attachment-display-buffer-action' is used. + +Select the window, if SELECT-WINDOW-P is non-nil. + +Return the window attachment is displayed in." + + (interactive + (list (pdf-annot-read-annotation + "Select a file annotation by clicking on it"))) + (let* ((buffer (pdf-annot-find-attachment-noselect a)) + (window (display-buffer + buffer (or display-action + pdf-annot-attachment-display-buffer-action)))) + (when select-window-p + (select-window window)) + window)) + +(defun pdf-annot-pop-to-attachment (a) + "Display annotation A's attachment in a window and select it." + (interactive + (list (pdf-annot-read-annotation + "Select a file annotation by clicking on it"))) + (pdf-annot-display-attachment a nil t)) + + +;; * ================================================================== * +;; * Interfacing with the display +;; * ================================================================== * + +(defun pdf-annot-image-position (a &optional image-size) + "Return the position of annotation A in image coordinates. + +IMAGE-SIZE should be a cons \(WIDTH . HEIGHT\) and defaults to +the page-image of the selected window." + + (unless image-size + (pdf-util-assert-pdf-window) + (setq image-size (pdf-view-image-size))) + (let ((e (pdf-util-scale + (pdf-annot-get a 'edges) + image-size))) + (pdf-util-with-edges (e) + `(,e-left . ,e-top)))) + +(defun pdf-annot-image-set-position (a x y &optional image-size) + "Set annotation A's position to X,Y in image coordinates. + +See `pdf-annot-image-position' for IMAGE-SIZE." + + (unless image-size + (pdf-util-assert-pdf-window) + (setq image-size (pdf-view-image-size))) + (let* ((edges (pdf-annot-get a 'edges)) + (x (/ x (float (car image-size)))) + (y (/ y (float (cdr image-size))))) + (pdf-util-with-edges (edges) + (let* ((w edges-width) + (h edges-height) + (x (max 0 (min x (- 1 w)))) + (y (max 0 (min y (- 1 h))))) + (pdf-annot-put a 'edges + (list x y -1 -1)))))) + +(defun pdf-annot-image-size (a &optional image-size) + "Return the size of annotation A in image coordinates. + +Returns \(WIDTH . HEIGHT\). + +See `pdf-annot-image-position' for IMAGE-SIZE." + (unless image-size + (pdf-util-assert-pdf-window) + (setq image-size (pdf-view-image-size))) + (let ((edges (pdf-util-scale + (pdf-annot-get a 'edges) image-size))) + (pdf-util-with-edges (edges) + (cons edges-width edges-height)))) + +(defun pdf-annot-image-set-size (a &optional width height image-size) + "Set annotation A's size in image to WIDTH and/or HEIGHT. + +See `pdf-annot-image-position' for IMAGE-SIZE." + (unless image-size + (pdf-util-assert-pdf-window) + (setq image-size (pdf-view-image-size))) + (let* ((edges (pdf-annot-get a 'edges)) + (w (and width + (/ width (float (car image-size))))) + (h (and height + (/ height (float (cdr image-size)))))) + (pdf-util-with-edges (edges) + (pdf-annot-put a 'edges + (list edges-left + edges-top + (if w (+ edges-left w) edges-right) + (if h (+ edges-top h) edges-bot)))))) + +(defun pdf-annot-at-position (pos) + "Return annotation at POS in the selected window. + +POS should be an absolute image position as a cons \(X . Y\). +Alternatively POS may also be an event position, in which case +`posn-window' and `posn-object-x-y' is used to find the image +position. + +Return nil, if no annotation was found." + (let (window) + (when (posnp pos) + (setq window (posn-window pos) + pos (posn-object-x-y pos))) + (save-selected-window + (when window (select-window window 'norecord)) + (let* ((annots (pdf-annot-getannots (pdf-view-current-page))) + (size (pdf-view-image-size)) + (rx (/ (car pos) (float (car size)))) + (ry (/ (cdr pos) (float (cdr size)))) + (rpos (cons rx ry))) + (or (cl-some (lambda (a) + (and (cl-some + (lambda (e) + (pdf-util-edges-inside-p e rpos)) + (pdf-annot-get-display-edges a)) + a)) + annots) + (error "No annotation at this position")))))) + +(defun pdf-annot-mouse-move (event &optional annot) + "Start moving an annotation at EVENT's position. + +EVENT should be a mouse event originating the request and is used +as a reference point. + +ANNOT is the annotation to operate on and defaults to the +annotation at EVENT's start position. + +This function does not return until the operation is completed, +i.e. a non mouse-movement event is read." + + (interactive "@e") + (pdf-util-assert-pdf-window (posn-window (event-start event))) + (select-window (posn-window (event-start event))) + (let* ((mpos (posn-object-x-y (event-start event))) + (a (or annot + (pdf-annot-at-position mpos)))) + (unless a + (error "No annotation at this position: %s" mpos)) + (let* ((apos (pdf-annot-image-position a)) + (offset (cons (- (car mpos) (car apos)) + (- (cdr mpos) (cdr apos)))) + (window (selected-window)) + make-pointer-invisible) + (when (pdf-util-track-mouse-dragging (ev 0.1) + (when (and (eq window (posn-window (event-start ev))) + (eq 'image (car-safe (posn-object (event-start ev))))) + (let ((pdf-view-inhibit-hotspots t) + (pdf-annot-inhibit-modification-hooks t) + (pdf-cache-image-inihibit t) + (xy (posn-object-x-y (event-start ev)))) + (pdf-annot-image-set-position + a (- (car xy) (car offset)) + (- (cdr xy) (cdr offset))) + (pdf-view-redisplay)))) + (pdf-annot-run-modified-hooks))) + nil)) + +(defun pdf-annot-hotspot-function (page size) + "Create image hotspots for page PAGE of size SIZE." + (apply #'nconc (mapcar (lambda (a) + (unless (eq (pdf-annot-get a 'type) + 'link) + (pdf-annot-create-hotspots a size))) + (pdf-annot-getannots page)))) + +(defun pdf-annot-create-hotspots (a size) + "Return a list of image hotspots for annotation A. + +SIZE is a cons (SX . SY), by which edges are scaled." + (let ((id (pdf-annot-get-id a)) + (edges (pdf-util-scale + (pdf-annot-get-display-edges a) + size 'round)) + (moveable-p (memq (pdf-annot-get a 'type) + '(file text))) + hotspots) + (dolist (e edges) + (pdf-util-with-edges (e) + (push `((rect . ((,e-left . ,e-top) . (,e-right . ,e-bot))) + ,id + (pointer + hand + help-echo + ,(pdf-annot-print-annotation a))) + hotspots))) + (pdf-annot-create-hotspot-binding id moveable-p a) + hotspots)) + +;; FIXME: Define a keymap as a template for this. Much cleaner. +(defun pdf-annot-create-hotspot-binding (id moveable-p annotation) + "Create a local keymap for interacting with ANNOTATION using the mouse. + +ID is the identifier for the ANNOTATION, as returned +`pdf-annot-get-id'. MOVEABLE-P indicates whether the annotation +is moveable." + ;; Activating + (local-set-key + (vector id 'mouse-1) + (lambda () + (interactive) + (pdf-annot-activate-annotation annotation))) + ;; Move + (when moveable-p + (local-set-key + (vector id 'down-mouse-1) + (lambda (ev) + (interactive "@e") + (pdf-annot-mouse-move ev annotation)))) + ;; Context Menu + (local-set-key + (vector id 'down-mouse-3) + (lambda () + (interactive "@") + (popup-menu (pdf-annot-create-context-menu annotation)))) + ;; Everything else + (local-set-key + (vector id t) + 'pdf-util-image-map-mouse-event-proxy)) + +(defun pdf-annot-show-annotation (a &optional highlight-p window) + "Make annotation A visible. + +Turn to A's page in WINDOW, and scroll it if necessary. + +If HIGHLIGHT-P is non-nil, visually distinguish annotation A from +other annotations." + + (save-selected-window + (when window (select-window window 'norecord)) + (pdf-util-assert-pdf-window) + (let ((page (pdf-annot-get a 'page)) + (size (pdf-view-image-size))) + (unless (= page (pdf-view-current-page)) + (pdf-view-goto-page page)) + (let ((edges (pdf-annot-get-display-edges a))) + (when highlight-p + (pdf-view-display-image + (pdf-view-create-image + (pdf-cache-renderpage-highlight + page (car size) + `("white" "steel blue" 0.35 ,@edges)) + :map (pdf-view-apply-hotspot-functions + window page size) + :width (car size)))) + (pdf-util-scroll-to-edges + (pdf-util-scale-relative-to-pixel (car edges))))))) + +(defun pdf-annot-read-annotation (&optional prompt) + "Let the user choose a annotation a mouse click using PROMPT." + (pdf-annot-at-position + (pdf-util-read-image-position + (or prompt "Choose a annotation by clicking on it")))) + + +;; * ================================================================== * +;; * Creating annotations +;; * ================================================================== * + +(defun pdf-annot-add-annotation (type edges &optional property-alist page) + "Create and add a new annotation of type TYPE to the document. + +TYPE determines the kind of annotation to add and maybe one of +`text', `squiggly', `underline', `strike-out' or `highlight'. + +EDGES determines where the annotation will appear on the page. +If type is `text', this should be a single list of \(LEFT TOP +RIGHT BOT\). Though, in this case only LEFT and TOP are used, +since the size of text annotations is fixed. Otherwise EDGES may +be a list of such elements. All values should be image relative +coordinates, i.e. in the range \[0;1\]. + +PROPERTY-ALIST is a list of annotation properties, which will be +put on the created annotation. + +PAGE determines the page of the annotation. It defaults to the +page currently displayed in the selected window. + +Signal an error, if PROPERTY-ALIST contains non-modifiable +properties or PAGE is nil and the selected window does not +display a PDF document or creating annotations of type TYPE is +not supported. + +Set buffers modified flag and calls +`pdf-annot-activate-annotation' if +`pdf-annot-activate-created-annotations' is non-nil. + +Return the new annotation." + + (unless (memq type (pdf-info-creatable-annotation-types)) + (error "Unsupported annotation type: %s" type)) + (unless page + (pdf-util-assert-pdf-window) + (setq page (pdf-view-current-page))) + (unless (consp (car-safe edges)) + (setq edges (list edges))) + (when (and (eq type 'text) + (> (length edges) 1)) + (error "Edges argument should be a single edge-list for text annotations")) + (let* ((selection-style pdf-view-selection-style) + (a (apply #'pdf-info-addannot + page + (if (eq type 'text) + (car edges) + (apply #'pdf-util-edges-union + (apply #'append + (mapcar + (lambda (e) + (pdf-info-getselection page e selection-style)) + edges)))) + type + selection-style + nil + (if (not (eq type 'text)) edges))) + (id (pdf-annot-get-id a))) + (when property-alist + (condition-case err + (setq a (pdf-info-editannot id property-alist)) + (error + (pdf-info-delannot id) + (signal (car err) (cdr err))))) + (setq a (pdf-annot-create a)) + (set-buffer-modified-p t) + (pdf-annot-run-modified-hooks :insert a) + (when pdf-annot-activate-created-annotations + (pdf-annot-activate-annotation a)) + a)) + +(defun pdf-annot-add-text-annotation (pos &optional icon property-alist) + "Add a new text annotation at POS in the selected window. + +POS should be a image position object or a cons \(X . Y\), both +being image coordinates. + +ICON determines how the annotation is displayed and should be +listed in `pdf-annot-standard-text-icons'. Any other value is ok +as well, but will render the annotation invisible. + +Adjust X and Y accordingly, if the position would render the +annotation off-page. + +Merge ICON as a icon property with PROPERTY-ALIST and +`pdf-annot-default-text-annotation-properties' and apply the +result to the created annotation. + +See also `pdf-annot-add-annotation'. + +Return the new annotation." + + (interactive + (let* ((posn (pdf-util-read-image-position + "Click where a new text annotation should be added ...")) + (window (posn-window posn))) + (select-window window) + (list posn))) + (pdf-util-assert-pdf-window) + (when (posnp pos) + (setq pos (posn-object-x-y pos))) + (let ((isize (pdf-view-image-size)) + (x (car pos)) + (y (cdr pos))) + (unless (and (>= x 0) + (< x (car isize))) + (signal 'args-out-of-range (list pos))) + (unless (and (>= y 0) + (< y (cdr isize))) + (signal 'args-out-of-range (list pos))) + (let ((size (pdf-util-scale-points-to-pixel + pdf-annot-text-annotation-size 'round))) + (setcar size (min (car size) (car isize))) + (setcdr size (min (cdr size) (cdr isize))) + (cl-decf x (max 0 (- (+ x (car size)) (car isize)))) + (cl-decf y (max 0 (- (+ y (cdr size)) (cdr isize)))) + (pdf-annot-add-annotation + 'text (pdf-util-scale-pixel-to-relative + (list x y -1 -1)) + (pdf-annot-merge-alists + (and icon `((icon . ,icon))) + property-alist + pdf-annot-default-text-annotation-properties + (cdr (assq 'text pdf-annot-default-annotation-properties)) + (cdr (assq t pdf-annot-default-annotation-properties)) + `((color . ,(car pdf-annot-color-history)))))))) + +(defun pdf-annot-mouse-add-text-annotation (ev) + "Add a text annotation using the mouse. + +EV describes the captured mouse event." + (interactive "@e") + (pdf-annot-add-text-annotation + (if (eq (car-safe ev) + 'menu-bar) + (let (echo-keystrokes) + (message nil) + (pdf-util-read-image-position + "Click where a new text annotation should be added ...")) + (event-start ev)))) + +(defun pdf-annot-add-markup-annotation (list-of-edges type &optional color + property-alist) + "Add a new markup annotation in the selected window. + +LIST-OF-EDGES determines the marked up area and should be a list +of \(LEFT TOP RIGHT BOT\), each value a relative coordinate. + +TYPE should be one of `squiggly', `underline', `strike-out' or +`highlight'. + +Merge COLOR as a color property with PROPERTY-ALIST and +`pdf-annot-default-markup-annotation-properties' and apply the +result to the created annotation. + +See also `pdf-annot-add-annotation'. + +Return the new annotation." + (interactive + (list (pdf-view-active-region t) + (let ((type (completing-read "Markup type (default highlight): " + '("squiggly" "highlight" "underline" "strike-out") + nil t))) + (if (equal type "") 'highlight (intern type))) + (pdf-annot-read-color))) + (pdf-util-assert-pdf-window) + (pdf-annot-add-annotation + type + list-of-edges + (pdf-annot-merge-alists + (and color `((color . ,color))) + property-alist + pdf-annot-default-markup-annotation-properties + (cdr (assq type pdf-annot-default-annotation-properties)) + (cdr (assq t pdf-annot-default-annotation-properties)) + (when pdf-annot-color-history + `((color . ,(car pdf-annot-color-history)))) + '((color . "#ffff00"))) + (pdf-view-current-page))) + +(defun pdf-annot-add-squiggly-markup-annotation (list-of-edges + &optional color property-alist) + "Add a new squiggly annotation in the selected window. + +LIST-OF-EDGES defines the annotation boundary. COLOR defines the +annotation color and PROPERTY-ALIST defines additional annotation +properties. See also `pdf-annot-add-markup-annotation'." + (interactive (list (pdf-view-active-region t))) + (pdf-annot-add-markup-annotation list-of-edges 'squiggly color property-alist)) + +(defun pdf-annot-add-underline-markup-annotation (list-of-edges + &optional color property-alist) + "Add a new underline annotation in the selected window. + +LIST-OF-EDGES defines the annotation boundary. COLOR defines the +annotation color and PROPERTY-ALIST defines additional annotation +properties. See also `pdf-annot-add-markup-annotation'." + (interactive (list (pdf-view-active-region t))) + (pdf-annot-add-markup-annotation list-of-edges 'underline color property-alist)) + +(defun pdf-annot-add-strikeout-markup-annotation (list-of-edges + &optional color property-alist) + "Add a new strike-out annotation in the selected window. + +LIST-OF-EDGES defines the annotation boundary. COLOR defines the +annotation color and PROPERTY-ALIST defines additional annotation +properties. See also `pdf-annot-add-markup-annotation'." + (interactive (list (pdf-view-active-region t))) + (pdf-annot-add-markup-annotation list-of-edges 'strike-out color property-alist)) + +(defun pdf-annot-add-highlight-markup-annotation (list-of-edges + &optional color property-alist) + "Add a new highlight annotation in the selected window. + +LIST-OF-EDGES defines the annotation boundary. COLOR defines the +annotation color and PROPERTY-ALIST defines additional annotation +properties. See also `pdf-annot-add-markup-annotation'." + (interactive (list (pdf-view-active-region t))) + (pdf-annot-add-markup-annotation list-of-edges 'highlight color property-alist)) + +(defun pdf-annot-read-color (&optional prompt) + "Read and return a color using PROMPT. + +Offer `pdf-annot-color-history' as default values." + (let* ((defaults (append + (delq nil + (list + (cdr (assq 'color + pdf-annot-default-markup-annotation-properties)) + (cdr (assq 'color + pdf-annot-default-text-annotation-properties)))) + pdf-annot-color-history)) + (prompt + (format "%s%s: " + (or prompt "Color") + (if defaults (format " (default %s)" (car defaults)) ""))) + (current-completing-read-function completing-read-function) + (completing-read-function + (lambda (prompt collection &optional predicate require-match + initial-input _hist _def inherit-input-method) + (funcall current-completing-read-function + prompt collection predicate require-match + initial-input 'pdf-annot-color-history + defaults + inherit-input-method)))) + (read-color prompt))) + +(defun pdf-annot-merge-alists (&rest alists) + "Merge ALISTS into a single one. + +Suppresses successive duplicate entries of keys after the first +occurrence in ALISTS." + + (let (merged) + (dolist (elt (apply #'append alists)) + (unless (assq (car elt) merged) + (push elt merged))) + (nreverse merged))) + + + +;; * ================================================================== * +;; * Displaying annotation contents +;; * ================================================================== * + +(defun pdf-annot-print-property (a property) + "Pretty print annotation A's property PROPERTY." + (let ((value (pdf-annot-get a property))) + (cl-case property + (color + (propertize (or value "") + 'face (and value + `(:background ,value)))) + ((created modified) + (let ((date value)) + (if (null date) + "No date" + (current-time-string date)))) + ;; print verbatim + (subject + (or value "No subject")) + (opacity + (let ((opacity (or value 1.0))) + (format "%d%%" (round (* 100 opacity))))) + (t (format "%s" (or value "")))))) + +(defun pdf-annot-print-annotation (a) + "Pretty print annotation A." + (or (run-hook-with-args-until-success + 'pdf-annot-print-annotation-functions a) + (pdf-annot-print-annotation-default a))) + +(defun pdf-annot-print-annotation-default (a) + "Default pretty printer for annotation A. + +The result consists of a header (as printed with +`pdf-annot-print-annotation-header') a newline and A's contents +property." + (concat + (pdf-annot-print-annotation-header a) + "\n" + (pdf-annot-get a 'contents))) + +(defun pdf-annot-print-annotation-header (a) + "Emit a suitable header string for annotation A." + (let ((header + (cond + ((eq 'file (pdf-annot-get a 'type)) + (let ((att (pdf-annot-get-attachment a))) + (format "File attachment `%s' of %s" + (or (cdr (assq 'filename att)) "unnamed") + (if (cdr (assq 'size att)) + (format "size %s" (file-size-human-readable + (cdr (assq 'size att)))) + "unknown size")))) + (t + (format "%s" + (mapconcat + #'identity + (mapcar + (lambda (property) + (pdf-annot-print-property + a property)) + `(subject + label + modified)) + ";")))))) + (setq header (propertize header 'face 'header-line + 'intangible t 'read-only t)) + ;; This `trick' makes the face apply in a tooltip. + (propertize header 'display header))) + +(defun pdf-annot-print-annotation-latex-maybe (a) + "Maybe print annotation A's content as a LaTeX fragment. + +See `pdf-annot-latex-string-predicate'." + (when (and (functionp pdf-annot-latex-string-predicate) + (funcall pdf-annot-latex-string-predicate + (pdf-annot-get a 'contents))) + (pdf-annot-print-annotation-latex a))) + +(defun pdf-annot-print-annotation-latex (a) + "Print annotation A's content as a LaTeX fragment. + +This compiles A's contents as a LaTeX fragment and puts the +resulting image as a display property on the contents, prefixed +by a header." + + (let (tempfile) + (unwind-protect + (with-current-buffer (pdf-annot-get-buffer a) + (let* ((page (pdf-annot-get a 'page)) + (header (pdf-annot-print-annotation-header a)) + (contents (pdf-annot-get a 'contents)) + (hash (sxhash (format + "pdf-annot-print-annotation-latex%s%s%s" + page header contents))) + (data (pdf-cache-lookup-image page 0 nil hash)) + ;; pdf-tools can only work with png files, so this + ;; binding ensures that pdf-tools can print the + ;; latex-preview regardless of the user + ;; configuration. + (org-preview-latex-default-process 'dvipng) + (org-format-latex-header pdf-annot-latex-header) + (temporary-file-directory + (pdf-util-expand-file-name "pdf-annot-print-annotation-latex"))) + (unless (file-directory-p temporary-file-directory) + (make-directory temporary-file-directory)) + (unless data + (setq tempfile (make-temp-file "pdf-annot" nil ".png")) + ;; FIXME: Why is this with-temp-buffer needed (which it is) ? + (with-temp-buffer + (org-create-formula-image + contents tempfile org-format-latex-options t)) + (setq data (pdf-util-munch-file tempfile)) + (if (and (> (length data) 3) + (equal (substring data 1 4) + "PNG")) + (pdf-cache-put-image page 0 data hash) + (setq data nil))) + (concat + header + "\n" + (if data + (propertize + contents 'display (pdf-view-create-image data)) + (propertize + contents + 'display + (concat + (propertize "Failed to compile latex fragment\n" + 'face 'error) + contents)))))) + (when (and tempfile + (file-exists-p tempfile)) + (delete-file tempfile))))) + + +;; * ================================================================== * +;; * Editing annotation contents +;; * ================================================================== * + +(defvar-local pdf-annot-edit-contents--annotation nil) +(put 'pdf-annot-edit-contents--annotation 'permanent-local t) +(defvar-local pdf-annot-edit-contents--buffer nil) + +(defcustom pdf-annot-edit-contents-setup-function + (lambda (a) + (let ((mode (if (funcall pdf-annot-latex-string-predicate + (pdf-annot-get a 'contents)) + 'latex-mode + 'org-mode))) + (unless (derived-mode-p mode) + (funcall mode)))) + "A function for setting up, e.g. the major-mode, of the edit buffer. + +The function receives one argument, the annotation whose contents +is about to be edited in this buffer. + +The default value turns on `latex-mode' if +`pdf-annot-latex-string-predicate' returns non-nil on the +annotation's contents and otherwise `org-mode'." + :type 'function) + +(defcustom pdf-annot-edit-contents-display-buffer-action + '((display-buffer-reuse-window + display-buffer-split-below-and-attach) + (inhibit-same-window . t) + (window-height . 0.25)) + "Display action when showing the edit buffer." + :type display-buffer--action-custom-type) + +(defvar pdf-annot-edit-contents-minor-mode-map + (let ((kmap (make-sparse-keymap))) + (set-keymap-parent kmap text-mode-map) + (define-key kmap (kbd "C-c C-c") #'pdf-annot-edit-contents-commit) + (define-key kmap (kbd "C-c C-q") #'pdf-annot-edit-contents-abort) + kmap)) + +(define-minor-mode pdf-annot-edit-contents-minor-mode + "Active when editing the contents of annotations." + :group 'pdf-annot + (when pdf-annot-edit-contents-minor-mode + (message "%s" + (substitute-command-keys + "Press \\[pdf-annot-edit-contents-commit] to commit your changes, \\[pdf-annot-edit-contents-abort] to abandon them.")))) + +(put 'pdf-annot-edit-contents-minor-mode 'permanent-local t) + +(defun pdf-annot-edit-contents-finalize (do-save &optional do-kill) + "Finalize edit-operations on an Annotation. + +If DO-SAVE is t, save the changes to annotation content without +asking. If DO-SAVE is `ask', check with the user if contents +should be saved. + +If DO-KILL is t, kill all windows displaying the annotation +contents. Else just bury the buffers." + (when (buffer-modified-p) + (cond + ((eq do-save 'ask) + (save-window-excursion + (display-buffer (current-buffer) nil (selected-frame)) + (when (y-or-n-p "Save changes to this annotation ?") + (pdf-annot-edit-contents-save-annotation)))) + (do-save + (pdf-annot-edit-contents-save-annotation))) + (set-buffer-modified-p nil)) + (dolist (win (get-buffer-window-list)) + (quit-window do-kill win))) + +(defun pdf-annot-edit-contents-save-annotation () + "Internal function to save the contents of the annotation under editing." + (when pdf-annot-edit-contents--annotation + (pdf-annot-put pdf-annot-edit-contents--annotation + 'contents + (buffer-substring-no-properties (point-min) (point-max))) + (set-buffer-modified-p nil))) + +(defun pdf-annot-edit-contents-commit () + "Save the change made to the current annotation." + (interactive) + (pdf-annot-edit-contents-finalize t)) + +(defun pdf-annot-edit-contents-abort () + "Abort the change made to the current annotation." + (interactive) + (pdf-annot-edit-contents-finalize nil t)) + +(defun pdf-annot-edit-contents-noselect (a) + "Internal function to setup all prerequisites for editing annotation A. + +At any given point of time, only one annotation can be in edit mode." + (with-current-buffer (pdf-annot-get-buffer a) + (when (and (buffer-live-p pdf-annot-edit-contents--buffer) + (not (eq a pdf-annot-edit-contents--annotation))) + (with-current-buffer pdf-annot-edit-contents--buffer + (pdf-annot-edit-contents-finalize 'ask))) + (unless (buffer-live-p pdf-annot-edit-contents--buffer) + (setq pdf-annot-edit-contents--buffer + (with-current-buffer (get-buffer-create + (format "*Edit Annotation %s*" + (buffer-name))) + (pdf-annot-edit-contents-minor-mode 1) + (current-buffer)))) + (with-current-buffer pdf-annot-edit-contents--buffer + (let ((inhibit-read-only t)) + (erase-buffer) + (save-excursion (insert (pdf-annot-get a 'contents))) + (set-buffer-modified-p nil)) + (setq pdf-annot-edit-contents--annotation a) + (funcall pdf-annot-edit-contents-setup-function a) + (current-buffer)))) + +(defun pdf-annot-edit-contents (a) + "Edit the contents of annotation A." + (select-window + (display-buffer + (pdf-annot-edit-contents-noselect a) + pdf-annot-edit-contents-display-buffer-action))) + +(defun pdf-annot-edit-contents-mouse (ev) + "Edit the contents of the annotation described by mouse event EV." + (interactive "@e") + (let* ((pos (posn-object-x-y (event-start ev))) + (a (and pos (pdf-annot-at-position pos)))) + (unless a + (error "No annotation at this position")) + (pdf-annot-edit-contents a))) + + + +;; * ================================================================== * +;; * Listing annotations +;; * ================================================================== * + +(defcustom pdf-annot-list-display-buffer-action + '((display-buffer-reuse-window + display-buffer-pop-up-window) + (inhibit-same-window . t)) + "Display action used when displaying the list buffer." + :type display-buffer--action-custom-type) + +(defcustom pdf-annot-list-format + '((page . 3) + (type . 10) + (label . 24) + (date . 24)) + "Annotation properties visible in the annotation list. + +It should be a list of \(PROPERTIZE. WIDTH\), where PROPERTY is a +symbol naming one of supported properties to list and WIDTH its +desired column-width. + +Currently supported properties are page, type, label, date and contents." + :type '(alist :key-type (symbol)) + :options '((page (integer :value 3 :tag "Column Width")) + (type (integer :value 10 :tag "Column Width" )) + (label (integer :value 24 :tag "Column Width")) + (date (integer :value 24 :tag "Column Width")) + (contents (integer :value 56 :tag "Column Width")))) + +(defcustom pdf-annot-list-highlight-type t + "Whether to highlight \"Type\" column annotation list with annotation color." + :type 'boolean) + +(defvar-local pdf-annot-list-buffer nil) + +(defvar-local pdf-annot-list-document-buffer nil) + +(defvar pdf-annot-list-mode-map + (let ((km (make-sparse-keymap))) + (define-key km (kbd "C-c C-f") #'pdf-annot-list-follow-minor-mode) + (define-key km (kbd "SPC") #'pdf-annot-list-display-annotation-from-id) + km)) + +(defun pdf-annot-property-completions (property) + "Return a list of completion candidates for annotation property PROPERTY. + +Return nil, if not available." + (cl-case property + (color (pdf-util-color-completions)) + (icon (copy-sequence pdf-annot-standard-text-icons)))) + +(defun pdf-annot-compare-annotations (a1 a2) + "Compare annotations A1 and A2. + +Return non-nil if A1's page is less than A2's one or if they +belong to the same page and A1 is displayed above/left of A2." + (let ((p1 (pdf-annot-get a1 'page)) + (p2 (pdf-annot-get a2 'page))) + (or (< p1 p2) + (and (= p1 p2) + (let ((e1 (pdf-util-scale + (car (pdf-annot-get-display-edges a1)) + '(1000 . 1000))) + (e2 (pdf-util-scale + (car (pdf-annot-get-display-edges a2)) + '(1000 . 1000)))) + (pdf-util-with-edges (e1 e2) + (or (< e1-top e2-top) + (and (= e1-top e2-top) + (<= e1-left e2-left))))))))) + +(defun pdf-annot-list-entries () + "Return all the annotations of this PDF buffer as a `tabulated-list'." + (unless (buffer-live-p pdf-annot-list-document-buffer) + (error "No PDF document associated with this buffer")) + (mapcar #'pdf-annot-list-create-entry + (sort (pdf-annot-getannots nil pdf-annot-list-listed-types + pdf-annot-list-document-buffer) + #'pdf-annot-compare-annotations))) + +(defun pdf-annot--make-entry-formatter (a) + "Return a formatter function for annotation A. + +A formatter function takes a format cons-cell and returns +pretty-printed output." + (lambda (fmt) + (let ((entry-type (car fmt)) + (entry-width (cdr fmt)) + ;; Taken from css-mode.el + (contrasty-color + (lambda (name) + (if (> (color-distance name "black") 292485) + "black" "white"))) + (prune-newlines + (lambda (str) + (replace-regexp-in-string "\n" " " str t t)))) + (cl-ecase entry-type + (date (propertize (pdf-annot-print-property a 'modified) + 'date + (pdf-annot-get a 'modified))) + (page (pdf-annot-print-property a 'page)) + (label (funcall prune-newlines + (pdf-annot-print-property a 'label))) + (contents + (truncate-string-to-width + (funcall prune-newlines + (pdf-annot-print-property a 'contents)) + entry-width)) + (type + (let ((color (pdf-annot-get a 'color)) + (type (pdf-annot-print-property a 'type))) + (if (and pdf-annot-list-highlight-type color) + (propertize + type 'face + `(:background ,color + :foreground ,(funcall contrasty-color color))) + type))))))) + +(defun pdf-annot-list-create-entry (a) + "Create a `tabulated-list-entries' entry for annotation A." + (list (pdf-annot-get-id a) + (vconcat + (mapcar (pdf-annot--make-entry-formatter a) + pdf-annot-list-format)))) + +(define-derived-mode pdf-annot-list-mode tablist-mode "Annots" + ;; @TODO: Remove the hard-coded index values here, and figure out a + ;; way to properly link this to the index values of + ;; `pdf-annot-list-format'. + + ;; @TODO: Add tests for annotation formatting and display + (let* ((page-sorter + (lambda (a b) + (< (string-to-number (aref (cadr a) 0)) + (string-to-number (aref (cadr b) 0))))) + (date-sorter + (lambda (a b) + (time-less-p (get-text-property 0 'date (aref (cadr a) 3)) + (get-text-property 0 'date (aref (cadr b) 3))))) + (format-generator + (lambda (format) + (let ((field (car format)) + (width (cdr format))) + (cl-case field + (page `("Pg." + ,width + ,page-sorter + :read-only t + :right-align t)) + (date `("Date" + ,width + ,date-sorter + :read-only t)) + (t (list + (capitalize (symbol-name field)) + width + t + :read-only t))))))) + (setq tabulated-list-entries 'pdf-annot-list-entries + tabulated-list-format (vconcat + (mapcar + format-generator + pdf-annot-list-format)) + tabulated-list-padding 2)) + (set-keymap-parent pdf-annot-list-mode-map tablist-mode-map) + (use-local-map pdf-annot-list-mode-map) + (when (assq 'type pdf-annot-list-format) + (setq tablist-current-filter + `(not (== "Type" "link")))) + (tabulated-list-init-header)) + +(defun pdf-annot-list-annotations () + "List annotations in a Dired like buffer. + +\\{pdf-annot-list-mode-map}" + (interactive) + (pdf-util-assert-pdf-buffer) + (let ((buffer (current-buffer))) + (with-current-buffer (get-buffer-create + (format "*%s's annots*" + (file-name-sans-extension + (buffer-name)))) + (delay-mode-hooks + (unless (derived-mode-p 'pdf-annot-list-mode) + (pdf-annot-list-mode)) + (setq pdf-annot-list-document-buffer buffer) + (tabulated-list-print) + (setq tablist-context-window-function + (lambda (id) (pdf-annot-list-context-function id buffer)) + tablist-operations-function #'pdf-annot-list-operation-function) + (let ((list-buffer (current-buffer))) + (with-current-buffer buffer + (setq pdf-annot-list-buffer list-buffer)))) + (run-mode-hooks) + (pop-to-buffer + (current-buffer) + pdf-annot-list-display-buffer-action) + (tablist-move-to-major-column) + (tablist-display-context-window)) + (add-hook 'pdf-info-close-document-hook + #'pdf-annot-list-update nil t) + (add-hook 'pdf-annot-modified-functions + #'pdf-annot-list-update nil t))) + +(defun pdf-annot-list-goto-annotation (a) + "List all the annotations in the current buffer. + +Goto the annotation A in the list." + (with-current-buffer (pdf-annot-get-buffer a) + (unless (and (buffer-live-p pdf-annot-list-buffer) + (get-buffer-window pdf-annot-list-buffer)) + (pdf-annot-list-annotations)) + (with-selected-window (get-buffer-window pdf-annot-list-buffer) + (goto-char (point-min)) + (let ((id (pdf-annot-get-id a))) + (while (and (not (eobp)) + (not (eq id (tabulated-list-get-id)))) + (forward-line)) + (unless (eq id (tabulated-list-get-id)) + (error "Unable to find annotation")) + (when (invisible-p (point)) + (tablist-suspend-filter t)) + (tablist-move-to-major-column))))) + + +(defun pdf-annot-list-update (&optional _fn) + "Update the list of annotations on any change. + +This is an internal function which runs as a hook in various situations." + (when (buffer-live-p pdf-annot-list-buffer) + (with-current-buffer pdf-annot-list-buffer + (unless tablist-edit-column-minor-mode + (tablist-revert)) + (tablist-context-window-update)))) + +(defun pdf-annot-list-context-function (id buffer) + "Show the contents of an Annotation. + +For an annotation identified by ID, belonging to PDF in BUFFER, +get the contents and display them on demand." + (with-current-buffer (get-buffer-create "*Contents*") + (set-window-buffer nil (current-buffer)) + (let ((inhibit-read-only t)) + (erase-buffer) + (when id + (save-excursion + (insert + (pdf-annot-print-annotation + (pdf-annot-getannot id buffer))))) + (read-only-mode 1)))) + +(defun pdf-annot-list-operation-function (op &rest args) + "Define bulk operations in Annotation list buffer. + +OP is the operation that the user wants to execute. Supported +operations are `delete' and `find-entry'. + +ARGS contain the annotation-ids to operate on." + (cl-ecase op + (supported-operations '(delete find-entry)) + (delete + (cl-destructuring-bind (ids) + args + (when (buffer-live-p pdf-annot-list-document-buffer) + (with-current-buffer pdf-annot-list-document-buffer + (pdf-annot-with-atomic-modifications + (dolist (a (mapcar #'pdf-annot-getannot ids)) + (pdf-annot-delete a))))))) + (find-entry + (cl-destructuring-bind (id) + args + (unless (buffer-live-p pdf-annot-list-document-buffer) + (error "No PDF document associated with this buffer")) + (let* ((buffer pdf-annot-list-document-buffer) + (a (pdf-annot-getannot id buffer)) + (pdf-window (save-selected-window + (or (get-buffer-window buffer) + (display-buffer buffer)))) + window) + (with-current-buffer buffer + (pdf-annot-activate-annotation a) + (setq window (selected-window))) + ;; Make it so that quitting the edit window returns to the + ;; list window. + (unless (memq window (list (selected-window) pdf-window)) + (let* ((quit-restore + (window-parameter window 'quit-restore))) + (when quit-restore + (setcar (nthcdr 2 quit-restore) (selected-window)))))))))) + +(defvar pdf-annot-list-display-annotation--timer nil) + +(defun pdf-annot-list-display-annotation-from-id (id) + "Display the Annotation ID in the PDF file. + +This allows us to follow the tabulated-list of annotations and +have the PDF buffer automatically move along with us." + (interactive (list (tabulated-list-get-id))) + (when id + (unless (buffer-live-p pdf-annot-list-document-buffer) + (error "PDF buffer was killed")) + (when (timerp pdf-annot-list-display-annotation--timer) + (cancel-timer pdf-annot-list-display-annotation--timer)) + (setq pdf-annot-list-display-annotation--timer + (run-with-idle-timer 0.1 nil + (lambda (buffer a) + (when (buffer-live-p buffer) + (with-selected-window + (or (get-buffer-window buffer) + (display-buffer + buffer + '(nil (inhibit-same-window . t)))) + (pdf-annot-show-annotation a t)))) + pdf-annot-list-document-buffer + (pdf-annot-getannot id pdf-annot-list-document-buffer))))) + +(define-minor-mode pdf-annot-list-follow-minor-mode + "Make the PDF follow the annotations in the list buffer." + :group 'pdf-annot + (unless (derived-mode-p 'pdf-annot-list-mode) + (error "Not in pdf-annot-list-mode")) + (cond + (pdf-annot-list-follow-minor-mode + (add-hook 'tablist-selection-changed-functions + #'pdf-annot-list-display-annotation-from-id nil t) + (let ((id (tabulated-list-get-id))) + (when id + (pdf-annot-list-display-annotation-from-id id)))) + (t + (remove-hook 'tablist-selection-changed-functions + #'pdf-annot-list-display-annotation-from-id t)))) + +(provide 'pdf-annot) +;;; pdf-annot.el ends here diff --git a/org/elpa/pdf-tools-20230404.327/pdf-cache.el b/org/elpa/pdf-tools-20230404.327/pdf-cache.el new file mode 100644 index 0000000..9c25e07 --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/pdf-cache.el @@ -0,0 +1,499 @@ +;;; pdf-cache.el --- Cache time-critical or frequent epdfinfo queries. -*- lexical-binding:t -*- + +;; Copyright (C) 2013 Andreas Politz + +;; Author: Andreas Politz +;; Keywords: files, doc-view, pdf + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; +;;; Code: +;; + +(require 'pdf-macs) +(require 'pdf-info) +(require 'pdf-util) + + +;; * ================================================================== * +;; * Customiazations +;; * ================================================================== * + +(defcustom pdf-cache-image-limit 64 + "Maximum number of cached PNG images per buffer." + :type 'integer + :group 'pdf-cache + :group 'pdf-view) + +(defcustom pdf-cache-prefetch-delay 0.5 + "Idle time in seconds before prefetching images starts." + :group 'pdf-view + :type 'number) + +(defcustom pdf-cache-prefetch-pages-function + 'pdf-cache-prefetch-pages-function-default + "A function returning a list of pages to be prefetched. + +It is called with no arguments in the PDF window and should +return a list of page-numbers, determining the pages that should +be prefetched and their order." + :group 'pdf-view + :type 'function) + + +;; * ================================================================== * +;; * Simple Value cache +;; * ================================================================== * + +(defvar-local pdf-cache--data nil) + +(defvar pdf-annot-modified-functions) + +(defun pdf-cache--initialize () + "Initialize the cache to store document data. + +Note: The cache is only initialized once. After that it needs to +be cleared before this function makes any changes to it. This is +an internal function and not meant to be directly used." + (unless pdf-cache--data + (setq pdf-cache--data (make-hash-table)) + (add-hook 'pdf-info-close-document-hook #'pdf-cache-clear-data nil t) + (add-hook 'pdf-annot-modified-functions + #'pdf-cache--clear-data-of-annotations + nil t))) + +(defun pdf-cache--clear-data-of-annotations (fn) + "Clear the data cache when annotations are modified. + +FN is a closure as described in `pdf-annot-modified-functions'. + +Note: This is an internal function and not meant to be directly used." + (apply #'pdf-cache-clear-data-of-pages + (mapcar (lambda (a) + (cdr (assq 'page a))) + (funcall fn t)))) + +(defun pdf-cache--data-put (key value &optional page) + "Put KEY with VALUE in the cache of PAGE, return value." + (pdf-cache--initialize) + (puthash page (cons (cons key value) + (assq-delete-all + key + (gethash page pdf-cache--data))) + pdf-cache--data) + value) + +(defun pdf-cache--data-get (key &optional page) + "Get value of KEY in the cache of PAGE. + +Returns a cons \(HIT . VALUE\), where HIT is non-nil if KEY was +stored previously for PAGE and VALUE its value. Otherwise HIT +is nil and VALUE undefined." + (pdf-cache--initialize) + (let ((elt (assq key (gethash page pdf-cache--data)))) + (if elt + (cons t (cdr elt)) + (cons nil nil)))) + +(defun pdf-cache--data-clear (key &optional page) + "Remove KEY from the cache of PAGE." + (pdf-cache--initialize) + (puthash page + (assq-delete-all key (gethash page pdf-cache--data)) + pdf-cache--data) + nil) + +(defun pdf-cache-clear-data-of-pages (&rest pages) + "Remove all PAGES from the cache." + (when pdf-cache--data + (dolist (page pages) + (remhash page pdf-cache--data)))) + +(defun pdf-cache-clear-data () + "Remove the entire cache." + (interactive) + (when pdf-cache--data + (clrhash pdf-cache--data))) + +(defmacro define-pdf-cache-function (command &optional page-arg-p) + "Define a simple data cache function. + +COMMAND is the name of the command, e.g. number-of-pages. It +should have a corresponding pdf-info function. If PAGE-ARG-P is +non-nil, define a one-dimensional cache indexed by the page +number. Otherwise the value is constant for each document, like +e.g. number-of-pages. + +Both args are unevaluated." + + (let ((args (if page-arg-p (list 'page))) + (fn (intern (format "pdf-cache-%s" command))) + (ifn (intern (format "pdf-info-%s" command))) + (doc (format "Cached version of `pdf-info-%s', which see. + +Make sure, not to modify its return value." command))) + `(defun ,fn ,args + ,doc + (let ((hit-value (pdf-cache--data-get ',command ,(if page-arg-p 'page)))) + (if (car hit-value) + (cdr hit-value) + (pdf-cache--data-put + ',command + ,(if page-arg-p + (list ifn 'page) + (list ifn)) + ,(if page-arg-p 'page))))))) + +(define-pdf-cache-function pagelinks t) +(define-pdf-cache-function number-of-pages) +;; The boundingbox may change if annotations change. +(define-pdf-cache-function boundingbox t) +(define-pdf-cache-function textregions t) +(define-pdf-cache-function pagesize t) + + +;; * ================================================================== * +;; * PNG image LRU cache +;; * ================================================================== * + +(defvar pdf-cache-image-inihibit nil + "Non-nil, if the image cache should be bypassed.") + +(defvar-local pdf-cache--image-cache nil) + +(defmacro pdf-cache--make-image (page width data hash) + "Make the image that we store in the image cache. + +An image is a tuple of PAGE WIDTH DATA HASH." + `(list ,page ,width ,data ,hash)) +(defmacro pdf-cache--image/page (img) + "Return the page value for IMG." + `(nth 0 ,img)) +(defmacro pdf-cache--image/width (img) + "Return the width value for IMG." + `(nth 1 ,img)) +(defmacro pdf-cache--image/data (img) + "Return the data value for IMG." + `(nth 2 ,img)) +(defmacro pdf-cache--image/hash (img) + "Return the hash value for IMG." + `(nth 3 ,img)) + +(defun pdf-cache--image-match (image page min-width &optional max-width hash) + "Match IMAGE with specs. + +IMAGE should be a list as created by `pdf-cache--make-image'. + +Return non-nil, if IMAGE's page is the same as PAGE, its width +is at least MIN-WIDTH and at most MAX-WIDTH and its stored +hash-value is `eql' to HASH." + (and (= (pdf-cache--image/page image) + page) + (or (null min-width) + (>= (pdf-cache--image/width image) + min-width)) + (or (null max-width) + (<= (pdf-cache--image/width image) + max-width)) + (eql (pdf-cache--image/hash image) + hash))) + +(defun pdf-cache-lookup-image (page min-width &optional max-width hash) + "Return PAGE's cached PNG data as a string or nil. + +Return an image of at least MIN-WIDTH and, if non-nil, maximum +width MAX-WIDTH and `eql' HASH value. + +Does not modify the cache. See also `pdf-cache-get-image'." + (let ((image (car (cl-member + (list page min-width max-width hash) + pdf-cache--image-cache + :test (lambda (spec image) + (apply #'pdf-cache--image-match image spec)))))) + (and image + (pdf-cache--image/data image)))) + +(defun pdf-cache-get-image (page min-width &optional max-width hash) + "Return PAGE's PNG data as a string. + +Return an image of at least MIN-WIDTH and, if non-nil, maximum +width MAX-WIDTH and `eql' HASH value. + +Remember that image was recently used. + +Returns nil, if no matching image was found." + (let ((cache pdf-cache--image-cache) + image) + ;; Find it in the cache. + (while (and (setq image (pop cache)) + (not (pdf-cache--image-match + image page min-width max-width hash)))) + ;; Remove it and push it to the front. + (when image + (setq pdf-cache--image-cache + (cons image (delq image pdf-cache--image-cache))) + (pdf-cache--image/data image)))) + +(defun pdf-cache-put-image (page width data &optional hash) + "Cache image of PAGE with WIDTH, DATA and HASH. + +DATA should the string of a PNG image of width WIDTH and from +page PAGE in the current buffer. See `pdf-cache-get-image' for +the HASH argument. + +This function always returns nil." + (unless pdf-cache--image-cache + (add-hook 'pdf-info-close-document-hook #'pdf-cache-clear-images nil t) + (add-hook 'pdf-annot-modified-functions + #'pdf-cache--clear-images-of-annotations nil t)) + (push (pdf-cache--make-image page width data hash) + pdf-cache--image-cache) + ;; Forget old image(s). + (when (> (length pdf-cache--image-cache) + pdf-cache-image-limit) + (if (> pdf-cache-image-limit 1) + (setcdr (nthcdr (1- pdf-cache-image-limit) + pdf-cache--image-cache) + nil) + (setq pdf-cache--image-cache nil))) + nil) + +(defun pdf-cache-clear-images () + "Clear the image cache." + (setq pdf-cache--image-cache nil)) + +(defun pdf-cache-clear-images-if (fn) + "Remove images from the cache according to FN. + +FN should be function accepting 4 Arguments \(PAGE WIDTH DATA +HASH\). It should return non-nil, if the image should be removed +from the cache." + (setq pdf-cache--image-cache + (cl-remove-if + (lambda (image) + (funcall + fn + (pdf-cache--image/page image) + (pdf-cache--image/width image) + (pdf-cache--image/data image) + (pdf-cache--image/hash image))) + pdf-cache--image-cache))) + + +(defun pdf-cache--clear-images-of-annotations (fn) + "Clear the images cache when annotations are modified. + +FN is a closure as described in `pdf-annot-modified-functions'. + +Note: This is an internal function and not meant to be directly used." + (apply #'pdf-cache-clear-images-of-pages + (mapcar (lambda (a) + (cdr (assq 'page a))) + (funcall fn t)))) + +(defun pdf-cache-clear-images-of-pages (&rest pages) + "Remove all images of PAGES from the image cache." + (pdf-cache-clear-images-if + (lambda (page &rest _) (memq page pages)))) + +(defun pdf-cache-renderpage (page min-width &optional max-width) + "Render PAGE according to MIN-WIDTH and MAX-WIDTH. + +Return the PNG data of an image as a string, such that its width +is at least MIN-WIDTH and, if non-nil, at most MAX-WIDTH. + +If such an image is not available in the cache, call +`pdf-info-renderpage' to create one." + (if pdf-cache-image-inihibit + (pdf-info-renderpage page min-width) + (or (pdf-cache-get-image page min-width max-width) + (let ((data (pdf-info-renderpage page min-width))) + (pdf-cache-put-image page min-width data) + data)))) + +(defun pdf-cache-renderpage-text-regions (page width single-line-p + &rest selection) + "Render PAGE according to WIDTH, SINGLE-LINE-P and SELECTION. + +See also `pdf-info-renderpage-text-regions' and +`pdf-cache-renderpage'." + (if pdf-cache-image-inihibit + (apply #'pdf-info-renderpage-text-regions + page width single-line-p nil nil selection) + (let ((hash (sxhash + (format "%S" (cons 'renderpage-text-regions + (cons single-line-p selection)))))) + (or (pdf-cache-get-image page width width hash) + (let ((data (apply #'pdf-info-renderpage-text-regions + page width single-line-p nil nil selection))) + (pdf-cache-put-image page width data hash) + data))))) + +(defun pdf-cache-renderpage-highlight (page width &rest regions) + "Highlight PAGE according to WIDTH and REGIONS. + +See also `pdf-info-renderpage-highlight' and +`pdf-cache-renderpage'." + (if pdf-cache-image-inihibit + (apply #'pdf-info-renderpage-highlight + page width nil regions) + (let ((hash (sxhash + (format "%S" (cons 'renderpage-highlight + regions))))) + (or (pdf-cache-get-image page width width hash) + (let ((data (apply #'pdf-info-renderpage-highlight + page width nil regions))) + (pdf-cache-put-image page width data hash) + data))))) + + +;; * ================================================================== * +;; * Prefetching images +;; * ================================================================== * + +(defvar-local pdf-cache--prefetch-pages nil + "Pages to be prefetched.") + +(defvar-local pdf-cache--prefetch-timer nil + "Timer used when prefetching images.") + +(define-minor-mode pdf-cache-prefetch-minor-mode + "Try to load images which will probably be needed in a while." + :group 'pdf-cache + (pdf-cache--prefetch-cancel) + (cond + (pdf-cache-prefetch-minor-mode + (pdf-util-assert-pdf-buffer) + (add-hook 'pre-command-hook #'pdf-cache--prefetch-stop nil t) + ;; FIXME: Disable the time when the buffer is killed or its + ;; major-mode changes. + (setq pdf-cache--prefetch-timer + (run-with-idle-timer (or pdf-cache-prefetch-delay 1) t + #'pdf-cache--prefetch-start (current-buffer)))) + (t + (remove-hook 'pre-command-hook #'pdf-cache--prefetch-stop t)))) + +(defun pdf-cache-prefetch-pages-function-default () + "The default function to prefetch pages. + +See `pdf-cache-prefetch-pages-function' for an explanation of +what this function does." + (let ((page (pdf-view-current-page))) + (pdf-util-remove-duplicates + (cl-remove-if-not + (lambda (page) + (and (>= page 1) + (<= page (pdf-cache-number-of-pages)))) + (append + ;; +1, -1, +2, -2, ... + (let ((sign 1) + (incr 1)) + (mapcar (lambda (_) + (setq page (+ page (* sign incr)) + sign (- sign) + incr (1+ incr)) + page) + (number-sequence 1 16))) + ;; First and last + (list 1 (pdf-cache-number-of-pages)) + ;; Links + (mapcar + (apply-partially 'alist-get 'page) + (cl-remove-if-not + (lambda (link) (eq (alist-get 'type link) 'goto-dest)) + (pdf-cache-pagelinks + (pdf-view-current-page))))))))) + +(defvar pdf-view-use-scaling) +(defun pdf-cache--prefetch-pages (window image-width) + "Internal function to prefetch pages and store them in the cache. + +WINDOW and IMAGE-WIDTH decide the page and scale of the final image." + (when (and (eq window (selected-window)) + (pdf-util-pdf-buffer-p)) + (let ((page (pop pdf-cache--prefetch-pages))) + (while (and page + (pdf-cache-lookup-image + page + image-width + (if pdf-view-use-scaling + (* 2 image-width) + image-width))) + (setq page (pop pdf-cache--prefetch-pages))) + (pdf-util-debug + (when (null page) + (message "Prefetching done."))) + (when page + (let* ((buffer (current-buffer)) + (pdf-info-asynchronous + (lambda (status data) + (when (and (null status) + (eq window + (selected-window)) + (eq buffer (window-buffer))) + (with-current-buffer (window-buffer) + (when (derived-mode-p 'pdf-view-mode) + (pdf-cache-put-image + page image-width data) + (image-size (pdf-view-create-page page)) + (pdf-util-debug + (message "Prefetched page %s." page)) + ;; Avoid max-lisp-eval-depth + (run-with-timer + 0.001 nil + #'pdf-cache--prefetch-pages window image-width))))))) + (condition-case err + (pdf-info-renderpage page image-width) + (error + (pdf-cache-prefetch-minor-mode -1) + (signal (car err) (cdr err))))))))) + +(defvar pdf-cache--prefetch-started-p nil + "Guard against multiple prefetch starts. + +Used solely in `pdf-cache--prefetch-start'.") + +(defun pdf-cache--prefetch-start (buffer) + "Start prefetching images in BUFFER." + (when (and pdf-cache-prefetch-minor-mode + (not pdf-cache--prefetch-started-p) + (pdf-util-pdf-buffer-p) + (not isearch-mode) + (null pdf-cache--prefetch-pages) + (eq (window-buffer) buffer) + (fboundp pdf-cache-prefetch-pages-function)) + (let* ((pdf-cache--prefetch-started-p t) + (pages (funcall pdf-cache-prefetch-pages-function))) + (setq pdf-cache--prefetch-pages + (butlast pages (max 0 (- (length pages) + pdf-cache-image-limit)))) + (pdf-cache--prefetch-pages + (selected-window) + (car (pdf-view-desired-image-size)))))) + +(defun pdf-cache--prefetch-stop () + "Stop prefetching images in current buffer." + (setq pdf-cache--prefetch-pages nil)) + +(defun pdf-cache--prefetch-cancel () + "Cancel prefetching images in current buffer." + (pdf-cache--prefetch-stop) + (when pdf-cache--prefetch-timer + (cancel-timer pdf-cache--prefetch-timer)) + (setq pdf-cache--prefetch-timer nil)) + +(provide 'pdf-cache) +;;; pdf-cache.el ends here diff --git a/org/elpa/pdf-tools-20230404.327/pdf-dev.el b/org/elpa/pdf-tools-20230404.327/pdf-dev.el new file mode 100644 index 0000000..6ea5d8c --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/pdf-dev.el @@ -0,0 +1,89 @@ +;;; pdf-dev.el --- Mother's little development helper -*- lexical-binding: t; -*- + +;; Copyright (C) 2015 Andreas Politz + +;; Author: Andreas Politz +;; Keywords: + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; +;; This file is only meant for developers. The entry point is +;; pdf-dev-minor-mode, which see. + +;;; Code: + +(defvar pdf-dev-root-directory + (file-name-directory + (directory-file-name + (file-name-directory load-file-name)))) + +(defun pdf-dev-reload () + "Reload Lisp files from source." + (interactive) + (let ((default-directory (expand-file-name + "lisp" + pdf-dev-root-directory)) + loaded) + (dolist (file (directory-files default-directory nil "\\`pdf-\\w*\\.el\\'")) + (push file loaded) + (load-file file)) + (message "Loaded %s" (mapconcat 'identity loaded " ")))) + +(define-minor-mode pdf-dev-minor-mode + "Make developing pdf-tools easier. + +It does the following: + +Quits the server and sets `pdf-info-epdfinfo-program' to +../server/epdfinfo. + +Installs a `compilation-finish-functions' which will restart +epdfinfo after a successful recompilation. + +Sets up `load-path' and reloads all PDF Tools Lisp files." + :group 'pdf-dev + (let ((lisp-dir (expand-file-name "lisp" pdf-dev-root-directory))) + (setq load-path (remove lisp-dir load-path)) + (cond + (pdf-dev-minor-mode + (add-hook 'compilation-finish-functions 'pdf-dev-compilation-finished) + (add-to-list 'load-path lisp-dir) + (setq pdf-info-epdfinfo-program + (expand-file-name + "epdfinfo" + (expand-file-name "server" pdf-dev-root-directory))) + (pdf-info-quit) + (pdf-dev-reload)) + (t + (remove-hook 'compilation-finish-functions 'pdf-dev-compilation-finished))))) + +(defun pdf-dev-compilation-finished (buffer status) + "Restart the epdfinfo server. + +BUFFER is the PDF buffer and STATUS is the compilation status of +building epdfinfo." + (with-current-buffer buffer + (when (and (equal status "finished\n") + (file-equal-p + (expand-file-name "server" pdf-dev-root-directory) + default-directory)) + (message "Restarting epdfinfo server") + (pdf-info-quit) + (let ((pdf-info-restart-process-p t)) + (pdf-info-process-assert-running))))) + +(provide 'pdf-dev) +;;; pdf-dev.el ends here diff --git a/org/elpa/pdf-tools-20230404.327/pdf-history.el b/org/elpa/pdf-tools-20230404.327/pdf-history.el new file mode 100644 index 0000000..e380cf5 --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/pdf-history.el @@ -0,0 +1,172 @@ +;;; pdf-history.el --- A simple stack-based history in PDF buffers. -*- lexical-binding: t -*- + +;; Copyright (C) 2013, 2014 Andreas Politz + +;; Author: Andreas Politz +;; Keywords: files, multimedia + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; + +(require 'pdf-view) +(require 'pdf-util) + +;;; Code: + +(defgroup pdf-history nil + "A simple stack-based history." + :group 'pdf-tools) + +(defvar-local pdf-history-stack nil + "The stack of history items.") + +(defvar-local pdf-history-index nil + "The current index into the `pdf-history-stack'.") + +(defvar pdf-history-minor-mode-map + (let ((kmap (make-sparse-keymap))) + (define-key kmap (kbd "B") #'pdf-history-backward) + (define-key kmap (kbd "N") #'pdf-history-forward) + (define-key kmap (kbd "l") #'pdf-history-backward) + (define-key kmap (kbd "r") #'pdf-history-forward) + kmap) + "Keymap used in `pdf-history-minor-mode'.") + +;;;###autoload +(define-minor-mode pdf-history-minor-mode + "Keep a history of previously visited pages. + +This is a simple stack-based history. Turning the page or +following a link pushes the left-behind page on the stack, which +may be navigated with the following keys. + +\\{pdf-history-minor-mode-map}" + :group 'pdf-history + (pdf-util-assert-pdf-buffer) + (pdf-history-clear) + (cond + (pdf-history-minor-mode + (pdf-history-push) + (add-hook 'pdf-view-after-change-page-hook + #'pdf-history-before-change-page-hook nil t)) + (t + (remove-hook 'pdf-view-after-change-page-hook + #'pdf-history-before-change-page-hook t)))) + +(defun pdf-history-before-change-page-hook () + "Push a history item, before leaving this page." + (when (and pdf-history-minor-mode + (not (bound-and-true-p pdf-isearch-active-mode)) + (pdf-view-current-page)) + (pdf-history-push))) + +(defun pdf-history-push () + "Push the current page on the stack. + +This function does nothing, if current stack item already +represents the current page." + (interactive) + (let ((item (pdf-history-create-item))) + (unless (and pdf-history-stack + (equal (nth pdf-history-index + pdf-history-stack) item)) + (setq pdf-history-stack + (last pdf-history-stack + (- (length pdf-history-stack) + pdf-history-index)) + pdf-history-index 0) + (push item pdf-history-stack)))) + +(defun pdf-history-clear () + "Remove all history items." + (interactive) + (setq pdf-history-stack nil + pdf-history-index 0) + (pdf-history-push)) + +(defun pdf-history-create-item () + "Create a history item representing the current page." + (list + (pdf-view-current-page))) + +(defun pdf-history-beginning-of-history-p () + "Return t, if at the beginning of the history." + (= pdf-history-index 0)) + +(defun pdf-history-end-of-history-p () + "Return t, if at the end of the history." + (= pdf-history-index + (1- (length pdf-history-stack)))) + +(defun pdf-history-backward (n) + "Go N times backward in the history." + (interactive "p") + (cond + ((and (> n 0) + (pdf-history-end-of-history-p)) + (error "End of history")) + ((and (< n 0) + (pdf-history-beginning-of-history-p)) + (error "Beginning of history")) + ((/= n 0) + (let ((i (min (max 0 (+ pdf-history-index n)) + (1- (length pdf-history-stack))))) + (prog1 + (- (+ pdf-history-index n) i) + (pdf-history-goto i)))) + (t 0))) + +(defun pdf-history-forward (n) + "Go N times forward in the history." + (interactive "p") + (pdf-history-backward (- n))) + +(defun pdf-history-goto (n) + "Go to item N in the history." + (interactive "p") + (when (null pdf-history-stack) + (error "The history is empty")) + (cond + ((>= n (length pdf-history-stack)) + (error "End of history")) + ((< n 0) + (error "Beginning of history")) + (t + (setq pdf-history-index n) + (pdf-view-goto-page + (car (nth n pdf-history-stack)))))) + +(defun pdf-history-debug () + "Visualize the history in the header-line." + (interactive) + (setq header-line-format + '(:eval + (let ((pages (mapcar 'car pdf-history-stack)) + (index pdf-history-index) + header) + (dotimes (i (length pages)) + (push (propertize + (format "%s" (nth i pages)) + 'face + (and (= i index) 'match)) + header)) + (concat + "(" (format "%d" index) ") " + (mapconcat 'identity (nreverse header) " | ")))))) + +(provide 'pdf-history) + +;;; pdf-history.el ends here diff --git a/org/elpa/pdf-tools-20230404.327/pdf-info.el b/org/elpa/pdf-tools-20230404.327/pdf-info.el new file mode 100644 index 0000000..db1dc7e --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/pdf-info.el @@ -0,0 +1,1769 @@ +;;; pdf-info.el --- Extract info from pdf-files via a helper process. -*- lexical-binding: t -*- + +;; Copyright (C) 2013, 2014 Andreas Politz + +;; Author: Andreas Politz +;; Keywords: files, multimedia + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; +;; This library represents the Lisp side of the epdfinfo server. This +;; program works on a command/response basis, but there should be no +;; need to understand the protocol, since every command has a +;; corresponding Lisp-function (see below under `High level +;; interface'). +;; +;; Most of these functions receive a file-or-buffer argument, which +;; may be what it says and defaults to the current buffer. Also, most +;; functions return some sort of alist, with, in most cases, +;; straight-forward key-value-pairs. Though some may be only +;; understandable in the context of Adobe's PDF spec \(Adobe +;; PDF32000\) or the poppler documentation (e.g. annotation flags). +;; +;; If the poppler library is fairly recent (>= 0.19.4, older versions +;; have a bug, which may corrupt the document), annotations maybe +;; modified to a certain degree, deleted and text-annotations created. +;; The state of these modifications is held in the server. In order +;; to realize, annotations retrieved or created are referenced by a +;; unique symbol. Saving these changes creates a new file, the +;; original document is never touched. + +;;; Todo: +;; +;; + Close documents at some time (e.g. when the buffer is killed) +;; + +;;; Code: + +(require 'tq) +(require 'cl-lib) + + + +;; * ================================================================== * +;; * Customizations +;; * ================================================================== * + +(defgroup pdf-info nil + "Extract infos from pdf-files via a helper process." + :group 'pdf-tools) + +(defcustom pdf-info-epdfinfo-program + (let ((executable (if (eq system-type 'windows-nt) + "epdfinfo.exe" "epdfinfo")) + (default-directory + (or (and load-file-name + (file-name-directory load-file-name)) + default-directory))) + (cl-labels ((try-directory (directory) + (and (file-directory-p directory) + (file-executable-p (expand-file-name executable directory)) + (expand-file-name executable directory)))) + (or (executable-find executable) + ;; This works if epdfinfo is in the same place as emacs and + ;; the editor was started with an absolute path, i.e. it is + ;; meant for Windows/Msys2. + (and (stringp (car-safe command-line-args)) + (file-name-directory (car command-line-args)) + (try-directory + (file-name-directory (car command-line-args)))) + ;; If we are running directly from the git repo. + (try-directory (expand-file-name "../server")) + ;; Fall back to epdfinfo in the directory of this file. + (expand-file-name executable)))) + "Filename of the epdfinfo executable." + :type 'file) + +(defcustom pdf-info-epdfinfo-error-filename nil + "Filename for error output of the epdfinfo executable. + +If nil, discard any error messages. Useful for debugging." + :type `(choice (const :tag "None" nil) + ,@(when (file-directory-p "/tmp/") + '((const "/tmp/epdfinfo.log"))) + (file))) + +(defcustom pdf-info-log nil + "Whether to log the communication with the server. + +If this is non-nil, all communication with the epdfinfo program +will be logged to the buffer \"*pdf-info-log*\"." + :type 'boolean) + +(defcustom pdf-info-log-entry-max 512 + "Maximum number of characters in a single log entry. + +This variable has no effect if `pdf-info-log' is nil." + :type 'integer) + +(defcustom pdf-info-restart-process-p 'ask + "What to do when the epdfinfo server died. + +This should be one of +nil -- do nothing, +t -- automatically restart it or +ask -- ask whether to restart or not. + +If it is `ask', the server quits and you answer no, this variable +is set to nil." + :type '(choice (const :tag "Do nothing" nil) + (const :tag "Restart silently" t) + (const :tag "Always ask" ask))) + +(defcustom pdf-info-close-document-hook nil + "A hook ran after a document was closed in the server. + +The hook is run in the documents buffer, if it exists. Otherwise +in a `with-temp-buffer' form." + :type 'hook) + + + +;; * ================================================================== * +;; * Variables +;; * ================================================================== * + +(defvar pdf-info-asynchronous nil + "If non-nil process queries asynchronously. + +More specifically the value should be a function of at 2 +arguments \(fn STATUS RESPONSE\), where STATUS is either nil, for +a successful query, or the symbol error. RESPONSE is either the +command's response or the error message. This does not work +recursive, i.e. if function wants to make another asynchronous +query it has to rebind this variable. + +Alternatively it may be a list \(FN . ARGS\), in which case FN +will be invoked like \(apply FN STATUS RESPONSE ARGS\). + +Also, all pdf-info functions normally returning a response return +nil. + +This variable should only be let-bound.") + +(defconst pdf-info-pdf-date-regexp + ;; Adobe PDF32000.book, 7.9.4 Dates + (eval-when-compile + (concat + ;; allow for preceding garbage + ;;"\\`" + "[dD]:" + "\\([0-9]\\{4\\}\\)" ;year + "\\(?:" + "\\([0-9]\\{2\\}\\)" ;month + "\\(?:" + "\\([0-9]\\{2\\}\\)" ;day + "\\(?:" + "\\([0-9]\\{2\\}\\)" ;hour + "\\(?:" + "\\([0-9]\\{2\\}\\)" ;minutes + "\\(?:" + "\\([0-9]\\{2\\}\\)" ;seconds + "\\)?\\)?\\)?\\)?\\)?" + "\\(?:" + "\\([+-Zz]\\)" ;UT delta char + "\\(?:" + "\\([0-9]\\{2\\}\\)" ;UT delta hours + "\\(?:" + "'" + "\\([0-9]\\{2\\}\\)" ;UT delta minutes + "\\)?\\)?\\)?" + ;; "\\'" + ;; allow for trailing garbage + ))) + +(defvar pdf-info--queue t + "Internally used transmission-queue for the server. + +This variable is initially t, telling the code starting the +server, that it never ran.") + + +;; * ================================================================== * +;; * Process handling +;; * ================================================================== * + +(defconst pdf-info-empty-page-data + (eval-when-compile + (concat + "%PDF-1.0\n1 0 obj<>endobj 2 0" + " obj<>endobj 3 0 obj<>endobj\nxref\n0 4\n00000000" + "0065535 f\n0000000010 00000 n\n0000000053 00000 n\n00000" + "00102 00000 n\ntrailer<>\nstartxref\n149\n%EOF")) + "PDF data of an empty page.") + +(defun pdf-info-process () + "Return the process object or nil." + (and pdf-info--queue + (not (eq t pdf-info--queue)) + (tq-process pdf-info--queue))) + +(defun pdf-info-check-epdfinfo (&optional interactive-p) + "Check if the server should be working properly. + +Signal an error if some problem was found. Message a +confirmation, if INTERACTIVE-P is non-nil and no problems were +found. + +Returns nil." + (interactive "p") + (let ((executable pdf-info-epdfinfo-program)) + (unless (stringp executable) + (error "pdf-info-epdfinfo-program is unset or not a string")) + (unless (file-executable-p executable) + (error "pdf-info-epdfinfo-program is not executable")) + (when pdf-info-epdfinfo-error-filename + (unless (and (stringp pdf-info-epdfinfo-error-filename) + (file-writable-p pdf-info-epdfinfo-error-filename)) + (error "pdf-info-epdfinfo-error-filename should contain writable filename"))) + (let* ((default-directory (expand-file-name "~/")) + (cmdfile (make-temp-file "commands")) + (pdffile (make-temp-file "empty.pdf")) + (tempdir (make-temp-file "tmpdir" t)) + (process-environment (cons (concat "TMPDIR=" tempdir) + process-environment))) + (unwind-protect + (with-temp-buffer + (with-temp-file pdffile + (set-buffer-multibyte nil) + (insert pdf-info-empty-page-data)) + (with-temp-file cmdfile + (insert (format "renderpage:%s:1:100\nquit\n" + (pdf-info-query--escape pdffile)))) + (unless (= 0 (apply #'call-process + executable cmdfile (current-buffer) + nil (when pdf-info-epdfinfo-error-filename + (list pdf-info-epdfinfo-error-filename)))) + (error "Error running `%s': %s" + pdf-info-epdfinfo-program + (buffer-string)))) + (when (file-exists-p cmdfile) + (delete-file cmdfile)) + (when (file-exists-p pdffile) + (delete-file pdffile)) + (when (file-exists-p tempdir) + (delete-directory tempdir t))))) + (when interactive-p + (message "The epdfinfo program appears to be working.")) + nil) + +(defun pdf-info-process-assert-running (&optional force) + "Assert a running process. + +If it never ran, i.e. `pdf-info-process' is t, start it +unconditionally. + +Otherwise, if FORCE is non-nil start it, if it is not running. +Else restart it with respect to the variable +`pdf-info-restart-process-p', which see. + +If getting the process to run fails, this function throws an +error." + (interactive "P") + (unless (and (processp (pdf-info-process)) + (eq (process-status (pdf-info-process)) + 'run)) + (when (pdf-info-process) + (tq-close pdf-info--queue) + (setq pdf-info--queue nil)) + (unless (or force + (eq pdf-info--queue t) + (and (eq pdf-info-restart-process-p 'ask) + (not noninteractive) + (y-or-n-p "The epdfinfo server quit, restart it ? ")) + (and pdf-info-restart-process-p + (not (eq pdf-info-restart-process-p 'ask)))) + + (when (eq pdf-info-restart-process-p 'ask) + (setq pdf-info-restart-process-p nil)) + (error "The epdfinfo server quit")) + (pdf-info-check-epdfinfo) + (let* ((process-connection-type) ;Avoid 4096 Byte bug #12440. + (default-directory "~") + (proc (apply #'start-process + "epdfinfo" " *epdfinfo*" pdf-info-epdfinfo-program + (when pdf-info-epdfinfo-error-filename + (list pdf-info-epdfinfo-error-filename))))) + (with-current-buffer " *epdfinfo*" + (erase-buffer)) + (set-process-query-on-exit-flag proc nil) + (set-process-coding-system proc 'utf-8-unix 'utf-8-unix) + (setq pdf-info--queue (tq-create proc)))) + pdf-info--queue) + +(when (< emacs-major-version 27) + (advice-add 'tq-process-buffer :around #'pdf-info--tq-workaround)) + +(defun pdf-info--tq-workaround (orig-fun tq &rest args) + "Fix a bug in trunk where the wrong callback gets called. + +ORIG-FUN is the callback that should be called. TQ and ARGS are +the transmission-queue and arguments to the callback." + ;; FIXME: Make me iterative. + (if (not (equal (car (process-command (tq-process tq))) + pdf-info-epdfinfo-program)) + (apply orig-fun tq args) + (let ((buffer (tq-buffer tq)) + done) + (when (buffer-live-p buffer) + (set-buffer buffer) + (while (and (not done) + (> (buffer-size) 0)) + (setq done t) + (if (tq-queue-empty tq) + (let ((buf (generate-new-buffer "*spurious*"))) + (copy-to-buffer buf (point-min) (point-max)) + (delete-region (point-min) (point)) + (pop-to-buffer buf nil) + (error "Spurious communication from process %s, see buffer %s" + (process-name (tq-process tq)) + (buffer-name buf))) + (goto-char (point-min)) + (when (re-search-forward (tq-queue-head-regexp tq) nil t) + (setq done nil) + (let ((answer (buffer-substring (point-min) (point))) + (fn (tq-queue-head-fn tq)) + (closure (tq-queue-head-closure tq))) + (delete-region (point-min) (point)) + (tq-queue-pop tq) + (condition-case-unless-debug err + (funcall fn closure answer) + (error + (message "Error while processing tq callback: %s" + (error-message-string err)))))))))))) + + +;; * ================================================================== * +;; * Sending and receiving +;; * ================================================================== * + +(defun pdf-info-query (cmd &rest args) + "Query the server using CMD and ARGS." + (pdf-info-process-assert-running) + (unless (symbolp cmd) + (setq cmd (intern cmd))) + (let* ((query (concat (mapconcat #'pdf-info-query--escape + (cons cmd args) ":") + "\n")) + (callback + (lambda (closure response) + (cl-destructuring-bind (status &rest result) + (pdf-info-query--parse-response cmd response) + (pdf-info-query--log response) + (let* (pdf-info-asynchronous) + (if (functionp closure) + (funcall closure status result) + (apply (car closure) status result (cdr closure))))))) + response status done + (closure (or pdf-info-asynchronous + (lambda (s r) + (setq status s response r done t))))) + (pdf-info-query--log query t) + (tq-enqueue + pdf-info--queue query "^\\.\n" closure callback) + (unless pdf-info-asynchronous + (while (and (not done) + (eq (process-status (pdf-info-process)) + 'run)) + (accept-process-output (pdf-info-process) 0.01)) + (when (and (not done) + (not (eq (process-status (pdf-info-process)) + 'run)) + (not (eq cmd 'quit))) + (error "The epdfinfo server quit unexpectedly")) + (cond + ((null status) response) + ((eq status 'error) + (error "epdfinfo: %s" response)) + ((eq status 'interrupted) + (error "epdfinfo: Command was interrupted")) + (t + (error "Internal error: invalid response status")))))) + +(defun pdf-info-interrupt () + "FIXME: This command does currently nothing." + (when (and (processp (pdf-info-process)) + (eq (process-status (pdf-info-process)) + 'run)) + (signal-process (pdf-info-process) 'SIGUSR1))) + +(defun pdf-info-query--escape (arg) + "Escape ARG for transmission to the server." + (if (null arg) + (string) + (with-current-buffer (get-buffer-create " *pdf-info-query--escape*") + (erase-buffer) + (insert (format "%s" arg)) + (goto-char 1) + (while (not (eobp)) + (cond + ((memq (char-after) '(?\\ ?:)) + (insert ?\\)) + ((eq (char-after) ?\n) + (delete-char 1) + (insert ?\\ ?n) + (backward-char))) + (forward-char)) + (buffer-substring-no-properties 1 (point-max))))) + +(defmacro pdf-info-query--read-record () + "Read a single record of the response in current buffer." + `(let (records done (beg (point))) + (while (not done) + (cl-case (char-after) + (?\\ + (delete-char 1) + (if (not (eq (char-after) ?n)) + (forward-char) + (delete-char 1) + (insert ?\n))) + ((?: ?\n) + (push (buffer-substring-no-properties + beg (point)) records) + (forward-char) + (setq beg (point) + done (bolp))) + (t (forward-char)))) + (nreverse records))) + +(defun pdf-info-query--parse-response (cmd response) + "Parse one epdfinfo RESPONSE to CMD. + +Returns a cons \(STATUS . RESULT\), where STATUS is one of nil +for a regular response, error for an error \(RESULT contains the +error message\) or interrupted, i.e. the command was +interrupted." + (with-current-buffer + (get-buffer-create " *pdf-info-query--parse-response*") + (erase-buffer) + (insert response) + (goto-char 1) + (cond + ((looking-at "ERR\n") + (forward-line) + (cons 'error (buffer-substring-no-properties + (point) + (progn + (re-search-forward "^\\.\n") + (1- (match-beginning 0)))))) + ((looking-at "OK\n") + (let (result) + (forward-line) + (while (not (and (= (char-after) ?.) + (= (char-after (1+ (point))) ?\n))) + (push (pdf-info-query--read-record) result)) + (cons nil (pdf-info-query--transform-response + cmd (nreverse result))))) + ((looking-at "INT\n") + (cons 'interrupted nil)) + (t + (cons 'error "Invalid server response"))))) + +(defun pdf-info-query--transform-response (cmd response) + "Transform a RESPONSE to CMD into a Lisp form." + (cl-case cmd + (open nil) + (close (equal "1" (caar response))) + (number-of-pages (string-to-number (caar response))) + (charlayout + (mapcar (lambda (elt) + (cl-assert (= 1 (length (cadr elt))) t) + `(,(aref (cadr elt) 0) + ,(mapcar #'string-to-number + (split-string (car elt) " " t)))) + response)) + (regexp-flags + (mapcar (lambda (elt) + (cons (intern (car elt)) + (string-to-number (cadr elt)))) + response)) + ((search-string search-regexp) + (mapcar + (lambda (r) + `((page . ,(string-to-number (nth 0 r))) + (text . ,(let (case-fold-search) + (pdf-util-highlight-regexp-in-string + (regexp-quote (nth 1 r)) (nth 2 r)))) + (edges . ,(mapcar (lambda (m) + (mapcar #'string-to-number + (split-string m " " t))) + (cddr (cdr r)))))) + response)) + (outline + (mapcar (lambda (r) + `((depth . ,(string-to-number (pop r))) + ,@(pdf-info-query--transform-action r))) + response)) + (pagelinks + (mapcar (lambda (r) + `((edges . + ,(mapcar #'string-to-number ;area + (split-string (pop r) " " t))) + ,@(pdf-info-query--transform-action r))) + response)) + (metadata + (let ((md (car response))) + (if (= 1 (length md)) + (list (cons 'title (car md))) + (list + (cons 'title (pop md)) + (cons 'author (pop md)) + (cons 'subject (pop md)) + (cons 'keywords-raw (car md)) + (cons 'keywords (split-string (pop md) "[\t\n ]*,[\t\n ]*" t)) + (cons 'creator (pop md)) + (cons 'producer (pop md)) + (cons 'format (pop md)) + (cons 'created (pop md)) + (cons 'modified (pop md)))))) + (gettext + (or (caar response) "")) + (getselection + (mapcar (lambda (line) + (mapcar #'string-to-number + (split-string (car line) " " t))) + response)) + (features (mapcar #'intern (car response))) + (pagesize + (setq response (car response)) + (cons (round (string-to-number (car response))) + (round (string-to-number (cadr response))))) + ((getannot editannot addannot) + (pdf-info-query--transform-annotation (car response))) + (getannots + (mapcar #'pdf-info-query--transform-annotation response)) + (getattachments + (mapcar #'pdf-info-query--transform-attachment response)) + ((getattachment-from-annot) + (pdf-info-query--transform-attachment (car response))) + (boundingbox + (mapcar #'string-to-number (car response))) + (synctex-forward-search + (let ((list (mapcar #'string-to-number (car response)))) + `((page . ,(car list)) + (edges . ,(cdr list))))) + (synctex-backward-search + `((filename . ,(caar response)) + (line . ,(string-to-number (cadr (car response)))) + (column . ,(string-to-number (cadr (cdar response)))))) + (delannot nil) + ((save) (caar response)) + ((renderpage renderpage-text-regions renderpage-highlight) + (pdf-util-munch-file (caar response))) + ((setoptions getoptions) + (let (options) + (dolist (key-value response) + (let ((key (intern (car key-value))) + (value (cadr key-value))) + (cl-case key + ((:render/printed) + (setq value (equal value "1"))) + ((:render/usecolors) + (setq value (ignore-errors + (let ((int-val (cl-parse-integer value))) + (if (> 3 int-val 0) + int-val + 0)))))) + (push value options) + (push key options))) + options)) + (pagelabels (mapcar #'car response)) + (ping (caar response)) + (t response))) + + +(defun pdf-info-query--transform-action (action) + "Transform ACTION response into a Lisp form." + (let ((type (intern (pop action)))) + `((type . ,type) + (title . ,(pop action)) + ,@(cl-case type + (goto-dest + `((page . ,(string-to-number (pop action))) + (top . ,(and (> (length (car action)) 0) + (string-to-number (pop action)))))) + (goto-remote + `((filename . ,(pop action)) + (page . ,(string-to-number (pop action))) + (top . ,(and (> (length (car action)) 0) + (string-to-number (pop action)))))) + (t `((uri . ,(pop action)))))))) + +(defun pdf-info-query--transform-annotation (a) + (cl-labels ((not-empty (s) + (if (not (equal s "")) s))) + (let (a1 a2 a3) + (cl-destructuring-bind (page edges type id flags color contents modified &rest rest) + a + (setq a1 `((page . ,(string-to-number page)) + (edges . ,(mapcar #'string-to-number + (split-string edges " " t))) + (type . ,(intern type)) + (id . ,(intern id)) + (flags . ,(string-to-number flags)) + (color . ,(not-empty color)) + (contents . ,contents) + (modified . ,(pdf-info-parse-pdf-date modified)))) + (when rest + (cl-destructuring-bind (label subject opacity popup-edges popup-is-open created + &rest rest) + rest + (setq a2 + `((label . ,(not-empty label)) + (subject . ,(not-empty subject)) + (opacity . ,(let ((o (not-empty opacity))) + (and o (string-to-number o)))) + (popup-edges . ,(let ((p (not-empty popup-edges))) + (when p + (mapcar #'string-to-number + (split-string p " " t))))) + (popup-is-open . ,(equal popup-is-open "1")) + (created . ,(pdf-info-parse-pdf-date (not-empty created))))) + (cond + ((eq (cdr (assoc 'type a1)) 'text) + (cl-destructuring-bind (icon state is-open) + rest + (setq a3 + `((icon . ,(not-empty icon)) + (state . ,(not-empty state)) + (is-open . ,(equal is-open "1")))))) + ((memq (cdr (assoc 'type a1)) + '(squiggly highlight underline strike-out)) + (setq a3 `((markup-edges + . ,(mapcar (lambda (r) + (mapcar #'string-to-number + (split-string r " " t))) + rest))))))))) + (append a1 a2 a3)))) + +(defun pdf-info-query--transform-attachment (a) + (cl-labels ((not-empty (s) + (if (not (equal s "")) s))) + (cl-destructuring-bind (id filename description size modified + created checksum file) + a + `((id . ,(intern id)) + (filename . ,(not-empty filename)) + (description . ,(not-empty description)) + (size . ,(let ((n (string-to-number size))) + (and (>= n 0) n))) + (modified . ,(not-empty modified)) + (created . ,(not-empty created)) + (checksum . ,(not-empty checksum)) + (file . ,(not-empty file)))))) + +(defun pdf-info-query--log (string &optional query-p) + "Log STRING as query/response, depending on QUERY-P. + +This is a no-op, if `pdf-info-log' is nil." + (when pdf-info-log + (with-current-buffer (get-buffer-create "*pdf-info-log*") + (buffer-disable-undo) + (let ((pos (point-max)) + (window (get-buffer-window))) + (save-excursion + (goto-char (point-max)) + (unless (bolp) + (insert ?\n)) + (insert + (propertize + (format-time-string "%H:%M:%S ") + 'face + (if query-p + 'font-lock-keyword-face + 'font-lock-function-name-face)) + (if (and (numberp pdf-info-log-entry-max) + (> (length string) + pdf-info-log-entry-max)) + (concat (substring string 0 pdf-info-log-entry-max) + "...[truncated]\n") + string))) + (when (and (window-live-p window) + (= pos (window-point window))) + (set-window-point window (point-max))))))) + + + +;; * ================================================================== * +;; * Utility functions +;; * ================================================================== * + +(defvar doc-view-buffer-file-name) +(defvar doc-view--buffer-file-name) + +(defun pdf-info--normalize-file-or-buffer (file-or-buffer) + "Return the PDF file corresponding to FILE-OR-BUFFER. + +FILE-OR-BUFFER may be nil, a PDF buffer, the name of a PDF buffer +or a PDF file." + (unless file-or-buffer + (setq file-or-buffer + (current-buffer))) + (when (bufferp file-or-buffer) + (unless (buffer-live-p file-or-buffer) + (error "Buffer is not live :%s" file-or-buffer)) + (with-current-buffer file-or-buffer + (unless (setq file-or-buffer + (cl-case major-mode + (doc-view-mode + (cond ((boundp 'doc-view-buffer-file-name) + doc-view-buffer-file-name) + ((boundp 'doc-view--buffer-file-name) + doc-view--buffer-file-name))) + (pdf-view-mode (pdf-view-buffer-file-name)) + (t (buffer-file-name)))) + (error "Buffer is not associated with any file :%s" (buffer-name))))) + (unless (stringp file-or-buffer) + (signal 'wrong-type-argument + (list 'stringp 'bufferp 'null file-or-buffer))) + ;; is file + (when (file-remote-p file-or-buffer) + (error "Processing remote files not supported :%s" + file-or-buffer)) + ;; (unless (file-readable-p file-or-buffer) + ;; (error "File not readable :%s" file-or-buffer)) + (expand-file-name file-or-buffer)) + +(defun pdf-info-valid-page-spec-p (pages) + "The type predicate for a valid page-spec." + (not (not (ignore-errors (pdf-info-normalize-page-range pages))))) + +(defun pdf-info-normalize-page-range (pages) + "Normalize PAGES for sending to the server. + +PAGES may be a single page number, a cons \(FIRST . LAST\), or +nil, which stands for all pages. + +The result is a cons \(FIRST . LAST\), where LAST may be 0 +representing the final page." + (cond + ((natnump pages) + (cons pages pages)) + ((null pages) + (cons 1 0)) + ((and (natnump (car pages)) + (natnump (cdr pages))) + pages) + (t + (signal 'wrong-type-argument + (list 'pdf-info-valid-page-spec-p pages))))) + +(defun pdf-info-parse-pdf-date (date) + (when (and date + (string-match pdf-info-pdf-date-regexp date)) + (let ((year (match-string 1 date)) + (month (match-string 2 date)) + (day (match-string 3 date)) + (hour (match-string 4 date)) + (min (match-string 5 date)) + (sec (match-string 6 date)) + (ut-char (match-string 7 date)) + (ut-hour (match-string 8 date)) + (ut-min (match-string 9 date)) + (tz 0)) + (when (or (equal ut-char "+") + (equal ut-char "-")) + (when ut-hour + (setq tz (* 3600 (string-to-number ut-hour)))) + (when ut-min + (setq tz (+ tz (* 60 (string-to-number ut-min))))) + (when (equal ut-char "-") + (setq tz (- tz)))) + (encode-time + (if sec (string-to-number sec) 0) + (if min (string-to-number min) 0) + (if hour (string-to-number hour) 0) + (if day (string-to-number day) 1) + (if month (string-to-number month) 1) + (string-to-number year) + tz)))) + +(defmacro pdf-info-compose-queries (let-forms &rest body) + "Let-bind each VAR to QUERIES results and evaluate BODY. + +All queries in each QUERIES form are run by the server in the +order they appear and the results collected in a list, which is +bound to VAR. Then BODY is evaluated and its value becomes the +final result of all queries, unless at least one of them provoked +an error. In this case BODY is ignored and the error is the +result. + +This macro handles synchronous and asynchronous calls, +i.e. `pdf-info-asynchronous' is non-nil, transparently. + +\(FN \(\(VAR QUERIES\)...\) BODY\)" + (declare (indent 1) + (debug ((&rest &or + (symbolp &optional form) + symbolp) + body))) + (unless (cl-every (lambda (form) + (when (symbolp form) + (setq form (list form))) + (and (consp form) + (symbolp (car form)) + (listp (cdr form)))) + let-forms) + (error "Invalid let-form: %s" let-forms)) + + (setq let-forms (mapcar (lambda (form) + (if (symbolp form) + (list form) + form)) + let-forms)) + (let* ((status (make-symbol "status")) + (response (make-symbol "response")) + (first-error (make-symbol "first-error")) + (done (make-symbol "done")) + (callback (make-symbol "callback")) + (results (make-symbol "results")) + (push-fn (make-symbol "push-fn")) + (terminal-fn (make-symbol "terminal-fn")) + (buffer (make-symbol "buffer"))) + `(let* (,status + ,response ,first-error ,done + (,buffer (current-buffer)) + (,callback pdf-info-asynchronous) + ;; Ensure a new alist on every invocation. + (,results (mapcar 'copy-sequence + ',(cl-mapcar (lambda (form) + (list (car form))) + let-forms))) + (,push-fn (lambda (status result var) + ;; Store result in alist RESULTS under key + ;; VAR. + (if status + (unless ,first-error + (setq ,first-error result)) + (let ((elt (assq var ,results))) + (setcdr elt (append (cdr elt) + (list result))))))) + (,terminal-fn + (lambda (&rest _) + ;; Let-bind responses corresponding to their variables, + ;; i.e. keys in alist RESULTS. + (let (,@(mapcar (lambda (var) + `(,var (cdr (assq ',var ,results)))) + (mapcar #'car let-forms))) + (setq ,status (not (not ,first-error)) + ,response (or ,first-error + (with-current-buffer ,buffer + ,@body)) + ,done t) + ;; Maybe invoke the CALLBACK (which was bound to + ;; pdf-info-asynchronous). + (when ,callback + (if (functionp ,callback) + (funcall ,callback ,status ,response) + (apply (car ,callback) + ,status ,response (cdr ,callback)))))))) + ;; Wrap each query in an asynchronous call, with its VAR as + ;; callback argument, so the PUSH-FN can put it in the alist + ;; RESULTS. + ,@(mapcar (lambda (form) + (list 'let (list + (list 'pdf-info-asynchronous + (list 'list push-fn (list 'quote (car form))))) + (cadr form))) + let-forms) + ;; Request a no-op, just so we know that we are finished. + (let ((pdf-info-asynchronous ,terminal-fn)) + (pdf-info-ping)) + ;; CALLBACK is the original value of pdf-info-asynchronous. If + ;; nil, this is a synchronous query. + (unless ,callback + (while (and (not ,done) + (eq (process-status (pdf-info-process)) + 'run)) + (accept-process-output (pdf-info-process) 0.01)) + (when (and (not ,done) + (not (eq (process-status (pdf-info-process)) + 'run))) + (error "The epdfinfo server quit unexpectedly")) + (when ,status + (error "epdfinfo: %s" ,response)) + ,response)))) + + +;; * ================================================================== * +;; * Buffer local server instances +;; * ================================================================== * + +(put 'pdf-info--queue 'permanent-local t) + +(defun pdf-info-make-local-server (&optional buffer force-restart-p) + "Create a server instance local to BUFFER. + +Does nothing if BUFFER already has a local instance. Unless +FORCE-RESTART-P is non-nil, then quit a potential process and +restart it." + (unless buffer + (setq buffer (current-buffer))) + (with-current-buffer buffer + (unless (and + (not force-restart-p) + (local-variable-p 'pdf-info--queue) + (processp (pdf-info-process)) + (eq (process-status (pdf-info-process)) + 'run)) + (when (and (local-variable-p 'pdf-info--queue) + (processp (pdf-info-process))) + (tq-close pdf-info--queue)) + (set (make-local-variable 'pdf-info--queue) nil) + (pdf-info-process-assert-running t) + (add-hook 'kill-buffer-hook #'pdf-info-kill-local-server nil t) + pdf-info--queue))) + +(defun pdf-info-kill-local-server (&optional buffer) + "Kill the local server in BUFFER. + +A No-op, if BUFFER has not running server instance." + (save-current-buffer + (when buffer + (set-buffer buffer)) + (when (local-variable-p 'pdf-info--queue) + (pdf-info-kill) + (kill-local-variable 'pdf-info--queue) + t))) + +(defun pdf-info-local-server-p (&optional buffer) + "Return non-nil, if BUFFER has a running server instance." + (unless buffer + (setq buffer (current-buffer))) + (setq buffer (get-buffer buffer)) + (and (buffer-live-p buffer) + (local-variable-p 'pdf-info--queue buffer))) + +(defun pdf-info-local-batch-query (producer-fn + consumer-fn + sentinel-fn + args) + "Process a set of queries asynchronously in a local instance." + (unless (pdf-info-local-server-p) + (error "Create a local server first")) + (let* ((buffer (current-buffer)) + (producer-symbol (make-symbol "producer")) + (consumer-symbol (make-symbol "consumer")) + (producer + (lambda (args) + (if (null args) + (funcall sentinel-fn 'finished buffer) + (let ((pdf-info-asynchronous + (apply-partially + (symbol-function consumer-symbol) + args))) + (cond + ((pdf-info-local-server-p buffer) + (with-current-buffer buffer + (apply producer-fn (car args)))) + (t + (funcall sentinel-fn 'error buffer))))))) + (consumer (lambda (args status result) + (if (not (pdf-info-local-server-p buffer)) + (funcall sentinel-fn 'error buffer) + (with-current-buffer buffer + (apply consumer-fn status result (car args))) + (funcall (symbol-function producer-symbol) + (cdr args)))))) + (fset producer-symbol producer) + (fset consumer-symbol consumer) + (funcall producer args))) + + + +;; * ================================================================== * +;; * High level interface +;; * ================================================================== * + +(defvar pdf-info-features nil) + +(defun pdf-info-features () + "Return a list of symbols describing compile-time features." + (or pdf-info-features + (setq pdf-info-features + (let (pdf-info-asynchronous) + (pdf-info-query 'features))))) + +(defun pdf-info-writable-annotations-p () + (not (null (memq 'writable-annotations (pdf-info-features))))) + +(defun pdf-info-markup-annotations-p () + (not (null (memq 'markup-annotations (pdf-info-features))))) + +(defmacro pdf-info-assert-writable-annotations () + `(unless (memq 'writable-annotations (pdf-info-features)) + (error "Writing annotations is not supported by this version of epdfinfo"))) + +(defmacro pdf-info-assert-markup-annotations () + `(unless (memq 'markup-annotations (pdf-info-features)) + (error "Creating markup annotations is not supported by this version of epdfinfo"))) + +(defun pdf-info-creatable-annotation-types () + (let ((features (pdf-info-features))) + (cond + ((not (memq 'writable-annotations features)) nil) + ((memq 'markup-annotations features) + (list 'text 'squiggly 'underline 'strike-out 'highlight)) + (t (list 'text))))) + +(defun pdf-info-open (&optional file-or-buffer password) + "Open the document FILE-OR-BUFFER using PASSWORD. + +Generally, documents are opened and closed automatically on +demand, so this function is rarely needed, unless a PASSWORD is +set on the document. + +Manually opened documents are never closed automatically." + + (pdf-info-query + 'open (pdf-info--normalize-file-or-buffer file-or-buffer) + password)) + +(defun pdf-info-close (&optional file-or-buffer) + "Close the document FILE-OR-BUFFER. + +Returns t, if the document was actually open, otherwise nil. +This command is rarely needed, see also `pdf-info-open'." + (let* ((pdf (pdf-info--normalize-file-or-buffer file-or-buffer)) + (buffer (cond + ((not file-or-buffer) (current-buffer)) + ((bufferp file-or-buffer) file-or-buffer) + ((stringp file-or-buffer) + (find-buffer-visiting file-or-buffer))))) + (prog1 + (pdf-info-query 'close pdf) + (if (buffer-live-p buffer) + (with-current-buffer buffer + (run-hooks 'pdf-info-close-document-hook)) + (with-temp-buffer + (run-hooks 'pdf-info-close-document-hook)))))) + +(defun pdf-info-encrypted-p (&optional file-or-buffer) + "Return non-nil if FILE-OR-BUFFER requires a password. + +Note: This function returns nil, if the document is encrypted, +but was already opened (presumably using a password)." + + (condition-case err + (pdf-info-open + (pdf-info--normalize-file-or-buffer file-or-buffer)) + (error (or (string-match-p + ":Document is encrypted\\'" (cadr err)) + (signal (car err) (cdr err)))))) + +(defun pdf-info-metadata (&optional file-or-buffer) + "Extract the metadata from the document FILE-OR-BUFFER. + +This returns an alist containing some information about the +document." + (pdf-info-query + 'metadata + (pdf-info--normalize-file-or-buffer file-or-buffer))) + +(defun pdf-info-search-string (string &optional pages file-or-buffer) + "Search for STRING in PAGES of document FILE-OR-BUFFER. + +See `pdf-info-normalize-page-range' for valid PAGES formats. + +This function returns a list of matches. Each item is an alist +containing keys PAGE, TEXT and EDGES, where PAGE and TEXT are the +matched page resp. line. EDGES is a list containing a single +edges element \(LEFT TOP RIGHT BOTTOM\). This is for consistency +with `pdf-info-search-regexp', which may return matches with +multiple edges. + +The TEXT contains `match' face properties on the matched parts. + +Search is case-insensitive, unless `case-fold-search' is nil and +searching case-sensitive is supported by the server." + + (let ((pages (pdf-info-normalize-page-range pages))) + (pdf-info-query + 'search-string + (pdf-info--normalize-file-or-buffer file-or-buffer) + (car pages) + (cdr pages) + string + (if case-fold-search 1 0)))) + +(defvar pdf-info-regexp-compile-flags nil + "PCRE compile flags. + +Don't use this, but the equally named function.") + +(defvar pdf-info-regexp-match-flags nil + "PCRE match flags. + +Don't use this, but the equally named function.") + +(defun pdf-info-regexp-compile-flags () + (or pdf-info-regexp-compile-flags + (let* (pdf-info-asynchronous + (flags (pdf-info-query 'regexp-flags)) + (match (cl-remove-if-not + (lambda (flag) + (string-match-p + "\\`match-" (symbol-name (car flag)))) + flags)) + (compile (cl-set-difference flags match))) + (setq pdf-info-regexp-compile-flags compile + pdf-info-regexp-match-flags match) + pdf-info-regexp-compile-flags))) + +(defun pdf-info-regexp-match-flags () + (or pdf-info-regexp-match-flags + (progn + (pdf-info-regexp-compile-flags) + pdf-info-regexp-match-flags))) + +(defvar pdf-info-regexp-flags '(multiline) + "Compile- and match-flags for the PCRE engine. + +This is a list of symbols denoting compile- and match-flags when +searching for regular expressions. + +You should not change this directly, but rather `let'-bind it +around a call to `pdf-info-search-regexp'. + +Valid compile-flags are: + +newline-crlf, newline-lf, newline-cr, dupnames, optimize, +no-auto-capture, raw, ungreedy, dollar-endonly, anchored, +extended, dotall, multiline and caseless. + +Note that the last one, caseless, is handled special, as it is +always added if `case-fold-search' is non-nil. + +And valid match-flags: + +match-anchored, match-notbol, match-noteol, match-notempty, +match-partial, match-newline-cr, match-newline-lf, +match-newline-crlf and match-newline-any. + +See the glib documentation at url +`https://developer.gnome.org/glib/stable/glib-Perl-compatible-regular-expressions.html'.") + +(defun pdf-info-search-regexp (pcre &optional pages + no-error + file-or-buffer) + "Search for a PCRE on PAGES of document FILE-OR-BUFFER. + +See `pdf-info-normalize-page-range' for valid PAGES formats and +`pdf-info-search-string' for its return value. + +Uses the flags in `pdf-info-regexp-flags', which see. If +`case-fold-search' is non-nil, the caseless flag is added. + +If NO-ERROR is non-nil, catch errors due to invalid regexps and +return nil. If it is the symbol `invalid-regexp', then re-signal +this kind of error as a `invalid-regexp' error." + + (cl-labels ((orflags (flags alist) + (cl-reduce + (lambda (v flag) + (let ((n + (cdr (assq flag alist)))) + (if n (logior n v) v))) + (cons 0 flags)))) + (let ((pages (pdf-info-normalize-page-range pages))) + (condition-case err + (pdf-info-query + 'search-regexp + (pdf-info--normalize-file-or-buffer file-or-buffer) + (car pages) + (cdr pages) + pcre + (orflags `(,(if case-fold-search + 'caseless) + ,@pdf-info-regexp-flags) + (pdf-info-regexp-compile-flags)) + (orflags pdf-info-regexp-flags + (pdf-info-regexp-match-flags))) + (error + (let ((re + (concat "\\`epdfinfo: *Invalid *regexp: *" + ;; glib error + "\\(?:Error while compiling regular expression" + " *%s *\\)?\\(.*\\)"))) + (if (or (null no-error) + (not (string-match + (format re (regexp-quote pcre)) + (cadr err)))) + (signal (car err) (cdr err)) + (if (eq no-error 'invalid-regexp) + (signal 'invalid-regexp + (list (match-string 1 (cadr err)))))))))))) + +(defun pdf-info-pagelinks (page &optional file-or-buffer) + "Return a list of links on PAGE in document FILE-OR-BUFFER. + +This function returns a list of alists with the following keys. +EDGES represents the relative bounding-box of the link , TYPE is +the type of the action, TITLE is a, possibly empty, name for this +action. + +TYPE may be one of + +goto-dest -- This is a internal link to some page. Each element +contains additional keys PAGE and TOP, where PAGE is the page of +the link and TOP its vertical position. + +goto-remote -- This a external link to some document. Same as +goto-dest, with an additional FILENAME of the external PDF. + +uri -- A link in form of some URI. Alist contains additional key +URI. + +In the first two cases, PAGE may be 0 and TOP nil, which means +these data is unspecified." + (cl-check-type page natnum) + (pdf-info-query + 'pagelinks + (pdf-info--normalize-file-or-buffer file-or-buffer) + page)) + +(defun pdf-info-number-of-pages (&optional file-or-buffer) + "Return the number of pages in document FILE-OR-BUFFER." + (pdf-info-query 'number-of-pages + (pdf-info--normalize-file-or-buffer + file-or-buffer))) + +(defun pdf-info-outline (&optional file-or-buffer) + "Return the PDF outline of document FILE-OR-BUFFER. + +This function returns a list of alists like `pdf-info-pagelinks'. +Additionally every alist has a DEPTH (>= 1) entry with the depth +of this element in the tree." + + (pdf-info-query + 'outline + (pdf-info--normalize-file-or-buffer file-or-buffer))) + +(defun pdf-info--selection-style (selection-style) + "SELECTION-STYLE is the smallest unit of the selected region. + +It must be one of glyph, word or line. If it is none of these, we +fallback to glyph." + (cl-case selection-style + (glyph 0) + (word 1) + (line 2) + (t 0))) + +(defun pdf-info-gettext (page edges &optional selection-style + file-or-buffer) + "Get text on PAGE according to EDGES. + +EDGES should contain relative coordinates. The selection may +extend over multiple lines, which works similar to a Emacs +region. SELECTION-STYLE may be one of glyph, word or line and +determines the smallest unit of the selected region. + +Return the text contained in the selection." + + (pdf-info-query + 'gettext + (pdf-info--normalize-file-or-buffer file-or-buffer) + page + (mapconcat #'number-to-string edges " ") + (pdf-info--selection-style selection-style))) + +(defun pdf-info-getselection (page edges + &optional selection-style file-or-buffer) + "Return the edges of the selection EDGES on PAGE. + +Arguments are the same as for `pdf-info-gettext'. Return a list +of edges corresponding to the text that would be returned by the +aforementioned function, when called with the same arguments." + (pdf-info-query + 'getselection + (pdf-info--normalize-file-or-buffer file-or-buffer) + page + (mapconcat #'number-to-string edges " ") + (pdf-info--selection-style selection-style))) + +(defun pdf-info-textregions (page &optional file-or-buffer) + "Return a list of edges describing PAGE's text-layout." + (pdf-info-getselection + page '(0 0 1 1) 'glyph file-or-buffer)) + +(defun pdf-info-charlayout (page &optional edges-or-pos file-or-buffer) + "Return the layout of characters of PAGE in/at EDGES-OR-POS. + +Returns a list of elements \(CHAR . \(LEFT TOP RIGHT BOT\)\) mapping +character to their corresponding relative bounding-boxes. + +EDGES-OR-POS may be a region \(LEFT TOP RIGHT BOT\) restricting +the returned value to include only characters fully contained in +it. Or a cons \(LEFT . TOP\) which means to only include the +character at this position. In this case the return value +contains at most one element." + + ;; FIXME: Actually returns \(CHAR . LEFT ...\). + + (unless edges-or-pos + (setq edges-or-pos '(0 0 1 1))) + (when (numberp (cdr edges-or-pos)) + (setq edges-or-pos (list (car edges-or-pos) + (cdr edges-or-pos) + -1 -1))) + (pdf-info-query + 'charlayout + (pdf-info--normalize-file-or-buffer file-or-buffer) + page + (mapconcat #'number-to-string edges-or-pos " "))) + +(defun pdf-info-pagesize (page &optional file-or-buffer) + "Return the size of PAGE as a cons \(WIDTH . HEIGHT\) + +The size is in PDF points." + (pdf-info-query + 'pagesize + (pdf-info--normalize-file-or-buffer file-or-buffer) + page)) + +(defun pdf-info-running-p () + "Return non-nil, if the server is running." + (and (processp (pdf-info-process)) + (eq (process-status (pdf-info-process)) + 'run))) + +(defun pdf-info-quit (&optional timeout) + "Quit the epdfinfo server. + +This blocks until all outstanding requests are answered. Unless +TIMEOUT is non-nil, in which case we wait at most TIMEOUT seconds +before killing the server." + (cl-check-type timeout (or null number)) + (when (pdf-info-running-p) + (let ((pdf-info-asynchronous + (if timeout (lambda (&rest _)) + pdf-info-asynchronous))) + (pdf-info-query 'quit) + (when timeout + (setq timeout (+ (float-time) (max 0 timeout))) + (while (and (pdf-info-running-p) + (> timeout (float-time))) + (accept-process-output (pdf-info-process) 0.5 nil t))))) + (when (processp (pdf-info-process)) + (tq-close pdf-info--queue)) + (setq pdf-info--queue nil)) + +(defun pdf-info-kill () + "Kill the epdfinfo server. + +Immediately delete the server process, see also `pdf-info-quit', +for a more sane way to exit the program." + (when (processp (pdf-info-process)) + (tq-close pdf-info--queue)) + (setq pdf-info--queue nil)) + +(defun pdf-info-getannots (&optional pages file-or-buffer) + "Return the annotations on PAGE. + +See `pdf-info-normalize-page-range' for valid PAGES formats. + +This function returns the annotations for PAGES as a list of +alists. Each element of this list describes one annotation and +contains the following keys. + +page - Its page number. +edges - Its area. +type - A symbol describing the annotation's type. +id - A document-wide unique symbol referencing this annotation. +flags - Its flags, binary encoded. +color - Its color in standard Emacs notation. +contents - The text of this annotation. +modified - The last modification date of this annotation. + +Additionally, if the annotation is a markup annotation, the +following keys are present. + +label - The annotation's label. +subject - The subject addressed. +opacity - The level of relative opacity. +popup-edges - The edges of a associated popup window or nil. +popup-is-open - Whether this window should be displayed open. +created - The date this markup annotation was created. + +If the annotation is also a markup text annotation, the alist +contains the following keys. + +text-icon - A string describing the purpose of this annotation. +text-state - A string, e.g. accepted or rejected." ;FIXME: Use symbols ? + + (let ((pages (pdf-info-normalize-page-range pages))) + (pdf-info-query + 'getannots + (pdf-info--normalize-file-or-buffer file-or-buffer) + (car pages) + (cdr pages)))) + +(defun pdf-info-getannot (id &optional file-or-buffer) + "Return the annotation for ID. + +ID should be a symbol, which was previously returned in a +`pdf-info-getannots' query. Signal an error, if an annotation +with ID is not available. + +See `pdf-info-getannots' for the kind of return value of this +function." + (pdf-info-query + 'getannot + (pdf-info--normalize-file-or-buffer file-or-buffer) + id)) + +(defun pdf-info-addannot (page edges type + &optional selection-style file-or-buffer + &rest markup-edges) + "Add a new annotation to PAGE with EDGES of TYPE. + +FIXME: TYPE may be one of `text', `markup-highlight', ... . +FIXME: -1 = 24 +See `pdf-info-getannots' for the kind of value of this function +returns." + (pdf-info-assert-writable-annotations) + (when (consp file-or-buffer) + (push file-or-buffer markup-edges) + (setq file-or-buffer nil)) + (apply + #'pdf-info-query + 'addannot + (pdf-info--normalize-file-or-buffer file-or-buffer) + page + type + (pdf-info--selection-style selection-style) + (mapconcat 'number-to-string edges " ") + (mapcar (lambda (me) + (mapconcat 'number-to-string me " ")) + markup-edges))) + +(defun pdf-info-delannot (id &optional file-or-buffer) + "Delete the annotation with ID in FILE-OR-BUFFER. + +ID should be a symbol, which was previously returned in a +`pdf-info-getannots' query. Signal an error, if annotation ID +does not exist." + (pdf-info-assert-writable-annotations) + (pdf-info-query + 'delannot + (pdf-info--normalize-file-or-buffer file-or-buffer) + id)) + +(defun pdf-info-mvannot (id edges &optional file-or-buffer) + "Move/Resize annotation ID to fit EDGES. + +ID should be a symbol, which was previously returned in a +`pdf-info-getannots' query. Signal an error, if annotation ID +does not exist. + +EDGES should be a list \(LEFT TOP RIGHT BOT\). RIGHT and/or BOT +may also be negative, which means to keep the width +resp. height." + (pdf-info-editannot id `((edges . ,edges)) file-or-buffer)) + +(defun pdf-info-editannot (id modifications &optional file-or-buffer) + "Edit annotation ID, applying MODIFICATIONS. + +ID should be a symbol, which was previously returned in a +`pdf-info-getannots' query. + +MODIFICATIONS is an alist of properties and their new values. + +The server must support modifying annotations for this to work." + + (pdf-info-assert-writable-annotations) + (let ((edits + (mapcar + (lambda (elt) + (cl-case (car elt) + (color + (list (car elt) + (pdf-util-hexcolor (cdr elt)))) + (edges + (list (car elt) + (mapconcat 'number-to-string (cdr elt) " "))) + ((popup-is-open is-open) + (list (car elt) (if (cdr elt) 1 0))) + (t + (list (car elt) (cdr elt))))) + modifications))) + (apply #'pdf-info-query + 'editannot + (pdf-info--normalize-file-or-buffer file-or-buffer) + id + (apply #'append edits)))) + +(defun pdf-info-save (&optional file-or-buffer) + "Save FILE-OR-BUFFER. + +This saves the document to a new temporary file, which is +returned and owned by the caller." + (pdf-info-assert-writable-annotations) + (pdf-info-query + 'save + (pdf-info--normalize-file-or-buffer file-or-buffer))) + +(defun pdf-info-getattachment-from-annot (id &optional do-save file-or-buffer) + "Return the attachment associated with annotation ID. + +ID should be a symbol which was previously returned in a +`pdf-info-getannots' query, and referencing an attachment of type +`file', otherwise an error is signaled. + +See `pdf-info-getattachments' for the kind of return value of this +function and the meaning of DO-SAVE." + + (pdf-info-query + 'getattachment-from-annot + (pdf-info--normalize-file-or-buffer file-or-buffer) + id + (if do-save 1 0))) + +(defun pdf-info-getattachments (&optional do-save file-or-buffer) + "Return all document level attachments. + +If DO-SAVE is non-nil, save the attachments data to a local file, +which is then owned by the caller, see below. + +This function returns a list of alists, where every element +contains the following keys. All values, except for id, may be +nil, i.e. not present. + +id - A symbol uniquely identifying this attachment. +filename - The filename of this attachment. +description - A description of this attachment. +size - The size in bytes. +modified - The last modification date. +created - The date of creation. +checksum - A MD5 checksum of this attachment's data. +file - The name of a tempfile containing the data (only present if + DO-SAVE is non-nil)." + + (pdf-info-query + 'getattachments + (pdf-info--normalize-file-or-buffer file-or-buffer) + (if do-save 1 0))) + +(defun pdf-info-synctex-forward-search (source &optional line column file-or-buffer) + "Perform a forward search with synctex. + +SOURCE should be a LaTeX buffer or the absolute filename of a +corresponding file. LINE and COLUMN represent the position in +the buffer or file. Finally FILE-OR-BUFFER corresponds to the +PDF document. + +Returns an alist with entries PAGE and relative EDGES describing +the position in the PDF document corresponding to the SOURCE +location." + + (let ((source (if (buffer-live-p (get-buffer source)) + (buffer-file-name (get-buffer source)) + source))) + (pdf-info-query + 'synctex-forward-search + (pdf-info--normalize-file-or-buffer file-or-buffer) + source + (or line 1) + (or column 1)))) + +(defun pdf-info-synctex-backward-search (page &optional x y file-or-buffer) + "Perform a backward search with synctex. + +Find the source location corresponding to the coordinates +\(X . Y\) on PAGE in FILE-OR-BUFFER. + +Returns an alist with entries FILENAME, LINE and COLUMN." + + + (pdf-info-query + 'synctex-backward-search + (pdf-info--normalize-file-or-buffer file-or-buffer) + page + (or x 0) + (or y 0))) + +(defun pdf-info-renderpage (page width &optional file-or-buffer &rest commands) + "Render PAGE with width WIDTH. + +Return the data of the corresponding PNG image." + (when (keywordp file-or-buffer) + (push file-or-buffer commands) + (setq file-or-buffer nil)) + (apply #'pdf-info-query + 'renderpage + (pdf-info--normalize-file-or-buffer file-or-buffer) + page + (* width (pdf-util-frame-scale-factor)) + (let (transformed) + (while (cdr commands) + (let ((kw (pop commands)) + (value (pop commands))) + (setq value + (cl-case kw + ((:crop-to :highlight-line :highlight-region :highlight-text) + (mapconcat #'number-to-string value " ")) + ((:foreground :background) + (pdf-util-hexcolor value)) + (:alpha + (number-to-string value)) + (:selection-style + (number-to-string (pdf-info--selection-style value))) + (otherwise value))) + (push kw transformed) + (push value transformed))) + (when commands + (error "Keyword is missing a value: %s" (car commands))) + (nreverse transformed)))) + +(defun pdf-info-renderpage-text-regions (page width single-line-p + &optional selection-style file-or-buffer + &rest regions) + "Highlight text on PAGE with width WIDTH using REGIONS. + +REGIONS is a list determining foreground and background color and +the regions to render. So each element should look like \(FG BG +\(LEFT TOP RIGHT BOT\) \(LEFT TOP RIGHT BOT\) ... \) . The +rendering is text-aware and is controlled by SELECTION-STYLE. + +If SINGLE-LINE-P is non-nil, the edges in REGIONS are each +supposed to be limited to a single line in the document. Setting +this, if applicable, avoids rendering problems. + +For the other args see `pdf-info-renderpage'. + +Return the data of the corresponding PNG image." + + (when (consp file-or-buffer) + (push file-or-buffer regions) + (setq file-or-buffer nil)) + + (apply #'pdf-info-renderpage + page width file-or-buffer + (apply #'append + `(:selection-style ,selection-style) + (mapcar (lambda (elt) + `(:foreground ,(pop elt) + :background ,(pop elt) + ,@(cl-mapcan (lambda (edges) + `(,(if single-line-p + :highlight-line + :highlight-text) + ,edges)) + elt))) + regions)))) + +(defun pdf-info-renderpage-highlight (page width + &optional file-or-buffer + &rest regions) + "Highlight regions on PAGE with width WIDTH using REGIONS. + +REGIONS is a list determining the background color, a alpha value +and the regions to render. So each element should look like \(FILL-COLOR +STROKE-COLOR ALPHA \(LEFT TOP RIGHT BOT\) \(LEFT TOP RIGHT BOT\) ... \) +. + +For the other args see `pdf-info-renderpage'. + +Return the data of the corresponding PNG image." + + (when (consp file-or-buffer) + (push file-or-buffer regions) + (setq file-or-buffer nil)) + + (apply #'pdf-info-renderpage + page width file-or-buffer + (apply #'append + (mapcar (lambda (elt) + `(:background ,(pop elt) + :foreground ,(pop elt) + :alpha ,(pop elt) + ,@(cl-mapcan (lambda (edges) + `(:highlight-region ,edges)) + elt))) + regions)))) + +(defun pdf-info-boundingbox (page &optional file-or-buffer) + "Return a bounding-box for PAGE. + +Returns a list \(LEFT TOP RIGHT BOT\)." + + (pdf-info-query + 'boundingbox + (pdf-info--normalize-file-or-buffer file-or-buffer) + page)) + +(defun pdf-info-getoptions (&optional file-or-buffer) + (pdf-info-query + 'getoptions + (pdf-info--normalize-file-or-buffer file-or-buffer))) + +(defun pdf-info-setoptions (&optional file-or-buffer &rest options) + (when (symbolp file-or-buffer) + (push file-or-buffer options) + (setq file-or-buffer nil)) + (unless (= (% (length options) 2) 0) + (error "Missing a option value")) + (apply #'pdf-info-query + 'setoptions + (pdf-info--normalize-file-or-buffer file-or-buffer) + (let (soptions) + (while options + (let ((key (pop options)) + (value (pop options))) + (unless (and (keywordp key) + (not (eq key :))) + (error "Keyword expected: %s" key)) + (cl-case key + ((:render/foreground :render/background) + (push (pdf-util-hexcolor value) + soptions)) + ((:render/printed) + (push (if value 1 0) soptions)) + ((:render/usecolors) + ;; 0 -> original color + ;; 1 -> recolor document to grayscale mapping black to + ;; :render/foreground and white to :render/background + ;; 2 -> recolor document by inverting the perceived lightness + ;; preserving hue + (push (if (and (integerp value) (> 3 value 0)) value 0) + soptions)) + (t (push value soptions))) + (push key soptions))) + soptions))) + + + +(defun pdf-info-pagelabels (&optional file-or-buffer) + "Return a list of pagelabels. + +Returns a list of strings corresponding to the labels of the +pages in FILE-OR-BUFFER." + + (pdf-info-query + 'pagelabels + (pdf-info--normalize-file-or-buffer file-or-buffer))) + +(defun pdf-info-ping (&optional message) + "Ping the server using MESSAGE. + +Returns MESSAGE, which defaults to \"pong\"." + (pdf-info-query 'ping (or message "pong"))) + +(provide 'pdf-info) + +;;; pdf-info.el ends here diff --git a/org/elpa/pdf-tools-20230404.327/pdf-isearch.el b/org/elpa/pdf-tools-20230404.327/pdf-isearch.el new file mode 100644 index 0000000..f5468eb --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/pdf-isearch.el @@ -0,0 +1,832 @@ +;;; pdf-isearch.el --- Isearch in pdf buffers. -*- lexical-binding: t -*- + +;; Copyright (C) 2013, 2014 Andreas Politz + +;; Author: Andreas Politz +;; Keywords: files, multimedia + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; +;;; Todo: +;; +;; * Add the possibility to limit the search to a range of pages. + +(require 'cl-lib) +(require 'pdf-util) +(require 'pdf-info) +(require 'pdf-misc) +(require 'pdf-view) +(require 'pdf-cache) +(require 'let-alist) + +;;; Code: + + + +;; * ================================================================== * +;; * Customizations +;; * ================================================================== * + +(defgroup pdf-isearch nil + "Isearch in pdf buffers." + :group 'pdf-tools) + +(defface pdf-isearch-match + '((((background dark)) (:inherit isearch)) + (((background light)) (:inherit isearch))) + "Face used to determine the colors of the current match." + :group 'pdf-isearch + :group 'pdf-tools-faces) + +(defface pdf-isearch-lazy + '((((background dark)) (:inherit lazy-highlight)) + (((background light)) (:inherit lazy-highlight))) + "Face used to determine the colors of non-current matches." + :group 'pdf-isearch + :group 'pdf-tools-faces) + +(defface pdf-isearch-batch + '((((background dark)) (:inherit match)) + (((background light)) (:inherit match))) + "Face used to determine the colors in `pdf-isearch-batch-mode'." + :group 'pdf-isearch + :group 'pdf-tools-faces) + +(defcustom pdf-isearch-hyphenation-character "-­" + "Characters used as hyphens when word searching." + :group 'pdf-isearch + :type 'string) + +(defvar pdf-isearch-search-fun-function nil + "Search function used when searching. + +Like `isearch-search-fun-function', though it should return a +function \(FN STRING &optional PAGES\), which in turn should +return a result like `pdf-info-search-regexp'.") + + +;; * ================================================================== * +;; * Internal Variables +;; * ================================================================== * + +(defvar-local pdf-isearch-current-page nil + "The page that is currently searched.") + +(defvar-local pdf-isearch-current-match nil + "A list ((LEFT TOP RIGHT BOT) ...) of the current match or nil. + +A match may contain more than one edges-element, e.g. when regexp +searching across multiple lines.") + +(defvar-local pdf-isearch-current-matches nil + "A list of matches of the last search.") + +(defvar-local pdf-isearch-current-parameter nil + "A list of search parameter \(search-string regex-p case-fold word-search\).") + + +;; * ================================================================== * +;; * Modes +;; * ================================================================== * + +(declare-function pdf-occur "pdf-occur.el") +(declare-function pdf-sync-backward-search "pdf-sync.el") + +(defvar pdf-isearch-minor-mode-map + (let ((kmap (make-sparse-keymap))) + (define-key kmap [remap occur] 'pdf-occur) + kmap) + "Keymap used in `pdf-isearch-minor-mode'.") + +(defvar pdf-isearch-active-mode-map + (let ((kmap (make-sparse-keymap))) + (set-keymap-parent kmap isearch-mode-map) + (define-key kmap (kbd "C-d") 'pdf-view-dark-minor-mode) + (define-key kmap (kbd "C-b") 'pdf-isearch-batch-mode) + (define-key kmap (kbd "M-s o") 'pdf-isearch-occur) + (define-key kmap (kbd "M-s s") 'pdf-isearch-sync-backward) + kmap) + "Keymap used in `pdf-isearch-active-mode'. + +This keymap is used, when isearching in PDF buffers. Its parent +keymap is `isearch-mode-map'.") + +(put 'image-scroll-up 'isearch-scroll t) +(put 'image-scroll-down 'isearch-scroll t) + +(define-minor-mode pdf-isearch-active-mode + "This mode is enabled when isearch is active in a PDF file." + :group 'pdf-isearch + (cond + (pdf-isearch-active-mode + (set (make-local-variable 'isearch-mode-map) + pdf-isearch-active-mode-map) + (setq overriding-terminal-local-map + isearch-mode-map)) + (t + ;;(setq overriding-terminal-local-map nil) ? + (kill-local-variable 'isearch-mode-map)))) + +;;;###autoload +(define-minor-mode pdf-isearch-minor-mode + "Isearch mode for PDF buffer. + +When this mode is enabled \\[isearch-forward], among other keys, +starts an incremental search in this PDF document. Since this mode +uses external programs to highlight found matches via +image-processing, proceeding to the next match may be slow. + +Therefore two isearch behaviours have been defined: Normal isearch and +batch mode. The later one is a minor mode +\(`pdf-isearch-batch-mode'\), which when activated inhibits isearch +from stopping at and highlighting every single match, but rather +display them batch-wise. Here a batch means a number of matches +currently visible in the selected window. + +The kind of highlighting is determined by three faces +`pdf-isearch-match' \(for the current match\), `pdf-isearch-lazy' +\(for all other matches\) and `pdf-isearch-batch' \(when in batch +mode\), which see. + +Colors may also be influenced by the minor-mode +`pdf-view-dark-minor-mode'. If this is minor mode enabled, each face's +dark colors, are used (see e.g. `frame-background-mode'), instead +of the light ones. + +\\{pdf-isearch-minor-mode-map} +While in `isearch-mode' the following keys are available. Note +that not every isearch command work as expected. + +\\{pdf-isearch-active-mode-map}" + :group 'pdf-isearch + (pdf-util-assert-pdf-buffer) + (cond + (pdf-isearch-minor-mode + (when (boundp 'character-fold-search) + (setq-local character-fold-search nil)) + (set (make-local-variable 'isearch-search-fun-function) + (lambda nil 'pdf-isearch-search-function)) + (set (make-local-variable 'isearch-push-state-function) + 'pdf-isearch-push-state-function) + (set (make-local-variable 'isearch-wrap-function) + 'pdf-isearch-wrap-function) + (set (make-local-variable 'isearch-lazy-highlight) nil) + ;; Make our commands work in isearch-mode. + (set (make-local-variable 'isearch-allow-scroll) t) + (set (make-local-variable 'search-exit-option) + ;; This maybe edit or t, but edit would suppress our cmds + ;; in isearch-other-meta-char. + (not (not search-exit-option))) + ;; FIXME: Die Variable imagemagick-render-type entweder an anderer + ;; Stelle global setzen oder nur irgendwo auf den + ;; Performancegewinn hinweisen. + (when (and (boundp 'imagemagick-render-type) + (= 0 imagemagick-render-type)) + ;; This enormously speeds up rendering. + (setq imagemagick-render-type 1)) + (add-hook 'isearch-mode-hook 'pdf-isearch-mode-initialize nil t) + (add-hook 'isearch-mode-end-hook 'pdf-isearch-mode-cleanup nil t) + (add-hook 'isearch-update-post-hook 'pdf-isearch-update nil t)) + (t + (when (boundp 'character-fold-search) + (kill-local-variable 'character-fold-search)) + (kill-local-variable 'search-exit-option) + (kill-local-variable 'isearch-allow-scroll) + (kill-local-variable 'isearch-search-fun-function) + (kill-local-variable 'isearch-push-state-function) + (kill-local-variable 'isearch-wrap-function) + (kill-local-variable 'isearch-lazy-highlight) + (remove-hook 'isearch-update-post-hook 'pdf-isearch-update t) + (remove-hook 'isearch-mode-hook 'pdf-isearch-mode-initialize t) + (remove-hook 'isearch-mode-end-hook 'pdf-isearch-mode-cleanup t)))) + +(define-minor-mode pdf-isearch-batch-mode + "Isearch PDF documents batch-wise. + +If this mode is enabled, isearching does not stop at every match, +but rather moves to the next one not currently visible. This +behaviour is much faster than ordinary isearch, since far less +different images have to be displayed." + :group 'pdf-isearch + (when isearch-mode + (pdf-isearch-redisplay) + (pdf-isearch-message + (if pdf-isearch-batch-mode "batch mode" "isearch mode")))) + + + +;; * ================================================================== * +;; * Isearch interface +;; * ================================================================== * + +(defvar pdf-isearch-filter-matches-function nil + "A function for filtering isearch matches. + +The function receives one argument: a list of matches, each +being a list of edges. It should return a subset of this list. +Edge coordinates are in image-space.") + +(defvar pdf-isearch-narrow-to-page nil + "Non-nil, if the search should be limited to the current page.") + +(defun pdf-isearch-search-function (string &rest _) + "Search for STRING in the current PDF buffer. + +This is a Isearch interface function." + (when (> (length string) 0) + (let ((same-search-p (pdf-isearch-same-search-p)) + (oldpage pdf-isearch-current-page) + (matches (pdf-isearch-search-page string)) + next-match) + ;; matches is a list of list of edges ((x0 y1 x1 y2) ...), + ;; sorted top to bottom ,left to right. Coordinates are in image + ;; space. + (unless isearch-forward + (setq matches (reverse matches))) + (when pdf-isearch-filter-matches-function + (setq matches (funcall pdf-isearch-filter-matches-function matches))) + ;; Where to go next ? + (setq pdf-isearch-current-page (pdf-view-current-page) + pdf-isearch-current-matches matches + next-match + (pdf-isearch-next-match + oldpage pdf-isearch-current-page + pdf-isearch-current-match matches + same-search-p + isearch-forward) + pdf-isearch-current-parameter + (list string isearch-regexp + isearch-case-fold-search isearch-word)) + (cond + (next-match + (setq pdf-isearch-current-match next-match) + (pdf-isearch-hl-matches next-match matches) + (pdf-isearch-focus-match next-match) + ;; Don't get off track. + (when (or (and (bobp) (not isearch-forward)) + (and (eobp) isearch-forward)) + (goto-char (1+ (/ (buffer-size) 2)))) + ;; Signal success to isearch. + (if isearch-forward + (re-search-forward ".") + (re-search-backward "."))) + ((and (not pdf-isearch-narrow-to-page) + (not (pdf-isearch-empty-match-p matches))) + (let ((next-page (pdf-isearch-find-next-matching-page + string pdf-isearch-current-page t))) + (when next-page + (pdf-view-goto-page next-page) + (pdf-isearch-search-function string)))))))) + +(defun pdf-isearch-push-state-function () + "Push the current search state. + +This is a Isearch interface function." + (let ((hscroll (window-hscroll)) + (vscroll (window-vscroll)) + (parms pdf-isearch-current-parameter) + (matches pdf-isearch-current-matches) + (match pdf-isearch-current-match) + (page pdf-isearch-current-page)) + (lambda (_state) + (setq pdf-isearch-current-parameter parms + pdf-isearch-current-matches matches + pdf-isearch-current-match match + pdf-isearch-current-page page) + + (pdf-view-goto-page pdf-isearch-current-page) + (when pdf-isearch-current-match + (pdf-isearch-hl-matches + pdf-isearch-current-match + pdf-isearch-current-matches)) + (image-set-window-hscroll hscroll) + (image-set-window-vscroll vscroll)))) + +(defun pdf-isearch-wrap-function () + "Go to first or last page. + +This is a Isearch interface function." + (let ((page (if isearch-forward + 1 + (pdf-cache-number-of-pages)))) + (unless (or pdf-isearch-narrow-to-page + (= page (pdf-view-current-page))) + (pdf-view-goto-page page) + (let ((next-screen-context-lines 0)) + (if (= page 1) + (image-scroll-down) + (image-scroll-up))))) + (setq pdf-isearch-current-match nil)) + +(defun pdf-isearch-mode-cleanup () + "Cleanup after exiting Isearch. + +This is a Isearch interface function." + (pdf-isearch-active-mode -1) + (pdf-view-redisplay)) + +(defun pdf-isearch-mode-initialize () + "Initialize isearching. + +This is a Isearch interface function." + (pdf-isearch-active-mode 1) + (setq pdf-isearch-current-page (pdf-view-current-page) + pdf-isearch-current-match nil + pdf-isearch-current-matches nil + pdf-isearch-current-parameter nil) + (goto-char (1+ (/ (buffer-size) 2)))) + +(defun pdf-isearch-same-search-p (&optional ignore-search-string-p) + "Return non-nil, if search parameter have not changed. + +Parameter inspected are `isearch-string' (unless +IGNORE-SEARCH-STRING-P is t) and `isearch-case-fold-search'. If +there was no previous search, this function returns t." + (or (null pdf-isearch-current-parameter) + (let ((parameter (list isearch-string + isearch-regexp + isearch-case-fold-search + isearch-word))) + (if ignore-search-string-p + (equal (cdr pdf-isearch-current-parameter) + (cdr parameter)) + (equal pdf-isearch-current-parameter + parameter))))) + +(defun pdf-isearch-next-match (last-page this-page last-match + all-matches continued-p + forward-p) + "Determine the next match." + (funcall (if pdf-isearch-batch-mode + 'pdf-isearch-next-match-batch + 'pdf-isearch-next-match-isearch) + last-page this-page last-match + all-matches continued-p forward-p)) + +(defun pdf-isearch-focus-match (current-match) + "Make the CURRENT-MATCH visible in the window." + (funcall (if pdf-isearch-batch-mode + 'pdf-isearch-focus-match-batch + 'pdf-isearch-focus-match-isearch) + current-match)) + +(defun pdf-isearch-redisplay () + "Redisplay the current highlighting." + (pdf-isearch-hl-matches pdf-isearch-current-match + pdf-isearch-current-matches)) + +(defun pdf-isearch-update () + "Update search and redisplay, if necessary." + (unless (pdf-isearch-same-search-p t) + (setq pdf-isearch-current-parameter + (list isearch-string isearch-regexp + isearch-case-fold-search isearch-word) + pdf-isearch-current-matches + (pdf-isearch-search-page isearch-string)) + (pdf-isearch-redisplay))) + +(defun pdf-isearch-message (fmt &rest args) + "Like `message', but Isearch friendly." + (unless args (setq args (list fmt) fmt "%s")) + (let ((msg (apply 'format fmt args))) + (if (cl-some (lambda (buf) + (buffer-local-value 'isearch-mode buf)) + (mapcar 'window-buffer (window-list))) + (let ((isearch-message-suffix-add + (format " [%s]" msg))) + (isearch-message) + (sit-for 1)) + (message "%s" msg)))) + +(defun pdf-isearch-empty-match-p (matches) + (and matches + (cl-every + (lambda (match) + (cl-every (lambda (edges) + (cl-every 'zerop edges)) + match)) + matches))) + +(defun pdf-isearch-occur () + "Run `occur' using the last search string or regexp." + (interactive) + (let ((case-fold-search isearch-case-fold-search) + (regexp + (cond + ((functionp isearch-word) + (funcall isearch-word isearch-string)) + (isearch-word (pdf-isearch-word-search-regexp + isearch-string nil + pdf-isearch-hyphenation-character)) + (isearch-regexp isearch-string)))) + (save-selected-window + (pdf-occur (or regexp isearch-string) regexp)) + (isearch-message))) + +(defun pdf-isearch-sync-backward () + "Visit the source of the beginning of the current match." + (interactive) + (pdf-util-assert-pdf-window) + (unless pdf-isearch-current-match + (user-error "No current or recent match")) + (when isearch-mode + (isearch-exit)) + (cl-destructuring-bind (left top _right _bot) + (car pdf-isearch-current-match) + (pdf-sync-backward-search left top))) + + +;; * ================================================================== * +;; * Interface to epdfinfo +;; * ================================================================== * + +(defun pdf-isearch-search-page (string &optional page) + "Search STRING on PAGE in the current window. + +Returns a list of edges (LEFT TOP RIGHT BOTTOM) in PDF +coordinates, sorted top to bottom, then left to right." + + (unless page (setq page (pdf-view-current-page))) + (mapcar (lambda (match) + (let-alist match + (pdf-util-scale-relative-to-pixel .edges 'round))) + (let ((case-fold-search isearch-case-fold-search)) + (funcall (pdf-isearch-search-fun) + string page)))) + +(defun pdf-isearch-search-fun () + (funcall (or pdf-isearch-search-fun-function + 'pdf-isearch-search-fun-default))) + +(defun pdf-isearch-search-fun-default () + "Return default functions to use for the search." + (cond + ((eq isearch-word t) + (lambda (string &optional pages) + ;; Use lax versions to not fail at the end of the word while + ;; the user adds and removes characters in the search string + ;; (or when using nonincremental word isearch) + (let ((lax (not (or isearch-nonincremental + (null (car isearch-cmds)) + (eq (length isearch-string) + (length (isearch--state-string + (car isearch-cmds)))))))) + (pdf-info-search-regexp + (pdf-isearch-word-search-regexp + string lax pdf-isearch-hyphenation-character) + pages 'invalid-regexp)))) + (isearch-regexp + (lambda (string &optional pages) + (pdf-info-search-regexp string pages 'invalid-regexp))) + (t + 'pdf-info-search-string))) + + +(defun pdf-isearch-word-search-regexp (string &optional lax hyphenization-chars) + "Return a PCRE which matches words, ignoring punctuation." + (let ((hyphenization-regexp + (and hyphenization-chars + (format "(?:[%s]\\n)?" + (replace-regexp-in-string + "[]^\\\\-]" "\\\\\\&" + hyphenization-chars t))))) + (cond + ((equal string "") "") + ((string-match-p "\\`\\W+\\'" string) "\\W+") + (t (concat + (if (string-match-p "\\`\\W" string) "\\W+" + (unless lax "\\b")) + (mapconcat (lambda (word) + (if hyphenization-regexp + (mapconcat + (lambda (ch) + (pdf-util-pcre-quote (string ch))) + (append word nil) + hyphenization-regexp) + (pdf-util-pcre-quote word))) + (split-string string "\\W+" t) "\\W+") + (if (string-match-p "\\W\\'" string) "\\W+" + (unless lax "\\b"))))))) + +(defun pdf-isearch-find-next-matching-page (string page &optional interactive-p) + "Find STRING after or before page PAGE, according to FORWARD-P. + +If INTERACTIVE-P is non-nil, give some progress feedback. +Returns the page number where STRING was found, or nil if there +is no such page." + ;; Do a exponentially expanding search. + (let* ((incr 1) + (pages (if isearch-forward + (cons (1+ page) + (1+ page)) + (cons (1- page) + (1- page)))) + (fn (pdf-isearch-search-fun)) + matched-page + reporter) + + (while (and (null matched-page) + (or (and isearch-forward + (<= (car pages) + (pdf-cache-number-of-pages))) + (and (not isearch-forward) + (>= (cdr pages) 1)))) + (let* ((case-fold-search isearch-case-fold-search) + (matches (funcall fn string pages))) + (setq matched-page + (alist-get 'page (if isearch-forward + (car matches) + (car (last matches)))))) + (setq incr (* incr 2)) + (cond (isearch-forward + (setcar pages (1+ (cdr pages))) + (setcdr pages (min (pdf-cache-number-of-pages) + (+ (cdr pages) incr)))) + (t + (setcdr pages (1- (car pages))) + (setcar pages (max 1 (- (car pages) + incr))))) + (when interactive-p + (when (and (not reporter) + (= incr 8)) ;;Don't bother right away. + (setq reporter + (apply + 'make-progress-reporter "Searching" + (if isearch-forward + (list (car pages) (pdf-cache-number-of-pages) nil 0) + (list 1 (cdr pages) nil 0))))) + (when reporter + (progress-reporter-update + reporter (if isearch-forward + (- (cdr pages) page) + (- page (car pages))))))) + matched-page)) + + + +;; * ================================================================== * +;; * Isearch Behavior +;; * ================================================================== * + +(defun pdf-isearch-next-match-isearch (last-page this-page last-match + matches same-search-p + forward) + "Default function for choosing the next match. + +Implements default isearch behaviour, i.e. it stops at every +match." + (cond + ((null last-match) + ;; Goto first match from top or bottom of the window. + (let* ((iedges (pdf-util-image-displayed-edges)) + (pos (pdf-util-with-edges (iedges) + (if forward + (list iedges-left iedges-top + iedges-left iedges-top) + (list iedges-right iedges-bot + iedges-right iedges-bot))))) + (pdf-isearch-closest-match (list pos) matches forward))) + ((not (eq last-page this-page)) + ;; First match from top-left or bottom-right of the new + ;; page. + (car matches)) + (same-search-p + ;; Next match after the last one. + (if last-match + (cadr (member last-match matches)))) + (matches + ;; Next match of new search closest to the last one. + (pdf-isearch-closest-match + last-match matches forward)))) + +(defun pdf-isearch-focus-match-isearch (match) + "Make the image area in MATCH visible in the selected window." + (pdf-util-scroll-to-edges (apply 'pdf-util-edges-union match))) + +(defun pdf-isearch-next-match-batch (last-page this-page last-match + matches same-search-p + forward-p) + "Select the next match, unseen in the current search direction." + + (if (or (null last-match) + (not same-search-p) + (not (eq last-page this-page))) + (pdf-isearch-next-match-isearch + last-page this-page last-match matches same-search-p forward-p) + (pdf-util-with-edges (match iedges) + (let ((iedges (pdf-util-image-displayed-edges))) + (car (cl-remove-if + ;; Filter matches visible on screen. + (lambda (edges) + (let ((match (apply 'pdf-util-edges-union edges))) + (and (<= match-right iedges-right) + (<= match-bot iedges-bot) + (>= match-left iedges-left) + (>= match-top iedges-top)))) + (cdr (member last-match matches)))))))) + +(defun pdf-isearch-focus-match-batch (match) + "Make the image area in MATCH eagerly visible in the selected window." + (pdf-util-scroll-to-edges (apply 'pdf-util-edges-union match) t)) + +(cl-deftype pdf-isearch-match () + `(satisfies + (lambda (match) + (cl-every (lambda (edges) + (and (consp edges) + (= (length edges) 4) + (cl-every 'numberp edges))) + match)))) + +(cl-deftype list-of (type) + `(satisfies + (lambda (l) + (and (listp l) + (cl-every (lambda (x) + (cl-typep x ',type)) + l))))) + +(defun pdf-isearch-closest-match (match matches + &optional forward-p) + "Find the nearest element to MATCH in MATCHES. + +The direction in which to look is determined by FORWARD-P. + +MATCH should be a list of edges, MATCHES a list of such element; +it is assumed to be ordered with respect to FORWARD-P." + + + (cl-check-type match pdf-isearch-match) + (cl-check-type matches (list-of pdf-isearch-match)) + (let ((matched (apply 'pdf-util-edges-union match))) + (pdf-util-with-edges (matched) + (cl-loop for next in matches do + (let ((edges (apply 'pdf-util-edges-union next))) + (pdf-util-with-edges (edges) + (when (if forward-p + (or (>= edges-top matched-bot) + (and (or (>= edges-top matched-top) + (>= edges-bot matched-bot)) + (>= edges-right matched-right))) + (or (<= edges-bot matched-top) + (and (or (<= edges-bot matched-bot) + (<= edges-top matched-top)) + (<= edges-left matched-left)))) + (cl-return next)))))))) + + + +;; * ================================================================== * +;; * Display +;; * ================================================================== * + + +(defun pdf-isearch-current-colors () + "Return the current color set. + +The return value depends on `pdf-view-dark-minor-mode' and +`pdf-isearch-batch-mode'. It is a list of four colors \(MATCH-FG +MATCH-BG LAZY-FG LAZY-BG\)." + (let ((dark-p pdf-view-dark-minor-mode)) + (cond + (pdf-isearch-batch-mode + (let ((colors (pdf-util-face-colors 'pdf-isearch-batch dark-p))) + (list (car colors) + (cdr colors) + (car colors) + (cdr colors)))) + (t + (let ((match (pdf-util-face-colors 'pdf-isearch-match dark-p)) + (lazy (pdf-util-face-colors 'pdf-isearch-lazy dark-p))) + (list (car match) + (cdr match) + (car lazy) + (cdr lazy))))))) + +(defvar pdf-isearch--hl-matches-tick 0) + +(defun pdf-isearch-hl-matches (current matches &optional occur-hack-p) + "Highlighting edges CURRENT and MATCHES." + (cl-check-type current pdf-isearch-match) + (cl-check-type matches (list-of pdf-isearch-match)) + (cl-destructuring-bind (fg1 bg1 fg2 bg2) + (pdf-isearch-current-colors) + (let* ((width (car (pdf-view-image-size))) + (page (pdf-view-current-page)) + (window (selected-window)) + (buffer (current-buffer)) + (tick (cl-incf pdf-isearch--hl-matches-tick)) + (pdf-info-asynchronous + (lambda (status data) + (when (and (null status) + (eq tick pdf-isearch--hl-matches-tick) + (buffer-live-p buffer) + (window-live-p window) + (eq (window-buffer window) + buffer)) + (with-selected-window window + (when (and (derived-mode-p 'pdf-view-mode) + (or isearch-mode + occur-hack-p) + (eq page (pdf-view-current-page))) + (pdf-view-display-image + (pdf-view-create-image data :width width)))))))) + (pdf-info-renderpage-text-regions + page width t nil nil + `(,fg1 ,bg1 ,@(pdf-util-scale-pixel-to-relative + current)) + `(,fg2 ,bg2 ,@(pdf-util-scale-pixel-to-relative + (apply 'append + (remove current matches)))))))) + + +;; * ================================================================== * +;; * Debug +;; * ================================================================== * + +;; The following isearch-search function is debuggable. +;; +(when nil + (defun isearch-search () + ;; Do the search with the current search string. + (if isearch-message-function + (funcall isearch-message-function nil t) + (isearch-message nil t)) + (if (and (eq isearch-case-fold-search t) search-upper-case) + (setq isearch-case-fold-search + (isearch-no-upper-case-p isearch-string isearch-regexp))) + (condition-case lossage + (let ((inhibit-point-motion-hooks + ;; FIXME: equality comparisons on functions is asking for trouble. + (and (eq isearch-filter-predicate 'isearch-filter-visible) + search-invisible)) + (inhibit-quit nil) + (case-fold-search isearch-case-fold-search) + (retry t)) + (setq isearch-error nil) + (while retry + (setq isearch-success + (isearch-search-string isearch-string nil t)) + ;; Clear RETRY unless the search predicate says + ;; to skip this search hit. + (if (or (not isearch-success) + (bobp) (eobp) + (= (match-beginning 0) (match-end 0)) + (funcall isearch-filter-predicate + (match-beginning 0) (match-end 0))) + (setq retry nil))) + (setq isearch-just-started nil) + (if isearch-success + (setq isearch-other-end + (if isearch-forward (match-beginning 0) (match-end 0))))) + + (quit (isearch-unread ?\C-g) + (setq isearch-success nil)) + + (invalid-regexp + (setq isearch-error (car (cdr lossage))) + (if (string-match + "\\`Premature \\|\\`Unmatched \\|\\`Invalid " + isearch-error) + (setq isearch-error "incomplete input"))) + + (search-failed + (setq isearch-success nil) + (setq isearch-error (nth 2 lossage))) + + ;; (error + ;; ;; stack overflow in regexp search. + ;; (setq isearch-error (format "%s" lossage))) + ) + + (if isearch-success + nil + ;; Ding if failed this time after succeeding last time. + (and (isearch--state-success (car isearch-cmds)) + (ding)) + (if (functionp (isearch--state-pop-fun (car isearch-cmds))) + (funcall (isearch--state-pop-fun (car isearch-cmds)) + (car isearch-cmds))) + (goto-char (isearch--state-point (car isearch-cmds)))))) + + +(provide 'pdf-isearch) + +;;; pdf-isearch.el ends here + +;; Local Variables: +;; byte-compile-warnings: (not obsolete) +;; End: diff --git a/org/elpa/pdf-tools-20230404.327/pdf-links.el b/org/elpa/pdf-tools-20230404.327/pdf-links.el new file mode 100644 index 0000000..d54981e --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/pdf-links.el @@ -0,0 +1,379 @@ +;;; pdf-links.el --- Handle PDF links. -*- lexical-binding: t -*- + +;; Copyright (C) 2013, 2014 Andreas Politz + +;; Author: Andreas Politz +;; Keywords: files, multimedia + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; + +(require 'pdf-info) +(require 'pdf-util) +(require 'pdf-misc) +(require 'pdf-cache) +(require 'pdf-isearch) +(require 'let-alist) +(require 'org) + +;;; Code: + + + +;; * ================================================================== * +;; * Customizations +;; * ================================================================== * + +(defgroup pdf-links nil + "Following links in PDF documents." + :group 'pdf-tools) + +(defface pdf-links-read-link + '((((background dark)) (:background "red" :foreground "yellow")) + (((background light)) (:background "red" :foreground "yellow"))) + "Face used to determine the colors when reading links." + ;; :group 'pdf-links + :group 'pdf-tools-faces) + +(defcustom pdf-links-read-link-convert-commands + '(;;"-font" "FreeMono" + "-pointsize" "%P" + "-undercolor" "%f" + "-fill" "%b" + "-draw" "text %X,%Y '%c'") + + "The commands for the convert program, when decorating links for reading. +See `pdf-util-convert' for an explanation of the format. + +Aside from the description there, two additional escape chars are +available. + +%P -- The scaled font pointsize, i.e. IMAGE-WIDTH * SCALE (See + `pdf-links-convert-pointsize-scale'). +%c -- String describing the current link key (e.g. AA, AB, + etc.)." + :group 'pdf-links + :type '(repeat string) + :link '(variable-link pdf-isearch-convert-commands) + :link '(url-link "http://www.imagemagick.org/script/convert.php")) + +(defcustom pdf-links-convert-pointsize-scale 0.01 + "The scale factor for the -pointsize convert command. + +This determines the relative size of the font, when interactively +reading links." + :group 'pdf-links + :type '(restricted-sexp :match-alternatives + ((lambda (x) (and (numberp x) + (<= x 1) + (>= x 0)))))) + +(defcustom pdf-links-browse-uri-function + 'pdf-links-browse-uri-default + "The function for handling uri links. + +This function should accept one argument, the URI to follow, and +do something with it." + :group 'pdf-links + :type 'function) + + +;; * ================================================================== * +;; * Minor Mode +;; * ================================================================== * + +(defvar pdf-links-minor-mode-map + (let ((kmap (make-sparse-keymap))) + (define-key kmap (kbd "f") 'pdf-links-isearch-link) + (define-key kmap (kbd "F") 'pdf-links-action-perform) + kmap)) + +;;;###autoload +(define-minor-mode pdf-links-minor-mode + "Handle links in PDF documents.\\ + +If this mode is enabled, most links in the document may be +activated by clicking on them or by pressing \\[pdf-links-action-perform] and selecting +one of the displayed keys, or by using isearch limited to +links via \\[pdf-links-isearch-link]. + +\\{pdf-links-minor-mode-map}" + :group 'pdf-links + (pdf-util-assert-pdf-buffer) + (cond + (pdf-links-minor-mode + (pdf-view-add-hotspot-function 'pdf-links-hotspots-function 0)) + (t + (pdf-view-remove-hotspot-function 'pdf-links-hotspots-function))) + (pdf-view-redisplay t)) + +(defun pdf-links-hotspots-function (page size) + "Create hotspots for links on PAGE using SIZE." + + (let ((links (pdf-cache-pagelinks page)) + (id-fmt "link-%d-%d") + (i 0) + (pointer 'hand) + hotspots) + (dolist (l links) + (let ((e (pdf-util-scale + (cdr (assq 'edges l)) size 'round)) + (id (intern (format id-fmt page + (cl-incf i))))) + (push `((rect . ((,(nth 0 e) . ,(nth 1 e)) + . (,(nth 2 e) . ,(nth 3 e)))) + ,id + (pointer + ,pointer + help-echo ,(pdf-links-action-to-string l))) + hotspots) + (local-set-key + (vector id 'mouse-1) + (lambda nil + (interactive "@") + (pdf-links-action-perform l))) + (local-set-key + (vector id t) + 'pdf-util-image-map-mouse-event-proxy))) + (nreverse hotspots))) + +(defun pdf-links-action-to-string (link) + "Return a string representation of ACTION." + (let-alist link + (concat + (cl-case .type + (goto-dest + (if (> .page 0) + (format "Goto page %d" .page) + "Destination not found")) + (goto-remote + (if (and .filename (file-exists-p .filename)) + (format "Goto %sfile '%s'" + (if (> .page 0) + (format "p.%d of " .page) + "") + .filename) + (format "Link to nonexistent file '%s'" .filename))) + (uri + (if (> (length .uri) 0) + (format "Link to uri '%s'" .uri) + (format "Link to empty uri"))) + (t (format "Unrecognized link type: %s" .type))) + (if (> (length .title) 0) + (format " (%s)" .title))))) + +;;;###autoload +(defun pdf-links-action-perform (link) + "Follow LINK, depending on its type. + +This may turn to another page, switch to another PDF buffer or +invoke `pdf-links-browse-uri-function'. + +Interactively, link is read via `pdf-links-read-link-action'. +This function displays characters around the links in the current +page and starts reading characters (ignoring case). After a +sufficient number of characters have been read, the corresponding +link's link is invoked. Additionally, SPC may be used to +scroll the current page." + (interactive + (list (or (pdf-links-read-link-action "Activate link (SPC scrolls): ") + (error "No link selected")))) + (let-alist link + (cl-case .type + ((goto-dest goto-remote) + (let ((window (selected-window))) + (cl-case .type + (goto-dest + (unless (> .page 0) + (error "Link points to nowhere"))) + (goto-remote + (unless (and .filename (file-exists-p .filename)) + (error "Link points to nonexistent file %s" .filename)) + (setq window (display-buffer + (or (find-buffer-visiting .filename) + (find-file-noselect .filename)))))) + (with-selected-window window + (when (derived-mode-p 'pdf-view-mode) + (when (> .page 0) + (pdf-view-goto-page .page)) + (when .top + ;; Showing the tooltip delays displaying the page for + ;; some reason (sit-for/redisplay don't help), do it + ;; later. + (run-with-idle-timer 0.001 nil + (lambda () + (when (window-live-p window) + (with-selected-window window + (when (derived-mode-p 'pdf-view-mode) + (pdf-util-tooltip-arrow .top))))))))))) + (uri + (funcall pdf-links-browse-uri-function .uri)) + (t + (error "Unrecognized link type: %s" .type))) + nil)) + +(defun pdf-links-read-link-action (prompt) + "Using PROMPT, interactively read a link-action. + +See `pdf-links-action-perform' for the interface." + + (pdf-util-assert-pdf-window) + (let* ((links (pdf-cache-pagelinks + (pdf-view-current-page))) + (keys (pdf-links-read-link-action--create-keys + (length links))) + (key-strings (mapcar (apply-partially 'apply 'string) + keys)) + (alist (cl-mapcar 'cons keys links)) + (size (pdf-view-image-size)) + (colors (pdf-util-face-colors + 'pdf-links-read-link pdf-view-dark-minor-mode)) + (args (list + :foreground (car colors) + :background (cdr colors) + :formats + `((?c . ,(lambda (_edges) (pop key-strings))) + (?P . ,(number-to-string + (max 1 (* (cdr size) + pdf-links-convert-pointsize-scale))))) + :commands pdf-links-read-link-convert-commands + :apply (pdf-util-scale-relative-to-pixel + (mapcar (lambda (l) (cdr (assq 'edges l))) + links))))) + (unless links + (error "No links on this page")) + (unwind-protect + (let ((image-data + (pdf-cache-get-image + (pdf-view-current-page) + (car size) (car size) 'pdf-links-read-link-action))) + (unless image-data + (setq image-data (apply 'pdf-util-convert-page args )) + (pdf-cache-put-image + (pdf-view-current-page) + (car size) image-data 'pdf-links-read-link-action)) + (pdf-view-display-image + (create-image image-data (pdf-view-image-type) t)) + (pdf-links-read-link-action--read-chars prompt alist)) + (pdf-view-redisplay)))) + +(defun pdf-links-read-link-action--read-chars (prompt alist) + (catch 'done + (let (key) + (while t + (let* ((chars (append (mapcar 'caar alist) + (mapcar 'downcase (mapcar 'caar alist)) + (list ?\s))) + (ch (read-char-choice prompt chars))) + (setq ch (upcase ch)) + (cond + ((= ch ?\s) + (when (= (window-vscroll) (image-scroll-up)) + (image-scroll-down (window-vscroll)))) + (t + (setq alist (delq nil (mapcar (lambda (elt) + (and (eq ch (caar elt)) + (cons (cdar elt) + (cdr elt)))) + alist)) + key (append key (list ch)) + prompt (concat prompt (list ch))) + (when (= (length alist) 1) + (message nil) + (throw 'done (cdar alist)))))))))) + +(defun pdf-links-read-link-action--create-keys (n) + (when (> n 0) + (let ((len (1+ (floor (log n 26)))) + keys) + (dotimes (i n) + (let (key) + (dotimes (_x len) + (push (+ (% i 26) ?A) key) + (setq i (/ i 26))) + (push key keys))) + (nreverse keys)))) + +(defun pdf-links-isearch-link () + (interactive) + (let* (quit-p + (isearch-mode-end-hook + (cons (lambda nil + (setq quit-p isearch-mode-end-hook-quit)) + isearch-mode-end-hook)) + (pdf-isearch-filter-matches-function + 'pdf-links-isearch-link-filter-matches) + (pdf-isearch-narrow-to-page t) + (isearch-message-prefix-add "(Links)") + pdf-isearch-batch-mode) + (isearch-forward) + (unless (or quit-p (null pdf-isearch-current-match)) + (let* ((page (pdf-view-current-page)) + (match (car pdf-isearch-current-match)) + (size (pdf-view-image-size)) + (links (sort (cl-remove-if + (lambda (e) + (= 0 (pdf-util-edges-intersection-area (car e) match))) + (mapcar (lambda (l) + (cons (pdf-util-scale (alist-get 'edges l) size) + l)) + (pdf-cache-pagelinks page))) + (lambda (e1 e2) + (> (pdf-util-edges-intersection-area + (alist-get 'edges e1) match) + (pdf-util-edges-intersection-area + (alist-get 'edges e2) match)))))) + (unless links + (error "No link found at this position")) + (pdf-links-action-perform (car links)))))) + +(defun pdf-links-isearch-link-filter-matches (matches) + (let ((links (pdf-util-scale + (mapcar (apply-partially 'alist-get 'edges) + (pdf-cache-pagelinks + (pdf-view-current-page))) + (pdf-view-image-size)))) + (cl-remove-if-not + (lambda (m) + (cl-some + (lambda (edges) + (cl-some (lambda (link) + (pdf-util-with-edges (link edges) + (let ((area (min (* link-width link-height) + (* edges-width edges-height)))) + (> (/ (pdf-util-edges-intersection-area edges link) + (float area)) 0.5)))) + links)) + m)) + matches))) + +(defun pdf-links-browse-uri-default (uri) + "Open the string URI using Org. + +Wraps the URI in \[\[ ... \]\] and calls `org-open-link-from-string' +on the resulting string." + (cl-check-type uri string) + (message "Opening `%s' with Org" uri) + (cond + ((fboundp 'org-link-open-from-string) + (org-link-open-from-string (format "[[%s]]" uri))) + ;; For Org 9.2 and older + ((fboundp 'org-open-link-from-string) + (org-open-link-from-string (format "[[%s]]" uri))))) + +(provide 'pdf-links) + +;;; pdf-links.el ends here diff --git a/org/elpa/pdf-tools-20230404.327/pdf-loader.el b/org/elpa/pdf-tools-20230404.327/pdf-loader.el new file mode 100644 index 0000000..b1eab34 --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/pdf-loader.el @@ -0,0 +1,80 @@ +;;; pdf-loader.el --- Minimal PDF Tools loader -*- lexical-binding: t; -*- + +;; Copyright (C) 2017 Andreas Politz + +;; Author: Andreas Politz +;; Keywords: + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; + +;;; Code: + +(defconst pdf-loader--auto-mode-alist-item + (copy-sequence "\\.[pP][dD][fF]\\'") + "The item used in `auto-mode-alist'.") + +(defconst pdf-loader--magic-mode-alist-item + (copy-sequence "%PDF") + "The item used in`magic-mode-alist'.") + + +(declare-function pdf-tools-install "pdf-tools.el") + +;;;###autoload +(defun pdf-loader-install (&optional no-query-p skip-dependencies-p + no-error-p force-dependencies-p) + "Prepare Emacs for using PDF Tools. + +This function acts as a replacement for `pdf-tools-install' and +makes Emacs load and use PDF Tools as soon as a PDF file is +opened, but not sooner. + +The arguments are passed verbatim to `pdf-tools-install', which +see." + (let ((args (list no-query-p skip-dependencies-p + no-error-p force-dependencies-p))) + (if (featurep 'pdf-tools) + (apply #'pdf-tools-install args) + (pdf-loader--install + (lambda () + (apply #'pdf-loader--load args)))))) + +(defun pdf-loader--load (&rest args) + (pdf-loader--uninstall) + (save-selected-window + (pdf-tools-install args))) + +(defun pdf-loader--install (loader) + (pdf-loader--uninstall) + (push (cons pdf-loader--auto-mode-alist-item loader) + auto-mode-alist) + (push (cons pdf-loader--magic-mode-alist-item loader) + magic-mode-alist)) + +(defun pdf-loader--uninstall () + (let ((elt (assoc pdf-loader--auto-mode-alist-item + auto-mode-alist))) + (when elt + (setq auto-mode-alist (remove elt auto-mode-alist)))) + (let ((elt (assoc pdf-loader--magic-mode-alist-item + magic-mode-alist))) + (when elt + (setq magic-mode-alist (remove elt magic-mode-alist))))) + +(provide 'pdf-loader) +;;; pdf-loader.el ends here diff --git a/org/elpa/pdf-tools-20230404.327/pdf-macs.el b/org/elpa/pdf-tools-20230404.327/pdf-macs.el new file mode 100644 index 0000000..e4ac6ea --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/pdf-macs.el @@ -0,0 +1,51 @@ +;;; pdf-macs.el --- Macros for pdf-tools. -*- lexical-binding:t -*- + +;; Copyright (C) 2013 Andreas Politz + +;; Author: Andreas Politz +;; Keywords: files, doc-view, pdf + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; +;;; Code: +;; + +(defmacro pdf-view-current-page (&optional window) + ;;TODO: write documentation! + `(image-mode-window-get 'page ,window)) + +(defmacro pdf-view-current-overlay (&optional window) + ;;TODO: write documentation! + `(image-mode-window-get 'overlay ,window)) + +(defmacro pdf-view-current-image (&optional window) + ;;TODO: write documentation! + `(image-mode-window-get 'image ,window)) + +(defmacro pdf-view-current-slice (&optional window) + ;;TODO: write documentation! + `(image-mode-window-get 'slice ,window)) + +(defmacro pdf-view-current-window-size (&optional window) + ;;TODO: write documentation! + `(image-mode-window-get 'window-size ,window)) + +(defmacro pdf-view-window-needs-redisplay (&optional window) + `(image-mode-window-get 'needs-redisplay ,window)) + +(provide 'pdf-macs) + +;;; pdf-macs.el ends here diff --git a/org/elpa/pdf-tools-20230404.327/pdf-misc.el b/org/elpa/pdf-tools-20230404.327/pdf-misc.el new file mode 100644 index 0000000..b6bb896 --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/pdf-misc.el @@ -0,0 +1,300 @@ +;;; pdf-misc.el --- Miscellaneous commands for PDF buffer. -*- lexical-binding: t; -*- + +;; Copyright (C) 2013, 2014 Andreas Politz + +;; Author: Andreas Politz +;; Keywords: files, multimedia + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; + + +(require 'pdf-view) +(require 'pdf-util) +(require 'imenu) + + + +;;; Code: + +(defvar pdf-misc-minor-mode-map + (let ((map (make-sparse-keymap))) + (define-key map (kbd "I") 'pdf-misc-display-metadata) + (define-key map (kbd "C-c C-p") 'pdf-misc-print-document) + map) + "Keymap used in `pdf-misc-minor-mode'.") + +;;;###autoload +(define-minor-mode pdf-misc-minor-mode + "FIXME: Not documented." + :group 'pdf-misc) + +;;;###autoload +(define-minor-mode pdf-misc-size-indication-minor-mode + "Provide a working size indication in the mode-line." + :group 'pdf-misc + (pdf-util-assert-pdf-buffer) + (cond + (pdf-misc-size-indication-minor-mode + (unless (assq 'pdf-misc-size-indication-minor-mode + mode-line-position) + (setq mode-line-position + `((pdf-misc-size-indication-minor-mode + (:eval (pdf-misc-size-indication))) + ,@mode-line-position)))) + (t + (setq mode-line-position + (cl-remove 'pdf-misc-size-indication-minor-mode + mode-line-position :key 'car-safe))))) + +(defun pdf-misc-size-indication () + "Return size indication string for the mode-line." + (let ((top (= (window-vscroll nil t) 0)) + (bot (>= (+ (- (nth 3 (window-inside-pixel-edges)) + (nth 1 (window-inside-pixel-edges))) + (window-vscroll nil t)) + (cdr (pdf-view-image-size t))))) + (cond + ((and top bot) " All") + (top " Top") + (bot " Bot") + (t (format + " %d%%%%" + (ceiling + (* 100 (/ (float (window-vscroll nil t)) + (cdr (pdf-view-image-size t)))))))))) + +(defvar pdf-misc-menu-bar-minor-mode-map (make-sparse-keymap) + "The keymap used in `pdf-misc-menu-bar-minor-mode'.") + +(easy-menu-define nil pdf-misc-menu-bar-minor-mode-map + "Menu for PDF Tools." + `("PDF Tools" + ["Go Backward" pdf-history-backward + :visible (bound-and-true-p pdf-history-minor-mode) + :active (and (bound-and-true-p pdf-history-minor-mode) + (not (pdf-history-end-of-history-p)))] + ["Go Forward" pdf-history-forward + :visible (bound-and-true-p pdf-history-minor-mode) + :active (not (pdf-history-end-of-history-p))] + ["--" nil + :visible (derived-mode-p 'pdf-virtual-view-mode)] + ["Next file" pdf-virtual-buffer-forward-file + :visible (derived-mode-p 'pdf-virtual-view-mode) + :active (pdf-virtual-document-next-file + (pdf-view-current-page))] + ["Previous file" pdf-virtual-buffer-backward-file + :visible (derived-mode-p 'pdf-virtual-view-mode) + :active (not (eq 1 (pdf-view-current-page)))] + ["--" nil + :visible (bound-and-true-p pdf-history-minor-mode)] + ["Add text annotation" pdf-annot-mouse-add-text-annotation + :visible (bound-and-true-p pdf-annot-minor-mode) + :keys "\\[pdf-annot-add-text-annotation]"] + ("Add markup annotation" + :active (pdf-view-active-region-p) + :visible (and (bound-and-true-p pdf-annot-minor-mode) + (pdf-info-markup-annotations-p)) + ["highlight" pdf-annot-add-highlight-markup-annotation] + ["squiggly" pdf-annot-add-squiggly-markup-annotation] + ["underline" pdf-annot-add-underline-markup-annotation] + ["strikeout" pdf-annot-add-strikeout-markup-annotation]) + ["--" nil :visible (bound-and-true-p pdf-annot-minor-mode)] + ["Display Annotations" pdf-annot-list-annotations + :help "List all annotations" + :visible (bound-and-true-p pdf-annot-minor-mode)] + ["Display Attachments" pdf-annot-attachment-dired + :help "Display attachments in a dired buffer" + :visible (featurep 'pdf-annot)] + ["Display Metadata" pdf-misc-display-metadata + :help "Display information about the document" + :visible (featurep 'pdf-misc)] + ["Display Outline" pdf-outline + :help "Display documents outline" + :visible (featurep 'pdf-outline)] + "--" + ("Render Options" + ["Printed Mode" (lambda () + (interactive) + (pdf-view-printer-minor-mode 'toggle)) + :style toggle + :selected pdf-view-printer-minor-mode + :help "Display the PDF as it would be printed."] + ["Midnight Mode" (lambda () + (interactive) + (pdf-view-midnight-minor-mode 'toggle)) + :style toggle + :selected pdf-view-midnight-minor-mode + :help "Apply a color-filter appropriate for past midnight reading."]) + "--" + ["Copy region" pdf-view-kill-ring-save + :keys "\\[kill-ring-save]" + :active (pdf-view-active-region-p)] + "--" + ["Isearch document" isearch-forward + :visible (bound-and-true-p pdf-isearch-minor-mode)] + ["Occur document" pdf-occur + :visible (featurep 'pdf-occur)] + "--" + ["Locate TeX source" pdf-sync-backward-search-mouse + :visible (and (featurep 'pdf-sync) + (equal last-command-event + last-nonmenu-event))] + ["--" nil :visible (and (featurep 'pdf-sync) + (equal last-command-event + last-nonmenu-event))] + ["Print" pdf-misc-print-document + :active (and (pdf-view-buffer-file-name) + (file-readable-p (pdf-view-buffer-file-name)))] + ["Create image" pdf-view-extract-region-image + :help "Create an image of the page or the selected region(s)."] + ["Create virtual PDF" pdf-virtual-buffer-create + :help "Create a PDF containing all documents in this directory." + :visible (bound-and-true-p pdf-virtual-global-minor-mode)] + "--" + ["Revert buffer" pdf-view-revert-buffer + :visible (pdf-info-writable-annotations-p)] + "--" + ["Customize" pdf-tools-customize])) + +;;;###autoload +(define-minor-mode pdf-misc-menu-bar-minor-mode + "Display a PDF Tools menu in the menu-bar." + :group 'pdf-misc + (pdf-util-assert-pdf-buffer)) + +(defvar pdf-misc-context-menu-minor-mode-map + (let ((kmap (make-sparse-keymap))) + (define-key kmap [down-mouse-3] 'pdf-misc-popup-context-menu) + kmap)) + +;;;###autoload +(define-minor-mode pdf-misc-context-menu-minor-mode + "Provide a right-click context menu in PDF buffers. + +\\{pdf-misc-context-menu-minor-mode-map}" + :group 'pdf-misc + (pdf-util-assert-pdf-buffer)) + +(defun pdf-misc-popup-context-menu (_event) + "Popup a context menu at position." + (interactive "@e") + (popup-menu + (cons 'keymap + (cddr (or (lookup-key pdf-misc-menu-bar-minor-mode-map + [menu-bar PDF\ Tools]) + (lookup-key pdf-misc-menu-bar-minor-mode-map + [menu-bar pdf\ tools])))))) + +(defun pdf-misc-display-metadata () + "Display all available metadata in a separate buffer." + (interactive) + (pdf-util-assert-pdf-buffer) + (let* ((buffer (current-buffer)) + (md (pdf-info-metadata))) + (with-current-buffer (get-buffer-create "*PDF-Metadata*") + (let* ((inhibit-read-only t) + (pad (apply' max (mapcar (lambda (d) + (length (symbol-name (car d)))) + md))) + (fmt (format "%%%ds:%%s\n" pad))) + (erase-buffer) + (setq header-line-format (buffer-name buffer) + buffer-read-only t) + (font-lock-mode 1) + (font-lock-add-keywords nil + '(("^ *\\(\\(?:\\w\\|-\\)+\\):" + (1 font-lock-keyword-face)))) + (dolist (d md) + (let ((key (car d)) + (val (cdr d))) + (cl-case key + (keywords + (setq val (mapconcat 'identity val ", ")))) + (let ((beg (+ (length (symbol-name key)) (point) 1)) + (fill-prefix + (make-string (1+ pad) ?\s))) + (insert (format fmt key val)) + (fill-region beg (point) ))))) + (goto-char 1) + (display-buffer (current-buffer))) + md)) + +(defgroup pdf-misc nil + "Miscellaneous options for PDF documents." + :group 'pdf-tools) + +(define-obsolete-variable-alias 'pdf-misc-print-programm + 'pdf-misc-print-program-executable "1.0") +(defcustom pdf-misc-print-program-executable nil + "The program used for printing. + +It is called with one argument, the PDF file." + :group 'pdf-misc + :type 'file) + +(define-obsolete-variable-alias 'pdf-misc-print-programm-args + 'pdf-misc-print-program-args "1.0") +(defcustom pdf-misc-print-program-args nil + "List of additional arguments passed to `pdf-misc-print-program'." + :group 'pdf-misc + :type '(repeat string)) + +(define-obsolete-function-alias 'pdf-misc-print-programm + 'pdf-misc-print-program "1.0") +(defun pdf-misc-print-program (&optional interactive-p) + "Return the program used to print PDFs (if the executable is installed). + +If INTERACTIVE-P is non-nil, ask the user for which program to +use when printing the PDF. Optionally, save the choice" + (or (and pdf-misc-print-program-executable + (executable-find pdf-misc-print-program-executable)) + (when interactive-p + (let* ((default (car (delq nil (mapcar + 'executable-find + '("gtklp" "xpp" "gpr"))))) + buffer-file-name + (program + (expand-file-name + (read-file-name + "Print with: " default nil t nil 'file-executable-p)))) + (when (and program + (executable-find program)) + (when (y-or-n-p "Save choice using customize? ") + (customize-save-variable + 'pdf-misc-print-program-executable program)) + (setq pdf-misc-print-program-executable program)))))) + +(defun pdf-misc-print-document (filename &optional interactive-p) + "Print the PDF doc FILENAME. + +`pdf-misc-print-program' handles the print program, which see for +definition of INTERACTIVE-P." + (interactive + (list (pdf-view-buffer-file-name) t)) + (cl-check-type filename (and string (satisfies file-readable-p))) + (let ((program (pdf-misc-print-program interactive-p)) + (args (append pdf-misc-print-program-args (list filename)))) + (unless program + (error "No print program available")) + (apply #'start-process "printing" nil program args) + (message "Print job started: %s %s" + program (mapconcat #'identity args " ")))) + + +(provide 'pdf-misc) + +;;; pdf-misc.el ends here diff --git a/org/elpa/pdf-tools-20230404.327/pdf-occur.el b/org/elpa/pdf-tools-20230404.327/pdf-occur.el new file mode 100644 index 0000000..47bf2d2 --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/pdf-occur.el @@ -0,0 +1,820 @@ +;;; pdf-occur.el --- Display matching lines of PDF documents. -*- lexical-binding: t -*- + +;; Copyright (C) 2013, 2014 Andreas Politz + +;; Author: Andreas Politz +;; Keywords: files, multimedia + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; + +(require 'pdf-tools) +(require 'pdf-view) +(require 'pdf-util) +(require 'pdf-info) +(require 'pdf-isearch) +(require 'tablist) +(require 'ibuf-ext) +(require 'dired) +(require 'let-alist) + +;;; Code: + + + + +;; * ================================================================== * +;; * Custom & Variables +;; * ================================================================== * + +(defgroup pdf-occur nil + "Display matching lines of PDF documents." + :group 'pdf-tools) + +(defface pdf-occur-document-face + '((default (:inherit font-lock-string-face))) + "Face used to highlight documents in the list buffer.") + +(defface pdf-occur-page-face + '((default (:inherit font-lock-type-face))) + "Face used to highlight page numbers in the list buffer.") + +(defcustom pdf-occur-search-batch-size 16 + "Maximum number of pages searched in one query. + +Lower numbers will make Emacs more responsive when searching at +the cost of slightly increased search time." + :type 'integer) + +(defcustom pdf-occur-prefer-string-search nil + "If non-nil, reverse the meaning of the regexp-p prefix-arg." + :type 'boolean) + +(defvar pdf-occur-history nil + "The history variable for search strings.") + +(defvar pdf-occur-search-pages-left nil + "The total number of pages left to search.") + +(defvar pdf-occur-search-documents nil + "The list of searched documents. + +Each element should be either the filename of a PDF document or a +cons \(FILENAME . PAGES\), where PAGES is the list of pages to +search. See `pdf-info-normalize-page-range' for its format.") + +(defvar pdf-occur-number-of-matches 0 + "The number of matches in all searched documents.") + +(defvar pdf-occur-search-string nil + "The currently used search string, resp. regexp.") + +(defvar pdf-occur-search-regexp-p nil + "Non-nil, if searching for a regexp.") + +(defvar pdf-occur-buffer-mode-map + (let ((kmap (make-sparse-keymap))) + (set-keymap-parent kmap tablist-mode-map) + (define-key kmap (kbd "RET") #'pdf-occur-goto-occurrence) + (define-key kmap (kbd "C-o") #'pdf-occur-view-occurrence) + (define-key kmap (kbd "SPC") #'pdf-occur-view-occurrence) + (define-key kmap (kbd "C-c C-f") #'next-error-follow-minor-mode) + (define-key kmap (kbd "g") #'pdf-occur-revert-buffer-with-args) + (define-key kmap (kbd "K") #'pdf-occur-abort-search) + (define-key kmap (kbd "D") #'pdf-occur-tablist-do-delete) + (define-key kmap (kbd "x") #'pdf-occur-tablist-do-flagged-delete) + (define-key kmap (kbd "A") #'pdf-occur-tablist-gather-documents) + kmap) + "The keymap used for `pdf-occur-buffer-mode'.") + + +;; * ================================================================== * +;; * High level functions +;; * ================================================================== * + +(define-derived-mode pdf-occur-buffer-mode tablist-mode "PDFOccur" + "Major mode for output from `pdf-occur`. \\ + +Some useful keys are: + +\\[pdf-occur-abort-search] - Abort the search. +\\[pdf-occur-revert-buffer-with-args] - Restart the search. +\\[universal-argument] \\[pdf-occur-revert-buffer-with-args] - Restart search with different regexp. +\\[universal-argument] \\[universal-argument] \\[pdf-occur-revert-buffer-with-args] - Same, but do a plain string search. + +\\[tablist-push-regexp-filter] - Filter matches by regexp on current or prefix-th column. +\\[tablist-pop-filter] - Remove last added filter. + +\\[pdf-occur-tablist-do-delete] - Remove the current file from the search. +\\[pdf-occur-tablist-gather-documents] - Include marked files from displayed `dired'/`ibuffer' and + `pdf-view-mode' buffers in the search. + +\\{pdf-occur-buffer-mode-map}" + (setq-local case-fold-search case-fold-search) + (setq-local next-error-function #'pdf-occur-next-error) + (setq-local revert-buffer-function + #'pdf-occur-revert-buffer) + (setq next-error-last-buffer (current-buffer)) + (setq-local tabulated-list-sort-key nil) + (setq-local tabulated-list-use-header-line t) + (setq-local tablist-operations-function + (lambda (op &rest _) + (cl-case op + (supported-operations '(find-entry)) + (find-entry + (let ((display-buffer-overriding-action + '(display-buffer-same-window))) + (pdf-occur-goto-occurrence))))))) + +;;;###autoload +(defun pdf-occur (string &optional regexp-p) + "List lines matching STRING or PCRE. + +Interactively search for a regexp. Unless a prefix arg was given, +in which case this functions performs a string search. + +If `pdf-occur-prefer-string-search' is non-nil, the meaning of +the prefix-arg is inverted." + (interactive + (progn + (pdf-util-assert-pdf-buffer) + (list + (pdf-occur-read-string + (pdf-occur-want-regexp-search-p)) + (pdf-occur-want-regexp-search-p)))) + (pdf-util-assert-pdf-buffer) + (pdf-occur-search (list (current-buffer)) string regexp-p)) + +(defvar ibuffer-filtering-qualifiers) +;;;###autoload +(defun pdf-occur-multi-command () + "Perform `pdf-occur' on multiple buffer. + +For a programmatic search of multiple documents see +`pdf-occur-search'." + (interactive) + (ibuffer) + (with-current-buffer "*Ibuffer*" + (pdf-occur-ibuffer-minor-mode) + (unless (member '(derived-mode . pdf-view-mode) + ibuffer-filtering-qualifiers) + (ibuffer-filter-by-derived-mode 'pdf-view-mode)) + (message + "%s" + (substitute-command-keys + "Mark a bunch of PDF buffers and type \\[pdf-occur-ibuffer-do-occur]")) + (sit-for 3))) + +(defun pdf-occur-revert-buffer (&rest _) + "Restart the search." + (pdf-occur-assert-occur-buffer-p) + (unless pdf-occur-search-documents + (error "No documents to search")) + (unless pdf-occur-search-string + (error "Nothing to search for")) + (let* ((2-columns-p (= 1 (length pdf-occur-search-documents))) + (filename-width + (min 24 + (apply #'max + (mapcar #'length + (mapcar #'pdf-occur-abbrev-document + (mapcar #'car pdf-occur-search-documents)))))) + (page-sorter (tablist-generate-sorter + (if 2-columns-p 0 1) + '< + 'string-to-number))) + (setq tabulated-list-format + (if 2-columns-p + `[("Page" 4 ,page-sorter :right-align t) + ("Line" 0 t)] + `[("Document" ,filename-width t) + ("Page" 4 ,page-sorter :right-align t) + ("Line" 0 t)]) + tabulated-list-entries nil)) + (tabulated-list-revert) + (pdf-occur-start-search + pdf-occur-search-documents + pdf-occur-search-string + pdf-occur-search-regexp-p) + (pdf-occur-update-header-line) + (setq mode-line-process + '(:propertize ":run" face compilation-mode-line-run))) + +(defun pdf-occur-revert-buffer-with-args (string &optional regexp-p documents) + "Restart the search with modified arguments. + +Interactively just restart the search, unless a prefix was given. +In this case read a new search string. With `C-u C-u' as prefix +additionally invert the current state of +`pdf-occur-search-regexp-p'." + (interactive + (progn + (pdf-occur-assert-occur-buffer-p) + (cond + (current-prefix-arg + (let ((regexp-p + (if (equal current-prefix-arg '(16)) + (not pdf-occur-search-regexp-p) + pdf-occur-search-regexp-p))) + (list + (pdf-occur-read-string regexp-p) + regexp-p))) + (t + (list pdf-occur-search-string + pdf-occur-search-regexp-p))))) + (setq pdf-occur-search-string string + pdf-occur-search-regexp-p regexp-p) + (when documents + (setq pdf-occur-search-documents + (pdf-occur-normalize-documents documents))) + (pdf-occur-revert-buffer)) + +(defun pdf-occur-abort-search () + "Abort the current search. + +This immediately kills the search process." + (interactive) + (unless (pdf-occur-search-in-progress-p) + (user-error "No search in progress")) + (pdf-info-kill-local-server) + (pdf-occur-search-finished t)) + + +;; * ================================================================== * +;; * Finding occurrences +;; * ================================================================== * + + +(defun pdf-occur-goto-occurrence (&optional no-select-window-p) + "Go to the occurrence at point. + +If EVENT is nil, use occurrence at current line. Select the +PDF's window, unless NO-SELECT-WINDOW-P is non-nil. + +FIXME: EVENT not used at the moment." + (interactive) + (let ((item (tabulated-list-get-id))) + (when item + (let* ((doc (plist-get item :document)) + (page (plist-get item :page)) + (match (plist-get item :match-edges)) + (buffer (if (bufferp doc) + doc + (or (find-buffer-visiting doc) + (find-file-noselect doc)))) + window) + (if no-select-window-p + (setq window (display-buffer buffer)) + (pop-to-buffer buffer) + (setq window (selected-window))) + (with-selected-window window + (when page + (pdf-view-goto-page page)) + ;; Abuse isearch. + (when match + (let ((pixel-match + (pdf-util-scale-relative-to-pixel match)) + (pdf-isearch-batch-mode t)) + (pdf-isearch-hl-matches pixel-match nil t) + (pdf-isearch-focus-match-batch pixel-match)))))))) + +(defun pdf-occur-view-occurrence (&optional _event) + "View the occurrence at EVENT. + +If EVENT is nil, use occurrence at current line." + (interactive (list last-nonmenu-event)) + (pdf-occur-goto-occurrence t)) + +(defun pdf-occur-next-error (&optional arg reset) + "Move to the Nth (default 1) next match in an PDF Occur mode buffer. +Compatibility function for \\[next-error] invocations." + (interactive "p") + ;; we need to run pdf-occur-find-match from within the Occur buffer + (with-current-buffer + ;; Choose the buffer and make it current. + (if (next-error-buffer-p (current-buffer)) + (current-buffer) + (next-error-find-buffer + nil nil + (lambda () + (eq major-mode 'pdf-occur-buffer-mode)))) + (when (bobp) + (setq reset t)) + (if reset + (goto-char (point-min)) + (beginning-of-line)) + (when (/= arg 0) + (when (eobp) + (forward-line -1)) + (when reset + (cl-decf arg)) + (let ((line (line-number-at-pos)) + (limit (line-number-at-pos + (if (>= arg 0) + (1- (point-max)) + (point-min))))) + (when (= line limit) + (error "No more matches")) + (forward-line + (if (>= arg 0) + (min arg (- limit line)) + (max arg (- limit line)))))) + ;; In case the *Occur* buffer is visible in a nonselected window. + (tablist-move-to-major-column) + (let ((win (get-buffer-window (current-buffer) t))) + (if win (set-window-point win (point)))) + (pdf-occur-goto-occurrence))) + + +;; * ================================================================== * +;; * Integration with other modes +;; * ================================================================== * + +;;;###autoload +(define-minor-mode pdf-occur-global-minor-mode + "Enable integration of Pdf Occur with other modes. + +This global minor mode enables (or disables) +`pdf-occur-ibuffer-minor-mode' and `pdf-occur-dired-minor-mode' +in all current and future ibuffer/dired buffer." + :global t + (let ((arg (if pdf-occur-global-minor-mode 1 -1))) + (dolist (buf (buffer-list)) + (with-current-buffer buf + (cond + ((derived-mode-p 'dired-mode) + (pdf-occur-dired-minor-mode arg)) + ((derived-mode-p 'ibuffer-mode) + (pdf-occur-ibuffer-minor-mode arg))))) + (cond + (pdf-occur-global-minor-mode + (add-hook 'dired-mode-hook #'pdf-occur-dired-minor-mode) + (add-hook 'ibuffer-mode-hook #'pdf-occur-ibuffer-minor-mode)) + (t + (remove-hook 'dired-mode-hook #'pdf-occur-dired-minor-mode) + (remove-hook 'ibuffer-mode-hook #'pdf-occur-ibuffer-minor-mode))))) + +(defvar pdf-occur-ibuffer-minor-mode-map + (let ((map (make-sparse-keymap))) + (define-key map [remap ibuffer-do-occur] #'pdf-occur-ibuffer-do-occur) + map) + "Keymap used in `pdf-occur-ibuffer-minor-mode'.") + +;;;###autoload +(define-minor-mode pdf-occur-ibuffer-minor-mode + "Hack into ibuffer's do-occur binding. + +This mode remaps `ibuffer-do-occur' to +`pdf-occur-ibuffer-do-occur', which will start the PDF Tools +version of `occur', if all marked buffer's are in `pdf-view-mode' +and otherwise fallback to `ibuffer-do-occur'.") + +(defun pdf-occur-ibuffer-do-occur (&optional regexp-p) + "Uses `pdf-occur-search', if appropriate. + +I.e. all marked buffers are in PDFView mode." + (interactive + (list (pdf-occur-want-regexp-search-p))) + (let* ((buffer (or (ibuffer-get-marked-buffers) + (and (ibuffer-current-buffer) + (list (ibuffer-current-buffer))))) + (pdf-only-p (cl-every + (lambda (buf) + (with-current-buffer buf + (derived-mode-p 'pdf-view-mode))) + buffer))) + (if (not pdf-only-p) + (call-interactively 'ibuffer-do-occur) + (let ((regexp (pdf-occur-read-string regexp-p))) + (pdf-occur-search buffer regexp regexp-p))))) + +(defvar pdf-occur-dired-minor-mode-map + (let ((map (make-sparse-keymap))) + (define-key map [remap dired-do-search] #'pdf-occur-dired-do-search) + map) + "Keymap used in `pdf-occur-dired-minor-mode'.") + +;;;###autoload +(define-minor-mode pdf-occur-dired-minor-mode + "Hack into dired's `dired-do-search' binding. + +This mode remaps `dired-do-search' to +`pdf-occur-dired-do-search', which will start the PDF Tools +version of `occur', if all marked buffer's are in `pdf-view-mode' +and otherwise fallback to `dired-do-search'.") + +(defun pdf-occur-dired-do-search () + "Uses `pdf-occur-search', if appropriate. + +I.e. all marked files look like PDF documents." + (interactive) + (let ((files (dired-get-marked-files))) + (if (not (cl-every (lambda (file) + (string-match-p + (car pdf-tools-auto-mode-alist-entry) + file)) + files)) + (call-interactively 'dired-do-search) + (let* ((regex-p (pdf-occur-want-regexp-search-p)) + (regexp (pdf-occur-read-string regex-p))) + (pdf-occur-search files regexp regex-p))))) + + + +;; * ================================================================== * +;; * Search engine +;; * ================================================================== * + + +(defun pdf-occur-search (documents string &optional regexp-p) + "Search DOCUMENTS for STRING. + +DOCUMENTS should be a list of buffers (objects, not names), +filenames or conses \(BUFFER-OR-FILENAME . PAGES\), where PAGES +determines the scope of the search of the respective document. +See `pdf-info-normalize-page-range' for its format. + +STRING is either the string to search for or, if REGEXP-P is +non-nil, a Perl compatible regular expression (PCRE). + +Display the occur buffer and start the search asynchronously. + +Returns the window where the buffer is displayed." + + (unless documents + (error "No documents to search")) + (when (or (null string) (= (length string) 0)) + (error "Not searching for the empty string")) + (with-current-buffer (get-buffer-create "*PDF-Occur*") + (pdf-occur-buffer-mode) + (setq-local pdf-occur-search-documents + (pdf-occur-normalize-documents documents)) + (setq-local pdf-occur-search-string string) + (setq-local pdf-occur-search-regexp-p regexp-p) + (setq-local pdf-occur-search-pages-left 0) + (setq-local pdf-occur-number-of-matches 0) + (pdf-occur-revert-buffer) + (display-buffer + (current-buffer)))) + +(advice-add 'tabulated-list-init-header :after #'pdf-occur--update-header) +(defun pdf-occur--update-header (&rest _) + "We want our own headers, thank you." + (when (derived-mode-p 'pdf-occur-buffer-mode) + (save-current-buffer + (with-no-warnings (pdf-occur-update-header-line))))) + +(defun pdf-occur-create-entry (filename page &optional match) + "Create a `tabulated-list-entries' entry for a search result. + +If match is nil, create a fake entry for documents w/o any +matches linked with PAGE." + (let* ((text (or (car match) "[No matches]")) + (edges (cdr match)) + (displayed-text + (if match + (replace-regexp-in-string "\n" "\\n" text t t) + (propertize text 'face 'font-lock-warning-face))) + (displayed-page + (if match + (propertize (format "%d" page) + 'face 'pdf-occur-page-face) + "")) + (displayed-document + (propertize + (pdf-occur-abbrev-document filename) + 'face 'pdf-occur-document-face)) + (id `(:document ,filename + :page ,page + :match-text ,(if match text) + :match-edges ,(if match edges)))) + (list id + (if (= (length pdf-occur-search-documents) 1) + (vector displayed-page displayed-text) + (vector displayed-document + displayed-page + displayed-text))))) + +(defun pdf-occur-update-header-line () + (pdf-occur-assert-occur-buffer-p) + (save-current-buffer + ;;force-mode-line-update seems to sometimes spuriously change the + ;;current buffer. + (setq header-line-format + `(:eval (concat + (if (= (length pdf-occur-search-documents) 1) + (format "%d match%s in document `%s'" + pdf-occur-number-of-matches + (if (/= 1 pdf-occur-number-of-matches) "es" "") + (pdf-occur-abbrev-document + (caar pdf-occur-search-documents))) + (format "%d match%s in %d documents" + pdf-occur-number-of-matches + (if (/= 1 pdf-occur-number-of-matches) "es" "") + (length pdf-occur-search-documents))) + (if (pdf-occur-search-in-progress-p) + (propertize + (concat " [" + (if (numberp pdf-occur-search-pages-left) + (format "%d pages left" + pdf-occur-search-pages-left) + "Searching") + "]") + 'face 'compilation-mode-line-run))))) + (force-mode-line-update))) + +(defun pdf-occur-search-finished (&optional abort-p) + (setq pdf-occur-search-pages-left 0) + (setq mode-line-process + (if abort-p + '(:propertize + ":aborted" face compilation-mode-line-fail) + '(:propertize + ":exit" face compilation-mode-line-exit))) + (let ((unmatched + (mapcar (lambda (doc) + (pdf-occur-create-entry doc 1)) + (cl-set-difference + (mapcar #'car + pdf-occur-search-documents) + (mapcar (lambda (elt) + (plist-get (car elt) :document)) + tabulated-list-entries) + :test 'equal)))) + (when (and unmatched + (> (length pdf-occur-search-documents) 1)) + (pdf-occur-insert-entries unmatched))) + (tablist-apply-filter) + (pdf-occur-update-header-line) + (pdf-isearch-message + (if abort-p + "Search aborted." + (format "Occur search finished with %d matches" + pdf-occur-number-of-matches)))) + +(defun pdf-occur-add-matches (filename matches) + (pdf-occur-assert-occur-buffer-p) + (when matches + (let (entries) + (dolist (match matches) + (let-alist match + (push (pdf-occur-create-entry filename .page (cons .text .edges)) + entries))) + (setq entries (nreverse entries)) + (pdf-occur-insert-entries entries)))) + +(defun pdf-occur-insert-entries (entries) + "Insert tabulated-list ENTRIES at the end." + (pdf-occur-assert-occur-buffer-p) + (let ((inhibit-read-only t) + (end-of-buffer (and (eobp) (not (bobp))))) + (save-excursion + (goto-char (point-max)) + (dolist (elt entries) + (apply tabulated-list-printer elt)) + (set-buffer-modified-p nil)) + (when end-of-buffer + (dolist (win (get-buffer-window-list)) + (set-window-point win (point-max)))) + (setq tabulated-list-entries + (append tabulated-list-entries + entries)))) + +(defun pdf-occur-search-in-progress-p () + (and (numberp pdf-occur-search-pages-left) + (> pdf-occur-search-pages-left 0))) + +(defun pdf-occur-start-search (documents string + &optional regexp-p) + (pdf-occur-assert-occur-buffer-p) + (pdf-info-make-local-server nil t) + (let ((batches (pdf-occur-create-batches + documents (or pdf-occur-search-batch-size 1)))) + (pdf-info-local-batch-query + (lambda (document pages) + (if regexp-p + (pdf-info-search-regexp string pages nil document) + (pdf-info-search-string string pages document))) + (lambda (status response document pages) + (if status + (error "%s" response) + (when (numberp pdf-occur-search-pages-left) + (cl-decf pdf-occur-search-pages-left + (1+ (- (cdr pages) (car pages))))) + (when (cl-member document pdf-occur-search-documents + :key 'car + :test 'equal) + (cl-incf pdf-occur-number-of-matches + (length response)) + (pdf-occur-add-matches document response) + (pdf-occur-update-header-line)))) + (lambda (status buffer) + (when (buffer-live-p buffer) + (with-current-buffer buffer + (pdf-occur-search-finished (eq status 'killed))))) + batches) + (setq pdf-occur-number-of-matches 0) + (setq pdf-occur-search-pages-left + (apply #'+ (mapcar (lambda (elt) + (1+ (- (cdr (nth 1 elt)) + (car (nth 1 elt))))) + batches))))) + + + +;; * ================================================================== * +;; * Editing searched documents +;; * ================================================================== * + +(defun pdf-occur-tablist-do-delete (&optional arg) + "Delete ARG documents from the search list." + (interactive "P") + (when (pdf-occur-search-in-progress-p) + (user-error "Can't delete while a search is in progress.")) + (let* ((items (tablist-get-marked-items arg)) + (documents (cl-remove-duplicates + (mapcar (lambda (entry) + (plist-get (car entry) :document)) + items) + :test 'equal))) + (unless documents + (error "No documents selected")) + (when (tablist-yes-or-no-p + 'Stop\ searching + nil (mapcar (lambda (d) (cons nil (vector d))) + documents)) + (setq pdf-occur-search-documents + (cl-remove-if (lambda (elt) + (member (car elt) documents)) + pdf-occur-search-documents) + tabulated-list-entries + (cl-remove-if (lambda (elt) + (when (member (plist-get (car elt) :document) + documents) + (when (plist-get (car elt) :match-edges) + (cl-decf pdf-occur-number-of-matches)) + t)) + tabulated-list-entries)) + (tablist-revert) + (pdf-occur-update-header-line) + (tablist-move-to-major-column)))) + +(defun pdf-occur-tablist-do-flagged-delete (&optional interactive) + "Stop searching all documents marked with a D." + (interactive "p") + (let* ((tablist-marker-char ?D)) + (if (save-excursion + (goto-char (point-min)) + (re-search-forward (tablist-marker-regexp) nil t)) + (pdf-occur-tablist-do-delete) + (or (not interactive) + (message "(No deletions requested)"))))) + +(defun pdf-occur-tablist-gather-documents () + "Gather marked documents in windows. + +Examine all dired/ibuffer windows and offer to put marked files +in the search list." + (interactive) + (let ((searched (mapcar #'car pdf-occur-search-documents)) + files) + (dolist (win (window-list)) + (with-selected-window win + (cond + ((derived-mode-p 'dired-mode) + (let ((marked (dired-get-marked-files nil nil nil t))) + (when (> (length marked) 1) + (when (eq t (car marked)) + (setq marked (cdr marked))) + (setq files + (append files marked nil))))) + ((derived-mode-p 'ibuffer-mode) + (dolist (fname (mapcar #'buffer-file-name + (ibuffer-get-marked-buffers))) + (when fname + (push fname files)))) + ((and (derived-mode-p 'pdf-view-mode) + (buffer-file-name)) + (push (buffer-file-name) files))))) + + (setq files + (cl-sort ;Looks funny. + (cl-set-difference + (cl-remove-duplicates + (cl-remove-if-not + (lambda (file) (string-match-p + (car pdf-tools-auto-mode-alist-entry) + file)) + files) + :test 'file-equal-p) + searched + :test 'file-equal-p) + 'string-lessp)) + (if (null files) + (message "No marked, new PDF files found in windows") + (when (tablist-yes-or-no-p + 'add nil (mapcar (lambda (file) + (cons nil (vector file))) + (cl-sort files #'string-lessp))) + (setq pdf-occur-search-documents + (append pdf-occur-search-documents + (pdf-occur-normalize-documents files))) + (message "Added %d file%s to the list of searched documents%s" + (length files) + (dired-plural-s (length files)) + (substitute-command-keys + " - Hit \\[pdf-occur-revert-buffer-with-args]")))))) + + +;; * ================================================================== * +;; * Utilities +;; * ================================================================== * + +(defun pdf-occur-read-string (&optional regexp-p) + (read-string + (concat + (format "List lines %s" + (if regexp-p "matching PCRE" "containing string")) + (if pdf-occur-search-string + (format " (default %s)" pdf-occur-search-string)) + ": ") + nil 'pdf-occur-history pdf-occur-search-string)) + +(defun pdf-occur-assert-occur-buffer-p () + (unless (derived-mode-p 'pdf-occur-buffer-mode) + (error "Not in PDF occur buffer"))) + +(defun pdf-occur-want-regexp-search-p () + (or (and current-prefix-arg + pdf-occur-prefer-string-search) + (and (null current-prefix-arg) + (not pdf-occur-prefer-string-search)))) + +;; FIXME: This will be confusing when searching documents with the +;; same base file-name. +(defun pdf-occur-abbrev-document (file-or-buffer) + (if (bufferp file-or-buffer) + (buffer-name file-or-buffer) + (let ((abbrev (file-name-nondirectory file-or-buffer))) + (if (> (length abbrev) 0) + abbrev + file-or-buffer)))) + +(defun pdf-occur-create-batches (documents batch-size) + (let (queries) + (dolist (d documents) + (let* ((file-or-buffer (car d)) + (pages (pdf-info-normalize-page-range (cdr d))) + (first (car pages)) + (last (if (eq (cdr pages) 0) + (pdf-info-number-of-pages file-or-buffer) + (cdr pages))) + (npages (1+ (- last first))) + (nbatches (ceiling + (/ (float npages) batch-size)))) + (dotimes (i nbatches) + (push + (list file-or-buffer + (cons (+ first (* i batch-size)) + (min last (+ first (1- (* (1+ i) batch-size)))))) + queries)))) + (nreverse queries))) + +(defun pdf-occur-normalize-documents (documents) + "Normalize list of documents. + +Replaces buffers with their associated filenames \(if +applicable\) and ensures that every element looks like +\(FILENAME-OR-BUFFER . PAGES\)." + (cl-sort (mapcar (lambda (doc) + (unless (consp doc) + (setq doc (cons doc nil))) + (when (and (bufferp (car doc)) + (buffer-file-name (car doc))) + (setq doc (cons (buffer-file-name (car doc)) + (cdr doc)))) + (if (stringp (car doc)) + (cons (expand-file-name (car doc)) (cdr doc)) + doc)) + documents) + (lambda (a b) (string-lessp + (if (bufferp a) (buffer-name a) a) + (if (bufferp b) (buffer-name b) b))) + :key 'car)) + +(provide 'pdf-occur) + +;;; pdf-occur.el ends here diff --git a/org/elpa/pdf-tools-20230404.327/pdf-outline.el b/org/elpa/pdf-tools-20230404.327/pdf-outline.el new file mode 100644 index 0000000..fc75b02 --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/pdf-outline.el @@ -0,0 +1,582 @@ +;;; pdf-outline.el --- Outline for PDF buffer -*- lexical-binding: t -*- + +;; Copyright (C) 2013, 2014 Andreas Politz + +;; Author: Andreas Politz +;; Keywords: files, multimedia + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; + +(require 'outline) +(require 'pdf-links) +(require 'pdf-view) +(require 'pdf-util) +(require 'cl-lib) +(require 'imenu) +(require 'let-alist) + +;;; Code: + +;; +;; User options +;; + +(defgroup pdf-outline nil + "Display a navigatable outline of a PDF document." + :group 'pdf-tools) + +(defcustom pdf-outline-buffer-indent 2 + "The level of indent in the Outline buffer." + :type 'integer) + +(defcustom pdf-outline-enable-imenu t + "Whether `imenu' should be enabled in PDF documents." + :type '(choice (const :tag "Yes" t) + (const :tag "No" nil))) + +(defcustom pdf-outline-imenu-keep-order t + "Whether `imenu' should be advised not to reorder the outline." + :type '(choice (const :tag "Yes" t) + (const :tag "No" nil))) + +(defcustom pdf-outline-imenu-use-flat-menus nil + "Whether the constructed Imenu should be a list, rather than a tree." + :type '(choice (const :tag "Yes" t) + (const :tag "No" nil))) + +(defcustom pdf-outline-display-buffer-action '(nil . nil) + "The display action used, when displaying the outline buffer." + :type display-buffer--action-custom-type) + +(defcustom pdf-outline-display-labels nil + "Whether the outline should display labels instead of page numbers. + +Usually a page's label is its displayed page number." + :type 'boolean) + +(defcustom pdf-outline-fill-column fill-column + "The value of `fill-column' in pdf outline buffers. + +Set to nil to disable line wrapping." + :type 'integer) + +(defvar pdf-outline-minor-mode-map + (let ((km (make-sparse-keymap))) + (define-key km (kbd "o") #'pdf-outline) + km) + "Keymap used for `pdf-outline-minor-mode'.") + +(defvar pdf-outline-buffer-mode-map + (let ((kmap (make-sparse-keymap))) + (dotimes (i 10) + (define-key kmap (vector (+ i ?0)) #'digit-argument)) + (define-key kmap "-" #'negative-argument) + (define-key kmap (kbd "p") #'previous-line) + (define-key kmap (kbd "n") #'next-line) + (define-key kmap (kbd "b") #'outline-backward-same-level) + (define-key kmap (kbd "d") #'hide-subtree) + (define-key kmap (kbd "a") #'show-all) + (define-key kmap (kbd "s") #'show-subtree) + (define-key kmap (kbd "f") #'outline-forward-same-level) + (define-key kmap (kbd "u") #'pdf-outline-up-heading) + (define-key kmap (kbd "Q") #'hide-sublevels) + (define-key kmap (kbd "<") #'beginning-of-buffer) + (define-key kmap (kbd ">") #'pdf-outline-end-of-buffer) + (define-key kmap (kbd "TAB") #'outline-toggle-children) + (define-key kmap (kbd "RET") #'pdf-outline-follow-link) + (define-key kmap (kbd "C-o") #'pdf-outline-display-link) + (define-key kmap (kbd "SPC") #'pdf-outline-display-link) + (define-key kmap [mouse-1] #'pdf-outline-mouse-display-link) + (define-key kmap (kbd "o") #'pdf-outline-select-pdf-window) + (define-key kmap (kbd ".") #'pdf-outline-move-to-current-page) + ;; (define-key kmap (kbd "Q") #'pdf-outline-quit) + (define-key kmap (kbd "C-c C-q") #'pdf-outline-quit-and-kill) + (define-key kmap (kbd "q") #'quit-window) + (define-key kmap (kbd "M-RET") #'pdf-outline-follow-link-and-quit) + (define-key kmap (kbd "C-c C-f") #'pdf-outline-follow-mode) + kmap) + "Keymap used in `pdf-outline-buffer-mode'.") + +;; +;; Internal Variables +;; + +(define-button-type 'pdf-outline + 'face nil + 'keymap nil) + +(defvar-local pdf-outline-pdf-window nil + "The PDF window corresponding to this outline buffer.") + +(defvar-local pdf-outline-pdf-document nil + "The PDF filename or buffer corresponding to this outline + buffer.") + +(defvar-local pdf-outline-follow-mode-last-link nil) + +;; +;; Functions +;; + +;;;###autoload +(define-minor-mode pdf-outline-minor-mode + "Display an outline of a PDF document. + +This provides a PDF's outline on the menu bar via imenu. +Additionally the same outline may be viewed in a designated +buffer. + +\\{pdf-outline-minor-mode-map}" + :group 'pdf-outline + (pdf-util-assert-pdf-buffer) + (cond + (pdf-outline-minor-mode + (when pdf-outline-enable-imenu + (pdf-outline-imenu-enable))) + (t + (when pdf-outline-enable-imenu + (pdf-outline-imenu-disable))))) + +(define-derived-mode pdf-outline-buffer-mode outline-mode "PDF Outline" + "View and traverse the outline of a PDF file. + +Press \\[pdf-outline-display-link] to display the PDF document, +\\[pdf-outline-select-pdf-window] to select its window, +\\[pdf-outline-move-to-current-page] to move to the outline item +of the current page, \\[pdf-outline-follow-link] to goto the +corresponding page or \\[pdf-outline-follow-link-and-quit] to +additionally quit the Outline. + +\\[pdf-outline-follow-mode] enters a variant of +`next-error-follow-mode'. Most `outline-mode' commands are +rebound to their respective last character. + +\\{pdf-outline-buffer-mode-map}" + (setq-local outline-regexp "\\( *\\).") + (setq-local outline-level + (lambda nil (1+ (/ (length (match-string 1)) + pdf-outline-buffer-indent)))) + + (toggle-truncate-lines 1) + (setq buffer-read-only t) + (when (> (count-lines 1 (point-max)) + (* 1.5 (frame-height))) + (hide-sublevels 1)) + (message "%s" + (substitute-command-keys + (concat + "Try \\[pdf-outline-display-link], " + "\\[pdf-outline-select-pdf-window], " + "\\[pdf-outline-move-to-current-page] or " + "\\[pdf-outline-follow-link-and-quit]")))) + +(define-minor-mode pdf-outline-follow-mode + "Display links as point moves." + :group 'pdf-outline + (setq pdf-outline-follow-mode-last-link nil) + (cond + (pdf-outline-follow-mode + (add-hook 'post-command-hook #'pdf-outline-follow-mode-pch nil t)) + (t + (remove-hook 'post-command-hook #'pdf-outline-follow-mode-pch t)))) + +(defun pdf-outline-follow-mode-pch () + (let ((link (pdf-outline-link-at-pos (point)))) + (when (and link + (not (eq link pdf-outline-follow-mode-last-link))) + (setq pdf-outline-follow-mode-last-link link) + (pdf-outline-display-link (point))))) + +;;;###autoload +(defun pdf-outline (&optional buffer no-select-window-p) + "Display an PDF outline of BUFFER. + +BUFFER defaults to the current buffer. Select the outline +buffer, unless NO-SELECT-WINDOW-P is non-nil." + (interactive (list nil (or current-prefix-arg + (consp last-nonmenu-event)))) + (let ((win + (display-buffer + (pdf-outline-noselect buffer) + pdf-outline-display-buffer-action))) + (unless no-select-window-p + (select-window win)))) + +(defun pdf-outline-noselect (&optional buffer) + "Create an PDF outline of BUFFER, but don't display it." + (save-current-buffer + (and buffer (set-buffer buffer)) + (pdf-util-assert-pdf-buffer) + (let* ((pdf-buffer (current-buffer)) + (pdf-file (pdf-view-buffer-file-name)) + (pdf-window (and (eq pdf-buffer (window-buffer)) + (selected-window))) + (bname (pdf-outline-buffer-name)) + (buffer-exists-p (get-buffer bname)) + (buffer (get-buffer-create bname))) + (with-current-buffer buffer + (setq-local fill-column pdf-outline-fill-column) + (unless buffer-exists-p + (when (= 0 (save-excursion + (pdf-outline-insert-outline pdf-buffer))) + (kill-buffer buffer) + (error "PDF has no outline")) + (pdf-outline-buffer-mode)) + (set (make-local-variable 'other-window-scroll-buffer) + pdf-buffer) + (setq pdf-outline-pdf-window pdf-window + pdf-outline-pdf-document (or pdf-file pdf-buffer)) + (current-buffer))))) + +(defun pdf-outline-buffer-name (&optional pdf-buffer) + (unless pdf-buffer (setq pdf-buffer (current-buffer))) + (let ((buf (format "*Outline %s*" (buffer-name pdf-buffer)))) + ;; (when (buffer-live-p (get-buffer buf)) + ;; (kill-buffer buf)) + buf)) + +(defun pdf-outline-insert-outline (pdf-buffer) + (let ((labels (and pdf-outline-display-labels + (pdf-info-pagelabels pdf-buffer))) + (nitems 0)) + (dolist (item (pdf-info-outline pdf-buffer)) + (let-alist item + (when (eq .type 'goto-dest) + (insert-text-button + (concat + (make-string (* (1- .depth) pdf-outline-buffer-indent) ?\s) + .title + (if (> .page 0) + (format " (%s)" + (if labels + (nth (1- .page) labels) + .page)) + "(invalid)")) + 'type 'pdf-outline + 'help-echo (pdf-links-action-to-string item) + 'pdf-outline-link item) + (newline) + (cl-incf nitems)))) + nitems)) + +(defun pdf-outline-get-pdf-window (&optional if-visible-p) + (save-selected-window + (let* ((buffer (cond + ((buffer-live-p pdf-outline-pdf-document) + pdf-outline-pdf-document) + ((bufferp pdf-outline-pdf-document) + (error "PDF buffer was killed")) + (t + (or + (find-buffer-visiting + pdf-outline-pdf-document) + (find-file-noselect + pdf-outline-pdf-document))))) + (pdf-window + (if (and (window-live-p pdf-outline-pdf-window) + (eq buffer + (window-buffer pdf-outline-pdf-window))) + pdf-outline-pdf-window + (or (get-buffer-window buffer) + (and (null if-visible-p) + (display-buffer + buffer + '(nil (inhibit-same-window . t)))))))) + (setq pdf-outline-pdf-window pdf-window)))) + + +;; +;; Commands +;; + +(defun pdf-outline-move-to-current-page () + "Move to the item corresponding to the current page. + +Open nodes as necessary." + (interactive) + (let (page) + (with-selected-window (pdf-outline-get-pdf-window) + (setq page (pdf-view-current-page))) + (pdf-outline-move-to-page page))) + +(defun pdf-outline-quit-and-kill () + "Quit browsing the outline and kill its buffer." + (interactive) + (pdf-outline-quit t)) + +(defun pdf-outline-quit (&optional kill) + "Quit browsing the outline buffer." + (interactive "P") + (let ((win (selected-window))) + (pdf-outline-select-pdf-window t) + (quit-window kill win))) + +(defun pdf-outline-up-heading (arg &optional invisible-ok) + "Like `outline-up-heading', but `push-mark' first." + (interactive "p") + (let ((pos (point))) + (outline-up-heading arg invisible-ok) + (unless (= pos (point)) + (push-mark pos)))) + +(defun pdf-outline-end-of-buffer () + "Move to the end of the outline buffer." + (interactive) + (let ((pos (point))) + (goto-char (point-max)) + (when (and (eobp) + (not (bobp)) + (null (button-at (point)))) + (forward-line -1)) + (unless (= pos (point)) + (push-mark pos)))) + +(defun pdf-outline-link-at-pos (&optional pos) + (unless pos (setq pos (point))) + (let ((button (or (button-at pos) + (button-at (1- pos))))) + (and button + (button-get button + 'pdf-outline-link)))) + +(defun pdf-outline-follow-link (&optional pos) + "Select PDF window and move to the page corresponding to POS." + (interactive) + (unless pos (setq pos (point))) + (let ((link (pdf-outline-link-at-pos pos))) + (unless link + (error "Nothing to follow here")) + (select-window (pdf-outline-get-pdf-window)) + (pdf-links-action-perform link))) + +(defun pdf-outline-follow-link-and-quit (&optional pos) + "Select PDF window and move to the page corresponding to POS. + +Then quit the outline window." + (interactive) + (let ((link (pdf-outline-link-at-pos (or pos (point))))) + (pdf-outline-quit) + (unless link + (error "Nothing to follow here")) + (pdf-links-action-perform link))) + +(defun pdf-outline-display-link (&optional pos) + "Display the page corresponding to the link at POS." + (interactive) + (unless pos (setq pos (point))) + (let ((inhibit-redisplay t) + (link (pdf-outline-link-at-pos pos))) + (unless link + (error "Nothing to follow here")) + (with-selected-window (pdf-outline-get-pdf-window) + (pdf-links-action-perform link)) + (force-mode-line-update t))) + +(defun pdf-outline-mouse-display-link (event) + "Display the page corresponding to the position of EVENT." + (interactive "@e") + (pdf-outline-display-link + (posn-point (event-start event)))) + +(defun pdf-outline-select-pdf-window (&optional no-create-p) + "Display and select the PDF document window." + (interactive) + (let ((win (pdf-outline-get-pdf-window no-create-p))) + (and (window-live-p win) + (select-window win)))) + +(defun pdf-outline-toggle-subtree () + "Toggle hidden state of the current complete subtree." + (interactive) + (save-excursion + (outline-back-to-heading) + (if (not (outline-invisible-p (line-end-position))) + (hide-subtree) + (show-subtree)))) + +(defun pdf-outline-move-to-page (page) + "Move to an outline item corresponding to PAGE." + (interactive + (list (or (and current-prefix-arg + (prefix-numeric-value current-prefix-arg)) + (read-number "Page: ")))) + (goto-char (pdf-outline-position-of-page page)) + (save-excursion + (while (outline-invisible-p) + (outline-up-heading 1 t) + (show-children))) + (save-excursion + (when (outline-invisible-p) + (outline-up-heading 1 t) + (show-children))) + (back-to-indentation)) + +(defun pdf-outline-position-of-page (page) + (let (curpage) + (save-excursion + (goto-char (point-min)) + (while (and (setq curpage (alist-get 'page (pdf-outline-link-at-pos))) + (< curpage page)) + (forward-line)) + (point)))) + + + +;; +;; Imenu Support +;; + + +;;;###autoload +(defun pdf-outline-imenu-enable () + "Enable imenu in the current PDF buffer." + (interactive) + (pdf-util-assert-pdf-buffer) + (setq-local imenu-create-index-function + (if pdf-outline-imenu-use-flat-menus + 'pdf-outline-imenu-create-index-flat + 'pdf-outline-imenu-create-index-tree)) + (imenu-add-to-menubar "PDF Outline")) + +(defun pdf-outline-imenu-disable () + "Disable imenu in the current PDF buffer." + (interactive) + (pdf-util-assert-pdf-buffer) + (setq-local imenu-create-index-function nil) + (local-set-key [menu-bar index] nil) + (when (eq pdf-view-mode-map + (keymap-parent (current-local-map))) + (use-local-map (keymap-parent (current-local-map))))) + + +(defun pdf-outline-imenu-create-item (link &optional labels) + (let-alist link + (list (format "%s (%s)" .title (if labels + (nth (1- .page) labels) + .page)) + 0 + 'pdf-outline-imenu-activate-link + link))) + +(defun pdf-outline-imenu-create-index-flat () + (let ((labels (and pdf-outline-display-labels + (pdf-info-pagelabels))) + index) + (dolist (item (pdf-info-outline)) + (let-alist item + (when (eq .type 'goto-dest) + (push (pdf-outline-imenu-create-item item labels) + index)))) + (nreverse index))) + + +(defun pdf-outline-imenu-create-index-tree () + (pdf-outline-imenu-create-index-tree-1 + (pdf-outline-treeify-outline-list + (cl-remove-if-not + (lambda (type) + (eq type 'goto-dest)) + (pdf-info-outline) + :key (apply-partially 'alist-get 'type))) + (and pdf-outline-display-labels + (pdf-info-pagelabels)))) + +(defun pdf-outline-imenu-create-index-tree-1 (nodes &optional labels) + (mapcar (lambda (node) + (let (children) + (when (consp (caar node)) + (setq children (cdr node) + node (car node))) + (let ((item + (pdf-outline-imenu-create-item node labels))) + (if children + (cons (alist-get 'title node) + (cons item (pdf-outline-imenu-create-index-tree-1 + children labels))) + item)))) + nodes)) + +(defun pdf-outline-treeify-outline-list (list) + (when list + (let ((depth (alist-get 'depth (car list))) + result) + (while (and list + (>= (alist-get 'depth (car list)) + depth)) + (when (= (alist-get 'depth (car list)) depth) + (let ((item (car list))) + (when (and (cdr list) + (> (alist-get 'depth (cadr list)) + depth)) + (setq item + (cons + item + (pdf-outline-treeify-outline-list (cdr list))))) + (push item result))) + (setq list (cdr list))) + (reverse result)))) + +(defun pdf-outline-imenu-activate-link (&rest args) + ;; bug #14029 + (when (eq (nth 2 args) 'pdf-outline-imenu-activate-link) + (setq args (cdr args))) + (pdf-links-action-perform (nth 2 args))) + +(defadvice imenu--split-menu (around pdf-outline activate) + "Advice to keep the original outline order. + + Calls `pdf-outline-imenu--split-menu' instead, if in a PDF + buffer and `pdf-outline-imenu-keep-order' is non-nil." + (if (not (and (pdf-util-pdf-buffer-p) + pdf-outline-imenu-keep-order)) + ad-do-it + (setq ad-return-value + (pdf-outline-imenu--split-menu menulist title)))) + +(defvar imenu--rescan-item) +(defvar imenu-sort-function) +(defvar imenu-create-index-function) +(defvar imenu-max-items) + +(defun pdf-outline-imenu--split-menu (menulist title) + "Replacement function for `imenu--split-menu'. + +This function does not move sub-menus to the top, therefore +keeping the original outline order of the document. Also it does +not call `imenu-sort-function'." + (let ((menulist (copy-sequence menulist)) + keep-at-top) + (if (memq imenu--rescan-item menulist) + (setq keep-at-top (list imenu--rescan-item) + menulist (delq imenu--rescan-item menulist))) + (if (> (length menulist) imenu-max-items) + (setq menulist + (mapcar + (lambda (menu) + (cons (format "From: %s" (caar menu)) menu)) + (imenu--split menulist imenu-max-items)))) + (cons title + (nconc (nreverse keep-at-top) menulist)))) + + +(provide 'pdf-outline) + +;;; pdf-outline.el ends here + +;; Local Variables: +;; byte-compile-warnings: (not obsolete) +;; End: diff --git a/org/elpa/pdf-tools-20230404.327/pdf-sync.el b/org/elpa/pdf-tools-20230404.327/pdf-sync.el new file mode 100644 index 0000000..cfbc2a3 --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/pdf-sync.el @@ -0,0 +1,768 @@ +;;; pdf-sync.el --- Use synctex to correlate LaTeX-Sources with PDF positions. -*- lexical-binding:t -*- +;; Copyright (C) 2013, 2014 Andreas Politz + +;; Author: Andreas Politz +;; Keywords: files, doc-view, pdf + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; +;; The backward search uses a heuristic, which is pretty simple, but +;; effective: It extracts the text around the click-position in the +;; PDF, normalizes its whitespace, deletes certain notorious +;; characters and translates certain other characters into their latex +;; equivalents. This transformed text is split into a series of +;; token. A similar operation is performed on the source code around +;; the position synctex points at. These two sequences of token are +;; aligned with a standard sequence alignment algorithm, resulting in +;; an alist of matched and unmatched tokens. This is then used to +;; find the corresponding word from the PDF file in the LaTeX buffer. + + +(require 'pdf-view) +(require 'pdf-info) +(require 'pdf-util) +(require 'let-alist) + +;;; Code: + +(defgroup pdf-sync nil + "Jump from TeX sources to PDF pages and back." + :group 'pdf-tools) + +(defcustom pdf-sync-forward-display-pdf-key "C-c C-g" + "Key to jump from a TeX buffer to its PDF file. + +This key is added to `TeX-source-correlate-method', when +command `pdf-sync-minor-mode' is activated and this map is defined." + :type 'key-sequence) + +(make-obsolete-variable + 'pdf-sync-forward-display-pdf-key + "Bound in Auctex's to C-c C-v, if TeX-source-correlate-mode is activate." "1.0") + +(defcustom pdf-sync-backward-hook nil + "Hook ran after going to a source location. + +The hook is run in the TeX buffer." + :type 'hook + :options '(pdf-sync-backward-beginning-of-word)) + +(defcustom pdf-sync-forward-hook nil + "Hook ran after displaying the PDF buffer. + +The hook is run in the PDF's buffer." + :type 'hook) + +(defcustom pdf-sync-forward-display-action nil + "Display action used when displaying PDF buffers." + :type 'display-buffer--action-custom-type) + +(defcustom pdf-sync-backward-display-action nil + "Display action used when displaying TeX buffers." + :type 'display-buffer--action-custom-type) + +(defcustom pdf-sync-locate-synctex-file-functions nil + "A list of functions for locating the synctex database. + +Each function on this hook should accept a single argument: The +absolute path of a PDF file. It should return the absolute path +of the corresponding synctex database or nil, if it was unable to +locate it." + :type 'hook) + +(defvar pdf-sync-minor-mode-map + (let ((kmap (make-sparse-keymap))) + (define-key kmap [double-mouse-1] #'pdf-sync-backward-search-mouse) + (define-key kmap [C-mouse-1] #'pdf-sync-backward-search-mouse) + kmap)) + +(defcustom pdf-sync-backward-redirect-functions nil + "List of functions which may redirect a backward search. + +Functions on this hook should accept three arguments, namely +SOURCE, LINE and COLUMN, where SOURCE is the absolute filename of +the source file and LINE and COLUMN denote the position in the +file. COLUMN may be negative, meaning unspecified. + +These functions should either return nil, if no redirection is +necessary. Or a list of the same structure, with some or all (or +none) values modified. + +AUCTeX installs a function here which changes the backward search +location for synthetic `TeX-region' files back to the equivalent +position in the original tex file." + :type '(repeat function)) + + +;;;###autoload +(define-minor-mode pdf-sync-minor-mode + "Correlate a PDF position with the TeX file. +\\ +This works via SyncTeX, which means the TeX sources need to have +been compiled with `--synctex=1'. In AUCTeX this can be done by +setting `TeX-source-correlate-method' to `synctex' (before AUCTeX +is loaded) and enabling `TeX-source-correlate-mode'. + +Then \\[pdf-sync-backward-search-mouse] in the PDF buffer will +open the corresponding TeX location. + +If AUCTeX is your preferred tex-mode, this library arranges to +bind `pdf-sync-forward-display-pdf-key' (the default is `C-c C-g') +to `pdf-sync-forward-search' in `TeX-source-correlate-map'. This +function displays the PDF page corresponding to the current +position in the TeX buffer. This function only works together +with AUCTeX." + :group 'pdf-sync + (pdf-util-assert-pdf-buffer)) + + +;; * ================================================================== * +;; * Backward search (PDF -> TeX) +;; * ================================================================== * + +(defcustom pdf-sync-backward-use-heuristic t + "Whether to apply a heuristic when backward searching. + +If nil, just go where Synctex tells us. Otherwise try to find +the exact location of the clicked-upon text in the PDF." + :type 'boolean) + +(defcustom pdf-sync-backward-text-translations + '((88 "X" "sum") + (94 "textasciicircum") + (126 "textasciitilde") + (169 "copyright" "textcopyright") + (172 "neg" "textlnot") + (174 "textregistered" "textregistered") + (176 "textdegree") + (177 "pm" "textpm") + (181 "upmu" "mu") + (182 "mathparagraph" "textparagraph" "P" "textparagraph") + (215 "times") + (240 "eth" "dh") + (915 "Upgamma" "Gamma") + (920 "Uptheta" "Theta") + (923 "Uplambda" "Lambda") + (926 "Upxi" "Xi") + (928 "Uppi" "Pi") + (931 "Upsigma" "Sigma") + (933 "Upupsilon" "Upsilon") + (934 "Upphi" "Phi") + (936 "Uppsi" "Psi") + (945 "upalpha" "alpha") + (946 "upbeta" "beta") + (947 "upgamma" "gamma") + (948 "updelta" "delta") + (949 "upvarepsilon" "varepsilon") + (950 "upzeta" "zeta") + (951 "upeta" "eta") + (952 "uptheta" "theta") + (953 "upiota" "iota") + (954 "upkappa" "varkappa" "kappa") + (955 "uplambda" "lambda") + (957 "upnu" "nu") + (958 "upxi" "xi") + (960 "uppi" "pi") + (961 "upvarrho" "uprho" "rho") + (962 "varsigma") + (963 "upvarsigma" "upsigma" "sigma") + (964 "uptau" "tau") + (965 "upupsilon" "upsilon") + (966 "upphi" "phi") + (967 "upchi" "chi") + (968 "uppsi" "psi") + (969 "upomega" "omega") + (977 "upvartheta" "vartheta") + (981 "upvarphi" "varphi") + (8224 "dagger") + (8225 "ddagger") + (8226 "bullet") + (8486 "Upomega" "Omega") + (8501 "aleph") + (8592 "mapsfrom" "leftarrow") + (8593 "uparrow") + (8594 "to" "mapsto" "rightarrow") + (8595 "downarrow") + (8596 "leftrightarrow") + (8656 "shortleftarrow" "Leftarrow") + (8657 "Uparrow") + (8658 "Mapsto" "rightrightarrows" "Rightarrow") + (8659 "Downarrow") + (8660 "Leftrightarrow") + (8704 "forall") + (8706 "partial") + (8707 "exists") + (8709 "varnothing" "emptyset") + (8710 "Updelta" "Delta") + (8711 "nabla") + (8712 "in") + (8722 "-") + (8725 "setminus") + (8727 "*") + (8734 "infty") + (8743 "wedge") + (8744 "vee") + (8745 "cap") + (8746 "cup") + (8756 "therefore") + (8757 "because") + (8764 "thicksim" "sim") + (8776 "thickapprox" "approx") + (8801 "equiv") + (8804 "leq") + (8805 "geq") + (8810 "lll") + (8811 "ggg") + (8814 "nless") + (8815 "ngtr") + (8822 "lessgtr") + (8823 "gtrless") + (8826 "prec") + (8832 "nprec") + (8834 "subset") + (8835 "supset") + (8838 "subseteq") + (8839 "supseteq") + (8853 "oplus") + (8855 "otimes") + (8869 "bot" "perp") + (9702 "circ") + (9792 "female" "venus") + (9793 "earth") + (9794 "male" "mars") + (9824 "spadesuit") + (9827 "clubsuit") + (9829 "heartsuit") + (9830 "diamondsuit")) + "Alist mapping PDF character to a list of LaTeX macro names. + +Adding a character here with its LaTeX equivalent names allows +the heuristic backward search to find its location in the source +file. These strings should not match +`pdf-sync-backward-source-flush-regexp'. + +Has no effect if `pdf-sync-backward-use-heuristic' is nil." + :type '(alist :key-type character + :value-type (repeat string))) + +(defconst pdf-sync-backward-text-flush-regexp + "[][.·{}|\\]\\|\\C.\\|-\n+" + "Regexp of ignored text when backward searching.") + +(defconst pdf-sync-backward-source-flush-regexp + "\\(?:\\\\\\(?:begin\\|end\\|\\(?:eq\\)?ref\\|label\\|cite\\){[^}]*}\\)\\|[][\\&{}$_]" + "Regexp of ignored source when backward searching.") + +(defconst pdf-sync-backward-context-limit 64 + "Number of character to include in the backward search.") + +(defun pdf-sync-backward-search-mouse (ev) + "Go to the source corresponding to position at event EV." + (interactive "@e") + (let* ((posn (event-start ev)) + (image (posn-image posn)) + (xy (posn-object-x-y posn))) + (unless image + (error "Outside of image area")) + (pdf-sync-backward-search (car xy) (cdr xy)))) + +(defun pdf-sync-backward-search (x y) + "Go to the source corresponding to image coordinates X, Y. + +Try to find the exact position, if +`pdf-sync-backward-use-heuristic' is non-nil." + (cl-destructuring-bind (source finder) + (pdf-sync-backward-correlate x y) + (pop-to-buffer (or (find-buffer-visiting source) + (find-file-noselect source)) + pdf-sync-backward-display-action) + (push-mark) + (funcall finder) + (run-hooks 'pdf-sync-backward-hook))) + +(defun pdf-sync-backward-correlate (x y) + "Find the source corresponding to image coordinates X, Y. + +Returns a list \(SOURCE FINDER\), where SOURCE is the name of the +TeX file and FINDER a function of zero arguments which, when +called in the buffer of the aforementioned file, will try to move +point to the correct position." + + (pdf-util-assert-pdf-window) + (let ((size (pdf-view-image-size)) + (page (pdf-view-current-page))) + (setq x (/ x (float (car size))) + y (/ y (float (cdr size)))) + (let-alist (pdf-info-synctex-backward-search page x y) + (let ((data (list (expand-file-name .filename) + .line .column))) + (cl-destructuring-bind (source line column) + (or (save-selected-window + (apply #'run-hook-with-args-until-success + 'pdf-sync-backward-redirect-functions data)) + data) + (list source + (if (not pdf-sync-backward-use-heuristic) + (lambda nil + (pdf-util-goto-position line column)) + (let ((context (pdf-sync-backward--get-text-context page x y))) + (lambda nil + (pdf-sync-backward--find-position line column context)))))))))) + +(defun pdf-sync-backward--find-position (line column context) + (pdf-util-goto-position line column) + (cl-destructuring-bind (windex chindex words) + context + (let* ((swords (pdf-sync-backward--get-source-context + nil (* 6 pdf-sync-backward-context-limit))) + (similarity-fn (lambda (text source) + (if (if (consp text) + (member source text) + (equal text source)) + 1024 -1024))) + (alignment + (pdf-util-seq-alignment + words swords similarity-fn 'infix))) + (setq alignment (cl-remove-if-not 'car (cdr alignment))) + (cl-assert (< windex (length alignment))) + + (let ((word (cdr (nth windex alignment)))) + (unless word + (setq chindex 0 + word (cdr (nth (1+ windex) alignment)))) + (unless word + (setq word (cdr (nth (1- windex) alignment)) + chindex (length word))) + (when word + (cl-assert (get-text-property 0 'position word) t) + (goto-char (get-text-property 0 'position word)) + (forward-char chindex)))))) + +(defun pdf-sync-backward--get-source-context (&optional position limit) + (save-excursion + (when position (goto-char position)) + (goto-char (line-beginning-position)) + (let* ((region + (cond + ((eq limit 'line) + (cons (line-beginning-position) + (line-end-position))) + + ;; Synctex usually jumps to the end macro, in case it + ;; does not understand the environment. + ((and (fboundp 'LaTeX-find-matching-begin) + (looking-at " *\\\\\\(end\\){")) + (cons (or (ignore-errors + (save-excursion + (LaTeX-find-matching-begin) + (forward-line 1) + (point))) + (point)) + (point))) + ((and (fboundp 'LaTeX-find-matching-end) + (looking-at " *\\\\\\(begin\\){")) + (goto-char (line-end-position)) + (cons (point) + (or (ignore-errors + (save-excursion + (LaTeX-find-matching-end) + (forward-line 0) + (point))) + (point)))) + (t (cons (point) (point))))) + (begin (car region)) + (end (cdr region))) + (when (numberp limit) + (let ((delta (- limit (- end begin)))) + (when (> delta 0) + (setq begin (max (point-min) + (- begin (/ delta 2))) + end (min (point-max) + (+ end (/ delta 2))))))) + (let ((string (buffer-substring-no-properties begin end))) + (dotimes (i (length string)) + (put-text-property i (1+ i) 'position (+ begin i) string)) + (nth 2 (pdf-sync-backward--tokenize + (pdf-sync-backward--source-strip-comments string) + nil + pdf-sync-backward-source-flush-regexp)))))) + +(defun pdf-sync-backward--source-strip-comments (string) + "Strip all standard LaTeX comments from string." + (with-temp-buffer + (save-excursion (insert string)) + (while (re-search-forward + "^\\(?:[^\\\n]\\|\\(?:\\\\\\\\\\)\\)*\\(%.*\\)" nil t) + (delete-region (match-beginning 1) (match-end 1))) + (buffer-string))) + +(defun pdf-sync-backward--get-text-context (page x y) + (cl-destructuring-bind (&optional char edges) + (car (pdf-info-charlayout page (cons x y))) + (when edges + (setq x (nth 0 edges) + y (nth 1 edges))) + (let* ((prefix (pdf-info-gettext page (list 0 0 x y))) + (suffix (pdf-info-gettext page (list x y 1 1))) + (need-suffix-space-p (memq char '(?\s ?\n))) + ;; Figure out whether we missed a space by matching the + ;; prefix's suffix with the line's prefix. Due to the text + ;; extraction in poppler, spaces are only inserted in + ;; between words. This test may fail, if prefix and line + ;; do not overlap, which may happen in various cases, but + ;; we don't care. + (need-prefix-space-p + (and (not need-suffix-space-p) + (memq + (ignore-errors + (aref (pdf-info-gettext page (list x y x y) 'line) + (- (length prefix) + (or (cl-position ?\n prefix :from-end t) + -1) + 1))) + '(?\s ?\n))))) + (setq prefix + (concat + (substring + prefix (max 0 (min (1- (length prefix)) + (- (length prefix) + pdf-sync-backward-context-limit)))) + (if need-prefix-space-p " ")) + suffix + (concat + (if need-suffix-space-p " ") + (substring + suffix 0 (max 0 (min (1- (length suffix)) + pdf-sync-backward-context-limit))))) + (pdf-sync-backward--tokenize + prefix suffix + pdf-sync-backward-text-flush-regexp + pdf-sync-backward-text-translations)))) + +(defun pdf-sync-backward--tokenize (prefix &optional suffix flush-re translation) + (with-temp-buffer + (when prefix (insert prefix)) + (let* ((center (copy-marker (point))) + (case-fold-search nil)) + (when suffix (insert suffix)) + (goto-char 1) + ;; Delete ignored text. + (when flush-re + (save-excursion + (while (re-search-forward flush-re nil t) + (replace-match " " t t)))) + ;; Normalize whitespace. + (save-excursion + (while (re-search-forward "[ \t\f\n]+" nil t) + (replace-match " " t t))) + ;; Split words and non-words + (save-excursion + (while (re-search-forward "[^ ]\\b\\|[^ [:alnum:]]" nil t) + (insert-before-markers " "))) + ;; Replace character + (let ((translate + (lambda (string) + (or (and (= (length string) 1) + (cdr (assq (aref string 0) + translation))) + string))) + words + (windex -1) + (chindex 0)) + (skip-chars-forward " ") + (while (and (not (eobp)) + (<= (point) center)) + (cl-incf windex) + (skip-chars-forward "^ ") + (skip-chars-forward " ")) + (goto-char center) + (when (eq ?\s (char-after)) + (skip-chars-backward " ")) + (setq chindex (- (skip-chars-backward "^ "))) + (setq words (split-string (buffer-string))) + (when translation + (setq words (mapcar translate words))) + (list windex chindex words))))) + +(defun pdf-sync-backward-beginning-of-word () + "Maybe move to the beginning of the word. + +Don't move if already at the beginning, or if not at a word +character. + +This function is meant to be put on `pdf-sync-backward-hook', when +word-level searching is desired." + (interactive) + (unless (or (looking-at "\\b\\w") + (not (looking-back "\\w" (1- (point))))) + (backward-word))) + +;; * ------------------------------------------------------------------ * +;; * Debugging backward search +;; * ------------------------------------------------------------------ * + +(defvar pdf-sync-backward-debug-trace nil) + +(defun pdf-sync-backward-debug-wrapper (fn-symbol fn &rest args) + (cond + ((eq fn-symbol 'pdf-sync-backward-search) + (setq pdf-sync-backward-debug-trace nil) + (apply fn args)) + (t + (let ((retval (apply fn args))) + (push `(,args . ,retval) + pdf-sync-backward-debug-trace) + retval)))) + +(define-minor-mode pdf-sync-backward-debug-minor-mode + "Aid in debugging the backward search." + :group 'pdf-sync + (let ((functions + '(pdf-sync-backward-search + pdf-sync-backward--tokenize + pdf-util-seq-alignment))) + (cond + (pdf-sync-backward-debug-minor-mode + (dolist (fn functions) + (advice-add fn :around + (apply-partially #'pdf-sync-backward-debug-wrapper fn) + `((name . ,(format "%s-debug" fn)))))) + (t + (dolist (fn functions) + (advice-remove fn (format "%s-debug" fn))))))) + +(defun pdf-sync-backward-debug-explain () + "Explain the last backward search. + +Needs to have `pdf-sync-backward-debug-minor-mode' enabled." + + (interactive) + (unless pdf-sync-backward-debug-trace + (error "No last search or `pdf-sync-backward-debug-minor-mode' not enabled.")) + + (with-current-buffer (get-buffer-create "*pdf-sync-backward trace*") + (cl-destructuring-bind (text source alignment &rest ignored) + (reverse pdf-sync-backward-debug-trace) + (let* ((fill-column 68) + (sep (format "\n%s\n" (make-string fill-column ?-))) + (highlight '(:background "chartreuse" :foreground "black")) + (or-sep "|") + (inhibit-read-only t) + (windex (nth 0 (cdr text))) + (chindex (nth 1 (cdr text)))) + (erase-buffer) + (font-lock-mode -1) + (view-mode 1) + (insert (propertize "Text Raw:" 'face 'font-lock-keyword-face)) + (insert sep) + (insert (nth 0 (car text))) + (insert (propertize "<|>" 'face highlight)) + (insert (nth 1 (car text))) + (insert sep) + (insert (propertize "Text Token:" 'face 'font-lock-keyword-face)) + (insert sep) + (fill-region (point) + (progn + (insert + (mapconcat (lambda (elt) + (if (consp elt) + (mapconcat #'identity elt or-sep) + elt)) + (nth 2 (cdr text)) " ")) + (point))) + (insert sep) + + (insert (propertize "Source Raw:" 'face 'font-lock-keyword-face)) + (insert sep) + (insert (nth 0 (car source))) + (insert sep) + (insert (propertize "Source Token:" 'face 'font-lock-keyword-face)) + (insert sep) + (fill-region (point) + (progn (insert (mapconcat #'identity (nth 2 (cdr source)) " ")) + (point))) + (insert sep) + + (insert (propertize "Alignment:" 'face 'font-lock-keyword-face)) + (insert (format " (windex=%d, chindex=%d" windex chindex)) + (insert sep) + (save-excursion (newline 2)) + (let ((column 0) + (index 0)) + (dolist (a (cdr (cdr alignment))) + (let* ((source (cdr a)) + (text (if (consp (car a)) + (mapconcat #'identity (car a) or-sep) + (car a))) + (extend (max (length text) + (length source)))) + (when (and (not (bolp)) + (> (+ column extend) + fill-column)) + (forward-line 2) + (newline 3) + (forward-line -2) + (setq column 0)) + (when text + (insert (propertize text 'face + (if (= index windex) + highlight + (if source 'match + 'lazy-highlight))))) + (move-to-column (+ column extend) t) + (insert " ") + (save-excursion + (forward-line) + (move-to-column column t) + (when source + (insert (propertize source 'face (if text + 'match + 'lazy-highlight)))) + (move-to-column (+ column extend) t) + (insert " ")) + (cl-incf column (+ 1 extend)) + (when text (cl-incf index))))) + (goto-char (point-max)) + (insert sep) + (goto-char 1) + (pop-to-buffer (current-buffer)))))) + + +;; * ================================================================== * +;; * Forward search (TeX -> PDF) +;; * ================================================================== * + +(defun pdf-sync-forward-search (&optional line column) + "Display the PDF location corresponding to LINE, COLUMN." + (interactive) + (cl-destructuring-bind (pdf page _x1 y1 _x2 _y2) + (pdf-sync-forward-correlate line column) + (let ((buffer (or (find-buffer-visiting pdf) + (find-file-noselect pdf)))) + (with-selected-window (display-buffer + buffer pdf-sync-forward-display-action) + (pdf-util-assert-pdf-window) + (when page + (pdf-view-goto-page page) + (when y1 + (let ((top (* y1 (cdr (pdf-view-image-size))))) + (pdf-util-tooltip-arrow (round top)))))) + (with-current-buffer buffer + (run-hooks 'pdf-sync-forward-hook))))) + +(defun pdf-sync-forward-correlate (&optional line column) + "Find the PDF location corresponding to LINE, COLUMN. + +Returns a list \(PDF PAGE X1 Y1 X2 Y2\), where PAGE, X1, Y1, X2 +and Y2 may be nil, if the destination could not be found." + (unless (fboundp 'TeX-master-file) + (error "This function works only with AUCTeX")) + (unless line (setq line (line-number-at-pos))) + (unless column (setq column (current-column))) + + (let* ((pdf (expand-file-name + (with-no-warnings (TeX-master-file "pdf")))) + (sfilename (pdf-sync-synctex-file-name + (buffer-file-name) pdf))) + (cons pdf + (condition-case error + (let-alist (pdf-info-synctex-forward-search + (or sfilename + (buffer-file-name)) + line column pdf) + (cons .page .edges)) + (error + (message "%s" (error-message-string error)) + (list nil nil nil nil nil)))))) + + + +;; * ================================================================== * +;; * Dealing with synctex files. +;; * ================================================================== * + +(defun pdf-sync-locate-synctex-file (pdffile) + "Locate the synctex database corresponding to PDFFILE. + +Returns either the absolute path of the database or nil. + +See also `pdf-sync-locate-synctex-file-functions'." + (cl-check-type pdffile string) + (setq pdffile (expand-file-name pdffile)) + (or (run-hook-with-args-until-success + 'pdf-sync-locate-synctex-file-functions pdffile) + (pdf-sync-locate-synctex-file-default pdffile))) + +(defun pdf-sync-locate-synctex-file-default (pdffile) + "The default function for locating a synctex database for PDFFILE. + +See also `pdf-sync-locate-synctex-file'." + (let ((default-directory + (file-name-directory pdffile)) + (basename (file-name-sans-extension + (file-name-nondirectory pdffile)))) + (cl-labels ((file-if-exists-p (file) + (and (file-exists-p file) + file))) + (or (file-if-exists-p + (expand-file-name (concat basename ".synctex.gz"))) + (file-if-exists-p + (expand-file-name (concat basename ".synctex"))) + ;; Some pdftex quote the basename. + (file-if-exists-p + (expand-file-name (concat "\"" basename "\"" ".synctex.gz"))) + (file-if-exists-p + (expand-file-name (concat "\"" basename "\"" ".synctex"))))))) + +(defun pdf-sync-synctex-file-name (filename pdffile) + "Find SyncTeX filename corresponding to FILENAME in the context of PDFFILE. + +This function consults the synctex.gz database of PDFFILE and +searches for a filename, which is `file-equal-p' to FILENAME. +The first such filename is returned, or nil if none was found." + + (when (file-exists-p filename) + (setq filename (expand-file-name filename)) + (let* ((synctex (pdf-sync-locate-synctex-file pdffile)) + (basename (file-name-nondirectory filename)) + (regexp (format "^ *Input *: *[^:\n]+ *:\\(.*%s\\)$" + (regexp-quote basename))) + (jka-compr-verbose nil)) + (when (and synctex + (file-readable-p synctex)) + (with-current-buffer (find-file-noselect synctex :nowarn) + (unless (or (verify-visited-file-modtime) + (buffer-modified-p)) + (revert-buffer :ignore-auto :noconfirm) + (goto-char (point-min))) + ;; Keep point in front of the found filename. It will + ;; probably be queried for again next time. + (let ((beg (point)) + (end (point-max))) + (catch 'found + (dotimes (_x 2) + (while (re-search-forward regexp end t) + (let ((syncname (match-string-no-properties 1))) + (when (and (file-exists-p syncname) + (file-equal-p filename syncname)) + (goto-char (line-beginning-position)) + (throw 'found syncname)))) + (setq end beg + beg (point-min)) + (goto-char beg))))))))) + +(provide 'pdf-sync) +;;; pdf-sync.el ends here diff --git a/org/elpa/pdf-tools-20230404.327/pdf-tools-autoloads.el b/org/elpa/pdf-tools-20230404.327/pdf-tools-autoloads.el new file mode 100644 index 0000000..a5cc8c1 --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/pdf-tools-autoloads.el @@ -0,0 +1,637 @@ +;;; pdf-tools-autoloads.el --- automatically extracted autoloads -*- lexical-binding: t -*- +;; +;;; Code: + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + + +;;;### (autoloads nil "pdf-annot" "pdf-annot.el" (0 0 0 0)) +;;; Generated autoloads from pdf-annot.el + +(autoload 'pdf-annot-minor-mode "pdf-annot" "\ +Support for PDF Annotations. + +This is a minor mode. If called interactively, toggle the +`Pdf-Annot minor mode' mode. If the prefix argument is positive, +enable the mode, and if it is zero or negative, disable the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `pdf-annot-minor-mode'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +\\{pdf-annot-minor-mode-map} + +\(fn &optional ARG)" t nil) + +(register-definition-prefixes "pdf-annot" '("pdf-annot-")) + +;;;*** + +;;;### (autoloads nil "pdf-cache" "pdf-cache.el" (0 0 0 0)) +;;; Generated autoloads from pdf-cache.el + +(register-definition-prefixes "pdf-cache" '("boundingbox" "define-pdf-cache-function" "page" "pdf-cache-" "textregions")) + +;;;*** + +;;;### (autoloads nil "pdf-dev" "pdf-dev.el" (0 0 0 0)) +;;; Generated autoloads from pdf-dev.el + +(register-definition-prefixes "pdf-dev" '("pdf-dev-")) + +;;;*** + +;;;### (autoloads nil "pdf-history" "pdf-history.el" (0 0 0 0)) +;;; Generated autoloads from pdf-history.el + +(autoload 'pdf-history-minor-mode "pdf-history" "\ +Keep a history of previously visited pages. + +This is a minor mode. If called interactively, toggle the +`Pdf-History minor mode' mode. If the prefix argument is +positive, enable the mode, and if it is zero or negative, disable +the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `pdf-history-minor-mode'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +This is a simple stack-based history. Turning the page or +following a link pushes the left-behind page on the stack, which +may be navigated with the following keys. + +\\{pdf-history-minor-mode-map} + +\(fn &optional ARG)" t nil) + +(register-definition-prefixes "pdf-history" '("pdf-history-")) + +;;;*** + +;;;### (autoloads nil "pdf-info" "pdf-info.el" (0 0 0 0)) +;;; Generated autoloads from pdf-info.el + +(register-definition-prefixes "pdf-info" '("pdf-info-")) + +;;;*** + +;;;### (autoloads nil "pdf-isearch" "pdf-isearch.el" (0 0 0 0)) +;;; Generated autoloads from pdf-isearch.el + +(autoload 'pdf-isearch-minor-mode "pdf-isearch" "\ +Isearch mode for PDF buffer. + +This is a minor mode. If called interactively, toggle the +`Pdf-Isearch minor mode' mode. If the prefix argument is +positive, enable the mode, and if it is zero or negative, disable +the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `pdf-isearch-minor-mode'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +When this mode is enabled \\[isearch-forward], among other keys, +starts an incremental search in this PDF document. Since this mode +uses external programs to highlight found matches via +image-processing, proceeding to the next match may be slow. + +Therefore two isearch behaviours have been defined: Normal isearch and +batch mode. The later one is a minor mode +\(`pdf-isearch-batch-mode'), which when activated inhibits isearch +from stopping at and highlighting every single match, but rather +display them batch-wise. Here a batch means a number of matches +currently visible in the selected window. + +The kind of highlighting is determined by three faces +`pdf-isearch-match' (for the current match), `pdf-isearch-lazy' +\(for all other matches) and `pdf-isearch-batch' (when in batch +mode), which see. + +Colors may also be influenced by the minor-mode +`pdf-view-dark-minor-mode'. If this is minor mode enabled, each face's +dark colors, are used (see e.g. `frame-background-mode'), instead +of the light ones. + +\\{pdf-isearch-minor-mode-map} +While in `isearch-mode' the following keys are available. Note +that not every isearch command work as expected. + +\\{pdf-isearch-active-mode-map} + +\(fn &optional ARG)" t nil) + +(register-definition-prefixes "pdf-isearch" '("pdf-isearch-")) + +;;;*** + +;;;### (autoloads nil "pdf-links" "pdf-links.el" (0 0 0 0)) +;;; Generated autoloads from pdf-links.el + +(autoload 'pdf-links-minor-mode "pdf-links" "\ +Handle links in PDF documents.\\ + +This is a minor mode. If called interactively, toggle the +`Pdf-Links minor mode' mode. If the prefix argument is positive, +enable the mode, and if it is zero or negative, disable the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `pdf-links-minor-mode'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +If this mode is enabled, most links in the document may be +activated by clicking on them or by pressing \\[pdf-links-action-perform] and selecting +one of the displayed keys, or by using isearch limited to +links via \\[pdf-links-isearch-link]. + +\\{pdf-links-minor-mode-map} + +\(fn &optional ARG)" t nil) + +(autoload 'pdf-links-action-perform "pdf-links" "\ +Follow LINK, depending on its type. + +This may turn to another page, switch to another PDF buffer or +invoke `pdf-links-browse-uri-function'. + +Interactively, link is read via `pdf-links-read-link-action'. +This function displays characters around the links in the current +page and starts reading characters (ignoring case). After a +sufficient number of characters have been read, the corresponding +link's link is invoked. Additionally, SPC may be used to +scroll the current page. + +\(fn LINK)" t nil) + +(register-definition-prefixes "pdf-links" '("pdf-links-")) + +;;;*** + +;;;### (autoloads nil "pdf-loader" "pdf-loader.el" (0 0 0 0)) +;;; Generated autoloads from pdf-loader.el + +(autoload 'pdf-loader-install "pdf-loader" "\ +Prepare Emacs for using PDF Tools. + +This function acts as a replacement for `pdf-tools-install' and +makes Emacs load and use PDF Tools as soon as a PDF file is +opened, but not sooner. + +The arguments are passed verbatim to `pdf-tools-install', which +see. + +\(fn &optional NO-QUERY-P SKIP-DEPENDENCIES-P NO-ERROR-P FORCE-DEPENDENCIES-P)" nil nil) + +(register-definition-prefixes "pdf-loader" '("pdf-loader--")) + +;;;*** + +;;;### (autoloads nil "pdf-macs" "pdf-macs.el" (0 0 0 0)) +;;; Generated autoloads from pdf-macs.el + +(register-definition-prefixes "pdf-macs" '("pdf-view-")) + +;;;*** + +;;;### (autoloads nil "pdf-misc" "pdf-misc.el" (0 0 0 0)) +;;; Generated autoloads from pdf-misc.el + +(autoload 'pdf-misc-minor-mode "pdf-misc" "\ +FIXME: Not documented. + +This is a minor mode. If called interactively, toggle the +`Pdf-Misc minor mode' mode. If the prefix argument is positive, +enable the mode, and if it is zero or negative, disable the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `pdf-misc-minor-mode'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +\(fn &optional ARG)" t nil) + +(autoload 'pdf-misc-size-indication-minor-mode "pdf-misc" "\ +Provide a working size indication in the mode-line. + +This is a minor mode. If called interactively, toggle the +`Pdf-Misc-Size-Indication minor mode' mode. If the prefix +argument is positive, enable the mode, and if it is zero or +negative, disable the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `pdf-misc-size-indication-minor-mode'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +\(fn &optional ARG)" t nil) + +(autoload 'pdf-misc-menu-bar-minor-mode "pdf-misc" "\ +Display a PDF Tools menu in the menu-bar. + +This is a minor mode. If called interactively, toggle the +`Pdf-Misc-Menu-Bar minor mode' mode. If the prefix argument is +positive, enable the mode, and if it is zero or negative, disable +the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `pdf-misc-menu-bar-minor-mode'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +\(fn &optional ARG)" t nil) + +(autoload 'pdf-misc-context-menu-minor-mode "pdf-misc" "\ +Provide a right-click context menu in PDF buffers. + +This is a minor mode. If called interactively, toggle the +`Pdf-Misc-Context-Menu minor mode' mode. If the prefix argument +is positive, enable the mode, and if it is zero or negative, +disable the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `pdf-misc-context-menu-minor-mode'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +\\{pdf-misc-context-menu-minor-mode-map} + +\(fn &optional ARG)" t nil) + +(register-definition-prefixes "pdf-misc" '("pdf-misc-")) + +;;;*** + +;;;### (autoloads nil "pdf-occur" "pdf-occur.el" (0 0 0 0)) +;;; Generated autoloads from pdf-occur.el + +(autoload 'pdf-occur "pdf-occur" "\ +List lines matching STRING or PCRE. + +Interactively search for a regexp. Unless a prefix arg was given, +in which case this functions performs a string search. + +If `pdf-occur-prefer-string-search' is non-nil, the meaning of +the prefix-arg is inverted. + +\(fn STRING &optional REGEXP-P)" t nil) + +(autoload 'pdf-occur-multi-command "pdf-occur" "\ +Perform `pdf-occur' on multiple buffer. + +For a programmatic search of multiple documents see +`pdf-occur-search'." t nil) + +(defvar pdf-occur-global-minor-mode nil "\ +Non-nil if Pdf-Occur-Global minor mode is enabled. +See the `pdf-occur-global-minor-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `pdf-occur-global-minor-mode'.") + +(custom-autoload 'pdf-occur-global-minor-mode "pdf-occur" nil) + +(autoload 'pdf-occur-global-minor-mode "pdf-occur" "\ +Enable integration of Pdf Occur with other modes. + +This is a minor mode. If called interactively, toggle the +`Pdf-Occur-Global minor mode' mode. If the prefix argument is +positive, enable the mode, and if it is zero or negative, disable +the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `(default-value \\='pdf-occur-global-minor-mode)'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +This global minor mode enables (or disables) +`pdf-occur-ibuffer-minor-mode' and `pdf-occur-dired-minor-mode' +in all current and future ibuffer/dired buffer. + +\(fn &optional ARG)" t nil) + +(autoload 'pdf-occur-ibuffer-minor-mode "pdf-occur" "\ +Hack into ibuffer's do-occur binding. + +This is a minor mode. If called interactively, toggle the +`Pdf-Occur-Ibuffer minor mode' mode. If the prefix argument is +positive, enable the mode, and if it is zero or negative, disable +the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `pdf-occur-ibuffer-minor-mode'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +This mode remaps `ibuffer-do-occur' to +`pdf-occur-ibuffer-do-occur', which will start the PDF Tools +version of `occur', if all marked buffer's are in `pdf-view-mode' +and otherwise fallback to `ibuffer-do-occur'. + +\(fn &optional ARG)" t nil) + +(autoload 'pdf-occur-dired-minor-mode "pdf-occur" "\ +Hack into dired's `dired-do-search' binding. + +This is a minor mode. If called interactively, toggle the +`Pdf-Occur-Dired minor mode' mode. If the prefix argument is +positive, enable the mode, and if it is zero or negative, disable +the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `pdf-occur-dired-minor-mode'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +This mode remaps `dired-do-search' to +`pdf-occur-dired-do-search', which will start the PDF Tools +version of `occur', if all marked buffer's are in `pdf-view-mode' +and otherwise fallback to `dired-do-search'. + +\(fn &optional ARG)" t nil) + +(register-definition-prefixes "pdf-occur" '("pdf-occur-")) + +;;;*** + +;;;### (autoloads nil "pdf-outline" "pdf-outline.el" (0 0 0 0)) +;;; Generated autoloads from pdf-outline.el + +(autoload 'pdf-outline-minor-mode "pdf-outline" "\ +Display an outline of a PDF document. + +This is a minor mode. If called interactively, toggle the +`Pdf-Outline minor mode' mode. If the prefix argument is +positive, enable the mode, and if it is zero or negative, disable +the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `pdf-outline-minor-mode'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +This provides a PDF's outline on the menu bar via imenu. +Additionally the same outline may be viewed in a designated +buffer. + +\\{pdf-outline-minor-mode-map} + +\(fn &optional ARG)" t nil) + +(autoload 'pdf-outline "pdf-outline" "\ +Display an PDF outline of BUFFER. + +BUFFER defaults to the current buffer. Select the outline +buffer, unless NO-SELECT-WINDOW-P is non-nil. + +\(fn &optional BUFFER NO-SELECT-WINDOW-P)" t nil) + +(autoload 'pdf-outline-imenu-enable "pdf-outline" "\ +Enable imenu in the current PDF buffer." t nil) + +(register-definition-prefixes "pdf-outline" '("pdf-outline")) + +;;;*** + +;;;### (autoloads nil "pdf-sync" "pdf-sync.el" (0 0 0 0)) +;;; Generated autoloads from pdf-sync.el + +(autoload 'pdf-sync-minor-mode "pdf-sync" "\ +Correlate a PDF position with the TeX file. +\\ +This works via SyncTeX, which means the TeX sources need to have +been compiled with `--synctex=1'. In AUCTeX this can be done by +setting `TeX-source-correlate-method' to `synctex' (before AUCTeX +is loaded) and enabling `TeX-source-correlate-mode'. + +This is a minor mode. If called interactively, toggle the +`Pdf-Sync minor mode' mode. If the prefix argument is positive, +enable the mode, and if it is zero or negative, disable the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `pdf-sync-minor-mode'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +Then \\[pdf-sync-backward-search-mouse] in the PDF buffer will +open the corresponding TeX location. + +If AUCTeX is your preferred tex-mode, this library arranges to +bind `pdf-sync-forward-display-pdf-key' (the default is `C-c C-g') +to `pdf-sync-forward-search' in `TeX-source-correlate-map'. This +function displays the PDF page corresponding to the current +position in the TeX buffer. This function only works together +with AUCTeX. + +\(fn &optional ARG)" t nil) + +(register-definition-prefixes "pdf-sync" '("pdf-sync-")) + +;;;*** + +;;;### (autoloads nil "pdf-tools" "pdf-tools.el" (0 0 0 0)) +;;; Generated autoloads from pdf-tools.el + +(defvar pdf-tools-handle-upgrades t "\ +Whether PDF Tools should handle upgrading itself.") + +(custom-autoload 'pdf-tools-handle-upgrades "pdf-tools" t) + +(autoload 'pdf-tools-install "pdf-tools" "\ +Install PDF-Tools in all current and future PDF buffers. + +If the `pdf-info-epdfinfo-program' is not running or does not +appear to be working, attempt to rebuild it. If this build +succeeded, continue with the activation of the package. +Otherwise fail silently, i.e. no error is signaled. + +Build the program (if necessary) without asking first, if +NO-QUERY-P is non-nil. + +Don't attempt to install system packages, if SKIP-DEPENDENCIES-P +is non-nil. + +Do not signal an error in case the build failed, if NO-ERROR-P is +non-nil. + +Attempt to install system packages (even if it is deemed +unnecessary), if FORCE-DEPENDENCIES-P is non-nil. + +Note that SKIP-DEPENDENCIES-P and FORCE-DEPENDENCIES-P are +mutually exclusive. + +Note further, that you can influence the installation directory +by setting `pdf-info-epdfinfo-program' to an appropriate +value (e.g. ~/bin/epdfinfo) before calling this function. + +See `pdf-view-mode' and `pdf-tools-enabled-modes'. + +\(fn &optional NO-QUERY-P SKIP-DEPENDENCIES-P NO-ERROR-P FORCE-DEPENDENCIES-P)" t nil) + +(autoload 'pdf-tools-enable-minor-modes "pdf-tools" "\ +Enable MODES in the current buffer. + +MODES defaults to `pdf-tools-enabled-modes'. + +\(fn &optional MODES)" t nil) + +(autoload 'pdf-tools-help "pdf-tools" "\ +Show a Help buffer for `pdf-tools'." t nil) + +(register-definition-prefixes "pdf-tools" '("pdf-tools-")) + +;;;*** + +;;;### (autoloads nil "pdf-util" "pdf-util.el" (0 0 0 0)) +;;; Generated autoloads from pdf-util.el + +(register-definition-prefixes "pdf-util" '("display-buffer-split-below-and-attach" "pdf-util-")) + +;;;*** + +;;;### (autoloads nil "pdf-view" "pdf-view.el" (0 0 0 0)) +;;; Generated autoloads from pdf-view.el + +(autoload 'pdf-view-bookmark-jump-handler "pdf-view" "\ +The bookmark handler-function interface for bookmark BMK. + +See also `pdf-view-bookmark-make-record'. + +\(fn BMK)" nil nil) + +(register-definition-prefixes "pdf-view" '("cua-copy-region--pdf-view-advice" "pdf-view-")) + +;;;*** + +;;;### (autoloads nil "pdf-virtual" "pdf-virtual.el" (0 0 0 0)) +;;; Generated autoloads from pdf-virtual.el + +(autoload 'pdf-virtual-edit-mode "pdf-virtual" "\ +Major mode when editing a virtual PDF buffer. + +\(fn)" t nil) + +(autoload 'pdf-virtual-view-mode "pdf-virtual" "\ +Major mode in virtual PDF buffers. + +\(fn)" t nil) + +(defvar pdf-virtual-global-minor-mode nil "\ +Non-nil if Pdf-Virtual-Global minor mode is enabled. +See the `pdf-virtual-global-minor-mode' command +for a description of this minor mode. +Setting this variable directly does not take effect; +either customize it (see the info node `Easy Customization') +or call the function `pdf-virtual-global-minor-mode'.") + +(custom-autoload 'pdf-virtual-global-minor-mode "pdf-virtual" nil) + +(autoload 'pdf-virtual-global-minor-mode "pdf-virtual" "\ +Enable recognition and handling of VPDF files. + +This is a minor mode. If called interactively, toggle the +`Pdf-Virtual-Global minor mode' mode. If the prefix argument is +positive, enable the mode, and if it is zero or negative, disable +the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `(default-value \\='pdf-virtual-global-minor-mode)'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +\(fn &optional ARG)" t nil) + +(autoload 'pdf-virtual-buffer-create "pdf-virtual" "\ + + +\(fn &optional FILENAMES BUFFER-NAME DISPLAY-P)" t nil) + +(register-definition-prefixes "pdf-virtual" '("pdf-virtual-")) + +;;;*** + +;;;### (autoloads nil nil ("pdf-tools-pkg.el") (0 0 0 0)) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; coding: utf-8 +;; End: +;;; pdf-tools-autoloads.el ends here diff --git a/org/elpa/pdf-tools-20230404.327/pdf-tools-pkg.el b/org/elpa/pdf-tools-20230404.327/pdf-tools-pkg.el new file mode 100644 index 0000000..433ec48 --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/pdf-tools-pkg.el @@ -0,0 +1,14 @@ +(define-package "pdf-tools" "20230404.327" "Support library for PDF documents" + '((emacs "26.3") + (tablist "1.0") + (let-alist "1.0.4")) + :commit "7ff6293a25baaae65651b3e1c54b61208279a7ef" :authors + '(("Andreas Politz" . "mail@andreas-politz.de")) + :maintainer + '("Vedang Manerikar" . "vedang.manerikar@gmail.com") + :keywords + '("files" "multimedia") + :url "http://github.com/vedang/pdf-tools/") +;; Local Variables: +;; no-byte-compile: t +;; End: diff --git a/org/elpa/pdf-tools-20230404.327/pdf-tools.el b/org/elpa/pdf-tools-20230404.327/pdf-tools.el new file mode 100644 index 0000000..b94c82f --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/pdf-tools.el @@ -0,0 +1,544 @@ +;;; pdf-tools.el --- Support library for PDF documents -*- lexical-binding:t -*- + +;; Copyright (C) 2013, 2014 Andreas Politz + +;; Author: Andreas Politz +;; Maintainer: Vedang Manerikar +;; URL: http://github.com/vedang/pdf-tools/ +;; Keywords: files, multimedia +;; Package: pdf-tools +;; Version: 1.0.0 +;; Package-Requires: ((emacs "26.3") (tablist "1.0") (let-alist "1.0.4")) + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; +;; PDF Tools is, among other things, a replacement of DocView for PDF +;; files. The key difference is, that pages are not prerendered by +;; e.g. ghostscript and stored in the file-system, but rather created +;; on-demand and stored in memory. +;; +;; Note: This package is built and tested on GNU/Linux systems. It +;; works on macOS and Windows, but is officially supported only on +;; GNU/Linux systems. This package will not make macOS or Windows +;; specific functionality changes, behaviour on these systems is +;; provided as-is. +;; +;; Note: If you ever update it, you need to restart Emacs afterwards. +;; +;; To activate the package put +;; +;; (pdf-tools-install) +;; +;; somewhere in your .emacs.el . +;; +;; M-x pdf-tools-help RET +;; +;; gives some help on using the package and +;; +;; M-x pdf-tools-customize RET +;; +;; offers some customization options. + +;; Features: +;; +;; * View +;; View PDF documents in a buffer with DocView-like bindings. +;; +;; * Isearch +;; Interactively search PDF documents like any other buffer. (Though +;; there is currently no regexp support.) +;; +;; * Follow links +;; Click on highlighted links, moving to some part of a different +;; page, some external file, a website or any other URI. Links may +;; also be followed by keyboard commands. +;; +;; * Annotations +;; Display and list text and markup annotations (like underline), +;; edit their contents and attributes (e.g. color), move them around, +;; delete them or create new ones and then save the modifications +;; back to the PDF file. +;; +;; * Attachments +;; Save files attached to the PDF-file or list them in a Dired buffer. +;; +;; * Outline +;; Use imenu or a special buffer to examine and navigate the PDF's +;; outline. +;; +;; * SyncTeX +;; Jump from a position on a page directly to the TeX source and +;; vice-versa. +;; +;; * Misc +;; + Display PDF's metadata. +;; + Mark a region and kill the text from the PDF. +;; + Search for occurrences of a string. +;; + Keep track of visited pages via a history. + +;;; Code: + +(require 'pdf-view) +(require 'pdf-util) +(require 'pdf-info) +(require 'cus-edit) +(require 'compile) +(require 'cl-lib) +(require 'package) + + + +;; * ================================================================== * +;; * Customizables +;; * ================================================================== * + +(defgroup pdf-tools nil + "Support library for PDF documents." + :group 'data) + +(defgroup pdf-tools-faces nil + "Faces determining the colors used in the pdf-tools package. + +In order to customize dark and light colors use +`pdf-tools-customize-faces', or set `custom-face-default-form' to +'all." + :group 'pdf-tools) + +(defconst pdf-tools-modes + '(pdf-history-minor-mode + pdf-isearch-minor-mode + pdf-links-minor-mode + pdf-misc-minor-mode + pdf-outline-minor-mode + pdf-misc-size-indication-minor-mode + pdf-misc-menu-bar-minor-mode + pdf-annot-minor-mode + pdf-sync-minor-mode + pdf-misc-context-menu-minor-mode + pdf-cache-prefetch-minor-mode + pdf-view-auto-slice-minor-mode + pdf-occur-global-minor-mode + pdf-virtual-global-minor-mode)) + +(defcustom pdf-tools-enabled-modes + '(pdf-history-minor-mode + pdf-isearch-minor-mode + pdf-links-minor-mode + pdf-misc-minor-mode + pdf-outline-minor-mode + pdf-misc-size-indication-minor-mode + pdf-misc-menu-bar-minor-mode + pdf-annot-minor-mode + pdf-sync-minor-mode + pdf-misc-context-menu-minor-mode + pdf-cache-prefetch-minor-mode + pdf-occur-global-minor-mode + ;; pdf-virtual-global-minor-mode + ) + "A list of automatically enabled minor-modes. + +PDF Tools is build as a series of minor-modes. This variable and +the function `pdf-tools-install' merely serve as a convenient +wrapper in order to load these modes in current and newly created +PDF buffers." + :group 'pdf-tools + :type `(set ,@(mapcar (lambda (mode) + `(function-item ,mode)) + pdf-tools-modes))) + +(defcustom pdf-tools-enabled-hook nil + "A hook ran after PDF Tools is enabled in a buffer." + :group 'pdf-tools + :type 'hook) + +(defconst pdf-tools-auto-mode-alist-entry + '("\\.[pP][dD][fF]\\'" . pdf-view-mode) + "The entry to use for `auto-mode-alist'.") + +(defconst pdf-tools-magic-mode-alist-entry + '("%PDF" . pdf-view-mode) + "The entry to use for `magic-mode-alist'.") + +(defun pdf-tools-customize () + "Customize Pdf Tools." + (interactive) + (customize-group 'pdf-tools)) + +(defun pdf-tools-customize-faces () + "Customize PDF Tool's faces." + (interactive) + (let ((buffer (format "*Customize Group: %s*" + (custom-unlispify-tag-name 'pdf-tools-faces)))) + (when (buffer-live-p (get-buffer buffer)) + (with-current-buffer (get-buffer buffer) + (rename-uniquely))) + (customize-group 'pdf-tools-faces) + (with-current-buffer buffer + (set (make-local-variable 'custom-face-default-form) 'all)))) + + +;; * ================================================================== * +;; * Installation +;; * ================================================================== * + +;;;###autoload +(defcustom pdf-tools-handle-upgrades t + "Whether PDF Tools should handle upgrading itself." + :group 'pdf-tools + :type 'boolean) + +(make-obsolete-variable 'pdf-tools-handle-upgrades + "Not used anymore" "0.90") + +(defconst pdf-tools-directory + (or (and load-file-name + (file-name-directory load-file-name)) + default-directory) + "The directory from where this library was first loaded.") + +(defvar pdf-tools-msys2-directory nil) + +(defcustom pdf-tools-installer-os nil + "Specifies which installer to use. + +If nil the installer is chosen automatically. This variable is +useful if you have multiple installers present on your +system (e.g. nix on arch linux)" + :group 'pdf-tools + :type 'string) + +(defun pdf-tools-identify-build-directory (directory) + "Return non-nil, if DIRECTORY appears to contain the epdfinfo source. + +Returns the expanded directory-name of DIRECTORY or nil." + (setq directory (file-name-as-directory + (expand-file-name directory))) + (and (file-exists-p (expand-file-name "autobuild" directory)) + (file-exists-p (expand-file-name "epdfinfo.c" directory)) + directory)) + +(defun pdf-tools-locate-build-directory () + "Attempt to locate a source directory. + +Returns a appropriate directory or nil. See also +`pdf-tools-identify-build-directory'." + (cl-some #'pdf-tools-identify-build-directory + (list default-directory + (expand-file-name "build/server" pdf-tools-directory) + (expand-file-name "server") + (expand-file-name "server" pdf-tools-directory) + (expand-file-name "../server" pdf-tools-directory)))) + +(defun pdf-tools-msys2-directory (&optional noninteractive-p) + "Locate the Msys2 installation directory. + +Ask the user if necessary and NONINTERACTIVE-P is nil. +Returns always nil, unless `system-type' equals windows-nt." + (cl-labels ((if-msys2-directory (directory) + (and (stringp directory) + (file-directory-p directory) + (file-exists-p + (expand-file-name "usr/bin/bash.exe" directory)) + directory))) + (when (eq system-type 'windows-nt) + (setq pdf-tools-msys2-directory + (or pdf-tools-msys2-directory + (cl-some #'if-msys2-directory + (cl-mapcan + (lambda (drive) + (list (format "%c:/msys64" drive) + (format "%c:/msys32" drive))) + (number-sequence ?c ?z))) + (unless (or noninteractive-p + (not (y-or-n-p "Do you have Msys2 installed ? "))) + (if-msys2-directory + (read-directory-name + "Please enter Msys2 installation directory: " nil nil t)))))))) + +(defun pdf-tools-msys2-mingw-bin () + "Return the location of /mingw*/bin." + (when (pdf-tools-msys2-directory) + (let ((arch (intern (car (split-string system-configuration "-" t))))) + (expand-file-name + (format "./mingw%s/bin" (if (eq arch 'x86_64) "64" "32")) + (pdf-tools-msys2-directory))))) + +(defun pdf-tools-find-bourne-shell () + "Locate a usable sh." + (or (and (eq system-type 'windows-nt) + (let* ((directory (pdf-tools-msys2-directory))) + (when directory + (expand-file-name "usr/bin/bash.exe" directory)))) + (executable-find "sh"))) + +(defun pdf-tools-build-server (target-directory + &optional + skip-dependencies-p + force-dependencies-p + callback + build-directory) + "Build the epdfinfo program in the background. + +Install into TARGET-DIRECTORY, which should be a directory. + +If CALLBACK is non-nil, it should be a function. It is called +with the compiled executable as the single argument or nil, if +the build failed. + +Expect sources to be in BUILD-DIRECTORY. If nil, search for it +using `pdf-tools-locate-build-directory'. + +See `pdf-tools-install' for the SKIP-DEPENDENCIES-P and +FORCE-DEPENDENCIES-P arguments. + +Returns the buffer of the compilation process." + + (unless callback (setq callback #'ignore)) + (unless build-directory + (setq build-directory (pdf-tools-locate-build-directory))) + (cl-check-type target-directory (satisfies file-directory-p)) + (setq target-directory (file-name-as-directory + (expand-file-name target-directory))) + (cl-check-type build-directory (and (not null) + (satisfies file-directory-p))) + (when (and skip-dependencies-p force-dependencies-p) + (error "Can't simultaneously skip and force dependencies")) + (let* ((compilation-auto-jump-to-first-error nil) + (compilation-scroll-output t) + (shell-file-name (pdf-tools-find-bourne-shell)) + (shell-command-switch "-c") + (process-environment process-environment) + (default-directory build-directory) + (autobuild (shell-quote-argument + (expand-file-name "autobuild" build-directory))) + (msys2-p (equal "bash.exe" (file-name-nondirectory shell-file-name)))) + (unless shell-file-name + (error "No suitable shell found")) + (when msys2-p + (push "BASH_ENV=/etc/profile" process-environment)) + (let ((executable + (expand-file-name + (concat "epdfinfo" (and (eq system-type 'windows-nt) ".exe")) + target-directory)) + (compilation-buffer + (compilation-start + (format "%s -i %s%s%s" + autobuild + (shell-quote-argument target-directory) + (cond + (skip-dependencies-p " -D") + (force-dependencies-p " -d") + (t "")) + (if pdf-tools-installer-os (concat " --os " pdf-tools-installer-os) "")) + t))) + ;; In most cases user-input is required, so select the window. + (if (get-buffer-window compilation-buffer) + (select-window (get-buffer-window compilation-buffer)) + (pop-to-buffer compilation-buffer)) + (with-current-buffer compilation-buffer + (setq-local compilation-error-regexp-alist nil) + (add-hook 'compilation-finish-functions + (lambda (_buffer status) + (funcall callback + (and (equal status "finished\n") + executable))) + nil t) + (current-buffer))))) + + +;; * ================================================================== * +;; * Initialization +;; * ================================================================== * + +;;;###autoload +(defun pdf-tools-install (&optional no-query-p skip-dependencies-p + no-error-p force-dependencies-p) + "Install PDF-Tools in all current and future PDF buffers. + +If the `pdf-info-epdfinfo-program' is not running or does not +appear to be working, attempt to rebuild it. If this build +succeeded, continue with the activation of the package. +Otherwise fail silently, i.e. no error is signaled. + +Build the program (if necessary) without asking first, if +NO-QUERY-P is non-nil. + +Don't attempt to install system packages, if SKIP-DEPENDENCIES-P +is non-nil. + +Do not signal an error in case the build failed, if NO-ERROR-P is +non-nil. + +Attempt to install system packages (even if it is deemed +unnecessary), if FORCE-DEPENDENCIES-P is non-nil. + +Note that SKIP-DEPENDENCIES-P and FORCE-DEPENDENCIES-P are +mutually exclusive. + +Note further, that you can influence the installation directory +by setting `pdf-info-epdfinfo-program' to an appropriate +value (e.g. ~/bin/epdfinfo) before calling this function. + +See `pdf-view-mode' and `pdf-tools-enabled-modes'." + (interactive) + (if (or (pdf-info-running-p) + (ignore-errors (pdf-info-check-epdfinfo) t)) + (pdf-tools-install-noverify) + (let ((target-directory + (or (and (stringp pdf-info-epdfinfo-program) + (file-name-directory + pdf-info-epdfinfo-program)) + pdf-tools-directory))) + (if (or no-query-p + (y-or-n-p "Need to (re)build the epdfinfo program, do it now ?")) + (pdf-tools-build-server + target-directory + skip-dependencies-p + force-dependencies-p + (lambda (executable) + (let ((msg (format + "Building the PDF Tools server %s" + (if executable "succeeded" "failed")))) + (if (not executable) + (funcall (if no-error-p #'message #'error) "%s" msg) + (message "%s" msg) + (setq pdf-info-epdfinfo-program executable) + (let ((pdf-info-restart-process-p t)) + (pdf-tools-install-noverify)))))) + (message "PDF Tools not activated"))))) + +(defun pdf-tools-install-noverify () + "Like `pdf-tools-install', but skip checking `pdf-info-epdfinfo-program'." + (add-to-list 'auto-mode-alist pdf-tools-auto-mode-alist-entry) + (add-to-list 'magic-mode-alist pdf-tools-magic-mode-alist-entry) + ;; FIXME: Generalize this sometime. + (when (memq 'pdf-occur-global-minor-mode + pdf-tools-enabled-modes) + (pdf-occur-global-minor-mode 1)) + (when (memq 'pdf-virtual-global-minor-mode + pdf-tools-enabled-modes) + (pdf-virtual-global-minor-mode 1)) + (add-hook 'pdf-view-mode-hook #'pdf-tools-enable-minor-modes) + (dolist (buf (buffer-list)) + ;; This when check should not be necessary, but somehow dead + ;; buffers are showing up here. See + ;; https://github.com/vedang/pdf-tools/pull/93 + (when (buffer-live-p buf) + (with-current-buffer buf + (when (and (not (derived-mode-p 'pdf-view-mode)) + (pdf-tools-pdf-buffer-p) + (buffer-file-name)) + (pdf-view-mode)))))) + +(defun pdf-tools-uninstall () + "Uninstall PDF-Tools in all current and future PDF buffers." + (interactive) + (pdf-info-quit) + (setq-default auto-mode-alist + (remove pdf-tools-auto-mode-alist-entry auto-mode-alist)) + (setq-default magic-mode-alist + (remove pdf-tools-magic-mode-alist-entry magic-mode-alist)) + (pdf-occur-global-minor-mode -1) + (pdf-virtual-global-minor-mode -1) + (remove-hook 'pdf-view-mode-hook #'pdf-tools-enable-minor-modes) + (dolist (buf (buffer-list)) + (with-current-buffer buf + (when (pdf-util-pdf-buffer-p buf) + (pdf-tools-disable-minor-modes pdf-tools-modes) + (normal-mode))))) + +(defun pdf-tools-pdf-buffer-p (&optional buffer) + "Check if the current buffer is a PDF document. + +Optionally, take BUFFER as an argument and check if it is a PDF document." + (save-current-buffer + (when buffer (set-buffer buffer)) + (save-excursion + (save-restriction + (widen) + (goto-char 1) + (looking-at "%PDF"))))) + +(defun pdf-tools-assert-pdf-buffer (&optional buffer) + "Throw an error if the current BUFFER does not contain a PDF document." + (unless (pdf-tools-pdf-buffer-p buffer) + (error "Buffer does not contain a PDF document"))) + +(defun pdf-tools-set-modes-enabled (enable &optional modes) + "Enable/Disable all the pdf-tools modes on the current buffer based on ENABLE. + +Accepts MODES as a optional argument to enable/disable specific modes." + (dolist (m (or modes pdf-tools-enabled-modes)) + (let ((enabled-p (and (boundp m) + (symbol-value m)))) + (unless (or (and enabled-p enable) + (and (not enabled-p) (not enable))) + (funcall m (if enable 1 -1)))))) + +;;;###autoload +(defun pdf-tools-enable-minor-modes (&optional modes) + "Enable MODES in the current buffer. + +MODES defaults to `pdf-tools-enabled-modes'." + (interactive) + (pdf-util-assert-pdf-buffer) + (pdf-tools-set-modes-enabled t modes) + (run-hooks 'pdf-tools-enabled-hook)) + +(defun pdf-tools-disable-minor-modes (&optional modes) + "Disable MODES in the current buffer. + +MODES defaults to `pdf-tools-enabled-modes'." + (interactive) + (pdf-tools-set-modes-enabled nil modes)) + +(declare-function pdf-occur-global-minor-mode "pdf-occur.el") +(declare-function pdf-virtual-global-minor-mode "pdf-virtual.el") + +;;;###autoload +(defun pdf-tools-help () + "Show a Help buffer for `pdf-tools'." + (interactive) + (help-setup-xref (list #'pdf-tools-help) + (called-interactively-p 'interactive)) + (with-help-window (help-buffer) + (princ "PDF Tools Help\n\n") + (princ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n") + (dolist (m (cons 'pdf-view-mode + (sort (copy-sequence pdf-tools-modes) #'string<))) + (princ (format "`%s' is " m)) + (describe-function-1 m) + (terpri) (terpri) + (princ " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n")))) + + +;; * ================================================================== * +;; * Debugging +;; * ================================================================== * + +(defvar pdf-tools-debug nil + "Non-nil, if debugging PDF Tools.") + +(defun pdf-tools-toggle-debug () + "Turn debugging on/off for pdf-tools." + (interactive) + (setq pdf-tools-debug (not pdf-tools-debug)) + (when (called-interactively-p 'any) + (message "Toggled debugging %s" (if pdf-tools-debug "on" "off")))) + +(provide 'pdf-tools) + +;;; pdf-tools.el ends here diff --git a/org/elpa/pdf-tools-20230404.327/pdf-util.el b/org/elpa/pdf-tools-20230404.327/pdf-util.el new file mode 100644 index 0000000..1e3b7be --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/pdf-util.el @@ -0,0 +1,1286 @@ +;;; pdf-util.el --- PDF Utility functions. -*- lexical-binding: t -*- + +;; Copyright (C) 2013, 2014 Andreas Politz + +;; Author: Andreas Politz +;; Keywords: files, multimedia + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; +;;; Todo: +;; + +;;; Code: + +(require 'pdf-macs) +(require 'cl-lib) +(require 'format-spec) +(require 'faces) + +;; These functions are only used after a PdfView window was asserted, +;; which won't succeed, if pdf-view.el isn't loaded. +(declare-function pdf-view-image-size "pdf-view") +(declare-function pdf-view-image-offset "pdf-view") +(declare-function pdf-cache-pagesize "pdf-cache") +(declare-function pdf-view-image-type "pdf-view") + + + +;; * ================================================================== * +;; * Transforming coordinates +;; * ================================================================== * + + +(defun pdf-util-scale (list-of-edges-or-pos scale &optional rounding-fn) + "Scale LIST-OF-EDGES-OR-POS by SCALE. + +SCALE is a cons (SX . SY), by which edges/positions are scaled. +If ROUNDING-FN is non-nil, it should be a function of one +argument, a real value, returning a rounded +value (e.g. `ceiling'). + +The elements in LIST-OF-EDGES-OR-POS should be either a list +\(LEFT TOP RIGHT BOT\) or a position \(X . Y\). + +LIST-OF-EDGES-OR-POS may also be a single such element. + +Return scaled list of edges if LIST-OF-EDGES-OR-POS was indeed a list, +else return the scaled singleton." + + (let ((have-list-p (listp (car list-of-edges-or-pos)))) + (unless have-list-p + (setq list-of-edges-or-pos (list list-of-edges-or-pos))) + (let* ((sx (car scale)) + (sy (cdr scale)) + (result + (mapcar + (lambda (edges) + (cond + ((consp (cdr edges)) + (let ((e (list (* (nth 0 edges) sx) + (* (nth 1 edges) sy) + (* (nth 2 edges) sx) + (* (nth 3 edges) sy)))) + (if rounding-fn + (mapcar rounding-fn e) + e))) + (rounding-fn + (cons (funcall rounding-fn (* (car edges) sx)) + (funcall rounding-fn (* (cdr edges) sy)))) + (t + (cons (* (car edges) sx) + (* (cdr edges) sy))))) + list-of-edges-or-pos))) + (if have-list-p + result + (car result))))) + +(defun pdf-util-scale-to (list-of-edges from to &optional rounding-fn) + "Scale LIST-OF-EDGES in FROM basis to TO. + +FROM and TO should both be a cons \(WIDTH . HEIGHT\). See also +`pdf-util-scale'." + + (pdf-util-scale list-of-edges + (cons (/ (float (car to)) + (float (car from))) + (/ (float (cdr to)) + (float (cdr from)))) + rounding-fn)) + +(defun pdf-util-scale-pixel-to-points (list-of-pixel-edges + &optional rounding-fn displayed-p window) + "Scale LIST-OF-PIXEL-EDGES to point values. + +The result depends on the currently displayed page in WINDOW. +See also `pdf-util-scale'." + (pdf-util-assert-pdf-window window) + (pdf-util-scale-to + list-of-pixel-edges + (pdf-view-image-size displayed-p window) + (pdf-cache-pagesize (pdf-view-current-page window)) + rounding-fn)) + +(defun pdf-util-scale-points-to-pixel (list-of-points-edges + &optional rounding-fn displayed-p window) + "Scale LIST-OF-POINTS-EDGES to point values. + +The result depends on the currently displayed page in WINDOW. +See also `pdf-util-scale'." + (pdf-util-assert-pdf-window window) + (pdf-util-scale-to + list-of-points-edges + (pdf-cache-pagesize (pdf-view-current-page window)) + (pdf-view-image-size displayed-p window) + rounding-fn)) + +(defun pdf-util-scale-relative-to-points (list-of-relative-edges + &optional rounding-fn window) + "Scale LIST-OF-RELATIVE-EDGES to point values. + +The result depends on the currently displayed page in WINDOW. +See also `pdf-util-scale'." + (pdf-util-assert-pdf-window window) + (pdf-util-scale-to + list-of-relative-edges + '(1.0 . 1.0) + (pdf-cache-pagesize (pdf-view-current-page window)) + rounding-fn)) + +(defun pdf-util-scale-points-to-relative (list-of-points-edges + &optional rounding-fn window) + "Scale LIST-OF-POINTS-EDGES to relative values. + +See also `pdf-util-scale'." + (pdf-util-assert-pdf-window window) + (pdf-util-scale-to + list-of-points-edges + (pdf-cache-pagesize (pdf-view-current-page window)) + '(1.0 . 1.0) + rounding-fn)) + +(defun pdf-util-scale-pixel-to-relative (list-of-pixel-edges + &optional rounding-fn displayed-p window) + "Scale LIST-OF-PIXEL-EDGES to relative values. + +The result depends on the currently displayed page in WINDOW. +See also `pdf-util-scale'." + (pdf-util-assert-pdf-window window) + (pdf-util-scale-to + list-of-pixel-edges + (pdf-view-image-size displayed-p window) + '(1.0 . 1.0) + rounding-fn)) + + +(defun pdf-util-scale-relative-to-pixel (list-of-relative-edges + &optional rounding-fn displayed-p window) + "Scale LIST-OF-EDGES to match SIZE. + +The result depends on the currently displayed page in WINDOW. +See also `pdf-util-scale'." + (pdf-util-assert-pdf-window window) + (pdf-util-scale-to + list-of-relative-edges + '(1.0 . 1.0) + (pdf-view-image-size displayed-p window) + rounding-fn)) + +(defun pdf-util-translate (list-of-edges-or-pos + offset &optional opposite-direction-p) + "Translate LIST-OF-EDGES-OR-POS by OFFSET + +OFFSET should be a cons \(X . Y\), by which to translate +LIST-OF-EDGES-OR-POS. If OPPOSITE-DIRECTION-P is non-nil +translate by \(-X . -Y\). + +See `pdf-util-scale' for the LIST-OF-EDGES-OR-POS argument." + + (let ((have-list-p (listp (car list-of-edges-or-pos)))) + (unless have-list-p + (setq list-of-edges-or-pos (list list-of-edges-or-pos))) + (let* ((ox (if opposite-direction-p + (- (car offset)) + (car offset))) + (oy (if opposite-direction-p + (- (cdr offset)) + (cdr offset))) + (result + (mapcar + (lambda (edges) + (cond + ((consp (cdr edges)) + (list (+ (nth 0 edges) ox) + (+ (nth 1 edges) oy) + (+ (nth 2 edges) ox) + (+ (nth 3 edges) oy))) + (t + (cons (+ (car edges) ox) + (+ (cdr edges) oy))))) + list-of-edges-or-pos))) + (if have-list-p + result + (car result))))) + +(defmacro pdf-util-with-edges (list-of-edges &rest body) + "Provide some convenient macros for the edges in LIST-OF-EDGES. + +LIST-OF-EDGES should be a list of variables \(X ...\), each one +holding a list of edges. Inside BODY the symbols X-left, X-top, +X-right, X-bot, X-width and X-height expand to their respective +values." + + (declare (indent 1) (debug (sexp &rest form))) + (unless (cl-every 'symbolp list-of-edges) + (error "Argument should be a list of symbols")) + (let ((list-of-syms + (mapcar (lambda (edge) + (cons edge (mapcar + (lambda (kind) + (intern (format "%s-%s" edge kind))) + '(left top right bot width height)))) + list-of-edges))) + (macroexpand-all + `(cl-symbol-macrolet + ,(apply #'nconc + (mapcar + (lambda (edge-syms) + (let ((edge (nth 0 edge-syms)) + (syms (cdr edge-syms))) + `((,(pop syms) (nth 0 ,edge)) + (,(pop syms) (nth 1 ,edge)) + (,(pop syms) (nth 2 ,edge)) + (,(pop syms) (nth 3 ,edge)) + (,(pop syms) (- (nth 2 ,edge) + (nth 0 ,edge))) + (,(pop syms) (- (nth 3 ,edge) + (nth 1 ,edge)))))) + list-of-syms)) + ,@body)))) + +(defun pdf-util-edges-transform (region elts &optional to-region-p) + "Translate ELTS according to REGION. + +ELTS may be one edges list or a position or a list thereof. +Translate each from region coordinates to (0 0 1 1) or the +opposite, if TO-REGION-P is non-nil. All coordinates should be +relative. + +Returns the translated list of elements or the single one +depending on the input." + + (when elts + (let ((have-list-p (consp (car-safe elts)))) + (unless have-list-p + (setq elts (list elts))) + (let ((result + (if (null region) + elts + (mapcar (lambda (edges) + (let ((have-pos-p (numberp (cdr edges)))) + (when have-pos-p + (setq edges (list (car edges) (cdr edges) + (car edges) (cdr edges)))) + (pdf-util-with-edges (edges region) + (let ((newedges + (mapcar (lambda (n) + (min 1.0 (max 0.0 n))) + (if to-region-p + `(,(/ (- edges-left region-left) + region-width) + ,(/ (- edges-top region-top) + region-height) + ,(/ (- edges-right region-left) + region-width) + ,(/ (- edges-bot region-top) + region-height)) + `(,(+ (* edges-left region-width) + region-left) + ,(+ (* edges-top region-height) + region-top) + ,(+ (* edges-right region-width) + region-left) + ,(+ (* edges-bot region-height) + region-top)))))) + (if have-pos-p + (cons (car newedges) (cadr newedges)) + newedges))))) + elts)))) + (if have-list-p + result + (car result)))))) + +;; * ================================================================== * +;; * Scrolling +;; * ================================================================== * + +(defun pdf-util-image-displayed-edges (&optional window displayed-p) + "Return the visible region of the image in WINDOW. + +Returns a list of pixel edges." + (pdf-util-assert-pdf-window) + (let* ((edges (window-inside-pixel-edges window)) + (isize (pdf-view-image-size displayed-p window)) + (offset (if displayed-p + `(0 . 0) + (pdf-view-image-offset window))) + (hscroll (* (window-hscroll window) + (frame-char-width (window-frame window)))) + (vscroll (window-vscroll window t)) + (x0 (+ hscroll (car offset))) + (y0 (+ vscroll (cdr offset))) + (x1 (min (car isize) + (+ x0 (- (nth 2 edges) (nth 0 edges))))) + (y1 (min (cdr isize) + (+ y0 (- (nth 3 edges) (nth 1 edges)))))) + (mapcar #'round (list x0 y0 x1 y1)))) + +(defun pdf-util-required-hscroll (edges &optional eager-p context-pixel) + "Return the amount of scrolling necessary, to make image EDGES visible. + +Scroll as little as necessary. Unless EAGER-P is non-nil, in +which case scroll as much as possible. + +Keep CONTEXT-PIXEL pixel of the image visible at the bottom and +top of the window. CONTEXT-PIXEL defaults to 0. + +Return the required hscroll in columns or nil, if scrolling is not +needed." + + (pdf-util-assert-pdf-window) + (unless context-pixel + (setq context-pixel 0)) + (let* ((win (window-inside-pixel-edges)) + (image-width (car (pdf-view-image-size t))) + (image-left (* (frame-char-width) + (window-hscroll))) + (edges (pdf-util-translate + edges + (pdf-view-image-offset) t))) + (pdf-util-with-edges (win edges) + (let* ((edges-left (- edges-left context-pixel)) + (edges-right (+ edges-right context-pixel))) + (if (< edges-left image-left) + (round (/ (max 0 (if eager-p + (- edges-right win-width) + edges-left)) + (frame-char-width))) + (if (> (min image-width + edges-right) + (+ image-left win-width)) + (round (/ (min (- image-width win-width) + (if eager-p + edges-left + (- edges-right win-width))) + (frame-char-width))))))))) + +(defun pdf-util-required-vscroll (edges &optional eager-p context-pixel) + "Return the amount of scrolling necessary, to make image EDGES visible. + +Scroll as little as necessary. Unless EAGER-P is non-nil, in +which case scroll as much as possible. + +Keep CONTEXT-PIXEL pixel of the image visible at the bottom and +top of the window. CONTEXT-PIXEL defaults to an equivalent pixel +value of `next-screen-context-lines'. + +Return the required vscroll in pixels or nil, if scrolling is not +needed. + +Note: For versions of emacs before 27 this will return lines instead of +pixels. This is because of a change that occurred to `image-mode' in 27." + (pdf-util-assert-pdf-window) + (let* ((win (window-inside-pixel-edges)) + (image-height (cdr (pdf-view-image-size t))) + (image-top (window-vscroll nil t)) + (edges (pdf-util-translate + edges + (pdf-view-image-offset) t))) + (pdf-util-with-edges (win edges) + (let* ((context-pixel (or context-pixel + (* next-screen-context-lines + (frame-char-height)))) + ;;Be careful not to modify edges. + (edges-top (- edges-top context-pixel)) + (edges-bot (+ edges-bot context-pixel)) + (vscroll + (cond ((< edges-top image-top) + (max 0 (if eager-p + (- edges-bot win-height) + edges-top))) + ((> (min image-height + edges-bot) + (+ image-top win-height)) + (min (- image-height win-height) + (if eager-p + edges-top + (- edges-bot win-height))))))) + + + (when vscroll + (round + ;; `image-set-window-vscroll' changed in version 27 to using + ;; pixels, not lines. + (if (version< emacs-version "27") + (/ vscroll (float (frame-char-height))) + vscroll))))))) + +(defun pdf-util-scroll-to-edges (edges &optional eager-p) + "Scroll window such that image EDGES are visible. + +Scroll as little as necessary. Unless EAGER-P is non-nil, in +which case scroll as much as possible." + + (let ((vscroll (pdf-util-required-vscroll edges eager-p)) + (hscroll (pdf-util-required-hscroll edges eager-p))) + (when vscroll + (image-set-window-vscroll vscroll)) + (when hscroll + (image-set-window-hscroll hscroll)))) + + + +;; * ================================================================== * +;; * Temporary files +;; * ================================================================== * + +(defvar pdf-util--base-directory nil + "Base directory for temporary files.") + +(defvar-local pdf-util--dedicated-directory nil + "The relative name of buffer's dedicated directory.") + +(defun pdf-util-dedicated-directory () + "Return the name of a existing dedicated directory. + +The directory is exclusive to the current buffer. It will be +automatically deleted, if Emacs or the current buffer are +killed." + (with-file-modes #o0700 + (unless (and pdf-util--base-directory + (file-directory-p + pdf-util--base-directory) + (not (file-symlink-p + pdf-util--base-directory))) + (add-hook 'kill-emacs-hook + (lambda nil + (when (and pdf-util--base-directory + (file-directory-p pdf-util--base-directory)) + (delete-directory pdf-util--base-directory t)))) + (setq pdf-util--base-directory + (make-temp-file "pdf-tools-" t))) + (unless (and pdf-util--dedicated-directory + (file-directory-p pdf-util--dedicated-directory) + (not (file-symlink-p + pdf-util--base-directory))) + (let ((temporary-file-directory + pdf-util--base-directory)) + (setq pdf-util--dedicated-directory + (make-temp-file (convert-standard-filename (pdf-util-temp-prefix)) + t)) + (add-hook 'kill-buffer-hook #'pdf-util-delete-dedicated-directory + nil t))) + pdf-util--dedicated-directory)) + +(defun pdf-util-delete-dedicated-directory () + "Delete current buffer's dedicated directory." + (delete-directory (pdf-util-dedicated-directory) t)) + +(defun pdf-util-expand-file-name (name) + "Expand filename against current buffer's dedicated directory." + (expand-file-name name (pdf-util-dedicated-directory))) + +(defun pdf-util-temp-prefix () + "Create a temp-file prefix for the current buffer" + (concat (if buffer-file-name + (file-name-nondirectory buffer-file-name) + (replace-regexp-in-string "[^[:alnum:]]+" "-" (buffer-name))) + "-")) + +(defun pdf-util-make-temp-file (&optional prefix dir-flag suffix) + "Create a temporary file in current buffer's dedicated directory. + +See `make-temp-file' for the arguments." + (let ((temporary-file-directory (pdf-util-dedicated-directory))) + (make-temp-file (convert-standard-filename + (or prefix (pdf-util-temp-prefix))) + dir-flag suffix))) + + +;; * ================================================================== * +;; * Various +;; * ================================================================== * + +(defmacro pdf-util-debug (&rest body) + "Execute BODY only if debugging is enabled." + (declare (indent 0) (debug t)) + `(when (bound-and-true-p pdf-tools-debug) + ,@body)) + +(defun pdf-util-pdf-buffer-p (&optional buffer) + (and (or (null buffer) + (buffer-live-p buffer)) + (save-current-buffer + (and buffer (set-buffer buffer)) + (derived-mode-p 'pdf-view-mode)))) + +(defun pdf-util-assert-pdf-buffer (&optional buffer) + (unless (pdf-util-pdf-buffer-p buffer) + (error "Buffer is not in PDFView mode"))) + +(defun pdf-util-pdf-window-p (&optional window) + (unless (or (null window) + (window-live-p window)) + (signal 'wrong-type-argument (list 'window-live-p window))) + (unless window (setq window (selected-window))) + (and (window-live-p window) + (with-selected-window window + (pdf-util-pdf-buffer-p)))) + +(defun pdf-util-assert-pdf-window (&optional window) + (unless (pdf-util-pdf-window-p window) + (error "Window's buffer is not in PdfView mode"))) + +(defun pdf-util-munch-file (filename &optional multibyte-p) + "Read contents from FILENAME and delete it. + +Return the file's content as a unibyte string, unless MULTIBYTE-P +is non-nil." + (unwind-protect + (with-temp-buffer + (set-buffer-multibyte multibyte-p) + (insert-file-contents-literally filename) + (buffer-substring-no-properties + (point-min) + (point-max))) + (when (and filename + (file-exists-p filename)) + (delete-file filename)))) + +(defun pdf-util-hexcolor (color) + "Return COLOR in hex-format. + +Signal an error, if color is invalid." + (if (string-match "\\`#[[:xdigit:]]\\{6\\}\\'" color) + color + (let ((values (color-values color))) + (unless values + (signal 'wrong-type-argument (list 'color-defined-p color))) + (apply #'format "#%02x%02x%02x" + (mapcar (lambda (c) (ash c -8)) + values))))) + +(defun pdf-util-highlight-regexp-in-string (regexp string &optional face) + "Highlight all occurrences of REGEXP in STRING using FACE. + +FACE defaults to the `match' face. Returns the new fontified +string." + (with-temp-buffer + (save-excursion (insert string)) + (while (and (not (eobp)) + (re-search-forward regexp nil t)) + (if (= (match-beginning 0) + (match-end 0)) + (forward-char) + (put-text-property + (match-beginning 0) + (point) + 'face (or face 'match)))) + (buffer-string))) + +(autoload 'list-colors-duplicates "facemenu") + +(defun pdf-util-color-completions () + "Return a fontified list of defined colors." + (let ((color-list (list-colors-duplicates)) + colors) + (dolist (cl color-list) + (dolist (c (reverse cl)) + (push (propertize c 'face `(:background ,c)) + colors))) + (nreverse colors))) + +(defun pdf-util-tooltip-in-window (text x y &optional window) + (let* ((we (window-inside-absolute-pixel-edges window)) + (dx (round (+ x (nth 0 we)))) + (dy (round (+ y (nth 1 we)))) + (tooltip-frame-parameters + `((left . ,dx) + (top . ,dy) + ,@tooltip-frame-parameters))) + (tooltip-show text))) + +;; FIXME: Defined in `pdf-view' but we can't require it here because it +;; requires us :-( +(defvar pdf-view-midnight-colors) + +(defun pdf-util-tooltip-arrow (image-top &optional timeout) + (pdf-util-assert-pdf-window) + (when (floatp image-top) + (setq image-top + (round (* image-top (cdr (pdf-view-image-size)))))) + (let* (x-gtk-use-system-tooltips ;allow for display property in tooltip + (dx (+ (or (car (window-margins)) 0) + (car (window-fringes)))) + (dy image-top) + (pos (list dx dy dx (+ dy (* 2 (frame-char-height))))) + (vscroll + (pdf-util-required-vscroll pos)) + (tooltip-frame-parameters + `((border-width . 0) + (internal-border-width . 0) + ,@tooltip-frame-parameters)) + (tooltip-hide-delay (or timeout 3))) + (when vscroll + (image-set-window-vscroll vscroll)) + (setq dy (max 0 (- dy + (cdr (pdf-view-image-offset)) + (window-vscroll nil t) + (frame-char-height)))) + (when (overlay-get (pdf-view-current-overlay) 'before-string) + (let* ((e (window-inside-pixel-edges)) + (xw (pdf-util-with-edges (e) e-width))) + (cl-incf dx (/ (- xw (car (pdf-view-image-size t))) 2)))) + (pdf-util-tooltip-in-window + (propertize + " " 'display (propertize + "\u2192" ;;right arrow + 'display '(height 2) + 'face `(:foreground + "orange red" + :background + ,(cond + ((bound-and-true-p pdf-view-midnight-minor-mode) + (cdr pdf-view-midnight-colors)) + ((bound-and-true-p pdf-view-themed-minor-mode) + (face-background 'default nil)) + (t "white"))))) + dx dy))) + +(defvar pdf-util--face-colors-cache (make-hash-table)) + +(advice-add 'enable-theme :after #'pdf-util--clear-faces-cache) +(defun pdf-util--clear-faces-cache (&rest _) + (clrhash pdf-util--face-colors-cache)) + +(defun pdf-util-face-colors (face &optional dark-p) + "Return both colors of FACE as a cons. + +Look also in inherited faces. If DARK-P is non-nil, return dark +colors, otherwise light." + (let* ((bg (if dark-p 'dark 'light)) + (spec (list (get face 'face-defface-spec) + (get face 'theme-face) + (get face 'customized-face))) + (cached (gethash face pdf-util--face-colors-cache))) + (cl-destructuring-bind (&optional cspec color-alist) + cached + (or (and color-alist + (equal cspec spec) + (cdr (assq bg color-alist))) + (let* ((this-bg (frame-parameter nil 'background-mode)) + (frame-background-mode bg) + (f (and (not (eq bg this-bg)) + (x-create-frame-with-faces '((visibility . nil)))))) + (with-selected-frame (or f (selected-frame)) + (unwind-protect + (let ((colors + (cons (face-attribute face :foreground nil 'default) + (face-attribute face :background nil 'default)))) + (puthash face `(,(mapcar #'copy-sequence spec) + ((,bg . ,colors) ,@color-alist)) + pdf-util--face-colors-cache) + colors) + (when (and f (frame-live-p f)) + (delete-frame f))))))))) + +(defun pdf-util-window-attach (awindow &optional window) + "Attach AWINDOW to WINDOW. + +This has the following effect. Whenever WINDOW, defaulting to +the selected window, stops displaying the buffer it currently +displays (e.g., by switching buffers or because it was deleted) +AWINDOW is deleted." + (unless window (setq window (selected-window))) + (let ((buffer (window-buffer window)) + (hook (make-symbol "window-attach-hook"))) + (fset hook + (lambda () + (when (or (not (window-live-p window)) + (not (eq buffer (window-buffer window)))) + (remove-hook 'window-configuration-change-hook + hook) + ;; Deleting windows inside wcch may cause errors in + ;; windows.el . + (run-with-timer + 0 nil (lambda (win) + (when (and (window-live-p win) + (not (eq win (selected-window)))) + (delete-window win))) + awindow)))) + (add-hook 'window-configuration-change-hook hook))) + +(defun display-buffer-split-below-and-attach (buf alist) + "Display buffer action using `pdf-util-window-attach'." + (let ((window (selected-window)) + (height (cdr (assq 'window-height alist))) + newwin) + (when height + (when (floatp height) + (setq height (round (* height (frame-height))))) + (setq height (- (max height window-min-height)))) + (setq newwin (window--display-buffer + buf + (split-window-below height) + 'window alist)) + (pdf-util-window-attach newwin window) + newwin)) + +(defun pdf-util-goto-position (line &optional column) + "Goto LINE and COLUMN in the current buffer. + +COLUMN defaults to 0. Widen the buffer, if the position is +outside the current limits." + (let ((pos + (when (> line 0) + (save-excursion + (save-restriction + (widen) + (goto-char 1) + (when (= 0 (forward-line (1- line))) + (when (and column (> column 0)) + (forward-char (1- column))) + (point))))))) + (when pos + (when (or (< pos (point-min)) + (> pos (point-max))) + (widen)) + (goto-char pos)))) + +(defun pdf-util-seq-alignment (seq1 seq2 &optional similarity-fn alignment-type) + "Return an alignment of sequences SEQ1 and SEQ2. + +SIMILARITY-FN should be a function. It is called with two +arguments: One element from SEQ1 and one from SEQ2. It should +return a number determining how similar the elements are, where +higher values mean `more similar'. The default returns 1 if the +elements are equal, else -1. + +ALIGNMENT-TYPE may be one of the symbols `prefix', `suffix', +`infix' or nil. If it is `prefix', trailing elements in SEQ2 may +be ignored. For example the alignment of + +\(0 1\) and \(0 1 2\) + +using prefix matching is 0, since the prefixes are equal and the +trailing 2 is ignored. The other possible values have similar +effects. The default is nil, which means to match the whole +sequences. + +Return a cons \(VALUE . ALIGNMENT\), where VALUE says how similar +the sequences are and ALIGNMENT is a list of \(E1 . E2\), where +E1 is an element from SEQ1 or nil, likewise for E2. If one of +them is nil, it means there is gap at this position in the +respective sequence." + + (cl-macrolet ((make-matrix (rows columns) + `(apply #'vector + (cl-loop for i from 1 to ,rows + collect (make-vector ,columns nil)))) + (mset (matrix row column newelt) + `(aset (aref ,matrix ,row) ,column ,newelt)) + (mref (matrix row column) + `(aref (aref ,matrix ,row) ,column))) + (let* ((len1 (length seq1)) + (len2 (length seq2)) + (d (make-matrix (1+ len1) (1+ len2))) + (prefix-p (memq alignment-type '(prefix infix))) + (suffix-p (memq alignment-type '(suffix infix))) + (similarity-fn (or similarity-fn + (lambda (a b) + (if (equal a b) 1 -1))))) + + (cl-loop for i from 0 to len1 do + (mset d i 0 (- i))) + (cl-loop for j from 0 to len2 do + (mset d 0 j (if suffix-p 0 (- j)))) + + (cl-loop for i from 1 to len1 do + (cl-loop for j from 1 to len2 do + (let ((max (max + (1- (mref d (1- i) j)) + (+ (mref d i (1- j)) + (if (and prefix-p (= i len1)) 0 -1)) + (+ (mref d (1- i) (1- j)) + (funcall similarity-fn + (elt seq1 (1- i)) + (elt seq2 (1- j))))))) + (mset d i j max)))) + + (let ((i len1) + (j len2) + alignment) + (while (or (> i 0) + (> j 0)) + (cond + ((and (> i 0) + (= (mref d i j) + (1- (mref d (1- i) j)))) + (cl-decf i) + (push (cons (elt seq1 i) nil) alignment)) + ((and (> j 0) + (= (mref d i j) + (+ (mref d i (1- j)) + (if (or (and (= i 0) suffix-p) + (and (= i len1) prefix-p)) + 0 -1)))) + (cl-decf j) + (push (cons nil (elt seq2 j)) alignment)) + (t + (cl-assert (and (> i 0) (> j 0)) t) + (cl-decf i) + (cl-decf j) + (push (cons (elt seq1 i) + (elt seq2 j)) + alignment)))) + (cons (mref d len1 len2) alignment))))) + + +(defun pdf-util-pcre-quote (string) + "Escape STRING for use as a PCRE. + +See also `regexp-quote'." + + (let ((to-escape + (eval-when-compile (append "\0\\|()[]{}^$*+?." nil))) + (chars (append string nil)) + escaped) + (dolist (ch chars) + (when (memq ch to-escape) + (push ?\\ escaped)) + (push ch escaped)) + (apply #'string (nreverse escaped)))) + +(defun pdf-util-frame-ppi () + "Return the PPI of the current frame." + (condition-case nil + (let* ((props (frame-monitor-attributes)) + (px (nthcdr 2 (alist-get 'geometry props))) + (mm (alist-get 'mm-size props)) + (dp (sqrt (+ (expt (nth 0 px) 2) + (expt (nth 1 px) 2)))) + (di (sqrt (+ (expt (/ (nth 0 mm) 25.4) 2) + (expt (/ (nth 1 mm) 25.4) 2))))) + (/ dp di)) + ;; Calculating frame-ppi failed, return 0 to indicate unknown. + ;; This can happen when (frame-monitor-attributes) does not have + ;; the right properties (Emacs 26, 27). It leads to the + ;; wrong-type-argument error, which is the only one we are + ;; catching here. We will catch more errors only if we see them + ;; happening. + (wrong-type-argument 0))) + +(defvar pdf-view-use-scaling) + +(defun pdf-util-frame-scale-factor () + "Return the frame scale factor depending on the image type used for display. +When `pdf-view-use-scaling' is non-nil, return the scale factor of the frame +if available. If the scale factor isn't available, return 2 if the +frame's PPI is larger than 180. Otherwise, return 1." + (if pdf-view-use-scaling + (or (and (fboundp 'frame-scale-factor) + (truncate (frame-scale-factor))) + (and (fboundp 'frame-monitor-attributes) + (cdr (assq 'backing-scale-factor (frame-monitor-attributes)))) + (if (>= (pdf-util-frame-ppi) 180) + 2 + 1)) + 1)) + + +;; * ================================================================== * +;; * Imagemagick's convert +;; * ================================================================== * + +(defcustom pdf-util-convert-program + ;; Avoid using the MS Windows command convert.exe . + (unless (memq system-type '(ms-dos windows-nt)) + (executable-find "convert")) + "Absolute path to the convert program." + :group 'pdf-tools + :type 'executable) + +(defcustom pdf-util-fast-image-format nil + "An image format appropriate for fast displaying. + +This should be a cons \(TYPE . EXT\) where type is the Emacs +image-type and EXT the appropriate file extension starting with a +dot. If nil, the value is determined automatically. + +Different formats have different properties, with respect to +Emacs loading time, convert creation time and the file-size. In +general, uncompressed formats are faster, but may need a fair +amount of (temporary) disk space." + :group 'pdf-tools + :type '(cons symbol string)) + +(defun pdf-util-assert-convert-program () + (unless (and pdf-util-convert-program + (file-executable-p pdf-util-convert-program)) + (error "The pdf-util-convert-program is unset or non-executable"))) + +(defun pdf-util-image-file-size (image-file) + "Determine the size of the image in IMAGE-FILE. + +Returns a cons \(WIDTH . HEIGHT\)." + (pdf-util-assert-convert-program) + (with-temp-buffer + (when (save-excursion + (= 0 (call-process + pdf-util-convert-program + nil (current-buffer) nil + image-file "-format" "%w %h" "info:"))) + (let ((standard-input (current-buffer))) + (cons (read) (read)))))) + +(defun pdf-util-convert (in-file out-file &rest spec) + "Convert image IN-FILE to OUT-FILE according to SPEC. + +IN-FILE should be the name of a file containing an image. Write +the result to OUT-FILE. The extension of this filename usually +determines the resulting image-type. + +SPEC is a property list, specifying what the convert program +should do with the image. All manipulations operate on a +rectangle, see below. + +SPEC may contain the following keys, respectively values. + +`:foreground' Set foreground color for all following operations. + +`:background' Dito, for the background color. + +`:commands' A list of strings representing arguments to convert +for image manipulations. It may contain %-escape characters, as +follows. + +%f -- Expands to the foreground color. +%b -- Expands to the background color. +%g -- Expands to the geometry of the current rectangle, i.e. WxH+X+Y. +%x -- Expands to the left edge of rectangle. +%X -- Expands to the right edge of rectangle. +%y -- Expands to the top edge of rectangle. +%Y -- Expands to the bottom edge of rectangle. +%w -- Expands to the width of rectangle. +%h -- Expands to the height of rectangle. + +Keep in mind, that every element of this list is seen by convert +as a single argument. + +`:formats' An alist of additional %-escapes. Every element +should be a cons \(CHAR . STRING\) or \(CHAR . FUNCTION\). In +the first case, all occurrences of %-CHAR in the above commands +will be replaced by STRING. In the second case FUNCTION is +called with the current rectangle and it should return the +replacement string. + +`:apply' A list of rectangles \(\(LEFT TOP RIGHT BOT\) ...\) in +IN-FILE coordinates. Each such rectangle triggers one execution +of the last commands given earlier in SPEC. E.g. a call like + + (pdf-util-convert + image-file out-file + :foreground \"black\" + :background \"white\" + :commands \\='(\"-fill\" \"%f\" \"-draw\" \"rectangle %x,%y,%X,%Y\") + :apply \\='((0 0 10 10) (10 10 20 20)) + :commands \\='(\"-fill\" \"%b\" \"-draw\" \"rectangle %x,%y,%X,%Y\") + :apply \\='((10 0 20 10) (0 10 10 20))) + +would draw a 4x4 checkerboard pattern in the left corner of the +image, while leaving the rest of it as it was. + +Returns OUT-FILE. + +See url `http://www.imagemagick.org/script/convert.php'." + (pdf-util-assert-convert-program) + (let* ((cmds (pdf-util-convert--create-commands spec)) + (status (apply #'call-process + pdf-util-convert-program nil + (get-buffer-create "*pdf-util-convert-output*") + nil + `(,in-file ,@cmds ,out-file)))) + (unless (and (numberp status) (= 0 status)) + (error "The convert program exited with error status: %s" status)) + out-file)) + +(defun pdf-util-convert-asynch (in-file out-file &rest spec-and-callback) + "Like `pdf-util-convert', but asynchronous. + +If the last argument is a function, it is installed as the +process sentinel. + +Returns the convert process." + (pdf-util-assert-convert-program) + (let ((callback (car (last spec-and-callback))) + spec) + (if (functionp callback) + (setq spec (butlast spec-and-callback)) + (setq spec spec-and-callback + callback nil)) + (let* ((cmds (pdf-util-convert--create-commands spec)) + (proc + (apply #'start-process "pdf-util-convert" + (get-buffer-create "*pdf-util-convert-output*") + pdf-util-convert-program + `(,in-file ,@cmds ,out-file)))) + (when callback + (set-process-sentinel proc callback)) + proc))) + +(defun pdf-util-convert-page (&rest specs) + "Convert image of current page according to SPECS. + +Return the converted PNG image as a string. See also +`pdf-util-convert'." + + (pdf-util-assert-pdf-window) + (let ((in-file (make-temp-file "pdf-util-convert" nil ".png")) + (out-file (make-temp-file "pdf-util-convert" nil ".png"))) + (unwind-protect + (let ((image-data + (plist-get (cdr (pdf-view-current-image)) :data))) + (with-temp-file in-file + (set-buffer-multibyte nil) + (set-buffer-file-coding-system 'binary) + (insert image-data)) + (pdf-util-munch-file + (apply #'pdf-util-convert + in-file out-file specs))) + (when (file-exists-p in-file) + (delete-file in-file)) + (when (file-exists-p out-file) + (delete-file out-file))))) + + +(defun pdf-util-convert--create-commands (spec) + (let ((fg "red") + (bg "red") + formats result cmds s) + (while (setq s (pop spec)) + (unless spec + (error "Missing value in convert spec:%s" (cons s spec))) + (cl-case s + (:foreground + (setq fg (pop spec))) + (:background + (setq bg (pop spec))) + (:commands + (setq cmds (pop spec))) + (:formats + (setq formats (append formats (pop spec) nil))) + (:apply + (dolist (m (pop spec)) + (pdf-util-with-edges (m) + (let ((alist (append + (mapcar (lambda (f) + (cons (car f) + (if (stringp (cdr f)) + (cdr f) + (funcall (cdr f) m)))) + formats) + `((?g . ,(format "%dx%d+%d+%d" + m-width m-height + m-left m-top)) + (?x . ,m-left) + (?X . ,m-right) + (?y . ,m-top) + (?Y . ,m-bot) + (?w . ,(- m-right m-left)) + (?h . ,(- m-bot m-top)) + (?f . ,fg) + (?b . ,bg))))) + (dolist (fmt cmds) + (push (format-spec fmt alist) result)))))))) + (nreverse result))) + +;; FIXME: Check code below and document. + +(defun pdf-util-edges-p (obj &optional relative-p) + "Return non-nil, if OBJ look like edges. + +If RELATIVE-P is non-nil, also check that all values <= 1." + + (and (consp obj) + (ignore-errors (= 4 (length obj))) + (cl-every (lambda (x) + (and (numberp x) + (>= x 0) + (or (null relative-p) + (<= x 1)))) + obj))) + +(defun pdf-util-edges-empty-p (edges) + "Return non-nil, if EDGES area is empty." + (pdf-util-with-edges (edges) + (or (<= edges-width 0) + (<= edges-height 0)))) + +(defun pdf-util-edges-inside-p (edges pos &optional epsilon) + (pdf-util-edges-contained-p + edges + (list (car pos) (cdr pos) (car pos) (cdr pos)) + epsilon)) + +(defun pdf-util-edges-contained-p (edges contained &optional epsilon) + (unless epsilon (setq epsilon 0)) + (pdf-util-with-edges (edges contained) + (and (<= (- edges-left epsilon) + contained-left) + (>= (+ edges-right epsilon) + contained-right) + (<= (- edges-top epsilon) + contained-top) + (>= (+ edges-bot epsilon) + contained-bot)))) + +(defun pdf-util-edges-intersection (e1 e2) + (pdf-util-with-edges (edges1 e1 e2) + (let ((left (max e1-left e2-left)) + (top (max e1-top e2-top)) + (right (min e1-right e2-right)) + (bot (min e1-bot e2-bot))) + (when (and (<= left right) + (<= top bot)) + (list left top right bot))))) + +(defun pdf-util-edges-union (&rest edges) + (if (null (cdr edges)) + (car edges) + (list (apply #'min (mapcar #'car edges)) + (apply #'min (mapcar #'cadr edges)) + (apply #'max (mapcar #'cl-caddr edges)) + (apply #'max (mapcar #'cl-cadddr edges))))) + +(defun pdf-util-edges-intersection-area (e1 e2) + (let ((inters (pdf-util-edges-intersection e1 e2))) + (if (null inters) + 0 + (pdf-util-with-edges (inters) + (* inters-width inters-height))))) + +(defun pdf-util-read-image-position (prompt) + "Read a image position using prompt. + +Return the event position object." + (save-selected-window + (let ((ev (pdf-util-read-click-event + (propertize prompt 'face 'minibuffer-prompt))) + (buffer (current-buffer))) + (unless (mouse-event-p ev) + (error "Not a mouse event")) + (let ((posn (event-start ev))) + (unless (and (eq (window-buffer + (posn-window posn)) + buffer) + (eq 'image (car-safe (posn-object posn)))) + (error "Invalid image position")) + posn)))) + +(defun pdf-util-read-click-event (&optional prompt seconds) + (let ((down (read-event prompt seconds))) + (unless (and (mouse-event-p down) + (equal (event-modifiers down) + '(down))) + (error "No a mouse click event")) + (let ((up (read-event prompt seconds))) + (unless (and (mouse-event-p up) + (equal (event-modifiers up) + '(click))) + (error "No a mouse click event")) + up))) + +(defun pdf-util-image-map-mouse-event-proxy (event) + "Set POS-OR-AREA in EVENT to 1 and unread it." + (interactive "e") + (setcar (cdr (cadr event)) 1) + (setq unread-command-events (list event))) + +(defun pdf-util-image-map-divert-mouse-clicks (id &optional buttons) + (dolist (kind '("" "down-" "drag-")) + (dolist (b (or buttons '(2 3 4 5 6))) + (local-set-key + (vector id (intern (format "%smouse-%d" kind b))) + 'pdf-util-image-map-mouse-event-proxy)))) + +(defmacro pdf-util-do-events (event-resolution-unread-p condition &rest body) + "Read EVENTs while CONDITION executing BODY. + +Process at most 1/RESOLUTION events per second. If UNREAD-p is +non-nil, unread the final non-processed event. + +\(FN (EVENT RESOLUTION &optional UNREAD-p) CONDITION &rest BODY\)" + (declare (indent 2) (debug ((symbolp form &optional form) form body))) + (cl-destructuring-bind (event resolution &optional unread-p) + event-resolution-unread-p + (let ((*seconds (make-symbol "seconds")) + (*timestamp (make-symbol "timestamp")) + (*clock (make-symbol "clock")) + (*unread-p (make-symbol "unread-p")) + (*resolution (make-symbol "resolution"))) + `(let* ((,*unread-p ,unread-p) + (,*resolution ,resolution) + (,*seconds 0) + (,*timestamp (float-time)) + (,*clock (lambda (&optional secs) + (when secs + (setq ,*seconds secs + ,*timestamp (float-time))) + (- (+ ,*timestamp ,*seconds) + (float-time)))) + (,event (read-event))) + (while ,condition + (when (<= (funcall ,*clock) 0) + (progn ,@body) + (setq ,event nil) + (funcall ,*clock ,*resolution)) + (setq ,event + (or (read-event nil nil + (and ,event + (max 0 (funcall ,*clock)))) + ,event))) + (when (and ,*unread-p ,event) + (setq unread-command-events + (append unread-command-events + (list ,event)))))))) + +(defmacro pdf-util-track-mouse-dragging (event-resolution &rest body) + "Read mouse movement events executing BODY. + +See also `pdf-util-do-events'. + +This macro should be used inside a command bound to a down-mouse +event. It evaluates to t, if at least one event was processed in +BODY, otherwise nil. In the latter case, the only event (usually +a mouse click event) is unread. + +\(FN (EVENT RESOLUTION) &rest BODY\)" + (declare (indent 1) (debug ((symbolp form) body))) + (let ((ran-once-p (make-symbol "ran-once-p"))) + `(let (,ran-once-p) + (track-mouse + (pdf-util-do-events (,@event-resolution t) + (mouse-movement-p ,(car event-resolution)) + (setq ,ran-once-p t) + ,@body)) + (when (and ,ran-once-p + unread-command-events) + (setq unread-command-events + (butlast unread-command-events))) + ,ran-once-p))) + +(defun pdf-util-remove-duplicates (list) + "Remove duplicates from LIST stably using `equal'." + (let ((ht (make-hash-table :test 'equal)) + result) + (dolist (elt list (nreverse result)) + (unless (gethash elt ht) + (push elt result) + (puthash elt t ht))))) + +(provide 'pdf-util) + +;;; pdf-util.el ends here diff --git a/org/elpa/pdf-tools-20230404.327/pdf-view.el b/org/elpa/pdf-tools-20230404.327/pdf-view.el new file mode 100644 index 0000000..c1fc21b --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/pdf-view.el @@ -0,0 +1,1788 @@ +;;; pdf-view.el --- View PDF documents. -*- lexical-binding:t -*- + +;; Copyright (C) 2013 Andreas Politz + +;; Author: Andreas Politz +;; Keywords: files, doc-view, pdf + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; Functions related to viewing PDF documents. + +;;; Code: + +(require 'image-mode) +(require 'pdf-macs) +(require 'pdf-util) +(require 'pdf-info) +(require 'pdf-cache) +(require 'jka-compr) +(require 'bookmark) +(require 'password-cache) + +(declare-function cua-copy-region "cua-base") +(declare-function pdf-tools-pdf-buffer-p "pdf-tools") + +;; * ================================================================== * +;; * Customizations +;; * ================================================================== * + +(defgroup pdf-view nil + "View PDF documents." + :group 'pdf-tools) + +(defcustom pdf-view-display-size 'fit-width + "The desired size of displayed pages. + +This may be one of `fit-height', `fit-width', `fit-page' or a +number as a scale factor applied to the document's size. Any +other value behaves like `fit-width'." + :group 'pdf-view + :type '(choice number + (const fit-height) + (const fit-width) + (const fit-page))) + +(make-variable-buffer-local 'pdf-view-display-size) + +(defcustom pdf-view-resize-factor 1.25 + "Fractional amount of resizing of one resize command." + :group 'pdf-view + :type 'number) + +(defcustom pdf-view-continuous t + "In Continuous mode reaching the page edge advances to next/previous page. + +When non-nil, scrolling a line upward at the bottom edge of the page +moves to the next page, and scrolling a line downward at the top edge +of the page moves to the previous page." + :type 'boolean + :group 'pdf-view) + +(defcustom pdf-view-bounding-box-margin 0.05 + "Fractional margin used for slicing with the bounding-box." + :group 'pdf-view + :type 'number) + +(defcustom pdf-view-use-imagemagick nil + "Whether imagemagick should be used for rendering. + +This variable has no effect, if imagemagick was not compiled into +Emacs or if imagemagick is the only way to display PNG images. +FIXME: Explain dis-/advantages of imagemagick and png." + :group 'pdf-view + :type 'boolean) + +(defcustom pdf-view-use-scaling t + "Whether images should be allowed to be scaled for rendering. + +This variable affects both the reuse of higher-resolution images +as lower-resolution ones by down-scaling the image. As well as +the rendering of higher-resolution for high-resolution displays, +if available." + :group 'pdf-view + :type 'boolean) + +(defface pdf-view-region + '((((background dark)) (:inherit region)) + (((background light)) (:inherit region))) + "Face used to determine the colors of the region." + :group 'pdf-view + :group 'pdf-tools-faces) + +(defface pdf-view-rectangle + '((((background dark)) (:inherit highlight)) + (((background light)) (:inherit highlight))) + "Face used to determine the colors of the highlighted rectangle." + :group 'pdf-view + :group 'pdf-tools-faces) + +(defcustom pdf-view-midnight-colors '("#839496" . "#002b36" ) + "Colors used when command `pdf-view-midnight-minor-mode' is activated. + +This should be a cons \(FOREGROUND . BACKGROUND\) of colors." + :group 'pdf-view + :type '(cons (color :tag "Foreground") + (color :tag "Background"))) + +(defcustom pdf-view-midnight-invert t + "In midnight mode invert the image color lightness maintaining hue. + +This is particularly useful if you are viewing documents with +color coded data in plots. This will maintain the colors such +that blue and red will remain these colors in the inverted +rendering. This inversion is non-trivial. This makes use of the +OKLab color space which is well calibrated to have equal +perceptual brightness across hue, but not all colors are within +the RGB gamut after inversion, causing some colors to saturate. +Nevertheless, this seems to work well in most cases." + :group 'pdf-view + :type 'boolean) + +(defcustom pdf-view-change-page-hook nil + "Hook run after changing to another page, but before displaying it. + +See also `pdf-view-before-change-page-hook' and +`pdf-view-after-change-page-hook'." + :group 'pdf-view + :type 'hook) + +(defcustom pdf-view-before-change-page-hook nil + "Hook run before changing to another page. + +See also `pdf-view-change-page-hook' and +`pdf-view-after-change-page-hook'." + :group 'pdf-view + :type 'hook) + +(defcustom pdf-view-after-change-page-hook nil + "Hook run after changing to and displaying another page. + +See also `pdf-view-change-page-hook' and +`pdf-view-before-change-page-hook'." + :group 'pdf-view + :type 'hook) + +(defcustom pdf-view-use-dedicated-register t + "Whether to use dedicated register for PDF positions. + +If this is non-nil, the commands `pdf-view-position-to-register' +and `pdf-view-jump-to-register' use the buffer-local variable +`pdf-view-register-alist' to store resp. retrieve marked +positions. Otherwise the common variable `register-alist' is +used." + :group 'pdf-view + :type 'boolean) + +(defcustom pdf-view-image-relief 0 + "Add a shadow rectangle around the page's image. + +See :relief property in Info node `(elisp) Image Descriptors'." + :group 'pdf-view + :type '(integer :tag "Pixel") + :link '(info-link "(elisp) Image Descriptors")) + +(defcustom pdf-view-max-image-width 4800 + "Maximum width of any image displayed in pixel." + :group 'pdf-view + :type '(integer :tag "Pixel")) + +(defcustom pdf-view-use-unicode-ligther t + "Decide whether to use unicode symbols in the mode-line. + +On some systems finding a font which supports those symbols can +take some time. If you don't want to spend that time waiting and +don't care for a nicer looking mode-line, set this variable to +nil. + +Note, that this option has only an effect when this library is +loaded." + :group 'pdf-view + :type 'boolean) + +(defcustom pdf-view-incompatible-modes + '(linum-mode linum-relative-mode helm-linum-relative-mode + nlinum-mode nlinum-hl-mode nlinum-relative-mode yalinum-mode) + "A list of modes incompatible with `pdf-view-mode'. + +Issue a warning, if one of them is active in a PDF buffer." + :group 'pdf-view + :type '(repeat symbol)) + +(defcustom pdf-view-selection-style 'word + "The current default selection style. + +Must be one of `glyph', `word', or `line'." + :group 'pdf-view + :type '(choice (const glyph) + (const word) + (const line))) + + +;; * ================================================================== * +;; * Internal variables and macros +;; * ================================================================== * + +(defvar-local pdf-view-active-region nil + "The active region as a list of edges. + +Edge values are relative coordinates.") + +(defvar-local pdf-view--have-rectangle-region nil + "Non-nil if the region is currently rendered as a rectangle. + +This variable is set in `pdf-view-mouse-set-region' and used in +`pdf-view-mouse-extend-region' to determine the right choice +regarding display of the region in the later function.") + +(defvar-local pdf-view--buffer-file-name nil + "Local copy of remote file or nil.") + +(defvar-local pdf-view--server-file-name nil + "The servers notion of this buffer's filename.") + +(defvar-local pdf-view--next-page-timer nil + "Timer used in `pdf-view-next-page-command'.") + +(defvar-local pdf-view--hotspot-functions nil + "Alist of hotspot functions.") + +(defvar-local pdf-view--current-rotation nil + "Current rotation of the page.") + +(defvar-local pdf-view-register-alist nil + "Local, dedicated register for PDF positions.") + +(defun pdf-view-current-pagelabel (&optional window) + (nth (1- (pdf-view-current-page window)) (pdf-info-pagelabels))) + +(defun pdf-view-active-region-p nil + "Return t if there are active regions." + (not (null pdf-view-active-region))) + +(defmacro pdf-view-assert-active-region () + "Signal an error if there are no active regions." + `(unless (pdf-view-active-region-p) + (error "The region is not active"))) + +(defconst pdf-view-have-image-mode-pixel-vscroll + (>= emacs-major-version 27) + "Whether `image-mode' scrolls vertically by pixels.") + + +;; * ================================================================== * +;; * Major Mode +;; * ================================================================== * + +(defvar pdf-view-mode-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map image-mode-map) + (define-key map (kbd "Q") 'kill-this-buffer) + ;; Navigation in the document + (define-key map (kbd "n") 'pdf-view-next-page-command) + (define-key map (kbd "p") 'pdf-view-previous-page-command) + (define-key map (kbd "") 'forward-page) + (define-key map (kbd "") 'backward-page) + (define-key map [remap forward-page] 'pdf-view-next-page-command) + (define-key map [remap backward-page] 'pdf-view-previous-page-command) + (define-key map (kbd "SPC") 'pdf-view-scroll-up-or-next-page) + (define-key map (kbd "S-SPC") 'pdf-view-scroll-down-or-previous-page) + (define-key map (kbd "DEL") 'pdf-view-scroll-down-or-previous-page) + (define-key map (kbd "C-n") 'pdf-view-next-line-or-next-page) + (define-key map (kbd "") 'pdf-view-next-line-or-next-page) + (define-key map [remap next-line] 'pdf-view-next-line-or-next-page) + (define-key map (kbd "C-p") 'pdf-view-previous-line-or-previous-page) + (define-key map (kbd "") 'pdf-view-previous-line-or-previous-page) + (define-key map [remap previous-line] 'pdf-view-previous-line-or-previous-page) + (define-key map (kbd "M-<") 'pdf-view-first-page) + (define-key map [remap beginning-of-buffer] 'pdf-view-first-page) + (define-key map (kbd "M->") 'pdf-view-last-page) + (define-key map [remap end-of-buffer] 'pdf-view-last-page) + (define-key map [remap goto-line] 'pdf-view-goto-page) + (define-key map (kbd "M-g l") 'pdf-view-goto-label) + (define-key map (kbd "RET") 'image-next-line) + ;; Zoom in/out. + (define-key map "+" 'pdf-view-enlarge) + (define-key map "=" 'pdf-view-enlarge) + (define-key map "-" 'pdf-view-shrink) + (define-key map "0" 'pdf-view-scale-reset) + ;; Fit the image to the window + (define-key map "W" 'pdf-view-fit-width-to-window) + (define-key map "H" 'pdf-view-fit-height-to-window) + (define-key map "P" 'pdf-view-fit-page-to-window) + ;; Slicing the image + (define-key map (kbd "s m") 'pdf-view-set-slice-using-mouse) + (define-key map (kbd "s b") 'pdf-view-set-slice-from-bounding-box) + (define-key map (kbd "s r") 'pdf-view-reset-slice) + ;; Rotation. + (define-key map (kbd "R") #'pdf-view-rotate) + ;; Reconvert + (define-key map (kbd "C-c C-c") 'doc-view-mode) + (define-key map (kbd "g") 'revert-buffer) + ;; Region + (define-key map [down-mouse-1] 'pdf-view-mouse-set-region) + (define-key map [M-down-mouse-1] 'pdf-view-mouse-set-region-rectangle) + (define-key map [C-down-mouse-1] 'pdf-view-mouse-extend-region) + (define-key map [remap kill-region] 'pdf-view-kill-ring-save) + (define-key map [remap kill-ring-save] 'pdf-view-kill-ring-save) + (define-key map [remap mark-whole-buffer] 'pdf-view-mark-whole-page) + ;; Other + (define-key map (kbd "C-c C-d") 'pdf-view-dark-minor-mode) + (define-key map (kbd "m") 'pdf-view-position-to-register) + (define-key map (kbd "'") 'pdf-view-jump-to-register) + + (define-key map (kbd "C-c C-i") 'pdf-view-extract-region-image) + ;; Rendering + (define-key map (kbd "C-c C-r m") 'pdf-view-midnight-minor-mode) + (define-key map (kbd "C-c C-r t") 'pdf-view-themed-minor-mode) + (define-key map (kbd "C-c C-r p") 'pdf-view-printer-minor-mode) + map) + "Keymap used by `pdf-view-mode' when displaying a doc as a set of images.") + +(define-derived-mode pdf-view-mode special-mode "PDFView" + "Major mode in PDF buffers. + +PDFView Mode is an Emacs PDF viewer. It displays PDF files as +PNG images in Emacs buffers." + :group 'pdf-view + :abbrev-table nil + :syntax-table nil + ;; Setup a local copy for remote files. + (when (and (or jka-compr-really-do-compress + (let ((file-name-handler-alist nil)) + (not (and buffer-file-name + (file-readable-p buffer-file-name))))) + (pdf-tools-pdf-buffer-p)) + (let ((tempfile (pdf-util-make-temp-file))) + (write-region nil nil tempfile nil 'no-message) + (setq-local pdf-view--buffer-file-name tempfile))) + ;; Decryption needs to be done before any other function calls into + ;; pdf-info.el (e.g. from the mode-line during redisplay during + ;; waiting for process output). + (pdf-view-decrypt-document) + + ;; Setup scroll functions + (if (boundp 'mwheel-scroll-up-function) ; not --without-x build + (setq-local mwheel-scroll-up-function + #'pdf-view-scroll-up-or-next-page)) + (if (boundp 'mwheel-scroll-down-function) + (setq-local mwheel-scroll-down-function + #'pdf-view-scroll-down-or-previous-page)) + + ;; Disable pixel-scroll-precision-mode locally if enabled + (if (bound-and-true-p pixel-scroll-precision-mode) + (set (make-local-variable 'pixel-scroll-precision-mode) nil)) + (if (boundp 'mwheel-coalesce-scroll-events) + (setq-local mwheel-coalesce-scroll-events t)) + + ;; Clearing overlays + (add-hook 'change-major-mode-hook + (lambda () + (remove-overlays (point-min) (point-max) 'pdf-view t)) + nil t) + (remove-overlays (point-min) (point-max) 'pdf-view t) ;Just in case. + + ;; Setup other local variables. + (setq-local mode-line-position + '(" P" (:eval (number-to-string (pdf-view-current-page))) + ;; Avoid errors during redisplay. + "/" (:eval (or (ignore-errors + (number-to-string (pdf-cache-number-of-pages))) + "???")))) + (setq-local auto-hscroll-mode nil) + (setq-local pdf-view--server-file-name (pdf-view-buffer-file-name)) + ;; High values of scroll-conservatively seem to trigger + ;; some display bug in xdisp.c:try_scrolling . + (setq-local scroll-conservatively 0) + (setq-local cursor-type nil) + (setq-local buffer-read-only t) + (setq-local view-read-only nil) + (setq-local bookmark-make-record-function + 'pdf-view-bookmark-make-record) + (setq-local revert-buffer-function #'pdf-view-revert-buffer) + ;; No auto-save at the moment. + (setq-local buffer-auto-save-file-name nil) + ;; Disable image rescaling. + (when (boundp 'image-scaling-factor) + (setq-local image-scaling-factor 1)) + ;; No undo at the moment. + (unless buffer-undo-list + (buffer-disable-undo)) + ;; Enable transient-mark-mode, so region deactivation when quitting + ;; will work. + (setq-local transient-mark-mode t) + + (add-hook 'window-configuration-change-hook + 'pdf-view-redisplay-some-windows nil t) + (add-hook 'deactivate-mark-hook 'pdf-view-deactivate-region nil t) + (add-hook 'write-contents-functions + 'pdf-view--write-contents-function nil t) + (add-hook 'kill-buffer-hook 'pdf-view-close-document nil t) + (pdf-view-add-hotspot-function + 'pdf-view-text-regions-hotspots-function -9) + + ;; Keep track of display info + (add-hook 'image-mode-new-window-functions + 'pdf-view-new-window-function nil t) + (image-mode-setup-winprops) + + ;; Issue a warning in the future about incompatible modes. + (run-with-timer 1 nil (lambda (buffer) + (when (buffer-live-p buffer) + (pdf-view-check-incompatible-modes buffer))) + (current-buffer))) + +(advice-add 'cua-copy-region + :before-until + #'cua-copy-region--pdf-view-advice) + +(defun cua-copy-region--pdf-view-advice (&rest _) + "If the current buffer is in `pdf-view' mode, call `pdf-view-kill-ring-save'." + (when (eq major-mode 'pdf-view-mode) + (pdf-view-kill-ring-save) + t)) + +(defun pdf-view-check-incompatible-modes (&optional buffer) + "Check BUFFER for incompatible modes, maybe issue a warning." + (with-current-buffer (or buffer (current-buffer)) + (let ((modes + (cl-remove-if-not + (lambda (mode) (and (symbolp mode) + (boundp mode) + (symbol-value mode))) + pdf-view-incompatible-modes))) + (when modes + (display-warning + 'pdf-view + (format "These modes are incompatible with `pdf-view-mode', + please deactivate them (or customize pdf-view-incompatible-modes): %s" + (mapconcat #'symbol-name modes ","))))))) + +(defun pdf-view-decrypt-document () + "Read a password, if the document is encrypted and open it." + (interactive) + (when (pdf-info-encrypted-p) + (let ((prompt (format "Enter password for `%s': " + (abbreviate-file-name + (buffer-file-name)))) + (key (concat "/pdf-tools" (buffer-file-name))) + (i 3) + password) + (while (and (> i 0) + (pdf-info-encrypted-p)) + (setq i (1- i)) + (setq password (password-read prompt key)) + (setq prompt "Invalid password, try again: ") + (ignore-errors (pdf-info-open nil password))) + (pdf-info-open nil password) + (password-cache-add key password))) + nil) + +(defun pdf-view-buffer-file-name () + "Return the local filename of the PDF in the current buffer. + +This may be different from variable `buffer-file-name' when +operating on a local copy of a remote file." + (or pdf-view--buffer-file-name + (buffer-file-name))) + +(defun pdf-view--write-contents-function () + "Function for `write-contents-functions' to save the buffer." + (when (pdf-util-pdf-buffer-p) + (let ((tempfile (pdf-info-save pdf-view--server-file-name))) + (unwind-protect + (progn + ;; Order matters here: We need to first copy the new + ;; content (tempfile) to the PDF, and then close the PDF. + ;; Since while closing the file (and freeing its resources + ;; in the process), it may be immediately reopened due to + ;; redisplay happening inside the pdf-info-close function + ;; (while waiting for a response from the process.). + (copy-file tempfile (or (buffer-file-name) + (read-file-name + "File name to save PDF to: ")) + t) + (pdf-info-close pdf-view--server-file-name) + + (when pdf-view--buffer-file-name + (copy-file tempfile pdf-view--buffer-file-name t)) + (clear-visited-file-modtime) + (set-buffer-modified-p nil) + (setq pdf-view--server-file-name + (pdf-view-buffer-file-name)) + t) + (when (file-exists-p tempfile) + (delete-file tempfile)))))) + +(defun pdf-view--after-revert () + "Reload the local copy in case of a remote file, and close the document." + (when pdf-view--buffer-file-name + (write-region nil nil pdf-view--buffer-file-name nil 'no-message)) + (pdf-info-close)) + +(defun pdf-view-revert-buffer (&optional ignore-auto noconfirm) + "Revert buffer while preserving current modes. + +Optional parameters IGNORE-AUTO and NOCONFIRM are defined as in +`revert-buffer'." + (interactive (list (not current-prefix-arg))) + ;; Bind to default so that we can use pdf-view-revert-buffer as + ;; revert-buffer-function. A binding of nil is needed in Emacs 24.3, but in + ;; later versions the semantics that nil means the default function should + ;; not relied upon. + (let ((revert-buffer-function (when (fboundp #'revert-buffer--default) + #'revert-buffer--default)) + (after-revert-hook + (cons #'pdf-view--after-revert + after-revert-hook))) + (prog1 + (revert-buffer ignore-auto noconfirm 'preserve-modes) + (pdf-view-redisplay t)))) + +(defun pdf-view-close-document () + "Return immediately after closing document. + +This function always succeeds. See also `pdf-info-close', which +does not return immediately." + (when (pdf-info-running-p) + (let ((pdf-info-asynchronous 'ignore)) + (ignore-errors + (pdf-info-close))))) + + +;; * ================================================================== * +;; * Scaling +;; * ================================================================== * + +(defun pdf-view-fit-page-to-window () + "Fit PDF to window. + +Choose the larger of PDF's height and width, and fits that +dimension to window." + (interactive) + (setq pdf-view-display-size 'fit-page) + (image-set-window-vscroll 0) + (image-set-window-hscroll 0) + (pdf-view-redisplay t)) + +(defun pdf-view-fit-height-to-window () + "Fit PDF height to window." + (interactive) + (setq pdf-view-display-size 'fit-height) + (image-set-window-vscroll 0) + (pdf-view-redisplay t)) + +(defun pdf-view-fit-width-to-window () + "Fit PDF size to window." + (interactive) + (setq pdf-view-display-size 'fit-width) + (image-set-window-hscroll 0) + (pdf-view-redisplay t)) + +(defun pdf-view-enlarge (factor) + "Enlarge PDF by FACTOR. + +When called interactively, uses the value of +`pdf-view-resize-factor'. + +For example, (pdf-view-enlarge 1.25) increases size by 25%." + (interactive + (list (float pdf-view-resize-factor))) + (let* ((size (pdf-view-image-size)) + (pagesize (pdf-cache-pagesize + (pdf-view-current-page))) + (scale (/ (float (car size)) + (float (car pagesize))))) + (setq pdf-view-display-size + (* factor scale)) + (pdf-view-redisplay t))) + +(defun pdf-view-shrink (factor) + "Shrink PDF by FACTOR. + +When called interactively, uses the value of +`pdf-view-resize-factor'. + +For example, (pdf-view-shrink 1.25) decreases size by 20%." + (interactive + (list (float pdf-view-resize-factor))) + (pdf-view-enlarge (/ 1.0 factor))) + +(defun pdf-view-scale-reset () + "Reset PDF to its default set." + (interactive) + (setq pdf-view-display-size 1.0) + (pdf-view-redisplay t)) + + +;; * ================================================================== * +;; * Rotation +;; * ================================================================== * +(defun pdf-view-rotate (angle) + "Rotate the current page by ANGLE degrees clockwise. +When called interactively, angle defaults to 90. Moreover, if +called interactively with a prefix argument, then rotate +anti-clockwise." + (interactive (list (if current-prefix-arg -90 90))) + (setq-local pdf-view--current-rotation + (mod (+ (or pdf-view--current-rotation 0) + angle) + 360)) + (pdf-view-redisplay t)) + + +;; * ================================================================== * +;; * Moving by pages and scrolling +;; * ================================================================== * + +(defvar pdf-view-inhibit-redisplay nil) +(defvar pdf-view-inhibit-hotspots nil) + +(defun pdf-view-goto-page (page &optional window) + "Go to PAGE in PDF. + +If optional parameter WINDOW, go to PAGE in all `pdf-view' +windows." + (interactive + (list (if current-prefix-arg + (prefix-numeric-value current-prefix-arg) + (read-number "Page: ")))) + (unless (and (>= page 1) + (<= page (pdf-cache-number-of-pages))) + (error "No such page: %d" page)) + (unless window + (setq window + (if (pdf-util-pdf-window-p) + (selected-window) + t))) + (save-selected-window + ;; Select the window for the hooks below. + (when (window-live-p window) + (select-window window 'norecord)) + (let ((changing-p + (not (eq page (pdf-view-current-page window))))) + (when changing-p + (run-hooks 'pdf-view-before-change-page-hook) + (setf (pdf-view-current-page window) page) + (run-hooks 'pdf-view-change-page-hook)) + (when (window-live-p window) + (pdf-view-redisplay window)) + (when changing-p + (pdf-view-deactivate-region) + (force-mode-line-update) + (run-hooks 'pdf-view-after-change-page-hook)))) + nil) + +(defun pdf-view-next-page (&optional n) + "View the next page in the PDF. + +Optional parameter N moves N pages forward." + (interactive "p") + (pdf-view-goto-page (+ (pdf-view-current-page) + (or n 1)))) + +(defun pdf-view-previous-page (&optional n) + "View the previous page in the PDF. + +Optional parameter N moves N pages backward." + (interactive "p") + (pdf-view-next-page (- (or n 1)))) + +(defun pdf-view-next-page-command (&optional n) + "View the next page in the PDF. + +Optional parameter N moves N pages forward. + +This command is a wrapper for `pdf-view-next-page' that will +indicate to the user if they are on the last page and more." + (declare (interactive-only pdf-view-next-page)) + (interactive "p") + (unless n (setq n 1)) + (when (> (+ (pdf-view-current-page) n) + (pdf-cache-number-of-pages)) + (user-error "Last page")) + (when (< (+ (pdf-view-current-page) n) 1) + (user-error "First page")) + (let ((pdf-view-inhibit-redisplay t)) + (pdf-view-goto-page + (+ (pdf-view-current-page) n))) + (force-mode-line-update) + (sit-for 0) + (when pdf-view--next-page-timer + (cancel-timer pdf-view--next-page-timer) + (setq pdf-view--next-page-timer nil)) + (if (or (not (input-pending-p)) + (and (> n 0) + (= (pdf-view-current-page) + (pdf-cache-number-of-pages))) + (and (< n 0) + (= (pdf-view-current-page) 1))) + (pdf-view-redisplay) + (setq pdf-view--next-page-timer + (run-with-idle-timer 0.001 nil 'pdf-view-redisplay (selected-window))))) + +(defun pdf-view-previous-page-command (&optional n) + "View the previous page in the PDF. + +Optional parameter N moves N pages backward. + +This command is a wrapper for `pdf-view-previous-page'." + (declare (interactive-only pdf-view-previous-page)) + (interactive "p") + (with-no-warnings + (pdf-view-next-page-command (- (or n 1))))) + +(defun pdf-view-first-page () + "View the first page." + (interactive) + (pdf-view-goto-page 1)) + +(defun pdf-view-last-page () + "View the last page." + (interactive) + (pdf-view-goto-page (pdf-cache-number-of-pages))) + +(defun pdf-view-scroll-up-or-next-page (&optional arg) + "Scroll page up ARG lines if possible, else go to the next page. + +When `pdf-view-continuous' is non-nil, scrolling upward at the +bottom edge of the page moves to the next page. Otherwise, go to +next page only on typing SPC (ARG is nil)." + (interactive "P") + (if (or pdf-view-continuous (null arg)) + (let ((hscroll (window-hscroll)) + (cur-page (pdf-view-current-page)) + (win-scroll (window-vscroll nil pdf-view-have-image-mode-pixel-vscroll)) + (img-scroll (image-scroll-up arg))) + (when (or + ;; There is no next line for the image to scroll to + (and img-scroll (= win-scroll img-scroll)) + ;; Workaround rounding/off-by-one issues. + (memq pdf-view-display-size + '(fit-height fit-page))) + (pdf-view-next-page) + (when (/= cur-page (pdf-view-current-page)) + (image-bob) + (image-bol 1)) + (image-set-window-hscroll hscroll))) + (image-scroll-up arg))) + +(defun pdf-view-scroll-down-or-previous-page (&optional arg) + "Scroll page down ARG lines if possible, else go to the previous page. + +When `pdf-view-continuous' is non-nil, scrolling downward at the +top edge of the page moves to the previous page. Otherwise, go +to previous page only on typing DEL (ARG is nil)." + (interactive "P") + (if (or pdf-view-continuous (null arg)) + (let ((hscroll (window-hscroll)) + (cur-page (pdf-view-current-page)) + (win-scroll (window-vscroll nil pdf-view-have-image-mode-pixel-vscroll)) + (img-scroll (image-scroll-down arg))) + (when (or + ;; There is no previous line for the image to scroll to + (and img-scroll (= win-scroll img-scroll)) + ;; Workaround rounding/off-by-one issues. + (memq pdf-view-display-size + '(fit-height fit-page))) + (pdf-view-previous-page) + (when (/= cur-page (pdf-view-current-page)) + (image-eob) + (image-bol 1)) + (image-set-window-hscroll hscroll))) + (image-scroll-down arg))) + +(defun pdf-view-next-line-or-next-page (&optional arg) + "Scroll upward by ARG lines if possible, else go to the next page. + +When `pdf-view-continuous' is non-nil, scrolling a line upward +at the bottom edge of the page moves to the next page." + (interactive "p") + (if pdf-view-continuous + (let ((hscroll (window-hscroll)) + (cur-page (pdf-view-current-page))) + (when (= (window-vscroll nil pdf-view-have-image-mode-pixel-vscroll) + (image-next-line arg)) + (pdf-view-next-page) + (when (/= cur-page (pdf-view-current-page)) + (image-bob) + (image-bol 1)) + (image-set-window-hscroll hscroll))) + (image-next-line 1))) + +(defun pdf-view-previous-line-or-previous-page (&optional arg) + "Scroll downward by ARG lines if possible, else go to the previous page. + +When `pdf-view-continuous' is non-nil, scrolling a line downward +at the top edge of the page moves to the previous page." + (interactive "p") + (if pdf-view-continuous + (let ((hscroll (window-hscroll)) + (cur-page (pdf-view-current-page))) + (when (= (window-vscroll nil pdf-view-have-image-mode-pixel-vscroll) + (image-previous-line arg)) + (pdf-view-previous-page) + (when (/= cur-page (pdf-view-current-page)) + (image-eob) + (image-bol 1)) + (image-set-window-hscroll hscroll))) + (image-previous-line arg))) + +(defun pdf-view-goto-label (label) + "Go to the page corresponding to LABEL. + +Usually, the label of a document's page is the same as its +displayed page number." + (interactive + (list (let ((labels (pdf-info-pagelabels))) + (completing-read "Goto label: " labels nil t)))) + (let ((index (cl-position label (pdf-info-pagelabels) :test 'equal))) + (unless index + (error "No such label: %s" label)) + (pdf-view-goto-page (1+ index)))) + +(defun pdf-view-center-in-window () + "Center PDF in window horizontally." + (interactive) + (image-set-window-hscroll + (/ (* (- (car (pdf-view-image-size)) + (window-pixel-width)) + (window-width)) + 2 (window-pixel-width))) ; convert from pixel to character width + (pdf-view-redisplay t)) + +(defun pdf-view-align-left () + "Align left edge of pdf with left edge of window." + (interactive) + (image-set-window-hscroll 0) + (pdf-view-redisplay t)) + +(defun pdf-view-align-right () + "Align right edge of pdf with right edge of window." + (interactive) + (image-set-window-hscroll + (/ (* (- (car (pdf-view-image-size)) + (window-pixel-width)) + (window-width)) + (window-pixel-width))) ; convert from pixel to character width + (pdf-view-redisplay t)) + + +;; * ================================================================== * +;; * Slicing +;; * ================================================================== * + +(defun pdf-view-set-slice (x y width height &optional window) + "Set the slice of the pages that should be displayed in WINDOW. + +WINDOW defaults to `selected-window' if not provided. +X, Y, WIDTH and HEIGHT should be relative coordinates, i.e. in +\[0;1\]. To reset the slice use `pdf-view-reset-slice'." + (unless (equal (pdf-view-current-slice window) + (list x y width height)) + (setf (pdf-view-current-slice window) + (mapcar (lambda (v) + (max 0 (min 1 v))) + (list x y width height))) + (pdf-view-redisplay window))) + +(defun pdf-view-set-slice-using-mouse () + "Set the slice of the images that should be displayed. + +Set the slice by pressing `mouse-1' at its top-left corner and +dragging it to its bottom-right corner. See also +`pdf-view-set-slice' and `pdf-view-reset-slice'." + (interactive) + (let ((size (pdf-view-image-size)) + x y w h done) + (while (not done) + (let ((e (read-event + (concat "Press mouse-1 at the top-left corner and " + "drag it to the bottom-right corner!")))) + (when (eq (car e) 'drag-mouse-1) + (setq x (car (posn-object-x-y (event-start e)))) + (setq y (cdr (posn-object-x-y (event-start e)))) + (setq w (- (car (posn-object-x-y (event-end e))) x)) + (setq h (- (cdr (posn-object-x-y (event-end e))) y)) + (setq done t)))) + (apply 'pdf-view-set-slice + (pdf-util-scale + (list x y w h) + (cons (/ 1.0 (float (car size))) + (/ 1.0 (float (cdr size)))))))) + +(defun pdf-view-set-slice-from-bounding-box (&optional window) + "Set the slice from the page's bounding-box. + +WINDOW defaults to `selected-window' if not provided. + +The result is that the margins are almost completely cropped, +much more accurate than could be done manually using +`pdf-view-set-slice-using-mouse'. + +See also `pdf-view-bounding-box-margin'." + (interactive) + (let* ((bb (pdf-cache-boundingbox (pdf-view-current-page window))) + (margin (max 0 (or pdf-view-bounding-box-margin 0))) + (slice (list (- (nth 0 bb) + (/ margin 2.0)) + (- (nth 1 bb) + (/ margin 2.0)) + (+ (- (nth 2 bb) (nth 0 bb)) + margin) + (+ (- (nth 3 bb) (nth 1 bb)) + margin)))) + (apply 'pdf-view-set-slice + (append slice (and window (list window)))))) + +(defun pdf-view-reset-slice (&optional window) + "Reset the current slice and redisplay WINDOW. + +WINDOW defaults to `selected-window' if not provided. + +After calling this function the whole page will be visible +again." + (interactive) + (when (pdf-view-current-slice window) + (setf (pdf-view-current-slice window) nil) + (pdf-view-redisplay window)) + nil) + +(define-minor-mode pdf-view-auto-slice-minor-mode + "Automatically slice pages according to their bounding boxes. + +See also `pdf-view-set-slice-from-bounding-box'." + :group 'pdf-view + (pdf-util-assert-pdf-buffer) + (cond + (pdf-view-auto-slice-minor-mode + (dolist (win (get-buffer-window-list nil nil t)) + (when (pdf-util-pdf-window-p win) + (pdf-view-set-slice-from-bounding-box win))) + (add-hook 'pdf-view-change-page-hook + 'pdf-view-set-slice-from-bounding-box nil t)) + (t + (progn (remove-hook 'pdf-view-change-page-hook + 'pdf-view-set-slice-from-bounding-box t) + (pdf-view-reset-slice))))) + + +;; * ================================================================== * +;; * Display +;; * ================================================================== * + +(defun pdf-view-image-type () + "Return the image type that should be used. + +The return value is either `imagemagick' (if available and wanted +or if png is not available) or `png'. + +Signal an error, if neither `imagemagick' nor `png' is available. + +See also `pdf-view-use-imagemagick'." + (cond ((and pdf-view-use-imagemagick + (fboundp 'imagemagick-types)) + 'imagemagick) + ((image-type-available-p 'image-io) + 'image-io) + ((image-type-available-p 'png) + 'png) + ((fboundp 'imagemagick-types) + 'imagemagick) + (t + (error "PNG image supported not compiled into Emacs")))) + +(defmacro pdf-view-create-image (data &rest props) + ;; TODO: add DATA and PROPS to docstring. + "Like `create-image', but with set DATA-P and TYPE arguments." + (declare (indent 1) (debug t)) + (let ((image-data (make-symbol "data"))) + `(let ((,image-data ,data)) + (apply #'create-image ,image-data (pdf-view-image-type) t ,@props + (cl-list* + :relief (or pdf-view-image-relief 0) + (when (and (eq (framep-on-display) 'mac) + (= (pdf-util-frame-scale-factor) 2)) + (list :data-2x ,image-data))))))) + +(defun pdf-view-create-page (page &optional window) + "Create an image of PAGE for display on WINDOW." + (let* ((size (pdf-view-desired-image-size page window)) + (data (pdf-cache-renderpage + page (car size) + (if pdf-view-use-scaling + (* 2 (car size)) + (car size)))) + (hotspots (pdf-view-apply-hotspot-functions + window page size))) + (pdf-view-create-image data + :width (car size) + :rotation (or pdf-view--current-rotation 0) + :map hotspots + :pointer 'arrow))) + +(defun pdf-view-image-size (&optional displayed-p window) + ;; TODO: add WINDOW to docstring. + "Return the size in pixel of the current image. + +If DISPLAYED-P is non-nil, return the size of the displayed +image. These values may be different, if slicing is used." + (if displayed-p + (with-selected-window (or window (selected-window)) + (image-display-size + (image-get-display-property) t)) + (image-size (pdf-view-current-image window) t))) + +(defun pdf-view-image-offset (&optional window) + ;; TODO: add WINDOW to docstring. + "Return the offset of the current image. + +It is equal to \(LEFT . TOP\) of the current slice in pixel." + (let* ((slice (pdf-view-current-slice window))) + (cond + (slice + (pdf-util-scale-relative-to-pixel + (cons (nth 0 slice) (nth 1 slice)) + window)) + (t + (cons 0 0))))) + +(defun pdf-view-display-page (page &optional window) + "Display page PAGE in WINDOW." + (setf (pdf-view-window-needs-redisplay window) nil) + (pdf-view-display-image + (pdf-view-create-page page window) + window)) + +(defun pdf-view-display-image (image &optional window inhibit-slice-p) + ;; TODO: write documentation! + (let ((ol (pdf-view-current-overlay window))) + (when (window-live-p (overlay-get ol 'window)) + (let* ((size (image-size image t)) + (slice (if (not inhibit-slice-p) + (pdf-view-current-slice window))) + (displayed-width (floor + (if slice + (* (nth 2 slice) + (car (image-size image))) + (car (image-size image)))))) + (setf (pdf-view-current-image window) image) + (move-overlay ol (point-min) (point-max)) + ;; In case the window is wider than the image, center the image + ;; horizontally. + (overlay-put ol 'before-string + (when (> (window-width window) + displayed-width) + (propertize " " 'display + `(space :align-to + ,(/ (- (window-width window) + displayed-width) 2))))) + (overlay-put ol 'display + (if slice + (list (cons 'slice + (pdf-util-scale slice size 'round)) + image) + image)) + (let* ((win (overlay-get ol 'window)) + (hscroll (image-mode-window-get 'hscroll win)) + (vscroll (image-mode-window-get 'vscroll win))) + ;; Reset scroll settings, in case they were changed. + (if hscroll (set-window-hscroll win hscroll)) + (if vscroll (set-window-vscroll + win vscroll pdf-view-have-image-mode-pixel-vscroll))))))) + +(defun pdf-view-redisplay (&optional window) + "Redisplay page in WINDOW. + +If WINDOW is t, redisplay pages in all windows." + (unless pdf-view-inhibit-redisplay + (if (not (eq t window)) + (pdf-view-display-page + (pdf-view-current-page window) + window) + (dolist (win (get-buffer-window-list nil nil t)) + (pdf-view-display-page + (pdf-view-current-page win) + win)) + (when (consp image-mode-winprops-alist) + (dolist (window (mapcar #'car image-mode-winprops-alist)) + (unless (or (not (window-live-p window)) + (eq (current-buffer) + (window-buffer window))) + (setf (pdf-view-window-needs-redisplay window) t))))) + (force-mode-line-update))) + +(defun pdf-view-redisplay-pages (&rest pages) + "Redisplay PAGES in all windows." + (pdf-util-assert-pdf-buffer) + (dolist (window (get-buffer-window-list nil nil t)) + (when (memq (pdf-view-current-page window) + pages) + (pdf-view-redisplay window)))) + +(defun pdf-view-maybe-redisplay-resized-windows () + "Redisplay some windows needing redisplay." + (unless (or (numberp pdf-view-display-size) + (pdf-view-active-region-p) + (> (minibuffer-depth) 0)) + (dolist (window (get-buffer-window-list nil nil t)) + (let ((stored (pdf-view-current-window-size window)) + (size (cons (window-width window) + (window-height window)))) + (unless (equal size stored) + (setf (pdf-view-current-window-size window) size) + (unless (or (null stored) + (and (eq pdf-view-display-size 'fit-width) + (eq (car size) (car stored))) + (and (eq pdf-view-display-size 'fit-height) + (eq (cdr size) (cdr stored)))) + (pdf-view-redisplay window))))))) + +(defun pdf-view-redisplay-some-windows () + (pdf-view-maybe-redisplay-resized-windows) + (dolist (window (get-buffer-window-list nil nil t)) + (when (pdf-view-window-needs-redisplay window) + (pdf-view-redisplay window)))) + +(defun pdf-view-new-window-function (winprops) + ;; TODO: write documentation! + ;; (message "New window %s for buf %s" (car winprops) (current-buffer)) + (cl-assert (or (eq t (car winprops)) + (eq (window-buffer (car winprops)) (current-buffer)))) + (let ((ol (image-mode-window-get 'overlay winprops))) + (if ol + (progn + (setq ol (copy-overlay ol)) + ;; `ol' might actually be dead. + (move-overlay ol (point-min) (point-max))) + (setq ol (make-overlay (point-min) (point-max) nil t)) + (overlay-put ol 'pdf-view t)) + (overlay-put ol 'window (car winprops)) + (unless (windowp (car winprops)) + ;; It's a pseudo entry. Let's make sure it's not displayed (the + ;; `window' property is only effective if its value is a window). + (cl-assert (eq t (car winprops))) + (delete-overlay ol)) + (image-mode-window-put 'overlay ol winprops) + ;; Clean up some overlays. + (dolist (ov (overlays-in (point-min) (point-max))) + (when (and (windowp (overlay-get ov 'window)) + (not (window-live-p (overlay-get ov 'window)))) + (delete-overlay ov))) + (when (and (windowp (car winprops)) + (null (image-mode-window-get 'image winprops))) + ;; We're not displaying an image yet, so let's do so. This + ;; happens when the buffer is displayed for the first time. + (with-selected-window (car winprops) + (pdf-view-goto-page + (or (image-mode-window-get 'page t) 1)))))) + +(defun pdf-view-desired-image-size (&optional page window) + ;; TODO: write documentation! + (let* ((pagesize (pdf-cache-pagesize + (or page (pdf-view-current-page window)))) + (slice (pdf-view-current-slice window)) + (width-scale (/ (/ (float (window-body-width window t)) + (or (nth 2 slice) 1.0)) + (float (car pagesize)))) + (height (- (nth 3 (window-inside-pixel-edges window)) + (nth 1 (window-inside-pixel-edges window)) + 1)) + (height-scale (/ (/ (float height) + (or (nth 3 slice) 1.0)) + (float (cdr pagesize)))) + (scale width-scale)) + (if (numberp pdf-view-display-size) + (setq scale (float pdf-view-display-size)) + (cl-case pdf-view-display-size + (fit-page + (setq scale (min height-scale width-scale))) + (fit-height + (setq scale height-scale)) + (t + (setq scale width-scale)))) + (let ((width (floor (* (car pagesize) scale))) + (height (floor (* (cdr pagesize) scale)))) + (when (> width (max 1 (or pdf-view-max-image-width width))) + (setq width pdf-view-max-image-width + height (* height (/ (float pdf-view-max-image-width) width)))) + (cons (max 1 width) (max 1 height))))) + +(defun pdf-view-text-regions-hotspots-function (page size) + "Return a list of hotspots for text regions on PAGE using SIZE. + +This will display a text cursor, when hovering over them." + (local-set-key [pdf-view-text-region t] + 'pdf-util-image-map-mouse-event-proxy) + (mapcar (lambda (region) + (let ((e (pdf-util-scale region size 'round))) + `((rect . ((,(nth 0 e) . ,(nth 1 e)) + . (,(nth 2 e) . ,(nth 3 e)))) + pdf-view-text-region + (pointer text)))) + (pdf-cache-textregions page))) + +(define-minor-mode pdf-view-dark-minor-mode + "Mode for PDF documents with dark background. + +This tells the various modes to use their face's dark colors." + :group 'pdf-view + (pdf-util-assert-pdf-buffer) + ;; FIXME: This should really be run in a hook. + (when (bound-and-true-p pdf-isearch-active-mode) + (with-no-warnings + (pdf-isearch-redisplay) + (pdf-isearch-message + (if pdf-view-dark-minor-mode "dark mode" "light mode"))))) + +(define-minor-mode pdf-view-printer-minor-mode + "Display the PDF as it would be printed." + :group 'pdf-view + :lighter " Prn" + (pdf-util-assert-pdf-buffer) + (let ((enable (lambda () + (pdf-info-setoptions :render/printed t)))) + (cond + (pdf-view-printer-minor-mode + (add-hook 'after-save-hook enable nil t) + (add-hook 'after-revert-hook enable nil t)) + (t + (remove-hook 'after-save-hook enable t) + (remove-hook 'after-revert-hook enable t)))) + (pdf-info-setoptions :render/printed pdf-view-printer-minor-mode) + (pdf-cache-clear-images) + (pdf-view-redisplay t)) + +(define-minor-mode pdf-view-midnight-minor-mode + "Apply a color-filter appropriate for past midnight reading. + +The colors are determined by the variable +`pdf-view-midnight-colors', which see. " + :group 'pdf-view + :lighter " Mid" + (pdf-util-assert-pdf-buffer) + ;; FIXME: Maybe these options should be passed stateless to pdf-info-renderpage ? + (let ((enable (lambda () + (pdf-info-setoptions + :render/foreground (or (car pdf-view-midnight-colors) "black") + :render/background (or (cdr pdf-view-midnight-colors) "white") + :render/usecolors + (if pdf-view-midnight-invert + ;; If midnight invert is enabled, pass "2" indicating + ;; that :render/foreground and :render/background should + ;; be ignored and to instead invert the PDF (preserving + ;; hue) + 2 + ;; If invert is not enabled, pass "1" indictating that + ;; :render/foreground and :render/background should be used + 1))))) + (cond + (pdf-view-midnight-minor-mode + (add-hook 'after-save-hook enable nil t) + (add-hook 'after-revert-hook enable nil t) + (funcall enable)) + (t + (remove-hook 'after-save-hook enable t) + (remove-hook 'after-revert-hook enable t) + (pdf-info-setoptions + ;; Value "0" indicates that colors should remain unchanged + :render/usecolors 0)))) + (pdf-cache-clear-images) + (pdf-view-redisplay t)) + +(defun pdf-view-set-theme-background () + "Set the buffer's color filter to correspond to the current Emacs theme." + (pdf-util-assert-pdf-buffer) + (pdf-info-setoptions + :render/foreground (face-foreground 'default nil) + :render/background (face-background 'default nil) + :render/usecolors 1)) + +(defun pdf-view-refresh-themed-buffer (&optional get-theme) + "Refresh the current buffer to activate applied colors. + +When GET-THEME is non-nil, also reset the applied colors to the +current theme's colors." + (pdf-util-assert-pdf-buffer) + (pdf-cache-clear-images) + (when get-theme + (pdf-view-set-theme-background)) + (pdf-view-redisplay t)) + +(define-minor-mode pdf-view-themed-minor-mode + "Synchronize color filter with the present Emacs theme. + +The colors are determined by the `face-foreground' and +`face-background' of the currently active theme." + :group 'pdf-view + :lighter " Thm" + (pdf-util-assert-pdf-buffer) + (cond + (pdf-view-themed-minor-mode + (add-hook 'after-save-hook #'pdf-view-set-theme-background nil t) + (add-hook 'after-revert-hook #'pdf-view-set-theme-background nil t)) + (t + (remove-hook 'after-save-hook #'pdf-view-set-theme-background t) + (remove-hook 'after-revert-hook #'pdf-view-set-theme-background t) + (pdf-info-setoptions :render/usecolors 0))) + (pdf-view-refresh-themed-buffer pdf-view-themed-minor-mode)) + +(when pdf-view-use-unicode-ligther + ;; This check uses an implementation detail, which hopefully gets the + ;; right answer. + (and (fontp (char-displayable-p ?⎙)) + (setcdr (assq 'pdf-view-printer-minor-mode minor-mode-alist) + (list " ⎙" ))) + (and (fontp (char-displayable-p ?🌙)) + (setcdr (assq 'pdf-view-midnight-minor-mode minor-mode-alist) + (list " 🌙" )))) + + +;; * ================================================================== * +;; * Hotspot handling +;; * ================================================================== * + +(defun pdf-view-add-hotspot-function (fn &optional layer) + "Register FN as a hotspot function in the current buffer, using LAYER. + +FN will be called in the PDF buffer with the page-number and the +image size \(WIDTH . HEIGHT\) as arguments. It should return a +list of hotspots applicable to the the :map image-property. + +LAYER determines the order: Functions in a higher LAYER will +supersede hotspots in lower ones." + (push (cons (or layer 0) fn) + pdf-view--hotspot-functions)) + +(defun pdf-view-remove-hotspot-function (fn) + "Unregister FN as a hotspot function in the current buffer." + (setq pdf-view--hotspot-functions + (cl-remove fn pdf-view--hotspot-functions + :key 'cdr))) + +(defun pdf-view-sorted-hotspot-functions () + ;; TODO: write documentation! + (mapcar 'cdr (cl-sort (copy-sequence pdf-view--hotspot-functions) + '> :key 'car))) + +(defun pdf-view-apply-hotspot-functions (window page image-size) + ;; TODO: write documentation! + (unless pdf-view-inhibit-hotspots + (save-selected-window + (when window (select-window window 'norecord)) + (apply 'nconc + (mapcar (lambda (fn) + (funcall fn page image-size)) + (pdf-view-sorted-hotspot-functions)))))) + + +;; * ================================================================== * +;; * Region +;; * ================================================================== * + +(defun pdf-view--push-mark () + ;; TODO: write documentation! + (let (mark-ring) + (push-mark-command nil)) + (setq deactivate-mark nil)) + +(defun pdf-view-active-region (&optional deactivate-p) + "Return the active region, a list of edges. + +Deactivate the region if DEACTIVATE-P is non-nil." + (pdf-view-assert-active-region) + (prog1 + pdf-view-active-region + (when deactivate-p + (pdf-view-deactivate-region)))) + +(defun pdf-view-deactivate-region () + "Deactivate the region." + (interactive) + (when pdf-view-active-region + (setq pdf-view-active-region nil) + (deactivate-mark) + (pdf-view-redisplay t))) + +(defun pdf-view-mouse-set-region (event &optional allow-extend-p + rectangle-p + selection-style) + "Select a region of text using the mouse with mouse event EVENT. + +Allow for stacking of regions, if ALLOW-EXTEND-P is non-nil. + +Create a rectangular region, if RECTANGLE-P is non-nil. + +Overwrite `pdf-view-selection-style' with SELECTION-STYLE, +which is one of `glyph', `word', or `line'. + +Stores the region in `pdf-view-active-region'." + (interactive "@e") + (setq pdf-view--have-rectangle-region rectangle-p) + (unless (and (eventp event) + (mouse-event-p event)) + (signal 'wrong-type-argument (list 'mouse-event-p event))) + (unless (and allow-extend-p + (or (null (get this-command 'pdf-view-region-window)) + (equal (get this-command 'pdf-view-region-window) + (selected-window)))) + (pdf-view-deactivate-region)) + (put this-command 'pdf-view-region-window + (selected-window)) + (let* ((window (selected-window)) + (pos (event-start event)) + (begin-inside-image-p t) + (begin (if (posn-image pos) + (posn-object-x-y pos) + (setq begin-inside-image-p nil) + (posn-x-y pos))) + (abs-begin (posn-x-y pos)) + (selection-style (or selection-style pdf-view-selection-style)) + pdf-view-continuous + region) + (when (pdf-util-track-mouse-dragging (event 0.05) + (let* ((pos (event-start event)) + (end (posn-object-x-y pos)) + (end-inside-image-p + (and (eq window (posn-window pos)) + (posn-image pos)))) + (when (or end-inside-image-p + begin-inside-image-p) + (cond + ((and end-inside-image-p + (not begin-inside-image-p)) + ;; Started selection outside the image, setup begin. + (let* ((xy (posn-x-y pos)) + (dxy (cons (- (car xy) (car begin)) + (- (cdr xy) (cdr begin)))) + (size (pdf-view-image-size t))) + (setq begin (cons (max 0 (min (car size) + (- (car end) (car dxy)))) + (max 0 (min (cdr size) + (- (cdr end) (cdr dxy))))) + ;; Store absolute position for later. + abs-begin (cons (- (car xy) + (- (car end) + (car begin))) + (- (cdr xy) + (- (cdr end) + (cdr begin)))) + begin-inside-image-p t))) + ((and begin-inside-image-p + (not end-inside-image-p)) + ;; Moved outside the image, setup end. + (let* ((xy (posn-x-y pos)) + (dxy (cons (- (car xy) (car abs-begin)) + (- (cdr xy) (cdr abs-begin)))) + (size (pdf-view-image-size t))) + (setq end (cons (max 0 (min (car size) + (+ (car begin) (car dxy)))) + (max 0 (min (cdr size) + (+ (cdr begin) (cdr dxy))))))))) + (let ((iregion (if rectangle-p + (list (min (car begin) (car end)) + (min (cdr begin) (cdr end)) + (max (car begin) (car end)) + (max (cdr begin) (cdr end))) + (list (car begin) (cdr begin) + (car end) (cdr end))))) + (setq region + (pdf-util-scale-pixel-to-relative iregion)) + (pdf-view-display-region + (cons region pdf-view-active-region) + rectangle-p + selection-style) + (pdf-util-scroll-to-edges iregion))))) + (setq pdf-view-active-region + (append pdf-view-active-region + (list region))) + (pdf-view--push-mark)))) + +(defun pdf-view-mouse-extend-region (event) + "Extend the currently active region with mouse event EVENT." + (interactive "@e") + (pdf-view-mouse-set-region + event t pdf-view--have-rectangle-region)) + +(defun pdf-view-mouse-set-region-rectangle (event) + "Like `pdf-view-mouse-set-region' but displays as a rectangle. + +EVENT is the mouse event. + +This is more useful for commands like +`pdf-view-extract-region-image'." + (interactive "@e") + (pdf-view-mouse-set-region event nil t)) + +(defun pdf-view-display-region (&optional region rectangle-p selection-style) + ;; TODO: write documentation! + (unless region + (pdf-view-assert-active-region) + (setq region pdf-view-active-region)) + (let ((colors (pdf-util-face-colors + (if rectangle-p 'pdf-view-rectangle 'pdf-view-region) + (bound-and-true-p pdf-view-dark-minor-mode))) + (page (pdf-view-current-page)) + (width (car (pdf-view-image-size)))) + (pdf-view-display-image + (pdf-view-create-image + (if rectangle-p + (pdf-info-renderpage-highlight + page width nil + `(,(car colors) ,(cdr colors) 0.35 ,@region)) + (pdf-info-renderpage-text-regions + page width nil selection-style nil + `(,(car colors) ,(cdr colors) ,@region))) + :width width)))) + +(defun pdf-view-kill-ring-save () + "Copy the region to the `kill-ring'." + (interactive) + (pdf-view-assert-active-region) + (let* ((txt (pdf-view-active-region-text))) + (pdf-view-deactivate-region) + (kill-new (mapconcat 'identity txt "\n")))) + +(defun pdf-view-mark-whole-page () + "Mark the whole page." + (interactive) + (pdf-view-deactivate-region) + (setq pdf-view-active-region + (list (list 0 0 1 1))) + (pdf-view--push-mark) + (pdf-view-display-region)) + +(defun pdf-view-active-region-text () + "Return the text of the active region as a list of strings." + (pdf-view-assert-active-region) + (mapcar + (lambda (edges) + (pdf-info-gettext + (pdf-view-current-page) + edges + pdf-view-selection-style)) + pdf-view-active-region)) + +(defun pdf-view-extract-region-image (regions &optional page size + output-buffer no-display-p) + ;; TODO: what is "resp."? Avoid contractions. + "Create a PNG image of REGIONS. + +REGIONS should have the same form as `pdf-view-active-region', +which see. PAGE and SIZE are the page resp. base-size of the +image from which the image-regions will be created; they default +to `pdf-view-current-page' resp. `pdf-view-image-size'. + +Put the image in OUTPUT-BUFFER, defaulting to \"*PDF region +image*\" and display it, unless NO-DISPLAY-P is non-nil. + +In case of multiple regions, the resulting image is constructed +by joining them horizontally. For this operation (and this only) +the `convert' program is used." + + (interactive + (list (if (pdf-view-active-region-p) + (pdf-view-active-region t) + '((0 0 1 1))))) + (unless page + (setq page (pdf-view-current-page))) + (unless size + (setq size (pdf-view-image-size))) + (unless output-buffer + (setq output-buffer (get-buffer-create "*PDF image*"))) + (let* ((images (mapcar (lambda (edges) + (let ((file (make-temp-file "pdf-view")) + (coding-system-for-write 'binary)) + (write-region + (pdf-info-renderpage + page (car size) + :crop-to edges) + nil file nil 'no-message) + file)) + regions)) + result) + (unwind-protect + (progn + (if (= (length images) 1) + (setq result (car images)) + (setq result (make-temp-file "pdf-view")) + ;; Join the images horizontally with a gap of 10 pixel. + (pdf-util-convert + "-noop" ;; workaround limitations of this function + result + :commands `("(" + ,@images + "-background" "white" + "-splice" "0x10+0+0" + ")" + "-gravity" "Center" + "-append" + "+gravity" + "-chop" "0x10+0+0") + :apply '((0 0 0 0)))) + (with-current-buffer output-buffer + (let ((inhibit-read-only t)) + (erase-buffer)) + (set-buffer-multibyte nil) + (insert-file-contents-literally result) + (image-mode) + (unless no-display-p + (pop-to-buffer (current-buffer))))) + (dolist (f (cons result images)) + (when (file-exists-p f) + (delete-file f)))))) + +;; * ================================================================== * +;; * Bookmark + Register Integration +;; * ================================================================== * + +(defun pdf-view-bookmark-make-record (&optional no-page no-slice no-size no-origin) + ;; TODO: add NO-PAGE, NO-SLICE, NO-SIZE, NO-ORIGIN to the docstring. + "Create a bookmark PDF record. + +The optional, boolean args exclude certain attributes." + (let ((displayed-p (eq (current-buffer) + (window-buffer)))) + (cons (buffer-name) + (append (bookmark-make-record-default nil t 1) + `(,(unless no-page + (cons 'page (pdf-view-current-page))) + ,(unless no-slice + (cons 'slice (and displayed-p + (pdf-view-current-slice)))) + ,(unless no-size + (cons 'size pdf-view-display-size)) + ,(unless no-origin + (cons 'origin + (and displayed-p + (let ((edges (pdf-util-image-displayed-edges nil t))) + (pdf-util-scale-pixel-to-relative + (cons (car edges) (cadr edges)) nil t))))) + (handler . pdf-view-bookmark-jump-handler)))))) + +;;;###autoload +(defun pdf-view-bookmark-jump-handler (bmk) + "The bookmark handler-function interface for bookmark BMK. + +See also `pdf-view-bookmark-make-record'." + (let ((page (bookmark-prop-get bmk 'page)) + (slice (bookmark-prop-get bmk 'slice)) + (size (bookmark-prop-get bmk 'size)) + (origin (bookmark-prop-get bmk 'origin)) + (file (bookmark-prop-get bmk 'filename)) + (show-fn-sym (make-symbol "pdf-view-bookmark-after-jump-hook"))) + (fset show-fn-sym + (lambda () + (remove-hook 'bookmark-after-jump-hook show-fn-sym) + (unless (derived-mode-p 'pdf-view-mode) + (pdf-view-mode)) + (with-selected-window + (or (get-buffer-window (current-buffer) 0) + (selected-window)) + (when size + (setq-local pdf-view-display-size size)) + (when slice + (apply 'pdf-view-set-slice slice)) + (when (numberp page) + (pdf-view-goto-page page)) + (when origin + (let ((size (pdf-view-image-size t))) + (image-set-window-hscroll + (round (/ (* (car origin) (car size)) + (frame-char-width)))) + (image-set-window-vscroll + (round (/ (* (cdr origin) (cdr size)) + (if pdf-view-have-image-mode-pixel-vscroll + 1 + (frame-char-height)))))))))) + (add-hook 'bookmark-after-jump-hook show-fn-sym) + (set-buffer (or (find-buffer-visiting file) + (find-file-noselect file))))) + +(defun pdf-view-bookmark-jump (bmk) + "Switch to bookmark BMK. + +This function is like `bookmark-jump', but it always uses the +selected window for display and does not run any hooks. Also, it +works only with bookmarks created by +`pdf-view-bookmark-make-record'." + + (let* ((file (bookmark-prop-get bmk 'filename)) + (buffer (or (find-buffer-visiting file) + (find-file-noselect file)))) + (switch-to-buffer buffer) + (let (bookmark-after-jump-hook) + (pdf-view-bookmark-jump-handler bmk) + (run-hooks 'bookmark-after-jump-hook)))) + +(defun pdf-view-registerv-make () + "Create a PDF register entry of the current position." + (registerv-make + (pdf-view-bookmark-make-record nil t t) + :print-func 'pdf-view-registerv-print-func + :jump-func 'pdf-view-bookmark-jump + :insert-func (lambda (bmk) + (insert (format "%S" bmk))))) + +(defun pdf-view-registerv-print-func (bmk) + "Print a textual representation of bookmark BMK. + +This function is used as the `:print-func' property with +`registerv-make'." + (let* ((file (bookmark-prop-get bmk 'filename)) + (buffer (find-buffer-visiting file)) + (page (bookmark-prop-get bmk 'page)) + (origin (bookmark-prop-get bmk 'origin))) + (princ (format "PDF position: %s, page %d, %d%%" + (if buffer + (buffer-name buffer) + file) + (or page 1) + (if origin + (round (* 100 (cdr origin))) + 0))))) + +(defmacro pdf-view-with-register-alist (&rest body) + "Setup the proper binding for `register-alist' in BODY. + +This macro may not work as desired when it is nested. See also +`pdf-view-use-dedicated-register'." + (declare (debug t) (indent 0)) + (let ((dedicated-p (make-symbol "dedicated-p"))) + `(let* ((,dedicated-p pdf-view-use-dedicated-register) + (register-alist + (if ,dedicated-p + pdf-view-register-alist + register-alist))) + (unwind-protect + (progn ,@body) + (when ,dedicated-p + (setq pdf-view-register-alist register-alist)))))) + +(defun pdf-view-position-to-register (register) + "Store current PDF position in register REGISTER. + +See also `point-to-register'." + (interactive + (list (pdf-view-with-register-alist + (register-read-with-preview "Position to register: ")))) + (pdf-view-with-register-alist + (set-register register (pdf-view-registerv-make)))) + +(defun pdf-view-jump-to-register (register &optional delete return-register) + ;; TODO: add RETURN-REGISTER to the docstring. + "Move point to a position stored in a REGISTER. + +Optional parameter DELETE is defined as in `jump-to-register'." + (interactive + (pdf-view-with-register-alist + (list + (register-read-with-preview "Jump to register: ") + current-prefix-arg + (and (or pdf-view-use-dedicated-register + (local-variable-p 'register-alist)) + (characterp last-command-event) + last-command-event)))) + (pdf-view-with-register-alist + (let ((return-pos (and return-register + (pdf-view-registerv-make)))) + (jump-to-register register delete) + (when return-register + (set-register return-register return-pos))))) + +(provide 'pdf-view) + +;;; pdf-view.el ends here diff --git a/org/elpa/pdf-tools-20230404.327/pdf-virtual.el b/org/elpa/pdf-tools-20230404.327/pdf-virtual.el new file mode 100644 index 0000000..f8ecf97 --- /dev/null +++ b/org/elpa/pdf-tools-20230404.327/pdf-virtual.el @@ -0,0 +1,1033 @@ +;;; pdf-virtual.el --- Virtual PDF documents -*- lexical-binding: t; -*- + +;; Copyright (C) 2015 Andreas Politz + +;; Author: Andreas Politz +;; Keywords: multimedia, files + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; A virtual PDF is a collection of pages, or parts thereof, of +;; arbitrary documents in one particular order. This library acts as +;; an intermediate between pdf-info.el and all other packages, in +;; order to transparently make this collection appear as one single +;; document. +;; +;; The trickiest part is to make these intermediate functions behave +;; like the pdf-info-* equivalents in both the synchronous and +;; asynchronous case. + +;;; Code: +(require 'let-alist) +(require 'pdf-info) +(require 'pdf-util) + +(declare-function pdf-view-mode "pdf-view.el") + +;; * ================================================================== * +;; * Variables +;; * ================================================================== * + +(defconst pdf-virtual-magic-mode-regexp "^ *;+ *%VPDF\\_>" + "A regexp matching the first line in a vpdf file.") + +(defvar-local pdf-virtual-document nil + "A list representing the virtual document.") + +(put 'pdf-virtual-document 'permanent-local t) + +(defvar pdf-virtual-adapter-alist nil + "Alist of server functions. + +Each element looks like \(PDF-VIRTUAL-FN . PDF-INFO-FN\). This +list is filled by the macro `pdf-virtual-define-adapter' and used +to enable/disable the corresponding advices.") + + +;; * ================================================================== * +;; * VPDF datastructure +;; * ================================================================== * + +(defun pdf-virtual-pagespec-normalize (page-spec &optional filename) + "Normalize PAGE-SPEC using FILENAME. + +PAGE-SPEC should be as described in +`pdf-virtual-document-create'. FILENAME is used to determine the +last page number, if needed. The `current-buffer', if it is nil. + +Returns a list \(\(FIRST . LAST\) . REGION\)\)." + + (let ((page-spec (cond + ((natnump page-spec) + (list (cons page-spec page-spec))) + ((null (car page-spec)) + (let ((npages (pdf-info-number-of-pages filename))) + (cons (cons 1 npages) + (cdr page-spec)))) + ((natnump (car page-spec)) + (cond + ((natnump (cdr page-spec)) + (list page-spec)) + (t + (cons (cons (car page-spec) + (car page-spec)) + (cdr page-spec))))) + (t page-spec)))) + (when (equal (cdr page-spec) + '(0 0 1 1)) + (setq page-spec `((,(caar page-spec) . ,(cdar page-spec))))) + page-spec)) + +(cl-defstruct pdf-virtual-range + ;; The PDF's filename. + filename + ;; First page in this range. + first + ;; Last page. + last + ;; The edges selected for these pages. + region + ;; The page-index corresponding to the first page in this range. + index-start) + +(cl-defstruct pdf-virtual-document + ;; Array of shared pdf-virtual-range structs, one element for each + ;; page. + page-array + ;; An alist mapping filenames to a list of pages. + file-map) + +(defun pdf-virtual-range-length (page) + "Return the number of pages in PAGE." + (1+ (- (pdf-virtual-range-last page) + (pdf-virtual-range-first page)))) + +(defun pdf-virtual-document-create (list &optional directory + file-error-handler) + "Create a virtual PDF from LIST using DIRECTORY. + +LIST should be a list of elements \(FILENAME . PAGE-SPECS\), +where FILENAME is a PDF document and PAGE-SPECS is a list of +PAGE-RANGE and/or \(PAGE-RANGE . EDGES\). In the later case, +EDGES should be a list of relative coordinates \(LEFT TOP RIGHT +BOT\) selecting a region of the page(s) in PAGE-RANGE. Giving no +PAGE-SPECs at all is equivalent to all pages of FILENAME. + +See `pdf-info-normalize-page-range' for the valid formats of +PAGE-RANGE. +" + + (unless (cl-every 'consp list) + (error "Every element should be a cons: %s" list)) + (unless (cl-every 'stringp (mapcar 'car list)) + (error "The car of every element should be a filename.")) + (unless (cl-every (lambda (elt) + (cl-every (lambda (page) + (or (pdf-info-valid-page-spec-p page) + (and (consp page) + (pdf-info-valid-page-spec-p (car page)) + (pdf-util-edges-p (cdr page) 'relative)))) + elt)) + (mapcar 'cdr list)) + (error + "The cdr of every element should be a list of page-specs")) + (let* ((doc (pdf-virtual-document--normalize + list (or directory default-directory) + file-error-handler)) + (npages 0) + document file-map) + (while doc + (let* ((elt (pop doc)) + (filename (car elt)) + (mapelt (assoc filename file-map)) + (page-specs (cdr elt))) + (if mapelt + (setcdr mapelt (cons (1+ npages) (cdr mapelt))) + (push (list filename (1+ npages)) file-map)) + (while page-specs + (let* ((ps (pop page-specs)) + (first (caar ps)) + (last (cdar ps)) + (region (cdr ps)) + (clx (make-pdf-virtual-range + :filename filename + :first first + :last last + :region region + :index-start npages))) + (cl-incf npages (1+ (- last first))) + (push (make-vector (1+ (- last first)) clx) + document))))) + (make-pdf-virtual-document + :page-array (apply 'vconcat (nreverse document)) + :file-map (nreverse + (mapcar (lambda (f) + (setcdr f (nreverse (cdr f))) + f) + file-map))))) + +(defun pdf-virtual-document--normalize (list &optional directory + file-error-handler) + (unless file-error-handler + (setq file-error-handler + (lambda (filename err) + (signal (car err) + (append (cdr err) (list filename)))))) + (let ((default-directory + (or directory default-directory))) + (setq list (cl-remove-if-not + (lambda (filename) + (condition-case err + (progn + (unless (file-readable-p filename) + (signal 'file-error + (list "File not readable: " filename))) + (pdf-info-open filename) + t) + (error + (funcall file-error-handler filename err) + nil))) + list + :key 'car)) + (let* ((file-attributes (make-hash-table :test 'equal)) + (file-equal-p (lambda (f1 f2) + (let ((a1 (gethash f1 file-attributes)) + (a2 (gethash f2 file-attributes))) + (if (and a1 a2) + (equal a1 a2) + (file-equal-p f1 f2))))) + files normalized) + ;; Optimize file-equal-p by caching file-attributes, which is slow + ;; and would be called quadratic times otherwise. (We don't want + ;; the same file under different names.) + (dolist (f (mapcar 'car list)) + (unless (find-file-name-handler f 'file-equal-p) + (puthash f (file-attributes f) file-attributes))) + (dolist (elt list) + (let ((file (cl-find (car elt) files :test file-equal-p))) + (unless file + (push (car elt) files) + (setq file (car elt))) + (let ((pages (mapcar (lambda (p) + (pdf-virtual-pagespec-normalize p file)) + (or (cdr elt) '(nil)))) + newpages) + (while pages + (let* ((spec (pop pages)) + (first (caar spec)) + (last (cdar spec)) + (region (cdr spec))) + (while (and pages + (eq (1+ last) + (caar (car pages))) + (equal region (cdr (car pages)))) + (setq last (cdar (pop pages)))) + (push `((,first . ,last) . ,region) newpages))) + (push (cons file (nreverse newpages)) + normalized)))) + (nreverse normalized)))) + +(defmacro pdf-virtual-document-defun (name args &optional documentation &rest body) + "Define a PDF Document function. + +Args are just like for `defun'. This macro will ensure, that the +DOCUMENT argument, which should be last, is setup properly in +case it is nil, i.e. check that the buffer passes +`pdf-virtual-buffer-assert-p' and use the variable +`pdf-virtual-document'." + + (declare (doc-string 3) (indent defun) + (debug (&define name lambda-list + [&optional stringp] + def-body))) + (unless (stringp documentation) + (push documentation body) + (setq documentation nil)) + (unless (memq '&optional args) + (setq args (append (butlast args) + (list '&optional) + (last args)))) + (when (memq '&rest args) + (error "&rest argument not supported")) + (let ((doc-arg (car (last args))) + (fn (intern (format "pdf-virtual-document-%s" name)))) + `(progn + (put ',fn 'definition-name ',name) + (defun ,fn + ,args ,documentation + (setq ,doc-arg + (or ,doc-arg + (progn (pdf-virtual-buffer-assert-p) + pdf-virtual-document))) + (cl-check-type ,doc-arg pdf-virtual-document) + ,@body)))) + +(pdf-virtual-document-defun filenames (doc) + "Return the list of filenames in DOC." + (mapcar 'car (pdf-virtual-document-file-map doc))) + +(pdf-virtual-document-defun normalize-pages (pages doc) + "Normalize PAGES using DOC. + +Like `pdf-info-normalize-page-range', except 0 is replaced by +DOC's last page." + + (setq pages (pdf-info-normalize-page-range pages)) + (if (eq 0 (cdr pages)) + `(,(car pages) . ,(pdf-virtual-document-number-of-pages doc)) + pages)) + +(pdf-virtual-document-defun page (page doc) + "Get PAGE of DOC. + +Returns a list \(FILENAME FILE-PAGE REGION\)." + (let ((page (car (pdf-virtual-document-pages (cons page page) doc)))) + (when page + (cl-destructuring-bind (filename first-last region) + page + (list filename (car first-last) region))))) + +(pdf-virtual-document-defun pages (pages doc) + "Get PAGES of DOC. + +PAGES should be a cons \(FIRST . LAST\). Return a list of +ranges corresponding to PAGES. Each element has the form + + \(FILENAME \(FILE-FIRT-PAGE . FILE-LAST-PAGE\) REGION\) +. +" + + (let ((begin (car pages)) + (end (cdr pages))) + (unless (<= begin end) + (error "begin should not exceed end: %s" (cons begin end))) + (let ((arr (pdf-virtual-document-page-array doc)) + result) + (when (or (< begin 1) + (> end (length arr))) + (signal 'args-out-of-range (list 'pages pages))) + (while (<= begin end) + (let* ((page (aref arr (1- begin))) + (filename (pdf-virtual-range-filename page)) + (offset (- (1- begin) + (pdf-virtual-range-index-start page))) + (first (+ (pdf-virtual-range-first page) + offset)) + (last (min (+ first (- end begin)) + (pdf-virtual-range-last page))) + (region (pdf-virtual-range-region page))) + (push `(,filename (,first . ,last) ,region) result) + (cl-incf begin (1+ (- last first))))) + (nreverse result)))) + +(pdf-virtual-document-defun number-of-pages (doc) + "Return the number of pages in DOC." + (length (pdf-virtual-document-page-array doc))) + +(pdf-virtual-document-defun page-of (filename &optional file-page limit doc) + "Return a page number displaying FILENAME's page FILE-PAGE in DOC. + +If FILE-PAGE is nil, return the first page displaying FILENAME. +If LIMIT is non-nil, it should be a range \(FIRST . LAST\) in +which the returned page should fall. This is useful if there are +more than one page displaying FILE-PAGE. LIMIT is ignored, if +FILE-PAGE is nil. + +Return nil if there is no matching page." + + (if (null file-page) + (cadr (assoc filename (pdf-virtual-document-file-map doc))) + (let ((pages (pdf-virtual-document-page-array doc))) + (catch 'found + (mapc + (lambda (pn) + (while (and (<= pn (length pages)) + (equal (pdf-virtual-range-filename (aref pages (1- pn))) + filename)) + (let* ((page (aref pages (1- pn))) + (first (pdf-virtual-range-first page)) + (last (pdf-virtual-range-last page))) + (when (and (>= file-page first) + (<= file-page last)) + (let ((r (+ (pdf-virtual-range-index-start page) + (- file-page (pdf-virtual-range-first page)) + 1))) + (when (or (null limit) + (and (>= r (car limit)) + (<= r (cdr limit)))) + (throw 'found r)))) + (cl-incf pn (1+ (- last first)))))) + (cdr (assoc filename (pdf-virtual-document-file-map doc)))) + nil)))) + +(pdf-virtual-document-defun find-matching-page (page predicate + &optional + backward-p doc) + (unless (and (>= page 1) + (<= page (length (pdf-virtual-document-page-array doc)))) + (signal 'args-out-of-range (list 'page page))) + (let* ((pages (pdf-virtual-document-page-array doc)) + (i (1- page)) + (this (aref pages i)) + other) + (while (and (< i (length pages)) + (>= i 0) + (null other)) + (setq i + (if backward-p + (1- (pdf-virtual-range-index-start this)) + (+ (pdf-virtual-range-length this) + (pdf-virtual-range-index-start this)))) + (when (and (< i (length pages)) + (>= i 0)) + (setq other (aref pages i)) + (unless (funcall predicate this other) + (setq other nil)))) + other)) + +(pdf-virtual-document-defun next-matching-page (page predicate doc) + (pdf-virtual-document-find-matching-page page predicate nil doc)) + +(pdf-virtual-document-defun previous-matching-page (page predicate doc) + (declare (indent 1)) + (pdf-virtual-document-find-matching-page page predicate t doc)) + +(pdf-virtual-document-defun next-file (page doc) + "Return the next page displaying a different file than PAGE. + +PAGE should be a page-number." + (let ((page (pdf-virtual-document-next-matching-page + page + (lambda (this other) + (not (equal (pdf-virtual-range-filename this) + (pdf-virtual-range-filename other))))))) + (when page + (1+ (pdf-virtual-range-index-start page))))) + +(pdf-virtual-document-defun previous-file (page doc) + "Return the previous page displaying a different file than PAGE. + +PAGE should be a page-number." + (let ((page (pdf-virtual-document-previous-matching-page + page + (lambda (this other) + (not (equal (pdf-virtual-range-filename this) + (pdf-virtual-range-filename other))))))) + (when page + (1+ (pdf-virtual-range-index-start page))))) + + +;; * ================================================================== * +;; * Modes +;; * ================================================================== * + +(defvar pdf-virtual-edit-mode-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map emacs-lisp-mode-map) + (define-key map (kbd "C-c C-c") 'pdf-virtual-view-mode) + map)) + + +;;;###autoload +(define-derived-mode pdf-virtual-edit-mode emacs-lisp-mode "VPDF-Edit" + "Major mode when editing a virtual PDF buffer." + (buffer-enable-undo) + (setq-local buffer-read-only nil) + (unless noninteractive + (message (substitute-command-keys "Press \\[pdf-virtual-view-mode] to view.")))) + +;; FIXME: Provide filename/region from-windows-gathering functions. +(defvar pdf-virtual-view-mode-map + (let ((map (make-sparse-keymap))) + (set-keymap-parent map pdf-view-mode-map) + (define-key map (kbd "C-c C-c") 'pdf-virtual-edit-mode) + (define-key map [remap backward-paragraph] 'pdf-virtual-buffer-backward-file) + (define-key map [remap forward-paragraph] 'pdf-virtual-buffer-forward-file) + (define-key map (kbd "C-c C-c") 'pdf-virtual-edit-mode) + map)) + +;;;###autoload +(define-derived-mode pdf-virtual-view-mode pdf-view-mode "VPDF-View" + "Major mode in virtual PDF buffers." + (setq-local write-contents-functions nil) + (remove-hook 'kill-buffer-hook 'pdf-view-close-document t) + (setq-local header-line-format + `(:eval (pdf-virtual-buffer-current-file))) + (unless noninteractive + (message (substitute-command-keys "Press \\[pdf-virtual-edit-mode] to edit.")))) + +;;;###autoload +(define-minor-mode pdf-virtual-global-minor-mode + "Enable recognition and handling of VPDF files." + :global t + :group 'pdf-tools + (let ((elt `(,pdf-virtual-magic-mode-regexp . pdf-virtual-view-mode))) + (cond + (pdf-virtual-global-minor-mode + (add-to-list 'magic-mode-alist elt)) + (t + (setq magic-mode-alist + (remove elt magic-mode-alist)))) + (dolist (elt pdf-virtual-adapter-alist) + (let ((fn (car elt)) + (orig (cdr elt))) + (advice-remove orig fn) + (when pdf-virtual-global-minor-mode + (advice-add orig :around fn)))))) + +(advice-add 'pdf-virtual-view-mode + :around 'pdf-virtual-view-mode-prepare) + +;; This needs to run before pdf-view-mode does its thing. +(defun pdf-virtual-view-mode-prepare (fn) + (let (list unreadable) + (save-excursion + (goto-char 1) + (unless (looking-at pdf-virtual-magic-mode-regexp) + (pdf-virtual-buffer-assert-p)) + (setq list (read (current-buffer)))) + (setq pdf-virtual-document + (pdf-virtual-document-create + list + nil + (lambda (filename _error) + (push filename unreadable)))) + (when unreadable + (display-warning + 'pdf-virtual + (format "Some documents could not be opened:\n%s" + (mapconcat (lambda (f) + (concat " " f)) + unreadable "\n")))) + (if (= (pdf-virtual-document-number-of-pages) 0) + (error "Document is empty.") + (unless pdf-virtual-global-minor-mode + (pdf-virtual-global-minor-mode 1)) + (funcall fn)))) + + +;; * ================================================================== * +;; * Buffer handling +;; * ================================================================== * + +;;;###autoload +(defun pdf-virtual-buffer-create (&optional filenames buffer-name display-p) + (interactive + (list (directory-files default-directory nil "\\.pdf\\'") + (read-string + "Buffer name (default: all.vpdf): " nil nil "all.vpdf") t)) + (with-current-buffer (generate-new-buffer buffer-name) + (insert ";; %VPDF 1.0\n\n") + (insert ";; File Format +;; +;; FORMAT ::= ( FILES* ) +;; FILES ::= ( FILE . PAGE-SPEC* ) +;; PAGE-SPEC ::= PAGE | ( PAGE . REGION ) +;; PAGE ::= NUMBER | ( FIRST . LAST ) +;; REGION ::= ( LEFT TOP RIGHT BOT ) +;; +;; 0 <= X <= 1, forall X in REGION . + +") + (if (null filenames) + (insert "nil\n") + (insert "(") + (dolist (f filenames) + (insert (format "(%S)\n " f))) + (delete-char -2) + (insert ")\n")) + (pdf-virtual-edit-mode) + (when display-p + (pop-to-buffer (current-buffer))) + (current-buffer))) + +(defun pdf-virtual-buffer-p (&optional buffer) + (save-current-buffer + (when buffer (set-buffer buffer)) + (or (derived-mode-p 'pdf-virtual-view-mode 'pdf-virtual-edit-mode) + pdf-virtual-document))) + +(defun pdf-virtual-view-window-p (&optional window) + (save-selected-window + (when window (select-window window 'norecord)) + (derived-mode-p 'pdf-virtual-view-mode))) + +(defun pdf-virtual-filename-p (filename) + (and (stringp filename) + (file-exists-p filename) + (with-temp-buffer + (save-excursion (insert-file-contents filename nil 0 128)) + (looking-at pdf-virtual-magic-mode-regexp)))) + +(defun pdf-virtual-buffer-assert-p (&optional buffer) + (unless (pdf-virtual-buffer-p buffer) + (error "Buffer is not a virtual PDF buffer"))) + +(defun pdf-virtual-view-window-assert-p (&optional window) + (unless (pdf-virtual-view-window-p window) + (error "Window's buffer is not in `pdf-virtual-view-mode'."))) + +(defun pdf-virtual-buffer-current-file (&optional window) + (pdf-virtual-view-window-assert-p window) + (pdf-virtual-range-filename + (aref (pdf-virtual-document-page-array + pdf-virtual-document) + (1- (pdf-view-current-page window))))) + +(defun pdf-virtual-buffer-forward-file (&optional n interactive-p) + (interactive "p\np") + (pdf-virtual-view-window-assert-p) + (let* ((pn (pdf-view-current-page)) + (pages (pdf-virtual-document-page-array + pdf-virtual-document)) + (page (aref pages (1- pn))) + (first-filepage (1+ (pdf-virtual-range-index-start page)))) + + (when (and (< n 0) + (not (= first-filepage pn))) + (cl-incf n)) + (setq pn first-filepage) + + (let (next) + (while (and (> n 0) + (setq next (pdf-virtual-document-next-file pn))) + (setq pn next) + (cl-decf n))) + (let (previous) + (while (and (< n 0) + (setq previous (pdf-virtual-document-previous-file pn))) + (setq pn previous) + (cl-incf n))) + (when interactive-p + (when (< n 0) + (message "First file.")) + (when (> n 0) + (message "Last file."))) + (pdf-view-goto-page pn) + n)) + +(defun pdf-virtual-buffer-backward-file (&optional n interactive-p) + (interactive "p\np") + (pdf-virtual-buffer-forward-file (- (or n 1)) interactive-p)) + + +;; * ================================================================== * +;; * Helper functions +;; * ================================================================== * + + +(defmacro pdf-virtual-dopages (bindings pages &rest body) + (declare (indent 2) (debug (sexp form &rest form))) + (let ((page (make-symbol "page"))) + `(dolist (,page ,pages) + (cl-destructuring-bind ,bindings + ,page + ,@body)))) + +(defun pdf-virtual--perform-search (string pages &optional regexp-p no-error) + (let* ((pages (pdf-virtual-document-normalize-pages pages)) + (file-pages (pdf-virtual-document-pages pages))) + (pdf-info-compose-queries + ((responses + (pdf-virtual-dopages (filename pages _region) + file-pages + (if regexp-p + (pdf-info-search-string string pages filename) + ;; FIXME: no-error won't work with synchronous calls. + (pdf-info-search-regexp string pages no-error filename))))) + (let (result) + (pdf-virtual-dopages (filename _ region) + file-pages + (let ((matches (pop responses))) + (when region + (setq matches + (mapcar + (lambda (m) + (let-alist m + `((edges . ,(pdf-util-edges-transform region .edges t)) + ,@m))) + (pdf-virtual--filter-edges + region matches + (apply-partially 'alist-get 'edges))))) + (dolist (m matches) + (push `((page . ,(pdf-virtual-document-page-of + filename (alist-get 'page m) + pages)) + ,@m) + result)))) + (nreverse result))))) + +(defun pdf-virtual--filter-edges (region elts &optional edges-key-fn) + (if (null region) + elts + (cl-remove-if-not + (lambda (edges) + (or (null edges) + (if (consp (car edges)) + (cl-some (apply-partially 'pdf-util-edges-intersection region) edges) + (pdf-util-edges-intersection region edges)))) + elts + :key edges-key-fn))) + +(defun pdf-virtual--transform-goto-dest (link filename region) + (let-alist link + (let ((local-page (pdf-virtual-document-page-of + filename .page))) + (if local-page + `((type . ,'goto-dest) + (title . , .title) + (page . ,local-page) + (top . ,(car (pdf-util-edges-transform + region (cons .top .top) t)))) + `((type . ,'goto-remote) + (title . , .title) + (filename . ,filename) + (page . , .page) + (top . , .top)))))) + + +;; * ================================================================== * +;; * Server adapter +;; * ================================================================== * + +(defmacro pdf-virtual-define-adapter (name arglist &optional doc &rest body) + ;; FIXME: Handle &optional + &rest argument. + (declare (doc-string 3) (indent 2) + (debug (&define name lambda-list + [&optional stringp] + def-body))) + (unless (stringp doc) + (push doc body) + (setq doc nil)) + (let ((fn (intern (format "pdf-virtual-%s" name))) + (base-fn (intern (format "pdf-info-%s" name))) + (base-fn-arg (make-symbol "fn")) + (true-file-or-buffer (make-symbol "true-file-or-buffer")) + (args (cl-remove-if (lambda (elt) + (memq elt '(&optional &rest))) + arglist))) + (unless (fboundp base-fn) + (error "Base function is undefined: %s" base-fn)) + (unless (memq 'file-or-buffer arglist) + (error "Argument list is missing a `file-or-buffer' argument: %s" arglist)) + `(progn + (put ',fn 'definition-name ',name) + (add-to-list 'pdf-virtual-adapter-alist ',(cons fn base-fn)) + (defun ,fn ,(cons base-fn-arg arglist) + ,(format "%sPDF virtual adapter to `%s'. + +This function delegates to `%s', +unless the FILE-OR-BUFFER argument denotes a VPDF document." + (if doc (concat doc "\n\n") "") + base-fn + base-fn) + (let ((,true-file-or-buffer + (cond + ((or (bufferp file-or-buffer) + (stringp file-or-buffer)) file-or-buffer) + ((or (null file-or-buffer) + ,(not (null (memq '&rest arglist)))) + (current-buffer))))) + (if (cond + ((null ,true-file-or-buffer) t) + ((bufferp ,true-file-or-buffer) + (not (pdf-virtual-buffer-p ,true-file-or-buffer))) + ((stringp ,true-file-or-buffer) + (not (pdf-virtual-filename-p ,true-file-or-buffer)))) + (,(if (memq '&rest arglist) 'apply 'funcall) ,base-fn-arg ,@args) + (when (stringp ,true-file-or-buffer) + (setq ,true-file-or-buffer + (find-file-noselect ,true-file-or-buffer))) + (save-current-buffer + (when (bufferp ,true-file-or-buffer) + (set-buffer ,true-file-or-buffer)) + ,@body))))))) + +(define-error 'pdf-virtual-unsupported-operation + "Operation not supported in VPDF buffer") + +(pdf-virtual-define-adapter open (&optional file-or-buffer password) + (mapc (lambda (file) + (pdf-info-open file password)) + (pdf-virtual-document-filenames))) + +(pdf-virtual-define-adapter close (&optional file-or-buffer) + (let ((files (cl-remove-if 'find-buffer-visiting + (pdf-virtual-document-filenames)))) + (pdf-info-compose-queries + ((results (mapc 'pdf-info-close files))) + (cl-some 'identity results)))) + +(pdf-virtual-define-adapter metadata (&optional file-or-buffer) + (pdf-info-compose-queries + ((md (mapc 'pdf-info-metadata (pdf-virtual-document-filenames)))) + (apply 'cl-mapcar (lambda (&rest elts) + (cons (caar elts) + (cl-mapcar 'cdr elts))) + md))) + +(pdf-virtual-define-adapter search-string (string &optional pages file-or-buffer) + (pdf-virtual--perform-search + string (pdf-virtual-document-normalize-pages pages))) + +(pdf-virtual-define-adapter search-regexp (pcre &optional + pages no-error file-or-buffer) + (pdf-virtual--perform-search + pcre (pdf-virtual-document-normalize-pages pages) 'regexp no-error)) + +(pdf-virtual-define-adapter pagelinks (page &optional file-or-buffer) + (cl-destructuring-bind (filename ext-page region) + (pdf-virtual-document-page page) + (pdf-info-compose-queries + ((links (pdf-info-pagelinks ext-page filename))) + (mapcar + (lambda (link) + (let-alist link + (if (not (eq .type 'goto-dest)) + link + `((edges . ,(pdf-util-edges-transform region .edges t)) + ,@(pdf-virtual--transform-goto-dest link filename region))))) + (pdf-virtual--filter-edges region (car links) 'car))))) + +(pdf-virtual-define-adapter number-of-pages (&optional file-or-buffer) + (pdf-info-compose-queries nil (pdf-virtual-document-number-of-pages))) + +(pdf-virtual-define-adapter outline (&optional file-or-buffer) + (let ((files (pdf-virtual-document-filenames))) + (pdf-info-compose-queries + ((outlines (mapc 'pdf-info-outline files))) + (cl-mapcan + (lambda (outline filename) + `(((depth . 1) + (type . goto-dest) + (title . ,filename) + (page . ,(pdf-virtual-document-page-of filename)) + (top . 0)) + ,@(delq + nil + (mapcar + (lambda (item) + (let-alist item + (if (not (eq .type 'goto-dest)) + `((depth . ,(1+ .depth)) + ,@item) + (cl-check-type filename string) + (let ((page (pdf-virtual-document-page-of + filename .page))) + (when page + `((depth . ,(1+ .depth)) + ,@(pdf-virtual--transform-goto-dest + item filename + (nth 2 (pdf-virtual-document-page page))))))))) + outline)))) + outlines files)))) + +(pdf-virtual-define-adapter gettext (page edges &optional + selection-style file-or-buffer) + (cl-destructuring-bind (filename file-page region) + (pdf-virtual-document-page page) + (let ((edges (pdf-util-edges-transform region edges))) + (pdf-info-gettext file-page edges selection-style filename)))) + +(pdf-virtual-define-adapter getselection (page edges &optional + selection-style file-or-buffer) + (cl-destructuring-bind (filename file-page region) + (pdf-virtual-document-page page) + (let ((edges (pdf-util-edges-transform region edges))) + (pdf-info-compose-queries + ((results (pdf-info-getselection file-page edges selection-style filename))) + (pdf-util-edges-transform + region + (pdf-virtual--filter-edges region (car results)) t))))) + +(pdf-virtual-define-adapter charlayout (page &optional edges-or-pos file-or-buffer) + (cl-destructuring-bind (filename file-page region) + (pdf-virtual-document-page page) + (let ((edges-or-pos (pdf-util-edges-transform region edges-or-pos))) + (pdf-info-compose-queries + ((results (pdf-info-charlayout file-page edges-or-pos filename))) + (mapcar (lambda (elt) + `(,(car elt) + . ,(pdf-util-edges-transform region (cdr elt) t))) + (pdf-virtual--filter-edges region (car results) 'cadr)))))) + +(pdf-virtual-define-adapter pagesize (page &optional file-or-buffer) + (cl-destructuring-bind (filename file-page region) + (pdf-virtual-document-page page) + (pdf-info-compose-queries + ((result (pdf-info-pagesize file-page filename))) + (if (null region) + (car result) + (pdf-util-with-edges (region) + (pdf-util-scale + (car result) (cons region-width region-height))))))) + +(pdf-virtual-define-adapter getannots (&optional pages file-or-buffer) + (let* ((pages (pdf-virtual-document-normalize-pages pages)) + (file-pages (pdf-virtual-document-pages pages))) + (pdf-info-compose-queries + ((annotations + (pdf-virtual-dopages (filename file-pages _region) + file-pages + (pdf-info-getannots file-pages filename)))) + (let ((page (car pages)) + result) + (pdf-virtual-dopages (_filename file-pages region) + file-pages + (dolist (a (pop annotations)) + (let ((edges (delq nil `(,(cdr (assq 'edges a)) + ,@(cdr (assq 'markup-edges a)))))) + (when (pdf-virtual--filter-edges region edges) + (let-alist a + (setcdr (assq 'page a) + (+ page (- .page (car file-pages)))) + (setcdr (assq 'id a) + (intern (format "%s/%d" .id (cdr (assq 'page a))))) + (when region + (when .edges + (setcdr (assq 'edges a) + (pdf-util-edges-transform region .edges t))) + (when .markup-edges + (setcdr (assq 'markup-edges a) + (pdf-util-edges-transform region .markup-edges t)))) + (push a result))))) + (cl-incf page (1+ (- (cdr file-pages) (car file-pages))))) + (nreverse result))))) + +(pdf-virtual-define-adapter getannot (id &optional file-or-buffer) + (let ((name (symbol-name id)) + page) + (save-match-data + (when (string-match "\\(.*\\)/\\([0-9]+\\)\\'" name) + (setq id (intern (match-string 1 name)) + page (string-to-number (match-string 2 name))))) + (if page + (cl-destructuring-bind (filename _ _) + (pdf-virtual-document-page page) + (pdf-info-compose-queries + ((result (pdf-info-getannot id filename))) + (let ((a (car result))) + (cl-destructuring-bind (_ _ region) + (pdf-virtual-document-page page) + (setcdr (assq 'page a) page) + (let-alist a + (setcdr (assq 'id a) + (intern (format "%s/%d" .id (cdr (assq 'page a))))) + (when region + (when .edges + (setcdr (assq 'edges a) + (pdf-util-edges-transform region .edges t))) + (when .markup-edges + (setcdr (assq 'markup-edges a) + (pdf-util-edges-transform region .markup-edges t)))))) + a))) + (pdf-info-compose-queries nil + (error "No such annotation: %s" id))))) + +(pdf-virtual-define-adapter addannot (page edges type &optional + file-or-buffer &rest markup-edges) + (signal 'pdf-virtual-unsupported-operation (list 'addannot))) + +(pdf-virtual-define-adapter delannot (id &optional file-or-buffer) + (signal 'pdf-virtual-unsupported-operation (list 'delannot))) + +(pdf-virtual-define-adapter mvannot (id edges &optional file-or-buffer) + (signal 'pdf-virtual-unsupported-operation (list 'mvannot))) + +(pdf-virtual-define-adapter editannot (id modifications &optional file-or-buffer) + (signal 'pdf-virtual-unsupported-operation (list 'editannot))) + +(pdf-virtual-define-adapter save (&optional file-or-buffer) + (signal 'pdf-virtual-unsupported-operation (list 'save))) + +;;(defvar-local pdf-virtual-annotation-mapping nil) + +(pdf-virtual-define-adapter getattachment-from-annot + (id &optional do-save file-or-buffer) + (let ((name (symbol-name id)) + page) + (save-match-data + (when (string-match "\\(.*\\)/\\([0-9]+\\)\\'" name) + (setq id (intern (match-string 1 name)) + page (string-to-number (match-string 2 name))))) + (if page + (cl-destructuring-bind (filename _ _) + (pdf-virtual-document-page page) + (pdf-info-getattachment-from-annot id do-save filename)) + (pdf-info-compose-queries nil + (error "No such annotation: %s" id))))) + +(pdf-virtual-define-adapter getattachments (&optional do-save file-or-buffer) + (pdf-info-compose-queries + ((results (mapc + (lambda (f) + (pdf-info-getattachments do-save f)) + (pdf-virtual-document-filenames)))) + (apply 'append results))) + +(pdf-virtual-define-adapter synctex-forward-search + (source &optional line column file-or-buffer) + (signal 'pdf-virtual-unsupported-operation (list 'synctex-forward-search))) + +(pdf-virtual-define-adapter synctex-backward-search (page &optional x y file-or-buffer) + (cl-destructuring-bind (filename file-page region) + (pdf-virtual-document-page page) + (cl-destructuring-bind (x &rest y) + (pdf-util-edges-transform region (cons x y)) + (pdf-info-synctex-backward-search file-page x y filename)))) + +(pdf-virtual-define-adapter renderpage (page width &optional file-or-buffer + &rest commands) + (when (keywordp file-or-buffer) + (push file-or-buffer commands) + (setq file-or-buffer nil)) + (cl-destructuring-bind (filename file-page region) + (pdf-virtual-document-page page) + (when region + (setq commands (append (list :crop-to region) commands) + width (pdf-util-with-edges (region) + (round (* width (max 1 (/ 1.0 (max 1e-6 region-width)))))))) + (apply 'pdf-info-renderpage file-page width filename commands))) + +(pdf-virtual-define-adapter boundingbox (page &optional file-or-buffer) + (cl-destructuring-bind (filename file-page region) + (pdf-virtual-document-page page) + (pdf-info-compose-queries + ((results (unless region (pdf-info-boundingbox file-page filename)))) + (if region + (list 0 0 1 1) + (car results))))) + +(pdf-virtual-define-adapter pagelabels (&optional file-or-buffer) + (signal 'pdf-virtual-unsupported-operation (list 'pagelabels))) + +(pdf-virtual-define-adapter setoptions (&optional file-or-buffer &rest options) + (when (keywordp file-or-buffer) + (push file-or-buffer options) + (setq file-or-buffer nil)) + (pdf-info-compose-queries + ((_ (dolist (f (pdf-virtual-document-filenames)) + (apply 'pdf-info-setoptions f options)))) + nil)) + +(pdf-virtual-define-adapter getoptions (&optional file-or-buffer) + (signal 'pdf-virtual-unsupported-operation (list 'getoptions))) + +(pdf-virtual-define-adapter encrypted-p (&optional file-or-buffer) + nil) + +(provide 'pdf-virtual) +;;; pdf-virtual.el ends here diff --git a/org/elpa/tablist-20230321.705/tablist-autoloads.el b/org/elpa/tablist-20230321.705/tablist-autoloads.el new file mode 100644 index 0000000..ed0000e --- /dev/null +++ b/org/elpa/tablist-20230321.705/tablist-autoloads.el @@ -0,0 +1,58 @@ +;;; tablist-autoloads.el --- automatically extracted autoloads -*- lexical-binding: t -*- +;; +;;; Code: + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + + +;;;### (autoloads nil "tablist" "tablist.el" (0 0 0 0)) +;;; Generated autoloads from tablist.el + +(autoload 'tablist-minor-mode "tablist" "\ +Toggle tablist minor mode. + +This is a minor mode. If called interactively, toggle the +`Tablist minor mode' mode. If the prefix argument is positive, +enable the mode, and if it is zero or negative, disable the mode. + +If called from Lisp, toggle the mode if ARG is `toggle'. Enable +the mode if ARG is nil, omitted, or is a positive number. +Disable the mode if ARG is a negative number. + +To check whether the minor mode is enabled in the current buffer, +evaluate `tablist-minor-mode'. + +The mode's hook is called both when the mode is enabled and when +it is disabled. + +\(fn &optional ARG)" t nil) + +(autoload 'tablist-mode "tablist" "\ + + +\(fn)" t nil) + +(register-definition-prefixes "tablist" '("tablist-")) + +;;;*** + +;;;### (autoloads nil "tablist-filter" "tablist-filter.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from tablist-filter.el + +(register-definition-prefixes "tablist-filter" '("tablist-filter-")) + +;;;*** + +;;;### (autoloads nil nil ("tablist-pkg.el") (0 0 0 0)) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; coding: utf-8 +;; End: +;;; tablist-autoloads.el ends here diff --git a/org/elpa/tablist-20230321.705/tablist-filter.el b/org/elpa/tablist-20230321.705/tablist-filter.el new file mode 100644 index 0000000..c5d56b8 --- /dev/null +++ b/org/elpa/tablist-20230321.705/tablist-filter.el @@ -0,0 +1,464 @@ +;;; tablist-filter.el --- Filter expressions for tablists. -*- lexical-binding:t -*- + +;; Copyright (C) 2013, 2014 Andreas Politz + +;; Author: Andreas Politz +;; Keywords: extensions, lisp + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; + +(defvar python-mode-hook) +(let (python-mode-hook) ;FIXME: Why? +(require 'semantic/wisent/comp) +(require 'semantic/wisent/wisent)) + +;;; Code: + +(defvar wisent-eoi-term) +(declare-function wisent-parse "semantic/wisent/wisent.el") + +;; +;; *Variables +;; + +(defvar tablist-filter-binary-operator + '((== . tablist-filter-op-equal) + (=~ . tablist-filter-op-regexp) + (< . tablist-filter-op-<) + (> . tablist-filter-op->) + (<= . tablist-filter-op-<=) + (>= . tablist-filter-op->=) + (= . tablist-filter-op-=))) + +(defvar tablist-filter-unary-operator nil) + +(defvar tablist-filter-wisent-parser nil) + +(defvar tablist-filter-lexer-regexps nil) + +(defvar tablist-filter-wisent-grammar + '( + ;; terminals + ;; Use lowercase for better looking error messages. + (operand unary-operator binary-operator or and not) + + ;; terminal associativity & precedence + ((left binary-operator) + (left unary-operator) + (left or) + (left and) + (left not)) + + ;; rules + (filter-or-empty + ((nil)) + ((?\( ?\)) nil) + ((filter) $1)) + (filter + ((operand) $1) ;;Named filter + ((operand binary-operator operand) `(,(intern $2) ,$1 ,$3)) + ((unary-operator operand) `(,(intern $1) ,$2)) + ((not filter) `(not ,$2)) + ((filter and filter) `(and ,$1 ,$3)) + ((filter or filter) `(or ,$1 ,$3)) + ((?\( filter ?\)) $2)))) + +;; +;; *Filter Parsing +;; + +(defun tablist-filter-parser-init (&optional reinitialize interactive) + (interactive (list t t)) + (unless (and tablist-filter-lexer-regexps + (not reinitialize)) + (let ((re (mapcar + (lambda (l) + (let ((re (regexp-opt + (mapcar 'symbol-name + (mapcar 'car l)) t))) + (if (= (length re) 0) + ".\\`" ;;matches nothing + re))) + (list tablist-filter-binary-operator + tablist-filter-unary-operator)))) + (setq tablist-filter-lexer-regexps + (nreverse + (cons (concat "\\(?:" (car re) "\\|" (cadr re) + "\\|[ \t\f\r\n\"!()]\\|&&\\|||\\)") + re))))) + (unless (and tablist-filter-wisent-parser + (not reinitialize)) + (let ((wisent-compile-grammar* + (symbol-function + 'wisent-compile-grammar))) + (setq tablist-filter-wisent-parser + ;; Trick the byte-compile into not using the byte-compile + ;; handler in semantic/wisent/comp.el, since it does not + ;; always work (wisent-context-compile-grammar n/a). + (funcall wisent-compile-grammar* + tablist-filter-wisent-grammar)))) + (when interactive + (message "Parser reinitialized.")) + nil) + +(defun tablist-filter-wisent-lexer () + (cl-destructuring-bind (unary-op binary-op keywords) + tablist-filter-lexer-regexps + (skip-chars-forward " \t\f\r\n") + (cond + ((eobp) (list wisent-eoi-term)) + ((= ?\" (char-after)) + `(operand , (condition-case err + (read (current-buffer)) + (error (signal (car err) (cons + "invalid lisp string" + (cdr err))))))) + ((looking-at unary-op) + (goto-char (match-end 0)) + `(unary-operator ,(match-string-no-properties 0))) + ((looking-at binary-op) + (goto-char (match-end 0)) + `(binary-operator ,(match-string-no-properties 0))) + ((looking-at "&&") + (forward-char 2) + `(and "&&")) + ((looking-at "||") + (forward-char 2) + `(or "||")) + ((= ?! (char-after)) + (forward-char) + `(not "!")) + ((= ?\( (char-after)) + (forward-char) + `(?\( "(")) + ((= ?\) (char-after)) + (forward-char) + `(?\) ")")) + (t + (let ((beg (point))) + (when (re-search-forward keywords nil 'move) + (goto-char (match-beginning 0))) + `(operand ,(buffer-substring-no-properties + beg + (point)))))))) + +(defun tablist-filter-parse (filter) + (interactive "sFilter: ") + (tablist-filter-parser-init) + (with-temp-buffer + (save-excursion (insert filter)) + (condition-case error + (wisent-parse tablist-filter-wisent-parser + 'tablist-filter-wisent-lexer + (lambda (msg) + (signal 'error + (replace-regexp-in-string + "\\$EOI" "end of input" + msg t t)))) + (error + (signal 'error + (append (if (consp (cdr error)) + (cdr error) + (list (cdr error))) + (list (point)))))))) + +(defun tablist-filter-unparse (filter &optional noerror) + (cl-labels + ((unparse (filter &optional noerror) + (cond + ((stringp filter) + (if (or (string-match (nth 2 tablist-filter-lexer-regexps) + filter) + (= 0 (length filter))) + (format "%S" filter) + filter)) + ((and (eq (car-safe filter) 'not) + (= (length filter) 2)) + (let ((paren (memq (car-safe (nth 1 filter)) '(or and)))) + (format "!%s%s%s" + (if paren "(" "") + (unparse (cadr filter) noerror) + (if paren ")" "")))) + ((and (memq (car-safe filter) '(and or)) + (= (length filter) 3)) + (let ((lparen (and (eq (car filter) 'and) + (eq 'or (car-safe (car-safe (cdr filter)))))) + (rparen (and (eq (car filter) 'and) + (eq 'or (car-safe (car-safe (cddr filter))))))) + (format "%s%s%s %s %s%s%s" + (if lparen "(" "") + (unparse (cadr filter) noerror) + (if lparen ")" "") + (cl-case (car filter) + (and "&&") (or "||")) + (if rparen "(" "") + (unparse (car (cddr filter)) noerror) + (if rparen ")" "")))) + ((and (assq (car-safe filter) tablist-filter-binary-operator) + (= (length filter) 3)) + (format "%s %s %s" + (unparse (cadr filter) noerror) + (car filter) + (unparse (car (cddr filter)) noerror))) + ((and (assq (car-safe filter) tablist-filter-unary-operator) + (= (length filter) 2)) + (format "%s %s" + (car filter) + (unparse (cadr filter) noerror))) + ((not filter) "") + (t (funcall (if noerror 'format 'error) + "Invalid filter: %s" filter))))) + (tablist-filter-parser-init) + (unparse filter noerror))) + +(defun tablist-filter-eval (filter id entry &optional named-alist) + (cl-labels + ((feval (filter) + (pcase filter + (`(not . ,(and operand (guard (not (cdr operand))))) + (not (feval (car operand)))) + (`(and . ,(and operands (guard (= 2 (length operands))))) + (and + (feval (nth 0 operands)) + (feval (nth 1 operands)))) + (`(or . ,(and operands (guard (= 2 (length operands))))) + (or + (feval (nth 0 operands)) + (feval (nth 1 operands)))) + (`(,op . ,(and operands (guard (= (length operands) 1)))) + (let ((fn (assq op tablist-filter-unary-operator))) + (unless fn + (error "Undefined unary operator: %s" op)) + (funcall fn id entry (car operands)))) + (`(,op . ,(and operands (guard (= (length operands) 2)))) + (let ((fn (cdr (assq op tablist-filter-binary-operator)))) + (unless fn + (error "Undefined binary operator: %s" op)) + (funcall fn id entry (car operands) + (cadr operands)))) + ((guard (stringp filter)) + (let ((fn (cdr (assoc filter named-alist)))) + (unless fn + (error "Undefined named filter: %s" filter)) + (if (functionp fn) + (funcall fn id entry)) + (feval + (if (stringp fn) (tablist-filter-unparse fn) fn)))) + (`nil t) + (_ (error "Invalid filter: %s" filter))))) + (feval filter))) + +;; +;; *Filter Operators +;; + +(defun tablist-filter-get-item-by-name (entry col-name) + (let* ((col (cl-position col-name tabulated-list-format + :key 'car + :test + (lambda (s1 s2) + (eq t (compare-strings + s1 nil nil s2 nil nil t))))) + (item (and col (elt entry col)))) + (unless col + (error "No such column: %s" col-name)) + (if (consp item) ;(LABEL . PROPS) + (car item) + item))) + +(defun tablist-filter-op-equal (_id entry op1 op2) + "COLUMN == STRING : Matches if COLUMN's entry is equal to STRING." + (let ((item (tablist-filter-get-item-by-name entry op1))) + (string= item op2))) + +(defun tablist-filter-op-regexp (_id entry op1 op2) + "COLUMN =~ REGEXP : Matches if COLUMN's entry matches REGEXP." + (let ((item (tablist-filter-get-item-by-name entry op1))) + (string-match op2 item))) + +(defun tablist-filter-op-< (id entry op1 op2) + "COLUMN < NUMBER : Matches if COLUMN's entry is less than NUMBER." + (tablist-filter-op-numeric '< id entry op1 op2)) + +(defun tablist-filter-op-> (id entry op1 op2) + "COLUMN > NUMBER : Matches if COLUMN's entry is greater than NUMBER." + (tablist-filter-op-numeric '> id entry op1 op2)) + +(defun tablist-filter-op-<= (id entry op1 op2) + "COLUMN <= NUMBER : Matches if COLUMN's entry is less than or equal to NUMBER." + (tablist-filter-op-numeric '<= id entry op1 op2)) + +(defun tablist-filter-op->= (id entry op1 op2) + "COLUMN >= NUMBER : Matches if COLUMN's entry is greater than or equal to NUMBER." + (tablist-filter-op-numeric '>= id entry op1 op2)) + +(defun tablist-filter-op-= (id entry op1 op2) + "COLUMN = NUMBER : Matches if COLUMN's entry as a number is equal to NUMBER." + (tablist-filter-op-numeric '= id entry op1 op2)) + +(defun tablist-filter-op-numeric (op _id entry op1 op2) + (let ((item (tablist-filter-get-item-by-name entry op1))) + (funcall op (string-to-number item) + (string-to-number op2)))) + +(defun tablist-filter-help (&optional temporary) + (interactive) + (cl-labels + ((princ-op (op) + (princ (car op)) + (princ (concat (make-string (max 0 (- 4 (length (symbol-name (car op))))) + ?\s) + "- " + (car (split-string + (or (documentation (cdr op)) + (format "FIXME: Not documented: %s" + (cdr op))) + "\n" t)) + "\n")))) + (with-temp-buffer-window + "*Help*" + (if temporary + '((lambda (buf alist) + (let ((win + (or (display-buffer-reuse-window buf alist) + (display-buffer-in-side-window buf alist)))) + (fit-window-to-buffer win) + win)) + (side . bottom))) + nil + (princ "Filter entries with the following operators.\n\n") + (princ "&& - FILTER1 && FILTER2 : Locical and.\n") + (princ "|| - FILTER1 || FILTER2 : Locical or.\n") + (dolist (op tablist-filter-binary-operator) + (princ-op op)) + (princ "! - ! FILTER : Locical not.\n\n") + (dolist (op tablist-filter-unary-operator) + (princ-op op)) + (princ "\"...\" may be used to quote names and values if necessary, +and \(...\) to group expressions.") + (with-current-buffer standard-output + (help-mode))))) + +;; +;; *Filter Functions +;; + +;; filter ::= nil | named | fn | (OP OP1 [OP2]) + +(defun tablist-filter-negate (filter) + "Return a filter not matching filter." + (cond + ((eq (car-safe filter) 'not) + (cadr filter)) + (filter + (list 'not filter)))) + +(defun tablist-filter-push (filter new-filter &optional or-p) + "Return a filter combining FILTER and NEW-FILTER. + +By default the filters are and'ed, unless OR-P is non-nil." + (if (or (null filter) + (null new-filter)) + (or filter + new-filter) + (list (if or-p 'or 'and) + filter new-filter))) + +(defun tablist-filter-pop (filter) + "Remove the first operator or operand from filter. + +If filter starts with a negation, return filter unnegated, +if filter starts with a dis- or conjunction, remove the first operand, +if filter is nil, raise an error, +else return nil." + (pcase filter + (`(,(or `and `or) . ,tail) + (car (cdr tail))) + (`(not . ,op1) + (car op1)) + (_ (unless filter + (error "Filter is empty"))))) + +(defun tablist-filter-map (fn filter) + (pcase filter + (`(,(or `and `or `not) . ,tail) + (cons (car filter) + (mapcar (lambda (f) + (tablist-filter-map fn f)) + tail))) + (_ (funcall fn filter)))) + +;; +;; *Reading Filter +;; + +(defvar tablist-filter-edit-history nil) +(defvar tablist-filter-edit-display-help t) + +(defun tablist-filter-edit-filter (prompt &optional + initial-filter history + validate-fn) + (let* ((str (tablist-filter-unparse initial-filter)) + (filter initial-filter) + (validate-fn (or validate-fn 'identity)) + error done) + (save-window-excursion + (when tablist-filter-edit-display-help + (tablist-filter-help t)) + (while (not done) + (minibuffer-with-setup-hook + (lambda () + (when error + (when (car error) + (goto-char (+ (field-beginning) + (car error))) + (skip-chars-backward " \t\n")) + (minibuffer-message "%s" (cdr error)) + (setq error nil))) + (setq str (propertize + (read-string prompt str + (or history 'tablist-filter-edit-history))) + done t)) + (condition-case err + (progn + (setq filter (tablist-filter-parse str)) + (funcall validate-fn filter)) + (error + (setq done nil) + (setq error (cons (car-safe (cddr err)) nil)) + (when (car error) + (setq str (with-temp-buffer + (insert str) + (goto-char (car error)) + (set-text-properties + (progn + (skip-chars-backward " \t\n") + (backward-char) + (point)) + (min (car error) (point-max)) + '(face error rear-nonsticky t)) + (buffer-string)))) + (setcdr error (error-message-string err))))) + filter))) + +(provide 'tablist-filter) +;; Local Variables: +;; outline-regexp: ";;\\(\\(?:[;*]+ \\| \\*+\\)[^\s\t\n]\\|###autoload\\)\\|(" +;; indent-tabs-mode: nil +;; End: +;;; tablist-filter.el ends here diff --git a/org/elpa/tablist-20230321.705/tablist-pkg.el b/org/elpa/tablist-20230321.705/tablist-pkg.el new file mode 100644 index 0000000..5627773 --- /dev/null +++ b/org/elpa/tablist-20230321.705/tablist-pkg.el @@ -0,0 +1,11 @@ +(define-package "tablist" "20230321.705" "Extended tabulated-list-mode" + '((emacs "24.3")) + :commit "5f7b71a92bfb25418d7da86ad9c45f14b149496f" :authors + '(("Andreas Politz" . "politza@fh-trier.de")) + :maintainer + '("Andreas Politz" . "politza@fh-trier.de") + :keywords + '("extensions" "lisp")) +;; Local Variables: +;; no-byte-compile: t +;; End: diff --git a/org/elpa/tablist-20230321.705/tablist.el b/org/elpa/tablist-20230321.705/tablist.el new file mode 100644 index 0000000..4fbeb6c --- /dev/null +++ b/org/elpa/tablist-20230321.705/tablist.el @@ -0,0 +1,1947 @@ +;;; tablist.el --- Extended tabulated-list-mode -*- lexical-binding: t -*- + +;; Copyright (C) 2013, 2014 Andreas Politz + +;; Author: Andreas Politz +;; Keywords: extensions, lisp +;; Package: tablist +;; Version: 1.0 +;; Package-Requires: ((emacs "24.3")) + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: +;; +;; This package adds marks and filters to tabulated-list-mode. It +;; also kind of puts a dired face on tabulated list buffers. +;; +;; It can be used by deriving from tablist-mode and some features by +;; using tablist-minor-mode inside a tabulated-list-mode buffer. +;; + +;;; Code: + +(require 'cl-lib) +(require 'ring) +(require 'tabulated-list) +(require 'dired) +(require 'tablist-filter) + +;; +;; *Macros +;; + +(defmacro tablist-save-marks (&rest body) + "Eval body, while preserving all marks." + (let ((marks (make-symbol "marks"))) + `(let (,marks) + (save-excursion + (goto-char (point-min)) + (let ((re "^\\([^ ]\\)")) + (while (re-search-forward re nil t) + (push (cons (tabulated-list-get-id) + (tablist-get-mark-state)) + ,marks)))) + (unwind-protect + (progn ,@body) + (save-excursion + (dolist (m ,marks) + (let ((id (pop m))) + (goto-char (point-min)) + (while (and id (not (eobp))) + (when (equal id (tabulated-list-get-id)) + (tablist-put-mark-state m) + (setq id nil)) + (forward-line))))))))) + +(defmacro tablist-with-remembering-entry (&rest body) + "Remember where body left of and restore previous position. + +If the current entry is still visible, move to it. Otherwise move +to the next visible one after it. If that also fails, goto to +the beginning of the buffer. Finally move point to the major +column." + (declare (indent 0) (debug t)) + (let ((re (make-symbol "re")) + (id (make-symbol "id")) + (col (make-symbol "col"))) + `(let ((,re + (replace-regexp-in-string + "[\t ]+" "[\t ]*" (regexp-quote + (or (thing-at-point 'line) "")) + t t)) + (,id (tabulated-list-get-id)) + (,col (tablist-current-column))) + (progn + ,@body + (let (success pos) + (goto-char (point-min)) + (setq pos (point)) + (while (and (setq success (re-search-forward ,re nil t)) + (> (point) (prog1 pos (setq pos (point)))) + (forward-line -1) + (not (equal ,id (tabulated-list-get-id)))) + (forward-line)) + (unless success + (goto-char (point-min)) + (while (and (not (eobp)) + (not success)) + (if (equal (tabulated-list-get-id) ,id) + (setq success t) + (forward-line)))) + (unless (and success (not (invisible-p (point)))) + (goto-char (point-min))) + (tablist-skip-invisible-entries) + (tablist-move-to-column + (or ,col (car (tablist-major-columns)))) + (dolist (win (get-buffer-window-list)) + (set-window-point win (point)))))))) + +(defmacro tablist-with-filter-displayed (&rest body) + "Display the current filter in the mode while evalling BODY." + (let ((state (make-symbol "state"))) + `(let ((,state (tablist-display-filter 'state))) + (tablist-display-filter t) + (unwind-protect + (progn ,@body) + (tablist-display-filter ,state))))) + +;; +;; *Mode Maps +;; + +(defvar tablist-mode-filter-map + (let ((kmap (make-sparse-keymap))) + (define-key kmap "p" #'tablist-pop-filter) + (define-key kmap "r" #'tablist-push-regexp-filter) + (define-key kmap "=" #'tablist-push-equal-filter) + (define-key kmap "n" #'tablist-push-numeric-filter) + (define-key kmap "!" #'tablist-negate-filter) + (define-key kmap "t" #'tablist-toggle-first-filter-logic) + (define-key kmap "/" #'tablist-display-filter) + (define-key kmap "z" #'tablist-suspend-filter) + + (define-key kmap "a" #'tablist-push-named-filter) + (define-key kmap "s" #'tablist-name-current-filter) + (define-key kmap "D" #'tablist-delete-named-filter) + (define-key kmap "d" #'tablist-deconstruct-named-filter) + (define-key kmap "e" #'tablist-edit-filter) + (define-key kmap "C" #'tablist-clear-filter) + kmap)) + +(defvar tablist-mode-mark-map + (let ((kmap (make-sparse-keymap))) + (define-key kmap "c" #'tablist-change-marks) + (define-key kmap "!" #'tablist-unmark-all-marks) + (define-key kmap "r" #'tablist-mark-items-regexp) + (define-key kmap "n" #'tablist-mark-items-numeric) + (define-key kmap "m" #'tablist-mark-forward) + kmap)) + +(defvar tablist-mode-regexp-map + (let ((kmap (make-sparse-keymap))) + ;; (define-key kmap "&" #'tablist-flag-gargabe-items) + (define-key kmap "m" #'tablist-mark-items-regexp) + kmap)) + +(defvar tablist-minor-mode-map + (let ((kmap (make-sparse-keymap))) + (define-key kmap "m" #'tablist-mark-forward) + (define-key kmap (kbd "DEL") #'tablist-unmark-backward) + (define-key kmap "k" #'tablist-do-kill-lines) + (define-key kmap "U" #'tablist-unmark-all-marks) + (define-key kmap "u" #'tablist-unmark-forward) + (define-key kmap "t" #'tablist-toggle-marks) + + (define-key kmap (kbd "TAB") #'tablist-forward-column) + (define-key kmap "\t" #'tablist-forward-column) + (define-key kmap [backtab] #'tablist-backward-column) + + (define-key kmap "%" tablist-mode-regexp-map) + (define-key kmap "*" tablist-mode-mark-map) + (define-key kmap "/" tablist-mode-filter-map) + + ;; (define-key kmap "e" #'tablist-edit-column) + ;; (define-key kmap "i" #'tablist-insert-entry) + (define-key kmap "s" #'tablist-sort) + (define-key kmap [remap back-to-indentation] #'tablist-move-to-major-column) + (define-key kmap [remap next-line] #'tablist-next-line) + (define-key kmap [remap previous-line] #'tablist-previous-line) + (define-key kmap "<" #'tablist-shrink-column) + (define-key kmap ">" #'tablist-enlarge-column) + (define-key kmap "q" #'tablist-quit) + (define-key kmap "G" #'tablist-revert) + (define-key kmap (kbd "C-c C-e") #'tablist-export-csv) + kmap)) + +(defvar tablist-mode-map + (let ((kmap (copy-keymap tablist-minor-mode-map))) + (set-keymap-parent kmap tabulated-list-mode-map) + (define-key kmap "d" #'tablist-flag-forward) + (define-key kmap (kbd "RET") #'tablist-find-entry) + (define-key kmap "f" #'tablist-find-entry) + ;; (define-key kmap "~" #'tablist-flag-gargabe-items) + (define-key kmap "D" #'tablist-do-delete) + ;; (define-key kmap "C" #'tablist-do-copy) + ;; (define-key kmap "R" #'tablist-do-rename) + (define-key kmap "x" #'tablist-do-flagged-delete) + ;; (define-key kmap "F" #'tablist-find-marked-items) + ;; (define-key kmap (kbd "C-o") #'tablist-display-item) + kmap)) + +;; +;; *Variables +;; + +;; Marking +(defvar tablist-umark-filtered-entries t) +(defvar tablist-marker-char dired-marker-char + "The character used for marking.") +(defvar tablist-marker-face 'dired-mark + "The face used for the mark character.") +(defvar tablist-marked-face 'dired-marked + "The face used for marked major columns.") + +;; Operations +(defvar-local tablist-operations-function nil + "A function for handling operations on the entries. + +The function is called with varying number of arguments, while +the first one is always a symbol describing one of the following +operations. + +`supported-operations' + +This is the only mandatory operation. There are no other +arguments and the function should return a list of symbols of +supported operations. + +`delete' + +The 2nd argument will be a list of entry ID's. The function +should somehow delete these entries and update +`tabulated-list-entries'. + +`find-entry' + +The 2nd argument is the ID of an entry. The function should +somehow find/display this entry, i.e. a kind of default +operation. + +`edit-column' + +The function is called with 3 further arguments: ID, INDEX and +NEW-COLUMN, where ID represents the entry to edit, INDEX is the index +of the column and NEW-COLUMN is the proposed new value for this +column. It should either + +i. return a new edited complete entry and update +`tabulated-list-entries', or + +ii. throw an error, if NEW-COLUMN is not a valid value for this +column. + +`complete' + +The function is called with 4 further arguments: ID, INDEX, +STRING and POS, where ID represents an entry, INDEX is the index +of the column to complete, STRING it's current value and POS an +offset of the current position of point into STRING. + +The function should return a collection for this column, suitable +as argument for the function `completion-in-region'.") + +;; Differentiating columns +(defvar-local tablist-major-columns nil + "Columns used to mark and when querying.") + +;; Filter +(defvar-local tablist-current-filter nil) +(defvar-local tablist-filter-suspended nil) +(defvar tablist-named-filter nil) + +;; History variables +(defvar tablist-column-name-history nil) + +;; Hooks +(defvar tablist-selection-changed-functions nil + "A hook run when ever point moves to a different entry.") + +;; Context Window +(defvar-local tablist-context-window nil) +(defvar-local tablist-context-window-function nil) +(defvar tablist-context-window-display-action + `((display-buffer-reuse-window + tablist-display-buffer-split-below-and-attach) + (window-height . 0.25) + (inhibit-same-window . t))) + +;; +;; *Setup +;; + +(defvar savehist-additional-variables) +(add-hook 'savehist-save-hook + (lambda nil + (add-to-list 'savehist-additional-variables 'tablist-named-filter))) + +;;;###autoload +(define-minor-mode tablist-minor-mode + "Toggle tablist minor mode." + :global nil + (unless (derived-mode-p 'tabulated-list-mode) + (error "Buffer is not in Tabulated List Mode")) + (tablist-init (not tablist-minor-mode))) + +;;;###autoload +(define-derived-mode tablist-mode tabulated-list-mode "TL" + (tablist-init)) + +(defun tablist-init (&optional disable) + (let ((cleaned-misc (cl-remove 'tablist-current-filter + mode-line-misc-info :key #'car-safe))) + (cond + ((not disable) + (set (make-local-variable 'mode-line-misc-info) + (append + (list + (list 'tablist-current-filter + '(:eval (format " [%s]" + (if tablist-filter-suspended + "suspended" + "filtered"))))))) + (add-hook 'post-command-hook + 'tablist-selection-changed-handler nil t) + (add-hook 'tablist-selection-changed-functions + 'tablist-context-window-update nil t)) + (t + (setq mode-line-misc-info cleaned-misc) + (remove-hook 'post-command-hook + 'tablist-selection-changed-handler t) + (remove-hook 'tablist-selection-changed-functions + 'tablist-context-window-update t))))) + +(defun tablist-quit () + (interactive) + (tablist-hide-context-window) + (quit-window)) + +(defvar-local tablist-selected-id nil) +(defvar tablist-edit-column-minor-mode) + +(defun tablist-selection-changed-handler () + (unless tablist-edit-column-minor-mode + (let ((id tablist-selected-id) + (selected (tabulated-list-get-id))) + (unless (eq selected id) + (setq tablist-selected-id selected) + (run-hook-with-args + 'tablist-selection-changed-functions + tablist-selected-id))))) + +(defvar tablist-context-window-update--timer nil) + +(defun tablist-context-window-update (&optional id) + (when (and tablist-context-window-function + (window-live-p tablist-context-window) + (not tablist-edit-column-minor-mode)) + (unless id + (setq id (tabulated-list-get-id))) + (when (timerp tablist-context-window-update--timer) + (cancel-timer tablist-context-window-update--timer)) + (setq tablist-context-window-update--timer + (run-with-idle-timer 0.1 nil + (lambda (fn window) + (when (window-live-p window) + (with-selected-window window + (set-window-dedicated-p nil nil) + (save-selected-window + (funcall fn id)) + (when (window-live-p (selected-window)) + (set-window-dedicated-p nil t))))) + tablist-context-window-function + tablist-context-window)))) + +(defun tablist-display-context-window () + (interactive) + (unless tablist-context-window-function + (error "No function for handling a context is defined")) + (unless (window-live-p tablist-context-window) + (setq tablist-context-window + (display-buffer + (current-buffer) + tablist-context-window-display-action))) + (prog1 + tablist-context-window + (tablist-context-window-update))) + +(defun tablist-hide-context-window () + (interactive) + (when (window-live-p tablist-context-window) + (let ((ignore-window-parameters t)) + (delete-window tablist-context-window))) + (setq tablist-context-window nil)) + +(defun tablist-toggle-context-window () + (interactive) + (if (window-live-p tablist-context-window) + (tablist-hide-context-window) + (tablist-display-context-window))) + +;; +;; *Marking +;; + +(defun tablist-revert () + "Revert the list with marks preserved, position kept." + (interactive) + (tablist-save-marks + (tablist-with-remembering-entry + (tabulated-list-revert)))) + +(defun tablist-major-columns () + (if (null tablist-major-columns) + (number-sequence 0 (1- (length tabulated-list-format))) + (if (numberp tablist-major-columns) + (list tablist-major-columns) + tablist-major-columns))) + +(defun tablist-put-mark (&optional pos) + "Put a mark before the entry at POS. + +POS defaults to point. Use `tablist-marker-char', +`tablist-marker-face', `tablist-marked-face' and +`tablist-major-columns' to determine how to mark and what to put +a face on." + (when (or (null tabulated-list-padding) + (< tabulated-list-padding 1)) + (setq tabulated-list-padding 1) + (tabulated-list-revert)) + (save-excursion + (and pos (goto-char pos)) + (unless (tabulated-list-get-id) + (error "No entry at this position")) + (let ((inhibit-read-only t)) + (tabulated-list-put-tag + (string tablist-marker-char)) + (put-text-property + (point-at-bol) + (1+ (point-at-bol)) + 'face tablist-marker-face) + (let ((columns (tablist-column-offsets))) + (dolist (c (tablist-major-columns)) + (when (and (>= c 0) + (< c (length columns))) + (let ((beg (+ (point-at-bol) + (nth c columns))) + (end (if (= c (1- (length columns))) + (point-at-eol) + (+ (point-at-bol) + (nth (1+ c) columns))))) + (cond + ((and tablist-marked-face + (not (eq tablist-marker-char ?\s))) + (tablist--save-face-property beg end) + (put-text-property + beg end 'face tablist-marked-face)) + (t (tablist--restore-face-property beg end)))))))))) + +(defun tablist-mark-forward (&optional arg interactive) + "Mark ARG entries forward. + +ARG is interpreted as a prefix-arg. If interactive is non-nil, +maybe use the active region instead of ARG. + +See `tablist-put-mark' for how entries are marked." + (interactive (list current-prefix-arg t)) + (cond + ;; Mark files in the active region. + ((and interactive (use-region-p)) + (save-excursion + (goto-char (region-beginning)) + (beginning-of-line) + (tablist-repeat-over-lines + (1+ (count-lines + (point) + (save-excursion + (goto-char (region-end)) + (beginning-of-line) + (point)))) + 'tablist-put-mark))) + ;; Mark the current (or next ARG) files. + (t + (tablist-repeat-over-lines + (prefix-numeric-value arg) + 'tablist-put-mark)))) + +(defun tablist-mark-backward (&optional arg interactive) + "Mark ARG entries backward. + +See `tablist-mark-forward'." + (interactive (list current-prefix-arg t)) + (tablist-mark-forward (- (prefix-numeric-value arg)) + interactive)) + +(defun tablist-unmark-forward (&optional arg interactive) + "Unmark ARG entries forward. + +See `tablist-mark-forward'." + (interactive (list current-prefix-arg t)) + (let ((tablist-marker-char ?\s) + tablist-marked-face) + (tablist-mark-forward arg interactive))) + +(defun tablist-unmark-backward (&optional arg interactive) + "Unmark ARG entries backward. + +See `tablist-mark-forward'." + (interactive (list current-prefix-arg t)) + (let ((tablist-marker-char ?\s) + tablist-marked-face) + (tablist-mark-backward arg interactive))) + +(defun tablist-flag-forward (&optional arg interactive) + "Flag ARG entries forward. + +See `tablist-mark-forward'." + (interactive (list current-prefix-arg t)) + (let ((tablist-marker-char ?D) + (tablist-marked-face 'dired-flagged)) + (tablist-mark-forward arg interactive))) + +(defun tablist-change-marks (old new) + "Change all OLD marks to NEW marks. + +OLD and NEW are both characters used to mark files." + (interactive + (let* ((cursor-in-echo-area t) + (old (progn (message "Change (old mark): ") (read-char))) + (new (progn (message "Change %c marks to (new mark): " old) + (read-char)))) + (list old new))) + (when (eq new ?\n) + (error "Mark character \\n is not allowed")) + (let ((default-mark-p (equal tablist-marker-char new)) + (tablist-marker-char old)) + (save-excursion + (tablist-map-over-marks + (lambda nil + (pcase new + (?D + (tablist-flag-forward 1)) + (_ + (let ((tablist-marker-char new) + (tablist-marked-face + (and default-mark-p + tablist-marked-face))) + (tablist-put-mark))))))))) + +(defun tablist-unmark-all-marks (&optional marks interactive) + "Remove all marks in MARKS. + +MARKS should be a string of mark characters to match and defaults +to all marks. Interactively, remove all marks, unless a prefix +arg was given, in which case ask about which ones to remove. +Give a message, if interactive is non-nil. + +Returns the number of unmarked marks." + (interactive + (list (if current-prefix-arg + (read-string "Remove marks: ")) t)) + (let ((re (if marks + (tablist-marker-regexp marks) + "^[^ ]")) + (removed 0)) + (save-excursion + (goto-char (point-min)) + (while (re-search-forward re nil t) + (let ((tablist-marker-char ?\s) + tablist-marker-face + tablist-marked-face) + (tablist-put-mark)) + (cl-incf removed))) + (when interactive + (message "Removed %d marks" removed)) + removed)) + +(defun tablist-toggle-marks () + "Unmark all marked and mark all unmarked entries. + +See `tablist-put-mark'." + (interactive) + (let ((marked-re (tablist-marker-regexp)) + (not-marked-re + (let ((tablist-marker-char ?\s)) + (tablist-marker-regexp)))) + (save-excursion + (goto-char (point-min)) + (tablist-skip-invisible-entries) + (while (not (eobp)) + (cond + ((looking-at marked-re) + (save-excursion (tablist-unmark-backward -1))) + ((looking-at not-marked-re) + (tablist-put-mark))) + (tablist-forward-entry))) + (tablist-move-to-major-column))) + +(defun tablist-get-marked-items (&optional arg distinguish-one-marked) + "Return marked or ARG entries." + (let ((items (save-excursion + (tablist-map-over-marks + (lambda () (cons (tabulated-list-get-id) + (tabulated-list-get-entry))) + arg nil distinguish-one-marked)))) + (if (and distinguish-one-marked + (eq (car items) t)) + items + (nreverse items)))) + +(defun tablist-mark-items-regexp (column-name regexp) + "Mark entries matching REGEXP in column COLUMN-NAME." + (interactive + (tablist-read-regexp-filter "Mark" current-prefix-arg )) + (tablist-map-with-filter + 'tablist-put-mark + `(=~ ,column-name ,regexp))) + +(defun tablist-mark-items-numeric (binop column-name operand) + "Mark items fulfilling BINOP with arg OPERAND in column COLUMN-NAME. + +First the column's value is coerced to a number N. Then the test +proceeds as \(BINOP N OPERAND\)." + (interactive + (tablist-read-numeric-filter "Mark" current-prefix-arg)) + (tablist-map-with-filter + 'tablist-put-mark + `(,binop ,column-name ,operand))) + +(defun tablist-map-over-marks (fn &optional arg show-progress + distinguish-one-marked) + (prog1 + (cond + ((and arg (integerp arg)) + (let (results) + (tablist-repeat-over-lines + arg + (lambda () + (if show-progress (sit-for 0)) + (push (funcall fn) results))) + (if (< arg 0) + (nreverse results) + results))) + (arg + ;; non-nil, non-integer ARG means use current item: + (tablist-skip-invisible-entries) + (unless (eobp) + (list (funcall fn)))) + (t + (cl-labels ((search (re) + (let (success) + (tablist-skip-invisible-entries) + (while (and (setq success + (re-search-forward re nil t)) + (invisible-p (point))) + (tablist-forward-entry)) + success))) + (let ((regexp (tablist-marker-regexp)) + next-position results found) + (save-excursion + (goto-char (point-min)) + ;; remember position of next marked file before BODY + ;; can insert lines before the just found file, + ;; confusing us by finding the same marked file again + ;; and again and... + (setq next-position (and (search regexp) + (point-marker)) + found (not (null next-position))) + (while next-position + (goto-char next-position) + (if show-progress (sit-for 0)) + (push (funcall fn) results) + ;; move after last match + (goto-char next-position) + (forward-line 1) + (set-marker next-position nil) + (setq next-position (and (search regexp) + (point-marker))))) + (if (and distinguish-one-marked (= (length results) 1)) + (setq results (cons t results))) + (if found + results + (unless (or (eobp) (invisible-p (point))) + (list (funcall fn)))))))) + (tablist-move-to-major-column))) + +(defun tablist-marker-regexp (&optional marks) + "Return a regexp matching marks in MARKS. + +MARKS should be a string of mark characters to match and defaults +to the current value of `tablist-marker-char' as a string." + (concat (format "^[%s]" + (or marks (string tablist-marker-char))))) + +(defun tablist-get-mark-state () + "Return the mark state of the entry at point." + (save-excursion + (beginning-of-line) + (when (looking-at "^\\([^ ]\\)") + (let ((mark (buffer-substring + (match-beginning 1) + (match-end 1)))) + (tablist-move-to-major-column) + (list (aref mark 0) + (get-text-property 0 'face mark) + (get-text-property (point) 'face)))))) + +(defun tablist-put-mark-state (state) + "Set the mark of the entry at point according to STATE. + +STATE is a return value of `tablist-get-mark-state'." + (cl-destructuring-bind (tablist-marker-char + tablist-marker-face + tablist-marked-face) + state + (tablist-put-mark))) + +(defun tablist-mark-prompt (arg items) + "Return a string suitable for use in a tablist prompt." + ;; distinguish-one-marked can cause the first element to be just t. + (if (eq (car items) t) (setq items (cdr items))) + (let ((count (length items))) + (if (= count 1) + (car items) + ;; more than 1 item: + (if (integerp arg) + ;; abs(arg) = count + ;; Perhaps this is nicer, but it also takes more screen space: + ;;(format "[%s %d items]" (if (> arg 0) "next" "previous") + ;; count) + (format "[next %d item%s]" + arg (dired-plural-s arg)) + (format "%c [%d item%s]" dired-marker-char count + (dired-plural-s count)))))) + +;; +;; *Movement +;; + +(defun tablist-forward-entry (&optional n) + "Move past the next N unfiltered entries." + (unless n (setq n 1)) + (while (and (> n 0) + (not (eobp))) + (forward-line) + (when (invisible-p (point)) + (tablist-skip-invisible-entries)) + (cl-decf n)) + (while (and (< n 0) + (not (bobp))) + (forward-line -1) + (when (invisible-p (point)) + (tablist-skip-invisible-entries t)) + (cl-incf n)) + n) + +(defun tablist-next-line (&optional n) + (interactive "p") + (when (and (< n 0) + (save-excursion + (end-of-line 0) + (tablist-skip-invisible-entries t) + (bobp))) + (signal 'beginning-of-buffer nil)) + (when (and (> n 0) + (save-excursion + (tablist-forward-entry) + (eobp))) + (signal 'end-of-buffer nil)) + + (let ((col (tablist-current-column))) + (tablist-forward-entry (or n 1)) + (if col + (tablist-move-to-column col) + (tablist-move-to-major-column)))) + +(defun tablist-previous-line (&optional n) + (interactive "p") + (tablist-next-line (- (or n 1)))) + +(defun tablist-repeat-over-lines (arg function) + "Call FUNCTION for the next ARG entries." + ;; Move out of potentially invisible area. + (tablist-skip-invisible-entries) + (let ((pos (make-marker))) + (while (and (> arg 0) + (not (eobp))) + (cl-decf arg) + (save-excursion + (tablist-forward-entry) + (move-marker pos (1+ (point)))) + (unless (eobp) + (save-excursion (funcall function))) + ;; Advance to the next line--actually, to the line that *was* next. + ;; (If FUNCTION inserted some new lines in between, skip them.) + (goto-char pos)) + (while (and (< arg 0) (not (bobp))) + (cl-incf arg) + (tablist-forward-entry -1) + (save-excursion (funcall function))) + (move-marker pos nil) + (tablist-move-to-major-column))) + +(defun tablist-move-to-column (n) + "Move to the N'th list column." + (interactive "p") + (when (tabulated-list-get-id) + (let ((columns (tablist-column-offsets))) + (when (or (< n 0) + (>= n (length columns))) + (error "No such column: %s" n)) + (beginning-of-line) + (forward-char (nth n columns)) + (when (and (plist-get (nthcdr 3 (elt tabulated-list-format n)) + :right-align) + (not (= n (1- (length columns))))) + (forward-char (1- (car (cdr (elt tabulated-list-format n))))))))) + +(defun tablist-move-to-major-column (&optional first-skip-invisible-p) + "Move to the first major column." + (interactive (list t)) + (when first-skip-invisible-p + (tablist-skip-invisible-entries)) + (tablist-move-to-column (car (tablist-major-columns)))) + +(defun tablist-forward-column (n) + "Move n columns forward, while wrapping around." + (interactive "p") + (unless (tabulated-list-get-id) + (error "No entry on this line")) + (let* ((columns (tablist-column-offsets)) + (current (1- (length columns)))) + ;; find current column + (while (and (>= current 0) + (> (nth current columns) + (current-column))) + (cl-decf current)) + ;; there may be an invisible spec here + (when (bolp) + (forward-char)) + ;; before any columns + (when (< current 0) + (goto-char (+ (point-at-bol) (if (> n 0) + (car columns) + (car (last columns))))) + (setq n (* (cl-signum n) (1- (abs n))))) + (when (/= n 0) + (tablist-move-to-column + (mod (+ current n) (length columns)))))) + +(defun tablist-backward-column (n) + "Move n columns backward, while wrapping around." + (interactive "p") + (tablist-forward-column (- n))) + +;; +(defun tablist-skip-invisible-entries (&optional backward) + "Skip invisible entries BACKWARD or forward. + +Do nothing, if the entry at point is visible. Otherwise move to +the beginning of the next visible entry in the direction +determined by BACKWARD. + +Return t, if point is now in a visible area." + + (cond + ((and backward + (not (bobp)) + (get-text-property (point) 'invisible)) + (when (get-text-property (1- (point)) 'invisible) + (goto-char (previous-single-property-change + (point) + 'invisible nil (point-min)))) + (forward-line -1)) + ((and (not backward) + (not (eobp)) + (get-text-property (point) 'invisible)) + (goto-char (next-single-property-change + (point) + 'invisible nil (point-max))))) + (not (invisible-p (point)))) + +;; +;; *Operations +;; + +(defun tablist-yes-or-no-p (operation arg items) + "Query the user whether to proceed with some operation. + +Operation should be a symbol or string describing the operation, +ARG the prefix-arg of the command used in +`tablist-get-marked-items' or elsewhere, to get the ITEMS." + + (let ((pp-items (mapcar 'tablist-pretty-print-entry + (mapcar 'cdr items))) + dired-no-confirm + (op-str (upcase-initials + (if (stringp operation) + operation + (symbol-name operation))))) + (dired-mark-pop-up + (format " *%s*" op-str) nil + pp-items + dired-deletion-confirmer + (format "%s %s " + op-str + (tablist-mark-prompt arg pp-items))))) + +(defun tablist-operation-available-p (op) + (and (functionp tablist-operations-function) + (memq op (funcall tablist-operations-function + 'supported-operations)))) + +(defun tablist-do-delete (&optional arg) + "Delete ARG entries." + (interactive "P") + (unless (tablist-operation-available-p 'delete) + (error "Deleting entries is not available in this buffer")) + (let ((items (tablist-get-marked-items arg))) + (when (tablist-yes-or-no-p 'delete arg items) + (tablist-do-kill-lines arg) + (funcall tablist-operations-function + 'delete (mapcar 'car items)) + (tablist-move-to-major-column)))) + +(defun tablist-do-flagged-delete (&optional interactive) + "Delete all entries marked with a D." + (interactive "p") + (let* ((tablist-marker-char ?D)) + (if (save-excursion + (goto-char (point-min)) + (re-search-forward (tablist-marker-regexp) nil t)) + (tablist-do-delete) + (or (not interactive) + (message "(No deletions requested)"))))) + +(defun tablist-do-kill-lines (&optional arg interactive) + "Remove ARG lines from the display." + (interactive (list current-prefix-arg t)) + (save-excursion + (let ((positions + (tablist-map-over-marks 'point arg)) + (inhibit-read-only t)) + (dolist (pos positions) + (goto-char pos) + (tabulated-list-delete-entry)) + (when interactive + (message (format "Killed %d line%s" + (length positions) + (dired-plural-s (length positions)))))))) + +(defun tablist-do-operation (arg fn operation &optional delete-p revert-p) + "Operate on marked items. + +ARG should be the `current-prefix-arg', FN is a function of two +arguments \(ID ENTRY\) handling the operation. It gets called +repeatedly with all marked items. OPERATION is a symbol or string +describing the operation, it is used for display. + +Optional non-nil DELETE-P means, remove the items from the display. +Optional REVERT-P means, revert the display afterwards." + (let ((items (tablist-get-marked-items arg))) + (unless items + (error "No items marked")) + (when (tablist-yes-or-no-p operation arg items) + (when delete-p + (tablist-do-kill-lines arg)) + (dolist (item items) + (funcall fn (car item))) + (when revert-p + (tablist-revert)) + (tablist-move-to-major-column)))) + +;; +;; *Editing +;; +(defvar tablist-edit-column-minor-mode-map + (let ((kmap (make-sparse-keymap))) + (set-keymap-parent kmap (current-global-map)) + (define-key kmap [remap self-insert-command] #'self-insert-command) + (define-key kmap "\r" #'tablist-edit-column-commit) + (define-key kmap (kbd "C-g") #'tablist-edit-column-quit) + (define-key kmap (kbd "C-c C-c") #'tablist-edit-column-commit) + (define-key kmap (kbd "C-c C-q") #'tablist-edit-column-quit) + (define-key kmap "\t" #'tablist-edit-column-complete) + (define-key kmap (kbd "TAB") #'tablist-edit-column-complete) + (define-key kmap [remap end-of-buffer] #'end-of-line) + (define-key kmap [remap beginning-of-buffer] #'beginning-of-line) + (define-key kmap [remap mark-whole-buffer] #'tablist-edit-column-mark-field) + kmap)) + +(define-minor-mode tablist-edit-column-minor-mode + "Toggle tablist-edit-column minor mode." + :global nil + (unless (or tablist-minor-mode + (derived-mode-p 'tablist-mode)) + (error "Not in a tablist buffer")) + (cond + (tablist-edit-column-minor-mode + (add-to-list 'mode-line-misc-info + '(tablist-edit-column-minor-mode "[edit]")) + (add-hook 'post-command-hook 'tablist-edit-column-constrain-point nil t) + (read-only-mode -1)) + (t + (remove-hook 'post-command-hook 'tablist-edit-column-constrain-point t) + (read-only-mode 1)))) + +(defun tablist-edit-column (&optional n) + (interactive "P") + (unless n (setq n (tablist-current-column))) + (tablist-assert-column-editable n) + (let* ((offsets (append (tablist-column-offsets) + (list (- (point-at-eol) + (point-at-bol))))) + (beg (+ (point-at-bol) + (nth n offsets))) + (end (+ (point-at-bol) + (nth (1+ n) offsets))) + (entry (tabulated-list-get-entry beg)) + (inhibit-read-only t) + (inhibit-field-text-motion t) + (alist `((entry . ,entry) + (column . ,n) + (id . ,(tabulated-list-get-id beg)))) + ov) + (goto-char beg) + (delete-region beg end) + (add-text-properties + (point-at-bol) (point-at-eol) + '(read-only t field t)) + (unless (= beg (point-at-bol)) + (put-text-property (1- beg) beg 'rear-nonsticky t)) + (save-excursion + ;; Keep one read-only space at the end for keeping text + ;; properties. + (insert + (propertize + (concat + (tablist-nth-entry n entry) + (propertize " " + 'display `(space :align-to ,(- end (point-at-bol))))) + 'field nil + 'front-sticky '(tablist-edit) + 'rear-nonsticky '(read-only field) + 'tablist-edit alist)) + (setq end (point))) + (add-text-properties + (1- end) end '(read-only t field 'tablist-edit-end)) + (setq ov (make-overlay beg end)) + (overlay-put ov 'priority 9999) + (overlay-put ov 'face '(:background "deep sky blue" :foreground "white")) + (overlay-put ov 'evaporate t) + (overlay-put ov 'tablist-edit t) + (tablist-edit-column-minor-mode 1))) + +(defun tablist-edit-column-quit () + (interactive) + (tablist-edit-column-commit t)) + +(defun tablist-edit-column-commit (&optional abandon-edit) + (interactive (list current-prefix-arg)) + (let ((inhibit-read-only t) + (inhibit-field-text-motion t) + bounds) + (condition-case nil + (setq bounds (tablist-edit-column-bounds)) + (error + (tablist-edit-column-minor-mode -1) + (tabulated-list-revert) + (put-text-property (point-min) (point-max) + 'tablist-edit nil) + (error "Unable to complete the edit"))) + (let* ((beg (car bounds)) + (end (cdr bounds)) + (alist (get-text-property beg 'tablist-edit)) + (column (cdr (assq 'column alist))) + (id (cdr (assq 'id alist))) + (entry (cdr (assq 'entry alist))) + (item (buffer-substring-no-properties beg (1- end)))) + + (unless abandon-edit + ;; Throws an error, if item is invalid. + (setq entry (funcall tablist-operations-function + 'edit-column id column item))) + (tablist-edit-column-minor-mode -1) + (remove-overlays beg end 'tablist-edit t) + (put-text-property beg end 'tablist-edit nil) + (delete-region (point-at-bol) (1+ (point-at-eol))) + (save-excursion + (tabulated-list-print-entry id entry)) + (forward-char (nth column (tablist-column-offsets)))))) + +(defun tablist-edit-column-complete () + (interactive) + (unless (tablist-operation-available-p 'complete) + (error "Completion not available")) + (cl-destructuring-bind (beg &rest end) + (tablist-edit-column-bounds t) + (let* ((string (buffer-substring-no-properties + beg end)) + (alist (get-text-property beg 'tablist-edit)) + (completions (funcall tablist-operations-function + 'complete + (cdr (assq 'id alist)) + (cdr (assq 'column alist)) + string + (- (point) beg)))) + (unless completions + (error "No completions available")) + (completion-in-region beg end completions)))) + +(defun tablist-column-editable (n) + (and (tablist-operation-available-p 'edit-column) + (not (tablist-column-property n :read-only)))) + +(defun tablist-assert-column-editable (n) + (unless (and (>= n 0) + (< n (length tabulated-list-format))) + (error "Invalid column number: %s" n)) + (unless (tablist-operation-available-p 'edit-column) + (error "Editing columns not enabled in this buffer")) + (when (tablist-column-property n :read-only) + (error "This column is read-only"))) + +(defun tablist-edit-column-constrain-point () + (unless tablist-edit-column-minor-mode + (error "Not editing a column")) + (unless (get-text-property (point) 'tablist-edit) + (let ((bounds (tablist-edit-column-bounds))) + (when bounds + (if (> (point) (cdr bounds)) + (goto-char (1- (cdr bounds))) + (goto-char (car bounds))) + (point))))) + +(defun tablist-edit-column-bounds (&optional skip-final-space) + (unless tablist-edit-column-minor-mode + (error "Not editing a column")) + (let ((pos (next-single-property-change + (point) 'tablist-edit)) + beg end) + (cond + ((null pos) + (setq end (previous-single-property-change + (point-max) 'tablist-edit) + beg (previous-single-property-change + end 'tablist-edit))) + ((get-text-property pos 'tablist-edit) + (setq beg pos + end (next-single-property-change + pos 'tablist-edit))) + (pos + (setq end pos + beg (previous-single-property-change + pos 'tablist-edit)))) + + (unless (and beg end (get-text-property beg 'tablist-edit)) + (error "Unable to locate edited text")) + (cons beg (if skip-final-space (1- end) end)))) + +(defun tablist-edit-column-mark-field () + (interactive) + (push-mark (field-beginning)) + (push-mark (field-end) nil t) + (goto-char (field-beginning))) + +(defun tablist-find-entry (&optional id) + (interactive) + (unless (tablist-operation-available-p 'find-entry) + (error "Finding entries not supported in this buffer")) + (funcall tablist-operations-function + 'find-entry + (or id (tabulated-list-get-id)))) + +;; +;; *Utility +;; + +(defun tablist-column-property (n prop) + (plist-get + (nthcdr 3 (aref tabulated-list-format n)) + prop)) + +(defun tablist-current-column () + "Return the column number at point. + +Returns nil, if point is before the first column." + (let ((column + (1- (cl-position + (current-column) + (append (tablist-column-offsets) + (list most-positive-fixnum)) + :test (lambda (column offset) (> offset column)))))) + (when (>= column 0) + column))) + +(defun tablist-column-offsets () + "Return a list of column positions. + +This is a list of offsets from the beginning of the line." + (let ((cc tabulated-list-padding) + columns) + (dotimes (i (length tabulated-list-format)) + (let* ((c (aref tabulated-list-format i)) + (len (nth 1 c)) + (pad (or (plist-get (nthcdr 3 c) :pad-right) + 1))) + (push cc columns) + (when (numberp len) + (cl-incf cc len)) + (when pad + (cl-incf cc pad)))) + (nreverse columns))) + +(defun tablist-pretty-print-entry (item) + (mapconcat (lambda (i) + (tablist-nth-entry i item)) + (tablist-major-columns) " ")) + +(defun tablist--save-face-property (beg end) + ;; We need to distinguish ,,not set'' from ''no face''. + (unless (and (text-property-not-all beg end 'face nil) + (< beg end)) + (put-text-property beg (1+ beg) 'face 'default)) + (unless (text-property-not-all beg end 'tablist-saved-face nil) + (tablist-copy-text-property beg end 'face 'tablist-saved-face))) + +(defun tablist--restore-face-property (beg end) + (when (text-property-not-all beg end 'tablist-saved-face nil) + (tablist-copy-text-property beg end 'tablist-saved-face 'face))) + +(defun tablist-copy-text-property (beg end from to) + "Copy text property FROM to TO in region BEG to END." + (let ((inhibit-read-only t)) + (save-excursion + (while (< beg end) + (goto-char beg) + (put-text-property + (point) + (setq beg (next-single-property-change + (point) from nil end)) + to + (get-text-property (point) from)))))) + +;; +(defun tablist-read-column-name (arg &optional prompt default) + "Read the name of a column using ARG. + +If ARG is a number, return column ARG. +If ARG is nil, return DEFAULT or the current column. +Else ask the user, using PROMPT and DEFAULT." + (cond + ((numberp arg) + (or (tablist-column-name + (prefix-numeric-value arg)) + (error "No such column: %d" (prefix-numeric-value arg)))) + ((null arg) + (or default + (tablist-column-name + (or (tablist-current-column) + (car (tablist-major-columns)) + 0)))) + (t + (let* ((default (or default + (tablist-column-name + (car (tablist-major-columns))))) + (result + (completing-read + (format "%s %s: " + (or prompt "Use column") + (if default + (format "(default %s)" + default) + "")) + (tablist-column-names) + nil t nil 'tablist-column-name-history))) + (if (> (length result) 0) + result + (if (not default) + (error "No column selected") + default)))))) + +(defun tablist-column-name (n) + "Return the name of column N." + (when (and n + (>= n 0) + (< n (length tabulated-list-format))) + (substring-no-properties + (car (elt tabulated-list-format n)) 0))) + +(defun tablist-column-names () + "Return a list of all column-names." + (mapcar 'tablist-column-name + (number-sequence 0 (1- (length tabulated-list-format))))) + +(defun tablist-nth-entry (n &optional entry) + (unless entry (setq entry (tabulated-list-get-entry))) + (when (and entry + (>= n 0) + (< n (length entry))) + (let ((str (elt entry n))) + (if (stringp str) + str + (car str))))) + +(defun tablist-major-column-name () + "Return a list of the major column names." + (tablist-column-name (car (tablist-major-columns)))) + +(defun tablist-export-csv (&optional separator always-quote-p + invisible-p out-buffer display-p) + "Export a tabulated list to a CSV format. + +Use SEPARATOR (or ;) and quote if necessary (or always if +ALWAYS-QUOTE-P is non-nil). Only consider non-filtered entries, +unless invisible-p is non-nil. Create a buffer for the output or +insert it after point in OUT-BUFFER. Finally if DISPLAY-P is +non-nil, display this buffer. + +Return the output buffer." + + (interactive (list nil t nil nil t)) + (unless (derived-mode-p 'tabulated-list-mode) + (error "Not in Tabulated List Mode")) + (unless (stringp separator) + (setq separator (string (or separator ?\;)))) + (let* ((outb (or out-buffer + (get-buffer-create + (format "%s.csv" (buffer-name))))) + (escape-re (format "[%s\"\n]" separator)) + (header (tablist-column-names))) + (unless (buffer-live-p outb) + (error "Expected a live buffer: %s" outb)) + (cl-labels + ((printit (entry) + (insert + (mapconcat + (lambda (e) + (unless (stringp e) + (setq e (car e))) + (if (or always-quote-p + (string-match escape-re e)) + (concat "\"" + (replace-regexp-in-string "\"" "\"\"" e t t) + "\"") + e)) + entry separator)) + (insert ?\n))) + (with-current-buffer outb + (let ((inhibit-read-only t)) + (erase-buffer) + (printit header))) + (save-excursion + (goto-char (point-min)) + (unless invisible-p + (tablist-skip-invisible-entries)) + (while (not (eobp)) + (let* ((entry (tabulated-list-get-entry))) + (with-current-buffer outb + (let ((inhibit-read-only t)) + (printit entry))) + (if invisible-p + (forward-line) + (tablist-forward-entry))))) + (if display-p + (display-buffer outb)) + outb))) + +;; + +(defun tablist-enlarge-column (&optional column width) + "Enlarge column COLUMN by WIDTH. + +This function is lazy and therefore pretty slow." + (interactive + (list nil (* (prefix-numeric-value current-prefix-arg) + 3))) + (unless column (setq column (tablist-current-column))) + (unless column + (error "No column given and no entry at point")) + (unless width (setq width 1)) + (when (or (not (numberp column)) + (< column 0) + (>= column (length tabulated-list-format))) + (error "No such column: %d" column)) + (when (= column (1- (length tabulated-list-format))) + (error "Can't resize last column")) + + (let* ((cur-width (cadr (elt tabulated-list-format column)))) + (setcar (cdr (elt tabulated-list-format column)) + (max 3 (+ cur-width width))) + (tablist-with-remembering-entry + (tablist-save-marks + (tabulated-list-init-header) + (tabulated-list-print))))) + +(defun tablist-shrink-column (&optional column width) + (interactive + (list nil (* (prefix-numeric-value current-prefix-arg) + 3))) + (tablist-enlarge-column column (- (or width 1)))) + +;; *Sorting +;; + +(defun tablist-sort (&optional column) + "Sort the tabulated-list by COLUMN. + +COLUMN may be either a name or an index. The default compare +function is given by the `tabulated-list-format', which see. + +This function saves the current sort column and the inverse +sort-direction in the variable `tabulated-list-sort-key', which +also determines the default COLUMN and direction. + +The main difference to `tabulated-list-sort' is, that this +function sorts the buffer in-place and it ignores a nil sort +entry in `tabulated-list-format' and sorts on the column +anyway (why not ?)." + + (interactive + (list + (if (null current-prefix-arg) + (tablist-column-name + (or (tablist-current-column) + (car (tablist-major-columns)) + 0)) + (tablist-read-column-name + '(4) "Sort by column" + (tablist-column-name (car (tablist-major-columns))))))) + + (unless column + (setq column (or (car tabulated-list-sort-key) + (tablist-column-name (car (tablist-major-columns))) + (tablist-column-name 0)))) + (when (numberp column) + (let ((column-name (tablist-column-name column))) + (unless column-name + (error "No such column: %d" column)) + (setq column column-name))) + + (setq tabulated-list-sort-key + (cons column + (if (equal column (car tabulated-list-sort-key)) + (cdr tabulated-list-sort-key)))) + + (let* ((entries (if (functionp tabulated-list-entries) + (funcall tabulated-list-entries) + tabulated-list-entries)) + (reverse (cdr tabulated-list-sort-key)) + (n (tabulated-list--column-number ;;errors if column is n/a + (car tabulated-list-sort-key))) + (compare-fn (nth 2 (aref tabulated-list-format n)))) + + (when (or (null compare-fn) + (eq compare-fn t)) + (setq compare-fn + (lambda (a b) + (setq a (aref (cadr a) n)) + (setq b (aref (cadr b) n)) + (string< (if (stringp a) a (car a)) + (if (stringp b) b (car b)))))) + + (unless compare-fn + (error "This column cannot be sorted: %s" column)) + + (setcdr tabulated-list-sort-key (not reverse)) + ;; Presort the entries and hash the result and sort the buffer. + (setq entries (sort (copy-sequence entries) compare-fn)) + (let ((hash (make-hash-table :test 'equal))) + (dotimes (i (length entries)) + (puthash (caar entries) i hash) + (setq entries (cdr entries))) + (tablist-with-remembering-entry + (goto-char (point-min)) + (tablist-skip-invisible-entries) + (let ((inhibit-read-only t)) + (sort-subr + nil 'tablist-forward-entry 'end-of-line + (lambda () + (gethash (tabulated-list-get-id) hash 0)) + nil (if reverse '< '>)))) + (tablist-move-to-column n) + ;; Make the sort arrows display. + (tabulated-list-init-header)))) + +;; +;; *Filter +;; + +(defun tablist-read-filter-name (prompt) + (let ((filter (cdr (assq major-mode tablist-named-filter)))) + (unless filter + (error "No filter defined for %s mode" mode-name)) + (let ((name (completing-read + (format "%s: " prompt) + filter + nil t))) + (unless (> (length name) 0) + (error "No filter selected")) + name))) + +(defun tablist-apply-filter (&optional filter) + "Apply FILTER to the current tabulated list. + +FILTER defaults to `tablist-current-filter'." + (unless filter (setq filter tablist-current-filter)) + (tablist-filter-unhide-buffer) + (when (and filter + (null tablist-filter-suspended)) + (tablist-with-remembering-entry + (tablist-map-with-filter + (lambda nil + (if tablist-umark-filtered-entries + (save-excursion (tablist-unmark-forward))) + (tablist-filter-hide-entry)) + (tablist-filter-negate filter)))) + (force-mode-line-update)) + +(defadvice tabulated-list-print (after tabulated-list activate) + "Reapply the filter." + (when (or tablist-minor-mode + (derived-mode-p 'tablist-mode)) + (tablist-apply-filter))) + +(defun tablist-eval-filter (filter) + (tablist-filter-eval + filter + (tabulated-list-get-id) + (tabulated-list-get-entry) + (cdr (assq major-mode tablist-named-filter)))) + +(defun tablist-map-with-filter (fn filter &optional show-progress + distinguish-one-marked) + "Call FN for every unfiltered entry matching FILTER." + (prog1 + (cl-labels ((search () + (tablist-skip-invisible-entries) + (while (and (not (eobp)) + (not (tablist-eval-filter filter))) + (tablist-forward-entry)) + (unless (eobp) + (point-marker)))) + (let (next-position results) + (save-excursion + (goto-char (point-min)) + (setq next-position (search)) + (while next-position + (goto-char next-position) + (if show-progress (sit-for 0)) + (push (funcall fn) results) + ;; move after last match + (goto-char next-position) + (forward-line 1) + (set-marker next-position nil) + (setq next-position (search))) + (if (and distinguish-one-marked (= (length results) 1)) + (setq results (cons t results)))))))) + +;; +;; **Filter Commands +;; +(defun tablist-push-filter (filter &optional interactive or-p) + (setq tablist-current-filter + (tablist-filter-push + tablist-current-filter + filter or-p)) + (tablist-apply-filter) + (when interactive + (tablist-display-filter-temporarily))) + +(defun tablist-pop-filter (&optional n interactive) + "Remove the first N filter components." + (interactive (list (prefix-numeric-value current-prefix-arg) t)) + (while (and tablist-current-filter + (> n 0)) + (setq tablist-current-filter + (tablist-filter-pop + tablist-current-filter)) + (cl-decf n)) + (tablist-apply-filter) + (when interactive + (when (> n 0) + (message "The filter is empty.")) + (tablist-display-filter-temporarily)) + n) + +(defun tablist-negate-filter (&optional interactive) + "Negate the current filter." + (interactive (list t)) + (setq tablist-current-filter + (tablist-filter-negate + tablist-current-filter)) + (tablist-apply-filter) + (when interactive + (tablist-display-filter-temporarily))) + +(defun tablist-toggle-first-filter-logic () + "Toggle between and/or for the first filter operand." + (interactive) + (setq tablist-current-filter + (pcase tablist-current-filter + (`(or ,x1 ,x2) + `(and ,x1 ,x2)) + (`(and ,x1 ,x2) + `(or ,x1 ,x2)) + (`(not ,x) x) + (x `(not ,x)))) + (tablist-apply-filter) + (tablist-display-filter-temporarily)) + +(defun tablist-suspend-filter (&optional flag) + "Temporarily disable filtering according to FLAG. + +Interactively, this command toggles filtering." + (interactive + (list (not tablist-filter-suspended))) + (let ((state tablist-filter-suspended)) + (unless (eq (not (not state)) + (not (not flag))) + (set (make-local-variable 'tablist-filter-suspended) flag) + (tablist-apply-filter)))) + +(defun tablist-read-regexp-filter (operation arg) + (let ((column-name (tablist-read-column-name arg))) + (list + column-name + (let ((re + (read-regexp (format "%s where %s matches: " operation column-name)))) + (unless (> (length re) 0) + (error "No regexp given")) + re)))) + +(defun tablist-read-equal-filter (operation arg) + (let ((column-name (tablist-read-column-name arg))) + (list + column-name + (read-string (format "%s where %s equals: " operation column-name))))) + +(defun tablist-read-numeric-filter (operation arg) + (let* ((entry (tabulated-list-get-entry 1)) + (default (cl-some + (lambda (idx) + (let ((value (tablist-nth-entry idx entry))) + (when (or (not (eq 0 (string-to-number value))) + (equal "0" value)) + (tablist-column-name idx)))) + (number-sequence 0 (length entry)))) + (column-name (tablist-read-column-name arg nil default)) + (op (completing-read + (format "%s %s matching binary op: " operation column-name) + '("=" "<" ">" "<=" ">=") nil t)) + oper) + + (when (equal "" op) + (error "No operation selected")) + (setq op (intern op)) + (setq oper (number-to-string + (read-number + (format "%s where %s %s " operation column-name op)))) + + (list op column-name oper))) + +(defun tablist-push-regexp-filter (column-name regexp) + "Add a new filter matching REGEXP in COLUMN-NAME. + +The filter is and'ed with the current filter. Use +`tablist-toggle-first-filter-logic' to change this." + (interactive + (tablist-with-filter-displayed + (tablist-read-regexp-filter "Filter" current-prefix-arg))) + (tablist-push-filter + `(=~ ,column-name ,regexp) + (called-interactively-p 'any))) + +(defun tablist-push-equal-filter (column-name string) + "Add a new filter whre string equals COLUMN-NAME's value. + +The filter is and'ed with the current filter. Use +`tablist-toggle-first-filter-logic' to change this." + (interactive + (tablist-with-filter-displayed + (tablist-read-equal-filter "Filter" current-prefix-arg))) + (tablist-push-filter + `(== ,column-name ,string) + (called-interactively-p 'any))) + +(defun tablist-push-numeric-filter (op column-name 2nd-arg) + "Add a new filter matching a numeric predicate. + +The filter is and'ed with the current filter. Use +`tablist-toggle-first-filter-logic' to change this." + (interactive + (tablist-with-filter-displayed + (tablist-read-numeric-filter "Filter" current-prefix-arg))) + (tablist-push-filter + `(,op ,column-name ,2nd-arg) + (called-interactively-p 'any))) + +(defun tablist-push-named-filter (name) + "Add a named filter called NAME. + +Named filter are saved in the variable `tablist-named-filter'." + (interactive + (tablist-with-filter-displayed + (list + (tablist-read-filter-name "Add filter")))) + (when (and name (symbolp name)) + (setq name (symbol-name name))) + (tablist-push-filter name (called-interactively-p 'any))) + +(defun tablist-delete-named-filter (name &optional mode) + (interactive + (tablist-with-filter-displayed + (list + (tablist-read-filter-name "Delete filter")))) + (setq tablist-current-filter + (tablist-filter-map + (lambda (f) + (when (equal f name) + (setq f (tablist-get-named-filter f))) + f) + tablist-current-filter)) + (unless mode (setq mode major-mode)) + (let ((mode-filter + (assq mode tablist-named-filter))) + (when mode-filter + (setcdr mode-filter + (cl-remove name (cdr mode-filter) + :test 'equal :key 'car))))) + +(defun tablist-name-current-filter (name) + (interactive + (list (tablist-with-filter-displayed + (read-string + "Add name for current filter: ")))) + (unless tablist-current-filter + (error "Filter is empty")) + (unless (> (length name) 0) + (error "No name given")) + (tablist-put-named-filter + name (if (stringp tablist-current-filter) + (tablist-get-named-filter + tablist-current-filter) + tablist-current-filter)) + (setq tablist-current-filter name) + (force-mode-line-update)) + +(defun tablist-deconstruct-named-filter () + (interactive) + (let (found) + (setq tablist-current-filter + (tablist-filter-map + (lambda (f) + (when (and (not found) + (stringp f)) + (setq found t) + (let ((df (tablist-get-named-filter f))) + (unless df + (error "Filter is not defined: %s" f)) + (setq f df))) + f) + tablist-current-filter)) + (unless found + (error "No named filter found")) + (force-mode-line-update))) + +(defun tablist-filter-names (&optional mode) + (mapcar 'car (cdr (assq (or mode major-mode) + tablist-named-filter)))) + +(defun tablist-get-named-filter (name &optional mode) + (cdr (assoc name + (cdr (assq (or mode major-mode) + tablist-named-filter))))) + +(defun tablist-put-named-filter (name filter &optional mode) + (unless mode (setq mode major-mode)) + (let ((mode-filter + (assq mode tablist-named-filter))) + (unless mode-filter + (setq mode-filter (cons mode nil)) + (push mode-filter tablist-named-filter)) + (let ((entry (assoc name mode-filter))) + (if entry + (setcdr entry filter) + (setcdr mode-filter + (list (cons name filter))))))) + +(defun tablist-validate-named-filter (filter) + (tablist-filter-map + (lambda (f) + (when (and (stringp f) + (null (tablist-get-named-filter f))) + (error "Undefined named filter: %s (defined: %s)" f + (mapconcat 'identity (tablist-filter-names) ",")))) + filter)) + +(defun tablist-edit-filter () + (interactive) + (setq tablist-current-filter + (tablist-with-filter-displayed + (tablist-filter-edit-filter + "Edit filter: " + tablist-current-filter + nil + 'tablist-validate-named-filter))) + (tablist-apply-filter)) + +(defun tablist-clear-filter () + (interactive) + (setq tablist-current-filter nil) + (tablist-apply-filter)) + +;; **Displaying filter +;; + +(defconst tablist-display-filter-mode-line-tag nil) + +(defun tablist-display-filter (&optional flag) + "Display the current filter according to FLAG. + +If FLAG has the value 'toggle, toggle it's visibility. +If FLAG has the 'state, then do nothing but return the current +visibility." + (interactive (list 'toggle)) + (let* ((tag 'tablist-display-filter-mode-line-tag) + (displayed-p (not (not (assq tag mode-line-format))))) + (if (eq flag 'state) + displayed-p + (let ((display-p (not (not (if (eq flag 'toggle) + (not displayed-p) + flag))))) + (unless (eq displayed-p display-p) + (setq mode-line-format + (if display-p + (list (cons tag mode-line-format) + '(:eval + (replace-regexp-in-string + "%" "%%" + (concat + (propertize "Filter: " 'face 'minibuffer-prompt) + (and tablist-filter-suspended + "[suspended] ") + (if tablist-current-filter + (tablist-filter-unparse + tablist-current-filter t) + "[none]"))))) + (cdr (assq tag mode-line-format))))) + (force-mode-line-update) + display-p)))) + +(defun tablist-display-filter-temporarily () + (tablist-with-filter-displayed + (sit-for 9999))) + +;; +;; **Hiding/Unhiding Entries +;; +(defun tablist-filter-set-entry-hidden (flag &optional pos) + (save-excursion + (when pos (goto-char pos)) + (beginning-of-line) + (let ((inhibit-read-only t)) + (add-text-properties + (point-at-bol) + (1+ (point-at-eol)) + `(invisible ,flag))))) + +(defun tablist-filter-hide-entry (&optional pos) + (interactive) + (tablist-filter-set-entry-hidden t pos)) + +(defun tablist-filter-unhide-entry (&optional pos) + (tablist-filter-set-entry-hidden nil pos)) + +(defun tablist-filter-unhide-buffer () + (let ((inhibit-read-only t)) + (remove-text-properties + (point-min) (point-max) + '(invisible)))) + +(defun tablist-window-attach (awindow &optional window) + "Attach AWINDOW to WINDOW. + +This has the following effect. Whenever WINDOW, defaulting to +the selected window, stops displaying the buffer it currently +displays (e.g., by switching buffers or because it was deleted) +AWINDOW is deleted." + (unless window (setq window (selected-window))) + (let ((buffer (window-buffer window)) + (hook (make-symbol "window-attach-hook"))) + (fset hook + (lambda () + (when (or (not (window-live-p window)) + (not (eq buffer (window-buffer window)))) + (remove-hook 'window-configuration-change-hook + hook) + ;; Deleting windows inside wcch may cause errors in + ;; windows.el . + (run-with-timer + 0 nil (lambda (win) + (when (and (window-live-p win) + (not (eq win (selected-window)))) + (delete-window win))) + awindow)))) + (add-hook 'window-configuration-change-hook hook))) + +(defun tablist-display-buffer-split-below-and-attach (buf alist) + "Display buffer action using `tablist-window-attach'." + (let ((window (selected-window)) + (height (cdr (assq 'window-height alist))) + newwin) + (when height + (when (floatp height) + (setq height (round (* height (frame-height))))) + (setq height (- (max height window-min-height)))) + (setq newwin (window--display-buffer + buf + (split-window-below height) + 'window alist)) + (tablist-window-attach newwin window) + newwin)) + +(defun tablist-generate-sorter (column compare-fn &optional read-fn) + "Generate a sort function for `tabulated-list' entries. + +Example: + + \(tablist-generate-sorter 0 '< 'string-to-number\) + +would create a sort function sorting `tabulated-list-entries' on +the 0-th column as numbers by the less-than relation." + + (lambda (e1 e2) + (funcall compare-fn + (funcall (or read-fn 'identity) + (aref (cadr e1) column)) + (funcall (or read-fn 'identity) + (aref (cadr e2) column))))) + +(provide 'tablist) +;; Local Variables: +;; outline-regexp: ";;\\(\\(?:[;*]+ \\| \\*+\\)[^\s\t\n]\\|###autoload\\)\\|(" +;; indent-tabs-mode: nil +;; End: +;;; tablist.el ends here diff --git a/org/elpa/websocket-20230305.410/websocket-autoloads.el b/org/elpa/websocket-20230305.410/websocket-autoloads.el new file mode 100644 index 0000000..c68dedb --- /dev/null +++ b/org/elpa/websocket-20230305.410/websocket-autoloads.el @@ -0,0 +1,22 @@ +;;; websocket-autoloads.el --- automatically extracted autoloads -*- lexical-binding: t -*- +;; +;;; Code: + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + + +;;;### (autoloads nil "websocket" "websocket.el" (0 0 0 0)) +;;; Generated autoloads from websocket.el + +(register-definition-prefixes "websocket" '("websocket-")) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; coding: utf-8 +;; End: +;;; websocket-autoloads.el ends here diff --git a/org/elpa/websocket-20230305.410/websocket-pkg.el b/org/elpa/websocket-20230305.410/websocket-pkg.el new file mode 100644 index 0000000..c805bde --- /dev/null +++ b/org/elpa/websocket-20230305.410/websocket-pkg.el @@ -0,0 +1,2 @@ +;;; Generated package description from websocket.el -*- no-byte-compile: t -*- +(define-package "websocket" "20230305.410" "Emacs WebSocket client and server" '((cl-lib "0.5")) :commit "1a08093b122d8cf20366a1cba5faddf7a53d08ed" :authors '(("Andrew Hyatt" . "ahyatt@gmail.com")) :maintainer '("Andrew Hyatt" . "ahyatt@gmail.com") :keywords '("communication" "websocket" "server") :url "https://github.com/ahyatt/emacs-websocket") diff --git a/org/elpa/websocket-20230305.410/websocket.el b/org/elpa/websocket-20230305.410/websocket.el new file mode 100644 index 0000000..4a6628c --- /dev/null +++ b/org/elpa/websocket-20230305.410/websocket.el @@ -0,0 +1,1054 @@ +;;; websocket.el --- Emacs WebSocket client and server -*- lexical-binding:t -*- + +;; Copyright (c) 2013, 2016-2017 Free Software Foundation, Inc. + +;; Author: Andrew Hyatt +;; Homepage: https://github.com/ahyatt/emacs-websocket +;; Keywords: Communication, Websocket, Server +;; Package-Version: 20230305.410 +;; Package-Commit: 1a08093b122d8cf20366a1cba5faddf7a53d08ed +;; Version: 1.14 +;; Package-Requires: ((cl-lib "0.5")) +;; +;; This program is free software; you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation; either version 2 of the +;; License, or (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: +;; This implements RFC 6455, which can be found at +;; http://tools.ietf.org/html/rfc6455. +;; +;; This library contains code to connect Emacs as a client to a +;; websocket server, and for Emacs to act as a server for websocket +;; connections. +;; +;; Websockets clients are created by calling `websocket-open', which +;; returns a `websocket' struct. Users of this library use the +;; websocket struct, and can call methods `websocket-send-text', which +;; sends text over the websocket, or `websocket-send', which sends a +;; `websocket-frame' struct, enabling finer control of what is sent. +;; A callback is passed to `websocket-open' that will retrieve +;; websocket frames called from the websocket. Websockets are +;; eventually closed with `websocket-close'. +;; +;; Server functionality is similar. A server is started with +;; `websocket-server' called with a port and the callbacks to use, +;; which returns a process. The process can later be closed with +;; `websocket-server-close'. A `websocket' struct is also created +;; for every connection, and is exposed through the callbacks. + +(require 'bindat) +(require 'url-parse) +(require 'url-cookie) +(require 'seq) +(eval-when-compile (require 'cl-lib)) + +;;; Code: + +(cl-defstruct (websocket + (:constructor nil) + (:constructor websocket-inner-create)) + "A websocket structure. +This follows the W3C Websocket API, except translated to elisp +idioms. The API is implemented in both the websocket struct and +additional methods. Due to how defstruct slots are accessed, all +API methods are prefixed with \"websocket-\" and take a websocket +as an argument, so the distrinction between the struct API and +the additional helper APIs are not visible to the caller. + +A websocket struct is created with `websocket-open'. + +`ready-state' contains one of `connecting', `open', or +`closed', depending on the state of the websocket. + +The W3C API \"bufferedAmount\" call is not currently implemented, +since there is no elisp API to get the buffered amount from the +subprocess. There may, in fact, be output data buffered, +however, when the `on-message' or `on-close' callbacks are +called. + +`on-open', `on-message', `on-close', and `on-error' are described +in `websocket-open'. + +The `negotiated-extensions' slot lists the extensions accepted by +both the client and server, and `negotiated-protocols' does the +same for the protocols." + ;; API + (ready-state 'connecting) + client-data + on-open + on-message + on-close + on-error + negotiated-protocols + negotiated-extensions + (server-p nil :read-only t) + + ;; Other data - clients should not have to access this. + (url (cl-assert nil) :read-only t) + (protocols nil :read-only t) + (extensions nil :read-only t) + (conn (cl-assert nil) :read-only t) + ;; Only populated for servers, this is the server connection. + server-conn + accept-string + (inflight-input nil)) + +(defvar websocket-version "1.12" + "Version numbers of this version of websocket.el.") + +(defvar websocket-debug nil + "Set to true to output debugging info to a per-websocket buffer. +The buffer is ` *websocket URL debug*' where URL is the +URL of the connection.") + +(defconst websocket-guid "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" + "The websocket GUID as defined in RFC 6455. +Do not change unless the RFC changes.") + +(defvar websocket-callback-debug-on-error nil + "If true, when an error happens in a client callback, invoke the debugger. +Having this on can cause issues with missing frames if the debugger is +exited by quitting instead of continuing, so it's best to have this set +to nil unless it is especially needed.") + +(defmacro websocket-document-function (function docstring) + "Document FUNCTION with DOCSTRING. Use this for defstruct accessor etc." + (declare (indent defun) + (doc-string 2)) + `(put ',function 'function-documentation ,docstring)) + +(websocket-document-function websocket-on-open + "Accessor for websocket on-open callback. +See `websocket-open' for details. + +\(fn WEBSOCKET)") + +(websocket-document-function websocket-on-message + "Accessor for websocket on-message callback. +See `websocket-open' for details. + +\(fn WEBSOCKET)") + +(websocket-document-function websocket-on-close + "Accessor for websocket on-close callback. +See `websocket-open' for details. + +\(fn WEBSOCKET)") + +(websocket-document-function websocket-on-error + "Accessor for websocket on-error callback. +See `websocket-open' for details. + +\(fn WEBSOCKET)") + +(defun websocket-genbytes (nbytes) + "Generate NBYTES random bytes." + (let ((s (make-string nbytes ?\s))) + (dotimes (i nbytes) + (aset s i (random 256))) + s)) + +(defun websocket-try-callback (websocket-callback callback-type websocket + &rest rest) + "Invoke function WEBSOCKET-CALLBACK with WEBSOCKET and REST args. +If an error happens, it is handled according to +`websocket-callback-debug-on-error'." + ;; This looks like it should be able to done more efficiently, but + ;; I'm not sure that's the case. We can't do it as a macro, since + ;; we want it to change whenever websocket-callback-debug-on-error + ;; changes. + (let ((args rest) + (debug-on-error websocket-callback-debug-on-error)) + (push websocket args) + (if websocket-callback-debug-on-error + (condition-case err + (apply (funcall websocket-callback websocket) args) + ((debug error) (funcall (websocket-on-error websocket) + websocket callback-type err))) + (condition-case err + (apply (funcall websocket-callback websocket) args) + (error (funcall (websocket-on-error websocket) websocket + callback-type err)))))) + +(defun websocket-genkey () + "Generate a key suitable for the websocket handshake." + (base64-encode-string (websocket-genbytes 16))) + +(defun websocket-calculate-accept (key) + "Calculate the expect value of the accept header. +This is based on the KEY from the Sec-WebSocket-Key header." + (base64-encode-string + (sha1 (concat key websocket-guid) nil nil t))) + +(defun websocket-get-bytes (s n) + "From string S, retrieve the value of N bytes. +Return the value as an unsigned integer. The value N must be a +power of 2, up to 8. + +We support getting frames up to 536870911 bytes (2^29 - 1), +approximately 537M long." + (if (= n 8) + (let* ((32-bit-parts + (bindat-get-field (bindat-unpack '((:val vec 2 u32)) s) :val)) + (cval + (logior (lsh (aref 32-bit-parts 0) 32) (aref 32-bit-parts 1)))) + (if (and (= (aref 32-bit-parts 0) 0) + (= (lsh (aref 32-bit-parts 1) -29) 0)) + cval + (signal 'websocket-unparseable-frame + (list "Frame value found too large to parse!")))) + ;; n is not 8 + (bindat-get-field + (condition-case _ + (bindat-unpack + `((:val + ,(cond ((= n 1) 'u8) + ((= n 2) 'u16) + ((= n 4) 'u32) + ;; This is an error with the library, + ;; not a user-facing, meaningful error. + (t (error + "websocket-get-bytes: Unknown N: %S" n))))) + s) + (args-out-of-range (signal 'websocket-unparseable-frame + (list (format "Frame unexpectedly short: %s" s))))) + :val))) + +(defun websocket-to-bytes (val nbytes) + "Encode the integer VAL in NBYTES of data. +NBYTES much be a power of 2, up to 8. + +This supports encoding values up to 536870911 bytes (2^29 - 1), +approximately 537M long." + (when (and (< nbytes 8) + (> val (expt 2 (* 8 nbytes)))) + ;; not a user-facing error, this must be caused from an error in + ;; this library + (error "websocket-to-bytes: Value %d could not be expressed in %d bytes" + val nbytes)) + (if (= nbytes 8) + (progn + (let* ((hi-32bits (lsh val -32)) + ;; This is just VAL on systems that don't have >= 32 bits. + (low-32bits (- val (lsh hi-32bits 32)))) + (when (or (> hi-32bits 0) (> (lsh low-32bits -29) 0)) + (signal 'websocket-frame-too-large (list val))) + (bindat-pack `((:val vec 2 u32)) + `((:val . [,hi-32bits ,low-32bits]))))) + (bindat-pack + `((:val ,(cond ((= nbytes 1) 'u8) + ((= nbytes 2) 'u16) + ((= nbytes 4) 'u32) + ;; Library error, not system error + (t (error "websocket-to-bytes: Unknown NBYTES: %S" nbytes))))) + `((:val . ,val))))) + +(defun websocket-get-opcode (s) + "Retrieve the opcode from first byte of string S." + (websocket-ensure-length s 1) + (let ((opcode (logand #xf (aref s 0)))) + (cond ((= opcode 0) 'continuation) + ((= opcode 1) 'text) + ((= opcode 2) 'binary) + ((= opcode 8) 'close) + ((= opcode 9) 'ping) + ((= opcode 10) 'pong)))) + +(defun websocket-get-payload-len (s) + "Parse out the payload length from the string S. +We start at position 0, and return a cons of the payload length and how +many bytes were consumed from the string." + (websocket-ensure-length s 1) + (let* ((initial-val (logand 127 (aref s 0)))) + (cond ((= initial-val 127) + (websocket-ensure-length s 9) + (cons (websocket-get-bytes (substring s 1) 8) 9)) + ((= initial-val 126) + (websocket-ensure-length s 3) + (cons (websocket-get-bytes (substring s 1) 2) 3)) + (t (cons initial-val 1))))) + +(cl-defstruct websocket-frame opcode payload length completep) + +(defun websocket-frame-text (frame) + "Given FRAME, return the payload as a utf-8 encoded string." + (cl-assert (websocket-frame-p frame)) + (decode-coding-string (websocket-frame-payload frame) 'utf-8)) + +(defun websocket-mask (key data) + "Using string KEY, mask string DATA according to the RFC. +This is used to both mask and unmask data." + ;; Returning the string as unibyte is important here. Because we set the + ;; string byte by byte, this results in a unibyte string. + (cl-loop + with result = (make-string (length data) ?x) + for i from 0 below (length data) + do (setf (seq-elt result i) (logxor (aref key (mod i 4)) (seq-elt data i))) + finally return result)) + +(defun websocket-ensure-length (s n) + "Ensure the string S has at most N bytes. +Otherwise we throw the error `websocket-incomplete-frame'." + (when (< (length s) n) + (throw 'websocket-incomplete-frame nil))) + +(defun websocket-encode-frame (frame should-mask) + "Encode the FRAME struct to the binary representation. +We mask the frame or not, depending on SHOULD-MASK." + (let* ((opcode (websocket-frame-opcode frame)) + (payload (websocket-frame-payload frame)) + (fin (websocket-frame-completep frame)) + (payloadp (and payload + (memq opcode '(continuation ping pong text binary)))) + (mask-key (when should-mask (websocket-genbytes 4)))) + (apply #'unibyte-string + (let ((val (append (list + (logior (pcase opcode + (`continuation 0) + (`text 1) + (`binary 2) + (`close 8) + (`ping 9) + (`pong 10)) + (if fin 128 0))) + (when payloadp + (list + (logior + (if should-mask 128 0) + (cond ((< (length payload) 126) (length payload)) + ((< (length payload) 65536) 126) + (t 127))))) + (when (and payloadp (>= (length payload) 126)) + (append (websocket-to-bytes + (length payload) + (cond ((< (length payload) 126) 1) + ((< (length payload) 65536) 2) + (t 8))) nil)) + (when (and payloadp should-mask) + (append mask-key nil)) + (when payloadp + (append (if should-mask (websocket-mask mask-key payload) + payload) + nil))))) + ;; We have to make sure the non-payload data is a full 32-bit frame + (if (= 1 (length val)) + (append val '(0)) val))))) + +(defun websocket-read-frame (s) + "Read from string S a `websocket-frame' struct with the contents. +This only gets complete frames. Partial frames need to wait until +the frame finishes. If the frame is not completed, return NIL." + (catch 'websocket-incomplete-frame + (websocket-ensure-length s 1) + (let* ((opcode (websocket-get-opcode s)) + (fin (logand 128 (aref s 0))) + (payloadp (memq opcode '(continuation text binary ping pong))) + (payload-len (when payloadp + (websocket-get-payload-len (substring s 1)))) + (maskp (and + payloadp + (= 128 (logand 128 (aref s 1))))) + (payload-start (when payloadp (+ (if maskp 5 1) (cdr payload-len)))) + (payload-end (when payloadp (+ payload-start (car payload-len)))) + (unmasked-payload (when payloadp + (websocket-ensure-length s payload-end) + (substring s payload-start payload-end)))) + (make-websocket-frame + :opcode opcode + :payload + (if maskp + (let ((masking-key (substring s (+ 1 (cdr payload-len)) + (+ 5 (cdr payload-len))))) + (websocket-mask masking-key unmasked-payload)) + unmasked-payload) + :length (if payloadp payload-end 1) + :completep (> fin 0))))) + +(defun websocket-format-error (err) + "Format an error message like command level does. +ERR should be a cons of error symbol and error data." + + ;; Formatting code adapted from `edebug-report-error' + (concat (or (get (car err) 'error-message) + (format "peculiar error (%s)" (car err))) + (when (cdr err) + (format ": %s" + (mapconcat #'prin1-to-string + (cdr err) ", "))))) + +(defun websocket-default-error-handler (_websocket type err) + "The default error handler used to handle errors in callbacks." + (display-warning 'websocket + (format "in callback `%S': %s" + type + (websocket-format-error err)) + :error)) + +;; Error symbols in use by the library +(put 'websocket-unsupported-protocol 'error-conditions + '(error websocket-error websocket-unsupported-protocol)) +(put 'websocket-unsupported-protocol 'error-message "Unsupported websocket protocol") +(put 'websocket-wss-needs-emacs-24 'error-conditions + '(error websocket-error websocket-unsupported-protocol + websocket-wss-needs-emacs-24)) +(put 'websocket-wss-needs-emacs-24 'error-message + "wss protocol is not supported for Emacs before version 24.") +(put 'websocket-received-error-http-response 'error-conditions + '(error websocket-error websocket-received-error-http-response)) +(put 'websocket-received-error-http-response 'error-message + "Error response received from websocket server") +(put 'websocket-invalid-header 'error-conditions + '(error websocket-error websocket-invalid-header)) +(put 'websocket-invalid-header 'error-message + "Invalid HTTP header sent") +(put 'websocket-illegal-frame 'error-conditions + '(error websocket-error websocket-illegal-frame)) +(put 'websocket-illegal-frame 'error-message + "Cannot send illegal frame to websocket") +(put 'websocket-closed 'error-conditions + '(error websocket-error websocket-closed)) +(put 'websocket-closed 'error-message + "Cannot send message to a closed websocket") +(put 'websocket-unparseable-frame 'error-conditions + '(error websocket-error websocket-unparseable-frame)) +(put 'websocket-unparseable-frame 'error-message + "Received an unparseable frame") +(put 'websocket-frame-too-large 'error-conditions + '(error websocket-error websocket-frame-too-large)) +(put 'websocket-frame-too-large 'error-message + "The frame being sent is too large for this emacs to handle") + +(defun websocket-intersect (a b) + "Simple list intersection, should function like Common Lisp's `intersection'." + (let ((result)) + (dolist (elem a (nreverse result)) + (when (member elem b) + (push elem result))))) + +(defun websocket-get-debug-buffer-create (websocket) + "Get or create the buffer corresponding to WEBSOCKET." + (let ((buf (get-buffer-create (format "*websocket %s debug*" + (websocket-url websocket))))) + (when (= 0 (buffer-size buf)) + (buffer-disable-undo buf)) + buf)) + +(defun websocket-debug (websocket msg &rest args) + "In the WEBSOCKET's debug buffer, send MSG, with format ARGS." + (when websocket-debug + (let ((buf (websocket-get-debug-buffer-create websocket))) + (save-excursion + (with-current-buffer buf + (goto-char (point-max)) + (insert "[WS] ") + (insert (apply #'format (append (list msg) args))) + (insert "\n")))))) + +(defun websocket-verify-response-code (output) + "Verify that OUTPUT contains a valid HTTP response code. +The only acceptable one to websocket is responce code 101. +A t value will be returned on success, and an error thrown +if not." + (unless (string-match "^HTTP/1.1 \\([[:digit:]]+\\)" output) + (signal 'websocket-invalid-header (list "Invalid HTTP status line"))) + (unless (equal "101" (match-string 1 output)) + (signal 'websocket-received-error-http-response + (list (string-to-number (match-string 1 output))))) + t) + +(defun websocket-parse-repeated-field (output field) + "From header-containing OUTPUT, parse out the list from a +possibly repeated field." + (let ((pos 0) + (extensions)) + (while (and pos + (string-match (format "\r\n%s: \\(.*\\)\r\n" field) + output pos)) + (when (setq pos (match-end 1)) + (setq extensions (append extensions (split-string + (match-string 1 output) ", ?"))))) + extensions)) + +(defun websocket-process-frame (websocket frame) + "Using the WEBSOCKET's filter and connection, process the FRAME. +This returns a lambda that should be executed when all frames have +been processed. If the frame has a payload, the lambda has the frame +passed to the filter slot of WEBSOCKET. If the frame is a ping, +the lambda has a reply with a pong. If the frame is a close, the lambda +has connection termination." + (let ((opcode (websocket-frame-opcode frame))) + (cond ((memq opcode '(continuation text binary)) + (lambda () (websocket-try-callback 'websocket-on-message 'on-message + websocket frame))) + ((eq opcode 'ping) + (lambda () (websocket-send websocket + (make-websocket-frame + :opcode 'pong + :payload (websocket-frame-payload frame) + :completep t)))) + ((eq opcode 'close) + (lambda () (delete-process (websocket-conn websocket)))) + (t (lambda ()))))) + +(defun websocket-process-input-on-open-ws (websocket text) + "This handles input processing for both the client and server filters." + (let ((current-frame) + (processing-queue) + (start-point 0)) + (while (setq current-frame (websocket-read-frame + (substring text start-point))) + (push (websocket-process-frame websocket current-frame) processing-queue) + (cl-incf start-point (websocket-frame-length current-frame))) + (when (> (length text) start-point) + (setf (websocket-inflight-input websocket) + (substring text start-point))) + (dolist (to-process (nreverse processing-queue)) + (funcall to-process)))) + +(defun websocket-send-text (websocket text) + "To the WEBSOCKET, send TEXT as a complete frame." + (websocket-send + websocket + (make-websocket-frame :opcode 'text + :payload (encode-coding-string + text 'raw-text) + :completep t))) + +(defun websocket-check (frame) + "Check FRAME for correctness, returning true if correct." + (or + ;; Text, binary, and continuation frames need payloads + (and (memq (websocket-frame-opcode frame) '(text binary continuation)) + (websocket-frame-payload frame)) + ;; Pings and pongs may optionally have them + (memq (websocket-frame-opcode frame) '(ping pong)) + ;; And close shouldn't have any payload, and should always be complete. + (and (eq (websocket-frame-opcode frame) 'close) + (not (websocket-frame-payload frame)) + (websocket-frame-completep frame)))) + +(defun websocket-send (websocket frame) + "To the WEBSOCKET server, send the FRAME. +This will raise an error if the frame is illegal. + +The error signaled may be of type `websocket-illegal-frame' if +the frame is malformed in some way, also having the condition +type of `websocket-error'. The data associated with the signal +is the frame being sent. + +If the websocket is closed a signal `websocket-closed' is sent, +also with `websocket-error' condition. The data in the signal is +also the frame. + +The frame may be too large for this buid of Emacs, in which case +`websocket-frame-too-large' is returned, with the data of the +size of the frame which was too large to process. This also has +the `websocket-error' condition." + (unless (websocket-check frame) + (signal 'websocket-illegal-frame (list frame))) + (websocket-debug websocket "Sending frame, opcode: %s payload: %s" + (websocket-frame-opcode frame) + (websocket-frame-payload frame)) + (unless (websocket-openp websocket) + (signal 'websocket-closed (list frame))) + (process-send-string (websocket-conn websocket) + ;; We mask only when we're a client, following the spec. + (websocket-encode-frame frame (not (websocket-server-p websocket))))) + +(defun websocket-openp (websocket) + "Check WEBSOCKET and return non-nil if the connection is open." + (and websocket + (not (eq 'close (websocket-ready-state websocket))) + (member (process-status (websocket-conn websocket)) '(open run)))) + +(defun websocket-close (websocket) + "Close WEBSOCKET and erase all the old websocket data." + (websocket-debug websocket "Closing websocket") + (websocket-try-callback 'websocket-on-close 'on-close websocket) + (when (websocket-openp websocket) + (websocket-send websocket + (make-websocket-frame :opcode 'close + :completep t)) + (setf (websocket-ready-state websocket) 'closed)) + (delete-process (websocket-conn websocket))) + +;;;;;;;;;;;;;;;;;;;;;; +;; Websocket client ;; +;;;;;;;;;;;;;;;;;;;;;; + +(cl-defun websocket-open (url &key protocols extensions (on-open 'identity) + (on-message (lambda (_w _f))) (on-close 'identity) + (on-error 'websocket-default-error-handler) + (nowait nil) (custom-header-alist nil)) + "Open a websocket connection to URL, returning the `websocket' struct. +The PROTOCOL argument is optional, and setting it will declare to +the server that this client supports the protocols in the list +given. We will require that the server also has to support that +protocols. + +Similar logic applies to EXTENSIONS, which is a list of conses, +the car of which is a string naming the extension, and the cdr of +which is the list of parameter strings to use for that extension. +The parameter strings are of the form \"key=value\" or \"value\". +EXTENSIONS can be NIL if none are in use. An example value would +be (\"deflate-stream\" . (\"mux\" \"max-channels=4\")). + +Cookies that are set via `url-cookie-store' will be used during +communication with the server, and cookies received from the +server will be stored in the same cookie storage that the +`url-cookie' package uses. + +Optionally you can specify +ON-OPEN, ON-MESSAGE and ON-CLOSE callbacks as well. + +The ON-OPEN callback is called after the connection is +established with the websocket as the only argument. The return +value is unused. + +The ON-MESSAGE callback is called after receiving a frame, and is +called with the websocket as the first argument and +`websocket-frame' struct as the second. The return value is +unused. + +The ON-CLOSE callback is called after the connection is closed, or +failed to open. It is called with the websocket as the only +argument, and the return value is unused. + +The ON-ERROR callback is called when any of the other callbacks +have an error. It takes the websocket as the first argument, and +a symbol as the second argument either `on-open', `on-message', +or `on-close', and the error as the third argument. Do NOT +rethrow the error, or else you may miss some websocket messages. +You similarly must not generate any other errors in this method. +If you want to debug errors, set +`websocket-callback-debug-on-error' to t, but this also can be +dangerous is the debugger is quit out of. If not specified, +`websocket-default-error-handler' is used. + +For each of these event handlers, the client code can store +arbitrary data in the `client-data' slot in the returned +websocket. + +The following errors might be thrown in this method or in +websocket processing, all of them having the error-condition +`websocket-error' in addition to their own symbol: + +`websocket-unsupported-protocol': Data in the error signal is the +protocol that is unsupported. For example, giving a URL starting +with http by mistake raises this error. + +`websocket-wss-needs-emacs-24': Trying to connect wss protocol +using Emacs < 24 raises this error. You can catch this error +also by `websocket-unsupported-protocol'. + +`websocket-received-error-http-response': Data in the error +signal is the integer error number. + +`websocket-invalid-header': Data in the error is a string +describing the invalid header received from the server. + +`websocket-unparseable-frame': Data in the error is a string +describing the problem with the frame. + +`nowait': If NOWAIT is true, return without waiting for the +connection to complete. + +`custom-headers-alist': An alist of custom headers to pass to the +server. The car is the header name, the cdr is the header value. +These are different from the extensions because it is not related +to the websocket protocol. +" + (let* ((name (format "websocket to %s" url)) + (url-struct (url-generic-parse-url url)) + (key (websocket-genkey)) + (coding-system-for-read 'binary) + (coding-system-for-write 'binary) + (conn (if (member (url-type url-struct) '("ws" "wss")) + (let* ((type (if (equal (url-type url-struct) "ws") + 'plain 'tls)) + (port (if (= 0 (url-port url-struct)) + (if (eq type 'tls) 443 80) + (url-port url-struct))) + (host (url-host url-struct))) + (if (eq type 'plain) + (make-network-process :name name :buffer nil :host host + :service port :nowait nowait) + (condition-case-unless-debug nil + (open-network-stream name nil host port :type type :nowait nowait) + (wrong-number-of-arguments + (signal 'websocket-wss-needs-emacs-24 (list "wss")))))) + (signal 'websocket-unsupported-protocol (list (url-type url-struct))))) + (websocket (websocket-inner-create + :conn conn + :url url + :on-open on-open + :on-message on-message + :on-close on-close + :on-error on-error + :protocols protocols + :extensions (mapcar 'car extensions) + :accept-string + (websocket-calculate-accept key)))) + (unless conn (error "Could not establish the websocket connection to %s" url)) + (process-put conn :websocket websocket) + (set-process-filter conn + (lambda (process output) + (let ((websocket (process-get process :websocket))) + (websocket-outer-filter websocket output)))) + (set-process-sentinel + conn + (websocket-sentinel url conn key protocols extensions custom-header-alist nowait)) + (set-process-query-on-exit-flag conn nil) + (websocket-ensure-handshake url conn key protocols extensions custom-header-alist nowait) + websocket)) + +(defun websocket-sentinel (url conn key protocols extensions custom-header-alist nowait) + #'(lambda (process change) + (let ((websocket (process-get process :websocket))) + (websocket-debug websocket "State change to %s" change) + (let ((status (process-status process))) + (when (and nowait (eq status 'open)) + (websocket-ensure-handshake url conn key protocols extensions custom-header-alist nowait)) + + (when (and (member status '(closed failed exit signal)) + (not (eq 'closed (websocket-ready-state websocket)))) + (setf (websocket-ready-state websocket) 'closed) + (websocket-try-callback 'websocket-on-close 'on-close websocket)))))) + +(defun websocket-ensure-handshake (url conn key protocols extensions custom-header-alist nowait) + (let ((url-struct (url-generic-parse-url url)) + (websocket (process-get conn :websocket))) + (when (and (eq 'connecting (websocket-ready-state websocket)) + (memq (process-status conn) + (list 'run (if nowait 'connect 'open)))) + (websocket-debug websocket "Sending handshake, key: %s, acceptance: %s" + key (websocket-accept-string websocket)) + (process-send-string conn + (format "GET %s HTTP/1.1\r\n%s" + (let ((path (url-filename url-struct))) + (if (> (length path) 0) path "/")) + (websocket-create-headers + url key protocols extensions custom-header-alist)))))) + +(defun websocket-process-headers (url headers) + "On opening URL, process the HEADERS sent from the server." + (when (string-match "Set-Cookie: \(.*\)\r\n" headers) + ;; The url-current-object is assumed to be set by + ;; url-cookie-handle-set-cookie. + (let ((url-current-object (url-generic-parse-url url))) + (url-cookie-handle-set-cookie (match-string 1 headers))))) + +(defun websocket-outer-filter (websocket output) + "Filter the WEBSOCKET server's OUTPUT. +This will parse headers and process frames repeatedly until there +is no more output or the connection closes. If the websocket +connection is invalid, the connection will be closed." + (websocket-debug websocket "Received: %s" output) + (let ((start-point) + (text (concat (websocket-inflight-input websocket) output)) + (header-end-pos)) + (setf (websocket-inflight-input websocket) nil) + ;; If we've received the complete header, check to see if we've + ;; received the desired handshake. + (when (and (eq 'connecting (websocket-ready-state websocket))) + (if (and (setq header-end-pos (string-match "\r\n\r\n" text)) + (setq start-point (+ 4 header-end-pos))) + (progn + (condition-case err + (progn + (websocket-verify-response-code text) + (websocket-verify-headers websocket text) + (websocket-process-headers (websocket-url websocket) text)) + (error + (websocket-close websocket) + (funcall (websocket-on-error websocket) + websocket 'on-open err))) + (setf (websocket-ready-state websocket) 'open) + (websocket-try-callback 'websocket-on-open 'on-open websocket)) + (setf (websocket-inflight-input websocket) text))) + (when (eq 'open (websocket-ready-state websocket)) + (websocket-process-input-on-open-ws + websocket (substring text (or start-point 0)))))) + +(defun websocket-verify-headers (websocket output) + "Based on WEBSOCKET's data, ensure the headers in OUTPUT are valid. +The output is assumed to have complete headers. This function +will either return t or call `error'. This has the side-effect +of populating the list of server extensions to WEBSOCKET." + (let ((accept-regexp + (concat "Sec-Web[Ss]ocket-Accept: " (regexp-quote (websocket-accept-string websocket))))) + (websocket-debug websocket "Checking for accept header regexp: %s" accept-regexp) + (unless (string-match accept-regexp output) + (signal 'websocket-invalid-header + (list "Incorrect handshake from websocket: is this really a websocket connection?")))) + (let ((case-fold-search t)) + (websocket-debug websocket "Checking for upgrade header") + (unless (string-match "\r\nUpgrade: websocket\r\n" output) + (signal 'websocket-invalid-header + (list "No 'Upgrade: websocket' header found"))) + (websocket-debug websocket "Checking for connection header") + (unless (string-match "\r\nConnection: upgrade\r\n" output) + (signal 'websocket-invalid-header + (list "No 'Connection: upgrade' header found"))) + (when (websocket-protocols websocket) + (dolist (protocol (websocket-protocols websocket)) + (websocket-debug websocket "Checking for protocol match: %s" + protocol) + (let ((protocols + (if (string-match (format "\r\nSec-Websocket-Protocol: %s\r\n" + protocol) + output) + (list protocol) + (signal 'websocket-invalid-header + (list "Incorrect or missing protocol returned by the server."))))) + (setf (websocket-negotiated-protocols websocket) protocols)))) + (let* ((extensions (websocket-parse-repeated-field + output + "Sec-WebSocket-Extensions")) + (extra-extensions)) + (dolist (ext extensions) + (let ((x (cl-first (split-string ext "; ?")))) + (unless (or (member x (websocket-extensions websocket)) + (member x extra-extensions)) + (push x extra-extensions)))) + (when extra-extensions + (signal 'websocket-invalid-header + (list (format "Non-requested extensions returned by server: %S" + extra-extensions)))) + (setf (websocket-negotiated-extensions websocket) extensions))) + t) + +;;;;;;;;;;;;;;;;;;;;;; +;; Websocket server ;; +;;;;;;;;;;;;;;;;;;;;;; + +(defvar websocket-server-websockets nil + "A list of current websockets live on any server.") + +(cl-defun websocket-server (port &rest plist) + "Open a websocket server on PORT. +If the plist contains a `:host' HOST pair, this value will be +used to configure the addresses the socket listens on. The symbol +`local' specifies the local host. If unspecified or nil, the +socket will listen on all addresses. + +This also takes a plist of callbacks: `:on-open', `:on-message', +`:on-close' and `:on-error', which operate exactly as documented +in the websocket client function `websocket-open'. Returns the +connection, which should be kept in order to pass to +`websocket-server-close'." + (let* ((conn (make-network-process + :name (format "websocket server on port %s" port) + :server t + :family 'ipv4 + :noquery t + :filter 'websocket-server-filter + :log 'websocket-server-accept + :filter-multibyte nil + :plist plist + :host (plist-get plist :host) + :service port))) + conn)) + +(defun websocket-server-close (conn) + "Closes the websocket, as well as all open websockets for this server." + (let ((to-delete)) + (dolist (ws websocket-server-websockets) + (when (eq (websocket-server-conn ws) conn) + (if (eq (websocket-ready-state ws) 'closed) + (unless (member ws to-delete) + (push ws to-delete)) + (websocket-close ws)))) + (dolist (ws to-delete) + (setq websocket-server-websockets (remove ws websocket-server-websockets)))) + (delete-process conn)) + +(defun websocket-server-accept (server client _message) + "Accept a new websocket connection from a client." + (let ((ws (websocket-inner-create + :server-conn server + :conn client + :url client + :server-p t + :on-open (or (process-get server :on-open) 'identity) + :on-message (or (process-get server :on-message) (lambda (_ws _frame))) + :on-close (let ((user-method + (or (process-get server :on-close) 'identity))) + (lambda (ws) + (setq websocket-server-websockets + (remove ws websocket-server-websockets)) + (funcall user-method ws))) + :on-error (or (process-get server :on-error) + 'websocket-default-error-handler) + :protocols (process-get server :protocol) + :extensions (mapcar 'car (process-get server :extensions))))) + (unless (member ws websocket-server-websockets) + (push ws websocket-server-websockets)) + (process-put client :websocket ws) + (set-process-coding-system client 'binary 'binary) + (set-process-sentinel client + (lambda (process change) + (let ((websocket (process-get process :websocket))) + (websocket-debug websocket "State change to %s" change) + (when (and + (member (process-status process) '(closed failed exit signal)) + (not (eq 'closed (websocket-ready-state websocket)))) + (websocket-try-callback 'websocket-on-close 'on-close websocket))))))) + +(defun websocket-create-headers (url key protocol extensions custom-headers-alist) + "Create connections headers for the given URL, KEY, PROTOCOL, and EXTENSIONS. +Additionally, the CUSTOM-HEADERS-ALIST is passed from the client. +All these parameters are defined as in `websocket-open'." + (let* ((parsed-url (url-generic-parse-url url)) + (host-port (if (url-port-if-non-default parsed-url) + (format "%s:%s" (url-host parsed-url) (url-port parsed-url)) + (url-host parsed-url))) + (cookie-header (url-cookie-generate-header-lines + host-port (car (url-path-and-query parsed-url)) + (equal (url-type parsed-url) "wss")))) + (concat + (format (concat "Host: %s\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + "Sec-WebSocket-Key: %s\r\n" + "Sec-WebSocket-Version: 13\r\n" + (when protocol + (concat + (mapconcat + (lambda (protocol) + (format "Sec-WebSocket-Protocol: %s" protocol)) + protocol "\r\n") + "\r\n")) + (when extensions + (format "Sec-WebSocket-Extensions: %s\r\n" + (mapconcat + (lambda (ext) + (concat + (car ext) + (when (cdr ext) "; ") + (when (cdr ext) + (mapconcat 'identity (cdr ext) "; ")))) + extensions ", ")))) + host-port + key + protocol) + (when cookie-header cookie-header) + (mapconcat (lambda (cons) (format "%s: %s" (car cons) (cdr cons))) + custom-headers-alist "\r\n") + (when custom-headers-alist "\r\n") + "\r\n"))) + +(defun websocket-get-server-response (websocket client-protocols client-extensions) + "Get the websocket response from client WEBSOCKET." + (let ((separator "\r\n")) + (concat "HTTP/1.1 101 Switching Protocols" separator + "Upgrade: websocket" separator + "Connection: Upgrade" separator + "Sec-WebSocket-Accept: " + (websocket-accept-string websocket) separator + (let ((protocols + (websocket-intersect client-protocols + (websocket-protocols websocket)))) + (when protocols + (concat + (mapconcat + (lambda (protocol) (format "Sec-WebSocket-Protocol: %s" + protocol)) protocols separator) + separator))) + (let ((extensions (websocket-intersect + client-extensions + (websocket-extensions websocket)))) + (when extensions + (concat + (mapconcat + (lambda (extension) (format "Sec-Websocket-Extensions: %s" + extension)) extensions separator) + separator))) + separator))) + +(defun websocket-server-filter (process output) + "This acts on all OUTPUT from websocket clients PROCESS." + (let* ((ws (process-get process :websocket)) + (text (concat (websocket-inflight-input ws) output))) + (setf (websocket-inflight-input ws) nil) + (cond ((eq (websocket-ready-state ws) 'connecting) + ;; check for connection string + (let ((end-of-header-pos + (let ((pos (string-match "\r\n\r\n" text))) + (when pos (+ 4 pos))))) + (if end-of-header-pos + (progn + (let ((header-info (websocket-verify-client-headers text))) + (if header-info + (progn (setf (websocket-accept-string ws) + (websocket-calculate-accept + (plist-get header-info :key))) + (process-send-string + process + (websocket-get-server-response + ws (plist-get header-info :protocols) + (plist-get header-info :extensions))) + (setf (websocket-ready-state ws) 'open) + (websocket-try-callback 'websocket-on-open + 'on-open ws)) + (message "Invalid client headers found in: %s" output) + (process-send-string process "HTTP/1.1 400 Bad Request\r\n\r\n") + (websocket-close ws))) + (when (> (length text) (+ 1 end-of-header-pos)) + (websocket-server-filter process (substring + text + end-of-header-pos)))) + (setf (websocket-inflight-input ws) text)))) + ((eq (websocket-ready-state ws) 'open) + (websocket-process-input-on-open-ws ws text)) + ((eq (websocket-ready-state ws) 'closed) + (message "WARNING: Should not have received further input on closed websocket"))))) + +(defun websocket-verify-client-headers (output) + "Verify the headers from the WEBSOCKET client connection in OUTPUT. +Unlike `websocket-verify-headers', this is a quieter routine. We +don't want to error due to a bad client, so we just print out +messages and a plist containing `:key', the websocket key, +`:protocols' and `:extensions'." + (cl-block nil + (let ((case-fold-search t) + (plist)) + (unless (string-match "HTTP/1.1" output) + (message "Websocket client connection: HTTP/1.1 not found") + (cl-return nil)) + (unless (string-match "^Host: " output) + (message "Websocket client connection: Host header not found") + (cl-return nil)) + (unless (string-match "^Upgrade: websocket\r\n" output) + (message "Websocket client connection: Upgrade: websocket not found") + (cl-return nil)) + (if (string-match "^Sec-WebSocket-Key: \\([[:graph:]]+\\)\r\n" output) + (setq plist (plist-put plist :key (match-string 1 output))) + (message "Websocket client connect: No key sent") + (cl-return nil)) + (unless (string-match "^Sec-WebSocket-Version: 13" output) + (message "Websocket client connect: Websocket version 13 not found") + (cl-return nil)) + (when (string-match "^Sec-WebSocket-Protocol:" output) + (setq plist (plist-put plist :protocols (websocket-parse-repeated-field + output + "Sec-Websocket-Protocol")))) + (when (string-match "^Sec-WebSocket-Extensions:" output) + (setq plist (plist-put plist :extensions (websocket-parse-repeated-field + output + "Sec-Websocket-Extensions")))) + plist))) + +(provide 'websocket) + +;;; websocket.el ends here