Compare commits
44 Commits
pkgs-updat
...
2f868e6b50
| Author | SHA1 | Date | |
|---|---|---|---|
| 2f868e6b50 | |||
| 46cf268dd7 | |||
| 2f27c73b2f | |||
| 348cc168cc | |||
| 423e200458 | |||
| 5721e18608 | |||
| d6f64e66ea | |||
| 14dcaaddde | |||
| 45d49daef0 | |||
| 59db017445 | |||
| a0e23086ce | |||
| 4fa60b9497 | |||
| 940979a9fe | |||
| 9d25a4c02d | |||
| 7577659e42 | |||
| 6b9f2a0cf1 | |||
| 59aaf6fc14 | |||
| 504c2b1bfa | |||
| 156cec64fb | |||
| 8b80ceda39 | |||
| b18d02d8d5 | |||
| ddba0ba9cd | |||
| 94dd0e848e | |||
| 52815c9fe4 | |||
| b11956a890 | |||
| 5e9bb3b882 | |||
| 3894350a6a | |||
| c43933e9f6 | |||
| 3b54a3236d | |||
| e162a12b58 | |||
| f3935715a4 | |||
| a075f93c3e | |||
| 6253368410 | |||
| ce2c9354ed | |||
| 900a4d9928 | |||
| 3476d496a7 | |||
| 1e9910e471 | |||
| a4e15965bb | |||
| 99a0d6a185 | |||
| d95f45d049 | |||
| 4fe9a6b7e1 | |||
| d861ac5e74 | |||
| 4b839a12cd | |||
| 43d61b31d4 |
333
README.md
333
README.md
@@ -2,11 +2,12 @@
|
||||
# Table of Contents
|
||||
|
||||
1. [Installation](#installation)
|
||||
2. [Usage](#usage)
|
||||
3. [Packages](#packages)
|
||||
4. [Information](#information)
|
||||
5. [Errors](#errors)
|
||||
6. [TODOs](#todos)
|
||||
2. [External programs](#programs)
|
||||
3. [Usage](#usage)
|
||||
4. [Packages](#packages)
|
||||
5. [Information](#information)
|
||||
6. [Errors](#errors)
|
||||
7. [TODOs](#todos)
|
||||
|
||||
This is an ongoing evolution of Emacs configuration files, inspired by
|
||||
a bunch of online resources.
|
||||
@@ -16,17 +17,41 @@ a bunch of online resources.
|
||||
|
||||
# Installation
|
||||
|
||||
Download repo and point the emacs `init` (and `early-init.el`) file to
|
||||
this configuration.
|
||||
Different ways to install:
|
||||
|
||||
Or run one of the following install script commands (using curl, wget or fetch).
|
||||
- **arch-linux:** If `emacs-conf` is available in a `custom` `pacman` repository
|
||||
|
||||
pacman -S emacs-conf
|
||||
ln -s /opt/emacs-conf/init ~/.config/emacs/
|
||||
ln -s /opt/emacs-conf/early-init.el ~/.config/emacs/
|
||||
|
||||
sh -c "$(curl -fsSL http://gitea.weseng.de/daniel/emacs/raw/master/scripts/install.sh)"
|
||||
sh -c "$(wget -O- http://gitea.weseng.de/daniel/emacs/raw/master/scripts/install.sh)"
|
||||
sh -c "$(fetch -o - http://gitea.weseng.de/daniel/emacs/raw/master/scripts/install.sh)"
|
||||
- **debian:** If `emacs-conf` is available in a `custom` `apt` repository
|
||||
|
||||
apt install emacs-conf
|
||||
ln -s /opt/emacs-conf/init ~/.config/emacs/
|
||||
ln -s /opt/emacs-conf/early-init.el ~/.config/emacs/
|
||||
|
||||
Installation path is `~/.config/emacs`. See details and other
|
||||
installed linux packages as requirements inside `sripts/install.sh`.
|
||||
- **manual:** Download or clone git repo and point the emacs `init` and
|
||||
`early-init.el` file to this configuration.
|
||||
|
||||
- **old:** Run one of the following install script commands (using curl,
|
||||
wget or fetch).
|
||||
|
||||
sh -c "$(curl -fsSL http://gitea.weseng.de/daniel/emacs/raw/master/scripts/install.sh)"
|
||||
sh -c "$(wget -O- http://gitea.weseng.de/daniel/emacs/raw/master/scripts/install.sh)"
|
||||
sh -c "$(fetch -o - http://gitea.weseng.de/daniel/emacs/raw/master/scripts/install.sh)"
|
||||
|
||||
Installation path is `~/.config/emacs`. See details and other
|
||||
installed linux packages as requirements inside `sripts/install.sh`.
|
||||
|
||||
|
||||
<a id="programs"></a>
|
||||
|
||||
# External programs
|
||||
|
||||
- `ripgrep` (optional) used by `counsel-rg` (package `counsel`)
|
||||
- `texlive-luatex` for `luainputenc.sty` used by org latex export
|
||||
- `texlive-xetex` for `realscripts.sty` for `KpRoman` used by org latex export
|
||||
|
||||
|
||||
<a id="usage"></a>
|
||||
@@ -60,7 +85,7 @@ General key bindings and functions
|
||||
|
||||
- `C-r` (`query-replace-regexp`) replace text
|
||||
- `C-x RET f` (`set-buffer-file-coding-system`) e.g. set to =utf-8
|
||||
- (`decode-coding-region`) e.g. decode to `utf-8` (郭富城Aaron Kwok)
|
||||
- (`decode-coding-region`) e.g. decode to `utf-8` (e.g. 晴天)
|
||||
- (`diff-buffer-with-file`) show a diff between buffer (current state) and file (saved state)
|
||||
|
||||
<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">
|
||||
@@ -97,35 +122,42 @@ General key bindings and functions
|
||||
|
||||
<tr>
|
||||
<td class="org-left">all-the-icons</td>
|
||||
<td class="org-right">20220929.2303</td>
|
||||
<td class="org-right">20230909.2053</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">all-the-icons-ivy-rich</td>
|
||||
<td class="org-right">20230420.1234</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">amx</td>
|
||||
<td class="org-right">20210305.118</td>
|
||||
<td class="org-right">20230413.121</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">anaconda-mode</td>
|
||||
<td class="org-right">20220922.741</td>
|
||||
<td class="org-right">20230821.2131</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">async</td>
|
||||
<td class="org-right">20221217.649</td>
|
||||
<td class="org-right">20230528.622</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">avy</td>
|
||||
<td class="org-right">20220910.1936</td>
|
||||
<td class="org-right">20230420.404</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
@@ -139,35 +171,42 @@ General key bindings and functions
|
||||
|
||||
<tr>
|
||||
<td class="org-left">biblio</td>
|
||||
<td class="org-right">20210418.406</td>
|
||||
<td class="org-right">20230202.1721</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">biblio-core</td>
|
||||
<td class="org-right">20210418.406</td>
|
||||
<td class="org-right">20230202.1721</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">bibtex-completion</td>
|
||||
<td class="org-right">20221024.857</td>
|
||||
<td class="org-right">20230918.953</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">bind-key</td>
|
||||
<td class="org-right">20221209.2013</td>
|
||||
<td class="org-right">20230203.2004</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">cfrs</td>
|
||||
<td class="org-right">20220129.1149</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">citeproc</td>
|
||||
<td class="org-right">20221216.1238</td>
|
||||
<td class="org-right">20230228.1414</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
@@ -181,14 +220,14 @@ General key bindings and functions
|
||||
|
||||
<tr>
|
||||
<td class="org-left">company</td>
|
||||
<td class="org-right">20221206.2122</td>
|
||||
<td class="org-right">20231023.1033</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">company-anaconda</td>
|
||||
<td class="org-right">20200404.1859</td>
|
||||
<td class="org-right">20230821.2126</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
@@ -202,7 +241,14 @@ General key bindings and functions
|
||||
|
||||
<tr>
|
||||
<td class="org-left">company-quickhelp</td>
|
||||
<td class="org-right">20221212.534</td>
|
||||
<td class="org-right">20231026.1714</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">company-statistics</td>
|
||||
<td class="org-right">20170210.1933</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
@@ -214,9 +260,16 @@ General key bindings and functions
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">compat</td>
|
||||
<td class="org-right">29.1.4.2</td>
|
||||
<td class="org-left">elpa-gnu</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">counsel</td>
|
||||
<td class="org-right">20221015.936</td>
|
||||
<td class="org-right">20231025.2311</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
@@ -237,14 +290,14 @@ General key bindings and functions
|
||||
|
||||
<tr>
|
||||
<td class="org-left">dash</td>
|
||||
<td class="org-right">20221013.836</td>
|
||||
<td class="org-right">20230714.723</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">dashboard</td>
|
||||
<td class="org-right">20221206.1228</td>
|
||||
<td class="org-right">20231031.359</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
@@ -272,7 +325,7 @@ General key bindings and functions
|
||||
|
||||
<tr>
|
||||
<td class="org-left">diff-hl</td>
|
||||
<td class="org-right">20221007.2147</td>
|
||||
<td class="org-right">20230807.1516</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
@@ -286,7 +339,28 @@ General key bindings and functions
|
||||
|
||||
<tr>
|
||||
<td class="org-left">elisp-refs</td>
|
||||
<td class="org-right">20220704.2141</td>
|
||||
<td class="org-right">20230920.201</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">emacsql</td>
|
||||
<td class="org-right">20230417.1448</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">emacsql-sqlite</td>
|
||||
<td class="org-right">20230225.2205</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">emacsql-sqlite-builtin</td>
|
||||
<td class="org-right">20230409.1847</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
@@ -300,7 +374,7 @@ General key bindings and functions
|
||||
|
||||
<tr>
|
||||
<td class="org-left">ess</td>
|
||||
<td class="org-right">20221204.1348</td>
|
||||
<td class="org-right">20230807.1422</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
@@ -314,14 +388,14 @@ General key bindings and functions
|
||||
|
||||
<tr>
|
||||
<td class="org-left">f</td>
|
||||
<td class="org-right">20220911.711</td>
|
||||
<td class="org-right">20230823.1159</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">flycheck</td>
|
||||
<td class="org-right">20221213.107</td>
|
||||
<td class="org-right">20230813.62</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
@@ -363,7 +437,7 @@ General key bindings and functions
|
||||
|
||||
<tr>
|
||||
<td class="org-left">git-commit</td>
|
||||
<td class="org-right">20221127.2227</td>
|
||||
<td class="org-right">20231030.2243</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
@@ -377,21 +451,21 @@ General key bindings and functions
|
||||
|
||||
<tr>
|
||||
<td class="org-left">gnuplot</td>
|
||||
<td class="org-right">20221112.2049</td>
|
||||
<td class="org-right">20230323.14</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">helpful</td>
|
||||
<td class="org-right">20221209.1743</td>
|
||||
<td class="org-right">20231028.516</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">ht</td>
|
||||
<td class="org-right">20221031.705</td>
|
||||
<td class="org-right">20230703.558</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
@@ -426,7 +500,7 @@ General key bindings and functions
|
||||
|
||||
<tr>
|
||||
<td class="org-left">ivy</td>
|
||||
<td class="org-right">20220926.125</td>
|
||||
<td class="org-right">20231025.2311</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
@@ -440,35 +514,35 @@ General key bindings and functions
|
||||
|
||||
<tr>
|
||||
<td class="org-left">ivy-rich</td>
|
||||
<td class="org-right">20210409.931</td>
|
||||
<td class="org-right">20230425.1422</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">js2-mode</td>
|
||||
<td class="org-right">20221028.1819</td>
|
||||
<td class="org-right">20230628.238</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">key-chord</td>
|
||||
<td class="org-right">20201222.203</td>
|
||||
<td class="org-right">20230522.223</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">langtool</td>
|
||||
<td class="org-right">20200529.23</td>
|
||||
<td class="org-right">20230222.326</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">ledger-mode</td>
|
||||
<td class="org-right">20220623.1125</td>
|
||||
<td class="org-right">20230925.1013</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
@@ -482,21 +556,21 @@ General key bindings and functions
|
||||
|
||||
<tr>
|
||||
<td class="org-left">magit</td>
|
||||
<td class="org-right">20221208.1848</td>
|
||||
<td class="org-right">20231103.1516</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">magit-section</td>
|
||||
<td class="org-right">20221127.2227</td>
|
||||
<td class="org-right">20231014.1405</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">markdown-mode</td>
|
||||
<td class="org-right">20221210.348</td>
|
||||
<td class="org-right">20231028.853</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
@@ -510,14 +584,21 @@ General key bindings and functions
|
||||
|
||||
<tr>
|
||||
<td class="org-left">mu4e-maildirs-extension</td>
|
||||
<td class="org-right">20220517.1852</td>
|
||||
<td class="org-left">melpa</td>
|
||||
<td class="org-right">melpa</td>
|
||||
<td class="org-left"> </td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">multiple-cursors</td>
|
||||
<td class="org-right">20221126.743</td>
|
||||
<td class="org-right">20230728.518</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">notmuch</td>
|
||||
<td class="org-right">20231006.2337</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
@@ -529,9 +610,23 @@ General key bindings and functions
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">olivetti</td>
|
||||
<td class="org-right">20231104.538</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">ol-notmuch</td>
|
||||
<td class="org-right">20230511.2048</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">org</td>
|
||||
<td class="org-right">9.6</td>
|
||||
<td class="org-right">9.6.11</td>
|
||||
<td class="org-left">elpa-gnu</td>
|
||||
</tr>
|
||||
|
||||
@@ -545,7 +640,7 @@ General key bindings and functions
|
||||
|
||||
<tr>
|
||||
<td class="org-left">org-brain</td>
|
||||
<td class="org-right">20210706.1519</td>
|
||||
<td class="org-right">20230217.1908</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
@@ -559,7 +654,7 @@ General key bindings and functions
|
||||
|
||||
<tr>
|
||||
<td class="org-left">org-contrib</td>
|
||||
<td class="org-right">0.4.1</td>
|
||||
<td class="org-right">0.4.2</td>
|
||||
<td class="org-left">elpa-nongnu</td>
|
||||
</tr>
|
||||
|
||||
@@ -587,14 +682,42 @@ General key bindings and functions
|
||||
|
||||
<tr>
|
||||
<td class="org-left">orgit</td>
|
||||
<td class="org-right">20221127.2228</td>
|
||||
<td class="org-right">20230917.1001</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">org-ref</td>
|
||||
<td class="org-right">20221129.1925</td>
|
||||
<td class="org-right">20231101.2355</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">org-roam</td>
|
||||
<td class="org-right">20230307.1721</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">org-roam-bibtex</td>
|
||||
<td class="org-right">20230628.2036</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">org-roam-timestamps</td>
|
||||
<td class="org-right">20221104.1544</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">org-roam-ui</td>
|
||||
<td class="org-right">20221105.104</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
@@ -608,7 +731,7 @@ General key bindings and functions
|
||||
|
||||
<tr>
|
||||
<td class="org-left">org-superstar</td>
|
||||
<td class="org-right">20210915.1934</td>
|
||||
<td class="org-right">20230116.1358</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
@@ -622,14 +745,14 @@ General key bindings and functions
|
||||
|
||||
<tr>
|
||||
<td class="org-left">ov</td>
|
||||
<td class="org-right">20200326.1042</td>
|
||||
<td class="org-right">20230522.1117</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">ox-pandoc</td>
|
||||
<td class="org-right">20220705.1036</td>
|
||||
<td class="org-right">20230627.643</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
@@ -643,28 +766,28 @@ General key bindings and functions
|
||||
|
||||
<tr>
|
||||
<td class="org-left">ox-tufte</td>
|
||||
<td class="org-right">20160926.1607</td>
|
||||
<td class="org-right">20231022.2117</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">page-break-lines</td>
|
||||
<td class="org-right">20210104.2224</td>
|
||||
<td class="org-right">20230804.658</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">parsebib</td>
|
||||
<td class="org-right">20221007.1402</td>
|
||||
<td class="org-right">20230228.153</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">pdf-tools</td>
|
||||
<td class="org-right">20221202.1104</td>
|
||||
<td class="org-right">20230611.239</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
@@ -685,7 +808,14 @@ General key bindings and functions
|
||||
|
||||
<tr>
|
||||
<td class="org-left">php-mode</td>
|
||||
<td class="org-right">20221112.1616</td>
|
||||
<td class="org-right">20230929.123</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">pkg-info</td>
|
||||
<td class="org-right">20150517.1143</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
@@ -699,14 +829,14 @@ General key bindings and functions
|
||||
|
||||
<tr>
|
||||
<td class="org-left">polymode</td>
|
||||
<td class="org-right">20220820.163</td>
|
||||
<td class="org-right">20230317.1218</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">popup</td>
|
||||
<td class="org-right">20220927.161</td>
|
||||
<td class="org-right">20230819.2306</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
@@ -718,9 +848,16 @@ General key bindings and functions
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">posframe</td>
|
||||
<td class="org-right">20230714.227</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">pos-tip</td>
|
||||
<td class="org-right">20220715.102</td>
|
||||
<td class="org-right">20230721.834</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
@@ -734,7 +871,7 @@ General key bindings and functions
|
||||
|
||||
<tr>
|
||||
<td class="org-left">pythonic</td>
|
||||
<td class="org-right">20220723.1741</td>
|
||||
<td class="org-right">20230821.1733</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
@@ -767,9 +904,23 @@ General key bindings and functions
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">seq</td>
|
||||
<td class="org-right">2.24</td>
|
||||
<td class="org-left">elpa-gnu</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">simple-httpd</td>
|
||||
<td class="org-right">20230821.1458</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">spacemacs-theme</td>
|
||||
<td class="org-right">20221103.1406</td>
|
||||
<td class="org-right">20230530.1751</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
@@ -783,14 +934,14 @@ General key bindings and functions
|
||||
|
||||
<tr>
|
||||
<td class="org-left">sql-indent</td>
|
||||
<td class="org-right">1.6</td>
|
||||
<td class="org-right">1.7</td>
|
||||
<td class="org-left">elpa-gnu</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">srefactor</td>
|
||||
<td class="org-right">20180703.181</td>
|
||||
<td class="org-right">20230504.617</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
@@ -811,42 +962,49 @@ General key bindings and functions
|
||||
|
||||
<tr>
|
||||
<td class="org-left">swiper</td>
|
||||
<td class="org-right">20220430.2247</td>
|
||||
<td class="org-right">20231025.2311</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">systemd</td>
|
||||
<td class="org-right">20210209.2052</td>
|
||||
<td class="org-right">20230201.302</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">tablist</td>
|
||||
<td class="org-right">20231019.1126</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">transient</td>
|
||||
<td class="org-right">20221202.1727</td>
|
||||
<td class="org-right">20231103.2312</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">treemacs</td>
|
||||
<td class="org-right">20221107.2105</td>
|
||||
<td class="org-right">20231101.115</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">treemacs-magit</td>
|
||||
<td class="org-right">20220917.1026</td>
|
||||
<td class="org-right">20230830.1936</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">use-package</td>
|
||||
<td class="org-right">20221209.2013</td>
|
||||
<td class="org-right">20230426.2324</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
@@ -860,14 +1018,14 @@ General key bindings and functions
|
||||
|
||||
<tr>
|
||||
<td class="org-left">visual-fill-column</td>
|
||||
<td class="org-right">20220519.1959</td>
|
||||
<td class="org-right">20230102.183</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">vterm</td>
|
||||
<td class="org-right">20221118.1354</td>
|
||||
<td class="org-right">20230417.424</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
@@ -881,35 +1039,42 @@ General key bindings and functions
|
||||
|
||||
<tr>
|
||||
<td class="org-left">web-mode</td>
|
||||
<td class="org-right">20221012.8</td>
|
||||
<td class="org-right">20231025.1927</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">websocket</td>
|
||||
<td class="org-right">20230809.305</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">which-key</td>
|
||||
<td class="org-right">20220811.1616</td>
|
||||
<td class="org-right">20230905.2128</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">with-editor</td>
|
||||
<td class="org-right">20221127.2243</td>
|
||||
<td class="org-right">20230917.958</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">yasnippet</td>
|
||||
<td class="org-right">20200604.246</td>
|
||||
<td class="org-right">20230914.14</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td class="org-left">yasnippet-snippets</td>
|
||||
<td class="org-right">20220713.1234</td>
|
||||
<td class="org-right">20230815.82</td>
|
||||
<td class="org-left">melpa</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
115
README.org
115
README.org
@@ -9,17 +9,43 @@ a bunch of online resources.
|
||||
:PROPERTIES:
|
||||
:CUSTOM_ID: installation
|
||||
:END:
|
||||
Download repo and point the emacs =init= (and =early-init.el=) file to
|
||||
this configuration.
|
||||
|
||||
Or run one of the following install script commands (using curl, wget or fetch).
|
||||
#+begin_src sh
|
||||
Different ways to install:
|
||||
|
||||
- arch-linux :: If ~emacs-conf~ is available in a ~custom~ ~pacman~ repository
|
||||
#+begin_src sh
|
||||
pacman -S emacs-conf
|
||||
ln -s /opt/emacs-conf/init ~/.config/emacs/
|
||||
ln -s /opt/emacs-conf/early-init.el ~/.config/emacs/
|
||||
#+end_src
|
||||
|
||||
- debian :: If ~emacs-conf~ is available in a ~custom~ ~apt~ repository
|
||||
#+begin_src sh
|
||||
apt install emacs-conf
|
||||
ln -s /opt/emacs-conf/init ~/.config/emacs/
|
||||
ln -s /opt/emacs-conf/early-init.el ~/.config/emacs/
|
||||
#+end_src
|
||||
|
||||
- manual :: Download or clone git repo and point the emacs =init= and
|
||||
=early-init.el= file to this configuration.
|
||||
|
||||
- old :: Run one of the following install script commands (using curl,
|
||||
wget or fetch).
|
||||
#+begin_src sh
|
||||
sh -c "$(curl -fsSL http://gitea.weseng.de/daniel/emacs/raw/master/scripts/install.sh)"
|
||||
sh -c "$(wget -O- http://gitea.weseng.de/daniel/emacs/raw/master/scripts/install.sh)"
|
||||
sh -c "$(fetch -o - http://gitea.weseng.de/daniel/emacs/raw/master/scripts/install.sh)"
|
||||
#+end_src
|
||||
Installation path is =~/.config/emacs=. See details and other
|
||||
installed linux packages as requirements inside =sripts/install.sh=.
|
||||
#+end_src
|
||||
Installation path is =~/.config/emacs=. See details and other
|
||||
installed linux packages as requirements inside =sripts/install.sh=.
|
||||
|
||||
* External programs
|
||||
:PROPERTIES:
|
||||
:CUSTOM_ID: programs
|
||||
:END:
|
||||
- =ripgrep= (optional) used by =counsel-rg= (package =counsel=)
|
||||
- =texlive-luatex= for =luainputenc.sty= used by org latex export
|
||||
- =texlive-xetex= for =realscripts.sty= for =KpRoman= used by org latex export
|
||||
|
||||
* Usage
|
||||
:PROPERTIES:
|
||||
@@ -51,14 +77,15 @@ commands and information.
|
||||
General key bindings and functions
|
||||
- =C-r= (=query-replace-regexp=) replace text
|
||||
- =C-x RET f= (=set-buffer-file-coding-system=) e.g. set to =utf-8
|
||||
- (=decode-coding-region=) e.g. decode to =utf-8= (郭富城Aaron Kwok)
|
||||
- (=decode-coding-region=) e.g. decode to =utf-8= (e.g. 晴天)
|
||||
- (=diff-buffer-with-file=) show a diff between buffer (current state) and file (saved state)
|
||||
|
||||
#+begin_src sh :exports results
|
||||
dir=$HOME/repos/emacs-conf/lisp
|
||||
dir=$(pwd)/lisp
|
||||
|
||||
verinfo() {
|
||||
#echo -n $1 ''
|
||||
# $dir: directory of packages
|
||||
# $1: package name (basenaem and w/o extension)
|
||||
if test -f $dir/$1.el; then
|
||||
ver=$(grep -i package-version: $dir/$1.el | cut -d":" -f2 | xargs)
|
||||
if test -z $ver; then
|
||||
@@ -71,31 +98,31 @@ verinfo() {
|
||||
fi
|
||||
}
|
||||
|
||||
pkg_custom=$(
|
||||
for i in $(echo awesome-tray dialog); do
|
||||
map_pkg_ver() {
|
||||
# $1: list of package names, either full path (can include a version) or just the package name
|
||||
# $2: repo name
|
||||
# 1st: get package name: strips list element to basename and removes version and extension
|
||||
# 2nd: get package version (from the installed directory)
|
||||
# 3rd: print info
|
||||
for i in $1; do
|
||||
pkg=$(sed 's/-[0-9].*//' <(basename $i))
|
||||
ver=$(verinfo $pkg)
|
||||
echo $pkg $ver custom
|
||||
done)
|
||||
pkg_elpagnu=$(
|
||||
for i in $(ls -F ~/repos/my-elpa-gnu/archive/*.tar | grep -v @); do
|
||||
pkg=$(sed 's/-[0-9].*//' <(basename $i))
|
||||
ver=$(verinfo $pkg)
|
||||
echo $pkg $ver elpa-gnu
|
||||
done)
|
||||
pkg_elpanongnu=$(
|
||||
for i in $(ls -F ~/repos/my-elpa-nongnu/archive/*.tar | grep -v @); do
|
||||
pkg=$(sed 's/-[0-9].*//' <(basename $i))
|
||||
ver=$(verinfo $pkg)
|
||||
echo $pkg $ver elpa-nongnu
|
||||
done)
|
||||
pkg_melpa=$(
|
||||
for i in $(sort <(ls ~/repos/my-melpa/packages/*.tar | xargs -n1) <(ls ~/repos/my-melpa/packages/*.el | xargs -n1)); do
|
||||
pkg=$(sed 's/-[0-9].*//' <(basename $i))
|
||||
ver=$(verinfo $pkg)
|
||||
echo $pkg $ver melpa
|
||||
done)
|
||||
echo -e "$pkg_custom\n$pkg_elpagnu\n$pkg_elpanongnu\n$pkg_melpa" | sort | column -t -N PACKAGE_____________________,VERSION______,REPO_______
|
||||
echo $pkg $ver $2
|
||||
done
|
||||
}
|
||||
|
||||
pkg_custom_list=$(echo awesome-tray dialog)
|
||||
pkg_elpagnu_list=$(ls -F ~/repos/my-elpa-gnu/archive/*.tar | grep -v @)
|
||||
pkg_elpanongnu_list=$(ls -F ~/repos/my-elpa-nongnu/archive/*.tar | grep -v @)
|
||||
pkg_melpa_list=$(sort <(ls ~/repos/my-melpa/packages/*.tar | xargs -n1) <(ls ~/repos/my-melpa/packages/*.el | xargs -n1))
|
||||
|
||||
pkg_custom=$(map_pkg_ver "$pkg_custom_list" custom)
|
||||
pkg_elpagnu=$(map_pkg_ver "$pkg_elpagnu_list" elpa-gnu)
|
||||
pkg_elpanongnu=$(map_pkg_ver "$pkg_elpanongnu_list" elpa-nongnu)
|
||||
pkg_melpa=$(map_pkg_ver "$pkg_melpa_list" melpa)
|
||||
echo -e "$pkg_custom\n$pkg_elpagnu\n$pkg_elpanongnu\n$pkg_melpa" | \
|
||||
sort | \
|
||||
column -t -N PACKAGE_____________________,VERSION______,REPO_______
|
||||
#+end_src
|
||||
|
||||
#+RESULTS:
|
||||
@@ -103,6 +130,7 @@ echo -e "$pkg_custom\n$pkg_elpagnu\n$pkg_elpanongnu\n$pkg_melpa" | sort | column
|
||||
| ace-window | 20220911.358 | melpa |
|
||||
| adaptive-wrap | 0.8 | elpa-gnu |
|
||||
| all-the-icons | 20220929.2303 | melpa |
|
||||
| all-the-icons-ivy-rich | 20221202.1336 | melpa |
|
||||
| amx | 20210305.118 | melpa |
|
||||
| anaconda-mode | 20220922.741 | melpa |
|
||||
| async | 20221217.649 | melpa |
|
||||
@@ -112,13 +140,16 @@ echo -e "$pkg_custom\n$pkg_elpagnu\n$pkg_elpanongnu\n$pkg_melpa" | sort | column
|
||||
| biblio-core | 20210418.406 | melpa |
|
||||
| bibtex-completion | 20221024.857 | melpa |
|
||||
| bind-key | 20221209.2013 | melpa |
|
||||
| cfrs | 20220129.1149 | melpa |
|
||||
| citeproc | 20221216.1238 | melpa |
|
||||
| cl-libify | 20181130.23 | melpa |
|
||||
| company | 20221206.2122 | melpa |
|
||||
| company-anaconda | 20200404.1859 | melpa |
|
||||
| company-ledger | 20210910.25 | melpa |
|
||||
| company-quickhelp | 20221212.534 | melpa |
|
||||
| company-statistics | 20170210.1933 | melpa |
|
||||
| company-web | 20220115.2146 | melpa |
|
||||
| compat | 28.1.2.2 | elpa-gnu |
|
||||
| counsel | 20221015.936 | melpa |
|
||||
| crdt | 0.3.5 | elpa-gnu |
|
||||
| ctable | 20210128.629 | melpa |
|
||||
@@ -130,6 +161,9 @@ echo -e "$pkg_custom\n$pkg_elpagnu\n$pkg_elpanongnu\n$pkg_melpa" | sort | column
|
||||
| diff-hl | 20221007.2147 | melpa |
|
||||
| dim | 20160818.949 | melpa |
|
||||
| elisp-refs | 20220704.2141 | melpa |
|
||||
| emacsql | 20221127.2146 | melpa |
|
||||
| emacsql-sqlite | 20221127.2146 | melpa |
|
||||
| emacsql-sqlite-builtin | 20221127.2146 | melpa |
|
||||
| emojify | 20210108.1111 | melpa |
|
||||
| ess | 20221204.1348 | melpa |
|
||||
| ess-R-data-view | 20130509.1158 | melpa |
|
||||
@@ -163,7 +197,10 @@ echo -e "$pkg_custom\n$pkg_elpagnu\n$pkg_elpanongnu\n$pkg_melpa" | sort | column
|
||||
| memoize | 20200103.2036 | melpa |
|
||||
| mu4e-maildirs-extension | 20220517.1852 | melpa |
|
||||
| multiple-cursors | 20221126.743 | melpa |
|
||||
| notmuch | 20221115.1134 | melpa |
|
||||
| ob-async | 20210428.2052 | melpa |
|
||||
| olivetti | 20220330.635 | melpa |
|
||||
| ol-notmuch | 20220428.1337 | melpa |
|
||||
| org | 9.6 | elpa-gnu |
|
||||
| org-appear | 20220617.2355 | melpa |
|
||||
| org-brain | 20210706.1519 | melpa |
|
||||
@@ -174,6 +211,10 @@ echo -e "$pkg_custom\n$pkg_elpagnu\n$pkg_elpanongnu\n$pkg_melpa" | sort | column
|
||||
| org-fragtog | 20220714.2146 | melpa |
|
||||
| orgit | 20221127.2228 | melpa |
|
||||
| org-ref | 20221129.1925 | melpa |
|
||||
| org-roam | 20221205.355 | melpa |
|
||||
| org-roam-bibtex | 20221104.2139 | melpa |
|
||||
| org-roam-timestamps | 20221104.1544 | melpa |
|
||||
| org-roam-ui | 20221105.104 | melpa |
|
||||
| org-sticky-header | 20201223.143 | melpa |
|
||||
| org-superstar | 20210915.1934 | melpa |
|
||||
| org-table-sticky-header | 20190924.506 | melpa |
|
||||
@@ -187,10 +228,12 @@ echo -e "$pkg_custom\n$pkg_elpagnu\n$pkg_elpanongnu\n$pkg_melpa" | sort | column
|
||||
| persist | 0.5 | elpa-gnu |
|
||||
| pfuture | 20220913.1401 | melpa |
|
||||
| php-mode | 20221112.1616 | melpa |
|
||||
| pkg-info | 20150517.1143 | melpa |
|
||||
| plantuml-mode | 20191102.2056 | melpa |
|
||||
| polymode | 20220820.163 | melpa |
|
||||
| popup | 20220927.161 | melpa |
|
||||
| popwin | 20210215.1849 | melpa |
|
||||
| posframe | 20221220.544 | melpa |
|
||||
| pos-tip | 20220715.102 | melpa |
|
||||
| powershell | 20220805.1712 | melpa |
|
||||
| pythonic | 20220723.1741 | melpa |
|
||||
@@ -198,6 +241,8 @@ echo -e "$pkg_custom\n$pkg_elpagnu\n$pkg_elpanongnu\n$pkg_melpa" | sort | column
|
||||
| rainbow-mode | 1.0.6 | elpa-gnu |
|
||||
| restart-emacs | 20201127.1425 | melpa |
|
||||
| s | 20220902.1511 | melpa |
|
||||
| seq | 2.23 | elpa-gnu |
|
||||
| simple-httpd | 20191103.1446 | melpa |
|
||||
| spacemacs-theme | 20221103.1406 | melpa |
|
||||
| sphinx-doc | 20210213.125 | melpa |
|
||||
| sql-indent | 1.6 | elpa-gnu |
|
||||
@@ -206,8 +251,9 @@ echo -e "$pkg_custom\n$pkg_elpagnu\n$pkg_elpanongnu\n$pkg_melpa" | sort | column
|
||||
| string-inflection | 20220910.1306 | melpa |
|
||||
| swiper | 20220430.2247 | melpa |
|
||||
| systemd | 20210209.2052 | melpa |
|
||||
| tablist | 20200427.2205 | melpa |
|
||||
| transient | 20221202.1727 | melpa |
|
||||
| treemacs | 20221107.2105 | melpa |
|
||||
| treemacs | 20221221.1301 | melpa |
|
||||
| treemacs-magit | 20220917.1026 | melpa |
|
||||
| use-package | 20221209.2013 | melpa |
|
||||
| virtual-auto-fill | 20200906.2038 | melpa |
|
||||
@@ -215,6 +261,7 @@ echo -e "$pkg_custom\n$pkg_elpagnu\n$pkg_elpanongnu\n$pkg_melpa" | sort | column
|
||||
| vterm | 20221118.1354 | melpa |
|
||||
| web-completion-data | 20160318.848 | melpa |
|
||||
| web-mode | 20221012.8 | melpa |
|
||||
| websocket | 20221218.115 | melpa |
|
||||
| which-key | 20220811.1616 | melpa |
|
||||
| with-editor | 20221127.2243 | melpa |
|
||||
| yasnippet | 20200604.246 | melpa |
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
;; A big contributor to startup times is garbage collection. We up the gc
|
||||
;; threshold to temporarily prevent it from running, then reset it later by
|
||||
;; enabling `gcmh-mode'. Not resetting it will cause stuttering/freezes.
|
||||
(setq gc-cons-threshold (* 50 1000 1000)) ;; Make startup faster by reducing the frequency of garbage collection. The default is 800 kilobytes. Measured in bytes. Will be decreased again at the end.
|
||||
(setq gc-cons-threshold (* 200 1024 1024)) ;; Make startup faster by reducing the frequency of garbage collection. The default is 800 kilobytes. Measured in bytes. Will (and should) be decreased again at the end.
|
||||
|
||||
;; make UTF-8 the default coding system:
|
||||
(set-language-environment "UTF-8")
|
||||
|
||||
1
init
1
init
@@ -54,6 +54,7 @@
|
||||
(require 'shell-settings) ;; sh-script powershell
|
||||
(require 'web-settings) ;; css js2 php web-mode company-web
|
||||
(require 'filetype-settings) ;; markdown sql systemd
|
||||
(require 'dot-settings) ;; graphviz dot
|
||||
(require 'polymode-settings) ;; polymode
|
||||
|
||||
(require 'post-settings)
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
'((avy "0.5.0"))
|
||||
:commit "77115afc1b0b9f633084cf7479c767988106c196" :authors
|
||||
'(("Oleh Krehel" . "ohwoeowho@gmail.com"))
|
||||
:maintainers
|
||||
'(("Oleh Krehel" . "ohwoeowho@gmail.com"))
|
||||
:maintainer
|
||||
'("Oleh Krehel" . "ohwoeowho@gmail.com")
|
||||
:keywords
|
||||
|
||||
16
lisp/all-the-icons-ivy-rich/all-the-icons-ivy-rich-pkg.el
Normal file
16
lisp/all-the-icons-ivy-rich/all-the-icons-ivy-rich-pkg.el
Normal file
@@ -0,0 +1,16 @@
|
||||
(define-package "all-the-icons-ivy-rich" "20230420.1234" "Better experience with icons for ivy"
|
||||
'((emacs "25.1")
|
||||
(ivy-rich "0.1.0")
|
||||
(all-the-icons "2.2.0"))
|
||||
:commit "c098cc85123a401b0ab8f2afd3a25853e61d7d28" :authors
|
||||
'(("Vincent Zhang" . "seagle0128@gmail.com"))
|
||||
:maintainers
|
||||
'(("Vincent Zhang" . "seagle0128@gmail.com"))
|
||||
:maintainer
|
||||
'("Vincent Zhang" . "seagle0128@gmail.com")
|
||||
:keywords
|
||||
'("convenience" "icons" "ivy")
|
||||
:url "https://github.com/seagle0128/all-the-icons-ivy-rich")
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
;; End:
|
||||
2090
lisp/all-the-icons-ivy-rich/all-the-icons-ivy-rich.el
Normal file
2090
lisp/all-the-icons-ivy-rich/all-the-icons-ivy-rich.el
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,8 @@
|
||||
(define-package "all-the-icons" "20220929.2303" "A library for inserting Developer icons"
|
||||
(define-package "all-the-icons" "20240623.1800" "A library for inserting Developer icons"
|
||||
'((emacs "24.3"))
|
||||
:commit "51bf77da1ebc3c199dfc11f54c0dce67559f5f40" :authors
|
||||
:commit "39ef44f810c34e8900978788467cc675870bcd19" :authors
|
||||
'(("Dominic Charlesworth" . "dgc336@gmail.com"))
|
||||
:maintainers
|
||||
'(("Dominic Charlesworth" . "dgc336@gmail.com"))
|
||||
:maintainer
|
||||
'("Dominic Charlesworth" . "dgc336@gmail.com")
|
||||
|
||||
@@ -168,6 +168,12 @@
|
||||
("dll" all-the-icons-faicon "cogs" :face all-the-icons-silver)
|
||||
("ds_store" all-the-icons-faicon "cogs" :face all-the-icons-silver)
|
||||
;; Source Codes
|
||||
("ada" all-the-icons-fileicon "ada" :v-adjust 0.0 :face all-the-icons-blue)
|
||||
("adb" all-the-icons-fileicon "ada" :v-adjust 0.0 :face all-the-icons-blue)
|
||||
("adc" all-the-icons-fileicon "ada" :v-adjust 0.0 :face all-the-icons-blue)
|
||||
("ads" all-the-icons-fileicon "ada" :v-adjust 0.0 :face all-the-icons-blue)
|
||||
("gpr" all-the-icons-fileicon "ada" :v-adjust 0.0 :face all-the-icons-green)
|
||||
("cgpr" all-the-icons-fileicon "ada" :v-adjust 0.0 :face all-the-icons-green)
|
||||
("scpt" all-the-icons-fileicon "apple" :face all-the-icons-pink)
|
||||
("aup" all-the-icons-fileicon "audacity" :face all-the-icons-yellow)
|
||||
("elm" all-the-icons-fileicon "elm" :face all-the-icons-blue)
|
||||
@@ -184,7 +190,6 @@
|
||||
("eclass" all-the-icons-fileicon "gentoo" :face all-the-icons-blue)
|
||||
("go" all-the-icons-fileicon "go" :height 1.0 :face all-the-icons-blue)
|
||||
("jl" all-the-icons-fileicon "julia" :face all-the-icons-purple :v-adjust 0.0)
|
||||
("magik" all-the-icons-faicon "magic" :face all-the-icons-blue)
|
||||
("matlab" all-the-icons-fileicon "matlab" :face all-the-icons-orange)
|
||||
("nix" all-the-icons-fileicon "nix" :face all-the-icons-blue)
|
||||
("pl" all-the-icons-alltheicon "perl" :face all-the-icons-lorange)
|
||||
@@ -210,6 +215,8 @@
|
||||
("rd" all-the-icons-fileicon "R" :face all-the-icons-lblue)
|
||||
("rdx" all-the-icons-fileicon "R" :face all-the-icons-lblue)
|
||||
("rsx" all-the-icons-fileicon "R" :face all-the-icons-lblue)
|
||||
("beancount" all-the-icons-faicon "credit-card" :face all-the-icons-lgreen)
|
||||
("ledger" all-the-icons-faicon "credit-card" :face all-the-icons-lgreen)
|
||||
("svelte" all-the-icons-fileicon "svelte" :v-adjust 0.0 :face all-the-icons-red)
|
||||
("gql" all-the-icons-fileicon "graphql" :face all-the-icons-dpink)
|
||||
("graphql" all-the-icons-fileicon "graphql" :face all-the-icons-dpink)
|
||||
@@ -247,6 +254,7 @@
|
||||
("sass" all-the-icons-alltheicon "sass" :face all-the-icons-dpink)
|
||||
("less" all-the-icons-alltheicon "less" :height 0.8 :face all-the-icons-dyellow)
|
||||
("postcss" all-the-icons-fileicon "postcss" :face all-the-icons-dred)
|
||||
("pcss" all-the-icons-fileicon "postcss" :face all-the-icons-dred)
|
||||
("sss" all-the-icons-fileicon "postcss" :face all-the-icons-dred)
|
||||
("styl" all-the-icons-alltheicon "stylus" :face all-the-icons-lgreen)
|
||||
("csv" all-the-icons-octicon "graph" :v-adjust 0.0 :face all-the-icons-dblue)
|
||||
@@ -277,11 +285,14 @@
|
||||
("react" all-the-icons-alltheicon "react" :height 1.1 :face all-the-icons-lblue)
|
||||
("ts" all-the-icons-fileicon "typescript" :height 1.0 :v-adjust -0.1 :face all-the-icons-blue-alt)
|
||||
("js" all-the-icons-alltheicon "javascript" :height 1.0 :v-adjust 0.0 :face all-the-icons-yellow)
|
||||
("mjs" all-the-icons-alltheicon "javascript" :height 1.0 :v-adjust 0.0 :face all-the-icons-yellow)
|
||||
("es" all-the-icons-alltheicon "javascript" :height 1.0 :v-adjust 0.0 :face all-the-icons-yellow)
|
||||
("jsx" all-the-icons-fileicon "jsx-2" :height 1.0 :v-adjust -0.1 :face all-the-icons-cyan-alt)
|
||||
("tsx" all-the-icons-fileicon "tsx" :height 1.0 :v-adjust -0.1 :face all-the-icons-cyan-alt)
|
||||
("njs" all-the-icons-alltheicon "nodejs" :height 1.2 :face all-the-icons-lgreen)
|
||||
("vue" all-the-icons-fileicon "vue" :face all-the-icons-lgreen)
|
||||
("wasm" all-the-icons-fileicon "wasm" :height 1.0 :face all-the-icons-purple-alt)
|
||||
("wat" all-the-icons-fileicon "wasm" :height 1.0 :face all-the-icons-purple-alt)
|
||||
|
||||
("sbt" all-the-icons-fileicon "sbt" :face all-the-icons-red)
|
||||
("scala" all-the-icons-alltheicon "scala" :face all-the-icons-red)
|
||||
@@ -380,12 +391,13 @@
|
||||
("mov" all-the-icons-faicon "film" :face all-the-icons-blue)
|
||||
("mp4" all-the-icons-faicon "film" :face all-the-icons-blue)
|
||||
("ogv" all-the-icons-faicon "film" :face all-the-icons-dblue)
|
||||
("mpg" all-the-icons-faicon "film" :face all-the-icons-blue)
|
||||
("mpeg" all-the-icons-faicon "film" :face all-the-icons-blue)
|
||||
("flv" all-the-icons-faicon "film" :face all-the-icons-blue)
|
||||
("ogv" all-the-icons-faicon "film" :face all-the-icons-dblue)
|
||||
("mpg" all-the-icons-faicon "film" :face all-the-icons-blue)
|
||||
("mpeg" all-the-icons-faicon "film" :face all-the-icons-blue)
|
||||
("flv" all-the-icons-faicon "film" :face all-the-icons-blue)
|
||||
("ogv" all-the-icons-faicon "film" :face all-the-icons-dblue)
|
||||
("mkv" all-the-icons-faicon "film" :face all-the-icons-blue)
|
||||
("webm" all-the-icons-faicon "film" :face all-the-icons-blue)
|
||||
("dav" all-the-icons-faicon "film" :face all-the-icons-blue)
|
||||
;; Fonts
|
||||
("ttf" all-the-icons-fileicon "font" :v-adjust 0.0 :face all-the-icons-dcyan)
|
||||
("woff" all-the-icons-fileicon "font" :v-adjust 0.0 :face all-the-icons-cyan)
|
||||
@@ -397,6 +409,8 @@
|
||||
("doc" all-the-icons-fileicon "word" :face all-the-icons-blue)
|
||||
("docx" all-the-icons-fileicon "word" :face all-the-icons-blue)
|
||||
("docm" all-the-icons-fileicon "word" :face all-the-icons-blue)
|
||||
("eml" all-the-icons-faicon "envelope" :face all-the-icons-blue)
|
||||
("msg" all-the-icons-faicon "envelope" :face all-the-icons-blue)
|
||||
("texi" all-the-icons-fileicon "tex" :face all-the-icons-lred)
|
||||
("tex" all-the-icons-fileicon "tex" :face all-the-icons-lred)
|
||||
("md" all-the-icons-octicon "markdown" :v-adjust 0.0 :face all-the-icons-lblue)
|
||||
@@ -405,7 +419,7 @@
|
||||
("pps" all-the-icons-fileicon "powerpoint" :face all-the-icons-orange)
|
||||
("ppt" all-the-icons-fileicon "powerpoint" :face all-the-icons-orange)
|
||||
("pptsx" all-the-icons-fileicon "powerpoint" :face all-the-icons-orange)
|
||||
("ppttx" all-the-icons-fileicon "powerpoint" :face all-the-icons-orange)
|
||||
("pptx" all-the-icons-fileicon "powerpoint" :face all-the-icons-orange)
|
||||
("knt" all-the-icons-fileicon "powerpoint" :face all-the-icons-cyan)
|
||||
("xlsx" all-the-icons-fileicon "excel" :face all-the-icons-dgreen)
|
||||
("xlsm" all-the-icons-fileicon "excel" :face all-the-icons-dgreen)
|
||||
@@ -577,13 +591,17 @@ for performance sake.")
|
||||
(erc-mode all-the-icons-faicon "commenting-o" :height 1.0 :v-adjust 0.0)
|
||||
(inferior-emacs-lisp-mode all-the-icons-fileicon "elisp" :height 1.0 :v-adjust -0.1 :face all-the-icons-lblue)
|
||||
(dired-mode all-the-icons-octicon "file-directory" :v-adjust 0.0)
|
||||
(wdired-mode all-the-icons-octicon "file-directory" :v-adjust 0.0 :face all-the-icons-dcyan)
|
||||
(lisp-interaction-mode all-the-icons-fileicon "lisp" :v-adjust -0.1 :face all-the-icons-orange)
|
||||
(sly-mrepl-mode all-the-icons-fileicon "clisp" :v-adjust -0.1 :face all-the-icons-orange)
|
||||
(slime-repl-mode all-the-icons-fileicon "clisp" :v-adjust -0.1 :face all-the-icons-orange)
|
||||
(org-mode all-the-icons-fileicon "org" :v-adjust 0.0 :face all-the-icons-lgreen)
|
||||
(typescript-mode all-the-icons-fileicon "typescript" :v-adjust -0.1 :face all-the-icons-blue-alt)
|
||||
(typescript-ts-mode all-the-icons-fileicon "typescript" :v-adjust -0.1 :face all-the-icons-blue-alt)
|
||||
(typescript-tsx-mode all-the-icons-fileicon "tsx" :v-adjust -0.1 :face all-the-icons-cyan-alt)
|
||||
(tsx-ts-mode all-the-icons-fileicon "tsx" :v-adjust -0.1 :face all-the-icons-cyan-alt)
|
||||
(js-mode all-the-icons-alltheicon "javascript" :v-adjust -0.1 :face all-the-icons-yellow)
|
||||
(js-ts-mode all-the-icons-alltheicon "javascript" :v-adjust -0.1 :face all-the-icons-yellow)
|
||||
(js-jsx-mode all-the-icons-alltheicon "javascript" :v-adjust -0.1 :face all-the-icons-yellow)
|
||||
(js2-mode all-the-icons-alltheicon "javascript" :v-adjust -0.1 :face all-the-icons-yellow)
|
||||
(js3-mode all-the-icons-alltheicon "javascript" :v-adjust -0.1 :face all-the-icons-yellow)
|
||||
@@ -602,6 +620,7 @@ for performance sake.")
|
||||
(ibuffer-mode all-the-icons-faicon "files-o" :v-adjust 0.0 :face all-the-icons-dsilver)
|
||||
(messages-buffer-mode all-the-icons-faicon "file-o" :v-adjust 0.0 :face all-the-icons-dsilver)
|
||||
(help-mode all-the-icons-faicon "info" :v-adjust -0.1 :face all-the-icons-purple)
|
||||
(helpful-mode all-the-icons-faicon "info" :v-adjust -0.1 :face all-the-icons-purple)
|
||||
(benchmark-init/tree-mode all-the-icons-octicon "dashboard" :v-adjust 0.0)
|
||||
(jenkins-mode all-the-icons-fileicon "jenkins" :face all-the-icons-blue)
|
||||
(magit-popup-mode all-the-icons-alltheicon "git" :face all-the-icons-red)
|
||||
@@ -612,6 +631,10 @@ for performance sake.")
|
||||
(mu4e-main-mode all-the-icons-octicon "mail" :v-adjust 0.0)
|
||||
(mu4e-view-mode all-the-icons-octicon "mail-read" :v-adjust 0.0)
|
||||
(sieve-mode all-the-icons-octicon "mail" :v-adjust 0.0)
|
||||
(gnus-group-mode all-the-icons-octicon "mail" :v-adjust 0.0)
|
||||
(gnus-summary-mode all-the-icons-octicon "mail" :v-adjust 0.0)
|
||||
(gnus-article-mode all-the-icons-octicon "mail-read" :v-adjust 0.0)
|
||||
(message-mode all-the-icons-octicon "pencil" :v-adjust 0.0)
|
||||
(package-menu-mode all-the-icons-faicon "archive" :height 1.0 :v-adjust 0.0 :face all-the-icons-silver)
|
||||
(paradox-menu-mode all-the-icons-faicon "archive" :height 1.0 :v-adjust 0.0 :face all-the-icons-silver)
|
||||
(Custom-mode all-the-icons-octicon "settings" :v-adjust -0.1)
|
||||
@@ -624,30 +647,39 @@ for performance sake.")
|
||||
(text-mode all-the-icons-octicon "file-text" :v-adjust 0.0 :face all-the-icons-cyan)
|
||||
(enh-ruby-mode all-the-icons-alltheicon "ruby-alt" :face all-the-icons-lred)
|
||||
(ruby-mode all-the-icons-alltheicon "ruby-alt" :face all-the-icons-lred)
|
||||
(ruby-ts-mode all-the-icons-alltheicon "ruby-alt" :face all-the-icons-lred)
|
||||
(inf-ruby-mode all-the-icons-alltheicon "ruby-alt" :face all-the-icons-red)
|
||||
(projectile-rails-compilation-mode all-the-icons-alltheicon "ruby-alt" :face all-the-icons-red)
|
||||
(rspec-compilation-mode all-the-icons-alltheicon "ruby-alt" :face all-the-icons-red)
|
||||
(rake-compilation-mode all-the-icons-alltheicon "ruby-alt" :face all-the-icons-red)
|
||||
(sh-mode all-the-icons-alltheicon "terminal" :face all-the-icons-purple)
|
||||
(bash-ts-mode all-the-icons-alltheicon "terminal" :face all-the-icons-purple)
|
||||
(shell-mode all-the-icons-alltheicon "terminal" :face all-the-icons-purple)
|
||||
(fish-mode all-the-icons-alltheicon "terminal" :face all-the-icons-lpink)
|
||||
(nginx-mode all-the-icons-fileicon "nginx" :height 0.9 :face all-the-icons-dgreen)
|
||||
(apache-mode all-the-icons-alltheicon "apache" :height 0.9 :face all-the-icons-dgreen)
|
||||
(makefile-mode all-the-icons-fileicon "gnu" :face all-the-icons-dorange)
|
||||
(cmake-mode all-the-icons-fileicon "cmake" :face all-the-icons-red)
|
||||
(cmake-ts-mode all-the-icons-fileicon "cmake" :face all-the-icons-red)
|
||||
(dockerfile-mode all-the-icons-fileicon "dockerfile" :face all-the-icons-blue)
|
||||
(dockerfile-ts-mode all-the-icons-fileicon "dockerfile" :face all-the-icons-blue)
|
||||
(docker-compose-mode all-the-icons-fileicon "dockerfile" :face all-the-icons-lblue)
|
||||
(nxml-mode all-the-icons-faicon "file-code-o" :height 0.95 :face all-the-icons-lorange)
|
||||
(json-mode all-the-icons-octicon "settings" :face all-the-icons-yellow)
|
||||
(json-ts-mode all-the-icons-octicon "settings" :face all-the-icons-yellow)
|
||||
(jsonian-mode all-the-icons-octicon "settings" :face all-the-icons-yellow)
|
||||
(yaml-mode all-the-icons-octicon "settings" :v-adjust 0.0 :face all-the-icons-dyellow)
|
||||
(yaml-ts-mode all-the-icons-octicon "settings" :v-adjust 0.0 :face all-the-icons-dyellow)
|
||||
(elisp-byte-code-mode all-the-icons-octicon "file-binary" :v-adjust 0.0 :face all-the-icons-dsilver)
|
||||
(archive-mode all-the-icons-octicon "file-zip" :v-adjust 0.0 :face all-the-icons-lmaroon)
|
||||
(elm-mode all-the-icons-fileicon "elm" :face all-the-icons-blue)
|
||||
(erlang-mode all-the-icons-alltheicon "erlang" :face all-the-icons-red :v-adjust -0.1 :height 0.9)
|
||||
(elixir-mode all-the-icons-alltheicon "elixir" :face all-the-icons-lorange :v-adjust -0.1 :height 0.9)
|
||||
(java-mode all-the-icons-alltheicon "java" :height 1.0 :face all-the-icons-purple)
|
||||
(java-ts-mode all-the-icons-alltheicon "java" :height 1.0 :face all-the-icons-purple)
|
||||
(go-mode all-the-icons-fileicon "go" :height 1.0 :face all-the-icons-blue)
|
||||
(go-ts-mode all-the-icons-fileicon "go" :height 1.0 :face all-the-icons-blue)
|
||||
(go-mod-ts-mode all-the-icons-fileicon "config-go" :height 1.0 :face all-the-icons-blue-alt)
|
||||
(go-dot-mod-mode all-the-icons-fileicon "config-go" :height 1.0 :face all-the-icons-blue-alt)
|
||||
(go-dot-work-mode all-the-icons-fileicon "config-go" :height 1.0 :face all-the-icons-blue-alt)
|
||||
(graphql-mode all-the-icons-fileicon "graphql" :face all-the-icons-dpink)
|
||||
@@ -656,24 +688,37 @@ for performance sake.")
|
||||
(perl-mode all-the-icons-alltheicon "perl" :face all-the-icons-lorange)
|
||||
(cperl-mode all-the-icons-alltheicon "perl" :face all-the-icons-lorange)
|
||||
(php-mode all-the-icons-fileicon "php" :face all-the-icons-lsilver)
|
||||
(php-ts-mode all-the-icons-fileicon "php" :face all-the-icons-lsilver)
|
||||
(phps-mode all-the-icons-fileicon "php" :face all-the-icons-lsilver)
|
||||
(prolog-mode all-the-icons-alltheicon "prolog" :height 1.1 :face all-the-icons-lmaroon)
|
||||
(python-mode all-the-icons-alltheicon "python" :height 1.0 :face all-the-icons-dblue)
|
||||
(python-ts-mode all-the-icons-alltheicon "python" :height 1.0 :face all-the-icons-dblue)
|
||||
(inferior-python-mode all-the-icons-alltheicon "python" :height 1.0 :face all-the-icons-dblue)
|
||||
(racket-mode all-the-icons-fileicon "racket" :height 1.2 :face all-the-icons-red)
|
||||
(rust-mode all-the-icons-alltheicon "rust" :height 1.2 :face all-the-icons-maroon)
|
||||
(rustic-mode all-the-icons-alltheicon "rust" :height 1.2 :face all-the-icons-maroon)
|
||||
(rust-ts-mode all-the-icons-alltheicon "rust" :height 1.2 :face all-the-icons-maroon)
|
||||
(scala-mode all-the-icons-alltheicon "scala" :face all-the-icons-red)
|
||||
(scheme-mode all-the-icons-fileicon "scheme" :height 1.2 :face all-the-icons-red)
|
||||
(swift-mode all-the-icons-alltheicon "swift" :height 1.0 :v-adjust -0.1 :face all-the-icons-green)
|
||||
(svelte-mode all-the-icons-fileicon "svelte" :v-adjust 0.0 :face all-the-icons-red)
|
||||
(ada-mode all-the-icons-fileicon "ada" :v-adjust 0.0 :face all-the-icons-blue)
|
||||
(ada-ts-mode all-the-icons-fileicon "ada" :v-adjust 0.0 :face all-the-icons-blue)
|
||||
(gpr-mode all-the-icons-fileicon "ada" :v-adjust 0.0 :face all-the-icons-green)
|
||||
(gpr-ts-mode all-the-icons-fileicon "ada" :v-adjust 0.0 :face all-the-icons-green)
|
||||
(c-mode all-the-icons-alltheicon "c-line" :face all-the-icons-blue)
|
||||
(c-ts-mode all-the-icons-alltheicon "c-line" :face all-the-icons-blue)
|
||||
(c++-mode all-the-icons-alltheicon "cplusplus-line" :v-adjust -0.2 :face all-the-icons-blue)
|
||||
(c++-ts-mode all-the-icons-alltheicon "cplusplus-line" :v-adjust -0.2 :face all-the-icons-blue)
|
||||
(csharp-mode all-the-icons-alltheicon "csharp-line" :face all-the-icons-dblue)
|
||||
(csharp-ts-mode all-the-icons-alltheicon "csharp-line" :face all-the-icons-dblue)
|
||||
(clojure-mode all-the-icons-alltheicon "clojure" :height 1.0 :face all-the-icons-blue)
|
||||
(cider-repl-mode all-the-icons-alltheicon "clojure" :height 1.0 :face all-the-icons-green)
|
||||
(clojurescript-mode all-the-icons-fileicon "cljs" :height 1.0 :face all-the-icons-dblue)
|
||||
(coffee-mode all-the-icons-alltheicon "coffeescript" :height 1.0 :face all-the-icons-maroon)
|
||||
(lisp-mode all-the-icons-fileicon "lisp" :face all-the-icons-orange)
|
||||
(css-mode all-the-icons-alltheicon "css3" :face all-the-icons-yellow)
|
||||
(css-ts-mode all-the-icons-alltheicon "css3" :face all-the-icons-yellow)
|
||||
(scss-mode all-the-icons-alltheicon "sass" :face all-the-icons-pink)
|
||||
(sass-mode all-the-icons-alltheicon "sass" :face all-the-icons-dpink)
|
||||
(less-css-mode all-the-icons-alltheicon "less" :height 0.8 :face all-the-icons-dyellow)
|
||||
@@ -684,6 +729,7 @@ for performance sake.")
|
||||
(literate-haskell-mode all-the-icons-alltheicon "haskell" :height 1.0 :face all-the-icons-red)
|
||||
(haml-mode all-the-icons-fileicon "haml" :face all-the-icons-lyellow)
|
||||
(html-mode all-the-icons-alltheicon "html5" :face all-the-icons-orange)
|
||||
(html-ts-mode all-the-icons-alltheicon "html5" :face all-the-icons-orange)
|
||||
(rhtml-mode all-the-icons-alltheicon "html5" :face all-the-icons-lred)
|
||||
(mustache-mode all-the-icons-fileicon "moustache" :face all-the-icons-green)
|
||||
(slim-mode all-the-icons-octicon "dashboard" :v-adjust 0.0 :face all-the-icons-yellow)
|
||||
@@ -703,6 +749,7 @@ for performance sake.")
|
||||
(vhdl-mode all-the-icons-fileicon "vhdl" :face all-the-icons-blue)
|
||||
(haskell-cabal-mode all-the-icons-fileicon "cabal" :face all-the-icons-lblue)
|
||||
(kotlin-mode all-the-icons-fileicon "kotlin" :face all-the-icons-orange)
|
||||
(kotlin-ts-mode all-the-icons-fileicon "kotlin" :face all-the-icons-orange)
|
||||
(nim-mode all-the-icons-fileicon "nimrod" :face all-the-icons-yellow)
|
||||
(sql-mode all-the-icons-octicon "database" :face all-the-icons-silver)
|
||||
(lua-mode all-the-icons-fileicon "lua" :face all-the-icons-dblue)
|
||||
@@ -722,15 +769,24 @@ for performance sake.")
|
||||
(hy-mode all-the-icons-fileicon "hy" :face all-the-icons-blue)
|
||||
(glsl-mode all-the-icons-fileicon "vertex-shader" :face all-the-icons-green)
|
||||
(zig-mode all-the-icons-fileicon "zig" :face all-the-icons-orange)
|
||||
(exwm-mode all-the-icons-octicon "browser" :v-adjust 0.2 :face all-the-icons-purple)
|
||||
(beancount-mode all-the-icons-faicon "credit-card" :face all-the-icons-lgreen)
|
||||
(ledger-mode all-the-icons-faicon "credit-card" :face all-the-icons-lgreen)
|
||||
(odin-mode all-the-icons-fileicon "odin" :height 1.1 :face all-the-icons-lblue)
|
||||
(pdf-view-mode all-the-icons-octicon "file-pdf" :v-adjust 0.0 :face all-the-icons-dred)
|
||||
(spacemacs-buffer-mode all-the-icons-fileicon "elisp" :height 1.0 :v-adjust -0.1 :face all-the-icons-purple)
|
||||
(elfeed-search-mode all-the-icons-faicon "rss-square" :face all-the-icons-orange)
|
||||
(elfeed-show-mode all-the-icons-faicon "rss" :face all-the-icons-orange)
|
||||
(emms-browser-mode all-the-icons-faicon "music" :face all-the-icons-silver)
|
||||
(emms-lyrics-mode all-the-icons-faicon "music" :face all-the-icons-silver)
|
||||
(emms-show-all-mode all-the-icons-faicon "music" :face all-the-icons-silver)
|
||||
(emms-metaplaylist-mode all-the-icons-faicon "music" :face all-the-icons-silver)
|
||||
(emms-tag-editor-mode all-the-icons-faicon "music" :face all-the-icons-silver)
|
||||
(emms-playlist-mode all-the-icons-faicon "music" :face all-the-icons-silver)
|
||||
(lilypond-mode all-the-icons-faicon "music" :face all-the-icons-green)
|
||||
(magik-session-mode all-the-icons-alltheicon "terminal" :face all-the-icons-blue)
|
||||
(magik-cb-mode all-the-icons-faicon "book" :face all-the-icons-blue)
|
||||
(meson-mode all-the-icons-fileicon "meson" :face all-the-icons-purple)
|
||||
(man-common all-the-icons-fileicon "man-page" :face all-the-icons-blue)))
|
||||
(man-common all-the-icons-fileicon "man-page" :face all-the-icons-blue)
|
||||
(ess-r-mode all-the-icons-fileicon "R" :face all-the-icons-lblue)))
|
||||
|
||||
(defvar all-the-icons-url-alist
|
||||
'(
|
||||
@@ -843,8 +899,8 @@ for performance sake.")
|
||||
(eq major-mode auto-mode)))
|
||||
|
||||
(defun all-the-icons-match-to-alist (file alist)
|
||||
"Match FILE against an entry in ALIST using `string-match'."
|
||||
(cdr (cl-find-if (lambda (it) (string-match (car it) file)) alist)))
|
||||
"Match FILE against an entry in ALIST using `string-match-p'."
|
||||
(cdr (cl-find-if (lambda (it) (string-match-p (car it) file)) alist)))
|
||||
|
||||
(defun all-the-icons-dir-is-submodule (dir)
|
||||
"Checker whether or not DIR is a git submodule."
|
||||
@@ -916,20 +972,21 @@ inserting functions.
|
||||
|
||||
Note: You want chevron, please use `all-the-icons-icon-for-dir-with-chevron'."
|
||||
(let* ((dirname (file-name-base (directory-file-name dir)))
|
||||
(path (expand-file-name dir))
|
||||
(icon (all-the-icons-match-to-alist dirname all-the-icons-dir-icon-alist))
|
||||
(args (cdr icon)))
|
||||
(when arg-overrides (setq args (append `(,(car args)) arg-overrides (cdr args))))
|
||||
(cond
|
||||
((file-remote-p path)
|
||||
(apply #'all-the-icons-octicon "terminal" (cdr args)))
|
||||
((file-symlink-p path)
|
||||
(apply #'all-the-icons-octicon "file-symlink-directory" (cdr args)))
|
||||
((all-the-icons-dir-is-submodule path)
|
||||
(apply #'all-the-icons-octicon "file-submodule" (cdr args)))
|
||||
((file-exists-p (format "%s/.git" path))
|
||||
(apply #'all-the-icons-octicon "repo" (cdr args)))
|
||||
(t (apply (car icon) args)))))
|
||||
(if (file-remote-p dir) ;; don't call expand-file-name on a remote dir as this can make emacs hang
|
||||
(apply #'all-the-icons-octicon "terminal" (cdr args))
|
||||
(let
|
||||
((path (expand-file-name dir)))
|
||||
(cond
|
||||
((file-symlink-p path)
|
||||
(apply #'all-the-icons-octicon "file-symlink-directory" (cdr args)))
|
||||
((all-the-icons-dir-is-submodule path)
|
||||
(apply #'all-the-icons-octicon "file-submodule" (cdr args)))
|
||||
((file-exists-p (format "%s/.git" path))
|
||||
(apply #'all-the-icons-octicon "repo" (cdr args)))
|
||||
(t (apply (car icon) args)))))))
|
||||
|
||||
;;;###autoload
|
||||
(defun all-the-icons-icon-for-file (file &rest arg-overrides)
|
||||
@@ -1004,7 +1061,7 @@ inserting functions."
|
||||
(defun all-the-icons-icon-family-for-file (file)
|
||||
"Get the icons font family for FILE."
|
||||
(let* ((ext (file-name-extension file))
|
||||
(icon (or (all-the-icons-match-to-alist file all-the-icons-regexp-icon-alist)
|
||||
(icon (or (all-the-icons-match-to-alist file all-the-icons-regexp-icon-alist)
|
||||
(and ext
|
||||
(cdr (assoc (downcase ext)
|
||||
all-the-icons-extension-icon-alist)))
|
||||
@@ -1164,7 +1221,7 @@ pause for DURATION seconds between printing each character."
|
||||
(mapc
|
||||
(lambda (it)
|
||||
(insert (format "%s - %s\n" (funcall insert-f (car it) :height height) (car it)))
|
||||
(when duration (sit-for duration 0)))
|
||||
(when duration (sit-for duration)))
|
||||
data)))
|
||||
|
||||
(defmacro all-the-icons-define-icon (name alist family &optional font-name)
|
||||
@@ -1219,8 +1276,6 @@ FONT-NAME is the name of the .ttf file providing the font, defaults to FAMILY."
|
||||
(interactive "P")
|
||||
(all-the-icons-insert arg (quote ,name)))))
|
||||
|
||||
(define-obsolete-function-alias 'define-icon 'all-the-icons-define-icon "4.0.0")
|
||||
|
||||
(all-the-icons-define-icon alltheicon all-the-icons-data/alltheicons-alist "all-the-icons")
|
||||
(all-the-icons-define-icon fileicon all-the-icons-data/file-icon-alist "file-icons")
|
||||
(all-the-icons-define-icon faicon all-the-icons-data/fa-icon-alist "FontAwesome")
|
||||
|
||||
@@ -312,7 +312,7 @@
|
||||
( "objective-j" . "\xe99e" )
|
||||
( "ocaml" . "\xe91a" )
|
||||
( "octave" . "\xea33" )
|
||||
( "odin" . "\eb36" )
|
||||
( "odin" . "\xeb36" )
|
||||
( "onenote" . "\xe9eb" )
|
||||
( "ooc" . "\xe9cb" )
|
||||
( "opa" . "\x2601" )
|
||||
|
||||
16
lisp/amx/amx-pkg.el
Normal file
16
lisp/amx/amx-pkg.el
Normal file
@@ -0,0 +1,16 @@
|
||||
(define-package "amx" "20230413.1210" "Alternative M-x with extra features."
|
||||
'((emacs "24.4")
|
||||
(s "0"))
|
||||
:commit "1c2428d21e9d2ee8bee944b572a39ca8c91ca13b" :authors
|
||||
'(("Ryan C. Thompson" . "rct@thompsonclan.org")
|
||||
("Cornelius Mika" . "cornelius.mika@gmail.com"))
|
||||
:maintainers
|
||||
'(("Ryan C. Thompson" . "rct@thompsonclan.org"))
|
||||
:maintainer
|
||||
'("Ryan C. Thompson" . "rct@thompsonclan.org")
|
||||
:keywords
|
||||
'("convenience" "usability" "completion")
|
||||
:url "http://github.com/DarwinAwardWinner/amx/")
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
;; End:
|
||||
@@ -8,8 +8,6 @@
|
||||
;; Cornelius Mika <cornelius.mika@gmail.com>
|
||||
;; Maintainer: Ryan C. Thompson <rct@thompsonclan.org>
|
||||
;; URL: http://github.com/DarwinAwardWinner/amx/
|
||||
;; Package-Version: 20210305.118
|
||||
;; Package-Commit: 37f9c7ae55eb0331b27200fb745206fc58ceffc0
|
||||
;; Package-Requires: ((emacs "24.4") (s "0"))
|
||||
;; Version: 3.4
|
||||
;; Keywords: convenience, usability, completion
|
||||
@@ -238,6 +236,7 @@ nil) if you don't find it useful."
|
||||
"\\`self-insert-and-exit\\'"
|
||||
"\\`ad-Orig-"
|
||||
"\\`menu-bar"
|
||||
"\\`kill-emacs\\'"
|
||||
amx-command-marked-ignored-p
|
||||
amx-command-obsolete-p
|
||||
amx-command-mouse-interactive-p)
|
||||
@@ -622,7 +621,7 @@ May not work for things like ido and ivy."
|
||||
|
||||
(cl-defun amx-completing-read-helm (choices &key initial-input predicate def)
|
||||
"Amx backend for helm completion."
|
||||
(require 'helm-config)
|
||||
(require 'helm)
|
||||
(require 'helm-mode) ; Provides `helm-comp-read-map'
|
||||
(helm-comp-read (amx-prompt-with-prefix-arg) choices
|
||||
:initial-input initial-input
|
||||
@@ -630,7 +629,7 @@ May not work for things like ido and ivy."
|
||||
:default def
|
||||
:name "Helm M-x Completions"
|
||||
:buffer "Helm M-x Completions"
|
||||
:history extended-command-history
|
||||
:history 'extended-command-history
|
||||
:reverse-history t
|
||||
:must-match t
|
||||
:fuzzy (or (bound-and-true-p helm-mode-fuzzy-match)
|
||||
@@ -675,17 +674,18 @@ May not work for things like ido and ivy."
|
||||
:auto-activate '(bound-and-true-p selectrum-mode))
|
||||
|
||||
(defsubst amx-auto-select-backend ()
|
||||
(cl-loop for (bname b) on amx-known-backends by 'cddr
|
||||
;; Don't auto-select the auto backend, or the
|
||||
;; default backend.
|
||||
unless (memq bname '(auto standard))
|
||||
;; Auto-select a backend if its auto-activate
|
||||
;; condition evaluates to non-nil.
|
||||
if (ignore-errors (eval (amx-backend-auto-activate b)))
|
||||
return b
|
||||
;; If no backend's auto-activate condition is
|
||||
;; fulfilled, auto-select the standard backend.
|
||||
finally return 'standard))
|
||||
(cl-loop
|
||||
for (bname b) on amx-known-backends by 'cddr
|
||||
;; Don't auto-select the auto backend, or the
|
||||
;; default backend.
|
||||
unless (memq bname '(auto standard))
|
||||
;; Auto-select a backend if its auto-activate
|
||||
;; condition evaluates to non-nil.
|
||||
if (ignore-errors (eval (amx-backend-auto-activate b)))
|
||||
return b
|
||||
;; If no backend's auto-activate condition is
|
||||
;; fulfilled, auto-select the standard backend.
|
||||
finally return 'standard))
|
||||
|
||||
(cl-defun amx-completing-read-auto (choices &key initial-input predicate def)
|
||||
"Automatically select the appropriate completion system for M-x.
|
||||
@@ -771,10 +771,10 @@ This should be the name of backend defined using
|
||||
;; This speeds up sorting.
|
||||
(let (new-commands)
|
||||
(mapatoms (lambda (symbol)
|
||||
(when (commandp symbol)
|
||||
(let ((known-command (assq symbol amx-data)))
|
||||
(if known-command
|
||||
(setq amx-cache (cons known-command amx-cache))
|
||||
(let ((known-command (assq symbol amx-data)))
|
||||
(if known-command
|
||||
(setq amx-cache (cons known-command amx-cache))
|
||||
(when (commandp symbol)
|
||||
(setq new-commands (cons (list symbol) new-commands)))))))
|
||||
(if (eq (length amx-cache) 0)
|
||||
(setq amx-cache new-commands)
|
||||
@@ -836,8 +836,8 @@ Otherwise, if optional arg COUNT-COMMANDS is non-nil, count the
|
||||
total number of defined commands in `obarray' and update if it
|
||||
has changed."
|
||||
(if (or (null amx-last-update-time)
|
||||
(and count-commands
|
||||
(amx-detect-new-commands)))
|
||||
(and count-commands
|
||||
(amx-detect-new-commands)))
|
||||
(amx-update)
|
||||
(amx--debug-message "No update needed at this time.")))
|
||||
|
||||
@@ -848,8 +848,8 @@ has changed."
|
||||
This function is normally idempotent, only having an effect the
|
||||
first time it is called, so it is safe to call it at the
|
||||
beginning of any function that expects amx to be initialized.
|
||||
However, optional arg REINIT forces the initialization needs to
|
||||
be re-run. Interactively, reinitialize when a prefix arg is
|
||||
However, optional arg REINIT forces the initialization to be
|
||||
re-run. Interactively, reinitialize when a prefix arg is
|
||||
provided."
|
||||
(interactive "P")
|
||||
(when (or reinit (not amx-initialized))
|
||||
@@ -1350,7 +1350,7 @@ current."
|
||||
(when amx-short-idle-update-timer
|
||||
(cancel-timer amx-short-idle-update-timer))
|
||||
(setq amx-short-idle-update-timer
|
||||
(run-with-idle-timer 1 t 'amx-idle-update)))
|
||||
(run-with-idle-timer 1 t 'amx-idle-update)))
|
||||
|
||||
(provide 'amx)
|
||||
;;; amx.el ends here
|
||||
@@ -1,13 +1,17 @@
|
||||
(define-package "anaconda-mode" "20220922.741" "Code navigation, documentation lookup and completion for Python"
|
||||
(define-package "anaconda-mode" "20250310.1512" "Code navigation, documentation lookup and completion for Python"
|
||||
'((emacs "25.1")
|
||||
(pythonic "0.1.0")
|
||||
(dash "2.6.0")
|
||||
(s "1.9")
|
||||
(f "0.16.2"))
|
||||
:commit "ca8edbaa7662d97e4a4416ec9a8d743863303911" :authors
|
||||
:commit "28b3e0088ac7113390aa006bf277c8aa14e561a2" :authors
|
||||
'(("Artem Malyshev" . "proofit404@gmail.com"))
|
||||
:maintainers
|
||||
'(("Artem Malyshev" . "proofit404@gmail.com"))
|
||||
:maintainer
|
||||
'("Artem Malyshev" . "proofit404@gmail.com")
|
||||
:keywords
|
||||
'("convenience" "anaconda")
|
||||
:url "https://github.com/proofit404/anaconda-mode")
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
|
||||
;; Author: Artem Malyshev <proofit404@gmail.com>
|
||||
;; URL: https://github.com/proofit404/anaconda-mode
|
||||
;; Version: 0.1.15
|
||||
;; Version: 0.1.16
|
||||
;; Package-Requires: ((emacs "25.1") (pythonic "0.1.0") (dash "2.6.0") (s "1.9") (f "0.16.2"))
|
||||
;; Keywords: convenience anaconda
|
||||
|
||||
;; 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
|
||||
@@ -28,6 +29,7 @@
|
||||
|
||||
(require 'ansi-color)
|
||||
(require 'pythonic)
|
||||
(require 'cl-lib)
|
||||
(require 'tramp)
|
||||
(require 'xref)
|
||||
(require 'json)
|
||||
@@ -77,6 +79,13 @@
|
||||
"Time in seconds `anaconda-mode' waits for a synchronous response."
|
||||
:type 'integer)
|
||||
|
||||
; create a defcustom that only allows for 'never, 'always, or 'remote
|
||||
(defcustom anaconda-mode-disable-rpc 'never
|
||||
"Disable RPC calls to the `anaconda-mode' server when remote."
|
||||
:type '(choice (const :tag "Never" never)
|
||||
(const :tag "Always" always)
|
||||
(const :tag "Remote" remote)))
|
||||
|
||||
;;; Compatibility
|
||||
|
||||
;; Functions from posframe which is an optional dependency
|
||||
@@ -85,7 +94,7 @@
|
||||
(declare-function posframe-show "posframe")
|
||||
|
||||
;;; Server.
|
||||
(defvar anaconda-mode-server-version "0.1.15"
|
||||
(defvar anaconda-mode-server-version "0.1.17"
|
||||
"Server version needed to run `anaconda-mode'.")
|
||||
|
||||
(defvar anaconda-mode-process-name "anaconda-mode"
|
||||
@@ -361,8 +370,11 @@ called when `anaconda-mode-port' will be bound."
|
||||
(defun anaconda-mode-call (command callback)
|
||||
"Make remote procedure call for COMMAND.
|
||||
Apply CALLBACK to the result asynchronously."
|
||||
(anaconda-mode-start
|
||||
(lambda () (anaconda-mode-jsonrpc command callback))))
|
||||
(unless (or (eq anaconda-mode-disable-rpc 'always)
|
||||
(and (eq anaconda-mode-disable-rpc 'remote)
|
||||
(pythonic-remote-p)))
|
||||
(anaconda-mode-start
|
||||
(lambda () (anaconda-mode-jsonrpc command callback)))))
|
||||
|
||||
(defun anaconda-mode-call-sync (command callback)
|
||||
"Make remote procedure call for COMMAND.
|
||||
@@ -699,26 +711,29 @@ Show ERROR-MESSAGE if result is empty."
|
||||
|
||||
;;; Eldoc.
|
||||
|
||||
(defun anaconda-mode-eldoc-function ()
|
||||
(defun anaconda-mode-eldoc-function (callback &rest _ignored)
|
||||
"Show eldoc for context at point."
|
||||
(anaconda-mode-call "eldoc" 'anaconda-mode-eldoc-callback)
|
||||
(anaconda-mode-call
|
||||
"eldoc"
|
||||
(lambda (x)
|
||||
(funcall callback (anaconda-mode-eldoc-format x))))
|
||||
;; Don't show response buffer name as ElDoc message.
|
||||
nil)
|
||||
|
||||
(defun anaconda-mode-eldoc-callback (result)
|
||||
"Display eldoc from server RESULT."
|
||||
(eldoc-message (anaconda-mode-eldoc-format result)))
|
||||
|
||||
(defun anaconda-mode-eldoc-format (result)
|
||||
"Format eldoc string from RESULT."
|
||||
(when result
|
||||
(let ((doc (anaconda-mode-eldoc-format-definition
|
||||
(aref result 0)
|
||||
(aref result 1)
|
||||
(aref result 2))))
|
||||
(let ((doc (cl-map 'list
|
||||
(lambda (s)
|
||||
(anaconda-mode-eldoc-format-definition
|
||||
(aref s 0)
|
||||
(aref s 1)
|
||||
(aref s 2)))
|
||||
result)))
|
||||
(if anaconda-mode-eldoc-as-single-line
|
||||
(substring doc 0 (min (frame-width) (length doc)))
|
||||
doc))))
|
||||
(let ((d (mapconcat #'identity doc ", ")))
|
||||
(substring d 0 (min (frame-width) (length d))))
|
||||
(mapconcat #'identity doc "\n")))))
|
||||
|
||||
(defun anaconda-mode-eldoc-format-definition (name index params)
|
||||
"Format function definition from NAME, INDEX and PARAMS."
|
||||
@@ -768,14 +783,15 @@ Show ERROR-MESSAGE if result is empty."
|
||||
|
||||
(defun turn-on-anaconda-eldoc-mode ()
|
||||
"Turn on `anaconda-eldoc-mode'."
|
||||
(make-local-variable 'eldoc-documentation-function)
|
||||
(setq-local eldoc-documentation-function 'anaconda-mode-eldoc-function)
|
||||
(eldoc-mode +1))
|
||||
(add-hook 'eldoc-documentation-functions
|
||||
#'anaconda-mode-eldoc-function nil 't)
|
||||
(unless (bound-and-true-p eldoc-mode)
|
||||
(eldoc-mode +1)))
|
||||
|
||||
(defun turn-off-anaconda-eldoc-mode ()
|
||||
"Turn off `anaconda-eldoc-mode'."
|
||||
(kill-local-variable 'eldoc-documentation-function)
|
||||
(eldoc-mode -1))
|
||||
(remove-hook 'eldoc-documentation-functions
|
||||
#'anaconda-mode-eldoc-function 't))
|
||||
|
||||
(provide 'anaconda-mode)
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
from __future__ import print_function
|
||||
import sys
|
||||
import os
|
||||
@@ -25,7 +24,7 @@ if IS_PY2:
|
||||
jedi_dep = ('jedi', '0.17.2')
|
||||
server_directory += '-py2'
|
||||
else:
|
||||
jedi_dep = ('jedi', '0.18.1')
|
||||
jedi_dep = ('jedi', '0.19.2')
|
||||
server_directory += '-py3'
|
||||
service_factory_dep = ('service_factory', '0.1.6')
|
||||
|
||||
@@ -71,10 +70,19 @@ def install_deps_setuptools():
|
||||
instrument_installation()
|
||||
|
||||
def install_deps_pip():
|
||||
import pathlib
|
||||
import shutil
|
||||
import subprocess
|
||||
cmd = [sys.executable, '-m', 'pip', 'install', '--target', server_directory]
|
||||
import tempfile
|
||||
import venv
|
||||
temp_dir = pathlib.Path(tempfile.mkdtemp())
|
||||
venv.create(temp_dir, with_pip=True)
|
||||
cmd = [temp_dir / 'bin' / 'pip', 'install', '--target', server_directory]
|
||||
cmd.extend(missing_dependencies)
|
||||
subprocess.check_call(cmd)
|
||||
try:
|
||||
subprocess.check_call(cmd)
|
||||
finally:
|
||||
shutil.rmtree(temp_dir)
|
||||
instrument_installation()
|
||||
|
||||
if missing_dependencies:
|
||||
@@ -192,11 +200,11 @@ def get_references(script, line, column):
|
||||
@script_method
|
||||
def eldoc(script, line, column):
|
||||
signatures = script.get_signatures(line, column)
|
||||
if len(signatures) == 1:
|
||||
signature = signatures[0]
|
||||
return [signature.name,
|
||||
signature.index,
|
||||
[param.description[6:] for param in signature.params]]
|
||||
if len(signatures) >= 1:
|
||||
return [(s.name,
|
||||
s.index,
|
||||
[param.description[6:] for param in s.params])
|
||||
for s in signatures]
|
||||
|
||||
# Run.
|
||||
|
||||
|
||||
12
lisp/anaphora/anaphora-pkg.el
Normal file
12
lisp/anaphora/anaphora-pkg.el
Normal file
@@ -0,0 +1,12 @@
|
||||
(define-package "anaphora" "20240120.1744" "anaphoric macros providing implicit temp variables" 'nil :commit "a755afa7db7f3fa515f8dd2c0518113be0b027f6" :authors
|
||||
'(("Roland Walker" . "walker@pobox.com"))
|
||||
:maintainers
|
||||
'(("Roland Walker" . "walker@pobox.com"))
|
||||
:maintainer
|
||||
'("Roland Walker" . "walker@pobox.com")
|
||||
:keywords
|
||||
'("extensions")
|
||||
:url "http://github.com/rolandwalker/anaphora")
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
;; End:
|
||||
474
lisp/anaphora/anaphora.el
Normal file
474
lisp/anaphora/anaphora.el
Normal file
@@ -0,0 +1,474 @@
|
||||
;;; anaphora.el --- anaphoric macros providing implicit temp variables -*- lexical-binding: t -*-
|
||||
;;
|
||||
;; This code is in the public domain.
|
||||
;;
|
||||
;; Author: Roland Walker <walker@pobox.com>
|
||||
;; Homepage: http://github.com/rolandwalker/anaphora
|
||||
;; URL: http://raw.githubusercontent.com/rolandwalker/anaphora/master/anaphora.el
|
||||
;; Version: 1.0.4
|
||||
;; Last-Updated: 18 Jun 2018
|
||||
;; EmacsWiki: Anaphora
|
||||
;; Keywords: extensions
|
||||
;;
|
||||
;;; Commentary:
|
||||
;;
|
||||
;; Quickstart
|
||||
;;
|
||||
;; (require 'anaphora)
|
||||
;;
|
||||
;; (awhen (big-long-calculation)
|
||||
;; (foo it) ; `it' is provided as
|
||||
;; (bar it)) ; a temporary variable
|
||||
;;
|
||||
;; ;; anonymous function to compute factorial using `self'
|
||||
;; (alambda (x) (if (= x 0) 1 (* x (self (1- x)))))
|
||||
;;
|
||||
;; ;; to fontify `it' and `self'
|
||||
;; (with-eval-after-load "lisp-mode"
|
||||
;; (anaphora-install-font-lock-keywords))
|
||||
;;
|
||||
;; Explanation
|
||||
;;
|
||||
;; Anaphoric expressions implicitly create one or more temporary
|
||||
;; variables which can be referred to during the expression. This
|
||||
;; technique can improve clarity in certain cases. It also enables
|
||||
;; recursion for anonymous functions.
|
||||
;;
|
||||
;; To use anaphora, place the anaphora.el library somewhere
|
||||
;; Emacs can find it, and add the following to your ~/.emacs file:
|
||||
;;
|
||||
;; (require 'anaphora)
|
||||
;;
|
||||
;; The following macros are made available
|
||||
;;
|
||||
;; `aand'
|
||||
;; `ablock'
|
||||
;; `acase'
|
||||
;; `acond'
|
||||
;; `aecase'
|
||||
;; `aetypecase'
|
||||
;; `apcase'
|
||||
;; `aif'
|
||||
;; `alambda'
|
||||
;; `alet'
|
||||
;; `aprog1'
|
||||
;; `aprog2'
|
||||
;; `atypecase'
|
||||
;; `awhen'
|
||||
;; `awhile'
|
||||
;; `a+'
|
||||
;; `a-'
|
||||
;; `a*'
|
||||
;; `a/'
|
||||
;;
|
||||
;; See Also
|
||||
;;
|
||||
;; M-x customize-group RET anaphora RET
|
||||
;; http://en.wikipedia.org/wiki/On_Lisp
|
||||
;; http://en.wikipedia.org/wiki/Anaphoric_macro
|
||||
;;
|
||||
;; Notes
|
||||
;;
|
||||
;; Partially based on examples from the book "On Lisp", by Paul
|
||||
;; Graham.
|
||||
;;
|
||||
;; Compatibility and Requirements
|
||||
;;
|
||||
;; GNU Emacs version 26.1 : yes
|
||||
;; GNU Emacs version 25.x : yes
|
||||
;; GNU Emacs version 24.x : yes
|
||||
;; GNU Emacs version 23.x : yes
|
||||
;; GNU Emacs version 22.x : yes
|
||||
;; GNU Emacs version 21.x and lower : unknown
|
||||
;;
|
||||
;; Bugs
|
||||
;;
|
||||
;; TODO
|
||||
;;
|
||||
;; better face for it and self
|
||||
;;
|
||||
;;; License
|
||||
;;
|
||||
;; All code contributed by the author to this library is placed in the
|
||||
;; public domain. It is the author's belief that the portions adapted
|
||||
;; from examples in "On Lisp" are in the public domain.
|
||||
;;
|
||||
;; Regardless of the copyright status of individual functions, all
|
||||
;; code herein is free software, and is provided without any express
|
||||
;; or implied warranties.
|
||||
;;
|
||||
;;; Code:
|
||||
;;
|
||||
|
||||
;;; requirements
|
||||
|
||||
;; for declare, labels, do, block, case, ecase, typecase, etypecase
|
||||
(require 'cl-lib)
|
||||
|
||||
;;; customizable variables
|
||||
|
||||
;;;###autoload
|
||||
(defgroup anaphora nil
|
||||
"Anaphoric macros providing implicit temp variables"
|
||||
:version "1.0.4"
|
||||
:link '(emacs-commentary-link :tag "Commentary" "anaphora")
|
||||
:link '(url-link :tag "GitHub" "http://github.com/rolandwalker/anaphora")
|
||||
:link '(url-link :tag "EmacsWiki" "http://emacswiki.org/emacs/Anaphora")
|
||||
:prefix "anaphora-"
|
||||
:group 'extensions)
|
||||
|
||||
;;;###autoload
|
||||
(defcustom anaphora-use-long-names-only nil
|
||||
"Use only long names such as `anaphoric-if' instead of traditional `aif'."
|
||||
:type 'boolean
|
||||
:group 'anaphora)
|
||||
|
||||
;;; font-lock
|
||||
|
||||
(defun anaphora-install-font-lock-keywords nil
|
||||
"Fontify keywords `it' and `self'."
|
||||
(font-lock-add-keywords 'emacs-lisp-mode `((,(concat "\\<" (regexp-opt '("it" "self") 'paren) "\\>")
|
||||
1 font-lock-variable-name-face)) 'append))
|
||||
|
||||
;;; aliases
|
||||
|
||||
;;;###autoload
|
||||
(progn
|
||||
(defun anaphora--install-traditional-aliases (&optional arg)
|
||||
"Install traditional short aliases for anaphoric macros.
|
||||
|
||||
With negative numeric ARG, remove traditional aliases."
|
||||
(let ((syms '(
|
||||
(if . t)
|
||||
(prog1 . t)
|
||||
(prog2 . t)
|
||||
(when . when)
|
||||
(while . t)
|
||||
(and . t)
|
||||
(cond . cond)
|
||||
(lambda . lambda)
|
||||
(block . block)
|
||||
(case . case)
|
||||
(ecase . ecase)
|
||||
(typecase . typecase)
|
||||
(etypecase . etypecase)
|
||||
(pcase . pcase)
|
||||
(let . let)
|
||||
(+ . t)
|
||||
(- . t)
|
||||
(* . t)
|
||||
(/ . t)
|
||||
)))
|
||||
(cond
|
||||
((and (numberp arg)
|
||||
(< arg 0))
|
||||
(dolist (cell syms)
|
||||
(when (ignore-errors
|
||||
(eq (symbol-function (intern-soft (format "a%s" (car cell))))
|
||||
(intern-soft (format "anaphoric-%s" (car cell)))))
|
||||
(fmakunbound (intern (format "a%s" (car cell)))))))
|
||||
(t
|
||||
(dolist (cell syms)
|
||||
(let* ((builtin (car cell))
|
||||
(traditional (intern (format "a%s" builtin)))
|
||||
(long (intern (format "anaphoric-%s" builtin))))
|
||||
(defalias traditional long)
|
||||
(put traditional 'lisp-indent-function
|
||||
(get builtin 'lisp-indent-function))
|
||||
(put traditional 'edebug-form-spec (cdr cell)))))))))
|
||||
|
||||
;;;###autoload
|
||||
(unless anaphora-use-long-names-only
|
||||
(anaphora--install-traditional-aliases))
|
||||
|
||||
;;; macros
|
||||
|
||||
;;;###autoload
|
||||
(defmacro anaphoric-if (cond then &rest else)
|
||||
"Like `if', but the result of evaluating COND is bound to `it'.
|
||||
|
||||
The variable `it' is available within THEN and ELSE.
|
||||
|
||||
COND, THEN, and ELSE are otherwise as documented for `if'."
|
||||
(declare (debug t)
|
||||
(indent 2))
|
||||
`(let ((it ,cond))
|
||||
(if it ,then ,@else)))
|
||||
|
||||
;;;###autoload
|
||||
(defmacro anaphoric-prog1 (first &rest body)
|
||||
"Like `prog1', but the result of evaluating FIRST is bound to `it'.
|
||||
|
||||
The variable `it' is available within BODY.
|
||||
|
||||
FIRST and BODY are otherwise as documented for `prog1'."
|
||||
(declare (debug t)
|
||||
(indent 1))
|
||||
`(let ((it ,first))
|
||||
(progn ,@body)
|
||||
it))
|
||||
|
||||
;;;###autoload
|
||||
(defmacro anaphoric-prog2 (form1 form2 &rest body)
|
||||
"Like `prog2', but the result of evaluating FORM2 is bound to `it'.
|
||||
|
||||
The variable `it' is available within BODY.
|
||||
|
||||
FORM1, FORM2, and BODY are otherwise as documented for `prog2'."
|
||||
(declare (debug t)
|
||||
(indent 2))
|
||||
`(progn
|
||||
,form1
|
||||
(let ((it ,form2))
|
||||
(progn ,@body)
|
||||
it)))
|
||||
|
||||
;;;###autoload
|
||||
(defmacro anaphoric-when (cond &rest body)
|
||||
"Like `when', but the result of evaluating COND is bound to `it'.
|
||||
|
||||
The variable `it' is available within BODY.
|
||||
|
||||
COND and BODY are otherwise as documented for `when'."
|
||||
(declare (debug when)
|
||||
(indent 1))
|
||||
`(anaphoric-if ,cond
|
||||
(progn ,@body)))
|
||||
|
||||
;;;###autoload
|
||||
(defmacro anaphoric-while (test &rest body)
|
||||
"Like `while', but the result of evaluating TEST is bound to `it'.
|
||||
|
||||
The variable `it' is available within BODY.
|
||||
|
||||
TEST and BODY are otherwise as documented for `while'."
|
||||
(declare (debug t)
|
||||
(indent 1))
|
||||
`(do ((it ,test ,test))
|
||||
((not it))
|
||||
,@body))
|
||||
|
||||
;;;###autoload
|
||||
(defmacro anaphoric-and (&rest conditions)
|
||||
"Like `and', but the result of the previous condition is bound to `it'.
|
||||
|
||||
The variable `it' is available within all CONDITIONS after the
|
||||
initial one.
|
||||
|
||||
CONDITIONS are otherwise as documented for `and'.
|
||||
|
||||
Note that some implementations of this macro bind only the first
|
||||
condition to `it', rather than each successive condition."
|
||||
(declare (debug t))
|
||||
(cond
|
||||
((null conditions)
|
||||
t)
|
||||
((null (cdr conditions))
|
||||
(car conditions))
|
||||
(t
|
||||
`(anaphoric-if ,(car conditions) (anaphoric-and ,@(cdr conditions))))))
|
||||
|
||||
;;;###autoload
|
||||
(defmacro anaphoric-cond (&rest clauses)
|
||||
"Like `cond', but the result of each condition is bound to `it'.
|
||||
|
||||
The variable `it' is available within the remainder of each of CLAUSES.
|
||||
|
||||
CLAUSES are otherwise as documented for `cond'."
|
||||
(declare (debug cond))
|
||||
(if (null clauses)
|
||||
nil
|
||||
(let ((cl1 (car clauses))
|
||||
(sym (gensym)))
|
||||
`(let ((,sym ,(car cl1)))
|
||||
(if ,sym
|
||||
(if (null ',(cdr cl1))
|
||||
,sym
|
||||
(let ((it ,sym)) ,@(cdr cl1)))
|
||||
(anaphoric-cond ,@(cdr clauses)))))))
|
||||
|
||||
;;;###autoload
|
||||
(defmacro anaphoric-lambda (args &rest body)
|
||||
"Like `lambda', but the function may refer to itself as `self'.
|
||||
|
||||
ARGS and BODY are otherwise as documented for `lambda'."
|
||||
(declare (debug lambda)
|
||||
(indent defun))
|
||||
`(cl-labels ((self ,args ,@body))
|
||||
#'self))
|
||||
|
||||
;;;###autoload
|
||||
(defmacro anaphoric-block (name &rest body)
|
||||
"Like `block', but the result of the previous expression is bound to `it'.
|
||||
|
||||
The variable `it' is available within all expressions of BODY
|
||||
except the initial one.
|
||||
|
||||
NAME and BODY are otherwise as documented for `block'."
|
||||
(declare (debug block)
|
||||
(indent 1))
|
||||
`(cl-block ,name
|
||||
,(funcall (anaphoric-lambda (body)
|
||||
(cl-case (length body)
|
||||
(0 nil)
|
||||
(1 (car body))
|
||||
(t `(let ((it ,(car body)))
|
||||
,(self (cdr body))))))
|
||||
body)))
|
||||
|
||||
;;;###autoload
|
||||
(defmacro anaphoric-case (expr &rest clauses)
|
||||
"Like `case', but the result of evaluating EXPR is bound to `it'.
|
||||
|
||||
The variable `it' is available within CLAUSES.
|
||||
|
||||
EXPR and CLAUSES are otherwise as documented for `case'."
|
||||
(declare (debug case)
|
||||
(indent 1))
|
||||
`(let ((it ,expr))
|
||||
(cl-case it ,@clauses)))
|
||||
|
||||
;;;###autoload
|
||||
(defmacro anaphoric-ecase (expr &rest clauses)
|
||||
"Like `ecase', but the result of evaluating EXPR is bound to `it'.
|
||||
|
||||
The variable `it' is available within CLAUSES.
|
||||
|
||||
EXPR and CLAUSES are otherwise as documented for `ecase'."
|
||||
(declare (debug ecase)
|
||||
(indent 1))
|
||||
`(let ((it ,expr))
|
||||
(cl-ecase it ,@clauses)))
|
||||
|
||||
;;;###autoload
|
||||
(defmacro anaphoric-typecase (expr &rest clauses)
|
||||
"Like `typecase', but the result of evaluating EXPR is bound to `it'.
|
||||
|
||||
The variable `it' is available within CLAUSES.
|
||||
|
||||
EXPR and CLAUSES are otherwise as documented for `typecase'."
|
||||
(declare (debug typecase)
|
||||
(indent 1))
|
||||
`(let ((it ,expr))
|
||||
(cl-typecase it ,@clauses)))
|
||||
|
||||
;;;###autoload
|
||||
(defmacro anaphoric-etypecase (expr &rest clauses)
|
||||
"Like `etypecase', but result of evaluating EXPR is bound to `it'.
|
||||
|
||||
The variable `it' is available within CLAUSES.
|
||||
|
||||
EXPR and CLAUSES are otherwise as documented for `etypecase'."
|
||||
(declare (debug etypecase)
|
||||
(indent 1))
|
||||
`(let ((it ,expr))
|
||||
(cl-etypecase it ,@clauses)))
|
||||
|
||||
;;;###autoload
|
||||
(defmacro anaphoric-pcase (expr &rest clauses)
|
||||
"Like `pcase', but the result of evaluating EXPR is bound to `it'.
|
||||
|
||||
The variable `it' is available within CLAUSES.
|
||||
|
||||
EXPR and CLAUSES are otherwise as documented for `pcase'."
|
||||
(declare (debug pcase)
|
||||
(indent 1))
|
||||
`(let ((it ,expr))
|
||||
(pcase it ,@clauses)))
|
||||
|
||||
;;;###autoload
|
||||
(defmacro anaphoric-let (form &rest body)
|
||||
"Like `let', but the result of evaluating FORM is bound to `it'.
|
||||
|
||||
FORM and BODY are otherwise as documented for `let'."
|
||||
(declare (debug let)
|
||||
(indent 1))
|
||||
`(let ((it ,form))
|
||||
(progn ,@body)))
|
||||
|
||||
;;;###autoload
|
||||
(defmacro anaphoric-+ (&rest numbers-or-markers)
|
||||
"Like `+', but the result of evaluating the previous expression is bound to `it'.
|
||||
|
||||
The variable `it' is available within all expressions after the
|
||||
initial one.
|
||||
|
||||
NUMBERS-OR-MARKERS are otherwise as documented for `+'."
|
||||
(declare (debug t))
|
||||
(cond
|
||||
((null numbers-or-markers)
|
||||
0)
|
||||
(t
|
||||
`(let ((it ,(car numbers-or-markers)))
|
||||
(+ it (anaphoric-+ ,@(cdr numbers-or-markers)))))))
|
||||
|
||||
;;;###autoload
|
||||
(defmacro anaphoric-- (&optional number-or-marker &rest numbers-or-markers)
|
||||
"Like `-', but the result of evaluating the previous expression is bound to `it'.
|
||||
|
||||
The variable `it' is available within all expressions after the
|
||||
initial one.
|
||||
|
||||
NUMBER-OR-MARKER and NUMBERS-OR-MARKERS are otherwise as
|
||||
documented for `-'."
|
||||
(declare (debug t))
|
||||
(cond
|
||||
((null number-or-marker)
|
||||
0)
|
||||
((null numbers-or-markers)
|
||||
`(- ,number-or-marker))
|
||||
(t
|
||||
`(let ((it ,(car numbers-or-markers)))
|
||||
(- ,number-or-marker (+ it (anaphoric-+ ,@(cdr numbers-or-markers))))))))
|
||||
|
||||
;;;###autoload
|
||||
(defmacro anaphoric-* (&rest numbers-or-markers)
|
||||
"Like `*', but the result of evaluating the previous expression is bound to `it'.
|
||||
|
||||
The variable `it' is available within all expressions after the
|
||||
initial one.
|
||||
|
||||
NUMBERS-OR-MARKERS are otherwise as documented for `*'."
|
||||
(declare (debug t))
|
||||
(cond
|
||||
((null numbers-or-markers)
|
||||
1)
|
||||
(t
|
||||
`(let ((it ,(car numbers-or-markers)))
|
||||
(* it (anaphoric-* ,@(cdr numbers-or-markers)))))))
|
||||
|
||||
;;;###autoload
|
||||
(defmacro anaphoric-/ (dividend divisor &rest divisors)
|
||||
"Like `/', but the result of evaluating the previous divisor is bound to `it'.
|
||||
|
||||
The variable `it' is available within all expressions after the
|
||||
first divisor.
|
||||
|
||||
DIVIDEND, DIVISOR, and DIVISORS are otherwise as documented for `/'."
|
||||
(declare (debug t))
|
||||
(cond
|
||||
((null divisors)
|
||||
`(/ ,dividend ,divisor))
|
||||
(t
|
||||
`(let ((it ,divisor))
|
||||
(/ ,dividend (* it (anaphoric-* ,@divisors)))))))
|
||||
|
||||
(provide 'anaphora)
|
||||
|
||||
;;
|
||||
;; Emacs
|
||||
;;
|
||||
;; Local Variables:
|
||||
;; indent-tabs-mode: nil
|
||||
;; mangle-whitespace: t
|
||||
;; require-final-newline: t
|
||||
;; coding: utf-8
|
||||
;; byte-compile-warnings: (not cl-functions redefine)
|
||||
;; End:
|
||||
;;
|
||||
;; LocalWords: Anaphora EXPR awhen COND ARGS alambda ecase typecase
|
||||
;; LocalWords: etypecase aprog aand acond ablock acase aecase alet
|
||||
;; LocalWords: atypecase aetypecase apcase
|
||||
;;
|
||||
|
||||
;;; anaphora.el ends here
|
||||
@@ -6,7 +6,7 @@
|
||||
;; Thierry Volpiatto <thievol@posteo.net>
|
||||
|
||||
;; Keywords: dired async byte-compile
|
||||
;; X-URL: https://github.com/jwiegley/dired-async
|
||||
;; X-URL: https://github.com/jwiegley/emacs-async
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
@@ -22,17 +22,22 @@
|
||||
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
;;
|
||||
|
||||
;; This package provide the `async-byte-recompile-directory' function
|
||||
;; which allows, as the name says to recompile a directory outside of
|
||||
;; your running emacs.
|
||||
;; The benefit is your files will be compiled in a clean environment without
|
||||
;; the old *.el files loaded.
|
||||
;; Among other things, this fix a bug in package.el which recompile
|
||||
;; the new files in the current environment with the old files loaded, creating
|
||||
;; errors in most packages after upgrades.
|
||||
;; your running emacs. Single files can be compiled with
|
||||
;; `async-byte-compile-file'. The benefit is your files will be
|
||||
;; compiled in a clean environment without the old *.el files
|
||||
;; loaded. A mode `async-bytecomp-package-mode' is provided to
|
||||
;; automatically compile packages asynchronously when installing or
|
||||
;; upgrading, among other things, this fix a bug in package.el which
|
||||
;; recompile the new files in the current environment with the old
|
||||
;; files loaded, creating errors in most packages after upgrades.
|
||||
;;
|
||||
;; NB: This package is advicing the function `package--compile'.
|
||||
;; NB: This package is advising the function `package--compile' when
|
||||
;; `async-bytecomp-package-mode' is enabled. This mode is useful
|
||||
;; only when using a synchronous package manager (e.g. M-x
|
||||
;; list-package), users of M-x helm-packages don't need this anymore.
|
||||
|
||||
;;; Code:
|
||||
|
||||
@@ -60,6 +65,33 @@ all packages are always compiled asynchronously."
|
||||
(defvar async-bytecomp-load-variable-regexp "\\`load-path\\'"
|
||||
"The variable used by `async-inject-variables' when (re)compiling async.")
|
||||
|
||||
(defun async-bytecomp--file-to-comp-buffer (file-or-dir &optional quiet type)
|
||||
(let ((bn (file-name-nondirectory file-or-dir))
|
||||
(action-name (pcase type
|
||||
('file "File")
|
||||
('directory "Directory"))))
|
||||
(if (file-exists-p async-byte-compile-log-file)
|
||||
(let ((buf (get-buffer-create byte-compile-log-buffer))
|
||||
(n 0))
|
||||
(with-current-buffer buf
|
||||
(goto-char (point-max))
|
||||
(let ((inhibit-read-only t))
|
||||
(insert-file-contents async-byte-compile-log-file)
|
||||
(compilation-mode))
|
||||
(display-buffer buf)
|
||||
(delete-file async-byte-compile-log-file)
|
||||
(unless quiet
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward "^.*:Error:" nil t)
|
||||
(cl-incf n)))
|
||||
(if (> n 0)
|
||||
(message "Failed to compile %d files in directory `%s'" n bn)
|
||||
(message "%s `%s' compiled asynchronously with warnings"
|
||||
action-name bn)))))
|
||||
(unless quiet
|
||||
(message "%s `%s' compiled asynchronously with success" action-name bn)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun async-byte-recompile-directory (directory &optional quiet)
|
||||
"Compile all *.el files in DIRECTORY asynchronously.
|
||||
@@ -73,26 +105,7 @@ All *.elc files are systematically deleted before proceeding."
|
||||
(load "async")
|
||||
(let ((call-back
|
||||
(lambda (&optional _ignore)
|
||||
(if (file-exists-p async-byte-compile-log-file)
|
||||
(let ((buf (get-buffer-create byte-compile-log-buffer))
|
||||
(n 0))
|
||||
(with-current-buffer buf
|
||||
(goto-char (point-max))
|
||||
(let ((inhibit-read-only t))
|
||||
(insert-file-contents async-byte-compile-log-file)
|
||||
(compilation-mode))
|
||||
(display-buffer buf)
|
||||
(delete-file async-byte-compile-log-file)
|
||||
(unless quiet
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward "^.*:Error:" nil t)
|
||||
(cl-incf n)))
|
||||
(if (> n 0)
|
||||
(message "Failed to compile %d files in directory `%s'" n directory)
|
||||
(message "Directory `%s' compiled asynchronously with warnings" directory)))))
|
||||
(unless quiet
|
||||
(message "Directory `%s' compiled asynchronously with success" directory))))))
|
||||
(async-bytecomp--file-to-comp-buffer directory quiet 'directory))))
|
||||
(async-start
|
||||
`(lambda ()
|
||||
(require 'bytecomp)
|
||||
@@ -140,13 +153,10 @@ All *.elc files are systematically deleted before proceeding."
|
||||
(memq cur-package (async-bytecomp--get-package-deps
|
||||
async-bytecomp-allowed-packages)))
|
||||
(progn
|
||||
;; FIXME: Why do we use (eq cur-package 'async) once
|
||||
;; and (string= cur-package "async") afterwards?
|
||||
(when (eq cur-package 'async)
|
||||
(fmakunbound 'async-byte-recompile-directory))
|
||||
;; Add to `load-path' the latest version of async and
|
||||
;; reload it when reinstalling async.
|
||||
(when (string= cur-package "async")
|
||||
(fmakunbound 'async-byte-recompile-directory)
|
||||
;; Add to `load-path' the latest version of async and
|
||||
;; reload it when reinstalling async.
|
||||
(cl-pushnew pkg-dir load-path)
|
||||
(load "async-bytecomp"))
|
||||
;; `async-byte-recompile-directory' will add directory
|
||||
@@ -158,7 +168,10 @@ All *.elc files are systematically deleted before proceeding."
|
||||
(define-minor-mode async-bytecomp-package-mode
|
||||
"Byte compile asynchronously packages installed with package.el.
|
||||
Async compilation of packages can be controlled by
|
||||
`async-bytecomp-allowed-packages'."
|
||||
`async-bytecomp-allowed-packages'.
|
||||
NOTE: Use this mode only if you install/upgrade etc... your packages
|
||||
synchronously, if you use a package manager like helm-package.el which
|
||||
by default is async you don't need this."
|
||||
:group 'async
|
||||
:global t
|
||||
(if async-bytecomp-package-mode
|
||||
@@ -173,28 +186,13 @@ Same as `byte-compile-file' but asynchronous."
|
||||
(interactive "fFile: ")
|
||||
(let ((call-back
|
||||
(lambda (&optional _ignore)
|
||||
(let ((bn (file-name-nondirectory file)))
|
||||
(if (file-exists-p async-byte-compile-log-file)
|
||||
(let ((buf (get-buffer-create byte-compile-log-buffer))
|
||||
start)
|
||||
(with-current-buffer buf
|
||||
(goto-char (setq start (point-max)))
|
||||
(let ((inhibit-read-only t))
|
||||
(insert-file-contents async-byte-compile-log-file)
|
||||
(compilation-mode))
|
||||
(display-buffer buf)
|
||||
(delete-file async-byte-compile-log-file)
|
||||
(save-excursion
|
||||
(goto-char start)
|
||||
(if (re-search-forward "^.*:Error:" nil t)
|
||||
(message "Failed to compile `%s'" bn)
|
||||
(message "`%s' compiled asynchronously with warnings" bn)))))
|
||||
(message "`%s' compiled asynchronously with success" bn))))))
|
||||
(async-bytecomp--file-to-comp-buffer file nil 'file))))
|
||||
(async-start
|
||||
`(lambda ()
|
||||
(require 'bytecomp)
|
||||
,(async-inject-variables async-bytecomp-load-variable-regexp)
|
||||
(let ((default-directory ,(file-name-directory file)))
|
||||
(let ((default-directory ,(file-name-directory file))
|
||||
error-data)
|
||||
(add-to-list 'load-path default-directory)
|
||||
(byte-compile-file ,file)
|
||||
(when (get-buffer byte-compile-log-buffer)
|
||||
|
||||
145
lisp/async/async-package.el
Normal file
145
lisp/async/async-package.el
Normal file
@@ -0,0 +1,145 @@
|
||||
;;; async-package.el --- Fetch packages asynchronously -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2014-2022 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Thierry Volpiatto <thievol@posteo.net>
|
||||
|
||||
;; Keywords: dired async byte-compile package
|
||||
;; X-URL: https://github.com/jwiegley/emacs-async
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; Provide the function `async-package-do-action' to
|
||||
;; (re)install/upgrade packages asynchronously.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(eval-when-compile (require 'cl-lib))
|
||||
(require 'async-bytecomp)
|
||||
(require 'dired-async)
|
||||
(require 'package)
|
||||
|
||||
(define-minor-mode async-package--modeline-mode
|
||||
"Notify mode-line that an async process run."
|
||||
:group 'async
|
||||
:global t
|
||||
:lighter (:eval (propertize (format " [%s async job Installing package(s)]"
|
||||
(length (dired-async-processes
|
||||
'async-pkg-install)))
|
||||
'face 'async-package-message))
|
||||
(unless async-package--modeline-mode
|
||||
(let ((visible-bell t)) (ding))))
|
||||
|
||||
(defvar async-pkg-install-after-hook nil
|
||||
"Hook that run after package installation.
|
||||
The hook runs in the call-back once installation is done in child emacs.")
|
||||
|
||||
(defface async-package-message
|
||||
'((t (:foreground "yellow")))
|
||||
"Face used for mode-line message."
|
||||
:group 'async)
|
||||
|
||||
(defun async-package-do-action (action packages error-file)
|
||||
"Execute ACTION asynchronously on PACKAGES.
|
||||
Argument ACTION can be one of \\='install, \\='upgrade, \\='reinstall.
|
||||
Argument PACKAGES is a list of packages (symbols).
|
||||
Argument ERROR-FILE is the file where errors are logged, if some."
|
||||
(require 'async-bytecomp)
|
||||
(let ((fn (pcase action
|
||||
('install 'package-install)
|
||||
('upgrade 'package-upgrade)
|
||||
('reinstall 'package-reinstall)))
|
||||
(action-string (pcase action
|
||||
('install "Installing")
|
||||
('upgrade "Upgrading")
|
||||
('reinstall "Reinstalling"))))
|
||||
(message "%s %s package(s)..." action-string (length packages))
|
||||
(process-put
|
||||
(async-start
|
||||
`(lambda ()
|
||||
(require 'bytecomp)
|
||||
(setq package-archives ',package-archives
|
||||
package-pinned-packages ',package-pinned-packages
|
||||
package-archive-contents ',package-archive-contents
|
||||
package-user-dir ,package-user-dir
|
||||
package-alist ',package-alist
|
||||
load-path ',load-path)
|
||||
;; Ensure `async-bytecomp-package-mode' doesn't kick in
|
||||
;; (issue #194) as some packages may enable it
|
||||
;; inconditionally. We don't need to compile async as we are
|
||||
;; already async and in a clean environment.
|
||||
(require 'async-bytecomp)
|
||||
(setq async-bytecomp-allowed-packages nil)
|
||||
(prog1
|
||||
(condition-case err
|
||||
(mapc ',fn ',packages)
|
||||
(error
|
||||
(with-temp-file ,error-file
|
||||
(insert
|
||||
(format
|
||||
"%S:\n Please refresh package list before %s"
|
||||
err ,action-string)))))
|
||||
(let (error-data)
|
||||
(when (get-buffer byte-compile-log-buffer)
|
||||
(setq error-data (with-current-buffer byte-compile-log-buffer
|
||||
(buffer-substring-no-properties
|
||||
(point-min) (point-max))))
|
||||
(unless (string= error-data "")
|
||||
(with-temp-file ,async-byte-compile-log-file
|
||||
(erase-buffer)
|
||||
(insert error-data)))))))
|
||||
(lambda (result)
|
||||
(if (file-exists-p error-file)
|
||||
(let ((buf (find-file-noselect error-file)))
|
||||
(pop-to-buffer
|
||||
buf '(nil . ((window-height . fit-window-to-buffer))))
|
||||
(special-mode)
|
||||
(delete-file error-file)
|
||||
(async-package--modeline-mode -1))
|
||||
(when result
|
||||
(let ((pkgs (if (listp result) result (list result))))
|
||||
(when (eq action 'install)
|
||||
(customize-save-variable
|
||||
'package-selected-packages
|
||||
(delete-dups (append pkgs package-selected-packages))))
|
||||
(package-load-all-descriptors) ; refresh package-alist.
|
||||
(mapc #'package-activate pkgs) ; load packages.
|
||||
(async-package--modeline-mode -1)
|
||||
(message "%s %s packages done" action-string (length packages))
|
||||
(run-with-timer
|
||||
0.1 nil
|
||||
(lambda (lst str)
|
||||
(dired-async-mode-line-message
|
||||
"%s %d package(s) done"
|
||||
'async-package-message
|
||||
str (length lst)))
|
||||
packages action-string)
|
||||
(when (file-exists-p async-byte-compile-log-file)
|
||||
(let ((buf (get-buffer-create byte-compile-log-buffer)))
|
||||
(with-current-buffer buf
|
||||
(goto-char (point-max))
|
||||
(let ((inhibit-read-only t))
|
||||
(insert-file-contents async-byte-compile-log-file)
|
||||
(compilation-mode))
|
||||
(display-buffer buf)
|
||||
(delete-file async-byte-compile-log-file)))))))
|
||||
(run-hooks 'async-pkg-install-after-hook)))
|
||||
'async-pkg-install t)
|
||||
(async-package--modeline-mode 1)))
|
||||
|
||||
(provide 'async-package)
|
||||
|
||||
;;; async-package.el ends here
|
||||
@@ -1,7 +1,9 @@
|
||||
(define-package "async" "20221217.649" "Asynchronous processing in Emacs"
|
||||
(define-package "async" "20241126.810" "Asynchronous processing in Emacs"
|
||||
'((emacs "24.4"))
|
||||
:commit "c4772bec684776e93f1b8d845b452dc850ee2315" :authors
|
||||
:commit "b99658e831bc7e7d20ed4bb0a85bdb5c7dd74142" :authors
|
||||
'(("John Wiegley" . "jwiegley@gmail.com"))
|
||||
:maintainers
|
||||
'(("Thierry Volpiatto" . "thievol@posteo.net"))
|
||||
:maintainer
|
||||
'("Thierry Volpiatto" . "thievol@posteo.net")
|
||||
:keywords
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
;; Maintainer: Thierry Volpiatto <thievol@posteo.net>
|
||||
|
||||
;; Created: 18 Jun 2012
|
||||
;; Version: 1.9.7
|
||||
;; Version: 1.9.9
|
||||
;; Package-Requires: ((emacs "24.4"))
|
||||
|
||||
;; Keywords: async
|
||||
@@ -34,6 +34,8 @@
|
||||
|
||||
(eval-when-compile (require 'cl-lib))
|
||||
|
||||
(defvar tramp-password-prompt-regexp)
|
||||
|
||||
(defgroup async nil
|
||||
"Simple asynchronous processing in Emacs"
|
||||
:group 'lisp)
|
||||
@@ -42,15 +44,34 @@
|
||||
"Default function to remove text properties in variables."
|
||||
:type 'function)
|
||||
|
||||
(defcustom async-prompt-for-password t
|
||||
"Prompt for password in parent Emacs if needed when non nil.
|
||||
When this is nil child Emacs will hang forever when a user interaction
|
||||
for password is required unless a password is stored in a \".authinfo\" file."
|
||||
:type 'boolean)
|
||||
|
||||
(defvar async-process-noquery-on-exit nil
|
||||
"Used as the :noquery argument to `make-process'.
|
||||
|
||||
Intended to be let-bound around a call to `async-start' or
|
||||
`async-start-process'. If non-nil, the child Emacs process will
|
||||
be silently killed if the user exits the parent Emacs.")
|
||||
|
||||
(defvar async-debug nil)
|
||||
(defvar async-send-over-pipe t)
|
||||
(defvar async-in-child-emacs nil)
|
||||
(defvar async-callback nil)
|
||||
(defvar async-callback-for-process nil)
|
||||
(defvar async-callback-for-process nil
|
||||
"Non-nil if the subprocess is not Emacs executing a lisp form.")
|
||||
(defvar async-callback-value nil)
|
||||
(defvar async-callback-value-set nil)
|
||||
(defvar async-current-process nil)
|
||||
(defvar async--procvar nil)
|
||||
(defvar async-read-marker nil
|
||||
"Position from which we read the last message packet.
|
||||
|
||||
Message packets are delivered from client line-by-line as base64
|
||||
encoded strings.")
|
||||
(defvar async-child-init nil
|
||||
"Initialisation file for async child Emacs.
|
||||
|
||||
@@ -96,14 +117,17 @@ is returned unmodified."
|
||||
collect elm))
|
||||
(t object)))
|
||||
|
||||
(defvar async-inject-variables-exclude-regexps '("-syntax-table\\'")
|
||||
"A list of regexps that `async-inject-variables' should ignore.")
|
||||
|
||||
(defun async-inject-variables
|
||||
(include-regexp &optional predicate exclude-regexp noprops)
|
||||
"Return a `setq' form that replicates part of the calling environment.
|
||||
|
||||
It sets the value for every variable matching INCLUDE-REGEXP and
|
||||
also PREDICATE. It will not perform injection for any variable
|
||||
matching EXCLUDE-REGEXP (if present) or representing a `syntax-table'
|
||||
i.e. ending by \"-syntax-table\".
|
||||
matching EXCLUDE-REGEXP (if present) and variables matching one of
|
||||
`async-inject-variables-exclude-regexps'.
|
||||
When NOPROPS is non nil it tries to strip out text properties of each
|
||||
variable's value with `async-variables-noprops-function'.
|
||||
|
||||
@@ -122,14 +146,16 @@ It is intended to be used as follows:
|
||||
,@(let (bindings)
|
||||
(mapatoms
|
||||
(lambda (sym)
|
||||
(let* ((sname (and (boundp sym) (symbol-name sym)))
|
||||
(value (and sname (symbol-value sym))))
|
||||
(let ((sname (and (boundp sym) (symbol-name sym)))
|
||||
value)
|
||||
(when (and sname
|
||||
(or (null include-regexp)
|
||||
(string-match include-regexp sname))
|
||||
(or (null exclude-regexp)
|
||||
(not (string-match exclude-regexp sname)))
|
||||
(not (string-match "-syntax-table\\'" sname)))
|
||||
(cl-loop for re in async-inject-variables-exclude-regexps
|
||||
never (string-match-p re sname)))
|
||||
(setq value (symbol-value sym))
|
||||
(unless (or (stringp value)
|
||||
(memq value '(nil t))
|
||||
(numberp value)
|
||||
@@ -171,12 +197,16 @@ It is intended to be used as follows:
|
||||
(prog1
|
||||
(funcall async-callback proc)
|
||||
(unless async-debug
|
||||
(kill-buffer (current-buffer))))
|
||||
;; we need to check this because theoretically
|
||||
;; `async-callback' could've killed it already
|
||||
(when (buffer-live-p (process-buffer proc))
|
||||
(kill-buffer (process-buffer proc)))))
|
||||
(set (make-local-variable 'async-callback-value) proc)
|
||||
(set (make-local-variable 'async-callback-value-set) t))
|
||||
;; Maybe strip out unreadable "#"; They are replaced by
|
||||
;; empty string unless they are prefixing a special
|
||||
;; object like a marker. See issue #145.
|
||||
(widen)
|
||||
(goto-char (point-min))
|
||||
(save-excursion
|
||||
;; Transform markers in list like
|
||||
@@ -189,22 +219,80 @@ It is intended to be used as follows:
|
||||
(replace-match "(" t t))
|
||||
(goto-char (point-max))
|
||||
(backward-sexp)
|
||||
(async-handle-result async-callback (read (current-buffer))
|
||||
(current-buffer)))
|
||||
(let ((value (read (current-buffer))))
|
||||
(async-handle-result async-callback value (current-buffer))))
|
||||
(set (make-local-variable 'async-callback-value)
|
||||
(list 'error
|
||||
(format "Async process '%s' failed with exit code %d"
|
||||
(process-name proc) (process-exit-status proc))))
|
||||
(set (make-local-variable 'async-callback-value-set) t))))))
|
||||
|
||||
(defun async-read-from-client (proc string &optional prompt-for-pwd)
|
||||
"Process text from client process.
|
||||
|
||||
The string chunks usually arrive in maximum of 4096 bytes, so a
|
||||
long client message might be split into multiple calls of this
|
||||
function.
|
||||
|
||||
We use a marker `async-read-marker' to track the position of the
|
||||
lasts complete line. Every time we get new input, we try to look
|
||||
for newline, and if found, process the entire line and bump the
|
||||
marker position to the end of this next line.
|
||||
|
||||
Argument PROMPT-FOR-PWD allow binding lexically the value of
|
||||
`async-prompt-for-password', if unspecified its global value
|
||||
is used."
|
||||
(with-current-buffer (process-buffer proc)
|
||||
(when (and prompt-for-pwd
|
||||
(boundp 'tramp-password-prompt-regexp)
|
||||
tramp-password-prompt-regexp
|
||||
(string-match tramp-password-prompt-regexp string))
|
||||
(process-send-string
|
||||
proc (concat (read-passwd (match-string 0 string)) "\n")))
|
||||
(goto-char (point-max))
|
||||
(save-excursion
|
||||
(insert string))
|
||||
|
||||
(while (search-forward "\n" nil t)
|
||||
(save-excursion
|
||||
(save-restriction
|
||||
(widen)
|
||||
(narrow-to-region async-read-marker (point))
|
||||
(goto-char (point-min))
|
||||
(let (msg)
|
||||
(condition-case nil
|
||||
;; It is safe to throw errors in the read because we
|
||||
;; send messages always on their own line, and they
|
||||
;; are always a base64 encoded string, so a message
|
||||
;; will always read. We will also ignore the rest
|
||||
;; of this line since there won't be anything
|
||||
;; interesting.
|
||||
(while (setq msg (read (current-buffer)))
|
||||
(let ((msg-decoded (ignore-errors (base64-decode-string msg))))
|
||||
(when msg-decoded
|
||||
(setq msg-decoded (car (read-from-string msg-decoded)))
|
||||
(when (and (listp msg-decoded)
|
||||
(async-message-p msg-decoded)
|
||||
async-callback)
|
||||
(funcall async-callback msg-decoded)))))
|
||||
;; This is OK, we reached the end of the chunk subprocess sent
|
||||
;; at this time.
|
||||
(invalid-read-syntax t)
|
||||
(end-of-file t)))
|
||||
(goto-char (point-max))
|
||||
(move-marker async-read-marker (point)))))))
|
||||
|
||||
(defun async--receive-sexp (&optional stream)
|
||||
;; FIXME: Why use `utf-8-auto' instead of `utf-8-unix'? This is
|
||||
;; a communication channel over which we have complete control,
|
||||
;; so we get to choose exactly which encoding and EOL we use, isn't it?
|
||||
;; so we get to choose exactly which encoding and EOL we use, isn't
|
||||
;; it?
|
||||
;; UPDATE: We use now `utf-8-emacs-unix' instead of `utf-8-auto' as
|
||||
;; recommended in bug#165.
|
||||
(let ((sexp (decode-coding-string (base64-decode-string (read stream))
|
||||
'utf-8-auto))
|
||||
'utf-8-emacs-unix))
|
||||
;; Parent expects UTF-8 encoded text.
|
||||
(coding-system-for-write 'utf-8-auto))
|
||||
(coding-system-for-write 'utf-8-emacs-unix))
|
||||
(if async-debug
|
||||
(message "Received sexp {{{%s}}}" (pp-to-string sexp)))
|
||||
(setq sexp (read sexp))
|
||||
@@ -221,7 +309,7 @@ It is intended to be used as follows:
|
||||
(print-symbols-bare t))
|
||||
(prin1 sexp (current-buffer))
|
||||
;; Just in case the string we're sending might contain EOF
|
||||
(encode-coding-region (point-min) (point-max) 'utf-8-auto)
|
||||
(encode-coding-region (point-min) (point-max) 'utf-8-emacs-unix)
|
||||
(base64-encode-region (point-min) (point-max) t)
|
||||
(goto-char (point-min)) (insert ?\")
|
||||
(goto-char (point-max)) (insert ?\" ?\n)))
|
||||
@@ -237,17 +325,27 @@ It is intended to be used as follows:
|
||||
"Called from the child Emacs process' command line."
|
||||
;; Make sure 'message' and 'prin1' encode stuff in UTF-8, as parent
|
||||
;; process expects.
|
||||
(let ((coding-system-for-write 'utf-8-auto)
|
||||
(let ((coding-system-for-write 'utf-8-emacs-unix)
|
||||
(args-left command-line-args-left))
|
||||
(setq async-in-child-emacs t
|
||||
debug-on-error async-debug
|
||||
command-line-args-left nil)
|
||||
(condition-case-unless-debug err
|
||||
(prin1 (funcall
|
||||
(async--receive-sexp (unless async-send-over-pipe
|
||||
args-left))))
|
||||
(let ((ret (funcall
|
||||
(async--receive-sexp (unless async-send-over-pipe
|
||||
args-left)))))
|
||||
;; The newlines makes client messages more robust and also
|
||||
;; handle some weird line-buffering issues on windows.
|
||||
;; Sometimes, the last "chunk" was not read by the filter,
|
||||
;; so a newline here should force a buffer flush.
|
||||
(princ "\n")
|
||||
(prin1 ret)
|
||||
(princ "\n"))
|
||||
(error
|
||||
(prin1 (list 'async-signal err))))))
|
||||
(progn
|
||||
(princ "\n")
|
||||
(prin1 (list 'async-signal err))
|
||||
(princ "\n"))))))
|
||||
|
||||
(defun async-ready (future)
|
||||
"Query a FUTURE to see if it is ready.
|
||||
@@ -277,20 +375,51 @@ its FINISH-FUNC is nil."
|
||||
#'identity async-callback-value (current-buffer))))))
|
||||
|
||||
(defun async-message-p (value)
|
||||
"Return non-nil of VALUE is an async.el message packet."
|
||||
"Return non-nil if VALUE is an async.el message packet."
|
||||
(and (listp value)
|
||||
(plist-get value :async-message)))
|
||||
|
||||
(defun async-send (&rest args)
|
||||
"Send the given messages to the asychronous Emacs PROCESS."
|
||||
(defun async-send (process-or-key &rest args)
|
||||
"Send the given message to the asynchronous child or parent Emacs.
|
||||
|
||||
To send messages from the parent to a child, PROCESS-OR-KEY is
|
||||
the child process object. ARGS is a plist. Example:
|
||||
|
||||
(async-send proc :operation :load-file :file \"this file\")
|
||||
|
||||
To send messages from the child to the parent, PROCESS-OR-KEY is
|
||||
the first key of the plist, ARGS is a value followed by
|
||||
optionally more key-value pairs. Example:
|
||||
|
||||
(async-send :status \"finished\" :file-size 123)"
|
||||
(let ((args (append args '(:async-message t))))
|
||||
(if async-in-child-emacs
|
||||
(if async-callback
|
||||
(funcall async-callback args))
|
||||
(async--transmit-sexp (car args) (list 'quote (cdr args))))))
|
||||
;; `princ' because async--insert-sexp already quotes everything.
|
||||
(princ
|
||||
(with-temp-buffer
|
||||
(async--insert-sexp (cons process-or-key args))
|
||||
;; always make sure that one message package has its own
|
||||
;; line as there can be any random debug garbage printed
|
||||
;; above it.
|
||||
(concat "\n" (buffer-string))))
|
||||
(async--transmit-sexp process-or-key (list 'quote args)))))
|
||||
|
||||
(defun async-receive ()
|
||||
"Send the given messages to the asychronous Emacs PROCESS."
|
||||
"Receive message from parent Emacs.
|
||||
|
||||
The child process blocks until a message is received.
|
||||
|
||||
Message is a plist with one key :async-message set to t always
|
||||
automatically added to signify this plist is an async message.
|
||||
|
||||
You can use `async-message-p' to test if the payload was a
|
||||
message.
|
||||
|
||||
Use
|
||||
|
||||
(let ((msg (async-receive))) ...)
|
||||
|
||||
to read and process a message."
|
||||
(async--receive-sexp))
|
||||
|
||||
;;;###autoload
|
||||
@@ -302,11 +431,31 @@ object will return the process object when the program is
|
||||
finished. Set DEFAULT-DIRECTORY to change PROGRAM's current
|
||||
working directory."
|
||||
(let* ((buf (generate-new-buffer (concat "*" name "*")))
|
||||
(buf-err (generate-new-buffer (concat "*" name ":err*")))
|
||||
(prt-for-pwd async-prompt-for-password)
|
||||
(proc (let ((process-connection-type nil))
|
||||
(apply #'start-process name buf program program-args))))
|
||||
(make-process
|
||||
:name name
|
||||
:buffer buf
|
||||
:stderr buf-err
|
||||
:command (cons program program-args)
|
||||
:noquery async-process-noquery-on-exit))))
|
||||
(set-process-sentinel
|
||||
(get-buffer-process buf-err)
|
||||
(lambda (proc _change)
|
||||
(unless (or async-debug (process-live-p proc))
|
||||
(kill-buffer (process-buffer proc)))))
|
||||
(with-current-buffer buf
|
||||
(set (make-local-variable 'async-callback) finish-func)
|
||||
(set (make-local-variable 'async-read-marker)
|
||||
(set-marker (make-marker) (point-min) buf))
|
||||
(set-marker-insertion-type async-read-marker nil)
|
||||
(set-process-sentinel proc #'async-when-done)
|
||||
;; Pass the value of `async-prompt-for-password' to the process
|
||||
;; filter fn through the lexical local var prt-for-pwd (Issue#182).
|
||||
(set-process-filter proc (lambda (proc string)
|
||||
(async-read-from-client
|
||||
proc string prt-for-pwd)))
|
||||
(unless (string= name "emacs")
|
||||
(set (make-local-variable 'async-callback-for-process) t))
|
||||
proc)))
|
||||
@@ -317,11 +466,20 @@ Can be one of \"-Q\" or \"-q\".
|
||||
Default is \"-Q\" but it is sometimes useful to use \"-q\" to have a
|
||||
enhanced config or some more variables loaded.")
|
||||
|
||||
(defvar async-library nil
|
||||
"Cache async library path.
|
||||
It is useful only when you run multiple async processes in a loop, to
|
||||
avoid calling many times `locate-library' which is costly.
|
||||
This variable should be let bound around an `async-start' call and not
|
||||
used globally. Should be found with `locate-library'.")
|
||||
|
||||
(defun async--emacs-program-args (&optional sexp)
|
||||
"Return a list of arguments for invoking the child Emacs."
|
||||
;; Using `locate-library' ensure we use the right file
|
||||
;; when the .elc have been deleted.
|
||||
(let ((args (list async-quiet-switch "-l" (locate-library "async"))))
|
||||
;; when the .elc have been deleted, its result can be cached in
|
||||
;; `async-library' see Issue#193.
|
||||
(let ((args (list async-quiet-switch "-l" (or async-library
|
||||
(locate-library "async")))))
|
||||
(when async-child-init
|
||||
(setq args (append args (list "-l" async-child-init))))
|
||||
(append args (list "-batch" "-f" "async-batch-invoke"
|
||||
@@ -348,6 +506,16 @@ When done, the return value is passed to FINISH-FUNC. Example:
|
||||
(message \"Async process done, result should be 222: %s\"
|
||||
result)))
|
||||
|
||||
If you call `async-send' from a child process, the message will
|
||||
be also passed to the FINISH-FUNC. You can test RESULT to see if
|
||||
it is a message by using `async-message-p'. If nil, it means
|
||||
this is the final result. Example of the FINISH-FUNC:
|
||||
|
||||
(lambda (result)
|
||||
(if (async-message-p result)
|
||||
(message \"Received a message from child process: %s\" result)
|
||||
(message \"Async process done, result: %s\" result)))
|
||||
|
||||
If FINISH-FUNC is nil or missing, a future is returned that can
|
||||
be inspected using `async-get', blocking until the value is
|
||||
ready. Example:
|
||||
@@ -392,7 +560,7 @@ returns nil. It can still be useful, however, as an argument to
|
||||
`async-ready' or `async-wait'."
|
||||
(let ((sexp start-func)
|
||||
;; Subordinate Emacs will send text encoded in UTF-8.
|
||||
(coding-system-for-read 'utf-8-auto))
|
||||
(coding-system-for-read 'utf-8-emacs-unix))
|
||||
(setq async--procvar
|
||||
(apply 'async-start-process
|
||||
"emacs" (file-truename
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
;; Thierry Volpiatto <thievol@posteo.net>
|
||||
|
||||
;; Keywords: dired async network
|
||||
;; X-URL: https://github.com/jwiegley/dired-async
|
||||
;; X-URL: https://github.com/jwiegley/emacs-async
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
@@ -81,6 +81,10 @@ or rename for `dired-async-skip-fast'."
|
||||
:risky t
|
||||
:type 'integer)
|
||||
|
||||
(defcustom dired-async-large-file-warning-threshold large-file-warning-threshold
|
||||
"Same as `large-file-warning-threshold' but for dired-async."
|
||||
:type 'integer)
|
||||
|
||||
(defface dired-async-message
|
||||
'((t (:foreground "yellow")))
|
||||
"Face used for mode-line message.")
|
||||
@@ -115,9 +119,9 @@ or rename for `dired-async-skip-fast'."
|
||||
(sit-for 3)
|
||||
(force-mode-line-update)))
|
||||
|
||||
(defun dired-async-processes ()
|
||||
(defun dired-async-processes (&optional propname)
|
||||
(cl-loop for p in (process-list)
|
||||
when (process-get p 'dired-async-process)
|
||||
when (process-get p (or propname 'dired-async-process))
|
||||
collect p))
|
||||
|
||||
(defun dired-async-kill-process ()
|
||||
@@ -242,6 +246,14 @@ cases if `dired-async-skip-fast' is non-nil."
|
||||
(funcall old-func file-creator operation
|
||||
(nreverse quick-list) name-constructor marker-char))))
|
||||
|
||||
(defun dired-async--abort-if-file-too-large (size op-type filename)
|
||||
"Warn when FILENAME larger than `dired-async-large-file-warning-threshold'.
|
||||
Same as `abort-if-file-too-large' but without user-error."
|
||||
(when (and dired-async-large-file-warning-threshold size
|
||||
(> size dired-async-large-file-warning-threshold))
|
||||
(files--ask-user-about-large-file
|
||||
size op-type filename nil)))
|
||||
|
||||
(defvar overwrite-query)
|
||||
(defun dired-async-create-files (file-creator operation fn-list name-constructor
|
||||
&optional _marker-char)
|
||||
@@ -251,7 +263,7 @@ See `dired-create-files' for the behavior of arguments."
|
||||
(setq overwrite-query nil)
|
||||
(let ((total (length fn-list))
|
||||
failures async-fn-list skipped callback
|
||||
async-quiet-switch)
|
||||
async-quiet-switch create-dir)
|
||||
(let (to)
|
||||
(dolist (from fn-list)
|
||||
(setq to (funcall name-constructor from))
|
||||
@@ -299,14 +311,22 @@ ESC or `q' to not overwrite any of the remaining files,
|
||||
(file-in-directory-p destname from)
|
||||
(error "Cannot copy `%s' into its subdirectory `%s'"
|
||||
from to)))
|
||||
(if overwrite
|
||||
(or (and dired-overwrite-confirmed
|
||||
(push (cons from to) async-fn-list))
|
||||
(progn
|
||||
(push (dired-make-relative from) failures)
|
||||
(dired-log "%s `%s' to `%s' failed\n"
|
||||
operation from to)))
|
||||
(push (cons from to) async-fn-list)))))
|
||||
;; Skip file if it is too large.
|
||||
(if (and (member operation '("Copy" "Rename"))
|
||||
(eq (dired-async--abort-if-file-too-large
|
||||
(file-attribute-size
|
||||
(file-attributes (file-truename from)))
|
||||
(downcase operation) from)
|
||||
'abort))
|
||||
(push from skipped)
|
||||
(if overwrite
|
||||
(or (and dired-overwrite-confirmed
|
||||
(push (cons from to) async-fn-list))
|
||||
(progn
|
||||
(push (dired-make-relative from) failures)
|
||||
(dired-log "%s `%s' to `%s' failed\n"
|
||||
operation from to)))
|
||||
(push (cons from to) async-fn-list))))))
|
||||
;; Fix tramp issue #80 with emacs-26, use "-q" only when needed.
|
||||
(setq async-quiet-switch
|
||||
(if (and (boundp 'tramp-cache-read-persistent-data)
|
||||
@@ -344,16 +364,31 @@ ESC or `q' to not overwrite any of the remaining files,
|
||||
for destp = (file-exists-p to)
|
||||
do (and bf destp
|
||||
(with-current-buffer bf
|
||||
(set-visited-file-name to t t))))))))
|
||||
(set-visited-file-name to t t)))))))
|
||||
(let ((dirp (file-directory-p to))
|
||||
(dest (file-name-directory to)))
|
||||
(when (boundp 'dired-create-destination-dirs)
|
||||
(setq create-dir
|
||||
(cl-case dired-create-destination-dirs
|
||||
(always 'always)
|
||||
(ask (and (null dirp)
|
||||
(null (file-directory-p dest))
|
||||
(y-or-n-p (format "Create directory `%s'? " dest)))
|
||||
'always))))))
|
||||
;; Start async process.
|
||||
(when async-fn-list
|
||||
(process-put
|
||||
(async-start `(lambda ()
|
||||
(require 'cl-lib) (require 'dired-aux) (require 'dired-x)
|
||||
,(async-inject-variables dired-async-env-variables-regexp)
|
||||
(advice-add #'files--ask-user-about-large-file
|
||||
:override (lambda (&rest args) nil))
|
||||
(let ((dired-recursive-copies (quote always))
|
||||
(dired-copy-preserve-time
|
||||
,dired-copy-preserve-time))
|
||||
,dired-copy-preserve-time)
|
||||
(dired-create-destination-dirs ',create-dir)
|
||||
(dired-vc-rename-file ,dired-vc-rename-file)
|
||||
auth-source-save-behavior)
|
||||
(setq overwrite-backup-query nil)
|
||||
;; Inline `backup-file' as long as it is not
|
||||
;; available in emacs.
|
||||
|
||||
15
lisp/avy/avy-pkg.el
Normal file
15
lisp/avy/avy-pkg.el
Normal file
@@ -0,0 +1,15 @@
|
||||
(define-package "avy" "20241101.1357" "Jump to arbitrary positions in visible text and select text quickly."
|
||||
'((emacs "24.1")
|
||||
(cl-lib "0.5"))
|
||||
:commit "933d1f36cca0f71e4acb5fac707e9ae26c536264" :authors
|
||||
'(("Oleh Krehel" . "ohwoeowho@gmail.com"))
|
||||
:maintainers
|
||||
'(("Oleh Krehel" . "ohwoeowho@gmail.com"))
|
||||
:maintainer
|
||||
'("Oleh Krehel" . "ohwoeowho@gmail.com")
|
||||
:keywords
|
||||
'("point" "location")
|
||||
:url "https://github.com/abo-abo/avy")
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
;; End:
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
;; Author: Oleh Krehel <ohwoeowho@gmail.com>
|
||||
;; URL: https://github.com/abo-abo/avy
|
||||
;; Package-Version: 20220910.1936
|
||||
;; Package-Commit: 955c8dedd68c74f3cf692c1249513f048518c4c9
|
||||
;; Version: 0.5.0
|
||||
;; Package-Requires: ((emacs "24.1") (cl-lib "0.5"))
|
||||
;; Keywords: point, location
|
||||
@@ -28,22 +26,22 @@
|
||||
;;; Commentary:
|
||||
;;
|
||||
;; With Avy, you can move point to any position in Emacs – even in a
|
||||
;; different window – using very few keystrokes. For this, you look at
|
||||
;; different window – using very few keystrokes. For this, you look at
|
||||
;; the position where you want point to be, invoke Avy, and then enter
|
||||
;; the sequence of characters displayed at that position.
|
||||
;;
|
||||
;; If the position you want to jump to can be determined after only
|
||||
;; issuing a single keystroke, point is moved to the desired position
|
||||
;; immediately after that keystroke. In case this isn't possible, the
|
||||
;; immediately after that keystroke. In case this isn't possible, the
|
||||
;; sequence of keystrokes you need to enter is comprised of more than
|
||||
;; one character. Avy uses a decision tree where each candidate position
|
||||
;; one character. Avy uses a decision tree where each candidate position
|
||||
;; is a leaf and each edge is described by a character which is distinct
|
||||
;; per level of the tree. By entering those characters, you navigate the
|
||||
;; per level of the tree. By entering those characters, you navigate the
|
||||
;; tree, quickly arriving at the desired candidate position, such that
|
||||
;; Avy can move point to it.
|
||||
;;
|
||||
;; Note that this only makes sense for positions you are able to see
|
||||
;; when invoking Avy. These kinds of positions are supported:
|
||||
;; when invoking Avy. These kinds of positions are supported:
|
||||
;;
|
||||
;; * character positions
|
||||
;; * word or subword start positions
|
||||
@@ -101,7 +99,7 @@ keys different than the following: a, e, i, o, u, y"
|
||||
(function :tag "Other command")))
|
||||
|
||||
(defcustom avy-keys-alist nil
|
||||
"Alist of avy-jump commands to `avy-keys' overriding the default `avy-keys'."
|
||||
"Alist of `avy-jump' commands to `avy-keys' overriding the default `avy-keys'."
|
||||
:type `(alist
|
||||
:key-type ,avy--key-type
|
||||
:value-type (repeat :tag "Keys" character)))
|
||||
@@ -158,27 +156,27 @@ Use `avy-styles-alist' to customize this per-command."
|
||||
(const :tag "Words" words)))
|
||||
|
||||
(defcustom avy-styles-alist nil
|
||||
"Alist of avy-jump commands to the style for each command.
|
||||
"Alist of `avy-jump' commands to the style for each command.
|
||||
If the commands isn't on the list, `avy-style' is used."
|
||||
:type '(alist
|
||||
:key-type (choice :tag "Command"
|
||||
(const avy-goto-char)
|
||||
(const avy-goto-char-2)
|
||||
(const avy-isearch)
|
||||
(const avy-goto-line)
|
||||
(const avy-goto-subword-0)
|
||||
(const avy-goto-subword-1)
|
||||
(const avy-goto-word-0)
|
||||
(const avy-goto-word-1)
|
||||
(const avy-copy-line)
|
||||
(const avy-copy-region)
|
||||
(const avy-move-line)
|
||||
(const avy-move-region)
|
||||
(const avy-kill-whole-line)
|
||||
(const avy-kill-region)
|
||||
(const avy-kill-ring-save-whole-line)
|
||||
(const avy-kill-ring-save-region)
|
||||
(function :tag "Other command"))
|
||||
(const avy-goto-char)
|
||||
(const avy-goto-char-2)
|
||||
(const avy-isearch)
|
||||
(const avy-goto-line)
|
||||
(const avy-goto-subword-0)
|
||||
(const avy-goto-subword-1)
|
||||
(const avy-goto-word-0)
|
||||
(const avy-goto-word-1)
|
||||
(const avy-copy-line)
|
||||
(const avy-copy-region)
|
||||
(const avy-move-line)
|
||||
(const avy-move-region)
|
||||
(const avy-kill-whole-line)
|
||||
(const avy-kill-region)
|
||||
(const avy-kill-ring-save-whole-line)
|
||||
(const avy-kill-ring-save-region)
|
||||
(function :tag "Other command"))
|
||||
:value-type (choice
|
||||
(const :tag "Pre" pre)
|
||||
(const :tag "At" at)
|
||||
@@ -397,7 +395,7 @@ SEQ-LEN is how many elements of KEYS it takes to identify a match."
|
||||
|
||||
(defvar avy-command nil
|
||||
"Store the current command symbol.
|
||||
E.g. 'avy-goto-line or 'avy-goto-char.")
|
||||
E.g. `avy-goto-line' or `avy-goto-char'.")
|
||||
|
||||
(defun avy-tree (lst keys)
|
||||
"Coerce LST into a balanced tree.
|
||||
@@ -840,11 +838,11 @@ Set `avy-style' according to COMMAND as well."
|
||||
avy-last-candidates))
|
||||
(min-dist
|
||||
(apply #'min
|
||||
(mapcar (lambda (x) (abs (- (caar x) (point)))) avy-last-candidates)))
|
||||
(mapcar (lambda (x) (abs (- (if (listp (car x)) (caar x) (car x)) (point)))) avy-last-candidates)))
|
||||
(pos
|
||||
(cl-position-if
|
||||
(lambda (x)
|
||||
(= (- (caar x) (point)) min-dist))
|
||||
(= (- (if (listp (car x)) (caar x) (car x)) (point)) min-dist))
|
||||
avy-last-candidates)))
|
||||
(funcall advancer pos avy-last-candidates)))
|
||||
|
||||
@@ -854,7 +852,8 @@ Set `avy-style' according to COMMAND as well."
|
||||
(avy--last-candidates-cycle
|
||||
(lambda (pos lst)
|
||||
(when (> pos 0)
|
||||
(goto-char (caar (nth (1- pos) lst)))))))
|
||||
(let ((candidate (nth (1- pos) lst)))
|
||||
(goto-char (if (listp (car candidate)) (caar candidate) (car candidate))))))))
|
||||
|
||||
(defun avy-next ()
|
||||
"Go to the next candidate of the last `avy-read'."
|
||||
@@ -862,7 +861,8 @@ Set `avy-style' according to COMMAND as well."
|
||||
(avy--last-candidates-cycle
|
||||
(lambda (pos lst)
|
||||
(when (< pos (1- (length lst)))
|
||||
(goto-char (caar (nth (1+ pos) lst)))))))
|
||||
(let ((candidate (nth (1+ pos) lst)))
|
||||
(goto-char (if (listp (car candidate)) (caar candidate) (car candidate))))))))
|
||||
|
||||
;;;###autoload
|
||||
(defun avy-process (candidates &optional overlay-fn cleanup-fn)
|
||||
@@ -935,14 +935,14 @@ multiple OVERLAY-FN invocations."
|
||||
(null (assoc invisible buffer-invisibility-spec)))))
|
||||
|
||||
(defun avy--next-visible-point ()
|
||||
"Return the next closest point without 'invisible property."
|
||||
"Return the next closest point without `invisible' property."
|
||||
(let ((s (point)))
|
||||
(while (and (not (= (point-max) (setq s (next-char-property-change s))))
|
||||
(not (avy--visible-p s))))
|
||||
s))
|
||||
|
||||
(defun avy--next-invisible-point ()
|
||||
"Return the next closest point with 'invisible property."
|
||||
"Return the next closest point with `invisible' property."
|
||||
(let ((s (point)))
|
||||
(while (and (not (= (point-max) (setq s (next-char-property-change s))))
|
||||
(avy--visible-p s)))
|
||||
@@ -1666,6 +1666,7 @@ When BOTTOM-UP is non-nil, display avy candidates from top to bottom"
|
||||
(defvar linum-overlays)
|
||||
(defvar linum-format)
|
||||
(declare-function linum--face-width "linum")
|
||||
(declare-function linum-mode "linum")
|
||||
|
||||
(define-minor-mode avy-linum-mode
|
||||
"Minor mode that uses avy hints for `linum-mode'."
|
||||
17
lisp/biblio-core/biblio-core-pkg.el
Normal file
17
lisp/biblio-core/biblio-core-pkg.el
Normal file
@@ -0,0 +1,17 @@
|
||||
(define-package "biblio-core" "20230202.1721" "A framework for looking up and displaying bibliographic entries"
|
||||
'((emacs "24.3")
|
||||
(let-alist "1.0.4")
|
||||
(seq "1.11")
|
||||
(dash "2.12.1"))
|
||||
:commit "ee52f6cda82ea6fbc3b400e7b12132595cc0374c" :authors
|
||||
'(("Clément Pit-Claudel" . "clement.pitclaudel@live.com"))
|
||||
:maintainers
|
||||
'(("Clément Pit-Claudel" . "clement.pitclaudel@live.com"))
|
||||
:maintainer
|
||||
'("Clément Pit-Claudel" . "clement.pitclaudel@live.com")
|
||||
:keywords
|
||||
'("bib" "tex" "convenience" "hypermedia")
|
||||
:url "https://github.com/cpitclaudel/biblio.el")
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
;; End:
|
||||
@@ -3,9 +3,7 @@
|
||||
;; Copyright (C) 2016 Clément Pit-Claudel
|
||||
|
||||
;; Author: Clément Pit-Claudel <clement.pitclaudel@live.com>
|
||||
;; Version: 0.2.1
|
||||
;; Package-Version: 20210418.406
|
||||
;; Package-Commit: 517ec18f00f91b61481214b178f7ae0b8fbc499b
|
||||
;; Version: 0.3
|
||||
;; Package-Requires: ((emacs "24.3") (let-alist "1.0.4") (seq "1.11") (dash "2.12.1"))
|
||||
;; Keywords: bib, tex, convenience, hypermedia
|
||||
;; URL: https://github.com/cpitclaudel/biblio.el
|
||||
@@ -215,7 +213,7 @@ URL and CALLBACK; see `url-queue-retrieve'"
|
||||
(if biblio-synchronous
|
||||
(with-current-buffer (url-retrieve-synchronously url)
|
||||
(funcall callback nil))
|
||||
(setq url-queue-timeout 1)
|
||||
(setq url-queue-timeout 5)
|
||||
(url-queue-retrieve url callback)))
|
||||
|
||||
(defun biblio-strip (str)
|
||||
@@ -485,7 +483,10 @@ will be called with the metadata of the current item.")
|
||||
|
||||
(defun biblio--completing-read-function ()
|
||||
"Return ido, unless user picked another completion package."
|
||||
(if (eq completing-read-function #'completing-read-default)
|
||||
(if (and (eq completing-read-function #'completing-read-default)
|
||||
(not (catch 'advised ;; https://github.com/cpitclaudel/biblio.el/issues/55
|
||||
(advice-mapc (lambda (&rest _args) (throw 'advised t))
|
||||
'completing-read-default))))
|
||||
#'ido-completing-read
|
||||
completing-read-function))
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
(define-package "biblio" "20210418.406" "Browse and import bibliographic references from CrossRef, arXiv, DBLP, HAL, Dissemin, and doi.org"
|
||||
(define-package "biblio" "20250102.1345" "Browse and import bibliographic references and BibTeX records from CrossRef, arXiv, DBLP, HAL, IEEE Xplore, Dissemin, and doi.org"
|
||||
'((emacs "24.3")
|
||||
(biblio-core "0.2"))
|
||||
:commit "368f45bf9a64450705a63598224c5af96160af76" :authors
|
||||
(biblio-core "0.3"))
|
||||
:commit "b700f0f2929829b2ca971511c5ebe61c67027e9f" :authors
|
||||
'(("Clément Pit-Claudel" . "clement.pitclaudel@live.com"))
|
||||
:maintainers
|
||||
'(("Clément Pit-Claudel" . "clement.pitclaudel@live.com"))
|
||||
:maintainer
|
||||
'("Clément Pit-Claudel" . "clement.pitclaudel@live.com")
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
;; Copyright (C) 2016 Clément Pit-Claudel
|
||||
|
||||
;; Author: Clément Pit-Claudel <clement.pitclaudel@live.com>
|
||||
;; Version: 0.2
|
||||
;; Package-Requires: ((emacs "24.3") (biblio-core "0.2"))
|
||||
;; Version: 0.3
|
||||
;; Package-Requires: ((emacs "24.3") (biblio-core "0.3"))
|
||||
;; Keywords: bib, tex, convenience, hypermedia
|
||||
;; URL: https://github.com/cpitclaudel/biblio.el
|
||||
|
||||
|
||||
19
lisp/bibtex-completion/bibtex-completion-pkg.el
Normal file
19
lisp/bibtex-completion/bibtex-completion-pkg.el
Normal file
@@ -0,0 +1,19 @@
|
||||
(define-package "bibtex-completion" "20241116.726" "A BibTeX backend for completion frameworks"
|
||||
'((parsebib "6.0")
|
||||
(s "1.9.0")
|
||||
(dash "2.6.0")
|
||||
(f "0.16.2")
|
||||
(cl-lib "0.5")
|
||||
(biblio "0.2")
|
||||
(emacs "26.1"))
|
||||
:commit "6064e8625b2958f34d6d40312903a85c173b5261" :authors
|
||||
'(("Titus von der Malsburg" . "malsburg@posteo.de")
|
||||
("Justin Burkett" . "justin@burkett.cc"))
|
||||
:maintainers
|
||||
'(("Titus von der Malsburg" . "malsburg@posteo.de"))
|
||||
:maintainer
|
||||
'("Titus von der Malsburg" . "malsburg@posteo.de")
|
||||
:url "https://github.com/tmalsburg/helm-bibtex")
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
;; End:
|
||||
@@ -4,10 +4,8 @@
|
||||
;; Justin Burkett <justin@burkett.cc>
|
||||
;; Maintainer: Titus von der Malsburg <malsburg@posteo.de>
|
||||
;; URL: https://github.com/tmalsburg/helm-bibtex
|
||||
;; Package-Version: 20221024.857
|
||||
;; Package-Commit: 78f5931e1cc82e7ae2bcf0508cf31d0d1629a8dd
|
||||
;; Version: 1.0.0
|
||||
;; Package-Requires: ((parsebib "1.0") (s "1.9.0") (dash "2.6.0") (f "0.16.2") (cl-lib "0.5") (biblio "0.2") (emacs "26.1"))
|
||||
;; Package-Requires: ((parsebib "6.0") (s "1.9.0") (dash "2.6.0") (f "0.16.2") (cl-lib "0.5") (biblio "0.2") (emacs "26.1"))
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
@@ -79,6 +77,20 @@ composed of the BibTeX-key plus a \".pdf\" suffix."
|
||||
:group 'bibtex-completion
|
||||
:type '(choice directory (repeat directory)))
|
||||
|
||||
;; From https://github.com/mwlodarczak/helm-bibtex/commit/4a421cae9b7d4cdb4a0933080633564b1774addb
|
||||
(defcustom bibtex-completion-watch-bibliography t
|
||||
"If non-nil (the default) the bibliography is reloaded
|
||||
proactively every time any of the BibTeX files changes.
|
||||
Changing the value of this variable after you load helm-bibtex
|
||||
has no effect: if you load helm-bibtex with this variable
|
||||
set to t and then decide you do not want to proactively reload the
|
||||
bibliography, you have to restart Emacs with the new setting
|
||||
(and likewise for loading helm-bibtex with the variable set to nil
|
||||
and later deciding you want to proactively reload the bibliography)."
|
||||
:group 'bibtex-completion
|
||||
:type 'boolean)
|
||||
|
||||
|
||||
(defcustom bibtex-completion-pdf-open-function 'find-file
|
||||
"The function used for opening PDF files.
|
||||
This can be an arbitrary function that takes one argument: the
|
||||
@@ -116,6 +128,7 @@ This should be a single character."
|
||||
(defcustom bibtex-completion-format-citation-functions
|
||||
'((org-mode . bibtex-completion-format-citation-ebib)
|
||||
(latex-mode . bibtex-completion-format-citation-cite)
|
||||
(LaTeX-mode . bibtex-completion-format-citation-cite)
|
||||
(markdown-mode . bibtex-completion-format-citation-pandoc-citeproc)
|
||||
(python-mode . bibtex-completion-format-citation-sphinxcontrib-bibtex)
|
||||
(rst-mode . bibtex-completion-format-citation-sphinxcontrib-bibtex)
|
||||
@@ -282,6 +295,7 @@ browser in `helm-browse-url-default-browser-alist'"
|
||||
"Autocite" "autocite*" "Autocite*" "citeauthor" "Citeauthor"
|
||||
"citeauthor*" "Citeauthor*" "citetitle" "citetitle*" "citeyear"
|
||||
"citeyear*" "citedate" "citedate*" "citeurl" "nocite" "fullcite"
|
||||
"citet" "citep" "citet*" "citep*"
|
||||
"footfullcite" "notecite" "Notecite" "pnotecite" "Pnotecite"
|
||||
"fnotecite")
|
||||
"The list of LaTeX cite commands.
|
||||
@@ -416,15 +430,16 @@ Also sets `bibtex-completion-display-formats-internal'."
|
||||
;; watches for automatic reloading of the bibliography when a file
|
||||
;; is changed:
|
||||
(mapc (lambda (file)
|
||||
(if (f-file? file)
|
||||
(let ((watch-descriptor
|
||||
(file-notify-add-watch file
|
||||
'(change)
|
||||
(lambda (event) (bibtex-completion-candidates)))))
|
||||
(setq bibtex-completion-file-watch-descriptors
|
||||
(cons watch-descriptor bibtex-completion-file-watch-descriptors)))
|
||||
(if (f-file? file)
|
||||
(if bibtex-completion-watch-bibliography
|
||||
(let ((watch-descriptor
|
||||
(file-notify-add-watch file
|
||||
'(change)
|
||||
(lambda (event) (bibtex-completion-candidates)))))
|
||||
(setq bibtex-completion-file-watch-descriptors
|
||||
(cons watch-descriptor bibtex-completion-file-watch-descriptors))))
|
||||
(user-error "Bibliography file %s could not be found" file)))
|
||||
(bibtex-completion-normalize-bibliography))
|
||||
(bibtex-completion-normalize-bibliography))
|
||||
|
||||
;; Pre-calculate minimal widths needed by the format strings for
|
||||
;; various entry types:
|
||||
@@ -479,9 +494,10 @@ for string replacement."
|
||||
for entry-type = (parsebib-find-next-item)
|
||||
while entry-type
|
||||
if (string= (downcase entry-type) "string")
|
||||
collect (let ((entry (parsebib-read-string (point) ht)))
|
||||
collect (let ((entry (parsebib-read-string ht)))
|
||||
(puthash (car entry) (cdr entry) ht)
|
||||
entry))))
|
||||
entry)
|
||||
else do (forward-line 1))))
|
||||
(-filter (lambda (x) x) strings)))
|
||||
|
||||
(defun bibtex-completion-update-strings-ht (ht strings)
|
||||
@@ -669,8 +685,8 @@ If HT-STRINGS is provided it is assumed to be a hash table."
|
||||
bibtex-completion-additional-search-fields))
|
||||
for entry-type = (parsebib-find-next-item)
|
||||
while entry-type
|
||||
unless (member-ignore-case entry-type '("preamble" "string" "comment"))
|
||||
collect (let* ((entry (parsebib-read-entry entry-type (point) ht-strings))
|
||||
if (not (member-ignore-case entry-type '("preamble" "string" "comment")))
|
||||
collect (let* ((entry (parsebib-read-entry nil ht-strings))
|
||||
(fields (append
|
||||
(list (if (assoc-string "author" entry 'case-fold)
|
||||
"author"
|
||||
@@ -681,7 +697,8 @@ If HT-STRINGS is provided it is assumed to be a hash table."
|
||||
fields)))
|
||||
(-map (lambda (it)
|
||||
(cons (downcase (car it)) (cdr it)))
|
||||
(bibtex-completion-prepare-entry entry fields)))))
|
||||
(bibtex-completion-prepare-entry entry fields)))
|
||||
else do (forward-line 1)))
|
||||
|
||||
(defun bibtex-completion-get-entry (entry-key)
|
||||
"Given a BibTeX key this function scans all bibliographies listed in `bibtex-completion-bibliography' and returns an alist of the record with that key.
|
||||
@@ -700,9 +717,10 @@ Fields from crossreferenced entries are appended to the requested entry."
|
||||
"\\)[[:space:]]*[\(\{][[:space:]]*"
|
||||
(regexp-quote entry-key) "[[:space:]]*,")
|
||||
nil t)
|
||||
(let ((entry-type (match-string 1)))
|
||||
(progn
|
||||
(goto-char (match-beginning 0))
|
||||
(reverse (bibtex-completion-prepare-entry
|
||||
(parsebib-read-entry entry-type (point) bibtex-completion-string-hash-table) nil do-not-find-pdf)))
|
||||
(parsebib-read-entry nil bibtex-completion-string-hash-table) nil do-not-find-pdf)))
|
||||
(progn
|
||||
(display-warning :warning (concat "Bibtex-completion couldn't find entry with key \"" entry-key "\"."))
|
||||
nil)))))
|
||||
@@ -1213,14 +1231,21 @@ string if FIELD is not present in ENTRY and DEFAULT is nil."
|
||||
"\\(^[^{]*{\\)\\|\\(}[^{]*{\\)\\|\\(}.*$\\)\\|\\(^[^{}]*$\\)"
|
||||
(lambda (x) (downcase (s-replace "\\" "\\\\" x)))
|
||||
value)))))
|
||||
("booktitle" value)
|
||||
("journal"
|
||||
(replace-regexp-in-string "[{}]" "" value))
|
||||
("booktitle"
|
||||
(replace-regexp-in-string "[{}]" "" value))
|
||||
;; Maintain the punctuation and capitalization that is used by
|
||||
;; the journal in its title.
|
||||
("pages" (s-join "–" (s-split "[^0-9]+" value t)))
|
||||
("doi" (s-concat " http://dx.doi.org/" value))
|
||||
("year" (or value
|
||||
(car (split-string (bibtex-completion-get-value "date" entry "") "-"))))
|
||||
(_ value))))))
|
||||
("year" value)
|
||||
(_ value))
|
||||
;; If field does not exist, try to retrieve value from
|
||||
;; alternative field (possibly a biblatex field):
|
||||
(pcase field
|
||||
("year" (car (split-string (bibtex-completion-get-value "date" entry "") "-")))
|
||||
("journal" (bibtex-completion-get-value "journaltitle" entry "")))))))
|
||||
default ""))
|
||||
|
||||
(defun bibtex-completion-apa-format-authors (value &optional abbrev)
|
||||
@@ -1300,18 +1325,9 @@ When ABBREV is non-nil, format in abbreviated APA style instead."
|
||||
(bibtex-completion-apa-format-editors value t))
|
||||
|
||||
(defun bibtex-completion-get-value (field entry &optional default)
|
||||
"Return the value for FIELD in ENTRY or DEFAULT if the value is not defined.
|
||||
Surrounding curly braces are stripped."
|
||||
"Return the value for FIELD in ENTRY or DEFAULT if the value is not defined."
|
||||
(let ((value (cdr (assoc-string field entry 'case-fold))))
|
||||
(if value
|
||||
(replace-regexp-in-string
|
||||
"\\(^[[:space:]]*[\"{][[:space:]]*\\)\\|\\([[:space:]]*[\"}][[:space:]]*$\\)"
|
||||
""
|
||||
;; Collapse whitespaces when the content is not a path:
|
||||
(if (equal bibtex-completion-pdf-field field)
|
||||
value
|
||||
(s-collapse-whitespace value)))
|
||||
default)))
|
||||
(or value default)))
|
||||
|
||||
(defun bibtex-completion-insert-key (keys)
|
||||
"Insert BibTeX KEYS at point."
|
||||
14
lisp/bind-key/bind-key-pkg.el
Normal file
14
lisp/bind-key/bind-key-pkg.el
Normal file
@@ -0,0 +1,14 @@
|
||||
(define-package "bind-key" "20230203.2004" "A simple way to manage personal keybindings"
|
||||
'((emacs "24.3"))
|
||||
:commit "77945e002f11440eae72d8730d3de218163d551e" :authors
|
||||
'(("John Wiegley" . "johnw@newartisans.com"))
|
||||
:maintainers
|
||||
'(("John Wiegley" . "johnw@newartisans.com"))
|
||||
:maintainer
|
||||
'("John Wiegley" . "johnw@newartisans.com")
|
||||
:keywords
|
||||
'("keys" "keybinding" "config" "dotemacs" "extensions")
|
||||
:url "https://github.com/jwiegley/use-package")
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
;; End:
|
||||
@@ -6,8 +6,6 @@
|
||||
;; Maintainer: John Wiegley <johnw@newartisans.com>
|
||||
;; Created: 16 Jun 2012
|
||||
;; Version: 2.4.1
|
||||
;; Package-Version: 20221209.2013
|
||||
;; Package-Commit: bcf0984cf55b70fe6896c6a15f61df92b24f8ffd
|
||||
;; Package-Requires: ((emacs "24.3"))
|
||||
;; Keywords: keys keybinding config dotemacs extensions
|
||||
;; URL: https://github.com/jwiegley/use-package
|
||||
@@ -168,7 +166,8 @@ KEY-NAME may be a vector, in which case it is passed straight to
|
||||
spelled-out keystrokes, e.g., \"C-c C-z\". See the documentation
|
||||
of `edmacro-mode' for details.
|
||||
|
||||
COMMAND must be an interactive function or lambda form.
|
||||
COMMAND must be an interactive function, lambda form, or a cons
|
||||
`(STRING . DEFN)'.
|
||||
|
||||
KEYMAP, if present, should be a keymap variable or symbol.
|
||||
For example:
|
||||
15
lisp/cfrs/cfrs-pkg.el
Normal file
15
lisp/cfrs/cfrs-pkg.el
Normal file
@@ -0,0 +1,15 @@
|
||||
(define-package "cfrs" "20220129.1149" "Child-frame based read-string"
|
||||
'((emacs "26.1")
|
||||
(dash "2.11.0")
|
||||
(s "1.10.0")
|
||||
(posframe "0.6.0"))
|
||||
:commit "f3a21f237b2a54e6b9f8a420a9da42b4f0a63121" :authors
|
||||
'(("Alexander Miller" . "alexanderm@web.de"))
|
||||
:maintainers
|
||||
'(("Alexander Miller" . "alexanderm@web.de"))
|
||||
:maintainer
|
||||
'("Alexander Miller" . "alexanderm@web.de")
|
||||
:url "https://github.com/Alexander-Miller/cfrs")
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
;; End:
|
||||
@@ -4,9 +4,7 @@
|
||||
|
||||
;; Author: Alexander Miller <alexanderm@web.de>
|
||||
;; Package-Requires: ((emacs "26.1") (dash "2.11.0") (s "1.10.0") (posframe "0.6.0"))
|
||||
;; Package-Commit: f3a21f237b2a54e6b9f8a420a9da42b4f0a63121
|
||||
;; Package-Version: 20220129.1149
|
||||
;; Package-X-Original-Version: 1.6.0
|
||||
;; Package-Version: 1.6.0
|
||||
;; Homepage: https://github.com/Alexander-Miller/cfrs
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
@@ -26,6 +26,8 @@
|
||||
;;; Code:
|
||||
|
||||
(require 'parse-time)
|
||||
(require 'compat)
|
||||
|
||||
(require 'citeproc-bibtex)
|
||||
|
||||
(defvar citeproc-blt-to-csl-types-alist
|
||||
@@ -473,7 +475,7 @@ biblatex variables in B."
|
||||
(citeproc-blt--get-standard 'address b)))
|
||||
(push (cons csl-place-var ~location) result)))
|
||||
;; url
|
||||
(-when-let (url (or (let ((u (alist-get 'url b))) (and u (citeproc-s-replace "\\" "" u)))
|
||||
(-when-let (url (or (let ((u (alist-get 'url b))) (and u (string-replace "\\" "" u)))
|
||||
(when-let ((~eprinttype (or (alist-get 'eprinttype b)
|
||||
(alist-get 'archiveprefix b)))
|
||||
(~eprint (alist-get 'eprint b))
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
(require 's)
|
||||
(require 'org)
|
||||
(require 'map)
|
||||
(require 'compat)
|
||||
;; Handle the fact that org-bibtex has been renamed to ol-bibtex -- for the time
|
||||
;; being we support both feature names.
|
||||
(or (require 'ol-bibtex nil t)
|
||||
@@ -262,7 +263,7 @@ replacements."
|
||||
(let ((wo-quotes (if (and (string= (substring s 0 1) "\"")
|
||||
(string= (substring s -1) "\""))
|
||||
(substring s 1 -1) s)))
|
||||
(citeproc-s-replace "\\&" "&" wo-quotes)))
|
||||
(string-replace "\\&" "&" wo-quotes)))
|
||||
|
||||
(defun citeproc-bt--to-csl (s &optional with-nocase)
|
||||
"Convert a BibTeX field S to a CSL one.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; citeproc-cite.el --- cite and citation rendering -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2017-2021 András Simonyi
|
||||
;; Copyright (C) 2017-2024 András Simonyi
|
||||
|
||||
;; Author: András Simonyi <andras.simonyi@gmail.com>
|
||||
|
||||
@@ -40,6 +40,11 @@
|
||||
(require 'citeproc-formatters)
|
||||
(require 'citeproc-sort)
|
||||
(require 'citeproc-subbibs)
|
||||
(require 'citeproc-date)
|
||||
(require 'citeproc-biblatex)
|
||||
|
||||
|
||||
(declare-function citeproc-style-category "citeproc-style" (style))
|
||||
|
||||
(cl-defstruct (citeproc-citation (:constructor citeproc-citation-create))
|
||||
"A struct representing a citation.
|
||||
@@ -77,6 +82,35 @@ Each function takes a single argument, a rich-text, and returns a
|
||||
post-processed rich-text value. The functions are applied in the
|
||||
order they appear in the list.")
|
||||
|
||||
(defun citeproc-cite--parse-locator-extra (s)
|
||||
"Parse extra locator text S into locator-date and locator-extra.
|
||||
Return a pair (LOCATOR-DATE . LOCATOR-EXTRA) where
|
||||
- LOCATOR-DATE is a `citeproc-date' struct or nil, and
|
||||
- LOCATOR-EXTRA is a string or nil."
|
||||
(let (locator-date locator-extra)
|
||||
(if (not (string-match-p "^[0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}" s))
|
||||
(setq locator-extra (and (not (s-blank-str-p s)) s))
|
||||
(setq locator-date (citeproc-date-parse (citeproc-blt--to-csl-date
|
||||
(substring s 0 10))))
|
||||
(let ((extra (substring s 10)))
|
||||
(unless (s-blank-str-p extra) (setq locator-extra extra))))
|
||||
(cons locator-date locator-extra)))
|
||||
|
||||
(defun citeproc-cite--internalize-locator (cite)
|
||||
"Internalize a CITE struct's locator by parsing it into fields.
|
||||
If the \"|\" separator is present in the locator then parse it
|
||||
into `locator', `locator-extra' and `locator-date', and update
|
||||
CITE with these fields accordingly. Returns the possibly modified
|
||||
CITE."
|
||||
(when-let ((locator (alist-get 'locator cite))
|
||||
(separator-pos (cl-position ?| locator)))
|
||||
(setf (alist-get 'locator cite) (substring locator 0 separator-pos))
|
||||
(pcase-let ((`(,locator-date . ,locator-extra) (citeproc-cite--parse-locator-extra
|
||||
(substring locator (1+ separator-pos)))))
|
||||
(when locator-date (push (cons 'locator-date locator-date) cite))
|
||||
(when locator-extra (push (cons 'locator-extra locator-extra) cite))))
|
||||
cite)
|
||||
|
||||
(defun citeproc-cite--varlist (cite)
|
||||
"Return the varlist belonging to CITE."
|
||||
(let* ((itd (alist-get 'itd cite))
|
||||
@@ -87,7 +121,8 @@ order they appear in the list.")
|
||||
'(label locator suppress-author suppress-date
|
||||
stop-rendering-at position near-note
|
||||
first-reference-note-number ignore-et-al
|
||||
bib-entry locator-only use-short-title))
|
||||
bib-entry locator-only use-short-title
|
||||
locator-extra locator-date))
|
||||
cite)))
|
||||
(nconc cite-vv item-vv)))
|
||||
|
||||
@@ -141,7 +176,7 @@ links else). For legacy reasons, any other value is treated as
|
||||
;; Add cite prefix and suffix
|
||||
(when (s-present-p plain-suff)
|
||||
(push (citeproc-rt-from-str suff) result)
|
||||
(unless (= (aref plain-suff 0) ?\s)
|
||||
(unless (memql (aref plain-suff 0) '(?, ?\s))
|
||||
(push " " result)))
|
||||
(push rendered-varlist result)
|
||||
(when (s-present-p plain-pref)
|
||||
@@ -228,7 +263,8 @@ For the optional INTERNAL-LINKS argument see
|
||||
(when outer-attrs
|
||||
(setq result (list outer-attrs result)))
|
||||
;; Prepend author to textual citations
|
||||
(when (eq (citeproc-citation-mode c) 'textual)
|
||||
(when (and (eq (citeproc-citation-mode c) 'textual)
|
||||
(not (member (citeproc-style-category style) '("numeric" "label"))))
|
||||
(let* ((first-elt (car cites)) ;; First elt is either a cite or a cite group.
|
||||
;; If the latter then we need to locate the
|
||||
;; first cite as the 2nd element of the first
|
||||
@@ -237,11 +273,11 @@ For the optional INTERNAL-LINKS argument see
|
||||
(cadr first-elt)
|
||||
first-elt))
|
||||
(author-cite
|
||||
(append '((suppress-author . nil) (stop-rendering-at . names))
|
||||
first-cite))
|
||||
(append '((suppress-author . nil) (stop-rendering-at . names)
|
||||
(prefix) (suffix) (locator))
|
||||
first-cite))
|
||||
(rendered-author (citeproc-cite--render author-cite style 'no-links)))
|
||||
(when (and (listp rendered-author)
|
||||
(alist-get 'stopped-rendering (car rendered-author)))
|
||||
(when (listp rendered-author)
|
||||
(setq result `(nil ,rendered-author " " ,result)))))
|
||||
;; Capitalize first
|
||||
(when (citeproc-citation-capitalize-first c)
|
||||
@@ -548,6 +584,7 @@ Possible values are `last', `first' and `subsequent'.")
|
||||
(unless (citeproc-proc-finalized proc)
|
||||
(citeproc-proc-process-uncited proc)
|
||||
(citeproc-sb-add-subbib-info proc)
|
||||
(citeproc-sb-prune-unrendered proc)
|
||||
(citeproc-proc-update-sortkeys proc)
|
||||
(citeproc-proc-sort-itds proc)
|
||||
(citeproc-proc-update-positions proc)
|
||||
|
||||
@@ -168,16 +168,6 @@ TYPED RTS is a list of (RICH-TEXT . TYPE) pairs"
|
||||
"Return the first text associated with TERM in CONTEXT."
|
||||
(citeproc-term-text-from-terms term (citeproc-context-terms context)))
|
||||
|
||||
(defun citeproc-term-inflected-text (term form number context)
|
||||
"Return the text associated with TERM having FORM and NUMBER."
|
||||
(let ((matches
|
||||
(--select (string= term (citeproc-term-name it))
|
||||
(citeproc-context-terms context))))
|
||||
(cond ((not matches) nil)
|
||||
((= (length matches) 1)
|
||||
(citeproc-term-text (car matches)))
|
||||
(t (citeproc-term--inflected-text-1 matches form number)))))
|
||||
|
||||
(defconst citeproc--term-form-fallback-alist
|
||||
'((verb-short . verb)
|
||||
(symbol . short)
|
||||
@@ -185,17 +175,21 @@ TYPED RTS is a list of (RICH-TEXT . TYPE) pairs"
|
||||
(short . long))
|
||||
"Alist containing the fallback form for each term form.")
|
||||
|
||||
(defun citeproc-term--inflected-text-1 (matches form number)
|
||||
(let ((match (--first (and (eq form (citeproc-term-form it))
|
||||
(or (not (citeproc-term-number it))
|
||||
(eq number (citeproc-term-number it))))
|
||||
matches)))
|
||||
(if match
|
||||
(citeproc-term-text match)
|
||||
(citeproc-term--inflected-text-1
|
||||
matches
|
||||
(alist-get form citeproc--term-form-fallback-alist)
|
||||
number))))
|
||||
(defun citeproc-term-inflected-text (term form number context)
|
||||
"Return the text associated with TERM having FORM and NUMBER."
|
||||
(let ((matches
|
||||
(--select (string= term (citeproc-term-name it))
|
||||
(citeproc-context-terms context))))
|
||||
(if (not matches) nil
|
||||
(let (match)
|
||||
(while (and (not match) form)
|
||||
(setq match (--first (and (eq form (citeproc-term-form it))
|
||||
(or (not (citeproc-term-number it))
|
||||
(eq number (citeproc-term-number it))))
|
||||
matches))
|
||||
(unless match
|
||||
(setq form (alist-get form citeproc--term-form-fallback-alist))))
|
||||
(when match (citeproc-term-text match))))))
|
||||
|
||||
(defun citeproc-term-get-gender (term context)
|
||||
"Return the gender of TERM or nil if none is given."
|
||||
@@ -224,6 +218,20 @@ no internal links should be produced."
|
||||
;; Else link each cite to the corresponding bib item.
|
||||
(if (eq mode 'cite) 'cited-item-no 'bib-item-no)))))
|
||||
|
||||
(defun citeproc-context-maybe-stop-rendering
|
||||
(trigger context result &optional var)
|
||||
"Stop rendering if a (`stop-rendering-at'. TRIGGER) pair is present in CONTEXT.
|
||||
In case of stopping return with RESULT. If the optional VAR
|
||||
symbol is non-nil then rendering is stopped only if VAR is eq to
|
||||
TRIGGER."
|
||||
(if (and (eq trigger (alist-get 'stop-rendering-at (citeproc-context-vars context)))
|
||||
(or (not var) (eq var trigger))
|
||||
(eq (cdr result) 'present-var))
|
||||
(let ((rt-result (car result)))
|
||||
(push '(stopped-rendering . t) (car rt-result))
|
||||
(throw 'stop-rendering (citeproc-rt-render-affixes rt-result)))
|
||||
result))
|
||||
|
||||
(defun citeproc-render-varlist-in-rt (var-alist style mode render-mode &optional
|
||||
internal-links no-external-links)
|
||||
"Render an item described by VAR-ALIST with STYLE in rich-text.
|
||||
@@ -263,7 +271,7 @@ external links."
|
||||
(citeproc-context-int-link-attrval
|
||||
style internal-links mode (alist-get 'position var-alist)))
|
||||
(cite-no-attr-val (cons cite-no-attr
|
||||
(alist-get 'citation-number var-alist))))
|
||||
(alist-get 'citation-number var-alist))))
|
||||
(cond ((consp rendered) (setf (car rendered)
|
||||
(-snoc (car rendered) cite-no-attr-val)))
|
||||
((stringp rendered) (setq rendered
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
(require 'citeproc-lib)
|
||||
(require 'citeproc-rt)
|
||||
(require 'citeproc-context)
|
||||
(require 'citeproc-number)
|
||||
|
||||
(cl-defstruct (citeproc-date (:constructor citeproc-date-create))
|
||||
"Struct for representing dates.
|
||||
@@ -94,7 +95,7 @@ Set the remaining slots to the values SEASON and CIRCA."
|
||||
(cons nil 'empty-vars)))
|
||||
(cons nil 'empty-vars))))
|
||||
;; Handle `year' citation mode by stopping if needed
|
||||
(citeproc-lib-maybe-stop-rendering 'issued context result var-sym)))
|
||||
(citeproc-context-maybe-stop-rendering 'issued context result var-sym)))
|
||||
|
||||
(defun citeproc--date-part (attrs _context &rest _body)
|
||||
"Function corresponding to the date-part CSL element."
|
||||
|
||||
@@ -33,8 +33,11 @@
|
||||
(require 's)
|
||||
(require 'cl-lib)
|
||||
|
||||
(cl-defstruct (citeproc-formatter (:constructor citeproc-formatter-create))
|
||||
"Output formatter struct with slots RT, CITE, BIB-ITEM and BIB.
|
||||
(require 'citeproc-s)
|
||||
(require 'citeproc-rt)
|
||||
|
||||
(cl-defstruct (citeproc-formatter (:constructor citeproc-formatter-create))
|
||||
"Output formatter struct with slots RT, CITE, BIB-ITEM and BIB.
|
||||
RT is a one-argument function mapping a rich-text to its
|
||||
formatted version,
|
||||
CITE is a one-argument function mapping the output of RT for a
|
||||
@@ -48,9 +51,9 @@ BIB is a two-argument function mapping a list of formatted
|
||||
bibliography,
|
||||
NO-EXTERNAL-LINKS is non-nil if the formatter doesn't support
|
||||
external linking."
|
||||
rt (cite #'identity) (bib-item (lambda (x _) x))
|
||||
(bib (lambda (x _) (mapconcat #'identity x "\n\n")))
|
||||
(no-external-links nil))
|
||||
rt (cite #'identity) (bib-item (lambda (x _) x))
|
||||
(bib (lambda (x _) (mapconcat #'identity x "\n\n")))
|
||||
(no-external-links nil))
|
||||
|
||||
(defun citeproc-formatter-fun-create (fmt-alist)
|
||||
"Return a rich-text formatter function based on FMT-ALIST.
|
||||
@@ -164,11 +167,18 @@ Performs finalization by removing unnecessary zero-width spaces."
|
||||
(setq result (citeproc-s-replace-all-seq
|
||||
result '((" " . " ") (" " . " ") ("," . ",") (";" . ";")
|
||||
(":" . ":") ("." . "."))))
|
||||
;; Starting and ending z-w spaces are also removed.
|
||||
(when (= (aref result 0) 8203)
|
||||
;; Starting and ending z-w spaces are also removed, but not before an asterisk
|
||||
;; to avoid creating an Org heading.
|
||||
(when (and (= (aref result 0) 8203)
|
||||
(not (= (aref result 1) ?*)))
|
||||
(setq result (substring result 1)))
|
||||
(when (= (aref result (- (length result) 1)) 8203)
|
||||
(setq result (substring result 0 -1))))
|
||||
(setq result (substring result 0 -1)))
|
||||
;; Prepend a zero width no-break space when the text starts with
|
||||
;; superscript to make Org parse it correctly.
|
||||
;; NOTE: This is a workaround, ideally should be fixed in Org.
|
||||
(when (= (aref result 0) ?^)
|
||||
(setq result (concat "" result))))
|
||||
result))
|
||||
|
||||
;; HTML
|
||||
@@ -255,11 +265,16 @@ CSL tests."
|
||||
"Return the LaTeX-escaped version of string S."
|
||||
(replace-regexp-in-string citeproc-fmt--latex-esc-regex "\\\\\\&" s))
|
||||
|
||||
(defconst citeproc-fmt--latex-uri-esc-regex
|
||||
(regexp-opt '("#" "%"))
|
||||
"Regular expression matching characters to be escaped in URIs for LaTeX output.")
|
||||
|
||||
(defun citeproc-fmt--latex-href (text uri)
|
||||
(let ((escaped-uri (replace-regexp-in-string "%" "\\\\%" uri)))
|
||||
(if (string-prefix-p "http" text)
|
||||
(concat "\\url{" escaped-uri "}")
|
||||
(concat "\\href{" escaped-uri "}{" text "}"))))
|
||||
(let ((escaped-uri (replace-regexp-in-string
|
||||
citeproc-fmt--latex-uri-esc-regex "\\\\\\&" uri)))
|
||||
(if (string-prefix-p "http" text)
|
||||
(concat "\\url{" escaped-uri "}")
|
||||
(concat "\\href{" escaped-uri "}{" text "}"))))
|
||||
|
||||
(defconst citeproc-fmt--latex-alist
|
||||
`((unformatted . ,#'citeproc-fmt--latex-escape)
|
||||
@@ -371,7 +386,9 @@ CSL tests."
|
||||
:rt (citeproc-formatter-fun-create citeproc-fmt--org-latex-alist)
|
||||
:bib #'citeproc-fmt--org-latex-bib-formatter))
|
||||
(latex . ,(citeproc-formatter-create
|
||||
:rt (citeproc-formatter-fun-create citeproc-fmt--latex-alist)))
|
||||
:rt (citeproc-formatter-fun-create citeproc-fmt--latex-alist)
|
||||
:bib (lambda (x _) (concat (mapconcat #'identity x "\n\n")
|
||||
"\\bigskip"))))
|
||||
(plain . ,(citeproc-formatter-create :rt #'citeproc-rt-to-plain
|
||||
:no-external-links t)))
|
||||
"Alist mapping supported output formats to formatter structs.")
|
||||
|
||||
@@ -143,7 +143,7 @@
|
||||
(setq type (cdr macro-val)))))
|
||||
;; We stop if only the title had to be rendered.
|
||||
(let ((result (cons (citeproc-rt-format-single attrs content context) type)))
|
||||
(citeproc-lib-maybe-stop-rendering
|
||||
(citeproc-context-maybe-stop-rendering
|
||||
'title context result (or (and .variable (intern .variable)) t))))))
|
||||
|
||||
(provide 'citeproc-generic-elements)
|
||||
|
||||
@@ -45,9 +45,10 @@ OCCURRED-BEFORE is used during bibliography generation to
|
||||
DISAMB-POS contains the position on which cite disambiguation is
|
||||
based. Possible values are 'first, 'ibid and 'subsequent,
|
||||
SUBBIB-NOS is a list of numeric indexes of sub-bibliographies
|
||||
in which the item occurs."
|
||||
in which the item occurs,
|
||||
UNCITED is t iff the item has no associated citation."
|
||||
varvals rawcite rawbibitem rc-uptodate sort-key occurred-before
|
||||
disamb-pos subbib-nos)
|
||||
disamb-pos subbib-nos uncited)
|
||||
|
||||
(defun citeproc-itd-getvar (itd var)
|
||||
"Return itemdata ITD's value for VAR ."
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
)
|
||||
|
||||
(defconst citeproc--date-vars
|
||||
'(accessed available-date event-date issued original-date submitted)
|
||||
'(accessed available-date event-date issued original-date submitted locator-date)
|
||||
"CSL date variables.")
|
||||
|
||||
(defconst citeproc--name-vars
|
||||
@@ -145,20 +145,6 @@ numeric content."
|
||||
(s-matches-p "\\`[[:alpha:]]?[[:digit:]]+[[:alpha:]]*\\(\\( *\\([,&-]\\|--\\) *\\)?[[:alpha:]]?[[:digit:]]+[[:alpha:]]*\\)?\\'"
|
||||
val))))
|
||||
|
||||
(defun citeproc-lib-maybe-stop-rendering
|
||||
(trigger context result &optional var)
|
||||
"Stop rendering if a (`stop-rendering-at'. TRIGGER) pair is present in CONTEXT.
|
||||
In case of stopping return with RESULT. If the optional VAR
|
||||
symbol is non-nil then rendering is stopped only if VAR is eq to
|
||||
TRIGGER."
|
||||
(if (and (eq trigger (alist-get 'stop-rendering-at (citeproc-context-vars context)))
|
||||
(or (not var) (eq var trigger))
|
||||
(eq (cdr result) 'present-var))
|
||||
(let ((rt-result (car result)))
|
||||
(push '(stopped-rendering . t) (car rt-result))
|
||||
(throw 'stop-rendering (citeproc-rt-render-affixes rt-result)))
|
||||
result))
|
||||
|
||||
(provide 'citeproc-lib)
|
||||
|
||||
;;; citeproc-lib.el ends here
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
(define-package "citeproc" "20221216.1238" "A CSL 1.0.2 Citation Processor"
|
||||
(define-package "citeproc" "20240722.1110" "A CSL 1.0.2 Citation Processor"
|
||||
'((emacs "26")
|
||||
(dash "2.13.0")
|
||||
(s "1.12.0")
|
||||
@@ -6,8 +6,11 @@
|
||||
(queue "0.2")
|
||||
(string-inflection "1.0")
|
||||
(org "9")
|
||||
(parsebib "2.4"))
|
||||
:commit "3cb83db147bdda208520246e82dbf9878fa3cbd0" :authors
|
||||
(parsebib "2.4")
|
||||
(compat "28.1"))
|
||||
:commit "54184baaff555b5c7993d566d75dd04ed485b5c0" :authors
|
||||
'(("András Simonyi" . "andras.simonyi@gmail.com"))
|
||||
:maintainers
|
||||
'(("András Simonyi" . "andras.simonyi@gmail.com"))
|
||||
:maintainer
|
||||
'("András Simonyi" . "andras.simonyi@gmail.com")
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'citeproc-s)
|
||||
|
||||
(defun citeproc-prange--end-significant (start end len)
|
||||
"Return the significant digits of the end in page range START END.
|
||||
START and END are strings of equal length containing integers. If
|
||||
|
||||
@@ -99,11 +99,11 @@ sorted."
|
||||
(push (cons 'editor-translator editor) result))
|
||||
result))
|
||||
|
||||
(defun citeproc-proc--put-item (proc item itemid)
|
||||
(defun citeproc-proc--put-item (proc item itemid &optional uncited)
|
||||
"Put parsed csl-json ITEM with ITEMID into PROC.
|
||||
Return the added itemdata structure."
|
||||
(let* ((int-vars (citeproc-proc--internalize-item proc item))
|
||||
(itemdata (citeproc-itemdata-create :varvals int-vars :rc-uptodate nil)))
|
||||
(itemdata (citeproc-itemdata-create :varvals int-vars :uncited uncited)))
|
||||
(citeproc-proc-put-itd-put itemid itemdata proc)
|
||||
(citeproc-itd-setvar itemdata 'citation-number
|
||||
(number-to-string (hash-table-count
|
||||
@@ -150,7 +150,7 @@ Return the itemdata struct that was added."
|
||||
(citeproc-proc--put-item
|
||||
proc
|
||||
(or item `((unprocessed-with-id . ,id)))
|
||||
id))))))
|
||||
id t))))))
|
||||
|
||||
(defun citeproc-proc-delete-occurrence-info (proc)
|
||||
"Remove all itemdata occurrence info from PROC."
|
||||
@@ -225,6 +225,19 @@ Return the PROC-internal representation of REP."
|
||||
(when bib-sort (setf (citeproc-style-bib-sort style) (byte-compile bib-sort)))
|
||||
(when cite-sort (setf (citeproc-style-cite-sort style) (byte-compile cite-sort)))))
|
||||
|
||||
(defun citeproc-proc-filtered-bib-p (proc)
|
||||
"Return whether PROC has nontrivial filters"
|
||||
(let ((filters (citeproc-proc-bib-filters proc)))
|
||||
(and filters (not (equal filters '(nil))))))
|
||||
|
||||
(defun citeproc-proc-max-offset (itds)
|
||||
"Return the maximal first field width of bibitems in ITDS.
|
||||
ITDS should be the value of the itemdata field of a citeproc-proc
|
||||
structure."
|
||||
(cl-loop for itd being the hash-values of itds
|
||||
when (listp (citeproc-itemdata-rawbibitem itd)) maximize
|
||||
(length (citeproc-rt-to-plain (cadr (citeproc-itemdata-rawbibitem itd))))))
|
||||
|
||||
(provide 'citeproc-proc)
|
||||
|
||||
;;; citeproc-proc.el ends here
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
(require 'cl-lib)
|
||||
(require 'let-alist)
|
||||
(require 's)
|
||||
(require 'compat)
|
||||
|
||||
(require 'citeproc-s)
|
||||
(require 'citeproc-lib)
|
||||
@@ -148,7 +149,7 @@ If optional SKIP-NOCASE is non-nil then skip spans with the
|
||||
|
||||
(defun citeproc-rt-strip-periods (rts)
|
||||
"Remove all periods from rich-texts RTS."
|
||||
(citeproc-rt-map-strings (lambda (x) (citeproc-s-replace "." "" x)) rts))
|
||||
(citeproc-rt-map-strings (lambda (x) (string-replace "." "" x)) rts))
|
||||
|
||||
(defun citeproc-rt-length (rt)
|
||||
"Return the length of rich-text RT as a string."
|
||||
@@ -532,12 +533,6 @@ The values are ordered depth-first."
|
||||
|
||||
;;; Helpers for bibliography rendering
|
||||
|
||||
(defun citeproc-rt-max-offset (itemdata)
|
||||
"Return the maximal first field width in rich-texts RTS."
|
||||
(cl-loop for itd being the hash-values of itemdata
|
||||
when (listp (citeproc-itemdata-rawbibitem itd)) maximize
|
||||
(length (citeproc-rt-to-plain (cadr (citeproc-itemdata-rawbibitem itd))))))
|
||||
|
||||
(defun citeproc-rt-subsequent-author-substitute (bib s)
|
||||
"Substitute S for subsequent author(s) in BIB.
|
||||
BIB is a list of bib entries in rich-text format. Return the
|
||||
|
||||
@@ -27,11 +27,7 @@
|
||||
|
||||
(require 'thingatpt)
|
||||
(require 's)
|
||||
|
||||
;; Handle the unavailability of `string-replace' in early Emacs versions
|
||||
(if (fboundp 'string-replace)
|
||||
(defalias 'citeproc-s-replace #'string-replace)
|
||||
(defalias 'citeproc-s-replace #'s-replace))
|
||||
(require 'compat)
|
||||
|
||||
(defun citeproc-s-camelcase-p (s)
|
||||
"Return whether string S is in camel case."
|
||||
@@ -151,12 +147,12 @@ first word is not in lowercase then return S."
|
||||
(buffer-string))
|
||||
s))
|
||||
|
||||
(defun citeproc-s-sentence-case-title (s omit-nocase)
|
||||
(defun citeproc-s-sentence-case-title (s &optional omit-nocase)
|
||||
"Return a sentence-cased version of title string S.
|
||||
If optional OMIT-NOCASE is non-nil then omit the nocase tags from the output."
|
||||
(if (s-blank-p s) s
|
||||
(let ((sliced (citeproc-s-slice-by-matches
|
||||
s "\\(<span class=\"nocase\">\\|</span>\\|: +\\w\\)"))
|
||||
s "\\(<span class=\"nocase\">\\|</span>\\|: +[\"'“‘]*[[:alpha:]]\\)"))
|
||||
(protect-level 0)
|
||||
(first t)
|
||||
result)
|
||||
@@ -165,13 +161,18 @@ If optional OMIT-NOCASE is non-nil then omit the nocase tags from the output."
|
||||
(pcase slice
|
||||
("<span class=\"nocase\">" (cl-incf protect-level) (if omit-nocase nil slice))
|
||||
("</span>" (cl-decf protect-level) (if omit-nocase nil slice))
|
||||
;; Don't touch the first letter after a colon since it is probably a subtitle.
|
||||
((pred (string-match-p "^:")) slice)
|
||||
;; Don't touch the first letter after a colon since it probably
|
||||
;; starts a subtitle.
|
||||
((pred (string-match-p "^: +[\"'“‘]*[[:alpha:]]")) (setq first nil) slice)
|
||||
(_ (cond ((< 0 protect-level) (setq first nil) slice)
|
||||
((not first) (downcase slice))
|
||||
(t (setq first nil)
|
||||
(concat (upcase (substring slice 0 1))
|
||||
(downcase (substring slice 1)))))))
|
||||
;; We upcase the first letter and downcase the rest.
|
||||
(let ((pos (string-match "[[:alpha:]]" slice)))
|
||||
(if pos (concat (substring slice 0 pos)
|
||||
(upcase (substring slice pos (1+ pos)))
|
||||
(downcase (substring slice (1+ pos))))
|
||||
slice))))))
|
||||
result))
|
||||
(apply #'concat (nreverse result)))))
|
||||
|
||||
@@ -232,7 +233,7 @@ OQ is the opening quote, CQ is the closing quote to use."
|
||||
REPLACEMENTS is an alist with (FROM . TO) elements."
|
||||
(let ((result s))
|
||||
(pcase-dolist (`(,from . ,to) replacements)
|
||||
(setq result (citeproc-s-replace from to result)))
|
||||
(setq result (string-replace from to result)))
|
||||
result))
|
||||
|
||||
(defun citeproc-s-replace-all-sim (s regex replacements)
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
(require 'citeproc-macro)
|
||||
(require 'citeproc-proc)
|
||||
(require 'citeproc-name)
|
||||
(require 'citeproc-number)
|
||||
|
||||
(defun citeproc--sort (_attrs _context &rest body)
|
||||
"Placeholder function corresponding to the cs:sort element of CSL."
|
||||
@@ -169,20 +170,20 @@ MODE is either `cite' or `bib'."
|
||||
|
||||
(defun citeproc-proc-sort-itds (proc)
|
||||
"Sort the itemdata in PROC."
|
||||
(let ((sorted-bib-p (citeproc-style-bib-sort (citeproc-proc-style proc)))
|
||||
(filters (citeproc-proc-bib-filters proc)))
|
||||
(when (or sorted-bib-p filters)
|
||||
(let* ((itds (hash-table-values (citeproc-proc-itemdata proc)))
|
||||
(sorted (if sorted-bib-p
|
||||
(let ((sort-orders (citeproc-style-bib-sort-orders
|
||||
(let ((is-sorted-bib (citeproc-style-bib-sort (citeproc-proc-style proc)))
|
||||
(is-filtered (citeproc-proc-filtered-bib-p proc)))
|
||||
(when (or is-sorted-bib is-filtered)
|
||||
(let* ((itds (citeproc-sort-itds-on-citnum
|
||||
(hash-table-values (citeproc-proc-itemdata proc)))))
|
||||
(when is-sorted-bib
|
||||
(let ((sort-orders (citeproc-style-bib-sort-orders
|
||||
(citeproc-proc-style proc))))
|
||||
(citeproc-sort-itds itds sort-orders))
|
||||
(citeproc-sort-itds-on-citnum itds))))
|
||||
(setq itds (citeproc-sort-itds itds sort-orders))))
|
||||
;; Additionally sort according to subbibliographies if there are filters.
|
||||
(when filters
|
||||
(setq sorted (sort sorted #'citeproc-sort-itds-on-subbib)))
|
||||
(when is-filtered
|
||||
(setq itds (sort itds #'citeproc-sort-itds-on-subbib)))
|
||||
;; Set the CSL citation-number field according to the sort order.
|
||||
(--each-indexed sorted
|
||||
(--each-indexed itds
|
||||
(citeproc-itd-setvar it 'citation-number
|
||||
(number-to-string (1+ it-index))))))))
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
|
||||
(cl-defstruct (citeproc-style (:constructor citeproc-style--create))
|
||||
"A struct representing a parsed and localized CSL style.
|
||||
CATEGORY is the style's category as a string,
|
||||
INFO is the style's general info (currently simply the
|
||||
corresponding fragment of the parsed xml),
|
||||
OPTS, BIB-OPTS, CITE-OPTS and LOCALE-OPTS are alists of general
|
||||
@@ -49,7 +50,6 @@ BIB-SORT-ORDERS and CITE-SORT-ORDERS are the lists of sort orders
|
||||
the n-th key should be in ascending or desending order,
|
||||
CITE-LAYOUT-ATTRS contains the attributes of the citation layout
|
||||
as an alist,
|
||||
CITE-NOTE is non-nil iff the style's citation-format is \"note\",
|
||||
DATE-TEXT and DATE-NUMERIC are the style's date formats,
|
||||
LOCALE contains the locale to be used or nil if not set,
|
||||
MACROS is an alist with macro names as keys and corresponding
|
||||
@@ -57,8 +57,8 @@ MACROS is an alist with macro names as keys and corresponding
|
||||
TERMS is the style's parsed term-list,
|
||||
USES-YS-VAR is non-nil iff the style uses the YEAR-SUFFIX
|
||||
CSL-variable."
|
||||
info opts bib-opts bib-sort bib-sort-orders
|
||||
bib-layout cite-opts cite-note cite-sort cite-sort-orders
|
||||
category info opts bib-opts bib-sort bib-sort-orders
|
||||
bib-layout cite-opts cite-sort cite-sort-orders
|
||||
cite-layout cite-layout-attrs locale-opts macros terms
|
||||
uses-ys-var date-text date-numeric locale)
|
||||
|
||||
@@ -98,12 +98,13 @@ in-style locale information will be loaded (if available)."
|
||||
(--each (cddr parsed-style)
|
||||
(pcase (car it)
|
||||
('info
|
||||
(let ((info-lst (cddr it)))
|
||||
(setf (citeproc-style-info style) info-lst
|
||||
(citeproc-style-cite-note style)
|
||||
(not (not (member '(category
|
||||
((citation-format . "note")))
|
||||
info-lst))))))
|
||||
(let* ((info-lst (cddr it))
|
||||
(category-info (cl-find-if
|
||||
(lambda (x) (and (eq 'category (car x))
|
||||
(eq 'citation-format (caaadr x))))
|
||||
info-lst))
|
||||
(category (cdaadr category-info)))
|
||||
(setf (citeproc-style-category style) category)))
|
||||
('locale
|
||||
(let ((lang (alist-get 'lang (cadr it))))
|
||||
(when (and (citeproc-locale--compatible-p lang locale)
|
||||
@@ -310,7 +311,16 @@ position and before the (possibly empty) body."
|
||||
(cons str (cdr result)))
|
||||
result)))
|
||||
;; Handle `author' citation mode by stopping if needed
|
||||
(citeproc-lib-maybe-stop-rendering 'names context final)))))
|
||||
(citeproc-context-maybe-stop-rendering 'names context final)))))
|
||||
|
||||
(defun citeproc-style-cite-note (style)
|
||||
"Return whether csl STYLE is a note style."
|
||||
(string= (citeproc-style-category style) "note"))
|
||||
|
||||
(defun citeproc-style-cite-superscript-p (style)
|
||||
"Return whether csl STYLE has a superscript citaton layout."
|
||||
(string= (alist-get 'vertical-align (citeproc-style-cite-layout-attrs style))
|
||||
"sup"))
|
||||
|
||||
(defun citeproc-style-global-opts (style layout)
|
||||
"Return the global opts in STYLE for LAYOUT.
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'subr-x)
|
||||
(require 'compat)
|
||||
(require 'dash)
|
||||
|
||||
(require 'citeproc-proc)
|
||||
@@ -39,7 +41,8 @@ see the documentation of `citeproc-add-subbib-filters'."
|
||||
(let* ((csl-type (alist-get 'type vv))
|
||||
(type (or (alist-get 'blt-type vv) csl-type))
|
||||
(keyword (alist-get 'keyword vv))
|
||||
(keywords (and keyword (split-string keyword "[ ,;]" t))))
|
||||
(keywords (and keyword (mapcar #'string-clean-whitespace
|
||||
(split-string keyword "[,;]" t)))))
|
||||
(--every-p
|
||||
(pcase it
|
||||
(`(type . ,key) (string= type key))
|
||||
@@ -54,17 +57,32 @@ see the documentation of `citeproc-add-subbib-filters'."
|
||||
|
||||
(defun citeproc-sb-add-subbib-info (proc)
|
||||
"Add subbibliography information to the items in PROC."
|
||||
(let ((filters (citeproc-proc-bib-filters proc)))
|
||||
(maphash
|
||||
(lambda (_ itemdata)
|
||||
(let* ((varvals (citeproc-itemdata-varvals itemdata))
|
||||
(subbib-nos
|
||||
(-non-nil
|
||||
(--map-indexed
|
||||
(when (citeproc-sb--match-p varvals it) it-index)
|
||||
filters))))
|
||||
(setf (citeproc-itemdata-subbib-nos itemdata) subbib-nos)))
|
||||
(citeproc-proc-itemdata proc))))
|
||||
(when (citeproc-proc-filtered-bib-p proc)
|
||||
(let ((filters (citeproc-proc-bib-filters proc)))
|
||||
(maphash
|
||||
(lambda (_ itemdata)
|
||||
(let* ((varvals (citeproc-itemdata-varvals itemdata))
|
||||
(subbib-nos
|
||||
(-non-nil
|
||||
(--map-indexed
|
||||
(when (citeproc-sb--match-p varvals it) it-index)
|
||||
filters))))
|
||||
(setf (citeproc-itemdata-subbib-nos itemdata) subbib-nos)))
|
||||
(citeproc-proc-itemdata proc)))))
|
||||
|
||||
(defun citeproc-sb-prune-unrendered (proc)
|
||||
"Remove all itemdata about unrendered items from PROC.
|
||||
An item is unrendered if
|
||||
- there are subbibfilters but none of them matches it, and
|
||||
- it is not cited."
|
||||
(when (citeproc-proc-filtered-bib-p proc)
|
||||
(let ((itemdata (citeproc-proc-itemdata proc)))
|
||||
(maphash
|
||||
(lambda (id data)
|
||||
(when (and (citeproc-itemdata-uncited data)
|
||||
(null (citeproc-itemdata-subbib-nos data)))
|
||||
(remhash id itemdata)))
|
||||
itemdata))))
|
||||
|
||||
(provide 'citeproc-subbibs)
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
;;; citeproc.el --- A CSL 1.0.2 Citation Processor -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2017-2022 András Simonyi
|
||||
;; Copyright (C) 2017-2024 András Simonyi
|
||||
|
||||
;; Author: András Simonyi <andras.simonyi@gmail.com>
|
||||
;; Maintainer: András Simonyi <andras.simonyi@gmail.com>
|
||||
;; URL: https://github.com/andras-simonyi/citeproc-el
|
||||
;; Keywords: bib
|
||||
;; Package-Requires: ((emacs "26") (dash "2.13.0") (s "1.12.0") (f "0.18.0") (queue "0.2") (string-inflection "1.0") (org "9") (parsebib "2.4"))
|
||||
;; Version: 0.9
|
||||
;; Package-Requires: ((emacs "26") (dash "2.13.0") (s "1.12.0") (f "0.18.0") (queue "0.2") (string-inflection "1.0") (org "9") (parsebib "2.4")(compat "28.1"))
|
||||
;; Version: 0.9.3
|
||||
|
||||
;; 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
|
||||
@@ -87,10 +87,12 @@ CITATIONS is a list of `citeproc-citation' structures."
|
||||
(new-ids (--remove (gethash it itemdata) uniq-ids)))
|
||||
;; Add all new items in one pass
|
||||
(citeproc-proc-put-items-by-id proc new-ids)
|
||||
;; Add itemdata to the cite structs and add them to the cite queue.
|
||||
;; Internalize the cites dealing with locator-extra if present, add itemdata to
|
||||
;; the cite structs and add them to the cite queue.
|
||||
(dolist (citation citations)
|
||||
(setf (citeproc-citation-cites citation)
|
||||
(--map (cons (cons 'itd (gethash (alist-get 'id it) itemdata)) it)
|
||||
(--map (cons (cons 'itd (gethash (alist-get 'id it) itemdata))
|
||||
(citeproc-cite--internalize-locator it))
|
||||
(citeproc-citation-cites citation)))
|
||||
(queue-append (citeproc-proc-citations proc) citation))
|
||||
(setf (citeproc-proc-finalized proc) nil))))
|
||||
@@ -196,8 +198,8 @@ formatting parameters keyed to the parameter names as symbols:
|
||||
punct-in-quote)))
|
||||
itemdata)
|
||||
(let* ((raw-bib
|
||||
(if (cdr filters)
|
||||
;; There are several filters, we need to select and sort the subbibs.
|
||||
(if (citeproc-proc-filtered-bib-p proc)
|
||||
;; There are filters, we need to select and sort the subbibs.
|
||||
(let* ((nr-of-filters (length filters))
|
||||
(result (make-list nr-of-filters nil))
|
||||
;; We store boolean to-be-sorted flags for each sub-bib
|
||||
@@ -228,7 +230,7 @@ formatting parameters keyed to the parameter names as symbols:
|
||||
result))
|
||||
;; Generate the raw bibs.
|
||||
(--map (mapcar #'citeproc-itemdata-rawbibitem it) result))
|
||||
;; No filters, so raw-bib is a list containg a single raw bibliograhy.
|
||||
;; No filters, so raw-bib is a list containing a single raw bibliograhy.
|
||||
(list (mapcar #'citeproc-itemdata-rawbibitem
|
||||
(citeproc-sort-itds-on-citnum (hash-table-values itemdata))))))
|
||||
;; Perform author-substitution.
|
||||
@@ -239,8 +241,12 @@ formatting parameters keyed to the parameter names as symbols:
|
||||
raw-bib)
|
||||
raw-bib))
|
||||
;; Calculate formatting params.
|
||||
(max-offset (if (alist-get 'second-field-align bib-opts)
|
||||
(citeproc-rt-max-offset itemdata)
|
||||
;; NOTE: This is the only place where we check whether there are
|
||||
;; bibliography items in the processor, even though the empty case
|
||||
;; could be handled way more efficiently.
|
||||
(max-offset (if (and (alist-get 'second-field-align bib-opts)
|
||||
(not (hash-table-empty-p itemdata)))
|
||||
(citeproc-proc-max-offset itemdata)
|
||||
0))
|
||||
(format-params (cons (cons 'max-offset max-offset)
|
||||
(citeproc-style-bib-opts-to-formatting-params bib-opts)))
|
||||
|
||||
14
lisp/cl-libify/cl-libify-pkg.el
Normal file
14
lisp/cl-libify/cl-libify-pkg.el
Normal file
@@ -0,0 +1,14 @@
|
||||
(define-package "cl-libify" "20181130.230" "Update elisp code to use cl-lib instead of cl"
|
||||
'((emacs "25"))
|
||||
:commit "e205b96f944a4f312fd523804cbbaf00027a3c8b" :authors
|
||||
'(("Steve Purcell" . "steve@sanityinc.com"))
|
||||
:maintainers
|
||||
'(("Steve Purcell" . "steve@sanityinc.com"))
|
||||
:maintainer
|
||||
'("Steve Purcell" . "steve@sanityinc.com")
|
||||
:keywords
|
||||
'("lisp")
|
||||
:url "https://github.com/purcell/cl-libify")
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
;; End:
|
||||
@@ -4,11 +4,9 @@
|
||||
|
||||
;; Author: Steve Purcell <steve@sanityinc.com>
|
||||
;; Keywords: lisp
|
||||
;; Package-Commit: e205b96f944a4f312fd523804cbbaf00027a3c8b
|
||||
;; Homepage: https://github.com/purcell/cl-libify
|
||||
;; Package-Requires: ((emacs "25"))
|
||||
;; Package-Version: 20181130.230
|
||||
;; Package-X-Original-Version: 0
|
||||
;; Package-Version: 0
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
14
lisp/code-cells/code-cells-pkg.el
Normal file
14
lisp/code-cells/code-cells-pkg.el
Normal file
@@ -0,0 +1,14 @@
|
||||
(define-package "code-cells" "20231119.2138" "Lightweight notebooks with support for ipynb files"
|
||||
'((emacs "27.1"))
|
||||
:commit "44546ca256f3da29e3ac884e3d699c8455acbd6e" :authors
|
||||
'(("Augusto Stoffel" . "arstoffel@gmail.com"))
|
||||
:maintainers
|
||||
'(("Augusto Stoffel" . "arstoffel@gmail.com"))
|
||||
:maintainer
|
||||
'("Augusto Stoffel" . "arstoffel@gmail.com")
|
||||
:keywords
|
||||
'("convenience" "outlines")
|
||||
:url "https://github.com/astoff/code-cells.el")
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
;; End:
|
||||
442
lisp/code-cells/code-cells.el
Normal file
442
lisp/code-cells/code-cells.el
Normal file
@@ -0,0 +1,442 @@
|
||||
;;; code-cells.el --- Lightweight notebooks with support for ipynb files -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2022, 2023 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Augusto Stoffel <arstoffel@gmail.com>
|
||||
;; Keywords: convenience, outlines
|
||||
;; URL: https://github.com/astoff/code-cells.el
|
||||
;; Package-Requires: ((emacs "27.1"))
|
||||
;; Version: 0.4
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; With this package, you can efficiently navigate, edit and execute
|
||||
;; code split into cells according to certain magic comments. It also
|
||||
;; allows you to open ipynb notebook files directly in Emacs. They
|
||||
;; will be automatically converted to a script for editing, and
|
||||
;; converted back to notebook format when saving. An external tool,
|
||||
;; Jupytext by default, is required for this.
|
||||
;;
|
||||
;; A minor mode, `code-cells-mode', provides the following features:
|
||||
;;
|
||||
;; - Fontification of cell boundaries.
|
||||
;;
|
||||
;; - Keybindings for the cell navigation and evaluation commands,
|
||||
;; under the `C-c %' prefix.
|
||||
;;
|
||||
;; - Outline mode integration: cell headers have outline level
|
||||
;; determined by the number of percent signs or asterisks; within a
|
||||
;; cell, outline headings are as determined by the major mode, but
|
||||
;; they are demoted by an amount corresponding to the level of the
|
||||
;; containing cell. This provides code folding and hierarchical
|
||||
;; navigation, among other things, when `outline-minor-mode' is
|
||||
;; active.
|
||||
;;
|
||||
;; This minor mode is automatically activated when opening an ipynb
|
||||
;; file, but you can also activate it in any other buffer, either
|
||||
;; manually or through a hook.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'outline)
|
||||
(require 'pulse)
|
||||
(eval-when-compile
|
||||
(require 'cl-lib)
|
||||
(require 'let-alist)
|
||||
(require 'rx))
|
||||
|
||||
(defgroup code-cells nil
|
||||
"Utilities for code split into cells."
|
||||
:group 'convenience
|
||||
:prefix "code-cells-")
|
||||
|
||||
;;; Cell navigation
|
||||
|
||||
(defcustom code-cells-boundary-regexp
|
||||
(rx line-start
|
||||
(+ (syntax comment-start))
|
||||
(or (seq (* (syntax whitespace)) "%" (group-n 1 (+ "%")))
|
||||
(group-n 1 (+ "*"))
|
||||
(seq " In[" (* (any space digit)) "]:")))
|
||||
"Regular expression specifying cell boundaries.
|
||||
It should match at the beginning of a line. The length of the
|
||||
first capture determines the outline level."
|
||||
:type 'regexp
|
||||
:safe #'stringp)
|
||||
|
||||
;;;###autoload
|
||||
(defun code-cells-forward-cell (&optional arg)
|
||||
"Move to the next cell boundary, or end of buffer.
|
||||
With ARG, repeat this that many times. If ARG is negative, move
|
||||
backward."
|
||||
(interactive "p")
|
||||
(let ((page-delimiter code-cells-boundary-regexp))
|
||||
(when (and (< 0 arg) (looking-at page-delimiter))
|
||||
(forward-char))
|
||||
(forward-page arg)
|
||||
(unless (eobp)
|
||||
(move-beginning-of-line 1))))
|
||||
|
||||
;;;###autoload
|
||||
(defun code-cells-backward-cell (&optional arg)
|
||||
"Move to the previous cell boundary, or beginning of buffer.
|
||||
With ARG, repeat this that many times. If ARG is negative, move
|
||||
forward."
|
||||
(interactive "p")
|
||||
(code-cells-forward-cell (- (or arg 1))))
|
||||
|
||||
(defun code-cells--bounds (&optional count use-region no-header)
|
||||
"Return the bounds of the current code cell, as a cons.
|
||||
|
||||
If COUNT is non-nil, return instead a region containing COUNT
|
||||
cells and starting or ending with the current cell, depending on
|
||||
the sign of COUNT.
|
||||
|
||||
If USE-REGION is non-nil and the region is active, return the
|
||||
region bounds instead.
|
||||
|
||||
If NO-HEADER is non-nil, do not include the cell boundary line."
|
||||
(if (and use-region (use-region-p))
|
||||
(list (region-beginning) (region-end))
|
||||
(setq count (or count 1))
|
||||
(save-excursion
|
||||
(let ((end (progn (code-cells-forward-cell (max count 1))
|
||||
(point))))
|
||||
(code-cells-backward-cell (abs count))
|
||||
(when no-header (forward-line))
|
||||
(list (point) end)))))
|
||||
|
||||
(defun code-cells--bounds-of-cell-relative-from (distance)
|
||||
"Return the bounds of the cell DISTANCE cells away from the current one."
|
||||
(save-excursion
|
||||
(when (/= 0 distance)
|
||||
;; Except when at the boundary, `(code-cells-forward-cell -1)' doesn't
|
||||
;; move out of current cell
|
||||
(unless (looking-at-p code-cells-boundary-regexp)
|
||||
(code-cells-backward-cell))
|
||||
(code-cells-forward-cell distance))
|
||||
(code-cells--bounds)))
|
||||
|
||||
(defun code-cells-move-cell-down (arg)
|
||||
"Move current code cell vertically ARG cells.
|
||||
Move up when ARG is negative and move down otherwise."
|
||||
(interactive "p")
|
||||
(pcase-let ((`(,current-beg ,current-end) (code-cells--bounds))
|
||||
(`(,next-beg ,next-end) (code-cells--bounds-of-cell-relative-from arg)))
|
||||
(unless (save-excursion
|
||||
(and (/= current-beg next-beg)
|
||||
(goto-char current-beg)
|
||||
(looking-at-p code-cells-boundary-regexp)
|
||||
(goto-char next-beg)
|
||||
(looking-at-p code-cells-boundary-regexp)))
|
||||
(user-error "Can't move cell"))
|
||||
(transpose-regions current-beg current-end next-beg next-end)))
|
||||
|
||||
;;;###autoload
|
||||
(defun code-cells-move-cell-up (&optional arg)
|
||||
"Move current code cell vertically up ARG cells."
|
||||
(interactive "p")
|
||||
(code-cells-move-cell-down (- arg)))
|
||||
|
||||
;;;###autoload
|
||||
(defun code-cells-mark-cell (&optional arg)
|
||||
"Put point at the beginning of this cell, mark at end.
|
||||
If ARG is non-nil, mark that many cells."
|
||||
(interactive "p")
|
||||
(pcase-let ((`(,start ,end) (code-cells--bounds arg)))
|
||||
(goto-char start)
|
||||
(push-mark end nil t)))
|
||||
|
||||
;;;###autoload
|
||||
(defun code-cells-comment-or-uncomment (&optional arg)
|
||||
"Comment or uncomment the current code cell.
|
||||
|
||||
ARG, if provided, is the number of comment characters to add or
|
||||
remove."
|
||||
(interactive "P")
|
||||
(pcase-let* ((`(,header ,end) (code-cells--bounds arg))
|
||||
(start (save-excursion
|
||||
(goto-char header)
|
||||
(forward-line)
|
||||
(point))))
|
||||
(comment-or-uncomment-region start end)))
|
||||
|
||||
;;;###autoload
|
||||
(defun code-cells-command (fun &rest options)
|
||||
"Return an anonymous command calling FUN on the current cell.
|
||||
|
||||
FUN is a function that takes two character positions as argument.
|
||||
Most interactive commands that act on a region are of this form
|
||||
and can be used here.
|
||||
|
||||
If OPTIONS contains the keyword :use-region, the command will act
|
||||
on the region instead of the current cell when appropriate.
|
||||
|
||||
If OPTIONS contains the keyword :pulse, provide visual feedback
|
||||
via `pulse-momentary-highlight-region'."
|
||||
(let ((use-region (car (memq :use-region options)))
|
||||
(pulse (car (memq :pulse options))))
|
||||
(lambda ()
|
||||
(interactive)
|
||||
(pcase-let ((`(,start ,end) (code-cells--bounds nil use-region)))
|
||||
(when pulse (pulse-momentary-highlight-region start end))
|
||||
(funcall fun start end)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun code-cells-speed-key (command)
|
||||
"Return a speed key definition, suitable for passing to `define-key'.
|
||||
The resulting keybinding will only have any effect when the point
|
||||
is at the beginning of a cell heading, in which case it executes
|
||||
COMMAND."
|
||||
(list 'menu-item nil command
|
||||
:filter (lambda (d)
|
||||
(when (and (bolp)
|
||||
(looking-at code-cells-boundary-regexp))
|
||||
d))))
|
||||
|
||||
;;; Code evaluation
|
||||
|
||||
(defcustom code-cells-eval-region-commands
|
||||
`((drepl--current . drepl-eval-region)
|
||||
(jupyter-repl-interaction-mode . ,(apply-partially 'jupyter-eval-region nil))
|
||||
(python-mode . python-shell-send-region)
|
||||
(emacs-lisp-mode . eval-region)
|
||||
(lisp-interaction-mode . eval-region))
|
||||
"Alist of commands to evaluate a region.
|
||||
The keys are major or minor modes and the values are functions
|
||||
taking region bounds as argument."
|
||||
:type '(alist :key-type symbol :value-type symbol))
|
||||
|
||||
;;;###autoload
|
||||
(defun code-cells-eval (start end)
|
||||
"Evaluate code according to current modes.
|
||||
The first suitable function from `code-cells-eval-region-commands'
|
||||
is used to do the job.
|
||||
|
||||
Interactively, evaluate the region, if active, otherwise the
|
||||
current code cell. With a numeric prefix, evaluate that many
|
||||
code cells.
|
||||
|
||||
Called from Lisp, evaluate region between START and END."
|
||||
(interactive (code-cells--bounds (prefix-numeric-value current-prefix-arg)
|
||||
'use-region
|
||||
'no-header))
|
||||
(funcall
|
||||
(or (seq-some (pcase-lambda (`(,mode . ,fun))
|
||||
(when (or (and (boundp mode) (symbol-value mode))
|
||||
(derived-mode-p mode))
|
||||
fun))
|
||||
code-cells-eval-region-commands)
|
||||
(user-error
|
||||
"No entry for the current modes in `code-cells-eval-region-commands'"))
|
||||
start end)
|
||||
(pulse-momentary-highlight-region start end))
|
||||
|
||||
;;;###autoload
|
||||
(defun code-cells-eval-above (arg)
|
||||
"Evaluate this and all above cells.
|
||||
ARG (interactively, the prefix argument) specifies how many
|
||||
additional cells after point to include."
|
||||
(interactive "p")
|
||||
(code-cells-eval (point-min) (save-excursion
|
||||
(code-cells-forward-cell arg)
|
||||
(point))))
|
||||
|
||||
;;; Minor mode
|
||||
|
||||
(defvar-local code-cells--saved-vars nil
|
||||
"A place to save variables before activating `code-cells-mode'.")
|
||||
|
||||
(defun code-cells--outline-level ()
|
||||
"Compute the outline level, taking code cells into account.
|
||||
To be used as the value of the variable `outline-level'.
|
||||
|
||||
At a cell boundary, returns the cell outline level, as determined by
|
||||
`code-cells-boundary-regexp'. Otherwise, returns the sum of the
|
||||
outline level as determined by the major mode and the current cell
|
||||
level."
|
||||
(let* ((at-boundary (looking-at-p code-cells-boundary-regexp))
|
||||
(mm-level (if at-boundary
|
||||
0
|
||||
(funcall (car code-cells--saved-vars))))
|
||||
(cell-level (if (or at-boundary
|
||||
(save-excursion
|
||||
(re-search-backward
|
||||
code-cells-boundary-regexp nil t)))
|
||||
(if (match-string 1)
|
||||
(- (match-end 1) (match-beginning 1))
|
||||
1)
|
||||
0)))
|
||||
(+ cell-level mm-level)))
|
||||
|
||||
(defface code-cells-header-line '((t :extend t :overline t :inherit font-lock-comment-face))
|
||||
"Face used by `code-cells-mode' to highlight cell boundaries.")
|
||||
|
||||
(defun code-cells--font-lock-keywords ()
|
||||
"Font lock keywords to highlight cell boundaries."
|
||||
`((,(rx (regexp code-cells-boundary-regexp) (* any) "\n")
|
||||
0 'code-cells-header-line append)))
|
||||
|
||||
;;;###autoload
|
||||
(define-minor-mode code-cells-mode
|
||||
"Minor mode for cell-oriented code."
|
||||
:keymap (make-sparse-keymap)
|
||||
(if code-cells-mode
|
||||
(progn
|
||||
(setq-local
|
||||
code-cells--saved-vars (list outline-level
|
||||
outline-regexp
|
||||
outline-heading-end-regexp
|
||||
paragraph-start)
|
||||
outline-level 'code-cells--outline-level
|
||||
outline-regexp (rx (or (regexp code-cells-boundary-regexp)
|
||||
(regexp outline-regexp)))
|
||||
outline-heading-end-regexp "\n"
|
||||
paragraph-separate (rx (or (regexp paragraph-separate)
|
||||
(regexp code-cells-boundary-regexp))))
|
||||
(font-lock-add-keywords nil (code-cells--font-lock-keywords)))
|
||||
(setq-local outline-level (pop code-cells--saved-vars)
|
||||
outline-regexp (pop code-cells--saved-vars)
|
||||
outline-heading-end-regexp (pop code-cells--saved-vars)
|
||||
paragraph-separate (pop code-cells--saved-vars))
|
||||
(font-lock-remove-keywords nil (code-cells--font-lock-keywords)))
|
||||
(font-lock-flush))
|
||||
|
||||
;;;###autoload
|
||||
(defun code-cells-mode-maybe ()
|
||||
"Turn on `code-cells-mode' if the buffer appears to contain cells.
|
||||
This function is useful when added to a major mode hook."
|
||||
(when (save-excursion
|
||||
(goto-char (point-min))
|
||||
(re-search-forward code-cells-boundary-regexp 5000 t))
|
||||
(code-cells-mode)))
|
||||
|
||||
(let ((map (make-sparse-keymap)))
|
||||
(define-key code-cells-mode-map "\C-c%" map)
|
||||
(define-key map ";" 'code-cells-comment-or-uncomment)
|
||||
(define-key map "@" 'code-cells-mark-cell)
|
||||
(define-key map "b" 'code-cells-backward-cell)
|
||||
(define-key map "f" 'code-cells-forward-cell)
|
||||
(define-key map "B" 'code-cells-move-cell-up)
|
||||
(define-key map "F" 'code-cells-move-cell-down)
|
||||
(define-key map "e" 'code-cells-eval))
|
||||
|
||||
;;; Jupyter notebook conversion
|
||||
|
||||
(defcustom code-cells-convert-ipynb-style
|
||||
'(("jupytext" "--to" "ipynb")
|
||||
("jupytext" "--to" "auto:percent")
|
||||
code-cells--guess-mode
|
||||
code-cells-convert-ipynb-hook)
|
||||
"Determines how to convert ipynb files for editing.
|
||||
The first two entries are lists of strings: the command name and
|
||||
arguments used, respectively, to convert to and from ipynb
|
||||
format.
|
||||
|
||||
The third entry is a function called with no arguments to
|
||||
determine the major mode to be called. The default setting tries
|
||||
to guess it from the notebook metadata.
|
||||
|
||||
The fourth entry, also optional, is a hook run after the new
|
||||
major mode is activated."
|
||||
:type '(list (repeat string) (repeat string) function symbol))
|
||||
|
||||
(defvar code-cells-convert-ipynb-hook '(code-cells-mode)
|
||||
"Hook used in the default `code-cells-convert-ipynb-style'.")
|
||||
|
||||
(defun code-cells--call-process (buffer command)
|
||||
"Pipe BUFFER through COMMAND, with output to the current buffer.
|
||||
Returns the process exit code. COMMAND is a list of strings, the
|
||||
program name followed by arguments."
|
||||
(unless (executable-find (car command))
|
||||
(error "Can't find %s" (car command)))
|
||||
(let ((logfile (make-temp-file "emacs-code-cells-")))
|
||||
(unwind-protect
|
||||
(prog1
|
||||
(apply #'call-process-region nil nil (car command) nil
|
||||
(list buffer logfile) nil
|
||||
(cdr command))
|
||||
(with-temp-buffer
|
||||
(insert-file-contents logfile)
|
||||
(unless (zerop (buffer-size))
|
||||
(lwarn 'code-cells :warning
|
||||
"Notebook conversion command %s said:\n%s"
|
||||
command
|
||||
(buffer-substring-no-properties
|
||||
(point-min) (point-max))))))
|
||||
(delete-file logfile))))
|
||||
|
||||
(defun code-cells--guess-mode ()
|
||||
"Guess major mode associated to the current ipynb buffer."
|
||||
(require 'json)
|
||||
(declare-function json-read "json.el")
|
||||
(goto-char (point-min))
|
||||
(let* ((nb (cl-letf ;; Skip over the possibly huge "cells" section
|
||||
(((symbol-function 'json-read-array) 'forward-sexp))
|
||||
(json-read)))
|
||||
(lang (let-alist nb
|
||||
(or .metadata.kernelspec.language
|
||||
.metadata.jupytext.main_language)))
|
||||
(mode (intern (concat lang "-mode"))))
|
||||
(alist-get mode (bound-and-true-p major-mode-remap-alist) mode)))
|
||||
|
||||
;;;###autoload
|
||||
(defun code-cells-convert-ipynb ()
|
||||
"Convert buffer from ipynb format to a regular script."
|
||||
(interactive)
|
||||
(let* ((mode (funcall (or (nth 2 code-cells-convert-ipynb-style)
|
||||
(progn ;For backwards compatibility with v0.3
|
||||
(lwarn 'code-cells :warning "\
|
||||
The third entry of `code-cells-convert-ipynb-style' should not be nil.")
|
||||
#'code-cells--guess-mode))))
|
||||
(exit (progn
|
||||
(goto-char (point-min))
|
||||
(code-cells--call-process t (nth 1 code-cells-convert-ipynb-style)))))
|
||||
(unless (zerop exit)
|
||||
(delete-region (point-min) (point))
|
||||
(error "Error converting notebook (exit code %s)" exit))
|
||||
(delete-region (point) (point-max))
|
||||
(goto-char (point-min))
|
||||
(set-buffer-modified-p nil)
|
||||
(add-hook 'write-file-functions #'code-cells-write-ipynb 80 t)
|
||||
(when (fboundp mode)
|
||||
(funcall mode)
|
||||
(run-hooks (nth 3 code-cells-convert-ipynb-style)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun code-cells-write-ipynb (&optional file)
|
||||
"Convert buffer to ipynb format and write to FILE.
|
||||
Interactively, asks for the file name. When called from Lisp,
|
||||
FILE defaults to the current buffer file name."
|
||||
(interactive "F")
|
||||
(let* ((file (or file buffer-file-name))
|
||||
(temp (generate-new-buffer " *cells--call-process output*"))
|
||||
(exit (code-cells--call-process temp (nth 0 code-cells-convert-ipynb-style))))
|
||||
(unless (eq 0 exit)
|
||||
(error "Error converting notebook (exit code %s)" exit))
|
||||
(with-current-buffer temp
|
||||
(write-region nil nil file)
|
||||
(kill-buffer))
|
||||
(when (eq file buffer-file-name)
|
||||
(set-buffer-modified-p nil)
|
||||
(set-visited-file-modtime))
|
||||
'job-done))
|
||||
|
||||
;;;###autoload
|
||||
(add-to-list 'auto-mode-alist '("\\.ipynb\\'" . code-cells-convert-ipynb))
|
||||
|
||||
(provide 'code-cells)
|
||||
;;; code-cells.el ends here
|
||||
19
lisp/company-anaconda/company-anaconda-pkg.el
Normal file
19
lisp/company-anaconda/company-anaconda-pkg.el
Normal file
@@ -0,0 +1,19 @@
|
||||
(define-package "company-anaconda" "20230821.2126" "Anaconda backend for company-mode"
|
||||
'((emacs "25.1")
|
||||
(company "0.8.0")
|
||||
(anaconda-mode "0.1.1")
|
||||
(cl-lib "0.5.0")
|
||||
(dash "2.6.0")
|
||||
(s "1.9"))
|
||||
:commit "14867265e474f7a919120bbac74870c3256cbacf" :authors
|
||||
'(("Artem Malyshev" . "proofit404@gmail.com"))
|
||||
:maintainers
|
||||
'(("Artem Malyshev" . "proofit404@gmail.com"))
|
||||
:maintainer
|
||||
'("Artem Malyshev" . "proofit404@gmail.com")
|
||||
:keywords
|
||||
'("convenience" "company" "anaconda")
|
||||
:url "https://github.com/proofit404/anaconda-mode")
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
;; End:
|
||||
@@ -4,10 +4,9 @@
|
||||
|
||||
;; Author: Artem Malyshev <proofit404@gmail.com>
|
||||
;; URL: https://github.com/proofit404/anaconda-mode
|
||||
;; Package-Version: 20200404.1859
|
||||
;; Package-Commit: da1566db41a68809ef7f91ebf2de28118067c89b
|
||||
;; Version: 0.2.0
|
||||
;; Package-Requires: ((company "0.8.0") (anaconda-mode "0.1.1") (cl-lib "0.5.0") (dash "2.6.0") (s "1.9"))
|
||||
;; Package-Requires: ((emacs "25.1") (company "0.8.0") (anaconda-mode "0.1.1") (cl-lib "0.5.0") (dash "2.6.0") (s "1.9"))
|
||||
;; Keywords: convenience company anaconda
|
||||
|
||||
;; 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
|
||||
15
lisp/company-ledger/company-ledger-pkg.el
Normal file
15
lisp/company-ledger/company-ledger-pkg.el
Normal file
@@ -0,0 +1,15 @@
|
||||
(define-package "company-ledger" "20210910.250" "Fuzzy auto-completion for Ledger & friends"
|
||||
'((emacs "24.3")
|
||||
(company "0.8.0"))
|
||||
:commit "55fdddd6c5e9c061c685b474ef5e148a4ac9b576" :authors
|
||||
'(("Debanjum Singh Solanky" . "debanjumATgmailDOTcom"))
|
||||
:maintainers
|
||||
'(("Debanjum Singh Solanky" . "debanjumATgmailDOTcom"))
|
||||
:maintainer
|
||||
'("Debanjum Singh Solanky" . "debanjumATgmailDOTcom")
|
||||
:keywords
|
||||
'("abbrev" "matching" "auto-complete" "beancount" "ledger" "company")
|
||||
:url "https://github.com/debanjum/company-ledger")
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
;; End:
|
||||
@@ -5,8 +5,6 @@
|
||||
;; Author: Debanjum Singh Solanky <debanjum AT gmail DOT com>
|
||||
;; Description: Fuzzy auto-completion for ledger & friends
|
||||
;; Keywords: abbrev, matching, auto-complete, beancount, ledger, company
|
||||
;; Package-Version: 20210910.250
|
||||
;; Package-Commit: 55fdddd6c5e9c061c685b474ef5e148a4ac9b576
|
||||
;; Version: 0.1.0
|
||||
;; Package-Requires: ((emacs "24.3") (company "0.8.0"))
|
||||
;; URL: https://github.com/debanjum/company-ledger
|
||||
16
lisp/company-quickhelp/company-quickhelp-pkg.el
Normal file
16
lisp/company-quickhelp/company-quickhelp-pkg.el
Normal file
@@ -0,0 +1,16 @@
|
||||
(define-package "company-quickhelp" "20231026.1714" "Popup documentation for completion candidates"
|
||||
'((emacs "24.3")
|
||||
(company "0.8.9")
|
||||
(pos-tip "0.4.6"))
|
||||
:commit "5bda859577582cc42d16fc0eaf5f7c8bedfd9e69" :authors
|
||||
'(("Lars Andersen" . "expez@expez.com"))
|
||||
:maintainers
|
||||
'(("Lars Andersen" . "expez@expez.com"))
|
||||
:maintainer
|
||||
'("Lars Andersen" . "expez@expez.com")
|
||||
:keywords
|
||||
'("company" "popup" "documentation" "quickhelp")
|
||||
:url "https://www.github.com/expez/company-quickhelp")
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
;; End:
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
;; Author: Lars Andersen <expez@expez.com>
|
||||
;; URL: https://www.github.com/expez/company-quickhelp
|
||||
;; Package-Version: 20221212.534
|
||||
;; Package-Commit: 9505fb09d064581da142d75c139d48b5cf695bd5
|
||||
;; Keywords: company popup documentation quickhelp
|
||||
;; Version: 2.2.0
|
||||
;; Package-Requires: ((emacs "24.3") (company "0.8.9") (pos-tip "0.4.6"))
|
||||
@@ -55,7 +53,7 @@
|
||||
"Delay, in seconds, before the quickhelp popup appears.
|
||||
|
||||
If set to nil the popup won't automatically appear, but can still
|
||||
be triggered manually using `company-quickhelp-show'."
|
||||
be triggered manually using `company-quickhelp-manual-begin'."
|
||||
:type '(choice (number :tag "Delay in seconds")
|
||||
(const :tag "Don't popup help automatically" nil))
|
||||
:group 'company-quickhelp)
|
||||
@@ -235,7 +233,6 @@ currently active `company' completion candidate."
|
||||
(defun company-quickhelp-hide ()
|
||||
(company-cancel))
|
||||
|
||||
|
||||
(defun company-quickhelp-pos-tip-available-p ()
|
||||
"Return t if and only if pos-tip is expected work in the current frame."
|
||||
(and
|
||||
15
lisp/company-statistics/company-statistics-pkg.el
Normal file
15
lisp/company-statistics/company-statistics-pkg.el
Normal file
@@ -0,0 +1,15 @@
|
||||
(define-package "company-statistics" "20170210.1933" "Sort candidates using completion history"
|
||||
'((emacs "24.3")
|
||||
(company "0.8.5"))
|
||||
:commit "e62157d43b2c874d2edbd547c3bdfb05d0a7ae5c" :authors
|
||||
'(("Ingo Lohmar" . "i.lohmar@gmail.com"))
|
||||
:maintainers
|
||||
'(("Ingo Lohmar" . "i.lohmar@gmail.com"))
|
||||
:maintainer
|
||||
'("Ingo Lohmar" . "i.lohmar@gmail.com")
|
||||
:keywords
|
||||
'("abbrev" "convenience" "matching")
|
||||
:url "https://github.com/company-mode/company-statistics")
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
;; End:
|
||||
375
lisp/company-statistics/company-statistics.el
Normal file
375
lisp/company-statistics/company-statistics.el
Normal file
@@ -0,0 +1,375 @@
|
||||
;;; company-statistics.el --- Sort candidates using completion history -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2014-2017 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Ingo Lohmar <i.lohmar@gmail.com>
|
||||
;; URL: https://github.com/company-mode/company-statistics
|
||||
;; Version: 0.2.3
|
||||
;; Keywords: abbrev, convenience, matching
|
||||
;; Package-Requires: ((emacs "24.3") (company "0.8.5"))
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
|
||||
;; GNU Emacs is free software: you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; GNU Emacs is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
;;
|
||||
;; Package installed from elpa.gnu.org:
|
||||
;;
|
||||
;; (add-hook 'after-init-hook #'company-statistics-mode)
|
||||
;;
|
||||
;; Manually installed: make sure that this file is in load-path, and
|
||||
;;
|
||||
;; (require 'company-statistics)
|
||||
;; (company-statistics-mode)
|
||||
;;
|
||||
;; Every time a candidate is chosen using company-mode, we keep track of this
|
||||
;; (for a limited amount of recent choices). When presenting completion
|
||||
;; candidates next time, they are sorted according to the score thus acquired.
|
||||
;;
|
||||
;; The same candidate might occur in different modes, projects, files etc., and
|
||||
;; possibly has a different meaning each time. Therefore along with the
|
||||
;; completion, we store some context information. In the default (heavy)
|
||||
;; configuration, we track the overall frequency, the major-mode of the buffer,
|
||||
;; the last preceding keyword, the parent symbol, and the filename (if it
|
||||
;; applies), and the same criteria are used to score all possible candidates.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'company)
|
||||
|
||||
(defgroup company-statistics nil
|
||||
"Completion candidates ranking by historical statistics."
|
||||
:group 'company)
|
||||
|
||||
(defcustom company-statistics-size 400
|
||||
"Number of completion choices that `company-statistics' keeps track of.
|
||||
As this is a global cache, making it too small defeats the purpose."
|
||||
:type 'integer
|
||||
:initialize #'custom-initialize-default
|
||||
:set #'company-statistics--log-resize)
|
||||
|
||||
(defcustom company-statistics-file
|
||||
(concat user-emacs-directory "company-statistics-cache.el")
|
||||
"File to save company-statistics state."
|
||||
:type 'string)
|
||||
|
||||
(defcustom company-statistics-auto-save t
|
||||
"Whether to save the statistics when leaving emacs."
|
||||
:type 'boolean)
|
||||
|
||||
(defcustom company-statistics-auto-restore t
|
||||
"Whether to restore statistics when company-statistics is enabled and has
|
||||
not been used before."
|
||||
:type 'boolean)
|
||||
|
||||
(defcustom company-statistics-capture-context #'company-statistics-capture-context-heavy
|
||||
"Function called with single argument (t if completion started manually).
|
||||
This is the place to store any context information for a completion run."
|
||||
:type 'function)
|
||||
|
||||
(defcustom company-statistics-score-change #'company-statistics-score-change-heavy
|
||||
"Function called with completion choice. Using arbitrary other info,
|
||||
it should produce an alist, each entry labeling a context and the
|
||||
associated score update: ((ctx-a . 1) (\"str\" . 0.5) (nil . 1)). Nil is
|
||||
the global context."
|
||||
:type 'function)
|
||||
|
||||
(defcustom company-statistics-score-calc #'company-statistics-score-calc-heavy
|
||||
"Function called with completion candidate. Using arbitrary other info,
|
||||
eg, on the current context, it should evaluate to the candidate's score (a
|
||||
number)."
|
||||
:type 'function)
|
||||
|
||||
;; internal vars, persistence
|
||||
|
||||
(defvar company-statistics--scores nil
|
||||
"Store selection frequency of candidates in given contexts.")
|
||||
|
||||
(defvar company-statistics--log nil
|
||||
"Ring keeping a log of statistics updates.")
|
||||
|
||||
(defvar company-statistics--index nil
|
||||
"Index into the log.")
|
||||
|
||||
(defun company-statistics--init ()
|
||||
"Initialize company-statistics."
|
||||
(setq company-statistics--scores
|
||||
(make-hash-table :test #'equal :size company-statistics-size))
|
||||
(setq company-statistics--log (make-vector company-statistics-size nil)
|
||||
company-statistics--index 0))
|
||||
|
||||
(defun company-statistics--initialized-p ()
|
||||
(hash-table-p company-statistics--scores))
|
||||
|
||||
(defun company-statistics--log-resize (_option new-size)
|
||||
(when (company-statistics--initialized-p)
|
||||
;; hash scoresheet auto-resizes, but log does not
|
||||
(let ((new-hist (make-vector new-size nil))
|
||||
;; use actual length, to also work for freshly restored stats
|
||||
(company-statistics-size (length company-statistics--log)))
|
||||
;; copy newest entries (possibly nil) to new-hist
|
||||
(dolist (i (number-sequence 0 (1- (min new-size company-statistics-size))))
|
||||
(let ((old-i (mod (+ (- company-statistics--index new-size) i)
|
||||
company-statistics-size)))
|
||||
(aset new-hist i (aref company-statistics--log old-i))))
|
||||
;; remove discarded log entry (when shrinking) from scores
|
||||
(when (< new-size company-statistics-size)
|
||||
(dolist (i (number-sequence
|
||||
company-statistics--index
|
||||
(+ company-statistics-size
|
||||
company-statistics--index
|
||||
(1- new-size))))
|
||||
(company-statistics--log-revert (mod i company-statistics-size))))
|
||||
(setq company-statistics--log new-hist)
|
||||
(setq company-statistics--index (if (<= new-size company-statistics-size)
|
||||
0
|
||||
company-statistics-size))))
|
||||
(setq company-statistics-size new-size))
|
||||
|
||||
(defun company-statistics--save ()
|
||||
"Save statistics."
|
||||
(with-temp-buffer
|
||||
(set-buffer-multibyte nil)
|
||||
(let (print-level print-length)
|
||||
(encode-coding-string
|
||||
(format
|
||||
"%S"
|
||||
`(setq
|
||||
company-statistics--scores ,company-statistics--scores
|
||||
company-statistics--log ,company-statistics--log
|
||||
company-statistics--index ,company-statistics--index))
|
||||
'utf-8 nil (current-buffer))
|
||||
(let ((coding-system-for-write 'binary))
|
||||
(write-region nil nil company-statistics-file)))))
|
||||
|
||||
(defun company-statistics--maybe-save ()
|
||||
(when (and (company-statistics--initialized-p)
|
||||
company-statistics-auto-save)
|
||||
(company-statistics--save)))
|
||||
|
||||
(defun company-statistics--load ()
|
||||
"Restore statistics."
|
||||
(load company-statistics-file 'noerror nil 'nosuffix))
|
||||
|
||||
;; score calculation for insert/retrieval --- can be changed on-the-fly
|
||||
|
||||
(defun company-statistics-score-change-light (_cand)
|
||||
"Count for global score and mode context."
|
||||
(list (cons nil 1)
|
||||
(cons major-mode 1))) ;major-mode is never nil
|
||||
|
||||
(defun company-statistics-score-calc-light (cand)
|
||||
"Global score, and bonus for matching major mode."
|
||||
(let ((scores (gethash cand company-statistics--scores)))
|
||||
(if scores
|
||||
;; cand may be in scores and still have no global score left
|
||||
(+ (or (cdr (assoc nil scores)) 0)
|
||||
(or (cdr (assoc major-mode scores)) 0))
|
||||
0)))
|
||||
|
||||
(defvar company-statistics--context nil
|
||||
"Current completion context, a list of entries searched using `assoc'.")
|
||||
|
||||
(defun company-statistics--last-keyword ()
|
||||
"Return last keyword, ie, text of region fontified with the
|
||||
font-lock-keyword-face up to point, or nil."
|
||||
(let ((face-pos (point)))
|
||||
(while (and (number-or-marker-p face-pos)
|
||||
(< (point-min) face-pos)
|
||||
(not (eq (get-text-property (1- face-pos) 'face)
|
||||
'font-lock-keyword-face)))
|
||||
(setq face-pos
|
||||
(previous-single-property-change face-pos 'face nil (point-min))))
|
||||
(when (and (number-or-marker-p face-pos)
|
||||
(eq (get-text-property (max (point-min) (1- face-pos)) 'face)
|
||||
'font-lock-keyword-face))
|
||||
(list :keyword
|
||||
(buffer-substring-no-properties
|
||||
(previous-single-property-change face-pos 'face nil (point-min))
|
||||
face-pos)))))
|
||||
|
||||
(defun company-statistics--parent-symbol ()
|
||||
"Return symbol immediately preceding current completion prefix, or nil.
|
||||
May be separated by punctuation, but not by whitespace."
|
||||
;; expects to be at start of company-prefix; little sense for lisps
|
||||
(let ((preceding (save-excursion
|
||||
(unless (zerop (skip-syntax-backward "."))
|
||||
(substring-no-properties (symbol-name (symbol-at-point)))))))
|
||||
(when preceding
|
||||
(list :symbol preceding))))
|
||||
|
||||
(defun company-statistics--file-name ()
|
||||
"Return buffer file name, or nil."
|
||||
(when buffer-file-name
|
||||
(list :file buffer-file-name)))
|
||||
|
||||
(defun company-statistics-capture-context-heavy (_manual)
|
||||
"Calculate some context, once for the whole completion run."
|
||||
(save-excursion
|
||||
(backward-char (length company-prefix))
|
||||
(setq company-statistics--context
|
||||
(delq nil
|
||||
(list (company-statistics--last-keyword)
|
||||
(company-statistics--parent-symbol)
|
||||
(company-statistics--file-name))))))
|
||||
|
||||
(defun company-statistics-score-change-heavy (_cand)
|
||||
"Count for global score, mode context, last keyword, parent symbol,
|
||||
buffer file name."
|
||||
(let ((last-kwd (assoc :keyword company-statistics--context))
|
||||
(parent-symbol (assoc :symbol company-statistics--context))
|
||||
(file (assoc :file company-statistics--context)))
|
||||
(nconc ;when's nil is removed
|
||||
(list (cons nil 1)
|
||||
(cons major-mode 1)) ;major-mode is never nil
|
||||
;; only add pieces of context if non-nil
|
||||
(when last-kwd (list (cons last-kwd 1)))
|
||||
(when parent-symbol (list (cons parent-symbol 1)))
|
||||
(when file (list (cons file 1))))))
|
||||
|
||||
(defun company-statistics-score-calc-heavy (cand)
|
||||
"Global score, and bonus for matching major mode, last keyword, parent
|
||||
symbol, buffer file name."
|
||||
(let ((scores (gethash cand company-statistics--scores))
|
||||
(last-kwd (assoc :keyword company-statistics--context))
|
||||
(parent-symbol (assoc :symbol company-statistics--context))
|
||||
(file (assoc :file company-statistics--context)))
|
||||
(if scores
|
||||
;; cand may be in scores and still have no global score left
|
||||
(+ (or (cdr (assoc nil scores)) 0)
|
||||
(or (cdr (assoc major-mode scores)) 0)
|
||||
;; some context may not apply, make sure to not get nil context
|
||||
(or (cdr (when last-kwd (assoc last-kwd scores))) 0)
|
||||
(or (cdr (when parent-symbol (assoc parent-symbol scores))) 0)
|
||||
(or (cdr (when file (assoc file scores))) 0))
|
||||
0)))
|
||||
|
||||
;; score manipulation in one place --- know about hash value alist structure
|
||||
|
||||
(defun company-statistics--alist-update (alist updates merger &optional filter)
|
||||
"Return new alist with conses from ALIST. Their cdrs are updated
|
||||
to (merger cdr update-cdr) if the UPDATES alist contains an entry with an
|
||||
equal-matching car. If FILTER called with the result is non-nil, remove
|
||||
the cons from the result. If no matching cons exists in ALIST, add the new
|
||||
one. ALIST structure and cdrs may be changed!"
|
||||
(let ((filter (or filter 'ignore))
|
||||
(updated alist)
|
||||
(new nil))
|
||||
(mapc
|
||||
(lambda (upd)
|
||||
(let ((found (assoc (car upd) alist)))
|
||||
(if found
|
||||
(let ((result (funcall merger (cdr found) (cdr upd))))
|
||||
(if (funcall filter result)
|
||||
(setq updated (delete found updated))
|
||||
(setcdr found result)))
|
||||
(push upd new))))
|
||||
updates)
|
||||
(nconc updated new)))
|
||||
|
||||
(defun company-statistics--scores-add (cand score-updates)
|
||||
(puthash cand
|
||||
(company-statistics--alist-update
|
||||
(gethash cand company-statistics--scores)
|
||||
score-updates
|
||||
#'+)
|
||||
company-statistics--scores))
|
||||
|
||||
(defun company-statistics--log-revert (&optional index)
|
||||
"Revert score updates for log entry. INDEX defaults to
|
||||
`company-statistics--index'."
|
||||
(let ((hist-entry
|
||||
(aref company-statistics--log
|
||||
(or index company-statistics--index))))
|
||||
(when hist-entry ;ignore nil entry
|
||||
(let* ((cand (car hist-entry))
|
||||
(score-updates (cdr hist-entry))
|
||||
(new-scores
|
||||
(company-statistics--alist-update
|
||||
(gethash cand company-statistics--scores)
|
||||
score-updates
|
||||
#'-
|
||||
#'zerop)))
|
||||
(if new-scores ;sth left
|
||||
(puthash cand new-scores company-statistics--scores)
|
||||
(remhash cand company-statistics--scores))))))
|
||||
|
||||
(defun company-statistics--log-store (result score-updates)
|
||||
"Insert/overwrite result and associated score updates."
|
||||
(aset company-statistics--log company-statistics--index
|
||||
(cons result score-updates))
|
||||
(setq company-statistics--index
|
||||
(mod (1+ company-statistics--index) company-statistics-size)))
|
||||
|
||||
;; core functions: updater, actual sorting transformer, minor-mode
|
||||
|
||||
(defun company-statistics--start (manual)
|
||||
(funcall company-statistics-capture-context manual))
|
||||
|
||||
(defun company-statistics--finished (result)
|
||||
"After completion, update scores and log."
|
||||
(let* ((score-updates (funcall company-statistics-score-change result))
|
||||
(result (substring-no-properties result)))
|
||||
(company-statistics--scores-add result score-updates)
|
||||
(company-statistics--log-revert)
|
||||
(company-statistics--log-store result score-updates)))
|
||||
|
||||
(defun company-sort-by-statistics (candidates)
|
||||
"Sort candidates by historical statistics. Stable sort, so order is only
|
||||
changed for candidates distinguishable by score."
|
||||
(setq candidates
|
||||
(sort candidates
|
||||
(lambda (cand1 cand2)
|
||||
(> (funcall company-statistics-score-calc cand1)
|
||||
(funcall company-statistics-score-calc cand2))))))
|
||||
|
||||
;;;###autoload
|
||||
(define-minor-mode company-statistics-mode
|
||||
"Statistical sorting for company-mode. Ranks completion candidates by
|
||||
the frequency with which they have been chosen in recent (as given by
|
||||
`company-statistics-size') history.
|
||||
|
||||
Turning this mode on and off preserves the statistics. They are also
|
||||
preserved automatically between Emacs sessions in the default
|
||||
configuration. You can customize this behavior with
|
||||
`company-statistics-auto-save', `company-statistics-auto-restore' and
|
||||
`company-statistics-file'."
|
||||
nil nil nil
|
||||
:global t
|
||||
(if company-statistics-mode
|
||||
(progn
|
||||
(unless (company-statistics--initialized-p)
|
||||
(if (and company-statistics-auto-restore
|
||||
(company-statistics--load))
|
||||
;; maybe of different size
|
||||
(company-statistics--log-resize nil company-statistics-size)
|
||||
(company-statistics--init)))
|
||||
(add-to-list 'company-transformers
|
||||
'company-sort-by-statistics 'append)
|
||||
(add-hook 'company-completion-started-hook
|
||||
'company-statistics--start)
|
||||
(add-hook 'company-completion-finished-hook
|
||||
'company-statistics--finished))
|
||||
(setq company-transformers
|
||||
(delq 'company-sort-by-statistics company-transformers))
|
||||
(remove-hook 'company-completion-started-hook
|
||||
'company-statistics--start)
|
||||
(remove-hook 'company-completion-finished-hook
|
||||
'company-statistics--finished)))
|
||||
|
||||
(add-hook 'kill-emacs-hook 'company-statistics--maybe-save)
|
||||
|
||||
(provide 'company-statistics)
|
||||
;;; company-statistics.el ends here
|
||||
@@ -5,6 +5,8 @@
|
||||
(web-completion-data "0.1.0"))
|
||||
:commit "e0c6bfa3ae7006c73d0fdfc0fdb69816309baf1b" :authors
|
||||
'(("Olexandr Sydorchuk" . "olexandr.syd@gmail.com"))
|
||||
:maintainers
|
||||
'(("Olexandr Sydorchuk" . "olexandr.syd@gmail.com"))
|
||||
:maintainer
|
||||
'("Olexandr Sydorchuk" . "olexandr.syd@gmail.com")
|
||||
:keywords
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; company-abbrev.el --- company-mode completion backend for abbrev
|
||||
;;; company-abbrev.el --- company-mode completion backend for abbrev -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2009-2011, 2013-2015, 2021 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2009-2011, 2013-2015, 2021, 2023 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Nikolaj Schumacher
|
||||
|
||||
@@ -29,21 +29,23 @@
|
||||
(require 'cl-lib)
|
||||
(require 'abbrev)
|
||||
|
||||
(defun company-abbrev-insert (match)
|
||||
(defun company-abbrev-insert (_match)
|
||||
"Replace MATCH with the expanded abbrev."
|
||||
(expand-abbrev))
|
||||
|
||||
;;;###autoload
|
||||
(defun company-abbrev (command &optional arg &rest ignored)
|
||||
(defun company-abbrev (command &optional arg &rest _ignored)
|
||||
"`company-mode' completion backend for abbrev."
|
||||
(interactive (list 'interactive))
|
||||
(cl-case command
|
||||
(interactive (company-begin-backend 'company-abbrev
|
||||
'company-abbrev-insert))
|
||||
(prefix (company-grab-symbol))
|
||||
(candidates (nconc
|
||||
(delete "" (all-completions arg global-abbrev-table))
|
||||
(delete "" (all-completions arg local-abbrev-table))))
|
||||
(candidates (apply
|
||||
#'nconc
|
||||
(mapcar (lambda (table)
|
||||
(delete "" (all-completions arg table)))
|
||||
(abbrev--active-tables))))
|
||||
(kind 'snippet)
|
||||
(meta (abbrev-expansion arg))
|
||||
(post-completion (expand-abbrev))))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; company-bbdb.el --- company-mode completion backend for BBDB in message-mode
|
||||
;;; company-bbdb.el --- company-mode completion backend for BBDB in message-mode -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2013-2016, 2020 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2013-2016, 2020, 2023 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Jan Tatarik <jan.tatarik@gmail.com>
|
||||
|
||||
@@ -23,9 +23,7 @@
|
||||
(require 'cl-lib)
|
||||
|
||||
(declare-function bbdb-record-get-field "bbdb")
|
||||
(declare-function bbdb-records "bbdb")
|
||||
(declare-function bbdb-dwim-mail "bbdb-com")
|
||||
(declare-function bbdb-search "bbdb-com")
|
||||
|
||||
(defgroup company-bbdb nil
|
||||
"Completion backend for BBDB."
|
||||
@@ -40,10 +38,12 @@
|
||||
(cl-mapcan (lambda (record)
|
||||
(mapcar (lambda (mail) (bbdb-dwim-mail record mail))
|
||||
(bbdb-record-get-field record 'mail)))
|
||||
(eval '(bbdb-search (bbdb-records) arg nil arg))))
|
||||
(eval `(let ((arg ,arg))
|
||||
(bbdb-search (bbdb-records) :all-names arg :mail arg))
|
||||
t)))
|
||||
|
||||
;;;###autoload
|
||||
(defun company-bbdb (command &optional arg &rest ignore)
|
||||
(defun company-bbdb (command &optional arg &rest _ignore)
|
||||
"`company-mode' completion backend for BBDB."
|
||||
(interactive (list 'interactive))
|
||||
(cl-case command
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; company-capf.el --- company-mode completion-at-point-functions backend -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2013-2021 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2013-2024 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
;;; Commentary:
|
||||
;;
|
||||
;; The CAPF back-end provides a bridge to the standard
|
||||
@@ -32,13 +31,27 @@
|
||||
(require 'company)
|
||||
(require 'cl-lib)
|
||||
|
||||
(defgroup company-capf nil
|
||||
"Completion backend as adapter for `completion-at-point-functions'."
|
||||
:group 'company)
|
||||
|
||||
(defcustom company-capf-disabled-functions '(tags-completion-at-point-function
|
||||
ispell-completion-at-point)
|
||||
"List of completion functions which should be ignored in this backend.
|
||||
|
||||
By default it contains the functions that duplicate the built-in backends
|
||||
but don't support the corresponding configuration options and/or alter the
|
||||
intended priority of the default backends' configuration."
|
||||
:type 'hook
|
||||
:package-version '(company . "1.0.0"))
|
||||
|
||||
;; Amortizes several calls to a c-a-p-f from the same position.
|
||||
(defvar company--capf-cache nil)
|
||||
|
||||
;; FIXME: Provide a way to save this info once in Company itself
|
||||
;; (https://github.com/company-mode/company-mode/pull/845).
|
||||
(defvar-local company-capf--current-completion-data nil
|
||||
"Value last returned by `company-capf' when called with `candidates'.
|
||||
"Value last returned by `company-capf' in response to `candidates'.
|
||||
For most properties/actions, this is just what we need: the exact values
|
||||
that accompanied the completion table that's currently is use.
|
||||
|
||||
@@ -46,6 +59,9 @@ that accompanied the completion table that's currently is use.
|
||||
a completion session (most importantly, by `company-sort-by-occurrence'),
|
||||
so we can't just use the preceding variable instead.")
|
||||
|
||||
(defvar-local company-capf--current-completion-metadata nil
|
||||
"Metadata computed with the current prefix and data above.")
|
||||
|
||||
(defun company--capf-data ()
|
||||
(let ((cache company--capf-cache))
|
||||
(if (and (equal (current-buffer) (car cache))
|
||||
@@ -57,105 +73,60 @@ so we can't just use the preceding variable instead.")
|
||||
(list (current-buffer) (point) (buffer-chars-modified-tick) data))
|
||||
data))))
|
||||
|
||||
(defun company--contains (elt lst)
|
||||
(when-let ((cur (car lst)))
|
||||
(cond
|
||||
((symbolp cur)
|
||||
(or (eq elt cur)
|
||||
(company--contains elt (cdr lst))))
|
||||
((listp cur)
|
||||
(or (company--contains elt cur)
|
||||
(company--contains elt (cdr lst)))))))
|
||||
|
||||
(defun company--capf-data-real ()
|
||||
(cl-letf* (((default-value 'completion-at-point-functions)
|
||||
(if (company--contains 'company-etags company-backends)
|
||||
;; Ignore tags-completion-at-point-function because it subverts
|
||||
;; company-etags in the default value of company-backends, where
|
||||
;; the latter comes later.
|
||||
(remove 'tags-completion-at-point-function
|
||||
(default-value 'completion-at-point-functions))
|
||||
(default-value 'completion-at-point-functions)))
|
||||
(completion-at-point-functions (company--capf-workaround))
|
||||
(data (run-hook-wrapped 'completion-at-point-functions
|
||||
;; Ignore misbehaving functions.
|
||||
#'company--capf-wrapper 'optimist)))
|
||||
(let ((data (run-hook-wrapped 'completion-at-point-functions
|
||||
;; Ignore disabled and misbehaving functions.
|
||||
#'company--capf-wrapper 'optimist)))
|
||||
(when (and (consp (cdr data)) (integer-or-marker-p (nth 1 data))) data)))
|
||||
|
||||
(defun company--capf-wrapper (fun which)
|
||||
(let ((buffer-read-only t)
|
||||
(inhibit-read-only nil)
|
||||
(completion-in-region-function
|
||||
(lambda (beg end coll pred)
|
||||
(throw 'company--illegal-completion-in-region
|
||||
(list fun beg end coll :predicate pred)))))
|
||||
(catch 'company--illegal-completion-in-region
|
||||
(condition-case nil
|
||||
(completion--capf-wrapper fun which)
|
||||
(buffer-read-only nil)))))
|
||||
;; E.g. tags-completion-at-point-function subverts company-etags in the
|
||||
;; default value of company-backends, where the latter comes later.
|
||||
(unless (memq fun company-capf-disabled-functions)
|
||||
(let ((buffer-read-only t)
|
||||
(inhibit-read-only nil)
|
||||
(completion-in-region-function
|
||||
(lambda (beg end coll pred)
|
||||
(throw 'company--illegal-completion-in-region
|
||||
(list fun beg end coll :predicate pred)))))
|
||||
(catch 'company--illegal-completion-in-region
|
||||
(condition-case nil
|
||||
(completion--capf-wrapper fun which)
|
||||
(buffer-read-only nil))))))
|
||||
|
||||
(declare-function python-shell-get-process "python")
|
||||
|
||||
(defun company--capf-workaround ()
|
||||
;; For http://debbugs.gnu.org/cgi/bugreport.cgi?bug=18067
|
||||
(if (or (not (listp completion-at-point-functions))
|
||||
(not (memq 'python-completion-complete-at-point completion-at-point-functions))
|
||||
(python-shell-get-process))
|
||||
completion-at-point-functions
|
||||
(remq 'python-completion-complete-at-point completion-at-point-functions)))
|
||||
|
||||
(defun company-capf--save-current-data (data)
|
||||
(setq company-capf--current-completion-data data)
|
||||
(defun company-capf--save-current-data (data metadata)
|
||||
(setq company-capf--current-completion-data data
|
||||
company-capf--current-completion-metadata metadata)
|
||||
(add-hook 'company-after-completion-hook
|
||||
#'company-capf--clear-current-data nil t))
|
||||
|
||||
(defun company-capf--clear-current-data (_ignored)
|
||||
(setq company-capf--current-completion-data nil))
|
||||
(setq company-capf--current-completion-data nil
|
||||
company-capf--current-completion-metadata nil))
|
||||
|
||||
(defvar-local company-capf--sorted nil)
|
||||
(defvar-local company-capf--current-boundaries nil)
|
||||
|
||||
(defun company-capf (command &optional arg &rest _args)
|
||||
(defun company-capf (command &optional arg &rest rest)
|
||||
"`company-mode' backend using `completion-at-point-functions'."
|
||||
(interactive (list 'interactive))
|
||||
(pcase command
|
||||
(`interactive (company-begin-backend 'company-capf))
|
||||
(`prefix
|
||||
(let ((res (company--capf-data)))
|
||||
(when res
|
||||
(let ((length (plist-get (nthcdr 4 res) :company-prefix-length))
|
||||
(prefix (buffer-substring-no-properties (nth 1 res) (point))))
|
||||
(cond
|
||||
((> (nth 2 res) (point)) 'stop)
|
||||
(length (cons prefix length))
|
||||
(t prefix))))))
|
||||
(company-capf--prefix))
|
||||
(`candidates
|
||||
(company-capf--candidates arg))
|
||||
(company-capf--candidates arg (car rest)))
|
||||
(`sorted
|
||||
company-capf--sorted)
|
||||
(`match
|
||||
;; Ask the for the `:company-match' function. If that doesn't help,
|
||||
;; fallback to sniffing for face changes to get a suitable value.
|
||||
(let ((f (plist-get (nthcdr 4 company-capf--current-completion-data)
|
||||
:company-match)))
|
||||
(if f (funcall f arg)
|
||||
(let* ((match-start nil) (pos -1)
|
||||
(prop-value nil) (faces nil)
|
||||
(has-face-p nil) chunks
|
||||
(limit (length arg)))
|
||||
(while (< pos limit)
|
||||
(setq pos
|
||||
(if (< pos 0) 0 (next-property-change pos arg limit)))
|
||||
(setq prop-value (or
|
||||
(get-text-property pos 'face arg)
|
||||
(get-text-property pos 'font-lock-face arg))
|
||||
faces (if (listp prop-value) prop-value (list prop-value))
|
||||
has-face-p (memq 'completions-common-part faces))
|
||||
(cond ((and (not match-start) has-face-p)
|
||||
(setq match-start pos))
|
||||
((and match-start (not has-face-p))
|
||||
(push (cons match-start pos) chunks)
|
||||
(setq match-start nil))))
|
||||
(nreverse chunks)))))
|
||||
(let ((f (or (plist-get (nthcdr 4 company-capf--current-completion-data)
|
||||
:company-match)
|
||||
#'company--match-from-capf-face)))
|
||||
(funcall f arg)))
|
||||
(`duplicates t)
|
||||
(`no-cache t) ;Not much can be done here, as long as we handle
|
||||
;non-prefix matches.
|
||||
@@ -185,20 +156,35 @@ so we can't just use the preceding variable instead.")
|
||||
(plist-get (nthcdr 4 (company--capf-data)) :company-require-match))
|
||||
(`init nil) ;Don't bother: plenty of other ways to initialize the code.
|
||||
(`post-completion
|
||||
(company--capf-post-completion arg))
|
||||
(company-capf--post-completion arg))
|
||||
(`adjust-boundaries
|
||||
(company--capf-boundaries
|
||||
company-capf--current-boundaries))
|
||||
(`expand-common
|
||||
(company-capf--expand-common arg (car rest)))
|
||||
))
|
||||
|
||||
(defun company-capf--prefix ()
|
||||
(let ((res (company--capf-data)))
|
||||
(when res
|
||||
(let ((length (plist-get (nthcdr 4 res) :company-prefix-length))
|
||||
(prefix (buffer-substring-no-properties (nth 1 res) (point)))
|
||||
(suffix (buffer-substring-no-properties (point) (nth 2 res))))
|
||||
(list prefix suffix length)))))
|
||||
|
||||
(defun company-capf--expand-common (prefix suffix)
|
||||
(let* ((data company-capf--current-completion-data)
|
||||
(table (nth 3 data))
|
||||
(pred (plist-get (nthcdr 4 data) :predicate)))
|
||||
(company--capf-expand-common prefix suffix table pred
|
||||
company-capf--current-completion-metadata)))
|
||||
|
||||
(defun company-capf--annotation (arg)
|
||||
(let* ((f (or (plist-get (nthcdr 4 company-capf--current-completion-data)
|
||||
:annotation-function)
|
||||
;; FIXME: Add a test.
|
||||
(cdr (assq 'annotation-function
|
||||
(completion-metadata
|
||||
(buffer-substring (nth 1 company-capf--current-completion-data)
|
||||
(nth 2 company-capf--current-completion-data))
|
||||
(nth 3 company-capf--current-completion-data)
|
||||
(plist-get (nthcdr 4 company-capf--current-completion-data)
|
||||
:predicate))))))
|
||||
company-capf--current-completion-metadata))))
|
||||
(annotation (when f (funcall f arg))))
|
||||
(if (and company-format-margin-function
|
||||
(equal annotation " <f>") ; elisp-completion-at-point, pre-icons
|
||||
@@ -207,49 +193,64 @@ so we can't just use the preceding variable instead.")
|
||||
nil
|
||||
annotation)))
|
||||
|
||||
(defun company-capf--candidates (input)
|
||||
(let ((res (company--capf-data)))
|
||||
(company-capf--save-current-data res)
|
||||
(when res
|
||||
(let* ((table (nth 3 res))
|
||||
(pred (plist-get (nthcdr 4 res) :predicate))
|
||||
(meta (completion-metadata
|
||||
(buffer-substring (nth 1 res) (nth 2 res))
|
||||
table pred))
|
||||
(candidates (completion-all-completions input table pred
|
||||
(length input)
|
||||
meta))
|
||||
(defun company-capf--candidates (input suffix)
|
||||
(let* ((current-capf (car company-capf--current-completion-data))
|
||||
(res (company--capf-data))
|
||||
(table (nth 3 res))
|
||||
(pred (plist-get (nthcdr 4 res) :predicate))
|
||||
(meta (and res
|
||||
(completion-metadata
|
||||
(buffer-substring (nth 1 res) (nth 2 res))
|
||||
table pred))))
|
||||
(when (and res
|
||||
(or (not current-capf)
|
||||
(equal current-capf (car res))))
|
||||
(let* ((interrupt (plist-get (nthcdr 4 res) :company-use-while-no-input))
|
||||
(all-result (company-capf--candidates-1 input suffix
|
||||
table pred
|
||||
meta
|
||||
(and non-essential
|
||||
(eq interrupt t))))
|
||||
(sortfun (cdr (assq 'display-sort-function meta)))
|
||||
(last (last candidates))
|
||||
(base-size (and (numberp (cdr last)) (cdr last))))
|
||||
(when base-size
|
||||
(setcdr last nil))
|
||||
(candidates (assoc-default :completions all-result)))
|
||||
(setq company-capf--sorted (functionp sortfun))
|
||||
(when candidates
|
||||
(company-capf--save-current-data res meta)
|
||||
(setq company-capf--current-boundaries
|
||||
(company--capf-boundaries-markers
|
||||
(assoc-default :boundaries all-result)
|
||||
company-capf--current-boundaries)))
|
||||
(when sortfun
|
||||
(setq candidates (funcall sortfun candidates)))
|
||||
(if (not (zerop (or base-size 0)))
|
||||
(let ((before (substring input 0 base-size)))
|
||||
(mapcar (lambda (candidate)
|
||||
(concat before candidate))
|
||||
candidates))
|
||||
candidates)))))
|
||||
candidates))))
|
||||
|
||||
(defun company--capf-post-completion (arg)
|
||||
(defun company-capf--candidates-1 (prefix suffix table pred meta interrupt-on-input)
|
||||
(if (not interrupt-on-input)
|
||||
(company--capf-completions prefix suffix table pred meta)
|
||||
(let (res)
|
||||
(and (while-no-input
|
||||
(setq res
|
||||
(company--capf-completions prefix suffix table pred meta))
|
||||
nil)
|
||||
(throw 'interrupted 'new-input))
|
||||
res)))
|
||||
|
||||
(defun company-capf--post-completion (arg)
|
||||
(let* ((res company-capf--current-completion-data)
|
||||
(exit-function (plist-get (nthcdr 4 res) :exit-function))
|
||||
(table (nth 3 res)))
|
||||
(table (nth 3 res))
|
||||
(prefix (nth 0 (company-capf--prefix))))
|
||||
(if exit-function
|
||||
;; We can more or less know when the user is done with completion,
|
||||
;; so we do something different than `completion--done'.
|
||||
;; Follow the example of `completion--done'.
|
||||
(funcall exit-function arg
|
||||
;; FIXME: Should probably use an additional heuristic:
|
||||
;; completion-at-point doesn't know when the user picked a
|
||||
;; particular candidate explicitly (it only checks whether
|
||||
;; further completions exist). Whereas company user can press
|
||||
;; RET (or use implicit completion with company-tng).
|
||||
(if (= (car (completion-boundaries arg table nil ""))
|
||||
(length arg))
|
||||
'sole
|
||||
(if (= (car (completion-boundaries prefix table nil ""))
|
||||
(length prefix))
|
||||
'exact
|
||||
'finished)))))
|
||||
|
||||
(provide 'company-capf)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; company-clang.el --- company-mode completion backend for Clang -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2009-2011, 2013-2021 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2009-2011, 2013-2023 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Nikolaj Schumacher
|
||||
|
||||
@@ -119,10 +119,9 @@ or automatically through a custom `company-clang-prefix-guesser'."
|
||||
|
||||
;; parsing ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; TODO: Handle Pattern (syntactic hints would be neat).
|
||||
;; Do we ever see OVERLOAD (or OVERRIDE)?
|
||||
(defconst company-clang--completion-pattern
|
||||
"^COMPLETION: \\_<\\(%s[a-zA-Z0-9_:]*\\)\\(?:\\(?: (InBase)\\)? : \\(.*\\)$\\)?$")
|
||||
"^COMPLETION: \\_<\\(%s[a-zA-Z0-9_:]*\\|Pattern\\)\\(?:\\(?: (InBase)\\)? : \\(.*\\)$\\)?$")
|
||||
|
||||
(defconst company-clang--error-buffer-name "*clang-error*")
|
||||
|
||||
@@ -138,14 +137,14 @@ or automatically through a custom `company-clang-prefix-guesser'."
|
||||
(regexp-quote prefix)))
|
||||
(case-fold-search nil)
|
||||
(results (make-hash-table :test 'equal :size (/ (point-max) 100)))
|
||||
lines match)
|
||||
lines)
|
||||
(while (re-search-forward pattern nil t)
|
||||
(setq match (match-string-no-properties 1))
|
||||
(unless (equal match "Pattern")
|
||||
(save-match-data
|
||||
(let ((match (match-string-no-properties 1))
|
||||
(meta (match-string-no-properties 2)))
|
||||
(when (equal match "Pattern")
|
||||
(setq match (company-clang--pattern-to-match meta)))
|
||||
(when (string-match ":" match)
|
||||
(setq match (substring match 0 (match-beginning 0)))))
|
||||
(let ((meta (match-string-no-properties 2)))
|
||||
(setq match (substring match 0 (match-beginning 0))))
|
||||
;; Avoiding duplicates:
|
||||
;; https://github.com/company-mode/company-mode/issues/841
|
||||
(cond
|
||||
@@ -154,7 +153,7 @@ or automatically through a custom `company-clang-prefix-guesser'."
|
||||
(puthash match meta results))
|
||||
;; Or it's the first time we see this completion
|
||||
((eq (gethash match results 'none) 'none)
|
||||
(puthash match nil results))))))
|
||||
(puthash match nil results)))))
|
||||
(maphash
|
||||
(lambda (match meta)
|
||||
(when meta
|
||||
@@ -163,6 +162,15 @@ or automatically through a custom `company-clang-prefix-guesser'."
|
||||
results)
|
||||
lines))
|
||||
|
||||
(defun company-clang--pattern-to-match (pat)
|
||||
(let ((start 0)
|
||||
(end nil))
|
||||
(when (string-match "#]" pat)
|
||||
(setq start (match-end 0)))
|
||||
(when (string-match "[ \(]<#" pat start)
|
||||
(setq end (match-beginning 0)))
|
||||
(substring pat start end)))
|
||||
|
||||
(defun company-clang--meta (candidate)
|
||||
(get-text-property 0 'meta candidate))
|
||||
|
||||
@@ -178,6 +186,8 @@ or automatically through a custom `company-clang-prefix-guesser'."
|
||||
(delete-region pt (point)))
|
||||
(buffer-string)))))
|
||||
|
||||
;; TODO: Parse the original formatting here, rather than guess.
|
||||
;; Strip it every time in the `meta' handler instead.
|
||||
(defun company-clang--annotation-1 (candidate)
|
||||
(let ((meta (company-clang--meta candidate)))
|
||||
(cond
|
||||
@@ -325,8 +335,8 @@ or automatically through a custom `company-clang-prefix-guesser'."
|
||||
|
||||
(defun company-clang--prefix ()
|
||||
(if company-clang-begin-after-member-access
|
||||
(company-grab-symbol-cons "\\.\\|->\\|::" 2)
|
||||
(company-grab-symbol)))
|
||||
(company-grab-symbol-parts "\\.\\|->\\|::" 2)
|
||||
(company-grab-symbol-parts)))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; company-cmake.el --- company-mode completion backend for CMake
|
||||
;;; company-cmake.el --- company-mode completion backend for CMake -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2013-2015, 2017-2018, 2020 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2013-2015, 2017-2018, 2020, 2023 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Chen Bin <chenbin DOT sh AT gmail>
|
||||
;; Version: 0.2
|
||||
@@ -49,7 +49,7 @@ They affect which types of symbols we get completion candidates for.")
|
||||
"^\\(%s[a-zA-Z0-9_<>]%s\\)$"
|
||||
"Regexp to match the candidates.")
|
||||
|
||||
(defvar company-cmake-modes '(cmake-mode)
|
||||
(defvar company-cmake-modes '(cmake-mode cmake-ts-mode)
|
||||
"Major modes in which cmake may complete.")
|
||||
|
||||
(defvar company-cmake--candidates-cache nil
|
||||
@@ -94,12 +94,10 @@ They affect which types of symbols we get completion candidates for.")
|
||||
))
|
||||
|
||||
(defun company-cmake--parse (prefix content cmd)
|
||||
(let ((start 0)
|
||||
(pattern (format company-cmake--completion-pattern
|
||||
(let ((pattern (format company-cmake--completion-pattern
|
||||
(regexp-quote prefix)
|
||||
(if (zerop (length prefix)) "+" "*")))
|
||||
(lines (split-string content "\n"))
|
||||
match
|
||||
rlt)
|
||||
(dolist (line lines)
|
||||
(when (string-match pattern line)
|
||||
@@ -185,7 +183,7 @@ They affect which types of symbols we get completion candidates for.")
|
||||
(and (eq (char-before (point)) ?\{)
|
||||
(eq (char-before (1- (point))) ?$))))
|
||||
|
||||
(defun company-cmake (command &optional arg &rest ignored)
|
||||
(defun company-cmake (command &optional arg &rest _ignored)
|
||||
"`company-mode' completion backend for CMake.
|
||||
CMake is a cross-platform, open-source make system."
|
||||
(interactive (list 'interactive))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; company-dabbrev-code.el --- dabbrev-like company-mode backend for code -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2009-2011, 2013-2016, 2021 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2009-2011, 2013-2016, 2021-2024 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Nikolaj Schumacher
|
||||
|
||||
@@ -48,13 +48,16 @@ complete only symbols, not text in comments or strings. In other modes
|
||||
(defcustom company-dabbrev-code-other-buffers t
|
||||
"Determines whether `company-dabbrev-code' should search other buffers.
|
||||
If `all', search all other buffers, except the ignored ones. If t, search
|
||||
buffers with the same major mode. If `code', search all buffers with major
|
||||
modes in `company-dabbrev-code-modes', or derived from one of them. See
|
||||
also `company-dabbrev-code-time-limit'."
|
||||
buffers with the same major mode. If `code', search all
|
||||
buffers with major modes in `company-dabbrev-code-modes', or derived from one of
|
||||
them. This can also be a function that takes the current buffer as
|
||||
parameter and returns a list of major modes to search. See also
|
||||
`company-dabbrev-code-time-limit'."
|
||||
:type '(choice (const :tag "Off" nil)
|
||||
(const :tag "Same major mode" t)
|
||||
(const :tag "Code major modes" code)
|
||||
(const :tag "All" all)))
|
||||
(const :tag "All" all)
|
||||
(function :tag "Function to return similar major-modes" group)))
|
||||
|
||||
(defcustom company-dabbrev-code-time-limit .1
|
||||
"Determines how long `company-dabbrev-code' should look for matches."
|
||||
@@ -69,14 +72,38 @@ also `company-dabbrev-code-time-limit'."
|
||||
"Non-nil to ignore case when collecting completion candidates."
|
||||
:type 'boolean)
|
||||
|
||||
(defcustom company-dabbrev-code-completion-styles nil
|
||||
"Non-nil to use the completion styles for fuzzy matching."
|
||||
:type '(choice (const :tag "Prefix matching only" nil)
|
||||
(const :tag "Matching according to `completion-styles'" t)
|
||||
(list :tag "Custom list of styles" symbol))
|
||||
:package-version '(company . "1.0.0"))
|
||||
|
||||
(defvar-local company-dabbrev--boundaries nil)
|
||||
(defvar-local company-dabbrev-code--sorted nil)
|
||||
|
||||
(defun company-dabbrev-code--make-regexp (prefix)
|
||||
(concat "\\_<" (if (equal prefix "")
|
||||
"\\([a-zA-Z]\\|\\s_\\)"
|
||||
(regexp-quote prefix))
|
||||
"\\(\\sw\\|\\s_\\)*\\_>"))
|
||||
(let ((prefix-re
|
||||
(cond
|
||||
((string-empty-p prefix)
|
||||
"\\([a-zA-Z]\\|\\s_\\)")
|
||||
((not company-dabbrev-code-completion-styles)
|
||||
(regexp-quote prefix))
|
||||
(t
|
||||
;; Use the cache at least after 2 chars. We could also cache
|
||||
;; earlier, for users who set company-min-p-l to 1 or 0.
|
||||
(let ((prefix (if (>= (length prefix) 2)
|
||||
(substring prefix 0 2)
|
||||
prefix)))
|
||||
(concat
|
||||
"\\(\\sw\\|\\s_\\)*"
|
||||
(mapconcat #'regexp-quote
|
||||
(mapcar #'string prefix)
|
||||
"\\(\\sw\\|\\s_\\)*")))))))
|
||||
(concat "\\_<" prefix-re "\\(\\sw\\|\\s_\\)*\\_>")))
|
||||
|
||||
;;;###autoload
|
||||
(defun company-dabbrev-code (command &optional arg &rest _ignored)
|
||||
(defun company-dabbrev-code (command &optional arg &rest rest)
|
||||
"dabbrev-like `company-mode' backend for code.
|
||||
The backend looks for all symbols in the current buffer that aren't in
|
||||
comments or strings."
|
||||
@@ -84,22 +111,77 @@ comments or strings."
|
||||
(cl-case command
|
||||
(interactive (company-begin-backend 'company-dabbrev-code))
|
||||
(prefix (and (or (eq t company-dabbrev-code-modes)
|
||||
(apply #'derived-mode-p company-dabbrev-code-modes))
|
||||
(cl-some #'derived-mode-p company-dabbrev-code-modes))
|
||||
(or company-dabbrev-code-everywhere
|
||||
(not (company-in-string-or-comment)))
|
||||
(or (company-grab-symbol) 'stop)))
|
||||
(candidates (let ((case-fold-search company-dabbrev-code-ignore-case))
|
||||
(company-dabbrev--search
|
||||
(company-dabbrev-code--make-regexp arg)
|
||||
company-dabbrev-code-time-limit
|
||||
(pcase company-dabbrev-code-other-buffers
|
||||
(`t (list major-mode))
|
||||
(`code company-dabbrev-code-modes)
|
||||
(`all `all))
|
||||
(not company-dabbrev-code-everywhere))))
|
||||
(company-grab-symbol-parts)))
|
||||
(candidates (company-dabbrev--candidates arg (car rest)))
|
||||
(adjust-boundaries (and company-dabbrev-code-completion-styles
|
||||
(company--capf-boundaries
|
||||
company-dabbrev--boundaries)))
|
||||
(expand-common (company-dabbrev-code--expand-common arg (car rest)))
|
||||
(kind 'text)
|
||||
(sorted company-dabbrev-code--sorted)
|
||||
(no-cache t)
|
||||
(ignore-case company-dabbrev-code-ignore-case)
|
||||
(match (when company-dabbrev-code-completion-styles
|
||||
(company--match-from-capf-face arg)))
|
||||
(duplicates t)))
|
||||
|
||||
(defun company-dabbrev-code--expand-common (prefix suffix)
|
||||
(when company-dabbrev-code-completion-styles
|
||||
(let ((completion-styles (if (listp company-dabbrev-code-completion-styles)
|
||||
company-dabbrev-code-completion-styles
|
||||
completion-styles)))
|
||||
(company--capf-expand-common prefix suffix
|
||||
(company-dabbrev-code--table prefix)))))
|
||||
|
||||
(defun company-dabbrev--candidates (prefix suffix)
|
||||
(let* ((case-fold-search company-dabbrev-code-ignore-case))
|
||||
(company-dabbrev-code--filter
|
||||
prefix suffix
|
||||
(company-dabbrev-code--table prefix))))
|
||||
|
||||
(defun company-dabbrev-code--table (prefix)
|
||||
(let ((regexp (company-dabbrev-code--make-regexp prefix)))
|
||||
(company-cache-fetch
|
||||
'dabbrev-code-candidates
|
||||
(lambda ()
|
||||
(company-dabbrev--search
|
||||
regexp
|
||||
company-dabbrev-code-time-limit
|
||||
(pcase company-dabbrev-code-other-buffers
|
||||
(`t (list major-mode))
|
||||
(`code company-dabbrev-code-modes)
|
||||
((pred functionp) (funcall company-dabbrev-code-other-buffers (current-buffer)))
|
||||
(`all `all))
|
||||
(not company-dabbrev-code-everywhere)))
|
||||
:expire t
|
||||
:check-tag
|
||||
(cons regexp company-dabbrev-code-completion-styles))))
|
||||
|
||||
(defun company-dabbrev-code--filter (prefix suffix table)
|
||||
(let ((completion-ignore-case company-dabbrev-code-ignore-case)
|
||||
(completion-styles (if (listp company-dabbrev-code-completion-styles)
|
||||
company-dabbrev-code-completion-styles
|
||||
completion-styles))
|
||||
(metadata (completion-metadata prefix table nil))
|
||||
res)
|
||||
(if (not company-dabbrev-code-completion-styles)
|
||||
(all-completions prefix table)
|
||||
(setq res (company--capf-completions
|
||||
prefix suffix
|
||||
table nil
|
||||
metadata))
|
||||
(when-let* ((sort-fn (completion-metadata-get metadata 'display-sort-function)))
|
||||
(setq company-dabbrev-code--sorted t)
|
||||
(setf (alist-get :completions res)
|
||||
(funcall sort-fn (alist-get :completions res))))
|
||||
(setq company-dabbrev--boundaries
|
||||
(company--capf-boundaries-markers
|
||||
(assoc-default :boundaries res)
|
||||
company-dabbrev--boundaries))
|
||||
(assoc-default :completions res))))
|
||||
|
||||
(provide 'company-dabbrev-code)
|
||||
;;; company-dabbrev-code.el ends here
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; company-dabbrev.el --- dabbrev-like company-mode completion backend -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2009-2011, 2013-2018, 2021 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2009-2011, 2013-2018, 2021-2023 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Nikolaj Schumacher
|
||||
|
||||
@@ -35,10 +35,13 @@
|
||||
(defcustom company-dabbrev-other-buffers 'all
|
||||
"Determines whether `company-dabbrev' should search other buffers.
|
||||
If `all', search all other buffers, except the ignored ones. If t, search
|
||||
buffers with the same major mode. See also `company-dabbrev-time-limit'."
|
||||
buffers with the same major mode. This can also be a function that takes
|
||||
the current buffer as parameter and returns a list of major modes to
|
||||
search. See also `company-dabbrev-time-limit'."
|
||||
:type '(choice (const :tag "Off" nil)
|
||||
(const :tag "Same major mode" t)
|
||||
(const :tag "All" all)))
|
||||
(const :tag "All" all)
|
||||
(function :tag "Function to return similar major-modes" group)))
|
||||
|
||||
(defcustom company-dabbrev-ignore-buffers "\\`[ *]"
|
||||
"Regexp matching the names of buffers to ignore.
|
||||
@@ -70,10 +73,7 @@ candidate is inserted, even some of its characters have different case."
|
||||
|
||||
The value of nil means keep them as-is.
|
||||
`case-replace' means use the value of `case-replace'.
|
||||
Any other value means downcase.
|
||||
|
||||
If you set this value to nil, you may also want to set
|
||||
`company-dabbrev-ignore-case' to any value other than `keep-prefix'."
|
||||
Any other value means downcase."
|
||||
:type '(choice
|
||||
(const :tag "Keep as-is" nil)
|
||||
(const :tag "Downcase" t)
|
||||
@@ -114,7 +114,7 @@ This variable affects both `company-dabbrev' and `company-dabbrev-code'."
|
||||
(when (and (>= (length match) company-dabbrev-minimum-length)
|
||||
(not (and company-dabbrev-ignore-invisible
|
||||
(invisible-p (match-beginning 0)))))
|
||||
(push match symbols)))))
|
||||
(puthash match t symbols)))))
|
||||
(goto-char (if pos (1- pos) (point-min)))
|
||||
;; Search before pos.
|
||||
(let ((tmp-end (point)))
|
||||
@@ -147,7 +147,9 @@ This variable affects both `company-dabbrev' and `company-dabbrev-code'."
|
||||
(defun company-dabbrev--search (regexp &optional limit other-buffer-modes
|
||||
ignore-comments)
|
||||
(let* ((start (current-time))
|
||||
(symbols (company-dabbrev--search-buffer regexp (point) nil start limit
|
||||
(symbols (company-dabbrev--search-buffer regexp (point)
|
||||
(make-hash-table :test 'equal)
|
||||
start limit
|
||||
ignore-comments)))
|
||||
(when other-buffer-modes
|
||||
(cl-dolist (buffer (delq (current-buffer) (buffer-list)))
|
||||
@@ -157,7 +159,7 @@ This variable affects both `company-dabbrev' and `company-dabbrev-code'."
|
||||
(funcall company-dabbrev-ignore-buffers buffer))
|
||||
(with-current-buffer buffer
|
||||
(when (or (eq other-buffer-modes 'all)
|
||||
(apply #'derived-mode-p other-buffer-modes))
|
||||
(cl-some #'derived-mode-p other-buffer-modes))
|
||||
(setq symbols
|
||||
(company-dabbrev--search-buffer regexp nil symbols start
|
||||
limit ignore-comments)))))
|
||||
@@ -167,16 +169,38 @@ This variable affects both `company-dabbrev' and `company-dabbrev-code'."
|
||||
symbols))
|
||||
|
||||
(defun company-dabbrev--prefix ()
|
||||
;; Not in the middle of a word.
|
||||
(unless (looking-at company-dabbrev-char-regexp)
|
||||
;; Emacs can't do greedy backward-search.
|
||||
(company-grab-line (format "\\(?:^\\| \\)[^ ]*?\\(\\(?:%s\\)*\\)"
|
||||
company-dabbrev-char-regexp)
|
||||
1)))
|
||||
;; Emacs can't do greedy backward-search.
|
||||
(list
|
||||
(company-grab-line (format "\\(?:^\\| \\)[^ ]*?\\(\\(?:%s\\)*\\)"
|
||||
company-dabbrev-char-regexp)
|
||||
1)
|
||||
(and (looking-at (format "\\(?:%s\\)*" company-dabbrev-char-regexp))
|
||||
(match-string 0))))
|
||||
|
||||
(defun company-dabbrev--filter (prefix candidates)
|
||||
(let ((completion-ignore-case company-dabbrev-ignore-case))
|
||||
(all-completions prefix candidates)))
|
||||
(let* ((completion-ignore-case company-dabbrev-ignore-case)
|
||||
(filtered (all-completions prefix candidates))
|
||||
(lp (length prefix))
|
||||
(downcase (if (eq company-dabbrev-downcase 'case-replace)
|
||||
case-replace
|
||||
company-dabbrev-downcase)))
|
||||
(when downcase
|
||||
(let ((ptr filtered))
|
||||
(while ptr
|
||||
(setcar ptr (downcase (car ptr)))
|
||||
(setq ptr (cdr ptr)))))
|
||||
(if (and (eq company-dabbrev-ignore-case 'keep-prefix)
|
||||
(not (= lp 0)))
|
||||
(company-substitute-prefix prefix filtered)
|
||||
filtered)))
|
||||
|
||||
(defun company-dabbrev--fetch ()
|
||||
(company-dabbrev--search (company-dabbrev--make-regexp)
|
||||
company-dabbrev-time-limit
|
||||
(pcase company-dabbrev-other-buffers
|
||||
(`t (list major-mode))
|
||||
((pred functionp) (funcall company-dabbrev-other-buffers (current-buffer)))
|
||||
(`all `all))))
|
||||
|
||||
;;;###autoload
|
||||
(defun company-dabbrev (command &optional arg &rest _ignored)
|
||||
@@ -186,21 +210,14 @@ This variable affects both `company-dabbrev' and `company-dabbrev-code'."
|
||||
(interactive (company-begin-backend 'company-dabbrev))
|
||||
(prefix (company-dabbrev--prefix))
|
||||
(candidates
|
||||
(let* ((case-fold-search company-dabbrev-ignore-case)
|
||||
(words (company-dabbrev--search (company-dabbrev--make-regexp)
|
||||
company-dabbrev-time-limit
|
||||
(pcase company-dabbrev-other-buffers
|
||||
(`t (list major-mode))
|
||||
(`all `all))))
|
||||
(downcase-p (if (eq company-dabbrev-downcase 'case-replace)
|
||||
case-replace
|
||||
company-dabbrev-downcase)))
|
||||
(setq words (company-dabbrev--filter arg words))
|
||||
(if downcase-p
|
||||
(mapcar 'downcase words)
|
||||
words)))
|
||||
(company-dabbrev--filter
|
||||
arg
|
||||
;; FIXME: Only cache the result of non-interrupted scans?
|
||||
(company-cache-fetch 'dabbrev-candidates #'company-dabbrev--fetch
|
||||
:expire t)))
|
||||
(kind 'text)
|
||||
(ignore-case company-dabbrev-ignore-case)
|
||||
(no-cache t)
|
||||
(ignore-case (and company-dabbrev-ignore-case t))
|
||||
(duplicates t)))
|
||||
|
||||
(provide 'company-dabbrev)
|
||||
|
||||
@@ -1,226 +0,0 @@
|
||||
;;; company-elisp.el --- company-mode completion backend for Emacs Lisp -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2009-2015, 2017, 2020 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Nikolaj Schumacher
|
||||
|
||||
;; This file is part of GNU Emacs.
|
||||
|
||||
;; GNU Emacs is free software: you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; GNU Emacs is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
;;; Commentary:
|
||||
;;
|
||||
;; In newer versions of Emacs, company-capf is used instead.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'company)
|
||||
(require 'cl-lib)
|
||||
(require 'help-mode)
|
||||
(require 'find-func)
|
||||
|
||||
(defgroup company-elisp nil
|
||||
"Completion backend for Emacs Lisp."
|
||||
:group 'company)
|
||||
|
||||
(defcustom company-elisp-detect-function-context t
|
||||
"If enabled, offer Lisp functions only in appropriate contexts.
|
||||
Functions are offered for completion only after \\=' and \(."
|
||||
:type '(choice (const :tag "Off" nil)
|
||||
(const :tag "On" t)))
|
||||
|
||||
(defcustom company-elisp-show-locals-first t
|
||||
"If enabled, locally bound variables and functions are displayed
|
||||
first in the candidates list."
|
||||
:type '(choice (const :tag "Off" nil)
|
||||
(const :tag "On" t)))
|
||||
|
||||
(defun company-elisp--prefix ()
|
||||
(let ((prefix (company-grab-symbol)))
|
||||
(if prefix
|
||||
(when (if (company-in-string-or-comment)
|
||||
(= (char-before (- (point) (length prefix))) ?`)
|
||||
(company-elisp--should-complete))
|
||||
prefix)
|
||||
'stop)))
|
||||
|
||||
(defun company-elisp--predicate (symbol)
|
||||
(or (boundp symbol)
|
||||
(fboundp symbol)
|
||||
(facep symbol)
|
||||
(featurep symbol)))
|
||||
|
||||
(defun company-elisp--fns-regexp (&rest names)
|
||||
(concat "\\_<\\(?:cl-\\)?" (regexp-opt names) "\\*?\\_>"))
|
||||
|
||||
(defvar company-elisp-parse-limit 30)
|
||||
(defvar company-elisp-parse-depth 100)
|
||||
|
||||
(defvar company-elisp-defun-names '("defun" "defmacro" "defsubst"))
|
||||
|
||||
(defvar company-elisp-var-binding-regexp
|
||||
(apply #'company-elisp--fns-regexp "let" "lambda" "lexical-let"
|
||||
company-elisp-defun-names)
|
||||
"Regular expression matching head of a multiple variable bindings form.")
|
||||
|
||||
(defvar company-elisp-var-binding-regexp-1
|
||||
(company-elisp--fns-regexp "dolist" "dotimes")
|
||||
"Regular expression matching head of a form with one variable binding.")
|
||||
|
||||
(defvar company-elisp-fun-binding-regexp
|
||||
(company-elisp--fns-regexp "flet" "labels")
|
||||
"Regular expression matching head of a function bindings form.")
|
||||
|
||||
(defvar company-elisp-defuns-regexp
|
||||
(concat "([ \t\n]*"
|
||||
(apply #'company-elisp--fns-regexp company-elisp-defun-names)))
|
||||
|
||||
(defun company-elisp--should-complete ()
|
||||
(let ((start (point))
|
||||
(depth (car (syntax-ppss))))
|
||||
(not
|
||||
(when (> depth 0)
|
||||
(save-excursion
|
||||
(up-list (- depth))
|
||||
(when (looking-at company-elisp-defuns-regexp)
|
||||
(forward-char)
|
||||
(forward-sexp 1)
|
||||
(unless (= (point) start)
|
||||
(condition-case nil
|
||||
(let ((args-end (scan-sexps (point) 2)))
|
||||
(or (null args-end)
|
||||
(> args-end start)))
|
||||
(scan-error
|
||||
t)))))))))
|
||||
|
||||
(defun company-elisp--locals (prefix functions-p)
|
||||
(let ((regexp (concat "[ \t\n]*\\(\\_<" (regexp-quote prefix)
|
||||
"\\(?:\\sw\\|\\s_\\)*\\_>\\)"))
|
||||
(pos (point))
|
||||
res)
|
||||
(condition-case nil
|
||||
(save-excursion
|
||||
(dotimes (_ company-elisp-parse-depth)
|
||||
(up-list -1)
|
||||
(save-excursion
|
||||
(when (eq (char-after) ?\()
|
||||
(forward-char 1)
|
||||
(when (ignore-errors
|
||||
(save-excursion (forward-list)
|
||||
(<= (point) pos)))
|
||||
(skip-chars-forward " \t\n")
|
||||
(cond
|
||||
((looking-at (if functions-p
|
||||
company-elisp-fun-binding-regexp
|
||||
company-elisp-var-binding-regexp))
|
||||
(down-list 1)
|
||||
(condition-case nil
|
||||
(dotimes (_ company-elisp-parse-limit)
|
||||
(save-excursion
|
||||
(when (looking-at "[ \t\n]*(")
|
||||
(down-list 1))
|
||||
(when (looking-at regexp)
|
||||
(cl-pushnew (match-string-no-properties 1) res)))
|
||||
(forward-sexp))
|
||||
(scan-error nil)))
|
||||
((unless functions-p
|
||||
(looking-at company-elisp-var-binding-regexp-1))
|
||||
(down-list 1)
|
||||
(when (looking-at regexp)
|
||||
(cl-pushnew (match-string-no-properties 1) res)))))))))
|
||||
(scan-error nil))
|
||||
res))
|
||||
|
||||
(defun company-elisp-candidates (prefix)
|
||||
(let* ((predicate (company-elisp--candidates-predicate prefix))
|
||||
(locals (company-elisp--locals prefix (eq predicate 'fboundp)))
|
||||
(globals (company-elisp--globals prefix predicate))
|
||||
(locals (cl-loop for local in locals
|
||||
when (not (member local globals))
|
||||
collect local)))
|
||||
(if company-elisp-show-locals-first
|
||||
(append (sort locals 'string<)
|
||||
(sort globals 'string<))
|
||||
(append locals globals))))
|
||||
|
||||
(defun company-elisp--globals (prefix predicate)
|
||||
(all-completions prefix obarray predicate))
|
||||
|
||||
(defun company-elisp--candidates-predicate (prefix)
|
||||
(let* ((completion-ignore-case nil)
|
||||
(beg (- (point) (length prefix)))
|
||||
(before (char-before beg)))
|
||||
(if (and company-elisp-detect-function-context
|
||||
(not (memq before '(?' ?`))))
|
||||
(if (and (eq before ?\()
|
||||
(not
|
||||
(save-excursion
|
||||
(ignore-errors
|
||||
(goto-char (1- beg))
|
||||
(or (company-elisp--before-binding-varlist-p)
|
||||
(progn
|
||||
(up-list -1)
|
||||
(company-elisp--before-binding-varlist-p)))))))
|
||||
'fboundp
|
||||
'boundp)
|
||||
'company-elisp--predicate)))
|
||||
|
||||
(defun company-elisp--before-binding-varlist-p ()
|
||||
(save-excursion
|
||||
(and (prog1 (search-backward "(")
|
||||
(forward-char 1))
|
||||
(looking-at company-elisp-var-binding-regexp))))
|
||||
|
||||
(defun company-elisp--doc (symbol)
|
||||
(let* ((symbol (intern symbol))
|
||||
(doc (if (fboundp symbol)
|
||||
(documentation symbol t)
|
||||
(documentation-property symbol 'variable-documentation t))))
|
||||
(and (stringp doc)
|
||||
(string-match ".*$" doc)
|
||||
(match-string 0 doc))))
|
||||
|
||||
;;;###autoload
|
||||
(defun company-elisp (command &optional arg &rest _ignored)
|
||||
"`company-mode' completion backend for Emacs Lisp."
|
||||
(interactive (list 'interactive))
|
||||
(cl-case command
|
||||
(interactive (company-begin-backend 'company-elisp))
|
||||
(prefix (and (derived-mode-p 'emacs-lisp-mode 'inferior-emacs-lisp-mode)
|
||||
(company-elisp--prefix)))
|
||||
(candidates (company-elisp-candidates arg))
|
||||
(sorted company-elisp-show-locals-first)
|
||||
(meta (company-elisp--doc arg))
|
||||
(doc-buffer (let ((symbol (intern arg)))
|
||||
(save-window-excursion
|
||||
(ignore-errors
|
||||
(cond
|
||||
((fboundp symbol) (describe-function symbol))
|
||||
((boundp symbol) (describe-variable symbol))
|
||||
((featurep symbol) (describe-package symbol))
|
||||
((facep symbol) (describe-face symbol))
|
||||
(t (signal 'user-error nil)))
|
||||
(help-buffer)))))
|
||||
(location (let ((sym (intern arg)))
|
||||
(cond
|
||||
((fboundp sym) (find-definition-noselect sym nil))
|
||||
((boundp sym) (find-definition-noselect sym 'defvar))
|
||||
((featurep sym) (cons (find-file-noselect (find-library-name
|
||||
(symbol-name sym)))
|
||||
0))
|
||||
((facep sym) (find-definition-noselect sym 'defface)))))))
|
||||
|
||||
(provide 'company-elisp)
|
||||
;;; company-elisp.el ends here
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; company-etags.el --- company-mode completion backend for etags
|
||||
;;; company-etags.el --- company-mode completion backend for etags -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2009-2011, 2013-2015, 2018-2019 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2009-2011, 2013-2015, 2018-2019, 2023-2024 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Nikolaj Schumacher
|
||||
|
||||
@@ -54,10 +54,18 @@ Set it to t or to a list of major modes."
|
||||
(symbol :tag "Major mode")))
|
||||
:package-version '(company . "0.9.0"))
|
||||
|
||||
(defcustom company-etags-completion-styles nil
|
||||
"Non-nil to use the completion styles for fuzzy matching."
|
||||
:type '(choice (const :tag "Prefix matching only" nil)
|
||||
(const :tag "Matching according to `completion-styles'" t)
|
||||
(list :tag "Custom list of styles" symbol))
|
||||
:package-version '(company . "1.0.0"))
|
||||
|
||||
(defvar company-etags-modes '(prog-mode c-mode objc-mode c++-mode java-mode
|
||||
jde-mode pascal-mode perl-mode python-mode))
|
||||
|
||||
(defvar-local company-etags-buffer-table 'unknown)
|
||||
(defvar-local company-etags--boundaries nil)
|
||||
|
||||
(defun company-etags-find-table ()
|
||||
(let ((file (expand-file-name
|
||||
@@ -74,34 +82,64 @@ Set it to t or to a list of major modes."
|
||||
(setq company-etags-buffer-table (company-etags-find-table))
|
||||
company-etags-buffer-table)))
|
||||
|
||||
(defun company-etags--candidates (prefix)
|
||||
(defun company-etags--candidates (prefix suffix)
|
||||
(let ((completion-ignore-case company-etags-ignore-case)
|
||||
(completion-styles (if (listp company-etags-completion-styles)
|
||||
company-etags-completion-styles
|
||||
completion-styles))
|
||||
(table (company-etags--table)))
|
||||
(and table
|
||||
(if company-etags-completion-styles
|
||||
(let ((res (company--capf-completions prefix suffix table)))
|
||||
(setq company-etags--boundaries
|
||||
(company--capf-boundaries-markers
|
||||
(assoc-default :boundaries res)
|
||||
company-etags--boundaries))
|
||||
(assoc-default :completions res))
|
||||
(all-completions prefix table)))))
|
||||
|
||||
(defun company-etags--table ()
|
||||
(let ((tags-table-list (company-etags-buffer-table))
|
||||
(tags-file-name tags-file-name)
|
||||
(completion-ignore-case company-etags-ignore-case))
|
||||
(tags-file-name tags-file-name))
|
||||
(and (or tags-file-name tags-table-list)
|
||||
(fboundp 'tags-completion-table)
|
||||
(save-excursion
|
||||
(visit-tags-table-buffer)
|
||||
(all-completions prefix (tags-completion-table))))))
|
||||
(tags-completion-table)))))
|
||||
|
||||
(defun company-etags--expand-common (prefix suffix)
|
||||
(when company-etags-completion-styles
|
||||
(let ((completion-styles (if (listp company-etags-completion-styles)
|
||||
company-etags-completion-styles
|
||||
completion-styles)))
|
||||
(company--capf-expand-common prefix suffix
|
||||
(company-etags--table)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun company-etags (command &optional arg &rest ignored)
|
||||
(defun company-etags (command &optional arg &rest rest)
|
||||
"`company-mode' completion backend for etags."
|
||||
(interactive (list 'interactive))
|
||||
(cl-case command
|
||||
(interactive (company-begin-backend 'company-etags))
|
||||
(prefix (and (apply #'derived-mode-p company-etags-modes)
|
||||
(prefix (and (cl-some #'derived-mode-p company-etags-modes)
|
||||
(or (eq t company-etags-everywhere)
|
||||
(apply #'derived-mode-p company-etags-everywhere)
|
||||
(cl-some #'derived-mode-p company-etags-everywhere)
|
||||
(not (company-in-string-or-comment)))
|
||||
(company-etags-buffer-table)
|
||||
(or (company-grab-symbol) 'stop)))
|
||||
(candidates (company-etags--candidates arg))
|
||||
(company-grab-symbol-parts)))
|
||||
(candidates (company-etags--candidates arg (car rest)))
|
||||
(adjust-boundaries (and company-etags-completion-styles
|
||||
(company--capf-boundaries
|
||||
company-etags--boundaries)))
|
||||
(expand-common (company-etags--expand-common arg (car rest)))
|
||||
(no-cache company-etags-completion-styles)
|
||||
(location (let ((tags-table-list (company-etags-buffer-table)))
|
||||
(when (fboundp 'find-tag-noselect)
|
||||
(save-excursion
|
||||
(let ((buffer (find-tag-noselect arg)))
|
||||
(cons buffer (with-current-buffer buffer (point))))))))
|
||||
(match (when company-etags-completion-styles
|
||||
(company--match-from-capf-face arg)))
|
||||
(ignore-case company-etags-ignore-case)))
|
||||
|
||||
(provide 'company-etags)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; company-files.el --- company-mode completion backend for file names
|
||||
;;; company-files.el --- company-mode completion backend for file names -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2009-2011, 2013-2021 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2009-2011, 2013-2024 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Nikolaj Schumacher
|
||||
|
||||
@@ -38,22 +38,14 @@ The values should use the same format as `completion-ignored-extensions'."
|
||||
:type '(repeat (string :tag "File extension or directory name"))
|
||||
:package-version '(company . "0.9.1"))
|
||||
|
||||
(defcustom company-files-chop-trailing-slash t
|
||||
"Non-nil to remove the trailing slash after inserting directory name.
|
||||
|
||||
This way it's easy to continue completion by typing `/' again.
|
||||
|
||||
Set this to nil to disable that behavior."
|
||||
:type 'boolean)
|
||||
|
||||
(defun company-files--directory-files (dir prefix)
|
||||
;; Don't use directory-files. It produces directories without trailing /.
|
||||
(condition-case err
|
||||
(condition-case _err
|
||||
(let ((comp (sort (file-name-all-completions prefix dir)
|
||||
(lambda (s1 s2) (string-lessp (downcase s1) (downcase s2))))))
|
||||
(when company-files-exclusions
|
||||
(setq comp (company-files--exclusions-filtered comp)))
|
||||
(if (equal prefix "")
|
||||
(if (string-empty-p prefix)
|
||||
(delete "../" (delete "./" comp))
|
||||
comp))
|
||||
(file-error nil)))
|
||||
@@ -105,54 +97,58 @@ Set this to nil to disable that behavior."
|
||||
|
||||
(defvar company-files--completion-cache nil)
|
||||
|
||||
(defun company-files--complete (prefix)
|
||||
(let* ((dir (file-name-directory prefix))
|
||||
(file (file-name-nondirectory prefix))
|
||||
(defun company-files--complete (_prefix)
|
||||
(let* ((full-prefix (company-files--grab-existing-name))
|
||||
(dir (file-name-directory full-prefix))
|
||||
(file (file-name-nondirectory full-prefix))
|
||||
(key (list file
|
||||
(expand-file-name dir)
|
||||
(nth 5 (file-attributes dir))))
|
||||
(completion-ignore-case read-file-name-completion-ignore-case))
|
||||
(unless (company-file--keys-match-p key (car company-files--completion-cache))
|
||||
(let* ((candidates (mapcar (lambda (f) (concat dir f))
|
||||
(company-files--directory-files dir file)))
|
||||
(unless (or (company-file--keys-match-p key (car company-files--completion-cache))
|
||||
(not (company-files--connected-p dir)))
|
||||
(let* ((candidates (company-files--directory-files dir file))
|
||||
(directories (unless (file-remote-p dir)
|
||||
(cl-remove-if-not (lambda (f)
|
||||
(and (company-files--trailing-slash-p f)
|
||||
(not (file-remote-p f))
|
||||
(company-files--connected-p f)))
|
||||
(company-files--trailing-slash-p f))
|
||||
candidates)))
|
||||
(children (and directories
|
||||
(cl-mapcan (lambda (d)
|
||||
(mapcar (lambda (c) (concat d c))
|
||||
(company-files--directory-files d "")))
|
||||
(company-files--directory-files d ""))
|
||||
directories))))
|
||||
(setq company-files--completion-cache
|
||||
(cons key (append candidates children)))))
|
||||
(all-completions prefix
|
||||
(cdr company-files--completion-cache))))
|
||||
(all-completions file (cdr company-files--completion-cache))))
|
||||
|
||||
(defun company-files--prefix ()
|
||||
(let ((existing (company-files--grab-existing-name)))
|
||||
(when existing
|
||||
(list existing (company-grab-suffix "[^ '\"\t\n\r/]*/?")))))
|
||||
|
||||
(defun company-file--keys-match-p (new old)
|
||||
(and (equal (cdr old) (cdr new))
|
||||
(string-prefix-p (car old) (car new))))
|
||||
|
||||
(defun company-files--post-completion (arg)
|
||||
(when (and company-files-chop-trailing-slash
|
||||
(company-files--trailing-slash-p arg))
|
||||
(delete-char -1)))
|
||||
(defun company-files--adjust-boundaries (_file prefix suffix)
|
||||
(cons
|
||||
(file-name-nondirectory prefix)
|
||||
suffix))
|
||||
|
||||
;;;###autoload
|
||||
(defun company-files (command &optional arg &rest ignored)
|
||||
(defun company-files (command &optional arg &rest rest)
|
||||
"`company-mode' completion backend existing file names.
|
||||
Completions works for proper absolute and relative files paths.
|
||||
File paths with spaces are only supported inside strings."
|
||||
(interactive (list 'interactive))
|
||||
(cl-case command
|
||||
(interactive (company-begin-backend 'company-files))
|
||||
(prefix (company-files--grab-existing-name))
|
||||
(candidates (company-files--complete arg))
|
||||
(prefix (company-files--prefix))
|
||||
(candidates
|
||||
(company-files--complete arg))
|
||||
(adjust-boundaries
|
||||
(company-files--adjust-boundaries arg (nth 0 rest) (nth 1 rest)))
|
||||
(location (cons (dired-noselect
|
||||
(file-name-directory (directory-file-name arg))) 1))
|
||||
(post-completion (company-files--post-completion arg))
|
||||
(kind (if (string-suffix-p "/" arg) 'folder 'file))
|
||||
(sorted t)
|
||||
(no-cache t)))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; company-gtags.el --- company-mode completion backend for GNU Global
|
||||
;;; company-gtags.el --- company-mode completion backend for GNU Global -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2009-2011, 2013-2021 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2009-2011, 2013-2021, 2023 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Nikolaj Schumacher
|
||||
|
||||
@@ -97,7 +97,6 @@ completion."
|
||||
|
||||
(defun company-gtags--fetch-tags (prefix)
|
||||
(with-temp-buffer
|
||||
(let (tags)
|
||||
;; For some reason Global v 6.6.3 is prone to returning exit status 1
|
||||
;; even on successful searches when '-T' is used.
|
||||
(when (/= 3 (process-file (company-gtags--executable) nil
|
||||
@@ -118,7 +117,7 @@ completion."
|
||||
'meta (match-string 4)
|
||||
'location (cons (expand-file-name (match-string 3))
|
||||
(string-to-number (match-string 2)))
|
||||
))))))
|
||||
)))))
|
||||
|
||||
(defun company-gtags--annotation (arg)
|
||||
(let ((meta (get-text-property 0 'meta arg)))
|
||||
@@ -135,14 +134,14 @@ completion."
|
||||
start (point)))))))
|
||||
|
||||
;;;###autoload
|
||||
(defun company-gtags (command &optional arg &rest ignored)
|
||||
(defun company-gtags (command &optional arg &rest _ignored)
|
||||
"`company-mode' completion backend for GNU Global."
|
||||
(interactive (list 'interactive))
|
||||
(cl-case command
|
||||
(interactive (company-begin-backend 'company-gtags))
|
||||
(prefix (and (company-gtags--executable)
|
||||
buffer-file-name
|
||||
(apply #'derived-mode-p company-gtags-modes)
|
||||
(cl-some #'derived-mode-p company-gtags-modes)
|
||||
(not (company-in-string-or-comment))
|
||||
(company-gtags--tags-available-p)
|
||||
(or (company-grab-symbol) 'stop)))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; company-ispell.el --- company-mode completion backend using Ispell
|
||||
;;; company-ispell.el --- company-mode completion backend using Ispell -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2009-2011, 2013-2016, 2018, 2021 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2009-2011, 2013-2016, 2018, 2021, 2023 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Nikolaj Schumacher
|
||||
|
||||
@@ -33,51 +33,67 @@
|
||||
"Completion backend using Ispell."
|
||||
:group 'company)
|
||||
|
||||
(defun company--set-dictionary (symbol value)
|
||||
(set-default-toplevel-value symbol value)
|
||||
(company-cache-delete 'ispell-candidates))
|
||||
|
||||
(defcustom company-ispell-dictionary nil
|
||||
"Dictionary to use for `company-ispell'.
|
||||
If nil, use `ispell-complete-word-dict'."
|
||||
|
||||
If nil, use `ispell-complete-word-dict' or `ispell-alternate-dictionary'."
|
||||
:type '(choice (const :tag "default (nil)" nil)
|
||||
(file :tag "dictionary" t)))
|
||||
(file :tag "dictionary" t))
|
||||
:set #'company--set-dictionary)
|
||||
|
||||
(defvar company-ispell-available 'unknown)
|
||||
|
||||
(defalias 'company-ispell--lookup-words
|
||||
(if (fboundp 'ispell-lookup-words)
|
||||
'ispell-lookup-words
|
||||
'lookup-words))
|
||||
|
||||
(defun company-ispell-available ()
|
||||
(when (eq company-ispell-available 'unknown)
|
||||
(condition-case err
|
||||
(progn
|
||||
(company-ispell--lookup-words "WHATEVER")
|
||||
(ispell-lookup-words "WHATEVER")
|
||||
(setq company-ispell-available t))
|
||||
(error
|
||||
(message "Company-Ispell: %s" (error-message-string err))
|
||||
(setq company-ispell-available nil))))
|
||||
company-ispell-available)
|
||||
|
||||
(defun company--ispell-dict ()
|
||||
"Determine which dictionary to use."
|
||||
(let ((dict (or company-ispell-dictionary
|
||||
ispell-complete-word-dict
|
||||
ispell-alternate-dictionary)))
|
||||
(when dict
|
||||
(expand-file-name dict))))
|
||||
|
||||
;;;###autoload
|
||||
(defun company-ispell (command &optional arg &rest ignored)
|
||||
(defun company-ispell (command &optional arg &rest _ignored)
|
||||
"`company-mode' completion backend using Ispell."
|
||||
(interactive (list 'interactive))
|
||||
(cl-case command
|
||||
(interactive (company-begin-backend 'company-ispell))
|
||||
(prefix (when (company-ispell-available)
|
||||
(company-grab-word)))
|
||||
(list
|
||||
(company-grab-word)
|
||||
(company-grab-word-suffix))))
|
||||
(candidates
|
||||
(let ((words (company-ispell--lookup-words
|
||||
arg
|
||||
(or company-ispell-dictionary ispell-complete-word-dict)))
|
||||
(completion-ignore-case t))
|
||||
(if (string= arg "")
|
||||
(let* ((dict (company--ispell-dict))
|
||||
(all-words
|
||||
(company-cache-fetch 'ispell-candidates
|
||||
(lambda () (ispell-lookup-words "" dict))
|
||||
:check-tag dict))
|
||||
(completion-ignore-case t))
|
||||
(if (string-empty-p arg)
|
||||
;; Small optimization.
|
||||
words
|
||||
;; Work around issue #284.
|
||||
(all-completions arg words))))
|
||||
all-words
|
||||
(company-substitute-prefix
|
||||
arg
|
||||
;; Work around issue #284.
|
||||
(all-completions arg all-words)))))
|
||||
(kind 'text)
|
||||
(no-cache t)
|
||||
(sorted t)
|
||||
(ignore-case 'keep-prefix)))
|
||||
(ignore-case t)))
|
||||
|
||||
(provide 'company-ispell)
|
||||
;;; company-ispell.el ends here
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; company-keywords.el --- A company backend for programming language keywords
|
||||
;;; company-keywords.el --- A company backend for programming language keywords -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2009-2011, 2013-2018, 2020-2021 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2009-2011, 2013-2018, 2020-2023 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Nikolaj Schumacher
|
||||
|
||||
@@ -403,7 +403,21 @@
|
||||
"i16" "i32" "i64" "include" "list" "map" "oneway" "optional" "required"
|
||||
"service" "set" "string" "struct" "throws" "typedef" "void"
|
||||
)
|
||||
(tuareg-mode
|
||||
;; ocaml, from https://v2.ocaml.org/manual/lex.html#sss:keywords
|
||||
"and" "as" "asr" "assert" "begin" "class"
|
||||
"constraint" "do" "done" "downto" "else" "end"
|
||||
"exception" "external" "false" "for" "fun" "function"
|
||||
"functor" "if" "in" "include" "inherit" "initializer"
|
||||
"land" "lazy" "let" "lor" "lsl" "lsr"
|
||||
"lxor" "match" "method" "mod" "module" "mutable"
|
||||
"new" "nonrec" "object" "of" "open" "or"
|
||||
"private" "rec" "sig" "struct" "then" "to"
|
||||
"true" "try" "type" "val" "virtual" "when"
|
||||
"while" "with"
|
||||
)
|
||||
;; aliases
|
||||
(caml-mode . tuareg-mode)
|
||||
(js2-mode . javascript-mode)
|
||||
(js2-jsx-mode . javascript-mode)
|
||||
(espresso-mode . javascript-mode)
|
||||
@@ -413,6 +427,7 @@
|
||||
(cperl-mode . perl-mode)
|
||||
(jde-mode . java-mode)
|
||||
(ess-julia-mode . julia-mode)
|
||||
(php-ts-mode . php-mode)
|
||||
(phps-mode . php-mode)
|
||||
(enh-ruby-mode . ruby-mode))
|
||||
"Alist mapping major-modes to sorted keywords for `company-keywords'.")
|
||||
@@ -439,7 +454,7 @@
|
||||
(makefile-mode . makefile-statements))))
|
||||
|
||||
;;;###autoload
|
||||
(defun company-keywords (command &optional arg &rest ignored)
|
||||
(defun company-keywords (command &optional arg &rest _ignored)
|
||||
"`company-mode' backend for programming language keywords."
|
||||
(interactive (list 'interactive))
|
||||
(cl-case command
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; company-nxml.el --- company-mode completion backend for nxml-mode
|
||||
;;; company-nxml.el --- company-mode completion backend for nxml-mode -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2009-2011, 2013-2015, 2017-2018 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2009-2011, 2013-2015, 2017-2018, 2023 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Nikolaj Schumacher
|
||||
|
||||
@@ -71,12 +71,11 @@
|
||||
|
||||
(defmacro company-nxml-prepared (&rest body)
|
||||
(declare (indent 0) (debug t))
|
||||
`(let ((lt-pos (save-excursion (search-backward "<" nil t)))
|
||||
xmltok-dtd)
|
||||
`(let ((lt-pos (save-excursion (search-backward "<" nil t))))
|
||||
(when (and lt-pos (= (rng-set-state-after lt-pos) lt-pos))
|
||||
,@body)))
|
||||
|
||||
(defun company-nxml-tag (command &optional arg &rest ignored)
|
||||
(defun company-nxml-tag (command &optional arg &rest _ignored)
|
||||
(cl-case command
|
||||
(prefix (and (derived-mode-p 'nxml-mode)
|
||||
rng-validate-mode
|
||||
@@ -86,7 +85,7 @@
|
||||
arg (rng-match-possible-start-tag-names))))
|
||||
(sorted t)))
|
||||
|
||||
(defun company-nxml-attribute (command &optional arg &rest ignored)
|
||||
(defun company-nxml-attribute (command &optional arg &rest _ignored)
|
||||
(cl-case command
|
||||
(prefix (and (derived-mode-p 'nxml-mode)
|
||||
rng-validate-mode
|
||||
@@ -99,7 +98,7 @@
|
||||
arg (rng-match-possible-attribute-names)))))
|
||||
(sorted t)))
|
||||
|
||||
(defun company-nxml-attribute-value (command &optional arg &rest ignored)
|
||||
(defun company-nxml-attribute-value (command &optional arg &rest _ignored)
|
||||
(cl-case command
|
||||
(prefix (and (derived-mode-p 'nxml-mode)
|
||||
rng-validate-mode
|
||||
@@ -121,7 +120,7 @@
|
||||
arg (rng-match-possible-value-strings))))))))
|
||||
|
||||
;;;###autoload
|
||||
(defun company-nxml (command &optional arg &rest ignored)
|
||||
(defun company-nxml (command &optional arg &rest _ignored)
|
||||
"`company-mode' completion backend for `nxml-mode'."
|
||||
(interactive (list 'interactive))
|
||||
(cl-case command
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; company-oddmuse.el --- company-mode completion backend for oddmuse-mode
|
||||
;;; company-oddmuse.el --- company-mode completion backend for oddmuse-mode -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2009-2011, 2013-2016, 2022 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2009-2011, 2013-2016, 2022, 2023 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Nikolaj Schumacher
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
(oddmuse-make-completion-table oddmuse-wiki)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun company-oddmuse (command &optional arg &rest ignored)
|
||||
(defun company-oddmuse (command &optional arg &rest _ignored)
|
||||
"`company-mode' completion backend for `oddmuse-mode'."
|
||||
(interactive (list 'interactive))
|
||||
(cl-case command
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
(define-package "company" "20221206.2122" "Modular text completion framework"
|
||||
'((emacs "25.1"))
|
||||
:commit "6884e3ad717419b4a64a5fab08c8cb9bd20a0b27" :maintainer
|
||||
'("Dmitry Gutov" . "dgutov@yandex.ru")
|
||||
(define-package "company" "20250228.258" "Modular text completion framework"
|
||||
'((emacs "26.1"))
|
||||
:commit "8d599ebc8a9aca27c0a6157aeb31c5b7f05ed0a3" :maintainers
|
||||
'(("Dmitry Gutov" . "dmitry@gutov.dev"))
|
||||
:maintainer
|
||||
'("Dmitry Gutov" . "dmitry@gutov.dev")
|
||||
:keywords
|
||||
'("abbrev" "convenience" "matching")
|
||||
:url "http://company-mode.github.io/")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; company-semantic.el --- company-mode completion backend using Semantic
|
||||
;;; company-semantic.el --- company-mode completion backend using Semantic -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2009-2011, 2013-2018 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2009-2011, 2013-2018, 2023 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Nikolaj Schumacher
|
||||
|
||||
@@ -126,11 +126,11 @@ and `c-electric-colon', for automatic completion right after \">\" and
|
||||
|
||||
(defun company-semantic--prefix ()
|
||||
(if company-semantic-begin-after-member-access
|
||||
(company-grab-symbol-cons "\\.\\|->\\|::" 2)
|
||||
(company-grab-symbol)))
|
||||
(company-grab-symbol-parts "\\.\\|->\\|::" 2)
|
||||
(company-grab-symbol-parts)))
|
||||
|
||||
;;;###autoload
|
||||
(defun company-semantic (command &optional arg &rest ignored)
|
||||
(defun company-semantic (command &optional arg &rest _ignored)
|
||||
"`company-mode' completion backend using CEDET Semantic."
|
||||
(interactive (list 'interactive))
|
||||
(cl-case command
|
||||
@@ -140,7 +140,7 @@ and `c-electric-colon', for automatic completion right after \">\" and
|
||||
(memq major-mode company-semantic-modes)
|
||||
(not (company-in-string-or-comment))
|
||||
(or (company-semantic--prefix) 'stop)))
|
||||
(candidates (if (and (equal arg "")
|
||||
(candidates (if (and (string-empty-p arg)
|
||||
(not (looking-back "->\\|\\.\\|::" (- (point) 2))))
|
||||
(company-semantic-completions-raw arg)
|
||||
(company-semantic-completions arg)))
|
||||
@@ -151,7 +151,7 @@ and `c-electric-colon', for automatic completion right after \">\" and
|
||||
(doc-buffer (company-semantic-doc-buffer
|
||||
(assoc arg company-semantic--current-tags)))
|
||||
;; Because "" is an empty context and doesn't return local variables.
|
||||
(no-cache (equal arg ""))
|
||||
(no-cache (string-empty-p arg))
|
||||
(duplicates t)
|
||||
(location (let ((tag (assoc arg company-semantic--current-tags)))
|
||||
(when (buffer-live-p (semantic-tag-buffer tag))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; company-template.el --- utility library for template expansion
|
||||
;;; company-template.el --- utility library for template expansion -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2009-2010, 2013-2017, 2019 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2009-2010, 2013-2017, 2019, 2023-2024 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Nikolaj Schumacher
|
||||
|
||||
@@ -205,6 +205,7 @@ after deleting a field in `company-template-remove-field'."
|
||||
(let* ((end (point-marker))
|
||||
(beg (- (point) (length call)))
|
||||
(templ (company-template-declare-template beg end))
|
||||
forward-sexp-function
|
||||
paren-open paren-close)
|
||||
(with-syntax-table (make-syntax-table (syntax-table))
|
||||
(modify-syntax-entry ?< "(")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; company-tempo.el --- company-mode completion backend for tempo
|
||||
;;; company-tempo.el --- company-mode completion backend for tempo -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2009-2011, 2013-2016 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2009-2011, 2013-2016, 2023 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Nikolaj Schumacher
|
||||
|
||||
@@ -56,13 +56,14 @@
|
||||
(car (split-string doc "\n" t)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun company-tempo (command &optional arg &rest ignored)
|
||||
(defun company-tempo (command &optional arg &rest _ignored)
|
||||
"`company-mode' completion backend for tempo."
|
||||
(interactive (list 'interactive))
|
||||
(cl-case command
|
||||
(interactive (company-begin-backend 'company-tempo))
|
||||
(prefix (or (car (tempo-find-match-string tempo-match-finder)) ""))
|
||||
(candidates (all-completions arg (tempo-build-collection)))
|
||||
(kind 'snippet)
|
||||
(meta (company-tempo-meta arg))
|
||||
(post-completion (when company-tempo-expand (company-tempo-insert arg)))
|
||||
(sorted t)))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; company-tng.el --- company-mode configuration for single-button interaction
|
||||
;;; company-tng.el --- company-mode configuration for single-button interaction -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2017-2021 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2017-2024 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Nikita Leshenko
|
||||
|
||||
@@ -111,7 +111,7 @@ confirm the selection and finish the completion."
|
||||
(let* ((ov company-tng--overlay)
|
||||
(selected (and company-selection
|
||||
(nth company-selection company-candidates)))
|
||||
(prefix (length company-prefix)))
|
||||
(prefix (length (car (company--boundaries)))))
|
||||
(move-overlay ov (- (point) prefix) (point))
|
||||
(overlay-put ov
|
||||
(if (= prefix 0) 'after-string 'display)
|
||||
@@ -140,7 +140,7 @@ confirm the selection and finish the completion."
|
||||
:type 'boolean)
|
||||
|
||||
;;;###autoload
|
||||
(define-obsolete-function-alias 'company-tng-configure-default 'company-tng-mode "0.9.14"
|
||||
(define-obsolete-function-alias 'company-tng-configure-default 'company-tng-mode "0.10.0"
|
||||
"Applies the default configuration to enable company-tng.")
|
||||
|
||||
(declare-function eglot--snippet-expansion-fn "eglot")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
;;; company-yasnippet.el --- company-mode completion backend for Yasnippet
|
||||
;;; company-yasnippet.el --- company-mode completion backend for Yasnippet -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2014-2015, 2020-2021 Free Software Foundation, Inc.
|
||||
;; Copyright (C) 2014-2015, 2020-2023 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Dmitry Gutov
|
||||
|
||||
@@ -72,7 +72,7 @@ It has to accept one argument: the snippet's name.")
|
||||
(let ((prefix (buffer-substring-no-properties (point) original)))
|
||||
(unless (equal prefix (car prefixes))
|
||||
(push prefix prefixes))))
|
||||
prefixes)))
|
||||
(nreverse prefixes))))
|
||||
|
||||
(defun company-yasnippet--candidates (prefix)
|
||||
;; Process the prefixes in reverse: unlike Yasnippet, we look for prefix
|
||||
@@ -135,8 +135,24 @@ It has to accept one argument: the snippet's name.")
|
||||
(ignore-errors (font-lock-ensure))))
|
||||
(current-buffer))))
|
||||
|
||||
(defun company-yasnippet--prefix ()
|
||||
;; We can avoid the prefix length manipulations after GH#426 is fixed.
|
||||
(let* ((prefix (company-grab-symbol))
|
||||
(tables (yas--get-snippet-tables))
|
||||
(key-prefixes (company-yasnippet--key-prefixes))
|
||||
key-prefix)
|
||||
(while (and key-prefixes
|
||||
(setq key-prefix (pop key-prefixes)))
|
||||
(when (company-yasnippet--completions-for-prefix
|
||||
prefix key-prefix tables)
|
||||
;; Stop iteration.
|
||||
(setq key-prefixes nil)))
|
||||
(if (equal key-prefix prefix)
|
||||
prefix
|
||||
(cons prefix (length key-prefix)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun company-yasnippet (command &optional arg &rest ignore)
|
||||
(defun company-yasnippet (command &optional arg &rest _ignore)
|
||||
"`company-mode' backend for `yasnippet'.
|
||||
|
||||
This backend should be used with care, because as long as there are
|
||||
@@ -163,10 +179,8 @@ shadow backends that come after it. Recommended usages:
|
||||
(cl-case command
|
||||
(interactive (company-begin-backend 'company-yasnippet))
|
||||
(prefix
|
||||
;; Should probably use `yas--current-key', but that's bound to be slower.
|
||||
;; How many trigger keys start with non-symbol characters anyway?
|
||||
(and (bound-and-true-p yas-minor-mode)
|
||||
(company-grab-symbol)))
|
||||
(company-yasnippet--prefix)))
|
||||
(annotation
|
||||
(funcall company-yasnippet-annotation-fn
|
||||
(get-text-property 0 'yas-annotation arg)))
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,7 +0,0 @@
|
||||
;;; Directory Local Variables
|
||||
;;; For more information see (info "(emacs) Directory Variables")
|
||||
|
||||
((emacs-lisp-mode
|
||||
(byte-compile-docstring-max-column . 100)
|
||||
(show-trailing-whitespace . t)
|
||||
(indent-tabs-mode . nil)))
|
||||
@@ -1,9 +1,205 @@
|
||||
#+options: toc:nil num:nil
|
||||
#+link: compat https://todo.sr.ht/~pkal/compat/
|
||||
#+link: compat-srht https://todo.sr.ht/~pkal/compat/
|
||||
#+link: compat-gh https://github.com/emacs-compat/compat/issues/
|
||||
#+options: toc:nil num:nil author:nil
|
||||
|
||||
* Release of "Compat" Version 29.1.4.2
|
||||
|
||||
- compat-28: Improve =make-separator-line= visuals on graphic displays.
|
||||
- compat-28: Add =native-comp-available-p=, which always returns nil.
|
||||
- compat-29: Add variable =lisp-directory=.
|
||||
|
||||
(Release <2023-07-30 Sun>)
|
||||
|
||||
* Release of "Compat" Version 29.1.4.1
|
||||
|
||||
- compat-29: Add ~directory-abbrev-apply~.
|
||||
- compat-29: Add ~directory-abbrev-make-regexp~.
|
||||
|
||||
(Release <2023-03-26 Sun>)
|
||||
|
||||
* Release of "Compat" Version 29.1.4.0
|
||||
|
||||
- compat-27: Drop obsolete ~compat-call dired-get-marked-files~.
|
||||
- compat-28: Add support for ~defcustom~ type ~natnum~.
|
||||
- compat-29: Add ~with-restriction~ and ~without-restriction~.
|
||||
- compat-29: Add ~cl-constantly~.
|
||||
- compat-29: Drop ~with-narrowing~ which was renamed to ~with-restriction~.
|
||||
- compat-28: Add support for ~defcustom~ type ~key~.
|
||||
|
||||
(Release <2023-03-05 Sun>)
|
||||
|
||||
* Release of "Compat" Version 29.1.3.4
|
||||
|
||||
- Ensure that ~seq~ is required properly both at compile time and runtime, such
|
||||
that compilation of downstream packages works even if Compat itself is not
|
||||
compiled. Magit uses a complex continuous integration system, where Magit is
|
||||
compiled and tested, while the Compat dependency is not compiled.
|
||||
- compat-28: Add ~process-lines-handling-status~ and ~process-lines-ignore-status~.
|
||||
|
||||
(Release <2023-02-11 Sat>)
|
||||
|
||||
* Release of "Compat" Version 29.1.3.3
|
||||
|
||||
- compat-27: Add ~with-suppressed-warnings~.
|
||||
- compat-29: Add ~cl-with-gensyms~ and ~cl-once-only~.
|
||||
- compat-29: Load ~seq~, which is preloaded on Emacs 29.
|
||||
|
||||
(Release <2023-02-08 Wed>)
|
||||
|
||||
* Release of "Compat" Version 29.1.3.2
|
||||
|
||||
- compat-26: Add ~make-temp-file~ with optional argument TEXT.
|
||||
- compat-27: Mark ~compat-call dired-get-marked-files~ as obsolete. See the
|
||||
section limitations in the Compat manual.
|
||||
- compat-29: Add ~funcall-with-delayed-message~ and ~with-delayed-message~.
|
||||
- compat-29: Add ~ert-with-temp-file~ and ~ert-with-temp-directory~.
|
||||
- compat-29: Add ~set-transient-map~ with optional arguments MESSAGE and TIMEOUT.
|
||||
|
||||
(Release <2023-02-01 Wed>)
|
||||
|
||||
* Release of "Compat" Version 29.1.3.1
|
||||
|
||||
- Fix regression, which prevented loading Compat in interpreted mode. We ensure
|
||||
that Compat works interpreted and byte compiled by running the entire test
|
||||
suite twice in the CI. See https://github.com/magit/magit/issues/4858 for the
|
||||
corresponding Magit issue.
|
||||
- compat-27: Add ~file-name-unquote~.
|
||||
- compat-28: Add ~mark-thing-at-mouse~.
|
||||
- compat-29: Replace ~string-lines~ with version from Emacs 29, support optional
|
||||
KEEP-NEWLINES argument.
|
||||
|
||||
(Release <2023-01-25 Wed>)
|
||||
|
||||
* Release of "Compat" Version 29.1.3.0
|
||||
|
||||
- compat-25: Add ~hash-table-empty-p~.
|
||||
- compat-25: Add ~macroexp-parse-body~ and ~macroexp-quote~.
|
||||
- compat-25: Add ~region-noncontiguous-p~.
|
||||
- compat-25: Add ~save-mark-and-excursion~.
|
||||
- compat-26: Add ~read-answer~.
|
||||
- compat-26: Add ~region-bounds~.
|
||||
- compat-27: Add ~date-ordinal-to-time~.
|
||||
- compat-27: Add ~file-size-human-readable-iec~.
|
||||
- compat-27: Add ~major-mode-suspend~ and ~major-mode-restore~.
|
||||
- compat-27: Add ~make-decoded-time~.
|
||||
- compat-27: Add ~minibuffer-history-value~.
|
||||
- compat-27: Add ~read-char-from-minibuffer~.
|
||||
- compat-27: Add ~ring-resize~.
|
||||
- compat-28: Add ~color-dark-p~.
|
||||
- compat-28: Add ~directory-files-and-attributes~ with COUNT argument.
|
||||
- compat-28: Add ~text-quoting-style~.
|
||||
- compat-28: Add ~with-window-non-dedicated~.
|
||||
- compat-29: Add ~buffer-local-set-state~ and ~buffer-local-restore-state~.
|
||||
- compat-29: Add ~compiled-function-p~.
|
||||
- compat-29: Add ~count-sentences~.
|
||||
- compat-29: Add ~delete-line~.
|
||||
- compat-29: Add ~get-scratch-buffer-create~.
|
||||
- compat-29: Add ~list-of-strings-p~.
|
||||
- compat-29: Add ~plist-get~ generalized variable.
|
||||
- compat-29: Add ~plistp~.
|
||||
- compat-29: Add ~read-multiple-choice~ with LONG-FORM argument.
|
||||
- compat-29: Add ~readablep~.
|
||||
- compat-29: Add ~substitute-quotes~.
|
||||
- compat-29: Add ~use-region-beginning~, ~use-region-end~ and ~use-region-noncontiguous-p~.
|
||||
- compat-29: Add ~with-narrowing~.
|
||||
|
||||
(Release <2023-01-22 Sun>)
|
||||
|
||||
* Release of "Compat" Version 29.1.2.0
|
||||
|
||||
- All compatibility functions are covered by tests!
|
||||
- Add links from compatibility definitions to tests.
|
||||
- BREAKING: Drop JSON parsing support (libjansson API, unused downstream).
|
||||
- BREAKING: Drop ~null-device~ (unused downstream).
|
||||
- BREAKING: Drop ~unlock-buffer~ (unused downstream).
|
||||
- compat-26: Add ~buffer-hash~.
|
||||
- compat-27: Add ~fixnump~ and ~bignump~.
|
||||
- compat-27: Add ~with-minibuffer-selected-window~.
|
||||
- compat-27: Add generalized variables for ~decoded-time-*~.
|
||||
- compat-28: Add ~macroexp-warn-and-return~.
|
||||
- compat-28: Add ~subr-native-elisp-p~.
|
||||
- compat-28: Add ~bounds-of-thing-at-mouse~.
|
||||
- compat-29: Add ~with-buffer-unmodified-if-unchanged~.
|
||||
- compat-29: Fix and test ~define-key~ with REMOVE argument.
|
||||
|
||||
(Release <2023-01-16 Mon>)
|
||||
|
||||
* Release of "Compat" Version 29.1.1.1
|
||||
|
||||
- Add tests, 167 out of 203 definitions tested (82%).
|
||||
- compat-25: Improve algorithmic complexity of ~sort~.
|
||||
- compat-28: Add ~make-separator-line~.
|
||||
- compat-29: Minor fixes to ~keymap-*~ functions.
|
||||
- compat-29: Add ~with-memoization~.
|
||||
- compat-29: Add ~buttonize~ and ~buttonize-region~.
|
||||
|
||||
(Release <2023-01-14 Sat>)
|
||||
|
||||
* Release of "Compat" Version 29.1.1.0
|
||||
|
||||
- The macros in ~compat-macs.el~ have been rewritten and simplified. The
|
||||
refactoring allows to further refine the criteria under which compatibility
|
||||
aliases, functions, macros and variables are installed.
|
||||
- Remove deprecated, prefixed compatibility functions.
|
||||
- Remove deprecated features ~compat-help~, ~compat-font-lock~ and ~compat-24~.
|
||||
- Compat uses runtime checks (~boundp~, ~fboundp~) to ensure that existing
|
||||
definitions are never overridden, when Compat is loaded on a newer Emacs than
|
||||
it was compiled on.
|
||||
- Compat compiles without byte compilation warnings on all supported Emacs
|
||||
versions. Warnings are treated as errors in the test suite.
|
||||
- Compat takes great care to remove unneeded definitions at compile time. On
|
||||
recent Emacs 29 the byte compiled files are empty and not loaded, such that
|
||||
Compat does not any cost to the Emacs process.
|
||||
- compat-26: Fix and test ~image-property~ setter.
|
||||
- compat-26: Fix and test ~read-multiple-choice~.
|
||||
- compat-28: Fix and test ~with-existing-directory~.
|
||||
- compat-28: Drop obsolete function ~make-directory-autoloads~.
|
||||
- compat-29: Drop broken functions ~string-pixel-width~ and
|
||||
~buffer-text-pixel-size~. These functions had poor performance which lead to a
|
||||
downstream issue in the doom-modeline package. If a more efficient solution is
|
||||
possible, the function will be added back. See [[compat-gh:8]] for the bug report.
|
||||
- compat-29: Drop broken function ~string-limit~.
|
||||
- compat-29: Drop broken macro ~with-buffer-unmodified-if-unchanged~, which relied
|
||||
on ~buffer-hash~ which does not exist on all supported Emacs versions.
|
||||
- compat-29: Add ~pos-bol~ and ~pos-eol~.
|
||||
|
||||
(Release <2023-01-07 Sat>)
|
||||
|
||||
* Release of "Compat" Version 29.1.0.1
|
||||
|
||||
- Add multiple new tests for existing APIs.
|
||||
- Fix bugs in compatibility functions: ~setq-local~, ~proper-list-p, prop-match-p~,
|
||||
~file-name-concat~, ~replace-regexp-in-region~, ~replace-string-in-region~.
|
||||
- Add new Emacs 29 APIs. Some of them are still untested and may change. If you
|
||||
intend to use an Emacs 29 API please be careful and if possible contribute
|
||||
test cases. All untested functions are marked in the Compat code. Over time
|
||||
tests for all functions will be added gradually.
|
||||
- Add the macros ~compat-call~ and ~compat-function~ to call compatibility
|
||||
functions. Since Compat avoids overwriting already existing functions, we must
|
||||
define separate compatibility function definitions for functions which changed
|
||||
their calling convention or behavior. These compatibility definitions can be
|
||||
looked up using ~compat-function~ and called with ~compat-call~. For example ~assoc~
|
||||
can be called with a ~TESTFN~ since Emacs 26. In Emacs 25 and older the calling
|
||||
convention was ~(assoc KEY ALIST)~. In order to use the new calling convention
|
||||
you can use ~(compat-call assoc KEY ALIST TESTFN)~.
|
||||
- Deprecate all ~compat-*~ prefixed functions. Instead use the aforementioned
|
||||
~compat-call~ or ~compat-function~ macros.
|
||||
- Deprecate ~compat-help.el~ and ~compat-font-lock.el.~
|
||||
- Development moved to GitHub.
|
||||
- BREAKING: Drop broken function ~func-arity~. Using ~func-arity~ is generally
|
||||
discouraged and the function is hard to implement properly due to all the
|
||||
various function types. There it is unlikely that the function will get
|
||||
reintroduced in Compat.
|
||||
- BREAKING: Drop broken function ~directory-files-recursively~. In case you need
|
||||
this function, a patch including tests is welcome.
|
||||
- BREAKING: Drop support for Emacs 24.3. Emacs 24.4 is required now. In case you
|
||||
still need Emacs 24.3 support, you can rely on Compat 28.1.2.2.
|
||||
|
||||
(Release <2023-01-05 Thu>)
|
||||
|
||||
* Release of "Compat" Version 28.1.2.2
|
||||
|
||||
This is a minor release that hopes to address [[compat:7]].
|
||||
This is a minor release that hopes to address [[compat-srht:7]].
|
||||
|
||||
(Release <2022-08-25 Thu>)
|
||||
|
||||
@@ -25,7 +221,7 @@ include much more documentation that had been the case previously.
|
||||
|
||||
The main change of this release has been the major simplification of
|
||||
Compat's initialisation system, improving the situation around issues
|
||||
people had been reporting ([[compat:4]], once again) with unconventional
|
||||
people had been reporting ([[compat-srht:4]], once again) with unconventional
|
||||
or unpopular packaging systems.
|
||||
|
||||
In addition to this, the following functional changes have been made:
|
||||
@@ -42,7 +238,7 @@ Minor improvements to manual are also part of this release.
|
||||
|
||||
This release just contains a hot-fix for an issue introduced in the
|
||||
last version, where compat.el raises an error during byte compilation.
|
||||
See [[compat:4]].
|
||||
See [[compat-srht:4]].
|
||||
|
||||
(Release <2022-06-19 Sun>)
|
||||
|
||||
@@ -62,7 +258,7 @@ Two main changes have necessitated a new patch release:
|
||||
|
||||
This is a minor release fixing a bug in =json-serialize=, that could
|
||||
cause unintended side-effects, not related to packages using Compat
|
||||
directly (see [[compat:2]]).
|
||||
directly (see [[compat-srht:2]]).
|
||||
|
||||
(Released <2022-05-05 Thu>)
|
||||
|
||||
@@ -98,11 +294,4 @@ as some of these changes a functional. These include:
|
||||
- Handling out-of-directory byte compilation better.
|
||||
- Fixing the usage and edge-cases of =and-let*=.
|
||||
|
||||
Furthermore a bug tracker was added: https://todo.sr.ht/~pkal/compat,
|
||||
which is the preferred way to report issues or feature requests.
|
||||
General problems, questions, etc. are still better discussed on the
|
||||
development mailing list: https://lists.sr.ht/~pkal/compat-devel.
|
||||
|
||||
(Released <2022-04-22 Fri>)
|
||||
|
||||
|
||||
|
||||
@@ -1,495 +0,0 @@
|
||||
;;; compat-24.el --- Compatibility Layer for Emacs 24.4 -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2021, 2022 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Philip Kaludercic <philipk@posteo.net>
|
||||
;; Maintainer: Compat Development <~pkal/compat-devel@lists.sr.ht>
|
||||
;; URL: https://git.sr.ht/~pkal/compat/
|
||||
;; Keywords: lisp
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; Find here the functionality added in Emacs 24.4, needed by older
|
||||
;; versions.
|
||||
;;
|
||||
;; Only load this library if you need to use one of the following
|
||||
;; functions:
|
||||
;;
|
||||
;; - `compat-='
|
||||
;; - `compat-<'
|
||||
;; - `compat->'
|
||||
;; - `compat-<='
|
||||
;; - `compat->='
|
||||
;; - `split-string'.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'compat-macs "compat-macs.el")
|
||||
|
||||
(compat-declare-version "24.4")
|
||||
|
||||
;;;; Defined in data.c
|
||||
|
||||
(compat-defun = (number-or-marker &rest numbers-or-markers)
|
||||
"Handle multiple arguments."
|
||||
:prefix t
|
||||
(catch 'fail
|
||||
(while numbers-or-markers
|
||||
(unless (= number-or-marker (car numbers-or-markers))
|
||||
(throw 'fail nil))
|
||||
(setq number-or-marker (pop numbers-or-markers)))
|
||||
t))
|
||||
|
||||
(compat-defun < (number-or-marker &rest numbers-or-markers)
|
||||
"Handle multiple arguments."
|
||||
:prefix t
|
||||
(catch 'fail
|
||||
(while numbers-or-markers
|
||||
(unless (< number-or-marker (car numbers-or-markers))
|
||||
(throw 'fail nil))
|
||||
(setq number-or-marker (pop numbers-or-markers)))
|
||||
t))
|
||||
|
||||
(compat-defun > (number-or-marker &rest numbers-or-markers)
|
||||
"Handle multiple arguments."
|
||||
:prefix t
|
||||
(catch 'fail
|
||||
(while numbers-or-markers
|
||||
(unless (> number-or-marker (car numbers-or-markers))
|
||||
(throw 'fail nil))
|
||||
(setq number-or-marker (pop numbers-or-markers)))
|
||||
t))
|
||||
|
||||
(compat-defun <= (number-or-marker &rest numbers-or-markers)
|
||||
"Handle multiple arguments."
|
||||
:prefix t
|
||||
(catch 'fail
|
||||
(while numbers-or-markers
|
||||
(unless (<= number-or-marker (car numbers-or-markers))
|
||||
(throw 'fail nil))
|
||||
(setq number-or-marker (pop numbers-or-markers)))
|
||||
t))
|
||||
|
||||
(compat-defun >= (number-or-marker &rest numbers-or-markers)
|
||||
"Handle multiple arguments."
|
||||
:prefix t
|
||||
(catch 'fail
|
||||
(while numbers-or-markers
|
||||
(unless (>= number-or-marker (pop numbers-or-markers))
|
||||
(throw 'fail nil)))
|
||||
t))
|
||||
|
||||
(compat-defun bool-vector-exclusive-or (a b &optional c)
|
||||
"Return A ^ B, bitwise exclusive or.
|
||||
If optional third argument C is given, store result into C.
|
||||
A, B, and C must be bool vectors of the same length.
|
||||
Return the destination vector if it changed or nil otherwise."
|
||||
(unless (bool-vector-p a)
|
||||
(signal 'wrong-type-argument (list 'bool-vector-p a)))
|
||||
(unless (bool-vector-p b)
|
||||
(signal 'wrong-type-argument (list 'bool-vector-p b)))
|
||||
(unless (or (null c) (bool-vector-p c))
|
||||
(signal 'wrong-type-argument (list 'bool-vector-p c)))
|
||||
(when (/= (length a) (length b))
|
||||
(signal 'wrong-length-argument (list (length a) (length b))))
|
||||
(let ((dest (or c (make-bool-vector (length a) nil))) changed)
|
||||
(when (/= (length a) (length dest))
|
||||
(signal 'wrong-length-argument (list (length a) (length dest))))
|
||||
(dotimes (i (length dest))
|
||||
(let ((val (not (eq (aref a i) (aref b i)))))
|
||||
(unless (eq val (aref dest i))
|
||||
(setq changed t))
|
||||
(aset dest i val)))
|
||||
(if c (and changed c) dest)))
|
||||
|
||||
(compat-defun bool-vector-union (a b &optional c)
|
||||
"Return A | B, bitwise or.
|
||||
If optional third argument C is given, store result into C.
|
||||
A, B, and C must be bool vectors of the same length.
|
||||
Return the destination vector if it changed or nil otherwise."
|
||||
(unless (bool-vector-p a)
|
||||
(signal 'wrong-type-argument (list 'bool-vector-p a)))
|
||||
(unless (bool-vector-p b)
|
||||
(signal 'wrong-type-argument (list 'bool-vector-p b)))
|
||||
(unless (or (null c) (bool-vector-p c))
|
||||
(signal 'wrong-type-argument (list 'bool-vector-p c)))
|
||||
(when (/= (length a) (length b))
|
||||
(signal 'wrong-length-argument (list (length a) (length b))))
|
||||
(let ((dest (or c (make-bool-vector (length a) nil))) changed)
|
||||
(when (/= (length a) (length dest))
|
||||
(signal 'wrong-length-argument (list (length a) (length dest))))
|
||||
(dotimes (i (length dest))
|
||||
(let ((val (or (aref a i) (aref b i))))
|
||||
(unless (eq val (aref dest i))
|
||||
(setq changed t))
|
||||
(aset dest i val)))
|
||||
(if c (and changed c) dest)))
|
||||
|
||||
(compat-defun bool-vector-intersection (a b &optional c)
|
||||
"Return A & B, bitwise and.
|
||||
If optional third argument C is given, store result into C.
|
||||
A, B, and C must be bool vectors of the same length.
|
||||
Return the destination vector if it changed or nil otherwise."
|
||||
(unless (bool-vector-p a)
|
||||
(signal 'wrong-type-argument (list 'bool-vector-p a)))
|
||||
(unless (bool-vector-p b)
|
||||
(signal 'wrong-type-argument (list 'bool-vector-p b)))
|
||||
(unless (or (null c) (bool-vector-p c))
|
||||
(signal 'wrong-type-argument (list 'bool-vector-p c)))
|
||||
(when (/= (length a) (length b))
|
||||
(signal 'wrong-length-argument (list (length a) (length b))))
|
||||
(let ((dest (or c (make-bool-vector (length a) nil))) changed)
|
||||
(when (/= (length a) (length dest))
|
||||
(signal 'wrong-length-argument (list (length a) (length dest))))
|
||||
(dotimes (i (length dest))
|
||||
(let ((val (and (aref a i) (aref b i))))
|
||||
(unless (eq val (aref dest i))
|
||||
(setq changed t))
|
||||
(aset dest i val)))
|
||||
(if c (and changed c) dest)))
|
||||
|
||||
(compat-defun bool-vector-set-difference (a b &optional c)
|
||||
"Return A &~ B, set difference.
|
||||
If optional third argument C is given, store result into C.
|
||||
A, B, and C must be bool vectors of the same length.
|
||||
Return the destination vector if it changed or nil otherwise."
|
||||
(unless (bool-vector-p a)
|
||||
(signal 'wrong-type-argument (list 'bool-vector-p a)))
|
||||
(unless (bool-vector-p b)
|
||||
(signal 'wrong-type-argument (list 'bool-vector-p b)))
|
||||
(unless (or (null c) (bool-vector-p c))
|
||||
(signal 'wrong-type-argument (list 'bool-vector-p c)))
|
||||
(when (/= (length a) (length b))
|
||||
(signal 'wrong-length-argument (list (length a) (length b))))
|
||||
(let ((dest (or c (make-bool-vector (length a) nil))) changed)
|
||||
(when (/= (length a) (length dest))
|
||||
(signal 'wrong-length-argument (list (length a) (length dest))))
|
||||
(dotimes (i (length dest))
|
||||
(let ((val (and (aref a i) (not (aref b i)))))
|
||||
(unless (eq val (aref dest i))
|
||||
(setq changed t))
|
||||
(aset dest i val)))
|
||||
(if c (and changed c) dest)))
|
||||
|
||||
(compat-defun bool-vector-not (a &optional b)
|
||||
"Compute ~A, set complement.
|
||||
If optional second argument B is given, store result into B.
|
||||
A and B must be bool vectors of the same length.
|
||||
Return the destination vector."
|
||||
(unless (bool-vector-p a)
|
||||
(signal 'wrong-type-argument (list 'bool-vector-p a)))
|
||||
(unless (or (null b) (bool-vector-p b))
|
||||
(signal 'wrong-type-argument (list 'bool-vector-p b)))
|
||||
(let ((dest (or b (make-bool-vector (length a) nil))))
|
||||
(when (/= (length a) (length dest))
|
||||
(signal 'wrong-length-argument (list (length a) (length dest))))
|
||||
(dotimes (i (length dest))
|
||||
(aset dest i (not (aref a i))))
|
||||
dest))
|
||||
|
||||
(compat-defun bool-vector-subsetp (a b)
|
||||
"Return t if every t value in A is also t in B, nil otherwise.
|
||||
A and B must be bool vectors of the same length."
|
||||
(unless (bool-vector-p a)
|
||||
(signal 'wrong-type-argument (list 'bool-vector-p a)))
|
||||
(unless (bool-vector-p b)
|
||||
(signal 'wrong-type-argument (list 'bool-vector-p b)))
|
||||
(when (/= (length a) (length b))
|
||||
(signal 'wrong-length-argument (list (length a) (length b))))
|
||||
(catch 'not-subset
|
||||
(dotimes (i (length a))
|
||||
(when (if (aref a i) (not (aref b i)) nil)
|
||||
(throw 'not-subset nil)))
|
||||
t))
|
||||
|
||||
(compat-defun bool-vector-count-consecutive (a b i)
|
||||
"Count how many consecutive elements in A equal B starting at I.
|
||||
A is a bool vector, B is t or nil, and I is an index into A."
|
||||
(unless (bool-vector-p a)
|
||||
(signal 'wrong-type-argument (list 'bool-vector-p a)))
|
||||
(setq b (and b t)) ;normalise to nil or t
|
||||
(unless (< i (length a))
|
||||
(signal 'args-out-of-range (list a i)))
|
||||
(let ((len (length a)) (n i))
|
||||
(while (and (< i len) (eq (aref a i) b))
|
||||
(setq i (1+ i)))
|
||||
(- i n)))
|
||||
|
||||
(compat-defun bool-vector-count-population (a)
|
||||
"Count how many elements in A are t.
|
||||
A is a bool vector. To count A's nil elements, subtract the
|
||||
return value from A's length."
|
||||
(unless (bool-vector-p a)
|
||||
(signal 'wrong-type-argument (list 'bool-vector-p a)))
|
||||
(let ((n 0))
|
||||
(dotimes (i (length a))
|
||||
(when (aref a i)
|
||||
(setq n (1+ n))))
|
||||
n))
|
||||
|
||||
;;;; Defined in subr.el
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defmacro with-eval-after-load (file &rest body)
|
||||
"Execute BODY after FILE is loaded.
|
||||
FILE is normally a feature name, but it can also be a file name,
|
||||
in case that file does not provide any feature. See `eval-after-load'
|
||||
for more details about the different forms of FILE and their semantics."
|
||||
(declare (indent 1) (debug (form def-body)))
|
||||
;; See https://nullprogram.com/blog/2018/02/22/ on how
|
||||
;; `eval-after-load' is used to preserve compatibility with 24.3.
|
||||
`(eval-after-load ,file `(funcall ',,`(lambda () ,@body))))
|
||||
|
||||
(compat-defun special-form-p (object)
|
||||
"Non-nil if and only if OBJECT is a special form."
|
||||
(if (and (symbolp object) (fboundp object))
|
||||
(setq object (condition-case nil
|
||||
(indirect-function object)
|
||||
(void-function nil))))
|
||||
(and (subrp object) (eq (cdr (subr-arity object)) 'unevalled)))
|
||||
|
||||
(compat-defun macrop (object)
|
||||
"Non-nil if and only if OBJECT is a macro."
|
||||
(let ((def (condition-case nil
|
||||
(indirect-function object)
|
||||
(void-function nil))))
|
||||
(when (consp def)
|
||||
(or (eq 'macro (car def))
|
||||
(and (autoloadp def) (memq (nth 4 def) '(macro t)))))))
|
||||
|
||||
(compat-defun string-suffix-p (suffix string &optional ignore-case)
|
||||
"Return non-nil if SUFFIX is a suffix of STRING.
|
||||
If IGNORE-CASE is non-nil, the comparison is done without paying
|
||||
attention to case differences."
|
||||
(let ((start-pos (- (length string) (length suffix))))
|
||||
(and (>= start-pos 0)
|
||||
(eq t (compare-strings suffix nil nil
|
||||
string start-pos nil ignore-case)))))
|
||||
|
||||
(compat-defun split-string (string &optional separators omit-nulls trim)
|
||||
"Extend `split-string' by a TRIM argument.
|
||||
The remaining arguments STRING, SEPARATORS and OMIT-NULLS are
|
||||
handled just as with `split-string'."
|
||||
:prefix t
|
||||
(let* ((token (split-string string separators omit-nulls))
|
||||
(trimmed (if trim
|
||||
(mapcar
|
||||
(lambda (token)
|
||||
(when (string-match (concat "\\`" trim) token)
|
||||
(setq token (substring token (match-end 0))))
|
||||
(when (string-match (concat trim "\\'") token)
|
||||
(setq token (substring token 0 (match-beginning 0))))
|
||||
token)
|
||||
token)
|
||||
token)))
|
||||
(if omit-nulls (delete "" trimmed) trimmed)))
|
||||
|
||||
(compat-defun delete-consecutive-dups (list &optional circular)
|
||||
"Destructively remove `equal' consecutive duplicates from LIST.
|
||||
First and last elements are considered consecutive if CIRCULAR is
|
||||
non-nil."
|
||||
(let ((tail list) last)
|
||||
(while (cdr tail)
|
||||
(if (equal (car tail) (cadr tail))
|
||||
(setcdr tail (cddr tail))
|
||||
(setq last tail
|
||||
tail (cdr tail))))
|
||||
(if (and circular
|
||||
last
|
||||
(equal (car tail) (car list)))
|
||||
(setcdr last nil)))
|
||||
list)
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defun define-error (name message &optional parent)
|
||||
"Define NAME as a new error signal.
|
||||
MESSAGE is a string that will be output to the echo area if such an error
|
||||
is signaled without being caught by a `condition-case'.
|
||||
PARENT is either a signal or a list of signals from which it inherits.
|
||||
Defaults to `error'."
|
||||
(unless parent (setq parent 'error))
|
||||
(let ((conditions
|
||||
(if (consp parent)
|
||||
(apply #'append
|
||||
(mapcar (lambda (parent)
|
||||
(cons parent
|
||||
(or (get parent 'error-conditions)
|
||||
(error "Unknown signal `%s'" parent))))
|
||||
parent))
|
||||
(cons parent (get parent 'error-conditions)))))
|
||||
(put name 'error-conditions
|
||||
(delete-dups (copy-sequence (cons name conditions))))
|
||||
(when message (put name 'error-message message))))
|
||||
|
||||
;;;; Defined in minibuffer.el
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defun completion-table-with-cache (fun &optional ignore-case)
|
||||
"Create dynamic completion table from function FUN, with cache.
|
||||
This is a wrapper for `completion-table-dynamic' that saves the last
|
||||
argument-result pair from FUN, so that several lookups with the
|
||||
same argument (or with an argument that starts with the first one)
|
||||
only need to call FUN once. This can be useful when FUN performs a
|
||||
relatively slow operation, such as calling an external process.
|
||||
|
||||
When IGNORE-CASE is non-nil, FUN is expected to be case-insensitive."
|
||||
(let* (last-arg last-result
|
||||
(new-fun
|
||||
(lambda (arg)
|
||||
(if (and last-arg (string-prefix-p last-arg arg ignore-case))
|
||||
last-result
|
||||
(prog1
|
||||
(setq last-result (funcall fun arg))
|
||||
(setq last-arg arg))))))
|
||||
(completion-table-dynamic new-fun)))
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defun completion-table-merge (&rest tables)
|
||||
"Create a completion table that collects completions from all TABLES."
|
||||
(lambda (string pred action)
|
||||
(cond
|
||||
((null action)
|
||||
(let ((retvals (mapcar (lambda (table)
|
||||
(try-completion string table pred))
|
||||
tables)))
|
||||
(if (member string retvals)
|
||||
string
|
||||
(try-completion string
|
||||
(mapcar (lambda (value)
|
||||
(if (eq value t) string value))
|
||||
(delq nil retvals))
|
||||
pred))))
|
||||
((eq action t)
|
||||
(apply #'append (mapcar (lambda (table)
|
||||
(all-completions string table pred))
|
||||
tables)))
|
||||
(t
|
||||
(completion--some (lambda (table)
|
||||
(complete-with-action action table string pred))
|
||||
tables)))))
|
||||
|
||||
;;;; Defined in subr-x.el
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-advise require (feature &rest args)
|
||||
"Allow for Emacs 24.x to require the inexistent FEATURE subr-x."
|
||||
;; As the compatibility advise around `require` is more a hack than
|
||||
;; of of actual value, the highlighting is suppressed.
|
||||
:no-highlight t
|
||||
(if (eq feature 'subr-x)
|
||||
(let ((entry (assq feature after-load-alist)))
|
||||
(let ((load-file-name nil))
|
||||
(dolist (form (cdr entry))
|
||||
(funcall (eval form t)))))
|
||||
(apply oldfun feature args)))
|
||||
|
||||
(compat-defun hash-table-keys (hash-table)
|
||||
"Return a list of keys in HASH-TABLE."
|
||||
(let (values)
|
||||
(maphash
|
||||
(lambda (k _v) (push k values))
|
||||
hash-table)
|
||||
values))
|
||||
|
||||
(compat-defun hash-table-values (hash-table)
|
||||
"Return a list of values in HASH-TABLE."
|
||||
(let (values)
|
||||
(maphash
|
||||
(lambda (_k v) (push v values))
|
||||
hash-table)
|
||||
values))
|
||||
|
||||
(compat-defun string-empty-p (string)
|
||||
"Check whether STRING is empty."
|
||||
(string= string ""))
|
||||
|
||||
(compat-defun string-join (strings &optional separator)
|
||||
"Join all STRINGS using SEPARATOR.
|
||||
Optional argument SEPARATOR must be a string, a vector, or a list of
|
||||
characters; nil stands for the empty string."
|
||||
(mapconcat #'identity strings separator))
|
||||
|
||||
(compat-defun string-blank-p (string)
|
||||
"Check whether STRING is either empty or only whitespace.
|
||||
The following characters count as whitespace here: space, tab, newline and
|
||||
carriage return."
|
||||
(string-match-p "\\`[ \t\n\r]*\\'" string))
|
||||
|
||||
(compat-defun string-remove-prefix (prefix string)
|
||||
"Remove PREFIX from STRING if present."
|
||||
(if (string-prefix-p prefix string)
|
||||
(substring string (length prefix))
|
||||
string))
|
||||
|
||||
(compat-defun string-remove-suffix (suffix string)
|
||||
"Remove SUFFIX from STRING if present."
|
||||
(if (string-suffix-p suffix string)
|
||||
(substring string 0 (- (length string) (length suffix)))
|
||||
string))
|
||||
|
||||
;;;; Defined in faces.el
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defun face-spec-set (face spec &optional spec-type)
|
||||
"Set the FACE's spec SPEC, define FACE, and recalculate its attributes.
|
||||
See `defface' for the format of SPEC.
|
||||
|
||||
The appearance of each face is controlled by its specs (set via
|
||||
this function), and by the internal frame-specific face
|
||||
attributes (set via `set-face-attribute').
|
||||
|
||||
This function also defines FACE as a valid face name if it is not
|
||||
already one, and (re)calculates its attributes on existing
|
||||
frames.
|
||||
|
||||
The optional argument SPEC-TYPE determines which spec to set:
|
||||
nil, omitted or `face-override-spec' means the override spec,
|
||||
which overrides all the other types of spec mentioned below
|
||||
(this is usually what you want if calling this function
|
||||
outside of Custom code);
|
||||
`customized-face' or `saved-face' means the customized spec or
|
||||
the saved custom spec;
|
||||
`face-defface-spec' means the default spec
|
||||
(usually set only via `defface');
|
||||
`reset' means to ignore SPEC, but clear the `customized-face'
|
||||
and `face-override-spec' specs;
|
||||
Any other value means not to set any spec, but to run the
|
||||
function for defining FACE and recalculating its attributes."
|
||||
(if (get face 'face-alias)
|
||||
(setq face (get face 'face-alias)))
|
||||
;; Save SPEC to the relevant symbol property.
|
||||
(unless spec-type
|
||||
(setq spec-type 'face-override-spec))
|
||||
(if (memq spec-type '(face-defface-spec face-override-spec
|
||||
customized-face saved-face))
|
||||
(put face spec-type spec))
|
||||
(if (memq spec-type '(reset saved-face))
|
||||
(put face 'customized-face nil))
|
||||
;; Setting the face spec via Custom empties out any override spec,
|
||||
;; similar to how setting a variable via Custom changes its values.
|
||||
(if (memq spec-type '(customized-face saved-face reset))
|
||||
(put face 'face-override-spec nil))
|
||||
;; If we reset the face based on its custom spec, it is unmodified
|
||||
;; as far as Custom is concerned.
|
||||
(unless (eq face 'face-override-spec)
|
||||
(put face 'face-modified nil))
|
||||
;; Initialize the face if it does not exist, then recalculate.
|
||||
(make-empty-face face)
|
||||
(dolist (frame (frame-list))
|
||||
(face-spec-recalc face frame)))
|
||||
|
||||
(compat--inhibit-prefixed (provide 'compat-24))
|
||||
;;; compat-24.el ends here
|
||||
@@ -1,11 +1,6 @@
|
||||
;;; compat-25.el --- Compatibility Layer for Emacs 25.1 -*- lexical-binding: t; -*-
|
||||
;;; compat-25.el --- Functionality added in Emacs 25.1 -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2021, 2022 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Philip Kaludercic <philipk@posteo.net>
|
||||
;; Maintainer: Compat Development <~pkal/compat-devel@lists.sr.ht>
|
||||
;; URL: https://git.sr.ht/~pkal/compat/
|
||||
;; Keywords: lisp
|
||||
;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
@@ -22,23 +17,17 @@
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; Find here the functionality added in Emacs 25.1, needed by older
|
||||
;; versions.
|
||||
;;
|
||||
;; Only load this library if you need to use one of the following
|
||||
;; functions:
|
||||
;;
|
||||
;; - `compat-sort'
|
||||
;; Functionality added in Emacs 25.1, needed by older Emacs versions.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'compat-macs "compat-macs.el")
|
||||
(eval-when-compile (load "compat-macs.el" nil t t))
|
||||
|
||||
(compat-declare-version "25.1")
|
||||
(compat-version "25.1")
|
||||
|
||||
;;;; Defined in alloc.c
|
||||
|
||||
(compat-defun bool-vector (&rest objects)
|
||||
(compat-defun bool-vector (&rest objects) ;; <compat-tests:bool-vector>
|
||||
"Return a new bool-vector with specified arguments as elements.
|
||||
Allows any number of arguments, including zero.
|
||||
usage: (bool-vector &rest OBJECTS)"
|
||||
@@ -53,53 +42,77 @@ usage: (bool-vector &rest OBJECTS)"
|
||||
|
||||
;;;; Defined in fns.c
|
||||
|
||||
(compat-defun sort (seq predicate)
|
||||
"Extend `sort' to sort SEQ as a vector."
|
||||
:prefix t
|
||||
(compat-defun sort (seq predicate) ;; <compat-tests:sort>
|
||||
"Handle vector SEQ."
|
||||
:extended t
|
||||
(cond
|
||||
((listp seq)
|
||||
(sort seq predicate))
|
||||
((vectorp seq)
|
||||
(let ((cseq (sort (append seq nil) predicate)))
|
||||
(dotimes (i (length cseq))
|
||||
(setf (aref seq i) (nth i cseq)))
|
||||
(apply #'vector cseq)))
|
||||
(let* ((list (sort (append seq nil) predicate))
|
||||
(p list) (i 0))
|
||||
(while p
|
||||
(aset seq i (car p))
|
||||
(setq i (1+ i) p (cdr p)))
|
||||
(apply #'vector list)))
|
||||
((signal 'wrong-type-argument 'list-or-vector-p))))
|
||||
|
||||
;;;; Defined in editfns.c
|
||||
|
||||
(compat-defun format-message (string &rest objects)
|
||||
"Format a string out of a format-string and arguments.
|
||||
The first argument is a format control string.
|
||||
The other arguments are substituted into it to make the result, a string.
|
||||
|
||||
This implementation is equivalent to `format'."
|
||||
(apply #'format string objects))
|
||||
|
||||
;;;; Defined in minibuf.c
|
||||
|
||||
;; TODO advise read-buffer to handle 4th argument
|
||||
(compat-defalias format-message format) ;; <compat-tests:format-message>
|
||||
|
||||
;;;; Defined in fileio.c
|
||||
|
||||
(compat-defun directory-name-p (name)
|
||||
(compat-defun directory-name-p (name) ;; <compat-tests:directory-name-p>
|
||||
"Return non-nil if NAME ends with a directory separator character."
|
||||
:realname compat--directory-name-p
|
||||
(eq (eval-when-compile
|
||||
(if (memq system-type '(cygwin windows-nt ms-dos))
|
||||
?\\ ?/))
|
||||
(aref name (1- (length name)))))
|
||||
|
||||
;;;; Defined in doc.c
|
||||
|
||||
(compat-defvar text-quoting-style nil ;; <compat-tests:text-quoting-style>
|
||||
"Style to use for single quotes in help and messages.
|
||||
|
||||
The value of this variable determines substitution of grave accents
|
||||
and apostrophes in help output (but not for display of Info
|
||||
manuals) and in functions like `message' and `format-message', but not
|
||||
in `format'.
|
||||
|
||||
The value should be one of these symbols:
|
||||
`curve': quote with curved single quotes ‘like this’.
|
||||
`straight': quote with straight apostrophes \\='like this\\='.
|
||||
`grave': quote with grave accent and apostrophe \\=`like this\\=';
|
||||
i.e., do not alter the original quote marks.
|
||||
nil: like `curve' if curved single quotes are displayable,
|
||||
and like `grave' otherwise. This is the default.
|
||||
|
||||
You should never read the value of this variable directly from a Lisp
|
||||
program. Use the function `text-quoting-style' instead, as that will
|
||||
compute the correct value for the current terminal in the nil case.")
|
||||
|
||||
;;;; Defined in simple.el
|
||||
|
||||
;; `save-excursion' behaved like `save-mark-and-excursion' before 25.1.
|
||||
(compat-defalias save-mark-and-excursion save-excursion) ;; <compat-tests:save-mark-and-excursion>
|
||||
|
||||
(declare-function region-bounds nil) ;; Defined in compat-26.el
|
||||
(compat-defun region-noncontiguous-p () ;; <compat-tests:region-noncontiguous-p>
|
||||
"Return non-nil if the region contains several pieces.
|
||||
An example is a rectangular region handled as a list of
|
||||
separate contiguous regions for each line."
|
||||
(let ((bounds (region-bounds))) (and (cdr bounds) bounds)))
|
||||
|
||||
;;;; Defined in subr.el
|
||||
|
||||
(compat-defun string-greaterp (string1 string2)
|
||||
(compat-defun string-greaterp (string1 string2) ;; <compat-tests:string-greaterp>
|
||||
"Return non-nil if STRING1 is greater than STRING2 in lexicographic order.
|
||||
Case is significant.
|
||||
Symbols are also allowed; their print names are used instead."
|
||||
(string-lessp string2 string1))
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defmacro with-file-modes (modes &rest body)
|
||||
(compat-defmacro with-file-modes (modes &rest body) ;; <compat-tests:with-file-modes>
|
||||
"Execute BODY with default file permissions temporarily set to MODES.
|
||||
MODES is as for `set-default-file-modes'."
|
||||
(declare (indent 1) (debug t))
|
||||
@@ -111,28 +124,7 @@ MODES is as for `set-default-file-modes'."
|
||||
,@body)
|
||||
(set-default-file-modes ,umask)))))
|
||||
|
||||
(compat-defun alist-get (key alist &optional default remove testfn)
|
||||
"Find the first element of ALIST whose `car' equals KEY and return its `cdr'.
|
||||
If KEY is not found in ALIST, return DEFAULT.
|
||||
Equality with KEY is tested by TESTFN, defaulting to `eq'."
|
||||
:realname compat--alist-get-full-elisp
|
||||
(ignore remove)
|
||||
(let (entry)
|
||||
(cond
|
||||
((or (null testfn) (eq testfn 'eq))
|
||||
(setq entry (assq key alist)))
|
||||
((eq testfn 'equal)
|
||||
(setq entry (assoc key alist)))
|
||||
((catch 'found
|
||||
(dolist (ent alist)
|
||||
(when (and (consp ent) (funcall testfn (car ent) key))
|
||||
(throw 'found (setq entry ent))))
|
||||
default)))
|
||||
(if entry (cdr entry) default)))
|
||||
|
||||
;;;; Defined in subr-x.el
|
||||
|
||||
(compat-defmacro if-let (spec then &rest else)
|
||||
(compat-defmacro if-let (spec then &rest else) ;; <compat-tests:if-let>
|
||||
"Bind variables according to SPEC and evaluate THEN or ELSE.
|
||||
Evaluate each binding in turn, as in `let*', stopping if a
|
||||
binding value is nil. If all are non-nil return the value of
|
||||
@@ -148,29 +140,40 @@ SYMBOL is checked for nil.
|
||||
As a special case, interprets a SPEC of the form \(SYMBOL SOMETHING)
|
||||
like \((SYMBOL SOMETHING)). This exists for backward compatibility
|
||||
with an old syntax that accepted only one binding."
|
||||
:realname compat--if-let
|
||||
:feature 'subr-x
|
||||
(declare (indent 2)
|
||||
(debug ([&or (symbolp form)
|
||||
(&rest [&or symbolp (symbolp form) (form)])]
|
||||
body)))
|
||||
(when (and (<= (length spec) 2)
|
||||
(not (listp (car spec))))
|
||||
(when (and (<= (length spec) 2) (not (listp (car spec))))
|
||||
;; Adjust the single binding case
|
||||
(setq spec (list spec)))
|
||||
`(compat--if-let* ,spec ,then ,(macroexp-progn else)))
|
||||
(let ((empty (make-symbol "s"))
|
||||
(last t) list)
|
||||
(dolist (var spec)
|
||||
(push `(,(if (cdr var) (car var) empty)
|
||||
(and ,last ,(if (cdr var) (cadr var) (car var))))
|
||||
list)
|
||||
(when (or (cdr var) (consp (car var)))
|
||||
(setq last (caar list))))
|
||||
`(let* ,(nreverse list)
|
||||
(if ,(caar list) ,then ,@else))))
|
||||
|
||||
(compat-defmacro when-let (spec &rest body)
|
||||
(compat-defmacro when-let (spec &rest body) ;; <compat-tests:when-let>
|
||||
"Bind variables according to SPEC and conditionally evaluate BODY.
|
||||
Evaluate each binding in turn, stopping if a binding value is nil.
|
||||
If all are non-nil, return the value of the last form in BODY.
|
||||
|
||||
The variable list SPEC is the same as in `if-let'."
|
||||
:feature 'subr-x
|
||||
(declare (indent 1) (debug if-let))
|
||||
`(compat--if-let ,spec ,(macroexp-progn body)))
|
||||
(list 'if-let spec (macroexp-progn body)))
|
||||
|
||||
(compat-defmacro thread-first (&rest forms)
|
||||
;;;; Defined in subr-x.el
|
||||
|
||||
(compat-defun hash-table-empty-p (hash-table) ;; <compat-tests:hash-table-empty-p>
|
||||
"Check whether HASH-TABLE is empty (has 0 elements)."
|
||||
(zerop (hash-table-count hash-table)))
|
||||
|
||||
(compat-defmacro thread-first (&rest forms) ;; <compat-tests:thread-first>
|
||||
"Thread FORMS elements as the first argument of their successor.
|
||||
Example:
|
||||
(thread-first
|
||||
@@ -183,7 +186,6 @@ Is equivalent to:
|
||||
(+ (- (/ (+ 5 20) 25)) 40)
|
||||
Note how the single `-' got converted into a list before
|
||||
threading."
|
||||
:feature 'subr-x
|
||||
(declare (indent 1)
|
||||
(debug (form &rest [&or symbolp (sexp &rest form)])))
|
||||
(let ((body (car forms)))
|
||||
@@ -195,7 +197,7 @@ threading."
|
||||
(cdr form))))
|
||||
body))
|
||||
|
||||
(compat-defmacro thread-last (&rest forms)
|
||||
(compat-defmacro thread-last (&rest forms) ;; <compat-tests:thread-last>
|
||||
"Thread FORMS elements as the last argument of their successor.
|
||||
Example:
|
||||
(thread-last
|
||||
@@ -208,7 +210,6 @@ Is equivalent to:
|
||||
(+ 40 (- (/ 25 (+ 20 5))))
|
||||
Note how the single `-' got converted into a list before
|
||||
threading."
|
||||
:feature 'subr-x
|
||||
(declare (indent 1) (debug thread-first))
|
||||
(let ((body (car forms)))
|
||||
(dolist (form (cdr forms))
|
||||
@@ -219,10 +220,31 @@ threading."
|
||||
|
||||
;;;; Defined in macroexp.el
|
||||
|
||||
(declare-function macrop nil (object))
|
||||
(compat-defun macroexpand-1 (form &optional environment)
|
||||
(compat-defun macroexp-parse-body (body) ;; <compat-tests:macroexp-parse-body>
|
||||
"Parse a function BODY into (DECLARATIONS . EXPS)."
|
||||
(let ((decls ()))
|
||||
(while (and (cdr body)
|
||||
(let ((e (car body)))
|
||||
(or (stringp e)
|
||||
(memq (car-safe e)
|
||||
'(:documentation declare interactive cl-declare)))))
|
||||
(push (pop body) decls))
|
||||
(cons (nreverse decls) body)))
|
||||
|
||||
(compat-defun macroexp-quote (v) ;; <compat-tests:macroexp-quote>
|
||||
"Return an expression E such that `(eval E)' is V.
|
||||
|
||||
E is either V or (quote V) depending on whether V evaluates to
|
||||
itself or not."
|
||||
(if (and (not (consp v))
|
||||
(or (keywordp v)
|
||||
(not (symbolp v))
|
||||
(memq v '(nil t))))
|
||||
v
|
||||
(list 'quote v)))
|
||||
|
||||
(compat-defun macroexpand-1 (form &optional environment) ;; <compat-tests:macroexpand-1>
|
||||
"Perform (at most) one step of macro expansion."
|
||||
:feature 'macroexp
|
||||
(cond
|
||||
((consp form)
|
||||
(let* ((head (car form))
|
||||
@@ -245,78 +267,5 @@ threading."
|
||||
form))))))))
|
||||
(t form)))
|
||||
|
||||
;;;; Defined in byte-run.el
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defun function-put (func prop value)
|
||||
"Set FUNCTION's property PROP to VALUE.
|
||||
The namespace for PROP is shared with symbols.
|
||||
So far, FUNCTION can only be a symbol, not a lambda expression."
|
||||
:version "24.4"
|
||||
(put func prop value))
|
||||
|
||||
;;;; Defined in files.el
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defun directory-files-recursively
|
||||
(dir regexp &optional include-directories predicate follow-symlinks)
|
||||
"Return list of all files under directory DIR whose names match REGEXP.
|
||||
This function works recursively. Files are returned in \"depth
|
||||
first\" order, and files from each directory are sorted in
|
||||
alphabetical order. Each file name appears in the returned list
|
||||
in its absolute form.
|
||||
|
||||
By default, the returned list excludes directories, but if
|
||||
optional argument INCLUDE-DIRECTORIES is non-nil, they are
|
||||
included.
|
||||
|
||||
PREDICATE can be either nil (which means that all subdirectories
|
||||
of DIR are descended into), t (which means that subdirectories that
|
||||
can't be read are ignored), or a function (which is called with
|
||||
the name of each subdirectory, and should return non-nil if the
|
||||
subdirectory is to be descended into).
|
||||
|
||||
If FOLLOW-SYMLINKS is non-nil, symbolic links that point to
|
||||
directories are followed. Note that this can lead to infinite
|
||||
recursion."
|
||||
:realname compat--directory-files-recursively
|
||||
(let* ((result nil)
|
||||
(files nil)
|
||||
(dir (directory-file-name dir))
|
||||
;; When DIR is "/", remote file names like "/method:" could
|
||||
;; also be offered. We shall suppress them.
|
||||
(tramp-mode (and tramp-mode (file-remote-p (expand-file-name dir)))))
|
||||
(dolist (file (sort (file-name-all-completions "" dir)
|
||||
'string<))
|
||||
(unless (member file '("./" "../"))
|
||||
(if (directory-name-p file)
|
||||
(let* ((leaf (substring file 0 (1- (length file))))
|
||||
(full-file (concat dir "/" leaf)))
|
||||
;; Don't follow symlinks to other directories.
|
||||
(when (and (or (not (file-symlink-p full-file))
|
||||
(and (file-symlink-p full-file)
|
||||
follow-symlinks))
|
||||
;; Allow filtering subdirectories.
|
||||
(or (eq predicate nil)
|
||||
(eq predicate t)
|
||||
(funcall predicate full-file)))
|
||||
(let ((sub-files
|
||||
(if (eq predicate t)
|
||||
(condition-case nil
|
||||
(compat--directory-files-recursively
|
||||
full-file regexp include-directories
|
||||
predicate follow-symlinks)
|
||||
(file-error nil))
|
||||
(compat--directory-files-recursively
|
||||
full-file regexp include-directories
|
||||
predicate follow-symlinks))))
|
||||
(setq result (nconc result sub-files))))
|
||||
(when (and include-directories
|
||||
(string-match regexp leaf))
|
||||
(setq result (nconc result (list full-file)))))
|
||||
(when (string-match regexp file)
|
||||
(push (concat dir "/" file) files)))))
|
||||
(nconc result (nreverse files))))
|
||||
|
||||
(compat--inhibit-prefixed (provide 'compat-25))
|
||||
(provide 'compat-25)
|
||||
;;; compat-25.el ends here
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
;;; compat-26.el --- Compatibility Layer for Emacs 26.1 -*- lexical-binding: t; -*-
|
||||
;;; compat-26.el --- Functionality added in Emacs 26.1 -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2021, 2022 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Philip Kaludercic <philipk@posteo.net>
|
||||
;; Maintainer: Compat Development <~pkal/compat-devel@lists.sr.ht>
|
||||
;; URL: https://git.sr.ht/~pkal/compat/
|
||||
;; Keywords: lisp
|
||||
;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
@@ -22,337 +17,284 @@
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; Find here the functionality added in Emacs 26.1, needed by older
|
||||
;; versions.
|
||||
;;
|
||||
;; Only load this library if you need to use one of the following
|
||||
;; functions:
|
||||
;;
|
||||
;; - `compat-sort'
|
||||
;; - `line-number-at-pos'
|
||||
;; - `compat-alist-get'
|
||||
;; - `string-trim-left'
|
||||
;; - `string-trim-right'
|
||||
;; - `string-trim'
|
||||
;; Functionality added in Emacs 26.1, needed by older Emacs versions.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'compat-macs "compat-macs.el")
|
||||
(eval-when-compile (load "compat-macs.el" nil t t))
|
||||
(compat-require compat-25 "25.1")
|
||||
|
||||
(compat-declare-version "26.1")
|
||||
|
||||
;;;; Defined in eval.c
|
||||
|
||||
(compat-defun func-arity (func)
|
||||
"Return minimum and maximum number of args allowed for FUNC.
|
||||
FUNC must be a function of some kind.
|
||||
The returned value is a cons cell (MIN . MAX). MIN is the minimum number
|
||||
of args. MAX is the maximum number, or the symbol `many', for a
|
||||
function with `&rest' args, or `unevalled' for a special form."
|
||||
:realname compat--func-arity
|
||||
(cond
|
||||
((or (null func) (and (symbolp func) (not (fboundp func))))
|
||||
(signal 'void-function func))
|
||||
((and (symbolp func) (not (null func)))
|
||||
(compat--func-arity (symbol-function func)))
|
||||
((eq (car-safe func) 'macro)
|
||||
(compat--func-arity (cdr func)))
|
||||
((subrp func)
|
||||
(subr-arity func))
|
||||
((memq (car-safe func) '(closure lambda))
|
||||
;; See lambda_arity from eval.c
|
||||
(when (eq (car func) 'closure)
|
||||
(setq func (cdr func)))
|
||||
(let ((syms-left (if (consp func)
|
||||
(car func)
|
||||
(signal 'invalid-function func)))
|
||||
(min-args 0) (max-args 0) optional)
|
||||
(catch 'many
|
||||
(dolist (next syms-left)
|
||||
(cond
|
||||
((not (symbolp next))
|
||||
(signal 'invalid-function func))
|
||||
((eq next '&rest)
|
||||
(throw 'many (cons min-args 'many)))
|
||||
((eq next '&optional)
|
||||
(setq optional t))
|
||||
(t (unless optional
|
||||
(setq min-args (1+ min-args)))
|
||||
(setq max-args (1+ max-args)))))
|
||||
(cons min-args max-args))))
|
||||
((and (byte-code-function-p func) (numberp (aref func 0)))
|
||||
;; See get_byte_code_arity from bytecode.c
|
||||
(let ((at (aref func 0)))
|
||||
(cons (logand at 127)
|
||||
(if (= (logand at 128) 0)
|
||||
(ash at -8)
|
||||
'many))))
|
||||
((and (byte-code-function-p func) (numberp (aref func 0)))
|
||||
;; See get_byte_code_arity from bytecode.c
|
||||
(let ((at (aref func 0)))
|
||||
(cons (logand at 127)
|
||||
(if (= (logand at 128) 0)
|
||||
(ash at -8)
|
||||
'many))))
|
||||
((and (byte-code-function-p func) (listp (aref func 0)))
|
||||
;; Based on `byte-compile-make-args-desc', this is required for
|
||||
;; old versions of Emacs that don't use a integer for the argument
|
||||
;; list description, per e2abe5a13dffb08d6371b6a611bc39c3a9ac2bc6.
|
||||
(let ((arglist (aref func 0)) (mandatory 0) nonrest)
|
||||
(while (and arglist (not (memq (car arglist) '(&optional &rest))))
|
||||
(setq mandatory (1+ mandatory))
|
||||
(setq arglist (cdr arglist)))
|
||||
(setq nonrest mandatory)
|
||||
(when (eq (car arglist) '&optional)
|
||||
(setq arglist (cdr arglist))
|
||||
(while (and arglist (not (eq (car arglist) '&rest)))
|
||||
(setq nonrest (1+ nonrest))
|
||||
(setq arglist (cdr arglist))))
|
||||
(cons mandatory (if arglist 'many nonrest))))
|
||||
((autoloadp func)
|
||||
(autoload-do-load func)
|
||||
(compat--func-arity func))
|
||||
((signal 'invalid-function func))))
|
||||
(compat-version "26.1")
|
||||
|
||||
;;;; Defined in fns.c
|
||||
|
||||
(compat-defun assoc (key alist &optional testfn)
|
||||
"Handle the optional argument TESTFN.
|
||||
Equality is defined by the function TESTFN, defaulting to
|
||||
`equal'. TESTFN is called with 2 arguments: a car of an alist
|
||||
element and KEY. With no optional argument, the function behaves
|
||||
just like `assoc'."
|
||||
:prefix t
|
||||
(if testfn
|
||||
(catch 'found
|
||||
(dolist (ent alist)
|
||||
(when (funcall testfn (car ent) key)
|
||||
(throw 'found ent))))
|
||||
(assoc key alist)))
|
||||
(compat-defun buffer-hash (&optional buffer-or-name) ;; <compat-tests:buffer-hash>
|
||||
"Return a hash of the contents of BUFFER-OR-NAME.
|
||||
This hash is performed on the raw internal format of the buffer,
|
||||
disregarding any coding systems. If nil, use the current buffer.
|
||||
|
||||
(compat-defun mapcan (func sequence)
|
||||
This function is useful for comparing two buffers running in the same
|
||||
Emacs, but is not guaranteed to return the same hash between different
|
||||
Emacs versions. It should be somewhat more efficient on larger
|
||||
buffers than `secure-hash' is, and should not allocate more memory.
|
||||
|
||||
It should not be used for anything security-related. See
|
||||
`secure-hash' for these applications."
|
||||
(with-current-buffer (or buffer-or-name (current-buffer))
|
||||
(save-restriction
|
||||
(widen)
|
||||
(sha1 (current-buffer) (point-min) (point-max)))))
|
||||
|
||||
(compat-defun mapcan (func sequence) ;; <compat-tests:mapcan>
|
||||
"Apply FUNC to each element of SEQUENCE.
|
||||
Concatenate the results by altering them (using `nconc').
|
||||
SEQUENCE may be a list, a vector, a boolean vector, or a string."
|
||||
(apply #'nconc (mapcar func sequence)))
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defun line-number-at-pos (&optional position absolute)
|
||||
"Handle optional argument ABSOLUTE:
|
||||
|
||||
If the buffer is narrowed, the return value by default counts the lines
|
||||
from the beginning of the accessible portion of the buffer. But if the
|
||||
second optional argument ABSOLUTE is non-nil, the value counts the lines
|
||||
from the absolute start of the buffer, disregarding the narrowing."
|
||||
:prefix t
|
||||
(compat-defun line-number-at-pos (&optional position absolute) ;; <compat-tests:line-number-at-pos>
|
||||
"Handle optional argument ABSOLUTE."
|
||||
:extended t
|
||||
(if absolute
|
||||
(save-restriction
|
||||
(widen)
|
||||
(line-number-at-pos position))
|
||||
(line-number-at-pos position)))
|
||||
|
||||
;;;; Defined in simple.el
|
||||
|
||||
(compat-defun region-bounds () ;; <compat-tests:region-bounds>
|
||||
"Return the boundaries of the region.
|
||||
Value is a list of one or more cons cells of the form (START . END).
|
||||
It will have more than one cons cell when the region is non-contiguous,
|
||||
see `region-noncontiguous-p' and `extract-rectangle-bounds'."
|
||||
(if (eval-when-compile (< emacs-major-version 25))
|
||||
;; FIXME: The `region-extract-function' of Emacs 24 has no support for the
|
||||
;; bounds argument.
|
||||
(list (cons (region-beginning) (region-end)))
|
||||
(funcall region-extract-function 'bounds)))
|
||||
|
||||
;;;; Defined in subr.el
|
||||
|
||||
(declare-function compat--alist-get-full-elisp "compat-25"
|
||||
(key alist &optional default remove testfn))
|
||||
(compat-defun alist-get (key alist &optional default remove testfn)
|
||||
"Handle TESTFN manually."
|
||||
:realname compat--alist-get-handle-testfn
|
||||
:prefix t
|
||||
(if testfn
|
||||
(compat--alist-get-full-elisp key alist default remove testfn)
|
||||
(alist-get key alist default remove)))
|
||||
(compat-defun provided-mode-derived-p (mode &rest modes) ;; <compat-tests:provided-derived-mode-p>
|
||||
"Non-nil if MODE is derived from one of MODES.
|
||||
Uses the `derived-mode-parent' property of the symbol to trace backwards.
|
||||
If you just want to check `major-mode', use `derived-mode-p'."
|
||||
;; If MODE is an alias, then look up the real mode function first.
|
||||
(let ((alias (symbol-function mode)))
|
||||
(when (and alias (symbolp alias))
|
||||
(setq mode alias)))
|
||||
(while
|
||||
(and
|
||||
(not (memq mode modes))
|
||||
(let* ((parent (get mode 'derived-mode-parent))
|
||||
(parentfn (symbol-function parent)))
|
||||
(setq mode (if (and parentfn (symbolp parentfn)) parentfn parent)))))
|
||||
mode)
|
||||
|
||||
(gv-define-expander compat-alist-get
|
||||
(lambda (do key alist &optional default remove testfn)
|
||||
(macroexp-let2 macroexp-copyable-p k key
|
||||
(gv-letplace (getter setter) alist
|
||||
(macroexp-let2 nil p `(if (and ,testfn (not (eq ,testfn 'eq)))
|
||||
(compat-assoc ,k ,getter ,testfn)
|
||||
(assq ,k ,getter))
|
||||
(funcall do (if (null default) `(cdr ,p)
|
||||
`(if ,p (cdr ,p) ,default))
|
||||
(lambda (v)
|
||||
(macroexp-let2 nil v v
|
||||
(let ((set-exp
|
||||
`(if ,p (setcdr ,p ,v)
|
||||
,(funcall setter
|
||||
`(cons (setq ,p (cons ,k ,v))
|
||||
,getter)))))
|
||||
`(progn
|
||||
,(cond
|
||||
((null remove) set-exp)
|
||||
((or (eql v default)
|
||||
(and (eq (car-safe v) 'quote)
|
||||
(eq (car-safe default) 'quote)
|
||||
(eql (cadr v) (cadr default))))
|
||||
`(if ,p ,(funcall setter `(delq ,p ,getter))))
|
||||
(t
|
||||
`(cond
|
||||
((not (eql ,default ,v)) ,set-exp)
|
||||
(,p ,(funcall setter
|
||||
`(delq ,p ,getter))))))
|
||||
,v))))))))))
|
||||
(compat-defun assoc (key alist &optional testfn) ;; <compat-tests:assoc>
|
||||
"Handle the optional TESTFN."
|
||||
:extended t
|
||||
(cond
|
||||
((or (eq testfn #'eq)
|
||||
(and (not testfn) (or (symbolp key) (integerp key)))) ;; eq_comparable_value
|
||||
(assq key alist))
|
||||
((or (eq testfn #'equal) (not testfn))
|
||||
(assoc key alist))
|
||||
(t
|
||||
(catch 'found
|
||||
(dolist (ent alist)
|
||||
(when (funcall testfn (car ent) key)
|
||||
(throw 'found ent)))))))
|
||||
|
||||
(compat-defun string-trim-left (string &optional regexp)
|
||||
"Trim STRING of leading string matching REGEXP.
|
||||
(compat-defun alist-get (key alist &optional default remove testfn) ;; <compat-tests:alist-get>
|
||||
"Handle optional argument TESTFN."
|
||||
:extended "25.1"
|
||||
(ignore remove)
|
||||
(let ((x (if (not testfn)
|
||||
(assq key alist)
|
||||
(compat--assoc key alist testfn))))
|
||||
(if x (cdr x) default)))
|
||||
|
||||
REGEXP defaults to \"[ \\t\\n\\r]+\"."
|
||||
:realname compat--string-trim-left
|
||||
:prefix t
|
||||
(compat-guard t ;; <compat-tests:alist-get-gv>
|
||||
(gv-define-expander compat--alist-get
|
||||
(lambda (do key alist &optional default remove testfn)
|
||||
(macroexp-let2 macroexp-copyable-p k key
|
||||
(gv-letplace (getter setter) alist
|
||||
(macroexp-let2 nil p `(compat--assoc ,k ,getter ,testfn)
|
||||
(funcall do (if (null default) `(cdr ,p)
|
||||
`(if ,p (cdr ,p) ,default))
|
||||
(lambda (v)
|
||||
(macroexp-let2 nil v v
|
||||
(let ((set-exp
|
||||
`(if ,p (setcdr ,p ,v)
|
||||
,(funcall setter
|
||||
`(cons (setq ,p (cons ,k ,v))
|
||||
,getter)))))
|
||||
`(progn
|
||||
,(cond
|
||||
((null remove) set-exp)
|
||||
((or (eql v default)
|
||||
(and (eq (car-safe v) 'quote)
|
||||
(eq (car-safe default) 'quote)
|
||||
(eql (cadr v) (cadr default))))
|
||||
`(if ,p ,(funcall setter `(delq ,p ,getter))))
|
||||
(t
|
||||
`(cond
|
||||
((not (eql ,default ,v)) ,set-exp)
|
||||
(,p ,(funcall setter
|
||||
`(delq ,p ,getter))))))
|
||||
,v))))))))))
|
||||
(unless (get 'alist-get 'gv-expander)
|
||||
(put 'alist-get 'gv-expander (get 'compat--alist-get 'gv-expander))))
|
||||
|
||||
(compat-defun string-trim-left (string &optional regexp) ;; <compat-tests:string-trim-left>
|
||||
"Handle optional argument REGEXP."
|
||||
:extended t
|
||||
(if (string-match (concat "\\`\\(?:" (or regexp "[ \t\n\r]+") "\\)") string)
|
||||
(substring string (match-end 0))
|
||||
string))
|
||||
|
||||
(compat-defun string-trim-right (string &optional regexp)
|
||||
"Trim STRING of trailing string matching REGEXP.
|
||||
|
||||
REGEXP defaults to \"[ \\t\\n\\r]+\"."
|
||||
:realname compat--string-trim-right
|
||||
:prefix t
|
||||
(compat-defun string-trim-right (string &optional regexp) ;; <compat-tests:string-trim-right>
|
||||
"Handle optional argument REGEXP."
|
||||
:extended t
|
||||
(let ((i (string-match-p
|
||||
(concat "\\(?:" (or regexp "[ \t\n\r]+") "\\)\\'")
|
||||
string)))
|
||||
(if i (substring string 0 i) string)))
|
||||
|
||||
(compat-defun string-trim (string &optional trim-left trim-right)
|
||||
"Trim STRING of leading with and trailing matching TRIM-LEFT and TRIM-RIGHT.
|
||||
|
||||
TRIM-LEFT and TRIM-RIGHT default to \"[ \\t\\n\\r]+\"."
|
||||
:prefix t
|
||||
;; `string-trim-left' and `string-trim-right' were moved from subr-x
|
||||
;; to subr in Emacs 27, so to avoid loading subr-x we use the
|
||||
;; compatibility function here:
|
||||
(compat-defun string-trim (string &optional trim-left trim-right) ;; <compat-tests:string-trim>
|
||||
"Handle optional arguments TRIM-LEFT and TRIM-RIGHT."
|
||||
:extended t
|
||||
(compat--string-trim-left
|
||||
(compat--string-trim-right
|
||||
string
|
||||
trim-right)
|
||||
trim-left))
|
||||
|
||||
(compat-defun caaar (x)
|
||||
(compat-defun caaar (x) ;; <compat-tests:cXXXr>
|
||||
"Return the `car' of the `car' of the `car' of X."
|
||||
(declare (pure t))
|
||||
(car (car (car x))))
|
||||
|
||||
(compat-defun caadr (x)
|
||||
(compat-defun caadr (x) ;; <compat-tests:cXXXr>
|
||||
"Return the `car' of the `car' of the `cdr' of X."
|
||||
(declare (pure t))
|
||||
(car (car (cdr x))))
|
||||
|
||||
(compat-defun cadar (x)
|
||||
(compat-defun cadar (x) ;; <compat-tests:cXXXr>
|
||||
"Return the `car' of the `cdr' of the `car' of X."
|
||||
(declare (pure t))
|
||||
(car (cdr (car x))))
|
||||
|
||||
(compat-defun caddr (x)
|
||||
(compat-defun caddr (x) ;; <compat-tests:cXXXr>
|
||||
"Return the `car' of the `cdr' of the `cdr' of X."
|
||||
(declare (pure t))
|
||||
(car (cdr (cdr x))))
|
||||
|
||||
(compat-defun cdaar (x)
|
||||
(compat-defun cdaar (x) ;; <compat-tests:cXXXr>
|
||||
"Return the `cdr' of the `car' of the `car' of X."
|
||||
(declare (pure t))
|
||||
(cdr (car (car x))))
|
||||
|
||||
(compat-defun cdadr (x)
|
||||
(compat-defun cdadr (x) ;; <compat-tests:cXXXr>
|
||||
"Return the `cdr' of the `car' of the `cdr' of X."
|
||||
(declare (pure t))
|
||||
(cdr (car (cdr x))))
|
||||
|
||||
(compat-defun cddar (x)
|
||||
(compat-defun cddar (x) ;; <compat-tests:cXXXr>
|
||||
"Return the `cdr' of the `cdr' of the `car' of X."
|
||||
(declare (pure t))
|
||||
(cdr (cdr (car x))))
|
||||
|
||||
(compat-defun cdddr (x)
|
||||
(compat-defun cdddr (x) ;; <compat-tests:cXXXr>
|
||||
"Return the `cdr' of the `cdr' of the `cdr' of X."
|
||||
(declare (pure t))
|
||||
(cdr (cdr (cdr x))))
|
||||
|
||||
(compat-defun caaaar (x)
|
||||
(compat-defun caaaar (x) ;; <compat-tests:cXXXXr>
|
||||
"Return the `car' of the `car' of the `car' of the `car' of X."
|
||||
(declare (pure t))
|
||||
(car (car (car (car x)))))
|
||||
|
||||
(compat-defun caaadr (x)
|
||||
(compat-defun caaadr (x) ;; <compat-tests:cXXXXr>
|
||||
"Return the `car' of the `car' of the `car' of the `cdr' of X."
|
||||
(declare (pure t))
|
||||
(car (car (car (cdr x)))))
|
||||
|
||||
(compat-defun caadar (x)
|
||||
(compat-defun caadar (x) ;; <compat-tests:cXXXXr>
|
||||
"Return the `car' of the `car' of the `cdr' of the `car' of X."
|
||||
(declare (pure t))
|
||||
(car (car (cdr (car x)))))
|
||||
|
||||
(compat-defun caaddr (x)
|
||||
(compat-defun caaddr (x) ;; <compat-tests:cXXXXr>
|
||||
"Return the `car' of the `car' of the `cdr' of the `cdr' of X."
|
||||
(declare (pure t))
|
||||
(car (car (cdr (cdr x)))))
|
||||
|
||||
(compat-defun cadaar (x)
|
||||
(compat-defun cadaar (x) ;; <compat-tests:cXXXXr>
|
||||
"Return the `car' of the `cdr' of the `car' of the `car' of X."
|
||||
(declare (pure t))
|
||||
(car (cdr (car (car x)))))
|
||||
|
||||
(compat-defun cadadr (x)
|
||||
(compat-defun cadadr (x) ;; <compat-tests:cXXXXr>
|
||||
"Return the `car' of the `cdr' of the `car' of the `cdr' of X."
|
||||
(declare (pure t))
|
||||
(car (cdr (car (cdr x)))))
|
||||
|
||||
(compat-defun caddar (x)
|
||||
(compat-defun caddar (x) ;; <compat-tests:cXXXXr>
|
||||
"Return the `car' of the `cdr' of the `cdr' of the `car' of X."
|
||||
(declare (pure t))
|
||||
(car (cdr (cdr (car x)))))
|
||||
|
||||
(compat-defun cadddr (x)
|
||||
(compat-defun cadddr (x) ;; <compat-tests:cXXXXr>
|
||||
"Return the `car' of the `cdr' of the `cdr' of the `cdr' of X."
|
||||
(declare (pure t))
|
||||
(car (cdr (cdr (cdr x)))))
|
||||
|
||||
(compat-defun cdaaar (x)
|
||||
(compat-defun cdaaar (x) ;; <compat-tests:cXXXXr>
|
||||
"Return the `cdr' of the `car' of the `car' of the `car' of X."
|
||||
(declare (pure t))
|
||||
(cdr (car (car (car x)))))
|
||||
|
||||
(compat-defun cdaadr (x)
|
||||
(compat-defun cdaadr (x) ;; <compat-tests:cXXXXr>
|
||||
"Return the `cdr' of the `car' of the `car' of the `cdr' of X."
|
||||
(declare (pure t))
|
||||
(cdr (car (car (cdr x)))))
|
||||
|
||||
(compat-defun cdadar (x)
|
||||
(compat-defun cdadar (x) ;; <compat-tests:cXXXXr>
|
||||
"Return the `cdr' of the `car' of the `cdr' of the `car' of X."
|
||||
(declare (pure t))
|
||||
(cdr (car (cdr (car x)))))
|
||||
|
||||
(compat-defun cdaddr (x)
|
||||
(compat-defun cdaddr (x) ;; <compat-tests:cXXXXr>
|
||||
"Return the `cdr' of the `car' of the `cdr' of the `cdr' of X."
|
||||
(declare (pure t))
|
||||
(cdr (car (cdr (cdr x)))))
|
||||
|
||||
(compat-defun cddaar (x)
|
||||
(compat-defun cddaar (x) ;; <compat-tests:cXXXXr>
|
||||
"Return the `cdr' of the `cdr' of the `car' of the `car' of X."
|
||||
(declare (pure t))
|
||||
(cdr (cdr (car (car x)))))
|
||||
|
||||
(compat-defun cddadr (x)
|
||||
(compat-defun cddadr (x) ;; <compat-tests:cXXXXr>
|
||||
"Return the `cdr' of the `cdr' of the `car' of the `cdr' of X."
|
||||
(declare (pure t))
|
||||
(cdr (cdr (car (cdr x)))))
|
||||
|
||||
(compat-defun cdddar (x)
|
||||
(compat-defun cdddar (x) ;; <compat-tests:cXXXXr>
|
||||
"Return the `cdr' of the `cdr' of the `cdr' of the `car' of X."
|
||||
(declare (pure t))
|
||||
(cdr (cdr (cdr (car x)))))
|
||||
|
||||
(compat-defun cddddr (x)
|
||||
(compat-defun cddddr (x) ;; <compat-tests:cXXXXr>
|
||||
"Return the `cdr' of the `cdr' of the `cdr' of the `cdr' of X."
|
||||
(declare (pure t))
|
||||
(cdr (cdr (cdr (cdr x)))))
|
||||
|
||||
(compat-defvar gensym-counter 0
|
||||
(compat-defvar gensym-counter 0 ;; <compat-tests:gensym>
|
||||
"Number used to construct the name of the next symbol created by `gensym'.")
|
||||
|
||||
(compat-defun gensym (&optional prefix)
|
||||
(compat-defun gensym (&optional prefix) ;; <compat-tests:gensym>
|
||||
"Return a new uninterned symbol.
|
||||
The name is made by appending `gensym-counter' to PREFIX.
|
||||
PREFIX is a string, and defaults to \"g\"."
|
||||
@@ -361,27 +303,52 @@ PREFIX is a string, and defaults to \"g\"."
|
||||
(1+ gensym-counter)))))
|
||||
(make-symbol (format "%s%d" (or prefix "g") num))))
|
||||
|
||||
(compat-defmacro if-let* (varlist then &rest else) ;; <compat-tests:if-let*>
|
||||
"Bind variables according to VARLIST and evaluate THEN or ELSE.
|
||||
This is like `if-let' but doesn't handle a VARLIST of the form
|
||||
\(SYMBOL SOMETHING) specially."
|
||||
(declare (indent 2)
|
||||
(debug ((&rest [&or symbolp (symbolp form) (form)])
|
||||
body)))
|
||||
(let ((empty (make-symbol "s"))
|
||||
(last t) list)
|
||||
(dolist (var varlist)
|
||||
(push `(,(if (cdr var) (car var) empty)
|
||||
(and ,last ,(if (cdr var) (cadr var) (car var))))
|
||||
list)
|
||||
(when (or (cdr var) (consp (car var)))
|
||||
(setq last (caar list))))
|
||||
`(let* ,(nreverse list)
|
||||
(if ,(caar list) ,then ,@else))))
|
||||
|
||||
(compat-defmacro when-let* (varlist &rest body) ;; <compat-tests:when-let*>
|
||||
"Bind variables according to VARLIST and conditionally evaluate BODY.
|
||||
This is like `when-let' but doesn't handle a VARLIST of the form
|
||||
\(SYMBOL SOMETHING) specially."
|
||||
(declare (indent 1) (debug if-let*))
|
||||
(list 'if-let* varlist (macroexp-progn body)))
|
||||
|
||||
(compat-defmacro and-let* (varlist &rest body) ;; <compat-tests:and-let*>
|
||||
"Bind variables according to VARLIST and conditionally evaluate BODY.
|
||||
Like `when-let*', except if BODY is empty and all the bindings
|
||||
are non-nil, then the result is non-nil."
|
||||
(declare (indent 1)
|
||||
(debug ((&rest [&or symbolp (symbolp form) (form)])
|
||||
body)))
|
||||
(let ((empty (make-symbol "s"))
|
||||
(last t) list)
|
||||
(dolist (var varlist)
|
||||
(push `(,(if (cdr var) (car var) empty)
|
||||
(and ,last ,(if (cdr var) (cadr var) (car var))))
|
||||
list)
|
||||
(when (or (cdr var) (consp (car var)))
|
||||
(setq last (caar list))))
|
||||
`(let* ,(nreverse list)
|
||||
(if ,(caar list) ,(macroexp-progn (or body '(t)))))))
|
||||
|
||||
;;;; Defined in files.el
|
||||
|
||||
(declare-function temporary-file-directory nil)
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defun make-nearby-temp-file (prefix &optional dir-flag suffix)
|
||||
"Create a temporary file as close as possible to `default-directory'.
|
||||
If PREFIX is a relative file name, and `default-directory' is a
|
||||
remote file name or located on a mounted file systems, the
|
||||
temporary file is created in the directory returned by the
|
||||
function `temporary-file-directory'. Otherwise, the function
|
||||
`make-temp-file' is used. PREFIX, DIR-FLAG and SUFFIX have the
|
||||
same meaning as in `make-temp-file'."
|
||||
(let ((handler (find-file-name-handler
|
||||
default-directory 'make-nearby-temp-file)))
|
||||
(if (and handler (not (file-name-absolute-p default-directory)))
|
||||
(funcall handler 'make-nearby-temp-file prefix dir-flag suffix)
|
||||
(let ((temporary-file-directory (temporary-file-directory)))
|
||||
(make-temp-file prefix dir-flag suffix)))))
|
||||
|
||||
(compat-defvar mounted-file-systems
|
||||
(compat-defvar mounted-file-systems ;; <compat-tests:mounted-file-systems>
|
||||
(eval-when-compile
|
||||
(if (memq system-type '(windows-nt cygwin))
|
||||
"^//[^/]+/"
|
||||
@@ -389,35 +356,16 @@ same meaning as in `make-temp-file'."
|
||||
"^" (regexp-opt '("/afs/" "/media/" "/mnt" "/net/" "/tmp_mnt/")))))
|
||||
"File systems that ought to be mounted.")
|
||||
|
||||
(compat-defun file-local-name (file)
|
||||
(compat-defun file-local-name (file) ;; <compat-tests:file-local-name>
|
||||
"Return the local name component of FILE.
|
||||
This function removes from FILE the specification of the remote host
|
||||
and the method of accessing the host, leaving only the part that
|
||||
identifies FILE locally on the remote system.
|
||||
The returned file name can be used directly as argument of
|
||||
`process-file', `start-file-process', or `shell-command'."
|
||||
:realname compat--file-local-name
|
||||
(or (file-remote-p file 'localname) file))
|
||||
|
||||
(compat-defun file-name-quoted-p (name &optional top)
|
||||
"Whether NAME is quoted with prefix \"/:\".
|
||||
If NAME is a remote file name and TOP is nil, check the local part of NAME."
|
||||
:realname compat--file-name-quoted-p
|
||||
(let ((file-name-handler-alist (unless top file-name-handler-alist)))
|
||||
(string-prefix-p "/:" (compat--file-local-name name))))
|
||||
|
||||
(compat-defun file-name-quote (name &optional top)
|
||||
"Add the quotation prefix \"/:\" to file NAME.
|
||||
If NAME is a remote file name and TOP is nil, the local part of
|
||||
NAME is quoted. If NAME is already a quoted file name, NAME is
|
||||
returned unchanged."
|
||||
(let ((file-name-handler-alist (unless top file-name-handler-alist)))
|
||||
(if (compat--file-name-quoted-p name top)
|
||||
name
|
||||
(concat (file-remote-p name) "/:" (compat--file-local-name name)))))
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defun temporary-file-directory ()
|
||||
(compat-defun temporary-file-directory () ;; <compat-tests:temporary-file-directory>
|
||||
"The directory for writing temporary files.
|
||||
In case of a remote `default-directory', this is a directory for
|
||||
temporary files on that remote host. If such a directory does
|
||||
@@ -426,87 +374,107 @@ mounted file system (see `mounted-file-systems'), the function
|
||||
returns `default-directory'.
|
||||
For a non-remote and non-mounted `default-directory', the value of
|
||||
the variable `temporary-file-directory' is returned."
|
||||
;; NOTE: The handler may fail with an error, since the
|
||||
;; `temporary-file-directory' handler was introduced in Emacs 26.
|
||||
(let ((handler (find-file-name-handler
|
||||
default-directory 'temporary-file-directory)))
|
||||
(if handler
|
||||
(funcall handler 'temporary-file-directory)
|
||||
(if (string-match mounted-file-systems default-directory)
|
||||
default-directory
|
||||
temporary-file-directory))))
|
||||
(or (and handler (ignore-errors (funcall handler 'temporary-file-directory)))
|
||||
(if-let ((remote (file-remote-p default-directory)))
|
||||
(concat remote "/tmp/") ;; FIXME: Guess /tmp on remote host
|
||||
(if (string-match mounted-file-systems default-directory)
|
||||
default-directory
|
||||
temporary-file-directory)))))
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defun file-attribute-type (attributes)
|
||||
(compat-defun make-temp-file (prefix &optional dir-flag suffix text) ;; <compat-tests:make-temp-file>
|
||||
"Handle optional argument TEXT."
|
||||
:extended t
|
||||
(let ((file (make-temp-file prefix dir-flag suffix)))
|
||||
(when text
|
||||
(with-temp-buffer
|
||||
(insert text)
|
||||
(write-region (point-min) (point-max) file)))
|
||||
file))
|
||||
|
||||
(compat-defun make-nearby-temp-file (prefix &optional dir-flag suffix) ;; <compat-tests:make-nearby-temp-file>
|
||||
"Create a temporary file as close as possible to `default-directory'.
|
||||
If PREFIX is a relative file name, and `default-directory' is a
|
||||
remote file name or located on a mounted file systems, the
|
||||
temporary file is created in the directory returned by the
|
||||
function `temporary-file-directory'. Otherwise, the function
|
||||
`make-temp-file' is used. PREFIX, DIR-FLAG and SUFFIX have the
|
||||
same meaning as in `make-temp-file'."
|
||||
;; NOTE: The handler may fail with an error, since the
|
||||
;; `make-nearby-temp-file' handler was introduced in Emacs 26.
|
||||
(let ((handler (and (not (file-name-absolute-p default-directory))
|
||||
(find-file-name-handler
|
||||
default-directory 'make-nearby-temp-file))))
|
||||
(or (and handler (ignore-errors (funcall handler 'make-nearby-temp-file
|
||||
prefix dir-flag suffix)))
|
||||
(let ((temporary-file-directory (temporary-file-directory)))
|
||||
(make-temp-file prefix dir-flag suffix)))))
|
||||
|
||||
(compat-defun file-attribute-type (attributes) ;; <compat-tests:file-attribute-getters>
|
||||
"The type field in ATTRIBUTES returned by `file-attributes'.
|
||||
The value is either t for directory, string (name linked to) for
|
||||
symbolic link, or nil."
|
||||
(nth 0 attributes))
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defun file-attribute-link-number (attributes)
|
||||
(compat-defun file-attribute-link-number (attributes) ;; <compat-tests:file-attribute-getters>
|
||||
"Return the number of links in ATTRIBUTES returned by `file-attributes'."
|
||||
(nth 1 attributes))
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defun file-attribute-user-id (attributes)
|
||||
(compat-defun file-attribute-user-id (attributes) ;; <compat-tests:file-attribute-getters>
|
||||
"The UID field in ATTRIBUTES returned by `file-attributes'.
|
||||
This is either a string or a number. If a string value cannot be
|
||||
looked up, a numeric value, either an integer or a float, is
|
||||
returned."
|
||||
(nth 2 attributes))
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defun file-attribute-group-id (attributes)
|
||||
(compat-defun file-attribute-group-id (attributes) ;; <compat-tests:file-attribute-getters>
|
||||
"The GID field in ATTRIBUTES returned by `file-attributes'.
|
||||
This is either a string or a number. If a string value cannot be
|
||||
looked up, a numeric value, either an integer or a float, is
|
||||
returned."
|
||||
(nth 3 attributes))
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defun file-attribute-access-time (attributes)
|
||||
(compat-defun file-attribute-access-time (attributes) ;; <compat-tests:file-attribute-getters>
|
||||
"The last access time in ATTRIBUTES returned by `file-attributes'.
|
||||
This a Lisp timestamp in the style of `current-time'."
|
||||
(nth 4 attributes))
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defun file-attribute-modification-time (attributes)
|
||||
(compat-defun file-attribute-modification-time (attributes) ;; <compat-tests:file-attribute-getters>
|
||||
"The modification time in ATTRIBUTES returned by `file-attributes'.
|
||||
This is the time of the last change to the file's contents, and
|
||||
is a Lisp timestamp in the style of `current-time'."
|
||||
(nth 5 attributes))
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defun file-attribute-status-change-time (attributes)
|
||||
(compat-defun file-attribute-status-change-time (attributes) ;; <compat-tests:file-attribute-getters>
|
||||
"The status modification time in ATTRIBUTES returned by `file-attributes'.
|
||||
This is the time of last change to the file's attributes: owner
|
||||
and group, access mode bits, etc., and is a Lisp timestamp in the
|
||||
style of `current-time'."
|
||||
(nth 6 attributes))
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defun file-attribute-size (attributes)
|
||||
(compat-defun file-attribute-size (attributes) ;; <compat-tests:file-attribute-getters>
|
||||
"The integer size (in bytes) in ATTRIBUTES returned by `file-attributes'."
|
||||
(nth 7 attributes))
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defun file-attribute-modes (attributes)
|
||||
(compat-defun file-attribute-modes (attributes) ;; <compat-tests:file-attribute-getters>
|
||||
"The file modes in ATTRIBUTES returned by `file-attributes'.
|
||||
This is a string of ten letters or dashes as in ls -l."
|
||||
(nth 8 attributes))
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defun file-attribute-inode-number (attributes)
|
||||
(compat-defun file-attribute-inode-number (attributes) ;; <compat-tests:file-attribute-getters>
|
||||
"The inode number in ATTRIBUTES returned by `file-attributes'.
|
||||
It is a nonnegative integer."
|
||||
(nth 10 attributes))
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defun file-attribute-device-number (attributes)
|
||||
(compat-defun file-attribute-device-number (attributes) ;; <compat-tests:file-attribute-getters>
|
||||
"The file system device number in ATTRIBUTES returned by `file-attributes'.
|
||||
It is an integer."
|
||||
(nth 11 attributes))
|
||||
|
||||
(compat-defun file-attribute-collect (attributes &rest attr-names)
|
||||
(compat-defun file-attribute-collect (attributes &rest attr-names) ;; <compat-tests:file-attribute-collect>
|
||||
"Return a sublist of ATTRIBUTES returned by `file-attributes'.
|
||||
ATTR-NAMES are symbols with the selected attribute names.
|
||||
|
||||
@@ -534,105 +502,28 @@ inode-number and device-number."
|
||||
(error "Wrong attribute name '%S'" attr))))
|
||||
(nreverse result)))
|
||||
|
||||
;;;; Defined in subr-x.el
|
||||
;;;; Defined in mouse.el
|
||||
|
||||
(compat-defmacro if-let* (varlist then &rest else)
|
||||
"Bind variables according to VARLIST and evaluate THEN or ELSE.
|
||||
This is like `if-let' but doesn't handle a VARLIST of the form
|
||||
\(SYMBOL SOMETHING) specially."
|
||||
:realname compat--if-let*
|
||||
:feature 'subr-x
|
||||
(declare (indent 2)
|
||||
(debug ((&rest [&or symbolp (symbolp form) (form)])
|
||||
body)))
|
||||
(let ((empty (make-symbol "s"))
|
||||
(last t) list)
|
||||
(dolist (var varlist)
|
||||
(push `(,(if (cdr var) (car var) empty)
|
||||
(and ,last ,(or (cadr var) (car var))))
|
||||
list)
|
||||
(when (or (cdr var) (consp (car var)))
|
||||
(setq last (caar list))))
|
||||
`(let* ,(nreverse list)
|
||||
(if ,(caar list) ,then ,@else))))
|
||||
|
||||
(compat-defmacro when-let* (varlist &rest body)
|
||||
"Bind variables according to VARLIST and conditionally evaluate BODY.
|
||||
This is like `when-let' but doesn't handle a VARLIST of the form
|
||||
\(SYMBOL SOMETHING) specially."
|
||||
;; :feature 'subr-x
|
||||
(declare (indent 1) (debug if-let*))
|
||||
(let ((empty (make-symbol "s"))
|
||||
(last t) list)
|
||||
(dolist (var varlist)
|
||||
(push `(,(if (cdr var) (car var) empty)
|
||||
(and ,last ,(or (cadr var) (car var))))
|
||||
list)
|
||||
(when (or (cdr var) (consp (car var)))
|
||||
(setq last (caar list))))
|
||||
`(let* ,(nreverse list)
|
||||
(when ,(caar list) ,@body))))
|
||||
|
||||
(compat-defmacro and-let* (varlist &rest body)
|
||||
"Bind variables according to VARLIST and conditionally evaluate BODY.
|
||||
Like `when-let*', except if BODY is empty and all the bindings
|
||||
are non-nil, then the result is non-nil."
|
||||
:feature 'subr-x
|
||||
(declare (indent 1) (debug if-let*))
|
||||
(let ((empty (make-symbol "s"))
|
||||
(last t) list)
|
||||
(dolist (var varlist)
|
||||
(push `(,(if (cdr var) (car var) empty)
|
||||
(and ,last ,(or (cadr var) (car var))))
|
||||
list)
|
||||
(when (or (cdr var) (consp (car var)))
|
||||
(setq last (caar list))))
|
||||
`(let* ,(nreverse list)
|
||||
(if ,(caar list) ,(macroexp-progn (or body '(t)))))))
|
||||
(compat-defvar mouse-select-region-move-to-beginning nil ;; <compat-tests:thing-at-mouse>
|
||||
"Effect of selecting a region extending backward from double click.
|
||||
Nil means keep point at the position clicked (region end);
|
||||
non-nil means move point to beginning of region.")
|
||||
|
||||
;;;; Defined in image.el
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defun image-property (image property)
|
||||
(compat-defun image-property (image property) ;; <compat-tests:image-property>
|
||||
"Return the value of PROPERTY in IMAGE.
|
||||
Properties can be set with
|
||||
|
||||
(setf (image-property IMAGE PROPERTY) VALUE)
|
||||
|
||||
If VALUE is nil, PROPERTY is removed from IMAGE."
|
||||
:feature image
|
||||
(plist-get (cdr image) property))
|
||||
|
||||
;;* UNTESTED
|
||||
(unless (get 'image-property 'gv-expander)
|
||||
(gv-define-setter image-property (image property value)
|
||||
(let ((image* (make-symbol "image"))
|
||||
(property* (make-symbol "property"))
|
||||
(value* (make-symbol "value")))
|
||||
`(let ((,image* ,image)
|
||||
(,property* ,property)
|
||||
(,value* ,value))
|
||||
(if
|
||||
(null ,value*)
|
||||
(while
|
||||
(cdr ,image*)
|
||||
(if
|
||||
(eq
|
||||
(cadr ,image*)
|
||||
,property*)
|
||||
(setcdr ,image*
|
||||
(cdddr ,image*))
|
||||
(setq ,image*
|
||||
(cddr ,image*))))
|
||||
(setcdr ,image*
|
||||
(plist-put
|
||||
(cdr ,image*)
|
||||
,property* ,value*)))))))
|
||||
|
||||
;;;; Defined in rmc.el
|
||||
|
||||
;;*UNTESTED
|
||||
(compat-defun read-multiple-choice
|
||||
(prompt choices &optional _help-string _show-help long-form)
|
||||
(compat-defun read-multiple-choice (prompt choices) ;; <compat-tests:read-multiple-choice>
|
||||
"Ask user to select an entry from CHOICES, promting with PROMPT.
|
||||
This function allows to ask the user a multiple-choice question.
|
||||
|
||||
@@ -641,35 +532,23 @@ KEY is a character the user should type to select the entry.
|
||||
NAME is a short name for the entry to be displayed while prompting
|
||||
\(if there's no room, it might be shortened).
|
||||
|
||||
If LONG-FORM, do a `completing-read' over the NAME elements in
|
||||
CHOICES instead."
|
||||
:note "This is a partial implementation of `read-multiple-choice', that
|
||||
NOTE: This is a partial implementation of `read-multiple-choice', that
|
||||
among other things doesn't offer any help and ignores the
|
||||
optional DESCRIPTION field."
|
||||
(if long-form
|
||||
(let ((options (mapconcat #'cadr choices "/"))
|
||||
choice)
|
||||
(setq prompt (concat prompt " (" options "): "))
|
||||
(setq choice (completing-read prompt (mapcar #'cadr choices) nil t))
|
||||
(catch 'found
|
||||
(dolist (option choices)
|
||||
(when (string= choice (cadr option))
|
||||
(throw 'found option)))
|
||||
(error "Invalid choice")))
|
||||
(let ((options
|
||||
(mapconcat
|
||||
(lambda (opt)
|
||||
(format
|
||||
"[%s] %s"
|
||||
(key-description (string (car opt)))
|
||||
(cadr opt)))
|
||||
choices " "))
|
||||
choice)
|
||||
(setq prompt (concat prompt " (" options "): "))
|
||||
(while (not (setq choice (assq (read-char prompt) choices)))
|
||||
(message "Invalid choice")
|
||||
(sit-for 1))
|
||||
choice)))
|
||||
(let ((options
|
||||
(mapconcat
|
||||
(lambda (opt)
|
||||
(format
|
||||
"[%s] %s"
|
||||
(key-description (string (car opt)))
|
||||
(cadr opt)))
|
||||
choices " "))
|
||||
choice)
|
||||
(setq prompt (concat prompt " (" options "): "))
|
||||
(while (not (setq choice (assq (read-event prompt) choices)))
|
||||
(message "Invalid choice")
|
||||
(sit-for 1))
|
||||
choice))
|
||||
|
||||
(compat--inhibit-prefixed (provide 'compat-26))
|
||||
(provide 'compat-26)
|
||||
;;; compat-26.el ends here
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,6 @@
|
||||
;;; compat-28.el --- Compatibility Layer for Emacs 28.1 -*- lexical-binding: t; -*-
|
||||
;;; compat-28.el --- Functionality added in Emacs 28.1 -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2021, 2022 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Philip Kaludercic <philipk@posteo.net>
|
||||
;; Maintainer: Compat Development <~pkal/compat-devel@lists.sr.ht>
|
||||
;; URL: https://git.sr.ht/~pkal/compat/
|
||||
;; Keywords: lisp
|
||||
;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
@@ -22,31 +17,23 @@
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; Find here the functionality added in Emacs 28.1, needed by older
|
||||
;; versions.
|
||||
;;
|
||||
;; Only load this library if you need to use one of the following
|
||||
;; functions:
|
||||
;;
|
||||
;; - `unlock-buffer'
|
||||
;; - `string-width'
|
||||
;; - `directory-files'
|
||||
;; - `json-serialize'
|
||||
;; - `json-insert'
|
||||
;; - `json-parse-string'
|
||||
;; - `json-parse-buffer'
|
||||
;; - `count-windows'
|
||||
;; Functionality added in Emacs 28.1, needed by older Emacs versions.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'compat-macs "compat-macs.el")
|
||||
(eval-when-compile (load "compat-macs.el" nil t t))
|
||||
(compat-require compat-27 "27.1")
|
||||
|
||||
(compat-declare-version "28.1")
|
||||
(compat-version "28.1")
|
||||
|
||||
;;;; Defined in comp.c
|
||||
|
||||
(compat-defalias native-comp-available-p ignore) ;; <compat-tests:native-comp-available-p>
|
||||
|
||||
;;;; Defined in fns.c
|
||||
|
||||
;;* INCOMPLETE FEATURE: Should handle multibyte regular expressions
|
||||
(compat-defun string-search (needle haystack &optional start-pos)
|
||||
;; FIXME Should handle multibyte regular expressions
|
||||
(compat-defun string-search (needle haystack &optional start-pos) ;; <compat-tests:string-search>
|
||||
"Search for the string NEEDLE in the strign HAYSTACK.
|
||||
|
||||
The return value is the position of the first occurrence of
|
||||
@@ -56,8 +43,9 @@ The optional START-POS argument says where to start searching in
|
||||
HAYSTACK and defaults to zero (start at the beginning).
|
||||
It must be between zero and the length of HAYSTACK, inclusive.
|
||||
|
||||
Case is always significant and text properties are ignored."
|
||||
:note "Prior to Emacs 27 `string-match' has issues handling
|
||||
Case is always significant and text properties are ignored.
|
||||
|
||||
NOTE: Prior to Emacs 27 `string-match' has issues handling
|
||||
multibyte regular expressions. As the compatibility function
|
||||
for `string-search' is implemented via `string-match', these
|
||||
issues are inherited."
|
||||
@@ -68,7 +56,7 @@ issues are inherited."
|
||||
(let ((case-fold-search nil))
|
||||
(string-match (regexp-quote needle) haystack start-pos))))
|
||||
|
||||
(compat-defun length= (sequence length)
|
||||
(compat-defun length= (sequence length) ;; [[compat-tests:length=]]
|
||||
"Returns non-nil if SEQUENCE has a length equal to LENGTH."
|
||||
(cond
|
||||
((null sequence) (zerop length))
|
||||
@@ -80,7 +68,7 @@ issues are inherited."
|
||||
(= (length sequence) length))
|
||||
((signal 'wrong-type-argument sequence))))
|
||||
|
||||
(compat-defun length< (sequence length)
|
||||
(compat-defun length< (sequence length) ;; [[compat-tests:length<]]
|
||||
"Returns non-nil if SEQUENCE is shorter than LENGTH."
|
||||
(cond
|
||||
((null sequence) (not (zerop length)))
|
||||
@@ -90,7 +78,7 @@ issues are inherited."
|
||||
(< (length sequence) length))
|
||||
((signal 'wrong-type-argument sequence))))
|
||||
|
||||
(compat-defun length> (sequence length)
|
||||
(compat-defun length> (sequence length) ;; [[compat-tests:length>]]
|
||||
"Returns non-nil if SEQUENCE is longer than LENGTH."
|
||||
(cond
|
||||
((listp sequence)
|
||||
@@ -101,62 +89,36 @@ issues are inherited."
|
||||
|
||||
;;;; Defined in fileio.c
|
||||
|
||||
(compat-defun file-name-concat (directory &rest components)
|
||||
(compat-defun file-name-concat (directory &rest components) ;; <compat-tests:file-name-concat>
|
||||
"Append COMPONENTS to DIRECTORY and return the resulting string.
|
||||
Elements in COMPONENTS must be a string or nil.
|
||||
DIRECTORY or the non-final elements in COMPONENTS may or may not end
|
||||
with a slash -- if they don’t end with a slash, a slash will be
|
||||
inserted before contatenating."
|
||||
(let ((seperator (eval-when-compile
|
||||
(let ((separator (eval-when-compile
|
||||
(if (memq system-type '(ms-dos windows-nt cygwin))
|
||||
"\\" "/")))
|
||||
(last (if components (car (last components)) directory)))
|
||||
(mapconcat (lambda (part)
|
||||
(if (eq part last) ;the last component is not modified
|
||||
last
|
||||
(replace-regexp-in-string
|
||||
(concat seperator "+\\'") "" part)))
|
||||
(cons directory components)
|
||||
seperator)))
|
||||
(components (delq nil
|
||||
(mapcar (lambda (x) (and (not (equal "" x)) x))
|
||||
(cons directory components))))
|
||||
(result ""))
|
||||
(while components
|
||||
(let ((c (pop components)))
|
||||
(setq result (concat result c
|
||||
(and components
|
||||
(not (string-suffix-p separator c))
|
||||
separator)))))
|
||||
result))
|
||||
|
||||
;;;; Defined in alloc.c
|
||||
|
||||
;;* UNTESTED (but also not necessary)
|
||||
(compat-defun garbage-collect-maybe (_factor)
|
||||
"Call ‘garbage-collect’ if enough allocation happened.
|
||||
FACTOR determines what \"enough\" means here: If FACTOR is a
|
||||
positive number N, it means to run GC if more than 1/Nth of the
|
||||
allocations needed to trigger automatic allocation took place.
|
||||
Therefore, as N gets higher, this is more likely to perform a GC.
|
||||
Returns non-nil if GC happened, and nil otherwise."
|
||||
:note "For releases of Emacs before version 28, this function will do nothing."
|
||||
;; Do nothing
|
||||
nil)
|
||||
|
||||
;;;; Defined in filelock.c
|
||||
|
||||
(compat-defun unlock-buffer ()
|
||||
"Handle `file-error' conditions:
|
||||
|
||||
Handles file system errors by calling ‘display-warning’ and
|
||||
continuing as if the error did not occur."
|
||||
:prefix t
|
||||
(condition-case error
|
||||
(unlock-buffer)
|
||||
(file-error
|
||||
(display-warning
|
||||
'(unlock-file)
|
||||
(message "%s, ignored" (error-message-string error))
|
||||
:warning))))
|
||||
(compat-defalias garbage-collect-maybe ignore) ;; <compat-tests:garbage-collect-maybe>
|
||||
|
||||
;;;; Defined in characters.c
|
||||
|
||||
(compat-defun string-width (string &optional from to)
|
||||
"Handle optional arguments FROM and TO:
|
||||
|
||||
Optional arguments FROM and TO specify the substring of STRING to
|
||||
consider, and are interpreted as in `substring'."
|
||||
:prefix t
|
||||
(compat-defun string-width (string &optional from to) ;; <compat-tests:string-width>
|
||||
"Handle optional arguments FROM and TO."
|
||||
:extended t
|
||||
(let* ((len (length string))
|
||||
(from (or from 0))
|
||||
(to (or to len)))
|
||||
@@ -166,80 +128,25 @@ consider, and are interpreted as in `substring'."
|
||||
|
||||
;;;; Defined in dired.c
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defun directory-files (directory &optional full match nosort count)
|
||||
"Handle additional optional argument COUNT:
|
||||
|
||||
If COUNT is non-nil and a natural number, the function will
|
||||
return COUNT number of file names (if so many are present)."
|
||||
:prefix t
|
||||
(compat-defun directory-files (directory &optional full match nosort count) ;; <compat-tests:directory-files>
|
||||
"Handle additional optional argument COUNT."
|
||||
:extended t
|
||||
(let ((files (directory-files directory full match nosort)))
|
||||
(when (natnump count)
|
||||
(setf (nthcdr count files) nil))
|
||||
files))
|
||||
|
||||
;;;; Defined in json.c
|
||||
|
||||
(declare-function json-insert nil (object &rest args))
|
||||
(declare-function json-serialize nil (object &rest args))
|
||||
(declare-function json-parse-string nil (string &rest args))
|
||||
(declare-function json-parse-buffer nil (&rest args))
|
||||
|
||||
(compat-defun json-serialize (object &rest args)
|
||||
"Handle top-level JSON values."
|
||||
:prefix t
|
||||
:min-version "27"
|
||||
(if (or (listp object) (vectorp object))
|
||||
(apply #'json-serialize object args)
|
||||
(substring (json-serialize (list object)) 1 -1)))
|
||||
|
||||
(compat-defun json-insert (object &rest args)
|
||||
"Handle top-level JSON values."
|
||||
:prefix t
|
||||
:min-version "27"
|
||||
(if (or (listp object) (vectorp object))
|
||||
(apply #'json-insert object args)
|
||||
;; `compat-json-serialize' is not sharp-quoted as the byte
|
||||
;; compiled doesn't always know that the function has been
|
||||
;; defined, but it will only be used in this function if the
|
||||
;; prefixed definition of `json-serialize' (see above) has also
|
||||
;; been defined.
|
||||
(insert (apply 'compat-json-serialize object args))))
|
||||
|
||||
(compat-defun json-parse-string (string &rest args)
|
||||
"Handle top-level JSON values."
|
||||
:prefix t
|
||||
:min-version "27"
|
||||
(if (string-match-p "\\`[[:space:]]*[[{]" string)
|
||||
(apply #'json-parse-string string args)
|
||||
;; Wrap the string in an array, and extract the value back using
|
||||
;; `elt', to ensure that no matter what the value of `:array-type'
|
||||
;; is we can access the first element.
|
||||
(elt (apply #'json-parse-string (concat "[" string "]") args) 0)))
|
||||
|
||||
(compat-defun json-parse-buffer (&rest args)
|
||||
"Handle top-level JSON values."
|
||||
:prefix t
|
||||
:min-version "27"
|
||||
(if (looking-at-p "[[:space:]]*[[{]")
|
||||
(apply #'json-parse-buffer args)
|
||||
(catch 'escape
|
||||
(atomic-change-group
|
||||
(with-syntax-table
|
||||
(let ((st (make-syntax-table)))
|
||||
(modify-syntax-entry ?\" "\"" st)
|
||||
(modify-syntax-entry ?. "_" st)
|
||||
st)
|
||||
(let ((inhibit-read-only t))
|
||||
(save-excursion
|
||||
(insert "[")
|
||||
(forward-sexp 1)
|
||||
(insert "]"))))
|
||||
(throw 'escape (elt (apply #'json-parse-buffer args) 0))))))
|
||||
(compat-defun directory-files-and-attributes (directory &optional full match nosort id-format count) ;; <compat-tests:directory-files-and-attributes>
|
||||
"Handle additional optional argument COUNT."
|
||||
:extended t
|
||||
(let ((files (directory-files-and-attributes directory full match nosort id-format)))
|
||||
(when (natnump count)
|
||||
(setf (nthcdr count files) nil))
|
||||
files))
|
||||
|
||||
;;;; xfaces.c
|
||||
|
||||
(compat-defun color-values-from-color-spec (spec)
|
||||
(compat-defun color-values-from-color-spec (spec) ;; <compat-tests:color-values-from-color-spec>
|
||||
"Parse color SPEC as a numeric color and return (RED GREEN BLUE).
|
||||
This function recognises the following formats for SPEC:
|
||||
|
||||
@@ -313,10 +220,50 @@ and BLUE, is normalized to have its value in [0,65535]."
|
||||
(<= 0 b) (<= b 65535))
|
||||
(list r g b))))))))
|
||||
|
||||
;;;; Defined in simple.el
|
||||
|
||||
(compat-defun make-separator-line (&optional length) ;; <compat-tests:make-separator-line>
|
||||
"Make a string appropriate for usage as a visual separator line.
|
||||
If LENGTH is nil, use the window width."
|
||||
(if (display-graphic-p)
|
||||
(if length
|
||||
(concat (propertize (make-string length ?\s) 'face '(:underline t)) "\n")
|
||||
(propertize "\n" 'face '(:extend t :height 0.1 :inverse-video t)))
|
||||
(concat (make-string (or length (1- (window-width))) ?-) "\n")))
|
||||
|
||||
;;;; Defined in subr.el
|
||||
|
||||
;;* INCOMPLETE FEATURE: Should handle multibyte regular expressions
|
||||
(compat-defun string-replace (fromstring tostring instring)
|
||||
(compat-defun process-lines-handling-status (program status-handler &rest args) ;; <compat-tests:process-lines-handling-status>
|
||||
"Execute PROGRAM with ARGS, returning its output as a list of lines.
|
||||
If STATUS-HANDLER is non-nil, it must be a function with one
|
||||
argument, which will be called with the exit status of the
|
||||
program before the output is collected. If STATUS-HANDLER is
|
||||
nil, an error is signaled if the program returns with a non-zero
|
||||
exit status."
|
||||
(with-temp-buffer
|
||||
(let ((status (apply #'call-process program nil (current-buffer) nil args)))
|
||||
(if status-handler
|
||||
(funcall status-handler status)
|
||||
(unless (eq status 0)
|
||||
(error "%s exited with status %s" program status)))
|
||||
(goto-char (point-min))
|
||||
(let (lines)
|
||||
(while (not (eobp))
|
||||
(setq lines (cons (buffer-substring-no-properties
|
||||
(line-beginning-position)
|
||||
(line-end-position))
|
||||
lines))
|
||||
(forward-line 1))
|
||||
(nreverse lines)))))
|
||||
|
||||
(compat-defun process-lines-ignore-status (program &rest args) ;; <compat-tests:process-lines-ignore-status>
|
||||
"Execute PROGRAM with ARGS, returning its output as a list of lines.
|
||||
The exit status of the program is ignored.
|
||||
Also see `process-lines'."
|
||||
(apply 'process-lines-handling-status program #'ignore args))
|
||||
|
||||
;; FIXME Should handle multibyte regular expressions
|
||||
(compat-defun string-replace (fromstring tostring instring) ;; <compat-tests:string-replace>
|
||||
"Replace FROMSTRING with TOSTRING in INSTRING each time it occurs."
|
||||
(when (equal fromstring "")
|
||||
(signal 'wrong-length-argument '(0)))
|
||||
@@ -326,14 +273,13 @@ and BLUE, is normalized to have its value in [0,65535]."
|
||||
tostring instring
|
||||
t t)))
|
||||
|
||||
(compat-defun always (&rest _arguments)
|
||||
(compat-defun always (&rest _arguments) ;; <compat-tests:always>
|
||||
"Do nothing and return t.
|
||||
This function accepts any number of ARGUMENTS, but ignores them.
|
||||
Also see `ignore'."
|
||||
t)
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defun insert-into-buffer (buffer &optional start end)
|
||||
(compat-defun insert-into-buffer (buffer &optional start end) ;; <compat-tests:insert-into-buffer>
|
||||
"Insert the contents of the current buffer into BUFFER.
|
||||
If START/END, only insert that region from the current buffer.
|
||||
Point in BUFFER will be placed after the inserted text."
|
||||
@@ -341,8 +287,7 @@ Point in BUFFER will be placed after the inserted text."
|
||||
(with-current-buffer buffer
|
||||
(insert-buffer-substring current start end))))
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defun replace-string-in-region (string replacement &optional start end)
|
||||
(compat-defun replace-string-in-region (string replacement &optional start end) ;; <compat-tests:replace-string-in-region>
|
||||
"Replace STRING with REPLACEMENT in the region from START to END.
|
||||
The number of replaced occurrences are returned, or nil if STRING
|
||||
doesn't exist in the region.
|
||||
@@ -359,18 +304,19 @@ Comparisons and replacements are done with fixed case."
|
||||
(error "End after end of buffer"))
|
||||
(setq end (point-max)))
|
||||
(save-excursion
|
||||
(let ((matches 0)
|
||||
(case-fold-search nil))
|
||||
(goto-char start)
|
||||
(while (search-forward string end t)
|
||||
(delete-region (match-beginning 0) (match-end 0))
|
||||
(insert replacement)
|
||||
(setq matches (1+ matches)))
|
||||
(and (not (zerop matches))
|
||||
matches))))
|
||||
(goto-char start)
|
||||
(save-restriction
|
||||
(narrow-to-region start end)
|
||||
(let ((matches 0)
|
||||
(case-fold-search nil))
|
||||
(while (search-forward string nil t)
|
||||
(delete-region (match-beginning 0) (match-end 0))
|
||||
(insert replacement)
|
||||
(setq matches (1+ matches)))
|
||||
(and (not (zerop matches))
|
||||
matches)))))
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defun replace-regexp-in-region (regexp replacement &optional start end)
|
||||
(compat-defun replace-regexp-in-region (regexp replacement &optional start end) ;; <compat-tests:replace-regexp-in-region>
|
||||
"Replace REGEXP with REPLACEMENT in the region from START to END.
|
||||
The number of replaced occurrences are returned, or nil if REGEXP
|
||||
doesn't exist in the region.
|
||||
@@ -395,17 +341,18 @@ REPLACEMENT can use the following special elements:
|
||||
(error "End after end of buffer"))
|
||||
(setq end (point-max)))
|
||||
(save-excursion
|
||||
(let ((matches 0)
|
||||
(case-fold-search nil))
|
||||
(goto-char start)
|
||||
(while (re-search-forward regexp end t)
|
||||
(replace-match replacement t)
|
||||
(setq matches (1+ matches)))
|
||||
(and (not (zerop matches))
|
||||
matches))))
|
||||
(goto-char start)
|
||||
(save-restriction
|
||||
(narrow-to-region start end)
|
||||
(let ((matches 0)
|
||||
(case-fold-search nil))
|
||||
(while (re-search-forward regexp nil t)
|
||||
(replace-match replacement t)
|
||||
(setq matches (1+ matches)))
|
||||
(and (not (zerop matches))
|
||||
matches)))))
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defun buffer-local-boundp (symbol buffer)
|
||||
(compat-defun buffer-local-boundp (symbol buffer) ;; <compat-tests:buffer-local-boundp>
|
||||
"Return non-nil if SYMBOL is bound in BUFFER.
|
||||
Also see `local-variable-p'."
|
||||
(catch 'fail
|
||||
@@ -414,26 +361,23 @@ Also see `local-variable-p'."
|
||||
(void-variable nil (throw 'fail nil)))
|
||||
t))
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defmacro with-existing-directory (&rest body)
|
||||
(compat-defmacro with-existing-directory (&rest body) ;; <compat-tests:with-existing-directory>
|
||||
"Execute BODY with `default-directory' bound to an existing directory.
|
||||
If `default-directory' is already an existing directory, it's not changed."
|
||||
(declare (indent 0) (debug t))
|
||||
(let ((quit (make-symbol "with-existing-directory-quit")))
|
||||
`(catch ',quit
|
||||
(dolist (dir (list default-directory
|
||||
(expand-file-name "~/")
|
||||
(getenv "TMPDIR")
|
||||
"/tmp/"
|
||||
;; XXX: check if "/" works on non-POSIX
|
||||
;; system.
|
||||
"/"))
|
||||
(when (and dir (file-exists-p dir))
|
||||
(throw ',quit (let ((default-directory dir))
|
||||
,@body)))))))
|
||||
`(let ((default-directory
|
||||
(or (catch 'quit
|
||||
(dolist (dir (list default-directory
|
||||
(expand-file-name "~/")
|
||||
temporary-file-directory
|
||||
(getenv "TMPDIR")
|
||||
"/tmp/"))
|
||||
(when (and dir (file-exists-p dir))
|
||||
(throw 'quit dir))))
|
||||
"/")))
|
||||
,@body))
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defmacro dlet (binders &rest body)
|
||||
(compat-defmacro dlet (binders &rest body) ;; <compat-tests:dlet>
|
||||
"Like `let' but using dynamic scoping."
|
||||
(declare (indent 1) (debug let))
|
||||
`(let (_)
|
||||
@@ -442,7 +386,7 @@ If `default-directory' is already an existing directory, it's not changed."
|
||||
binders)
|
||||
(let ,binders ,@body)))
|
||||
|
||||
(compat-defun ensure-list (object)
|
||||
(compat-defun ensure-list (object) ;; <compat-tests:ensure-list>
|
||||
"Return OBJECT as a list.
|
||||
If OBJECT is already a list, return OBJECT itself. If it's
|
||||
not a list, return a one-element list containing OBJECT."
|
||||
@@ -450,18 +394,19 @@ not a list, return a one-element list containing OBJECT."
|
||||
object
|
||||
(list object)))
|
||||
|
||||
(compat-defun subr-primitive-p (object)
|
||||
"Return t if OBJECT is a built-in primitive function."
|
||||
(subrp object))
|
||||
(compat-defalias subr-primitive-p subrp) ;; <compat-tests:subr-primitive-p>
|
||||
|
||||
;;;; Defined in data.c
|
||||
|
||||
(compat-defalias subr-native-elisp-p ignore) ;; <compat-tests:subr-native-elisp-p>
|
||||
|
||||
;;;; Defined in subr-x.el
|
||||
|
||||
(compat-defun string-clean-whitespace (string)
|
||||
(compat-defun string-clean-whitespace (string) ;; <compat-tests:string-clean-whitespace>
|
||||
"Clean up whitespace in STRING.
|
||||
All sequences of whitespaces in STRING are collapsed into a
|
||||
single space character, and leading/trailing whitespace is
|
||||
removed."
|
||||
:feature 'subr-x
|
||||
(let ((blank "[[:blank:]\r\n]+"))
|
||||
(replace-regexp-in-string
|
||||
"^[[:blank:]\r\n]+\\|[[:blank:]\r\n]+$"
|
||||
@@ -469,12 +414,11 @@ removed."
|
||||
(replace-regexp-in-string
|
||||
blank " " string))))
|
||||
|
||||
(compat-defun string-fill (string length)
|
||||
(compat-defun string-fill (string length) ;; <compat-tests:string-fill>
|
||||
"Clean up whitespace in STRING.
|
||||
All sequences of whitespaces in STRING are collapsed into a
|
||||
single space character, and leading/trailing whitespace is
|
||||
removed."
|
||||
:feature 'subr-x
|
||||
(with-temp-buffer
|
||||
(insert string)
|
||||
(goto-char (point-min))
|
||||
@@ -483,13 +427,7 @@ removed."
|
||||
(fill-region (point-min) (point-max)))
|
||||
(buffer-string)))
|
||||
|
||||
(compat-defun string-lines (string &optional omit-nulls)
|
||||
"Split STRING into a list of lines.
|
||||
If OMIT-NULLS, empty lines will be removed from the results."
|
||||
:feature 'subr-x
|
||||
(split-string string "\n" omit-nulls))
|
||||
|
||||
(compat-defun string-pad (string length &optional padding start)
|
||||
(compat-defun string-pad (string length &optional padding start) ;; <compat-tests:string-pad>
|
||||
"Pad STRING to LENGTH using PADDING.
|
||||
If PADDING is nil, the space character is used. If not nil, it
|
||||
should be a character.
|
||||
@@ -500,7 +438,6 @@ is done.
|
||||
If START is nil (or not present), the padding is done to the end
|
||||
of the string, and if non-nil, padding is done to the start of
|
||||
the string."
|
||||
:feature 'subr-x
|
||||
(unless (natnump length)
|
||||
(signal 'wrong-type-argument (list 'natnump length)))
|
||||
(let ((pad-length (- length (length string))))
|
||||
@@ -512,20 +449,18 @@ the string."
|
||||
(and (not start)
|
||||
(make-string pad-length (or padding ?\s)))))))
|
||||
|
||||
(compat-defun string-chop-newline (string)
|
||||
(compat-defun string-chop-newline (string) ;; <compat-tests:string-chop-newline>
|
||||
"Remove the final newline (if any) from STRING."
|
||||
:feature 'subr-x
|
||||
(if (and (>= (length string) 1) (= (aref string (1- (length string))) ?\n))
|
||||
(substring string 0 -1)
|
||||
string))
|
||||
|
||||
(compat-defmacro named-let (name bindings &rest body)
|
||||
(compat-defmacro named-let (name bindings &rest body) ;; <compat-tests:named-let>
|
||||
"Looping construct taken from Scheme.
|
||||
Like `let', bind variables in BINDINGS and then evaluate BODY,
|
||||
but with the twist that BODY can evaluate itself recursively by
|
||||
calling NAME, where the arguments passed to NAME are used
|
||||
as the new values of the bound variables in the recursive invocation."
|
||||
:feature 'subr-x
|
||||
(declare (indent 2) (debug (symbolp (&rest (symbolp form)) body)))
|
||||
(let ((fargs (mapcar (lambda (b)
|
||||
(let ((var (if (consp b) (car b) b)))
|
||||
@@ -596,10 +531,9 @@ as the new values of the bound variables in the recursive invocation."
|
||||
sets))
|
||||
(cons 'setq (apply #'nconc (nreverse sets)))))
|
||||
(`(throw ',quit ,expr))))))
|
||||
(let ((tco-body (funcall tco (macroexpand-all (macroexp-progn body)))))
|
||||
(when tco-body
|
||||
(setq body `((catch ',quit
|
||||
(while t (let ,rargs ,@(macroexp-unprogn tco-body))))))))
|
||||
(when-let ((tco-body (funcall tco (macroexpand-all (macroexp-progn body)))))
|
||||
(setq body `((catch ',quit
|
||||
(while t (let ,rargs ,@(macroexp-unprogn tco-body)))))))
|
||||
(let ((expand (macroexpand-all (macroexp-progn body) (list (cons name macro)))))
|
||||
(if total-tco
|
||||
`(let ,bindings ,expand)
|
||||
@@ -609,9 +543,7 @@ as the new values of the bound variables in the recursive invocation."
|
||||
|
||||
;;;; Defined in files.el
|
||||
|
||||
(declare-function compat--string-trim-left "compat-26" (string &optional regexp))
|
||||
(declare-function compat--directory-name-p "compat-25" (name))
|
||||
(compat-defun file-name-with-extension (filename extension)
|
||||
(compat-defun file-name-with-extension (filename extension) ;; <compat-tests:file-name-with-extension>
|
||||
"Set the EXTENSION of a FILENAME.
|
||||
The extension (in a file name) is the part that begins with the last \".\".
|
||||
|
||||
@@ -622,19 +554,18 @@ Errors if the FILENAME or EXTENSION are empty, or if the given
|
||||
FILENAME has the format of a directory.
|
||||
|
||||
See also `file-name-sans-extension'."
|
||||
(let ((extn (compat--string-trim-left extension "[.]")))
|
||||
(let ((extn (string-remove-prefix "." extension)))
|
||||
(cond
|
||||
((string= filename "")
|
||||
(error "Empty filename"))
|
||||
((string= extn "")
|
||||
(error "Malformed extension: %s" extension))
|
||||
((compat--directory-name-p filename)
|
||||
((directory-name-p filename)
|
||||
(error "Filename is a directory: %s" filename))
|
||||
(t
|
||||
(concat (file-name-sans-extension filename) "." extn)))))
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defun directory-empty-p (dir)
|
||||
(compat-defun directory-empty-p (dir) ;; <compat-tests:directory-empty-p>
|
||||
"Return t if DIR names an existing directory containing no other files.
|
||||
Return nil if DIR does not name a directory, or if there was
|
||||
trouble determining whether DIR is a directory or empty.
|
||||
@@ -644,7 +575,7 @@ See `file-symlink-p' to distinguish symlinks."
|
||||
(and (file-directory-p dir)
|
||||
(null (directory-files dir nil directory-files-no-dot-files-regexp t))))
|
||||
|
||||
(compat-defun file-modes-number-to-symbolic (mode &optional filetype)
|
||||
(compat-defun file-modes-number-to-symbolic (mode &optional filetype) ;; <compat-tests:file-modes-number-to-symbolic>
|
||||
"Return a string describing a file's MODE.
|
||||
For instance, if MODE is #o700, then it produces `-rwx------'.
|
||||
FILETYPE if provided should be a character denoting the type of file,
|
||||
@@ -652,7 +583,7 @@ such as `?d' for a directory, or `?l' for a symbolic link and will override
|
||||
the leading `-' char."
|
||||
(string
|
||||
(or filetype
|
||||
(pcase (lsh mode -12)
|
||||
(pcase (ash mode -12)
|
||||
;; POSIX specifies that the file type is included in st_mode
|
||||
;; and provides names for the file types but values only for
|
||||
;; the permissions (e.g., S_IWOTH=2).
|
||||
@@ -682,8 +613,7 @@ the leading `-' char."
|
||||
(if (zerop (logand 1 mode)) ?- ?x)
|
||||
(if (zerop (logand 1 mode)) ?T ?t))))
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defun file-backup-file-names (filename)
|
||||
(compat-defun file-backup-file-names (filename) ;; <compat-tests:file-backup-file-names>
|
||||
"Return a list of backup files for FILENAME.
|
||||
The list will be sorted by modification time so that the most
|
||||
recent files are first."
|
||||
@@ -702,7 +632,7 @@ recent files are first."
|
||||
(push candidate files))))
|
||||
(sort files #'file-newer-than-file-p)))
|
||||
|
||||
(compat-defun make-lock-file-name (filename)
|
||||
(compat-defun make-lock-file-name (filename) ;; <compat-tests:make-lock-file-name>
|
||||
"Make a lock file name for FILENAME.
|
||||
This prepends \".#\" to the non-directory part of FILENAME, and
|
||||
doesn't respect `lock-file-name-transforms', as Emacs 28.1 and
|
||||
@@ -712,21 +642,9 @@ onwards does."
|
||||
".#" (file-name-nondirectory filename))
|
||||
(file-name-directory filename)))
|
||||
|
||||
;;;; Defined in files-x.el
|
||||
|
||||
(declare-function tramp-tramp-file-p "tramp" (name))
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defun null-device ()
|
||||
"Return the best guess for the null device."
|
||||
(require 'tramp)
|
||||
(if (tramp-tramp-file-p default-directory)
|
||||
"/dev/null"
|
||||
null-device))
|
||||
|
||||
;;;; Defined in minibuffer.el
|
||||
|
||||
(compat-defun format-prompt (prompt default &rest format-args)
|
||||
(compat-defun format-prompt (prompt default &rest format-args) ;; <compat-tests:format-prompt>
|
||||
"Format PROMPT with DEFAULT.
|
||||
If FORMAT-ARGS is nil, PROMPT is used as a plain string. If
|
||||
FORMAT-ARGS is non-nil, PROMPT is used as a format control
|
||||
@@ -751,15 +669,56 @@ is included in the return value."
|
||||
default)))
|
||||
": "))
|
||||
|
||||
;;;; Defined in windows.el
|
||||
;;;; Defined in faces.el
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defun count-windows (&optional minibuf all-frames)
|
||||
"Handle optional argument ALL-FRAMES:
|
||||
(compat-defvar color-luminance-dark-limit 0.325 ;; <compat-tests:color-dark-p>
|
||||
"The relative luminance below which a color is considered \"dark\".
|
||||
A \"dark\" color in this sense provides better contrast with white
|
||||
than with black; see `color-dark-p'.
|
||||
This value was determined experimentally."
|
||||
:constant t)
|
||||
|
||||
If ALL-FRAMES is non-nil, count the windows in all frames instead
|
||||
just the selected frame."
|
||||
:prefix t
|
||||
(compat-defun color-dark-p (rgb) ;; <compat-tests:color-dark-p>
|
||||
"Whether RGB is more readable against white than black.
|
||||
RGB is a 3-element list (R G B), each component in the range [0,1].
|
||||
This predicate can be used both for determining a suitable (black or white)
|
||||
contrast color with RGB as background and as foreground."
|
||||
(unless (<= 0 (apply #'min rgb) (apply #'max rgb) 1)
|
||||
(error "RGB components %S not in [0,1]" rgb))
|
||||
;; Compute the relative luminance after gamma-correcting (assuming sRGB),
|
||||
;; and compare to a cut-off value determined experimentally.
|
||||
;; See https://en.wikipedia.org/wiki/Relative_luminance for details.
|
||||
(let* ((sr (nth 0 rgb))
|
||||
(sg (nth 1 rgb))
|
||||
(sb (nth 2 rgb))
|
||||
;; Gamma-correct the RGB components to linear values.
|
||||
;; Use the power 2.2 as an approximation to sRGB gamma;
|
||||
;; it should be good enough for the purpose of this function.
|
||||
(r (expt sr 2.2))
|
||||
(g (expt sg 2.2))
|
||||
(b (expt sb 2.2))
|
||||
(y (+ (* r 0.2126) (* g 0.7152) (* b 0.0722))))
|
||||
(< y color-luminance-dark-limit)))
|
||||
|
||||
;;;; Defined in window.el
|
||||
|
||||
(compat-defmacro with-window-non-dedicated (window &rest body) ;; <compat-tests:with-window-non-dedicated>
|
||||
"Evaluate BODY with WINDOW temporarily made non-dedicated.
|
||||
If WINDOW is nil, use the selected window. Return the value of
|
||||
the last form in BODY."
|
||||
(declare (indent 1) (debug t))
|
||||
(let ((window-dedicated-sym (gensym))
|
||||
(window-sym (gensym)))
|
||||
`(let* ((,window-sym (window-normalize-window ,window t))
|
||||
(,window-dedicated-sym (window-dedicated-p ,window-sym)))
|
||||
(set-window-dedicated-p ,window-sym nil)
|
||||
(unwind-protect
|
||||
(progn ,@body)
|
||||
(set-window-dedicated-p ,window-sym ,window-dedicated-sym)))))
|
||||
|
||||
(compat-defun count-windows (&optional minibuf all-frames) ;; <compat-tests:count-windows>
|
||||
"Handle optional argument ALL-FRAMES."
|
||||
:extended t
|
||||
(if all-frames
|
||||
(let ((sum 0))
|
||||
(dolist (frame (frame-list))
|
||||
@@ -770,37 +729,61 @@ just the selected frame."
|
||||
|
||||
;;;; Defined in thingatpt.el
|
||||
|
||||
(declare-function mouse-set-point "mouse" (event &optional promote-to-region))
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defun thing-at-mouse (event thing &optional no-properties)
|
||||
(compat-defun thing-at-mouse (event thing &optional no-properties) ;; <compat-tests:thing-at-mouse>
|
||||
"Return the THING at mouse click.
|
||||
Like `thing-at-point', but tries to use the event
|
||||
where the mouse button is clicked to find a thing nearby."
|
||||
:feature 'thingatpt
|
||||
;; No :feature specified, since the function is autoloaded.
|
||||
(save-excursion
|
||||
(mouse-set-point event)
|
||||
(thing-at-point thing no-properties)))
|
||||
|
||||
(compat-defun bounds-of-thing-at-mouse (event thing) ;; <compat-tests:thing-at-mouse>
|
||||
"Determine start and end locations for THING at mouse click given by EVENT.
|
||||
Like `bounds-of-thing-at-point', but tries to use the position in EVENT
|
||||
where the mouse button is clicked to find the thing nearby."
|
||||
;; No :feature specified, since the function is autoloaded.
|
||||
(save-excursion
|
||||
(mouse-set-point event)
|
||||
(bounds-of-thing-at-point thing)))
|
||||
|
||||
;;;; Defined in mouse.el
|
||||
|
||||
(compat-defun mark-thing-at-mouse (click thing) ;; <compat-tests:thing-at-mouse>
|
||||
"Activate the region around THING found near the mouse CLICK."
|
||||
(when-let ((bounds (bounds-of-thing-at-mouse click thing)))
|
||||
(goto-char (if mouse-select-region-move-to-beginning
|
||||
(car bounds) (cdr bounds)))
|
||||
(push-mark (if mouse-select-region-move-to-beginning
|
||||
(cdr bounds) (car bounds))
|
||||
t 'activate)))
|
||||
|
||||
;;;; Defined in macroexp.el
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defun macroexp-file-name ()
|
||||
(compat-defun macroexp-warn-and-return (msg form &optional _category _compile-only _arg) ;; <compat-tests:macroexp-warn-and-return>
|
||||
"Return code equivalent to FORM labeled with warning MSG.
|
||||
CATEGORY is the category of the warning, like the categories that
|
||||
can appear in `byte-compile-warnings'.
|
||||
COMPILE-ONLY non-nil means no warning should be emitted if the code
|
||||
is executed without being compiled first.
|
||||
ARG is a symbol (or a form) giving the source code position for the message.
|
||||
It should normally be a symbol with position and it defaults to FORM."
|
||||
(macroexp--warn-and-return msg form))
|
||||
|
||||
(compat-defun macroexp-file-name () ;; <compat-tests:macroexp-file-name>
|
||||
"Return the name of the file from which the code comes.
|
||||
Returns nil when we do not know.
|
||||
A non-nil result is expected to be reliable when called from a macro in order
|
||||
to find the file in which the macro's call was found, and it should be
|
||||
reliable as well when used at the top-level of a file.
|
||||
Other uses risk returning non-nil value that point to the wrong file."
|
||||
:feature 'macroexp
|
||||
(let ((file (car (last current-load-list))))
|
||||
(or (if (stringp file) file)
|
||||
(bound-and-true-p byte-compile-current-file))))
|
||||
|
||||
;;;; Defined in env.el
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defmacro with-environment-variables (variables &rest body)
|
||||
(compat-defmacro with-environment-variables (variables &rest body) ;; <compat-tests:with-environment-variables>
|
||||
"Set VARIABLES in the environent and execute BODY.
|
||||
VARIABLES is a list of variable settings of the form (VAR VALUE),
|
||||
where VAR is the name of the variable (a string) and VALUE
|
||||
@@ -816,67 +799,56 @@ The previous values will be be restored upon exit."
|
||||
variables)
|
||||
,@body))
|
||||
|
||||
;;;; Defined in button.el
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defun button-buttonize (string callback &optional data)
|
||||
"Make STRING into a button and return it.
|
||||
When clicked, CALLBACK will be called with the DATA as the
|
||||
function argument. If DATA isn't present (or is nil), the button
|
||||
itself will be used instead as the function argument."
|
||||
:feature 'button
|
||||
(propertize string
|
||||
'face 'button
|
||||
'button t
|
||||
'follow-link t
|
||||
'category t
|
||||
'button-data data
|
||||
'keymap button-map
|
||||
'action callback))
|
||||
|
||||
;;;; Defined in autoload.el
|
||||
|
||||
(defvar generated-autoload-file)
|
||||
|
||||
;;* UNTESTED
|
||||
(compat-defun make-directory-autoloads (dir output-file)
|
||||
"Update autoload definitions for Lisp files in the directories DIRS.
|
||||
DIR can be either a single directory or a list of
|
||||
directories. (The latter usage is discouraged.)
|
||||
|
||||
The autoloads will be written to OUTPUT-FILE. If any Lisp file
|
||||
binds `generated-autoload-file' as a file-local variable, write
|
||||
its autoloads into the specified file instead.
|
||||
|
||||
The function does NOT recursively descend into subdirectories of the
|
||||
directory or directories specified."
|
||||
(let ((generated-autoload-file output-file))
|
||||
;; We intentionally don't sharp-quote
|
||||
;; `update-directory-autoloads', because it was deprecated in
|
||||
;; Emacs 28 and we don't want to trigger the byte compiler for
|
||||
;; newer versions.
|
||||
(apply 'update-directory-autoloads
|
||||
(if (listp dir) dir (list dir)))))
|
||||
|
||||
;;;; Defined in time-data.el
|
||||
|
||||
(compat-defun decoded-time-period (time)
|
||||
(compat-defun decoded-time-period (time) ;; <compat-tests:decoded-time-period>
|
||||
"Interpret DECODED as a period and return its length in seconds.
|
||||
For computational purposes, years are 365 days long and months
|
||||
are 30 days long."
|
||||
:feature 'time-date
|
||||
:version "28"
|
||||
;; Inlining the definitions from compat-27
|
||||
(+ (if (consp (nth 0 time))
|
||||
;; Fractional second.
|
||||
(/ (float (car (nth 0 time)))
|
||||
(cdr (nth 0 time)))
|
||||
(or (nth 0 time) 0))
|
||||
(* (or (nth 1 time) 0) 60)
|
||||
(* (or (nth 2 time) 0) 60 60)
|
||||
(* (or (nth 3 time) 0) 60 60 24)
|
||||
(* (or (nth 4 time) 0) 60 60 24 30)
|
||||
(* (or (nth 5 time) 0) 60 60 24 365)))
|
||||
:feature time-date
|
||||
(+ (if (consp (decoded-time-second time))
|
||||
(/ (float (car (decoded-time-second time)))
|
||||
(cdr (decoded-time-second time)))
|
||||
(or (decoded-time-second time) 0))
|
||||
(* (or (decoded-time-minute time) 0) 60)
|
||||
(* (or (decoded-time-hour time) 0) 60 60)
|
||||
(* (or (decoded-time-day time) 0) 60 60 24)
|
||||
(* (or (decoded-time-month time) 0) 60 60 24 30)
|
||||
(* (or (decoded-time-year time) 0) 60 60 24 365)))
|
||||
|
||||
(compat--inhibit-prefixed (provide 'compat-28))
|
||||
;;;; Defined in doc.c
|
||||
|
||||
(compat-defun text-quoting-style () ;; <compat-tests:text-quoting-style>
|
||||
"Return the current effective text quoting style.
|
||||
If the variable `text-quoting-style' is `grave', `straight' or
|
||||
`curve', just return that value. If it is nil (the default), return
|
||||
`grave' if curved quotes cannot be displayed (for instance, on a
|
||||
terminal with no support for these characters), otherwise return
|
||||
`quote'. Any other value is treated as `grave'.
|
||||
|
||||
Note that in contrast to the variable `text-quoting-style', this
|
||||
function will never return nil."
|
||||
(cond
|
||||
((memq text-quoting-style '(grave straight curve))
|
||||
text-quoting-style)
|
||||
((not text-quoting-style) 'grave)
|
||||
(t 'curve)))
|
||||
|
||||
;;;; Defined in button.el
|
||||
|
||||
;; Obsolete Alias since 29
|
||||
(compat-defalias button-buttonize buttonize :obsolete t) ;; <compat-tests:button-buttonize>
|
||||
|
||||
;;;; Defined in wid-edit.el
|
||||
|
||||
(compat-guard t ;; <compat-tests:widget-natnum>
|
||||
:feature wid-edit
|
||||
(define-widget 'natnum 'restricted-sexp
|
||||
"A nonnegative integer."
|
||||
:tag "Integer (positive)"
|
||||
:value 0
|
||||
:type-error "This field should contain a nonnegative integer"
|
||||
:match-alternatives '(natnump)))
|
||||
|
||||
(provide 'compat-28)
|
||||
;;; compat-28.el ends here
|
||||
|
||||
1585
lisp/compat/compat-29.el
Normal file
1585
lisp/compat/compat-29.el
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,48 +0,0 @@
|
||||
;;; compat-font-lock.el --- -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2022 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Philip Kaludercic <philipk@posteo.net>
|
||||
;; Keywords:
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; Optional font-locking for `compat' definitions. Every symbol with
|
||||
;; an active compatibility definition will be highlighted.
|
||||
;;
|
||||
;; Load this file to enable the functionality.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(eval-and-compile
|
||||
(require 'cl-lib)
|
||||
(require 'compat-macs))
|
||||
|
||||
(defvar compat-generate-common-fn)
|
||||
(let ((compat-generate-common-fn
|
||||
(lambda (name _def-fn _install-fn check-fn attr _type)
|
||||
(unless (and (plist-get attr :no-highlight)
|
||||
(funcall check-fn))
|
||||
`(font-lock-add-keywords
|
||||
'emacs-lisp-mode
|
||||
',`((,(concat "\\_<\\("
|
||||
(regexp-quote (symbol-name name))
|
||||
"\\)\\_>")
|
||||
1 font-lock-preprocessor-face prepend)))))))
|
||||
(load "compat"))
|
||||
|
||||
(provide 'compat-font-lock)
|
||||
;;; compat-font-lock.el ends here
|
||||
@@ -1,57 +0,0 @@
|
||||
;;; compat-help.el --- Documentation for compat functions -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2022 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Philip Kaludercic <philipk@posteo.net>
|
||||
|
||||
;; 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:
|
||||
|
||||
;; Load this file to insert `compat'-relevant documentation next to
|
||||
;; the regular documentation of a symbol.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(defun compat---describe (symbol)
|
||||
"Insert documentation for SYMBOL if it has compatibility code."
|
||||
(let ((compat (get symbol 'compat-def)))
|
||||
(when compat
|
||||
(let ((doc (get compat 'compat-doc))
|
||||
(start (point)))
|
||||
(when doc
|
||||
(insert "There is a ")
|
||||
(insert-button
|
||||
"compatibility notice"
|
||||
'action (let ((type (get compat 'compat-type)))
|
||||
(cond
|
||||
((memq type '(func macro advice))
|
||||
#'find-function)
|
||||
((memq type '(variable))
|
||||
#'find-variable)
|
||||
((error "Unknown type"))))
|
||||
'button-data compat)
|
||||
(insert (format " for %s (for versions of Emacs before %s):"
|
||||
(symbol-name symbol)
|
||||
(get compat 'compat-version)))
|
||||
(add-text-properties start (point) '(face bold))
|
||||
(newline 2)
|
||||
(insert (substitute-command-keys doc))
|
||||
(fill-region start (point))
|
||||
(newline 2))))))
|
||||
|
||||
(add-hook 'help-fns-describe-function-functions #'compat---describe)
|
||||
|
||||
(provide 'compat-help)
|
||||
;;; compat-help.el ends here
|
||||
@@ -1,9 +1,6 @@
|
||||
;;; compat-macs.el --- Compatibility Macros -*- lexical-binding: t; no-byte-compile: t; -*-
|
||||
;;; compat-macs.el --- Compatibility Macros -*- lexical-binding: t; no-byte-compile: t; -*-
|
||||
|
||||
;; Copyright (C) 2021, 2022 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Philip Kaludercic <philipk@posteo.net>
|
||||
;; Keywords: lisp
|
||||
;; Copyright (C) 2021-2023 Free Software Foundation, Inc.
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
@@ -20,297 +17,249 @@
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; These macros are used to define compatibility functions, macros and
|
||||
;; advice.
|
||||
;; This file provides *internal* macros, which are used by Compat to
|
||||
;; facilitate the definition of compatibility functions, macros and
|
||||
;; variables. The `compat-macs' feature should never be loaded at
|
||||
;; runtime in your Emacs and will only be used during byte
|
||||
;; compilation. Every definition provided here should be considered
|
||||
;; internal and may change any time between Compat releases.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(defmacro compat--ignore (&rest _)
|
||||
"Ignore all arguments."
|
||||
nil)
|
||||
;; We always require subr-x at compile time for the fboundp check
|
||||
;; since definitions have been moved around. The cl-lib macros are
|
||||
;; needed by compatibility definitions.
|
||||
(require 'subr-x)
|
||||
(require 'cl-lib)
|
||||
|
||||
(defvar compat--inhibit-prefixed nil
|
||||
"Non-nil means that prefixed definitions are not loaded.
|
||||
A prefixed function is something like `compat-assoc', that is
|
||||
only made visible when the respective compatibility version file
|
||||
is loaded (in this case `compat-26').")
|
||||
(defvar compat-macs--version nil
|
||||
"Version of the currently defined compatibility definitions.")
|
||||
|
||||
(defmacro compat--inhibit-prefixed (&rest body)
|
||||
"Ignore BODY unless `compat--inhibit-prefixed' is true."
|
||||
`(unless (bound-and-true-p compat--inhibit-prefixed)
|
||||
,@body))
|
||||
(defun compat-macs--strict (cond &rest error)
|
||||
"Assert strict COND, otherwise fail with ERROR."
|
||||
(when (bound-and-true-p compat-strict)
|
||||
(apply #'compat-macs--assert cond error)))
|
||||
|
||||
(defvar compat-current-version nil
|
||||
"Default version to use when no explicit version was given.")
|
||||
(defun compat-macs--assert (cond &rest error)
|
||||
"Assert COND, otherwise fail with ERROR."
|
||||
(unless cond (apply #'error error)))
|
||||
|
||||
(defmacro compat-declare-version (version)
|
||||
"Set the Emacs version that is currently being handled to VERSION."
|
||||
;; FIXME: Avoid setting the version for any definition that might
|
||||
;; follow, but try to restrict it to the current file/buffer.
|
||||
(setq compat-current-version version)
|
||||
nil)
|
||||
(defun compat-macs--docstring (type name docstring)
|
||||
"Format DOCSTRING for NAME of TYPE.
|
||||
Prepend compatibility notice to the actual documentation string."
|
||||
(with-temp-buffer
|
||||
(insert
|
||||
(format
|
||||
"[Compatibility %s for `%s', defined in Emacs %s. \
|
||||
See (compat) Emacs %s' for more details.]\n\n%s"
|
||||
type name compat-macs--version compat-macs--version docstring))
|
||||
(let ((fill-column 80))
|
||||
(fill-region (point-min) (point-max)))
|
||||
(buffer-string)))
|
||||
|
||||
(defvar compat--generate-function #'compat--generate-default
|
||||
"Function used to generate compatibility code.
|
||||
The function must take six arguments: NAME, DEF-FN, INSTALL-FN,
|
||||
CHECK-FN, ATTR and TYPE. The resulting body is constructed by
|
||||
invoking the functions DEF-FN (passed the \"realname\" and the
|
||||
version number, returning the compatibility definition), the
|
||||
INSTALL-FN (passed the \"realname\" and returning the
|
||||
installation code), CHECK-FN (passed the \"realname\" and
|
||||
returning a check to see if the compatibility definition should
|
||||
be installed). ATTR is a plist used to modify the generated
|
||||
code. The following attributes are handled, all others are
|
||||
ignored:
|
||||
(defun compat-macs--check-attributes (attrs preds)
|
||||
"Check ATTRS given PREDS predicate plist and return rest."
|
||||
(while (keywordp (car attrs))
|
||||
(compat-macs--assert (cdr attrs) "Attribute list length is odd")
|
||||
(compat-macs--assert (let ((p (plist-get preds (car attrs))))
|
||||
(and p (or (eq p t) (funcall p (cadr attrs)))))
|
||||
"Invalid attribute %s" (car attrs))
|
||||
(setq attrs (cddr attrs)))
|
||||
attrs)
|
||||
|
||||
- :min-version :: Prevent the compatibility definition from begin
|
||||
installed in versions older than indicated (string).
|
||||
(defun compat-macs--guard (attrs preds fun)
|
||||
"Guard compatibility definition generation.
|
||||
The version constraints specified by ATTRS are checked. PREDS is
|
||||
a plist of predicates for arguments which are passed to FUN."
|
||||
(declare (indent 2))
|
||||
(compat-macs--assert compat-macs--version "No `compat-version' was declared")
|
||||
(let* ((body (compat-macs--check-attributes
|
||||
attrs `(,@preds :feature symbolp)))
|
||||
(feature (plist-get attrs :feature))
|
||||
(attrs `(:body ,body ,@attrs))
|
||||
args)
|
||||
;; Require feature at compile time
|
||||
(when feature
|
||||
(compat-macs--assert (not (eq feature 'subr-x)) "Invalid feature subr-x")
|
||||
(require feature))
|
||||
;; The current Emacs must be older than the currently declared version.
|
||||
(when (version< emacs-version compat-macs--version)
|
||||
(while preds
|
||||
(push (plist-get attrs (car preds)) args)
|
||||
(setq preds (cddr preds)))
|
||||
(setq body (apply fun (nreverse args)))
|
||||
(if (and feature body)
|
||||
`(with-eval-after-load ',feature ,@body)
|
||||
(macroexp-progn body)))))
|
||||
|
||||
- :max-version :: Prevent the compatibility definition from begin
|
||||
installed in versions newer than indicated (string).
|
||||
(defun compat-macs--defun (type name arglist docstring rest)
|
||||
"Define function NAME of TYPE with ARGLIST and DOCSTRING.
|
||||
REST are attributes and the function BODY."
|
||||
(compat-macs--guard
|
||||
rest (list :extended (lambda (x) (or (booleanp x) (version-to-list x)))
|
||||
:obsolete (lambda (x) (or (booleanp x) (stringp x)))
|
||||
:body t)
|
||||
(lambda (extended obsolete body)
|
||||
(when (stringp extended)
|
||||
(compat-macs--assert
|
||||
(and (version< extended compat-macs--version) (version< "24.4" extended))
|
||||
"Invalid :extended version %s for %s %s" extended type name)
|
||||
(setq extended (version<= extended emacs-version)))
|
||||
(compat-macs--strict (eq extended (fboundp name))
|
||||
"Wrong :extended flag for %s %s" type name)
|
||||
;; Remove unsupported declares. It might be possible to set these
|
||||
;; properties otherwise. That should be looked into and implemented
|
||||
;; if it is the case.
|
||||
(when (and (listp (car-safe body)) (eq (caar body) 'declare) (<= emacs-major-version 25))
|
||||
(setcar body (assq-delete-all 'pure (assq-delete-all
|
||||
'side-effect-free (car body)))))
|
||||
;; Use `:extended' name if the function is already defined.
|
||||
(let* ((defname (if (and extended (fboundp name))
|
||||
(intern (format "compat--%s" name))
|
||||
name))
|
||||
(def `(,(if (memq '&key arglist)
|
||||
(if (eq type 'macro) 'cl-defmacro 'cl-defun)
|
||||
(if (eq type 'macro) 'defmacro 'defun))
|
||||
,defname ,arglist
|
||||
,(compat-macs--docstring type name docstring)
|
||||
,@body)))
|
||||
`(,@(if (eq defname name)
|
||||
;; An additional fboundp check is performed at runtime to make
|
||||
;; sure that we never redefine an existing definition if Compat
|
||||
;; is loaded on a newer Emacs version. Declare the function,
|
||||
;; such that the byte compiler does not complain about possibly
|
||||
;; missing functions at runtime. The warnings are generated due
|
||||
;; to the fboundp check.
|
||||
`((declare-function ,name nil)
|
||||
(unless (fboundp ',name) ,def))
|
||||
(list def))
|
||||
,@(when obsolete
|
||||
`((make-obsolete
|
||||
',defname ,(if (stringp obsolete) obsolete "No substitute")
|
||||
,compat-macs--version))))))))
|
||||
|
||||
- :feature :: The library the code is supposed to be loaded
|
||||
with (via `eval-after-load').
|
||||
(defmacro compat-guard (cond &rest rest)
|
||||
"Guard definition with a runtime COND and a version check.
|
||||
The runtime condition must make sure that no definition is
|
||||
overriden. REST is an attribute plist followed by the definition
|
||||
body. The attributes specify the conditions under which the
|
||||
definition is generated.
|
||||
|
||||
- :cond :: Only install the compatibility code, iff the value
|
||||
evaluates to non-nil.
|
||||
- :feature :: Wrap the definition with `with-eval-after-load' for
|
||||
the given feature."
|
||||
(declare (debug ([&rest keywordp sexp] def-body))
|
||||
(indent 1))
|
||||
(compat-macs--guard rest '(:body t)
|
||||
(lambda (body)
|
||||
(compat-macs--assert body "The guarded body is empty")
|
||||
(if (eq cond t)
|
||||
body
|
||||
(compat-macs--strict (eval cond t) "Guard %S failed" cond)
|
||||
`((when ,cond ,@body))))))
|
||||
|
||||
For prefixed functions, this can be interpreted as a test to
|
||||
`defalias' an existing definition or not.
|
||||
(defmacro compat-defalias (name def &rest attrs)
|
||||
"Define compatibility alias NAME as DEF.
|
||||
ATTRS is a plist of attributes, which specify the conditions
|
||||
under which the definition is generated.
|
||||
|
||||
- :no-highlight :: Do not highlight this definition as
|
||||
compatibility function.
|
||||
- :obsolete :: Mark the alias as obsolete if t.
|
||||
|
||||
- :version :: Manual specification of the version the compatee
|
||||
code was defined in (string).
|
||||
|
||||
- :realname :: Manual specification of a \"realname\" to use for
|
||||
the compatibility definition (symbol).
|
||||
|
||||
- :notes :: Additional notes that a developer using this
|
||||
compatibility function should keep in mind.
|
||||
|
||||
- :prefix :: Add a `compat-' prefix to the name, and define the
|
||||
compatibility code unconditionally.
|
||||
|
||||
TYPE is used to set the symbol property `compat-type' for NAME.")
|
||||
|
||||
(defun compat--generate-default (name def-fn install-fn check-fn attr type)
|
||||
"Generate a leaner compatibility definition.
|
||||
See `compat-generate-function' for details on the arguments NAME,
|
||||
DEF-FN, INSTALL-FN, CHECK-FN, ATTR and TYPE."
|
||||
(let* ((min-version (plist-get attr :min-version))
|
||||
(max-version (plist-get attr :max-version))
|
||||
(feature (plist-get attr :feature))
|
||||
(cond (plist-get attr :cond))
|
||||
(version (or (plist-get attr :version)
|
||||
compat-current-version))
|
||||
(realname (or (plist-get attr :realname)
|
||||
(intern (format "compat--%S" name))))
|
||||
(check (cond
|
||||
((or (and min-version
|
||||
(version< emacs-version min-version))
|
||||
(and max-version
|
||||
(version< max-version emacs-version)))
|
||||
'(compat--ignore))
|
||||
((plist-get attr :prefix)
|
||||
'(compat--inhibit-prefixed))
|
||||
((and version (version<= version emacs-version) (not cond))
|
||||
'(compat--ignore))
|
||||
(`(when (and ,(if cond cond t)
|
||||
,(funcall check-fn)))))))
|
||||
(cond
|
||||
((and (plist-get attr :prefix) (memq type '(func macro))
|
||||
(string-match "\\`compat-\\(.+\\)\\'" (symbol-name name))
|
||||
(let* ((actual-name (intern (match-string 1 (symbol-name name))))
|
||||
(body (funcall install-fn actual-name version)))
|
||||
(when (and (version<= version emacs-version)
|
||||
(fboundp actual-name))
|
||||
`(,@check
|
||||
,(if feature
|
||||
;; See https://nullprogram.com/blog/2018/02/22/:
|
||||
`(eval-after-load ,feature `(funcall ',(lambda () ,body)))
|
||||
body))))))
|
||||
((plist-get attr :realname)
|
||||
`(progn
|
||||
,(funcall def-fn realname version)
|
||||
(,@check
|
||||
,(let ((body (funcall install-fn realname version)))
|
||||
(if feature
|
||||
;; See https://nullprogram.com/blog/2018/02/22/:
|
||||
`(eval-after-load ,feature `(funcall ',(lambda () ,body)))
|
||||
body)))))
|
||||
((let* ((body (if (eq type 'advice)
|
||||
`(,@check
|
||||
,(funcall def-fn realname version)
|
||||
,(funcall install-fn realname version))
|
||||
`(,@check ,(funcall def-fn name version)))))
|
||||
(if feature
|
||||
;; See https://nullprogram.com/blog/2018/02/22/:
|
||||
`(eval-after-load ,feature `(funcall ',(lambda () ,body)))
|
||||
body))))))
|
||||
|
||||
(defun compat-generate-common (name def-fn install-fn check-fn attr type)
|
||||
"Common code for generating compatibility definitions.
|
||||
See `compat-generate-function' for details on the arguments NAME,
|
||||
DEF-FN, INSTALL-FN, CHECK-FN, ATTR and TYPE."
|
||||
(when (and (plist-get attr :cond) (plist-get attr :prefix))
|
||||
(error "A prefixed function %s cannot have a condition" name))
|
||||
(funcall compat--generate-function
|
||||
name def-fn install-fn check-fn attr type))
|
||||
|
||||
(defun compat-common-fdefine (type name arglist docstring rest)
|
||||
"Generate compatibility code for a function NAME.
|
||||
TYPE is one of `func', for functions and `macro' for macros, and
|
||||
`advice' ARGLIST is passed on directly to the definition, and
|
||||
DOCSTRING is prepended with a compatibility note. REST contains
|
||||
the remaining definition, that may begin with a property list of
|
||||
attributes (see `compat-generate-common')."
|
||||
(let ((oldname name) (body rest))
|
||||
(while (keywordp (car body))
|
||||
(setq body (cddr body)))
|
||||
;; It might be possible to set these properties otherwise. That
|
||||
;; should be looked into and implemented if it is the case.
|
||||
(when (and (listp (car-safe body)) (eq (caar body) 'declare))
|
||||
(when (version<= emacs-version "25")
|
||||
(delq (assq 'side-effect-free (car body)) (car body))
|
||||
(delq (assq 'pure (car body)) (car body))))
|
||||
;; Check if we want an explicitly prefixed function
|
||||
(when (plist-get rest :prefix)
|
||||
(setq name (intern (format "compat-%s" name))))
|
||||
(compat-generate-common
|
||||
name
|
||||
(lambda (realname version)
|
||||
`(,(cond
|
||||
((memq type '(func advice)) 'defun)
|
||||
((eq type 'macro) 'defmacro)
|
||||
((error "Unknown type")))
|
||||
,realname ,arglist
|
||||
;; Prepend compatibility notice to the actual
|
||||
;; documentation string.
|
||||
,(let ((type (cond
|
||||
((eq type 'func) "function")
|
||||
((eq type 'macro) "macro")
|
||||
((eq type 'advice) "advice")
|
||||
((error "Unknown type")))))
|
||||
(if version
|
||||
(format
|
||||
"[Compatibility %s for `%S', defined in Emacs %s]\n\n%s"
|
||||
type oldname version docstring)
|
||||
(format
|
||||
"[Compatibility %s for `%S']\n\n%s"
|
||||
type oldname docstring)))
|
||||
;; Advice may use the implicit variable `oldfun', but
|
||||
;; to avoid triggering the byte compiler, we make
|
||||
;; sure the argument is used at least once.
|
||||
,@(if (eq type 'advice)
|
||||
(cons '(ignore oldfun) body)
|
||||
body)))
|
||||
(lambda (realname _version)
|
||||
(cond
|
||||
((memq type '(func macro))
|
||||
;; Functions and macros are installed by
|
||||
;; aliasing the name of the compatible
|
||||
;; function to the name of the compatibility
|
||||
;; function.
|
||||
`(defalias ',name #',realname))
|
||||
((eq type 'advice)
|
||||
`(advice-add ',name :around #',realname))))
|
||||
(lambda ()
|
||||
(cond
|
||||
((memq type '(func macro))
|
||||
`(not (fboundp ',name)))
|
||||
((eq type 'advice) t)))
|
||||
rest type)))
|
||||
- :feature :: See `compat-guard'."
|
||||
(declare (debug (name symbolp [&rest keywordp sexp])))
|
||||
(compat-macs--guard attrs '(:obsolete booleanp)
|
||||
(lambda (obsolete)
|
||||
(compat-macs--strict (not (fboundp name)) "%s already defined" name)
|
||||
;; The fboundp check is performed at runtime to make sure that we never
|
||||
;; redefine an existing definition if Compat is loaded on a newer Emacs
|
||||
;; version.
|
||||
`((unless (fboundp ',name)
|
||||
(defalias ',name ',def
|
||||
,(compat-macs--docstring 'function name
|
||||
(get name 'function-documentation)))
|
||||
,@(when obsolete
|
||||
`((make-obsolete ',name ',def ,compat-macs--version))))))))
|
||||
|
||||
(defmacro compat-defun (name arglist docstring &rest rest)
|
||||
"Define NAME with arguments ARGLIST as a compatibility function.
|
||||
The function must be documented in DOCSTRING. REST may begin
|
||||
with a plist, that is interpreted by the macro but not passed on
|
||||
to the actual function. See `compat-generate-common' for a
|
||||
listing of attributes.
|
||||
"Define compatibility function NAME with arguments ARGLIST.
|
||||
The function must be documented in DOCSTRING. REST is an
|
||||
attribute plist followed by the function body. The attributes
|
||||
specify the conditions under which the definition is generated.
|
||||
|
||||
The definition will only be installed, if the version this
|
||||
function was defined in, as indicated by the `:version'
|
||||
attribute, is greater than the current Emacs version."
|
||||
- :extended :: Mark the function as extended if t. The function
|
||||
must be called explicitly via `compat-call'. This attribute
|
||||
should be used for functions which extend already existing
|
||||
functions, e.g., functions which changed their calling
|
||||
convention or their behavior. The value can also be a version
|
||||
string, which specifies the Emacs version when the original
|
||||
version of the function was introduced.
|
||||
|
||||
- :obsolete :: Mark the function as obsolete if t, can be a
|
||||
string describing the obsoletion.
|
||||
|
||||
- :feature :: See `compat-guard'."
|
||||
(declare (debug (&define name (&rest symbolp)
|
||||
stringp
|
||||
[&rest keywordp sexp]
|
||||
def-body))
|
||||
(doc-string 3) (indent 2))
|
||||
(compat-common-fdefine 'func name arglist docstring rest))
|
||||
(compat-macs--defun 'function name arglist docstring rest))
|
||||
|
||||
(defmacro compat-defmacro (name arglist docstring &rest rest)
|
||||
"Define NAME with arguments ARGLIST as a compatibility macro.
|
||||
The macro must be documented in DOCSTRING. REST may begin
|
||||
with a plist, that is interpreted by this macro but not passed on
|
||||
to the actual macro. See `compat-generate-common' for a
|
||||
listing of attributes.
|
||||
|
||||
The definition will only be installed, if the version this
|
||||
function was defined in, as indicated by the `:version'
|
||||
attribute, is greater than the current Emacs version."
|
||||
"Define compatibility macro NAME with arguments ARGLIST.
|
||||
The macro must be documented in DOCSTRING. REST is an attribute
|
||||
plist followed by the macro body. See `compat-defun' for
|
||||
details."
|
||||
(declare (debug compat-defun) (doc-string 3) (indent 2))
|
||||
(compat-common-fdefine 'macro name arglist docstring rest))
|
||||
(compat-macs--defun 'macro name arglist docstring rest))
|
||||
|
||||
(defmacro compat-advise (name arglist docstring &rest rest)
|
||||
"Define NAME with arguments ARGLIST as a compatibility advice.
|
||||
The advice function must be documented in DOCSTRING. REST may
|
||||
begin with a plist, that is interpreted by this macro but not
|
||||
passed on to the actual advice function. See
|
||||
`compat-generate-common' for a listing of attributes. The advice
|
||||
wraps the old definition, that is accessible via using the symbol
|
||||
`oldfun'.
|
||||
(defmacro compat-defvar (name initval docstring &rest attrs)
|
||||
"Define compatibility variable NAME with initial value INITVAL.
|
||||
The variable must be documented in DOCSTRING. ATTRS is a plist
|
||||
of attributes, which specify the conditions under which the
|
||||
definition is generated.
|
||||
|
||||
The advice will only be installed, if the version this function
|
||||
was defined in, as indicated by the `:version' attribute, is
|
||||
greater than the current Emacs version."
|
||||
(declare (debug compat-defun) (doc-string 3) (indent 2))
|
||||
(compat-common-fdefine 'advice name (cons 'oldfun arglist) docstring rest))
|
||||
- :constant :: Mark the variable as constant if t.
|
||||
|
||||
(defmacro compat-defvar (name initval docstring &rest attr)
|
||||
"Declare compatibility variable NAME with initial value INITVAL.
|
||||
The obligatory documentation string DOCSTRING must be given.
|
||||
- :local :: Make the variable buffer-local if t. If the value is
|
||||
`permanent' make the variable additionally permanently local.
|
||||
|
||||
The remaining arguments ATTR form a plist, modifying the
|
||||
behaviour of this macro. See `compat-generate-common' for a
|
||||
listing of attributes. Furthermore, `compat-defvar' also handles
|
||||
the attribute `:local' that either makes the variable permanent
|
||||
local with a value of `permanent' or just buffer local with any
|
||||
non-nil value."
|
||||
- :obsolete :: Mark the variable as obsolete if t, can be a
|
||||
string describing the obsoletion.
|
||||
|
||||
- :feature :: See `compat-guard'."
|
||||
(declare (debug (name form stringp [&rest keywordp sexp]))
|
||||
(doc-string 3) (indent 2))
|
||||
;; Check if we want an explicitly prefixed function
|
||||
(let ((oldname name))
|
||||
(when (plist-get attr :prefix)
|
||||
(setq name (intern (format "compat-%s" name))))
|
||||
(compat-generate-common
|
||||
name
|
||||
(lambda (realname version)
|
||||
(let ((localp (plist-get attr :local)))
|
||||
`(progn
|
||||
(,(if (plist-get attr :constant) 'defconst 'defvar)
|
||||
,realname ,initval
|
||||
;; Prepend compatibility notice to the actual
|
||||
;; documentation string.
|
||||
,(if version
|
||||
(format
|
||||
"[Compatibility variable for `%S', defined in Emacs %s]\n\n%s"
|
||||
oldname version docstring)
|
||||
(format
|
||||
"[Compatibility variable for `%S']\n\n%s"
|
||||
oldname docstring)))
|
||||
;; Make variable as local if necessary
|
||||
,(cond
|
||||
((eq localp 'permanent)
|
||||
`(put ',realname 'permanent-local t))
|
||||
(localp
|
||||
`(make-variable-buffer-local ',realname))))))
|
||||
(lambda (realname _version)
|
||||
`(defvaralias ',name ',realname))
|
||||
(lambda ()
|
||||
`(not (boundp ',name)))
|
||||
attr 'variable)))
|
||||
(compat-macs--guard
|
||||
attrs (list :constant #'booleanp
|
||||
:local (lambda (x) (memq x '(nil t permanent)))
|
||||
:obsolete (lambda (x) (or (booleanp x) (stringp x))))
|
||||
(lambda (constant local obsolete)
|
||||
(compat-macs--strict (not (boundp name)) "%s already defined" name)
|
||||
(compat-macs--assert (not (and constant local)) "Both :constant and :local")
|
||||
;; The boundp check is performed at runtime to make sure that we never
|
||||
;; redefine an existing definition if Compat is loaded on a newer Emacs
|
||||
;; version.
|
||||
`((unless (boundp ',name)
|
||||
(,(if constant 'defconst 'defvar)
|
||||
,name ,initval
|
||||
,(compat-macs--docstring 'variable name docstring))
|
||||
,@(when obsolete
|
||||
`((make-obsolete-variable
|
||||
',name ,(if (stringp obsolete) obsolete "No substitute")
|
||||
,compat-macs--version))))
|
||||
,@(and local `((make-variable-buffer-local ',name)))
|
||||
,@(and (eq local 'permanent) `((put ',name 'permanent-local t)))))))
|
||||
|
||||
(defmacro compat-version (version)
|
||||
"Set the Emacs version that is currently being handled to VERSION."
|
||||
(setq compat-macs--version version)
|
||||
nil)
|
||||
|
||||
(defmacro compat-require (feature version)
|
||||
"Require FEATURE if the Emacs version is less than VERSION."
|
||||
(when (version< emacs-version version)
|
||||
(require feature)
|
||||
`(require ',feature)))
|
||||
|
||||
(provide 'compat-macs)
|
||||
;;; compat-macs.el ends here
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
;; Generated package description from compat.el -*- no-byte-compile: t -*-
|
||||
(define-package "compat" "28.1.2.2" "Emacs Lisp Compatibility Library" '((emacs "24.3") (nadvice "0.3")) :commit "d533692182c084bad623977b69f9dc298255eaab" :authors '(("Philip Kaludercic" . "philipk@posteo.net")) :maintainer '("Compat Development" . "~pkal/compat-devel@lists.sr.ht") :keywords '("lisp") :url "https://sr.ht/~pkal/compat")
|
||||
(define-package "compat" "29.1.4.2" "Emacs Lisp Compatibility Library" '((emacs "24.4") (seq "2.3")) :commit "74300f16a1630a33a86710aa20c1fc26f5f89f75" :authors '(("Philip Kaludercic" . "philipk@posteo.net") ("Daniel Mendler" . "mail@daniel-mendler.de")) :maintainer '(("Daniel Mendler" . "mail@daniel-mendler.de") ("Compat Development" . "~pkal/compat-devel@lists.sr.ht")) :keywords '("lisp" "maint") :url "https://github.com/emacs-compat/compat")
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user