commit 162e43ced804a8b84cbb89bee015c19ef2dfebb8 parent 7179e9cbbba2c4bcf373fcafd4ca51623a570139 Author: dwrz <dwrz@dwrz.net> Date: Sun, 24 Nov 2024 22:05:29 +0000 Update Emacs packages Diffstat:
551 files changed, 55993 insertions(+), 52350 deletions(-)
diff --git a/emacs/elpa/archives/gnu/archive-contents b/emacs/elpa/archives/gnu/archive-contents @@ -1296,7 +1296,7 @@ ("Markus Triska" . "triska@metalevel.at")) (:commit . "ea8710335eec483b576c7a800c92b8fd214aa6dd"))]) (eev . - [(20241022) + [(20241123) ((emacs (25 1))) "Support for e-scripts (eepitch blocks, elisp hyperlinks, etc)" tar @@ -1305,7 +1305,7 @@ (:maintainer "Eduardo Ochs" . "eduardoochs@gmail.com") (:authors ("Eduardo Ochs" . "eduardoochs@gmail.com")) - (:commit . "25c810004c2201960f32a60b362eb6ebe524de9f"))]) + (:commit . "be6786072fb38edaafea4a0051f5e81e8c5d4c1e"))]) (ef-themes . [(1 9 0) ((emacs @@ -1377,13 +1377,13 @@ (:url . "https://elpa.gnu.org/packages/electric-spacing.html") (:commit . "122ac5d08c3d3d91251752136abab9721d90e36c"))]) (elisa . - [(1 1 1) + [(1 1 3) ((emacs (29 2)) (ellama (0 11 2)) (llm - (0 9 1)) + (0 18 1)) (async (1 9 8)) (plz @@ -1394,7 +1394,7 @@ (:maintainer "Sergey Kostyaev" . "sskostyaev@gmail.com") (:authors ("Sergey Kostyaev" . "sskostyaev@gmail.com")) - (:commit . "4a4d1db3594a53fd90fcd453cf642d96f70a70ff"))]) + (:commit . "322d7eb839f1e981b8aa09a6ee4a7d6a22173772"))]) (elisp-benchmarks . [(1 16) nil "elisp benchmarks collection" tar @@ -1405,7 +1405,7 @@ (:url . "https://elpa.gnu.org/packages/elisp-benchmarks.html") (:commit . "1a3d97954957a95a179806e0d49ca6d178b097af"))]) (ellama . - [(0 12 5) + [(0 12 6) ((emacs (28 1)) (llm @@ -1413,7 +1413,7 @@ (spinner (1 7 4)) (transient - (0 7 6)) + (0 7)) (compat (29 1))) "Tool for interacting with LLMs" tar @@ -1422,7 +1422,7 @@ (:maintainer "Sergey Kostyaev" . "sskostyaev@gmail.com") (:authors ("Sergey Kostyaev" . "sskostyaev@gmail.com")) - (:commit . "e8f64969d66aa71341804e0a4f8d3e7c632bf3b6"))]) + (:commit . "c44d58f3f8ed05b67980fdf57279664fc0a22846"))]) (emacs-gc-stats . [(1 4 2) ((emacs @@ -1489,7 +1489,7 @@ ("Adam Porter" . "adam@alphapapa.net")) (:commit . "26bf5a4efd08bc724cf29c412c36c2909d72bb13"))]) (emms . - [(20 1) + [(20 2) ((cl-lib (0 5)) (nadvice @@ -1502,7 +1502,7 @@ (:maintainer "Yoni Rabkin" . "yrk@gnu.org") (:authors ("Jorgen Schäfer" . "forcer@forcix.cx")) - (:commit . "b5567be2176dcbdf42aa2d0ccad32a44f245dd09"))]) + (:commit . "e9b407ddf6362525ccc57423cda80716eec5b7bc"))]) (engrave-faces . [(0 3 1) ((emacs diff --git a/emacs/elpa/archives/gnu/archive-contents.signed b/emacs/elpa/archives/gnu/archive-contents.signed @@ -1 +1 @@ -Good signature from 645357D2883A0966 GNU ELPA Signing Agent (2023) <elpasign@elpa.gnu.org> (trust undefined) created at 2024-11-20T10:05:03+0000 using EDDSA -\ No newline at end of file +Good signature from 645357D2883A0966 GNU ELPA Signing Agent (2023) <elpasign@elpa.gnu.org> (trust undefined) created at 2024-11-24T10:05:02+0000 using EDDSA +\ No newline at end of file diff --git a/emacs/elpa/archives/melpa/archive-contents b/emacs/elpa/archives/melpa/archive-contents @@ -131,7 +131,7 @@ (angular-mode . [(20151201 2127) nil "Major mode for Angular.js" tar ((:url . "https://github.com/emacsattic/angular-mode") (:commit . "8720cde86af0f1859ccc8580571e8d0ad1c52cff") (:revdesc . "8720cde86af0") (:keywords "languages" "javascript") (:authors ("Rudolf Olah" . "omouse@gmail.com")) (:maintainers ("Rudolf Olah" . "omouse@gmail.com")) (:maintainer "Rudolf Olah" . "omouse@gmail.com"))]) (angular-snippets . [(20140514 523) ((s (1 4 0)) (dash (1 2 0))) "Yasnippets for AngularJS" tar ((:url . "https://github.com/magnars/angular-snippets.el") (:commit . "af5ae0a4a8603b040446c28afcf6ca01a8b4bd7b") (:revdesc . "af5ae0a4a860") (:keywords "snippets") (:authors ("Magnar Sveen" . "magnars@gmail.com")) (:maintainers ("Magnar Sveen" . "magnars@gmail.com")) (:maintainer "Magnar Sveen" . "magnars@gmail.com"))]) (anki-connect . [(20191123 1858) ((emacs (24 3))) "AnkiConnect API" tar ((:url . "https://github.com/lujun9972/anki-connect.el") (:commit . "1324f0c248aa2c6e73d6cf93fad6119d699f7dae") (:revdesc . "1324f0c248aa") (:keywords "lisp" "anki") (:authors ("DarkSun" . "lujun9972@gmail.com")) (:maintainers ("DarkSun" . "lujun9972@gmail.com")) (:maintainer "DarkSun" . "lujun9972@gmail.com"))]) - (anki-editor . [(20241019 726) ((emacs (25 1))) "Minor mode for making Anki cards with Org" tar ((:url . "https://github.com/anki-editor/anki-editor") (:commit . "dc0111527b99445689ec043ae9a8a7d8504c4949") (:revdesc . "dc0111527b99"))]) + (anki-editor . [(20241122 614) ((emacs (25 1))) "Minor mode for making Anki cards with Org" tar ((:url . "https://github.com/anki-editor/anki-editor") (:commit . "32706314adf6d02a407f2b0b411741d9c4722c05") (:revdesc . "32706314adf6"))]) (anki-editor-view . [(20230807 806) ((emacs (29 1))) "Open anki-editor notes from Anki" tar ((:url . "https://gitlab.com/vherrmann/anki-editor-view") (:commit . "6ad8c6be4f44de0c33eab012e507320b732d4800") (:revdesc . "6ad8c6be4f44") (:authors ("Valentin Herrmann" . "me@valentin-herrmann.de")) (:maintainers ("Valentin Herrmann" . "me@valentin-herrmann.de")) (:maintainer "Valentin Herrmann" . "me@valentin-herrmann.de"))]) (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" tar ((:url . "https://github.com/davidshepherd7/anki-mode") (:commit . "7cde5a68c9d0ef3811b0bd480274ea79909d2ddc") (:revdesc . "7cde5a68c9d0") (:keywords "tools") (:authors ("David Shepherd" . "davidshepherd7@gmail.com")) (:maintainers ("David Shepherd" . "davidshepherd7@gmail.com")) (:maintainer "David Shepherd" . "davidshepherd7@gmail.com"))]) (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" tar ((:url . "https://github.com/lujun9972/anki-vocabulary.el") (:commit . "863fe0219577f996ab126f1b7902db3c2cc59b2b") (:revdesc . "863fe0219577") (:keywords "lisp" "anki" "translator" "chinese") (:authors ("DarkSun" . "lujun9972@gmail.com")) (:maintainers ("DarkSun" . "lujun9972@gmail.com")) (:maintainer "DarkSun" . "lujun9972@gmail.com"))]) @@ -189,7 +189,7 @@ (astute . [(20241015 444) ((emacs (25 1))) "A minor mode to redisplay `smart' typography" tar ((:url . "https://github.com/rnkn/astute") (:commit . "69d413c952771c0d06cda161fb25fe495fb895b0") (:revdesc . "69d413c95277") (:keywords "faces" "wp") (:authors ("Paul W. Rankin" . "rnkn@rnkn.xyz")) (:maintainers ("Paul W. Rankin" . "rnkn@rnkn.xyz")) (:maintainer "Paul W. Rankin" . "rnkn@rnkn.xyz"))]) (astyle . [(20200328 616) ((emacs (24 4)) (reformatter (0 3))) "Astyle formatter functions" tar ((:url . "https://github.com/storvik/emacs-astyle") (:commit . "04ff2941f08c4b731fe6a18ee1697436d1ca1cc0") (:revdesc . "04ff2941f08c") (:keywords "astyle" "c" "c++" "cpp" "reformatter"))]) (asx . [(20191024 1100) ((emacs (26 1))) "Ask StackExchange/StackOverflow" tar ((:url . "https://github.com/ragone/asx") (:commit . "5ca12cc51bb02b5926adf9a7976ba9ca08a1ea21") (:revdesc . "5ca12cc51bb0") (:keywords "convenience") (:authors ("Alex Ragone" . "ragonedk@gmail.com")) (:maintainers ("Alex Ragone" . "ragonedk@gmail.com")) (:maintainer "Alex Ragone" . "ragonedk@gmail.com"))]) - (async . [(20241005 1824) ((emacs (24 4))) "Asynchronous processing in Emacs" tar ((:url . "https://github.com/jwiegley/emacs-async") (:commit . "af47d6f930f93d4fdc4ca46e19e17547bf486c4c") (:revdesc . "af47d6f930f9") (:keywords "async") (:authors ("John Wiegley" . "jwiegley@gmail.com")) (:maintainers ("Thierry Volpiatto" . "thievol@posteo.net")) (:maintainer "Thierry Volpiatto" . "thievol@posteo.net"))]) + (async . [(20241120 642) ((emacs (24 4))) "Asynchronous processing in Emacs" tar ((:url . "https://github.com/jwiegley/emacs-async") (:commit . "863b3366a0077279646bf9eec1f97dba6c052440") (:revdesc . "863b3366a007") (:keywords "async") (:authors ("John Wiegley" . "jwiegley@gmail.com")) (:maintainers ("Thierry Volpiatto" . "thievol@posteo.net")) (:maintainer "Thierry Volpiatto" . "thievol@posteo.net"))]) (async-await . [(20220827 437) ((emacs (25 1)) (promise (1 1)) (iter2 (0 9 10))) "Async/Await" tar ((:url . "https://github.com/chuntaro/emacs-async-await") (:commit . "e0d15e8057ed7520100bc50c5552278292ebcb07") (:revdesc . "e0d15e8057ed") (:keywords "async" "await" "convenience") (:authors ("chuntaro" . "chuntaro@sakura-games.jp")) (:maintainers ("chuntaro" . "chuntaro@sakura-games.jp")) (:maintainer "chuntaro" . "chuntaro@sakura-games.jp"))]) (async-backup . [(20230412 1534) ((emacs (24 4))) "Backup on each save without freezing Emacs" tar ((:url . "https://codeberg.org/contrapunctus/async-backup") (:commit . "d07a7bd4a5c3332a8a585680d67925385c595927") (:revdesc . "d07a7bd4a5c3") (:keywords "files") (:authors ("contrapunctus" . "xmpp:contrapunctus@jabjab.de")) (:maintainers ("contrapunctus" . "xmpp:contrapunctus@jabjab.de")) (:maintainer "contrapunctus" . "xmpp:contrapunctus@jabjab.de"))]) (async-job-queue . [(20230427 2122) ((async (1 4)) (emacs (25 1)) (queue (0 2))) "Dispatch queue of async jobs to a fixed number of slots" tar ((:url . "https://github.com/owinebar/emacs-async-job-queue") (:commit . "eeafcce7f960305666b2a51aec55cc6333f6af1b") (:revdesc . "eeafcce7f960") (:keywords "extensions" "lisp"))]) @@ -389,7 +389,7 @@ (bookmark-view . [(20240102 334) ((emacs (27 1))) "Bookmark views" tar ((:url . "https://github.com/minad/bookmark-view") (:commit . "2d16b2f88a106e57c58ad2af1f7166a847996512") (:revdesc . "2d16b2f88a10"))]) (bool-flip . [(20161215 1539) ((emacs (24 3))) "Flip the boolean under the point" tar ((:url . "https://github.com/michaeljb/bool-flip") (:commit . "0f7cc9b387429239fb929896511727d4e49a795b") (:revdesc . "0f7cc9b38742") (:keywords "boolean" "convenience" "usability") (:authors ("Michael Brandt" . "michaelbrandt5@gmail.com")) (:maintainers ("Michael Brandt" . "michaelbrandt5@gmail.com")) (:maintainer "Michael Brandt" . "michaelbrandt5@gmail.com"))]) (boon . [(20240628 703) ((emacs (26 1)) (dash (2 12 0)) (expand-region (0 10 0)) (multiple-cursors (1 3 0))) "Ergonomic Command Mode for Emacs" tar ((:url . "https://github.com/jyp/boon") (:commit . "19a7f76e75759f5266986b40c470edb1f70c43df") (:revdesc . "19a7f76e7575"))]) - (borg . [(20241102 1638) ((emacs (27 1)) (epkg (4 0 1)) (magit (4 1 0))) "Assimilate Emacs packages as Git submodules" tar ((:url . "https://github.com/emacscollective/borg") (:commit . "d1bee4874b2203ba1a067530f4142e969200f97d") (:revdesc . "d1bee4874b22") (:keywords "tools") (:authors ("Jonas Bernoulli" . "emacs.borg@jonas.bernoulli.dev")) (:maintainers ("Jonas Bernoulli" . "emacs.borg@jonas.bernoulli.dev")) (:maintainer "Jonas Bernoulli" . "emacs.borg@jonas.bernoulli.dev"))]) + (borg . [(20241123 2122) ((emacs (27 1)) (epkg (4 0 1)) (magit (4 1 0))) "Assimilate Emacs packages as Git submodules" tar ((:url . "https://github.com/emacscollective/borg") (:commit . "00e0540a95595e02da0947ccee5f1969f2e0c5eb") (:revdesc . "00e0540a9559") (:keywords "tools") (:authors ("Jonas Bernoulli" . "emacs.borg@jonas.bernoulli.dev")) (:maintainers ("Jonas Bernoulli" . "emacs.borg@jonas.bernoulli.dev")) (:maintainer "Jonas Bernoulli" . "emacs.borg@jonas.bernoulli.dev"))]) (borland-blue-theme . [(20160117 1321) ((emacs (24 1))) "Blue/yellow theme based on old DOS Borland/Turbo C IDE" tar ((:url . "https://codeberg.org/fourier/borland-blue-theme") (:commit . "db74eefebbc89d3c62575f8f50b319e87b4a3470") (:revdesc . "db74eefebbc8") (:keywords "themes") (:authors ("Alexey Veretennikov" . "alexeydotveretennikovatgmaildotcom")) (:maintainers ("Alexey Veretennikov" . "alexeydotveretennikovatgmaildotcom")) (:maintainer "Alexey Veretennikov" . "alexeydotveretennikovatgmaildotcom"))]) (boron-theme . [(20170808 1308) ((emacs (24 0))) "An Emacs 24 theme based on Boron (tmTheme)" tar ((:url . "https://github.com/emacsfodder/emacs-boron-theme") (:commit . "87ae1a765e07429fec25d2f29b004f84b52d2e0a") (:revdesc . "87ae1a765e07"))]) (boxes . [(20241003 847) ((emacs (24 3))) "ASCII boxes unlimited!" tar ((:url . "https://github.com/ascii-boxes/boxes") (:commit . "bae35281d0f814c704ef4a174a5f734541e1f457") (:revdesc . "bae35281d0f8") (:keywords "extensions") (:authors ("Jason L. Shiffer" . "jshiffer@zerotao.com")) (:maintainers ("Jason L. Shiffer" . "jshiffer@zerotao.com")) (:maintainer "Jason L. Shiffer" . "jshiffer@zerotao.com"))]) @@ -474,14 +474,14 @@ (camcorder . [(20190317 2138) ((emacs (24)) (names (20150000)) (cl-lib (0 5))) "Record screencasts in gif or other formats" tar ((:url . "https://github.com/Malabarba/camcorder.el") (:commit . "b11ca61491a27681bb3131b72b51c105fd996bed") (:revdesc . "b11ca61491a2") (:keywords "multimedia" "screencast") (:authors ("Artur Malabarba" . "bruce.connor.am@gmail.com")) (:maintainers ("Artur Malabarba" . "bruce.connor.am@gmail.com")) (:maintainer "Artur Malabarba" . "bruce.connor.am@gmail.com"))]) (caml . [(20231011 328) ((emacs (24 4))) "Caml mode for GNU Emacs" tar ((:url . "https://github.com/ocaml/caml-mode") (:commit . "47defafa2b08fb680e89bfee9cb9ce82bd9e3bcf") (:revdesc . "47defafa2b08") (:keywords "ocaml") (:authors ("Jacques Garrigue" . "garrigue@kurims.kyoto-u.ac.jp") ("Ian T Zimmerman" . "itz@rahul.net") ("Damien Doligez" . "damien.doligez@inria.fr")) (:maintainers ("Christophe Troestler" . "Christophe.Troestler@umons.ac.be")) (:maintainer "Christophe Troestler" . "Christophe.Troestler@umons.ac.be"))]) (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 ((:url . "https://github.com/kisaragi-hiu/cangjie.el") (:commit . "d6882e15f47fdde37e9f739dde604d77d25f11db") (:revdesc . "d6882e15f47f") (:keywords "convenience" "writing"))]) - (cape . [(20241105 858) ((emacs (28 1)) (compat (30))) "Completion At Point Extensions" tar ((:url . "https://github.com/minad/cape") (:commit . "74c3501ecd19ec9af0d30c16c10ded47dc995ffa") (:revdesc . "74c3501ecd19") (:keywords "abbrev" "convenience" "matching" "completion" "text") (:authors ("Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainers ("Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainer "Daniel Mendler" . "mail@daniel-mendler.de"))]) + (cape . [(20241123 925) ((emacs (28 1)) (compat (30))) "Completion At Point Extensions" tar ((:url . "https://github.com/minad/cape") (:commit . "9a7c44fe8b7ace73fa8ebf6b5805474f0ca07d01") (:revdesc . "9a7c44fe8b7a") (:keywords "abbrev" "convenience" "matching" "completion" "text") (:authors ("Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainers ("Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainer "Daniel Mendler" . "mail@daniel-mendler.de"))]) (capnp-mode . [(20210707 2310) nil "Major mode for editing Capn' Proto Files" tar ((:url . "https://github.com/capnproto/capnproto") (:commit . "f7fccad7d737f77896211bec1173117497634143") (:revdesc . "f7fccad7d737") (:authors ("Brian Taylor" . "el.wubo@gmail.com")) (:maintainers ("Brian Taylor" . "el.wubo@gmail.com")) (:maintainer "Brian Taylor" . "el.wubo@gmail.com"))]) (capture . [(20130828 1644) nil "Screencasting with \"avconv\" or \"ffmpeg\"" tar ((:url . "https://github.com/pashinin/capture.el") (:commit . "9140c207b48b3520a2f06674b3e1bee2fc92b80c") (:revdesc . "9140c207b48b") (:authors ("Sergey Pashinin" . "sergeyatpashinindotcom")) (:maintainers ("Sergey Pashinin" . "sergeyatpashinindotcom")) (:maintainer "Sergey Pashinin" . "sergeyatpashinindotcom"))]) (carbon-now-sh . [(20220701 332) ((emacs (24 4))) "Https://carbon.now.sh integration" tar ((:url . "https://github.com/veelenga/carbon-now-sh.el") (:commit . "e66f2e43e288f35ad9075f5fc84d59ad348efc88") (:revdesc . "e66f2e43e288") (:keywords "convenience"))]) (cardano-tx . [(20230606 1150) ((emacs (27 1)) (f (0 20 0)) (yasnippet (0 14 0)) (yaml-mode (0 0 15)) (yaml (0 1 0)) (helm (3 6 2)) (cbor (0 2 5)) (bech32 (0 2 1)) (readable-numbers (0 1 0)) (emacsql (3 0 0)) (emacsql-sqlite (3 1 1))) "Cardano transaction editor" tar ((:url . "https://github.com/Titan-C/cardano.el") (:commit . "cf85424b305e8f89debb756dc67eebc84639f711") (:revdesc . "cf85424b305e") (:authors ("Oscar Najera" . "https://oscarnajera.com")) (:maintainers ("Oscar Najera" . "hi@oscarnajera.com")) (:maintainer "Oscar Najera" . "hi@oscarnajera.com"))]) (cardano-wallet . [(20230606 1150) ((emacs (27 1)) (yaml (0 1 0)) (dash (2 19 0)) (yaml-mode (0 0 15)) (readable-numbers (0 1 0)) (cardano-tx (0 1 2))) "Interact with cardano wallet" tar ((:url . "https://github.com/Titan-C/cardano.el") (:commit . "cf85424b305e8f89debb756dc67eebc84639f711") (:revdesc . "cf85424b305e") (:authors ("Oscar Najera" . "https://github.com/titan")) (:maintainers ("Oscar Najera" . "hi@oscarnajera.com")) (:maintainer "Oscar Najera" . "hi@oscarnajera.com"))]) (cargo . [(20231229 915) ((emacs (24 3)) (markdown-mode (2 4))) "Emacs Minor Mode for Cargo, Rust's Package Manager" tar ((:url . "https://github.com/kwrooijen/cargo.el") (:commit . "7f8466063381eed05d4e222ce822b1dd44e3bf17") (:revdesc . "7f8466063381") (:keywords "tools"))]) - (cargo-mode . [(20240928 1910) ((emacs (25 1))) "Cargo Major Mode. Cargo is the Rust package manager" tar ((:url . "https://github.com/ayrat555/cargo-mode") (:commit . "8321d01fa4d30391a9918bd9782fadbab27843fd") (:revdesc . "8321d01fa4d3") (:keywords "tools") (:authors ("Ayrat Badykov" . "ayratin555@gmail.com")) (:maintainers ("Ayrat Badykov" . "ayratin555@gmail.com")) (:maintainer "Ayrat Badykov" . "ayratin555@gmail.com"))]) + (cargo-mode . [(20241121 638) ((emacs (25 1))) "Cargo Major Mode. Cargo is the Rust package manager" tar ((:url . "https://github.com/ayrat555/cargo-mode") (:commit . "1b97dec6fc5f8ff3a531f8d6dd33fbcc4ae1ba27") (:revdesc . "1b97dec6fc5f") (:keywords "tools") (:authors ("Ayrat Badykov" . "ayratin555@gmail.com")) (:maintainers ("Ayrat Badykov" . "ayratin555@gmail.com")) (:maintainer "Ayrat Badykov" . "ayratin555@gmail.com"))]) (cargo-transient . [(20230512 131) ((emacs (28 1))) "A transient UI for Cargo, Rust's package manager" tar ((:url . "https://github.com/peterstuart/cargo-transient") (:commit . "34d63dfb99ee9a6068dadd6390763c9735c17a85") (:revdesc . "34d63dfb99ee") (:authors ("Peter Stuart" . "peter@peterstuart.org")) (:maintainers ("Peter Stuart" . "peter@peterstuart.org")) (:maintainer "Peter Stuart" . "peter@peterstuart.org"))]) (caroline-theme . [(20160318 520) ((emacs (24))) "A trip down to New Orleans.." tar ((:url . "https://github.com/xjackk/caroline-theme") (:commit . "222fd483db304509f9e422dc82883d808e023ceb") (:revdesc . "222fd483db30") (:authors ("Jack Killilea" . "jaaacckz1@gmail.com")) (:maintainers ("Jack Killilea" . "jaaacckz1@gmail.com")) (:maintainer "Jack Killilea" . "jaaacckz1@gmail.com"))]) (cascading-dir-locals . [(20211013 1955) ((emacs (26 1))) "Apply all (!) .dir-locals.el from root to current directory" tar ((:url . "https://github.com/fritzgrabo/cascading-dir-locals") (:commit . "345d4b70e837d45ee84014684127e7399932d5e6") (:revdesc . "345d4b70e837") (:keywords "convenience") (:authors ("Fritz Grabo" . "hello@fritzgrabo.com")) (:maintainers ("Fritz Grabo" . "hello@fritzgrabo.com")) (:maintainer "Fritz Grabo" . "hello@fritzgrabo.com"))]) @@ -490,7 +490,7 @@ (cask-mode . [(20160410 1449) ((emacs (24 3))) "Major mode for editing Cask files" tar ((:url . "https://github.com/Wilfred/cask-mode") (:commit . "c97755267b7215f02df7b0c16b4210c04aee6566") (:revdesc . "c97755267b72") (:authors ("Wilfred Hughes" . "me@wilfred.me.uk")) (:maintainers ("Wilfred Hughes" . "me@wilfred.me.uk")) (:maintainer "Wilfred Hughes" . "me@wilfred.me.uk"))]) (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 ((:url . "https://github.com/AdrieanKhisbe/cask-package-toolset.el") (:commit . "2c74cd827e88c7f8360581a841e45f0b794510e7") (:revdesc . "2c74cd827e88") (:keywords "convenience" "tools") (:authors ("Adrien Becchis" . "adriean.khisbe@live.fr")) (:maintainers ("Adrien Becchis" . "adriean.khisbe@live.fr")) (:maintainer "Adrien Becchis" . "adriean.khisbe@live.fr"))]) (caskxy . [(20140513 1539) ((log4e (0 2 0)) (yaxception (0 1))) "Control Cask in Emacs" tar ((:url . "https://github.com/aki2o/caskxy") (:commit . "279f3ab79bd77fe69cb3148a79896b9bf118a9b3") (:revdesc . "279f3ab79bd7") (:keywords "convenience") (:authors ("Hiroaki Otsu" . "ootsuhiroaki@gmail.com")) (:maintainers ("Hiroaki Otsu" . "ootsuhiroaki@gmail.com")) (:maintainer "Hiroaki Otsu" . "ootsuhiroaki@gmail.com"))]) - (casual . [(20241112 2336) ((emacs (29 1)) (transient (0 6 0))) "Transient user interfaces for various modes" tar ((:url . "https://github.com/kickingvegas/casual") (:commit . "988f28bfd0564247dbb10d4343d2241f847190f6") (:revdesc . "988f28bfd056") (:keywords "tools" "wp") (:authors ("Charles Choi" . "kickingvegas@gmail.com")) (:maintainers ("Charles Choi" . "kickingvegas@gmail.com")) (:maintainer "Charles Choi" . "kickingvegas@gmail.com"))]) + (casual . [(20241123 2154) ((emacs (29 1)) (transient (0 6 0))) "Transient user interfaces for various modes" tar ((:url . "https://github.com/kickingvegas/casual") (:commit . "72126c3fae2584f8f542ce409f46fa92a9b8b456") (:revdesc . "72126c3fae25") (:keywords "tools" "wp") (:authors ("Charles Choi" . "kickingvegas@gmail.com")) (:maintainers ("Charles Choi" . "kickingvegas@gmail.com")) (:maintainer "Charles Choi" . "kickingvegas@gmail.com"))]) (casual-avy . [(20241021 2353) ((emacs (29 1)) (avy (0 5 0)) (casual (2 0 0))) "Transient UI for Avy" tar ((:url . "https://github.com/kickingvegas/casual-avy") (:commit . "7e8f7703f4ab4886f27241664aa5e1510103f74e") (:revdesc . "7e8f7703f4ab") (:keywords "tools") (:authors ("Charles Choi" . "kickingvegas@gmail.com")) (:maintainers ("Charles Choi" . "kickingvegas@gmail.com")) (:maintainer "Charles Choi" . "kickingvegas@gmail.com"))]) (casual-suite . [(20241022 3) ((emacs (29 1)) (casual (2 0 0)) (casual-avy (2 0 0)) (casual-symbol-overlay (2 0 0))) "A suite of opinionated Transient UIs" tar ((:url . "https://github.com/kickingvegas/casual-suite") (:commit . "c590e78d756bc6b3d43ab5cf8618e41b2a5bc88b") (:revdesc . "c590e78d756b") (:keywords "tools") (:authors ("Charles Choi" . "kickingvegas@gmail.com")) (:maintainers ("Charles Choi" . "kickingvegas@gmail.com")) (:maintainer "Charles Choi" . "kickingvegas@gmail.com"))]) (casual-symbol-overlay . [(20241021 2358) ((emacs (29 1)) (casual (2 0 0)) (symbol-overlay (4 2))) "Transient UI for Symbol Overlay" tar ((:url . "https://github.com/kickingvegas/casual-symbol-overlay") (:commit . "1453e7486dd0921f0319f21dd8c8b603e4eb7300") (:revdesc . "1453e7486dd0") (:keywords "tools") (:authors ("Charles Choi" . "kickingvegas@gmail.com")) (:maintainers ("Charles Choi" . "kickingvegas@gmail.com")) (:maintainer "Charles Choi" . "kickingvegas@gmail.com"))]) @@ -531,7 +531,7 @@ (chapel-mode . [(20210513 457) ((emacs (25 1)) (hydra (0 15 0))) "A major mode for the Chapel programming language" tar ((:url . "https://github.com/damon-kwok/chapel-mode") (:commit . "39fd24bb7cf44808200354ac0496be4fc4fddd9a") (:revdesc . "39fd24bb7cf4") (:keywords "chapel" "chpl" "programming" "languages"))]) (char-menu . [(20210321 1657) ((emacs (24 3)) (avy-menu (0 1))) "Create your own menu for fast insertion of arbitrary symbols" tar ((:url . "https://github.com/mrkkrp/char-menu") (:commit . "d77c4d64fc8acc386a0fb9727d346c838e75f011") (:revdesc . "d77c4d64fc8a") (:keywords "convenience" "editing") (:authors ("Mark Karpov" . "markkarpov92@gmail.com")) (:maintainers ("Mark Karpov" . "markkarpov92@gmail.com")) (:maintainer "Mark Karpov" . "markkarpov92@gmail.com"))]) (charmap . [(20200616 1418) nil "Unicode table for Emacs" tar ((:url . "https://github.com/lateau/charmap") (:commit . "feac50b87d2a596c5e5b7b82b79ddd65b6dedd8c") (:revdesc . "feac50b87d2a") (:keywords "unicode" "character" "ucs") (:authors ("Anan Mikami" . "lateau@gmail.com")) (:maintainers ("Anan Mikami" . "lateau@gmail.com")) (:maintainer "Anan Mikami" . "lateau@gmail.com"))]) - (chatgpt-shell . [(20241120 1025) ((emacs (28 1)) (shell-maker (0 68 1))) "A multi-llm comint Emacs shell (plus other goodies)" tar ((:url . "https://github.com/xenodium/chatgpt-shell") (:commit . "7132a3d718941493818df47a61f6d6006a513ac1") (:revdesc . "7132a3d71894"))]) + (chatgpt-shell . [(20241123 2155) ((emacs (28 1)) (shell-maker (0 70 2))) "A multi-llm Emacs shell (ChatGPT, Claude, Gemini) + editing integrations" tar ((:url . "https://github.com/xenodium/chatgpt-shell") (:commit . "94d5ee2c1f087b78b129f73d3e90d15809456f4d") (:revdesc . "94d5ee2c1f08"))]) (chatu . [(20240518 615) ((org (9 6 6)) (emacs (29 1)) (plantuml-mode (1 2 9))) "Convert and insert any images to org-mode or markdown buffer" tar ((:url . "https://github.com/kimim/chatu") (:commit . "f813f0bc926346fbd8151d2ae7079119d4657abb") (:revdesc . "f813f0bc9263") (:keywords "multimedia" "convenience") (:authors ("Kimi Ma" . "kimi.im@outlook.com")) (:maintainers ("Kimi Ma" . "kimi.im@outlook.com")) (:maintainer "Kimi Ma" . "kimi.im@outlook.com"))]) (chatwork . [(20240910 1531) nil "ChatWork client for Emacs" tar ((:url . "https://github.com/ataka/chatwork") (:commit . "5abbf07bd6063c922191cc645f5771a943e3043c") (:revdesc . "5abbf07bd606") (:keywords "web") (:authors ("Masayuki Ataka" . "masayuki.ataka@gmail.com")) (:maintainers ("Masayuki Ataka" . "masayuki.ataka@gmail.com")) (:maintainer "Masayuki Ataka" . "masayuki.ataka@gmail.com"))]) (cheat-sh . [(20210607 1307) ((emacs (25 1))) "Interact with cheat.sh" tar ((:url . "https://github.com/davep/cheat-sh.el") (:commit . "33bae22feae8d3375739c6bdef08d0dcdf47ee42") (:revdesc . "33bae22feae8") (:keywords "docs" "help") (:authors ("Dave Pearson" . "davep@davep.org")) (:maintainers ("Dave Pearson" . "davep@davep.org")) (:maintainer "Dave Pearson" . "davep@davep.org"))]) @@ -578,7 +578,7 @@ (citar . [(20241027 1331) ((emacs (27 1)) (parsebib (4 2)) (org (9 5)) (citeproc (0 9))) "Citation-related commands for org, latex, markdown" tar ((:url . "https://github.com/emacs-citar/citar") (:commit . "46bc177f53147a387407b1578ca38a3e96ad49a3") (:revdesc . "46bc177f5314") (:authors ("Bruce D'Arcus" . "https://github.com/bdarcus")) (:maintainers ("Bruce D'Arcus" . "https://github.com/bdarcus")) (:maintainer "Bruce D'Arcus" . "https://github.com/bdarcus"))]) (citar-denote . [(20240908 2154) ((emacs (28 1)) (citar (1 4)) (denote (2 0)) (dash (2 19 1))) "Minor mode integrating Citar and Denote" tar ((:url . "https://github.com/pprevos/citar-denote") (:commit . "c0c467653976ab40ff330fcb4586fadb69e48a29") (:revdesc . "c0c467653976") (:authors ("Peter Prevos" . "peter@prevos.net")) (:maintainers ("Peter Prevos" . "peter@prevos.net")) (:maintainer "Peter Prevos" . "peter@prevos.net"))]) (citar-embark . [(20231122 1548) ((emacs (27 1)) (embark (0 17)) (citar (0 9 7))) "Citar/Embark integration" tar ((:url . "https://github.com/emacs-citar/citar") (:commit . "572b7b6e569e9423dd948539fa48d3f53ceffe57") (:revdesc . "572b7b6e569e") (:keywords "bib" "extensions") (:authors ("Bruce D'Arcus" . "bdarcus@gmail.com")) (:maintainers ("Bruce D'Arcus" . "bdarcus@gmail.com")) (:maintainer "Bruce D'Arcus" . "bdarcus@gmail.com"))]) - (citar-org-roam . [(20240212 2159) ((emacs (27 1)) (org-roam (2 2)) (citar (1 2 0))) "Citar/org-roam integration" tar ((:url . "https://github.com/emacs-citar/citar-org-roam") (:commit . "999268c7a077aad6a8f4dfc88d0eeabdf4267fea") (:revdesc . "999268c7a077") (:authors ("Bruce D'Arcus" . "bdarcus@gmail.com")) (:maintainers ("Bruce D'Arcus" . "bdarcus@gmail.com")) (:maintainer "Bruce D'Arcus" . "bdarcus@gmail.com"))]) + (citar-org-roam . [(20241124 1352) ((emacs (27 1)) (org-roam (2 2)) (citar (1 2 0))) "Citar/org-roam integration" tar ((:url . "https://github.com/emacs-citar/citar-org-roam") (:commit . "e2cd111456d59fbf0b79e6684ad46c3686169f53") (:revdesc . "e2cd111456d5") (:authors ("Bruce D'Arcus" . "bdarcus@gmail.com")) (:maintainers ("Bruce D'Arcus" . "bdarcus@gmail.com")) (:maintainer "Bruce D'Arcus" . "bdarcus@gmail.com"))]) (citeproc . [(20240722 1110) ((emacs (26)) (dash (2 13 0)) (s (1 12 0)) (f (0 18 0)) (queue (0 2)) (string-inflection (1 0)) (org (9)) (parsebib (2 4)) (compat (28 1))) "A CSL 1.0.2 Citation Processor" tar ((:url . "https://github.com/andras-simonyi/citeproc-el") (:commit . "54184baaff555b5c7993d566d75dd04ed485b5c0") (:revdesc . "54184baaff55") (:keywords "bib") (:authors ("András Simonyi" . "andras.simonyi@gmail.com")) (:maintainers ("András Simonyi" . "andras.simonyi@gmail.com")) (:maintainer "András Simonyi" . "andras.simonyi@gmail.com"))]) (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 ((:url . "https://github.com/andras-simonyi/citeproc-org") (:commit . "22a759c4f0ec80075014dcc594baa4d1b470d995") (:revdesc . "22a759c4f0ec") (:keywords "org-ref" "org-mode" "cite" "bib") (:authors ("András Simonyi" . "andras.simonyi@gmail.com")) (:maintainers ("András Simonyi" . "andras.simonyi@gmail.com")) (:maintainer "András Simonyi" . "andras.simonyi@gmail.com"))]) (citre . [(20241028 1548) ((emacs (26 1))) "Superior code reading & auto-completion tool with pluggable backends" tar ((:url . "https://github.com/universal-ctags/citre") (:commit . "9220f430b5588f7e2d9ca82797eb37d1d7752620") (:revdesc . "9220f430b558") (:keywords "convenience" "tools") (:authors ("Hao Wang" . "amaikinono@gmail.com")) (:maintainers ("Hao Wang" . "amaikinono@gmail.com")) (:maintainer "Hao Wang" . "amaikinono@gmail.com"))]) @@ -626,7 +626,7 @@ (clojure-snippets . [(20220914 950) ((yasnippet (0 10 0))) "Yasnippets for clojure" tar ((:url . "https://github.com/mpenet/clojure-snippets") (:commit . "66d23f0ffedf2cc2be0387c3504b5f89d7300cfa") (:revdesc . "66d23f0ffedf") (:keywords "snippets") (:authors ("Max Penet" . "m@qbits.cc")) (:maintainers ("Max Penet" . "m@qbits.cc")) (:maintainer "Max Penet" . "m@qbits.cc"))]) (clojure-ts-mode . [(20241104 2135) ((emacs (29 1))) "Major mode for Clojure code" tar ((:url . "https://github.com/clojure-emacs/clojure-ts-mode") (:commit . "3ca382c3ccf2ad560d0974229ec88963e82d2fe7") (:revdesc . "3ca382c3ccf2") (:keywords "languages" "clojure" "clojurescript" "lisp") (:maintainers ("Danny Freeman" . "danny@dfreeman.email")) (:maintainer "Danny Freeman" . "danny@dfreeman.email"))]) (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" tar ((:url . "https://github.com/clojure-emacs/clomacs") (:commit . "9cd7c9fd86bc7bc627a31275d1ef131378b90a49") (:revdesc . "9cd7c9fd86bc") (:keywords "clojure" "interaction") (:authors ("Kostafey" . "kostafey@gmail.com")) (:maintainers ("Kostafey" . "kostafey@gmail.com")) (:maintainer "Kostafey" . "kostafey@gmail.com"))]) - (closql . [(20240808 1934) ((emacs (26 1)) (compat (30 0 0 0)) (emacsql (4 0 0))) "Store EIEIO objects using EmacSQL" tar ((:url . "https://github.com/magit/closql") (:commit . "c1a346d56ecee16d1f0d7707f0d62c72604a8802") (:revdesc . "c1a346d56ece") (:keywords "extensions") (:authors ("Jonas Bernoulli" . "emacs.closql@jonas.bernoulli.dev")) (:maintainers ("Jonas Bernoulli" . "emacs.closql@jonas.bernoulli.dev")) (:maintainer "Jonas Bernoulli" . "emacs.closql@jonas.bernoulli.dev"))]) + (closql . [(20241123 2130) ((emacs (26 1)) (compat (30 0 0 0)) (emacsql (4 0 0))) "Store EIEIO objects using EmacSQL" tar ((:url . "https://github.com/magit/closql") (:commit . "8f99eac1235c4e93759923703b14c18de9563efe") (:revdesc . "8f99eac1235c") (:keywords "extensions") (:authors ("Jonas Bernoulli" . "emacs.closql@jonas.bernoulli.dev")) (:maintainers ("Jonas Bernoulli" . "emacs.closql@jonas.bernoulli.dev")) (:maintainer "Jonas Bernoulli" . "emacs.closql@jonas.bernoulli.dev"))]) (closure-lint-mode . [(20101118 2124) nil "Minor mode for the Closure Linter" tar ((:url . "https://github.com/r0man/closure-lint-mode") (:commit . "bc3d2fd5c35580bf1b8af43b12484c95a343b4b5") (:revdesc . "bc3d2fd5c355") (:keywords "tools" "closure" "javascript" "lint" "flymake") (:authors ("Roman Scherer" . "roman@burningswell.com")) (:maintainers ("Roman Scherer" . "roman@burningswell.com")) (:maintainer "Roman Scherer" . "roman@burningswell.com"))]) (cloud-theme . [(20220205 1336) ((emacs (24))) "A light colored theme" tar ((:url . "https://github.com/vallyscode/cloud-theme") (:commit . "16ef7fbf0a423b29e3c3a0a2d9525afaf265aaed") (:revdesc . "16ef7fbf0a42") (:keywords "color" "theme") (:authors ("Valerii Lysenko" . "vallyscode@gmail.com")) (:maintainers ("Valerii Lysenko" . "vallyscode@gmail.com")) (:maintainer "Valerii Lysenko" . "vallyscode@gmail.com"))]) (cloud-to-butt-erc . [(20130627 2308) nil "Replace 'the cloud' with 'my butt'" tar ((:url . "https://github.com/leathekd/cloud-to-butt-erc") (:commit . "6710c03d1bc91736435cbfe845924940cae34e5c") (:revdesc . "6710c03d1bc9") (:authors ("David Leatherman" . "leathekd@gmail.com")) (:maintainers ("David Leatherman" . "leathekd@gmail.com")) (:maintainer "David Leatherman" . "leathekd@gmail.com"))]) @@ -634,11 +634,11 @@ (cm-mode . [(20240422 725) ((emacs (25 1)) (cl-lib (0 5))) "Minor mode for CriticMarkup" tar ((:url . "https://github.com/joostkremers/criticmarkup-emacs") (:commit . "a9381f57f3005a9b26f81085ecb2accf680c6f6b") (:revdesc . "a9381f57f300") (:keywords "text" "markdown") (:authors ("Joost Kremers" . "joostkremers@fastmail.fm")) (:maintainers ("Joost Kremers" . "joostkremers@fastmail.fm")) (:maintainer "Joost Kremers" . "joostkremers@fastmail.fm"))]) (cmake-font-lock . [(20230304 2223) ((cmake-mode (0 0))) "Advanced, type aware, highlight support for CMake" tar ((:url . "https://github.com/Lindydancer/cmake-font-lock") (:commit . "a6038e916bcca807ae695f7d7e5c300c3f38f415") (:revdesc . "a6038e916bcc") (:keywords "faces" "languages"))]) (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" tar ((:url . "https://github.com/atilaneves/cmake-ide") (:commit . "28dc4ab5bd01d99553901b4efeb7234280928b18") (:revdesc . "28dc4ab5bd01") (:keywords "languages") (:authors ("Atila Neves" . "atila.neves@gmail.com")) (:maintainers ("Atila Neves" . "atila.neves@gmail.com")) (:maintainer "Atila Neves" . "atila.neves@gmail.com"))]) - (cmake-mode . [(20241106 1341) ((emacs (24 1))) "Major-mode for editing CMake sources" tar ((:url . "https://gitlab.kitware.com/cmake/cmake.git") (:commit . "e22c8383b9ae4f27a78f7a8849693c03ca29c7bb") (:revdesc . "e22c8383b9ae"))]) + (cmake-mode . [(20241121 1615) ((emacs (24 1))) "Major-mode for editing CMake sources" tar ((:url . "https://gitlab.kitware.com/cmake/cmake.git") (:commit . "eb281d34548f4234e68ff31d1050aca7e8441d86") (:revdesc . "eb281d34548f"))]) (cmake-project . [(20171121 1115) nil "Integrates CMake build process with Emacs" tar ((:url . "https://github.com/alamaison/emacs-cmake-project") (:commit . "d3f408f226eff3f77f7e00dd519f4efc78fd292d") (:revdesc . "d3f408f226ef") (:keywords "c" "cmake" "languages" "tools") (:authors ("Alexander Lamaison" . "alexander.lamaison@gmail")) (:maintainers ("Alexander Lamaison" . "alexander.lamaison@gmail")) (:maintainer "Alexander Lamaison" . "alexander.lamaison@gmail"))]) (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" tar ((:url . "https://github.com/mallt/cmd-to-echo") (:commit . "e0e874fc0e1ad6d291e39ed76023445297ad438a") (:revdesc . "e0e874fc0e1a") (:authors ("Tijs Mallaerts" . "tijs.mallaerts@gmail.com")) (:maintainers ("Tijs Mallaerts" . "tijs.mallaerts@gmail.com")) (:maintainer "Tijs Mallaerts" . "tijs.mallaerts@gmail.com"))]) (cmm-mode . [(20150225 746) nil "Major mode for C-- source code" tar ((:url . "https://github.com/bgamari/cmm-mode") (:commit . "c3ad514dff3eb30434f6b20d953276d4c00de1ee") (:revdesc . "c3ad514dff3e"))]) - (cnfonts . [(20240430 536) ((emacs (24))) "A simple Chinese fonts config tool" tar ((:url . "https://github.com/tumashu/cnfonts") (:commit . "1f57d4f64f50e4dbc7ab4d963278b746f904c454") (:revdesc . "1f57d4f64f50") (:keywords "convenience" "chinese" "font") (:authors ("Feng Shu" . "tumashu@163.com")) (:maintainers ("Feng Shu" . "tumashu@163.com")) (:maintainer "Feng Shu" . "tumashu@163.com"))]) + (cnfonts . [(20241120 2133) ((emacs (24))) "A simple Chinese fonts config tool" tar ((:url . "https://github.com/tumashu/cnfonts") (:commit . "0b4fb8c2f743594010bb8137db6e71087efdaf67") (:revdesc . "0b4fb8c2f743") (:keywords "convenience" "chinese" "font") (:authors ("Feng Shu" . "tumashu@163.com")) (:maintainers ("Feng Shu" . "tumashu@163.com")) (:maintainer "Feng Shu" . "tumashu@163.com"))]) (cobalt . [(20180304 1155) ((emacs (24))) "Easily use the Cobalt.rs static site generator" tar ((:url . "https://github.com/cobalt-org/cobalt.el") (:commit . "634ace275697e188746ca22a30ff94380ec756be") (:revdesc . "634ace275697") (:keywords "convenience") (:authors ("Juan Karlo Licudine" . "accidentalrebel@gmail.com")) (:maintainers ("Juan Karlo Licudine" . "accidentalrebel@gmail.com")) (:maintainer "Juan Karlo Licudine" . "accidentalrebel@gmail.com"))]) (cobra-mode . [(20140116 2116) nil "Major mode for .NET-based Cobra language" tar ((:url . "https://github.com/Nekroze/cobra-mode") (:commit . "acd6e53f6286af5176471d01f25257e5ddb6dd01") (:revdesc . "acd6e53f6286") (:keywords "languages"))]) (coc-dc . [(20241104 1739) ((emacs (27 2)) (hydra (0 14 0))) "A Clash of Clans damage calculator" tar ((:url . "https://github.com/S0mbr3/coc-damage-calculator") (:commit . "097bc2496263fc1e69a04d0528b41baf2fd08115") (:revdesc . "097bc2496263") (:keywords "games") (:authors ("S0mbr3" . "0xf2f@proton.me")) (:maintainers ("S0mbr3" . "0xf2f@proton.me")) (:maintainer "S0mbr3" . "0xf2f@proton.me"))]) @@ -759,7 +759,7 @@ (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" tar ((:url . "https://github.com/abingham/emacs-ycmd") (:commit . "966594701c1eef1f6d4dad0c71c6d43a029977d7") (:revdesc . "966594701c1e"))]) (compdef . [(20200304 611) ((emacs (24 4))) "A local completion definer" tar ((:url . "https://github.com/cyruseuros/compdef") (:commit . "30fb5846ed851efee641ce8c5d8879ad36cd7ac6") (:revdesc . "30fb5846ed85") (:keywords "convenience"))]) (competitive-programming-snippets . [(20201115 1702) ((emacs (26)) (yasnippet (0 8 0))) "Competitive Programming snippets for yasnippet" tar ((:url . "https://github.com/sei40kr/competitive-programming-snippets") (:commit . "3b43c1aeaa6676d1d3d0c47e78790db9bee150b6") (:revdesc . "3b43c1aeaa66") (:keywords "tools") (:authors ("Seong Yong-ju" . "sei40kr@gmail.com")) (:maintainers ("Seong Yong-ju" . "sei40kr@gmail.com")) (:maintainer "Seong Yong-ju" . "sei40kr@gmail.com"))]) - (compile-angel . [(20241120 505) ((emacs (26 1))) "Automatically Compile Elisp files (auto-compile alternative)" tar ((:url . "https://github.com/jamescherti/compile-angel.el") (:commit . "359069adbd67e713782a08ae2554032cf1477703") (:revdesc . "359069adbd67") (:keywords "convenience"))]) + (compile-angel . [(20241122 635) ((emacs (26 1))) "Automatically Compile Elisp files (auto-compile alternative)" tar ((:url . "https://github.com/jamescherti/compile-angel.el") (:commit . "552b9bcd7fb54e12762fe1f5539363dba9e2acad") (:revdesc . "552b9bcd7fb5") (:keywords "convenience"))]) (compile-multi . [(20240923 1814) ((emacs (28 1))) "A multi target interface to compile" tar ((:url . "https://github.com/mohkale/compile-multi") (:commit . "94b2f267d1e424cf523643a3c9841c83f0a86368") (:revdesc . "94b2f267d1e4") (:keywords "tools" "compile" "build") (:authors ("mohsin kaleem" . "mohkale@kisara.moe")) (:maintainers ("mohsin kaleem" . "mohkale@kisara.moe")) (:maintainer "mohsin kaleem" . "mohkale@kisara.moe"))]) (compile-multi-all-the-icons . [(20240923 1814) ((emacs (28 0)) (all-the-icons-completion (0 0 1))) "Affixate `compile-multi' with icons" tar ((:url . "https://github.com/mohkale/compile-multi") (:commit . "94b2f267d1e424cf523643a3c9841c83f0a86368") (:revdesc . "94b2f267d1e4") (:keywords "tools" "compile" "build") (:authors ("mohsin kaleem" . "mohkale@kisara.moe")) (:maintainers ("mohsin kaleem" . "mohkale@kisara.moe")) (:maintainer "mohsin kaleem" . "mohkale@kisara.moe"))]) (compile-multi-embark . [(20240923 1814) ((emacs (28 1)) (compile-multi (0 4)) (embark (0 22 1))) "Integration for `compile-multi' and `embark'" tar ((:url . "https://github.com/mohkale/compile-multi") (:commit . "94b2f267d1e424cf523643a3c9841c83f0a86368") (:revdesc . "94b2f267d1e4") (:keywords "project" "convenience") (:authors ("Mohsin Kaleem" . "mohkale@kisara.moe")) (:maintainers ("Mohsin Kaleem" . "mohkale@kisara.moe")) (:maintainer "Mohsin Kaleem" . "mohkale@kisara.moe"))]) @@ -814,7 +814,7 @@ (control-mode . [(20160624 1710) nil "A \"control\" mode, similar to vim's \"normal\" mode" tar ((:url . "https://github.com/stephendavidmarsh/control-mode") (:commit . "6bf487144119b03f9cc54168f70e3d7d8d84e22b") (:revdesc . "6bf487144119") (:keywords "convenience" "emulations") (:authors ("Stephen Marsh" . "stephen.david.marsh@gmail.com")) (:maintainers ("Stephen Marsh" . "stephen.david.marsh@gmail.com")) (:maintainer "Stephen Marsh" . "stephen.david.marsh@gmail.com"))]) (conventional-changelog . [(20230902 815) ((emacs (26 3)) (transient (0 4 1))) "Conventional Changelog Generator" tar ((:url . "https://github.com/liuyinz/emacs-conventional-changelog") (:commit . "97778186ff529a487d7fb0fc20d199d26ef70f5c") (:revdesc . "97778186ff52") (:keywords "tools") (:authors ("liuyinz" . "liuyinz95@gmail.com")) (:maintainers ("liuyinz" . "liuyinz95@gmail.com")) (:maintainer "liuyinz" . "liuyinz95@gmail.com"))]) (cool-mode . [(20231026 456) ((emacs (25))) "Major mode for cool compiler language" tar ((:url . "https://github.com/nverno/cool-mode") (:commit . "46b6a38a99a954c5e77e90506eafec4092690692") (:revdesc . "46b6a38a99a9") (:authors ("Noah Peart" . "noah.v.peart@gmail.com")) (:maintainers ("Noah Peart" . "noah.v.peart@gmail.com")) (:maintainer "Noah Peart" . "noah.v.peart@gmail.com"))]) - (copilot-chat . [(20241118 1209) ((request (0 3 2)) (markdown-mode (2 6)) (emacs (27 1)) (chatgpt-shell (1 6 1)) (magit (4 0 0))) "Copilot chat interface" tar ((:url . "https://github.com/chep/copilot-chat.el") (:commit . "d2f3ef17d755d8920c747ee5677db5b003a13406") (:revdesc . "d2f3ef17d755") (:keywords "convenience" "tools") (:authors ("cedric.chepied" . "cedric.chepied@gmail.com")) (:maintainers ("cedric.chepied" . "cedric.chepied@gmail.com")) (:maintainer "cedric.chepied" . "cedric.chepied@gmail.com"))]) + (copilot-chat . [(20241121 1103) ((request (0 3 2)) (markdown-mode (2 6)) (emacs (27 1)) (chatgpt-shell (1 6 1)) (magit (4 0 0))) "Copilot chat interface" tar ((:url . "https://github.com/chep/copilot-chat.el") (:commit . "25e90bd7db9034ebbbce1873eaef83cf9d011fa5") (:revdesc . "25e90bd7db90") (:keywords "convenience" "tools") (:authors ("cedric.chepied" . "cedric.chepied@gmail.com")) (:maintainers ("cedric.chepied" . "cedric.chepied@gmail.com")) (:maintainer "cedric.chepied" . "cedric.chepied@gmail.com"))]) (copy-as-format . [(20231112 1710) ((cl-lib (0 5))) "Copy buffer locations as GitHub/Slack/JIRA etc... formatted code" tar ((:url . "https://github.com/sshaw/copy-as-format") (:commit . "b9f6f725ca9701c5a02bfb479573fdfcce2e1e30") (:revdesc . "b9f6f725ca97") (:keywords "github" "slack" "jira" "telegram" "gitlab" "bitbucket" "org-mode" "pod" "rst" "asciidoc" "whatsapp" "tools" "convenience") (:authors ("Skye Shaw" . "skye.shaw@gmail.com")) (:maintainers ("Skye Shaw" . "skye.shaw@gmail.com")) (:maintainer "Skye Shaw" . "skye.shaw@gmail.com"))]) (copy-file-on-save . [(20230402 1829) ((emacs (24 3)) (compat (29))) "Copy file on save, automatic deployment it" tar ((:url . "https://github.com/emacs-php/emacs-auto-deployment") (:commit . "370b1586feb2690d3c72185bd4f17c31ce03673a") (:revdesc . "370b1586feb2") (:keywords "files" "comm" "deploy") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainers ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me"))]) (copyit . [(20241030 543) ((emacs (24 3)) (s (1 9 0))) "Copy it, yank anything!" tar ((:url . "https://github.com/zonuexe/emacs-copyit") (:commit . "09556ba8407dc2b132b7f76cd1b458c0773a1fe8") (:revdesc . "09556ba8407d") (:keywords "convenience" "yank" "clipboard") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainers ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me"))]) @@ -952,7 +952,7 @@ (dash-at-point . [(20211023 104) nil "Search the word at point with Dash" tar ((:url . "https://github.com/stanaka/dash-at-point") (:commit . "fba1a6f42ea51d05110e12c62bdced664059eb55") (:revdesc . "fba1a6f42ea5") (:authors ("Shinji Tanaka" . "shinji.tanaka@gmail.com")) (:maintainers ("Shinji Tanaka" . "shinji.tanaka@gmail.com")) (:maintainer "Shinji Tanaka" . "shinji.tanaka@gmail.com"))]) (dash-docs . [(20210830 926) ((emacs (24 4)) (cl-lib (0 5)) (async (1 9 3))) "Offline documentation browser using Dash docsets" tar ((:url . "https://github.com/dash-docs-el/dash-docs") (:commit . "29848b6b347ac520f7646c200ed2ec36cea3feda") (:revdesc . "29848b6b347a") (:keywords "docs") (:authors ("Raimon Grau" . "raimonster@gmail.com") ("Toni Reina" . "areina0@gmail.com") ("Bryan Gilbert" . "bryan@bryan.sh")) (:maintainers ("Raimon Grau" . "raimonster@gmail.com") ("Toni Reina" . "areina0@gmail.com") ("Bryan Gilbert" . "bryan@bryan.sh")) (:maintainer "Raimon Grau" . "raimonster@gmail.com"))]) (dash-functional . [(20210826 1149) ((dash (2 18 0))) "Collection of useful combinators for Emacs Lisp" tar ((:url . "https://github.com/magnars/dash.el") (:commit . "39d067b9fbb2db65fc7a6938bfb21489ad990cb4") (:revdesc . "39d067b9fbb2") (:keywords "extensions" "lisp") (:authors ("Matus Goljer" . "matus.goljer@gmail.com") ("Magnar Sveen" . "magnars@gmail.com")) (:maintainers ("Matus Goljer" . "matus.goljer@gmail.com") ("Magnar Sveen" . "magnars@gmail.com")) (:maintainer "Matus Goljer" . "matus.goljer@gmail.com"))]) - (dashboard . [(20240923 2345) ((emacs (26 1))) "A startup screen extracted from Spacemacs" tar ((:url . "https://github.com/emacs-dashboard/emacs-dashboard") (:commit . "946b9957470a3cac6b089bdf2d9edd07a29fcc9c") (:revdesc . "946b9957470a") (:keywords "startup" "screen" "tools" "dashboard") (:authors ("Rakan Al-Hneiti" . "rakan.alhneiti@gmail.com")) (:maintainers ("Jesús Martínez" . "jesusmartinez93@gmail.com") ("Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Jesús Martínez" . "jesusmartinez93@gmail.com"))]) + (dashboard . [(20241120 2030) ((emacs (26 1))) "A startup screen extracted from Spacemacs" tar ((:url . "https://github.com/emacs-dashboard/emacs-dashboard") (:commit . "9479466d39652a8e32b74ee83822421fa08024d9") (:revdesc . "9479466d3965") (:keywords "startup" "screen" "tools" "dashboard") (:authors ("Rakan Al-Hneiti" . "rakan.alhneiti@gmail.com")) (:maintainers ("Jesús Martínez" . "jesusmartinez93@gmail.com") ("Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Jesús Martínez" . "jesusmartinez93@gmail.com"))]) (dashboard-hackernews . [(20240918 1301) ((emacs (24)) (dashboard (1 2 5)) (request (0 3 0))) "Display Hacker News on dashboard" tar ((:url . "https://github.com/hyakt/emacs-dashboard-hackernews") (:commit . "ea49fd79d12c26a2c3f9bcdffd0d70dcfee7cd74") (:revdesc . "ea49fd79d12c") (:authors ("Hayato KAJIYAMA" . "kaji1216@gmail.com")) (:maintainers ("Hayato KAJIYAMA" . "kaji1216@gmail.com")) (:maintainer "Hayato KAJIYAMA" . "kaji1216@gmail.com"))]) (dashboard-ls . [(20240101 841) ((emacs (26 1)) (dashboard (1 2 5))) "Display files/directories in current directory on Dashboard" tar ((:url . "https://github.com/emacs-dashboard/dashboard-ls") (:commit . "bc79640e8fcc625ff1af31d5e17b054b1f535f39") (:revdesc . "bc79640e8fcc") (:keywords "convenience" "directory" "file" "show") (:authors ("Jen-Chieh" . "jcs090218@gmail.com")) (:maintainers ("Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Jen-Chieh" . "jcs090218@gmail.com"))]) (dashboard-project-status . [(20190202 1354) ((emacs (24)) (git (0 1 1)) (dashboard (1 2 5))) "Display a git project status in a dashboard widget" tar ((:url . "https://github.com/functionreturnfunction/dashboard-project-status") (:commit . "7675c138e9df8fe2c626e7ba9bbb8b6717671a41") (:revdesc . "7675c138e9df") (:authors ("Jason Duncan" . "jasond496@msn.com")) (:maintainers ("Jason Duncan" . "jasond496@msn.com")) (:maintainer "Jason Duncan" . "jasond496@msn.com"))]) @@ -1103,7 +1103,7 @@ (dispass . [(20140202 1531) ((dash (1 0 0))) "Emacs wrapper for DisPass" tar ((:url . "https://github.com/ryuslash/dispass.el") (:commit . "b6e8f89040ebaaf0e7609b04bc27a8979f0ae861") (:revdesc . "b6e8f89040eb") (:keywords "processes") (:authors ("Tom Willemsen" . "tom@ryuslash.org")) (:maintainers ("Tom Willemsen" . "tom@ryuslash.org")) (:maintainer "Tom Willemsen" . "tom@ryuslash.org"))]) (display-theme . [(20140115 1556) ((emacs (24))) "Display current theme(s) at mode-line" tar ((:url . "https://github.com/kawabata/emacs-display-theme") (:commit . "b180b3be7a74ae4799a14e7e4bc2fe10e3ff7a15") (:revdesc . "b180b3be7a74") (:keywords "tools") (:authors ("Taichi" . "kawabata.taichi_at_gmail.com")) (:maintainers ("Taichi" . "kawabata.taichi_at_gmail.com")) (:maintainer "Taichi" . "kawabata.taichi_at_gmail.com"))]) (display-wttr . [(20221102 1426) ((emacs (27 1))) "Display wttr(weather) in the mode line" tar ((:url . "https://git.sr.ht/~josegpt/display-wttr") (:commit . "7062953d034e27c297d58748cf74dad552aa2873") (:revdesc . "7062953d034e") (:authors ("Jose G Perez Taveras" . "josegpt27@gmail.com")) (:maintainers ("Jose G Perez Taveras" . "josegpt27@gmail.com")) (:maintainer "Jose G Perez Taveras" . "josegpt27@gmail.com"))]) - (disproject . [(20241120 654) ((emacs (29 4)) (transient (0 7 8))) "Dispatch project commands with Transient" tar ((:url . "https://github.com/aurtzy/disproject") (:commit . "cdde9bd1c32dc99f9ea4a42741f242c99dd4570e") (:revdesc . "cdde9bd1c32d") (:keywords "convenience" "files" "vc") (:authors ("aurtzy" . "aurtzy@gmail.com")) (:maintainers ("aurtzy" . "aurtzy@gmail.com")) (:maintainer "aurtzy" . "aurtzy@gmail.com"))]) + (disproject . [(20241121 1908) ((emacs (29 4)) (transient (0 7 8))) "Dispatch project commands with Transient" tar ((:url . "https://github.com/aurtzy/disproject") (:commit . "c694d36cebbb30eedcf7ae1176f92b72d74c0a22") (:revdesc . "c694d36cebbb") (:keywords "convenience" "files" "vc") (:authors ("aurtzy" . "aurtzy@gmail.com")) (:maintainers ("aurtzy" . "aurtzy@gmail.com")) (:maintainer "aurtzy" . "aurtzy@gmail.com"))]) (dispwatch . [(20210305 342) ((emacs (24 4))) "Watch displays for configuration changes" tar ((:url . "https://github.com/mnp/dispwatch") (:commit . "03abbac89a9f625aaa1a808dd49ae4906f466421") (:revdesc . "03abbac89a9f") (:keywords "frames") (:authors ("Mitchell Perilstein" . "mitchell.perilstein@gmail.com")) (:maintainers ("Mitchell Perilstein" . "mitchell.perilstein@gmail.com")) (:maintainer "Mitchell Perilstein" . "mitchell.perilstein@gmail.com"))]) (dist-file-mode . [(20240107 2040) ((emacs (26))) "Dispatch major mode for *.dist files" tar ((:url . "https://github.com/emacs-php/dist-file-mode.el") (:commit . "8bb2f05487164cd690cac9c9c442969f6f79b81f") (:revdesc . "8bb2f0548716") (:keywords "files" "convenience") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainers ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me"))]) (distel-completion-lib . [(20180827 1344) nil "Completion library for Erlang/Distel" tar ((:url . "https://github.com/sebastiw/distel-completion") (:commit . "acc4c0a5521904203d797fe96b08e5fae4233c7e") (:revdesc . "acc4c0a55219") (:keywords "erlang" "distel" "completion"))]) @@ -1170,7 +1170,7 @@ (dropbox . [(20220314 1638) ((request (0 3 0)) (json (1 2)) (oauth (1 0 3))) "Emacs backend for dropbox" tar ((:url . "https://github.com/pavpanchekha/dropbox.el") (:commit . "c048faad0be24e8fa31974f08b710a87cf5b668c") (:revdesc . "c048faad0be2") (:keywords "dropbox") (:authors ("Pavel Panchekha" . "me@pavpanchekha.com")) (:maintainers ("Pavel Panchekha" . "me@pavpanchekha.com")) (:maintainer "Pavel Panchekha" . "me@pavpanchekha.com"))]) (drupal-mode . [(20240816 1236) ((php-mode (1 5 0))) "Advanced minor mode for Drupal development" tar ((:url . "https://github.com/arnested/drupal-mode") (:commit . "3f91d1d44df11ebd0137a896055fca6a1bb2f554") (:revdesc . "3f91d1d44df1") (:keywords "programming" "php" "drupal") (:authors ("Arne Jørgensen" . "arne@arnested.dk")) (:maintainers ("Arne Jørgensen" . "arne@arnested.dk")) (:maintainer "Arne Jørgensen" . "arne@arnested.dk"))]) (drupal-spell . [(20130520 1655) nil "Aspell extra dictionary for Drupal" tar ((:url . "https://github.com/arnested/drupal-spell") (:commit . "a69f5e3b62c4c0da74ce26c1d00d5b8f7395e4ae") (:revdesc . "a69f5e3b62c4") (:keywords "wp") (:authors ("Arne Jørgensen" . "arne@arnested.dk")) (:maintainers ("Arne Jørgensen" . "arne@arnested.dk")) (:maintainer "Arne Jørgensen" . "arne@arnested.dk"))]) - (dslide . [(20241119 859) ((emacs (29 2))) "Domain Specific sLIDEs. A presentation framework" tar ((:url . "https://github.com/positron-solutions/dslide") (:commit . "4209916697c74f196be6834edfa01a25da597444") (:revdesc . "4209916697c7") (:keywords "convenience" "org-mode" "presentation" "narrowing") (:authors ("Positron" . "contact@positron.solutions")) (:maintainers ("Positron" . "contact@positron.solutions")) (:maintainer "Positron" . "contact@positron.solutions"))]) + (dslide . [(20241123 852) ((emacs (29 2))) "Domain Specific sLIDEs. A presentation framework" tar ((:url . "https://github.com/positron-solutions/dslide") (:commit . "552e63c6ac43c2679f49b68affb4679788f8e8b9") (:revdesc . "552e63c6ac43") (:keywords "convenience" "org-mode" "presentation" "narrowing") (:authors ("Positron" . "contact@positron.solutions")) (:maintainers ("Positron" . "contact@positron.solutions")) (:maintainer "Positron" . "contact@positron.solutions"))]) (dsvn . [(20221102 1416) nil "Subversion interface" tar ((:url . "https://github.com/emacsmirror/dsvn") (:commit . "36ecd5219584e46dcf6bd252e2ea1ec517d2fc05") (:revdesc . "36ecd5219584") (:keywords "docs") (:authors ("David Kågedal" . "davidk@lysator.liu.se") ("Mattias Engdegård" . "mattiase@acm.org")) (:maintainers ("Mattias Engdegård" . "mattiase@acm.org")) (:maintainer "Mattias Engdegård" . "mattiase@acm.org"))]) (dtb-mode . [(20210105 1132) ((emacs (25))) "Show device tree souce in dtbs" tar ((:url . "https://github.com/schspa/dtb-mode") (:commit . "d5bca7d1afaac5615c586b60c7314a1d0e2514dc") (:revdesc . "d5bca7d1afaa") (:keywords "dtb" "dts" "convenience") (:authors ("Schspa Shi" . "schspa@gmail.com")) (:maintainers ("Schspa Shi" . "schspa@gmail.com")) (:maintainer "Schspa Shi" . "schspa@gmail.com"))]) (dtext-mode . [(20231120 1606) ((emacs (24 4))) "Major mode for Danbooru DText" tar ((:url . "https://github.com/JohnDevlopment/dtext-mode.el") (:commit . "5c68d1c05c4606f68384569d9baaef4f6e72fc73") (:revdesc . "5c68d1c05c46") (:keywords "languages") (:authors ("John Russell" . "johndevlopment7@gmail.com")) (:maintainers ("John Russell" . "johndevlopment7@gmail.com")) (:maintainer "John Russell" . "johndevlopment7@gmail.com"))]) @@ -1190,7 +1190,7 @@ (duplicate-thing . [(20181031 1500) nil "Duplicate current line & selection" tar ((:url . "https://github.com/ongaeshi/duplicate-thing") (:commit . "9d8fd05e3e5caa35d3f2a0c0032c92f0c0908e21") (:revdesc . "9d8fd05e3e5c") (:keywords "convenience" "command" "duplicate" "line" "selection"))]) (dut-mode . [(20170729 2111) ((emacs (24))) "Major mode for the Dut programming language" tar ((:url . "https://github.com/dut-lang/dut-mode") (:commit . "9235c7acaa6690942e9de8b7acd1e4be0c859dc1") (:revdesc . "9235c7acaa66") (:keywords "languages" "gut"))]) (dw . [(20210331 2311) ((emacs (25 1))) "Diceware passphrase generation commands" tar ((:url . "https://github.com/integral-dw/dw-passphrase-generator") (:commit . "61c5718ba64ace4c9e29de18aa2690ecc3f0f258") (:revdesc . "61c5718ba64a") (:keywords "convenience" "games") (:authors ("D. Williams" . "d.williams@posteo.net")) (:maintainers ("D. Williams" . "d.williams@posteo.net")) (:maintainer "D. Williams" . "d.williams@posteo.net"))]) - (dwim-coder-mode . [(20240712 1047) ((emacs (29))) "DWIM keybindings for C, Python, Rust, and more" tar ((:url . "https://gitlab.com/sadiq/dwim-coder-mode") (:commit . "02f5fa0c3ae5cc17ca860c792d988705f41b0eee") (:revdesc . "02f5fa0c3ae5") (:keywords "convenience" "hacks") (:authors ("Mohammed Sadiq" . "sadiq@sadiqpk.org")) (:maintainers ("Mohammed Sadiq" . "sadiq@sadiqpk.org")) (:maintainer "Mohammed Sadiq" . "sadiq@sadiqpk.org"))]) + (dwim-coder-mode . [(20241121 1117) ((emacs (29))) "DWIM keybindings for C, Python, Rust, and more" tar ((:url . "https://gitlab.com/sadiq/dwim-coder-mode") (:commit . "dda1e9b991c9dc7ff2a2779731783db3176c3b61") (:revdesc . "dda1e9b991c9") (:keywords "convenience" "hacks") (:authors ("Mohammed Sadiq" . "sadiq@sadiqpk.org")) (:maintainers ("Mohammed Sadiq" . "sadiq@sadiqpk.org")) (:maintainer "Mohammed Sadiq" . "sadiq@sadiqpk.org"))]) (dwim-shell-command . [(20241115 845) ((emacs (28 1))) "Shell commands with DWIM behaviour" tar ((:url . "https://github.com/xenodium/dwim-shell-command") (:commit . "1fa8b9d361f01618bf65111ac0b253adb0599a09") (:revdesc . "1fa8b9d361f0"))]) (dyalog-mode . [(20230214 1027) ((cl-lib (0 2)) (emacs (24 3))) "Major mode for editing Dyalog APL source code" tar ((:url . "https://github.com/harsman/dyalog-mode") (:commit . "13c0d391aa878a1609259a89fe3e6db8d21935e8") (:revdesc . "13c0d391aa87") (:keywords "languages") (:authors ("Joakim Hårsman" . "joakim.harsman@gmail.com")) (:maintainers ("Joakim Hårsman" . "joakim.harsman@gmail.com")) (:maintainer "Joakim Hårsman" . "joakim.harsman@gmail.com"))]) (dylan . [(20241102 2315) ((emacs (25 1))) "Dylan editing modes" tar ((:url . "https://github.com/dylan-lang/dylan-emacs-support") (:commit . "21e5953e2b1832f6a2c72012bd13795dc1ede52f") (:revdesc . "21e5953e2b18"))]) @@ -1212,7 +1212,7 @@ (eacl . [(20220526 1434) ((emacs (25 1))) "Auto-complete lines by grepping project" tar ((:url . "https://github.com/redguardtoo/eacl") (:commit . "4fe2cafbfeb73d806ebea8801c3522ff2886f30b") (:revdesc . "4fe2cafbfeb7") (:keywords "abbrev" "convenience" "matching") (:authors ("Chen Bin" . "chenbinDOTshATgmailDOTcom")) (:maintainers ("Chen Bin" . "chenbinDOTshATgmailDOTcom")) (:maintainer "Chen Bin" . "chenbinDOTshATgmailDOTcom"))]) (earl . [(20241020 1847) ((emacs (29 1))) "Erlang distribution protocol implementation" tar ((:url . "https://github.com/axelf4/earl") (:commit . "aa10aae9891a599f523f269cc391ed316775d12a") (:revdesc . "aa10aae9891a") (:keywords "comm" "extensions" "languages" "processes") (:authors ("Axel Forsman" . "axel@axelf.se")) (:maintainers ("Axel Forsman" . "axel@axelf.se")) (:maintainer "Axel Forsman" . "axel@axelf.se"))]) (earthfile-mode . [(20230809 2250) ((emacs (26))) "Major mode for editing Earthly file" tar ((:url . "https://github.com/earthly/earthly-emacs") (:commit . "3029e5ab06171ca5947041e95053561e10e5ba41") (:revdesc . "3029e5ab0617") (:authors ("Thanabodee Charoenpiriyakij" . "wingyminus@gmail.com")) (:maintainers ("Thanabodee Charoenpiriyakij" . "wingyminus@gmail.com")) (:maintainer "Thanabodee Charoenpiriyakij" . "wingyminus@gmail.com"))]) - (eask . [(20241117 1929) ((emacs (26 1))) "Core Eask APIs, for Eask CLI development" tar ((:url . "https://github.com/emacs-eask/eask") (:commit . "79eef0a2d94f5f6880baa90fde50b885a71e2d2c") (:revdesc . "79eef0a2d94f") (:keywords "lisp" "eask" "api") (:authors ("Jen-Chieh" . "jcs090218@gmail.com")) (:maintainers ("Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Jen-Chieh" . "jcs090218@gmail.com"))]) + (eask . [(20241123 1454) ((emacs (26 1))) "Core Eask APIs, for Eask CLI development" tar ((:url . "https://github.com/emacs-eask/eask") (:commit . "106755df719ceb202d52146d436f370f5bf8f095") (:revdesc . "106755df719c") (:keywords "lisp" "eask" "api") (:authors ("Jen-Chieh" . "jcs090218@gmail.com")) (:maintainers ("Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Jen-Chieh" . "jcs090218@gmail.com"))]) (eask-mode . [(20240101 819) ((emacs (24 3)) (eask (0 1 0))) "Major mode for editing Eask files" tar ((:url . "https://github.com/emacs-eask/eask-mode") (:commit . "774bf05f2d778a107f27f8fa47034ad15f16395c") (:revdesc . "774bf05f2d77") (:keywords "lisp" "eask") (:authors ("Jen-Chieh" . "jcs090218@gmail.com")) (:maintainers ("Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Jen-Chieh" . "jcs090218@gmail.com"))]) (easky . [(20240608 744) ((emacs (27 1)) (eask-mode (0 1 0)) (eask (0 1 0)) (ansi (0 4 1)) (lv (0 0)) (marquee-header (0 1 0))) "Control the Eask command-line interface" tar ((:url . "https://github.com/emacs-eask/easky") (:commit . "d75ec4865742a4939bd685360f8ec5b076bdcf77") (:revdesc . "d75ec4865742") (:keywords "maint" "easky") (:authors ("Jen-Chieh" . "jcs090218@gmail.com")) (:maintainers ("Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Jen-Chieh" . "jcs090218@gmail.com"))]) (easy-after-load . [(20170817 1231) nil "Eval-after-load for all files in a directory" tar ((:url . "https://github.com/pd/easy-after-load") (:commit . "29e20145da49ac9ea40463c552130777408040de") (:revdesc . "29e20145da49"))]) @@ -1287,7 +1287,7 @@ (el-get . [(20240408 837) nil "Manage the external elisp bits and pieces you depend upon" tar ((:url . "https://github.com/dimitri/el-get") (:commit . "1c5b0eb7fa162523183a96e409e4e3ae6b5cc3a0") (:revdesc . "1c5b0eb7fa16") (:keywords "emacs" "package" "elisp" "install" "elpa" "git" "git-svn" "bzr" "cvs" "svn" "darcs" "hg" "apt-get" "fink" "pacman" "http" "http-tar" "emacswiki") (:authors ("Dimitri Fontaine" . "dim@tapoueh.org")) (:maintainers ("Dimitri Fontaine" . "dim@tapoueh.org")) (:maintainer "Dimitri Fontaine" . "dim@tapoueh.org"))]) (el-init . [(20150728 920) ((emacs (24)) (cl-lib (0 5)) (anaphora (1 0 0))) "A loader inspired by init-loader" tar ((:url . "https://github.com/HKey/el-init") (:commit . "25fd21d820bca1cf576b8f70c8d5a3bc76792597") (:revdesc . "25fd21d820bc") (:authors ("Hiroki YAMAKAWA" . "s06139@gmail.com")) (:maintainers ("Hiroki YAMAKAWA" . "s06139@gmail.com")) (:maintainer "Hiroki YAMAKAWA" . "s06139@gmail.com"))]) (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" tar ((:url . "https://github.com/HKey/el-init-viewer") (:commit . "c40417db7808c8b8c9b2f196a69de5da7eee84a2") (:revdesc . "c40417db7808") (:authors ("Hiroki YAMAKAWA" . "s06139@gmail.com")) (:maintainers ("Hiroki YAMAKAWA" . "s06139@gmail.com")) (:maintainer "Hiroki YAMAKAWA" . "s06139@gmail.com"))]) - (el-job . [(20241119 1918) ((emacs (28 1)) (compat (30))) "Call a function using all CPU cores" tar ((:url . "https://github.com/meedstrom/el-job") (:commit . "c1d9aec762c7ca571ec61a6cbf581279bbb8ee67") (:revdesc . "c1d9aec762c7") (:keywords "processes") (:authors ("Martin Edström" . "meedstrom91@gmail.com")) (:maintainers ("Martin Edström" . "meedstrom91@gmail.com")) (:maintainer "Martin Edström" . "meedstrom91@gmail.com"))]) + (el-job . [(20241120 2102) ((emacs (28 1)) (compat (30))) "Call a function using all CPU cores" tar ((:url . "https://github.com/meedstrom/el-job") (:commit . "307d81fd1d1c96cc3a44d9492db0886a7dafe85c") (:revdesc . "307d81fd1d1c") (:keywords "processes") (:authors ("Martin Edström" . "meedstrom91@gmail.com")) (:maintainers ("Martin Edström" . "meedstrom91@gmail.com")) (:maintainer "Martin Edström" . "meedstrom91@gmail.com"))]) (el-mock . [(20220625 1949) nil "Tiny Mock and Stub framework in Emacs Lisp" tar ((:url . "https://github.com/rejeep/el-mock.el") (:commit . "6cfbc9de8f1927295dca6864907fe4156bd71910") (:revdesc . "6cfbc9de8f19") (:keywords "lisp" "testing" "unittest") (:authors ("rubikitch" . "rubikitch@ruby-lang.org")) (:maintainers ("Johan Andersson" . "johan.rejeep@gmail.com")) (:maintainer "Johan Andersson" . "johan.rejeep@gmail.com"))]) (el-patch . [(20231123 2216) ((emacs (26))) "Future-proof your Elisp" tar ((:url . "https://github.com/radian-software/el-patch") (:commit . "92803e7ea6e07cd56667ed7ea0dfacfc1f37f6d9") (:revdesc . "92803e7ea6e0") (:keywords "extensions") (:authors ("Radian LLC" . "contact+el-patch@radian.codes")) (:maintainers ("Radian LLC" . "contact+el-patch@radian.codes")) (:maintainer "Radian LLC" . "contact+el-patch@radian.codes"))]) (el-secretario . [(20220426 1905) ((emacs (27 1)) (org-ql (0 6 -1)) (hercules (0 3))) "Unify all your inboxes with the Emacs secretary" tar ((:url . "https://git.sr.ht/~zetagon/el-secretario") (:commit . "575396ca689065188ad0f90c379d9bcf7ff6fc0b") (:revdesc . "575396ca6890") (:keywords "convenience") (:authors ("Leo Okawa Ericson" . "http://github/Zetagon")) (:maintainers ("Leo" . "github@relevant-information.com")) (:maintainer "Leo" . "github@relevant-information.com"))]) @@ -1340,7 +1340,7 @@ (elforth . [(20210522 928) ((emacs (26 1))) "Do you have what it takes to hack Emacs Lisp in Forth?" tar ((:url . "https://github.com/lassik/elforth") (:commit . "2d8540434a28e7edaa04a992c3c362832b2fd61e") (:revdesc . "2d8540434a28") (:keywords "games") (:authors ("Lassi Kortela" . "lassi@lassi.io")) (:maintainers ("Lassi Kortela" . "lassi@lassi.io")) (:maintainer "Lassi Kortela" . "lassi@lassi.io"))]) (elgrep . [(20230814 1215) ((emacs (26 2)) (async (1 5))) "Searching files for regular expressions" tar ((:url . "https://github.com/TobiasZawada/elgrep") (:commit . "329eaf2e9e994e5535c7f7fe2685ec21d8323384") (:revdesc . "329eaf2e9e99") (:keywords "tools" "matching" "files" "unix") (:authors ("Tobias Zawada" . "i@tn-home.de")) (:maintainers ("Tobias Zawada" . "i@tn-home.de")) (:maintainer "Tobias Zawada" . "i@tn-home.de"))]) (elhome . [(20161025 2042) ((initsplit (20120630))) "A framework for a \"home\" Emacs configuration" tar ((:url . "https://github.com/demyanrogozhin/elhome") (:commit . "e789e806469af3e9705f72298683c21f6c3a516d") (:revdesc . "e789e806469a") (:keywords "lisp") (:authors ("Dave Abrahams" . "dave@boostpro.com")) (:maintainers ("Demyan Rogozhin" . "demyan.rogozhin@gmail.com")) (:maintainer "Demyan Rogozhin" . "demyan.rogozhin@gmail.com"))]) - (elisa . [(20241106 1905) ((emacs (29 2)) (ellama (0 11 2)) (llm (0 9 1)) (async (1 9 8)) (plz (0 9))) "Emacs Lisp Information System Assistant" tar ((:url . "https://github.com/s-kostyaev/elisa") (:commit . "4a4d1db3594a53fd90fcd453cf642d96f70a70ff") (:revdesc . "4a4d1db3594a") (:keywords "help" "local" "tools") (:authors ("Sergey Kostyaev" . "sskostyaev@gmail.com")) (:maintainers ("Sergey Kostyaev" . "sskostyaev@gmail.com")) (:maintainer "Sergey Kostyaev" . "sskostyaev@gmail.com"))]) + (elisa . [(20241123 2205) ((emacs (29 2)) (ellama (0 11 2)) (llm (0 18 1)) (async (1 9 8)) (plz (0 9))) "Emacs Lisp Information System Assistant" tar ((:url . "https://github.com/s-kostyaev/elisa") (:commit . "322d7eb839f1e981b8aa09a6ee4a7d6a22173772") (:revdesc . "322d7eb839f1") (:keywords "help" "local" "tools") (:authors ("Sergey Kostyaev" . "sskostyaev@gmail.com")) (:maintainers ("Sergey Kostyaev" . "sskostyaev@gmail.com")) (:maintainer "Sergey Kostyaev" . "sskostyaev@gmail.com"))]) (elisp-autofmt . [(20240801 1325) ((emacs (28 1))) "Emacs lisp auto-format" tar ((:url . "https://codeberg.org/ideasman42/emacs-elisp-autofmt") (:commit . "43a44dcbd17adf3b235de93e748321c7076f1c3c") (:revdesc . "43a44dcbd17a") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainers ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com"))]) (elisp-def . [(20230901 2308) ((dash (2 12 0)) (f (0 19 0)) (s (1 11 0)) (emacs (24 3))) "Macro-aware go-to-definition for elisp" tar ((:url . "https://github.com/Wilfred/elisp-def") (:commit . "1ad4baccbf3d0d13e7607d332ae6bc60a5dd7360") (:revdesc . "1ad4baccbf3d") (:keywords "lisp") (:authors ("Wilfred Hughes" . "me@wilfred.me.uk")) (:maintainers ("Wilfred Hughes" . "me@wilfred.me.uk")) (:maintainer "Wilfred Hughes" . "me@wilfred.me.uk"))]) (elisp-demos . [(20240128 810) ((emacs (26 3))) "Elisp API Demos" tar ((:url . "https://github.com/xuchunyang/elisp-demos") (:commit . "1a108d1c5011f9ced58be2ca98bea1fbd4130a2f") (:revdesc . "1a108d1c5011") (:keywords "lisp" "docs"))]) @@ -1355,7 +1355,7 @@ (elixir-mode . [(20230626 1738) ((emacs (25))) "Major mode for editing Elixir files" tar ((:url . "https://github.com/elixir-editors/emacs-elixir") (:commit . "00d6580a040a750e019218f9392cf9a4c2dac23a") (:revdesc . "00d6580a040a") (:keywords "languages" "elixir"))]) (elixir-ts-mode . [(20240820 947) ((emacs (29 1)) (heex-ts-mode (1 3))) "Major mode for Elixir with tree-sitter support" tar ((:url . "https://github.com/wkirschbaum/elixir-ts-mode") (:commit . "b35c983f551ccf821ebebad50747b5b417133e52") (:revdesc . "b35c983f551c") (:keywords "elixir" "languages" "tree-sitter"))]) (elixir-yasnippets . [(20150417 1239) ((yasnippet (0 8 0))) "Yasnippets for Elixir" tar ((:url . "https://github.com/hisea/elixir-yasnippets") (:commit . "980ca7626c14ef0573bec0035ec7942796062783") (:revdesc . "980ca7626c14") (:keywords "snippets") (:authors ("Yinghai Zhao" . "zyinghai@gmail.com")) (:maintainers ("Yinghai Zhao" . "zyinghai@gmail.com")) (:maintainer "Yinghai Zhao" . "zyinghai@gmail.com"))]) - (ellama . [(20241118 1307) ((emacs (28 1)) (llm (0 6 0)) (spinner (1 7 4)) (transient (0 7 6)) (compat (29 1))) "Tool for interacting with LLMs" tar ((:url . "https://github.com/s-kostyaev/ellama") (:commit . "e8f64969d66aa71341804e0a4f8d3e7c632bf3b6") (:revdesc . "e8f64969d66a") (:keywords "help" "local" "tools") (:authors ("Sergey Kostyaev" . "sskostyaev@gmail.com")) (:maintainers ("Sergey Kostyaev" . "sskostyaev@gmail.com")) (:maintainer "Sergey Kostyaev" . "sskostyaev@gmail.com"))]) + (ellama . [(20241123 1355) ((emacs (28 1)) (llm (0 6 0)) (spinner (1 7 4)) (transient (0 7)) (compat (29 1))) "Tool for interacting with LLMs" tar ((:url . "https://github.com/s-kostyaev/ellama") (:commit . "c44d58f3f8ed05b67980fdf57279664fc0a22846") (:revdesc . "c44d58f3f8ed") (:keywords "help" "local" "tools") (:authors ("Sergey Kostyaev" . "sskostyaev@gmail.com")) (:maintainers ("Sergey Kostyaev" . "sskostyaev@gmail.com")) (:maintainer "Sergey Kostyaev" . "sskostyaev@gmail.com"))]) (ellocate . [(20200112 1931) ((emacs (25 1)) (s (1 12 0)) (f (0 20 0))) "The locate command reimplemented in Emacs Lisp" tar ((:url . "https://github.com/walseb/ellocate") (:commit . "81405082f68f0577c9f176d3d4f034a7142aba59") (:revdesc . "81405082f68f") (:keywords "matching") (:authors ("Sebastian Wålinder" . "s.walinder@gmail.com")) (:maintainers ("Sebastian Wålinder" . "s.walinder@gmail.com")) (:maintainer "Sebastian Wålinder" . "s.walinder@gmail.com"))]) (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 ((:url . "https://github.com/jcollard/elm-mode") (:commit . "699841865e1bd5b7f2077baa7121510b6bcad3c7") (:revdesc . "699841865e1b"))]) (elm-test-runner . [(20230905 331) ((emacs (24 4))) "Enhanced support for running elm-test" tar ((:url . "https://github.com/juanedi/elm-test-runner") (:commit . "b664e50a4c849f5f2e2f434fc01718da10515612") (:revdesc . "b664e50a4c84"))]) @@ -1387,7 +1387,7 @@ (elune-theme . [(20231009 1709) nil "Elune theme" tar ((:url . "https://github.com/hsnovel/elune-theme") (:commit . "4d0217a7601e34fa84fc174ccf7945cd598d4135") (:revdesc . "4d0217a7601e") (:authors ("ağan Korkmaz" . "xcatalystt@gmail.com")) (:maintainers ("ağan Korkmaz" . "xcatalystt@gmail.com")) (:maintainer "ağan Korkmaz" . "xcatalystt@gmail.com"))]) (elvish-mode . [(20180809 1612) ((emacs (24 3))) "Defines a major mode for Elvish" tar ((:url . "https://github.com/ALSchwalm/elvish-mode") (:commit . "c3a7e31564256b9755b1ab9fb40d32ad78cd1ad2") (:revdesc . "c3a7e3156425") (:authors ("Adam Schwalm" . "adamschwalm@gmail.com")) (:maintainers ("Adam Schwalm" . "adamschwalm@gmail.com")) (:maintainer "Adam Schwalm" . "adamschwalm@gmail.com"))]) (elwm . [(20150817 1007) ((dash (1 1 0))) "Minimalistic window manager for emacs" tar ((:url . "https://github.com/Fuco1/elwm") (:commit . "c33b183f006ad476c3a44dab316f580f8b369930") (:revdesc . "c33b183f006a") (:keywords "docs") (:authors ("Matus Goljer" . "matus.goljer@gmail.com")) (:maintainers ("Matus Goljer" . "matus.goljer@gmail.com")) (:maintainer "Matus Goljer" . "matus.goljer@gmail.com"))]) - (elx . [(20240805 1311) ((emacs (26 1)) (compat (30 0 0 0)) (llama (0 3 1))) "Extract information from Emacs Lisp libraries" tar ((:url . "https://github.com/emacscollective/elx") (:commit . "be1afda54a182c726d7f0c584b2ac4854384ffda") (:revdesc . "be1afda54a18") (:keywords "docs" "libraries" "packages") (:authors ("Jonas Bernoulli" . "emacs.elx@jonas.bernoulli.dev")) (:maintainers ("Jonas Bernoulli" . "emacs.elx@jonas.bernoulli.dev")) (:maintainer "Jonas Bernoulli" . "emacs.elx@jonas.bernoulli.dev"))]) + (elx . [(20241123 2125) ((emacs (26 1)) (compat (30 0 0 0)) (llama (0 3 1))) "Extract information from Emacs Lisp libraries" tar ((:url . "https://github.com/emacscollective/elx") (:commit . "02ceae51c97ee0b05433c58faf874f68a88fa255") (:revdesc . "02ceae51c97e") (:keywords "docs" "libraries" "packages") (:authors ("Jonas Bernoulli" . "emacs.elx@jonas.bernoulli.dev")) (:maintainers ("Jonas Bernoulli" . "emacs.elx@jonas.bernoulli.dev")) (:maintainer "Jonas Bernoulli" . "emacs.elx@jonas.bernoulli.dev"))]) (elysium . [(20241102 2222) ((emacs (27 1)) (gptel (0 9 0))) "Automatically apply LLM-created code-suggestions" tar ((:url . "https://github.com/lanceberge/elysium") (:commit . "dcb194e0e49e2c1864e0fa2ccec3d7e37b0a44b6") (:revdesc . "dcb194e0e49e") (:authors ("Lance Bergeron" . "bergeron.lance6@gmail.com")) (:maintainers ("Lance Bergeron" . "bergeron.lance6@gmail.com")) (:maintainer "Lance Bergeron" . "bergeron.lance6@gmail.com"))]) (emacs-everywhere . [(20240509 1715) ((emacs (26 3))) "System-wide popup windows for quick edits" tar ((:url . "https://github.com/tecosaur/emacs-everywhere") (:commit . "0b731ca6da351ba40953d090acf69e81757d437b") (:revdesc . "0b731ca6da35") (:keywords "convenience" "frames") (:authors ("TEC" . "https://github.com/tecosaur")) (:maintainers ("TEC" . "contact@tecosaur.net")) (:maintainer "TEC" . "contact@tecosaur.net"))]) (emacsc . [(20241119 1435) nil "Helper for emacsc(1)" tar ((:url . "https://github.com/knu/emacsc") (:commit . "0868b7f52adae264fb79e10e57a7481632eee76e") (:revdesc . "0868b7f52ada") (:keywords "tools") (:authors ("Akinori MUSHA" . "knu@iDaemons.org")) (:maintainers ("Akinori MUSHA" . "knu@iDaemons.org")) (:maintainer "Akinori MUSHA" . "knu@iDaemons.org"))]) @@ -1406,7 +1406,7 @@ (embrace . [(20231027 419) ((cl-lib (0 5)) (expand-region (0 10 0))) "Add/Change/Delete pairs based on `expand-region'" tar ((:url . "https://github.com/cute-jumper/embrace.el") (:commit . "c7e748603151d7d91c237fd2d9cdf56e9f3b1ea8") (:revdesc . "c7e748603151") (:keywords "extensions") (:authors ("Junpeng Qiu" . "qjpchmail@gmail.com")) (:maintainers ("Junpeng Qiu" . "qjpchmail@gmail.com")) (:maintainer "Junpeng Qiu" . "qjpchmail@gmail.com"))]) (emidje . [(20190209 1726) ((emacs (25)) (cider (0 17 0)) (seq (2 16)) (magit-popup (2 4 0))) "Test runner and report viewer for Midje" tar ((:url . "https://github.com/nubank/emidje") (:commit . "7e92f053964d925c97dc8cca8d4d70a3030021db") (:revdesc . "7e92f053964d") (:keywords "tools") (:authors ("Alan Ghelardi" . "alan.ghelardi@nubank.com.br")) (:maintainers ("Alan Ghelardi" . "alan.ghelardi@nubank.com.br")) (:maintainer "Alan Ghelardi" . "alan.ghelardi@nubank.com.br"))]) (emmet-mode . [(20240617 45) nil "Unofficial Emmet's support for emacs" tar ((:url . "https://github.com/smihica/emmet-mode") (:commit . "322d3bb112fced57d63b44863357f7a0b7eee1e3") (:revdesc . "322d3bb112fc") (:keywords "convenience") (:authors ("Shin Aoyama" . "smihica@gmail.com")) (:maintainers ("Shin Aoyama" . "smihica@gmail.com")) (:maintainer "Shin Aoyama" . "smihica@gmail.com"))]) - (emms . [(20241110 1436) ((cl-lib (0 5)) (nadvice (0 3)) (seq (0))) "The Emacs Multimedia System" tar ((:url . "https://git.savannah.gnu.org/git/emms.git") (:commit . "e8c8f948b8779b3701ef3399a7510c885a5a8886") (:revdesc . "e8c8f948b877") (:keywords "emms" "mp3" "ogg" "flac" "music" "mpeg" "video" "multimedia") (:authors ("Jorgen Schäfer" . "forcer@forcix.cx")) (:maintainers ("Yoni Rabkin" . "yrk@gnu.org")) (:maintainer "Yoni Rabkin" . "yrk@gnu.org"))]) + (emms . [(20241122 2105) ((cl-lib (0 5)) (nadvice (0 3)) (seq (0))) "The Emacs Multimedia System" tar ((:url . "https://git.savannah.gnu.org/git/emms.git") (:commit . "732fa2b0a12c6a2e3d894fd9cbaccc2aa194fde6") (:revdesc . "732fa2b0a12c") (:keywords "emms" "mp3" "ogg" "flac" "music" "mpeg" "video" "multimedia") (:authors ("Jorgen Schäfer" . "forcer@forcix.cx")) (:maintainers ("Yoni Rabkin" . "yrk@gnu.org")) (:maintainer "Yoni Rabkin" . "yrk@gnu.org"))]) (emms-info-mediainfo . [(20131223 1300) ((emms (0))) "Info-method for EMMS using medianfo" tar ((:url . "https://github.com/fgallina/emms-info-mediainfo") (:commit . "bce16eae9eacd38719fea62a9755225a888da59d") (:revdesc . "bce16eae9eac") (:keywords "multimedia" "processes") (:authors ("Fabián Ezequiel Gallina" . "fgallina@gnu.org")) (:maintainers ("Fabián Ezequiel Gallina" . "fgallina@gnu.org")) (:maintainer "Fabián Ezequiel Gallina" . "fgallina@gnu.org"))]) (emms-mark-ext . [(20130529 327) ((emms (3 0))) "Extra functions for emms-mark-mode and emms-tag-edit-mode" tar ((:url . "https://github.com/vapniks/emms-mark-ext") (:commit . "ec68129e3e9e469e5bf160c6a1b7030e322f3541") (:revdesc . "ec68129e3e9e") (:keywords "convenience" "multimedia") (:authors ("Joe Bloggs" . "vapniks@yahoo.com")) (:maintainers ("Joe Bloggs" . "vapniks@yahoo.com")) (:maintainer "Joe Bloggs" . "vapniks@yahoo.com"))]) (emms-mode-line-cycle . [(20160221 1120) ((emacs (24)) (emms (4 0))) "Display the emms mode line as a ticker" tar ((:url . "https://github.com/momomo5717/emms-mode-line-cycle") (:commit . "2c2f395e484a1d345050ddd61ff5fab71a92a6bc") (:revdesc . "2c2f395e484a") (:keywords "emms" "mode-line"))]) @@ -1441,7 +1441,7 @@ (epc . [(20140610 534) ((concurrent (0 3 1)) (ctable (0 1 2))) "A RPC stack for the Emacs Lisp" tar ((:url . "https://github.com/kiwanami/emacs-epc") (:commit . "94cd36a3bec752263ac9b1b3a9dd2def329d2af7") (:revdesc . "94cd36a3bec7") (:keywords "lisp" "rpc") (:authors ("SAKURAI Masashi" . "m.sakuraiatkiwanami.net")) (:maintainers ("SAKURAI Masashi" . "m.sakuraiatkiwanami.net")) (:maintainer "SAKURAI Masashi" . "m.sakuraiatkiwanami.net"))]) (epic . [(20170210 23) ((htmlize (1 47))) "Evernote Picker for Cocoa Emacs" tar ((:url . "https://github.com/yoshinari-nomura/epic") (:commit . "a41826c330eb0ea061d58a08cc861b0c4ac8ec4e") (:revdesc . "a41826c330eb") (:keywords "evernote" "applescript") (:authors ("Yoshinari Nomura" . "nom@quickhack.net")) (:maintainers ("Yoshinari Nomura" . "nom@quickhack.net")) (:maintainer "Yoshinari Nomura" . "nom@quickhack.net"))]) (eping . [(20201027 2149) ((emacs (25 1))) "Ping websites to check internet connectivity" tar ((:url . "https://github.com/sean-hut/eping") (:commit . "004496ee06c0b8ead4a4f49e17109e8eb32eb49d") (:revdesc . "004496ee06c0") (:keywords "comm" "processes" "terminals" "unix") (:authors ("Sean Hutchings" . "seanhut@yandex.com")) (:maintainers ("Sean Hutchings" . "seanhut@yandex.com")) (:maintainer "Sean Hutchings" . "seanhut@yandex.com"))]) - (epkg . [(20241015 1238) ((emacs (26 1)) (compat (30 0 0 0)) (closql (2 0 0)) (emacsql (4 0 2)) (llama (0 3 1))) "Browse the Emacsmirror package database" tar ((:url . "https://github.com/emacscollective/epkg") (:commit . "771a7ee802e90b4bb60c54cceb3d6bff1819dcf2") (:revdesc . "771a7ee802e9") (:keywords "tools") (:authors ("Jonas Bernoulli" . "emacs.epkg@jonas.bernoulli.dev")) (:maintainers ("Jonas Bernoulli" . "emacs.epkg@jonas.bernoulli.dev")) (:maintainer "Jonas Bernoulli" . "emacs.epkg@jonas.bernoulli.dev"))]) + (epkg . [(20241123 2129) ((emacs (26 1)) (compat (30 0 0 0)) (closql (2 0 0)) (emacsql (4 0 2)) (llama (0 3 1))) "Browse the Emacsmirror package database" tar ((:url . "https://github.com/emacscollective/epkg") (:commit . "cb104ca2f22686f94bbaba6b96eda0f22c094184") (:revdesc . "cb104ca2f226") (:keywords "tools") (:authors ("Jonas Bernoulli" . "emacs.epkg@jonas.bernoulli.dev")) (:maintainers ("Jonas Bernoulli" . "emacs.epkg@jonas.bernoulli.dev")) (:maintainer "Jonas Bernoulli" . "emacs.epkg@jonas.bernoulli.dev"))]) (epkg-marginalia . [(20240821 2319) ((emacs (27 1)) (compat (30 0 0 0)) (epkg (4 0 0)) (marginalia (1 7))) "Show Epkg information in completion annotations" tar ((:url . "https://github.com/emacscollective/epkg-marginalia") (:commit . "58d5f2b6b6f68a22510cf4301dadf2ec4b5ffcaa") (:revdesc . "58d5f2b6b6f6") (:keywords "tools") (:authors ("Jonas Bernoulli" . "emacs.epkg-marginalia@jonas.bernoulli.dev")) (:maintainers ("Jonas Bernoulli" . "emacs.epkg-marginalia@jonas.bernoulli.dev")) (:maintainer "Jonas Bernoulli" . "emacs.epkg-marginalia@jonas.bernoulli.dev"))]) (epl . [(20180205 2049) ((cl-lib (0 3))) "Emacs Package Library" tar ((:url . "https://github.com/cask/epl") (:commit . "78ab7a85c08222cd15582a298a364774e3282ce6") (:revdesc . "78ab7a85c082") (:keywords "convenience") (:authors ("Sebastian Wiesner" . "swiesner@lunaryorn.com")) (:maintainers ("Johan Andersson" . "johan.rejeep@gmail.com") ("Sebastian Wiesner" . "swiesner@lunaryorn.com")) (:maintainer "Johan Andersson" . "johan.rejeep@gmail.com"))]) (epm . [(20190509 443) ((emacs (24 3)) (epl (0 8))) "Emacs Package Manager" tar ((:url . "https://github.com/xuchunyang/epm") (:commit . "6375ddbf93c5f25647f6ebb25b54045b3c93a5be") (:revdesc . "6375ddbf93c5") (:authors ("Chunyang Xu" . "xuchunyang.me@gmail.com")) (:maintainers ("Chunyang Xu" . "xuchunyang.me@gmail.com")) (:maintainer "Chunyang Xu" . "xuchunyang.me@gmail.com"))]) @@ -1543,7 +1543,7 @@ (evalator-clojure . [(20160208 2148) ((cider (0 10 0)) (evalator (1 0 0))) "Clojure evaluation context for evalator via CIDER" tar ((:url . "https://github.com/seanirby/evalator-clojure") (:commit . "caa4e0a137bdfada86593128a654e16aa617ad50") (:revdesc . "caa4e0a137bd") (:keywords "languages" "clojure" "cider" "helm") (:maintainers ("Sean Irby" . "sean.t.irby@gmail.com")) (:maintainer "Sean Irby" . "sean.t.irby@gmail.com"))]) (evangelion-theme . [(20241116 1036) ((emacs (27 1))) "A dark colour scheme inspired by Neon Genesis Evangelion" tar ((:url . "https://github.com/crmsnbleyd/evangelion-theme") (:commit . "89577330e93f1c11b3e75d1c8bbae6accc18fc48") (:revdesc . "89577330e93f") (:keywords "faces" "theme") (:authors ("Andrew Jose" . "mail@drewsh.com")) (:maintainers ("Andrew Jose" . "mail@drewsh.com")) (:maintainer "Andrew Jose" . "mail@drewsh.com"))]) (eve-mode . [(20170822 2231) ((emacs (25)) (polymode (1 0)) (markdown-mode (2 0))) "Major mode for editing Eve documents" tar ((:url . "https://github.com/witheve/emacs-eve-mode") (:commit . "a4661114d9c18725691b76321d72167ca5a9070a") (:revdesc . "a4661114d9c1") (:keywords "languages" "wp" "tools") (:authors ("Joshua Cole" . "joshuafcole@gmail.com")) (:maintainers ("Joshua Cole" . "joshuafcole@gmail.com")) (:maintainer "Joshua Cole" . "joshuafcole@gmail.com"))]) - (evedel . [(20241114 11) ((emacs (29 1)) (gptel (0 9 0))) "Instructed LLM programmer/assistant" tar ((:url . "https://github.com/daedsidog/evedel") (:commit . "0e6faec72903e1fd541c416883696309aa300ced") (:revdesc . "0e6faec72903") (:keywords "convenience" "tools") (:authors ("daedsidog" . "contact@daedsidog.com")) (:maintainers ("daedsidog" . "contact@daedsidog.com")) (:maintainer "daedsidog" . "contact@daedsidog.com"))]) + (evedel . [(20241124 31) ((emacs (29 1)) (gptel (0 9 0))) "Instructed LLM programmer/assistant" tar ((:url . "https://github.com/daedsidog/evedel") (:commit . "d1605980b0968e42063ae6a80344e9bb48cfd9f5") (:revdesc . "d1605980b096") (:keywords "convenience" "tools") (:authors ("daedsidog" . "contact@daedsidog.com")) (:maintainers ("daedsidog" . "contact@daedsidog.com")) (:maintainer "daedsidog" . "contact@daedsidog.com"))]) (evenok . [(20241031 2134) ((emacs (28 1))) "Themes with perceptively evenly distributed colors" tar ((:url . "https://codeberg.org/mekeor/evenok") (:commit . "06a84eea4cf9a845266f8bde68abe25d85bd2b77") (:revdesc . "06a84eea4cf9") (:keywords "faces" "theme") (:authors ("Mekeor Melire" . "mekeor@posteo.de")) (:maintainers ("Mekeor Melire" . "mekeor@posteo.de")) (:maintainer "Mekeor Melire" . "mekeor@posteo.de"))]) (everlasting-scratch . [(20240612 814) ((emacs (25 1))) "The *scratch* that lasts forever" tar ((:url . "https://github.com/beacoder/everlasting-scratch") (:commit . "fa1b2af29e8bb463400bbea912ab4dfaa2b0c890") (:revdesc . "fa1b2af29e8b") (:keywords "convenience" "tool") (:authors ("Huming Chen" . "chenhuming@gmail.com")) (:maintainers ("Huming Chen" . "chenhuming@gmail.com")) (:maintainer "Huming Chen" . "chenhuming@gmail.com"))]) (evil . [(20241006 1754) ((emacs (24 1)) (cl-lib (0 5)) (goto-chg (1 6)) (nadvice (0 3))) "Extensible vi layer" tar ((:url . "https://github.com/emacs-evil/evil") (:commit . "b7ab3840dbfc1da5f9ad56542fc94e3dab4be5f1") (:revdesc . "b7ab3840dbfc") (:keywords "emulations") (:maintainers ("Tom Dalziel" . "tom.dalziel@gmail.com")) (:maintainer "Tom Dalziel" . "tom.dalziel@gmail.com"))]) @@ -1554,7 +1554,7 @@ (evil-cleverparens . [(20240529 1025) ((evil (1 0)) (paredit (1)) (smartparens (1 6 1)) (emacs (24 4)) (dash (2 12 0))) "Evil friendly minor-mode for editing lisp" tar ((:url . "https://github.com/emacs-evil/evil-cleverparens") (:commit . "6637717af0bdac55f97eef98433d53a10395cf77") (:revdesc . "6637717af0bd") (:keywords "convenience" "emulations") (:authors ("Olli Piepponen" . "opieppo@gmail.com")) (:maintainers ("Olli Piepponen" . "opieppo@gmail.com")) (:maintainer "Olli Piepponen" . "opieppo@gmail.com"))]) (evil-colemak-basics . [(20241004 1613) ((emacs (24 3)) (evil (1 2 12)) (evil-snipe (2 0 3))) "Basic Colemak key bindings for evil-mode" tar ((:url . "https://github.com/wbolster/emacs-evil-colemak-basics") (:commit . "9465c8da35fe7dd0f66184e671e357ec91faa3fe") (:revdesc . "9465c8da35fe") (:keywords "convenience" "emulations" "colemak" "evil") (:authors ("Wouter Bolsterlee" . "wouter@bolsterl.ee")) (:maintainers ("Wouter Bolsterlee" . "wouter@bolsterl.ee")) (:maintainer "Wouter Bolsterlee" . "wouter@bolsterl.ee"))]) (evil-colemak-minimal . [(20171006 1317) ((emacs (24)) (evil (1 2 12))) "Minimal Colemak key bindings for evil-mode" tar ((:url . "https://github.com/bmallred/evil-colemak-minimal") (:commit . "6d98b6da60f414524a0d718f76024c26dce742b3") (:revdesc . "6d98b6da60f4") (:keywords "colemak" "evil") (:authors ("Bryan Allred" . "bryan@revolvingcow.com")) (:maintainers ("Bryan Allred" . "bryan@revolvingcow.com")) (:maintainer "Bryan Allred" . "bryan@revolvingcow.com"))]) - (evil-collection . [(20241116 1603) ((emacs (26 3)) (evil (1 2 13)) (annalist (1 0))) "A set of keybindings for Evil mode" tar ((:url . "https://github.com/emacs-evil/evil-collection") (:commit . "4f179477f7d2ab705b05f5e3524a9aa3de8d6d3d") (:revdesc . "4f179477f7d2") (:keywords "evil" "tools") (:authors ("James Nguyen" . "james@jojojames.com")) (:maintainers ("James Nguyen" . "james@jojojames.com")) (:maintainer "James Nguyen" . "james@jojojames.com"))]) + (evil-collection . [(20241123 2106) ((emacs (26 3)) (evil (1 2 13)) (annalist (1 0))) "A set of keybindings for Evil mode" tar ((:url . "https://github.com/emacs-evil/evil-collection") (:commit . "2c4e2aca1ad7be8eb41e4cb9b58b8023d8a5fd8b") (:revdesc . "2c4e2aca1ad7") (:keywords "evil" "tools") (:authors ("James Nguyen" . "james@jojojames.com")) (:maintainers ("James Nguyen" . "james@jojojames.com")) (:maintainer "James Nguyen" . "james@jojojames.com"))]) (evil-commentary . [(20230610 1006) ((evil (1 0 0))) "Comment stuff out. A port of vim-commentary" tar ((:url . "https://github.com/linktohack/evil-commentary") (:commit . "c5945f28ce47644c828aac1f5f6ec335478d17fb") (:revdesc . "c5945f28ce47") (:keywords "evil" "comment" "commentary" "evil-commentary") (:authors ("Quang Linh LE" . "linktohack@gmail.com")) (:maintainers ("Quang Linh LE" . "linktohack@gmail.com")) (:maintainer "Quang Linh LE" . "linktohack@gmail.com"))]) (evil-dvorak . [(20160416 1841) ((evil (1 0 8))) "Evil keybindings for that work with dvorak mode" tar ((:url . "https://github.com/jbranso/evil-dvorak") (:commit . "e7b80077d6f332452049eb3d7ea51f6c8fbf5947") (:revdesc . "e7b80077d6f3") (: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" tar ((:url . "https://github.com/PythonNut/evil-easymotion") (:commit . "f96c2ed38ddc07908db7c3c11bcd6285a3e8c2e9") (:revdesc . "f96c2ed38ddc") (:keywords "convenience" "evil") (:authors ("PythonNut" . "pythonnut@pythonnut.com")) (:maintainers ("PythonNut" . "pythonnut@pythonnut.com")) (:maintainer "PythonNut" . "pythonnut@pythonnut.com"))]) @@ -1563,7 +1563,7 @@ (evil-ex-fasd . [(20180903 612) ((emacs (24 4)) (evil (1 1 0)) (fasd (0))) "Using fasd right from evil-ex" tar ((:url . "https://github.com/yqrashawn/evil-ex-fasd") (:commit . "ed8fbbe23a8a268d9dcbf1a6132e928ba2c655c5") (:revdesc . "ed8fbbe23a8a") (:keywords "tools" "fasd" "evil" "navigation") (:authors ("Rashawn Zhang" . "namy.19@gmail.com")) (:maintainers ("Rashawn Zhang" . "namy.19@gmail.com")) (:maintainer "Rashawn Zhang" . "namy.19@gmail.com"))]) (evil-ex-shell-command . [(20181226 226) ((emacs (24 4)) (evil (1 1 0))) "Invoke shell-command right from evil-ex" tar ((:url . "https://github.com/yqrashawn/evil-ex-shell-command") (:commit . "a6ca6d27c07f6a0807abfb5b8f8865f1d17f54aa") (:revdesc . "a6ca6d27c07f") (:keywords "tools" "shell-command" "evil") (:authors ("Rashawn Zhang" . "namy.19@gmail.com")) (:maintainers ("Rashawn Zhang" . "namy.19@gmail.com")) (:maintainer "Rashawn Zhang" . "namy.19@gmail.com"))]) (evil-exchange . [(20200118 252) ((evil (1 2 8)) (cl-lib (0 3))) "Exchange text more easily within Evil" tar ((:url . "https://github.com/Dewdrops/evil-exchange") (:commit . "3030e21ee16a42dfce7f7cf86147b778b3f5d8c1") (:revdesc . "3030e21ee16a") (:keywords "evil" "plugin") (:authors ("Dewdrops" . "v_v_4474@126.com")) (:maintainers ("Dewdrops" . "v_v_4474@126.com")) (:maintainer "Dewdrops" . "v_v_4474@126.com"))]) - (evil-expat . [(20190521 714) ((emacs (24 3)) (evil (1 0 0))) "Evil ex commands" tar ((:url . "https://github.com/edkolev/evil-expat") (:commit . "f4fcd0aa3edc359adb5c986b5dd9188d220d84e2") (:revdesc . "f4fcd0aa3edc") (:keywords "emulations" "evil" "vim") (:authors ("edkolev" . "evgenysw@gmail.com")) (:maintainers ("edkolev" . "evgenysw@gmail.com")) (:maintainer "edkolev" . "evgenysw@gmail.com"))]) + (evil-expat . [(20241120 1350) ((emacs (24 3)) (evil (1 0 0))) "Evil ex commands" tar ((:url . "https://github.com/edkolev/evil-expat") (:commit . "23610598a9f1450f2deafc47726d5b7ce61e8695") (:revdesc . "23610598a9f1") (:keywords "emulations" "evil" "vim") (:authors ("edkolev" . "evgenysw@gmail.com")) (:maintainers ("edkolev" . "evgenysw@gmail.com")) (:maintainer "edkolev" . "evgenysw@gmail.com"))]) (evil-extra-operator . [(20210225 1239) ((evil (1 0 7))) "Evil operator for evaluating codes, taking notes, searching via google, etc" tar ((:url . "https://github.com/Dewdrops/evil-extra-operator") (:commit . "49c2dae224705f05dcfa03868b9fbbb72f2b5a8d") (:revdesc . "49c2dae22470") (:keywords "evil" "plugin") (:authors ("Dewdrops" . "v_v_4474@126.com")) (:maintainers ("Dewdrops" . "v_v_4474@126.com")) (:maintainer "Dewdrops" . "v_v_4474@126.com"))]) (evil-find-char-pinyin . [(20160514 2041) ((evil (1 2 12)) (pinyinlib (0 1 0))) "Evil's f/F/t/T/evil-snipe commands with Pinyin support" tar ((:url . "https://github.com/cute-jumper/evil-find-char-pinyin") (:commit . "04e277946d658f1a73c68dcbbadea9c21097a31c") (:revdesc . "04e277946d65") (:keywords "extensions") (:authors ("Junpeng Qiu" . "qjpchmail@gmail.com")) (:maintainers ("Junpeng Qiu" . "qjpchmail@gmail.com")) (:maintainer "Junpeng Qiu" . "qjpchmail@gmail.com"))]) (evil-fringe-mark . [(20190320 453) ((emacs (24 3)) (evil (1 0 0)) (fringe-helper (0 1 1)) (goto-chg (1 6))) "Display evil-mode marks in the fringe" tar ((:url . "https://github.com/Andrew-William-Smith/evil-fringe-mark") (:commit . "a1689fddb7ee79aaa720a77aada1208b8afd5c20") (:revdesc . "a1689fddb7ee") (:authors ("Andrew Smith" . "andy.bill.smith@gmail.com")) (:maintainers ("Andrew Smith" . "andy.bill.smith@gmail.com")) (:maintainer "Andrew Smith" . "andy.bill.smith@gmail.com"))]) @@ -1574,7 +1574,7 @@ (evil-indent-textobject . [(20130831 2219) ((evil (0))) "Evil textobjects based on indentation" tar ((:url . "https://github.com/cofi/evil-indent-textobject") (:commit . "70a1154a531b7cfdbb9a31d6922482791e20a3a7") (:revdesc . "70a1154a531b") (:keywords "convenience" "evil") (:authors ("Michael Markert" . "markert.michael@gmail.com")) (:maintainers ("Michael Markert" . "markert.michael@gmail.com")) (:maintainer "Michael Markert" . "markert.michael@gmail.com"))]) (evil-leader . [(20140606 1243) ((evil (0))) "Let there be <leader>" tar ((:url . "https://github.com/cofi/evil-leader") (:commit . "39f7014bcf8b36463e0c7512c638bda4bac6c2cf") (:revdesc . "39f7014bcf8b") (:keywords "evil" "vim-emulation" "leader") (:authors ("Michael Markert" . "markert.michael@googlemail.com")) (:maintainers ("Michael Markert" . "markert.michael@googlemail.com")) (:maintainer "Michael Markert" . "markert.michael@googlemail.com"))]) (evil-ledger . [(20180802 1612) ((emacs (24 4)) (evil (1 2 12)) (ledger-mode (0))) "Make `ledger-mode' more `evil'" tar ((:url . "https://github.com/atheriel/evil-ledger") (:commit . "7a9f9f5d39c42fffdba8004f8982642351f2b233") (:revdesc . "7a9f9f5d39c4") (:keywords "convenience" "evil" "languages" "ledger" "vim-emulation") (:authors ("Aaron Jacobs" . "atheriel@gmail.com")) (:maintainers ("Aaron Jacobs" . "atheriel@gmail.com")) (:maintainer "Aaron Jacobs" . "atheriel@gmail.com"))]) - (evil-lion . [(20241119 1044) ((emacs (24 3)) (evil (1 0 0))) "Evil align operator, port of vim-lion" tar ((:url . "https://github.com/edkolev/evil-lion") (:commit . "88bf528c5e79b4a7cc28525865824ad737a4b954") (:revdesc . "88bf528c5e79") (:keywords "emulations" "evil" "vim") (:authors ("edkolev" . "evgenysw@gmail.com")) (:maintainers ("edkolev" . "evgenysw@gmail.com")) (:maintainer "edkolev" . "evgenysw@gmail.com"))]) + (evil-lion . [(20241120 1351) ((emacs (24 3)) (evil (1 0 0))) "Evil align operator, port of vim-lion" tar ((:url . "https://github.com/edkolev/evil-lion") (:commit . "5a0bca151466960e090d1803c4c5ded88875f90a") (:revdesc . "5a0bca151466") (:keywords "emulations" "evil" "vim") (:authors ("edkolev" . "evgenysw@gmail.com")) (:maintainers ("edkolev" . "evgenysw@gmail.com")) (:maintainer "edkolev" . "evgenysw@gmail.com"))]) (evil-lisp-state . [(20160404 248) ((evil (1 0 9)) (bind-map (0)) (smartparens (1 6 1))) "An evil state to edit Lisp code" tar ((:url . "https://github.com/syl20bnr/evil-lisp-state") (:commit . "3c65fecd9917a41eaf6460f22187e2323821f3ce") (:revdesc . "3c65fecd9917") (:keywords "convenience" "editing" "evil" "smartparens" "lisp" "mnemonic") (:authors ("Sylvain Benner" . "sylvain.benner@gmail.com")) (:maintainers ("Sylvain Benner" . "sylvain.benner@gmail.com")) (:maintainer "Sylvain Benner" . "sylvain.benner@gmail.com"))]) (evil-lispops . [(20240428 1356) ((emacs (26 1)) (evil (1 2 10))) "Operations for editing lisp evilly" tar ((:url . "https://github.com/precompute/evil-lispops") (:commit . "372b52df1a45fcea6c9461e7909cfdbb1db822a9") (:revdesc . "372b52df1a45") (:authors ("precompute" . "git@precompute.net")) (:maintainers ("precompute" . "git@precompute.net")) (:maintainer "precompute" . "git@precompute.net"))]) (evil-lispy . [(20190502 739) ((lispy (0 26 0)) (evil (1 2 12)) (hydra (0 13 5))) "Precision Lisp editing with Evil and Lispy" tar ((:url . "https://github.com/mikavilpas/evil-lispy") (:commit . "ed317f7fccbdbeea8aa04a91b1b1f48a0e2ddc4e") (:revdesc . "ed317f7fccbd") (:keywords "lisp") (:authors ("Brandon Carrell" . "brandoncarrell@gmail.com") ("Mika Vilpas" . "mika.vilpas@gmail.com")) (:maintainers ("Brandon Carrell" . "brandoncarrell@gmail.com") ("Mika Vilpas" . "mika.vilpas@gmail.com")) (:maintainer "Brandon Carrell" . "brandoncarrell@gmail.com"))]) @@ -1975,7 +1975,7 @@ (foreign-regexp . [(20200325 50) nil "Search and replace by foreign regexp" tar ((:url . "https://github.com/k-talo/foreign-regexp.el") (:commit . "e2dd47f2160cadc194eb156e7c76c3c869e6706e") (:revdesc . "e2dd47f2160c") (:keywords "convenience" "emulations" "matching" "tools" "unix" "wp") (:authors ("K-talo Miyazaki" . "KeitarodotMiyazakiatgmaildotcom")) (:maintainers ("K-talo Miyazaki" . "KeitarodotMiyazakiatgmaildotcom")) (:maintainer "K-talo Miyazaki" . "KeitarodotMiyazakiatgmaildotcom"))]) (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" tar ((:url . "https://github.com/zweifisch/foreman-mode") (:commit . "22b3bb13134b617870ed1e888af739f4818be929") (:revdesc . "22b3bb13134b") (:keywords "foreman") (:authors ("ZHOU Feng" . "zf.pascal@gmail.com")) (:maintainers ("ZHOU Feng" . "zf.pascal@gmail.com")) (:maintainer "ZHOU Feng" . "zf.pascal@gmail.com"))]) (forest-blue-theme . [(20160627 842) ((emacs (24))) "Emacs theme with a dark background" tar ((:url . "https://github.com/olkinn/forest-blue-emacs") (:commit . "58096ce1a25615d2bae806c3775bae3e2775019d") (:revdesc . "58096ce1a256"))]) - (forge . [(20241114 1523) ((emacs (27 1)) (compat (30 0 0 0)) (closql (2 0 0)) (dash (2 19 1)) (emacsql (4 0 3)) (ghub (4 1 1)) (let-alist (1 0 6)) (magit (4 1 1)) (markdown-mode (2 6)) (seq (2 24)) (transient (0 7 6)) (yaml (0 5 5))) "Access Git forges from Magit" tar ((:url . "https://github.com/magit/forge") (:commit . "969b52372a9cdddf23804c999355c72644effeb2") (:revdesc . "969b52372a9c") (:keywords "git" "tools" "vc") (:authors ("Jonas Bernoulli" . "emacs.forge@jonas.bernoulli.dev")) (:maintainers ("Jonas Bernoulli" . "emacs.forge@jonas.bernoulli.dev")) (:maintainer "Jonas Bernoulli" . "emacs.forge@jonas.bernoulli.dev"))]) + (forge . [(20241123 2131) ((emacs (27 1)) (compat (30 0 0 0)) (closql (2 0 0)) (dash (2 19 1)) (emacsql (4 0 3)) (ghub (4 1 1)) (let-alist (1 0 6)) (magit (4 1 1)) (markdown-mode (2 6)) (seq (2 24)) (transient (0 7 6)) (yaml (0 5 5))) "Access Git forges from Magit" tar ((:url . "https://github.com/magit/forge") (:commit . "079d2d62b6c8590e7d165df7dc1517f7a3fca82c") (:revdesc . "079d2d62b6c8") (:keywords "git" "tools" "vc") (:authors ("Jonas Bernoulli" . "emacs.forge@jonas.bernoulli.dev")) (:maintainers ("Jonas Bernoulli" . "emacs.forge@jonas.bernoulli.dev")) (:maintainer "Jonas Bernoulli" . "emacs.forge@jonas.bernoulli.dev"))]) (form-feed . [(20210508 1627) ((emacs (24 1))) "Display ^L glyphs as horizontal lines" tar ((:url . "https://depp.brause.cc/form-feed.git") (:commit . "ac1f0ef30a11979f5dfe12d8c05a666739e486ff") (:revdesc . "ac1f0ef30a11") (:keywords "faces") (:authors ("Vasilij Schneidermann" . "mail@vasilij.de")) (:maintainers ("Vasilij Schneidermann" . "mail@vasilij.de")) (:maintainer "Vasilij Schneidermann" . "mail@vasilij.de"))]) (form-feed-st . [(20231002 2211) ((emacs (25 1))) "Display ^L glyphs as full-width horizontal lines" tar ((:url . "https://github.com/leodag/form-feed-st") (:commit . "f91c8daf35b7588e0aa24c8716c8cfd8ff0067c8") (:revdesc . "f91c8daf35b7") (:keywords "faces"))]) (format-all . [(20241001 839) ((emacs (24 4)) (inheritenv (0 1)) (language-id (0 20))) "Auto-format C, C++, JS, Python, Ruby and 50 other languages" tar ((:url . "https://github.com/lassik/emacs-format-all-the-code") (:commit . "9ae47456dad2925e4d41f58bd2c864b87f82aa8b") (:revdesc . "9ae47456dad2") (:keywords "languages" "util") (:authors ("Lassi Kortela" . "lassi@lassi.io")) (:maintainers ("Lassi Kortela" . "lassi@lassi.io")) (:maintainer "Lassi Kortela" . "lassi@lassi.io"))]) @@ -2018,7 +2018,7 @@ (function-args . [(20220516 1226) ((ivy (0 9 1))) "C++ completion for GNU Emacs" tar ((:url . "https://github.com/abo-abo/function-args") (:commit . "beba049751fed78666c87bd146a6f1cf149bb819") (:revdesc . "beba049751fe") (:authors ("Oleh Krehel" . "ohwoeowho@gmail.com")) (:maintainers ("Oleh Krehel" . "ohwoeowho@gmail.com")) (:maintainer "Oleh Krehel" . "ohwoeowho@gmail.com"))]) (fuo . [(20190812 927) ((emacs (24 4))) "Feeluown client" tar ((:url . "https://github.com/feeluown/emacs-fuo") (:commit . "0e4122f94a336a50c02bc96652d25ac3d74bedeb") (:revdesc . "0e4122f94a33") (:keywords "feeluown" "multimedia" "unix") (:authors ("cosven" . "yinshaowen241@gmail.com")) (:maintainers ("cosven" . "yinshaowen241@gmail.com")) (:maintainer "cosven" . "yinshaowen241@gmail.com"))]) (furl . [(20150509 316) nil "Friendly URL retrieval" tar ((:url . "https://github.com/nex3/furl-el") (:commit . "014438271e0ef27333dfcd599cb247f12a20d870") (:revdesc . "014438271e0e") (:authors ("Natalie Weizenbaum" . "nweiz@google.com")) (:maintainers ("Natalie Weizenbaum" . "nweiz@google.com")) (:maintainer "Natalie Weizenbaum" . "nweiz@google.com"))]) - (fussy . [(20240607 2153) ((emacs (27 2)) (flx (0 5))) "Fuzzy completion style using `flx'" tar ((:url . "https://github.com/jojojames/fussy") (:commit . "21f4ac6b971f61890d46308d7ac5db64c20228e6") (:revdesc . "21f4ac6b971f") (:keywords "matching") (:authors ("James Nguyen" . "james@jojojames.com")) (:maintainers ("James Nguyen" . "james@jojojames.com")) (:maintainer "James Nguyen" . "james@jojojames.com"))]) + (fussy . [(20241123 2300) ((emacs (27 2)) (flx (0 5))) "Fuzzy completion style using `flx'" tar ((:url . "https://github.com/jojojames/fussy") (:commit . "edd8c1adf052b1801259062add7eeb80f80266a4") (:revdesc . "edd8c1adf052") (:keywords "matching") (:authors ("James Nguyen" . "james@jojojames.com")) (:maintainers ("James Nguyen" . "james@jojojames.com")) (:maintainer "James Nguyen" . "james@jojojames.com"))]) (futhark-mode . [(20241120 854) ((emacs (24 3)) (cl-lib (0 5)) (reformatter (0 4))) "Major mode for editing Futhark source files" tar ((:url . "https://github.com/diku-dk/futhark-mode") (:commit . "a9cb4ee550d1ae14a7274d4e0c9bb6a2dff17c5a") (:revdesc . "a9cb4ee550d1") (:keywords "languages"))]) (fuz . [(20200104 524) ((emacs (25 1))) "Fast and precise fuzzy scoring/matching utils" tar ((:url . "https://github.com/rustify-emacs/fuz.el") (:commit . "0b6b64cebde5675be3a28520ee16234db48d3b8b") (:revdesc . "0b6b64cebde5") (:keywords "lisp") (:authors ("Zhu Zihao" . "all_but_last@163.com")) (:maintainers ("Zhu Zihao" . "all_but_last@163.com")) (:maintainer "Zhu Zihao" . "all_but_last@163.com"))]) (fuzzy . [(20240101 830) ((emacs (24 3))) "Fuzzy Matching" tar ((:url . "https://github.com/auto-complete/fuzzy-el") (:commit . "295140da741ac02c1bd3dec69ccf7f6268d60ec5") (:revdesc . "295140da741a") (:keywords "convenience") (:authors ("Tomohiro Matsuyama" . "m2ym.pub@gmail.com")) (:maintainers ("Tomohiro Matsuyama" . "m2ym.pub@gmail.com")) (:maintainer "Tomohiro Matsuyama" . "m2ym.pub@gmail.com"))]) @@ -2055,7 +2055,7 @@ (geiser-stklos . [(20231004 2013) ((emacs (24 4)) (geiser (0 16))) "STklos Scheme implementation of the geiser protocols" tar ((:url . "https://gitlab.com/emacs-geiser/stklos") (:commit . "c634fc2049f1616b772f5e9cb78c6171dcc4c34d") (:revdesc . "c634fc2049f1") (:keywords "languages" "stklos" "scheme" "geiser") (:authors ("Jeronimo Pellegrini" . "(j_p@aleph0.info)")) (:maintainers ("Jeronimo Pellegrini" . "(j_p@aleph0.info)")) (:maintainer "Jeronimo Pellegrini" . "(j_p@aleph0.info)"))]) (gemini-mode . [(20221127 1619) ((emacs (24 4))) "A simple highlighting package for text/gemini" tar ((:url . "https://git.carcosa.net/jmcbray/gemini.el.git") (:commit . "a7dd7c6ea4e036d0d5ecc4a5d284874c400f10ba") (:revdesc . "a7dd7c6ea4e0") (:keywords "languages") (:authors ("Jason McBrayer" . "jmcbray@carcosa.net") ("tastytea" . "tastytea@tastytea.de") ("tienne Deparis" . "etienne@depar.is")) (:maintainers ("Jason McBrayer" . "jmcbray@carcosa.net") ("tastytea" . "tastytea@tastytea.de") ("tienne Deparis" . "etienne@depar.is")) (:maintainer "Jason McBrayer" . "jmcbray@carcosa.net"))]) (gemini-write . [(20211114 1032) ((emacs (26)) (elpher (2 8 0)) (gemini-mode (1 0 0))) "Elpher for Titan" tar ((:url . "https://alexschroeder.ch/cgit/gemini-write") (:commit . "2a7d07d0ce4c5b8750f3ff1182ad94ee616734c8") (:revdesc . "2a7d07d0ce4c") (:keywords "comm" "gemini") (:authors ("Alex Schroeder" . "alex@gnu.org")) (:maintainers ("Alex Schroeder" . "alex@gnu.org")) (:maintainer "Alex Schroeder" . "alex@gnu.org"))]) - (gemtext-mode . [(20231029 2010) ((emacs (29 1))) "Major mode for Gemtext-formatted text" tar ((:url . "https://git.sr.ht/~arjca/gemtext-mode.el") (:commit . "431b3b1d7c4310ef09ba16adbc870bc0af2c0e9b") (:revdesc . "431b3b1d7c43") (:keywords "languages" "gemtext" "gemini") (:authors ("Antoine Aubé" . "courriel@arjca.fr")) (:maintainers ("Antoine Aubé" . "courriel@arjca.fr")) (:maintainer "Antoine Aubé" . "courriel@arjca.fr"))]) + (gemtext-mode . [(20241123 947) ((emacs (29 1))) "Major mode for Gemtext-formatted text" tar ((:url . "https://git.sr.ht/~arjca/gemtext-mode.el") (:commit . "bdaa67f9ffbc5ea31438eb68d444082a11994226") (:revdesc . "bdaa67f9ffbc") (:keywords "languages" "gemtext" "gemini") (:authors ("Antoine Aubé" . "courriel@arjca.fr")) (:maintainers ("Antoine Aubé" . "courriel@arjca.fr")) (:maintainer "Antoine Aubé" . "courriel@arjca.fr"))]) (general . [(20240410 1650) ((emacs (24 4)) (cl-lib (0 5))) "Convenience wrappers for keybindings" tar ((:url . "https://github.com/noctuid/general.el") (:commit . "826bf2b97a0fb4a34c5eb96ec2b172d682fd548f") (:revdesc . "826bf2b97a0f") (:keywords "vim" "evil" "leader" "keybindings" "keys") (:authors ("Fox Kiester" . "noct@posteo.net")) (:maintainers ("Fox Kiester" . "noct@posteo.net")) (:maintainer "Fox Kiester" . "noct@posteo.net"))]) (genexpr-mode . [(20240930 1335) ((emacs (27 1))) "Major mode for editing GenExpr files" tar ((:url . "https://github.com/larme/genexpr-mode") (:commit . "27d9d4d32aef1799698ddbf75e92cb71d0ce99bf") (:revdesc . "27d9d4d32aef") (:keywords "languages" "dsp") (:authors ("Zhao Shenyang" . "dev@zsy.im")) (:maintainers ("Zhao Shenyang" . "dev@zsy.im")) (:maintainer "Zhao Shenyang" . "dev@zsy.im"))]) (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 ((:url . "https://github.com/aki2o/emacs-genrnc") (:commit . "da75b1966a73ad215ec2ced4522c25f4d0bf1f9a") (:revdesc . "da75b1966a73") (:keywords "xml") (:authors ("Hiroaki Otsu" . "ootsuhiroaki@gmail.com")) (:maintainers ("Hiroaki Otsu" . "ootsuhiroaki@gmail.com")) (:maintainer "Hiroaki Otsu" . "ootsuhiroaki@gmail.com"))]) @@ -2076,7 +2076,7 @@ (gherkin-mode . [(20171224 1353) nil "An emacs major mode for editing gherkin files" tar ((:url . "https://github.com/candera/gherkin-mode") (:commit . "0313492e7da152f0aa73ddf96c0287ded8f51253") (:revdesc . "0313492e7da1") (:keywords "languages"))]) (ghost-blog . [(20171023 742) ((markdown-mode (1 0))) "A package to manage Ghost blog" tar ((:url . "https://github.com/javaguirre/ghost-blog-emacs") (:commit . "71b358643cc9a2db1bf752281ff94aba9b59e4cc") (:revdesc . "71b358643cc9") (:keywords "ghost" "blog") (:authors ("Javier Aguirre" . "hello@javaguirre.net")) (:maintainers ("Javier Aguirre" . "hello@javaguirre.net")) (:maintainer "Javier Aguirre" . "hello@javaguirre.net"))]) (ghq . [(20230510 332) ((emacs (26 1)) (dash (2 18 0)) (s (1 7 0))) "Ghq interface for emacs" tar ((:url . "https://github.com/lafrenierejm/emacs-ghq") (:commit . "eb197c14e53ac57a136ea8d34eec7528487c3301") (:revdesc . "eb197c14e53a") (:keywords "convenience") (:authors ("Roman Coedo" . "romancoedo@gmail.com")) (:maintainers ("Joseph LaFreniere" . "joseph@lafreniere.xyz")) (:maintainer "Joseph LaFreniere" . "joseph@lafreniere.xyz"))]) - (ghub . [(20241001 1025) ((emacs (26 3)) (compat (30 0 0 0)) (let-alist (1 0 6)) (treepy (0 1 2))) "Client libraries for Git forge APIs" tar ((:url . "https://github.com/magit/ghub") (:commit . "23d1cd6b089db6619d02d66957c6a274311abd60") (:revdesc . "23d1cd6b089d") (:keywords "tools") (:authors ("Jonas Bernoulli" . "emacs.ghub@jonas.bernoulli.dev")) (:maintainers ("Jonas Bernoulli" . "emacs.ghub@jonas.bernoulli.dev")) (:maintainer "Jonas Bernoulli" . "emacs.ghub@jonas.bernoulli.dev"))]) + (ghub . [(20241123 2135) ((emacs (26 3)) (compat (30 0 0 0)) (let-alist (1 0 6)) (treepy (0 1 2))) "Client libraries for Git forge APIs" tar ((:url . "https://github.com/magit/ghub") (:commit . "4f39b86544ab064204efd0dda381af90fae70f43") (:revdesc . "4f39b86544ab") (:keywords "tools") (:authors ("Jonas Bernoulli" . "emacs.ghub@jonas.bernoulli.dev")) (:maintainers ("Jonas Bernoulli" . "emacs.ghub@jonas.bernoulli.dev")) (:maintainer "Jonas Bernoulli" . "emacs.ghub@jonas.bernoulli.dev"))]) (ghub+ . [(20191229 1748) ((emacs (25)) (ghub (2 0)) (apiwrap (0 5))) "A thick GitHub API client built on ghub" tar ((:url . "https://github.com/vermiculus/ghub-plus") (:commit . "b1adef2402d7599911d4dd447a987a0cea04e6fe") (:revdesc . "b1adef2402d7") (:keywords "extensions" "multimedia" "tools") (:authors ("Sean Allred" . "code@seanallred.com")) (:maintainers ("Sean Allred" . "code@seanallred.com")) (:maintainer "Sean Allred" . "code@seanallred.com"))]) (gif-screencast . [(20230728 1144) ((emacs (25 1))) "One-frame-per-action GIF recording" tar ((:url . "https://gitlab.com/Ambrevar/emacs-gif-screencast") (:commit . "6798656d3d3107d16e30cc26bc3928b00e50c1ca") (:revdesc . "6798656d3d31") (:keywords "multimedia" "screencast") (:authors ("Pierre Neidhardt" . "mail@ambrevar.xyz")) (:maintainers ("Pierre Neidhardt" . "mail@ambrevar.xyz")) (:maintainer "Pierre Neidhardt" . "mail@ambrevar.xyz"))]) (gift-mode . [(20210528 1459) nil "Major mode for editing GIFT format quizzes" tar ((:url . "https://github.com/csrhodes/gift-mode") (:commit . "c93354e8fe1173b22f398f17b127875807f15b87") (:revdesc . "c93354e8fe11") (:authors ("Christophe Rhodes" . "christophe@rhodes.io")) (:maintainers ("Christophe Rhodes" . "christophe@rhodes.io")) (:maintainer "Christophe Rhodes" . "christophe@rhodes.io"))]) @@ -2112,7 +2112,7 @@ (git-msg-prefix . [(20191031 1304) ((emacs (24)) (s (1 10 0)) (dash (2 9 0))) "Insert commit message prefix (issue number)" tar ((:url . "https://github.com/kidd/git-msg-prefix.el") (:commit . "43f6b31c1090371260a2f15b2117a7666920bee7") (:revdesc . "43f6b31c1090") (:keywords "vc" "tools") (:authors ("Raimon Grau" . "raimonster@gmail.com")) (:maintainers ("Raimon Grau" . "raimonster@gmail.com")) (:maintainer "Raimon Grau" . "raimonster@gmail.com"))]) (git-ps1-mode . [(20200113 704) nil "Global minor-mode to print __git_ps1 in mode-line" tar ((:url . "https://github.com/10sr/git-ps1-mode-el") (:commit . "6762a309bd593d26258dfbf43e7bc21254a70fbf") (:revdesc . "6762a309bd59") (:keywords "utility" "mode-line" "git") (:authors ("10sr" . "8slashes+el[at]gmail[dot]com")) (:maintainers ("10sr" . "8slashes+el[at]gmail[dot]com")) (:maintainer "10sr" . "8slashes+el[at]gmail[dot]com"))]) (git-time-metric . [(20181116 2011) nil "Provide function to record time with gtm ( git time metric )" tar ((:url . "https://github.com/c301/gtm-emacs-plugin") (:commit . "287108ed1d6885dc795eb3bad4476aa08c626186") (:revdesc . "287108ed1d68") (:keywords "tools" "gtm" "productivity" "time") (:authors ("Anton Sivolapov" . "anton.sivolapov@gmail.com")) (:maintainers ("Anton Sivolapov" . "anton.sivolapov@gmail.com")) (:maintainer "Anton Sivolapov" . "anton.sivolapov@gmail.com"))]) - (git-timemachine . [(20240427 924) ((emacs (24 3)) (transient (0 1 0))) "Walk through git revisions of a file" tar ((:url . "https://codeberg.org/pidu/git-timemachine") (:commit . "3780835fcd67c3703ffa768206121851e6895ece") (:revdesc . "3780835fcd67") (:keywords "vc") (:authors ("Peter Stiernström" . "peter@stiernstrom.se")) (:maintainers ("Peter Stiernström" . "peter@stiernstrom.se")) (:maintainer "Peter Stiernström" . "peter@stiernstrom.se"))]) + (git-timemachine . [(20241123 1033) ((emacs (24 3)) (transient (0 1 0))) "Walk through git revisions of a file" tar ((:url . "https://codeberg.org/pidu/git-timemachine") (:commit . "2f8d2bd2cb815873d14d333b217d1fdfefca1731") (:revdesc . "2f8d2bd2cb81") (:keywords "vc") (:authors ("Peter Stiernström" . "peter@stiernstrom.se")) (:maintainers ("Peter Stiernström" . "peter@stiernstrom.se")) (:maintainer "Peter Stiernström" . "peter@stiernstrom.se"))]) (git-walktree . [(20191101 302) ((emacs (26 1)) (git (0 1 1)) (cl-lib (0 5))) "Browse Git tree and blob objects" tar ((:url . "https://github.com/10sr/git-walktree-el") (:commit . "a1a5490b89d193724ec637818baf2d8edf97c638") (:revdesc . "a1a5490b89d1") (:keywords "vc" "utility" "git") (:authors ("10sr" . "8.slashes[at]gmail[dot]com")) (:maintainers ("10sr" . "8.slashes[at]gmail[dot]com")) (:maintainer "10sr" . "8.slashes[at]gmail[dot]com"))]) (git-wip-timemachine . [(20150408 1006) ((s (1 9 0))) "Walk through git-wip revisions of a file" tar ((:url . "https://github.com/itsjeyd/git-wip-timemachine") (:commit . "1ce257e6c25117b01f1b899aca21e07eae084d40") (:revdesc . "1ce257e6c251") (:keywords "git") (:authors ("Tim Krones" . "t.krones@gmx.net")) (:maintainers ("Tim Krones" . "t.krones@gmx.net")) (:maintainer "Tim Krones" . "t.krones@gmx.net"))]) (gitconfig . [(20130718 935) nil "Emacs lisp interface to work with git-config variables" tar ((:url . "https://github.com/tonini/gitconfig.el") (:commit . "6c313a39e20702ddcebc12d146f69db1ce668901") (:revdesc . "6c313a39e207") (:keywords "git" "gitconfig" "git-config"))]) @@ -2230,7 +2230,7 @@ (gpt . [(20241020 1841) ((emacs (24 4))) "Run instruction-following language models" tar ((:url . "https://github.com/stuhlmueller/gpt.el") (:commit . "3f3d0c4c1f2d5460ed3296a63c7938c5040aaa8e") (:revdesc . "3f3d0c4c1f2d") (:keywords "openai" "anthropic" "claude" "language" "copilot" "convenience" "tools") (:authors ("Andreas Stuhlmueller" . "andreas@ought.org")) (:maintainers ("Andreas Stuhlmueller" . "andreas@ought.org")) (:maintainer "Andreas Stuhlmueller" . "andreas@ought.org"))]) (gpt-commit . [(20230716 331) ((emacs (27 1)) (magit (2 90)) (request (0 3 2))) "Commit messages with GPT in Emacs" tar ((:url . "https://github.com/ywkim/gpt-commit") (:commit . "8a8883be2051eed499c5bc3035a75ff56d64d5ff") (:revdesc . "8a8883be2051") (:authors ("Youngwook Kim" . "youngwook.kim@gmail.com")) (:maintainers ("Youngwook Kim" . "youngwook.kim@gmail.com")) (:maintainer "Youngwook Kim" . "youngwook.kim@gmail.com"))]) (gptai . [(20230530 1853) ((emacs (24 1))) "Integrate with the OpenAI API" tar ((:url . "https://github.com/antonhibl/gptai") (:commit . "e7b8b91b425986868e8bc0edcac384ba47d4d4b7") (:revdesc . "e7b8b91b4259") (:keywords "comm" "convenience") (:authors ("Anton Hibl" . "antonhibl11@gmail.com")) (:maintainers ("Anton Hibl" . "antonhibl11@gmail.com")) (:maintainer "Anton Hibl" . "antonhibl11@gmail.com"))]) - (gptel . [(20241115 456) ((emacs (27 1)) (transient (0 4 0)) (compat (29 1 4 1))) "Interact with ChatGPT or other LLMs" tar ((:url . "https://github.com/karthink/gptel") (:commit . "51ae43f4edefe0375acbcb836d94d8d0348a531d") (:revdesc . "51ae43f4edef") (:keywords "convenience") (:authors ("Karthik Chikmagalur" . "karthik.chikmagalur@gmail.com")) (:maintainers ("Karthik Chikmagalur" . "karthik.chikmagalur@gmail.com")) (:maintainer "Karthik Chikmagalur" . "karthik.chikmagalur@gmail.com"))]) + (gptel . [(20241123 2058) ((emacs (27 1)) (transient (0 4 0)) (compat (29 1 4 1))) "Interact with ChatGPT or other LLMs" tar ((:url . "https://github.com/karthink/gptel") (:commit . "20e07943d792133ba57a325e123436de471e1429") (:revdesc . "20e07943d792") (:keywords "convenience") (:authors ("Karthik Chikmagalur" . "karthik.chikmagalur@gmail.com")) (:maintainers ("Karthik Chikmagalur" . "karthik.chikmagalur@gmail.com")) (:maintainer "Karthik Chikmagalur" . "karthik.chikmagalur@gmail.com"))]) (gpx . [(20240609 2200) ((emacs (27 1))) "Major mode for GPX files" tar ((:url . "https://github.com/mkcms/gpx-mode") (:commit . "88aa5fed1b0987d90f442eb002ab0f2e4731e223") (:revdesc . "88aa5fed1b09") (:keywords "data" "tools") (:authors ("Michał Krzywkowski" . "k.michal@zoho.com")) (:maintainers ("Michał Krzywkowski" . "k.michal@zoho.com")) (:maintainer "Michał Krzywkowski" . "k.michal@zoho.com"))]) (grab-mac-link . [(20210511 1303) ((emacs (24))) "Grab link from Mac Apps and insert it into Emacs" tar ((:url . "https://github.com/xuchunyang/grab-mac-link.el") (:commit . "5fdb03bf57bc4a530374b896e0f8b5139dc794e3") (:revdesc . "5fdb03bf57bc") (:keywords "mac" "hyperlink"))]) (grab-x-link . [(20191113 848) ((emacs (24)) (cl-lib (0 5))) "Grab links from X11 apps and insert into Emacs" tar ((:url . "https://github.com/xuchunyang/grab-x-link") (:commit . "d898db46e4864118359fdedfe915e180de3fe290") (:revdesc . "d898db46e486") (:keywords "hyperlink") (:authors ("Xu Chunyang" . "mail@xuchunyang.me")) (:maintainers ("Xu Chunyang" . "mail@xuchunyang.me")) (:maintainer "Xu Chunyang" . "mail@xuchunyang.me"))]) @@ -2326,7 +2326,7 @@ (heaven-and-hell . [(20190713 1830) ((emacs (24 4))) "Easy toggle light/dark themes" tar ((:url . "https://github.com/valignatev/heaven-and-hell") (:commit . "e1febfd60d060c110a1e43c5f093cd8537251308") (:revdesc . "e1febfd60d06") (:keywords "faces") (:authors ("Valentin Ignatev" . "valentignatev@gmail.com")) (:maintainers ("Valentin Ignatev" . "valentignatev@gmail.com")) (:maintainer "Valentin Ignatev" . "valentignatev@gmail.com"))]) (heex-ts-mode . [(20240113 1104) ((emacs (29 1))) "Major mode for Heex with tree-sitter support" tar ((:url . "https://github.com/wkirschbaum/heex-ts-mode") (:commit . "90142df2929956536dc1eaae3bb5ca04dc4232ab") (:revdesc . "90142df29299") (:keywords "heex" "languages" "tree-sitter"))]) (helix-theme . [(20240814 1212) nil "Color theme inspired by Helix editor's default colors" tar ((:url . "https://github.com/ibakepunk/helix-theme") (:commit . "8c70b48fe5fbb392d237b6be2ae9da7b84236320") (:revdesc . "8c70b48fe5fb") (:keywords "faces"))]) - (helm . [(20241112 620) ((helm-core (4 0)) (wfnames (1 2))) "Helm is an Emacs incremental and narrowing framework" tar ((:url . "https://github.com/emacs-helm/helm") (:commit . "0e2aef09de299e72f7fd914191713989de760166") (:revdesc . "0e2aef09de29") (:keywords "helm" "convenience" "files" "buffers" "grep" "completion" "lisp" "matching" "tools" "help") (:authors ("Thierry Volpiatto" . "thievol@posteo.net")) (:maintainers ("Thierry Volpiatto" . "thievol@posteo.net")) (:maintainer "Thierry Volpiatto" . "thievol@posteo.net"))]) + (helm . [(20241124 730) ((helm-core (4 0)) (wfnames (1 2))) "Helm is an Emacs incremental and narrowing framework" tar ((:url . "https://github.com/emacs-helm/helm") (:commit . "41bd8802171abbac29d5e494ad15cbf08776f2d7") (:revdesc . "41bd8802171a") (:keywords "helm" "convenience" "files" "buffers" "grep" "completion" "lisp" "matching" "tools" "help") (:authors ("Thierry Volpiatto" . "thievol@posteo.net")) (:maintainers ("Thierry Volpiatto" . "thievol@posteo.net")) (:maintainer "Thierry Volpiatto" . "thievol@posteo.net"))]) (helm-R . [(20120820 14) ((helm (20120517)) (ess (20120509))) "Helm-sources and some utilities for GNU R" tar ((:url . "https://github.com/myuhe/helm-R.el") (:commit . "b0eb9d5f6a483a9dbe6eb6cf1f2024d4f5938bc2") (:revdesc . "b0eb9d5f6a48") (:keywords "convenience") (:authors ("myuhe" . "yuhei.maeda_at_gmail.com")))]) (helm-ack . [(20141030 1226) ((helm (1 0)) (cl-lib (0 5))) "Ack command with helm interface" tar ((:url . "https://github.com/emacsorphanage/helm-ack") (:commit . "5982f3cb6ec9f460ebbe06ec0ce7b3590bca3118") (:revdesc . "5982f3cb6ec9") (:authors ("Syohei YOSHIDA" . "syohex@gmail.com")) (:maintainers ("Syohei YOSHIDA" . "syohex@gmail.com")) (:maintainer "Syohei YOSHIDA" . "syohex@gmail.com"))]) (helm-ad . [(20151209 1015) ((dash (2 8 0)) (helm (1 6 2))) "Helm source for Active Directory" tar ((:url . "https://github.com/tnoda/helm-ad") (:commit . "8ac044705d8620ee354a9cfa8cc1b865e83c0d55") (:revdesc . "8ac044705d86") (:keywords "comm") (:authors ("Takahiro Noda" . "takahiro.noda+github@gmail.com")) (:maintainers ("Takahiro Noda" . "takahiro.noda+github@gmail.com")) (:maintainer "Takahiro Noda" . "takahiro.noda+github@gmail.com"))]) @@ -2360,7 +2360,7 @@ (helm-comint . [(20231102 2029) ((emacs (25 1)) (helm (3 9 4))) "Comint prompt navigation for helm" tar ((:url . "https://github.com/emacs-helm/helm-comint") (:commit . "9215b2aa8f42f62cbda66a1503832abb7f491549") (:revdesc . "9215b2aa8f42") (:keywords "processes" "matching") (:authors ("Pierre Neidhardt" . "mail@ambrevar.xyz")) (:maintainers ("Benedict Wang" . "foss@bhw.name")) (:maintainer "Benedict Wang" . "foss@bhw.name"))]) (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" tar ((:url . "https://github.com/xuchunyang/helm-commandlinefu") (:commit . "9ee7e018c5db23ae9c8d1c8fa969876f15b7280d") (:revdesc . "9ee7e018c5db") (:keywords "commandlinefu.com") (:authors ("Chunyang Xu" . "xuchunyang56@gmail.com")) (:maintainers ("Chunyang Xu" . "xuchunyang56@gmail.com")) (:maintainer "Chunyang Xu" . "xuchunyang56@gmail.com"))]) (helm-company . [(20231113 701) ((helm (1 5 9)) (company (0 10 0))) "Helm interface for company-mode" tar ((:url . "https://github.com/Sodel-the-Vociferous/helm-company") (:commit . "4622b82353220ee6cc33468f710fa5b6b253b7f1") (:revdesc . "4622b8235322") (:authors ("Yasuyuki Oka" . "yasuyk@gmail.com")) (:maintainers ("Daniel Ralston" . "Sodel-the-Vociferous@users.noreply.github.com")) (:maintainer "Daniel Ralston" . "Sodel-the-Vociferous@users.noreply.github.com"))]) - (helm-core . [(20241109 438) ((emacs (25 1)) (async (1 9 8))) "Development files for Helm" tar ((:url . "https://github.com/emacs-helm/helm") (:commit . "dd059c1f7022391466ac339c2c64bad5a30c498c") (:revdesc . "dd059c1f7022") (:authors ("Thierry Volpiatto" . "thievol@posteo.net")) (:maintainers ("Thierry Volpiatto" . "thievol@posteo.net")) (:maintainer "Thierry Volpiatto" . "thievol@posteo.net"))]) + (helm-core . [(20241124 745) ((emacs (25 1)) (async (1 9 8))) "Development files for Helm" tar ((:url . "https://github.com/emacs-helm/helm") (:commit . "4999541feab3e859a14ed36f1fd13a1104483e7b") (:revdesc . "4999541feab3") (:authors ("Thierry Volpiatto" . "thievol@posteo.net")) (:maintainers ("Thierry Volpiatto" . "thievol@posteo.net")) (:maintainer "Thierry Volpiatto" . "thievol@posteo.net"))]) (helm-cscope . [(20190615 41) ((xcscope (1 0)) (helm (1 6 7)) (cl-lib (0 5)) (emacs (24 1))) "Helm interface for xcscope.el" tar ((:url . "https://github.com/alpha22jp/helm-cscope.el") (:commit . "af1d9e7f4460a88d7400b5a74d5da68084089ac1") (:revdesc . "af1d9e7f4460") (:keywords "cscope" "helm") (:authors ("alpha22jp" . "alpha22jp@gmail.com")) (:maintainers ("alpha22jp" . "alpha22jp@gmail.com")) (:maintainer "alpha22jp" . "alpha22jp@gmail.com"))]) (helm-css-scss . [(20230522 1113) ((emacs (24 3)) (helm (1 0))) "CSS/SCSS/LESS Selectors with helm interface" tar ((:url . "https://github.com/emacsorphanage/helm-css-scss") (:commit . "2169d83d8fdc661241df208cb3235112735d936e") (:revdesc . "2169d83d8fdc") (:keywords "convenience" "scss" "css" "less" "selector" "helm"))]) (helm-ctest . [(20220721 400) ((s (1 9 0)) (dash (2 11 0)) (helm-core (3 6 0))) "Run ctest from within emacs" tar ((:url . "https://github.com/danlamanna/helm-ctest") (:commit . "48edc9fa862219da34feb423c06c33d8f6d43722") (:revdesc . "48edc9fa8622") (:keywords "helm" "ctest") (:authors ("Dan LaManna" . "me@danlamanna.com")) (:maintainers ("Dan LaManna" . "me@danlamanna.com")) (:maintainer "Dan LaManna" . "me@danlamanna.com"))]) @@ -2610,7 +2610,7 @@ (hydandata-light-theme . [(20190809 1925) nil "A light color theme that is easy on your eyes" tar ((:url . "https://github.com/chkhd/hydandata-light-theme") (:commit . "812ffa4bee3163098ef66ee4506feed45018be4e") (:revdesc . "812ffa4bee31") (:keywords "color-theme" "theme") (:authors ("David Chkhikvadze" . "david@chkhd.net")) (:maintainers ("David Chkhikvadze" . "david@chkhd.net")) (:maintainer "David Chkhikvadze" . "david@chkhd.net"))]) (hyde . [(20160508 308) nil "Major mode to help create and manage Jekyll blogs" tar ((:url . "https://github.com/nibrahim/Hyde") (:commit . "a8cd6ed00ecd8d7de0ded2f4867015b412b15b76") (:revdesc . "a8cd6ed00ecd"))]) (hydra . [(20220910 1206) ((cl-lib (0 5)) (lv (0))) "Make bindings that stick around" tar ((:url . "https://github.com/abo-abo/hydra") (:commit . "317e1de33086637579a7aeb60f77ed0405bf359b") (:revdesc . "317e1de33086") (:keywords "bindings") (:authors ("Oleh Krehel" . "ohwoeowho@gmail.com")) (:maintainers ("Oleh Krehel" . "ohwoeowho@gmail.com")) (:maintainer "Oleh Krehel" . "ohwoeowho@gmail.com"))]) - (hyperbole . [(20241119 534) ((emacs (27 2))) "GNU Hyperbole: The Everyday Hypertextual Information Manager" tar ((:url . "https://git.savannah.gnu.org/git/hyperbole.git") (:commit . "f2b98683ef86cc6464fbff59f9ae07e69999a943") (:revdesc . "f2b98683ef86") (:keywords "comm" "convenience" "files" "frames" "hypermedia" "languages" "mail" "matching" "mouse" "multimedia" "outlines" "tools" "wp") (:authors ("Robert Weiner" . "rsw@gnu.org")) (:maintainers ("Robert Weiner" . "rsw@gnu.org")) (:maintainer "Robert Weiner" . "rsw@gnu.org"))]) + (hyperbole . [(20241124 812) ((emacs (27 2))) "GNU Hyperbole: The Everyday Hypertextual Information Manager" tar ((:url . "https://git.savannah.gnu.org/git/hyperbole.git") (:commit . "32539095993667792ab59ec5084611f5cc10f420") (:revdesc . "325390959936") (:keywords "comm" "convenience" "files" "frames" "hypermedia" "languages" "mail" "matching" "mouse" "multimedia" "outlines" "tools" "wp") (:authors ("Robert Weiner" . "rsw@gnu.org")) (:maintainers ("Robert Weiner" . "rsw@gnu.org")) (:maintainer "Robert Weiner" . "rsw@gnu.org"))]) (hyperdrive . [(20241101 2353) ((emacs (28 1)) (map (3 0)) (compat (30 0 0 0)) (org (9 7 6)) (plz (0 9 1)) (persist (0 6 1)) (taxy-magit-section (0 14)) (transient (0 7 7))) "P2P filesystem" tar ((:url . "https://git.sr.ht/~ushin/hyperdrive.el") (:commit . "581752cad8bcd701c863b08a779e4ca982325cae") (:revdesc . "581752cad8bc") (:authors ("Joseph Turner" . "joseph@ushin.org")) (:maintainers ("Joseph Turner" . "~ushin/ushin@lists.sr.ht")) (:maintainer "Joseph Turner" . "~ushin/ushin@lists.sr.ht"))]) (hyperdrive-org-transclusion . [(20241028 427) ((emacs (28 1)) (hyperdrive (0 4 2)) (org-transclusion (1 4 0))) "Tranclude hyperdrive content" tar ((:url . "https://git.sr.ht/~ushin/hyperdrive-org-transclusion") (:commit . "252e2df3fe7a07a122a365a637c47a43b26e179c") (:revdesc . "252e2df3fe7a") (:authors ("Joseph Turner" . "joseph@ushin.org")) (:maintainers ("Joseph Turner" . "~ushin/ushin@lists.sr.ht")) (:maintainer "Joseph Turner" . "~ushin/ushin@lists.sr.ht"))]) (hyperkitty . [(20220226 1951) ((request (0 3 2)) (emacs (25 1))) "Emacs interface for Hyperkitty archives" tar ((:url . "https://github.com/maxking/hyperkitty.el") (:commit . "2c1d22ff017d096c359aa151e6a29f7214a58118") (:revdesc . "2c1d22ff017d") (:keywords "mail" "hyperkitty" "mailman") (:authors ("Abhilash Raj" . "maxking@asynchronous.in")) (:maintainers ("Abhilash Raj" . "maxking@asynchronous.in")) (:maintainer "Abhilash Raj" . "maxking@asynchronous.in"))]) @@ -2900,7 +2900,7 @@ (jtsx . [(20240715 2002) ((emacs (29 1))) "Extends JSX/TSX built-in support" tar ((:url . "https://github.com/llemaitre19/jtsx") (:commit . "e81259a7584619ce3266a2d532f674ef45ee4274") (:revdesc . "e81259a75846") (:keywords "languages") (:authors ("Loïc Lemaître" . "loic.lemaitre@gmail.com")) (:maintainers ("Loïc Lemaître" . "loic.lemaitre@gmail.com")) (:maintainer "Loïc Lemaître" . "loic.lemaitre@gmail.com"))]) (julia-formatter . [(20231130 1512) ((emacs (27 1)) (session-async (0 0 5))) "Use JuliaFormatter.jl for julia code" tar ((:url . "https://codeberg.org/FelipeLema/julia-formatter.el") (:commit . "4b40481cc9c0dcb3c9704436e00d613067d44bf5") (:revdesc . "4b40481cc9c0") (:keywords "convenience" "tools") (:authors ("Felipe Lema" . "felipe.lema@mortemale.org")) (:maintainers ("Felipe Lema" . "felipe.lema@mortemale.org")) (:maintainer "Felipe Lema" . "felipe.lema@mortemale.org"))]) (julia-mode . [(20241120 857) ((emacs (26 1))) "Major mode for editing Julia source code" tar ((:url . "https://github.com/JuliaEditorSupport/julia-emacs") (:commit . "709c43410fb5da068d7d582cf3f545f7a7a68133") (:revdesc . "709c43410fb5") (:keywords "languages"))]) - (julia-repl . [(20241113 1152) ((emacs (25 1)) (s (1 12))) "A minor mode for a Julia REPL" tar ((:url . "https://github.com/tpapp/julia-repl") (:commit . "bb90cc1fceccc8dfd0e4b60d624271e4aca6b9b8") (:revdesc . "bb90cc1fcecc") (:keywords "languages") (:authors ("Tamas Papp" . "tkpapp@gmail.com")) (:maintainers ("Tamas Papp" . "tkpapp@gmail.com")) (:maintainer "Tamas Papp" . "tkpapp@gmail.com"))]) + (julia-repl . [(20241120 1523) ((emacs (25 1)) (s (1 12))) "A minor mode for a Julia REPL" tar ((:url . "https://github.com/tpapp/julia-repl") (:commit . "1f4f6b4e01ff1529b0d7917fbd9ce29451a66510") (:revdesc . "1f4f6b4e01ff") (:keywords "languages") (:authors ("Tamas Papp" . "tkpapp@gmail.com")) (:maintainers ("Tamas Papp" . "tkpapp@gmail.com")) (:maintainer "Tamas Papp" . "tkpapp@gmail.com"))]) (julia-shell . [(20161125 1910) ((julia-mode (0 3))) "Major mode for an inferior Julia shell" tar ((:url . "https://github.com/dennisog/julia-shell-mode") (:commit . "583a0b2ca20461ab4356929fd0f2212c22341b69") (:revdesc . "583a0b2ca204") (:authors ("Dennis Ogbe" . "dogbe@purdue.edu")) (:maintainers ("Dennis Ogbe" . "dogbe@purdue.edu")) (:maintainer "Dennis Ogbe" . "dogbe@purdue.edu"))]) (julia-snail . [(20240812 840) ((emacs (26 2)) (dash (2 16 0)) (julia-mode (0 3)) (s (1 12 0)) (spinner (1 7 3)) (popup (0 5 9))) "Julia Snail" tar ((:url . "https://github.com/gcv/julia-snail") (:commit . "dff92c4250e40a6cc106f0ea993f9631ad55eb7c") (:revdesc . "dff92c4250e4"))]) (julia-ts-mode . [(20230921 1433) ((emacs (29 1)) (julia-mode (0 4))) "Major mode for Julia source code using tree-sitter" tar ((:url . "https://github.com/JuliaEditorSupport/julia-ts-mode") (:commit . "44260b265359c7ed4052398e099ad019ce899109") (:revdesc . "44260b265359") (:keywords "julia" "languages" "tree-sitter"))]) @@ -2914,7 +2914,7 @@ (jupyter . [(20241120 230) ((emacs (27)) (cl-lib (0 5)) (org (9 1 6)) (zmq (0 10 10)) (simple-httpd (1 5 0)) (websocket (1 9))) "Jupyter" tar ((:url . "https://github.com/emacs-jupyter/jupyter") (:commit . "577371744b36aa0afa117b7ded21d08f60331ff6") (:revdesc . "577371744b36") (:authors ("Nathaniel Nicandro" . "nathanielnicandro@gmail.com")) (:maintainers ("Nathaniel Nicandro" . "nathanielnicandro@gmail.com")) (:maintainer "Nathaniel Nicandro" . "nathanielnicandro@gmail.com"))]) (just-mode . [(20240424 1809) ((emacs (26 1))) "Justfile editing mode" tar ((:url . "https://github.com/leon-barrett/just-mode.el") (:commit . "4c0df4cc4b8798f1a7e99fb78b79c4bf7eec12c1") (:revdesc . "4c0df4cc4b87") (:keywords "files" "languages" "tools") (:authors ("Leon Barrett" . "(leon@barrettnexus.com)")) (:maintainers ("Leon Barrett" . "(leon@barrettnexus.com)")) (:maintainer "Leon Barrett" . "(leon@barrettnexus.com)"))]) (just-ts-mode . [(20241014 2252) ((emacs (29 1))) "Justfile editing mode" tar ((:url . "https://github.com/leon-barrett/just-ts-mode.el") (:commit . "acb598f1edabae9f679a507c8e22c21b3f2da132") (:revdesc . "acb598f1edab") (:keywords "files" "languages" "tools" "treesitter") (:authors ("Leon Barrett" . "(leon@barrettnexus.com)")) (:maintainers ("Leon Barrett" . "(leon@barrettnexus.com)")) (:maintainer "Leon Barrett" . "(leon@barrettnexus.com)"))]) - (justl . [(20241116 530) ((transient (0 1 0)) (emacs (27 1)) (s (1 2 0)) (f (0 20 0)) (inheritenv (0 2))) "Major mode for driving just files" tar ((:url . "https://github.com/psibi/justl.el") (:commit . "82925541b4a36e0e9f95eee0f4a0ea348c750990") (:revdesc . "82925541b4a3") (:keywords "just" "justfile" "tools" "processes"))]) + (justl . [(20241123 1442) ((transient (0 1 0)) (emacs (27 1)) (s (1 2 0)) (f (0 20 0)) (inheritenv (0 2))) "Major mode for driving just files" tar ((:url . "https://github.com/psibi/justl.el") (:commit . "16b6ed54ceae839da032e5850075cab43c46be08") (:revdesc . "16b6ed54ceae") (:keywords "just" "justfile" "tools" "processes"))]) (jvm-mode . [(20150422 708) ((dash (2 6 0)) (emacs (24))) "Monitor and manage your JVMs" tar ((:url . "https://github.com/martintrojer/jvm-mode.el") (:commit . "3355dbaf5b0185aadfbad24160399abb32c5bea0") (:revdesc . "3355dbaf5b01") (:keywords "convenience") (:authors ("Martin Trojer" . "martin.trojer@gmail.com")) (:maintainers ("Martin Trojer" . "martin.trojer@gmail.com")) (:maintainer "Martin Trojer" . "martin.trojer@gmail.com"))]) (jwt . [(20241031 2258) ((emacs (29 1))) "Interact with JSON Web Tokens" tar ((:url . "https://github.com/joshbax189/jwt-el") (:commit . "d7deb62f8c2df58d5cfebf087a147c75207964e8") (:revdesc . "d7deb62f8c2d") (:keywords "tools" "convenience"))]) (k8s-mode . [(20230305 1039) ((emacs (24 3)) (yaml-mode (0 0 10))) "Major mode for Kubernetes configuration file" tar ((:url . "https://github.com/TxGVNN/emacs-k8s-mode") (:commit . "83266cecd6a39cdf57d124270646047860bfb7ab") (:revdesc . "83266cecd6a3") (:authors ("Giap Tran" . "txgvnn@gmail.com")) (:maintainers ("Giap Tran" . "txgvnn@gmail.com")) (:maintainer "Giap Tran" . "txgvnn@gmail.com"))]) @@ -2930,7 +2930,7 @@ (kana . [(20210531 1427) ((emacs (24 4)) (dash (2 17 0))) "Learn Japanese hiragana and katakana" tar ((:url . "https://github.com/chenyanming/kana") (:commit . "d3d550aad67ef8625b3860598bf3622f5b2a7d32") (:revdesc . "d3d550aad67e") (:keywords "tools") (:authors ("Damon Chan" . "elecming@gmail.com")) (:maintainers ("Damon Chan" . "elecming@gmail.com")) (:maintainer "Damon Chan" . "elecming@gmail.com"))]) (kanagawa-themes . [(20241028 1204) ((emacs (24 3))) "Elegant theme inspired by The Great Wave off Kanagawa" tar ((:url . "https://github.com/Fabiokleis/kanagawa-emacs") (:commit . "6fe28070d7b3581415faa3e61af786b596ef3bb0") (:revdesc . "6fe28070d7b3") (:keywords "themes" "faces") (:authors ("Sion Eltnam Sokaris" . "meritamen@sdf.org")) (:maintainers ("Fabio Kleis" . "fabiohkrc@gmail.com") ("Sion Eltnam Sokaris" . "meritamen@sdf.org")) (:maintainer "Fabio Kleis" . "fabiohkrc@gmail.com"))]) (kanban . [(20230210 1505) nil "Parse org-todo headlines to use org-tables as Kanban tables" tar ((:url . "https://hg.sr.ht/~arnebab/kanban.el") (:commit . "d70fa7acab2bfcbb7d3da43c1343073f7eff4998") (:revdesc . "d70fa7acab2bfcbb7d3da43c1343073f7eff4998") (:keywords "outlines" "convenience") (:authors ("Arne Babenhauserheide" . "arne_bab@web.de")) (:maintainers ("Arne Babenhauserheide" . "arne_bab@web.de")) (:maintainer "Arne Babenhauserheide" . "arne_bab@web.de"))]) - (kanji-mode . [(20230928 1113) nil "View stroke order for kanji characters at cursor" tar ((:url . "https://github.com/wsgac/kanji-mode") (:commit . "731b3a5447bcb899ba1d86b645a344e0915d04f3") (:revdesc . "731b3a5447bc") (:authors ("Wojciech Gac" . "wojciech.s.gac@gmail.com")) (:maintainers ("Wojciech Gac" . "wojciech.s.gac@gmail.com")) (:maintainer "Wojciech Gac" . "wojciech.s.gac@gmail.com"))]) + (kanji-mode . [(20241120 1923) nil "View stroke order for kanji characters at cursor" tar ((:url . "https://github.com/wsgac/kanji-mode") (:commit . "09719b00d60e22bd31c93b21c0c817eced9d0406") (:revdesc . "09719b00d60e") (:authors ("Wojciech Gac" . "wojciech.s.gac@gmail.com")) (:maintainers ("Wojciech Gac" . "wojciech.s.gac@gmail.com")) (:maintainer "Wojciech Gac" . "wojciech.s.gac@gmail.com"))]) (kaocha-runner . [(20240625 1010) ((emacs (26)) (s (1 4 0)) (cider (0 21 0)) (parseedn (0 1 0))) "A package for running Kaocha tests via CIDER" tar ((:url . "https://github.com/magnars/kaocha-runner.el") (:commit . "98f45ee396802c2225595c9151d4a941f9dcaa9d") (:revdesc . "98f45ee39680") (:authors ("Magnar Sveen" . "magnars@gmail.com")) (:maintainers ("Magnar Sveen" . "magnars@gmail.com")) (:maintainer "Magnar Sveen" . "magnars@gmail.com"))]) (kaolin-themes . [(20241104 1) ((emacs (25 1)) (autothemer (0 2 2)) (cl-lib (0 6))) "A set of eye pleasing themes" tar ((:url . "https://github.com/ogdenwebb/emacs-kaolin-themes") (:commit . "343ad8cd73c7509af2ea7af5eb856ece97dee7a3") (:revdesc . "343ad8cd73c7") (:keywords "dark" "light" "teal" "blue" "violet" "purple" "brown" "theme" "faces") (:authors ("Ogden Webb" . "ogdenwebb@gmail.com")) (:maintainers ("Ogden Webb" . "ogdenwebb@gmail.com")) (:maintainer "Ogden Webb" . "ogdenwebb@gmail.com"))]) (kaomoji . [(20220721 441) ((emacs (24 3)) (helm-core (3 6 0))) "Input kaomoji superb easily" tar ((:url . "https://github.com/kuanyui/kaomoji.el") (:commit . "fba0018a13eba70c2bffc6153dcfee99937fa3d6") (:revdesc . "fba0018a13eb") (:keywords "tools" "fun") (:authors ("Ono Hiroko" . "azazabc123@gmail.com")) (:maintainers ("Ono Hiroko" . "azazabc123@gmail.com")) (:maintainer "Ono Hiroko" . "azazabc123@gmail.com"))]) @@ -2966,7 +2966,7 @@ (kfg . [(20140909 538) ((f (0 17 1))) "An emacs configuration system" tar ((:url . "https://github.com/czipperz/kfg") (:commit . "ffc35b77f227d4c64a1271ec30d31333ffeb0013") (:revdesc . "ffc35b77f227") (:authors ("Austin Bingham" . "austin.bingham@gmail.com")) (:maintainers ("Austin Bingham" . "austin.bingham@gmail.com")) (:maintainer "Austin Bingham" . "austin.bingham@gmail.com"))]) (khalel . [(20240527 527) ((emacs (27 1))) "Import, edit and create calendar events through khal" tar ((:url . "https://gitlab.com/hperrey/khalel") (:commit . "14ef50352394cd1d62b80bc17ab14f4f801f47cd") (:revdesc . "14ef50352394") (:keywords "event" "calendar" "ics" "khal") (:authors ("Hanno Perrey" . "http://gitlab.com/hperrey")) (:maintainers ("Hanno Perrey" . "hanno@hoowl.se")) (:maintainer "Hanno Perrey" . "hanno@hoowl.se"))]) (khardel . [(20231126 1502) ((emacs (27 1)) (yaml-mode (0 0 13))) "Integrate with khard" tar ((:url . "https://github.com/DamienCassou/khardel") (:commit . "205e374b36252183a146a7a8f857bcf95a77edc3") (:revdesc . "205e374b3625") (:authors ("Damien Cassou" . "damien@cassou.me")) (:maintainers ("Damien Cassou" . "damien@cassou.me")) (:maintainer "Damien Cassou" . "damien@cassou.me"))]) - (khoj . [(20241119 130) ((emacs (27 1)) (transient (0 3 0)) (dash (2 19 1))) "Your Second Brain" tar ((:url . "https://github.com/khoj-ai/khoj") (:commit . "5134d49d7133e34962c396dc7be75bb6c3a46a29") (:revdesc . "5134d49d7133") (:keywords "search" "chat" "ai" "org-mode" "outlines" "markdown" "pdf" "image") (:authors ("Debanjum Singh Solanky" . "debanjum@khoj.dev") ("Saba Imran" . "saba@khoj.dev")) (:maintainers ("Debanjum Singh Solanky" . "debanjum@khoj.dev") ("Saba Imran" . "saba@khoj.dev")) (:maintainer "Debanjum Singh Solanky" . "debanjum@khoj.dev"))]) + (khoj . [(20241124 651) ((emacs (27 1)) (transient (0 3 0)) (dash (2 19 1))) "Your Second Brain" tar ((:url . "https://github.com/khoj-ai/khoj") (:commit . "2d683898c272fd25b3b33b7368a3bcf904b65ee0") (:revdesc . "2d683898c272") (:keywords "search" "chat" "ai" "org-mode" "outlines" "markdown" "pdf" "image") (:authors ("Debanjum Singh Solanky" . "debanjum@khoj.dev") ("Saba Imran" . "saba@khoj.dev")) (:maintainers ("Debanjum Singh Solanky" . "debanjum@khoj.dev") ("Saba Imran" . "saba@khoj.dev")) (:maintainer "Debanjum Singh Solanky" . "debanjum@khoj.dev"))]) (kibit-helper . [(20150508 1533) ((s (0 8)) (emacs (24))) "Conveniently use the Kibit Leiningen plugin from Emacs" tar ((:url . "https://github.com/brunchboy/kibit-helper") (:commit . "ec5f154db3bb0c838e86f527353f08644cede926") (:revdesc . "ec5f154db3bb") (:keywords "languages" "clojure" "kibit") (:authors ("James Elliott" . "james@brunchboy.com")) (:maintainers ("James Elliott" . "james@brunchboy.com")) (:maintainer "James Elliott" . "james@brunchboy.com"))]) (kill-file-path . [(20230306 1041) ((emacs (26))) "Copy file name into kill ring" tar ((:url . "https://github.com/chyla/kill-file-path") (:commit . "5dcbce69cbae17665216a32dd20f27de54c62972") (:revdesc . "5dcbce69cbae") (:keywords "files") (:authors ("Adam Chyła" . "adam@chyla.org")) (:maintainers ("Adam Chyła" . "adam@chyla.org")) (:maintainer "Adam Chyła" . "adam@chyla.org"))]) (kill-or-bury-alive . [(20230606 1503) ((emacs (24 4))) "Precise control over buffer killing" tar ((:url . "https://github.com/mrkkrp/kill-or-bury-alive") (:commit . "16c393db6ad0c7e184af0a24d26b637e23543b1f") (:revdesc . "16c393db6ad0") (:keywords "convenience") (:authors ("Mark Karpov" . "markkarpov92@gmail.com")) (:maintainers ("Mark Karpov" . "markkarpov92@gmail.com")) (:maintainer "Mark Karpov" . "markkarpov92@gmail.com"))]) @@ -3088,7 +3088,7 @@ (ligature-pragmatapro . [(20221127 2252) ((emacs (28)) (ligature (1 0))) "PragmataPro support for ligature.el" tar ((:url . "https://gitlab.com/wavexx/ligature-pragmatapro.el") (:commit . "85f7b15a5cf5f2ee843bc0469e03602a0251c275") (:revdesc . "85f7b15a5cf5") (:keywords "faces" "fonts" "ligatures" "programming-ligatures") (:authors ("Yuri D'Elia" . "wavexx@thregr.org")) (:maintainers ("Yuri D'Elia" . "wavexx@thregr.org")) (:maintainer "Yuri D'Elia" . "wavexx@thregr.org"))]) (light-soap-theme . [(20150607 1445) ((emacs (24))) "Emacs 24 theme with a light background" tar ((:url . "https://github.com/mswift42/light-soap-theme") (:commit . "76a787bd40c6b567ae68ced7f5d9f9f10725e00d") (:revdesc . "76a787bd40c6"))]) (line-reminder . [(20240715 2304) ((emacs (25 1)) (fringe-helper (1 0 1)) (ov (1 0 6)) (ht (2 0))) "Line annotation for changed and saved lines" tar ((:url . "https://github.com/emacs-vs/line-reminder") (:commit . "76677e48451b77508673a52dcc0845b87e5f81fe") (:revdesc . "76677e48451b") (:keywords "convenience" "annotation") (:authors ("Jen-Chieh" . "jcs090218@gmail.com")) (:maintainers ("Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Jen-Chieh" . "jcs090218@gmail.com"))]) - (line-up-words . [(20180219 1024) nil "Align words in an intelligent way" tar ((:url . "https://github.com/janestreet/line-up-words") (:commit . "2c236f5772e18d0e50d7ca2eee7eebbe356d9b60") (:revdesc . "2c236f5772e1"))]) + (line-up-words . [(20241121 2033) nil "Align words in an intelligent way" tar ((:url . "https://github.com/janestreet/line-up-words") (:commit . "3c1339a3fb3840dfaea50d8cb966c90b19d14925") (:revdesc . "3c1339a3fb38"))]) (lines-at-once . [(20180422 247) ((emacs (25))) "Insert and edit multiple lines at once" tar ((:url . "https://github.com/jiahaoli95/lines-at-once.el") (:commit . "a018ba90549384d52ec58c2685fd14a0f65252be") (:revdesc . "a018ba905493") (:keywords "abbrev" "tools") (:authors ("Jiahao Li" . "jiahaowork@gmail.com")) (:maintainers ("Jiahao Li" . "jiahaowork@gmail.com")) (:maintainer "Jiahao Li" . "jiahaowork@gmail.com"))]) (lingr . [(20100807 1731) nil "Lingr Client for GNU Emacs" tar ((:url . "https://github.com/lugecy/lingr-el") (:commit . "4215a8704492d3c860097cbe2649936c22c196df") (:revdesc . "4215a8704492") (:keywords "chat" "client" "internet") (:authors ("lugecy" . "lugecy@gmail.com")) (:maintainers ("lugecy" . "lugecy@gmail.com")) (:maintainer "lugecy" . "lugecy@gmail.com"))]) (linguistic . [(20181129 2116) nil "A package for basic linguistic analysis" tar ((:url . "https://github.com/andcarnivorous/linguistic") (:commit . "23e47e98cdb09ee61883669b6d8a11bf6449862c") (:revdesc . "23e47e98cdb0") (:keywords "linguistics" "text analysis" "matching") (:authors ("Andrew Favia" . "drewlinguistics01atgmaildotcom")) (:maintainers ("Andrew Favia" . "drewlinguistics01atgmaildotcom")) (:maintainer "Andrew Favia" . "drewlinguistics01atgmaildotcom"))]) @@ -3181,7 +3181,7 @@ (lsp-latex . [(20241006 800) ((emacs (27 1)) (lsp-mode (6 0)) (consult (0 35))) "LSP-mode client for LaTeX, on texlab" tar ((:url . "https://github.com/ROCKTAKEY/lsp-latex") (:commit . "36a37a8e0a6b0edbea8e67dab89d12980d2a368f") (:revdesc . "36a37a8e0a6b") (:keywords "languages" "tex") (:authors ("ROCKTAKEY" . "rocktakey@gmail.com")) (:maintainers ("ROCKTAKEY" . "rocktakey@gmail.com")) (:maintainer "ROCKTAKEY" . "rocktakey@gmail.com"))]) (lsp-ltex . [(20240425 2049) ((emacs (27 1)) (lsp-mode (6 1))) "LSP Clients for LTEX" tar ((:url . "https://github.com/emacs-languagetool/lsp-ltex") (:commit . "c473ed37aa0f2769bb0b4c344cc28f95975dbc17") (:revdesc . "c473ed37aa0f") (:keywords "convenience" "lsp" "languagetool" "checker") (:authors ("Jen-Chieh" . "jcs090218@gmail.com")) (:maintainers ("Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Jen-Chieh" . "jcs090218@gmail.com"))]) (lsp-metals . [(20241112 1142) ((emacs (27 1)) (scala-mode (0 23)) (lsp-mode (7 0)) (lsp-treemacs (0 2)) (dap-mode (0 3)) (dash (2 18 0)) (f (0 20 0)) (ht (2 0)) (treemacs (3 1))) "Scala Client settings" tar ((:url . "https://github.com/emacs-lsp/lsp-metals") (:commit . "b5139c959336758a93d0e55458e6ca938d9fd16a") (:revdesc . "b5139c959336") (:keywords "languages" "extensions") (:authors ("Ross A. Baker" . "ross@rossabaker.com") ("Evgeny Kurnevsky" . "kurnevsky@gmail.com")) (:maintainers ("Ross A. Baker" . "ross@rossabaker.com") ("Evgeny Kurnevsky" . "kurnevsky@gmail.com")) (:maintainer "Ross A. Baker" . "ross@rossabaker.com"))]) - (lsp-mode . [(20241119 828) ((emacs (27 1)) (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 ((:url . "https://github.com/emacs-lsp/lsp-mode") (:commit . "620bbd7163fa9d9281cd315ffa3ee29d83be8686") (:revdesc . "620bbd7163fa") (:keywords "languages"))]) + (lsp-mode . [(20241123 739) ((emacs (27 1)) (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 ((:url . "https://github.com/emacs-lsp/lsp-mode") (:commit . "ae4907082b429c35bdc675cb5614e1d9aa520171") (:revdesc . "ae4907082b42") (:keywords "languages"))]) (lsp-mssql . [(20230510 1124) ((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 ((:url . "https://github.com/emacs-lsp/lsp-mssql") (:commit . "a0dba8f86a2ace7e800a9dc8f814767625a509af") (:revdesc . "a0dba8f86a2a") (:keywords "data" "languages") (:authors ("Ivan Yonchovski" . "yyoncho@gmail.com")) (:maintainers ("Ivan Yonchovski" . "yyoncho@gmail.com")) (:maintainer "Ivan Yonchovski" . "yyoncho@gmail.com"))]) (lsp-origami . [(20230815 704) ((emacs (27 1)) (origami (1 0)) (lsp-mode (6 1))) "Origami.el support for lsp-mode" tar ((:url . "https://github.com/emacs-lsp/lsp-origami") (:commit . "86aa06517910141c3d5054eea5f7723461fce6a6") (:revdesc . "86aa06517910") (:keywords "languages" "lsp-mode"))]) (lsp-p4 . [(20190127 1049) ((lsp-mode (3 0))) "P4 support for lsp-mode" tar ((:url . "https://github.com/dmakarov/p4ls") (:commit . "084e33a5782f9153502d9b03e63d9cbbe81cdaeb") (:revdesc . "084e33a5782f") (:keywords "lsp" "p4"))]) @@ -3221,7 +3221,7 @@ (magic-filetype . [(20240130 1805) ((emacs (24 3)) (s (1 9 0))) "Enhance filetype major mode" tar ((:url . "https://github.com/emacs-php/magic-filetype.el") (:commit . "3979ddbd8066d7390e31bde2b35f997c5f5f4516") (:revdesc . "3979ddbd8066") (:keywords "emulations" "vim" "ft" "file" "magic-mode") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainers ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me"))]) (magic-latex-buffer . [(20210306 422) ((cl-lib (0 5)) (emacs (25 1))) "Magically enhance LaTeX-mode font-locking for semi-WYSIWYG editing" tar ((:url . "https://github.com/zk-phi/magic-latex-buffer") (:commit . "903ec91872760e47c0e5715795f8465173615098") (:revdesc . "903ec9187276"))]) (magik-mode . [(20241111 1446) ((emacs (24 4)) (compat (28 1))) "Emacs major mode for Smallworld Magik files" tar ((:url . "https://github.com/roadrunner1776/magik") (:commit . "441389f75bdf6990556b96597979bf4a0b9cbdec") (:revdesc . "441389f75bdf") (:keywords "languages"))]) - (magit . [(20241116 1557) ((emacs (26 1)) (compat (30 0 0 0)) (dash (2 19 1)) (magit-section (4 1 2)) (seq (2 24)) (transient (0 7 8)) (with-editor (3 4 2))) "A Git porcelain inside Emacs" tar ((:url . "https://github.com/magit/magit") (:commit . "8cee789f7a61a491d23a78360cbd2d626eda0f06") (:revdesc . "8cee789f7a61") (:keywords "git" "tools" "vc") (:authors ("Marius Vollmer" . "marius.vollmer@gmail.com") ("Jonas Bernoulli" . "emacs.magit@jonas.bernoulli.dev")) (:maintainers ("Jonas Bernoulli" . "emacs.magit@jonas.bernoulli.dev") ("Kyle Meyer" . "kyle@kyleam.com")) (:maintainer "Jonas Bernoulli" . "emacs.magit@jonas.bernoulli.dev"))]) + (magit . [(20241124 1509) ((emacs (26 1)) (compat (30 0 0 0)) (dash (2 19 1)) (magit-section (4 1 2)) (seq (2 24)) (transient (0 7 8)) (with-editor (3 4 2))) "A Git porcelain inside Emacs" tar ((:url . "https://github.com/magit/magit") (:commit . "1e17181a21ffaec20c9540f413bea04ca20d65f1") (:revdesc . "1e17181a21ff") (:keywords "git" "tools" "vc") (:authors ("Marius Vollmer" . "marius.vollmer@gmail.com") ("Jonas Bernoulli" . "emacs.magit@jonas.bernoulli.dev")) (:maintainers ("Jonas Bernoulli" . "emacs.magit@jonas.bernoulli.dev") ("Kyle Meyer" . "kyle@kyleam.com")) (:maintainer "Jonas Bernoulli" . "emacs.magit@jonas.bernoulli.dev"))]) (magit-annex . [(20240811 1850) ((emacs (26 1)) (magit (4 0 0))) "Control git-annex from Magit" tar ((:url . "https://github.com/magit/magit-annex") (:commit . "9db0bc61461f222106c7ae3d8cd6d3de1f1b143f") (:revdesc . "9db0bc61461f") (:keywords "vc" "tools") (:authors ("Kyle Meyer" . "kyle@kyleam.com") ("Rémi Vanicat" . "vanicat@debian.org")) (:maintainers ("Kyle Meyer" . "kyle@kyleam.com") ("Rémi Vanicat" . "vanicat@debian.org")) (:maintainer "Kyle Meyer" . "kyle@kyleam.com"))]) (magit-commit-mark . [(20241110 245) ((emacs (29 1)) (magit (3 3 0))) "Support marking commits as read" tar ((:url . "https://codeberg.org/ideasman42/emacs-magit-commit-mark") (:commit . "e468518c7b8f90deda03cc4f0e2616b367cfdee8") (:revdesc . "e468518c7b8f") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainers ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com"))]) (magit-delta . [(20220125 50) ((emacs (25 1)) (magit (20200426)) (xterm-color (2 0))) "Use Delta when displaying diffs in Magit" tar ((:url . "https://github.com/dandavison/magit-delta") (:commit . "5fc7dbddcfacfe46d3fd876172ad02a9ab6ac616") (:revdesc . "5fc7dbddcfac") (:authors ("Dan Davison" . "dandavison7@gmail.com")) (:maintainers ("Dan Davison" . "dandavison7@gmail.com")) (:maintainer "Dan Davison" . "dandavison7@gmail.com"))]) @@ -3242,7 +3242,7 @@ (magit-popup . [(20200719 1015) ((emacs (24 4)) (dash (2 13 0))) "Define prefix-infix-suffix command combos" tar ((:url . "https://github.com/magit/magit-popup") (:commit . "d8585fa39f88956963d877b921322530257ba9f5") (:revdesc . "d8585fa39f88") (:keywords "bindings") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainers ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li"))]) (magit-rbr . [(20181009 2016) ((magit (2 13 0)) (emacs (24 3))) "Support for git rbr in Magit" tar ((:url . "https://github.com/fanatoly/magit-rbr") (:commit . "029203b3e48537205052a058e964f058cd802c3c") (:revdesc . "029203b3e485") (:keywords "git" "magit" "rbr" "tools") (:authors ("Anatoly Fayngelerin" . "fanatoly+magitrbr@gmail.com")) (:maintainers ("Anatoly Fayngelerin" . "fanatoly+magitrbr@gmail.com")) (:maintainer "Anatoly Fayngelerin" . "fanatoly+magitrbr@gmail.com"))]) (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" tar ((:url . "https://github.com/jtamagnan/magit-reviewboard") (:commit . "aceedff88921f1dfef8a6b2fb18fe316fb7223a8") (:revdesc . "aceedff88921") (:keywords "magit" "vc") (:authors ("Jules Tamagnan" . "jtamagnan@gmail.com")) (:maintainers ("Jules Tamagnan" . "jtamagnan@gmail.com")) (:maintainer "Jules Tamagnan" . "jtamagnan@gmail.com"))]) - (magit-section . [(20241102 1300) ((emacs (26 1)) (compat (30 0 0 0)) (dash (2 19 1)) (seq (2 24))) "Sections for read-only buffers" tar ((:url . "https://github.com/magit/magit") (:commit . "4992c3d1f64e0e983692c7a61d47069f47380dbf") (:revdesc . "4992c3d1f64e") (:keywords "tools") (:authors ("Jonas Bernoulli" . "emacs.magit@jonas.bernoulli.dev")) (:maintainers ("Jonas Bernoulli" . "emacs.magit@jonas.bernoulli.dev")) (:maintainer "Jonas Bernoulli" . "emacs.magit@jonas.bernoulli.dev"))]) + (magit-section . [(20241122 1431) ((emacs (26 1)) (compat (30 0 0 0)) (dash (2 19 1)) (seq (2 24))) "Sections for read-only buffers" tar ((:url . "https://github.com/magit/magit") (:commit . "93a7752842b2d4feff6b5deba44411e9c4249dfe") (:revdesc . "93a7752842b2") (:keywords "tools") (:authors ("Jonas Bernoulli" . "emacs.magit@jonas.bernoulli.dev")) (:maintainers ("Jonas Bernoulli" . "emacs.magit@jonas.bernoulli.dev")) (:maintainer "Jonas Bernoulli" . "emacs.magit@jonas.bernoulli.dev"))]) (magit-stats . [(20230223 1819) ((emacs (25 1))) "Generates GIT Repo Statistics Report" tar ((:url . "https://github.com/LionyxML/magit-stats") (:commit . "41b18e5fc664dba93981a7931f476632c5b54a7d") (:revdesc . "41b18e5fc664") (:keywords "vc" "convenience"))]) (magit-stgit . [(20241012 119) ((emacs (24 4)) (magit (2 12 0)) (transient (0 3 7))) "StGit extension for Magit" tar ((:url . "https://github.com/stacked-git/magit-stgit") (:commit . "51168b7438dfb5ca6b9239b8564397cc0cc6e798") (:revdesc . "51168b7438df") (:keywords "git" "tools" "vc") (:authors ("Lluís Vilanova" . "vilanova@ac.upc.edu")) (:maintainers ("Peter Grayson" . "pete@jpgrayson.net")) (:maintainer "Peter Grayson" . "pete@jpgrayson.net"))]) (magit-svn . [(20220314 1451) ((emacs (25 1)) (magit (2 90 1)) (transient (0 3 2))) "Git-Svn extension for Magit" tar ((:url . "https://github.com/emacsorphanage/magit-svn") (:commit . "b8277081db90977247ae3900ea6afeb0ca644d36") (:revdesc . "b8277081db90") (:keywords "vc" "tools") (:authors ("Phil Jackson" . "phil@shellarchive.co.uk")) (:maintainers ("Phil Jackson" . "phil@shellarchive.co.uk")) (:maintainer "Phil Jackson" . "phil@shellarchive.co.uk"))]) @@ -3275,7 +3275,7 @@ (map-progress . [(20190128 16) ((cl-lib (0 6 1))) "Mapping macros that report progress" tar ((:url . "https://github.com/tarsius/map-progress") (:commit . "1fb916159cd054c233ce3c80d9d01adfae640297") (:revdesc . "1fb916159cd0") (:keywords "convenience") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainers ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li"))]) (map-regexp . [(20190128 18) ((cl-lib (0 6 1))) "Map over matches of a regular expression" tar ((:url . "https://github.com/tarsius/map-regexp") (:commit . "ae2d1c22f786ad987aef3e319925e80160a887a0") (:revdesc . "ae2d1c22f786") (:keywords "convenience") (:authors ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainers ("Jonas Bernoulli" . "jonas@bernoul.li")) (:maintainer "Jonas Bernoulli" . "jonas@bernoul.li"))]) (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 ((:url . "https://github.com/nlamirault/marcopolo") (:commit . "85db828f2bb4346a811b3326349b1c6d0aae4601") (:revdesc . "85db828f2bb4") (:keywords "docker") (:authors ("Nicolas Lamirault" . "nicolas.lamirault@gmail.com")) (:maintainers ("Nicolas Lamirault" . "nicolas.lamirault@gmail.com")) (:maintainer "Nicolas Lamirault" . "nicolas.lamirault@gmail.com"))]) - (marginalia . [(20240926 918) ((emacs (28 1)) (compat (30))) "Enrich existing commands with completion annotations" tar ((:url . "https://github.com/minad/marginalia") (:commit . "be2e57efff640880251c082ac93bd365b7202e6a") (:revdesc . "be2e57efff64") (:keywords "docs" "help" "matching" "completion") (:authors ("Omar Antolín Camarena" . "omar@matem.unam.mx") ("Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainers ("Omar Antolín Camarena" . "omar@matem.unam.mx") ("Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainer "Omar Antolín Camarena" . "omar@matem.unam.mx"))]) + (marginalia . [(20241124 1138) ((emacs (28 1)) (compat (30))) "Enrich existing commands with completion annotations" tar ((:url . "https://github.com/minad/marginalia") (:commit . "643a5f50c9f9d0698c8b1d72678886aefcf69052") (:revdesc . "643a5f50c9f9") (:keywords "docs" "help" "matching" "completion") (:authors ("Omar Antolín Camarena" . "omar@matem.unam.mx") ("Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainers ("Omar Antolín Camarena" . "omar@matem.unam.mx") ("Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainer "Omar Antolín Camarena" . "omar@matem.unam.mx"))]) (mark-multiple . [(20121118 1554) nil "Sorta lets you mark several regions at once" tar ((:url . "https://github.com/magnars/mark-multiple.el") (:commit . "f6a53c7c5283d640ae718f4548b0fda78877a375") (:revdesc . "f6a53c7c5283") (:keywords "marking" "library") (:authors ("Magnar Sveen" . "magnars@gmail.com")) (:maintainers ("Magnar Sveen" . "magnars@gmail.com")) (:maintainer "Magnar Sveen" . "magnars@gmail.com"))]) (mark-thing-at . [(20241022 2232) ((emacs (26)) (choice-program (0 14))) "Mark a pattern at the current point" tar ((:url . "https://github.com/plandes/mark-thing-at") (:commit . "d9499bc82e214e35eac074303a64c023fb10ea5c") (:revdesc . "d9499bc82e21") (:keywords "mark" "point" "lisp"))]) (mark-tools . [(20130614 1025) nil "Some simple tools to access the mark-ring in Emacs" tar ((:url . "https://github.com/stsquad/emacs-mark-tools") (:commit . "a11b61effa90bd0abc876d12573674d36fc17f0c") (:revdesc . "a11b61effa90") (:authors ("Alex Bennée" . "alex@bennee.com")) (:maintainers ("Alex Bennée" . "alex@bennee.com")) (:maintainer "Alex Bennée" . "alex@bennee.com"))]) @@ -3296,7 +3296,7 @@ (marshal . [(20201223 1853) ((emacs (25 1)) (ht (2 0))) "Eieio extension for automatic (un)marshalling" tar ((:url . "https://github.com/sigma/marshal.el") (:commit . "490496d974d03906f784707ecc2e0ac36ed84b96") (:revdesc . "490496d974d0") (:keywords "extensions") (:authors ("Yann Hodique" . "yann.hodique@gmail.com")) (:maintainers ("Yann Hodique" . "yann.hodique@gmail.com")) (:maintainer "Yann Hodique" . "yann.hodique@gmail.com"))]) (maruo-macro-mode . [(20160616 1349) ((emacs (24 3))) "Major mode for editing Hidemaru/Maruo macro script" tar ((:url . "https://github.com/zonuexe/maruo-macro-mode.el") (:commit . "8fc9a38ad051eafa8eb94038711acc52c5d1d8d5") (:revdesc . "8fc9a38ad051") (:keywords "programming" "editor" "macro") (:authors ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainers ("USAMI Kenta" . "tadsan@zonu.me")) (:maintainer "USAMI Kenta" . "tadsan@zonu.me"))]) (masm-mode . [(20200308 1450) ((emacs (25 1))) "MASM x86 and x64 assembly major mode" tar ((:url . "https://github.com/YiGeeker/masm-mode") (:commit . "ab63524d195332ec9f703783704231606e69c292") (:revdesc . "ab63524d1953") (:keywords "languages") (:authors ("YiGeeker" . "zyfchinese@yeah.net")) (:maintainers ("YiGeeker" . "zyfchinese@yeah.net")) (:maintainer "YiGeeker" . "zyfchinese@yeah.net"))]) - (mastodon . [(20241102 1634) ((emacs (28 1)) (request (0 3 0)) (persist (0 4)) (tp (0 6))) "Client for fediverse services using the Mastodon API" tar ((:url . "https://codeberg.org/martianh/mastodon.el") (:commit . "31557be472a94b48163a5651640d3e807a6cbdf2") (:revdesc . "31557be472a9") (:authors ("Johnson Denen" . "johnson.denen@gmail.com") ("Marty Hiatt" . "mousebot@disroot.org")) (:maintainers ("Marty Hiatt" . "mousebot@disroot.org")) (:maintainer "Marty Hiatt" . "mousebot@disroot.org"))]) + (mastodon . [(20241121 1724) ((emacs (28 1)) (request (0 3 0)) (persist (0 4)) (tp (0 6))) "Client for fediverse services using the Mastodon API" tar ((:url . "https://codeberg.org/martianh/mastodon.el") (:commit . "cf6416313084a04e5028f46274e88284e2d120ee") (:revdesc . "cf6416313084") (:authors ("Johnson Denen" . "johnson.denen@gmail.com") ("Marty Hiatt" . "mousebot@disroot.org")) (:maintainers ("Marty Hiatt" . "mousebot@disroot.org")) (:maintainer "Marty Hiatt" . "mousebot@disroot.org"))]) (material-theme . [(20210904 1226) ((emacs (24 1))) "A Theme based on the colors of the Google Material Design" tar ((:url . "https://github.com/cpaulik/emacs-material-theme") (:commit . "6823009bc92f82aa3a90e27e1009f7da8e87b648") (:revdesc . "6823009bc92f") (:keywords "themes") (:authors ("Christoph Paulik" . "cpaulik@gmail.com")) (:maintainers ("Christoph Paulik" . "cpaulik@gmail.com")) (:maintainer "Christoph Paulik" . "cpaulik@gmail.com"))]) (math-preview . [(20240801 513) ((emacs (26 1)) (json (1 4)) (dash (2 18 0)) (s (1 12 0))) "Preview TeX math equations inline" tar ((:url . "https://gitlab.com/matsievskiysv/math-preview") (:commit . "a2ca3c175468ceaf02bab6cdfd8ef016bda2b98d") (:revdesc . "a2ca3c175468") (:keywords "convenience"))]) (math-symbol-lists . [(20220828 2047) nil "Lists of Unicode math symbols and latex commands" tar ((:url . "https://github.com/vspinu/math-symbol-lists") (:commit . "ac3eb053d3b576fcdd192b0ac6ad5090ea3a7079") (:revdesc . "ac3eb053d3b5") (:keywords "unicode" "symbols" "mathematics") (:authors ("Vitalie Spinu" . "spinuvit@gmail.com")) (:maintainers ("Vitalie Spinu" . "spinuvit@gmail.com")) (:maintainer "Vitalie Spinu" . "spinuvit@gmail.com"))]) @@ -3328,7 +3328,7 @@ (memoize . [(20200103 2036) nil "Memoization functions" tar ((:url . "https://github.com/skeeto/emacs-memoize") (:commit . "51b075935ca7070f62fae1d69fe0ff7d8fa56fdd") (:revdesc . "51b075935ca7") (:authors ("Christopher Wellons" . "mosquitopsu@gmail.com")) (:maintainers ("Christopher Wellons" . "mosquitopsu@gmail.com")) (:maintainer "Christopher Wellons" . "mosquitopsu@gmail.com"))]) (memolist . [(20150804 1721) ((markdown-mode (22 0)) (ag (0 45))) "Memolist.el is Emacs port of memolist.vim" tar ((:url . "https://github.com/mikanfactory/memolist.el") (:commit . "60c296e202a71e9dcf1c3936d47b5c4b95c5839f") (:revdesc . "60c296e202a7") (:keywords "markdown" "memo") (:authors ("mikanfactory" . "k952i4j14x17_at_gmail.com")))]) (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 ((:url . "https://github.com/skangas/mentor") (:commit . "f51dd4f3f87c54b7cc92189924b9d873a53f5a75") (:revdesc . "f51dd4f3f87c") (:keywords "comm" "processes" "bittorrent") (:authors ("Stefan Kangas" . "stefankangas@gmail.com")) (:maintainers ("Stefan Kangas" . "stefankangas@gmail.com")) (:maintainer "Stefan Kangas" . "stefankangas@gmail.com"))]) - (meow . [(20241117 201) ((emacs (27 1))) "Yet Another modal editing" tar ((:url . "https://github.com/meow-edit/meow") (:commit . "c0985b3531ca14067d96ed3018bec80fe7eeb7db") (:revdesc . "c0985b3531ca") (:keywords "convenience" "modal-editing"))]) + (meow . [(20241122 2159) ((emacs (27 1))) "Yet Another modal editing" tar ((:url . "https://github.com/meow-edit/meow") (:commit . "813892013b971e6a938d2b443a2b50c68dc67d99") (:revdesc . "813892013b97") (:keywords "convenience" "modal-editing"))]) (meow-tree-sitter . [(20240701 1422) ((emacs (29 1)) (meow (1 2 0))) "Tree-sitter powered motions for Meow" tar ((:url . "https://github.com/skissue/meow-tree-sitter") (:commit . "d8dce964fac631a6d44b650a733075e14854159c") (:revdesc . "d8dce964fac6") (:keywords "convenience" "files" "languages" "tools") (:authors ("Ad" . "me@skissue.xyz")) (:maintainers ("Ad" . "me@skissue.xyz")) (:maintainer "Ad" . "me@skissue.xyz"))]) (merlin . [(20240925 900) ((emacs (25 1))) "Mode for Merlin, an assistant for OCaml" tar ((:url . "https://github.com/ocaml/merlin") (:commit . "80e919cf32a62acdaee95a5dab9b4bc18a8b4034") (:revdesc . "80e919cf32a6") (:keywords "ocaml" "languages") (:authors ("Frédéric Bour" . "frederic.bourlakaban.net")) (:maintainers ("Frédéric Bour" . "frederic.bourlakaban.net")) (:maintainer "Frédéric Bour" . "frederic.bourlakaban.net"))]) (merlin-ac . [(20221123 1408) ((emacs (25 1)) (merlin (3)) (auto-complete (1 5))) "Merlin and auto-complete integration" tar ((:url . "https://github.com/ocaml/merlin") (:commit . "8bcab034a680f57ddf58092fda6288dc4caddd2a") (:revdesc . "8bcab034a680") (:keywords "ocaml" "languages") (:authors ("Simon Castellan" . "simon.castellaniuwt.fr") ("Frédéric Bour" . "frederic.bourlakaban.net") ("Thomas Refis" . "thomas.refisgmail.com")) (:maintainers ("Simon Castellan" . "simon.castellaniuwt.fr") ("Frédéric Bour" . "frederic.bourlakaban.net") ("Thomas Refis" . "thomas.refisgmail.com")) (:maintainer "Simon Castellan" . "simon.castellaniuwt.fr"))]) @@ -3357,7 +3357,7 @@ (meyvn . [(20240905 43) ((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" tar ((:url . "https://github.com/danielsz/meyvn-el") (:commit . "8d00ada6daa5617fa60f76e0be2cf2f5d1babcf9") (:revdesc . "8d00ada6daa5") (:authors ("Daniel Szmulewicz" . "daniel.szmulewicz@gmail.com")) (:maintainers ("Daniel Szmulewicz" . "daniel.szmulewicz@gmail.com")) (:maintainer "Daniel Szmulewicz" . "daniel.szmulewicz@gmail.com"))]) (mgmtconfig-mode . [(20240330 2205) ((emacs (24 3))) "Mgmt configuration management language" tar ((:url . "https://github.com/purpleidea/mgmt") (:commit . "1b00af6926d8699d9d04062f28fddd43c6340bac") (:revdesc . "1b00af6926d8") (:keywords "languages") (:authors ("Peter Oliver" . "mgmtconfig@mavit.org.uk")) (:maintainers ("Mgmt contributors" . "https://github.com/purpleidea/mgmt")) (:maintainer "Mgmt contributors" . "https://github.com/purpleidea/mgmt"))]) (mhc . [(20240419 10) ((calfw (20150703))) "Message Harmonized Calendaring system" tar ((:url . "https://github.com/yoshinari-nomura/mhc") (:commit . "b527a88748651d06222ad24f7417941088515275") (:revdesc . "b527a8874865") (:keywords "calendar") (:authors ("Yoshinari Nomura" . "nom@quickhack.net")) (:maintainers ("Yoshinari Nomura" . "nom@quickhack.net")) (:maintainer "Yoshinari Nomura" . "nom@quickhack.net"))]) - (miasma-theme . [(20241117 2101) nil "Miasma: color theme inspired by the woods" tar ((:url . "https://github.com/daut/miasma-theme.el") (:commit . "9212213d12d40c6631a30a407b1b981e1a1101f0") (:revdesc . "9212213d12d4"))]) + (miasma-theme . [(20241122 1754) nil "Miasma: color theme inspired by the woods" tar ((:url . "https://github.com/daut/miasma-theme.el") (:commit . "ada1805f4485851d61b39c1855386d356fd2d00c") (:revdesc . "ada1805f4485"))]) (mic . [(20240806 1655) ((emacs (26 1))) "Minimal and combinable configuration manager" tar ((:url . "https://github.com/ROCKTAKEY/mic") (:commit . "f552ddf397e899e9c2b96ef4e56a08cc8804a1c5") (:revdesc . "f552ddf397e8") (:keywords "convenience") (:authors ("ROCKTAKEY" . "rocktakey@gmail.com")) (:maintainers ("ROCKTAKEY" . "rocktakey@gmail.com")) (:maintainer "ROCKTAKEY" . "rocktakey@gmail.com"))]) (mic-paren . [(20170731 1907) nil "Advanced highlighting of matching parentheses" tar ((:url . "https://github.com/emacsattic/mic-paren") (:commit . "d0410c7d805c9aaf51a1bcefaaef092bed5824c4") (:revdesc . "d0410c7d805c") (:keywords "languages" "faces" "parenthesis" "matching") (:authors ("Mikael Sjödin" . "(mic@docs.uu.se)") ("Klaus Berndl" . "berndl@sdm.de") ("Jonathan Kotta" . "jpkotta@gmail.com")))]) (micgoline . [(20160415 326) ((emacs (24 3)) (powerline (2 3))) "Powerline mode, color schemes from microsoft and google's logo" tar ((:url . "https://github.com/yzprofile/micgoline") (:commit . "e3e2effe4846175a3b52b4092c0c134ced5978d8") (:revdesc . "e3e2effe4846") (:keywords "mode-line" "powerline" "theme") (:authors ("yzprofile" . "yzprofiles@gmail.com")) (:maintainers ("yzprofile" . "yzprofiles@gmail.com")) (:maintainer "yzprofile" . "yzprofiles@gmail.com"))]) @@ -3366,7 +3366,7 @@ (milkode . [(20140927 529) nil "Command line search and direct jump with Milkode" tar ((:url . "https://github.com/ongaeshi/emacs-milkode") (:commit . "ba97e2aeefa1d9d0b3835bf08edd0de248b0c513") (:revdesc . "ba97e2aeefa1") (:keywords "milkode" "search" "grep" "jump" "keyword"))]) (mimetypes . [(20201115 1605) ((emacs (25 1))) "Guess a file's mimetype by extension" tar ((:url . "https://github.com/cniles/emacs-mimetypes") (:commit . "1663054ce266ed25e47ec707c19f619d33225903") (:revdesc . "1663054ce266") (:authors ("Craig Niles" . "niles.catgmail.com")) (:maintainers ("Craig Niles" . "niles.catgmail.com")) (:maintainer "Craig Niles" . "niles.catgmail.com"))]) (mindre-theme . [(20240610 2131) ((emacs (26 1))) "Minimal, light theme" tar ((:url . "https://github.com/erikbackman/mindre-theme") (:commit . "cbecece36988f83b7e355a3fcf5229f2494f3688") (:revdesc . "cbecece36988") (:keywords "faces") (:authors ("Erik Bäckman" . "contact@ebackman.net")) (:maintainers ("Erik Bäckman" . "contact@ebackman.net")) (:maintainer "Erik Bäckman" . "contact@ebackman.net"))]) - (mindstream . [(20241024 323) ((emacs (25 1)) (magit (3 3 0))) "Start writing, stay focused, don't worry" tar ((:url . "https://github.com/countvajhula/mindstream") (:commit . "7e9f28f6342dba4215cf3066c0d52bbe2e4d0f34") (:revdesc . "7e9f28f6342d") (:keywords "convenience" "files" "languages" "outlines" "tools" "vc" "wp") (:authors ("Siddhartha Kasivajhula" . "sid@countvajhula.com")) (:maintainers ("Siddhartha Kasivajhula" . "sid@countvajhula.com")) (:maintainer "Siddhartha Kasivajhula" . "sid@countvajhula.com"))]) + (mindstream . [(20241121 19) ((emacs (25 1)) (magit (3 3 0))) "Start writing, stay focused, don't worry" tar ((:url . "https://github.com/countvajhula/mindstream") (:commit . "cad6a33c7e45f7c52f627d38d3d1f8f35a53413e") (:revdesc . "cad6a33c7e45") (:keywords "convenience" "files" "languages" "outlines" "tools" "vc" "wp") (:authors ("Siddhartha Kasivajhula" . "sid@countvajhula.com")) (:maintainers ("Siddhartha Kasivajhula" . "sid@countvajhula.com")) (:maintainer "Siddhartha Kasivajhula" . "sid@countvajhula.com"))]) (minesweeper . [(20200416 2342) nil "Play minesweeper in Emacs" tar ((:url . "https://hg.sr.ht/~zck/minesweeper") (:commit . "d4248e3c9b3e9e7277cb9e6d081330611898f334") (:revdesc . "d4248e3c9b3e9e7277cb9e6d081330611898f334") (:keywords "game" "fun" "minesweeper" "inane" "diversion") (:authors ("Zachary Kanfer" . "zkanfer@gmail.com")) (:maintainers ("Zachary Kanfer" . "zkanfer@gmail.com")) (:maintainer "Zachary Kanfer" . "zkanfer@gmail.com"))]) (mingus . [(20230518 1726) ((libmpdee (2 2))) "MPD Interface" tar ((:url . "https://github.com/pft/mingus") (:commit . "3fa9b95552eb062eb245321abb7f442c458618dc") (:revdesc . "3fa9b95552eb") (:keywords "multimedia" "elisp" "music" "mpd") (:authors ("Niels Giesen" . "pfton#emacs")) (:maintainers ("Niels Giesen" . "pfton#emacs")) (:maintainer "Niels Giesen" . "pfton#emacs"))]) (mini-echo . [(20241029 401) ((emacs (29 1)) (dash (2 19 1)) (hide-mode-line (1 0 3))) "Echo buffer status in minibuffer window" tar ((:url . "https://github.com/liuyinz/mini-echo.el") (:commit . "381ec09c9efeb15509e7489c64a3b92141ad52c3") (:revdesc . "381ec09c9efe") (:keywords "frames") (:authors ("liuyinz" . "liuyinz95@gmail.com")) (:maintainers ("liuyinz" . "liuyinz95@gmail.com")) (:maintainer "liuyinz" . "liuyinz95@gmail.com"))]) @@ -3380,7 +3380,7 @@ (miniedit . [(20100419 1745) nil "Enhanced editing for minibuffer fields" tar ((:url . "https://github.com/emacsorphanage/miniedit") (:commit . "e12bf659c3eb92dd8a4cb77642dc0865c54667a3") (:revdesc . "e12bf659c3eb"))]) (minimal-session-saver . [(20140508 2041) nil "Very lean session saver" tar ((:url . "https://github.com/rolandwalker/minimal-session-saver") (:commit . "ac42b6835f777a8a7e04599d8f20ec650997ba96") (:revdesc . "ac42b6835f77") (:keywords "tools" "frames" "project") (:authors ("Roland Walker" . "walker@pobox.com")) (:maintainers ("Roland Walker" . "walker@pobox.com")) (:maintainer "Roland Walker" . "walker@pobox.com"))]) (minimal-theme . [(20190113 2132) nil "A light/dark minimalistic Emacs 24 theme" tar ((:url . "https://github.com/anler/minimal-theme") (:commit . "063b4d8ca33d55d04c341f0b2b777ec241a3e201") (:revdesc . "063b4d8ca33d") (:keywords "color" "theme" "minimal") (:authors ("Anler Hp" . "anler86[at]gmail.com")) (:maintainers ("Anler Hp" . "anler86[at]gmail.com")) (:maintainer "Anler Hp" . "anler86[at]gmail.com"))]) - (minions . [(20240805 1422) ((emacs (26 1)) (compat (30 0 0 0))) "A minor-mode menu for the mode line" tar ((:url . "https://github.com/tarsius/minions") (:commit . "413b95a0d1c7c10d0f8d440d1982062b73d5ea4a") (:revdesc . "413b95a0d1c7") (:keywords "convenience") (:authors ("Jonas Bernoulli" . "emacs.minions@jonas.bernoulli.dev")) (:maintainers ("Jonas Bernoulli" . "emacs.minions@jonas.bernoulli.dev")) (:maintainer "Jonas Bernoulli" . "emacs.minions@jonas.bernoulli.dev"))]) + (minions . [(20241123 2136) ((emacs (26 1)) (compat (30 0 0 0))) "A minor-mode menu for the mode line" tar ((:url . "https://github.com/tarsius/minions") (:commit . "e04415dc028ba252f079cfc7d6dff3059a047fbd") (:revdesc . "e04415dc028b") (:keywords "convenience") (:authors ("Jonas Bernoulli" . "emacs.minions@jonas.bernoulli.dev")) (:maintainers ("Jonas Bernoulli" . "emacs.minions@jonas.bernoulli.dev")) (:maintainer "Jonas Bernoulli" . "emacs.minions@jonas.bernoulli.dev"))]) (minitest . [(20231222 1521) ((dash (1 0 0))) "An Emacs mode for ruby minitest files" tar ((:url . "https://github.com/arthurnn/minitest-emacs") (:commit . "5999c45c047212cee15a2be67e78787776a79c35") (:revdesc . "5999c45c0472"))]) (minizinc-mode . [(20180201 1450) ((emacs (24 1))) "Major mode for MiniZinc code" tar ((:url . "https://github.com/m00nlight/minizinc-mode") (:commit . "2512521ba7f8e263a06db88df663fc6b3cca7e16") (:revdesc . "2512521ba7f8") (:keywords "languages" "minizinc"))]) (minor-mode-hack . [(20170926 34) nil "Change priority of minor-mode keymaps" tar ((:url . "https://github.com/rubikitch/minor-mode-hack") (:commit . "c3aa957602c924c01fe07d48d191b8616fb3696a") (:revdesc . "c3aa957602c9") (:keywords "lisp") (:authors ("rubikitch" . "rubikitch@ruby-lang.org")) (:maintainers ("rubikitch" . "rubikitch@ruby-lang.org")) (:maintainer "rubikitch" . "rubikitch@ruby-lang.org"))]) @@ -3389,7 +3389,7 @@ (mip-mode . [(20151127 617) nil "Virtual projects for emacs" tar ((:url . "https://gitlab.com/gaudecker/mip-mode") (:commit . "7c88c383b4c7ed0a4c1dc397735f365c1fcb461c") (:revdesc . "7c88c383b4c7") (:keywords "workspaces" "workspace" "project" "projects" "mip-mode") (:authors ("Eeli Reilin" . "gaudecker@fea.st")) (:maintainers ("Eeli Reilin" . "gaudecker@fea.st")) (:maintainer "Eeli Reilin" . "gaudecker@fea.st"))]) (mips-mode . [(20220608 1204) ((emacs (25 1))) "Major-mode for MIPS assembly" tar ((:url . "https://github.com/hlissner/emacs-mips-mode") (:commit . "98795cdc81979821ac35d9f94ce354cd99780c67") (:revdesc . "98795cdc8197") (:keywords "languages" "mips" "assembly") (:authors ("Henrik Lissner" . "http://github/hlissner")) (:maintainers ("Henrik Lissner" . "contact@henrik.io")) (:maintainer "Henrik Lissner" . "contact@henrik.io"))]) (mise . [(20241106 1515) ((emacs (29 1)) (inheritenv (0 2)) (dash (2 19 1))) "Support for `mise' cli" tar ((:url . "https://github.com/liuyinz/mise.el") (:commit . "6e32b3787dd926cc9d8e9202b5aaa82682398261") (:revdesc . "6e32b3787dd9") (:keywords "tools" "processes") (:authors ("liuyinz" . "liuyinz95@gmail.com")) (:maintainers ("Liuyinz" . "liuyinz95@gmail.com")) (:maintainer "Liuyinz" . "liuyinz95@gmail.com"))]) - (mistty . [(20241115 1744) ((emacs (29 1))) "Shell/Comint alternative based on term.el" tar ((:url . "https://github.com/szermatt/mistty") (:commit . "046f79219d516e33d73b39b6f5779790cd814893") (:revdesc . "046f79219d51") (:keywords "convenience" "unix") (:authors ("Stephane Zermatten" . "szermatt@gmx.net")) (:maintainers ("Stephane Zermatten" . "szermatt@gmx.net")) (:maintainer "Stephane Zermatten" . "szermatt@gmx.net"))]) + (mistty . [(20241124 1049) ((emacs (29 1))) "Shell/Comint alternative based on term.el" tar ((:url . "https://github.com/szermatt/mistty") (:commit . "45f1b757a3c4bc75103a8eb3c687cd3c08b137c1") (:revdesc . "45f1b757a3c4") (:keywords "convenience" "unix") (:authors ("Stephane Zermatten" . "szermatt@gmx.net")) (:maintainers ("Stephane Zermatten" . "szermatt@gmx.net")) (:maintainer "Stephane Zermatten" . "szermatt@gmx.net"))]) (mix . [(20240122 720) ((emacs (25 1))) "Mix Major Mode. Build Elixir using Mix" tar ((:url . "https://github.com/ayrat555/mix.el") (:commit . "16cc69cbf919769c191b1c49c1cab324fd0682a9") (:revdesc . "16cc69cbf919") (:keywords "tools") (:authors ("Ayrat Badykov" . "ayratin555@gmail.com")) (:maintainers ("Ayrat Badykov" . "ayratin555@gmail.com")) (:maintainer "Ayrat Badykov" . "ayratin555@gmail.com"))]) (mixed-pitch . [(20210304 1900) ((emacs (24 3))) "Use a variable pitch, keeping fixed pitch where it's sensible" tar ((:url . "https://gitlab.com/jabranham/mixed-pitch") (:commit . "519e05f74825abf04b7d2e0e38ec040d013a125a") (:revdesc . "519e05f74825") (:authors ("J. Alexander Branham" . "branham@utexas.edu")) (:maintainers ("J. Alexander Branham" . "branham@utexas.edu")) (:maintainer "J. Alexander Branham" . "branham@utexas.edu"))]) (mkdown . [(20140517 1418) ((markdown-mode (2 0))) "Pretty Markdown previews based on mkdown.com" tar ((:url . "https://github.com/ajtulloch/mkdown.el") (:commit . "8e23de82719af6c5b53b52b3308a02b3a1fb872e") (:revdesc . "8e23de82719a") (:keywords "markdown"))]) @@ -3462,7 +3462,7 @@ (mpdel-embark . [(20230103 2021) ((emacs (26 1)) (mpdel (2 0 0)) (libmpdel (2 0 0)) (embark (0 19))) "Integrate MPDel with Embark" tar ((:url . "https://github.com/mpdel/mpdel-embark") (:commit . "31d91a62b680fb4472ec34c04ac6af80bb3cf4b8") (:revdesc . "31d91a62b680") (:keywords "multimedia") (:authors ("Damien Cassou" . "damien@cassou.me")) (:maintainers ("Damien Cassou" . "damien@cassou.me")) (:maintainer "Damien Cassou" . "damien@cassou.me"))]) (mpdmacs . [(20240917 310) ((emacs (29 1)) (elmpd (0 3))) "A lightweight MPD client" tar ((:url . "https://github.com/sp1ff/mpdmacs") (:commit . "fca8374804216fb0533b5cbe92199dc4179033db") (:revdesc . "fca837480421") (:keywords "comm") (:authors ("Michael Herstine" . "sp1ff@pobox.com")) (:maintainers ("Michael Herstine" . "sp1ff@pobox.com")) (:maintainer "Michael Herstine" . "sp1ff@pobox.com"))]) (mpmc-queue . [(20180303 2029) ((emacs (26 0)) (queue (0 2 0))) "A multiple-producer-multiple-consumer queue" tar ((:url . "https://github.com/smizoe/mpmc-queue") (:commit . "df07d6bef7468edb1d73ef73b8331b94d0e5d0ca") (:revdesc . "df07d6bef746") (:keywords "lisp" "async") (:authors ("Sho Mizoe" . "sho.mizoe@gmail.com")) (:maintainers ("Sho Mizoe" . "sho.mizoe@gmail.com")) (:maintainer "Sho Mizoe" . "sho.mizoe@gmail.com"))]) - (mpv . [(20220801 1917) ((emacs (25 1))) "Control mpv for easy note-taking" tar ((:url . "https://github.com/kljohann/mpv.el") (:commit . "2e0234bc21a3dcdf12d94d3285475e7f6769d3e8") (:revdesc . "2e0234bc21a3") (:keywords "tools" "multimedia") (:authors ("Johann Klähn" . "johann@jklaehn.de")) (:maintainers ("Johann Klähn" . "johann@jklaehn.de")) (:maintainer "Johann Klähn" . "johann@jklaehn.de"))]) + (mpv . [(20241121 2308) ((emacs (25 1))) "Control mpv for easy note-taking" tar ((:url . "https://github.com/kljohann/mpv.el") (:commit . "62cb8825d525d7c9475dd93d62ba84d419bc4832") (:revdesc . "62cb8825d525") (:keywords "tools" "multimedia") (:authors ("Johann Klähn" . "johann@jklaehn.de")) (:maintainers ("Johann Klähn" . "johann@jklaehn.de")) (:maintainer "Johann Klähn" . "johann@jklaehn.de"))]) (mpvi . [(20240315 214) ((emacs (28 1)) (emms (11))) "Media tool based on EMMS and MPV" tar ((:url . "https://github.com/lorniu/mpvi") (:commit . "2412e4cd2879e1ebeaf29b92104abc94226b50bc") (:revdesc . "2412e4cd2879") (:keywords "convenience" "docs" "multimedia" "application") (:authors ("lorniu" . "lorniu@gmail.com")) (:maintainers ("lorniu" . "lorniu@gmail.com")) (:maintainer "lorniu" . "lorniu@gmail.com"))]) (mqr . [(20180527 1204) ((emacs (24 4))) "Multi-dimensional query and replace" tar ((:url . "https://github.com/calancha/multi-replace") (:commit . "4ade19d4620b8b61340290bf63fa56d5e493859f") (:revdesc . "4ade19d4620b") (:keywords "convenience" "extensions" "lisp") (:authors ("Tino Calancha" . "tino.calancha@gmail.com")) (:maintainers ("Tino Calancha" . "tino.calancha@gmail.com")) (:maintainer "Tino Calancha" . "tino.calancha@gmail.com"))]) (mqtt-mode . [(20180611 1735) ((emacs (25)) (dash (2 12 0))) "Client for interaction with MQTT servers" tar ((:url . "https://github.com/andrmuel/mqtt-mode") (:commit . "613e70e9b9940e635e779994b5c83f86eb62c8e6") (:revdesc . "613e70e9b994") (:keywords "tools") (:authors ("Andreas Müller" . "code@0x7.ch")) (:maintainers ("Andreas Müller" . "code@0x7.ch")) (:maintainer "Andreas Müller" . "code@0x7.ch"))]) @@ -3587,7 +3587,7 @@ (nix-modeline . [(20210405 742) ((emacs (25 1))) "Info about in-progress Nix evaluations on your modeline" tar ((:url . "https://github.com/ocelot-project/nix-modeline") (:commit . "9a6116a11bdacf649f2c50ae1f2f4b12c03bed70") (:revdesc . "9a6116a11bda") (:keywords "processes" "unix" "tools") (:authors ("Jordan Mulcahey" . "snhjordy@gmail.com")) (:maintainers ("Jordan Mulcahey" . "snhjordy@gmail.com")) (:maintainer "Jordan Mulcahey" . "snhjordy@gmail.com"))]) (nix-sandbox . [(20210325 1622) ((dash (2 12 1)) (s (1 10 0))) "Utility functions to work with nix-shell sandboxes" tar ((:url . "https://github.com/nix-community/nix-emacs") (:commit . "d3ec98405f1f9dac833abf9e146249b1b943870d") (:revdesc . "d3ec98405f1f") (:authors ("Sven Keidel" . "svenkeidel@gmail.com")) (:maintainers ("Sven Keidel" . "svenkeidel@gmail.com")) (:maintainer "Sven Keidel" . "svenkeidel@gmail.com"))]) (nix-ts-mode . [(20240930 651) ((emacs (29 1))) "Major mode for Nix expressions, powered by tree-sitter" tar ((:url . "https://github.com/nix-community/nix-ts-mode") (:commit . "9419d014cada54d34e5004e24a31462e8597fd28") (:revdesc . "9419d014cada") (:keywords "nix" "languages") (:maintainers ("Remi Gelinas" . "mail@remigelin.as")) (:maintainer "Remi Gelinas" . "mail@remigelin.as"))]) - (nix-update . [(20220816 2212) ((emacs (25))) "Update \"fetch\" blocks in .nix expressions" tar ((:url . "https://github.com/jwiegley/nix-update-el") (:commit . "aab70a38165575a9cb41726f1cc67df60fbf2832") (:revdesc . "aab70a381655") (:keywords "nix") (:authors ("John Wiegley" . "johnw@newartisans.com")) (:maintainers ("John Wiegley" . "johnw@newartisans.com")) (:maintainer "John Wiegley" . "johnw@newartisans.com"))]) + (nix-update . [(20241123 2159) ((emacs (25))) "Update \"fetch\" blocks in .nix expressions" tar ((:url . "https://github.com/jwiegley/nix-update-el") (:commit . "77022ccd918d665acbb519b243e7e3dc5eae1c47") (:revdesc . "77022ccd918d") (:keywords "nix") (:authors ("John Wiegley" . "johnw@newartisans.com")) (:maintainers ("John Wiegley" . "johnw@newartisans.com")) (:maintainer "John Wiegley" . "johnw@newartisans.com"))]) (nixfmt . [(20240724 1531) ((emacs (24)) (reformatter (0 3))) "Reformat Nix using nixfmt" tar ((:url . "https://github.com/purcell/emacs-nixfmt") (:commit . "9c8a1c12320247a3fe643191b7574a3674fba317") (:revdesc . "9c8a1c123202") (:keywords "languages") (:authors ("Steve Purcell" . "steve@sanityinc.com")) (:maintainers ("Steve Purcell" . "steve@sanityinc.com")) (:maintainer "Steve Purcell" . "steve@sanityinc.com"))]) (nixos-options . [(20160209 1841) ((emacs (24))) "Interface for browsing and completing NixOS options" tar ((:url . "https://github.com/nix-community/nix-emacs") (:commit . "045825c2e1cf0a4fb0a472e72c1dae8f55202cef") (:revdesc . "045825c2e1cf") (:keywords "unix") (:authors ("Diego Berrocal" . "cestdiego@gmail.com") ("Travis B. Hartwell" . "nafai@travishartwell.net")) (:maintainers ("Diego Berrocal" . "cestdiego@gmail.com") ("Travis B. Hartwell" . "nafai@travishartwell.net")) (:maintainer "Diego Berrocal" . "cestdiego@gmail.com"))]) (nixpkgs-fmt . [(20200327 2302) ((emacs (24)) (reformatter (0 3))) "Reformat Nix using nixpkgs-fmt" tar ((:url . "https://github.com/purcell/emacs-nixpkgs-fmt") (:commit . "83e03d6f20bdf79c1c448c15734367b1a7cc6b02") (:revdesc . "83e03d6f20bd") (:keywords "languages") (:authors ("Steve Purcell" . "steve@sanityinc.com")) (:maintainers ("Steve Purcell" . "steve@sanityinc.com")) (:maintainer "Steve Purcell" . "steve@sanityinc.com"))]) @@ -4029,7 +4029,7 @@ (orthodox-christian-new-calendar-holidays . [(20210830 1657) nil "Feasts (NS)" tar ((:url . "https://github.com/cmchittom/orthodox-christian-new-calendar-holidays") (:commit . "6869024ecd45eefd0ec648979c6a59d7c79770e0") (:revdesc . "6869024ecd45") (:keywords "calendar") (:authors ("Carson Chittom" . "carson@wistly.net")) (:maintainers ("Carson Chittom" . "carson@wistly.net")) (:maintainer "Carson Chittom" . "carson@wistly.net"))]) (osa . [(20200522 2103) ((emacs (25 1))) "OSA (JavaScript / AppleScript) bridge" tar ((:url . "https://github.com/atomontage/osa") (:commit . "615ca9eef4131a23d9971691fa0d0f20fe59d01b") (:revdesc . "615ca9eef413") (:keywords "extensions") (:authors ("xristos" . "xristos@sdf.org")) (:maintainers ("xristos" . "xristos@sdf.org")) (:maintainer "xristos" . "xristos@sdf.org"))]) (osa-chrome . [(20230515 237) ((emacs (25 1)) (osa (1 0))) "Google Chrome remote tab control" tar ((:url . "https://github.com/atomontage/osa-chrome") (:commit . "981c35136102eeca77d0e1a41e7c95e8486a1dce") (:revdesc . "981c35136102") (:keywords "comm") (:authors ("xristos" . "xristos@sdf.org")) (:maintainers ("xristos" . "xristos@sdf.org")) (:maintainer "xristos" . "xristos@sdf.org"))]) - (osm . [(20241119 2137) ((emacs (28 1)) (compat (30))) "OpenStreetMap viewer" tar ((:url . "https://github.com/minad/osm") (:commit . "ab76f8a9e79e0ec6330071b4aed974270b6f2a15") (:revdesc . "ab76f8a9e79e") (:keywords "network" "multimedia" "hypermedia" "mouse") (:authors ("Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainers ("Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainer "Daniel Mendler" . "mail@daniel-mendler.de"))]) + (osm . [(20241122 130) ((emacs (28 1)) (compat (30))) "OpenStreetMap viewer" tar ((:url . "https://github.com/minad/osm") (:commit . "6a2416dc4c3be22573cd9f5fb285df3f4bd6b6ea") (:revdesc . "6a2416dc4c3b") (:keywords "network" "multimedia" "hypermedia" "mouse") (:authors ("Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainers ("Daniel Mendler" . "mail@daniel-mendler.de")) (:maintainer "Daniel Mendler" . "mail@daniel-mendler.de"))]) (osx-browse . [(20140508 2041) ((string-utils (0 3 2)) (browse-url-dwim (0 6 6))) "Web browsing helpers for OS X" tar ((:url . "https://github.com/rolandwalker/osx-browse") (:commit . "838b81625853e04919fbb56fd21f387762b2e3f5") (:revdesc . "838b81625853") (:keywords "hypermedia" "external") (:authors ("Roland Walker" . "walker@pobox.com")) (:maintainers ("Roland Walker" . "walker@pobox.com")) (:maintainer "Roland Walker" . "walker@pobox.com"))]) (osx-clipboard . [(20141012 717) nil "Use the OS X clipboard from terminal Emacs" tar ((:url . "https://github.com/joddie/osx-clipboard-mode") (:commit . "e46dd31327a3f92f77b013b4c9b1e5fdd0e5c73d") (:revdesc . "e46dd31327a3") (:authors ("Jon Oddie" . "jonxfieldatgmail.com")) (:maintainers ("Jon Oddie" . "jonxfieldatgmail.com")) (:maintainer "Jon Oddie" . "jonxfieldatgmail.com"))]) (osx-dictionary . [(20240330 942) ((cl-lib (0 5))) "Interface for OSX Dictionary.app" tar ((:url . "https://github.com/xuchunyang/osx-dictionary.el") (:commit . "6abfd6908b0dc773020466225c908000870b383b") (:revdesc . "6abfd6908b0d") (:keywords "mac" "dictionary") (:authors ("Chunyang Xu" . "mail@xuchunyang.me")) (:maintainers ("Chunyang Xu" . "mail@xuchunyang.me")) (:maintainer "Chunyang Xu" . "mail@xuchunyang.me"))]) @@ -4041,9 +4041,9 @@ (osx-trash . [(20220913 1736) ((emacs (24 1))) "System trash for OS X" tar ((:url . "https://github.com/emacsorphanage/osx-trash") (:commit . "90f0c99206022fec646206018fcd63d9d2e57325") (:revdesc . "90f0c9920602") (:keywords "files" "convenience" "tools" "unix") (:authors ("Sebastian Wiesner" . "swiesner@lunaryorn.com")) (:maintainers ("Sebastian Wiesner" . "swiesner@lunaryorn.com")) (:maintainer "Sebastian Wiesner" . "swiesner@lunaryorn.com"))]) (otama . [(20160404 1032) nil "Org-table Manipulator" tar ((:url . "https://github.com/yoshinari-nomura/otama") (:commit . "b69e0740846ace7885b0c0717f7abe8d0419eefd") (:revdesc . "b69e0740846a") (:keywords "database" "org-mode") (:authors ("Yoshinari Nomura" . "nom@quickhack.net")) (:maintainers ("Yoshinari Nomura" . "nom@quickhack.net")) (:maintainer "Yoshinari Nomura" . "nom@quickhack.net"))]) (other-emacs-eval . [(20180408 1348) ((emacs (25 1)) (async (1 9 2))) "Evaluate the Emacs Lisp expression in other Emacs" tar ((:url . "https://github.com/xuchunyang/other-emacs-eval") (:commit . "8ace5acafef65daabf0c6619eff60733d7f5d792") (:revdesc . "8ace5acafef6") (:keywords "tools") (:authors ("Xu Chunyang" . "mail@xuchunyang.me")) (:maintainers ("Xu Chunyang" . "mail@xuchunyang.me")) (:maintainer "Xu Chunyang" . "mail@xuchunyang.me"))]) - (otpp . [(20241115 2256) ((emacs (28 1)) (compat (29 1))) "One tab per project, with unique names" tar ((:url . "https://github.com/abougouffa/one-tab-per-project") (:commit . "6507da9014b6d4b76925c089cafa62f1cb0b4500") (:revdesc . "6507da9014b6") (:keywords "convenience") (:authors ("Abdelhak Bougouffa (rot13" . "\"nobhtbhssn@srqbencebwrpg.bet\")")) (:maintainers ("Abdelhak Bougouffa (rot13" . "\"nobhtbhssn@srqbencebwrpg.bet\")")) (:maintainer "Abdelhak Bougouffa (rot13" . "\"nobhtbhssn@srqbencebwrpg.bet\")"))]) + (otpp . [(20241121 1445) ((emacs (28 1)) (compat (29 1))) "One tab per project, with unique names" tar ((:url . "https://github.com/abougouffa/one-tab-per-project") (:commit . "09445a75464d5e92d8e283078ad16c05022f7d9f") (:revdesc . "09445a75464d") (:keywords "convenience") (:authors ("Abdelhak Bougouffa (rot13" . "\"nobhtbhssn@srqbencebwrpg.bet\")")) (:maintainers ("Abdelhak Bougouffa (rot13" . "\"nobhtbhssn@srqbencebwrpg.bet\")")) (:maintainer "Abdelhak Bougouffa (rot13" . "\"nobhtbhssn@srqbencebwrpg.bet\")"))]) (ouroboros . [(20230606 1150) ((emacs (27 1)) (dash (2 19 0)) (cbor (0 2 5)) (bech32 (0 2 1))) "Ouroboros network mini-protocol" tar ((:url . "https://github.com/Titan-C/cardano.el") (:commit . "cf85424b305e8f89debb756dc67eebc84639f711") (:revdesc . "cf85424b305e") (:authors ("Oscar Najera" . "https://oscarnajera.com")) (:maintainers ("Oscar Najera" . "hi@oscarnajera.com")) (:maintainer "Oscar Najera" . "hi@oscarnajera.com"))]) - (outline-indent . [(20241119 1447) ((emacs (26 1))) "Folding text based on indentation (origami alternative)" tar ((:url . "https://github.com/jamescherti/outline-indent.el") (:commit . "60f0786a6ede572fd3dfe0bc05597f1a24fef5da") (:revdesc . "60f0786a6ede") (:keywords "outlines"))]) + (outline-indent . [(20241124 514) ((emacs (26 1))) "Folding text based on indentation (origami alternative)" tar ((:url . "https://github.com/jamescherti/outline-indent.el") (:commit . "c10ac32b0a241e62d92d91e79be5c67cac449864") (:revdesc . "c10ac32b0a24") (:keywords "outlines"))]) (outline-magic . [(20180619 1819) nil "Outline mode extensions for Emacs" tar ((:url . "https://github.com/tj64/outline-magic") (:commit . "2a5f07417b696cf7541d435c43bafcc64817636b") (:revdesc . "2a5f07417b69") (:keywords "outlines") (:authors ("Carsten Dominik" . "dominik@science.uva.nl")) (:maintainers ("Thorsten Jolitz" . "tjolitzATgmailDOTcom")) (:maintainer "Thorsten Jolitz" . "tjolitzATgmailDOTcom"))]) (outline-minor-faces . [(20240831 2209) ((emacs (26 1)) (compat (30 0 0 0))) "Highlight only section headings" tar ((:url . "https://github.com/tarsius/outline-minor-faces") (:commit . "4628613f3570b865b2c22b750ebd41443c1848c2") (:revdesc . "4628613f3570") (:keywords "faces" "outlines") (:authors ("Jonas Bernoulli" . "emacs.outline-minor-faces@jonas.bernoulli.dev")) (:maintainers ("Jonas Bernoulli" . "emacs.outline-minor-faces@jonas.bernoulli.dev")) (:maintainer "Jonas Bernoulli" . "emacs.outline-minor-faces@jonas.bernoulli.dev"))]) (outline-toc . [(20200401 1208) nil "Sidebar showing a \"table of contents\"" tar ((:url . "https://github.com/abingham/outline-toc.el") (:commit . "81d373633b40628cc3a6b6fb534fd7730076bcdb") (:revdesc . "81d373633b40") (:keywords "convenience" "outlines") (:authors ("Austin Bingham" . "austin.bingham@gmail.com")) (:maintainers ("Austin Bingham" . "austin.bingham@gmail.com")) (:maintainer "Austin Bingham" . "austin.bingham@gmail.com"))]) @@ -4107,7 +4107,7 @@ (pacfiles-mode . [(20230503 1523) ((emacs (26 1))) "The pacnew and pacsave merging tool" tar ((:url . "https://github.com/UndeadKernel/pacfiles-mode") (:commit . "a613d1d88dba4cb293ecaf42a9aeff7d8a3ce8aa") (:revdesc . "a613d1d88dba") (:keywords "files" "pacman" "arch" "pacnew" "pacsave" "update" "linux") (:authors ("Carlos G. Cordero" . "http://github/UndeadKernel")) (:maintainers ("Carlos G. Cordero" . "pacfiles@binarycharly.com")) (:maintainer "Carlos G. Cordero" . "pacfiles@binarycharly.com"))]) (pack . [(20191017 456) ((emacs (24)) (cl-lib (0 5))) "Pack and unpack archive files" tar ((:url . "https://github.com/10sr/pack-el") (:commit . "85cd856fdc00a2365e88b50373b99f1b3d2227be") (:revdesc . "85cd856fdc00") (:keywords "files" "dired") (:authors ("10sr" . "8.slashes@gmail.com")) (:maintainers ("10sr" . "8.slashes@gmail.com")) (:maintainer "10sr" . "8.slashes@gmail.com"))]) (package+ . [(20230805 2115) ((emacs (24 3))) "Extensions for the package library" tar ((:url . "https://github.com/zenspider/package") (:commit . "57a53a1da75d76a9dcd17008d1c1d77475b9671a") (:revdesc . "57a53a1da75d") (:keywords "extensions" "tools") (:authors ("Ryan Davis" . "ryand-ruby@zenspider.com")) (:maintainers ("Ryan Davis" . "ryand-ruby@zenspider.com")) (:maintainer "Ryan Davis" . "ryand-ruby@zenspider.com"))]) - (package-build . [(20240930 1924) ((emacs (26 1)) (compat (30 0 0 0))) "Tools for assembling a package archive" tar ((:url . "https://github.com/melpa/package-build") (:commit . "af2dc7784df675cfca7b307e77ec2084ca5432f4") (:revdesc . "af2dc7784df6") (:keywords "maint" "tools") (:authors ("Donald Ephraim Curtis" . "dcurtis@milkbox.net") ("Steve Purcell" . "steve@sanityinc.com") ("Jonas Bernoulli" . "emacs.package-build@jonas.bernoulli.dev") ("Phil Hagelberg" . "technomancy@gmail.com")) (:maintainers ("Jonas Bernoulli" . "emacs.package-build@jonas.bernoulli.dev")) (:maintainer "Jonas Bernoulli" . "emacs.package-build@jonas.bernoulli.dev"))]) + (package-build . [(20241123 2136) ((emacs (26 1)) (compat (30 0 0 0))) "Tools for assembling a package archive" tar ((:url . "https://github.com/melpa/package-build") (:commit . "c1b276904278f0f89da2684f5e044760e3232c29") (:revdesc . "c1b276904278") (:keywords "maint" "tools") (:authors ("Donald Ephraim Curtis" . "dcurtis@milkbox.net") ("Steve Purcell" . "steve@sanityinc.com") ("Jonas Bernoulli" . "emacs.package-build@jonas.bernoulli.dev") ("Phil Hagelberg" . "technomancy@gmail.com")) (:maintainers ("Jonas Bernoulli" . "emacs.package-build@jonas.bernoulli.dev")) (:maintainer "Jonas Bernoulli" . "emacs.package-build@jonas.bernoulli.dev"))]) (package-filter . [(20161122 719) nil "Package archive whitelist and blacklist" tar ((:url . "https://github.com/milkypostman/package-filter") (:commit . "c8e2531227c02c4c5e9d593f2cdb6a4ab4a6849b") (:revdesc . "c8e2531227c0") (:authors ("Donald Ephraim Curtis" . "dcurtis@milkbox.net")) (:maintainers ("Donald Ephraim Curtis" . "dcurtis@milkbox.net")) (:maintainer "Donald Ephraim Curtis" . "dcurtis@milkbox.net"))]) (package-lint . [(20240923 1044) ((emacs (24 4)) (let-alist (1 0 6))) "A linting library for elisp package authors" tar ((:url . "https://github.com/purcell/package-lint") (:commit . "ae5491c511cb49ddb75d6dd4cd934bf71e47a2d5") (:revdesc . "ae5491c511cb") (:keywords "lisp") (:authors ("Steve Purcell" . "steve@sanityinc.com") ("Fanael Linithien" . "fanael4@gmail.com")) (:maintainers ("Steve Purcell" . "steve@sanityinc.com") ("Fanael Linithien" . "fanael4@gmail.com")) (:maintainer "Steve Purcell" . "steve@sanityinc.com"))]) (package-lint-flymake . [(20240923 931) ((emacs (26 1)) (package-lint (0 5))) "A package-lint Flymake backend" tar ((:url . "https://github.com/purcell/package-lint") (:commit . "e3d3fb254221d053c75edfd9f0ebfa58d1eb52f9") (:revdesc . "e3d3fb254221"))]) @@ -4407,7 +4407,7 @@ (prompt-text . [(20190408 310) nil "Configure your minibuffer prompt" tar ((:url . "https://github.com/10sr/prompt-text-el") (:commit . "b842bf13c53d0a2bd2bc7a00d37cc713d69fa9e9") (:revdesc . "b842bf13c53d") (:keywords "utility" "minibuffer") (:authors ("10sr" . "8slashes+el[at]gmail[dot]com")) (:maintainers ("10sr" . "8slashes+el[at]gmail[dot]com")) (:maintainer "10sr" . "8slashes+el[at]gmail[dot]com"))]) (prompts . [(20160916 1041) ((dash (2 13 0))) "Utilities for working with text prompts" tar ((:url . "https://github.com/GuiltyDolphin/prompts.el") (:commit . "1cd5e732ff2a86b47836eb7252e5b59cd4b6ab26") (:revdesc . "1cd5e732ff2a") (:keywords "input" "minibuffer") (:authors ("Ben Moon" . "guiltydolphin@gmail.com")) (:maintainers ("Ben Moon" . "guiltydolphin@gmail.com")) (:maintainer "Ben Moon" . "guiltydolphin@gmail.com"))]) (pronto . [(20200218 1633) ((emacs (24))) "Compilation mode for pronto stylechecks" tar ((:url . "https://github.com/julianrubisch/pronto.el") (:commit . "c0cd13d8219879610b7fe284b182a9db4d3d40b3") (:revdesc . "c0cd13d82198") (:keywords "processes" "tools") (:authors ("Julian Rubisch" . "julian@julianrubisch.at")) (:maintainers ("Julian Rubisch" . "julian@julianrubisch.at")) (:maintainer "Julian Rubisch" . "julian@julianrubisch.at"))]) - (proof-general . [(20240912 1558) ((emacs (25 2))) "A generic Emacs interface for proof assistants" tar ((:url . "https://github.com/ProofGeneral/PG") (:commit . "1ffca70b2fcfd1c524f9b9e5ceebae07d3b745b6") (:revdesc . "1ffca70b2fcf") (:maintainers (nil . "proof-general-maintainers@groupes.renater.fr")) (:maintainer nil . "proof-general-maintainers@groupes.renater.fr"))]) + (proof-general . [(20241121 1756) ((emacs (25 2))) "A generic Emacs interface for proof assistants" tar ((:url . "https://github.com/ProofGeneral/PG") (:commit . "8401163e42a2a92894c987005498da0f84a03773") (:revdesc . "8401163e42a2") (:maintainers (nil . "proof-general-maintainers@groupes.renater.fr")) (:maintainer nil . "proof-general-maintainers@groupes.renater.fr"))]) (prop-menu . [(20150728 1118) ((emacs (24 3)) (cl-lib (0 5))) "Create and display a context menu based on text and overlay properties" tar ((:url . "https://github.com/david-christiansen/prop-menu-el") (:commit . "50b102c1c0935fd3e0c465feed7f27d66b21cdf3") (:revdesc . "50b102c1c093") (:keywords "convenience") (:authors ("David Christiansen" . "david@davidchristiansen.dk")) (:maintainers ("David Christiansen" . "david@davidchristiansen.dk")) (:maintainer "David Christiansen" . "david@davidchristiansen.dk"))]) (propfont-mixed . [(20150113 2211) ((emacs (24)) (cl-lib (0 5))) "Use proportional fonts with space-based indentation" tar ((:url . "https://github.com/ikirill/propfont-mixed") (:commit . "0b461ef4754a469610dba71874a34b6da42176bf") (:revdesc . "0b461ef4754a") (:keywords "faces") (:authors ("Kirill Ignatiev" . "github.com/ikirill")) (:maintainers ("Kirill Ignatiev" . "github.com/ikirill")) (:maintainer "Kirill Ignatiev" . "github.com/ikirill"))]) (proportional . [(20221205 1417) ((emacs (25 1))) "Use a proportional font everywhere" tar ((:url . "https://github.com/ksjogo/proportional") (:commit . "6b675694292a5dbebb52b6196e8ccee6e3a73042") (:revdesc . "6b675694292a") (:keywords "faces"))]) @@ -4516,7 +4516,7 @@ (qwen-chat-shell . [(20240612 343) ((emacs (27 1)) (shell-maker (0 50 1))) "Qwen-chat shell + buffer insert commands" tar ((:url . "https://github.com/Pavinberg/qwen-chat-shell") (:commit . "2d6562c8a75aebf7a59e554011571ba5883cf4fd") (:revdesc . "2d6562c8a75a") (:authors ("Pavinberg" . "pavin0702@gmail.com")) (:maintainers ("Pavinberg" . "pavin0702@gmail.com")) (:maintainer "Pavinberg" . "pavin0702@gmail.com"))]) (r-autoyas . [(20140101 1510) ((ess (0)) (yasnippet (0 8 0))) "Provides automatically created yasnippets for R function argument lists" tar ((:url . "https://github.com/mattfidler/r-autoyas.el") (:commit . "d321a7da0ef2e94668d53e0807277da7b70ea678") (:revdesc . "d321a7da0ef2") (:keywords "r" "yasnippet"))]) (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" tar ((:url . "https://github.com/racer-rust/emacs-racer") (:commit . "1e63e98626737ea9b662d4a9b1ffd6842b1c648c") (:revdesc . "1e63e9862673") (:keywords "abbrev" "convenience" "matching" "rust" "tools"))]) - (racket-mode . [(20241116 1700) ((emacs (25 1))) "Racket editing, REPL, and more" tar ((:url . "https://github.com/greghendershott/racket-mode") (:commit . "c5bee6895b2d028820a75356abacc19a5ed11918") (:revdesc . "c5bee6895b2d") (:authors ("Greg Hendershott" . "racket-mode-author@greghendershott.com")))]) + (racket-mode . [(20241121 2018) ((emacs (25 1))) "Racket editing, REPL, and more" tar ((:url . "https://github.com/greghendershott/racket-mode") (:commit . "09f5019321f3fc59ee013841a06696be313aecf0") (:revdesc . "09f5019321f3") (:authors ("Greg Hendershott" . "racket-mode-author@greghendershott.com")))]) (rails-i18n . [(20220126 1643) ((emacs (27 2)) (yaml (0 1 0)) (dash (2 19 1))) "Seach and insert i18n on ruby code" tar ((:url . "https://github.com/otavioschwanck/rails-i18n.el") (:commit . "8e87e4e48e31902b8259ded28a208c2e7efea6e9") (:revdesc . "8e87e4e48e31") (:keywords "tools" "languages") (:authors ("Otávio Schwanck dos Santos" . "otavioschwanck@gmail.com")) (:maintainers ("Otávio Schwanck dos Santos" . "otavioschwanck@gmail.com")) (:maintainer "Otávio Schwanck dos Santos" . "otavioschwanck@gmail.com"))]) (rails-log-mode . [(20140408 425) nil "Major mode for viewing Rails log files" tar ((:url . "https://github.com/ananthakumaran/rails-log-mode") (:commit . "ff440003ad7d47cb0ac3300f2a632f4cfd36a446") (:revdesc . "ff440003ad7d") (:keywords "rails" "log") (:authors ("Anantha kumaran" . "ananthakumaran@gmail.com")) (:maintainers ("Anantha kumaran" . "ananthakumaran@gmail.com")) (:maintainer "Anantha kumaran" . "ananthakumaran@gmail.com"))]) (rails-routes . [(20220126 1631) ((emacs (27 2)) (inflections (1 1))) "Search for and insert rails routes" tar ((:url . "https://github.com/otavioschwanck/rails-routes.el") (:commit . "eab995a9297ca5bd9bd4f4c2737f2fecfc36def0") (:revdesc . "eab995a9297c") (:keywords "tools" "languages") (:authors ("Otávio Schwanck" . "otavioschwanck@gmail.com")) (:maintainers ("Otávio Schwanck" . "otavioschwanck@gmail.com")) (:maintainer "Otávio Schwanck" . "otavioschwanck@gmail.com"))]) @@ -4827,7 +4827,7 @@ (shell-current-directory . [(20140101 2354) nil "Create new shell based on buffer directory" tar ((:url . "https://github.com/metaperl/shell-current-directory") (:commit . "bf843771bf9a4aa05e054ade799eb8862f3be89a") (:revdesc . "bf843771bf9a") (:keywords "shell" "comint"))]) (shell-here . [(20220102 1703) nil "Open a shell relative to the working directory" tar ((:url . "https://codeberg.org/emacs-weirdware/shell-here") (:commit . "eeb437ff26d62a5009046b1b3b4503b768e3131a") (:revdesc . "eeb437ff26d6") (:keywords "unix" "tools" "processes") (:authors ("Ian Eure" . "ian.eure@gmail.com")) (:maintainers ("Ian Eure" . "ian.eure@gmail.com")) (:maintainer "Ian Eure" . "ian.eure@gmail.com"))]) (shell-history . [(20100505 839) nil "Integration with shell history" tar ((:url . "https://github.com/emacsorphanage/shell-history") (:commit . "ee371a81f2d2bf5a308344078329ca1e9b5ed38c") (:revdesc . "ee371a81f2d2") (:keywords "processes" "convenience") (:authors ("rubikitch" . "rubikitch@ruby-lang.org")) (:maintainers ("rubikitch" . "rubikitch@ruby-lang.org")) (:maintainer "rubikitch" . "rubikitch@ruby-lang.org"))]) - (shell-maker . [(20241119 1109) ((emacs (27 1))) "Interaction mode for making comint shells" tar ((:url . "https://github.com/xenodium/shell-maker") (:commit . "d90ec9ad3f83d381de65159043318f3381bb3a36") (:revdesc . "d90ec9ad3f83"))]) + (shell-maker . [(20241123 1808) ((emacs (27 1))) "Interaction mode for making comint shells" tar ((:url . "https://github.com/xenodium/shell-maker") (:commit . "82db4dbedfd8196d487bb18be186204b9b840a85") (:revdesc . "82db4dbedfd8"))]) (shell-pop . [(20231228 612) ((emacs (24 1)) (cl-lib (0 5))) "Helps you to use shell easily on Emacs. Only one key action to work" tar ((:url . "https://github.com/kyagi/shell-pop-el") (:commit . "ff3dc705ee1c7bc566b35c17e4635c57061fe3ae") (:revdesc . "ff3dc705ee1c") (:keywords "shell" "terminal" "tools") (:authors ("Kazuo YAGI" . "kazuo.yagi@gmail.com")) (:maintainers ("Kazuo YAGI" . "kazuo.yagi@gmail.com")) (:maintainer "Kazuo YAGI" . "kazuo.yagi@gmail.com"))]) (shell-split-string . [(20151224 1008) nil "Split strings using shell-like syntax" tar ((:url . "https://github.com/10sr/shell-split-string-el") (:commit . "19f6f999c33cc66a4c91bacdcc3697c25d97bf5a") (:revdesc . "19f6f999c33c") (:keywords "utility" "library" "shell" "string") (:authors ("10sr" . "8.slashes+el[at]gmail[dot]com")) (:maintainers ("10sr" . "8.slashes+el[at]gmail[dot]com")) (:maintainer "10sr" . "8.slashes+el[at]gmail[dot]com"))]) (shell-switcher . [(20210509 1045) ((emacs (24))) "Provide fast switching between shell buffers" tar ((:url . "https://github.com/DamienCassou/shell-switcher") (:commit . "ed74b20fa12935be0068765f5bc8de97b92a8020") (:revdesc . "ed74b20fa129") (:keywords "emacs" "package" "elisp" "shell" "eshell" "term" "switcher") (:authors ("Damien Cassou" . "damien.cassou@gmail.com")) (:maintainers ("Damien Cassou" . "damien.cassou@gmail.com")) (:maintainer "Damien Cassou" . "damien.cassou@gmail.com"))]) @@ -4862,7 +4862,7 @@ (side-hustle . [(20240625 1228) ((emacs (24 4)) (seq (2 20))) "Hustle through Imenu in a side window" tar ((:url . "https://github.com/rnkn/side-hustle") (:commit . "94450b58cec1b809afe08d0754a6662839efbc9d") (:revdesc . "94450b58cec1") (:keywords "convenience") (:authors ("Paul W. Rankin" . "rnkn@rnkn.xyz")) (:maintainers ("Paul W. Rankin" . "rnkn@rnkn.xyz")) (:maintainer "Paul W. Rankin" . "rnkn@rnkn.xyz"))]) (side-notes . [(20240629 1008) ((emacs (24 4))) "Easy access to a directory notes file" tar ((:url . "https://github.com/rnkn/side-notes") (:commit . "96a142dfd5768d66b1d574027e13c572e4c82a87") (:revdesc . "96a142dfd576") (:keywords "convenience") (:authors ("Paul W. Rankin" . "rnkn@rnkn.xyz")) (:maintainers ("Paul W. Rankin" . "rnkn@rnkn.xyz")) (:maintainer "Paul W. Rankin" . "rnkn@rnkn.xyz"))]) (sidecar-locals . [(20240421 655) ((emacs (27 1))) "A flexible alternative to built-in dir-locals" tar ((:url . "https://codeberg.org/ideasman42/emacs-sidecar-locals") (:commit . "3daf8c07fac7c4ada7a02a1edad2f64894463614") (:revdesc . "3daf8c07fac7") (:keywords "convenience") (:authors ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainers ("Campbell Barton" . "ideasman42@gmail.com")) (:maintainer "Campbell Barton" . "ideasman42@gmail.com"))]) - (sideline . [(20241117 1845) ((emacs (27 1)) (ht (2 4))) "Show information on the side" tar ((:url . "https://github.com/emacs-sideline/sideline") (:commit . "56d4a8558870546516523bf08d35a6859f632855") (:revdesc . "56d4a8558870") (:keywords "convenience") (:authors ("Jen-Chieh" . "jcs090218@gmail.com")) (:maintainers ("Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Jen-Chieh" . "jcs090218@gmail.com"))]) + (sideline . [(20241123 311) ((emacs (27 1)) (ht (2 4))) "Show information on the side" tar ((:url . "https://github.com/emacs-sideline/sideline") (:commit . "b329d097a37585cd21c3b9a5862e0bb2a2f76442") (:revdesc . "b329d097a375") (:keywords "convenience") (:authors ("Jen-Chieh" . "jcs090218@gmail.com")) (:maintainers ("Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Jen-Chieh" . "jcs090218@gmail.com"))]) (sideline-blame . [(20240906 1906) ((emacs (27 1)) (sideline (0 1 0)) (vc-msg (1 1 1))) "Show blame messages with sideline" tar ((:url . "https://github.com/emacs-sideline/sideline-blame") (:commit . "48288bc77a90b58c7609598d0a129ba1638d0098") (:revdesc . "48288bc77a90") (:keywords "convenience" "blame") (:authors ("Jen-Chieh" . "jcs090218@gmail.com")) (:maintainers ("Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Jen-Chieh" . "jcs090218@gmail.com"))]) (sideline-flycheck . [(20240629 840) ((emacs (27 1)) (sideline (0 1 1)) (flycheck (0 14)) (ht (2 4))) "Show flycheck errors with sideline" tar ((:url . "https://github.com/emacs-sideline/sideline-flycheck") (:commit . "4147f2754c353e0b7920caf385b8dccc5e6301f7") (:revdesc . "4147f2754c35") (:keywords "convenience" "flycheck") (:authors ("Jen-Chieh" . "jcs090218@gmail.com")) (:maintainers ("Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Jen-Chieh" . "jcs090218@gmail.com"))]) (sideline-flymake . [(20240509 742) ((emacs (27 1)) (sideline (0 1 0))) "Show flymake errors with sideline" tar ((:url . "https://github.com/emacs-sideline/sideline-flymake") (:commit . "06e84875022a5645ece8f4c2c8b56aa5f003c65d") (:revdesc . "06e84875022a") (:keywords "convenience" "flymake") (:authors ("Jen-Chieh" . "jcs090218@gmail.com")) (:maintainers ("Jen-Chieh" . "jcs090218@gmail.com")) (:maintainer "Jen-Chieh" . "jcs090218@gmail.com"))]) @@ -4899,10 +4899,10 @@ (skewer-reload-stylesheets . [(20160725 1220) ((skewer-mode (1 5 3))) "Live-edit CSS, SCSS, Less, and friends" tar ((:url . "https://github.com/NateEag/skewer-reload-stylesheets") (:commit . "3207abca9551660407a6b009cb40fb32bbb550da") (:revdesc . "3207abca9551") (:authors ("Nate Eagleson" . "nate@nateeag.com")) (:maintainers ("Nate Eagleson" . "nate@nateeag.com")) (:maintainer "Nate Eagleson" . "nate@nateeag.com"))]) (skype . [(20160711 824) nil "Skype UI for emacs users." tar ((:url . "https://github.com/kiwanami/emacs-skype") (:commit . "8e3b33e620ed355522aa36434ff41e3ced080629") (:revdesc . "8e3b33e620ed") (:keywords "skype" "chat") (:authors ("SAKURAI Masashi" . "m.sakurai@kiwanami.net")) (:maintainers ("SAKURAI Masashi" . "m.sakurai@kiwanami.net")) (:maintainer "SAKURAI Masashi" . "m.sakurai@kiwanami.net"))]) (sl . [(20161217 1404) ((cl-lib (0 5))) "An Emacs clone of sl(1)" tar ((:url . "https://github.com/xuchunyang/sl.el") (:commit . "0882117728be91276b815e18c2a66106bf9d69d3") (:revdesc . "0882117728be") (:authors ("Chunyang Xu" . "mail@xuchunyang.me")) (:maintainers ("Chunyang Xu" . "mail@xuchunyang.me")) (:maintainer "Chunyang Xu" . "mail@xuchunyang.me"))]) - (slack . [(20241119 2336) ((websocket (1 8)) (request (0 2 0)) (oauth2 (0 10)) (circe (2 2)) (alert (1 2)) (emojify (0 2)) (emacs (25 1)) (dash (2 19 1)) (s (1 13 1))) "Slack client for Emacs" tar ((:url . "https://github.com/emacs-slack/emacs-slack") (:commit . "113cb87e0a0a3daeae4f1c587fe7c1a0b66cdb61") (:revdesc . "113cb87e0a0a") (:keywords "tools") (:authors ("yuya.minami" . "yuya.minami@yuyaminami-no-MacBook-Pro.local")) (:maintainers ("yuya.minami" . "yuya.minami@yuyaminami-no-MacBook-Pro.local")) (:maintainer "yuya.minami" . "yuya.minami@yuyaminami-no-MacBook-Pro.local"))]) + (slack . [(20241123 1653) ((websocket (1 8)) (request (0 2 0)) (oauth2 (0 10)) (circe (2 2)) (alert (1 2)) (emojify (0 2)) (emacs (25 1)) (dash (2 19 1)) (s (1 13 1)) (ts (0 3))) "Slack client for Emacs" tar ((:url . "https://github.com/emacs-slack/emacs-slack") (:commit . "603e26caf0ae2cfec0c64bd8861060ee1871ebe9") (:revdesc . "603e26caf0ae") (:keywords "tools") (:authors ("yuya.minami" . "yuya.minami@yuyaminami-no-MacBook-Pro.local")) (:maintainers ("yuya.minami" . "yuya.minami@yuyaminami-no-MacBook-Pro.local")) (:maintainer "yuya.minami" . "yuya.minami@yuyaminami-no-MacBook-Pro.local"))]) (slideview . [(20150324 2240) ((cl-lib (0 3))) "File slideshow" tar ((:url . "https://github.com/mhayashi1120/Emacs-slideview") (:commit . "b6d170bda139aedf81b47dc55cbd1a3af512fb4c") (:revdesc . "b6d170bda139") (:keywords "files") (:authors ("Masahiro Hayashi" . "mhayashi1120@gmail.com")) (:maintainers ("Masahiro Hayashi" . "mhayashi1120@gmail.com")) (:maintainer "Masahiro Hayashi" . "mhayashi1120@gmail.com"))]) (slim-mode . [(20240513 2118) nil "Major mode for editing Slim files" tar ((:url . "https://github.com/slim-template/emacs-slim") (:commit . "8c92169817f2fa59255f547f0a9fb4fbb8309db9") (:revdesc . "8c92169817f2") (:keywords "markup" "language"))]) - (slime . [(20241118 1544) ((emacs (24 3)) (macrostep (0 9))) "Superior Lisp Interaction Mode for Emacs" tar ((:url . "https://github.com/slime/slime") (:commit . "929753a0dfb04832e3e358e5c83a90086111aedf") (:revdesc . "929753a0dfb0") (:keywords "languages" "lisp" "slime"))]) + (slime . [(20241121 1734) ((emacs (24 3)) (macrostep (0 9))) "Superior Lisp Interaction Mode for Emacs" tar ((:url . "https://github.com/slime/slime") (:commit . "9be8de1faac578407cbaebf4e17ecfb30867673e") (:revdesc . "9be8de1faac5") (:keywords "languages" "lisp" "slime"))]) (slime-company . [(20210124 1627) ((emacs (24 4)) (slime (2 13)) (company (0 9 0))) "Slime completion backend for company mode" tar ((:url . "https://github.com/anwyn/slime-company") (:commit . "f20ecc4104d4c35052696e7e760109fb02060e72") (:revdesc . "f20ecc4104d4") (:keywords "convenience" "lisp" "abbrev") (:authors ("Ole Arndt" . "anwyn@sugarshark.com")) (:maintainers ("Ole Arndt" . "anwyn@sugarshark.com")) (:maintainer "Ole Arndt" . "anwyn@sugarshark.com"))]) (slime-docker . [(20210426 1422) ((emacs (24 4)) (slime (2 16)) (docker-tramp (0 1))) "Integration of SLIME with Docker containers" tar ((:url . "https://github.com/cl-docker-images/slime-docker") (:commit . "c7d073720f2bd8e9f72a20309fff2afa4c4e798d") (:revdesc . "c7d073720f2b") (:keywords "docker" "lisp" "slime"))]) (slime-repl-ansi-color . [(20230214 1453) ((emacs (24)) (slime (2 3 1))) "Turn on ANSI colors in REPL output;" tar ((:url . "https://gitlab.com/augfab/slime-repl-ansi-color") (:commit . "9e8af90490332217e45d7568f1690df3f4e25d4b") (:revdesc . "9e8af9049033") (:keywords "lisp") (:authors ("Max Mikhanosha" . "max@openchat.com")) (:maintainers ("Augustin Fabre" . "augustin@augfab.fr")) (:maintainer "Augustin Fabre" . "augustin@augfab.fr"))]) @@ -5054,7 +5054,7 @@ (sr-speedbar . [(20220705 1231) nil "Same frame speedbar" tar ((:url . "https://github.com/emacsorphanage/sr-speedbar") (:commit . "73ecfc21cf38f0cb1dfbbebebdc3cf573eccf7d2") (:revdesc . "73ecfc21cf38") (:keywords "speedbar" "sr-speedbar.el") (:authors ("Sebastian Rose" . "sebastian_rose@gmx.de")) (:maintainers ("Sebastian Rose" . "sebastian_rose@gmx.de") ("Peter Lunicks" . "plunix@users.sourceforge.net")) (:maintainer "Sebastian Rose" . "sebastian_rose@gmx.de"))]) (srcery-theme . [(20240220 805) ((emacs (24))) "Dark color theme" tar ((:url . "https://github.com/srcery-colors/srcery-emacs") (:commit . "60028633c5722e6b8ea12844618be0e9b31be55a") (:revdesc . "60028633c572") (:keywords "faces"))]) (srefactor . [(20230504 617) ((emacs (24 4))) "A refactoring tool based on Semantic parser framework" tar ((:url . "https://github.com/tuhdo/semantic-refactor") (:commit . "95c70a94b5aad4c85b35569e2f2325047791153a") (:revdesc . "95c70a94b5aa") (:keywords "c" "languages" "tools") (:authors ("Do Hoang" . "tuhdo1710@gmail.com")))]) - (srfi . [(20241115 2307) ((emacs (25 1))) "Scheme Requests for Implementation browser" tar ((:url . "https://github.com/srfi-explorations/emacs-srfi") (:commit . "72d09e6c34f0809536a668ca7031ead6ba082ded") (:revdesc . "72d09e6c34f0") (:keywords "languages" "util") (:authors ("Lassi Kortela" . "lassi@lassi.io")) (:maintainers ("Lassi Kortela" . "lassi@lassi.io")) (:maintainer "Lassi Kortela" . "lassi@lassi.io"))]) + (srfi . [(20241121 1857) ((emacs (25 1))) "Scheme Requests for Implementation browser" tar ((:url . "https://github.com/srfi-explorations/emacs-srfi") (:commit . "e9f6edb09d9cce461249ad54505911d71ca81a45") (:revdesc . "e9f6edb09d9c") (:keywords "languages" "util") (:authors ("Lassi Kortela" . "lassi@lassi.io")) (:maintainers ("Lassi Kortela" . "lassi@lassi.io")) (:maintainer "Lassi Kortela" . "lassi@lassi.io"))]) (srv . [(20180715 1959) ((emacs (24 3))) "Perform SRV DNS requests" tar ((:url . "https://github.com/legoscia/srv.el") (:commit . "714387d5a5cf34d8d8cd96bdb1f9cb8ded823ff7") (:revdesc . "714387d5a5cf") (:keywords "comm") (:authors ("Magnus Henoch" . "magnus.henoch@gmail.com")) (:maintainers ("Magnus Henoch" . "magnus.henoch@gmail.com")) (:maintainer "Magnus Henoch" . "magnus.henoch@gmail.com"))]) (ssass-mode . [(20200211 132) ((emacs (24 3))) "Edit Sass without a Turing Machine" tar ((:url . "https://github.com/AdamNiederer/ssass-mode") (:commit . "96f557887ad97a0066a60c54f92b7234b8407016") (:revdesc . "96f557887ad9") (:keywords "languages" "sass") (:authors ("Adam Niederer" . "adam.niederer@gmail.com")) (:maintainers ("Adam Niederer" . "adam.niederer@gmail.com")) (:maintainer "Adam Niederer" . "adam.niederer@gmail.com"))]) (ssh . [(20120904 2042) nil "Support for remote logins using ssh" tar ((:url . "https://codeberg.org/emacs-weirdware-abandoned/ssh") (:commit . "c17cf5b43df8ac4662a0580f85898e1f078df0d1") (:revdesc . "c17cf5b43df8") (:keywords "unix" "comm") (:authors ("Noah Friedman" . "friedman@splode.com")) (:maintainers ("Ian Eure" . "ian.eure@gmail.com")) (:maintainer "Ian Eure" . "ian.eure@gmail.com"))]) @@ -5154,7 +5154,7 @@ (symon . [(20170224 833) nil "Tiny graphical system monitor" tar ((:url . "https://github.com/zk-phi/symon") (:commit . "76461679dfe13a5dccd3c8735fb6f58b26b46733") (:revdesc . "76461679dfe1"))]) (symon-lingr . [(20150719 1342) ((symon (1 1 2)) (cl-lib (0 5))) "A notification-based Lingr client powered by symon.el" tar ((:url . "https://github.com/zk-phi/symon-lingr") (:commit . "056d1a473e36992ff5881e5ce6fdc331cead975f") (:revdesc . "056d1a473e36"))]) (sync-recentf . [(20160326 2001) nil "Synchronize the recent files list between Emacs instances" tar ((:url . "https://github.com/ffevotte/sync-recentf") (:commit . "0052561d5c5b5c2684faedc3eead776aec06c3ed") (:revdesc . "0052561d5c5b") (:keywords "recentf") (:authors ("François Févotte" . "fevotte@gmail.com")) (:maintainers ("François Févotte" . "fevotte@gmail.com")) (:maintainer "François Févotte" . "fevotte@gmail.com"))]) - (syncthing . [(20240101 2334) ((emacs (27 1))) "Client for Syncthing" tar ((:url . "https://github.com/KeyWeeUsr/emacs-syncthing") (:commit . "9f44d45a55b460b7eaeb9fb15d17d94e790705e0") (:revdesc . "9f44d45a55b4") (:keywords "convenience" "syncthing" "sync" "client" "view") (:authors ("Peter Badida" . "keyweeusr@gmail.com")) (:maintainers ("Peter Badida" . "keyweeusr@gmail.com")) (:maintainer "Peter Badida" . "keyweeusr@gmail.com"))]) + (syncthing . [(20241121 2359) ((emacs (27 1))) "Client for Syncthing" tar ((:url . "https://github.com/KeyWeeUsr/emacs-syncthing") (:commit . "725b2dac739c6dd03db0a03f49f3c1cbf9b336bd") (:revdesc . "725b2dac739c") (:keywords "convenience" "syncthing" "sync" "client" "view") (:authors ("Peter Badida" . "keyweeusr@gmail.com")) (:maintainers ("Peter Badida" . "keyweeusr@gmail.com")) (:maintainer "Peter Badida" . "keyweeusr@gmail.com"))]) (synonymous . [(20180325 1817) ((emacs (24)) (cl-lib (0 5)) (request (0 2 0))) "A thesaurus at your fingertips" tar ((:url . "https://github.com/toroidal-code/synonymous.el") (:commit . "2cb9a674d84fddf3f1b00c9d6b13a853576acb87") (:revdesc . "2cb9a674d84f") (:keywords "utility") (:authors ("Katherine Whitlock" . "toroidalcode@gmail.com") ("authored by Manuel Serrano" . "Manuel.Serrano@inria.fr")) (:maintainers ("Katherine Whitlock" . "toroidalcode@gmail.com") ("authored by Manuel Serrano" . "Manuel.Serrano@inria.fr")) (:maintainer "Katherine Whitlock" . "toroidalcode@gmail.com"))]) (synosaurus . [(20191125 552) ((cl-lib (0 5))) "An extensible thesaurus supporting lookup and substitution" tar ((:url . "https://github.com/hpdeifel/synosaurus") (:commit . "14d34fc92a77c3a916b4d58400424c44ae99cd81") (:revdesc . "14d34fc92a77") (:keywords "wp") (:authors ("Hans-Peter Deifel" . "hpd@hpdeifel.de")) (:maintainers ("Hans-Peter Deifel" . "hpd@hpdeifel.de")) (:maintainer "Hans-Peter Deifel" . "hpd@hpdeifel.de"))]) (synquid . [(20160930 1550) ((flycheck (27)) (emacs (24 3))) "Major mode for editing Synquid files" tar ((:url . "https://github.com/cpitclaudel/synquid-emacs") (:commit . "28701ce1a15437202f53ab93a14bcba1de83fd2c") (:revdesc . "28701ce1a154") (:keywords "languages") (:authors ("Clément Pit-Claudel" . "clement.pitclaudel@live.com")) (:maintainers ("Clément Pit-Claudel" . "clement.pitclaudel@live.com")) (:maintainer "Clément Pit-Claudel" . "clement.pitclaudel@live.com"))]) @@ -5180,8 +5180,8 @@ (tabby-mode . [(20240107 2124) ((emacs (25 1))) "Minor mode for the Tabby AI coding assistant" tar ((:url . "https://github.com/ragnard/tabby-mode") (:commit . "b656727247c5fc78690827fecf232edc1945a331") (:revdesc . "b656727247c5") (:keywords "tools" "convenience") (:authors ("Ragnar Dahlén" . "r.dahlen@gmail.com")) (:maintainers ("Ragnar Dahlén" . "r.dahlen@gmail.com")) (:maintainer "Ragnar Dahlén" . "r.dahlen@gmail.com"))]) (tabgo . [(20240204 1326) ((emacs (27 1))) "Jump to tabs, avy style" tar ((:url . "https://github.com/isamert/tabgo.el") (:commit . "83b7d3261e9a6aaffd8e97bc047b77a6131789ee") (:revdesc . "83b7d3261e9a") (:authors ("Isa Mert Gurbuz" . "isamertgurbuz@gmail.com")) (:maintainers ("Isa Mert Gurbuz" . "isamertgurbuz@gmail.com")) (:maintainer "Isa Mert Gurbuz" . "isamertgurbuz@gmail.com"))]) (tablist . [(20231019 1126) ((emacs (24 3))) "Extended tabulated-list-mode" tar ((:url . "https://github.com/emacsorphanage/tablist") (:commit . "fcd37147121fabdf003a70279cf86fbe08cfac6f") (:revdesc . "fcd37147121f") (:keywords "extensions" "lisp") (:authors ("Andreas Politz" . "politza@fh-trier.de")) (:maintainers ("Andreas Politz" . "politza@fh-trier.de")) (:maintainer "Andreas Politz" . "politza@fh-trier.de"))]) - (tabnine . [(20241112 1629) ((emacs (27 1)) (dash (2 16 0)) (s (1 12 0)) (editorconfig (0 9 1)) (language-id (0 5 1)) (transient (0 4 0))) "An unofficial TabNine package with TabNine Chat supported" tar ((:url . "https://github.com/shuxiao9058/tabnine") (:commit . "f410e1820151957926fcd44ecaf8a34307d04465") (:revdesc . "f410e1820151") (:keywords "convenience") (:authors ("Aaron Ji" . "shuxiao9058@gmail.com") ("Tommy Xiang" . "tommyx058@gmail.com") ("John Gong" . "gjtzone@hotmail.com")) (:maintainers ("Aaron Ji" . "shuxiao9058@gmail.com") ("Tommy Xiang" . "tommyx058@gmail.com") ("John Gong" . "gjtzone@hotmail.com")) (:maintainer "Aaron Ji" . "shuxiao9058@gmail.com"))]) - (tabspaces . [(20240924 1414) ((emacs (27 1)) (project (0 8 1))) "Leverage tab-bar and project for buffer-isolated workspaces" tar ((:url . "https://github.com/mclear-tools/tabspaces") (:commit . "49bd9508bade2962f72f4fab9ffc12ef31c271f7") (:revdesc . "49bd9508bade") (:keywords "convenience" "frames") (:authors ("Colin McLear" . "mclear@fastmail.com")))]) + (tabnine . [(20241123 715) ((emacs (27 1)) (dash (2 16 0)) (s (1 12 0)) (editorconfig (0 9 1)) (language-id (0 5 1)) (transient (0 4 0))) "An unofficial TabNine package with TabNine Chat supported" tar ((:url . "https://github.com/shuxiao9058/tabnine") (:commit . "1f7e417eb18e097c0c08c9d151f40f476aa64608") (:revdesc . "1f7e417eb18e") (:keywords "convenience") (:authors ("Aaron Ji" . "shuxiao9058@gmail.com") ("Tommy Xiang" . "tommyx058@gmail.com") ("John Gong" . "gjtzone@hotmail.com")) (:maintainers ("Aaron Ji" . "shuxiao9058@gmail.com") ("Tommy Xiang" . "tommyx058@gmail.com") ("John Gong" . "gjtzone@hotmail.com")) (:maintainer "Aaron Ji" . "shuxiao9058@gmail.com"))]) + (tabspaces . [(20241123 1957) ((emacs (27 1)) (project (0 8 1))) "Leverage tab-bar and project for buffer-isolated workspaces" tar ((:url . "https://github.com/mclear-tools/tabspaces") (:commit . "4fd52c33f4a215360e2b2e1b237115a217ae9bbe") (:revdesc . "4fd52c33f4a2") (:keywords "convenience" "frames") (:authors ("Colin McLear" . "mclear@fastmail.com")))]) (tabula-rasa . [(20141216 547) ((emacs (24 4))) "Distraction free writing mode" tar ((:url . "https://github.com/dppdppd/Tabula-Rasa") (:commit . "e85fff9de18dc31bc6a7aca726e34a95cc5459f5") (:revdesc . "e85fff9de18d") (:keywords "distraction free" "writing") (:authors ("Ido Magal" . "misc@satans.church")) (:maintainers ("Ido Magal" . "misc@satans.church")) (:maintainer "Ido Magal" . "misc@satans.church"))]) (tagedit . [(20161121 855) ((s (1 3 1)) (dash (1 0 3))) "Some paredit-like features for html-mode" tar ((:url . "https://github.com/magnars/tagedit") (:commit . "b3a70101a0dcf85498c92b7fcfa7fdbac869746c") (:revdesc . "b3a70101a0dc") (:keywords "convenience") (:authors ("Magnar Sveen" . "magnars@gmail.com")) (:maintainers ("Magnar Sveen" . "magnars@gmail.com")) (:maintainer "Magnar Sveen" . "magnars@gmail.com"))]) (take-off . [(20140531 917) ((emacs (24 3)) (web-server (0 1 0))) "Emacs remote web access" tar ((:url . "https://github.com/tburette/take-off") (:commit . "aa9ea45566fc74febbb6ee9c409ecc4b59246215") (:revdesc . "aa9ea45566fc") (:authors ("Thomas Burette" . "burettethomas@gmail.com")) (:maintainers ("Thomas Burette" . "burettethomas@gmail.com")) (:maintainer "Thomas Burette" . "burettethomas@gmail.com"))]) @@ -5333,7 +5333,7 @@ (tramp-term . [(20220725 1441) nil "Automatic setup of directory tracking in ssh sessions" tar ((:url . "https://github.com/cuspymd/tramp-term.el") (:commit . "ed75189122737d301f716a30a8013205aa3736f1") (:revdesc . "ed7518912273") (:keywords "comm" "terminals") (:authors ("Randy Morris" . "randy.morris@archlinux.us")) (:maintainers ("Randy Morris" . "randy.morris@archlinux.us")) (:maintainer "Randy Morris" . "randy.morris@archlinux.us"))]) (transducers . [(20241103 35) ((emacs (28 1))) "Ergonomic, efficient data processing" tar ((:url . "https://github.com/fosskers/transducers.el") (:commit . "f8f46db6ddba6641669160fffb3f98213ab5b213") (:revdesc . "f8f46db6ddba") (:keywords "lisp") (:authors ("Colin Woodbury" . "colin@fosskers.ca")) (:maintainers ("Colin Woodbury" . "colin@fosskers.ca")) (:maintainer "Colin Woodbury" . "colin@fosskers.ca"))]) (transfer-sh . [(20200601 1708) ((emacs (24 3)) (async (1 0))) "Simple interface for sending buffer contents to transfer.sh" tar ((:url . "https://gitlab.com/tuedachu/transfer-sh.el") (:commit . "0621a66d00ec91a209a542c10b158095088bd44d") (:revdesc . "0621a66d00ec") (:keywords "comm" "convenience" "files"))]) - (transient . [(20241115 2034) ((emacs (26 1)) (compat (30 0 0 0)) (seq (2 24))) "Transient commands" tar ((:url . "https://github.com/magit/transient") (:commit . "291b86e66de3d7b73384f8751050acbdd2187ddb") (:revdesc . "291b86e66de3") (:keywords "extensions") (:authors ("Jonas Bernoulli" . "emacs.transient@jonas.bernoulli.dev")) (:maintainers ("Jonas Bernoulli" . "emacs.transient@jonas.bernoulli.dev")) (:maintainer "Jonas Bernoulli" . "emacs.transient@jonas.bernoulli.dev"))]) + (transient . [(20241123 1834) ((emacs (26 1)) (compat (30 0 0 0)) (seq (2 24))) "Transient commands" tar ((:url . "https://github.com/magit/transient") (:commit . "7e50a8fa8ee71f9ada1e9065ba7b1a079c9f3ba8") (:revdesc . "7e50a8fa8ee7") (:keywords "extensions") (:authors ("Jonas Bernoulli" . "emacs.transient@jonas.bernoulli.dev")) (:maintainers ("Jonas Bernoulli" . "emacs.transient@jonas.bernoulli.dev")) (:maintainer "Jonas Bernoulli" . "emacs.transient@jonas.bernoulli.dev"))]) (transient-dwim . [(20221225 1630) ((emacs (26 1)) (transient (0 1))) "Useful preset transient commands" tar ((:url . "https://github.com/conao3/transient-dwim.el") (:commit . "cb5e0d35729fc6448553b7a17fc5c843f00e8c1d") (:revdesc . "cb5e0d35729f") (:keywords "tools") (:authors ("Naoya Yamashita" . "conao3@gmail.com")) (:maintainers ("Naoya Yamashita" . "conao3@gmail.com")) (:maintainer "Naoya Yamashita" . "conao3@gmail.com"))]) (transient-extras . [(20230721 839) ((emacs (28 1))) "Extra features for transient" tar ((:url . "https://github.com/haji-ali/transient-extras") (:commit . "ca0d5c597382615f0ee8300ff8718f54f8214359") (:revdesc . "ca0d5c597382") (:keywords "convenience") (:authors ("Al Haji-Ali" . "abdo.haji.ali@gmail.com") ("Samuel W. Flint" . "swflint@flintfam.org")) (:maintainers ("Al Haji-Ali" . "abdo.haji.ali@gmail.com") ("Samuel W. Flint" . "swflint@flintfam.org")) (:maintainer "Al Haji-Ali" . "abdo.haji.ali@gmail.com"))]) (transient-extras-a2ps . [(20230303 1511) ((emacs (28 1)) (transient-extras (1 0 0))) "A transient interface to a2ps" tar ((:url . "https://github.com/haji-ali/transient-extras") (:commit . "e91a1cddb1f0cb8b99d2bd30db64d467e5fa7ea8") (:revdesc . "e91a1cddb1f0") (:keywords "convenience") (:authors ("Samuel W. Flint" . "swflint@flintfam.org")) (:maintainers ("Samuel W. Flint" . "swflint@flintfam.org")) (:maintainer "Samuel W. Flint" . "swflint@flintfam.org"))]) @@ -5350,10 +5350,10 @@ (tree-edit . [(20231124 1712) ((emacs (29 1)) (dash (2 19)) (reazon (0 4 0)) (s (0 0 0))) "A library for structural refactoring and editing" tar ((:url . "https://github.com/ethan-leba/tree-edit") (:commit . "3e71d276e7369ff4525f0e2b84356a31fe6b7782") (:revdesc . "3e71d276e736") (:authors ("Ethan Leba" . "ethanleba5@gmail.com")) (:maintainers ("Ethan Leba" . "ethanleba5@gmail.com")) (:maintainer "Ethan Leba" . "ethanleba5@gmail.com"))]) (tree-mode . [(20151104 1331) nil "A mode to manage tree widgets" tar ((:url . "https://github.com/emacsorphanage/tree-mode") (:commit . "b06078826d5875d74b0e7b7ac47b0d0917610534") (:revdesc . "b06078826d58") (:keywords "help" "convenience" "widget") (:authors (nil . "wenbinye@163.com")) (:maintainers (nil . "wenbinye@163.com")) (:maintainer nil . "wenbinye@163.com"))]) (tree-sitter . [(20220212 1632) ((emacs (25 1)) (tsc (0 18 0))) "Incremental parsing system" tar ((:url . "https://github.com/emacs-tree-sitter/elisp-tree-sitter") (:commit . "909717c685ff5a2327fa2ca8fb8a25216129361c") (:revdesc . "909717c685ff") (:keywords "languages" "tools" "parsers" "tree-sitter") (:authors ("Tuấn-Anh Nguyễn" . "ubolonton@gmail.com")) (:maintainers ("Tuấn-Anh Nguyễn" . "ubolonton@gmail.com")) (:maintainer "Tuấn-Anh Nguyễn" . "ubolonton@gmail.com"))]) - (tree-sitter-ess-r . [(20241120 757) ((emacs (26 1)) (ess (18 10 1)) (tree-sitter (0 12 1)) (tree-sitter-langs (0 12 0))) "R with tree-sitter" tar ((:url . "https://github.com/ShuguangSun/tree-sitter-ess-r") (:commit . "895846900530017e91f95374a125c66b01d8925c") (:revdesc . "895846900530") (:keywords "tools") (:authors ("Shuguang Sun" . "shuguang79@qq.com")) (:maintainers ("Shuguang Sun" . "shuguang79@qq.com")) (:maintainer "Shuguang Sun" . "shuguang79@qq.com"))]) + (tree-sitter-ess-r . [(20241120 1547) ((emacs (26 1)) (ess (18 10 1)) (tree-sitter (0 12 1)) (tree-sitter-langs (0 12 0))) "R with tree-sitter" tar ((:url . "https://github.com/ShuguangSun/tree-sitter-ess-r") (:commit . "5e5dbd4d1cf6417530bae2f620405d304fac7772") (:revdesc . "5e5dbd4d1cf6") (:keywords "tools") (:authors ("Shuguang Sun" . "shuguang79@qq.com")) (:maintainers ("Shuguang Sun" . "shuguang79@qq.com")) (:maintainer "Shuguang Sun" . "shuguang79@qq.com"))]) (tree-sitter-indent . [(20220411 1439) ((emacs (26 1)) (tree-sitter (0 12 1)) (seq (2 20))) "Provide indentation with a Tree-sitter backend" tar ((:url . "https://codeberg.org/FelipeLema/tree-sitter-indent.el") (:commit . "4ef246db3e4ff99f672fe5e4b416c890f885c09e") (:revdesc . "4ef246db3e4f") (:keywords "convenience" "internal") (:authors ("Felipe Lema" . "felipelema@mortemale.org")) (:maintainers ("Felipe Lema" . "felipelema@mortemale.org")) (:maintainer "Felipe Lema" . "felipelema@mortemale.org"))]) (tree-sitter-ispell . [(20240610 2252) ((emacs (26 1)) (tree-sitter (0 15 0))) "Run ispell on tree-sitter text nodes" tar ((:url . "https://github.com/erickgnavar/tree-sitter-ispell.el") (:commit . "a06eff00affff85992d2a8ad0019034747ffeb70") (:revdesc . "a06eff00afff") (:authors ("Erick Navarro" . "erick@navarro.io")) (:maintainers ("Erick Navarro" . "erick@navarro.io")) (:maintainer "Erick Navarro" . "erick@navarro.io"))]) - (tree-sitter-langs . [(20241118 451) ((emacs (25 1)) (tree-sitter (0 15 0))) "Grammar bundle for tree-sitter" tar ((:url . "https://github.com/emacs-tree-sitter/tree-sitter-langs") (:commit . "b955ffbe26b3a7e931f116720efa7dee9de35174") (:revdesc . "b955ffbe26b3") (:keywords "languages" "tools" "parsers" "tree-sitter") (:authors ("Tuấn-Anh Nguyễn" . "ubolonton@gmail.com")) (:maintainers ("Tuấn-Anh Nguyễn" . "ubolonton@gmail.com")) (:maintainer "Tuấn-Anh Nguyễn" . "ubolonton@gmail.com"))]) + (tree-sitter-langs . [(20241120 1722) ((emacs (25 1)) (tree-sitter (0 15 0))) "Grammar bundle for tree-sitter" tar ((:url . "https://github.com/emacs-tree-sitter/tree-sitter-langs") (:commit . "2e9f14626bbbcf7b37487d9b2b2969dea9284c6a") (:revdesc . "2e9f14626bbb") (:keywords "languages" "tools" "parsers" "tree-sitter") (:authors ("Tuấn-Anh Nguyễn" . "ubolonton@gmail.com")) (:maintainers ("Tuấn-Anh Nguyễn" . "ubolonton@gmail.com")) (:maintainer "Tuấn-Anh Nguyễn" . "ubolonton@gmail.com"))]) (treebundel . [(20240531 2321) ((emacs (27 1)) (compat (29 1 4 2))) "Bundle related git-worktrees together" tar ((:url . "https://github.com/purplg/treebundel") (:commit . "b0a5d1bf924d8cadde5bae50b8d9ac131279b828") (:revdesc . "b0a5d1bf924d") (:keywords "convenience" "vc"))]) (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" tar ((:url . "https://github.com/cyberthal/treefactor") (:commit . "75357757022a4399ab772ff0d92065bd114dabe9") (:revdesc . "75357757022a") (:keywords "outlines" "files" "convenience") (:authors ("Leo Littlebook" . "Leo.Littlebook@gmail.com")) (:maintainers ("Leo Littlebook" . "Leo.Littlebook@gmail.com")) (:maintainer "Leo Littlebook" . "Leo.Littlebook@gmail.com"))]) (treemacs . [(20241113 2139) ((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 ((:url . "https://github.com/Alexander-Miller/treemacs") (:commit . "2fd7745f1bc446fc590dc7ba2eb4e062a51fbb3e") (:revdesc . "2fd7745f1bc4") (:authors ("Alexander Miller" . "alexanderm@web.de")) (:maintainers ("Alexander Miller" . "alexanderm@web.de")) (:maintainer "Alexander Miller" . "alexanderm@web.de"))]) @@ -5441,7 +5441,7 @@ (unidecode . [(20201213 1449) nil "Transliterate Unicode to ASCII" tar ((:url . "https://github.com/sindikat/unidecode") (:commit . "525b51b38f5b0435642005957740fe22ecb2a53c") (:revdesc . "525b51b38f5b") (:authors ("sindikat" . "sindikatatmail36dotnet")) (:maintainers ("John Mastro" . "john.b.mastro@gmail.com")) (:maintainer "John Mastro" . "john.b.mastro@gmail.com"))]) (unifdef . [(20200517 514) nil "Delete code guarded by processor directives" tar ((:url . "https://github.com/Lindydancer/unifdef") (:commit . "7a4b76f664c4375e3d98e8af0a29270752c13701") (:revdesc . "7a4b76f664c4") (:keywords "convenience" "languages"))]) (unify-opening . [(20230903 844) ((emacs (24 4))) "Unify the mechanism to open files" tar ((:url . "https://github.com/DamienCassou/unify-opening") (:commit . "282ce0e35ecebbe602bec6f8d64f0192d8a18342") (:revdesc . "282ce0e35ece") (:authors ("Damien Cassou" . "damien.cassou@gmail.com")) (:maintainers ("Damien Cassou" . "damien.cassou@gmail.com")) (:maintainer "Damien Cassou" . "damien.cassou@gmail.com"))]) - (uniline . [(20241116 1149) ((emacs (29 1)) (hydra (0 15 0))) "Draw UNICODE lines, boxes, arrows onto existing text" tar ((:url . "https://github.com/tbanel/uniline") (:commit . "7f94b02530fc7ad4da2f540d8afaddbb963f7eb8") (:revdesc . "7f94b02530fc") (:keywords "convenience" "text"))]) + (uniline . [(20241122 951) ((emacs (29 1)) (hydra (0 15 0))) "Draw UNICODE lines, boxes, arrows onto existing text" tar ((:url . "https://github.com/tbanel/uniline") (:commit . "2cc8e5f2cbf04d8a2fddb81eb3c08f8b35f2df60") (:revdesc . "2cc8e5f2cbf0") (:keywords "convenience" "text"))]) (unipoint . [(20140113 2224) nil "A simple way to insert unicode characters by TeX name" tar ((:url . "https://github.com/apg/unipoint") (:commit . "5da04aebac35a5c9e1d8704f2231808d42f4b36a") (:revdesc . "5da04aebac35") (:authors ("Andrew Gwozdziewycz" . "git@apgwoz.com")) (:maintainers ("Andrew Gwozdziewycz" . "git@apgwoz.com")) (:maintainer "Andrew Gwozdziewycz" . "git@apgwoz.com"))]) (unison . [(20160704 740) ((emacs (24 1))) "Sync with Unison" tar ((:url . "https://github.com/unhammer/unison.el") (:commit . "a78a04c0d1398d00f75a1bd4799622a65bcb0f28") (:revdesc . "a78a04c0d139") (:keywords "sync") (:authors ("Kevin Brubeck Unhammer" . "unhammer@fsfe.org")) (:maintainers ("Kevin Brubeck Unhammer" . "unhammer@fsfe.org")) (:maintainer "Kevin Brubeck Unhammer" . "unhammer@fsfe.org"))]) (unison-mode . [(20160513 1501) nil "Syntax highlighting for unison file synchronization program" tar ((:url . "https://github.com/impaktor/unison-mode") (:commit . "0bd6a65c0d12f87fcf7bdff15fe54444959b93bf") (:revdesc . "0bd6a65c0d12") (:keywords "symchronization" "unison") (:authors ("Karl Fogelmark" . "karlfogel@gmail.com")) (:maintainers ("Karl Fogelmark" . "karlfogel@gmail.com")) (:maintainer "Karl Fogelmark" . "karlfogel@gmail.com"))]) @@ -5543,7 +5543,7 @@ (visual-fill-column . [(20240411 656) ((emacs (25 1))) "Fill-column for visual-line-mode" tar ((:url . "https://codeberg.org/joostkremers/visual-fill-column") (:commit . "e04d3521b6dc2435de4c4a4b9cac5feb194f0d5b") (:revdesc . "e04d3521b6dc") (:authors ("Joost Kremers" . "joostkremers@fastmail.fm")) (:maintainers ("Joost Kremers" . "joostkremers@fastmail.fm")) (:maintainer "Joost Kremers" . "joostkremers@fastmail.fm"))]) (visual-regexp . [(20210502 2019) ((cl-lib (0 2))) "A regexp/replace command for Emacs with interactive visual feedback" tar ((:url . "https://github.com/benma/visual-regexp.el") (:commit . "48457d42a5e0fe10fa3a9c15854f1f127ade09b5") (:revdesc . "48457d42a5e0") (:keywords "regexp" "replace" "visual" "feedback") (:authors ("Marko Bencun" . "mbencun@gmail.com")) (:maintainers ("Marko Bencun" . "mbencun@gmail.com")) (:maintainer "Marko Bencun" . "mbencun@gmail.com"))]) (visual-regexp-steroids . [(20170222 253) ((visual-regexp (1 1))) "Extends visual-regexp to support other regexp engines" tar ((:url . "https://github.com/benma/visual-regexp-steroids.el") (:commit . "a6420b25ec0fbba43bf57875827092e1196d8a9e") (:revdesc . "a6420b25ec0f") (:keywords "external" "foreign" "regexp" "replace" "python" "visual" "feedback") (:authors ("Marko Bencun" . "mbencun@gmail.com")) (:maintainers ("Marko Bencun" . "mbencun@gmail.com")) (:maintainer "Marko Bencun" . "mbencun@gmail.com"))]) - (visual-replace . [(20241118 2004) ((emacs (26 1))) "A prompt for replace-string and query-replace" tar ((:url . "https://github.com/szermatt/visual-replace") (:commit . "ef41f40371974e8c13dbd82f2fd11fdee98d99a1") (:revdesc . "ef41f4037197") (:keywords "convenience" "matching" "replace") (:authors ("Stephane Zermatten" . "szermatt@gmail.com")) (:maintainers ("Stephane Zermatten" . "szermatt@gmail.com")) (:maintainer "Stephane Zermatten" . "szermatt@gmail.com"))]) + (visual-replace . [(20241124 1051) ((emacs (26 1))) "A prompt for replace-string and query-replace" tar ((:url . "https://github.com/szermatt/visual-replace") (:commit . "19544555e7b5bba624238217a295fd4c80c0ed1d") (:revdesc . "19544555e7b5") (:keywords "convenience" "matching" "replace") (:authors ("Stephane Zermatten" . "szermatt@gmail.com")) (:maintainers ("Stephane Zermatten" . "szermatt@gmail.com")) (:maintainer "Stephane Zermatten" . "szermatt@gmail.com"))]) (vlc . [(20200328 1143) ((emacs (25 1))) "VideoLAN VLC Media Player Control" tar ((:url . "https://github.com/xuchunyang/vlc.el") (:commit . "07c4a12904f2700fb8420c4e71395fd59a5e6faa") (:revdesc . "07c4a12904f2") (:keywords "tools"))]) (vlf . [(20191126 2250) nil "View Large Files" tar ((:url . "https://github.com/m00natic/vlfi") (:commit . "cc02f2533782d6b9b628cec7e2dcf25b2d05a27c") (:revdesc . "cc02f2533782") (:keywords "large files" "utilities") (:maintainers ("Andrey Kotlarski" . "m00naticus@gmail.com")) (:maintainer "Andrey Kotlarski" . "m00naticus@gmail.com"))]) (vline . [(20210805 1528) ((emacs (24 3))) "Column highlighting (vertical line displaying) mode" tar ((:url . "https://github.com/buzztaiki/vline") (:commit . "f5d7b5743dceca75b81c8c95287cd5b0341debf9") (:revdesc . "f5d7b5743dce") (:keywords "faces" "editing" "emulating") (:authors ("Taiki SUGAWARA" . "buzz.taiki@gmail.com")) (:maintainers ("Taiki SUGAWARA" . "buzz.taiki@gmail.com")) (:maintainer "Taiki SUGAWARA" . "buzz.taiki@gmail.com"))]) @@ -5556,7 +5556,7 @@ (vscdark-theme . [(20191212 107) ((emacs (24 1))) "VS Code Dark+ like theme" tar ((:url . "https://github.com/abelikoff/vscdark-theme") (:commit . "f419553e2a2f091a8bc257fb5ab520326e93ddd4") (:revdesc . "f419553e2a2f"))]) (vscode-dark-plus-theme . [(20230725 1703) nil "Default Visual Studio Code Dark+ theme" tar ((:url . "https://github.com/ianyepan/vscode-dark-plus-emacs-theme") (:commit . "65420ca73b543e1e7955905bea1a8d7e5fe6c5ff") (:revdesc . "65420ca73b54"))]) (vscode-icon . [(20230330 2206) ((emacs (25 1))) "Utility package to provide Vscode style icons" tar ((:url . "https://github.com/jojojames/vscode-icon-emacs") (:commit . "3976bc2e7e2fe0068ae59c11d226f67e0e87aaea") (:revdesc . "3976bc2e7e2f") (:keywords "files" "tools") (:authors ("James Nguyen" . "james@jojojames.com")) (:maintainers ("James Nguyen" . "james@jojojames.com")) (:maintainer "James Nguyen" . "james@jojojames.com"))]) - (vsh-mode . [(20240820 1320) ((emacs (30 0))) "Alternate PTY interface for complex terminal sessions" tar ((:url . "https://github.com/hardenedapple/vsh") (:commit . "40daabb4b05e1dce8bc9b68cb437d9aff3cfa7d0") (:revdesc . "40daabb4b05e") (:keywords "processes") (:authors ("Matthew Malcomson" . "hardenedapple@gmail.com")) (:maintainers ("Matthew Malcomson" . "hardenedapple@gmail.com")) (:maintainer "Matthew Malcomson" . "hardenedapple@gmail.com"))]) + (vsh-mode . [(20241104 1341) ((emacs (30 0))) "Alternate PTY interface for complex terminal sessions" tar ((:url . "https://github.com/hardenedapple/vsh") (:commit . "47b6190777be9e1c4c0efb94c166b29c83b10553") (:revdesc . "47b6190777be") (:keywords "processes") (:authors ("Matthew Malcomson" . "hardenedapple@gmail.com")) (:maintainers ("Matthew Malcomson" . "hardenedapple@gmail.com")) (:maintainer "Matthew Malcomson" . "hardenedapple@gmail.com"))]) (vterm . [(20241118 1627) ((emacs (25 1))) "Fully-featured terminal emulator" tar ((:url . "https://github.com/akermu/emacs-libvterm") (:commit . "fd50624723200f4ac261f122f6332f57796c782f") (:revdesc . "fd5062472320") (:keywords "terminals") (:authors ("Lukas Fürmetz" . "fuermetz@mailbox.org")) (:maintainers ("Lukas Fürmetz" . "fuermetz@mailbox.org")) (:maintainer "Lukas Fürmetz" . "fuermetz@mailbox.org"))]) (vterm-hotkey . [(20240702 1445) ((emacs (29 4)) (vterm (0 0))) "Control vterm buffers with hotkeys" tar ((:url . "https://github.com/rootatpixel/vterm-hotkey") (:commit . "039033a4c30dabca625d6924d1796bb9e13d85c7") (:revdesc . "039033a4c30d") (:keywords "terminals" "processes" "hotkeys"))]) (vterm-toggle . [(20230912 246) ((emacs (25 1)) (vterm (0 0 1))) "Toggles between the vterm buffer and other buffers" tar ((:url . "https://github.com/jixiuf/vterm-toggle") (:commit . "06cb4f3c565e46470a3c4505c11e26066d869715") (:revdesc . "06cb4f3c565e") (:keywords "vterm" "terminals") (:authors (nil . "jixiufjixiuf@qq.com")) (:maintainers (nil . "jixiufjixiuf@qq.com")) (:maintainer nil . "jixiufjixiuf@qq.com"))]) @@ -5663,7 +5663,7 @@ (winum . [(20190911 1607) ((cl-lib (0 5)) (dash (2 13 0))) "Navigate windows and frames using numbers" tar ((:url . "https://github.com/deb0ch/emacs-winum") (:commit . "098249c65042ee0308b8236d1ee838c8da8fdf25") (:revdesc . "098249c65042") (:keywords "convenience" "frames" "windows" "multi-screen") (:authors ("Thomas de Beauchêne" . "thomas.de.beauchene@gmail.com")) (:maintainers ("Thomas de Beauchêne" . "thomas.de.beauchene@gmail.com")) (:maintainer "Thomas de Beauchêne" . "thomas.de.beauchene@gmail.com"))]) (wisp-mode . [(20240921 1758) ((emacs (24 4))) "Tools for wisp: the Whitespace-to-Lisp preprocessor" tar ((:url . "https://hg.sr.ht/~arnebab/wisp") (:commit . "61d068638c88d149a6f75619e284f8c1e9657e90") (:revdesc . "61d068638c88d149a6f75619e284f8c1e9657e90") (:keywords "languages" "lisp" "scheme") (:authors ("Arne Babenhauserheide" . "arne_bab@web.de")) (:maintainers ("Arne Babenhauserheide" . "arne_bab@web.de")) (:maintainer "Arne Babenhauserheide" . "arne_bab@web.de"))]) (wispjs-mode . [(20170720 1919) ((clojure-mode (0))) "Major mode for Wisp code" tar ((:url . "https://github.com/krisajenkins/wispjs-mode") (:commit . "60f9f5fd9d1556e2d008939f67eb1b1d0f325fa8") (:revdesc . "60f9f5fd9d15") (:authors ("Kris Jenkins" . "krisajenkins@gmail.com")) (:maintainers ("Kris Jenkins" . "krisajenkins@gmail.com")) (:maintainer "Kris Jenkins" . "krisajenkins@gmail.com"))]) - (with-editor . [(20240831 2230) ((emacs (26 1)) (compat (30 0 0 0))) "Use the Emacsclient as $EDITOR" tar ((:url . "https://github.com/magit/with-editor") (:commit . "77cb2403158cfea9d8bfb8adad81b84d1d6d7c6a") (:revdesc . "77cb2403158c") (:keywords "processes" "terminals") (:authors ("Jonas Bernoulli" . "emacs.with-editor@jonas.bernoulli.dev")) (:maintainers ("Jonas Bernoulli" . "emacs.with-editor@jonas.bernoulli.dev")) (:maintainer "Jonas Bernoulli" . "emacs.with-editor@jonas.bernoulli.dev"))]) + (with-editor . [(20241123 2137) ((emacs (26 1)) (compat (30 0 0 0))) "Use the Emacsclient as $EDITOR" tar ((:url . "https://github.com/magit/with-editor") (:commit . "57f20bdb0d50256acdd12019aaa42b609204699b") (:revdesc . "57f20bdb0d50") (:keywords "processes" "terminals") (:authors ("Jonas Bernoulli" . "emacs.with-editor@jonas.bernoulli.dev")) (:maintainers ("Jonas Bernoulli" . "emacs.with-editor@jonas.bernoulli.dev")) (:maintainer "Jonas Bernoulli" . "emacs.with-editor@jonas.bernoulli.dev"))]) (with-emacs . [(20220814 444) ((emacs (24 4))) "Evaluate Emacs Lisp expressions in a separate Emacs process" tar ((:url . "https://github.com/twlz0ne/with-emacs.el") (:commit . "fb9ef454a4bb2d6de3415807b4858a20a9cc0dad") (:revdesc . "fb9ef454a4bb") (:keywords "tools") (:authors ("Gong Qijian" . "gongqijian@gmail.com")) (:maintainers ("Gong Qijian" . "gongqijian@gmail.com")) (:maintainer "Gong Qijian" . "gongqijian@gmail.com"))]) (with-namespace . [(20130407 1822) ((dash (1 1 0)) (loop (1 1))) "Interoperable elisp namespaces" tar ((:url . "https://github.com/Wilfred/with-namespace.el") (:commit . "36828a40428c8e53c117f2df830b2f7a59ddd306") (:revdesc . "36828a40428c") (:keywords "namespaces") (:authors ("Wilfred Hughes" . "me@wilfred.me.uk")) (:maintainers ("Wilfred Hughes" . "me@wilfred.me.uk")) (:maintainer "Wilfred Hughes" . "me@wilfred.me.uk"))]) (with-proxy . [(20200510 414) ((emacs (24 4))) "Evaluate expressions with proxy" tar ((:url . "https://github.com/twlz0ne/with-proxy.el") (:commit . "93b1ed2f3060f305009fa71f4fb5bb10173a10e3") (:revdesc . "93b1ed2f3060") (:keywords "comm") (:authors ("Gong Qijian" . "gongqijian@gmail.com")) (:maintainers ("Gong Qijian" . "gongqijian@gmail.com")) (:maintainer "Gong Qijian" . "gongqijian@gmail.com"))]) diff --git a/emacs/elpa/archives/nongnu/archive-contents b/emacs/elpa/archives/nongnu/archive-contents @@ -486,7 +486,7 @@ ("Arne Jørgensen" . "arne@arnested.dk")) (:commit . "f632fa5f140b04260fa23b15ffccbfe5a787b2e2"))]) (dslide . - [(0 5 3) + [(0 5 4) ((emacs (29 2))) "Domain Specific sLIDEs. A presentation framework" tar @@ -495,7 +495,7 @@ (:maintainer "Positron" . "contact@positron.solutions") (:authors ("Positron" . "contact@positron.solutions")) - (:commit . "2d8a9ac3e37157ce8b78880ebc1defc61303a44d"))]) + (:commit . "dee290e1c41fdcaa3be508f8476b3ca3a5e56ed1"))]) (eat . [(0 9 4) ((emacs @@ -2015,7 +2015,7 @@ ("David Christiansen" . "david@davidchristiansen.dk")) (:commit . "1edda80e2e32b72e77f4f16ae5b83c312c68ee95"))]) (racket-mode . - [(1 0 20241116 120019) + [(1 0 20241121 151851) ((emacs (25 1))) "Racket editing, REPL, and more" tar diff --git a/emacs/elpa/archives/nongnu/archive-contents.signed b/emacs/elpa/archives/nongnu/archive-contents.signed @@ -1 +1 @@ -Good signature from 645357D2883A0966 GNU ELPA Signing Agent (2023) <elpasign@elpa.gnu.org> (trust undefined) created at 2024-11-20T10:10:03+0000 using EDDSA -\ No newline at end of file +Good signature from 645357D2883A0966 GNU ELPA Signing Agent (2023) <elpasign@elpa.gnu.org> (trust undefined) created at 2024-11-24T10:10:03+0000 using EDDSA +\ No newline at end of file diff --git a/emacs/elpa/cape-20241105.858/cape-pkg.el b/emacs/elpa/cape-20241105.858/cape-pkg.el @@ -1,11 +0,0 @@ -;; -*- no-byte-compile: t; lexical-binding: nil -*- -(define-package "cape" "20241105.858" - "Completion At Point Extensions." - '((emacs "28.1") - (compat "30")) - :url "https://github.com/minad/cape" - :commit "74c3501ecd19ec9af0d30c16c10ded47dc995ffa" - :revdesc "74c3501ecd19" - :keywords '("abbrev" "convenience" "matching" "completion" "text") - :authors '(("Daniel Mendler" . "mail@daniel-mendler.de")) - :maintainers '(("Daniel Mendler" . "mail@daniel-mendler.de"))) diff --git a/emacs/elpa/cape-20241105.858/cape.el b/emacs/elpa/cape-20241105.858/cape.el @@ -1,1303 +0,0 @@ -;;; cape.el --- Completion At Point Extensions -*- lexical-binding: t -*- - -;; Copyright (C) 2021-2024 Free Software Foundation, Inc. - -;; Author: Daniel Mendler <mail@daniel-mendler.de> -;; Maintainer: Daniel Mendler <mail@daniel-mendler.de> -;; Created: 2021 -;; Package-Version: 20241105.858 -;; Package-Revision: 74c3501ecd19 -;; Package-Requires: ((emacs "28.1") (compat "30")) -;; URL: https://github.com/minad/cape -;; Keywords: abbrev, convenience, matching, completion, text - -;; This file is 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 <https://www.gnu.org/licenses/>. - -;;; Commentary: - -;; Let your completions fly! This package provides additional completion -;; backends in the form of Capfs (completion-at-point-functions). -;; -;; `cape-abbrev': Complete abbreviation (add-global-abbrev, add-mode-abbrev). -;; `cape-dabbrev': Complete word from current buffers. -;; `cape-dict': Complete word from dictionary file. -;; `cape-elisp-block': Complete Elisp in Org or Markdown code block. -;; `cape-elisp-symbol': Complete Elisp symbol. -;; `cape-emoji': Complete Emoji. -;; `cape-file': Complete file name. -;; `cape-history': Complete from Eshell, Comint or minibuffer history. -;; `cape-keyword': Complete programming language keyword. -;; `cape-line': Complete entire line from file. -;; `cape-rfc1345': Complete Unicode char using RFC 1345 mnemonics. -;; `cape-sgml': Complete Unicode char from SGML entity, e.g., &alpha. -;; `cape-tex': Complete Unicode char from TeX command, e.g. \hbar. - -;;; Code: - -(require 'compat) -(eval-when-compile - (require 'cl-lib) - (require 'subr-x)) - -;;;; Customization - -(defgroup cape nil - "Completion At Point Extensions." - :link '(info-link :tag "Info Manual" "(cape)") - :link '(url-link :tag "Website" "https://github.com/minad/cape") - :link '(emacs-library-link :tag "Library Source" "cape.el") - :group 'convenience - :group 'tools - :group 'matching - :prefix "cape-") - -(defcustom cape-dict-limit 100 - "Maximal number of completion candidates returned by `cape-dict'." - :type '(choice (const nil) natnum)) - -(defcustom cape-dict-file "/usr/share/dict/words" - "Path to dictionary word list file. -This variable can also be a list of paths or -a function returning a single or more paths." - :type '(choice string (repeat string) function)) - -(defcustom cape-dict-case-replace 'case-replace - "Preserve case of input. -See `dabbrev-case-replace' for details." - :type '(choice (const :tag "off" nil) - (const :tag "use `case-replace'" case-replace) - (other :tag "on" t))) - -(defcustom cape-dict-case-fold 'case-fold-search - "Case fold search during search. -See `dabbrev-case-fold-search' for details." - :type '(choice (const :tag "off" nil) - (const :tag "use `case-fold-search'" case-fold-search) - (other :tag "on" t))) - -(defcustom cape-dabbrev-min-length 4 - "Minimum length of Dabbrev expansions. -This setting ensures that words which are too short -are not offered as completion candidates, such that -auto completion does not pop up too aggressively." - :type 'natnum) - -(defcustom cape-dabbrev-check-other-buffers t - "Buffers to check for Dabbrev. - -If t, check all other buffers, subject to Dabbrev ignore rules. -If a function, only search the buffers returned by this function. -Any other non-nil value only checks some other buffers, as per -`dabbrev-select-buffers-function'." - :type `(choice (const :tag "off" nil) - (const :tag "same-mode buffers" ,#'cape--buffers-major-mode) - (function :tag "function") - (const :tag "some" some) - (other :tag "all" t))) - -(defcustom cape-file-directory nil - "Base directory used by `cape-file." - :type '(choice (const nil) string function)) - -(defcustom cape-file-prefix "file:" - "File completion trigger prefixes. -The value can be a string or a list of strings. The default -`file:' is the prefix of Org file links which work in arbitrary -buffers via `org-open-at-point-global'." - :type '(choice string (repeat string))) - -(defcustom cape-file-directory-must-exist t - "The parent directory must exist for file completion." - :type 'boolean) - -(defcustom cape-line-buffer-function #'cape--buffers-major-mode - "Function which returns list of buffers. -The buffers are scanned for completion candidates by `cape-line'." - :type '(choice (const :tag "Current buffer" current-buffer) - (const :tag "All buffers" buffer-list) - (const :tag "Buffers with same major mode" cape--buffers-major-mode) - (function :tag "Custom function"))) - -(defcustom cape-elisp-symbol-wrapper - '((org-mode ?~ ?~) - (markdown-mode ?` ?`) - (emacs-lisp-mode ?` ?') - (rst-mode "``" "``") - (log-edit-mode "`" "'") - (change-log-mode "`" "'") - (message-mode "`" "'") - (rcirc-mode "`" "'")) - "Wrapper characters for symbols." - :type '(alist :key-type symbol :value-type (list (choice character string) - (choice character string)))) - -;;;; Helpers - -(defun cape--case-fold-p (fold) - "Return non-nil if case folding is enabled for FOLD." - (if (eq fold 'case-fold-search) case-fold-search fold)) - -(defun cape--case-replace-list (flag input strs) - "Replace case of STRS depending on INPUT and FLAG." - (if (and (if (eq flag 'case-replace) case-replace flag) - (let (case-fold-search) (string-match-p "\\`[[:upper:]]" input))) - (mapcar (apply-partially #'cape--case-replace flag input) strs) - strs)) - -(defun cape--case-replace (flag input str) - "Replace case of STR depending on INPUT and FLAG." - (or (and (if (eq flag 'case-replace) case-replace flag) - (string-prefix-p input str t) - (let (case-fold-search) (string-match-p "\\`[[:upper:]]" input)) - (save-match-data - ;; Ensure that single character uppercase input does not lead to an - ;; all uppercase result. - (when (and (= (length input) 1) (> (length str) 1)) - (setq input (concat input (substring str 1 2)))) - (and (string-match input input) - (replace-match str nil nil input)))) - str)) - -(defun cape--separator-p (str) - "Return non-nil if input STR has a separator character. -Separator characters are used by completion styles like Orderless -to split filter words. In Corfu, the separator is configurable -via the variable `corfu-separator'." - (string-search (string ;; Support `corfu-separator' and Orderless - (or (and (bound-and-true-p corfu-mode) - (bound-and-true-p corfu-separator)) - ?\s)) - str)) - -(defmacro cape--silent (&rest body) - "Silence BODY." - (declare (indent 0)) - `(cl-letf ((inhibit-message t) - (message-log-max nil) - ((symbol-function #'minibuffer-message) #'ignore)) - (ignore-errors ,@body))) - -(defun cape--bounds (thing) - "Return bounds of THING." - (or (bounds-of-thing-at-point thing) (cons (point) (point)))) - -(defmacro cape--wrapped-table (wrap body) - "Create wrapped completion table, handle `completion--unquote'. -WRAP is the wrapper function. -BODY is the wrapping expression." - (declare (indent 1)) - `(lambda (str pred action) - (,@body - (let ((result (complete-with-action action table str pred))) - (when (and (eq action 'completion--unquote) (functionp (cadr result))) - (cl-callf ,wrap (cadr result))) - result)))) - -(defun cape--accept-all-table (table) - "Create completion TABLE which accepts all input." - (cape--wrapped-table cape--accept-all-table - (or (eq action 'lambda)))) - -(defun cape--passthrough-table (table) - "Create completion TABLE disabling any filtering." - (cape--wrapped-table cape--passthrough-table - (let (completion-ignore-case completion-regexp-list (_ (setq str "")))))) - -(defun cape--noninterruptible-table (table) - "Create non-interruptible completion TABLE." - (cape--wrapped-table cape--noninterruptible-table - (let (throw-on-input)))) - -(defun cape--silent-table (table) - "Create a new completion TABLE which is silent (no messages, no errors)." - (cape--wrapped-table cape--silent-table - (cape--silent))) - -(defun cape--nonessential-table (table) - "Mark completion TABLE as `non-essential'." - (let ((dir default-directory)) - (cape--wrapped-table cape--nonessential-table - (let ((default-directory dir) - (non-essential t)))))) - -(defvar cape--debug-length 5 - "Length of printed lists in `cape--debug-print'.") - -(defvar cape--debug-id 0 - "Completion table identifier.") - -(defun cape--debug-message (&rest msg) - "Print debug MSG." - (let ((inhibit-message t)) - (apply #'message msg))) - -(defun cape--debug-print (obj &optional full) - "Print OBJ as string, truncate lists if FULL is nil." - (cond - ((symbolp obj) (symbol-name obj)) - ((functionp obj) "#<function>") - ((proper-list-p obj) - (concat - "(" - (string-join - (mapcar #'cape--debug-print - (if full obj (take cape--debug-length obj))) - " ") - (if (and (not full) (length> obj cape--debug-length)) " ...)" ")"))) - (t (let ((print-level 2)) - (prin1-to-string obj))))) - -(defun cape--debug-table (table name beg end) - "Create completion TABLE with debug messages. -NAME is the name of the Capf, BEG and END are the input markers." - (lambda (str pred action) - (let ((result (complete-with-action action table str pred))) - (if (and (eq action 'completion--unquote) (functionp (cadr result))) - ;; See `cape--wrapped-table' - (cl-callf cape--debug-table (cadr result) name beg end) - (cape--debug-message - "%s(action=%S input=%s:%s:%S prefix=%S ignore-case=%S%s%s) => %s" - name - (pcase action - ('nil 'try) - ('t 'all) - ('lambda 'test) - (_ action)) - (+ beg 0) (+ end 0) (buffer-substring-no-properties beg end) - str completion-ignore-case - (if completion-regexp-list - (format " regexp=%s" (cape--debug-print completion-regexp-list t)) - "") - (if pred - (format " predicate=%s" (cape--debug-print pred)) - "") - (cape--debug-print result))) - result))) - -(cl-defun cape--properties-table (table &key category (sort t) strip &allow-other-keys) - "Create completion TABLE with properties. -CATEGORY is the optional completion category. -SORT should be nil to disable sorting. -STRIP means to strip all metadata." - ;; The metadata will be overridden if the category is non-nil, if the table is - ;; a function table or if sorting should be disabled for a non-nil - ;; non-function table. - (if (or category (functionp table) (and (not sort) table)) - (let ((metadata (and (not strip) - `(metadata - ,@(and category `((category . ,category))) - ,@(and (not sort) '((display-sort-function . identity) - (cycle-sort-function . identity))))))) - (lambda (str pred action) - (if (eq action 'metadata) - metadata - (complete-with-action action table str pred)))) - table)) - -(defun cape--dynamic-table (beg end fun) - "Create dynamic completion table from FUN with caching. -BEG and END are the input bounds. FUN is the function which -computes the candidates. FUN must return a pair of a predicate -function function and the list of candidates. The predicate is -passed new input and must return non-nil if the candidates are -still valid. - -It is only necessary to use this function if the set of -candidates is computed dynamically based on the input and not -statically determined. The behavior is similar but slightly -different to `completion-table-dynamic'. - -The difference to the builtins `completion-table-dynamic' and -`completion-table-with-cache' is that this function does not use -the prefix argument of the completion table to compute the -candidates. Instead it uses the input in the buffer between BEG -and END to FUN to compute the candidates. This way the dynamic -candidate computation is compatible with non-prefix completion -styles like `substring' or `orderless', which pass the empty -string as first argument to the completion table." - (let ((beg (copy-marker beg)) - (end (copy-marker end t)) - valid table) - (lambda (str pred action) - ;; Bail out early for `metadata' and `boundaries'. This is a pointless - ;; move because of caching, but we do it anyway in the hope that the - ;; profiler report looks less confusing, since the weight of the expensive - ;; FUN computation is moved to the `all-completions' action. Computing - ;; `all-completions' must surely be most expensive, so nobody will suspect - ;; a thing. - (unless (or (eq action 'metadata) (eq (car-safe action) 'boundaries)) - (let ((input (buffer-substring-no-properties beg end))) - (unless (and valid - (or (cape--separator-p input) - (funcall valid input))) - (let* (;; Reset in case `all-completions' is used inside FUN - completion-ignore-case completion-regexp-list - ;; Retrieve new state by calling FUN - (new (funcall fun input)) - ;; No interrupt during state update - throw-on-input) - (setq valid (car new) table (cdr new))))) - (complete-with-action action table str pred))))) - -;;;; Capfs - -;;;;; cape-history - -(declare-function ring-elements "ring") -(declare-function eshell-bol "eshell") -(declare-function comint-line-beginning-position "comint") -(defvar eshell-history-ring) -(defvar comint-input-ring) - -(defvar cape--history-properties - (list :company-kind (lambda (_) 'text) - :exclusive 'no) - "Completion extra properties for `cape-history'.") - -;;;###autoload -(defun cape-history (&optional interactive) - "Complete from Eshell, Comint or minibuffer history. -See also `consult-history' for a more flexible variant based on -`completing-read'. If INTERACTIVE is nil the function acts like a Capf." - (interactive (list t)) - (if interactive - (cape-interactive #'cape-history) - (let (history bol) - (cond - ((derived-mode-p 'eshell-mode) - (setq history eshell-history-ring - bol (static-if (< emacs-major-version 30) - (save-excursion (eshell-bol) (point)) - (line-beginning-position)))) - ((derived-mode-p 'comint-mode) - (setq history comint-input-ring - bol (comint-line-beginning-position))) - ((and (minibufferp) (not (eq minibuffer-history-variable t))) - (setq history (symbol-value minibuffer-history-variable) - bol (line-beginning-position)))) - (when (ring-p history) - (setq history (ring-elements history))) - (when history - `(,bol ,(point) - ,(cape--properties-table history :sort nil) - ,@cape--history-properties))))) - -;;;;; cape-file - -(defvar comint-unquote-function) -(defvar comint-requote-function) - -(defvar cape--file-properties - (list :annotation-function (lambda (s) (if (string-suffix-p "/" s) " Dir" " File")) - :company-kind (lambda (s) (if (string-suffix-p "/" s) 'folder 'file)) - :exclusive 'no) - "Completion extra properties for `cape-file'.") - -;;;###autoload -(defun cape-file (&optional interactive) - "Complete file name at point. -See the user option `cape-file-directory-must-exist'. -If INTERACTIVE is nil the function acts like a Capf." - (interactive (list t)) - (if interactive - (cape-interactive '(cape-file-directory-must-exist) #'cape-file) - (pcase-let* ((default-directory (pcase cape-file-directory - ('nil default-directory) - ((pred stringp) cape-file-directory) - (_ (funcall cape-file-directory)))) - (prefix (and cape-file-prefix - (looking-back - (concat - (regexp-opt (ensure-list cape-file-prefix) t) - "[^ \n\t]*") - (pos-bol)) - (match-end 1))) - (`(,beg . ,end) (if prefix - (cons prefix (point)) - (cape--bounds 'filename))) - (non-essential t) - (file (buffer-substring-no-properties beg end))) - (when (or prefix - (not cape-file-directory-must-exist) - (and (string-search "/" file) - (file-exists-p (file-name-directory file)))) - (unless (boundp 'comint-unquote-function) - (require 'comint)) - `(,beg ,end - ,(cape--nonessential-table - (completion-table-with-quoting - #'read-file-name-internal - comint-unquote-function - comint-requote-function)) - ,@(when (or prefix (string-match-p "./" file)) - '(:company-prefix-length t)) - ,@cape--file-properties))))) - -;;;;; cape-elisp-symbol - -(autoload 'elisp--company-kind "elisp-mode") -(autoload 'elisp--company-doc-buffer "elisp-mode") -(autoload 'elisp--company-doc-string "elisp-mode") -(autoload 'elisp--company-location "elisp-mode") - -(defvar cape--elisp-symbol-properties - (list :annotation-function #'cape--elisp-symbol-annotation - :exit-function #'cape--elisp-symbol-exit - :predicate #'cape--elisp-symbol-predicate - :company-kind #'elisp--company-kind - :company-doc-buffer #'elisp--company-doc-buffer - :company-docsig #'elisp--company-doc-string - :company-location #'elisp--company-location - :exclusive 'no) - "Completion extra properties for `cape-elisp-symbol'.") - -(defun cape--elisp-symbol-predicate (sym) - "Return t if SYM is bound, fbound or propertized." - (or (fboundp sym) (boundp sym) (symbol-plist sym))) - -(defun cape--elisp-symbol-exit (sym status) - "Wrap symbol SYM with `cape-elisp-symbol-wrapper' buffers. -STATUS is the exit status." - (when-let (((not (eq status 'exact))) - (c (cl-loop for (m . c) in cape-elisp-symbol-wrapper - if (derived-mode-p m) return c)) - ((or (not (derived-mode-p 'emacs-lisp-mode)) - ;; Inside comment or string - (let ((s (syntax-ppss))) (or (nth 3 s) (nth 4 s))))) - (x (if (stringp (car c)) (car c) (string (car c)))) - (y (if (stringp (cadr c)) (cadr c) (string (cadr c))))) - (save-excursion - (backward-char (length sym)) - (unless (save-excursion - (and (ignore-errors (or (backward-char (length x)) t)) - (looking-at-p (regexp-quote x)))) - (insert x))) - (unless (looking-at-p (regexp-quote y)) - (insert y)))) - -(defun cape--elisp-symbol-annotation (sym) - "Return kind of SYM." - (setq sym (intern-soft sym)) - (cond - ((special-form-p sym) " Special") - ((macrop sym) " Macro") - ((commandp sym) " Command") - ((fboundp sym) " Function") - ((custom-variable-p sym) " Custom") - ((boundp sym) " Variable") - ((featurep sym) " Feature") - ((facep sym) " Face") - (t " Symbol"))) - -;;;###autoload -(defun cape-elisp-symbol (&optional interactive) - "Complete Elisp symbol at point. -If INTERACTIVE is nil the function acts like a Capf." - (interactive (list t)) - (if interactive - ;; No cycling since it breaks the :exit-function. - (let (completion-cycle-threshold) - (cape-interactive #'cape-elisp-symbol)) - (pcase-let ((`(,beg . ,end) (cape--bounds 'symbol))) - (when (eq (char-after beg) ?') - (setq beg (1+ beg) end (max beg end))) - `(,beg ,end - ,(cape--properties-table obarray :category 'symbol) - ,@cape--elisp-symbol-properties)))) - -;;;;; cape-elisp-block - -(declare-function org-element-context "org-element") -(declare-function markdown-code-block-lang "ext:markdown-mode") - -(defun cape--inside-block-p (&rest langs) - "Return non-nil if inside LANGS code block." - (when-let ((face (get-text-property (point) 'face)) - (lang (or (and (if (listp face) - (memq 'org-block face) - (eq 'org-block face)) - (plist-get (cadr (org-element-context)) :language)) - (and (if (listp face) - (memq 'markdown-code-face face) - (eq 'markdown-code-face face)) - (save-excursion - (markdown-code-block-lang)))))) - (member lang langs))) - -;;;###autoload -(defun cape-elisp-block (&optional interactive) - "Complete Elisp in Org or Markdown code block. -This Capf is particularly useful for literate Emacs configurations. -If INTERACTIVE is nil the function acts like a Capf." - (interactive (list t)) - (cond - (interactive - ;; No code block check. Always complete Elisp when command was - ;; explicitly invoked interactively. - (cape-interactive #'elisp-completion-at-point)) - ((cape--inside-block-p "elisp" "emacs-lisp") - (elisp-completion-at-point)))) - -;;;;; cape-dabbrev - -(defvar cape--dabbrev-properties - (list :annotation-function (lambda (_) " Dabbrev") - :company-kind (lambda (_) 'text) - :exclusive 'no) - "Completion extra properties for `cape-dabbrev'.") - -(defvar dabbrev-case-replace) -(defvar dabbrev-case-fold-search) -(defvar dabbrev-abbrev-char-regexp) -(defvar dabbrev-abbrev-skip-leading-regexp) -(declare-function dabbrev--find-all-expansions "dabbrev") -(declare-function dabbrev--reset-global-variables "dabbrev") - -(defun cape--dabbrev-list (input) - "Find all Dabbrev expansions for INPUT." - (cape--silent - (let* ((chk cape-dabbrev-check-other-buffers) - (funp (and (not (memq chk '(nil t some))) (functionp chk)))) - (dlet ((dabbrev-check-other-buffers (and chk (not funp))) - (dabbrev-check-all-buffers (eq chk t)) - (dabbrev-search-these-buffers-only (and funp (funcall chk)))) - (dabbrev--reset-global-variables) - (cons - (apply-partially #'string-prefix-p input) - (cl-loop with min-len = (+ cape-dabbrev-min-length (length input)) - with ic = (cape--case-fold-p dabbrev-case-fold-search) - for w in (dabbrev--find-all-expansions input ic) - if (>= (length w) min-len) collect - (cape--case-replace (and ic dabbrev-case-replace) input w))))))) - -(defun cape--dabbrev-bounds () - "Return bounds of abbreviation." - (unless (boundp 'dabbrev-abbrev-char-regexp) - (require 'dabbrev)) - (let ((re (or dabbrev-abbrev-char-regexp "\\sw\\|\\s_")) - (limit (minibuffer-prompt-end))) - (when (or (looking-at re) - (and (> (point) limit) - (save-excursion (forward-char -1) (looking-at re)))) - (cons (save-excursion - (while (and (> (point) limit) - (save-excursion (forward-char -1) (looking-at re))) - (forward-char -1)) - (when dabbrev-abbrev-skip-leading-regexp - (while (looking-at dabbrev-abbrev-skip-leading-regexp) - (forward-char 1))) - (point)) - (save-excursion - (while (looking-at re) - (forward-char 1)) - (point)))))) - -;;;###autoload -(defun cape-dabbrev (&optional interactive) - "Complete with Dabbrev at point. - -If INTERACTIVE is nil the function acts like a Capf. In case you -observe a performance issue with auto-completion and `cape-dabbrev' -it is strongly recommended to disable scanning in other buffers. -See the user options `cape-dabbrev-min-length' and -`cape-dabbrev-check-other-buffers'." - (interactive (list t)) - (if interactive - (cape-interactive '((cape-dabbrev-min-length 0)) #'cape-dabbrev) - (when-let ((bounds (cape--dabbrev-bounds))) - `(,(car bounds) ,(cdr bounds) - ,(cape--properties-table - (completion-table-case-fold - (cape--dynamic-table (car bounds) (cdr bounds) #'cape--dabbrev-list) - (not (cape--case-fold-p dabbrev-case-fold-search))) - :category 'cape-dabbrev) - ,@cape--dabbrev-properties)))) - -;;;;; cape-dict - -(defvar cape--dict-properties - (list :annotation-function (lambda (_) " Dict") - :company-kind (lambda (_) 'text) - :exclusive 'no) - "Completion extra properties for `cape-dict'.") - -(defun cape--dict-list (input) - "Return all words from `cape-dict-file' matching INPUT." - (unless (equal input "") - (let* ((inhibit-message t) - (message-log-max nil) - (default-directory - (if (and (not (file-remote-p default-directory)) - (file-directory-p default-directory)) - default-directory - user-emacs-directory)) - (files (mapcar #'expand-file-name - (ensure-list - (if (functionp cape-dict-file) - (funcall cape-dict-file) - cape-dict-file)))) - (words - (apply #'process-lines-ignore-status - "grep" - (concat "-Fh" - (and (cape--case-fold-p cape-dict-case-fold) "i") - (and cape-dict-limit (format "m%d" cape-dict-limit))) - input files))) - (cons - (apply-partially - (if (and cape-dict-limit (length= words cape-dict-limit)) - #'equal #'string-search) - input) - (cape--case-replace-list cape-dict-case-replace input words))))) - -;;;###autoload -(defun cape-dict (&optional interactive) - "Complete word from dictionary at point. -This completion function works best if the dictionary is sorted -by frequency. See the custom option `cape-dict-file'. If -INTERACTIVE is nil the function acts like a Capf." - (interactive (list t)) - (if interactive - (cape-interactive #'cape-dict) - (pcase-let ((`(,beg . ,end) (cape--bounds 'word))) - `(,beg ,end - ,(cape--properties-table - (completion-table-case-fold - (cape--dynamic-table beg end #'cape--dict-list) - (not (cape--case-fold-p cape-dict-case-fold))) - :sort nil ;; Presorted word list (by frequency) - :category 'cape-dict) - ,@cape--dict-properties)))) - -;;;;; cape-abbrev - -(defun cape--abbrev-list () - "Abbreviation list." - (delete "" (cl-loop for x in (abbrev--suggest-get-active-tables-including-parents) - nconc (all-completions "" x)))) - -(defun cape--abbrev-annotation (abbrev) - "Annotate ABBREV with expansion." - (concat " " - (truncate-string-to-width - (format - "%s" - (symbol-value - (cl-loop for x in (abbrev--suggest-get-active-tables-including-parents) - thereis (abbrev--symbol abbrev x)))) - 30 0 nil t))) - -(defun cape--abbrev-exit (_str status) - "Expand expansion if STATUS is not exact." - (unless (eq status 'exact) - (expand-abbrev))) - -(defvar cape--abbrev-properties - (list :annotation-function #'cape--abbrev-annotation - :exit-function #'cape--abbrev-exit - :company-kind (lambda (_) 'snippet) - :exclusive 'no) - "Completion extra properties for `cape-abbrev'.") - -;;;###autoload -(defun cape-abbrev (&optional interactive) - "Complete abbreviation at point. -If INTERACTIVE is nil the function acts like a Capf." - (interactive (list t)) - (if interactive - ;; No cycling since it breaks the :exit-function. - (let (completion-cycle-threshold) - (cape-interactive #'cape-abbrev)) - (when-let (abbrevs (cape--abbrev-list)) - (let ((bounds (cape--bounds 'symbol))) - `(,(car bounds) ,(cdr bounds) - ,(cape--properties-table abbrevs :category 'cape-abbrev) - ,@cape--abbrev-properties))))) - -;;;;; cape-line - -(defvar cape--line-properties nil - "Completion extra properties for `cape-line'.") - -(defun cape--buffers-major-mode () - "Return buffers with same major mode as current buffer." - (cl-loop for buf in (buffer-list) - if (eq major-mode (buffer-local-value 'major-mode buf)) - collect buf)) - -(defun cape--line-list () - "Return all lines from buffer." - (let ((ht (make-hash-table :test #'equal)) - (curr-buf (current-buffer)) - (buffers (funcall cape-line-buffer-function)) - lines) - (dolist (buf (ensure-list buffers)) - (with-current-buffer buf - (let ((beg (point-min)) - (max (point-max)) - (pt (if (eq curr-buf buf) (point) -1)) - end) - (save-excursion - (while (< beg max) - (goto-char beg) - (setq end (pos-eol)) - (unless (<= beg pt end) - (let ((line (buffer-substring-no-properties beg end))) - (unless (or (string-blank-p line) (gethash line ht)) - (puthash line t ht) - (push line lines)))) - (setq beg (1+ end))))))) - (nreverse lines))) - -;;;###autoload -(defun cape-line (&optional interactive) - "Complete current line from other lines. -The buffers returned by `cape-line-buffer-function' are scanned for lines. -If INTERACTIVE is nil the function acts like a Capf." - (interactive (list t)) - (if interactive - (cape-interactive #'cape-line) - `(,(pos-bol) ,(point) - ,(cape--properties-table (cape--line-list) :sort nil) - ,@cape--line-properties))) - -;;;; Capf combinators - -(defun cape--company-call (&rest app) - "Apply APP and handle future return values." - ;; Backends are non-interruptible. Disable interrupts! - (let ((toi throw-on-input) - (throw-on-input nil)) - (pcase (apply app) - ;; Handle async future return values. - (`(:async . ,fetch) - (let ((res 'cape--waiting)) - (if toi - (unwind-protect - (progn - (funcall fetch - (lambda (arg) - (when (eq res 'cape--waiting) - (push 'cape--done unread-command-events) - (setq res arg)))) - (when (eq res 'cape--waiting) - (let ((ev (let ((input-method-function nil) - (echo-keystrokes 0)) - (read-event nil t)))) - (unless (eq ev 'cape--done) - (push (cons t ev) unread-command-events) - (setq res 'cape--cancelled) - (throw toi t))))) - (setq unread-command-events - (delq 'cape--done unread-command-events))) - (funcall fetch (lambda (arg) (setq res arg))) - ;; Force synchronization, not interruptible! We use polling - ;; here and ignore pending input since we don't use - ;; `sit-for'. This is the same method used by Company itself. - (while (eq res 'cape--waiting) - (sleep-for 0.01))) - res)) - ;; Plain old synchronous return value. - (res res)))) - -(defvar-local cape--company-init nil) - -;;;###autoload -(defun cape-company-to-capf (backend &optional valid) - "Convert Company BACKEND function to Capf. -VALID is a function taking the old and new input string. It should -return nil if the cached candidates became invalid. The default value -for VALID is `string-prefix-p' such that the candidates are only fetched -again if the input prefix changed." - (lambda () - (when (and (symbolp backend) (not (fboundp backend))) - (ignore-errors (require backend nil t))) - (when (bound-and-true-p company-mode) - (error "`cape-company-to-capf' should not be used with `company-mode', use the Company backend directly instead")) - (when (and (symbolp backend) (not (alist-get backend cape--company-init))) - (funcall backend 'init) - (put backend 'company-init t) - (setf (alist-get backend cape--company-init) t)) - (when-let ((prefix (cape--company-call backend 'prefix)) - (initial-input (if (stringp prefix) prefix (car-safe prefix)))) - (let* ((end (point)) (beg (- end (length initial-input))) - (valid (if (cape--company-call backend 'no-cache initial-input) - #'equal (or valid #'string-prefix-p))) - restore-props) - (list beg end - (funcall - (if (cape--company-call backend 'ignore-case) - #'completion-table-case-fold - #'identity) - (cape--properties-table - (cape--dynamic-table - beg end - (lambda (input) - (let ((cands (cape--company-call backend 'candidates input))) - ;; The candidate string including text properties should be - ;; restored in the :exit-function, unless the UI guarantees - ;; this itself, like Corfu. - (unless (bound-and-true-p corfu-mode) - (setq restore-props cands)) - (cons (apply-partially valid input) cands)))) - :category backend - :sort (not (cape--company-call backend 'sorted)))) - :exclusive 'no - :company-prefix-length (cdr-safe prefix) - :company-doc-buffer (lambda (x) (cape--company-call backend 'doc-buffer x)) - :company-location (lambda (x) (cape--company-call backend 'location x)) - :company-docsig (lambda (x) (cape--company-call backend 'meta x)) - :company-deprecated (lambda (x) (cape--company-call backend 'deprecated x)) - :company-kind (lambda (x) (cape--company-call backend 'kind x)) - :annotation-function (lambda (x) - (when-let (ann (cape--company-call backend 'annotation x)) - (concat " " (string-trim ann)))) - :exit-function (lambda (x _status) - ;; Restore the candidate string including - ;; properties if restore-props is non-nil. See - ;; the comment above. - (setq x (or (car (member x restore-props)) x)) - (cape--company-call backend 'post-completion x))))))) - -;;;###autoload -(defun cape-interactive (&rest capfs) - "Complete interactively with the given CAPFS." - (let* ((ctx (and (consp (car capfs)) (car capfs))) - (capfs (if ctx (cdr capfs) capfs)) - (completion-at-point-functions - (if ctx - (mapcar (lambda (f) `(lambda () (let ,ctx (funcall ',f)))) capfs) - capfs))) - (unless (completion-at-point) - (user-error "%s: No completions" - (mapconcat (lambda (fun) - (if (symbolp fun) - (symbol-name fun) - "anonymous-capf")) - capfs ", "))))) - -;;;###autoload -(defun cape-capf-interactive (capf) - "Create interactive completion function from CAPF." - (lambda (&optional interactive) - (interactive (list t)) - (if interactive (cape-interactive capf) (funcall capf)))) - -;;;###autoload -(defun cape-wrap-super (&rest capfs) - "Call CAPFS and return merged completion result. -The CAPFS list can contain the keyword `:with' to mark the Capfs -afterwards as auxiliary One of the non-auxiliary Capfs before -`:with' must return non-nil for the super Capf to set in and -return a non-nil result. Such behavior is useful when listing -multiple super Capfs in the `completion-at-point-functions': - - (setq completion-at-point-functions - (list (cape-capf-super \\='eglot-completion-at-point - :with \\='tempel-complete) - (cape-capf-super \\='cape-dabbrev - :with \\='tempel-complete)))" - (when-let ((results (cl-loop for capf in capfs until (eq capf :with) - for res = (funcall capf) - if res collect (cons t res)))) - (pcase-let* ((results (nconc results - (cl-loop for capf in (cdr (memq :with capfs)) - for res = (funcall capf) - if res collect (cons nil res)))) - (`((,_main ,beg ,end . ,_)) results) - (cand-ht nil) - (tables nil) - (exclusive nil) - (prefix-len nil) - (cand-functions - '(:company-docsig :company-location :company-kind - :company-doc-buffer :company-deprecated - :annotation-function :exit-function))) - (cl-loop for (main beg2 end2 table . plist) in results do - ;; Note: `cape-capf-super' currently cannot merge Capfs which - ;; trigger at different beginning positions. In order to support - ;; this, take the smallest BEG value and then normalize all - ;; candidates by prefixing them such that they all start at the - ;; smallest BEG position. - (when (= beg beg2) - (push (list main (plist-get plist :predicate) table - ;; Plist attached to the candidates - (mapcan (lambda (f) - (when-let ((v (plist-get plist f))) - (list f v))) - cand-functions)) - tables) - ;; The resulting merged Capf is exclusive if one of the main - ;; Capfs is exclusive. - (when (and main (not (eq (plist-get plist :exclusive) 'no))) - (setq exclusive t)) - (setq end (max end end2)) - (let ((plen (plist-get plist :company-prefix-length))) - (cond - ((eq plen t) - (setq prefix-len t)) - ((and (not prefix-len) (integerp plen)) - (setq prefix-len plen)) - ((and (integerp prefix-len) (integerp plen)) - (setq prefix-len (max prefix-len plen))))))) - (setq tables (nreverse tables)) - `(,beg ,end - ,(lambda (str pred action) - (pcase action - (`(boundaries . ,_) nil) - ('metadata - '(metadata (category . cape-super) - (display-sort-function . identity) - (cycle-sort-function . identity))) - ('t ;; all-completions - (let ((ht (make-hash-table :test #'equal)) - (candidates nil)) - (cl-loop for (main table-pred table cand-plist) in tables do - (let* ((pr (if (and table-pred pred) - (lambda (x) (and (funcall table-pred x) (funcall pred x))) - (or table-pred pred))) - (md (completion-metadata "" table pr)) - (sort (or (completion-metadata-get md 'display-sort-function) - #'identity)) - ;; Always compute candidates of the main Capf - ;; tables, which come first in the tables - ;; list. For the :with Capfs only compute - ;; candidates if we've already determined that - ;; main candidates are available. - (cands (when (or main (or exclusive cand-ht candidates)) - (funcall sort (all-completions str table pr))))) - ;; Handle duplicates with a hash table. - (cl-loop - for cand in-ref cands - for dup = (gethash cand ht t) do - (cond - ((eq dup t) - ;; Candidate does not yet exist. - (puthash cand cand-plist ht)) - ((not (equal dup cand-plist)) - ;; Duplicate candidate. Candidate plist is - ;; different, therefore disambiguate the - ;; candidates. - (setf cand (propertize cand 'cape-capf-super - (cons cand cand-plist)))))) - (when cands (push cands candidates)))) - (when (or cand-ht candidates) - (setq candidates (apply #'nconc (nreverse candidates)) - cand-ht ht) - candidates))) - (_ ;; try-completion and test-completion - (cl-loop for (_main table-pred table _cand-plist) in tables thereis - (complete-with-action - action table str - (if (and table-pred pred) - (lambda (x) (and (funcall table-pred x) (funcall pred x))) - (or table-pred pred))))))) - :company-prefix-length ,prefix-len - ,@(and (not exclusive) '(:exclusive no)) - ,@(mapcan - (lambda (prop) - (list prop - (lambda (cand &rest args) - (if-let ((ref (get-text-property 0 'cape-capf-super cand))) - (when-let ((fun (plist-get (cdr ref) prop))) - (apply fun (car ref) args)) - (when-let ((plist (and cand-ht (gethash cand cand-ht))) - (fun (plist-get plist prop))) - (apply fun cand args)))))) - cand-functions))))) - -;;;###autoload -(defun cape-wrap-debug (capf &optional name) - "Call CAPF and return a completion table which prints trace messages. -If CAPF is an anonymous lambda, pass the Capf NAME explicitly for -meaningful debugging output." - (unless name - (setq name (if (symbolp capf) capf "capf"))) - (setq name (format "%s@%s" name (cl-incf cape--debug-id))) - (pcase (funcall capf) - (`(,beg ,end ,table . ,plist) - (let* ((limit (1+ cape--debug-length)) - (pred (plist-get plist :predicate)) - (cands - ;; Reset regexps for `all-completions' - (let (completion-ignore-case completion-regexp-list) - (all-completions - "" table - (lambda (&rest args) - (and (or (not pred) (apply pred args)) (>= (cl-decf limit) 0)))))) - (plist-str "") - (plist-elt plist)) - (while (cdr plist-elt) - (setq plist-str (format "%s %s=%s" plist-str - (substring (symbol-name (car plist-elt)) 1) - (cape--debug-print (cadr plist-elt))) - plist-elt (cddr plist-elt))) - (cape--debug-message - "%s => input=%s:%s:%S table=%s%s" - name (+ beg 0) (+ end 0) (buffer-substring-no-properties beg end) - (cape--debug-print cands) - plist-str)) - `(,beg ,end ,(cape--debug-table - table name (copy-marker beg) (copy-marker end t)) - ,@(when-let ((exit (plist-get plist :exit-function))) - (list :exit-function - (lambda (cand status) - (cape--debug-message "%s:exit(candidate=%S status=%s)" - name cand status) - (funcall exit cand status)))) - . ,plist)) - (result - (cape--debug-message "%s() => %s (No completion)" - name (cape--debug-print result))))) - -;;;###autoload -(defun cape-wrap-buster (capf &optional valid) - "Call CAPF and return a completion table with cache busting. -This function can be used as an advice around an existing Capf. -The cache is busted when the input changes. The argument VALID -can be a function taking the old and new input string. It should -return nil if the new input requires that the completion table is -refreshed. The default value for VALID is `equal', such that the -completion table is refreshed on every input change." - (setq valid (or valid #'equal)) - (pcase (funcall capf) - (`(,beg ,end ,table . ,plist) - (setq plist `(:cape--buster t . ,plist)) - `(,beg ,end - ,(let* ((beg (copy-marker beg)) - (end (copy-marker end t)) - (input (buffer-substring-no-properties beg end))) - (lambda (str pred action) - (let ((new-input (buffer-substring-no-properties beg end))) - (unless (or (not (eq action t)) - (cape--separator-p new-input) - (funcall valid input new-input)) - (pcase - ;; Reset in case `all-completions' is used inside CAPF - (let (completion-ignore-case completion-regexp-list) - (funcall capf)) - ((and `(,new-beg ,new-end ,new-table . ,new-plist) - (guard (and (= beg new-beg) (= end new-end)))) - (let (throw-on-input) ;; No interrupt during state update - (setf table new-table - input new-input - (cddr plist) new-plist)))))) - (complete-with-action action table str pred))) - ,@plist)))) - -;;;###autoload -(defun cape-wrap-passthrough (capf) - "Call CAPF and make sure that no completion style filtering takes place." - (pcase (funcall capf) - (`(,beg ,end ,table . ,plist) - `(,beg ,end ,(cape--passthrough-table table) ,@plist)))) - -;;;###autoload -(defun cape-wrap-properties (capf &rest properties) - "Call CAPF and strip or add completion PROPERTIES. -Completion properties include for example :exclusive, -:annotation-function and the various :company-* extensions. Furthermore -a boolean :sort flag and a completion :category symbol can be specified. -The boolean :strip flag means to strip all completion properties." - (pcase (funcall capf) - (`(,beg ,end ,table . ,plist) - `(,beg ,end - ,(apply #'cape--properties-table table properties) - ,@(and (not (plist-get properties :strip)) - (append properties plist)))))) - -;;;###autoload -(defun cape-wrap-nonexclusive (capf) - "Call CAPF and ensure that it is marked as non-exclusive. -This function can be used as an advice around an existing Capf." - (cape-wrap-properties capf :exclusive 'no)) - -;;;###autoload -(defun cape-wrap-predicate (capf predicate) - "Call CAPF and add an additional candidate PREDICATE. -The PREDICATE is passed the candidate symbol or string." - (pcase (funcall capf) - (`(,beg ,end ,table . ,plist) - `(,beg ,end ,table - :predicate - ,(if-let (pred (plist-get plist :predicate)) - ;; First argument is key, second is value for hash tables. - ;; The first argument can be a cons cell for alists. Then - ;; the candidate itself is either a string or a symbol. We - ;; normalize the calling convention here such that PREDICATE - ;; always receives a string or a symbol. - (lambda (&rest args) - (when (apply pred args) - (setq args (car args)) - (funcall predicate (if (consp args) (car args) args)))) - (lambda (key &optional _val) - (funcall predicate (if (consp key) (car key) key)))) - ,@plist)))) - -;;;###autoload -(defun cape-wrap-silent (capf) - "Call CAPF and silence it (no messages, no errors). -This function can be used as an advice around an existing Capf." - (pcase (cape--silent (funcall capf)) - (`(,beg ,end ,table . ,plist) - `(,beg ,end ,(cape--silent-table table) ,@plist)))) - -;;;###autoload -(defun cape-wrap-case-fold (capf &optional nofold) - "Call CAPF and return a case-insensitive completion table. -If NOFOLD is non-nil return a case sensitive table instead. This -function can be used as an advice around an existing Capf." - (pcase (funcall capf) - (`(,beg ,end ,table . ,plist) - `(,beg ,end ,(completion-table-case-fold table nofold) ,@plist)))) - -;;;###autoload -(defun cape-wrap-noninterruptible (capf) - "Call CAPF and return a non-interruptible completion table. -This function can be used as an advice around an existing Capf." - (pcase (let (throw-on-input) (funcall capf)) - (`(,beg ,end ,table . ,plist) - `(,beg ,end ,(cape--noninterruptible-table table) ,@plist)))) - -;;;###autoload -(defun cape-wrap-prefix-length (capf length) - "Call CAPF and ensure that prefix length is greater or equal than LENGTH. -If the prefix is long enough, enforce auto completion." - (pcase (funcall capf) - (`(,beg ,end ,table . ,plist) - (when (>= (- end beg) length) - `(,beg ,end ,table - :company-prefix-length t - ,@plist))))) - -;;;###autoload -(defun cape-wrap-inside-faces (capf &rest faces) - "Call CAPF only if inside FACES. -This function can be used as an advice around an existing Capf." - (when-let (((> (point) (point-min))) - (fs (get-text-property (1- (point)) 'face)) - ((if (listp fs) - (cl-loop for f in fs thereis (memq f faces)) - (memq fs faces)))) - (funcall capf))) - -;;;###autoload -(defun cape-wrap-inside-code (capf) - "Call CAPF only if inside code, not inside a comment or string. -This function can be used as an advice around an existing Capf." - (let ((s (syntax-ppss))) - (and (not (nth 3 s)) (not (nth 4 s)) (funcall capf)))) - -;;;###autoload -(defun cape-wrap-inside-comment (capf) - "Call CAPF only if inside comment. -This function can be used as an advice around an existing Capf." - (and (nth 4 (syntax-ppss)) (funcall capf))) - -;;;###autoload -(defun cape-wrap-inside-string (capf) - "Call CAPF only if inside string. -This function can be used as an advice around an existing Capf." - (and (nth 3 (syntax-ppss)) (funcall capf))) - -;;;###autoload -(defun cape-wrap-purify (capf) - "Call CAPF and ensure that it does not illegally modify the buffer. -This function can be used as an advice around an existing -Capf. It has been introduced mainly to fix the broken -`pcomplete-completions-at-point' function in Emacs versions < 29." - ;; bug#50470: Fix Capfs which illegally modify the buffer or which illegally - ;; call `completion-in-region'. The workaround here was proposed by - ;; @jakanakaevangeli and is used in his capf-autosuggest package. In Emacs 29 - ;; the purity bug of Pcomplete has been fixed, such that make - ;; `cape-wrap-purify' is not necessary anymore. - (catch 'cape--illegal-completion-in-region - (condition-case nil - (let ((buffer-read-only t) - (inhibit-read-only nil) - (completion-in-region-function - (lambda (beg end coll pred) - (throw 'cape--illegal-completion-in-region - (list beg end coll :predicate pred))))) - (funcall capf)) - (buffer-read-only nil)))) - -;;;###autoload -(defun cape-wrap-accept-all (capf) - "Call CAPF and return a completion table which accepts every input. -This function can be used as an advice around an existing Capf." - (pcase (funcall capf) - (`(,beg ,end ,table . ,plist) - `(,beg ,end ,(cape--accept-all-table table) . ,plist)))) - -;;;###autoload (autoload 'cape-capf-accept-all "cape") -;;;###autoload (autoload 'cape-capf-buster "cape") -;;;###autoload (autoload 'cape-capf-case-fold "cape") -;;;###autoload (autoload 'cape-capf-debug "cape") -;;;###autoload (autoload 'cape-capf-inside-code "cape") -;;;###autoload (autoload 'cape-capf-inside-comment "cape") -;;;###autoload (autoload 'cape-capf-inside-faces "cape") -;;;###autoload (autoload 'cape-capf-inside-string "cape") -;;;###autoload (autoload 'cape-capf-nonexclusive "cape") -;;;###autoload (autoload 'cape-capf-noninterruptible "cape") -;;;###autoload (autoload 'cape-capf-passthrough "cape") -;;;###autoload (autoload 'cape-capf-predicate "cape") -;;;###autoload (autoload 'cape-capf-prefix-length "cape") -;;;###autoload (autoload 'cape-capf-properties "cape") -;;;###autoload (autoload 'cape-capf-purify "cape") -;;;###autoload (autoload 'cape-capf-silent "cape") -;;;###autoload (autoload 'cape-capf-super "cape") - -(dolist (wrapper (list #'cape-wrap-accept-all #'cape-wrap-buster - #'cape-wrap-case-fold #'cape-wrap-debug - #'cape-wrap-inside-code #'cape-wrap-inside-comment - #'cape-wrap-inside-faces #'cape-wrap-inside-string - #'cape-wrap-nonexclusive #'cape-wrap-noninterruptible - #'cape-wrap-passthrough #'cape-wrap-predicate - #'cape-wrap-prefix-length #'cape-wrap-properties - #'cape-wrap-purify #'cape-wrap-silent #'cape-wrap-super)) - (let ((name (string-remove-prefix "cape-wrap-" (symbol-name wrapper)))) - (defalias (intern (format "cape-capf-%s" name)) - (lambda (capf &rest args) (lambda () (apply wrapper capf args))) - (format "Create a %s Capf from CAPF. -The Capf calls `%s' with CAPF and ARGS as arguments." name wrapper)))) - -(defvar-keymap cape-prefix-map - :doc "Keymap used as completion entry point. -The keymap should be installed globally under a prefix." - "p" #'completion-at-point - "t" #'complete-tag - "d" #'cape-dabbrev - "h" #'cape-history - "f" #'cape-file - "s" #'cape-elisp-symbol - "e" #'cape-elisp-block - "a" #'cape-abbrev - "l" #'cape-line - "w" #'cape-dict - "k" 'cape-keyword - ":" 'cape-emoji - "\\" 'cape-tex - "_" 'cape-tex - "^" 'cape-tex - "&" 'cape-sgml - "r" 'cape-rfc1345) - -;;;###autoload (autoload 'cape-prefix-map "cape" nil t 'keymap) -(defalias 'cape-prefix-map cape-prefix-map) - -(provide 'cape) -;;; cape.el ends here diff --git a/emacs/elpa/cape-20241105.858/cape.elc b/emacs/elpa/cape-20241105.858/cape.elc Binary files differ. diff --git a/emacs/elpa/cape-20241105.858/cape-autoloads.el b/emacs/elpa/cape-20241123.925/cape-autoloads.el diff --git a/emacs/elpa/cape-20241105.858/cape-char.el b/emacs/elpa/cape-20241123.925/cape-char.el diff --git a/emacs/elpa/cape-20241105.858/cape-char.elc b/emacs/elpa/cape-20241123.925/cape-char.elc Binary files differ. diff --git a/emacs/elpa/cape-20241105.858/cape-keyword.el b/emacs/elpa/cape-20241123.925/cape-keyword.el diff --git a/emacs/elpa/cape-20241105.858/cape-keyword.elc b/emacs/elpa/cape-20241123.925/cape-keyword.elc Binary files differ. diff --git a/emacs/elpa/cape-20241123.925/cape-pkg.el b/emacs/elpa/cape-20241123.925/cape-pkg.el @@ -0,0 +1,11 @@ +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "cape" "20241123.925" + "Completion At Point Extensions." + '((emacs "28.1") + (compat "30")) + :url "https://github.com/minad/cape" + :commit "9a7c44fe8b7ace73fa8ebf6b5805474f0ca07d01" + :revdesc "9a7c44fe8b7a" + :keywords '("abbrev" "convenience" "matching" "completion" "text") + :authors '(("Daniel Mendler" . "mail@daniel-mendler.de")) + :maintainers '(("Daniel Mendler" . "mail@daniel-mendler.de"))) diff --git a/emacs/elpa/cape-20241123.925/cape.el b/emacs/elpa/cape-20241123.925/cape.el @@ -0,0 +1,1302 @@ +;;; cape.el --- Completion At Point Extensions -*- lexical-binding: t -*- + +;; Copyright (C) 2021-2024 Free Software Foundation, Inc. + +;; Author: Daniel Mendler <mail@daniel-mendler.de> +;; Maintainer: Daniel Mendler <mail@daniel-mendler.de> +;; Created: 2021 +;; Package-Version: 20241123.925 +;; Package-Revision: 9a7c44fe8b7a +;; Package-Requires: ((emacs "28.1") (compat "30")) +;; URL: https://github.com/minad/cape +;; Keywords: abbrev, convenience, matching, completion, text + +;; This file is 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 <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; Let your completions fly! This package provides additional completion +;; backends in the form of Capfs (completion-at-point-functions). +;; +;; `cape-abbrev': Complete abbreviation (add-global-abbrev, add-mode-abbrev). +;; `cape-dabbrev': Complete word from current buffers. +;; `cape-dict': Complete word from dictionary file. +;; `cape-elisp-block': Complete Elisp in Org or Markdown code block. +;; `cape-elisp-symbol': Complete Elisp symbol. +;; `cape-emoji': Complete Emoji. +;; `cape-file': Complete file name. +;; `cape-history': Complete from Eshell, Comint or minibuffer history. +;; `cape-keyword': Complete programming language keyword. +;; `cape-line': Complete entire line from file. +;; `cape-rfc1345': Complete Unicode char using RFC 1345 mnemonics. +;; `cape-sgml': Complete Unicode char from SGML entity, e.g., &alpha. +;; `cape-tex': Complete Unicode char from TeX command, e.g. \hbar. + +;;; Code: + +(require 'compat) +(eval-when-compile + (require 'cl-lib) + (require 'subr-x)) + +;;;; Customization + +(defgroup cape nil + "Completion At Point Extensions." + :link '(info-link :tag "Info Manual" "(cape)") + :link '(url-link :tag "Website" "https://github.com/minad/cape") + :link '(emacs-library-link :tag "Library Source" "cape.el") + :group 'convenience + :group 'tools + :group 'matching + :prefix "cape-") + +(defcustom cape-dict-limit 100 + "Maximal number of completion candidates returned by `cape-dict'." + :type '(choice (const nil) natnum)) + +(defcustom cape-dict-file "/usr/share/dict/words" + "Path to dictionary word list file. +This variable can also be a list of paths or +a function returning a single or more paths." + :type '(choice string (repeat string) function)) + +(defcustom cape-dict-case-replace 'case-replace + "Preserve case of input. +See `dabbrev-case-replace' for details." + :type '(choice (const :tag "off" nil) + (const :tag "use `case-replace'" case-replace) + (other :tag "on" t))) + +(defcustom cape-dict-case-fold 'case-fold-search + "Case fold search during search. +See `dabbrev-case-fold-search' for details." + :type '(choice (const :tag "off" nil) + (const :tag "use `case-fold-search'" case-fold-search) + (other :tag "on" t))) + +(defcustom cape-dabbrev-min-length 4 + "Minimum length of Dabbrev expansions. +This setting ensures that words which are too short +are not offered as completion candidates, such that +auto completion does not pop up too aggressively." + :type 'natnum) + +(defcustom cape-dabbrev-check-other-buffers t + "Buffers to check for Dabbrev. + +If t, check all other buffers, subject to Dabbrev ignore rules. +If a function, only search the buffers returned by this function. +Any other non-nil value only checks some other buffers, as per +`dabbrev-select-buffers-function'." + :type `(choice (const :tag "off" nil) + (const :tag "same-mode buffers" ,#'cape--buffers-major-mode) + (function :tag "function") + (const :tag "some" some) + (other :tag "all" t))) + +(defcustom cape-file-directory nil + "Base directory used by `cape-file." + :type '(choice (const nil) string function)) + +(defcustom cape-file-prefix "file:" + "File completion trigger prefixes. +The value can be a string or a list of strings. The default +`file:' is the prefix of Org file links which work in arbitrary +buffers via `org-open-at-point-global'." + :type '(choice string (repeat string))) + +(defcustom cape-file-directory-must-exist t + "The parent directory must exist for file completion." + :type 'boolean) + +(defcustom cape-line-buffer-function #'cape--buffers-major-mode + "Function which returns list of buffers. +The buffers are scanned for completion candidates by `cape-line'." + :type '(choice (const :tag "Current buffer" current-buffer) + (const :tag "All buffers" buffer-list) + (const :tag "Buffers with same major mode" cape--buffers-major-mode) + (function :tag "Custom function"))) + +(defcustom cape-elisp-symbol-wrapper + '((org-mode ?~ ?~) + (markdown-mode ?` ?`) + (emacs-lisp-mode ?` ?') + (rst-mode "``" "``") + (log-edit-mode "`" "'") + (change-log-mode "`" "'") + (message-mode "`" "'") + (rcirc-mode "`" "'")) + "Wrapper characters for symbols." + :type '(alist :key-type symbol :value-type (list (choice character string) + (choice character string)))) + +;;;; Helpers + +(defun cape--case-fold-p (fold) + "Return non-nil if case folding is enabled for FOLD." + (if (eq fold 'case-fold-search) case-fold-search fold)) + +(defun cape--case-replace-list (flag input strs) + "Replace case of STRS depending on INPUT and FLAG." + (if (and (if (eq flag 'case-replace) case-replace flag) + (let (case-fold-search) (string-match-p "\\`[[:upper:]]" input))) + (mapcar (apply-partially #'cape--case-replace flag input) strs) + strs)) + +(defun cape--case-replace (flag input str) + "Replace case of STR depending on INPUT and FLAG." + (or (and (if (eq flag 'case-replace) case-replace flag) + (string-prefix-p input str t) + (let (case-fold-search) (string-match-p "\\`[[:upper:]]" input)) + (save-match-data + ;; Ensure that single character uppercase input does not lead to an + ;; all uppercase result. + (when (and (= (length input) 1) (> (length str) 1)) + (setq input (concat input (substring str 1 2)))) + (and (string-match input input) + (replace-match str nil nil input)))) + str)) + +(defun cape--separator-p (str) + "Return non-nil if input STR has a separator character. +Separator characters are used by completion styles like Orderless +to split filter words. In Corfu, the separator is configurable +via the variable `corfu-separator'." + (string-search (string ;; Support `corfu-separator' and Orderless + (or (and (bound-and-true-p corfu-mode) + (bound-and-true-p corfu-separator)) + ?\s)) + str)) + +(defmacro cape--silent (&rest body) + "Silence BODY." + (declare (indent 0)) + `(cl-letf ((inhibit-message t) + (message-log-max nil) + ((symbol-function #'minibuffer-message) #'ignore)) + (ignore-errors ,@body))) + +(defun cape--bounds (thing) + "Return bounds of THING." + (or (bounds-of-thing-at-point thing) (cons (point) (point)))) + +(defmacro cape--wrapped-table (wrap body) + "Create wrapped completion table, handle `completion--unquote'. +WRAP is the wrapper function. +BODY is the wrapping expression." + (declare (indent 1)) + `(lambda (str pred action) + (,@body + (let ((result (complete-with-action action table str pred))) + (when (and (eq action 'completion--unquote) (functionp (cadr result))) + (cl-callf ,wrap (cadr result))) + result)))) + +(defun cape--accept-all-table (table) + "Create completion TABLE which accepts all input." + (cape--wrapped-table cape--accept-all-table + (or (eq action 'lambda)))) + +(defun cape--passthrough-table (table) + "Create completion TABLE disabling any filtering." + (cape--wrapped-table cape--passthrough-table + (let (completion-ignore-case completion-regexp-list (_ (setq str "")))))) + +(defun cape--noninterruptible-table (table) + "Create non-interruptible completion TABLE." + (cape--wrapped-table cape--noninterruptible-table + (let (throw-on-input)))) + +(defun cape--silent-table (table) + "Create a new completion TABLE which is silent (no messages, no errors)." + (cape--wrapped-table cape--silent-table + (cape--silent))) + +(defun cape--nonessential-table (table) + "Mark completion TABLE as `non-essential'." + (let ((dir default-directory)) + (cape--wrapped-table cape--nonessential-table + (let ((default-directory dir) + (non-essential t)))))) + +(defvar cape--debug-length 5 + "Length of printed lists in `cape--debug-print'.") + +(defvar cape--debug-id 0 + "Completion table identifier.") + +(defun cape--debug-message (&rest msg) + "Print debug MSG." + (let ((inhibit-message t)) + (apply #'message msg))) + +(defun cape--debug-print (obj &optional full) + "Print OBJ as string, truncate lists if FULL is nil." + (cond + ((symbolp obj) (symbol-name obj)) + ((functionp obj) "#<function>") + ((proper-list-p obj) + (concat + "(" + (string-join + (mapcar #'cape--debug-print + (if full obj (take cape--debug-length obj))) + " ") + (if (and (not full) (length> obj cape--debug-length)) " ...)" ")"))) + (t (let ((print-level 2)) + (prin1-to-string obj))))) + +(defun cape--debug-table (table name beg end) + "Create completion TABLE with debug messages. +NAME is the name of the Capf, BEG and END are the input markers." + (lambda (str pred action) + (let ((result (complete-with-action action table str pred))) + (if (and (eq action 'completion--unquote) (functionp (cadr result))) + ;; See `cape--wrapped-table' + (cl-callf cape--debug-table (cadr result) name beg end) + (cape--debug-message + "%s(action=%S input=%s:%s:%S prefix=%S ignore-case=%S%s%s) => %s" + name + (pcase action + ('nil 'try) + ('t 'all) + ('lambda 'test) + (_ action)) + (+ beg 0) (+ end 0) (buffer-substring-no-properties beg end) + str completion-ignore-case + (if completion-regexp-list + (format " regexp=%s" (cape--debug-print completion-regexp-list t)) + "") + (if pred + (format " predicate=%s" (cape--debug-print pred)) + "") + (cape--debug-print result))) + result))) + +(cl-defun cape--properties-table (table &key category (sort t) strip &allow-other-keys) + "Create completion TABLE with properties. +CATEGORY is the optional completion category. +SORT should be nil to disable sorting. +STRIP means to strip all metadata." + ;; The metadata will be overridden if the category is non-nil, if the table is + ;; a function table or if sorting should be disabled for a non-nil + ;; non-function table. + (if (or category (functionp table) (and (not sort) table)) + (let ((metadata (and (not strip) + `(metadata + ,@(and category `((category . ,category))) + ,@(and (not sort) '((display-sort-function . identity) + (cycle-sort-function . identity))))))) + (lambda (str pred action) + (if (eq action 'metadata) + metadata + (complete-with-action action table str pred)))) + table)) + +(defun cape--dynamic-table (beg end fun) + "Create dynamic completion table from FUN with caching. +BEG and END are the input bounds. FUN is the function which +computes the candidates. FUN must return a pair of a predicate +function function and the list of candidates. The predicate is +passed new input and must return non-nil if the candidates are +still valid. + +It is only necessary to use this function if the set of +candidates is computed dynamically based on the input and not +statically determined. The behavior is similar but slightly +different to `completion-table-dynamic'. + +The difference to the builtins `completion-table-dynamic' and +`completion-table-with-cache' is that this function does not use +the prefix argument of the completion table to compute the +candidates. Instead it uses the input in the buffer between BEG +and END to FUN to compute the candidates. This way the dynamic +candidate computation is compatible with non-prefix completion +styles like `substring' or `orderless', which pass the empty +string as first argument to the completion table." + (let ((beg (copy-marker beg)) + (end (copy-marker end t)) + valid table) + (lambda (str pred action) + ;; Bail out early for `metadata' and `boundaries'. This is a pointless + ;; move because of caching, but we do it anyway in the hope that the + ;; profiler report looks less confusing, since the weight of the expensive + ;; FUN computation is moved to the `all-completions' action. Computing + ;; `all-completions' must surely be most expensive, so nobody will suspect + ;; a thing. + (unless (or (eq action 'metadata) (eq (car-safe action) 'boundaries)) + (let ((input (buffer-substring-no-properties beg end))) + (unless (and valid + (or (cape--separator-p input) + (funcall valid input))) + (let* (;; Reset in case `all-completions' is used inside FUN + completion-ignore-case completion-regexp-list + ;; Retrieve new state by calling FUN + (new (and (< beg end) (funcall fun input))) + ;; No interrupt during state update + throw-on-input) + (setq valid (car new) table (cdr new))))) + (complete-with-action action table str pred))))) + +;;;; Capfs + +;;;;; cape-history + +(declare-function ring-elements "ring") +(declare-function eshell-bol "eshell") +(declare-function comint-line-beginning-position "comint") +(defvar eshell-history-ring) +(defvar comint-input-ring) + +(defvar cape--history-properties + (list :company-kind (lambda (_) 'text) + :exclusive 'no) + "Completion extra properties for `cape-history'.") + +;;;###autoload +(defun cape-history (&optional interactive) + "Complete from Eshell, Comint or minibuffer history. +See also `consult-history' for a more flexible variant based on +`completing-read'. If INTERACTIVE is nil the function acts like a Capf." + (interactive (list t)) + (if interactive + (cape-interactive #'cape-history) + (let (history bol) + (cond + ((derived-mode-p 'eshell-mode) + (setq history eshell-history-ring + bol (static-if (< emacs-major-version 30) + (save-excursion (eshell-bol) (point)) + (line-beginning-position)))) + ((derived-mode-p 'comint-mode) + (setq history comint-input-ring + bol (comint-line-beginning-position))) + ((and (minibufferp) (not (eq minibuffer-history-variable t))) + (setq history (symbol-value minibuffer-history-variable) + bol (line-beginning-position)))) + (when (ring-p history) + (setq history (ring-elements history))) + (when history + `(,bol ,(point) + ,(cape--properties-table history :sort nil) + ,@cape--history-properties))))) + +;;;;; cape-file + +(defvar comint-unquote-function) +(defvar comint-requote-function) + +(defvar cape--file-properties + (list :annotation-function (lambda (s) (if (string-suffix-p "/" s) " Dir" " File")) + :company-kind (lambda (s) (if (string-suffix-p "/" s) 'folder 'file)) + :exclusive 'no) + "Completion extra properties for `cape-file'.") + +;;;###autoload +(defun cape-file (&optional interactive) + "Complete file name at point. +See the user option `cape-file-directory-must-exist'. +If INTERACTIVE is nil the function acts like a Capf." + (interactive (list t)) + (if interactive + (cape-interactive '(cape-file-directory-must-exist) #'cape-file) + (pcase-let* ((default-directory (pcase cape-file-directory + ('nil default-directory) + ((pred stringp) cape-file-directory) + (_ (funcall cape-file-directory)))) + (prefix (and cape-file-prefix + (looking-back + (concat + (regexp-opt (ensure-list cape-file-prefix) t) + "[^ \n\t]*") + (pos-bol)) + (match-end 1))) + (`(,beg . ,end) (if prefix + (cons prefix (point)) + (cape--bounds 'filename))) + (non-essential t) + (file (buffer-substring-no-properties beg end))) + (when (or prefix + (not cape-file-directory-must-exist) + (and (string-search "/" file) + (file-exists-p (file-name-directory file)))) + (unless (boundp 'comint-unquote-function) + (require 'comint)) + `(,beg ,end + ,(cape--nonessential-table + (completion-table-with-quoting + #'read-file-name-internal + comint-unquote-function + comint-requote-function)) + ,@(when (or prefix (string-match-p "./" file)) + '(:company-prefix-length t)) + ,@cape--file-properties))))) + +;;;;; cape-elisp-symbol + +(autoload 'elisp--company-kind "elisp-mode") +(autoload 'elisp--company-doc-buffer "elisp-mode") +(autoload 'elisp--company-doc-string "elisp-mode") +(autoload 'elisp--company-location "elisp-mode") + +(defvar cape--elisp-symbol-properties + (list :annotation-function #'cape--elisp-symbol-annotation + :exit-function #'cape--elisp-symbol-exit + :predicate #'cape--elisp-symbol-predicate + :company-kind #'elisp--company-kind + :company-doc-buffer #'elisp--company-doc-buffer + :company-docsig #'elisp--company-doc-string + :company-location #'elisp--company-location + :exclusive 'no) + "Completion extra properties for `cape-elisp-symbol'.") + +(defun cape--elisp-symbol-predicate (sym) + "Return t if SYM is bound, fbound or propertized." + (or (fboundp sym) (boundp sym) (symbol-plist sym))) + +(defun cape--elisp-symbol-exit (sym status) + "Wrap symbol SYM with `cape-elisp-symbol-wrapper' buffers. +STATUS is the exit status." + (when-let (((not (eq status 'exact))) + (c (cl-loop for (m . c) in cape-elisp-symbol-wrapper + if (derived-mode-p m) return c)) + ((or (not (derived-mode-p 'emacs-lisp-mode)) + ;; Inside comment or string + (let ((s (syntax-ppss))) (or (nth 3 s) (nth 4 s))))) + (x (if (stringp (car c)) (car c) (string (car c)))) + (y (if (stringp (cadr c)) (cadr c) (string (cadr c))))) + (save-excursion + (backward-char (length sym)) + (unless (save-excursion + (and (ignore-errors (or (backward-char (length x)) t)) + (looking-at-p (regexp-quote x)))) + (insert x))) + (unless (looking-at-p (regexp-quote y)) + (insert y)))) + +(defun cape--elisp-symbol-annotation (sym) + "Return kind of SYM." + (setq sym (intern-soft sym)) + (cond + ((special-form-p sym) " Special") + ((macrop sym) " Macro") + ((commandp sym) " Command") + ((fboundp sym) " Function") + ((custom-variable-p sym) " Custom") + ((boundp sym) " Variable") + ((featurep sym) " Feature") + ((facep sym) " Face") + (t " Symbol"))) + +;;;###autoload +(defun cape-elisp-symbol (&optional interactive) + "Complete Elisp symbol at point. +If INTERACTIVE is nil the function acts like a Capf." + (interactive (list t)) + (if interactive + ;; No cycling since it breaks the :exit-function. + (let (completion-cycle-threshold) + (cape-interactive #'cape-elisp-symbol)) + (pcase-let ((`(,beg . ,end) (cape--bounds 'symbol))) + (when (eq (char-after beg) ?') + (setq beg (1+ beg) end (max beg end))) + `(,beg ,end + ,(cape--properties-table obarray :category 'symbol) + ,@cape--elisp-symbol-properties)))) + +;;;;; cape-elisp-block + +(declare-function org-element-context "org-element") +(declare-function markdown-code-block-lang "ext:markdown-mode") + +(defun cape--inside-block-p (&rest langs) + "Return non-nil if inside LANGS code block." + (when-let ((face (get-text-property (point) 'face)) + (lang (or (and (if (listp face) + (memq 'org-block face) + (eq 'org-block face)) + (plist-get (cadr (org-element-context)) :language)) + (and (if (listp face) + (memq 'markdown-code-face face) + (eq 'markdown-code-face face)) + (save-excursion + (markdown-code-block-lang)))))) + (member lang langs))) + +;;;###autoload +(defun cape-elisp-block (&optional interactive) + "Complete Elisp in Org or Markdown code block. +This Capf is particularly useful for literate Emacs configurations. +If INTERACTIVE is nil the function acts like a Capf." + (interactive (list t)) + (cond + (interactive + ;; No code block check. Always complete Elisp when command was + ;; explicitly invoked interactively. + (cape-interactive #'elisp-completion-at-point)) + ((cape--inside-block-p "elisp" "emacs-lisp") + (elisp-completion-at-point)))) + +;;;;; cape-dabbrev + +(defvar cape--dabbrev-properties + (list :annotation-function (lambda (_) " Dabbrev") + :company-kind (lambda (_) 'text) + :exclusive 'no) + "Completion extra properties for `cape-dabbrev'.") + +(defvar dabbrev-case-replace) +(defvar dabbrev-case-fold-search) +(defvar dabbrev-abbrev-char-regexp) +(defvar dabbrev-abbrev-skip-leading-regexp) +(declare-function dabbrev--find-all-expansions "dabbrev") +(declare-function dabbrev--reset-global-variables "dabbrev") + +(defun cape--dabbrev-list (input) + "Find all Dabbrev expansions for INPUT." + (cape--silent + (let* ((chk cape-dabbrev-check-other-buffers) + (funp (and (not (memq chk '(nil t some))) (functionp chk)))) + (dlet ((dabbrev-check-other-buffers (and chk (not funp))) + (dabbrev-check-all-buffers (eq chk t)) + (dabbrev-search-these-buffers-only (and funp (funcall chk)))) + (dabbrev--reset-global-variables) + (cons + (apply-partially #'string-prefix-p input) + (cl-loop with min-len = (+ cape-dabbrev-min-length (length input)) + with ic = (cape--case-fold-p dabbrev-case-fold-search) + for w in (dabbrev--find-all-expansions input ic) + if (>= (length w) min-len) collect + (cape--case-replace (and ic dabbrev-case-replace) input w))))))) + +(defun cape--dabbrev-bounds () + "Return bounds of abbreviation." + (unless (boundp 'dabbrev-abbrev-char-regexp) + (require 'dabbrev)) + (let ((re (or dabbrev-abbrev-char-regexp "\\sw\\|\\s_")) + (limit (minibuffer-prompt-end))) + (when (or (looking-at re) + (and (> (point) limit) + (save-excursion (forward-char -1) (looking-at re)))) + (cons (save-excursion + (while (and (> (point) limit) + (save-excursion (forward-char -1) (looking-at re))) + (forward-char -1)) + (when dabbrev-abbrev-skip-leading-regexp + (while (looking-at dabbrev-abbrev-skip-leading-regexp) + (forward-char 1))) + (point)) + (save-excursion + (while (looking-at re) + (forward-char 1)) + (point)))))) + +;;;###autoload +(defun cape-dabbrev (&optional interactive) + "Complete with Dabbrev at point. + +If INTERACTIVE is nil the function acts like a Capf. In case you +observe a performance issue with auto-completion and `cape-dabbrev' +it is strongly recommended to disable scanning in other buffers. +See the user options `cape-dabbrev-min-length' and +`cape-dabbrev-check-other-buffers'." + (interactive (list t)) + (if interactive + (cape-interactive '((cape-dabbrev-min-length 0)) #'cape-dabbrev) + (when-let ((bounds (cape--dabbrev-bounds))) + `(,(car bounds) ,(cdr bounds) + ,(cape--properties-table + (completion-table-case-fold + (cape--dynamic-table (car bounds) (cdr bounds) #'cape--dabbrev-list) + (not (cape--case-fold-p dabbrev-case-fold-search))) + :category 'cape-dabbrev) + ,@cape--dabbrev-properties)))) + +;;;;; cape-dict + +(defvar cape--dict-properties + (list :annotation-function (lambda (_) " Dict") + :company-kind (lambda (_) 'text) + :exclusive 'no) + "Completion extra properties for `cape-dict'.") + +(defun cape--dict-list (input) + "Return all words from `cape-dict-file' matching INPUT." + (let* ((inhibit-message t) + (message-log-max nil) + (default-directory + (if (and (not (file-remote-p default-directory)) + (file-directory-p default-directory)) + default-directory + user-emacs-directory)) + (files (mapcar #'expand-file-name + (ensure-list + (if (functionp cape-dict-file) + (funcall cape-dict-file) + cape-dict-file)))) + (words + (apply #'process-lines-ignore-status + "grep" + (concat "-Fh" + (and (cape--case-fold-p cape-dict-case-fold) "i") + (and cape-dict-limit (format "m%d" cape-dict-limit))) + input files))) + (cons + (apply-partially + (if (and cape-dict-limit (length= words cape-dict-limit)) + #'equal #'string-search) + input) + (cape--case-replace-list cape-dict-case-replace input words)))) + +;;;###autoload +(defun cape-dict (&optional interactive) + "Complete word from dictionary at point. +This completion function works best if the dictionary is sorted +by frequency. See the custom option `cape-dict-file'. If +INTERACTIVE is nil the function acts like a Capf." + (interactive (list t)) + (if interactive + (cape-interactive #'cape-dict) + (pcase-let ((`(,beg . ,end) (cape--bounds 'word))) + `(,beg ,end + ,(cape--properties-table + (completion-table-case-fold + (cape--dynamic-table beg end #'cape--dict-list) + (not (cape--case-fold-p cape-dict-case-fold))) + :sort nil ;; Presorted word list (by frequency) + :category 'cape-dict) + ,@cape--dict-properties)))) + +;;;;; cape-abbrev + +(defun cape--abbrev-list () + "Abbreviation list." + (delete "" (cl-loop for x in (abbrev--suggest-get-active-tables-including-parents) + nconc (all-completions "" x)))) + +(defun cape--abbrev-annotation (abbrev) + "Annotate ABBREV with expansion." + (concat " " + (truncate-string-to-width + (format + "%s" + (symbol-value + (cl-loop for x in (abbrev--suggest-get-active-tables-including-parents) + thereis (abbrev--symbol abbrev x)))) + 30 0 nil t))) + +(defun cape--abbrev-exit (_str status) + "Expand expansion if STATUS is not exact." + (unless (eq status 'exact) + (expand-abbrev))) + +(defvar cape--abbrev-properties + (list :annotation-function #'cape--abbrev-annotation + :exit-function #'cape--abbrev-exit + :company-kind (lambda (_) 'snippet) + :exclusive 'no) + "Completion extra properties for `cape-abbrev'.") + +;;;###autoload +(defun cape-abbrev (&optional interactive) + "Complete abbreviation at point. +If INTERACTIVE is nil the function acts like a Capf." + (interactive (list t)) + (if interactive + ;; No cycling since it breaks the :exit-function. + (let (completion-cycle-threshold) + (cape-interactive #'cape-abbrev)) + (when-let (abbrevs (cape--abbrev-list)) + (let ((bounds (cape--bounds 'symbol))) + `(,(car bounds) ,(cdr bounds) + ,(cape--properties-table abbrevs :category 'cape-abbrev) + ,@cape--abbrev-properties))))) + +;;;;; cape-line + +(defvar cape--line-properties nil + "Completion extra properties for `cape-line'.") + +(defun cape--buffers-major-mode () + "Return buffers with same major mode as current buffer." + (cl-loop for buf in (buffer-list) + if (eq major-mode (buffer-local-value 'major-mode buf)) + collect buf)) + +(defun cape--line-list () + "Return all lines from buffer." + (let ((ht (make-hash-table :test #'equal)) + (curr-buf (current-buffer)) + (buffers (funcall cape-line-buffer-function)) + lines) + (dolist (buf (ensure-list buffers)) + (with-current-buffer buf + (let ((beg (point-min)) + (max (point-max)) + (pt (if (eq curr-buf buf) (point) -1)) + end) + (save-excursion + (while (< beg max) + (goto-char beg) + (setq end (pos-eol)) + (unless (<= beg pt end) + (let ((line (buffer-substring-no-properties beg end))) + (unless (or (string-blank-p line) (gethash line ht)) + (puthash line t ht) + (push line lines)))) + (setq beg (1+ end))))))) + (nreverse lines))) + +;;;###autoload +(defun cape-line (&optional interactive) + "Complete current line from other lines. +The buffers returned by `cape-line-buffer-function' are scanned for lines. +If INTERACTIVE is nil the function acts like a Capf." + (interactive (list t)) + (if interactive + (cape-interactive #'cape-line) + `(,(pos-bol) ,(point) + ,(cape--properties-table (cape--line-list) :sort nil) + ,@cape--line-properties))) + +;;;; Capf combinators + +(defun cape--company-call (&rest app) + "Apply APP and handle future return values." + ;; Backends are non-interruptible. Disable interrupts! + (let ((toi throw-on-input) + (throw-on-input nil)) + (pcase (apply app) + ;; Handle async future return values. + (`(:async . ,fetch) + (let ((res 'cape--waiting)) + (if toi + (unwind-protect + (progn + (funcall fetch + (lambda (arg) + (when (eq res 'cape--waiting) + (push 'cape--done unread-command-events) + (setq res arg)))) + (when (eq res 'cape--waiting) + (let ((ev (let ((input-method-function nil) + (echo-keystrokes 0)) + (read-event nil t)))) + (unless (eq ev 'cape--done) + (push (cons t ev) unread-command-events) + (setq res 'cape--cancelled) + (throw toi t))))) + (setq unread-command-events + (delq 'cape--done unread-command-events))) + (funcall fetch (lambda (arg) (setq res arg))) + ;; Force synchronization, not interruptible! We use polling + ;; here and ignore pending input since we don't use + ;; `sit-for'. This is the same method used by Company itself. + (while (eq res 'cape--waiting) + (sleep-for 0.01))) + res)) + ;; Plain old synchronous return value. + (res res)))) + +(defvar-local cape--company-init nil) + +;;;###autoload +(defun cape-company-to-capf (backend &optional valid) + "Convert Company BACKEND function to Capf. +VALID is a function taking the old and new input string. It should +return nil if the cached candidates became invalid. The default value +for VALID is `string-prefix-p' such that the candidates are only fetched +again if the input prefix changed." + (lambda () + (when (and (symbolp backend) (not (fboundp backend))) + (ignore-errors (require backend nil t))) + (when (bound-and-true-p company-mode) + (error "`cape-company-to-capf' should not be used with `company-mode', use the Company backend directly instead")) + (when (and (symbolp backend) (not (alist-get backend cape--company-init))) + (funcall backend 'init) + (put backend 'company-init t) + (setf (alist-get backend cape--company-init) t)) + (when-let ((prefix (cape--company-call backend 'prefix)) + (initial-input (if (stringp prefix) prefix (car-safe prefix)))) + (let* ((end (point)) (beg (- end (length initial-input))) + (valid (if (cape--company-call backend 'no-cache initial-input) + #'equal (or valid #'string-prefix-p))) + restore-props) + (list beg end + (funcall + (if (cape--company-call backend 'ignore-case) + #'completion-table-case-fold + #'identity) + (cape--properties-table + (cape--dynamic-table + beg end + (lambda (input) + (let ((cands (cape--company-call backend 'candidates input))) + ;; The candidate string including text properties should be + ;; restored in the :exit-function, unless the UI guarantees + ;; this itself, like Corfu. + (unless (bound-and-true-p corfu-mode) + (setq restore-props cands)) + (cons (apply-partially valid input) cands)))) + :category backend + :sort (not (cape--company-call backend 'sorted)))) + :exclusive 'no + :company-prefix-length (cdr-safe prefix) + :company-doc-buffer (lambda (x) (cape--company-call backend 'doc-buffer x)) + :company-location (lambda (x) (cape--company-call backend 'location x)) + :company-docsig (lambda (x) (cape--company-call backend 'meta x)) + :company-deprecated (lambda (x) (cape--company-call backend 'deprecated x)) + :company-kind (lambda (x) (cape--company-call backend 'kind x)) + :annotation-function (lambda (x) + (when-let (ann (cape--company-call backend 'annotation x)) + (concat " " (string-trim ann)))) + :exit-function (lambda (x _status) + ;; Restore the candidate string including + ;; properties if restore-props is non-nil. See + ;; the comment above. + (setq x (or (car (member x restore-props)) x)) + (cape--company-call backend 'post-completion x))))))) + +;;;###autoload +(defun cape-interactive (&rest capfs) + "Complete interactively with the given CAPFS." + (let* ((ctx (and (consp (car capfs)) (car capfs))) + (capfs (if ctx (cdr capfs) capfs)) + (completion-at-point-functions + (if ctx + (mapcar (lambda (f) `(lambda () (let ,ctx (funcall ',f)))) capfs) + capfs))) + (unless (completion-at-point) + (user-error "%s: No completions" + (mapconcat (lambda (fun) + (if (symbolp fun) + (symbol-name fun) + "anonymous-capf")) + capfs ", "))))) + +;;;###autoload +(defun cape-capf-interactive (capf) + "Create interactive completion function from CAPF." + (lambda (&optional interactive) + (interactive (list t)) + (if interactive (cape-interactive capf) (funcall capf)))) + +;;;###autoload +(defun cape-wrap-super (&rest capfs) + "Call CAPFS and return merged completion result. +The CAPFS list can contain the keyword `:with' to mark the Capfs +afterwards as auxiliary One of the non-auxiliary Capfs before +`:with' must return non-nil for the super Capf to set in and +return a non-nil result. Such behavior is useful when listing +multiple super Capfs in the `completion-at-point-functions': + + (setq completion-at-point-functions + (list (cape-capf-super \\='eglot-completion-at-point + :with \\='tempel-complete) + (cape-capf-super \\='cape-dabbrev + :with \\='tempel-complete)))" + (when-let ((results (cl-loop for capf in capfs until (eq capf :with) + for res = (funcall capf) + if res collect (cons t res)))) + (pcase-let* ((results (nconc results + (cl-loop for capf in (cdr (memq :with capfs)) + for res = (funcall capf) + if res collect (cons nil res)))) + (`((,_main ,beg ,end . ,_)) results) + (cand-ht nil) + (tables nil) + (exclusive nil) + (prefix-len nil) + (cand-functions + '(:company-docsig :company-location :company-kind + :company-doc-buffer :company-deprecated + :annotation-function :exit-function))) + (cl-loop for (main beg2 end2 table . plist) in results do + ;; Note: `cape-capf-super' currently cannot merge Capfs which + ;; trigger at different beginning positions. In order to support + ;; this, take the smallest BEG value and then normalize all + ;; candidates by prefixing them such that they all start at the + ;; smallest BEG position. + (when (= beg beg2) + (push (list main (plist-get plist :predicate) table + ;; Plist attached to the candidates + (mapcan (lambda (f) + (when-let ((v (plist-get plist f))) + (list f v))) + cand-functions)) + tables) + ;; The resulting merged Capf is exclusive if one of the main + ;; Capfs is exclusive. + (when (and main (not (eq (plist-get plist :exclusive) 'no))) + (setq exclusive t)) + (setq end (max end end2)) + (let ((plen (plist-get plist :company-prefix-length))) + (cond + ((eq plen t) + (setq prefix-len t)) + ((and (not prefix-len) (integerp plen)) + (setq prefix-len plen)) + ((and (integerp prefix-len) (integerp plen)) + (setq prefix-len (max prefix-len plen))))))) + (setq tables (nreverse tables)) + `(,beg ,end + ,(lambda (str pred action) + (pcase action + (`(boundaries . ,_) nil) + ('metadata + '(metadata (category . cape-super) + (display-sort-function . identity) + (cycle-sort-function . identity))) + ('t ;; all-completions + (let ((ht (make-hash-table :test #'equal)) + (candidates nil)) + (cl-loop for (main table-pred table cand-plist) in tables do + (let* ((pr (if (and table-pred pred) + (lambda (x) (and (funcall table-pred x) (funcall pred x))) + (or table-pred pred))) + (md (completion-metadata "" table pr)) + (sort (or (completion-metadata-get md 'display-sort-function) + #'identity)) + ;; Always compute candidates of the main Capf + ;; tables, which come first in the tables + ;; list. For the :with Capfs only compute + ;; candidates if we've already determined that + ;; main candidates are available. + (cands (when (or main (or exclusive cand-ht candidates)) + (funcall sort (all-completions str table pr))))) + ;; Handle duplicates with a hash table. + (cl-loop + for cand in-ref cands + for dup = (gethash cand ht t) do + (cond + ((eq dup t) + ;; Candidate does not yet exist. + (puthash cand cand-plist ht)) + ((not (equal dup cand-plist)) + ;; Duplicate candidate. Candidate plist is + ;; different, therefore disambiguate the + ;; candidates. + (setf cand (propertize cand 'cape-capf-super + (cons cand cand-plist)))))) + (when cands (push cands candidates)))) + (when (or cand-ht candidates) + (setq candidates (apply #'nconc (nreverse candidates)) + cand-ht ht) + candidates))) + (_ ;; try-completion and test-completion + (cl-loop for (_main table-pred table _cand-plist) in tables thereis + (complete-with-action + action table str + (if (and table-pred pred) + (lambda (x) (and (funcall table-pred x) (funcall pred x))) + (or table-pred pred))))))) + :company-prefix-length ,prefix-len + ,@(and (not exclusive) '(:exclusive no)) + ,@(mapcan + (lambda (prop) + (list prop + (lambda (cand &rest args) + (if-let ((ref (get-text-property 0 'cape-capf-super cand))) + (when-let ((fun (plist-get (cdr ref) prop))) + (apply fun (car ref) args)) + (when-let ((plist (and cand-ht (gethash cand cand-ht))) + (fun (plist-get plist prop))) + (apply fun cand args)))))) + cand-functions))))) + +;;;###autoload +(defun cape-wrap-debug (capf &optional name) + "Call CAPF and return a completion table which prints trace messages. +If CAPF is an anonymous lambda, pass the Capf NAME explicitly for +meaningful debugging output." + (unless name + (setq name (if (symbolp capf) capf "capf"))) + (setq name (format "%s@%s" name (cl-incf cape--debug-id))) + (pcase (funcall capf) + (`(,beg ,end ,table . ,plist) + (let* ((limit (1+ cape--debug-length)) + (pred (plist-get plist :predicate)) + (cands + ;; Reset regexps for `all-completions' + (let (completion-ignore-case completion-regexp-list) + (all-completions + "" table + (lambda (&rest args) + (and (or (not pred) (apply pred args)) (>= (cl-decf limit) 0)))))) + (plist-str "") + (plist-elt plist)) + (while (cdr plist-elt) + (setq plist-str (format "%s %s=%s" plist-str + (substring (symbol-name (car plist-elt)) 1) + (cape--debug-print (cadr plist-elt))) + plist-elt (cddr plist-elt))) + (cape--debug-message + "%s => input=%s:%s:%S table=%s%s" + name (+ beg 0) (+ end 0) (buffer-substring-no-properties beg end) + (cape--debug-print cands) + plist-str)) + `(,beg ,end ,(cape--debug-table + table name (copy-marker beg) (copy-marker end t)) + ,@(when-let ((exit (plist-get plist :exit-function))) + (list :exit-function + (lambda (cand status) + (cape--debug-message "%s:exit(candidate=%S status=%s)" + name cand status) + (funcall exit cand status)))) + . ,plist)) + (result + (cape--debug-message "%s() => %s (No completion)" + name (cape--debug-print result))))) + +;;;###autoload +(defun cape-wrap-buster (capf &optional valid) + "Call CAPF and return a completion table with cache busting. +This function can be used as an advice around an existing Capf. +The cache is busted when the input changes. The argument VALID +can be a function taking the old and new input string. It should +return nil if the new input requires that the completion table is +refreshed. The default value for VALID is `equal', such that the +completion table is refreshed on every input change." + (setq valid (or valid #'equal)) + (pcase (funcall capf) + (`(,beg ,end ,table . ,plist) + (setq plist `(:cape--buster t . ,plist)) + `(,beg ,end + ,(let* ((beg (copy-marker beg)) + (end (copy-marker end t)) + (input (buffer-substring-no-properties beg end))) + (lambda (str pred action) + (let ((new-input (buffer-substring-no-properties beg end))) + (unless (or (not (eq action t)) + (cape--separator-p new-input) + (funcall valid input new-input)) + (pcase + ;; Reset in case `all-completions' is used inside CAPF + (let (completion-ignore-case completion-regexp-list) + (funcall capf)) + ((and `(,new-beg ,new-end ,new-table . ,new-plist) + (guard (and (= beg new-beg) (= end new-end)))) + (let (throw-on-input) ;; No interrupt during state update + (setf table new-table + input new-input + (cddr plist) new-plist)))))) + (complete-with-action action table str pred))) + ,@plist)))) + +;;;###autoload +(defun cape-wrap-passthrough (capf) + "Call CAPF and make sure that no completion style filtering takes place." + (pcase (funcall capf) + (`(,beg ,end ,table . ,plist) + `(,beg ,end ,(cape--passthrough-table table) ,@plist)))) + +;;;###autoload +(defun cape-wrap-properties (capf &rest properties) + "Call CAPF and strip or add completion PROPERTIES. +Completion properties include for example :exclusive, +:annotation-function and the various :company-* extensions. Furthermore +a boolean :sort flag and a completion :category symbol can be specified. +The boolean :strip flag means to strip all completion properties." + (pcase (funcall capf) + (`(,beg ,end ,table . ,plist) + `(,beg ,end + ,(apply #'cape--properties-table table properties) + ,@(and (not (plist-get properties :strip)) + (append properties plist)))))) + +;;;###autoload +(defun cape-wrap-nonexclusive (capf) + "Call CAPF and ensure that it is marked as non-exclusive. +This function can be used as an advice around an existing Capf." + (cape-wrap-properties capf :exclusive 'no)) + +;;;###autoload +(defun cape-wrap-predicate (capf predicate) + "Call CAPF and add an additional candidate PREDICATE. +The PREDICATE is passed the candidate symbol or string." + (pcase (funcall capf) + (`(,beg ,end ,table . ,plist) + `(,beg ,end ,table + :predicate + ,(if-let (pred (plist-get plist :predicate)) + ;; First argument is key, second is value for hash tables. + ;; The first argument can be a cons cell for alists. Then + ;; the candidate itself is either a string or a symbol. We + ;; normalize the calling convention here such that PREDICATE + ;; always receives a string or a symbol. + (lambda (&rest args) + (when (apply pred args) + (setq args (car args)) + (funcall predicate (if (consp args) (car args) args)))) + (lambda (key &optional _val) + (funcall predicate (if (consp key) (car key) key)))) + ,@plist)))) + +;;;###autoload +(defun cape-wrap-silent (capf) + "Call CAPF and silence it (no messages, no errors). +This function can be used as an advice around an existing Capf." + (pcase (cape--silent (funcall capf)) + (`(,beg ,end ,table . ,plist) + `(,beg ,end ,(cape--silent-table table) ,@plist)))) + +;;;###autoload +(defun cape-wrap-case-fold (capf &optional nofold) + "Call CAPF and return a case-insensitive completion table. +If NOFOLD is non-nil return a case sensitive table instead. This +function can be used as an advice around an existing Capf." + (pcase (funcall capf) + (`(,beg ,end ,table . ,plist) + `(,beg ,end ,(completion-table-case-fold table nofold) ,@plist)))) + +;;;###autoload +(defun cape-wrap-noninterruptible (capf) + "Call CAPF and return a non-interruptible completion table. +This function can be used as an advice around an existing Capf." + (pcase (let (throw-on-input) (funcall capf)) + (`(,beg ,end ,table . ,plist) + `(,beg ,end ,(cape--noninterruptible-table table) ,@plist)))) + +;;;###autoload +(defun cape-wrap-prefix-length (capf length) + "Call CAPF and ensure that prefix length is greater or equal than LENGTH. +If the prefix is long enough, enforce auto completion." + (pcase (funcall capf) + (`(,beg ,end ,table . ,plist) + (when (>= (- end beg) length) + `(,beg ,end ,table + :company-prefix-length t + ,@plist))))) + +;;;###autoload +(defun cape-wrap-inside-faces (capf &rest faces) + "Call CAPF only if inside FACES. +This function can be used as an advice around an existing Capf." + (when-let (((> (point) (point-min))) + (fs (get-text-property (1- (point)) 'face)) + ((if (listp fs) + (cl-loop for f in fs thereis (memq f faces)) + (memq fs faces)))) + (funcall capf))) + +;;;###autoload +(defun cape-wrap-inside-code (capf) + "Call CAPF only if inside code, not inside a comment or string. +This function can be used as an advice around an existing Capf." + (let ((s (syntax-ppss))) + (and (not (nth 3 s)) (not (nth 4 s)) (funcall capf)))) + +;;;###autoload +(defun cape-wrap-inside-comment (capf) + "Call CAPF only if inside comment. +This function can be used as an advice around an existing Capf." + (and (nth 4 (syntax-ppss)) (funcall capf))) + +;;;###autoload +(defun cape-wrap-inside-string (capf) + "Call CAPF only if inside string. +This function can be used as an advice around an existing Capf." + (and (nth 3 (syntax-ppss)) (funcall capf))) + +;;;###autoload +(defun cape-wrap-purify (capf) + "Call CAPF and ensure that it does not illegally modify the buffer. +This function can be used as an advice around an existing +Capf. It has been introduced mainly to fix the broken +`pcomplete-completions-at-point' function in Emacs versions < 29." + ;; bug#50470: Fix Capfs which illegally modify the buffer or which illegally + ;; call `completion-in-region'. The workaround here was proposed by + ;; @jakanakaevangeli and is used in his capf-autosuggest package. In Emacs 29 + ;; the purity bug of Pcomplete has been fixed, such that make + ;; `cape-wrap-purify' is not necessary anymore. + (catch 'cape--illegal-completion-in-region + (condition-case nil + (let ((buffer-read-only t) + (inhibit-read-only nil) + (completion-in-region-function + (lambda (beg end coll pred) + (throw 'cape--illegal-completion-in-region + (list beg end coll :predicate pred))))) + (funcall capf)) + (buffer-read-only nil)))) + +;;;###autoload +(defun cape-wrap-accept-all (capf) + "Call CAPF and return a completion table which accepts every input. +This function can be used as an advice around an existing Capf." + (pcase (funcall capf) + (`(,beg ,end ,table . ,plist) + `(,beg ,end ,(cape--accept-all-table table) . ,plist)))) + +;;;###autoload (autoload 'cape-capf-accept-all "cape") +;;;###autoload (autoload 'cape-capf-buster "cape") +;;;###autoload (autoload 'cape-capf-case-fold "cape") +;;;###autoload (autoload 'cape-capf-debug "cape") +;;;###autoload (autoload 'cape-capf-inside-code "cape") +;;;###autoload (autoload 'cape-capf-inside-comment "cape") +;;;###autoload (autoload 'cape-capf-inside-faces "cape") +;;;###autoload (autoload 'cape-capf-inside-string "cape") +;;;###autoload (autoload 'cape-capf-nonexclusive "cape") +;;;###autoload (autoload 'cape-capf-noninterruptible "cape") +;;;###autoload (autoload 'cape-capf-passthrough "cape") +;;;###autoload (autoload 'cape-capf-predicate "cape") +;;;###autoload (autoload 'cape-capf-prefix-length "cape") +;;;###autoload (autoload 'cape-capf-properties "cape") +;;;###autoload (autoload 'cape-capf-purify "cape") +;;;###autoload (autoload 'cape-capf-silent "cape") +;;;###autoload (autoload 'cape-capf-super "cape") + +(dolist (wrapper (list #'cape-wrap-accept-all #'cape-wrap-buster + #'cape-wrap-case-fold #'cape-wrap-debug + #'cape-wrap-inside-code #'cape-wrap-inside-comment + #'cape-wrap-inside-faces #'cape-wrap-inside-string + #'cape-wrap-nonexclusive #'cape-wrap-noninterruptible + #'cape-wrap-passthrough #'cape-wrap-predicate + #'cape-wrap-prefix-length #'cape-wrap-properties + #'cape-wrap-purify #'cape-wrap-silent #'cape-wrap-super)) + (let ((name (string-remove-prefix "cape-wrap-" (symbol-name wrapper)))) + (defalias (intern (format "cape-capf-%s" name)) + (lambda (capf &rest args) (lambda () (apply wrapper capf args))) + (format "Create a %s Capf from CAPF. +The Capf calls `%s' with CAPF and ARGS as arguments." name wrapper)))) + +(defvar-keymap cape-prefix-map + :doc "Keymap used as completion entry point. +The keymap should be installed globally under a prefix." + "p" #'completion-at-point + "t" #'complete-tag + "d" #'cape-dabbrev + "h" #'cape-history + "f" #'cape-file + "s" #'cape-elisp-symbol + "e" #'cape-elisp-block + "a" #'cape-abbrev + "l" #'cape-line + "w" #'cape-dict + "k" 'cape-keyword + ":" 'cape-emoji + "\\" 'cape-tex + "_" 'cape-tex + "^" 'cape-tex + "&" 'cape-sgml + "r" 'cape-rfc1345) + +;;;###autoload (autoload 'cape-prefix-map "cape" nil t 'keymap) +(defalias 'cape-prefix-map cape-prefix-map) + +(provide 'cape) +;;; cape.el ends here diff --git a/emacs/elpa/cape-20241123.925/cape.elc b/emacs/elpa/cape-20241123.925/cape.elc Binary files differ. diff --git a/emacs/elpa/gptel-20241115.456/gptel-openai.el b/emacs/elpa/gptel-20241115.456/gptel-openai.el @@ -1,454 +0,0 @@ -;;; gptel-openai.el --- ChatGPT suppport for gptel -*- lexical-binding: t; -*- - -;; Copyright (C) 2023 Karthik Chikmagalur - -;; Author: Karthik Chikmagalur <karthikchikmagalur@gmail.com> - -;; 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 <https://www.gnu.org/licenses/>. - -;;; Commentary: - -;; This file adds support for the ChatGPT API to gptel - -;;; Code: -(require 'cl-generic) -(eval-when-compile - (require 'cl-lib)) -(require 'map) - -(defvar gptel-model) -(defvar gptel-stream) -(defvar gptel-use-curl) -(defvar gptel-backend) -(defvar gptel-temperature) -(defvar gptel-max-tokens) -(defvar gptel--system-message) -(defvar json-object-type) -(defvar gptel-mode) -(defvar gptel-track-response) -(defvar gptel-track-media) -(declare-function gptel-context--collect-media "gptel-context") -(declare-function gptel--base64-encode "gptel") -(declare-function gptel--trim-prefixes "gptel") -(declare-function gptel--parse-media-links "gptel") -(declare-function gptel--model-capable-p "gptel") -(declare-function gptel--model-name "gptel") -(declare-function gptel--get-api-key "gptel") -(declare-function prop-match-value "text-property-search") -(declare-function text-property-search-backward "text-property-search") -(declare-function json-read "json") -(declare-function gptel-prompt-prefix-string "gptel") -(declare-function gptel-response-prefix-string "gptel") -(declare-function gptel--merge-plists "gptel") -(declare-function gptel-context--wrap "gptel-context") - -(defmacro gptel--json-read () - (if (fboundp 'json-parse-buffer) - `(json-parse-buffer - :object-type 'plist - :null-object nil - :false-object :json-false) - (require 'json) - (defvar json-object-type) - (declare-function json-read "json" ()) - `(let ((json-object-type 'plist)) - (json-read)))) - -(defmacro gptel--json-encode (object) - (if (fboundp 'json-serialize) - `(json-serialize ,object - :null-object nil - :false-object :json-false) - (require 'json) - (defvar json-false) - (declare-function json-encode "json" (object)) - `(let ((json-false :json-false)) - (json-encode ,object)))) - -(defun gptel--process-models (models) - "Convert items in MODELS to symbols with appropriate properties." - (let ((models-processed)) - (dolist (model models) - (cl-etypecase model - (string (push (intern model) models-processed)) - (symbol (push model models-processed)) - (cons - (cl-destructuring-bind (name . props) model - (setf (symbol-plist name) - ;; MAYBE: Merging existing symbol plists is safer, but makes it - ;; difficult to reset a symbol plist, since removing keys from - ;; it (as opposed to setting them to nil) is more work. - ;; - ;; (map-merge 'plist (symbol-plist name) props) - props) - (push name models-processed))))) - (nreverse models-processed))) - -;;; Common backend struct for LLM support -(defvar gptel--known-backends nil - "Alist of LLM backends known to gptel. - -This is an alist mapping user-provided names to backend structs, -see `gptel-backend'. - -You can have more than one backend pointing to the same resource -with differing settings.") - -(cl-defstruct - (gptel-backend (:constructor gptel--make-backend) - (:copier gptel--copy-backend)) - name host header protocol stream - endpoint key models url request-params - curl-args) - -;;; OpenAI (ChatGPT) -(cl-defstruct (gptel-openai (:constructor gptel--make-openai) - (:copier nil) - (:include gptel-backend))) - -(cl-defmethod gptel-curl--parse-stream ((_backend gptel-openai) _info) - (let* ((content-strs)) - (condition-case nil - (while (re-search-forward "^data:" nil t) - (save-match-data - (unless (looking-at " *\\[DONE\\]") - (when-let* ((response (gptel--json-read)) - (delta (map-nested-elt - response '(:choices 0 :delta))) - (content (plist-get delta :content))) - (push content content-strs))))) - (error - (goto-char (match-beginning 0)))) - (apply #'concat (nreverse content-strs)))) - -(cl-defmethod gptel--parse-response ((_backend gptel-openai) response _info) - (map-nested-elt response '(:choices 0 :message :content))) - -(cl-defmethod gptel--request-data ((_backend gptel-openai) prompts) - "JSON encode PROMPTS for sending to ChatGPT." - (let ((prompts-plist - `(:model ,(gptel--model-name gptel-model) - :messages [,@prompts] - :stream ,(or (and gptel-stream gptel-use-curl - (gptel-backend-stream gptel-backend)) - :json-false)))) - (when gptel-temperature - (plist-put prompts-plist :temperature gptel-temperature)) - (when gptel-max-tokens - (plist-put prompts-plist :max_completion_tokens gptel-max-tokens)) - ;; Merge request params with model and backend params. - (gptel--merge-plists - prompts-plist - (gptel-backend-request-params gptel-backend) - (gptel--model-request-params gptel-model)))) - -(cl-defmethod gptel--parse-buffer ((_backend gptel-openai) &optional max-entries) - (let ((prompts) (prop) - (include-media (and gptel-track-media - (or (gptel--model-capable-p 'media) - (gptel--model-capable-p 'url))))) - (if (or gptel-mode gptel-track-response) - (while (and - (or (not max-entries) (>= max-entries 0)) - (setq prop (text-property-search-backward - 'gptel 'response - (when (get-char-property (max (point-min) (1- (point))) - 'gptel) - t)))) - (if (prop-match-value prop) ;assistant role - (push (list :role "assistant" - :content - (buffer-substring-no-properties (prop-match-beginning prop) - (prop-match-end prop))) - prompts) - (if include-media - (push (list :role "user" - :content - (gptel--openai-parse-multipart - (gptel--parse-media-links - major-mode (prop-match-beginning prop) (prop-match-end prop)))) - prompts) - (push (list :role "user" - :content - (gptel--trim-prefixes - (buffer-substring-no-properties (prop-match-beginning prop) - (prop-match-end prop)))) - prompts))) - (and max-entries (cl-decf max-entries))) - (push (list :role "user" - :content - (gptel--trim-prefixes (buffer-substring-no-properties (point-min) (point-max)))) - prompts)) - (if (and (not (gptel--model-capable-p 'nosystem)) - gptel--system-message) - (cons (list :role "system" - :content gptel--system-message) - prompts) - prompts))) - -;; TODO This could be a generic function -(defun gptel--openai-parse-multipart (parts) - "Convert a multipart prompt PARTS to the OpenAI API format. - -The input is an alist of the form - ((:text \"some text\") - (:media \"/path/to/media.png\" :mime \"image/png\") - (:text \"More text\")). - -The output is a vector of entries in a backend-appropriate -format." - (cl-loop - for part in parts - for n upfrom 1 - with last = (length parts) - for text = (plist-get part :text) - for media = (plist-get part :media) - if text do - (and (or (= n 1) (= n last)) (setq text (gptel--trim-prefixes text))) and - unless (string-empty-p text) - collect `(:type "text" :text ,text) into parts-array end - else if media - collect - `(:type "image_url" - :image_url (:url ,(concat "data:" (plist-get part :mime) - ";base64," (gptel--base64-encode media)))) - into parts-array end and - if (plist-get part :url) - collect - `(:type "image_url" - :image_url (:url ,(plist-get part :url))) - into parts-array - finally return (vconcat parts-array))) - -;; TODO: Does this need to be a generic function? -(cl-defmethod gptel--wrap-user-prompt ((_backend gptel-openai) prompts - &optional inject-media) - "Wrap the last user prompt in PROMPTS with the context string. - -If INJECT-MEDIA is non-nil wrap it with base64-encoded media -files in the context." - (if inject-media - ;; Wrap the first user prompt with included media files/contexts - (when-let ((media-list (gptel-context--collect-media))) - (cl-callf (lambda (current) - (vconcat - (gptel--openai-parse-multipart media-list) - (cl-typecase current - (string `((:type "text" :text ,current))) - (vector current) - (t current)))) - (plist-get (cadr prompts) :content))) - ;; Wrap the last user prompt with included text contexts - (cl-callf (lambda (current) - (cl-etypecase current - (string (gptel-context--wrap current)) - (vector (if-let ((wrapped (gptel-context--wrap nil))) - (vconcat `((:type "text" :text ,wrapped)) - current) - current)))) - (plist-get (car (last prompts)) :content)))) - -;;;###autoload -(cl-defun gptel-make-openai - (name &key curl-args models stream key request-params - (header - (lambda () (when-let (key (gptel--get-api-key)) - `(("Authorization" . ,(concat "Bearer " key)))))) - (host "api.openai.com") - (protocol "https") - (endpoint "/v1/chat/completions")) - "Register an OpenAI API-compatible backend for gptel with NAME. - -Keyword arguments: - -CURL-ARGS (optional) is a list of additional Curl arguments. - -HOST (optional) is the API host, typically \"api.openai.com\". - -MODELS is a list of available model names, as symbols. -Additionally, you can specify supported LLM capabilities like -vision or tool-use by appending a plist to the model with more -information, in the form - - (model-name . plist) - -For a list of currently recognized plist keys, see -`gptel--openai-models'. An example of a model specification -including both kinds of specs: - -:models -\\='(gpt-3.5-turbo ;Simple specs - gpt-4-turbo - (gpt-4o-mini ;Full spec - :description - \"Affordable and intelligent small model for lightweight tasks\" - :capabilities (media tool json url) - :mime-types - (\"image/jpeg\" \"image/png\" \"image/gif\" \"image/webp\"))) - -STREAM is a boolean to toggle streaming responses, defaults to -false. - -PROTOCOL (optional) specifies the protocol, https by default. - -ENDPOINT (optional) is the API endpoint for completions, defaults to -\"/v1/chat/completions\". - -HEADER (optional) is for additional headers to send with each -request. It should be an alist or a function that retuns an -alist, like: - ((\"Content-Type\" . \"application/json\")) - -KEY (optional) is a variable whose value is the API key, or -function that returns the key. - -REQUEST-PARAMS (optional) is a plist of additional HTTP request -parameters (as plist keys) and values supported by the API. Use -these to set parameters that gptel does not provide user options -for." - (declare (indent 1)) - (let ((backend (gptel--make-openai - :curl-args curl-args - :name name - :host host - :header header - :key key - :models (gptel--process-models models) - :protocol protocol - :endpoint endpoint - :stream stream - :request-params request-params - :url (if protocol - (concat protocol "://" host endpoint) - (concat host endpoint))))) - (prog1 backend - (setf (alist-get name gptel--known-backends - nil nil #'equal) - backend)))) - -;;; Azure -;;;###autoload -(cl-defun gptel-make-azure - (name &key curl-args host - (protocol "https") - (header (lambda () `(("api-key" . ,(gptel--get-api-key))))) - (key 'gptel-api-key) - models stream endpoint request-params) - "Register an Azure backend for gptel with NAME. - -Keyword arguments: - -CURL-ARGS (optional) is a list of additional Curl arguments. - -HOST is the API host. - -MODELS is a list of available model names, as symbols. - -STREAM is a boolean to toggle streaming responses, defaults to -false. - -PROTOCOL (optional) specifies the protocol, https by default. - -ENDPOINT is the API endpoint for completions. - -HEADER (optional) is for additional headers to send with each -request. It should be an alist or a function that retuns an -alist, like: - ((\"Content-Type\" . \"application/json\")) - -KEY (optional) is a variable whose value is the API key, or -function that returns the key. - -REQUEST-PARAMS (optional) is a plist of additional HTTP request -parameters (as plist keys) and values supported by the API. Use -these to set parameters that gptel does not provide user options -for. - -Example: -------- - - (gptel-make-azure - \"Azure-1\" - :protocol \"https\" - :host \"RESOURCE_NAME.openai.azure.com\" - :endpoint - \"/openai/deployments/DEPLOYMENT_NAME/completions?api-version=2023-05-15\" - :stream t - :models \\='(gpt-3.5-turbo gpt-4))" - (declare (indent 1)) - (let ((backend (gptel--make-openai - :curl-args curl-args - :name name - :host host - :header header - :key key - :models (gptel--process-models models) - :protocol protocol - :endpoint endpoint - :stream stream - :request-params request-params - :url (if protocol - (concat protocol "://" host endpoint) - (concat host endpoint))))) - (prog1 backend - (setf (alist-get name gptel--known-backends - nil nil #'equal) - backend)))) - -;; GPT4All -;;;###autoload -(defalias 'gptel-make-gpt4all 'gptel-make-openai - "Register a GPT4All backend for gptel with NAME. - -Keyword arguments: - -CURL-ARGS (optional) is a list of additional Curl arguments. - -HOST is where GPT4All runs (with port), typically localhost:4891 - -MODELS is a list of available model names, as symbols. - -STREAM is a boolean to toggle streaming responses, defaults to -false. - -PROTOCOL specifies the protocol, https by default. - -ENDPOINT (optional) is the API endpoint for completions, defaults to -\"/api/v1/completions\" - -HEADER (optional) is for additional headers to send with each -request. It should be an alist or a function that retuns an -alist, like: -((\"Content-Type\" . \"application/json\")) - -KEY (optional) is a variable whose value is the API key, or -function that returns the key. This is typically not required for -local models like GPT4All. - -REQUEST-PARAMS (optional) is a plist of additional HTTP request -parameters (as plist keys) and values supported by the API. Use -these to set parameters that gptel does not provide user options -for. - -Example: -------- - -(gptel-make-gpt4all - \"GPT4All\" - :protocol \"http\" - :host \"localhost:4891\" - :models \\='(mistral-7b-openorca.Q4_0.gguf))") - -(provide 'gptel-openai) -;;; gptel-openai.el ends here diff --git a/emacs/elpa/gptel-20241115.456/gptel-openai.elc b/emacs/elpa/gptel-20241115.456/gptel-openai.elc Binary files differ. diff --git a/emacs/elpa/gptel-20241115.456/gptel-pkg.el b/emacs/elpa/gptel-20241115.456/gptel-pkg.el @@ -1,12 +0,0 @@ -;; -*- no-byte-compile: t; lexical-binding: nil -*- -(define-package "gptel" "20241115.456" - "Interact with ChatGPT or other LLMs." - '((emacs "27.1") - (transient "0.4.0") - (compat "29.1.4.1")) - :url "https://github.com/karthink/gptel" - :commit "51ae43f4edefe0375acbcb836d94d8d0348a531d" - :revdesc "51ae43f4edef" - :keywords '("convenience") - :authors '(("Karthik Chikmagalur" . "karthik.chikmagalur@gmail.com")) - :maintainers '(("Karthik Chikmagalur" . "karthik.chikmagalur@gmail.com"))) diff --git a/emacs/elpa/gptel-20241115.456/gptel-rewrite.el b/emacs/elpa/gptel-20241115.456/gptel-rewrite.el @@ -1,433 +0,0 @@ -;;; gptel-rewrite.el --- Refactoring functions for gptel -*- lexical-binding: t; -*- - -;; Copyright (C) 2024 Karthik Chikmagalur - -;; Author: Karthik Chikmagalur <karthikchikmagalur@gmail.com> -;; Keywords: hypermedia, convenience, tools - -;; 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 <https://www.gnu.org/licenses/>. - -;;; Commentary: - -;; - -;;; Code: -(require 'gptel-transient) -(require 'cl-lib) - -(defvar eldoc-documentation-functions) -(defvar diff-entire-buffers) - -(declare-function diff-no-select "diff") - -;; * User options - -(defcustom gptel-rewrite-directives-hook (list #'gptel--rewrite-message) - "Hook run to generate gptel's default rewrite directives. - -Each function in this hook is called with no arguments until one -returns a non-nil value, the base string to use as the -rewrite/refactor instruction. - -Use this hook to tailor context-specific refactoring directives. -For example, you can specialize the default refactor directive -for a particular major-mode." - :group 'gptel - :type 'hook) - -(defface gptel-rewrite-highlight-face - '((((class color) (min-colors 88) (background dark)) - :background "#041714" :extend t) - (((class color) (min-colors 88) (background light)) - :background "light goldenrod yellow" :extend t) - (t :inherit secondary-selection)) - "Face for highlighting regions with pending rewrites." - :group 'gptel) - -;; * Variables - -(defvar-keymap gptel-rewrite-actions-map - :doc "Keymap for gptel rewrite actions at point." - "C-c C-k" #'gptel--rewrite-clear - "C-c C-a" #'gptel--rewrite-apply - "C-c C-d" #'gptel--rewrite-diff - "C-c C-e" #'gptel--rewrite-ediff - "C-c C-n" #'gptel--rewrite-next - "C-c C-p" #'gptel--rewrite-previous - "C-c C-m" #'gptel--rewrite-merge) - -(defvar-local gptel--rewrite-overlays nil - "List of active rewrite overlays in the buffer.") - -(defvar-local gptel--rewrite-message nil) - -;; * Helper functions - -(defun gptel--rewrite-sanitize-overlays () - "Ensure gptel's rewrite overlays in buffer are consistent." - (setq gptel--rewrite-overlays - (cl-delete-if-not #'overlay-buffer - gptel--rewrite-overlays))) - -(defsubst gptel--refactor-or-rewrite () - "Rewrite should be refactored into refactor. - -Or is it the other way around?" - (if (derived-mode-p 'prog-mode) - "Refactor" "Rewrite")) - -(defun gptel--rewrite-message () - "Set a generic refactor/rewrite message for the buffer." - (if (derived-mode-p 'prog-mode) - (format "You are a %s programmer. Generate only code, no explanation, no code fences. Refactor the following code." - (gptel--strip-mode-suffix major-mode)) - (format "You are a prose editor. Rewrite the following text to be more professional."))) - -(defun gptel--rewrite-key-help (callback) - "Eldoc documentation function for gptel rewrite actions. - -CALLBACK is supplied by Eldoc, see -`eldoc-documentation-functions'." - (when (and gptel--rewrite-overlays - (get-char-property (point) 'gptel-rewrite)) - (funcall callback - (format (substitute-command-keys "%s rewrite available: accept \\[gptel--rewrite-apply], clear \\[gptel--rewrite-clear], merge \\[gptel--rewrite-merge], diff \\[gptel--rewrite-diff] or ediff \\[gptel--rewrite-ediff]") - (propertize (concat (gptel-backend-name gptel-backend) - ":" (gptel--model-name gptel-model)) - 'face 'mode-line-emphasis))))) - -(defun gptel--rewrite-move (search-func) - "Move directionally to a gptel rewrite location using SEARCH-FUNC." - (let* ((ov (cdr (get-char-property-and-overlay (point) 'gptel-rewrite))) - (pt (save-excursion - (if ov - (goto-char - (funcall search-func (overlay-start ov) 'gptel-rewrite)) - (goto-char - (max (1- (funcall search-func (point) 'gptel-rewrite)) - (point-min)))) - (funcall search-func (point) 'gptel-rewrite)))) - (if (get-char-property pt 'gptel-rewrite) - (goto-char pt) - (user-error "No further rewrite regions!")))) - -(defun gptel--rewrite-next () - "Go to next pending LLM rewrite in buffer, if one exists." - (interactive) - (gptel--rewrite-move #'next-single-char-property-change)) - -(defun gptel--rewrite-previous () - "Go to previous pending LLM rewrite in buffer, if one exists." - (interactive) - (gptel--rewrite-move #'previous-single-char-property-change)) - -(defun gptel--rewrite-overlay-at (&optional pt) - "Check for a gptel rewrite overlay at PT and return it. - -If no suitable overlay is found, raise an error." - (pcase-let ((`(,response . ,ov) - (get-char-property-and-overlay (or pt (point)) 'gptel-rewrite)) - (diff-entire-buffers nil)) - (unless ov (user-error "Could not find region being rewritten.")) - (unless response (user-error "No LLM output available for this rewrite.")) - ov)) - -(defun gptel--rewrite-prepare-buffer (ovs &optional buf) - "Prepare new buffer with LLM changes applied and return it. - -This is used for (e)diff purposes. - -RESPONSE is the LLM response. OVS are the overlays specifying -the changed regions. BUF is the (current) buffer." - (setq buf (or buf (current-buffer))) - (with-current-buffer buf - (let ((pmin (point-min)) - (pmax (point-max)) - (pt (point)) - ;; (mode major-mode) - (newbuf (get-buffer-create "*gptel-diff*")) - (inhibit-read-only t) - (inhibit-message t)) - (save-restriction - (widen) - (with-current-buffer newbuf - (erase-buffer) - (insert-buffer-substring buf))) - (with-current-buffer newbuf - (narrow-to-region pmin pmax) - (goto-char pt) - ;; We mostly just want font-locking - ;; (delay-mode-hooks (funcall mode)) - ;; Apply the changes to the new buffer - (save-excursion - (gptel--rewrite-apply ovs))) - newbuf))) - -;; * Refactor action functions - -(defun gptel--rewrite-clear (&optional ovs) - "Clear pending LLM responses in OVS or at point." - (interactive (list (gptel--rewrite-overlay-at))) - (dolist (ov (ensure-list ovs)) - (setq gptel--rewrite-overlays (delq ov gptel--rewrite-overlays)) - (delete-overlay ov)) - (unless gptel--rewrite-overlays - (remove-hook 'eldoc-documentation-functions 'gptel--rewrite-key-help 'local)) - (message "Cleared pending LLM response(s).")) - -(defun gptel--rewrite-apply (&optional ovs) - "Apply pending LLM responses in OVS or at point." - (interactive (list (gptel--rewrite-overlay-at))) - (cl-loop for ov in (ensure-list ovs) - for ov-beg = (overlay-start ov) - for ov-end = (overlay-end ov) - for response = (overlay-get ov 'gptel-rewrite) - do (overlay-put ov 'before-string nil) - (goto-char ov-beg) - (delete-region ov-beg ov-end) - (insert response)) - (message "Replaced region(s) with LLM output.")) - -(defun gptel--rewrite-diff (&optional ovs switches) - "Diff pending LLM responses in OVS or at point." - (interactive (list (gptel--rewrite-overlay-at))) - (let* ((buf (current-buffer)) - (newbuf (gptel--rewrite-prepare-buffer ovs)) - (diff-buf (diff-no-select - (if-let ((buf-file (buffer-file-name buf))) - (expand-file-name buf-file) buf) - newbuf switches))) - (with-current-buffer diff-buf - (setq-local diff-jump-to-old-file t)) - (display-buffer diff-buf))) - -(defun gptel--rewrite-ediff (&optional ovs) - "Ediff pending LLM responses in OVS or at point." - (interactive (list (gptel--rewrite-overlay-at))) - (letrec ((newbuf (gptel--rewrite-prepare-buffer ovs)) - (cwc (current-window-configuration)) - (gptel--ediff-restore - (lambda () - (when (window-configuration-p cwc) - (set-window-configuration cwc)) - (remove-hook 'ediff-quit-hook gptel--ediff-restore)))) - (add-hook 'ediff-quit-hook gptel--ediff-restore) - (ediff-buffers (current-buffer) newbuf))) - -(defun gptel--rewrite-merge (&optional ovs) - "Insert pending LLM responses in OVS as merge conflicts." - (interactive (list (gptel--rewrite-overlay-at))) - (let ((changed)) - (dolist (ov (ensure-list ovs)) - (save-excursion - (when-let (new-str (overlay-get ov 'gptel-rewrite)) - ;; Insert merge - (goto-char (overlay-start ov)) - (unless (bolp) (insert "\n")) - (insert-before-markers "<<<<<<< original\n") - (goto-char (overlay-end ov)) - (unless (bolp) (insert "\n")) - (insert - "=======\n" new-str - "\n>>>>>>> " (gptel-backend-name gptel-backend) "\n") - (setq changed t)))) - (when changed (smerge-mode 1))) - (gptel--rewrite-clear ovs)) - -;; * Transient Prefix for rewriting/refactoring - -;;;###autoload (autoload 'gptel-rewrite-menu "gptel-rewrite" nil t) -(transient-define-prefix gptel-rewrite-menu () - "Rewrite or refactor text region using an LLM." - [:description - (lambda () - (format "Directive: %s" - (truncate-string-to-width - gptel--rewrite-message - (max (- (window-width) 14) 20) nil nil t))) - (gptel--infix-rewrite-prompt)] - ;; FIXME: We are requiring `gptel-transient' because of this suffix, perhaps - ;; we can get find some way around that? - [:description (lambda () (concat "Context for " (gptel--refactor-or-rewrite))) - :if use-region-p - (gptel--suffix-context-buffer :key "C")] - [[:description "Diff Options" - :if (lambda () gptel--rewrite-overlays) - ("-b" "Ignore whitespace changes" ("-b" "--ignore-space-change")) - ("-w" "Ignore all whitespace" ("-w" "--ignore-all-space")) - ("-i" "Ignore case" ("-i" "--ignore-case")) - (gptel--rewrite-infix-diff:-U)] - [:description gptel--refactor-or-rewrite - :if use-region-p - (gptel--suffix-rewrite)]] - [[:description (lambda () (concat "Diff " (gptel--refactor-or-rewrite) "s")) - :if (lambda () gptel--rewrite-overlays) - (gptel--suffix-rewrite-diff) - (gptel--suffix-rewrite-ediff)] - [:description (lambda () (concat "Continue " (gptel--refactor-or-rewrite) "s")) - :if (lambda () (gptel--rewrite-sanitize-overlays)) - (gptel--suffix-rewrite-merge) - (gptel--suffix-rewrite-apply)] - [:description (lambda () (concat "Reject " (gptel--refactor-or-rewrite) "s")) - :if (lambda () (gptel--rewrite-sanitize-overlays)) - (gptel--suffix-rewrite-clear)]] - (interactive) - (unless gptel--rewrite-message - (setq gptel--rewrite-message - (save-mark-and-excursion - (run-hook-with-args-until-success - 'gptel-rewrite-directives-hook)))) - (transient-setup 'gptel-rewrite-menu)) - -;; * Transient infixes for rewriting/refactoring - -(transient-define-infix gptel--infix-rewrite-prompt () - "Chat directive (system message) to use for rewriting or refactoring." - :description (lambda () (if (derived-mode-p 'prog-mode) - "Set directives for refactor" - "Set directives for rewrite")) - :format "%k %d" - :class 'transient-lisp-variable - :variable 'gptel--rewrite-message - :key "d" - :prompt "Set directive for rewrite: " - :reader (lambda (prompt _ history) - (read-string - prompt - (save-mark-and-excursion - (run-hook-with-args-until-success - 'gptel-rewrite-directives-hook)) - history))) - -(transient-define-argument gptel--rewrite-infix-diff:-U () - :description "Context lines" - :class 'transient-option - :argument "-U" - :reader #'transient-read-number-N0) - -;; * Transient suffixes for rewriting/refactoring - -(transient-define-suffix gptel--suffix-rewrite (&optional rewrite-message) - "Rewrite or refactor region contents." - :key "r" - :description #'gptel--refactor-or-rewrite - (interactive (list gptel--rewrite-message)) - (let* ((prompt (buffer-substring-no-properties - (region-beginning) (region-end))) - (gptel--system-message (or rewrite-message gptel--rewrite-message)) - ;; always send context with system message - (gptel-use-context (and gptel-use-context 'system))) - (deactivate-mark) - (gptel-request prompt - :context - (let ((ov (make-overlay (region-beginning) (region-end)))) - (overlay-put ov 'category 'gptel) - (overlay-put ov 'evaporate t) - ov) - :callback - (lambda (response info) - (if (not response) - (message (concat "LLM response error: %s. Rewrite/refactor in buffer %s canceled." - (propertize "❌" 'face 'error)) - (plist-get info :status) - (plist-get info :buffer)) - ;; Store response - (let ((buf (plist-get info :buffer)) - (ov (plist-get info :context)) - (action-str) (hint-str)) - (with-current-buffer buf - (if (derived-mode-p 'prog-mode) - (progn - (setq action-str "refactor") - (when (string-match-p "^```" response) - (setq response (replace-regexp-in-string "^```.*$" "" response)))) - (setq action-str "rewrite")) - (setq hint-str (concat "[" (gptel-backend-name gptel-backend) - ":" (gptel--model-name gptel-model) "] " - (upcase action-str) " READY ✓\n")) - (add-hook 'eldoc-documentation-functions #'gptel--rewrite-key-help nil 'local) - (overlay-put ov 'gptel-rewrite response) - (overlay-put ov 'face 'gptel-rewrite-highlight-face) - (overlay-put ov 'keymap gptel-rewrite-actions-map) - (overlay-put ov 'before-string - (concat (propertize - " " 'display `(space :align-to (- right ,(1+ (length hint-str))))) - (propertize hint-str 'face 'success))) - (overlay-put - ov 'help-echo - (format "%s rewrite available: -- accept \\[gptel--rewrite-apply], -- clear \\[gptel--rewrite-clear], -- merge \\[gptel--accept-merge], -- diff \\[gptel--rewrite-diff], -- ediff \\[gptel--rewrite-ediff]" - (propertize (concat (gptel-backend-name gptel-backend) - ":" (gptel--model-name gptel-model))))) - (push ov gptel--rewrite-overlays)) - ;; Message user - (message - (concat - "LLM %s output" - (unless (eq (current-buffer) buf) (format " in buffer %s " buf)) - (substitute-command-keys " ready, \\[gptel-menu] to continue.")) - action-str))))))) - -(transient-define-suffix gptel--suffix-rewrite-diff (&optional switches) - "Diff LLM output against buffer." - :if (lambda () gptel--rewrite-overlays) - :key "D" - :description (concat "Diff LLM " (downcase (gptel--refactor-or-rewrite)) "s") - (interactive (list (transient-args transient-current-command))) - (gptel--rewrite-diff gptel--rewrite-overlays switches)) - -(transient-define-suffix gptel--suffix-rewrite-ediff () - "Ediff LLM output against buffer." - :if (lambda () gptel--rewrite-overlays) - :key "E" - :description (concat "Ediff LLM " (downcase (gptel--refactor-or-rewrite)) "s") - (interactive) - (gptel--rewrite-ediff gptel--rewrite-overlays)) - -(transient-define-suffix gptel--suffix-rewrite-merge () - "Insert LLM output as merge conflicts" - :if (lambda () gptel--rewrite-overlays) - :key "cm" - :description "Accept as merge conflicts" - (interactive) - (gptel--rewrite-merge gptel--rewrite-overlays)) - -(transient-define-suffix gptel--suffix-rewrite-apply () - "Accept pending LLM rewrites." - :if (lambda () gptel--rewrite-overlays) - :key "ca" - :description "Accept in-place" - (interactive) - (gptel--rewrite-apply gptel--rewrite-overlays)) - -(transient-define-suffix gptel--suffix-rewrite-clear () - "Clear pending LLM rewrites." - :if (lambda () gptel--rewrite-overlays) - :key "ck" - :description (concat "Clear pending " - (downcase (gptel--refactor-or-rewrite)) - "s") - (interactive) - (gptel--rewrite-clear gptel--rewrite-overlays)) - -(provide 'gptel-rewrite) -;;; gptel-rewrite.el ends here - -;; Local Variables: -;; outline-regexp: "^;; \\*+" -;; End: diff --git a/emacs/elpa/gptel-20241115.456/gptel-rewrite.elc b/emacs/elpa/gptel-20241115.456/gptel-rewrite.elc Binary files differ. diff --git a/emacs/elpa/gptel-20241115.456/gptel-transient.elc b/emacs/elpa/gptel-20241115.456/gptel-transient.elc Binary files differ. diff --git a/emacs/elpa/gptel-20241115.456/gptel.el b/emacs/elpa/gptel-20241115.456/gptel.el @@ -1,1888 +0,0 @@ -;;; gptel.el --- Interact with ChatGPT or other LLMs -*- lexical-binding: t; -*- - -;; Copyright (C) 2023 Karthik Chikmagalur - -;; Author: Karthik Chikmagalur <karthik.chikmagalur@gmail.com> -;; Package-Version: 20241115.456 -;; Package-Revision: 51ae43f4edef -;; Package-Requires: ((emacs "27.1") (transient "0.4.0") (compat "29.1.4.1")) -;; Keywords: convenience -;; URL: https://github.com/karthink/gptel - -;; SPDX-License-Identifier: GPL-3.0-or-later - -;; 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 <https://www.gnu.org/licenses/>. - -;; This file is NOT part of GNU Emacs. - -;;; Commentary: - -;; gptel is a simple Large Language Model chat client, with support for multiple -;; models and backends. -;; -;; It works in the spirit of Emacs, available at any time and in any buffer. -;; -;; gptel supports -;; -;; - The services ChatGPT, Azure, Gemini, Anthropic AI, Anyscale, Together.ai, -;; Perplexity, Anyscale, OpenRouter, Groq, PrivateGPT, DeepSeek, Cerebras, -;; Github Models and Kagi (FastGPT & Summarizer) -;; - Local models via Ollama, Llama.cpp, Llamafiles or GPT4All -;; -;; Additionally, any LLM service (local or remote) that provides an -;; OpenAI-compatible API is supported. -;; -;; Features: -;; - It’s async and fast, streams responses. -;; - Interact with LLMs from anywhere in Emacs (any buffer, shell, minibuffer, -;; wherever) -;; - LLM responses are in Markdown or Org markup. -;; - Supports conversations and multiple independent sessions. -;; - Supports multi-modal models (send images, documents). -;; - Save chats as regular Markdown/Org/Text files and resume them later. -;; - You can go back and edit your previous prompts or LLM responses when -;; continuing a conversation. These will be fed back to the model. -;; - Redirect prompts and responses easily -;; - Rewrite, refactor or fill in regions in buffers -;; - Write your own commands for custom tasks with a simple API. -;; -;; Requirements for ChatGPT, Azure, Gemini or Kagi: -;; -;; - You need an appropriate API key. Set the variable `gptel-api-key' to the -;; key or to a function of no arguments that returns the key. (It tries to -;; use `auth-source' by default) -;; -;; ChatGPT is configured out of the box. For the other sources: -;; -;; - For Azure: define a gptel-backend with `gptel-make-azure', which see. -;; - For Gemini: define a gptel-backend with `gptel-make-gemini', which see. -;; - For Anthropic (Claude): define a gptel-backend with `gptel-make-anthropic', -;; which see -;; - For Together.ai, Anyscale, Perplexity, Groq, OpenRouter, DeepSeek, Cerebras or -;; Github Models: define a gptel-backend with `gptel-make-openai', which see. -;; - For PrivateGPT: define a backend with `gptel-make-privategpt', which see. -;; - For Kagi: define a gptel-backend with `gptel-make-kagi', which see. -;; -;; For local models using Ollama, Llama.cpp or GPT4All: -;; -;; - The model has to be running on an accessible address (or localhost) -;; - Define a gptel-backend with `gptel-make-ollama' or `gptel-make-gpt4all', -;; which see. -;; - Llama.cpp or Llamafiles: Define a gptel-backend with `gptel-make-openai', -;; -;; Consult the package README for examples and more help with configuring -;; backends. -;; -;; Usage: -;; -;; gptel can be used in any buffer or in a dedicated chat buffer. The -;; interaction model is simple: Type in a query and the response will be -;; inserted below. You can continue the conversation by typing below the -;; response. -;; -;; To use this in any buffer: -;; -;; - Call `gptel-send' to send the buffer's text up to the cursor. Select a -;; region to send only the region. -;; -;; - You can select previous prompts and responses to continue the conversation. -;; -;; - Call `gptel-send' with a prefix argument to access a menu where you can set -;; your backend, model and other parameters, or to redirect the -;; prompt/response. -;; -;; To use this in a dedicated buffer: -;; -;; - M-x gptel: Start a chat session -;; -;; - In the chat session: Press `C-c RET' (`gptel-send') to send your prompt. -;; Use a prefix argument (`C-u C-c RET') to access a menu. In this menu you -;; can set chat parameters like the system directives, active backend or -;; model, or choose to redirect the input or output elsewhere (such as to the -;; kill ring). -;; -;; - You can save this buffer to a file. When opening this file, turn on -;; `gptel-mode' before editing it to restore the conversation state and -;; continue chatting. -;; -;; - To include media files with your request, you can add them to the context -;; (described next), or include them as links in Org or Markdown mode chat -;; buffers. Sending media is disabled by default, you can turn it on globally -;; via `gptel-track-media', or locally in a chat buffer via the header line. -;; -;; Include more context with requests: -;; -;; If you want to provide the LLM with more context, you can add arbitrary -;; regions, buffers or files to the query with `gptel-add'. To add text or -;; media files, call `gptel-add' in Dired or use the dedicated `gptel-add-file'. -;; -;; You can also add context from gptel's menu instead (gptel-send with a prefix -;; arg), as well as examine or modify context. -;; -;; When context is available, gptel will include it with each LLM query. -;; -;; Rewrite/refactor interface -;; -;; In any buffer: with a region selected, you can rewrite prose, refactor code -;; or fill in the region. Use gptel's menu (C-u M-x `gptel-send') to access -;; this feature. -;; -;; gptel in Org mode: -;; -;; gptel offers a few extra conveniences in Org mode. -;; - You can limit the conversation context to an Org heading with -;; `gptel-org-set-topic'. -;; -;; - You can have branching conversations in Org mode, where each hierarchical -;; outline path through the document is a separate conversation branch. -;; See the variable `gptel-org-branching-context'. -;; -;; - You can declare the gptel model, backend, temperature, system message and -;; other parameters as Org properties with the command -;; `gptel-org-set-properties'. gptel queries under the corresponding heading -;; will always use these settings, allowing you to create mostly reproducible -;; LLM chat notebooks. -;; -;; Finally, gptel offers a general purpose API for writing LLM ineractions -;; that suit your workflow, see `gptel-request'. - -;;; Code: -(declare-function markdown-mode "markdown-mode") -(declare-function gptel-curl-get-response "gptel-curl") -(declare-function gptel-menu "gptel-transient") -(declare-function gptel-system-prompt "gptel-transient") -(declare-function pulse-momentary-highlight-region "pulse") - -(declare-function ediff-make-cloned-buffer "ediff-util") -(declare-function ediff-regions-internal "ediff") - -(declare-function gptel-org--create-prompt "gptel-org") -(declare-function gptel-org-set-topic "gptel-org") -(declare-function gptel-org--save-state "gptel-org") -(declare-function gptel-org--restore-state "gptel-org") -(declare-function gptel--stream-convert-markdown->org "gptel-org") -(declare-function gptel--convert-markdown->org "gptel-org") -(define-obsolete-function-alias - 'gptel-set-topic 'gptel-org-set-topic "0.7.5") - -(eval-when-compile - (require 'subr-x) - (require 'cl-lib)) -(require 'compat nil t) -(require 'url) -(require 'map) -(require 'text-property-search) -(require 'cl-generic) -(require 'gptel-openai) - -(with-eval-after-load 'org - (require 'gptel-org)) - - -;;; User options - -(defgroup gptel nil - "Interact with LLMs from anywhere in Emacs." - :group 'hypermedia) - -;; (defcustom gptel-host "api.openai.com" -;; "The API host queried by gptel." -;; :group 'gptel -;; :type 'string) -(make-obsolete-variable - 'gptel-host - "Use `gptel-make-openai' instead." - "0.5.0") - -(defcustom gptel-proxy "" - "Path to a proxy to use for gptel interactions. -Passed to curl via --proxy arg, for example \"proxy.yourorg.com:80\" -Leave it empty if you don't use a proxy." - :type 'string) - -(defcustom gptel-api-key #'gptel-api-key-from-auth-source - "An API key (string) for the default LLM backend. - -OpenAI by default. - -Can also be a function of no arguments that returns an API -key (more secure) for the active backend." - :type '(choice - (string :tag "API key") - (function :tag "Function that returns the API key"))) - -(defcustom gptel-stream t - "Stream responses from the LLM as they are received. - -This option is ignored unless -- the LLM backend supports streaming, and -- Curl is in use (see `gptel-use-curl') - -When set to nil, Emacs waits for the full response and inserts it -all at once. This wait is asynchronous. - -\='tis a bit silly." - :type 'boolean) -(make-obsolete-variable 'gptel-playback 'gptel-stream "0.3.0") - -(defcustom gptel-use-curl (and (executable-find "curl") t) - "Whether gptel should prefer Curl when available." - :type 'boolean) - -(defcustom gptel-curl-file-size-threshold 130000 - "Size threshold for using file input with Curl. - -Specifies the size threshold for when to use a temporary file to pass data to -Curl in GPTel queries. If the size of the data to be sent exceeds this -threshold, the data is written to a temporary file and passed to Curl using the -`--data-binary' option with a file reference. Otherwise, the data is passed -directly as a command-line argument. - -The value is an integer representing the number of bytes. - -Adjusting this value may be necessary depending on the environment -and the typical size of the data being sent in GPTel queries. -A larger value may improve performance by avoiding the overhead of creating -temporary files for small data payloads, while a smaller value may be needed -if the command-line argument size is limited by the operating system." - :type 'natnum) - -(defcustom gptel-response-filter-functions - (list #'gptel--convert-org) - "Abnormal hook for transforming the response from an LLM. - -This is used to format the response in some way, such as filling -paragraphs, adding annotations or recording information in the -response like links. - -Each function in this hook receives two arguments, the response -string to transform and the LLM interaction buffer. It -should return the transformed string. - -NOTE: This is only used for non-streaming responses. To -transform streaming responses, use `gptel-post-stream-hook' and -`gptel-post-response-functions'." - :type 'hook) - -(defcustom gptel-pre-response-hook nil - "Hook run before inserting the LLM response into the current buffer. - -This hook is called in the buffer where the LLM response will be -inserted. - -Note: this hook only runs if the request succeeds." - :type 'hook) - -(define-obsolete-variable-alias - 'gptel-post-response-hook 'gptel-post-response-functions - "0.6.0" - "Post-response functions are now called with two arguments: the -start and end buffer positions of the response.") - -(defcustom gptel-post-response-functions nil - "Abnormal hook run after inserting the LLM response into the current buffer. - -This hook is called in the buffer to which the LLM response is -sent, and after the full response has been inserted. Each -function is called with two arguments: the response beginning and -end positions. - -Note: this hook runs even if the request fails. In this case the -response beginning and end positions are both the cursor position -at the time of the request." - :type 'hook) - -;; (defcustom gptel-pre-stream-insert-hook nil -;; "Hook run before each insertion of the LLM's streaming response. - -;; This hook is called in the buffer from which the prompt was sent -;; to the LLM, immediately before text insertion." -;; :group 'gptel -;; :type 'hook) - -(defcustom gptel-post-stream-hook nil - "Hook run after each insertion of the LLM's streaming response. - -This hook is called in the buffer from which the prompt was sent -to the LLM, and after a text insertion." - :type 'hook) - -(defcustom gptel-save-state-hook nil - "Hook run before gptel saves model parameters to a file. - -You can use this hook to store additional conversation state or -model parameters to the chat buffer, or to modify the buffer in -some other way." - :type 'hook) - -(defcustom gptel-default-mode (if (fboundp 'markdown-mode) - 'markdown-mode - 'text-mode) - "The default major mode for dedicated chat buffers. - -If `markdown-mode' is available, it is used. Otherwise gptel -defaults to `text-mode'." - :type 'function) - -;; TODO: Handle `prog-mode' using the `comment-start' variable -(defcustom gptel-prompt-prefix-alist - '((markdown-mode . "### ") - (org-mode . "*** ") - (text-mode . "### ")) - "String used as a prefix to the query being sent to the LLM. - -This is meant for the user to distinguish between queries and -responses, and is removed from the query before it is sent. - -This is an alist mapping major modes to the prefix strings. This -is only inserted in dedicated gptel buffers." - :type '(alist :key-type symbol :value-type string)) - -(defcustom gptel-response-prefix-alist - '((markdown-mode . "") - (org-mode . "") - (text-mode . "")) - "String inserted before the response from the LLM. - -This is meant for the user to distinguish between queries and -responses. - -This is an alist mapping major modes to the reply prefix strings. This -is only inserted in dedicated gptel buffers before the AI's response." - :type '(alist :key-type symbol :value-type string)) - -(defcustom gptel-use-header-line t - "Whether `gptel-mode' should use header-line for status information. - -When set to nil, use the mode line for (minimal) status -information and the echo area for messages." - :type 'boolean) - -(defcustom gptel-display-buffer-action '(pop-to-buffer) - "The action used to display gptel chat buffers. - -The gptel buffer is displayed in a window using - - (display-buffer BUFFER gptel-display-buffer-action) - -The value of this option has the form (FUNCTION . ALIST), -where FUNCTION is a function or a list of functions. Each such -function should accept two arguments: a buffer to display and an -alist of the same form as ALIST. See info node `(elisp)Choosing -Window' for details." - :type display-buffer--action-custom-type) - -(defcustom gptel-crowdsourced-prompts-file - (let ((cache-dir (or (eval-when-compile - (require 'xdg) - (xdg-cache-home)) - user-emacs-directory))) - (expand-file-name "gptel-crowdsourced-prompts.csv" cache-dir)) - "File used to store crowdsourced system prompts. - -These are prompts cached from an online source (see -`gptel--crowdsourced-prompts-url'), and can be set from the -transient menu interface provided by `gptel-menu'." - :type 'file) - -;; Model and interaction parameters -(defcustom gptel-directives - '((default . "You are a large language model living in Emacs and a helpful assistant. Respond concisely.") - (programming . "You are a large language model and a careful programmer. Provide code and only code as output without any additional text, prompt or note.") - (writing . "You are a large language model and a writing assistant. Respond concisely.") - (chat . "You are a large language model and a conversation partner. Respond concisely.")) - "System prompts (directives) for the LLM. - -These are system instructions sent at the beginning of each -request to the LLM. - -Each entry in this alist maps a symbol naming the directive to -the string that is sent. To set the directive for a chat session -interactively call `gptel-send' with a prefix argument." - :safe #'always - :type '(alist :key-type symbol :value-type string)) - -(defvar gptel--system-message (alist-get 'default gptel-directives) - "The system message used by gptel.") -(put 'gptel--system-message 'safe-local-variable #'always) - -(defcustom gptel-max-tokens nil - "Max tokens per response. - -This is roughly the number of words in the response. 100-300 is a -reasonable range for short answers, 400 or more for longer -responses. - -To set the target token count for a chat session interactively -call `gptel-send' with a prefix argument." - :safe #'always - :type '(choice (natnum :tag "Specify Token count") - (const :tag "Default" nil))) - -(defcustom gptel-model 'gpt-4o-mini - "GPT Model for chat. - -The name of the model, as a symbol. This is the name as expected -by the LLM provider's API. - -The current options for ChatGPT are -- `gpt-3.5-turbo' -- `gpt-3.5-turbo-16k' -- `gpt-4o-mini' -- `gpt-4' -- `gpt-4o' -- `gpt-4-turbo' -- `gpt-4-turbo-preview' -- `gpt-4-32k' -- `gpt-4-1106-preview' - -To set the model for a chat session interactively call -`gptel-send' with a prefix argument." - :safe #'always - :type '(choice - (symbol :tag "Specify model name") - (const :tag "GPT 4 omni mini" gpt-4o-mini) - (const :tag "GPT 3.5 turbo" gpt-3.5-turbo) - (const :tag "GPT 3.5 turbo 16k" gpt-3.5-turbo-16k) - (const :tag "GPT 4" gpt-4) - (const :tag "GPT 4 omni" gpt-4o) - (const :tag "GPT 4 turbo" gpt-4-turbo) - (const :tag "GPT 4 turbo (preview)" gpt-4-turbo-preview) - (const :tag "GPT 4 32k" gpt-4-32k) - (const :tag "GPT 4 1106 (preview)" gpt-4-1106-preview))) - -(defcustom gptel-temperature 1.0 - "\"Temperature\" of the LLM response. - -This is a number between 0.0 and 2.0 that controls the randomness -of the response, with 2.0 being the most random. - -To set the temperature for a chat session interactively call -`gptel-send' with a prefix argument." - :safe #'always - :type 'number) - -(defvar gptel--known-backends) - -(defconst gptel--openai-models - '((gpt-4o - :description "Advanced model for complex tasks; cheaper & faster than GPT-Turbo" - :capabilities (media tool json url) - :mime-types ("image/jpeg" "image/png" "image/gif" "image/webp") - :context-window 128 - :input-cost 2.50 - :output-cost 10 - :cutoff-date "2023-10") - (gpt-4o-mini - :description "Cheap model for fast tasks; cheaper & more capable than GPT-3.5 Turbo" - :capabilities (media tool json url) - :mime-types ("image/jpeg" "image/png" "image/gif" "image/webp") - :context-window 128 - :input-cost 0.15 - :output-cost 0.60 - :cutoff-date "2023-10") - (gpt-4-turbo - :description "Previous high-intelligence model" - :capabilities (media tool url) - :mime-types ("image/jpeg" "image/png" "image/gif" "image/webp") - :context-window 128 - :input-cost 10 - :output-cost 30 - :cutoff-date "2023-12") - ;; points to gpt-4-0613 - (gpt-4 - :description "GPT-4 snapshot from June 2023 with improved function calling support" - :context-window 8.192 - :input-cost 30 - :output-cost 60 - :cutoff-date "2023-09") - (gpt-4-turbo-preview - :description "Points to gpt-4-0125-preview" - :context-window 128 - :input-cost 10 - :output-cost 30 - :cutoff-date "2023-12") - (gpt-4-0125-preview - :description "GPT-4 Turbo preview model intended to reduce cases of “laziness”" - :context-window 128 - :input-cost 10 - :output-cost 30 - :cutoff-date "2023-12") - (o1-preview - :description "Reasoning model designed to solve hard problems across domains" - :context-window 128 - :input-cost 15 - :output-cost 60 - :cutoff-date "2023-10" - :capabilities (nosystem) - :request-params (:stream :json-false)) - (o1-mini - :description "Faster and cheaper reasoning model good at coding, math, and science" - :context-window 128 - :input-cost 3 - :output-cost 12 - :cutoff-date "2023-10" - :capabilities (nosystem) - :request-params (:stream :json-false)) - ;; limited information available - (gpt-4-32k - :input-cost 60 - :output-cost 120) - (gpt-4-1106-preview - :description "Preview model with improved function calling support" - :context-window 128 - :input-cost 10 - :output-cost 30 - :cutoff-date "2023-04") - (gpt-3.5-turbo - :description "More expensive & less capable than GPT-4o-mini; use that instead" - :capabilities (tool) - :mime-types ("image/jpeg" "image/png" "image/gif" "image/webp") - :context-window 16.358 - :input-cost 0.50 - :output-cost 1.50 - :cutoff-date "2021-09") - (gpt-3.5-turbo-16k - :description "More expensive & less capable than GPT-4o-mini; use that instead" - :mime-types ("image/jpeg" "image/png" "image/gif" "image/webp") - :context-window 16.385 - :input-cost 3 - :output-cost 4 - :cutoff-date "2021-09")) - "List of available OpenAI models and associated properties. -Keys: - -- `:description': a brief description of the model. - -- `:capabilities': a list of capabilities supported by the model. - -- `:mime-types': a list of supported MIME types for media files. - -- `:context-window': the context window size, in thousands of tokens. - -- `:input-cost': the input cost, in US dollars per million tokens. - -- `:output-cost': the output cost, in US dollars per million tokens. - -- `:cutoff-date': the knowledge cutoff date. - -- `:request-params': a plist of additional request parameters to - include when using this model. - -Information about the OpenAI models was obtained from the following -sources: - -- <https://openai.com/pricing> -- <https://platform.openai.com/docs/models>") - -(defvar gptel--openai - (gptel-make-openai - "ChatGPT" - :key 'gptel-api-key - :stream t - :models gptel--openai-models)) - -(defcustom gptel-backend gptel--openai - "LLM backend to use. - -This is the default \"backend\", an object of type -`gptel-backend' containing connection, authentication and model -information. - -A backend for ChatGPT is pre-defined by gptel. Backends for -other LLM providers (local or remote) may be constructed using -one of the available backend creation functions: -- `gptel-make-openai' -- `gptel-make-azure' -- `gptel-make-ollama' -- `gptel-make-gpt4all' -- `gptel-make-gemini' -See their documentation for more information and the package -README for examples." - :safe #'always - :type `(choice - (const :tag "ChatGPT" ,gptel--openai) - (restricted-sexp :match-alternatives (gptel-backend-p 'nil) - :tag "Other backend"))) - -(defvar gptel-expert-commands nil - "Whether experimental gptel options should be enabled. - -This opens up advanced options in `gptel-menu'.") - -(defvar-local gptel--bounds nil) -(put 'gptel--bounds 'safe-local-variable #'always) - -(defvar gptel--num-messages-to-send nil) -(put 'gptel--num-messages-to-send 'safe-local-variable #'always) - -(defcustom gptel-log-level nil - "Logging level for gptel. - -This is one of nil or the symbols info and debug: - -nil: Don't log responses -info: Log request and response bodies -debug: Log request/response bodies, headers and all other - connection settings. - -When non-nil, information is logged to `gptel--log-buffer-name', -which see." - :type '(choice - (const :tag "No logging" nil) - (const :tag "Limited" info) - (const :tag "Full" debug))) -(make-obsolete-variable - 'gptel--debug 'gptel-log-level "0.6.5") - -(defcustom gptel-track-response t - "Distinguish between user messages and LLM responses. - -When creating a prompt to send to the LLM, gptel distinguishes -between text entered by the user and past LLM responses. This -distinction is necessary for back-and-forth conversation with an -LLM. - -In regular Emacs buffers you can turn this behavior off by -setting `gptel-track-response' to nil. All text, including -past LLM responses, is then treated as user input when sending -queries. - -This variable has no effect in dedicated chat buffers (buffers -with `gptel-mode' enabled), where user prompts and responses are -always handled separately." - :type 'boolean) - -(defcustom gptel-track-media nil - "Whether supported media in chat buffers should be sent. - -When the active `gptel-model' supports it, gptel can send images -or other media from links in chat buffers to the LLM. To use -this, the following steps are required. - -1. `gptel-track-media' (this variable) should be non-nil - -2. The LLM should provide vision or document support. Currently, -only the OpenAI, Anthropic and Ollama APIs are supported. See -the documentation of `gptel-make-openai', `gptel-make-anthropic' -and `gptel-make-ollama' resp. for details on how to specify media -support for models. - -3. Only \"standalone\" links in chat buffers are considered. -These are links on their own line with no surrounding text. -Further: - -- In Org mode, only files or URLs of the form - [[/path/to/media][bracket links]] and <angle/link/path> - are sent. - -- In Markdown mode, only files or URLS of the form - [bracket link](/path/to/media) and <angle/link/path> - are sent. - -This option has no effect in non-chat buffers. To include -media (including images) more generally, use `gptel-add'." - :type 'boolean) - -(defcustom gptel-use-context 'system - "Where in the request to inject gptel's additional context. - -gptel always includes the active region or the buffer up to the -cursor in the request to the LLM. Additionally, you can add -other buffers or their regions to the context with -`gptel-add-context', or from gptel's menu. This data will be -sent with every request. - -This option controls whether and where this additional context is -included in the request. - -Currently supported options are: - - nil - Do not use the context. - system - Include the context with the system message. - user - Include the context with the user prompt." - :group 'gptel - :type '(choice - (const :tag "Don't include context" nil) - (const :tag "With system message" system) - (const :tag "With user prompt" user))) - -(defvar-local gptel--old-header-line nil) - -(defvar gptel-context--alist nil - "List of gptel's context sources. - -Each entry is of the form - (buffer . (overlay1 overlay2 ...)) -or - (\"path/to/file\").") - - -;;; Utility functions - -(defun gptel-api-key-from-auth-source (&optional host user) - "Lookup api key in the auth source. -By default, the LLM host for the active backend is used as HOST, -and \"apikey\" as USER." - (if-let ((secret - (plist-get - (car (auth-source-search - :host (or host (gptel-backend-host gptel-backend)) - :user (or user "apikey") - :require '(:secret))) - :secret))) - (if (functionp secret) - (encode-coding-string (funcall secret) 'utf-8) - secret) - (user-error "No `gptel-api-key' found in the auth source"))) - -;; FIXME Should we utf-8 encode the api-key here? -(defun gptel--get-api-key (&optional key) - "Get api key from KEY, or from `gptel-api-key'." - (when-let ((key-sym (or key (gptel-backend-key gptel-backend)))) - (cl-typecase key-sym - (function (funcall key-sym)) - (string key-sym) - (symbol (if-let ((val (symbol-value key-sym))) - (gptel--get-api-key - (symbol-value key-sym)) - (error "`gptel-api-key' is not valid"))) - (t (error "`gptel-api-key' is not valid"))))) - -(defsubst gptel--to-number (val) - "Ensure VAL is a number." - (cond - ((numberp val) val) - ((stringp val) (string-to-number val)) - ((error "%S cannot be converted to a number" val)))) - -(defsubst gptel--to-string (s) - "Convert S to a string, if possible." - (cl-etypecase s - (symbol (symbol-name s)) - (string s) - (number (number-to-string s)))) - -(defsubst gptel--intern (s) - "Intern S, if possible." - (cl-etypecase s - (symbol s) - (string (intern s)))) - -(defun gptel--merge-plists (&rest plists) - "Merge PLISTS, altering the first one. - -Later plists in the sequence take precedence over earlier ones." - (let (;; (rtn (copy-sequence (pop plists))) - (rtn (pop plists)) - p v ls) - (while plists - (setq ls (pop plists)) - (while ls - (setq p (pop ls) v (pop ls)) - (setq rtn (plist-put rtn p v)))) - rtn)) -(defun gptel-auto-scroll () - "Scroll window if LLM response continues below viewport. - -Note: This will move the cursor." - (when-let ((win (get-buffer-window (current-buffer) 'visible)) - ((not (pos-visible-in-window-p (point) win))) - (scroll-error-top-bottom t)) - (condition-case nil - (with-selected-window win - (scroll-up-command)) - (error nil)))) - -(defun gptel-beginning-of-response (&optional _ _ arg) - "Move point to the beginning of the LLM response ARG times." - (interactive "p") - ;; FIXME: Only works for arg == 1 - (gptel-end-of-response nil nil (- (or arg 1)))) - -(defun gptel-end-of-response (&optional _ _ arg) - "Move point to the end of the LLM response ARG times." - (interactive (list nil nil - (prefix-numeric-value current-prefix-arg))) - (unless arg (setq arg 1)) - (let ((search (if (> arg 0) - #'text-property-search-forward - #'text-property-search-backward))) - (dotimes (_ (abs arg)) - (funcall search 'gptel 'response t) - (if (> arg 0) - (when (looking-at (concat "\n\\{1,2\\}" - (regexp-quote - (gptel-prompt-prefix-string)) - "?")) - (goto-char (match-end 0))) - (when (looking-back (concat (regexp-quote - (gptel-response-prefix-string)) - "?") - (point-min)) - (goto-char (match-beginning 0))))))) - -(defmacro gptel--at-word-end (&rest body) - "Execute BODY at end of the current word or punctuation." - `(save-excursion - (skip-syntax-forward "w.") - ,(macroexp-progn body))) - -(defun gptel-prompt-prefix-string () - "Prefix before user prompts in `gptel-mode'." - (or (alist-get major-mode gptel-prompt-prefix-alist) "")) - -(defun gptel-response-prefix-string () - "Prefix before LLM responses in `gptel-mode'." - (or (alist-get major-mode gptel-response-prefix-alist) "")) - -(defsubst gptel--trim-prefixes (s) - "Remove prompt/response prefixes from string S." - (string-trim s - (format "[\t\r\n ]*\\(?:%s\\)?[\t\r\n ]*" - (regexp-quote (gptel-prompt-prefix-string))) - (format "[\t\r\n ]*\\(?:%s\\)?[\t\r\n ]*" - (regexp-quote (gptel-response-prefix-string))))) - -(defsubst gptel--link-standalone-p (beg end) - "Return non-nil if positions BEG and END are isolated. - -This means the extent from BEG to END is the only non-whitespace -content on this line." - (save-excursion - (and (= beg (progn (goto-char beg) (beginning-of-line) - (skip-chars-forward "\t ") - (point))) - (= end (progn (goto-char end) (end-of-line) - (skip-chars-backward "\t ") - (point)))))) - -(defvar-local gptel--backend-name nil - "Store to persist backend name across Emacs sessions. - -Note: Changing this variable does not affect gptel\\='s behavior -in any way.") -(put 'gptel--backend-name 'safe-local-variable #'always) - -;;;; Model interface -;; NOTE: This interface would be simpler to implement as a defstruct. But then -;; users cannot set `gptel-model' to a symbol/string directly, or we'd need -;; another map from these symbols to the actual model structs. - -(defsubst gptel--model-name (model) - "Get name of gptel MODEL." - (gptel--to-string model)) - -(defsubst gptel--model-capabilities (model) - "Get MODEL capabilities." - (get model :capabilities)) - -(defsubst gptel--model-mimes (model) - "Get supported mime-types for MODEL." - (get model :mime-types)) - -(defsubst gptel--model-capable-p (cap &optional model) - "Return non-nil if MODEL supports capability CAP." - (memq cap (gptel--model-capabilities - (or model gptel-model)))) - -;; TODO Handle model mime specifications like "image/*" -(defsubst gptel--model-mime-capable-p (mime &optional model) - "Return non nil if MODEL can understand MIME type." - (car-safe (member mime (gptel--model-mimes - (or model gptel-model))))) - -(defsubst gptel--model-request-params (model) - "Get model-specific request parameters for MODEL." - (get model :request-params)) - -;;;; File handling -(defun gptel--base64-encode (file) - "Encode FILE as a base64 string. - -FILE is assumed to exist and be a regular file." - (with-temp-buffer - (insert-file-contents-literally file) - (base64-encode-region (point-min) (point-max) - :no-line-break) - (buffer-string))) - -;;;; Response text recognition - -(defun gptel--get-buffer-bounds () - "Return the gptel response boundaries in the buffer as an alist." - (save-excursion - (save-restriction - (widen) - (goto-char (point-max)) - (let ((prop) (bounds)) - (while (setq prop (text-property-search-backward - 'gptel 'response t)) - (push (cons (prop-match-beginning prop) - (prop-match-end prop)) - bounds)) - bounds)))) - -(defun gptel--get-bounds () - "Return the gptel response boundaries around point." - (let (prop) - (save-excursion - (when (text-property-search-backward - 'gptel 'response t) - (when (setq prop (text-property-search-forward - 'gptel 'response t)) - (cons (prop-match-beginning prop) - (prop-match-end prop))))))) - -(defun gptel--in-response-p (&optional pt) - "Check if position PT is inside a gptel response." - (get-char-property (or pt (point)) 'gptel)) - -(defun gptel--at-response-history-p (&optional pt) - "Check if gptel response at position PT has variants." - (get-char-property (or pt (point)) 'gptel-history)) - -(defvar gptel--mode-description-alist - '((js2-mode . "Javascript") - (sh-mode . "Shell") - (enh-ruby-mode . "Ruby") - (yaml-mode . "Yaml") - (yaml-ts-mode . "Yaml") - (rustic-mode . "Rust")) - "Mapping from unconventionally named major modes to languages. - -This is used when generating system prompts for rewriting and -when including context from these major modes.") - -(defun gptel--strip-mode-suffix (mode-sym) - "Remove the -mode suffix from MODE-SYM. - -MODE-SYM is typically a major-mode symbol." - (or (alist-get mode-sym gptel--mode-description-alist) - (let ((mode-name (thread-last - (symbol-name mode-sym) - (string-remove-suffix "-mode") - (string-remove-suffix "-ts")))) - (if (provided-mode-derived-p - mode-sym 'prog-mode 'text-mode 'tex-mode) - mode-name "")))) - - -;;; Logging - -(defconst gptel--log-buffer-name "*gptel-log*" - "Log buffer for gptel.") - -(declare-function json-pretty-print "json") - -(defun gptel--log (data &optional type no-json) - "Log DATA to `gptel--log-buffer-name'. - -TYPE is a label for data being logged. DATA is assumed to be -Valid JSON unless NO-JSON is t." - (with-current-buffer (get-buffer-create gptel--log-buffer-name) - (let ((p (goto-char (point-max)))) - (unless (bobp) (insert "\n")) - (insert (format "{\"gptel\": \"%s\", " (or type "none")) - (format-time-string "\"timestamp\": \"%Y-%m-%d %H:%M:%S\"}\n") - data) - (unless no-json (ignore-errors (json-pretty-print p (point))))))) - - -;;; Saving and restoring state - -(defun gptel--restore-state () - "Restore gptel state when turning on `gptel-mode'." - (when (buffer-file-name) - (if (derived-mode-p 'org-mode) - (progn - (require 'gptel-org) - (gptel-org--restore-state)) - (when gptel--bounds - (mapc (pcase-lambda (`(,beg . ,end)) - (put-text-property beg end 'gptel 'response)) - gptel--bounds) - (message "gptel chat restored.")) - (when gptel--backend-name - (if-let ((backend (alist-get - gptel--backend-name gptel--known-backends - nil nil #'equal))) - (setq-local gptel-backend backend) - (message - (substitute-command-keys - (concat - "Could not activate gptel backend \"%s\"! " - "Switch backends with \\[universal-argument] \\[gptel-send]" - " before using gptel.")) - gptel--backend-name)))))) - -(defun gptel--save-state () - "Write the gptel state to the buffer. - -This saves chat metadata when writing the buffer to disk. To -restore a chat session, turn on `gptel-mode' after opening the -file." - (run-hooks 'gptel-save-state-hook) - (if (derived-mode-p 'org-mode) - (progn - (require 'gptel-org) - (gptel-org--save-state)) - (let ((print-escape-newlines t)) - (save-excursion - (save-restriction - (add-file-local-variable 'gptel-model gptel-model) - (add-file-local-variable 'gptel--backend-name - (gptel-backend-name gptel-backend)) - (unless (equal (default-value 'gptel-temperature) gptel-temperature) - (add-file-local-variable 'gptel-temperature gptel-temperature)) - (unless (string= (default-value 'gptel--system-message) - gptel--system-message) - (add-file-local-variable 'gptel--system-message gptel--system-message)) - (when gptel-max-tokens - (add-file-local-variable 'gptel-max-tokens gptel-max-tokens)) - (when (natnump gptel--num-messages-to-send) - (add-file-local-variable 'gptel--num-messages-to-send - gptel--num-messages-to-send)) - (add-file-local-variable 'gptel--bounds (gptel--get-buffer-bounds))))))) - - -;;; Minor mode and UI - -;; NOTE: It's not clear that this is the best strategy: -(add-to-list 'text-property-default-nonsticky '(gptel . t)) - -;;;###autoload -(define-minor-mode gptel-mode - "Minor mode for interacting with LLMs." - :lighter " GPT" - :keymap - (let ((map (make-sparse-keymap))) - (define-key map (kbd "C-c RET") #'gptel-send) - map) - (if gptel-mode - (progn - (unless (or (derived-mode-p 'org-mode 'markdown-mode) - (eq major-mode 'text-mode)) - (gptel-mode -1) - (user-error (format "`gptel-mode' is not supported in `%s'." major-mode))) - (add-hook 'before-save-hook #'gptel--save-state nil t) - (gptel--restore-state) - (if gptel-use-header-line - (setq gptel--old-header-line header-line-format - header-line-format - (list '(:eval (concat (propertize " " 'display '(space :align-to 0)) - (format "%s" (gptel-backend-name gptel-backend)))) - (propertize " Ready" 'face 'success) - '(:eval - (let* ((model (gptel--model-name gptel-model)) - (system - (propertize - (buttonize - (format "[Prompt: %s]" - (or (car-safe (rassoc gptel--system-message gptel-directives)) - (truncate-string-to-width gptel--system-message 15 nil nil t))) - (lambda (&rest _) (gptel-system-prompt))) - 'mouse-face 'highlight - 'help-echo "System message for session")) - (context - (and gptel-context--alist - (cl-loop for entry in gptel-context--alist - if (bufferp (car entry)) count it into bufs - else count (stringp (car entry)) into files - finally return - (propertize - (buttonize - (concat "[Context: " - (and (> bufs 0) (format "%d buf" bufs)) - (and (> bufs 1) "s") - (and (> bufs 0) (> files 0) ", ") - (and (> files 0) (format "%d file" files)) - (and (> files 1) "s") - "]") - (lambda (&rest _) - (require 'gptel-context) - (gptel-context--buffer-setup))) - 'mouse-face 'highlight - 'help-echo "Active gptel context")))) - (toggle-track-media - (lambda (&rest _) - (setq-local gptel-track-media - (not gptel-track-media)) - (if gptel-track-media - (message - (concat - "Sending media from included links. To include media, create " - "a \"standalone\" link in a paragraph by itself, separated from surrounding text.")) - (message "Ignoring image links. Only link text will be sent.")) - (run-at-time 0 nil #'force-mode-line-update))) - (track-media - (and (gptel--model-capable-p 'media) - (if gptel-track-media - (propertize - (buttonize "[Sending media]" toggle-track-media) - 'mouse-face 'highlight - 'help-echo - "Sending media from standalone links/urls when supported.\nClick to toggle") - (propertize - (buttonize "[Ignoring media]" toggle-track-media) - 'mouse-face 'highlight - 'help-echo - "Ignoring images from standalone links/urls.\nClick to toggle"))))) - (concat - (propertize - " " 'display - `(space :align-to (- right ,(+ 5 (length model) (length system) - (length track-media) (length context))))) - track-media (and context " ") context " " system " " - (propertize - (buttonize (concat "[" model "]") - (lambda (&rest _) (gptel-menu))) - 'mouse-face 'highlight - 'help-echo "GPT model in use")))))) - (setq mode-line-process - '(:eval (concat " " - (buttonize (gptel--model-name gptel-model) - (lambda (&rest _) (gptel-menu)))))))) - (remove-hook 'before-save-hook #'gptel--save-state t) - (if gptel-use-header-line - (setq header-line-format gptel--old-header-line - gptel--old-header-line nil) - (setq mode-line-process nil)))) - -(defun gptel--update-status (&optional msg face) - "Update status MSG in FACE." - (when gptel-mode - (if gptel-use-header-line - (and (consp header-line-format) - (setf (nth 1 header-line-format) - (propertize msg 'face face))) - (if (member msg '(" Typing..." " Waiting...")) - (setq mode-line-process (propertize msg 'face face)) - (setq mode-line-process - '(:eval (concat " " - (buttonize (gptel--model-name gptel-model) - (lambda (&rest _) (gptel-menu)))))) - (message (propertize msg 'face face)))) - (force-mode-line-update))) - -(declare-function gptel-context--wrap "gptel-context") - - -;;; Send queries, handle responses -(cl-defun gptel-request - (&optional prompt &key callback - (buffer (current-buffer)) - position context dry-run - (stream nil) (in-place nil) - (system gptel--system-message)) - "Request a response from the `gptel-backend' for PROMPT. - -The request is asynchronous, the function immediately returns -with the data that was sent. - -Note: This function is not fully self-contained. Consider -let-binding the parameters `gptel-backend' and `gptel-model' -around calls to it as required. - -If PROMPT is -- a string, it is used to create a full prompt suitable for - sending to the LLM. -- nil but region is active, the region contents are used. -- nil, the current buffer's contents up to (point) are used. - Previous responses from the LLM are identified as responses. -- A list of plists, it is used as is. - -Keyword arguments: - -CALLBACK, if supplied, is a function of two arguments, called -with the RESPONSE (a string) and INFO (a plist): - - (callback RESPONSE INFO) - -RESPONSE is nil if there was no response or an error. - -The INFO plist has (at least) the following keys: -:data - The request data included with the query -:position - marker at the point the request was sent, unless - POSITION is specified. -:buffer - The buffer current when the request was sent, - unless BUFFER is specified. -:status - Short string describing the result of the request - -Example of a callback that messages the user with the response -and info: - - (lambda (response info) - (if response - (let ((posn (marker-position (plist-get info :position))) - (buf (buffer-name (plist-get info :buffer)))) - (message \"Response for request from %S at %d: %s\" - buf posn response)) - (message \"gptel-request failed with message: %s\" - (plist-get info :status)))) - -Or, for just the response: - - (lambda (response _) - ;; Do something with response - (message (rot13-string response))) - -If CALLBACK is omitted, the response is inserted at the point the -request was sent. - -BUFFER and POSITION are the buffer and position (integer or -marker) at which the response is inserted. If a CALLBACK is -specified, no response is inserted and these arguments are -ignored, but they are still available in the INFO plist passed -to CALLBACK for you to use. - -BUFFER defaults to the current buffer, and POSITION to the value -of (point) or (region-end), depending on whether the region is -active. - -CONTEXT is any additional data needed for the callback to run. It -is included in the INFO argument to the callback. - -SYSTEM is the system message (chat directive) sent to the LLM. If -omitted, the value of `gptel--system-message' for the current -buffer is used. - -The following keywords are mainly for internal use: - -IN-PLACE is a boolean used by the default callback when inserting -the response to determine if delimiters are needed between the -prompt and the response. - -STREAM is a boolean that determines if the response should be -streamed, as in `gptel-stream'. Do not set this if you are -specifying a custom CALLBACK! - -If DRY-RUN is non-nil, construct and return the full -query data as usual, but do not send the request. - -Model parameters can be let-bound around calls to this function." - (declare (indent 1)) - ;; TODO Remove this check in version 1.0 - (gptel--sanitize-model) - (let* ((gptel--system-message - ;Add context chunks to system message if required - (if (and gptel-context--alist - (eq gptel-use-context 'system) - (not (gptel--model-capable-p 'nosystem))) - (gptel-context--wrap system) - system)) - (gptel-stream stream) - (start-marker - (cond - ((null position) - (if (use-region-p) - (set-marker (make-marker) (region-end)) - (gptel--at-word-end (point-marker)))) - ((markerp position) position) - ((integerp position) - (set-marker (make-marker) position buffer)))) - (full-prompt - (cond - ((null prompt) - (gptel--create-prompt start-marker)) - ((stringp prompt) - ;; FIXME Dear reader, welcome to Jank City: - (with-temp-buffer - (let ((gptel-model (buffer-local-value 'gptel-model buffer)) - (gptel-backend (buffer-local-value 'gptel-backend buffer))) - (insert prompt) - (gptel--create-prompt)))) - ((consp prompt) prompt))) - (request-data (gptel--request-data gptel-backend full-prompt)) - (info (list :data request-data - :buffer buffer - :position start-marker))) - ;; This context should not be confused with the context aggregation context! - (when context (plist-put info :context context)) - (when in-place (plist-put info :in-place in-place)) - (unless dry-run - (funcall (if gptel-use-curl - #'gptel-curl-get-response #'gptel--url-get-response) - info callback)) - request-data)) - -;; TODO: Handle multiple requests(#15). (Only one request from one buffer at a time?) -;;;###autoload -(defun gptel-send (&optional arg) - "Submit this prompt to the current LLM backend. - -By default, the contents of the buffer up to the cursor position -are sent. If the region is active, its contents are sent -instead. - -The response from the LLM is inserted below the cursor position -at the time of sending. To change this behavior or model -parameters, use prefix arg ARG activate a transient menu with -more options instead. - -This command is asynchronous, you can continue to use Emacs while -waiting for the response." - (interactive "P") - (if (and arg (require 'gptel-transient nil t)) - (call-interactively #'gptel-menu) - (message "Querying %s..." (gptel-backend-name gptel-backend)) - (gptel--sanitize-model) - (gptel-request nil :stream gptel-stream) - (gptel--update-status " Waiting..." 'warning))) - -(declare-function json-pretty-print-buffer "json") -(defun gptel--inspect-query (request-data &optional arg) - "Show REQUEST-DATA, the full LLM query to be sent, in a buffer. - -This functions as a dry run of `gptel-send'. If ARG is -the symbol json, show the encoded JSON query instead of the Lisp -structure gptel uses." - (with-current-buffer (get-buffer-create "*gptel-query*") - (let ((standard-output (current-buffer)) - (inhibit-read-only t)) - (buffer-disable-undo) - (erase-buffer) - (if (eq arg 'json) - (progn (fundamental-mode) - (insert (gptel--json-encode request-data)) - (json-pretty-print-buffer)) - (lisp-data-mode) - (prin1 request-data) - (pp-buffer)) - (goto-char (point-min)) - (view-mode 1) - (display-buffer (current-buffer) gptel-display-buffer-action)))) - -(defun gptel--insert-response (response info) - "Insert the LLM RESPONSE into the gptel buffer. - -INFO is a plist containing information relevant to this buffer. -See `gptel--url-get-response' for details." - (let* ((status-str (plist-get info :status)) - (gptel-buffer (plist-get info :buffer)) - (start-marker (plist-get info :position)) - response-beg response-end) - ;; Handle read-only buffers - (when (with-current-buffer gptel-buffer - (or buffer-read-only - (get-char-property start-marker 'read-only))) - (message "Buffer is read only, displaying reply in buffer \"*LLM response*\"") - (display-buffer - (with-current-buffer (get-buffer-create "*LLM response*") - (visual-line-mode 1) - (goto-char (point-max)) - (move-marker start-marker (point) (current-buffer)) - (current-buffer)) - '((display-buffer-reuse-window - display-buffer-pop-up-window) - (reusable-frames . visible)))) - ;; Insert response and status message/error message - (with-current-buffer gptel-buffer - (if response - (progn - (setq response (gptel--transform-response - response gptel-buffer)) - (save-excursion - (put-text-property - 0 (length response) 'gptel 'response response) - (with-current-buffer (marker-buffer start-marker) - (goto-char start-marker) - (run-hooks 'gptel-pre-response-hook) - (unless (or (bobp) (plist-get info :in-place)) - (insert "\n\n") - (when gptel-mode - (insert (gptel-response-prefix-string)))) - (setq response-beg (point)) ;Save response start position - (insert response) - (setq response-end (point)) - (pulse-momentary-highlight-region response-beg response-end) - (when gptel-mode (insert "\n\n" (gptel-prompt-prefix-string)))) ;Save response end position - (when gptel-mode (gptel--update-status " Ready" 'success)))) - (gptel--update-status - (format " Response Error: %s" status-str) 'error) - (message "gptel response error: (%s) %s" - status-str (plist-get info :error)))) - ;; Run hook in visible window to set window-point, BUG #269 - (if-let ((gptel-window (get-buffer-window gptel-buffer 'visible))) - (with-selected-window gptel-window - (run-hook-with-args 'gptel-post-response-functions response-beg response-end)) - (with-current-buffer gptel-buffer - (run-hook-with-args 'gptel-post-response-functions response-beg response-end))))) - -(defun gptel--create-prompt (&optional prompt-end) - "Return a full conversation prompt from the contents of this buffer. - -If `gptel--num-messages-to-send' is set, limit to that many -recent exchanges. - -If the region is active limit the prompt to the region contents -instead. - -If `gptel-context--alist' is non-nil and the additional -context needs to be included with the user prompt, add it. - -If PROMPT-END (a marker) is provided, end the prompt contents -there." - (save-excursion - (save-restriction - (let* ((max-entries (and gptel--num-messages-to-send - (* 2 gptel--num-messages-to-send))) - (prompt-end (or prompt-end (point-max))) - (prompts - (cond - ((use-region-p) - ;; Narrow to region - (narrow-to-region (region-beginning) (region-end)) - (goto-char (point-max)) - (gptel--parse-buffer gptel-backend max-entries)) - ((derived-mode-p 'org-mode) - (require 'gptel-org) - (goto-char prompt-end) - (gptel-org--create-prompt prompt-end)) - (t (goto-char prompt-end) - (gptel--parse-buffer gptel-backend max-entries))))) - ;; NOTE: prompts is modified in place here - (when gptel-context--alist - ;; Inject context chunks into the last user prompt if required. - ;; This is also the fallback for when `gptel-use-context' is set to - ;; 'system but the model does not support system messages. - (when (and gptel-use-context - (or (eq gptel-use-context 'user) - (gptel--model-capable-p 'nosystem)) - (> (length prompts) 0)) ;FIXME context should be injected - ;even when there are no prompts - (gptel--wrap-user-prompt gptel-backend prompts)) - ;; Inject media chunks into the first user prompt if required. Media - ;; chunks are always included with the first user message, - ;; irrespective of the preference in `gptel-use-context'. This is - ;; because media cannot be included (in general) with system messages. - (when (and gptel-use-context gptel-track-media - (gptel--model-capable-p 'media)) - (gptel--wrap-user-prompt gptel-backend prompts :media))) - prompts)))) - -(cl-defgeneric gptel--parse-buffer (backend max-entries) - "Parse current buffer backwards from point and return a list of prompts. - -BACKEND is the LLM backend in use. - -MAX-ENTRIES is the number of queries/responses to include for -contexbt.") - -(cl-defgeneric gptel--parse-media-links (mode beg end) - "Find media links between BEG and END. - -MODE is the major-mode of the buffer. - -Returns a plist where each entry is of the form - (:text \"some text\") -or - (:media \"media uri or file path\")." - (ignore mode) ;byte-compiler - (list `(:text ,(buffer-substring beg end)))) - -(defvar markdown-regex-link-inline) -(defvar markdown-regex-angle-uri) -(declare-function markdown-link-at-pos "markdown-mode") -(declare-function mailcap-file-name-to-mime-type "mailcap") - -(cl-defmethod gptel--parse-media-links ((_mode (eql 'markdown-mode)) beg end) - "Parse text and actionable links between BEG and END. - -Return a list of the form - ((:text \"some text\") - (:media \"/path/to/media.png\" :mime \"image/png\") - (:text \"More text\")) -for inclusion into the user prompt for the gptel request." - (require 'mailcap) ;FIXME Avoid this somehow - (let ((parts) (from-pt)) - (save-excursion - (setq from-pt (goto-char beg)) - (while (re-search-forward - (concat "\\(?:" markdown-regex-link-inline "\\|" - markdown-regex-angle-uri "\\)") - end t) - (when-let* ((link-at-pt (markdown-link-at-pos (point))) - ((gptel--link-standalone-p - (car link-at-pt) (cadr link-at-pt))) - (path (nth 3 link-at-pt)) - (path (string-remove-prefix "file://" path)) - (mime (mailcap-file-name-to-mime-type path)) - ((gptel--model-mime-capable-p mime))) - (cond - ((seq-some (lambda (p) (string-prefix-p p path)) - '("https:" "http:" "ftp:")) - ;; Collect text up to this image, and collect this image url - (when (gptel--model-capable-p 'url) ; FIXME This is not a good place - ; to check for url capability! - (push (list :text (buffer-substring-no-properties from-pt (car link-at-pt))) - parts) - (push (list :url path :mime mime) parts) - (setq from-pt (cadr link-at-pt)))) - ((file-readable-p path) - ;; Collect text up to this image, and collect this image - (push (list :text (buffer-substring-no-properties from-pt (car link-at-pt))) - parts) - (push (list :media path :mime mime) parts) - (setq from-pt (cadr link-at-pt))))))) - (unless (= from-pt end) - (push (list :text (buffer-substring-no-properties from-pt end)) parts)) - (nreverse parts))) - -(cl-defgeneric gptel--wrap-user-prompt (backend _prompts) - "Wrap the last prompt in PROMPTS with gptel's context. - -PROMPTS is a structure as returned by `gptel--parse-buffer'. -Typically this is a list of plists. - -BACKEND is the gptel backend in use." - (display-warning - '(gptel context) - (format "Context support not implemented for backend %s, ignoring context" - (gptel-backend-name backend)))) - -(cl-defgeneric gptel--request-data (backend prompts) - "Generate a plist of all data for an LLM query. - -BACKEND is the LLM backend in use. - -PROMPTS is the plist of previous user queries and LLM responses.") - -;; TODO: Use `run-hook-wrapped' with an accumulator instead to handle -;; buffer-local hooks, etc. -(defun gptel--transform-response (content-str buffer) - "Filter CONTENT-STR through `gptel-response-filter-functions`. - -BUFFER is passed along with CONTENT-STR to each function in this -hook." - (let ((filtered-str content-str)) - (dolist (filter-func gptel-response-filter-functions filtered-str) - (condition-case nil - (when (functionp filter-func) - (setq filtered-str - (funcall filter-func filtered-str buffer))) - (error - (display-warning '(gptel filter-functions) - (format "Function %S returned an error" - filter-func))))))) - -(defun gptel--convert-org (content buffer) - "Transform CONTENT according to required major-mode. - -Currently only `org-mode' is handled. - -BUFFER is the LLM interaction buffer." - (if (with-current-buffer buffer (derived-mode-p 'org-mode)) - (gptel--convert-markdown->org content) - content)) - -(defun gptel--url-get-response (info &optional callback) - "Fetch response to prompt in INFO from the LLM. - -INFO is a plist with the following keys: -- :data (the data being sent) -- :buffer (the gptel buffer) -- :position (marker at which to insert the response). - -Call CALLBACK with the response and INFO afterwards. If omitted -the response is inserted into the current buffer after point." - (let* ((inhibit-message t) - (message-log-max nil) - (backend gptel-backend) - (url-request-method "POST") - (url-request-extra-headers - (append '(("Content-Type" . "application/json")) - (when-let ((header (gptel-backend-header gptel-backend))) - (if (functionp header) - (funcall header) header)))) - (url-request-data - (encode-coding-string - (gptel--json-encode (plist-get info :data)) - 'utf-8))) - ;; why do these checks not occur inside of `gptel--log'? - (when gptel-log-level ;logging - (when (eq gptel-log-level 'debug) - (gptel--log (gptel--json-encode - (mapcar (lambda (pair) (cons (intern (car pair)) (cdr pair))) - url-request-extra-headers)) - "request headers")) - (gptel--log url-request-data "request body")) - (url-retrieve (let ((backend-url (gptel-backend-url gptel-backend))) - (if (functionp backend-url) - (funcall backend-url) backend-url)) - (lambda (_) - (pcase-let ((`(,response ,http-msg ,error) - (gptel--url-parse-response backend (current-buffer)))) - (plist-put info :status http-msg) - (when error (plist-put info :error error)) - (funcall (or callback #'gptel--insert-response) - response info) - (kill-buffer))) - nil t nil))) - -(cl-defgeneric gptel--parse-response (backend response proc-info) - "Response extractor for LLM requests. - -BACKEND is the LLM backend in use. - -RESPONSE is the parsed JSON of the response, as a plist. - -PROC-INFO is a plist with process information and other context. -See `gptel-curl--get-response' for its contents.") - -(defvar url-http-end-of-headers) -(defvar url-http-response-status) -(defun gptel--url-parse-response (backend response-buffer) - "Parse response from BACKEND in RESPONSE-BUFFER." - (when (buffer-live-p response-buffer) - (with-current-buffer response-buffer - (when gptel-log-level ;logging - (save-excursion - (goto-char url-http-end-of-headers) - (when (eq gptel-log-level 'debug) - (gptel--log (gptel--json-encode (buffer-substring-no-properties (point-min) (point))) - "response headers")) - (gptel--log (buffer-substring-no-properties (point) (point-max)) - "response body"))) - (if-let* ((http-msg (string-trim (buffer-substring (line-beginning-position) - (line-end-position)))) - (response (progn (goto-char url-http-end-of-headers) - (condition-case nil - (gptel--json-read) - (error 'json-read-error))))) - (cond - ;; FIXME Handle the case where HTTP 100 is followed by HTTP (not 200) BUG #194 - ((or (memq url-http-response-status '(200 100)) - (string-match-p "\\(?:1\\|2\\)00 OK" http-msg)) - (list (string-trim (gptel--parse-response backend response - `(:buffer ,response-buffer - :backend ,backend))) - http-msg)) - ((plist-get response :error) - (let* ((error-data (plist-get response :error)) - (error-msg (plist-get error-data :message)) - (error-type (plist-get error-data :type)) - (backend-name (gptel-backend-name backend))) - (if (stringp error-data) - (progn - (message "%s error: (%s) %s" backend-name http-msg error-data) - (setq error-msg (string-trim error-data))) - (when (stringp error-msg) - (message "%s error: (%s) %s" backend-name http-msg (string-trim error-msg))) - (when error-type - (setq http-msg (concat "(" http-msg ") " (string-trim error-type))))) - (list nil (concat "(" http-msg ") " (or error-msg ""))))) - ((eq response 'json-read-error) - (list nil (concat "(" http-msg ") Malformed JSON in response.") "json-read-error")) - (t (list nil (concat "(" http-msg ") Could not parse HTTP response.") - "Could not parse HTTP response."))) - (list nil (concat "(" http-msg ") Could not parse HTTP response.") - "Could not parse HTTP response."))))) - -(cl-defun gptel--sanitize-model (&key (backend gptel-backend) - (model gptel-model) - (shoosh t)) - "Check if MODEL is available in BACKEND, adjust accordingly. - -If SHOOSH is true, don't issue a warning." - (let ((available (gptel-backend-models backend))) - (when (stringp model) - (unless shoosh - (display-warning - 'gptel - (format "`gptel-model' expects a symbol, found string \"%s\" - Resetting `gptel-model' to %s" - model model))) - (setq gptel-model (gptel--intern model) - model gptel-model)) - (unless (member model available) - (let ((fallback (car available))) - (unless shoosh - (display-warning - 'gptel - (format (concat "Preferred `gptel-model' \"%s\" not" - "supported in \"%s\", using \"%s\" instead") - model (gptel-backend-name backend) fallback))) - (setq-local gptel-model fallback))))) - -;;;###autoload -(defun gptel (name &optional _ initial interactivep) - "Switch to or start a chat session with NAME. - -Ask for API-KEY if `gptel-api-key' is unset. - -If region is active, use it as the INITIAL prompt. Returns the -buffer created or switched to. - -INTERACTIVEP is t when gptel is called interactively." - (interactive - (let* ((backend (default-value 'gptel-backend)) - (backend-name - (format "*%s*" (gptel-backend-name backend)))) - (list (read-buffer - "Create or choose gptel buffer: " - backend-name nil ; DEFAULT and REQUIRE-MATCH - (lambda (b) ; PREDICATE - ;; NOTE: buffer check is required (#450) - (and-let* ((buf (get-buffer (or (car-safe b) b)))) - (buffer-local-value 'gptel-mode buf)))) - (condition-case nil - (gptel--get-api-key - (gptel-backend-key backend)) - ((error user-error) - (setq gptel-api-key - (read-passwd - (format "%s API key: " backend-name))))) - (and (use-region-p) - (buffer-substring (region-beginning) - (region-end))) - t))) - (with-current-buffer (get-buffer-create name) - (cond ;Set major mode - ((eq major-mode gptel-default-mode)) - ((eq gptel-default-mode 'text-mode) - (text-mode) - (visual-line-mode 1)) - (t (funcall gptel-default-mode))) - (gptel--sanitize-model :backend (default-value 'gptel-backend) - :model (default-value 'gptel-model) - :shoosh nil) - (unless gptel-mode (gptel-mode 1)) - (goto-char (point-max)) - (skip-chars-backward "\t\r\n") - (if (bobp) (insert (or initial (gptel-prompt-prefix-string)))) - (when interactivep - (display-buffer (current-buffer) gptel-display-buffer-action) - (message "Send your query with %s!" - (substitute-command-keys "\\[gptel-send]"))) - (current-buffer))) - - -;;; Response tweaking commands - -(defun gptel--attach-response-history (history &optional buf) - "Attach HISTORY to the next gptel response in buffer BUF. - -HISTORY is a list of strings typically containing text replaced -by gptel. BUF is the current buffer if not specified. - -This is used to maintain variants of prompts or responses to diff -against if required." - (with-current-buffer (or buf (current-buffer)) - (letrec ((gptel--attach-after - (lambda (b e) - (put-text-property b e 'gptel-history - (append (ensure-list history) - (get-char-property (1- e) 'gptel-history))) - (remove-hook 'gptel-post-response-functions - gptel--attach-after 'local)))) - (add-hook 'gptel-post-response-functions gptel--attach-after - nil 'local)))) - -(defun gptel--ediff (&optional arg bounds-func) - "Ediff response at point against previous gptel responses. - -If prefix ARG is non-nil, select the previous response to ediff -against interactively. - -If specified, use BOUNDS-FUNC to compute the bounds of the -response at point. This can be used to include additional -context for the ediff session." - (interactive "P") - (when (gptel--at-response-history-p) - (pcase-let* ((`(,beg . ,end) (funcall (or bounds-func #'gptel--get-bounds))) - (prev-response - (if arg - (completing-read "Choose response variant to diff against: " - (get-char-property (point) 'gptel-history) - nil t) - (car-safe (get-char-property (point) 'gptel-history)))) - (buffer-mode major-mode) - (bufname (buffer-name)) - (`(,new-buf ,new-beg ,new-end) - (with-current-buffer - (get-buffer-create (concat bufname "-PREVIOUS-*")) - (let ((inhibit-read-only t)) - (erase-buffer) - (delay-mode-hooks (funcall buffer-mode)) - (visual-line-mode) - (insert prev-response) - (goto-char (point-min)) - (list (current-buffer) (point-min) (point-max)))))) - (unless prev-response (user-error "gptel response is additive: no changes to ediff")) - (require 'ediff) - (letrec ((cwc (current-window-configuration)) - (gptel--ediff-restore - (lambda () - (when (window-configuration-p cwc) - (set-window-configuration cwc)) - (kill-buffer (get-buffer (concat bufname "-PREVIOUS-*"))) - (kill-buffer (get-buffer (concat bufname "-CURRENT-*"))) - (remove-hook 'ediff-quit-hook gptel--ediff-restore)))) - (add-hook 'ediff-quit-hook gptel--ediff-restore) - (apply - #'ediff-regions-internal - (get-buffer (ediff-make-cloned-buffer (current-buffer) "-CURRENT-*")) - beg end new-buf new-beg new-end - nil - (list 'ediff-regions-wordwise 'word-wise nil) - ;; (if (transient-arg-value "-w" args) - ;; (list 'ediff-regions-wordwise 'word-wise nil) - ;; (list 'ediff-regions-linewise nil nil)) - ))))) - -(defun gptel--mark-response () - "Mark gptel response at point, if any." - (interactive) - (unless (gptel--in-response-p) (user-error "No gptel response at point")) - (pcase-let ((`(,beg . ,end) (gptel--get-bounds))) - (goto-char beg) (push-mark) (goto-char end) (activate-mark))) - -(defun gptel--previous-variant (&optional arg) - "Switch to previous gptel-response at this point, if it exists." - (interactive "p") - (pcase-let* ((`(,beg . ,end) (gptel--get-bounds)) - (history (get-char-property (point) 'gptel-history)) - (alt-response (car-safe history)) - (offset)) - (unless (and history alt-response) - (user-error "No variant responses available")) - (if (> arg 0) - (setq history (append (cdr history) - (list (buffer-substring-no-properties beg end)))) - (setq - alt-response (car (last history)) - history (cons (buffer-substring-no-properties beg end) - (nbutlast history)))) - (add-text-properties - 0 (length alt-response) - `(gptel response gptel-history ,history) - alt-response) - (setq offset (min (- (point) beg) (1- (length alt-response)))) - (delete-region beg end) - (insert alt-response) - (goto-char (+ beg offset)) - (pulse-momentary-highlight-region beg (+ beg (length alt-response))))) - -(defun gptel--next-variant (&optional arg) - "Switch to next gptel-response at this point, if it exists." - (interactive "p") - (gptel--previous-variant (- arg))) - -(provide 'gptel) -;;; gptel.el ends here - -;; Local Variables: -;; bug-reference-url-format: "https://github.com/karthink/gptel/issues/%s" -;; End: diff --git a/emacs/elpa/gptel-20241115.456/gptel.elc b/emacs/elpa/gptel-20241115.456/gptel.elc Binary files differ. diff --git a/emacs/elpa/gptel-20241115.456/gptel-anthropic.el b/emacs/elpa/gptel-20241123.2058/gptel-anthropic.el diff --git a/emacs/elpa/gptel-20241115.456/gptel-anthropic.elc b/emacs/elpa/gptel-20241123.2058/gptel-anthropic.elc Binary files differ. diff --git a/emacs/elpa/gptel-20241115.456/gptel-autoloads.el b/emacs/elpa/gptel-20241123.2058/gptel-autoloads.el diff --git a/emacs/elpa/gptel-20241115.456/gptel-context.el b/emacs/elpa/gptel-20241123.2058/gptel-context.el diff --git a/emacs/elpa/gptel-20241115.456/gptel-context.elc b/emacs/elpa/gptel-20241123.2058/gptel-context.elc Binary files differ. diff --git a/emacs/elpa/gptel-20241115.456/gptel-curl.el b/emacs/elpa/gptel-20241123.2058/gptel-curl.el diff --git a/emacs/elpa/gptel-20241115.456/gptel-curl.elc b/emacs/elpa/gptel-20241123.2058/gptel-curl.elc Binary files differ. diff --git a/emacs/elpa/gptel-20241115.456/gptel-gemini.el b/emacs/elpa/gptel-20241123.2058/gptel-gemini.el diff --git a/emacs/elpa/gptel-20241115.456/gptel-gemini.elc b/emacs/elpa/gptel-20241123.2058/gptel-gemini.elc Binary files differ. diff --git a/emacs/elpa/gptel-20241115.456/gptel-kagi.el b/emacs/elpa/gptel-20241123.2058/gptel-kagi.el diff --git a/emacs/elpa/gptel-20241115.456/gptel-kagi.elc b/emacs/elpa/gptel-20241123.2058/gptel-kagi.elc Binary files differ. diff --git a/emacs/elpa/gptel-20241115.456/gptel-ollama.el b/emacs/elpa/gptel-20241123.2058/gptel-ollama.el diff --git a/emacs/elpa/gptel-20241115.456/gptel-ollama.elc b/emacs/elpa/gptel-20241123.2058/gptel-ollama.elc Binary files differ. diff --git a/emacs/elpa/gptel-20241123.2058/gptel-openai.el b/emacs/elpa/gptel-20241123.2058/gptel-openai.el @@ -0,0 +1,455 @@ +;;; gptel-openai.el --- ChatGPT suppport for gptel -*- lexical-binding: t; -*- + +;; Copyright (C) 2023 Karthik Chikmagalur + +;; Author: Karthik Chikmagalur <karthikchikmagalur@gmail.com> + +;; 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 <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; This file adds support for the ChatGPT API to gptel + +;;; Code: +(require 'cl-generic) +(eval-when-compile + (require 'cl-lib)) +(require 'map) + +(defvar gptel-model) +(defvar gptel-stream) +(defvar gptel-use-curl) +(defvar gptel-backend) +(defvar gptel-temperature) +(defvar gptel-max-tokens) +(defvar gptel--system-message) +(defvar json-object-type) +(defvar gptel-mode) +(defvar gptel-track-response) +(defvar gptel-track-media) +(declare-function gptel-context--collect-media "gptel-context") +(declare-function gptel--base64-encode "gptel") +(declare-function gptel--trim-prefixes "gptel") +(declare-function gptel--parse-media-links "gptel") +(declare-function gptel--model-capable-p "gptel") +(declare-function gptel--model-name "gptel") +(declare-function gptel--get-api-key "gptel") +(declare-function prop-match-value "text-property-search") +(declare-function text-property-search-backward "text-property-search") +(declare-function json-read "json") +(declare-function gptel-prompt-prefix-string "gptel") +(declare-function gptel-response-prefix-string "gptel") +(declare-function gptel--merge-plists "gptel") +(declare-function gptel--model-request-params "gptel") +(declare-function gptel-context--wrap "gptel-context") + +(defmacro gptel--json-read () + (if (fboundp 'json-parse-buffer) + `(json-parse-buffer + :object-type 'plist + :null-object nil + :false-object :json-false) + (require 'json) + (defvar json-object-type) + (declare-function json-read "json" ()) + `(let ((json-object-type 'plist)) + (json-read)))) + +(defmacro gptel--json-encode (object) + (if (fboundp 'json-serialize) + `(json-serialize ,object + :null-object nil + :false-object :json-false) + (require 'json) + (defvar json-false) + (declare-function json-encode "json" (object)) + `(let ((json-false :json-false)) + (json-encode ,object)))) + +(defun gptel--process-models (models) + "Convert items in MODELS to symbols with appropriate properties." + (let ((models-processed)) + (dolist (model models) + (cl-etypecase model + (string (push (intern model) models-processed)) + (symbol (push model models-processed)) + (cons + (cl-destructuring-bind (name . props) model + (setf (symbol-plist name) + ;; MAYBE: Merging existing symbol plists is safer, but makes it + ;; difficult to reset a symbol plist, since removing keys from + ;; it (as opposed to setting them to nil) is more work. + ;; + ;; (map-merge 'plist (symbol-plist name) props) + props) + (push name models-processed))))) + (nreverse models-processed))) + +;;; Common backend struct for LLM support +(defvar gptel--known-backends nil + "Alist of LLM backends known to gptel. + +This is an alist mapping user-provided names to backend structs, +see `gptel-backend'. + +You can have more than one backend pointing to the same resource +with differing settings.") + +(cl-defstruct + (gptel-backend (:constructor gptel--make-backend) + (:copier gptel--copy-backend)) + name host header protocol stream + endpoint key models url request-params + curl-args) + +;;; OpenAI (ChatGPT) +(cl-defstruct (gptel-openai (:constructor gptel--make-openai) + (:copier nil) + (:include gptel-backend))) + +(cl-defmethod gptel-curl--parse-stream ((_backend gptel-openai) _info) + (let* ((content-strs)) + (condition-case nil + (while (re-search-forward "^data:" nil t) + (save-match-data + (unless (looking-at " *\\[DONE\\]") + (when-let* ((response (gptel--json-read)) + (delta (map-nested-elt + response '(:choices 0 :delta))) + (content (plist-get delta :content))) + (push content content-strs))))) + (error + (goto-char (match-beginning 0)))) + (apply #'concat (nreverse content-strs)))) + +(cl-defmethod gptel--parse-response ((_backend gptel-openai) response _info) + (map-nested-elt response '(:choices 0 :message :content))) + +(cl-defmethod gptel--request-data ((_backend gptel-openai) prompts) + "JSON encode PROMPTS for sending to ChatGPT." + (let ((prompts-plist + `(:model ,(gptel--model-name gptel-model) + :messages [,@prompts] + :stream ,(or (and gptel-stream gptel-use-curl + (gptel-backend-stream gptel-backend)) + :json-false)))) + (when gptel-temperature + (plist-put prompts-plist :temperature gptel-temperature)) + (when gptel-max-tokens + (plist-put prompts-plist :max_completion_tokens gptel-max-tokens)) + ;; Merge request params with model and backend params. + (gptel--merge-plists + prompts-plist + (gptel-backend-request-params gptel-backend) + (gptel--model-request-params gptel-model)))) + +(cl-defmethod gptel--parse-buffer ((_backend gptel-openai) &optional max-entries) + (let ((prompts) (prop) + (include-media (and gptel-track-media + (or (gptel--model-capable-p 'media) + (gptel--model-capable-p 'url))))) + (if (or gptel-mode gptel-track-response) + (while (and + (or (not max-entries) (>= max-entries 0)) + (setq prop (text-property-search-backward + 'gptel 'response + (when (get-char-property (max (point-min) (1- (point))) + 'gptel) + t)))) + (if (prop-match-value prop) ;assistant role + (push (list :role "assistant" + :content + (buffer-substring-no-properties (prop-match-beginning prop) + (prop-match-end prop))) + prompts) + (if include-media + (push (list :role "user" + :content + (gptel--openai-parse-multipart + (gptel--parse-media-links + major-mode (prop-match-beginning prop) (prop-match-end prop)))) + prompts) + (push (list :role "user" + :content + (gptel--trim-prefixes + (buffer-substring-no-properties (prop-match-beginning prop) + (prop-match-end prop)))) + prompts))) + (and max-entries (cl-decf max-entries))) + (push (list :role "user" + :content + (gptel--trim-prefixes (buffer-substring-no-properties (point-min) (point-max)))) + prompts)) + (if (and (not (gptel--model-capable-p 'nosystem)) + gptel--system-message) + (cons (list :role "system" + :content gptel--system-message) + prompts) + prompts))) + +;; TODO This could be a generic function +(defun gptel--openai-parse-multipart (parts) + "Convert a multipart prompt PARTS to the OpenAI API format. + +The input is an alist of the form + ((:text \"some text\") + (:media \"/path/to/media.png\" :mime \"image/png\") + (:text \"More text\")). + +The output is a vector of entries in a backend-appropriate +format." + (cl-loop + for part in parts + for n upfrom 1 + with last = (length parts) + for text = (plist-get part :text) + for media = (plist-get part :media) + if text do + (and (or (= n 1) (= n last)) (setq text (gptel--trim-prefixes text))) and + unless (string-empty-p text) + collect `(:type "text" :text ,text) into parts-array end + else if media + collect + `(:type "image_url" + :image_url (:url ,(concat "data:" (plist-get part :mime) + ";base64," (gptel--base64-encode media)))) + into parts-array end and + if (plist-get part :url) + collect + `(:type "image_url" + :image_url (:url ,(plist-get part :url))) + into parts-array + finally return (vconcat parts-array))) + +;; TODO: Does this need to be a generic function? +(cl-defmethod gptel--wrap-user-prompt ((_backend gptel-openai) prompts + &optional inject-media) + "Wrap the last user prompt in PROMPTS with the context string. + +If INJECT-MEDIA is non-nil wrap it with base64-encoded media +files in the context." + (if inject-media + ;; Wrap the first user prompt with included media files/contexts + (when-let ((media-list (gptel-context--collect-media))) + (cl-callf (lambda (current) + (vconcat + (gptel--openai-parse-multipart media-list) + (cl-typecase current + (string `((:type "text" :text ,current))) + (vector current) + (t current)))) + (plist-get (cadr prompts) :content))) + ;; Wrap the last user prompt with included text contexts + (cl-callf (lambda (current) + (cl-etypecase current + (string (gptel-context--wrap current)) + (vector (if-let ((wrapped (gptel-context--wrap nil))) + (vconcat `((:type "text" :text ,wrapped)) + current) + current)))) + (plist-get (car (last prompts)) :content)))) + +;;;###autoload +(cl-defun gptel-make-openai + (name &key curl-args models stream key request-params + (header + (lambda () (when-let (key (gptel--get-api-key)) + `(("Authorization" . ,(concat "Bearer " key)))))) + (host "api.openai.com") + (protocol "https") + (endpoint "/v1/chat/completions")) + "Register an OpenAI API-compatible backend for gptel with NAME. + +Keyword arguments: + +CURL-ARGS (optional) is a list of additional Curl arguments. + +HOST (optional) is the API host, typically \"api.openai.com\". + +MODELS is a list of available model names, as symbols. +Additionally, you can specify supported LLM capabilities like +vision or tool-use by appending a plist to the model with more +information, in the form + + (model-name . plist) + +For a list of currently recognized plist keys, see +`gptel--openai-models'. An example of a model specification +including both kinds of specs: + +:models +\\='(gpt-3.5-turbo ;Simple specs + gpt-4-turbo + (gpt-4o-mini ;Full spec + :description + \"Affordable and intelligent small model for lightweight tasks\" + :capabilities (media tool json url) + :mime-types + (\"image/jpeg\" \"image/png\" \"image/gif\" \"image/webp\"))) + +STREAM is a boolean to toggle streaming responses, defaults to +false. + +PROTOCOL (optional) specifies the protocol, https by default. + +ENDPOINT (optional) is the API endpoint for completions, defaults to +\"/v1/chat/completions\". + +HEADER (optional) is for additional headers to send with each +request. It should be an alist or a function that retuns an +alist, like: + ((\"Content-Type\" . \"application/json\")) + +KEY (optional) is a variable whose value is the API key, or +function that returns the key. + +REQUEST-PARAMS (optional) is a plist of additional HTTP request +parameters (as plist keys) and values supported by the API. Use +these to set parameters that gptel does not provide user options +for." + (declare (indent 1)) + (let ((backend (gptel--make-openai + :curl-args curl-args + :name name + :host host + :header header + :key key + :models (gptel--process-models models) + :protocol protocol + :endpoint endpoint + :stream stream + :request-params request-params + :url (if protocol + (concat protocol "://" host endpoint) + (concat host endpoint))))) + (prog1 backend + (setf (alist-get name gptel--known-backends + nil nil #'equal) + backend)))) + +;;; Azure +;;;###autoload +(cl-defun gptel-make-azure + (name &key curl-args host + (protocol "https") + (header (lambda () `(("api-key" . ,(gptel--get-api-key))))) + (key 'gptel-api-key) + models stream endpoint request-params) + "Register an Azure backend for gptel with NAME. + +Keyword arguments: + +CURL-ARGS (optional) is a list of additional Curl arguments. + +HOST is the API host. + +MODELS is a list of available model names, as symbols. + +STREAM is a boolean to toggle streaming responses, defaults to +false. + +PROTOCOL (optional) specifies the protocol, https by default. + +ENDPOINT is the API endpoint for completions. + +HEADER (optional) is for additional headers to send with each +request. It should be an alist or a function that retuns an +alist, like: + ((\"Content-Type\" . \"application/json\")) + +KEY (optional) is a variable whose value is the API key, or +function that returns the key. + +REQUEST-PARAMS (optional) is a plist of additional HTTP request +parameters (as plist keys) and values supported by the API. Use +these to set parameters that gptel does not provide user options +for. + +Example: +------- + + (gptel-make-azure + \"Azure-1\" + :protocol \"https\" + :host \"RESOURCE_NAME.openai.azure.com\" + :endpoint + \"/openai/deployments/DEPLOYMENT_NAME/completions?api-version=2023-05-15\" + :stream t + :models \\='(gpt-3.5-turbo gpt-4))" + (declare (indent 1)) + (let ((backend (gptel--make-openai + :curl-args curl-args + :name name + :host host + :header header + :key key + :models (gptel--process-models models) + :protocol protocol + :endpoint endpoint + :stream stream + :request-params request-params + :url (if protocol + (concat protocol "://" host endpoint) + (concat host endpoint))))) + (prog1 backend + (setf (alist-get name gptel--known-backends + nil nil #'equal) + backend)))) + +;; GPT4All +;;;###autoload +(defalias 'gptel-make-gpt4all 'gptel-make-openai + "Register a GPT4All backend for gptel with NAME. + +Keyword arguments: + +CURL-ARGS (optional) is a list of additional Curl arguments. + +HOST is where GPT4All runs (with port), typically localhost:4891 + +MODELS is a list of available model names, as symbols. + +STREAM is a boolean to toggle streaming responses, defaults to +false. + +PROTOCOL specifies the protocol, https by default. + +ENDPOINT (optional) is the API endpoint for completions, defaults to +\"/api/v1/completions\" + +HEADER (optional) is for additional headers to send with each +request. It should be an alist or a function that retuns an +alist, like: +((\"Content-Type\" . \"application/json\")) + +KEY (optional) is a variable whose value is the API key, or +function that returns the key. This is typically not required for +local models like GPT4All. + +REQUEST-PARAMS (optional) is a plist of additional HTTP request +parameters (as plist keys) and values supported by the API. Use +these to set parameters that gptel does not provide user options +for. + +Example: +------- + +(gptel-make-gpt4all + \"GPT4All\" + :protocol \"http\" + :host \"localhost:4891\" + :models \\='(mistral-7b-openorca.Q4_0.gguf))") + +(provide 'gptel-openai) +;;; gptel-openai.el ends here diff --git a/emacs/elpa/gptel-20241123.2058/gptel-openai.elc b/emacs/elpa/gptel-20241123.2058/gptel-openai.elc Binary files differ. diff --git a/emacs/elpa/gptel-20241115.456/gptel-org.el b/emacs/elpa/gptel-20241123.2058/gptel-org.el diff --git a/emacs/elpa/gptel-20241115.456/gptel-org.elc b/emacs/elpa/gptel-20241123.2058/gptel-org.elc Binary files differ. diff --git a/emacs/elpa/gptel-20241123.2058/gptel-pkg.el b/emacs/elpa/gptel-20241123.2058/gptel-pkg.el @@ -0,0 +1,12 @@ +;; -*- no-byte-compile: t; lexical-binding: nil -*- +(define-package "gptel" "20241123.2058" + "Interact with ChatGPT or other LLMs." + '((emacs "27.1") + (transient "0.4.0") + (compat "29.1.4.1")) + :url "https://github.com/karthink/gptel" + :commit "20e07943d792133ba57a325e123436de471e1429" + :revdesc "20e07943d792" + :keywords '("convenience") + :authors '(("Karthik Chikmagalur" . "karthik.chikmagalur@gmail.com")) + :maintainers '(("Karthik Chikmagalur" . "karthik.chikmagalur@gmail.com"))) diff --git a/emacs/elpa/gptel-20241115.456/gptel-privategpt.el b/emacs/elpa/gptel-20241123.2058/gptel-privategpt.el diff --git a/emacs/elpa/gptel-20241115.456/gptel-privategpt.elc b/emacs/elpa/gptel-20241123.2058/gptel-privategpt.elc Binary files differ. diff --git a/emacs/elpa/gptel-20241123.2058/gptel-rewrite.el b/emacs/elpa/gptel-20241123.2058/gptel-rewrite.el @@ -0,0 +1,450 @@ +;;; gptel-rewrite.el --- Refactoring functions for gptel -*- lexical-binding: t; -*- + +;; Copyright (C) 2024 Karthik Chikmagalur + +;; Author: Karthik Chikmagalur <karthikchikmagalur@gmail.com> +;; Keywords: hypermedia, convenience, tools + +;; 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 <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; + +;;; Code: +(require 'gptel-transient) +(require 'cl-lib) + +(defvar eldoc-documentation-functions) +(defvar diff-entire-buffers) + +(declare-function diff-no-select "diff") + +;; * User options + +(defcustom gptel-rewrite-directives-hook (list #'gptel--rewrite-message) + "Hook run to generate gptel's default rewrite directives. + +Each function in this hook is called with no arguments until one +returns a non-nil value, the base string to use as the +rewrite/refactor instruction. + +Use this hook to tailor context-specific refactoring directives. +For example, you can specialize the default refactor directive +for a particular major-mode." + :group 'gptel + :type 'hook) + +(defface gptel-rewrite-highlight-face + '((((class color) (min-colors 88) (background dark)) + :background "#041714" :extend t) + (((class color) (min-colors 88) (background light)) + :background "light goldenrod yellow" :extend t) + (t :inherit secondary-selection)) + "Face for highlighting regions with pending rewrites." + :group 'gptel) + +;; * Variables + +(defvar-keymap gptel-rewrite-actions-map + :doc "Keymap for gptel rewrite actions at point." + "C-c C-k" #'gptel--rewrite-clear + "C-c C-a" #'gptel--rewrite-apply + "C-c C-d" #'gptel--rewrite-diff + "C-c C-e" #'gptel--rewrite-ediff + "C-c C-n" #'gptel--rewrite-next + "C-c C-p" #'gptel--rewrite-previous + "C-c C-m" #'gptel--rewrite-merge) + +(defvar-local gptel--rewrite-overlays nil + "List of active rewrite overlays in the buffer.") + +(defvar-local gptel--rewrite-message nil) + +;; * Helper functions + +(defun gptel--rewrite-sanitize-overlays () + "Ensure gptel's rewrite overlays in buffer are consistent." + (setq gptel--rewrite-overlays + (cl-delete-if-not #'overlay-buffer + gptel--rewrite-overlays))) + +(defsubst gptel--refactor-or-rewrite () + "Rewrite should be refactored into refactor. + +Or is it the other way around?" + (if (derived-mode-p 'prog-mode) + "Refactor" "Rewrite")) + +(defun gptel--rewrite-message () + "Set a generic refactor/rewrite message for the buffer." + (if (derived-mode-p 'prog-mode) + (format "You are a %s programmer. Generate only code, no explanation, no code fences. Refactor the following code." + (gptel--strip-mode-suffix major-mode)) + (format "You are a prose editor. Rewrite the following text to be more professional."))) + +(defun gptel--rewrite-key-help (callback) + "Eldoc documentation function for gptel rewrite actions. + +CALLBACK is supplied by Eldoc, see +`eldoc-documentation-functions'." + (when (and gptel--rewrite-overlays + (get-char-property (point) 'gptel-rewrite)) + (funcall callback + (format (substitute-command-keys "%s rewrite available: accept \\[gptel--rewrite-apply], clear \\[gptel--rewrite-clear], merge \\[gptel--rewrite-merge], diff \\[gptel--rewrite-diff] or ediff \\[gptel--rewrite-ediff]") + (propertize (concat (gptel-backend-name gptel-backend) + ":" (gptel--model-name gptel-model)) + 'face 'mode-line-emphasis))))) + +(defun gptel--rewrite-move (search-func) + "Move directionally to a gptel rewrite location using SEARCH-FUNC." + (let* ((ov (cdr (get-char-property-and-overlay (point) 'gptel-rewrite))) + (pt (save-excursion + (if ov + (goto-char + (funcall search-func (overlay-start ov) 'gptel-rewrite)) + (goto-char + (max (1- (funcall search-func (point) 'gptel-rewrite)) + (point-min)))) + (funcall search-func (point) 'gptel-rewrite)))) + (if (get-char-property pt 'gptel-rewrite) + (goto-char pt) + (user-error "No further rewrite regions!")))) + +(defun gptel--rewrite-next () + "Go to next pending LLM rewrite in buffer, if one exists." + (interactive) + (gptel--rewrite-move #'next-single-char-property-change)) + +(defun gptel--rewrite-previous () + "Go to previous pending LLM rewrite in buffer, if one exists." + (interactive) + (gptel--rewrite-move #'previous-single-char-property-change)) + +(defun gptel--rewrite-overlay-at (&optional pt) + "Check for a gptel rewrite overlay at PT and return it. + +If no suitable overlay is found, raise an error." + (pcase-let ((`(,response . ,ov) + (get-char-property-and-overlay (or pt (point)) 'gptel-rewrite)) + (diff-entire-buffers nil)) + (unless ov (user-error "Could not find region being rewritten.")) + (unless response (user-error "No LLM output available for this rewrite.")) + ov)) + +(defun gptel--rewrite-prepare-buffer (ovs &optional buf) + "Prepare new buffer with LLM changes applied and return it. + +This is used for (e)diff purposes. + +RESPONSE is the LLM response. OVS are the overlays specifying +the changed regions. BUF is the (current) buffer." + (setq buf (or buf (current-buffer))) + (with-current-buffer buf + (let ((pmin (point-min)) + (pmax (point-max)) + (pt (point)) + ;; (mode major-mode) + (newbuf (get-buffer-create "*gptel-diff*")) + (inhibit-read-only t) + (inhibit-message t)) + (save-restriction + (widen) + (with-current-buffer newbuf + (erase-buffer) + (insert-buffer-substring buf))) + (with-current-buffer newbuf + (narrow-to-region pmin pmax) + (goto-char pt) + ;; We mostly just want font-locking + ;; (delay-mode-hooks (funcall mode)) + ;; Apply the changes to the new buffer + (save-excursion + (gptel--rewrite-apply ovs))) + newbuf))) + +;; * Refactor action functions + +(defun gptel--rewrite-clear (&optional ovs) + "Clear pending LLM responses in OVS or at point." + (interactive (list (gptel--rewrite-overlay-at))) + (dolist (ov (ensure-list ovs)) + (setq gptel--rewrite-overlays (delq ov gptel--rewrite-overlays)) + (delete-overlay ov)) + (unless gptel--rewrite-overlays + (remove-hook 'eldoc-documentation-functions 'gptel--rewrite-key-help 'local)) + (message "Cleared pending LLM response(s).")) + +(defun gptel--rewrite-apply (&optional ovs) + "Apply pending LLM responses in OVS or at point." + (interactive (list (gptel--rewrite-overlay-at))) + (cl-loop for ov in (ensure-list ovs) + for ov-beg = (overlay-start ov) + for ov-end = (overlay-end ov) + for response = (overlay-get ov 'gptel-rewrite) + do (overlay-put ov 'before-string nil) + (goto-char ov-beg) + (delete-region ov-beg ov-end) + (insert response)) + (message "Replaced region(s) with LLM output.")) + +(defun gptel--rewrite-diff (&optional ovs switches) + "Diff pending LLM responses in OVS or at point." + (interactive (list (gptel--rewrite-overlay-at))) + (let* ((buf (current-buffer)) + (newbuf (gptel--rewrite-prepare-buffer ovs)) + (diff-buf (diff-no-select + (if-let ((buf-file (buffer-file-name buf))) + (expand-file-name buf-file) buf) + newbuf switches))) + (with-current-buffer diff-buf + (setq-local diff-jump-to-old-file t)) + (display-buffer diff-buf))) + +(defun gptel--rewrite-ediff (&optional ovs) + "Ediff pending LLM responses in OVS or at point." + (interactive (list (gptel--rewrite-overlay-at))) + (letrec ((newbuf (gptel--rewrite-prepare-buffer ovs)) + (cwc (current-window-configuration)) + (gptel--ediff-restore + (lambda () + (when (window-configuration-p cwc) + (set-window-configuration cwc)) + (remove-hook 'ediff-quit-hook gptel--ediff-restore)))) + (add-hook 'ediff-quit-hook gptel--ediff-restore) + (ediff-buffers (current-buffer) newbuf))) + +(defun gptel--rewrite-merge (&optional ovs) + "Insert pending LLM responses in OVS as merge conflicts." + (interactive (list (gptel--rewrite-overlay-at))) + (let ((changed)) + (dolist (ov (ensure-list ovs)) + (save-excursion + (when-let (new-str (overlay-get ov 'gptel-rewrite)) + ;; Insert merge + (goto-char (overlay-start ov)) + (unless (bolp) (insert "\n")) + (insert-before-markers "<<<<<<< original\n") + (goto-char (overlay-end ov)) + (unless (bolp) (insert "\n")) + (insert + "=======\n" new-str + "\n>>>>>>> " (gptel-backend-name gptel-backend) "\n") + (setq changed t)))) + (when changed (smerge-mode 1))) + (gptel--rewrite-clear ovs)) + +;; * Transient Prefix for rewriting/refactoring + +;;;###autoload (autoload 'gptel-rewrite-menu "gptel-rewrite" nil t) +(transient-define-prefix gptel-rewrite-menu () + "Rewrite or refactor text region using an LLM." + [:description + (lambda () + (format "Directive: %s" + (truncate-string-to-width + gptel--rewrite-message + (max (- (window-width) 14) 20) nil nil t))) + (gptel--infix-rewrite-prompt)] + ;; FIXME: We are requiring `gptel-transient' because of this suffix, perhaps + ;; we can get find some way around that?